]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/bkey_methods.c
27f196ef0b186963df59c6523479db6593e11eee
[bcachefs-tools-debian] / libbcachefs / bkey_methods.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include "bcachefs.h"
4 #include "bkey_methods.h"
5 #include "btree_types.h"
6 #include "alloc_background.h"
7 #include "dirent.h"
8 #include "ec.h"
9 #include "error.h"
10 #include "extents.h"
11 #include "inode.h"
12 #include "quota.h"
13 #include "xattr.h"
14
15 const char * const bch_bkey_types[] = {
16 #define x(name, nr) #name,
17         BCH_BKEY_TYPES()
18 #undef x
19         NULL
20 };
21
22 static const char *deleted_key_invalid(const struct bch_fs *c,
23                                         struct bkey_s_c k)
24 {
25         return NULL;
26 }
27
28 #define bch2_bkey_ops_deleted (struct bkey_ops) {       \
29         .key_invalid = deleted_key_invalid,             \
30 }
31
32 #define bch2_bkey_ops_discard (struct bkey_ops) {       \
33         .key_invalid = deleted_key_invalid,             \
34 }
35
36 static const char *empty_val_key_invalid(const struct bch_fs *c, struct bkey_s_c k)
37 {
38         if (bkey_val_bytes(k.k))
39                 return "value size should be zero";
40
41         return NULL;
42 }
43
44 #define bch2_bkey_ops_error (struct bkey_ops) {         \
45         .key_invalid = empty_val_key_invalid,           \
46 }
47
48 static const char *key_type_cookie_invalid(const struct bch_fs *c,
49                                            struct bkey_s_c k)
50 {
51         if (bkey_val_bytes(k.k) != sizeof(struct bch_cookie))
52                 return "incorrect value size";
53
54         return NULL;
55 }
56
57 #define bch2_bkey_ops_cookie (struct bkey_ops) {        \
58         .key_invalid = key_type_cookie_invalid,         \
59 }
60
61 #define bch2_bkey_ops_whiteout (struct bkey_ops) {      \
62         .key_invalid = empty_val_key_invalid,           \
63 }
64
65 static const struct bkey_ops bch2_bkey_ops[] = {
66 #define x(name, nr) [KEY_TYPE_##name]   = bch2_bkey_ops_##name,
67         BCH_BKEY_TYPES()
68 #undef x
69 };
70
71 const char *bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k)
72 {
73         if (k.k->type >= KEY_TYPE_MAX)
74                 return "invalid type";
75
76         return bch2_bkey_ops[k.k->type].key_invalid(c, k);
77 }
78
79 const char *__bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
80                                 enum btree_node_type type)
81 {
82         if (k.k->u64s < BKEY_U64s)
83                 return "u64s too small";
84
85         if ((btree_node_type_is_extents(type) ||
86              type == BKEY_TYPE_BTREE) &&
87             bkey_val_u64s(k.k) > BKEY_EXTENT_VAL_U64s_MAX)
88                 return "value too big";
89
90         if (btree_node_type_is_extents(type)) {
91                 if ((k.k->size == 0) != bkey_deleted(k.k))
92                         return "bad size field";
93
94                 if (k.k->size > k.k->p.offset)
95                         return "size greater than offset";
96         } else {
97                 if (k.k->size)
98                         return "nonzero size field";
99         }
100
101         if (k.k->p.snapshot)
102                 return "nonzero snapshot";
103
104         if (type != BKEY_TYPE_BTREE &&
105             !bkey_cmp(k.k->p, POS_MAX))
106                 return "POS_MAX key";
107
108         return NULL;
109 }
110
111 const char *bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
112                               enum btree_node_type type)
113 {
114         return __bch2_bkey_invalid(c, k, type) ?:
115                 bch2_bkey_val_invalid(c, k);
116 }
117
118 const char *bch2_bkey_in_btree_node(struct btree *b, struct bkey_s_c k)
119 {
120         if (bkey_cmp(bkey_start_pos(k.k), b->data->min_key) < 0)
121                 return "key before start of btree node";
122
123         if (bkey_cmp(k.k->p, b->data->max_key) > 0)
124                 return "key past end of btree node";
125
126         return NULL;
127 }
128
129 void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
130 {
131         const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
132         const char *invalid;
133
134         BUG_ON(!k.k->u64s);
135
136         invalid = bch2_bkey_invalid(c, k, btree_node_type(b)) ?:
137                 bch2_bkey_in_btree_node(b, k);
138         if (invalid) {
139                 char buf[160];
140
141                 bch2_bkey_val_to_text(&PBUF(buf), c, k);
142                 bch2_fs_bug(c, "invalid bkey %s: %s", buf, invalid);
143                 return;
144         }
145
146         if (ops->key_debugcheck)
147                 ops->key_debugcheck(c, b, k);
148 }
149
150 void bch2_bpos_to_text(struct printbuf *out, struct bpos pos)
151 {
152         if (!bkey_cmp(pos, POS_MIN))
153                 pr_buf(out, "POS_MIN");
154         else if (!bkey_cmp(pos, POS_MAX))
155                 pr_buf(out, "POS_MAX");
156         else
157                 pr_buf(out, "%llu:%llu", pos.inode, pos.offset);
158 }
159
160 void bch2_bkey_to_text(struct printbuf *out, const struct bkey *k)
161 {
162         pr_buf(out, "u64s %u type %u ", k->u64s, k->type);
163
164         bch2_bpos_to_text(out, k->p);
165
166         pr_buf(out, " snap %u len %u ver %llu",
167                k->p.snapshot, k->size, k->version.lo);
168 }
169
170 void bch2_val_to_text(struct printbuf *out, struct bch_fs *c,
171                       struct bkey_s_c k)
172 {
173         const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
174
175         if (likely(ops->val_to_text))
176                 ops->val_to_text(out, c, k);
177         else
178                 pr_buf(out, " %s", bch_bkey_types[k.k->type]);
179 }
180
181 void bch2_bkey_val_to_text(struct printbuf *out, struct bch_fs *c,
182                            struct bkey_s_c k)
183 {
184         bch2_bkey_to_text(out, k.k);
185         pr_buf(out, ": ");
186         bch2_val_to_text(out, c, k);
187 }
188
189 void bch2_bkey_swab(const struct bkey_format *f,
190                     struct bkey_packed *k)
191 {
192         const struct bkey_ops *ops = &bch2_bkey_ops[k->type];
193
194         bch2_bkey_swab_key(f, k);
195
196         if (ops->swab)
197                 ops->swab(f, k);
198 }
199
200 bool bch2_bkey_normalize(struct bch_fs *c, struct bkey_s k)
201 {
202         const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
203
204         return ops->key_normalize
205                 ? ops->key_normalize(c, k)
206                 : false;
207 }
208
209 enum merge_result bch2_bkey_merge(struct bch_fs *c,
210                                   struct bkey_s l, struct bkey_s r)
211 {
212         const struct bkey_ops *ops = &bch2_bkey_ops[l.k->type];
213         enum merge_result ret;
214
215         if (key_merging_disabled(c) ||
216             !ops->key_merge ||
217             l.k->type != r.k->type ||
218             bversion_cmp(l.k->version, r.k->version) ||
219             bkey_cmp(l.k->p, bkey_start_pos(r.k)))
220                 return BCH_MERGE_NOMERGE;
221
222         ret = ops->key_merge(c, l, r);
223
224         if (ret != BCH_MERGE_NOMERGE)
225                 l.k->needs_whiteout |= r.k->needs_whiteout;
226         return ret;
227 }
228
229 static const struct old_bkey_type {
230         u8              btree_node_type;
231         u8              old;
232         u8              new;
233 } bkey_renumber_table[] = {
234         {BKEY_TYPE_BTREE,       128, KEY_TYPE_btree_ptr         },
235         {BKEY_TYPE_EXTENTS,     128, KEY_TYPE_extent            },
236         {BKEY_TYPE_EXTENTS,     129, KEY_TYPE_extent            },
237         {BKEY_TYPE_EXTENTS,     130, KEY_TYPE_reservation       },
238         {BKEY_TYPE_INODES,      128, KEY_TYPE_inode             },
239         {BKEY_TYPE_INODES,      130, KEY_TYPE_inode_generation  },
240         {BKEY_TYPE_DIRENTS,     128, KEY_TYPE_dirent            },
241         {BKEY_TYPE_DIRENTS,     129, KEY_TYPE_whiteout          },
242         {BKEY_TYPE_XATTRS,      128, KEY_TYPE_xattr             },
243         {BKEY_TYPE_XATTRS,      129, KEY_TYPE_whiteout          },
244         {BKEY_TYPE_ALLOC,       128, KEY_TYPE_alloc             },
245         {BKEY_TYPE_QUOTAS,      128, KEY_TYPE_quota             },
246 };
247
248 void bch2_bkey_renumber(enum btree_node_type btree_node_type,
249                         struct bkey_packed *k,
250                         int write)
251 {
252         const struct old_bkey_type *i;
253
254         for (i = bkey_renumber_table;
255              i < bkey_renumber_table + ARRAY_SIZE(bkey_renumber_table);
256              i++)
257                 if (btree_node_type == i->btree_node_type &&
258                     k->type == (write ? i->new : i->old)) {
259                         k->type = write ? i->old : i->new;
260                         break;
261                 }
262 }