aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/relocation.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r--fs/btrfs/relocation.c70
1 files changed, 47 insertions, 23 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index ce459a7cb16d..7cdc76007c6c 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1264,10 +1264,10 @@ static int __must_check __add_reloc_root(struct btrfs_root *root)
1264} 1264}
1265 1265
1266/* 1266/*
1267 * helper to update/delete the 'address of tree root -> reloc tree' 1267 * helper to delete the 'address of tree root -> reloc tree'
1268 * mapping 1268 * mapping
1269 */ 1269 */
1270static int __update_reloc_root(struct btrfs_root *root, int del) 1270static void __del_reloc_root(struct btrfs_root *root)
1271{ 1271{
1272 struct rb_node *rb_node; 1272 struct rb_node *rb_node;
1273 struct mapping_node *node = NULL; 1273 struct mapping_node *node = NULL;
@@ -1275,7 +1275,7 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
1275 1275
1276 spin_lock(&rc->reloc_root_tree.lock); 1276 spin_lock(&rc->reloc_root_tree.lock);
1277 rb_node = tree_search(&rc->reloc_root_tree.rb_root, 1277 rb_node = tree_search(&rc->reloc_root_tree.rb_root,
1278 root->commit_root->start); 1278 root->node->start);
1279 if (rb_node) { 1279 if (rb_node) {
1280 node = rb_entry(rb_node, struct mapping_node, rb_node); 1280 node = rb_entry(rb_node, struct mapping_node, rb_node);
1281 rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); 1281 rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
@@ -1283,23 +1283,45 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
1283 spin_unlock(&rc->reloc_root_tree.lock); 1283 spin_unlock(&rc->reloc_root_tree.lock);
1284 1284
1285 if (!node) 1285 if (!node)
1286 return 0; 1286 return;
1287 BUG_ON((struct btrfs_root *)node->data != root); 1287 BUG_ON((struct btrfs_root *)node->data != root);
1288 1288
1289 if (!del) { 1289 spin_lock(&root->fs_info->trans_lock);
1290 spin_lock(&rc->reloc_root_tree.lock); 1290 list_del_init(&root->root_list);
1291 node->bytenr = root->node->start; 1291 spin_unlock(&root->fs_info->trans_lock);
1292 rb_node = tree_insert(&rc->reloc_root_tree.rb_root, 1292 kfree(node);
1293 node->bytenr, &node->rb_node); 1293}
1294 spin_unlock(&rc->reloc_root_tree.lock); 1294
1295 if (rb_node) 1295/*
1296 backref_tree_panic(rb_node, -EEXIST, node->bytenr); 1296 * helper to update the 'address of tree root -> reloc tree'
1297 } else { 1297 * mapping
1298 spin_lock(&root->fs_info->trans_lock); 1298 */
1299 list_del_init(&root->root_list); 1299static int __update_reloc_root(struct btrfs_root *root, u64 new_bytenr)
1300 spin_unlock(&root->fs_info->trans_lock); 1300{
1301 kfree(node); 1301 struct rb_node *rb_node;
1302 struct mapping_node *node = NULL;
1303 struct reloc_control *rc = root->fs_info->reloc_ctl;
1304
1305 spin_lock(&rc->reloc_root_tree.lock);
1306 rb_node = tree_search(&rc->reloc_root_tree.rb_root,
1307 root->node->start);
1308 if (rb_node) {
1309 node = rb_entry(rb_node, struct mapping_node, rb_node);
1310 rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
1302 } 1311 }
1312 spin_unlock(&rc->reloc_root_tree.lock);
1313
1314 if (!node)
1315 return 0;
1316 BUG_ON((struct btrfs_root *)node->data != root);
1317
1318 spin_lock(&rc->reloc_root_tree.lock);
1319 node->bytenr = new_bytenr;
1320 rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
1321 node->bytenr, &node->rb_node);
1322 spin_unlock(&rc->reloc_root_tree.lock);
1323 if (rb_node)
1324 backref_tree_panic(rb_node, -EEXIST, node->bytenr);
1303 return 0; 1325 return 0;
1304} 1326}
1305 1327
@@ -1420,7 +1442,6 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
1420{ 1442{
1421 struct btrfs_root *reloc_root; 1443 struct btrfs_root *reloc_root;
1422 struct btrfs_root_item *root_item; 1444 struct btrfs_root_item *root_item;
1423 int del = 0;
1424 int ret; 1445 int ret;
1425 1446
1426 if (!root->reloc_root) 1447 if (!root->reloc_root)
@@ -1432,11 +1453,9 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
1432 if (root->fs_info->reloc_ctl->merge_reloc_tree && 1453 if (root->fs_info->reloc_ctl->merge_reloc_tree &&
1433 btrfs_root_refs(root_item) == 0) { 1454 btrfs_root_refs(root_item) == 0) {
1434 root->reloc_root = NULL; 1455 root->reloc_root = NULL;
1435 del = 1; 1456 __del_reloc_root(reloc_root);
1436 } 1457 }
1437 1458
1438 __update_reloc_root(reloc_root, del);
1439
1440 if (reloc_root->commit_root != reloc_root->node) { 1459 if (reloc_root->commit_root != reloc_root->node) {
1441 btrfs_set_root_node(root_item, reloc_root->node); 1460 btrfs_set_root_node(root_item, reloc_root->node);
1442 free_extent_buffer(reloc_root->commit_root); 1461 free_extent_buffer(reloc_root->commit_root);
@@ -2287,7 +2306,7 @@ void free_reloc_roots(struct list_head *list)
2287 while (!list_empty(list)) { 2306 while (!list_empty(list)) {
2288 reloc_root = list_entry(list->next, struct btrfs_root, 2307 reloc_root = list_entry(list->next, struct btrfs_root,
2289 root_list); 2308 root_list);
2290 __update_reloc_root(reloc_root, 1); 2309 __del_reloc_root(reloc_root);
2291 free_extent_buffer(reloc_root->node); 2310 free_extent_buffer(reloc_root->node);
2292 free_extent_buffer(reloc_root->commit_root); 2311 free_extent_buffer(reloc_root->commit_root);
2293 kfree(reloc_root); 2312 kfree(reloc_root);
@@ -2332,7 +2351,7 @@ again:
2332 2351
2333 ret = merge_reloc_root(rc, root); 2352 ret = merge_reloc_root(rc, root);
2334 if (ret) { 2353 if (ret) {
2335 __update_reloc_root(reloc_root, 1); 2354 __del_reloc_root(reloc_root);
2336 free_extent_buffer(reloc_root->node); 2355 free_extent_buffer(reloc_root->node);
2337 free_extent_buffer(reloc_root->commit_root); 2356 free_extent_buffer(reloc_root->commit_root);
2338 kfree(reloc_root); 2357 kfree(reloc_root);
@@ -4522,6 +4541,11 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
4522 BUG_ON(rc->stage == UPDATE_DATA_PTRS && 4541 BUG_ON(rc->stage == UPDATE_DATA_PTRS &&
4523 root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID); 4542 root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID);
4524 4543
4544 if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
4545 if (buf == root->node)
4546 __update_reloc_root(root, cow->start);
4547 }
4548
4525 level = btrfs_header_level(buf); 4549 level = btrfs_header_level(buf);
4526 if (btrfs_header_generation(buf) <= 4550 if (btrfs_header_generation(buf) <=
4527 btrfs_root_last_snapshot(&root->root_item)) 4551 btrfs_root_last_snapshot(&root->root_item))