GNU Linux-libre 6.9.1-gnu
[releases.git] / fs / bcachefs / bkey_types.h
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
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
22 static inline size_t bkey_val_bytes(const struct bkey *k)
23 {
24         return bkey_val_u64s(k) * sizeof(u64);
25 }
26
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
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
70 static inline struct bkey_s bkey_to_s(struct bkey *k)
71 {
72         return (struct bkey_s) { .k = k, .v = NULL };
73 }
74
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
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
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 */