aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLiu Bo <bo.li.liu@oracle.com>2013-03-04 11:25:37 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-03-04 16:33:22 -0500
commitaca1bba6f9bc550a33312b28e98b3de5ddb3bb15 (patch)
tree00d21d15fe4e57ee3e1618c898d0a78c7aab5068 /fs
parent8f71f3e0e4fb5a2445fb93d3057a33aefc4aa30d (diff)
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: Liu Bo <bo.li.liu@oracle.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/relocation.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 16e0c6fbdbed..0f001c14eaf4 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2240,13 +2240,28 @@ again:
2240} 2240}
2241 2241
2242static noinline_for_stack 2242static noinline_for_stack
2243void free_reloc_roots(struct list_head *list)
2244{
2245 struct btrfs_root *reloc_root;
2246
2247 while (!list_empty(list)) {
2248 reloc_root = list_entry(list->next, struct btrfs_root,
2249 root_list);
2250 __update_reloc_root(reloc_root, 1);
2251 free_extent_buffer(reloc_root->node);
2252 free_extent_buffer(reloc_root->commit_root);
2253 kfree(reloc_root);
2254 }
2255}
2256
2257static noinline_for_stack
2243int merge_reloc_roots(struct reloc_control *rc) 2258int merge_reloc_roots(struct reloc_control *rc)
2244{ 2259{
2245 struct btrfs_root *root; 2260 struct btrfs_root *root;
2246 struct btrfs_root *reloc_root; 2261 struct btrfs_root *reloc_root;
2247 LIST_HEAD(reloc_roots); 2262 LIST_HEAD(reloc_roots);
2248 int found = 0; 2263 int found = 0;
2249 int ret; 2264 int ret = 0;
2250again: 2265again:
2251 root = rc->extent_root; 2266 root = rc->extent_root;
2252 2267
@@ -2272,20 +2287,33 @@ again:
2272 BUG_ON(root->reloc_root != reloc_root); 2287 BUG_ON(root->reloc_root != reloc_root);
2273 2288
2274 ret = merge_reloc_root(rc, root); 2289 ret = merge_reloc_root(rc, root);
2275 BUG_ON(ret); 2290 if (ret)
2291 goto out;
2276 } else { 2292 } else {
2277 list_del_init(&reloc_root->root_list); 2293 list_del_init(&reloc_root->root_list);
2278 } 2294 }
2279 ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1); 2295 ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1);
2280 BUG_ON(ret < 0); 2296 if (ret < 0) {
2297 if (list_empty(&reloc_root->root_list))
2298 list_add_tail(&reloc_root->root_list,
2299 &reloc_roots);
2300 goto out;
2301 }
2281 } 2302 }
2282 2303
2283 if (found) { 2304 if (found) {
2284 found = 0; 2305 found = 0;
2285 goto again; 2306 goto again;
2286 } 2307 }
2308out:
2309 if (ret) {
2310 btrfs_std_error(root->fs_info, ret);
2311 if (!list_empty(&reloc_roots))
2312 free_reloc_roots(&reloc_roots);
2313 }
2314
2287 BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root)); 2315 BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root));
2288 return 0; 2316 return ret;
2289} 2317}
2290 2318
2291static void free_block_list(struct rb_root *blocks) 2319static void free_block_list(struct rb_root *blocks)
@@ -4266,14 +4294,9 @@ int btrfs_recover_relocation(struct btrfs_root *root)
4266out_free: 4294out_free:
4267 kfree(rc); 4295 kfree(rc);
4268out: 4296out:
4269 while (!list_empty(&reloc_roots)) { 4297 if (!list_empty(&reloc_roots))
4270 reloc_root = list_entry(reloc_roots.next, 4298 free_reloc_roots(&reloc_roots);
4271 struct btrfs_root, root_list); 4299
4272 list_del(&reloc_root->root_list);
4273 free_extent_buffer(reloc_root->node);
4274 free_extent_buffer(reloc_root->commit_root);
4275 kfree(reloc_root);
4276 }
4277 btrfs_free_path(path); 4300 btrfs_free_path(path);
4278 4301
4279 if (err == 0) { 4302 if (err == 0) {