
From: Alex Tomas <alex@clusterfs.com>

The setting of i_disksize can race against concurrent invokations of
ext3_get_block().  Moving this inside i_truncate_sem fixes it up.



 25-akpm/fs/ext3/inode.c |   17 +++++------------
 1 files changed, 5 insertions(+), 12 deletions(-)

diff -puN fs/ext3/inode.c~ext3-i_disksize-locking-fix fs/ext3/inode.c
--- 25/fs/ext3/inode.c~ext3-i_disksize-locking-fix	Mon Oct 13 14:31:13 2003
+++ 25-akpm/fs/ext3/inode.c	Mon Oct 13 14:31:13 2003
@@ -769,7 +769,6 @@ ext3_get_block_handle(handle_t *handle, 
 	int boundary = 0;
 	int depth = ext3_block_to_path(inode, iblock, offsets, &boundary);
 	struct ext3_inode_info *ei = EXT3_I(inode);
-	loff_t new_size;
 
 	J_ASSERT(handle != NULL || create == 0);
 
@@ -834,23 +833,17 @@ out:
 	if (!err)
 		err = ext3_splice_branch(handle, inode, iblock, chain,
 					 partial, left);
+	/* i_disksize growing is protected by truncate_sem
+	 * don't forget to protect it if you're about to implement
+	 * concurrent ext3_get_block() -bzzz */
+	if (!err && extend_disksize && inode->i_size > ei->i_disksize)
+		ei->i_disksize = inode->i_size;
 	up(&ei->truncate_sem);
 	if (err == -EAGAIN)
 		goto changed;
 	if (err)
 		goto cleanup;
 
-	if (extend_disksize) {
-		/*
-		 * This is not racy against ext3_truncate's modification of
-		 * i_disksize because VM/VFS ensures that the file cannot be
-		 * extended while truncate is in progress.  It is racy between
-		 * multiple parallel instances of get_block, but we have BKL.
-		 */
-		new_size = inode->i_size;
-		if (new_size > ei->i_disksize)
-			ei->i_disksize = new_size;
-	}
 	set_buffer_new(bh_result);
 	goto got_it;
 

_
