214 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2#ifndef _BCACHEFS_BKEY_TYPES_H3#define _BCACHEFS_BKEY_TYPES_H4 5#include "bcachefs_format.h"6 7/*8 * bkey_i - bkey with inline value9 * bkey_s - bkey with split value10 * bkey_s_c - bkey with split value, const11 */12 13#define bkey_p_next(_k) vstruct_next(_k)14 15static inline struct bkey_i *bkey_next(struct bkey_i *k)16{17 return (struct bkey_i *) ((u64 *) k->_data + k->k.u64s);18}19 20#define bkey_val_u64s(_k) ((_k)->u64s - BKEY_U64s)21 22static inline size_t bkey_val_bytes(const struct bkey *k)23{24 return bkey_val_u64s(k) * sizeof(u64);25}26 27static inline void set_bkey_val_u64s(struct bkey *k, unsigned val_u64s)28{29 unsigned u64s = BKEY_U64s + val_u64s;30 31 BUG_ON(u64s > U8_MAX);32 k->u64s = u64s;33}34 35static inline void set_bkey_val_bytes(struct bkey *k, unsigned bytes)36{37 set_bkey_val_u64s(k, DIV_ROUND_UP(bytes, sizeof(u64)));38}39 40#define bkey_val_end(_k) ((void *) (((u64 *) (_k).v) + bkey_val_u64s((_k).k)))41 42#define bkey_deleted(_k) ((_k)->type == KEY_TYPE_deleted)43 44#define bkey_whiteout(_k) \45 ((_k)->type == KEY_TYPE_deleted || (_k)->type == KEY_TYPE_whiteout)46 47/* bkey with split value, const */48struct bkey_s_c {49 const struct bkey *k;50 const struct bch_val *v;51};52 53/* bkey with split value */54struct bkey_s {55 union {56 struct {57 struct bkey *k;58 struct bch_val *v;59 };60 struct bkey_s_c s_c;61 };62};63 64#define bkey_s_null ((struct bkey_s) { .k = NULL })65#define bkey_s_c_null ((struct bkey_s_c) { .k = NULL })66 67#define bkey_s_err(err) ((struct bkey_s) { .k = ERR_PTR(err) })68#define bkey_s_c_err(err) ((struct bkey_s_c) { .k = ERR_PTR(err) })69 70static inline struct bkey_s bkey_to_s(struct bkey *k)71{72 return (struct bkey_s) { .k = k, .v = NULL };73}74 75static inline struct bkey_s_c bkey_to_s_c(const struct bkey *k)76{77 return (struct bkey_s_c) { .k = k, .v = NULL };78}79 80static inline struct bkey_s bkey_i_to_s(struct bkey_i *k)81{82 return (struct bkey_s) { .k = &k->k, .v = &k->v };83}84 85static inline struct bkey_s_c bkey_i_to_s_c(const struct bkey_i *k)86{87 return (struct bkey_s_c) { .k = &k->k, .v = &k->v };88}89 90/*91 * For a given type of value (e.g. struct bch_extent), generates the types for92 * bkey + bch_extent - inline, split, split const - and also all the conversion93 * functions, which also check that the value is of the correct type.94 *95 * We use anonymous unions for upcasting - e.g. converting from e.g. a96 * bkey_i_extent to a bkey_i - since that's always safe, instead of conversion97 * functions.98 */99#define x(name, ...) \100struct bkey_i_##name { \101 union { \102 struct bkey k; \103 struct bkey_i k_i; \104 }; \105 struct bch_##name v; \106}; \107 \108struct bkey_s_c_##name { \109 union { \110 struct { \111 const struct bkey *k; \112 const struct bch_##name *v; \113 }; \114 struct bkey_s_c s_c; \115 }; \116}; \117 \118struct bkey_s_##name { \119 union { \120 struct { \121 struct bkey *k; \122 struct bch_##name *v; \123 }; \124 struct bkey_s_c_##name c; \125 struct bkey_s s; \126 struct bkey_s_c s_c; \127 }; \128}; \129 \130static inline struct bkey_i_##name *bkey_i_to_##name(struct bkey_i *k) \131{ \132 EBUG_ON(!IS_ERR_OR_NULL(k) && k->k.type != KEY_TYPE_##name); \133 return container_of(&k->k, struct bkey_i_##name, k); \134} \135 \136static inline const struct bkey_i_##name * \137bkey_i_to_##name##_c(const struct bkey_i *k) \138{ \139 EBUG_ON(!IS_ERR_OR_NULL(k) && k->k.type != KEY_TYPE_##name); \140 return container_of(&k->k, struct bkey_i_##name, k); \141} \142 \143static inline struct bkey_s_##name bkey_s_to_##name(struct bkey_s k) \144{ \145 EBUG_ON(!IS_ERR_OR_NULL(k.k) && k.k->type != KEY_TYPE_##name); \146 return (struct bkey_s_##name) { \147 .k = k.k, \148 .v = container_of(k.v, struct bch_##name, v), \149 }; \150} \151 \152static inline struct bkey_s_c_##name bkey_s_c_to_##name(struct bkey_s_c k)\153{ \154 EBUG_ON(!IS_ERR_OR_NULL(k.k) && k.k->type != KEY_TYPE_##name); \155 return (struct bkey_s_c_##name) { \156 .k = k.k, \157 .v = container_of(k.v, struct bch_##name, v), \158 }; \159} \160 \161static inline struct bkey_s_##name name##_i_to_s(struct bkey_i_##name *k)\162{ \163 return (struct bkey_s_##name) { \164 .k = &k->k, \165 .v = &k->v, \166 }; \167} \168 \169static inline struct bkey_s_c_##name \170name##_i_to_s_c(const struct bkey_i_##name *k) \171{ \172 return (struct bkey_s_c_##name) { \173 .k = &k->k, \174 .v = &k->v, \175 }; \176} \177 \178static inline struct bkey_s_##name bkey_i_to_s_##name(struct bkey_i *k) \179{ \180 EBUG_ON(!IS_ERR_OR_NULL(k) && k->k.type != KEY_TYPE_##name); \181 return (struct bkey_s_##name) { \182 .k = &k->k, \183 .v = container_of(&k->v, struct bch_##name, v), \184 }; \185} \186 \187static inline struct bkey_s_c_##name \188bkey_i_to_s_c_##name(const struct bkey_i *k) \189{ \190 EBUG_ON(!IS_ERR_OR_NULL(k) && k->k.type != KEY_TYPE_##name); \191 return (struct bkey_s_c_##name) { \192 .k = &k->k, \193 .v = container_of(&k->v, struct bch_##name, v), \194 }; \195} \196 \197static inline struct bkey_i_##name *bkey_##name##_init(struct bkey_i *_k)\198{ \199 struct bkey_i_##name *k = \200 container_of(&_k->k, struct bkey_i_##name, k); \201 \202 bkey_init(&k->k); \203 memset(&k->v, 0, sizeof(k->v)); \204 k->k.type = KEY_TYPE_##name; \205 set_bkey_val_bytes(&k->k, sizeof(k->v)); \206 \207 return k; \208}209 210BCH_BKEY_TYPES();211#undef x212 213#endif /* _BCACHEFS_BKEY_TYPES_H */214