aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
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) {