]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
bcachefs: Ensure btree node scan runs before checking for scanned nodes
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 25 Jun 2025 16:45:11 +0000 (12:45 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 26 Jun 2025 04:01:16 +0000 (00:01 -0400)
Previously, calling bch2_btree_has_scanned_nodes() when btree node
scan hadn't actually run would erroniously return false - causing us to
think a btree was entirely gone.

This fixes a 6.16 regression from moving the scheduling of btree node
scan out of bch2_btree_lost_data() (fixing the bug where we'd schedule
it persistently in the superblock) and only scheduling it when
check_toploogy() is asking for scanned btree nodes.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_gc.c
fs/bcachefs/btree_node_scan.c
fs/bcachefs/btree_node_scan.h

index 697c6ecc3a6555916e380d033a0201df6e4b3b83..bac108e93823c2621df51255b908f9fa3cb17f38 100644 (file)
@@ -534,32 +534,39 @@ fsck_err:
        return ret;
 }
 
-static int bch2_check_root(struct btree_trans *trans, enum btree_id i,
+static int bch2_check_root(struct btree_trans *trans, enum btree_id btree,
                           bool *reconstructed_root)
 {
        struct bch_fs *c = trans->c;
-       struct btree_root *r = bch2_btree_id_root(c, i);
+       struct btree_root *r = bch2_btree_id_root(c, btree);
        struct printbuf buf = PRINTBUF;
        int ret = 0;
 
-       bch2_btree_id_to_text(&buf, i);
+       bch2_btree_id_to_text(&buf, btree);
 
        if (r->error) {
                bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf);
 
-               r->alive = false;
-               r->error = 0;
+               ret = bch2_btree_has_scanned_nodes(c, btree);
+               if (ret < 0)
+                       goto err;
 
-               if (!bch2_btree_has_scanned_nodes(c, i)) {
+               if (!ret) {
                        __fsck_err(trans,
-                                  FSCK_CAN_FIX|(!btree_id_important(i) ? FSCK_AUTOFIX : 0),
+                                  FSCK_CAN_FIX|(!btree_id_important(btree) ? FSCK_AUTOFIX : 0),
                                   btree_root_unreadable_and_scan_found_nothing,
                                   "no nodes found for btree %s, continue?", buf.buf);
-                       bch2_btree_root_alloc_fake_trans(trans, i, 0);
+
+                       r->alive = false;
+                       r->error = 0;
+                       bch2_btree_root_alloc_fake_trans(trans, btree, 0);
                } else {
-                       bch2_btree_root_alloc_fake_trans(trans, i, 1);
-                       bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX);
-                       ret = bch2_get_scanned_nodes(c, i, 0, POS_MIN, SPOS_MAX);
+                       r->alive = false;
+                       r->error = 0;
+                       bch2_btree_root_alloc_fake_trans(trans, btree, 1);
+
+                       bch2_shoot_down_journal_keys(c, btree, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX);
+                       ret = bch2_get_scanned_nodes(c, btree, 0, POS_MIN, SPOS_MAX);
                        if (ret)
                                goto err;
                }
index a35847734a609d93b00bc6456d13f89299822b00..23d8c62ea4b67bbb187d0b42b765e43efbb91b24 100644 (file)
@@ -521,8 +521,12 @@ bool bch2_btree_node_is_stale(struct bch_fs *c, struct btree *b)
        return false;
 }
 
-bool bch2_btree_has_scanned_nodes(struct bch_fs *c, enum btree_id btree)
+int bch2_btree_has_scanned_nodes(struct bch_fs *c, enum btree_id btree)
 {
+       int ret = bch2_run_print_explicit_recovery_pass(c, BCH_RECOVERY_PASS_scan_for_btree_nodes);
+       if (ret)
+               return ret;
+
        struct found_btree_node search = {
                .btree_id       = btree,
                .level          = 0,
index 08687b209787be00a6ddc746f03d056e64c704ec..66e6f9ed19d04b706ce65dcf254050009336e9b9 100644 (file)
@@ -4,7 +4,7 @@
 
 int bch2_scan_for_btree_nodes(struct bch_fs *);
 bool bch2_btree_node_is_stale(struct bch_fs *, struct btree *);
-bool bch2_btree_has_scanned_nodes(struct bch_fs *, enum btree_id);
+int bch2_btree_has_scanned_nodes(struct bch_fs *, enum btree_id);
 int bch2_get_scanned_nodes(struct bch_fs *, enum btree_id, unsigned, struct bpos, struct bpos);
 void bch2_find_btree_nodes_exit(struct find_btree_nodes *);