diff options
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r-- | fs/btrfs/relocation.c | 81 |
1 files changed, 57 insertions, 24 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index ce459a7cb16d..429c73c374b8 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -571,7 +571,9 @@ static int is_cowonly_root(u64 root_objectid) | |||
571 | root_objectid == BTRFS_CHUNK_TREE_OBJECTID || | 571 | root_objectid == BTRFS_CHUNK_TREE_OBJECTID || |
572 | root_objectid == BTRFS_DEV_TREE_OBJECTID || | 572 | root_objectid == BTRFS_DEV_TREE_OBJECTID || |
573 | root_objectid == BTRFS_TREE_LOG_OBJECTID || | 573 | root_objectid == BTRFS_TREE_LOG_OBJECTID || |
574 | root_objectid == BTRFS_CSUM_TREE_OBJECTID) | 574 | root_objectid == BTRFS_CSUM_TREE_OBJECTID || |
575 | root_objectid == BTRFS_UUID_TREE_OBJECTID || | ||
576 | root_objectid == BTRFS_QUOTA_TREE_OBJECTID) | ||
575 | return 1; | 577 | return 1; |
576 | return 0; | 578 | return 0; |
577 | } | 579 | } |
@@ -1264,10 +1266,10 @@ static int __must_check __add_reloc_root(struct btrfs_root *root) | |||
1264 | } | 1266 | } |
1265 | 1267 | ||
1266 | /* | 1268 | /* |
1267 | * helper to update/delete the 'address of tree root -> reloc tree' | 1269 | * helper to delete the 'address of tree root -> reloc tree' |
1268 | * mapping | 1270 | * mapping |
1269 | */ | 1271 | */ |
1270 | static int __update_reloc_root(struct btrfs_root *root, int del) | 1272 | static void __del_reloc_root(struct btrfs_root *root) |
1271 | { | 1273 | { |
1272 | struct rb_node *rb_node; | 1274 | struct rb_node *rb_node; |
1273 | struct mapping_node *node = NULL; | 1275 | struct mapping_node *node = NULL; |
@@ -1275,7 +1277,7 @@ static int __update_reloc_root(struct btrfs_root *root, int del) | |||
1275 | 1277 | ||
1276 | spin_lock(&rc->reloc_root_tree.lock); | 1278 | spin_lock(&rc->reloc_root_tree.lock); |
1277 | rb_node = tree_search(&rc->reloc_root_tree.rb_root, | 1279 | rb_node = tree_search(&rc->reloc_root_tree.rb_root, |
1278 | root->commit_root->start); | 1280 | root->node->start); |
1279 | if (rb_node) { | 1281 | if (rb_node) { |
1280 | node = rb_entry(rb_node, struct mapping_node, rb_node); | 1282 | node = rb_entry(rb_node, struct mapping_node, rb_node); |
1281 | rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); | 1283 | rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); |
@@ -1283,23 +1285,45 @@ static int __update_reloc_root(struct btrfs_root *root, int del) | |||
1283 | spin_unlock(&rc->reloc_root_tree.lock); | 1285 | spin_unlock(&rc->reloc_root_tree.lock); |
1284 | 1286 | ||
1285 | if (!node) | 1287 | if (!node) |
1286 | return 0; | 1288 | return; |
1287 | BUG_ON((struct btrfs_root *)node->data != root); | 1289 | BUG_ON((struct btrfs_root *)node->data != root); |
1288 | 1290 | ||
1289 | if (!del) { | 1291 | spin_lock(&root->fs_info->trans_lock); |
1290 | spin_lock(&rc->reloc_root_tree.lock); | 1292 | list_del_init(&root->root_list); |
1291 | node->bytenr = root->node->start; | 1293 | spin_unlock(&root->fs_info->trans_lock); |
1292 | rb_node = tree_insert(&rc->reloc_root_tree.rb_root, | 1294 | kfree(node); |
1293 | node->bytenr, &node->rb_node); | 1295 | } |
1294 | spin_unlock(&rc->reloc_root_tree.lock); | 1296 | |
1295 | if (rb_node) | 1297 | /* |
1296 | backref_tree_panic(rb_node, -EEXIST, node->bytenr); | 1298 | * helper to update the 'address of tree root -> reloc tree' |
1297 | } else { | 1299 | * mapping |
1298 | spin_lock(&root->fs_info->trans_lock); | 1300 | */ |
1299 | list_del_init(&root->root_list); | 1301 | static int __update_reloc_root(struct btrfs_root *root, u64 new_bytenr) |
1300 | spin_unlock(&root->fs_info->trans_lock); | 1302 | { |
1301 | kfree(node); | 1303 | struct rb_node *rb_node; |
1304 | struct mapping_node *node = NULL; | ||
1305 | struct reloc_control *rc = root->fs_info->reloc_ctl; | ||
1306 | |||
1307 | spin_lock(&rc->reloc_root_tree.lock); | ||
1308 | rb_node = tree_search(&rc->reloc_root_tree.rb_root, | ||
1309 | root->node->start); | ||
1310 | if (rb_node) { | ||
1311 | node = rb_entry(rb_node, struct mapping_node, rb_node); | ||
1312 | rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); | ||
1302 | } | 1313 | } |
1314 | spin_unlock(&rc->reloc_root_tree.lock); | ||
1315 | |||
1316 | if (!node) | ||
1317 | return 0; | ||
1318 | BUG_ON((struct btrfs_root *)node->data != root); | ||
1319 | |||
1320 | spin_lock(&rc->reloc_root_tree.lock); | ||
1321 | node->bytenr = new_bytenr; | ||
1322 | rb_node = tree_insert(&rc->reloc_root_tree.rb_root, | ||
1323 | node->bytenr, &node->rb_node); | ||
1324 | spin_unlock(&rc->reloc_root_tree.lock); | ||
1325 | if (rb_node) | ||
1326 | backref_tree_panic(rb_node, -EEXIST, node->bytenr); | ||
1303 | return 0; | 1327 | return 0; |
1304 | } | 1328 | } |
1305 | 1329 | ||
@@ -1420,7 +1444,6 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, | |||
1420 | { | 1444 | { |
1421 | struct btrfs_root *reloc_root; | 1445 | struct btrfs_root *reloc_root; |
1422 | struct btrfs_root_item *root_item; | 1446 | struct btrfs_root_item *root_item; |
1423 | int del = 0; | ||
1424 | int ret; | 1447 | int ret; |
1425 | 1448 | ||
1426 | if (!root->reloc_root) | 1449 | if (!root->reloc_root) |
@@ -1432,11 +1455,9 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, | |||
1432 | if (root->fs_info->reloc_ctl->merge_reloc_tree && | 1455 | if (root->fs_info->reloc_ctl->merge_reloc_tree && |
1433 | btrfs_root_refs(root_item) == 0) { | 1456 | btrfs_root_refs(root_item) == 0) { |
1434 | root->reloc_root = NULL; | 1457 | root->reloc_root = NULL; |
1435 | del = 1; | 1458 | __del_reloc_root(reloc_root); |
1436 | } | 1459 | } |
1437 | 1460 | ||
1438 | __update_reloc_root(reloc_root, del); | ||
1439 | |||
1440 | if (reloc_root->commit_root != reloc_root->node) { | 1461 | if (reloc_root->commit_root != reloc_root->node) { |
1441 | btrfs_set_root_node(root_item, reloc_root->node); | 1462 | btrfs_set_root_node(root_item, reloc_root->node); |
1442 | free_extent_buffer(reloc_root->commit_root); | 1463 | free_extent_buffer(reloc_root->commit_root); |
@@ -2287,7 +2308,7 @@ void free_reloc_roots(struct list_head *list) | |||
2287 | while (!list_empty(list)) { | 2308 | while (!list_empty(list)) { |
2288 | reloc_root = list_entry(list->next, struct btrfs_root, | 2309 | reloc_root = list_entry(list->next, struct btrfs_root, |
2289 | root_list); | 2310 | root_list); |
2290 | __update_reloc_root(reloc_root, 1); | 2311 | __del_reloc_root(reloc_root); |
2291 | free_extent_buffer(reloc_root->node); | 2312 | free_extent_buffer(reloc_root->node); |
2292 | free_extent_buffer(reloc_root->commit_root); | 2313 | free_extent_buffer(reloc_root->commit_root); |
2293 | kfree(reloc_root); | 2314 | kfree(reloc_root); |
@@ -2332,7 +2353,7 @@ again: | |||
2332 | 2353 | ||
2333 | ret = merge_reloc_root(rc, root); | 2354 | ret = merge_reloc_root(rc, root); |
2334 | if (ret) { | 2355 | if (ret) { |
2335 | __update_reloc_root(reloc_root, 1); | 2356 | __del_reloc_root(reloc_root); |
2336 | free_extent_buffer(reloc_root->node); | 2357 | free_extent_buffer(reloc_root->node); |
2337 | free_extent_buffer(reloc_root->commit_root); | 2358 | free_extent_buffer(reloc_root->commit_root); |
2338 | kfree(reloc_root); | 2359 | kfree(reloc_root); |
@@ -2388,6 +2409,13 @@ out: | |||
2388 | btrfs_std_error(root->fs_info, ret); | 2409 | btrfs_std_error(root->fs_info, ret); |
2389 | if (!list_empty(&reloc_roots)) | 2410 | if (!list_empty(&reloc_roots)) |
2390 | free_reloc_roots(&reloc_roots); | 2411 | free_reloc_roots(&reloc_roots); |
2412 | |||
2413 | /* new reloc root may be added */ | ||
2414 | mutex_lock(&root->fs_info->reloc_mutex); | ||
2415 | list_splice_init(&rc->reloc_roots, &reloc_roots); | ||
2416 | mutex_unlock(&root->fs_info->reloc_mutex); | ||
2417 | if (!list_empty(&reloc_roots)) | ||
2418 | free_reloc_roots(&reloc_roots); | ||
2391 | } | 2419 | } |
2392 | 2420 | ||
2393 | BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root)); | 2421 | BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root)); |
@@ -4522,6 +4550,11 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, | |||
4522 | BUG_ON(rc->stage == UPDATE_DATA_PTRS && | 4550 | BUG_ON(rc->stage == UPDATE_DATA_PTRS && |
4523 | root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID); | 4551 | root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID); |
4524 | 4552 | ||
4553 | if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) { | ||
4554 | if (buf == root->node) | ||
4555 | __update_reloc_root(root, cow->start); | ||
4556 | } | ||
4557 | |||
4525 | level = btrfs_header_level(buf); | 4558 | level = btrfs_header_level(buf); |
4526 | if (btrfs_header_generation(buf) <= | 4559 | if (btrfs_header_generation(buf) <= |
4527 | btrfs_root_last_snapshot(&root->root_item)) | 4560 | btrfs_root_last_snapshot(&root->root_item)) |