Skip to content

Commit 4a4f9b5

Browse files
author
Kent Overstreet
committed
bcachefs: Don't set BCH_FEATURE_incompat_version_field unless requested
We shouldn't be setting incompatible bits or the incompatible version field unless explicitly request or allowed - otherwise we break mounting with old kernels or userspace. Reported-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent eb54d26 commit 4a4f9b5

File tree

2 files changed

+20
-15
lines changed

2 files changed

+20
-15
lines changed

fs/bcachefs/super-io.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,20 @@ enum bcachefs_metadata_version bch2_latest_compatible_version(enum bcachefs_meta
6969
return v;
7070
}
7171

72-
void bch2_set_version_incompat(struct bch_fs *c, enum bcachefs_metadata_version version)
72+
bool bch2_set_version_incompat(struct bch_fs *c, enum bcachefs_metadata_version version)
7373
{
74-
mutex_lock(&c->sb_lock);
75-
SET_BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb,
76-
max(BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb), version));
77-
c->disk_sb.sb->features[0] |= cpu_to_le64(BCH_FEATURE_incompat_version_field);
78-
bch2_write_super(c);
79-
mutex_unlock(&c->sb_lock);
74+
bool ret = (c->sb.features & BIT_ULL(BCH_FEATURE_incompat_version_field)) &&
75+
version <= c->sb.version_incompat_allowed;
76+
77+
if (ret) {
78+
mutex_lock(&c->sb_lock);
79+
SET_BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb,
80+
max(BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb), version));
81+
bch2_write_super(c);
82+
mutex_unlock(&c->sb_lock);
83+
}
84+
85+
return ret;
8086
}
8187

8288
const char * const bch2_sb_fields[] = {
@@ -1219,9 +1225,11 @@ void bch2_sb_upgrade(struct bch_fs *c, unsigned new_version, bool incompat)
12191225
c->disk_sb.sb->version = cpu_to_le16(new_version);
12201226
c->disk_sb.sb->features[0] |= cpu_to_le64(BCH_SB_FEATURES_ALL);
12211227

1222-
if (incompat)
1228+
if (incompat) {
12231229
SET_BCH_SB_VERSION_INCOMPAT_ALLOWED(c->disk_sb.sb,
12241230
max(BCH_SB_VERSION_INCOMPAT_ALLOWED(c->disk_sb.sb), new_version));
1231+
c->disk_sb.sb->features[0] |= cpu_to_le64(BCH_FEATURE_incompat_version_field);
1232+
}
12251233
}
12261234

12271235
static int bch2_sb_ext_validate(struct bch_sb *sb, struct bch_sb_field *f,

fs/bcachefs/super-io.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,14 @@ static inline bool bch2_version_compatible(u16 version)
2121
void bch2_version_to_text(struct printbuf *, enum bcachefs_metadata_version);
2222
enum bcachefs_metadata_version bch2_latest_compatible_version(enum bcachefs_metadata_version);
2323

24-
void bch2_set_version_incompat(struct bch_fs *, enum bcachefs_metadata_version);
24+
bool bch2_set_version_incompat(struct bch_fs *, enum bcachefs_metadata_version);
2525

2626
static inline bool bch2_request_incompat_feature(struct bch_fs *c,
2727
enum bcachefs_metadata_version version)
2828
{
29-
if (unlikely(version > c->sb.version_incompat)) {
30-
if (version > c->sb.version_incompat_allowed)
31-
return false;
32-
bch2_set_version_incompat(c, version);
33-
}
34-
return true;
29+
return likely(version <= c->sb.version_incompat)
30+
? true
31+
: bch2_set_version_incompat(c, version);
3532
}
3633

3734
static inline size_t bch2_sb_field_bytes(struct bch_sb_field *f)

0 commit comments

Comments
 (0)