diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-09 18:11:58 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-09 18:11:58 -0500 |
| commit | e36aeee65d4db050bd8713537416a0a0632db079 (patch) | |
| tree | 4d6ec6397598bb93e877ef84cdd6537a62736484 | |
| parent | b2f051ae390432789f2b02fe451aa23ae2698e3d (diff) | |
| parent | e325a88f17196f18888f6e1426eb9fe3b4346d28 (diff) | |
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2:
ocfs2: fix rename vs unlink race
[PATCH] Fix possibly too long write in o2hb_setup_one_bio()
ocfs2: fix write() performance regression
ocfs2: Commit journal on sync writes
ocfs2: Re-order iput in ocfs2_drop_dentry_lock
ocfs2: Create locks at initially requested level
[PATCH] Fix priority mistakes in fs/ocfs2/{alloc.c, dlmglue.c}
[2.6 patch] make ocfs2_find_entry_el() static
| -rw-r--r-- | fs/ocfs2/alloc.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/aops.c | 22 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/heartbeat.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/dcache.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/dir.c | 6 | ||||
| -rw-r--r-- | fs/ocfs2/dlmglue.c | 25 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 26 | ||||
| -rw-r--r-- | fs/ocfs2/namei.c | 13 |
8 files changed, 73 insertions, 25 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 4ba7f0bdc248..ce62c152823d 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
| @@ -3946,7 +3946,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode, | |||
| 3946 | struct ocfs2_merge_ctxt ctxt; | 3946 | struct ocfs2_merge_ctxt ctxt; |
| 3947 | struct ocfs2_extent_list *rightmost_el; | 3947 | struct ocfs2_extent_list *rightmost_el; |
| 3948 | 3948 | ||
| 3949 | if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) { | 3949 | if (!(rec->e_flags & OCFS2_EXT_UNWRITTEN)) { |
| 3950 | ret = -EIO; | 3950 | ret = -EIO; |
| 3951 | mlog_errno(ret); | 3951 | mlog_errno(ret); |
| 3952 | goto out; | 3952 | goto out; |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index c69c1b300155..556e34ccb005 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -729,6 +729,27 @@ static void ocfs2_clear_page_regions(struct page *page, | |||
| 729 | } | 729 | } |
| 730 | 730 | ||
| 731 | /* | 731 | /* |
| 732 | * Nonsparse file systems fully allocate before we get to the write | ||
| 733 | * code. This prevents ocfs2_write() from tagging the write as an | ||
| 734 | * allocating one, which means ocfs2_map_page_blocks() might try to | ||
| 735 | * read-in the blocks at the tail of our file. Avoid reading them by | ||
| 736 | * testing i_size against each block offset. | ||
| 737 | */ | ||
| 738 | static int ocfs2_should_read_blk(struct inode *inode, struct page *page, | ||
| 739 | unsigned int block_start) | ||
| 740 | { | ||
| 741 | u64 offset = page_offset(page) + block_start; | ||
| 742 | |||
| 743 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) | ||
| 744 | return 1; | ||
| 745 | |||
| 746 | if (i_size_read(inode) > offset) | ||
| 747 | return 1; | ||
| 748 | |||
| 749 | return 0; | ||
| 750 | } | ||
| 751 | |||
| 752 | /* | ||
| 732 | * Some of this taken from block_prepare_write(). We already have our | 753 | * Some of this taken from block_prepare_write(). We already have our |
| 733 | * mapping by now though, and the entire write will be allocating or | 754 | * mapping by now though, and the entire write will be allocating or |
| 734 | * it won't, so not much need to use BH_New. | 755 | * it won't, so not much need to use BH_New. |
| @@ -781,6 +802,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno, | |||
| 781 | set_buffer_uptodate(bh); | 802 | set_buffer_uptodate(bh); |
| 782 | } else if (!buffer_uptodate(bh) && !buffer_delay(bh) && | 803 | } else if (!buffer_uptodate(bh) && !buffer_delay(bh) && |
| 783 | !buffer_new(bh) && | 804 | !buffer_new(bh) && |
| 805 | ocfs2_should_read_blk(inode, page, block_start) && | ||
| 784 | (block_start < from || block_end > to)) { | 806 | (block_start < from || block_end > to)) { |
| 785 | ll_rw_block(READ, 1, &bh); | 807 | ll_rw_block(READ, 1, &bh); |
| 786 | *wait_bh++=bh; | 808 | *wait_bh++=bh; |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 9cc7c0418b70..f02ccb34604d 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
| @@ -267,7 +267,7 @@ static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, | |||
| 267 | current_page = cs / spp; | 267 | current_page = cs / spp; |
| 268 | page = reg->hr_slot_data[current_page]; | 268 | page = reg->hr_slot_data[current_page]; |
| 269 | 269 | ||
| 270 | vec_len = min(PAGE_CACHE_SIZE, | 270 | vec_len = min(PAGE_CACHE_SIZE - vec_start, |
| 271 | (max_slots-cs) * (PAGE_CACHE_SIZE/spp) ); | 271 | (max_slots-cs) * (PAGE_CACHE_SIZE/spp) ); |
| 272 | 272 | ||
| 273 | mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n", | 273 | mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n", |
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 3094ddb7a254..1957a5ed219e 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
| @@ -318,9 +318,9 @@ out_attach: | |||
| 318 | static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, | 318 | static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, |
| 319 | struct ocfs2_dentry_lock *dl) | 319 | struct ocfs2_dentry_lock *dl) |
| 320 | { | 320 | { |
| 321 | iput(dl->dl_inode); | ||
| 321 | ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); | 322 | ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); |
| 322 | ocfs2_lock_res_free(&dl->dl_lockres); | 323 | ocfs2_lock_res_free(&dl->dl_lockres); |
| 323 | iput(dl->dl_inode); | ||
| 324 | kfree(dl); | 324 | kfree(dl); |
| 325 | } | 325 | } |
| 326 | 326 | ||
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 6a2f143e269c..63b28fdceb4a 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
| @@ -208,9 +208,9 @@ out: | |||
| 208 | return NULL; | 208 | return NULL; |
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, | 211 | static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, |
| 212 | struct inode *dir, | 212 | struct inode *dir, |
| 213 | struct ocfs2_dir_entry **res_dir) | 213 | struct ocfs2_dir_entry **res_dir) |
| 214 | { | 214 | { |
| 215 | struct super_block *sb; | 215 | struct super_block *sb; |
| 216 | struct buffer_head *bh_use[NAMEI_RA_SIZE]; | 216 | struct buffer_head *bh_use[NAMEI_RA_SIZE]; |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 41c76ff2fcfb..4e97dcceaf8f 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
| @@ -670,7 +670,7 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc | |||
| 670 | { | 670 | { |
| 671 | mlog_entry_void(); | 671 | mlog_entry_void(); |
| 672 | 672 | ||
| 673 | BUG_ON((!lockres->l_flags & OCFS2_LOCK_BUSY)); | 673 | BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY))); |
| 674 | BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); | 674 | BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); |
| 675 | 675 | ||
| 676 | if (lockres->l_requested > LKM_NLMODE && | 676 | if (lockres->l_requested > LKM_NLMODE && |
| @@ -980,18 +980,6 @@ again: | |||
| 980 | goto unlock; | 980 | goto unlock; |
| 981 | } | 981 | } |
| 982 | 982 | ||
| 983 | if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) { | ||
| 984 | /* lock has not been created yet. */ | ||
| 985 | spin_unlock_irqrestore(&lockres->l_lock, flags); | ||
| 986 | |||
| 987 | ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0); | ||
| 988 | if (ret < 0) { | ||
| 989 | mlog_errno(ret); | ||
| 990 | goto out; | ||
| 991 | } | ||
| 992 | goto again; | ||
| 993 | } | ||
| 994 | |||
| 995 | if (lockres->l_flags & OCFS2_LOCK_BLOCKED && | 983 | if (lockres->l_flags & OCFS2_LOCK_BLOCKED && |
| 996 | !ocfs2_may_continue_on_blocked_lock(lockres, level)) { | 984 | !ocfs2_may_continue_on_blocked_lock(lockres, level)) { |
| 997 | /* is the lock is currently blocked on behalf of | 985 | /* is the lock is currently blocked on behalf of |
| @@ -1006,7 +994,14 @@ again: | |||
| 1006 | mlog(ML_ERROR, "lockres %s has action %u pending\n", | 994 | mlog(ML_ERROR, "lockres %s has action %u pending\n", |
| 1007 | lockres->l_name, lockres->l_action); | 995 | lockres->l_name, lockres->l_action); |
| 1008 | 996 | ||
| 1009 | lockres->l_action = OCFS2_AST_CONVERT; | 997 | if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) { |
| 998 | lockres->l_action = OCFS2_AST_ATTACH; | ||
| 999 | lkm_flags &= ~LKM_CONVERT; | ||
| 1000 | } else { | ||
| 1001 | lockres->l_action = OCFS2_AST_CONVERT; | ||
| 1002 | lkm_flags |= LKM_CONVERT; | ||
| 1003 | } | ||
| 1004 | |||
| 1010 | lockres->l_requested = level; | 1005 | lockres->l_requested = level; |
| 1011 | lockres_or_flags(lockres, OCFS2_LOCK_BUSY); | 1006 | lockres_or_flags(lockres, OCFS2_LOCK_BUSY); |
| 1012 | spin_unlock_irqrestore(&lockres->l_lock, flags); | 1007 | spin_unlock_irqrestore(&lockres->l_lock, flags); |
| @@ -1021,7 +1016,7 @@ again: | |||
| 1021 | status = dlmlock(osb->dlm, | 1016 | status = dlmlock(osb->dlm, |
| 1022 | level, | 1017 | level, |
| 1023 | &lockres->l_lksb, | 1018 | &lockres->l_lksb, |
| 1024 | lkm_flags|LKM_CONVERT, | 1019 | lkm_flags, |
| 1025 | lockres->l_name, | 1020 | lockres->l_name, |
| 1026 | OCFS2_LOCK_ID_MAX_LEN - 1, | 1021 | OCFS2_LOCK_ID_MAX_LEN - 1, |
| 1027 | ocfs2_locking_ast, | 1022 | ocfs2_locking_ast, |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index f92fe91ff260..bbac7cd33e0b 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -1891,9 +1891,11 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, | |||
| 1891 | ssize_t written = 0; | 1891 | ssize_t written = 0; |
| 1892 | size_t ocount; /* original count */ | 1892 | size_t ocount; /* original count */ |
| 1893 | size_t count; /* after file limit checks */ | 1893 | size_t count; /* after file limit checks */ |
| 1894 | loff_t *ppos = &iocb->ki_pos; | 1894 | loff_t old_size, *ppos = &iocb->ki_pos; |
| 1895 | u32 old_clusters; | ||
| 1895 | struct file *file = iocb->ki_filp; | 1896 | struct file *file = iocb->ki_filp; |
| 1896 | struct inode *inode = file->f_path.dentry->d_inode; | 1897 | struct inode *inode = file->f_path.dentry->d_inode; |
| 1898 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 1897 | 1899 | ||
| 1898 | mlog_entry("(0x%p, %u, '%.*s')\n", file, | 1900 | mlog_entry("(0x%p, %u, '%.*s')\n", file, |
| 1899 | (unsigned int)nr_segs, | 1901 | (unsigned int)nr_segs, |
| @@ -1949,6 +1951,13 @@ relock: | |||
| 1949 | goto relock; | 1951 | goto relock; |
| 1950 | } | 1952 | } |
| 1951 | 1953 | ||
| 1954 | /* | ||
| 1955 | * To later detect whether a journal commit for sync writes is | ||
| 1956 | * necessary, we sample i_size, and cluster count here. | ||
| 1957 | */ | ||
| 1958 | old_size = i_size_read(inode); | ||
| 1959 | old_clusters = OCFS2_I(inode)->ip_clusters; | ||
| 1960 | |||
| 1952 | /* communicate with ocfs2_dio_end_io */ | 1961 | /* communicate with ocfs2_dio_end_io */ |
| 1953 | ocfs2_iocb_set_rw_locked(iocb, rw_level); | 1962 | ocfs2_iocb_set_rw_locked(iocb, rw_level); |
| 1954 | 1963 | ||
| @@ -1978,6 +1987,21 @@ out_dio: | |||
| 1978 | /* buffered aio wouldn't have proper lock coverage today */ | 1987 | /* buffered aio wouldn't have proper lock coverage today */ |
| 1979 | BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); | 1988 | BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); |
| 1980 | 1989 | ||
| 1990 | if ((file->f_flags & O_SYNC && !direct_io) || IS_SYNC(inode)) { | ||
| 1991 | /* | ||
| 1992 | * The generic write paths have handled getting data | ||
| 1993 | * to disk, but since we don't make use of the dirty | ||
| 1994 | * inode list, a manual journal commit is necessary | ||
| 1995 | * here. | ||
| 1996 | */ | ||
| 1997 | if (old_size != i_size_read(inode) || | ||
| 1998 | old_clusters != OCFS2_I(inode)->ip_clusters) { | ||
| 1999 | ret = journal_force_commit(osb->journal->j_journal); | ||
| 2000 | if (ret < 0) | ||
| 2001 | written = ret; | ||
| 2002 | } | ||
| 2003 | } | ||
| 2004 | |||
| 1981 | /* | 2005 | /* |
| 1982 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io | 2006 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io |
| 1983 | * function pointer which is called when o_direct io completes so that | 2007 | * function pointer which is called when o_direct io completes so that |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 729259016c18..989ac2718587 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
| @@ -1105,9 +1105,16 @@ static int ocfs2_rename(struct inode *old_dir, | |||
| 1105 | goto bail; | 1105 | goto bail; |
| 1106 | } | 1106 | } |
| 1107 | 1107 | ||
| 1108 | if (!new_de && new_inode) | 1108 | if (!new_de && new_inode) { |
| 1109 | mlog(ML_ERROR, "inode %lu does not exist in it's parent " | 1109 | /* |
| 1110 | "directory!", new_inode->i_ino); | 1110 | * Target was unlinked by another node while we were |
| 1111 | * waiting to get to ocfs2_rename(). There isn't | ||
| 1112 | * anything we can do here to help the situation, so | ||
| 1113 | * bubble up the appropriate error. | ||
| 1114 | */ | ||
| 1115 | status = -ENOENT; | ||
| 1116 | goto bail; | ||
| 1117 | } | ||
| 1111 | 1118 | ||
| 1112 | /* In case we need to overwrite an existing file, we blow it | 1119 | /* In case we need to overwrite an existing file, we blow it |
| 1113 | * away first */ | 1120 | * away first */ |
