summaryrefslogtreecommitdiff
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2020-03-13 11:44:46 -0400
committerDavid Sterba <dsterba@suse.com>2020-03-23 17:01:58 +0100
commitf28de8d8fd376ba57aaed53cdc1a0ba2238e8ebf (patch)
tree001c226f54ef3310d71b4dc011ef442dcd6ecc4f /fs/btrfs
parent1a0afa0ecfc4dbc8d7583d03cafd3f68f781df0c (diff)
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')
-rw-r--r--fs/btrfs/relocation.c12
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 */