]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bcachefs: Don't persistently run scan_for_btree_nodes
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 7 Jun 2025 18:27:35 +0000 (14:27 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 12 Jun 2025 03:21:30 +0000 (23:21 -0400)
bch2_btree_lost_data() gets called on btree node read error, but the
error might be transient.

btree_node_scan is expensive, and there's no need to run it persistently
(marking it in the superblock as required to run) - check_topology
will run it if required, via bch2_get_scanned_nodes().

Running it non-persistently is fine, to avoid check_topology having to
rewind recovery to run it.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/recovery.c
fs/bcachefs/recovery_passes.c

index dbd0662607250813bd3ab0abc8a38aab7a528525..06d0ba0fbffb42c794512f5e645b4921d8f4cc98 100644 (file)
@@ -99,9 +99,11 @@ int bch2_btree_lost_data(struct bch_fs *c,
                goto out;
        case BTREE_ID_snapshots:
                ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_reconstruct_snapshots, 0) ?: ret;
+               ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_topology, 0) ?: ret;
                ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_scan_for_btree_nodes, 0) ?: ret;
                goto out;
        default:
+               ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_topology, 0) ?: ret;
                ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_scan_for_btree_nodes, 0) ?: ret;
                goto out;
        }
index 605588e33fb3d0ba4f8b445a24551ab20112cfeb..35ac0d64d73afdd0e405a57610424c9f7adaebfa 100644 (file)
@@ -294,8 +294,13 @@ static bool recovery_pass_needs_set(struct bch_fs *c,
                                    enum bch_run_recovery_pass_flags *flags)
 {
        struct bch_fs_recovery *r = &c->recovery;
-       bool in_recovery = test_bit(BCH_FS_in_recovery, &c->flags);
-       bool persistent = !in_recovery || !(*flags & RUN_RECOVERY_PASS_nopersistent);
+
+       /*
+        * Never run scan_for_btree_nodes persistently: check_topology will run
+        * it if required
+        */
+       if (pass == BCH_RECOVERY_PASS_scan_for_btree_nodes)
+               *flags |= RUN_RECOVERY_PASS_nopersistent;
 
        if ((*flags & RUN_RECOVERY_PASS_ratelimit) &&
            !bch2_recovery_pass_want_ratelimit(c, pass))
@@ -310,6 +315,8 @@ static bool recovery_pass_needs_set(struct bch_fs *c,
         * Otherwise, we run run_explicit_recovery_pass when we find damage, so
         * it should run again even if it's already run:
         */
+       bool in_recovery = test_bit(BCH_FS_in_recovery, &c->flags);
+       bool persistent = !in_recovery || !(*flags & RUN_RECOVERY_PASS_nopersistent);
 
        if (persistent
            ? !(c->sb.recovery_passes_required & BIT_ULL(pass))
@@ -334,6 +341,7 @@ int __bch2_run_explicit_recovery_pass(struct bch_fs *c,
        struct bch_fs_recovery *r = &c->recovery;
        int ret = 0;
 
+
        lockdep_assert_held(&c->sb_lock);
 
        bch2_printbuf_make_room(out, 1024);
@@ -446,7 +454,7 @@ int bch2_require_recovery_pass(struct bch_fs *c,
 
 int bch2_run_print_explicit_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass)
 {
-       enum bch_run_recovery_pass_flags flags = RUN_RECOVERY_PASS_nopersistent;
+       enum bch_run_recovery_pass_flags flags = 0;
 
        if (!recovery_pass_needs_set(c, pass, &flags))
                return 0;