1 // SPDX-License-Identifier: GPL-2.0
4 #include "bkey_methods.h"
5 #include "btree_types.h"
6 #include "alloc_background.h"
16 const char * const bch2_bkey_types[] = {
17 #define x(name, nr) #name,
23 static const char *deleted_key_invalid(const struct bch_fs *c,
29 #define bch2_bkey_ops_deleted (struct bkey_ops) { \
30 .key_invalid = deleted_key_invalid, \
33 #define bch2_bkey_ops_discard (struct bkey_ops) { \
34 .key_invalid = deleted_key_invalid, \
37 static const char *empty_val_key_invalid(const struct bch_fs *c, struct bkey_s_c k)
39 if (bkey_val_bytes(k.k))
40 return "value size should be zero";
45 #define bch2_bkey_ops_error (struct bkey_ops) { \
46 .key_invalid = empty_val_key_invalid, \
49 static const char *key_type_cookie_invalid(const struct bch_fs *c,
52 if (bkey_val_bytes(k.k) != sizeof(struct bch_cookie))
53 return "incorrect value size";
58 #define bch2_bkey_ops_cookie (struct bkey_ops) { \
59 .key_invalid = key_type_cookie_invalid, \
62 #define bch2_bkey_ops_whiteout (struct bkey_ops) { \
63 .key_invalid = empty_val_key_invalid, \
66 static const char *key_type_inline_data_invalid(const struct bch_fs *c,
72 static void key_type_inline_data_to_text(struct printbuf *out, struct bch_fs *c,
75 pr_buf(out, "(%zu bytes)", bkey_val_bytes(k.k));
78 static const struct bkey_ops bch2_bkey_ops_inline_data = {
79 .key_invalid = key_type_inline_data_invalid,
80 .val_to_text = key_type_inline_data_to_text,
83 static const struct bkey_ops bch2_bkey_ops[] = {
84 #define x(name, nr) [KEY_TYPE_##name] = bch2_bkey_ops_##name,
89 const char *bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k)
91 if (k.k->type >= KEY_TYPE_MAX)
92 return "invalid type";
94 return bch2_bkey_ops[k.k->type].key_invalid(c, k);
97 const char *__bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
98 enum btree_node_type type)
100 if (k.k->u64s < BKEY_U64s)
101 return "u64s too small";
103 if (type == BKEY_TYPE_BTREE &&
104 bkey_val_u64s(k.k) > BKEY_BTREE_PTR_VAL_U64s_MAX)
105 return "value too big";
107 if (btree_node_type_is_extents(type)) {
108 if ((k.k->size == 0) != bkey_deleted(k.k))
109 return "bad size field";
111 if (k.k->size > k.k->p.offset)
112 return "size greater than offset";
115 return "nonzero size field";
119 return "nonzero snapshot";
121 if (type != BKEY_TYPE_BTREE &&
122 !bkey_cmp(k.k->p, POS_MAX))
123 return "POS_MAX key";
128 const char *bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
129 enum btree_node_type type)
131 return __bch2_bkey_invalid(c, k, type) ?:
132 bch2_bkey_val_invalid(c, k);
135 const char *bch2_bkey_in_btree_node(struct btree *b, struct bkey_s_c k)
137 if (bkey_cmp(bkey_start_pos(k.k), b->data->min_key) < 0)
138 return "key before start of btree node";
140 if (bkey_cmp(k.k->p, b->data->max_key) > 0)
141 return "key past end of btree node";
146 void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
148 const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
153 invalid = bch2_bkey_invalid(c, k, btree_node_type(b)) ?:
154 bch2_bkey_in_btree_node(b, k);
158 bch2_bkey_val_to_text(&PBUF(buf), c, k);
159 bch2_fs_bug(c, "invalid bkey %s: %s", buf, invalid);
163 if (ops->key_debugcheck)
164 ops->key_debugcheck(c, k);
167 void bch2_bpos_to_text(struct printbuf *out, struct bpos pos)
169 if (!bkey_cmp(pos, POS_MIN))
170 pr_buf(out, "POS_MIN");
171 else if (!bkey_cmp(pos, POS_MAX))
172 pr_buf(out, "POS_MAX");
174 pr_buf(out, "%llu:%llu", pos.inode, pos.offset);
177 void bch2_bkey_to_text(struct printbuf *out, const struct bkey *k)
179 pr_buf(out, "u64s %u type %s ", k->u64s,
180 bch2_bkey_types[k->type]);
182 bch2_bpos_to_text(out, k->p);
184 pr_buf(out, " snap %u len %u ver %llu",
185 k->p.snapshot, k->size, k->version.lo);
188 void bch2_val_to_text(struct printbuf *out, struct bch_fs *c,
191 const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
193 if (likely(ops->val_to_text))
194 ops->val_to_text(out, c, k);
197 void bch2_bkey_val_to_text(struct printbuf *out, struct bch_fs *c,
200 bch2_bkey_to_text(out, k.k);
202 bch2_val_to_text(out, c, k);
205 void bch2_bkey_swab(const struct bkey_format *f,
206 struct bkey_packed *k)
208 const struct bkey_ops *ops = &bch2_bkey_ops[k->type];
210 bch2_bkey_swab_key(f, k);
216 bool bch2_bkey_normalize(struct bch_fs *c, struct bkey_s k)
218 const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
220 return ops->key_normalize
221 ? ops->key_normalize(c, k)
225 enum merge_result bch2_bkey_merge(struct bch_fs *c,
226 struct bkey_s l, struct bkey_s r)
228 const struct bkey_ops *ops = &bch2_bkey_ops[l.k->type];
229 enum merge_result ret;
231 if (key_merging_disabled(c) ||
233 l.k->type != r.k->type ||
234 bversion_cmp(l.k->version, r.k->version) ||
235 bkey_cmp(l.k->p, bkey_start_pos(r.k)))
236 return BCH_MERGE_NOMERGE;
238 ret = ops->key_merge(c, l, r);
240 if (ret != BCH_MERGE_NOMERGE)
241 l.k->needs_whiteout |= r.k->needs_whiteout;
245 static const struct old_bkey_type {
249 } bkey_renumber_table[] = {
250 {BKEY_TYPE_BTREE, 128, KEY_TYPE_btree_ptr },
251 {BKEY_TYPE_EXTENTS, 128, KEY_TYPE_extent },
252 {BKEY_TYPE_EXTENTS, 129, KEY_TYPE_extent },
253 {BKEY_TYPE_EXTENTS, 130, KEY_TYPE_reservation },
254 {BKEY_TYPE_INODES, 128, KEY_TYPE_inode },
255 {BKEY_TYPE_INODES, 130, KEY_TYPE_inode_generation },
256 {BKEY_TYPE_DIRENTS, 128, KEY_TYPE_dirent },
257 {BKEY_TYPE_DIRENTS, 129, KEY_TYPE_whiteout },
258 {BKEY_TYPE_XATTRS, 128, KEY_TYPE_xattr },
259 {BKEY_TYPE_XATTRS, 129, KEY_TYPE_whiteout },
260 {BKEY_TYPE_ALLOC, 128, KEY_TYPE_alloc },
261 {BKEY_TYPE_QUOTAS, 128, KEY_TYPE_quota },
264 void bch2_bkey_renumber(enum btree_node_type btree_node_type,
265 struct bkey_packed *k,
268 const struct old_bkey_type *i;
270 for (i = bkey_renumber_table;
271 i < bkey_renumber_table + ARRAY_SIZE(bkey_renumber_table);
273 if (btree_node_type == i->btree_node_type &&
274 k->type == (write ? i->new : i->old)) {
275 k->type = write ? i->old : i->new;