aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-03-30 22:25:45 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2024-04-03 14:44:18 -0400
commit27fcec6c27caec05a512d2f1be7f855d8899cb8d (patch)
treec111892700954d3585e137ed2a23ac001d53a8a8 /fs
parentfa14b50460baba40c8b1138c517fb8cf04464292 (diff)
downloadlinux-27fcec6c27caec05a512d2f1be7f855d8899cb8d.tar.gz
bcachefs: Clear recovery_passes_required as they complete without errors
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/recovery.c4
-rw-r--r--fs/bcachefs/recovery_passes.c41
-rw-r--r--fs/bcachefs/util.h10
3 files changed, 43 insertions, 12 deletions
diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c
index e8b43400929362..88b794d5dbd065 100644
--- a/fs/bcachefs/recovery.c
+++ b/fs/bcachefs/recovery.c
@@ -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;
}
diff --git a/fs/bcachefs/recovery_passes.c b/fs/bcachefs/recovery_passes.c
index 0089d9456b1006..b066c5155b7429 100644
--- a/fs/bcachefs/recovery_passes.c
+++ b/fs/bcachefs/recovery_passes.c
@@ -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++;
}
diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h
index 175aee3074c7d5..4577c0789a3a7f 100644
--- a/fs/bcachefs/util.h
+++ b/fs/bcachefs/util.h
@@ -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 */