Commit aca1bba6 authored by Liu Bo's avatar Liu Bo Committed by Josef Bacik

Btrfs: build up error handling for merge_reloc_roots

We first use btrfs_std_error hook to replace with BUG_ON, and we
also need to cleanup what is left, including reloc roots rbtree
and reloc roots list.
Here we use a helper function to cleanup both rbtree and list, and
since this function can also be used in the balance recover path,
we also make the change as well to keep code simple.
Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
parent 8f71f3e0
...@@ -2239,6 +2239,21 @@ int prepare_to_merge(struct reloc_control *rc, int err) ...@@ -2239,6 +2239,21 @@ int prepare_to_merge(struct reloc_control *rc, int err)
return err; return err;
} }
static noinline_for_stack
void free_reloc_roots(struct list_head *list)
{
struct btrfs_root *reloc_root;
while (!list_empty(list)) {
reloc_root = list_entry(list->next, struct btrfs_root,
root_list);
__update_reloc_root(reloc_root, 1);
free_extent_buffer(reloc_root->node);
free_extent_buffer(reloc_root->commit_root);
kfree(reloc_root);
}
}
static noinline_for_stack static noinline_for_stack
int merge_reloc_roots(struct reloc_control *rc) int merge_reloc_roots(struct reloc_control *rc)
{ {
...@@ -2246,7 +2261,7 @@ int merge_reloc_roots(struct reloc_control *rc) ...@@ -2246,7 +2261,7 @@ int merge_reloc_roots(struct reloc_control *rc)
struct btrfs_root *reloc_root; struct btrfs_root *reloc_root;
LIST_HEAD(reloc_roots); LIST_HEAD(reloc_roots);
int found = 0; int found = 0;
int ret; int ret = 0;
again: again:
root = rc->extent_root; root = rc->extent_root;
...@@ -2272,20 +2287,33 @@ int merge_reloc_roots(struct reloc_control *rc) ...@@ -2272,20 +2287,33 @@ int merge_reloc_roots(struct reloc_control *rc)
BUG_ON(root->reloc_root != reloc_root); BUG_ON(root->reloc_root != reloc_root);
ret = merge_reloc_root(rc, root); ret = merge_reloc_root(rc, root);
BUG_ON(ret); if (ret)
goto out;
} else { } else {
list_del_init(&reloc_root->root_list); list_del_init(&reloc_root->root_list);
} }
ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1); ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1);
BUG_ON(ret < 0); if (ret < 0) {
if (list_empty(&reloc_root->root_list))
list_add_tail(&reloc_root->root_list,
&reloc_roots);
goto out;
}
} }
if (found) { if (found) {
found = 0; found = 0;
goto again; goto again;
} }
out:
if (ret) {
btrfs_std_error(root->fs_info, ret);
if (!list_empty(&reloc_roots))
free_reloc_roots(&reloc_roots);
}
BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root)); BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root));
return 0; return ret;
} }
static void free_block_list(struct rb_root *blocks) static void free_block_list(struct rb_root *blocks)
...@@ -4266,14 +4294,9 @@ int btrfs_recover_relocation(struct btrfs_root *root) ...@@ -4266,14 +4294,9 @@ int btrfs_recover_relocation(struct btrfs_root *root)
out_free: out_free:
kfree(rc); kfree(rc);
out: out:
while (!list_empty(&reloc_roots)) { if (!list_empty(&reloc_roots))
reloc_root = list_entry(reloc_roots.next, free_reloc_roots(&reloc_roots);
struct btrfs_root, root_list);
list_del(&reloc_root->root_list);
free_extent_buffer(reloc_root->node);
free_extent_buffer(reloc_root->commit_root);
kfree(reloc_root);
}
btrfs_free_path(path); btrfs_free_path(path);
if (err == 0) { if (err == 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