Commit f28de8d8 authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

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: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
[ update changelog ]
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 1a0afa0e
...@@ -2275,18 +2275,18 @@ static int clean_dirty_subvols(struct reloc_control *rc) ...@@ -2275,18 +2275,18 @@ static int clean_dirty_subvols(struct reloc_control *rc)
list_del_init(&root->reloc_dirty_list); list_del_init(&root->reloc_dirty_list);
root->reloc_root = NULL; 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 * Need barrier to ensure clear_bit() only happens after
* root->reloc_root = NULL. Pairs with have_reloc_root. * root->reloc_root = NULL. Pairs with have_reloc_root.
*/ */
smp_wmb(); smp_wmb();
clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state); 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); btrfs_put_root(root);
} else { } else {
/* Orphan reloc tree, just clean it up */ /* Orphan reloc tree, just clean it up */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment