Commit 7f391b2f authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: bch2_run_online_recovery_passes()

Add a new helper for running online recovery passes - i.e. online fsck.
This is a subset of our normal recovery passes, and does not - for now -
use or follow c->curr_recovery_pass.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 0953450a
...@@ -1047,6 +1047,13 @@ struct bch_fs { ...@@ -1047,6 +1047,13 @@ struct bch_fs {
/* RECOVERY */ /* RECOVERY */
u64 journal_replay_seq_start; u64 journal_replay_seq_start;
u64 journal_replay_seq_end; u64 journal_replay_seq_end;
/*
* Two different uses:
* "Has this fsck pass?" - i.e. should this type of error be an
* emergency read-only
* And, in certain situations fsck will rewind to an earlier pass: used
* for signaling to the toplevel code which pass we want to run now.
*/
enum bch_recovery_pass curr_recovery_pass; enum bch_recovery_pass curr_recovery_pass;
/* bitmap of explicitly enabled recovery passes: */ /* bitmap of explicitly enabled recovery passes: */
u64 recovery_passes_explicit; u64 recovery_passes_explicit;
......
...@@ -665,7 +665,7 @@ u64 bch2_fsck_recovery_passes(void) ...@@ -665,7 +665,7 @@ u64 bch2_fsck_recovery_passes(void)
static bool should_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass) static bool should_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass)
{ {
struct recovery_pass_fn *p = recovery_pass_fns + c->curr_recovery_pass; struct recovery_pass_fn *p = recovery_pass_fns + pass;
if (c->opts.norecovery && pass > BCH_RECOVERY_PASS_snapshots_read) if (c->opts.norecovery && pass > BCH_RECOVERY_PASS_snapshots_read)
return false; return false;
...@@ -682,12 +682,8 @@ static bool should_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pa ...@@ -682,12 +682,8 @@ static bool should_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pa
static int bch2_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass) static int bch2_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass)
{ {
int ret;
c->curr_recovery_pass = pass;
if (should_run_recovery_pass(c, pass)) {
struct recovery_pass_fn *p = recovery_pass_fns + pass; struct recovery_pass_fn *p = recovery_pass_fns + pass;
int ret;
if (!(p->when & PASS_SILENT)) if (!(p->when & PASS_SILENT))
bch2_print(c, KERN_INFO bch2_log_msg(c, "%s..."), bch2_print(c, KERN_INFO bch2_log_msg(c, "%s..."),
...@@ -698,9 +694,6 @@ static int bch2_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass) ...@@ -698,9 +694,6 @@ static int bch2_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass)
if (!(p->when & PASS_SILENT)) if (!(p->when & PASS_SILENT))
bch2_print(c, KERN_CONT " done\n"); bch2_print(c, KERN_CONT " done\n");
c->recovery_passes_complete |= BIT_ULL(pass);
}
return 0; return 0;
} }
...@@ -709,17 +702,43 @@ static int bch2_run_recovery_passes(struct bch_fs *c) ...@@ -709,17 +702,43 @@ static int bch2_run_recovery_passes(struct bch_fs *c)
int ret = 0; int ret = 0;
while (c->curr_recovery_pass < ARRAY_SIZE(recovery_pass_fns)) { while (c->curr_recovery_pass < ARRAY_SIZE(recovery_pass_fns)) {
if (should_run_recovery_pass(c, c->curr_recovery_pass)) {
ret = bch2_run_recovery_pass(c, c->curr_recovery_pass); ret = bch2_run_recovery_pass(c, c->curr_recovery_pass);
if (bch2_err_matches(ret, BCH_ERR_restart_recovery)) if (bch2_err_matches(ret, BCH_ERR_restart_recovery))
continue; continue;
if (ret) if (ret)
break; break;
c->recovery_passes_complete |= BIT_ULL(c->curr_recovery_pass);
}
c->curr_recovery_pass++; c->curr_recovery_pass++;
} }
return ret; return ret;
} }
int bch2_run_online_recovery_passes(struct bch_fs *c)
{
int ret = 0;
for (unsigned i = 0; i < ARRAY_SIZE(recovery_pass_fns); i++) {
struct recovery_pass_fn *p = recovery_pass_fns + i;
if (!(p->when & PASS_ONLINE))
continue;
ret = bch2_run_recovery_pass(c, i);
if (bch2_err_matches(ret, BCH_ERR_restart_recovery)) {
i = c->curr_recovery_pass;
continue;
}
if (ret)
break;
}
return ret;
}
int bch2_fs_recovery(struct bch_fs *c) int bch2_fs_recovery(struct bch_fs *c)
{ {
struct bch_sb_field_clean *clean = NULL; struct bch_sb_field_clean *clean = NULL;
......
...@@ -31,6 +31,7 @@ static inline int bch2_run_explicit_recovery_pass(struct bch_fs *c, ...@@ -31,6 +31,7 @@ static inline int bch2_run_explicit_recovery_pass(struct bch_fs *c,
} }
} }
int bch2_run_online_recovery_passes(struct bch_fs *);
u64 bch2_fsck_recovery_passes(void); u64 bch2_fsck_recovery_passes(void);
int bch2_fs_recovery(struct bch_fs *); int bch2_fs_recovery(struct bch_fs *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment