bcachefs: Clear recovery_passes_required as they complete without errors
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 31 Mar 2024 02:25:45 +0000 (22:25 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Wed, 3 Apr 2024 18:44:18 +0000 (14:44 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/recovery.c
fs/bcachefs/recovery_passes.c
fs/bcachefs/util.h

index e8b434009293627331f42d2dcf2dbaa896009c57..88b794d5dbd0656e5c99f36b961dd5c5a4697d61 100644 (file)
@@ -838,9 +838,7 @@ use_clean:
        }
 
        if (!test_bit(BCH_FS_error, &c->flags) &&
-           (!bch2_is_zero(ext->recovery_passes_required, sizeof(ext->recovery_passes_required)) ||
-            !bch2_is_zero(ext->errors_silent, sizeof(ext->errors_silent)))) {
-               memset(ext->recovery_passes_required, 0, sizeof(ext->recovery_passes_required));
+           !bch2_is_zero(ext->errors_silent, sizeof(ext->errors_silent))) {
                memset(ext->errors_silent, 0, sizeof(ext->errors_silent));
                write_sb = true;
        }
index 0089d9456b100647cc60bc805885f19af2f39c89..b066c5155b7429ed8269b99f463ff66c214fada1 100644 (file)
@@ -59,18 +59,23 @@ static struct recovery_pass_fn recovery_pass_fns[] = {
 #undef x
 };
 
-u64 bch2_recovery_passes_to_stable(u64 v)
-{
-       static const u8 map[] = {
+static const u8 passes_to_stable_map[] = {
 #define x(n, id, ...)  [BCH_RECOVERY_PASS_##n] = BCH_RECOVERY_PASS_STABLE_##n,
        BCH_RECOVERY_PASSES()
 #undef x
-       };
+};
+
+static enum bch_recovery_pass_stable bch2_recovery_pass_to_stable(enum bch_recovery_pass pass)
+{
+       return passes_to_stable_map[pass];
+}
 
+u64 bch2_recovery_passes_to_stable(u64 v)
+{
        u64 ret = 0;
-       for (unsigned i = 0; i < ARRAY_SIZE(map); i++)
+       for (unsigned i = 0; i < ARRAY_SIZE(passes_to_stable_map); i++)
                if (v & BIT_ULL(i))
-                       ret |= BIT_ULL(map[i]);
+                       ret |= BIT_ULL(passes_to_stable_map[i]);
        return ret;
 }
 
@@ -116,13 +121,13 @@ int bch2_run_explicit_recovery_pass(struct bch_fs *c,
 int bch2_run_explicit_recovery_pass_persistent(struct bch_fs *c,
                                               enum bch_recovery_pass pass)
 {
-       __le64 s = cpu_to_le64(bch2_recovery_passes_to_stable(BIT_ULL(pass)));
+       enum bch_recovery_pass_stable s = bch2_recovery_pass_to_stable(pass);
 
        mutex_lock(&c->sb_lock);
        struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
 
-       if (!(ext->recovery_passes_required[0] & s)) {
-               ext->recovery_passes_required[0] |= s;
+       if (!test_bit_le64(s, ext->recovery_passes_required)) {
+               __set_bit_le64(s, ext->recovery_passes_required);
                bch2_write_super(c);
        }
        mutex_unlock(&c->sb_lock);
@@ -130,6 +135,21 @@ int bch2_run_explicit_recovery_pass_persistent(struct bch_fs *c,
        return bch2_run_explicit_recovery_pass(c, pass);
 }
 
+static void bch2_clear_recovery_pass_required(struct bch_fs *c,
+                                             enum bch_recovery_pass pass)
+{
+       enum bch_recovery_pass_stable s = bch2_recovery_pass_to_stable(pass);
+
+       mutex_lock(&c->sb_lock);
+       struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
+
+       if (test_bit_le64(s, ext->recovery_passes_required)) {
+               __clear_bit_le64(s, ext->recovery_passes_required);
+               bch2_write_super(c);
+       }
+       mutex_unlock(&c->sb_lock);
+}
+
 u64 bch2_fsck_recovery_passes(void)
 {
        u64 ret = 0;
@@ -218,6 +238,9 @@ int bch2_run_recovery_passes(struct bch_fs *c)
 
                c->recovery_pass_done = max(c->recovery_pass_done, c->curr_recovery_pass);
 
+               if (!test_bit(BCH_FS_error, &c->flags))
+                       bch2_clear_recovery_pass_required(c, c->curr_recovery_pass);
+
                c->curr_recovery_pass++;
        }
 
index 175aee3074c7d539d40e7ec3ffc072a0e3d2d388..4577c0789a3a7f6540a8c1d19c7f86f92f00c30a 100644 (file)
@@ -797,4 +797,14 @@ static inline void __set_bit_le64(size_t bit, __le64 *addr)
        addr[bit / 64] |= cpu_to_le64(BIT_ULL(bit % 64));
 }
 
+static inline void __clear_bit_le64(size_t bit, __le64 *addr)
+{
+       addr[bit / 64] &= !cpu_to_le64(BIT_ULL(bit % 64));
+}
+
+static inline bool test_bit_le64(size_t bit, __le64 *addr)
+{
+       return (addr[bit / 64] & cpu_to_le64(BIT_ULL(bit % 64))) != 0;
+}
+
 #endif /* _BCACHEFS_UTIL_H */