Commit a02a0121 authored by Kent Overstreet's avatar Kent Overstreet

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: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent e3804b55
......@@ -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) \
......
......@@ -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 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b, unsigned flags)
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));
......
......@@ -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));
......
......@@ -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 @@ static int read_one_super(struct bch_sb_handle *sb, u64 offset, struct printbuf
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);
......
......@@ -9,6 +9,12 @@
#include <asm/byteorder.h>
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);
......
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