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>
This commit is contained in:
parent
1a0afa0ecf
commit
f28de8d8fd
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue