aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2011-05-30 07:29:20 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-08-05 00:58:39 -0400
commit57073d3492dd72685cdcc61b6fb8d05b3a38e891 (patch)
tree108dd67525a40844b4ca5eb5b7c3b87e9b6085b5
parentfac04f94c7b94ef1c62490b176b77f2572086629 (diff)
ext3: Fix oops in ext3_try_to_allocate_with_rsv()
commit ad95c5e9bc8b5885f94dce720137cac8fa8da4c9 upstream. Block allocation is called from two places: ext3_get_blocks_handle() and ext3_xattr_block_set(). These two callers are not necessarily synchronized because xattr code holds only xattr_sem and i_mutex, and ext3_get_blocks_handle() may hold only truncate_mutex when called from writepage() path. Block reservation code does not expect two concurrent allocations to happen to the same inode and thus assertions can be triggered or reservation structure corruption can occur. Fix the problem by taking truncate_mutex in xattr code to serialize allocations. CC: Sage Weil <sage@newdream.net> Reported-by: Fyodor Ustinov <ufm@ufm.su> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--fs/ext3/xattr.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 32e6cc23bd9..d565759d82e 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -803,8 +803,16 @@ inserted:
803 /* We need to allocate a new block */ 803 /* We need to allocate a new block */
804 ext3_fsblk_t goal = ext3_group_first_block_no(sb, 804 ext3_fsblk_t goal = ext3_group_first_block_no(sb,
805 EXT3_I(inode)->i_block_group); 805 EXT3_I(inode)->i_block_group);
806 ext3_fsblk_t block = ext3_new_block(handle, inode, 806 ext3_fsblk_t block;
807 goal, &error); 807
808 /*
809 * Protect us agaist concurrent allocations to the
810 * same inode from ext3_..._writepage(). Reservation
811 * code does not expect racing allocations.
812 */
813 mutex_lock(&EXT3_I(inode)->truncate_mutex);
814 block = ext3_new_block(handle, inode, goal, &error);
815 mutex_unlock(&EXT3_I(inode)->truncate_mutex);
808 if (error) 816 if (error)
809 goto cleanup; 817 goto cleanup;
810 ea_idebug(inode, "creating block %d", block); 818 ea_idebug(inode, "creating block %d", block);