diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-07-10 13:42:26 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:10:06 -0400 |
commit | 065bd3356ce490ae9454d8b3c98ff298e13d09ac (patch) | |
tree | 968bb0d1b3135ca9d51cdf43c2a963bede5552ab /fs/bcachefs/recovery.c | |
parent | 6619d84626ff266721f4c3c24339c60ca8cb12e0 (diff) | |
download | lwn-065bd3356ce490ae9454d8b3c98ff298e13d09ac.tar.gz lwn-065bd3356ce490ae9454d8b3c98ff298e13d09ac.zip |
bcachefs: Version table now lists required recovery passes
Now that we've got forward compatibility sorted out, we should be doing
more frequent version upgrades in the future.
To avoid having to run a full fsck for every version upgrade, this
improves the BCH_METADATA_VERSIONS() table to explicitly specify a
bitmask of recovery passes to run when upgrading to or past a given
version.
This means we can also delete PASS_UPGRADE().
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/recovery.c')
-rw-r--r-- | fs/bcachefs/recovery.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 9ca6c236f508..0486ec9d281c 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -1115,6 +1115,7 @@ static void check_version_upgrade(struct bch_fs *c) unsigned latest_version = bcachefs_metadata_version_current; unsigned old_version = c->sb.version_upgrade_complete ?: c->sb.version; unsigned new_version = 0; + u64 recovery_passes; if (old_version < bcachefs_metadata_required_upgrade_below) { if (c->opts.version_upgrade == BCH_VERSION_UPGRADE_incompatible || @@ -1158,12 +1159,15 @@ static void check_version_upgrade(struct bch_fs *c) bch2_version_to_text(&buf, new_version); prt_newline(&buf); - prt_str(&buf, "fsck required"); + recovery_passes = bch2_upgrade_recovery_passes(c, old_version, new_version); + if (recovery_passes) { + prt_str(&buf, "fsck required"); - bch_info(c, "%s", buf.buf); + c->recovery_passes_explicit |= recovery_passes; + c->opts.fix_errors = FSCK_OPT_YES; + } - c->opts.fsck = true; - c->opts.fix_errors = FSCK_OPT_YES; + bch_info(c, "%s", buf.buf); mutex_lock(&c->sb_lock); bch2_sb_upgrade(c, new_version); @@ -1196,21 +1200,30 @@ static struct recovery_pass_fn recovery_passes[] = { #undef x }; +u64 bch2_fsck_recovery_passes(void) +{ + u64 ret = 0; + + for (unsigned i = 0; i < ARRAY_SIZE(recovery_passes); i++) + if (recovery_passes[i].when & PASS_FSCK) + ret |= BIT_ULL(i); + return ret; +} + static bool should_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass) { struct recovery_pass_fn *p = recovery_passes + c->curr_recovery_pass; if (c->opts.norecovery && pass > BCH_RECOVERY_PASS_snapshots_read) return false; + if (c->recovery_passes_explicit & BIT_ULL(pass)) + return true; if ((p->when & PASS_FSCK) && c->opts.fsck) return true; if ((p->when & PASS_UNCLEAN) && !c->sb.clean) return true; if (p->when & PASS_ALWAYS) return true; - if (p->when >= PASS_UPGRADE(0) && - bch2_version_upgrading_to(c, p->when >> 4)) - return true; return false; } @@ -1294,7 +1307,7 @@ int bch2_fs_recovery(struct bch_fs *c) goto err; } - if (!c->opts.nochanges) + if (c->opts.fsck || !(c->opts.nochanges && c->opts.norecovery)) check_version_upgrade(c); if (c->opts.fsck && c->opts.norecovery) { |