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 b49908a167ae..cd098a7b77fc 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/*
@@ -2072,7 +2083,7 @@ static void ext3_clear_blocks(handle_t *handle, struct inode *inode,
2072 ext3_journal_dirty_metadata(handle, bh); 2083 ext3_journal_dirty_metadata(handle, bh);
2073 } 2084 }
2074 ext3_mark_inode_dirty(handle, inode); 2085 ext3_mark_inode_dirty(handle, inode);
2075 ext3_journal_test_restart(handle, inode); 2086 truncate_restart_transaction(handle, inode);
2076 if (bh) { 2087 if (bh) {
2077 BUFFER_TRACE(bh, "retaking write access"); 2088 BUFFER_TRACE(bh, "retaking write access");
2078 ext3_journal_get_write_access(handle, bh); 2089 ext3_journal_get_write_access(handle, bh);
@@ -2282,7 +2293,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
2282 return; 2293 return;
2283 if (try_to_extend_transaction(handle, inode)) { 2294 if (try_to_extend_transaction(handle, inode)) {
2284 ext3_mark_inode_dirty(handle, inode); 2295 ext3_mark_inode_dirty(handle, inode);
2285 ext3_journal_test_restart(handle, inode); 2296 truncate_restart_transaction(handle, inode);
2286 } 2297 }
2287 2298
2288 ext3_free_blocks(handle, inode, nr, 1); 2299 ext3_free_blocks(handle, inode, nr, 1);
@@ -2892,6 +2903,10 @@ static int ext3_do_update_inode(handle_t *handle,
2892 struct buffer_head *bh = iloc->bh; 2903 struct buffer_head *bh = iloc->bh;
2893 int err = 0, rc, block; 2904 int err = 0, rc, block;
2894 2905
2906again:
2907 /* we can't allow multiple procs in here at once, its a bit racey */
2908 lock_buffer(bh);
2909
2895 /* For fields not not tracking in the in-memory inode, 2910 /* For fields not not tracking in the in-memory inode,
2896 * initialise them to zero for new inodes. */ 2911 * initialise them to zero for new inodes. */
2897 if (ei->i_state & EXT3_STATE_NEW) 2912 if (ei->i_state & EXT3_STATE_NEW)
@@ -2951,16 +2966,20 @@ static int ext3_do_update_inode(handle_t *handle,
2951 /* If this is the first large file 2966 /* If this is the first large file
2952 * created, add a flag to the superblock. 2967 * created, add a flag to the superblock.
2953 */ 2968 */
2969 unlock_buffer(bh);
2954 err = ext3_journal_get_write_access(handle, 2970 err = ext3_journal_get_write_access(handle,
2955 EXT3_SB(sb)->s_sbh); 2971 EXT3_SB(sb)->s_sbh);
2956 if (err) 2972 if (err)
2957 goto out_brelse; 2973 goto out_brelse;
2974
2958 ext3_update_dynamic_rev(sb); 2975 ext3_update_dynamic_rev(sb);
2959 EXT3_SET_RO_COMPAT_FEATURE(sb, 2976 EXT3_SET_RO_COMPAT_FEATURE(sb,
2960 EXT3_FEATURE_RO_COMPAT_LARGE_FILE); 2977 EXT3_FEATURE_RO_COMPAT_LARGE_FILE);
2961 handle->h_sync = 1; 2978 handle->h_sync = 1;
2962 err = ext3_journal_dirty_metadata(handle, 2979 err = ext3_journal_dirty_metadata(handle,
2963 EXT3_SB(sb)->s_sbh); 2980 EXT3_SB(sb)->s_sbh);
2981 /* get our lock and start over */
2982 goto again;
2964 } 2983 }
2965 } 2984 }
2966 } 2985 }
@@ -2983,6 +3002,7 @@ static int ext3_do_update_inode(handle_t *handle,
2983 raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); 3002 raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
2984 3003
2985 BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); 3004 BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
3005 unlock_buffer(bh);
2986 rc = ext3_journal_dirty_metadata(handle, bh); 3006 rc = ext3_journal_dirty_metadata(handle, bh);
2987 if (!err) 3007 if (!err)
2988 err = rc; 3008 err = rc;