diff options
author | Josef Bacik <josef@toxicpanda.com> | 2020-03-13 18:44:46 +0300 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2020-03-23 19:01:58 +0300 |
commit | f28de8d8fd376ba57aaed53cdc1a0ba2238e8ebf (patch) | |
tree | 001c226f54ef3310d71b4dc011ef442dcd6ecc4f /fs/btrfs/relocation.c | |
parent | 1a0afa0ecfc4dbc8d7583d03cafd3f68f781df0c (diff) | |
download | linux-f28de8d8fd376ba57aaed53cdc1a0ba2238e8ebf.tar.xz |
btrfs: clear DEAD_RELOC_TREE before dropping the reloc root
The DEAD_RELOC_TREE flag is in place in order to avoid a use after free
in init_reloc_root, tracking the presence of reloc_root. However adding
the explicit tree references in previous patches makes the use after
free impossible because at this point we no longer have a reloc_control
set on the fs_info and thus cannot enter the function.
So move this to be coupled with clearing the root->reloc_root so we're
consistent with all other operations of the reloc root.
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
[ update changelog ]
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r-- | fs/btrfs/relocation.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index a0c8f7949a19..54724ae45380 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2275,18 +2275,18 @@ static int clean_dirty_subvols(struct reloc_control *rc) list_del_init(&root->reloc_dirty_list); root->reloc_root = NULL; - if (reloc_root) { - - ret2 = btrfs_drop_snapshot(reloc_root, 0, 1); - if (ret2 < 0 && !ret) - ret = ret2; - } /* * Need barrier to ensure clear_bit() only happens after * root->reloc_root = NULL. Pairs with have_reloc_root. */ smp_wmb(); clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state); + + if (reloc_root) { + ret2 = btrfs_drop_snapshot(reloc_root, 0, 1); + if (ret2 < 0 && !ret) + ret = ret2; + } btrfs_put_root(root); } else { /* Orphan reloc tree, just clean it up */ |