aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext3/inode.c')
-rw-r--r--fs/ext3/inode.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 953b430f92e3..acf1b1423327 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -172,10 +172,21 @@ static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
172 * so before we call here everything must be consistently dirtied against 172 * so before we call here everything must be consistently dirtied against
173 * this transaction. 173 * this transaction.
174 */ 174 */
175static int ext3_journal_test_restart(handle_t *handle, struct inode *inode) 175static int truncate_restart_transaction(handle_t *handle, struct inode *inode)
176{ 176{
177 int ret;
178
177 jbd_debug(2, "restarting handle %p\n", handle); 179 jbd_debug(2, "restarting handle %p\n", handle);
178 return ext3_journal_restart(handle, blocks_for_truncate(inode)); 180 /*
181 * Drop truncate_mutex to avoid deadlock with ext3_get_blocks_handle
182 * At this moment, get_block can be called only for blocks inside
183 * i_size since page cache has been already dropped and writes are
184 * blocked by i_mutex. So we can safely drop the truncate_mutex.
185 */
186 mutex_unlock(&EXT3_I(inode)->truncate_mutex);
187 ret = ext3_journal_restart(handle, blocks_for_truncate(inode));
188 mutex_lock(&EXT3_I(inode)->truncate_mutex);
189 return ret;
179} 190}
180 191
181/* 192/*
@@ -2075,7 +2086,7 @@ static void ext3_clear_blocks(handle_t *handle, struct inode *inode,
2075 ext3_journal_dirty_metadata(handle, bh); 2086 ext3_journal_dirty_metadata(handle, bh);
2076 } 2087 }
2077 ext3_mark_inode_dirty(handle, inode); 2088 ext3_mark_inode_dirty(handle, inode);
2078 ext3_journal_test_restart(handle, inode); 2089 truncate_restart_transaction(handle, inode);
2079 if (bh) { 2090 if (bh) {
2080 BUFFER_TRACE(bh, "retaking write access"); 2091 BUFFER_TRACE(bh, "retaking write access");
2081 ext3_journal_get_write_access(handle, bh); 2092 ext3_journal_get_write_access(handle, bh);
@@ -2285,7 +2296,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
2285 return; 2296 return;
2286 if (try_to_extend_transaction(handle, inode)) { 2297 if (try_to_extend_transaction(handle, inode)) {
2287 ext3_mark_inode_dirty(handle, inode); 2298 ext3_mark_inode_dirty(handle, inode);
2288 ext3_journal_test_restart(handle, inode); 2299 truncate_restart_transaction(handle, inode);
2289 } 2300 }
2290 2301
2291 ext3_free_blocks(handle, inode, nr, 1); 2302 ext3_free_blocks(handle, inode, nr, 1);
@@ -2895,6 +2906,10 @@ static int ext3_do_update_inode(handle_t *handle,
2895 struct buffer_head *bh = iloc->bh; 2906 struct buffer_head *bh = iloc->bh;
2896 int err = 0, rc, block; 2907 int err = 0, rc, block;
2897 2908
2909again:
2910 /* we can't allow multiple procs in here at once, its a bit racey */
2911 lock_buffer(bh);
2912
2898 /* For fields not not tracking in the in-memory inode, 2913 /* For fields not not tracking in the in-memory inode,
2899 * initialise them to zero for new inodes. */ 2914 * initialise them to zero for new inodes. */
2900 if (ei->i_state & EXT3_STATE_NEW) 2915 if (ei->i_state & EXT3_STATE_NEW)
@@ -2954,16 +2969,20 @@ static int ext3_do_update_inode(handle_t *handle,
2954 /* If this is the first large file 2969 /* If this is the first large file
2955 * created, add a flag to the superblock. 2970 * created, add a flag to the superblock.
2956 */ 2971 */
2972 unlock_buffer(bh);
2957 err = ext3_journal_get_write_access(handle, 2973 err = ext3_journal_get_write_access(handle,
2958 EXT3_SB(sb)->s_sbh); 2974 EXT3_SB(sb)->s_sbh);
2959 if (err) 2975 if (err)
2960 goto out_brelse; 2976 goto out_brelse;
2977
2961 ext3_update_dynamic_rev(sb); 2978 ext3_update_dynamic_rev(sb);
2962 EXT3_SET_RO_COMPAT_FEATURE(sb, 2979 EXT3_SET_RO_COMPAT_FEATURE(sb,
2963 EXT3_FEATURE_RO_COMPAT_LARGE_FILE); 2980 EXT3_FEATURE_RO_COMPAT_LARGE_FILE);
2964 handle->h_sync = 1; 2981 handle->h_sync = 1;
2965 err = ext3_journal_dirty_metadata(handle, 2982 err = ext3_journal_dirty_metadata(handle,
2966 EXT3_SB(sb)->s_sbh); 2983 EXT3_SB(sb)->s_sbh);
2984 /* get our lock and start over */
2985 goto again;
2967 } 2986 }
2968 } 2987 }
2969 } 2988 }
@@ -2986,6 +3005,7 @@ static int ext3_do_update_inode(handle_t *handle,
2986 raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); 3005 raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
2987 3006
2988 BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); 3007 BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
3008 unlock_buffer(bh);
2989 rc = ext3_journal_dirty_metadata(handle, bh); 3009 rc = ext3_journal_dirty_metadata(handle, bh);
2990 if (!err) 3010 if (!err)
2991 err = rc; 3011 err = rc;