#define __BKEY_PADDED(key, pad)                                        \
        struct bkey_i key; __u64 key ## _pad[pad]
 
+enum bch_bkey_type_flags {
+       BKEY_TYPE_strict_btree_checks   = BIT(0),
+};
+
 /*
  * - DELETED keys are used internally to mark keys that should be ignored but
  *   override keys in composition order.  Their version number is ignored.
  *
  * - WHITEOUT: for hash table btrees
  */
-#define BCH_BKEY_TYPES()                               \
-       x(deleted,              0)                      \
-       x(whiteout,             1)                      \
-       x(error,                2)                      \
-       x(cookie,               3)                      \
-       x(hash_whiteout,        4)                      \
-       x(btree_ptr,            5)                      \
-       x(extent,               6)                      \
-       x(reservation,          7)                      \
-       x(inode,                8)                      \
-       x(inode_generation,     9)                      \
-       x(dirent,               10)                     \
-       x(xattr,                11)                     \
-       x(alloc,                12)                     \
-       x(quota,                13)                     \
-       x(stripe,               14)                     \
-       x(reflink_p,            15)                     \
-       x(reflink_v,            16)                     \
-       x(inline_data,          17)                     \
-       x(btree_ptr_v2,         18)                     \
-       x(indirect_inline_data, 19)                     \
-       x(alloc_v2,             20)                     \
-       x(subvolume,            21)                     \
-       x(snapshot,             22)                     \
-       x(inode_v2,             23)                     \
-       x(alloc_v3,             24)                     \
-       x(set,                  25)                     \
-       x(lru,                  26)                     \
-       x(alloc_v4,             27)                     \
-       x(backpointer,          28)                     \
-       x(inode_v3,             29)                     \
-       x(bucket_gens,          30)                     \
-       x(snapshot_tree,        31)                     \
-       x(logged_op_truncate,   32)                     \
-       x(logged_op_finsert,    33)                     \
-       x(accounting,           34)                     \
-       x(inode_alloc_cursor,   35)
+#define BCH_BKEY_TYPES()                                               \
+       x(deleted,              0,      0)                              \
+       x(whiteout,             1,      0)                              \
+       x(error,                2,      0)                              \
+       x(cookie,               3,      0)                              \
+       x(hash_whiteout,        4,      BKEY_TYPE_strict_btree_checks)  \
+       x(btree_ptr,            5,      BKEY_TYPE_strict_btree_checks)  \
+       x(extent,               6,      BKEY_TYPE_strict_btree_checks)  \
+       x(reservation,          7,      BKEY_TYPE_strict_btree_checks)  \
+       x(inode,                8,      BKEY_TYPE_strict_btree_checks)  \
+       x(inode_generation,     9,      BKEY_TYPE_strict_btree_checks)  \
+       x(dirent,               10,     BKEY_TYPE_strict_btree_checks)  \
+       x(xattr,                11,     BKEY_TYPE_strict_btree_checks)  \
+       x(alloc,                12,     BKEY_TYPE_strict_btree_checks)  \
+       x(quota,                13,     BKEY_TYPE_strict_btree_checks)  \
+       x(stripe,               14,     BKEY_TYPE_strict_btree_checks)  \
+       x(reflink_p,            15,     BKEY_TYPE_strict_btree_checks)  \
+       x(reflink_v,            16,     BKEY_TYPE_strict_btree_checks)  \
+       x(inline_data,          17,     BKEY_TYPE_strict_btree_checks)  \
+       x(btree_ptr_v2,         18,     BKEY_TYPE_strict_btree_checks)  \
+       x(indirect_inline_data, 19,     BKEY_TYPE_strict_btree_checks)  \
+       x(alloc_v2,             20,     BKEY_TYPE_strict_btree_checks)  \
+       x(subvolume,            21,     BKEY_TYPE_strict_btree_checks)  \
+       x(snapshot,             22,     BKEY_TYPE_strict_btree_checks)  \
+       x(inode_v2,             23,     BKEY_TYPE_strict_btree_checks)  \
+       x(alloc_v3,             24,     BKEY_TYPE_strict_btree_checks)  \
+       x(set,                  25,     0)                              \
+       x(lru,                  26,     BKEY_TYPE_strict_btree_checks)  \
+       x(alloc_v4,             27,     BKEY_TYPE_strict_btree_checks)  \
+       x(backpointer,          28,     BKEY_TYPE_strict_btree_checks)  \
+       x(inode_v3,             29,     BKEY_TYPE_strict_btree_checks)  \
+       x(bucket_gens,          30,     BKEY_TYPE_strict_btree_checks)  \
+       x(snapshot_tree,        31,     BKEY_TYPE_strict_btree_checks)  \
+       x(logged_op_truncate,   32,     BKEY_TYPE_strict_btree_checks)  \
+       x(logged_op_finsert,    33,     BKEY_TYPE_strict_btree_checks)  \
+       x(accounting,           34,     BKEY_TYPE_strict_btree_checks)  \
+       x(inode_alloc_cursor,   35,     BKEY_TYPE_strict_btree_checks)
 
 enum bch_bkey_type {
-#define x(name, nr) KEY_TYPE_##name    = nr,
+#define x(name, nr, ...) KEY_TYPE_##name       = nr,
        BCH_BKEY_TYPES()
 #undef x
        KEY_TYPE_MAX,
 
 #include "xattr.h"
 
 const char * const bch2_bkey_types[] = {
-#define x(name, nr) #name,
+#define x(name, nr, ...) #name,
        BCH_BKEY_TYPES()
 #undef x
        NULL
 })
 
 const struct bkey_ops bch2_bkey_ops[] = {
-#define x(name, nr) [KEY_TYPE_##name]  = bch2_bkey_ops_##name,
+#define x(name, nr, ...) [KEY_TYPE_##name]     = bch2_bkey_ops_##name,
        BCH_BKEY_TYPES()
 #undef x
 };
 #undef x
 };
 
+static const enum bch_bkey_type_flags bch2_bkey_type_flags[] = {
+#define x(name, nr, flags)     [KEY_TYPE_##name] = flags,
+       BCH_BKEY_TYPES()
+#undef x
+};
+
 const char *bch2_btree_node_type_str(enum btree_node_type type)
 {
        return type == BKEY_TYPE_btree ? "internal btree node" : bch2_btree_id_str(type - 1);
        if (type >= BKEY_TYPE_NR)
                return 0;
 
-       bkey_fsck_err_on(k.k->type < KEY_TYPE_MAX &&
-                        (type == BKEY_TYPE_btree || (from.flags & BCH_VALIDATE_commit)) &&
+       enum bch_bkey_type_flags bkey_flags = k.k->type < KEY_TYPE_MAX
+               ? bch2_bkey_type_flags[k.k->type]
+               : 0;
+
+       bool strict_key_type_allowed =
+               (from.flags & BCH_VALIDATE_commit) ||
+               type == BKEY_TYPE_btree ||
+               (from.btree < BTREE_ID_NR &&
+                (bkey_flags & BKEY_TYPE_strict_btree_checks));
+
+       bkey_fsck_err_on(strict_key_type_allowed &&
+                        k.k->type < KEY_TYPE_MAX &&
                         !(bch2_key_types_allowed[type] & BIT_ULL(k.k->type)),
                         c, bkey_invalid_type_for_btree,
                         "invalid key type for btree %s (%s)",