btrfs-progs: Fix memory leak when 0 sized block group item is found
authorQu Wenruo <quwenruo@cn.fujitsu.com>
Tue, 25 Apr 2017 08:01:17 +0000 (16:01 +0800)
committerDavid Sterba <dsterba@suse.com>
Tue, 2 May 2017 14:13:37 +0000 (16:13 +0200)
When a 0 sized block group item is found, set_extent_bits() will not
really set any bits.
While set_state_private() still inserts allocated block group cache into
block group extent_io_tree.

So at close_ctree() time, we won't free the private block group cache
stored since we can't find any bit set for the 0 sized block group.

To fix it, at btrfs_read_block_groups() we skip any 0 sized block group,
so such leak won't happen.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
extent-tree.c

index 3e32e43..b12ee29 100644 (file)
@@ -3250,6 +3250,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                }
                leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
+
                cache = kzalloc(sizeof(*cache), GFP_NOFS);
                if (!cache) {
                        ret = -ENOMEM;
@@ -3266,6 +3267,17 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                if (found_key.offset == 0)
                        key.objectid++;
                btrfs_release_path(path);
+
+               /*
+                * Skip 0 sized block group, don't insert them into block
+                * group cache tree, as its length is 0, it won't get
+                * freed at close_ctree() time.
+                */
+               if (found_key.offset == 0) {
+                       free(cache);
+                       continue;
+               }
+
                cache->flags = btrfs_block_group_flags(&cache->item);
                bit = 0;
                if (cache->flags & BTRFS_BLOCK_GROUP_DATA) {