bcachefs: bch2_require_recovery_pass()
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 31 May 2025 16:48:00 +0000 (12:48 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 2 Jun 2025 16:16:35 +0000 (12:16 -0400)
Add a helper for requiring that a recovery pass has already run: either
run it directly, if we're still in recovery, or if we're not in recovery
check if it has run recently and schedule it if it hasn't.

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

index 6b0791e1e64d14fd25ce65e0050cdfb9c094d4c3..6e0bf7ff2641a005dfa36b63cc917d95e8543ab5 100644 (file)
        x(BCH_ERR_fsck,                 fsck_errors_not_fixed)                  \
        x(BCH_ERR_fsck,                 fsck_repair_unimplemented)              \
        x(BCH_ERR_fsck,                 fsck_repair_impossible)                 \
-       x(EINVAL,                       restart_recovery)                       \
-       x(EINVAL,                       cannot_rewind_recovery)                 \
+       x(EINVAL,                       recovery_will_run)                      \
+       x(BCH_ERR_recovery_will_run,    restart_recovery)                       \
+       x(BCH_ERR_recovery_will_run,    cannot_rewind_recovery)                 \
+       x(BCH_ERR_recovery_will_run,    recovery_pass_will_run)                 \
        x(0,                            data_update_done)                       \
+       x(0,                            bkey_was_deleted)                       \
        x(BCH_ERR_data_update_done,     data_update_done_would_block)           \
        x(BCH_ERR_data_update_done,     data_update_done_unwritten)             \
        x(BCH_ERR_data_update_done,     data_update_done_no_writes_needed)      \
index f6ddbab5ee82e5b0f7fd4abc85ac4caf67d69511..9da43452fb300a650acbcc9f1c916b157f0b57ec 100644 (file)
@@ -384,6 +384,35 @@ int bch2_run_explicit_recovery_pass(struct bch_fs *c,
        return ret;
 }
 
+/*
+ * Returns 0 if @pass has run recently, otherwise one of
+ * -BCH_ERR_restart_recovery
+ * -BCH_ERR_recovery_pass_will_run
+ */
+int bch2_require_recovery_pass(struct bch_fs *c,
+                              struct printbuf *out,
+                              enum bch_recovery_pass pass)
+{
+       if (test_bit(BCH_FS_in_recovery, &c->flags) &&
+           c->recovery.passes_complete & BIT_ULL(pass))
+               return 0;
+
+       guard(mutex)(&c->sb_lock);
+
+       if (bch2_recovery_pass_want_ratelimit(c, pass))
+               return 0;
+
+       enum bch_run_recovery_pass_flags flags = 0;
+       int ret = 0;
+
+       if (recovery_pass_needs_set(c, pass, &flags)) {
+               ret = __bch2_run_explicit_recovery_pass(c, out, pass, flags);
+               bch2_write_super(c);
+       }
+
+       return ret ?: bch_err_throw(c, recovery_pass_will_run);
+}
+
 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;
index dc0d2014ff9bc598a3aab00396d11544363fb707..a97a462b5e1133decdfe14241165a72fe9f5c22c 100644 (file)
@@ -24,6 +24,9 @@ int bch2_run_explicit_recovery_pass(struct bch_fs *, struct printbuf *,
                                    enum bch_recovery_pass,
                                    enum bch_run_recovery_pass_flags);
 
+int bch2_require_recovery_pass(struct bch_fs *, struct printbuf *,
+                              enum bch_recovery_pass);
+
 int bch2_run_online_recovery_passes(struct bch_fs *, u64);
 int bch2_run_recovery_passes(struct bch_fs *, enum bch_recovery_pass);