Skip to content

Commit 47fe65b

Browse files
author
Kent Overstreet
committed
bcachefs: Add missing restart handling to check_topology()
The next patch will add logging of the specific error being corrected in repair paths to the journal; this means __bch2_fsck_err() can return transaction restarts in places that previously weren't expecting them. check_topology() is old code that doesn't use btree iterators for btree node locking - it'll have to be rewritten in the future to work online. Signed-off-by: Kent Overstreet <[email protected]>
1 parent 19272b3 commit 47fe65b

File tree

1 file changed

+60
-35
lines changed

1 file changed

+60
-35
lines changed

fs/bcachefs/btree_gc.c

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,11 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct
397397
continue;
398398
}
399399

400-
ret = btree_check_node_boundaries(trans, b, prev, cur, pulled_from_scan);
400+
ret = lockrestart_do(trans,
401+
btree_check_node_boundaries(trans, b, prev, cur, pulled_from_scan));
402+
if (ret < 0)
403+
goto err;
404+
401405
if (ret == DID_FILL_FROM_SCAN) {
402406
new_pass = true;
403407
ret = 0;
@@ -438,7 +442,8 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct
438442

439443
if (!ret && !IS_ERR_OR_NULL(prev)) {
440444
BUG_ON(cur);
441-
ret = btree_repair_node_end(trans, b, prev, pulled_from_scan);
445+
ret = lockrestart_do(trans,
446+
btree_repair_node_end(trans, b, prev, pulled_from_scan));
442447
if (ret == DID_FILL_FROM_SCAN) {
443448
new_pass = true;
444449
ret = 0;
@@ -519,49 +524,65 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct
519524
bch2_bkey_buf_exit(&prev_k, c);
520525
bch2_bkey_buf_exit(&cur_k, c);
521526
printbuf_exit(&buf);
527+
bch_err_fn(c, ret);
528+
return ret;
529+
}
530+
531+
static int bch2_check_root(struct btree_trans *trans, enum btree_id i,
532+
bool *reconstructed_root)
533+
{
534+
struct bch_fs *c = trans->c;
535+
struct btree_root *r = bch2_btree_id_root(c, i);
536+
struct printbuf buf = PRINTBUF;
537+
int ret = 0;
538+
539+
bch2_btree_id_to_text(&buf, i);
540+
541+
if (r->error) {
542+
bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf);
543+
544+
r->alive = false;
545+
r->error = 0;
546+
547+
if (!bch2_btree_has_scanned_nodes(c, i)) {
548+
__fsck_err(trans,
549+
FSCK_CAN_FIX|(!btree_id_important(i) ? FSCK_AUTOFIX : 0),
550+
btree_root_unreadable_and_scan_found_nothing,
551+
"no nodes found for btree %s, continue?", buf.buf);
552+
bch2_btree_root_alloc_fake_trans(trans, i, 0);
553+
} else {
554+
bch2_btree_root_alloc_fake_trans(trans, i, 1);
555+
bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX);
556+
ret = bch2_get_scanned_nodes(c, i, 0, POS_MIN, SPOS_MAX);
557+
if (ret)
558+
goto err;
559+
}
560+
561+
*reconstructed_root = true;
562+
}
563+
err:
564+
fsck_err:
565+
printbuf_exit(&buf);
566+
bch_err_fn(c, ret);
522567
return ret;
523568
}
524569

525570
int bch2_check_topology(struct bch_fs *c)
526571
{
527572
struct btree_trans *trans = bch2_trans_get(c);
528573
struct bpos pulled_from_scan = POS_MIN;
529-
struct printbuf buf = PRINTBUF;
530574
int ret = 0;
531575

532576
bch2_trans_srcu_unlock(trans);
533577

534578
for (unsigned i = 0; i < btree_id_nr_alive(c) && !ret; i++) {
535-
struct btree_root *r = bch2_btree_id_root(c, i);
536579
bool reconstructed_root = false;
580+
recover:
581+
ret = lockrestart_do(trans, bch2_check_root(trans, i, &reconstructed_root));
582+
if (ret)
583+
break;
537584

538-
printbuf_reset(&buf);
539-
bch2_btree_id_to_text(&buf, i);
540-
541-
if (r->error) {
542-
reconstruct_root:
543-
bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf);
544-
545-
r->alive = false;
546-
r->error = 0;
547-
548-
if (!bch2_btree_has_scanned_nodes(c, i)) {
549-
__fsck_err(trans,
550-
FSCK_CAN_FIX|(!btree_id_important(i) ? FSCK_AUTOFIX : 0),
551-
btree_root_unreadable_and_scan_found_nothing,
552-
"no nodes found for btree %s, continue?", buf.buf);
553-
bch2_btree_root_alloc_fake_trans(trans, i, 0);
554-
} else {
555-
bch2_btree_root_alloc_fake_trans(trans, i, 1);
556-
bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX);
557-
ret = bch2_get_scanned_nodes(c, i, 0, POS_MIN, SPOS_MAX);
558-
if (ret)
559-
break;
560-
}
561-
562-
reconstructed_root = true;
563-
}
564-
585+
struct btree_root *r = bch2_btree_id_root(c, i);
565586
struct btree *b = r->b;
566587

567588
btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read);
@@ -575,17 +596,21 @@ int bch2_check_topology(struct bch_fs *c)
575596

576597
r->b = NULL;
577598

578-
if (!reconstructed_root)
579-
goto reconstruct_root;
599+
if (!reconstructed_root) {
600+
r->error = -EIO;
601+
goto recover;
602+
}
580603

604+
struct printbuf buf = PRINTBUF;
605+
bch2_btree_id_to_text(&buf, i);
581606
bch_err(c, "empty btree root %s", buf.buf);
607+
printbuf_exit(&buf);
582608
bch2_btree_root_alloc_fake_trans(trans, i, 0);
583609
r->alive = false;
584610
ret = 0;
585611
}
586612
}
587-
fsck_err:
588-
printbuf_exit(&buf);
613+
589614
bch2_trans_put(trans);
590615
return ret;
591616
}

0 commit comments

Comments
 (0)