Skip to content

Commit 1841027

Browse files
author
Kent Overstreet
committed
bcachefs: bch2_gc_btree() should not use btree_root_lock
btree_root_lock is for the root keys in btree_root, not the pointers to the nodes themselves; this fixes a lock ordering issue between btree_root_lock and btree node locks. Signed-off-by: Kent Overstreet <[email protected]>
1 parent f236ea4 commit 1841027

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

fs/bcachefs/btree_gc.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -641,16 +641,30 @@ static int bch2_gc_btree(struct btree_trans *trans, enum btree_id btree, bool in
641641
target_depth = 0;
642642

643643
/* root */
644-
mutex_lock(&c->btree_root_lock);
645-
struct btree *b = bch2_btree_id_root(c, btree)->b;
646-
if (!btree_node_fake(b)) {
644+
do {
645+
retry_root:
646+
bch2_trans_begin(trans);
647+
648+
struct btree_iter iter;
649+
bch2_trans_node_iter_init(trans, &iter, btree, POS_MIN,
650+
0, bch2_btree_id_root(c, btree)->b->c.level, 0);
651+
struct btree *b = bch2_btree_iter_peek_node(&iter);
652+
ret = PTR_ERR_OR_ZERO(b);
653+
if (ret)
654+
goto err_root;
655+
656+
if (b != btree_node_root(c, b)) {
657+
bch2_trans_iter_exit(trans, &iter);
658+
goto retry_root;
659+
}
660+
647661
gc_pos_set(c, gc_pos_btree(btree, b->c.level + 1, SPOS_MAX));
648-
ret = lockrestart_do(trans,
649-
bch2_gc_mark_key(trans, b->c.btree_id, b->c.level + 1,
650-
NULL, NULL, bkey_i_to_s_c(&b->key), initial));
662+
struct bkey_s_c k = bkey_i_to_s_c(&b->key);
663+
ret = bch2_gc_mark_key(trans, btree, b->c.level + 1, NULL, NULL, k, initial);
651664
level = b->c.level;
652-
}
653-
mutex_unlock(&c->btree_root_lock);
665+
err_root:
666+
bch2_trans_iter_exit(trans, &iter);
667+
} while (bch2_err_matches(ret, BCH_ERR_transaction_restart));
654668

655669
if (ret)
656670
return ret;

0 commit comments

Comments
 (0)