bcachefs: bcachefs_metadata_version_disk_accounting_big_endian

Fix sort order for disk accounting keys, in order to fix a regression on
mount times.

The typetag is now the most significant byte of the key, meaning disk
accounting keys of the same type now sort together.

This lets us skip over disk accounting keys that aren't mirrored in
memory when reading accounting at startup, instead of having them
interleaved with other counter types.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-11-29 17:41:43 -05:00
parent ab7eb8e365
commit c6b74e6733
5 changed files with 51 additions and 15 deletions

View File

@ -679,7 +679,8 @@ struct bch_sb_field_ext {
x(disk_accounting_inum, BCH_VERSION(1, 11)) \
x(rebalance_work_acct_fix, BCH_VERSION(1, 12)) \
x(inode_has_child_snapshots, BCH_VERSION(1, 13)) \
x(backpointer_bucket_gen, BCH_VERSION(1, 14))
x(backpointer_bucket_gen, BCH_VERSION(1, 14)) \
x(disk_accounting_big_endian, BCH_VERSION(1, 15))
enum bcachefs_metadata_version {
bcachefs_metadata_version_min = 9,

View File

@ -698,8 +698,11 @@ int bch2_accounting_read(struct bch_fs *c)
percpu_memset(c->usage, 0, sizeof(*c->usage));
percpu_up_write(&c->mark_lock);
int ret = for_each_btree_key(trans, iter,
BTREE_ID_accounting, POS_MIN,
struct btree_iter iter;
bch2_trans_iter_init(trans, &iter, BTREE_ID_accounting, POS_MIN,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots);
iter.flags &= ~BTREE_ITER_with_journal;
int ret = for_each_btree_key_continue(trans, iter,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k, ({
struct bkey u;
struct bkey_s_c k = bch2_btree_path_peek_slot_exact(btree_iter_path(trans, &iter), &u);
@ -710,8 +713,14 @@ int bch2_accounting_read(struct bch_fs *c)
struct disk_accounting_pos acc_k;
bpos_to_disk_accounting_pos(&acc_k, k.k->p);
if (!bch2_accounting_is_mem(acc_k))
if (acc_k.type >= BCH_DISK_ACCOUNTING_TYPE_NR)
break;
if (!bch2_accounting_is_mem(acc_k)) {
struct disk_accounting_pos next = { .type = acc_k.type + 1 };
bch2_btree_iter_set_pos(&iter, disk_accounting_pos_to_bpos(&next));
continue;
}
accounting_read_key(trans, k);
}));
@ -896,10 +905,13 @@ void bch2_verify_accounting_clean(struct bch_fs *c)
bpos_to_disk_accounting_pos(&acc_k, k.k->p);
if (acc_k.type >= BCH_DISK_ACCOUNTING_TYPE_NR)
continue;
break;
if (acc_k.type == BCH_DISK_ACCOUNTING_inum)
if (!bch2_accounting_is_mem(acc_k)) {
struct disk_accounting_pos next = { .type = acc_k.type + 1 };
bch2_btree_iter_set_pos(&iter, disk_accounting_pos_to_bpos(&next));
continue;
}
bch2_accounting_mem_read(c, k.k->p, v, nr);

View File

@ -63,20 +63,24 @@ static inline void fs_usage_data_type_to_base(struct bch_fs_usage_base *fs_usage
static inline void bpos_to_disk_accounting_pos(struct disk_accounting_pos *acc, struct bpos p)
{
acc->_pad = p;
BUILD_BUG_ON(sizeof(*acc) != sizeof(p));
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
bch2_bpos_swab(&acc->_pad);
acc->_pad = p;
#else
memcpy_swab(acc, &p, sizeof(p));
#endif
}
static inline struct bpos disk_accounting_pos_to_bpos(struct disk_accounting_pos *k)
static inline struct bpos disk_accounting_pos_to_bpos(struct disk_accounting_pos *acc)
{
struct bpos ret = k->_pad;
struct bpos p;
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
bch2_bpos_swab(&ret);
p = acc->_pad;
#else
memcpy_swab(&p, acc, sizeof(p));
#endif
return ret;
return p;
}
int bch2_disk_accounting_mod(struct btree_trans *, struct disk_accounting_pos *,

View File

@ -85,7 +85,12 @@
x(backpointer_bucket_gen, \
BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers),\
BCH_FSCK_ERR_backpointer_to_missing_ptr, \
BCH_FSCK_ERR_ptr_to_missing_backpointer)
BCH_FSCK_ERR_ptr_to_missing_backpointer) \
x(disk_accounting_big_endian, \
BIT_ULL(BCH_RECOVERY_PASS_check_allocations), \
BCH_FSCK_ERR_accounting_mismatch, \
BCH_FSCK_ERR_accounting_key_replicas_nr_devs_0, \
BCH_FSCK_ERR_accounting_key_junk_at_end)
#define DOWNGRADE_TABLE() \
x(bucket_stripe_sectors, \
@ -128,7 +133,12 @@
BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers),\
BCH_FSCK_ERR_backpointer_bucket_offset_wrong, \
BCH_FSCK_ERR_backpointer_to_missing_ptr, \
BCH_FSCK_ERR_ptr_to_missing_backpointer)
BCH_FSCK_ERR_ptr_to_missing_backpointer) \
x(disk_accounting_big_endian, \
BIT_ULL(BCH_RECOVERY_PASS_check_allocations), \
BCH_FSCK_ERR_accounting_mismatch, \
BCH_FSCK_ERR_accounting_key_replicas_nr_devs_0, \
BCH_FSCK_ERR_accounting_key_junk_at_end)
struct upgrade_downgrade_entry {
u64 recovery_passes;

View File

@ -709,4 +709,13 @@ static inline bool test_bit_le64(size_t bit, __le64 *addr)
return (addr[bit / 64] & cpu_to_le64(BIT_ULL(bit % 64))) != 0;
}
static inline void memcpy_swab(void *_dst, void *_src, size_t len)
{
u8 *dst = _dst + len;
u8 *src = _src;
while (len--)
*--dst = *src++;
}
#endif /* _BCACHEFS_UTIL_H */