ext4: fix memory leaks in error path handling of ext4_ext_zeroout()
authorJing Zhang <zj.barak@gmail.com>
Mon, 31 May 2010 02:49:44 +0000 (22:49 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 2 Aug 2010 17:21:17 +0000 (10:21 -0700)
commit b720303df7352d4a7a1f61e467e0a124913c0d41 upstream (as of v2.6.34-git13)

When EIO occurs after bio is submitted, there is no memory free
operation for bio, which results in memory leakage. And there is also
no check against bio_alloc() for bio.

Acked-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Signed-off-by: Jing Zhang <zj.barak@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/ext4/extents.c

index 4378941b49582ce6778deee1f4192db62cac26ab..f4844edba4a870bd410be9df76bee67266cadff6 100644 (file)
@@ -2446,7 +2446,7 @@ static void bi_complete(struct bio *bio, int error)
 /* FIXME!! we need to try to merge to left or right after zero-out  */
 static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
 {
-       int ret = -EIO;
+       int ret;
        struct bio *bio;
        int blkbits, blocksize;
        sector_t ee_pblock;
@@ -2470,6 +2470,9 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
                        len = ee_len;
 
                bio = bio_alloc(GFP_NOIO, len);
+               if (!bio)
+                       return -ENOMEM;
+
                bio->bi_sector = ee_pblock;
                bio->bi_bdev   = inode->i_sb->s_bdev;
 
@@ -2497,17 +2500,15 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
                submit_bio(WRITE, bio);
                wait_for_completion(&event);
 
-               if (test_bit(BIO_UPTODATE, &bio->bi_flags))
-                       ret = 0;
-               else {
-                       ret = -EIO;
-                       break;
+               if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+                       bio_put(bio);
+                       return -EIO;
                }
                bio_put(bio);
                ee_len    -= done;
                ee_pblock += done  << (blkbits - 9);
        }
-       return ret;
+       return 0;
 }
 
 #define EXT4_EXT_ZERO_LEN 7