1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _BCACHEFS_BKEY_TYPES_H
3 #define _BCACHEFS_BKEY_TYPES_H
4
5 #include "bcachefs_format.h"
6
7 /*
8 * bkey_i - bkey with inline value
9 * bkey_s - bkey with split value
10 * bkey_s_c - bkey with split value, const
11 */
12
13 #define bkey_p_next(_k) vstruct_next(_k)
14
bkey_next(struct bkey_i * k)15 static 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
bkey_val_bytes(const struct bkey * k)22 static inline size_t bkey_val_bytes(const struct bkey *k)
23 {
24 return bkey_val_u64s(k) * sizeof(u64);
25 }
26
set_bkey_val_u64s(struct bkey * k,unsigned val_u64s)27 static 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
set_bkey_val_bytes(struct bkey * k,unsigned bytes)35 static 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 */
48 struct bkey_s_c {
49 const struct bkey *k;
50 const struct bch_val *v;
51 };
52
53 /* bkey with split value */
54 struct 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
bkey_to_s(struct bkey * k)70 static inline struct bkey_s bkey_to_s(struct bkey *k)
71 {
72 return (struct bkey_s) { .k = k, .v = NULL };
73 }
74
bkey_to_s_c(const struct bkey * k)75 static 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
bkey_i_to_s(struct bkey_i * k)80 static 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
bkey_i_to_s_c(const struct bkey_i * k)85 static 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 for
92 * bkey + bch_extent - inline, split, split const - and also all the conversion
93 * 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. a
96 * bkey_i_extent to a bkey_i - since that's always safe, instead of conversion
97 * functions.
98 */
99 #define x(name, ...) \
100 struct bkey_i_##name { \
101 union { \
102 struct bkey k; \
103 struct bkey_i k_i; \
104 }; \
105 struct bch_##name v; \
106 }; \
107 \
108 struct 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 \
118 struct 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 \
130 static 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 \
136 static inline const struct bkey_i_##name * \
137 bkey_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 \
143 static 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 \
152 static 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 \
161 static 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 \
169 static inline struct bkey_s_c_##name \
170 name##_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 \
178 static 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 \
187 static inline struct bkey_s_c_##name \
188 bkey_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 \
197 static 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
210 BCH_BKEY_TYPES();
211 #undef x
212
213 #endif /* _BCACHEFS_BKEY_TYPES_H */
214