]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ext3: i_disksize locking fix
authorAndrew Morton <akpm@osdl.org>
Thu, 16 Oct 2003 00:32:49 +0000 (17:32 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Thu, 16 Oct 2003 00:32:49 +0000 (17:32 -0700)
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.

fs/ext3/inode.c

index 1144f75b06624ad624790ec079ae8c582a8c15cc..02a877d32232500e2b3f862b7495526ac5ef64a0 100644 (file)
@@ -769,7 +769,6 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
        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;