From a02a0121b3de81f985d6c751f1557c7aea832b9a Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 28 Jun 2023 20:27:07 -0400 Subject: bcachefs: bch2_version_compatible() This adds a new helper for checking if an on-disk version is compatible with the running version of bcachefs - prep work for introducing major:minor version numbers. Signed-off-by: Kent Overstreet --- fs/bcachefs/bcachefs_format.h | 2 - fs/bcachefs/btree_io.c | 10 ++--- fs/bcachefs/journal_io.c | 22 +++-------- fs/bcachefs/super-io.c | 86 ++++++++++++++++++++++--------------------- fs/bcachefs/super-io.h | 6 +++ 5 files changed, 60 insertions(+), 66 deletions(-) (limited to 'fs') diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index 158cefb87684..4401d27675ed 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -1574,8 +1574,6 @@ struct bch_sb_field_journal_seq_blacklist { * One common version number for all on disk data structures - superblock, btree * nodes, journal entries */ -#define BCH_JSET_VERSION_OLD 2 -#define BCH_BSET_VERSION_OLD 3 #define BCH_METADATA_VERSIONS() \ x(bkey_renumber, 10) \ diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 990c2fa28114..9985ecd7265d 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -699,11 +699,9 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca, struct printbuf buf2 = PRINTBUF; int ret = 0; - btree_err_on((version != BCH_BSET_VERSION_OLD && - version < bcachefs_metadata_version_min) || - version >= bcachefs_metadata_version_max, + btree_err_on(!bch2_version_compatible(version), BTREE_ERR_INCOMPATIBLE, c, ca, b, i, - "unsupported bset version"); + "unsupported bset version %u", version); if (btree_err_on(version < c->sb.version_min, BTREE_ERR_FIXABLE, c, NULL, b, i, @@ -2019,9 +2017,7 @@ do_write: BUG_ON(BSET_BIG_ENDIAN(i) != CPU_BIG_ENDIAN); BUG_ON(i->seq != b->data->keys.seq); - i->version = c->sb.version < bcachefs_metadata_version_bkey_renumber - ? cpu_to_le16(BCH_BSET_VERSION_OLD) - : cpu_to_le16(c->sb.version); + i->version = cpu_to_le16(c->sb.version); SET_BSET_OFFSET(i, b->written); SET_BSET_CSUM_TYPE(i, bch2_meta_checksum_type(c)); diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index 7d0dd1b1d5cf..a084c6d0fe23 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -745,14 +745,10 @@ static int jset_validate(struct bch_fs *c, return JOURNAL_ENTRY_NONE; version = le32_to_cpu(jset->version); - if (journal_entry_err_on((version != BCH_JSET_VERSION_OLD && - version < bcachefs_metadata_version_min) || - version >= bcachefs_metadata_version_max, - c, jset, NULL, - "%s sector %llu seq %llu: unknown journal entry version %u", + if (journal_entry_err_on(!bch2_version_compatible(version), c, jset, NULL, + "%s sector %llu seq %llu: incompatible journal entry version %u", ca ? ca->name : c->name, - sector, le64_to_cpu(jset->seq), - version)) { + sector, le64_to_cpu(jset->seq), version)) { /* don't try to continue: */ return -EINVAL; } @@ -796,14 +792,10 @@ static int jset_validate_early(struct bch_fs *c, return JOURNAL_ENTRY_NONE; version = le32_to_cpu(jset->version); - if (journal_entry_err_on((version != BCH_JSET_VERSION_OLD && - version < bcachefs_metadata_version_min) || - version >= bcachefs_metadata_version_max, - c, jset, NULL, + if (journal_entry_err_on(!bch2_version_compatible(version), c, jset, NULL, "%s sector %llu seq %llu: unknown journal entry version %u", ca ? ca->name : c->name, - sector, le64_to_cpu(jset->seq), - version)) { + sector, le64_to_cpu(jset->seq), version)) { /* don't try to continue: */ return -EINVAL; } @@ -1755,9 +1747,7 @@ void bch2_journal_write(struct closure *cl) } jset->magic = cpu_to_le64(jset_magic(c)); - jset->version = c->sb.version < bcachefs_metadata_version_bkey_renumber - ? cpu_to_le32(BCH_JSET_VERSION_OLD) - : cpu_to_le32(c->sb.version); + jset->version = cpu_to_le32(c->sb.version); SET_JSET_BIG_ENDIAN(jset, CPU_BIG_ENDIAN); SET_JSET_CSUM_TYPE(jset, bch2_meta_checksum_type(c)); diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index 2237b1b94bbc..55a6c64de09c 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -269,40 +269,58 @@ static int validate_sb_layout(struct bch_sb_layout *layout, struct printbuf *out return 0; } -static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out, - int rw) +static int bch2_sb_compatible(struct bch_sb *sb, struct printbuf *out) { - struct bch_sb *sb = disk_sb->sb; - struct bch_sb_field *f; - struct bch_sb_field_members *mi; - enum bch_opt_id opt_id; - u32 version, version_min; - u16 block_size; - int ret; - - version = le16_to_cpu(sb->version); - version_min = version >= bcachefs_metadata_version_bkey_renumber - ? le16_to_cpu(sb->version_min) - : version; - - if (version >= bcachefs_metadata_version_max) { - prt_printf(out, "Unsupported superblock version %u (min %u, max %u)", - version, bcachefs_metadata_version_min, bcachefs_metadata_version_max); + u16 version = le16_to_cpu(sb->version); + u16 version_min = le16_to_cpu(sb->version_min); + + if (!bch2_version_compatible(version)) { + prt_str(out, "Unsupported superblock version "); + bch2_version_to_text(out, version); + prt_str(out, " (min "); + bch2_version_to_text(out, bcachefs_metadata_version_min); + prt_str(out, ", max "); + bch2_version_to_text(out, bcachefs_metadata_version_current); + prt_str(out, ")"); return -BCH_ERR_invalid_sb_version; } - if (version_min < bcachefs_metadata_version_min) { - prt_printf(out, "Unsupported superblock version %u (min %u, max %u)", - version_min, bcachefs_metadata_version_min, bcachefs_metadata_version_max); + if (!bch2_version_compatible(version_min)) { + prt_str(out, "Unsupported superblock version_min "); + bch2_version_to_text(out, version_min); + prt_str(out, " (min "); + bch2_version_to_text(out, bcachefs_metadata_version_min); + prt_str(out, ", max "); + bch2_version_to_text(out, bcachefs_metadata_version_current); + prt_str(out, ")"); return -BCH_ERR_invalid_sb_version; } if (version_min > version) { - prt_printf(out, "Bad minimum version %u, greater than version field %u", - version_min, version); + prt_str(out, "Bad minimum version "); + bch2_version_to_text(out, version_min); + prt_str(out, ", greater than version field "); + bch2_version_to_text(out, version); return -BCH_ERR_invalid_sb_version; } + return 0; +} + +static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out, + int rw) +{ + struct bch_sb *sb = disk_sb->sb; + struct bch_sb_field *f; + struct bch_sb_field_members *mi; + enum bch_opt_id opt_id; + u16 block_size; + int ret; + + ret = bch2_sb_compatible(sb, out); + if (ret) + return ret; + if (sb->features[1] || (le64_to_cpu(sb->features[0]) & (~0ULL << BCH_FEATURE_NR))) { prt_printf(out, "Filesystem has incompatible features"); @@ -350,7 +368,7 @@ static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out, if (rw == READ) { /* * Been seeing a bug where these are getting inexplicably - * zeroed, so we'r now validating them, but we have to be + * zeroed, so we're now validating them, but we have to be * careful not to preven people's filesystems from mounting: */ if (!BCH_SB_JOURNAL_FLUSH_DELAY(sb)) @@ -531,7 +549,6 @@ int bch2_sb_from_fs(struct bch_fs *c, struct bch_dev *ca) static int read_one_super(struct bch_sb_handle *sb, u64 offset, struct printbuf *err) { struct bch_csum csum; - u32 version, version_min; size_t bytes; int ret; reread: @@ -551,22 +568,9 @@ reread: return -BCH_ERR_invalid_sb_magic; } - version = le16_to_cpu(sb->sb->version); - version_min = version >= bcachefs_metadata_version_bkey_renumber - ? le16_to_cpu(sb->sb->version_min) - : version; - - if (version >= bcachefs_metadata_version_max) { - prt_printf(err, "Unsupported superblock version %u (min %u, max %u)", - version, bcachefs_metadata_version_min, bcachefs_metadata_version_max); - return -BCH_ERR_invalid_sb_version; - } - - if (version_min < bcachefs_metadata_version_min) { - prt_printf(err, "Unsupported superblock version %u (min %u, max %u)", - version_min, bcachefs_metadata_version_min, bcachefs_metadata_version_max); - return -BCH_ERR_invalid_sb_version; - } + ret = bch2_sb_compatible(sb->sb, err); + if (ret) + return ret; bytes = vstruct_bytes(sb->sb); diff --git a/fs/bcachefs/super-io.h b/fs/bcachefs/super-io.h index 4a193add3447..cda71ec845a5 100644 --- a/fs/bcachefs/super-io.h +++ b/fs/bcachefs/super-io.h @@ -9,6 +9,12 @@ #include +static inline bool bch2_version_compatible(u16 version) +{ + return version <= bcachefs_metadata_version_current && + version >= bcachefs_metadata_version_min; +} + void bch2_version_to_text(struct printbuf *, unsigned); struct bch_sb_field *bch2_sb_field_get(struct bch_sb *, enum bch_sb_field_type); -- cgit v1.2.3