mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2026-01-06 02:26:17 +00:00
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 <kent.overstreet@linux.dev>
This commit is contained in:
parent
e3804b55e4
commit
a02a0121b3
@ -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 @@ 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));
|
||||
|
||||
|
||||
@ -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,6 +269,44 @@ static int validate_sb_layout(struct bch_sb_layout *layout, struct printbuf *out
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bch2_sb_compatible(struct bch_sb *sb, struct printbuf *out)
|
||||
{
|
||||
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 (!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_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)
|
||||
{
|
||||
@ -276,32 +314,12 @@ static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out,
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
return -BCH_ERR_invalid_sb_version;
|
||||
}
|
||||
ret = bch2_sb_compatible(sb, out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (sb->features[1] ||
|
||||
(le64_to_cpu(sb->features[0]) & (~0ULL << BCH_FEATURE_NR))) {
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user