btrfs-progs: super-recover: fix double free fs_devices memory
authorWang Shilong <wangshilong1991@gmail.com>
Thu, 18 Sep 2014 09:01:12 +0000 (05:01 -0400)
committerDavid Sterba <dsterba@suse.cz>
Fri, 10 Oct 2014 08:38:32 +0000 (10:38 +0200)
super-recover collects btrfs devices infomation using existed
functions scan_one_devices().

Problem is fs_devices is freed twice in close_ctree() and
free_recover_superblock() for super correction path.

Fix this problem by checking whether fs_devices memory
have been freed before we free it.

Cc: Eric Sandeen <sandeen@redhat.com>
Cc: Chris Murphy <lists@colorremedies.com>
Acked-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Wang Shilong <wangshilong1991@gmail.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
super-recover.c

index 767de4b..419b86a 100644 (file)
@@ -69,21 +69,11 @@ void init_recover_superblock(struct btrfs_recover_superblock *recover)
 static
 void free_recover_superblock(struct btrfs_recover_superblock *recover)
 {
-       struct btrfs_device *device;
        struct super_block_record *record;
 
        if (!recover->fs_devices)
                return;
 
-       while (!list_empty(&recover->fs_devices->devices)) {
-               device = list_entry(recover->fs_devices->devices.next,
-                               struct btrfs_device, dev_list);
-               list_del_init(&device->dev_list);
-               free(device->name);
-               free(device);
-       }
-       free(recover->fs_devices);
-
        while (!list_empty(&recover->good_supers)) {
                record = list_entry(recover->good_supers.next,
                                struct super_block_record, list);
@@ -341,6 +331,9 @@ int btrfs_recover_superblocks(const char *dname,
 no_recover:
        recover_err_str(ret);
        free_recover_superblock(&recover);
+       /* check if we have freed fs_deivces in close_ctree() */
+       if (!root)
+               btrfs_close_devices(recover.fs_devices);
        return ret;
 }