]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ext4: Ensure zeroout blocks have no dirty metadata
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Mon, 31 May 2010 02:49:20 +0000 (22:49 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 2 Aug 2010 17:21:11 +0000 (10:21 -0700)
commit 515f41c33a9d44a964264c9511ad2c869af1fac3 upstream (as of v2.6.33-rc3)

This fixes a bug (found by Curt Wohlgemuth) in which new blocks
returned from an extent created with ext4_ext_zeroout() can have dirty
metadata still associated with them.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Curt Wohlgemuth <curtw@google.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/ext4/extents.c

index f2effe45eeff35290703859441bec4cfc8b30c71..b14fb6d695c701de83f1b3ade845c047404e92d5 100644 (file)
@@ -3029,6 +3029,14 @@ out:
        return err;
 }
 
+static void unmap_underlying_metadata_blocks(struct block_device *bdev,
+                       sector_t block, int count)
+{
+       int i;
+       for (i = 0; i < count; i++)
+                unmap_underlying_metadata(bdev, block + i);
+}
+
 static int
 ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
                        ext4_lblk_t iblock, unsigned int max_blocks,
@@ -3104,6 +3112,18 @@ out:
        } else
                allocated = ret;
        set_buffer_new(bh_result);
+       /*
+        * if we allocated more blocks than requested
+        * we need to make sure we unmap the extra block
+        * allocated. The actual needed block will get
+        * unmapped later when we find the buffer_head marked
+        * new.
+        */
+       if (allocated > max_blocks) {
+               unmap_underlying_metadata_blocks(inode->i_sb->s_bdev,
+                                       newblock + max_blocks,
+                                       allocated - max_blocks);
+       }
 map_out:
        set_buffer_mapped(bh_result);
 out1: