]> git.baikalelectronics.ru Git - kernel.git/commitdiff
btrfs: unset reloc control if we fail to recover
authorJosef Bacik <josef@toxicpanda.com>
Wed, 4 Mar 2020 16:18:25 +0000 (11:18 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Apr 2020 08:50:15 +0000 (10:50 +0200)
commit 974f7bc84693a793b5f7f1b340b4b15fd377a2e4 upstream.

If we fail to load an fs root, or fail to start a transaction we can
bail without unsetting the reloc control, which leads to problems later
when we free the reloc control but still have it attached to the file
system.

In the normal path we'll end up calling unset_reloc_control() twice, but
all it does is set fs_info->reloc_control = NULL, and we can only have
one balance at a time so it's not racey.

CC: stable@vger.kernel.org # 5.4+
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/btrfs/relocation.c

index 72ef93fea1fbeceab94933a857942c3983de7528..04bdbbb746a48ef353310bf2bb38ced900416b0a 100644 (file)
@@ -4584,9 +4584,8 @@ int btrfs_recover_relocation(struct btrfs_root *root)
 
        trans = btrfs_join_transaction(rc->extent_root);
        if (IS_ERR(trans)) {
-               unset_reloc_control(rc);
                err = PTR_ERR(trans);
-               goto out_free;
+               goto out_unset;
        }
 
        rc->merge_reloc_tree = 1;
@@ -4606,7 +4605,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
                if (IS_ERR(fs_root)) {
                        err = PTR_ERR(fs_root);
                        list_add_tail(&reloc_root->root_list, &reloc_roots);
-                       goto out_free;
+                       goto out_unset;
                }
 
                err = __add_reloc_root(reloc_root);
@@ -4616,7 +4615,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
 
        err = btrfs_commit_transaction(trans);
        if (err)
-               goto out_free;
+               goto out_unset;
 
        merge_reloc_roots(rc);
 
@@ -4632,7 +4631,8 @@ out_clean:
        ret = clean_dirty_subvols(rc);
        if (ret < 0 && !err)
                err = ret;
-out_free:
+out_unset:
+       unset_reloc_control(rc);
        kfree(rc);
 out:
        if (!list_empty(&reloc_roots))