Skip to content

Commit ea287ab

Browse files
josefbacikkdave
authored andcommitted
btrfs: track reloc roots based on their commit root bytenr
We always search the commit root of the extent tree for looking up back references, however we track the reloc roots based on their current bytenr. This is wrong, if we commit the transaction between relocating tree blocks we could end up in this code in build_backref_tree if (key.objectid == key.offset) { /* * Only root blocks of reloc trees use backref * pointing to itself. */ root = find_reloc_root(rc, cur->bytenr); ASSERT(root); cur->root = root; break; } find_reloc_root() is looking based on the bytenr we had in the commit root, but if we've COWed this reloc root we will not find that bytenr, and we will trip over the ASSERT(root). Fix this by using the commit_root->start bytenr for indexing the commit root. Then we change the __update_reloc_root() caller to be used when we switch the commit root for the reloc root during commit. This fixes the panic I was seeing when we started throttling relocation for delayed refs. Signed-off-by: Josef Bacik <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 50dbbb7 commit ea287ab

File tree

1 file changed

+7
-10
lines changed

1 file changed

+7
-10
lines changed

fs/btrfs/relocation.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,7 +1339,7 @@ static int __must_check __add_reloc_root(struct btrfs_root *root)
13391339
if (!node)
13401340
return -ENOMEM;
13411341

1342-
node->bytenr = root->node->start;
1342+
node->bytenr = root->commit_root->start;
13431343
node->data = root;
13441344

13451345
spin_lock(&rc->reloc_root_tree.lock);
@@ -1371,10 +1371,11 @@ static void __del_reloc_root(struct btrfs_root *root)
13711371
if (rc && root->node) {
13721372
spin_lock(&rc->reloc_root_tree.lock);
13731373
rb_node = tree_search(&rc->reloc_root_tree.rb_root,
1374-
root->node->start);
1374+
root->commit_root->start);
13751375
if (rb_node) {
13761376
node = rb_entry(rb_node, struct mapping_node, rb_node);
13771377
rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
1378+
RB_CLEAR_NODE(&node->rb_node);
13781379
}
13791380
spin_unlock(&rc->reloc_root_tree.lock);
13801381
if (!node)
@@ -1405,7 +1406,7 @@ static void __del_reloc_root(struct btrfs_root *root)
14051406
* helper to update the 'address of tree root -> reloc tree'
14061407
* mapping
14071408
*/
1408-
static int __update_reloc_root(struct btrfs_root *root, u64 new_bytenr)
1409+
static int __update_reloc_root(struct btrfs_root *root)
14091410
{
14101411
struct btrfs_fs_info *fs_info = root->fs_info;
14111412
struct rb_node *rb_node;
@@ -1414,7 +1415,7 @@ static int __update_reloc_root(struct btrfs_root *root, u64 new_bytenr)
14141415

14151416
spin_lock(&rc->reloc_root_tree.lock);
14161417
rb_node = tree_search(&rc->reloc_root_tree.rb_root,
1417-
root->node->start);
1418+
root->commit_root->start);
14181419
if (rb_node) {
14191420
node = rb_entry(rb_node, struct mapping_node, rb_node);
14201421
rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
@@ -1426,7 +1427,7 @@ static int __update_reloc_root(struct btrfs_root *root, u64 new_bytenr)
14261427
BUG_ON((struct btrfs_root *)node->data != root);
14271428

14281429
spin_lock(&rc->reloc_root_tree.lock);
1429-
node->bytenr = new_bytenr;
1430+
node->bytenr = root->node->start;
14301431
rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
14311432
node->bytenr, &node->rb_node);
14321433
spin_unlock(&rc->reloc_root_tree.lock);
@@ -1595,6 +1596,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
15951596
}
15961597

15971598
if (reloc_root->commit_root != reloc_root->node) {
1599+
__update_reloc_root(reloc_root);
15981600
btrfs_set_root_node(root_item, reloc_root->node);
15991601
free_extent_buffer(reloc_root->commit_root);
16001602
reloc_root->commit_root = btrfs_root_node(reloc_root);
@@ -4660,11 +4662,6 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
46604662
BUG_ON(rc->stage == UPDATE_DATA_PTRS &&
46614663
root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID);
46624664

4663-
if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
4664-
if (buf == root->node)
4665-
__update_reloc_root(root, cow->start);
4666-
}
4667-
46684665
level = btrfs_header_level(buf);
46694666
if (btrfs_header_generation(buf) <=
46704667
btrfs_root_last_snapshot(&root->root_item))

0 commit comments

Comments
 (0)