bcachefs: bcachefs_metadata_version_disk_accounting_big_endian
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 29 Nov 2024 22:41:43 +0000 (17:41 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 29 Dec 2024 18:30:39 +0000 (13:30 -0500)
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>
fs/bcachefs/bcachefs_format.h
fs/bcachefs/disk_accounting.c
fs/bcachefs/disk_accounting.h
fs/bcachefs/sb-downgrade.c
fs/bcachefs/util.h

index e4bb74d6f439f4336d489ecac3a1978817e635b5..cef22c15c25650c1d102a3f5fda40c0bda691479 100644 (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,
index 22a7db63e50ce82ed2f032afb22b1f738937eb8e..72c8dcb9226f3bd0e94617f3525ccb68295c25bf 100644 (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);
 
index 2560de10b09dbf813c0ae93b891a9d51903612ac..fc1b673689c80e1f89f54bc61366f2834b65ae9b 100644 (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 *,
index 9879845413a694e640bf9cd82c6673a0dd087806..051214fdc73521dd2ab5b05609fdcc34caa34daa 100644 (file)
        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,                                \
          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;
index 5e4820c8fa44b8852ddfbf2cb6e0d869d017cb36..c292b9ce82406bb3d5857db78b681a04eb7459dc 100644 (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 */