]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/bkey_methods.c
Update bcachefs sources to edf5f38218 bcachefs: Refactor superblock code
[bcachefs-tools-debian] / libbcachefs / bkey_methods.c
1
2 #include "bcachefs.h"
3 #include "bkey_methods.h"
4 #include "btree_types.h"
5 #include "alloc.h"
6 #include "dirent.h"
7 #include "error.h"
8 #include "extents.h"
9 #include "inode.h"
10 #include "quota.h"
11 #include "xattr.h"
12
13 const struct bkey_ops bch2_bkey_ops[] = {
14         [BKEY_TYPE_EXTENTS]     = bch2_bkey_extent_ops,
15         [BKEY_TYPE_INODES]      = bch2_bkey_inode_ops,
16         [BKEY_TYPE_DIRENTS]     = bch2_bkey_dirent_ops,
17         [BKEY_TYPE_XATTRS]      = bch2_bkey_xattr_ops,
18         [BKEY_TYPE_ALLOC]       = bch2_bkey_alloc_ops,
19         [BKEY_TYPE_QUOTAS]      = bch2_bkey_quota_ops,
20         [BKEY_TYPE_BTREE]       = bch2_bkey_btree_ops,
21 };
22
23 const char *bch2_bkey_val_invalid(struct bch_fs *c, enum bkey_type type,
24                                   struct bkey_s_c k)
25 {
26         const struct bkey_ops *ops = &bch2_bkey_ops[type];
27
28         switch (k.k->type) {
29         case KEY_TYPE_DELETED:
30         case KEY_TYPE_DISCARD:
31                 return NULL;
32
33         case KEY_TYPE_ERROR:
34                 return bkey_val_bytes(k.k) != 0
35                         ? "value size should be zero"
36                         : NULL;
37
38         case KEY_TYPE_COOKIE:
39                 return bkey_val_bytes(k.k) != sizeof(struct bch_cookie)
40                         ? "incorrect value size"
41                         : NULL;
42
43         default:
44                 if (k.k->type < KEY_TYPE_GENERIC_NR)
45                         return "invalid type";
46
47                 return ops->key_invalid(c, k);
48         }
49 }
50
51 const char *__bch2_bkey_invalid(struct bch_fs *c, enum bkey_type type,
52                               struct bkey_s_c k)
53 {
54         const struct bkey_ops *ops = &bch2_bkey_ops[type];
55
56         if (k.k->u64s < BKEY_U64s)
57                 return "u64s too small";
58
59         if (!ops->is_extents) {
60                 if (k.k->size)
61                         return "nonzero size field";
62         } else {
63                 if ((k.k->size == 0) != bkey_deleted(k.k))
64                         return "bad size field";
65         }
66
67         if (ops->is_extents &&
68             !k.k->size &&
69             !bkey_deleted(k.k))
70                 return "zero size field";
71
72         if (k.k->p.snapshot)
73                 return "nonzero snapshot";
74
75         if (type != BKEY_TYPE_BTREE &&
76             !bkey_cmp(k.k->p, POS_MAX))
77                 return "POS_MAX key";
78
79         return NULL;
80 }
81
82 const char *bch2_bkey_invalid(struct bch_fs *c, enum bkey_type type,
83                               struct bkey_s_c k)
84 {
85         return __bch2_bkey_invalid(c, type, k) ?:
86                 bch2_bkey_val_invalid(c, type, k);
87 }
88
89 const char *bch2_bkey_in_btree_node(struct btree *b, struct bkey_s_c k)
90 {
91         if (bkey_cmp(bkey_start_pos(k.k), b->data->min_key) < 0)
92                 return "key before start of btree node";
93
94         if (bkey_cmp(k.k->p, b->data->max_key) > 0)
95                 return "key past end of btree node";
96
97         return NULL;
98 }
99
100 void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
101 {
102         enum bkey_type type = btree_node_type(b);
103         const struct bkey_ops *ops = &bch2_bkey_ops[type];
104         const char *invalid;
105
106         BUG_ON(!k.k->u64s);
107
108         invalid = bch2_bkey_invalid(c, type, k) ?:
109                 bch2_bkey_in_btree_node(b, k);
110         if (invalid) {
111                 char buf[160];
112
113                 bch2_bkey_val_to_text(c, type, buf, sizeof(buf), k);
114                 bch2_fs_bug(c, "invalid bkey %s: %s", buf, invalid);
115                 return;
116         }
117
118         if (k.k->type >= KEY_TYPE_GENERIC_NR &&
119             ops->key_debugcheck)
120                 ops->key_debugcheck(c, b, k);
121 }
122
123 #define p(...)  (out += scnprintf(out, end - out, __VA_ARGS__))
124
125 int bch2_bkey_to_text(char *buf, size_t size, const struct bkey *k)
126 {
127         char *out = buf, *end = buf + size;
128
129         p("u64s %u type %u ", k->u64s, k->type);
130
131         if (bkey_cmp(k->p, POS_MAX))
132                 p("%llu:%llu", k->p.inode, k->p.offset);
133         else
134                 p("POS_MAX");
135
136         p(" snap %u len %u ver %llu", k->p.snapshot, k->size, k->version.lo);
137
138         return out - buf;
139 }
140
141 int bch2_val_to_text(struct bch_fs *c, enum bkey_type type,
142                      char *buf, size_t size, struct bkey_s_c k)
143 {
144         const struct bkey_ops *ops = &bch2_bkey_ops[type];
145         char *out = buf, *end = buf + size;
146
147         switch (k.k->type) {
148         case KEY_TYPE_DELETED:
149                 p(" deleted");
150                 break;
151         case KEY_TYPE_DISCARD:
152                 p(" discard");
153                 break;
154         case KEY_TYPE_ERROR:
155                 p(" error");
156                 break;
157         case KEY_TYPE_COOKIE:
158                 p(" cookie");
159                 break;
160         default:
161                 if (k.k->type >= KEY_TYPE_GENERIC_NR && ops->val_to_text)
162                         ops->val_to_text(c, buf, size, k);
163                 break;
164         }
165
166         return out - buf;
167 }
168
169 int bch2_bkey_val_to_text(struct bch_fs *c, enum bkey_type type,
170                           char *buf, size_t size, struct bkey_s_c k)
171 {
172         char *out = buf, *end = buf + size;
173
174         out += bch2_bkey_to_text(out, end - out, k.k);
175         out += scnprintf(out, end - out, ": ");
176         out += bch2_val_to_text(c, type, out, end - out, k);
177
178         return out - buf;
179 }
180
181 void bch2_bkey_swab(enum bkey_type type,
182                    const struct bkey_format *f,
183                    struct bkey_packed *k)
184 {
185         const struct bkey_ops *ops = &bch2_bkey_ops[type];
186
187         bch2_bkey_swab_key(f, k);
188
189         if (ops->swab)
190                 ops->swab(f, k);
191 }