Commit 2abc726a authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

btrfs: do not init a reloc root if we aren't relocating

We previously were checking if the root had a dead root before accessing
root->reloc_root in order to avoid a use-after-free type bug.  However
this scenario happens after we've unset the reloc control, so we would
have been saved if we'd simply checked for fs_info->reloc_control.  At
this point during relocation we no longer need to be creating new reloc
roots, so simply move this check above the reloc_root checks to avoid
any future races and confusion.
Reviewed-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 6217b0fa
...@@ -1511,6 +1511,10 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans, ...@@ -1511,6 +1511,10 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
int clear_rsv = 0; int clear_rsv = 0;
int ret; int ret;
if (!rc || !rc->create_reloc_tree ||
root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID)
return 0;
/* /*
* The subvolume has reloc tree but the swap is finished, no need to * The subvolume has reloc tree but the swap is finished, no need to
* create/update the dead reloc tree * create/update the dead reloc tree
...@@ -1524,10 +1528,6 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans, ...@@ -1524,10 +1528,6 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
return 0; return 0;
} }
if (!rc || !rc->create_reloc_tree ||
root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID)
return 0;
if (!trans->reloc_reserved) { if (!trans->reloc_reserved) {
rsv = trans->block_rsv; rsv = trans->block_rsv;
trans->block_rsv = rc->block_rsv; trans->block_rsv = rc->block_rsv;
...@@ -2369,6 +2369,18 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, ...@@ -2369,6 +2369,18 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
trans = NULL; trans = NULL;
goto out; goto out;
} }
/*
* At this point we no longer have a reloc_control, so we can't
* depend on btrfs_init_reloc_root to update our last_trans.
*
* But that's ok, we started the trans handle on our
* corresponding fs_root, which means it's been added to the
* dirty list. At commit time we'll still call
* btrfs_update_reloc_root() and update our root item
* appropriately.
*/
reloc_root->last_trans = trans->transid;
trans->block_rsv = rc->block_rsv; trans->block_rsv = rc->block_rsv;
replaced = 0; replaced = 0;
......
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