Skip to content

Commit 8ed823b

Browse files
author
Kent Overstreet
committed
bcachefs: Fix compat issue with old alloc_v4 keys
we allow new fields to be added to existing key types, and new versions should treat them as being zeroed; this was not handled in alloc_v4_validate. Reported-by: [email protected] Signed-off-by: Kent Overstreet <[email protected]>
1 parent 7f2de69 commit 8ed823b

File tree

3 files changed

+36
-24
lines changed

3 files changed

+36
-24
lines changed

fs/bcachefs/alloc_background.c

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -240,71 +240,73 @@ int bch2_alloc_v3_validate(struct bch_fs *c, struct bkey_s_c k,
240240
int bch2_alloc_v4_validate(struct bch_fs *c, struct bkey_s_c k,
241241
enum bch_validate_flags flags)
242242
{
243-
struct bkey_s_c_alloc_v4 a = bkey_s_c_to_alloc_v4(k);
243+
struct bch_alloc_v4 a;
244244
int ret = 0;
245245

246-
bkey_fsck_err_on(alloc_v4_u64s_noerror(a.v) > bkey_val_u64s(k.k),
246+
bkey_val_copy(&a, bkey_s_c_to_alloc_v4(k));
247+
248+
bkey_fsck_err_on(alloc_v4_u64s_noerror(&a) > bkey_val_u64s(k.k),
247249
c, alloc_v4_val_size_bad,
248250
"bad val size (%u > %zu)",
249-
alloc_v4_u64s_noerror(a.v), bkey_val_u64s(k.k));
251+
alloc_v4_u64s_noerror(&a), bkey_val_u64s(k.k));
250252

251-
bkey_fsck_err_on(!BCH_ALLOC_V4_BACKPOINTERS_START(a.v) &&
252-
BCH_ALLOC_V4_NR_BACKPOINTERS(a.v),
253+
bkey_fsck_err_on(!BCH_ALLOC_V4_BACKPOINTERS_START(&a) &&
254+
BCH_ALLOC_V4_NR_BACKPOINTERS(&a),
253255
c, alloc_v4_backpointers_start_bad,
254256
"invalid backpointers_start");
255257

256-
bkey_fsck_err_on(alloc_data_type(*a.v, a.v->data_type) != a.v->data_type,
258+
bkey_fsck_err_on(alloc_data_type(a, a.data_type) != a.data_type,
257259
c, alloc_key_data_type_bad,
258260
"invalid data type (got %u should be %u)",
259-
a.v->data_type, alloc_data_type(*a.v, a.v->data_type));
261+
a.data_type, alloc_data_type(a, a.data_type));
260262

261263
for (unsigned i = 0; i < 2; i++)
262-
bkey_fsck_err_on(a.v->io_time[i] > LRU_TIME_MAX,
264+
bkey_fsck_err_on(a.io_time[i] > LRU_TIME_MAX,
263265
c, alloc_key_io_time_bad,
264266
"invalid io_time[%s]: %llu, max %llu",
265267
i == READ ? "read" : "write",
266-
a.v->io_time[i], LRU_TIME_MAX);
268+
a.io_time[i], LRU_TIME_MAX);
267269

268-
unsigned stripe_sectors = BCH_ALLOC_V4_BACKPOINTERS_START(a.v) * sizeof(u64) >
270+
unsigned stripe_sectors = BCH_ALLOC_V4_BACKPOINTERS_START(&a) * sizeof(u64) >
269271
offsetof(struct bch_alloc_v4, stripe_sectors)
270-
? a.v->stripe_sectors
272+
? a.stripe_sectors
271273
: 0;
272274

273-
switch (a.v->data_type) {
275+
switch (a.data_type) {
274276
case BCH_DATA_free:
275277
case BCH_DATA_need_gc_gens:
276278
case BCH_DATA_need_discard:
277279
bkey_fsck_err_on(stripe_sectors ||
278-
a.v->dirty_sectors ||
279-
a.v->cached_sectors ||
280-
a.v->stripe,
280+
a.dirty_sectors ||
281+
a.cached_sectors ||
282+
a.stripe,
281283
c, alloc_key_empty_but_have_data,
282284
"empty data type free but have data %u.%u.%u %u",
283285
stripe_sectors,
284-
a.v->dirty_sectors,
285-
a.v->cached_sectors,
286-
a.v->stripe);
286+
a.dirty_sectors,
287+
a.cached_sectors,
288+
a.stripe);
287289
break;
288290
case BCH_DATA_sb:
289291
case BCH_DATA_journal:
290292
case BCH_DATA_btree:
291293
case BCH_DATA_user:
292294
case BCH_DATA_parity:
293-
bkey_fsck_err_on(!a.v->dirty_sectors &&
295+
bkey_fsck_err_on(!a.dirty_sectors &&
294296
!stripe_sectors,
295297
c, alloc_key_dirty_sectors_0,
296298
"data_type %s but dirty_sectors==0",
297-
bch2_data_type_str(a.v->data_type));
299+
bch2_data_type_str(a.data_type));
298300
break;
299301
case BCH_DATA_cached:
300-
bkey_fsck_err_on(!a.v->cached_sectors ||
301-
a.v->dirty_sectors ||
302+
bkey_fsck_err_on(!a.cached_sectors ||
303+
a.dirty_sectors ||
302304
stripe_sectors ||
303-
a.v->stripe,
305+
a.stripe,
304306
c, alloc_key_cached_inconsistency,
305307
"data type inconsistency");
306308

307-
bkey_fsck_err_on(!a.v->io_time[READ] &&
309+
bkey_fsck_err_on(!a.io_time[READ] &&
308310
c->curr_recovery_pass > BCH_RECOVERY_PASS_check_alloc_to_lru_refs,
309311
c, alloc_key_cached_but_read_time_zero,
310312
"cached bucket with read_time == 0");

fs/bcachefs/alloc_background_format.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct bch_alloc_v4 {
6969
__u64 io_time[2];
7070
__u32 stripe;
7171
__u32 nr_external_backpointers;
72+
/* end of fields in original version of alloc_v4 */
7273
__u64 fragmentation_lru;
7374
__u32 stripe_sectors;
7475
__u32 pad;

fs/bcachefs/btree_iter.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,15 @@ static inline struct bkey_s_c bch2_bkey_get_iter(struct btree_trans *trans,
569569
bkey_s_c_to_##_type(__bch2_bkey_get_iter(_trans, _iter, \
570570
_btree_id, _pos, _flags, KEY_TYPE_##_type))
571571

572+
#define bkey_val_copy(_dst_v, _src_k) \
573+
do { \
574+
unsigned b = min_t(unsigned, sizeof(*_dst_v), \
575+
bkey_val_bytes(_src_k.k)); \
576+
memcpy(_dst_v, _src_k.v, b); \
577+
if (b < sizeof(*_dst_v)) \
578+
memset((void *) (_dst_v) + b, 0, sizeof(*_dst_v) - b); \
579+
} while (0)
580+
572581
static inline int __bch2_bkey_get_val_typed(struct btree_trans *trans,
573582
unsigned btree_id, struct bpos pos,
574583
unsigned flags, unsigned type,

0 commit comments

Comments
 (0)