summaryrefslogtreecommitdiff
path: root/libbcachefs/bkey_methods.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/bkey_methods.c')
-rw-r--r--libbcachefs/bkey_methods.c127
1 files changed, 85 insertions, 42 deletions
diff --git a/libbcachefs/bkey_methods.c b/libbcachefs/bkey_methods.c
index 23894158..1736a483 100644
--- a/libbcachefs/bkey_methods.c
+++ b/libbcachefs/bkey_methods.c
@@ -18,28 +18,11 @@ const struct bkey_ops *bch2_bkey_ops[] = {
[BKEY_TYPE_BTREE] = &bch2_bkey_btree_ops,
};
-/* Returns string indicating reason for being invalid, or NULL if valid: */
-const char *bch2_bkey_invalid(struct bch_fs *c, enum bkey_type type,
- struct bkey_s_c k)
+const char *bch2_bkey_val_invalid(struct bch_fs *c, enum bkey_type type,
+ struct bkey_s_c k)
{
const struct bkey_ops *ops = bch2_bkey_ops[type];
- if (k.k->u64s < BKEY_U64s)
- return "u64s too small";
-
- if (!ops->is_extents) {
- if (k.k->size)
- return "nonzero size field";
- } else {
- if ((k.k->size == 0) != bkey_deleted(k.k))
- return "bad size field";
- }
-
- if (ops->is_extents &&
- !k.k->size &&
- !bkey_deleted(k.k))
- return "zero size field";
-
switch (k.k->type) {
case KEY_TYPE_DELETED:
case KEY_TYPE_DISCARD:
@@ -63,8 +46,41 @@ const char *bch2_bkey_invalid(struct bch_fs *c, enum bkey_type type,
}
}
-const char *bch2_btree_bkey_invalid(struct bch_fs *c, struct btree *b,
- struct bkey_s_c k)
+const char *__bch2_bkey_invalid(struct bch_fs *c, enum bkey_type type,
+ struct bkey_s_c k)
+{
+ const struct bkey_ops *ops = bch2_bkey_ops[type];
+
+ if (k.k->u64s < BKEY_U64s)
+ return "u64s too small";
+
+ if (!ops->is_extents) {
+ if (k.k->size)
+ return "nonzero size field";
+ } else {
+ if ((k.k->size == 0) != bkey_deleted(k.k))
+ return "bad size field";
+ }
+
+ if (ops->is_extents &&
+ !k.k->size &&
+ !bkey_deleted(k.k))
+ return "zero size field";
+
+ if (k.k->p.snapshot)
+ return "nonzero snapshot";
+
+ return NULL;
+}
+
+const char *bch2_bkey_invalid(struct bch_fs *c, enum bkey_type type,
+ struct bkey_s_c k)
+{
+ return __bch2_bkey_invalid(c, type, k) ?:
+ bch2_bkey_val_invalid(c, type, k);
+}
+
+const char *bch2_bkey_in_btree_node(struct btree *b, struct bkey_s_c k)
{
if (bkey_cmp(bkey_start_pos(k.k), b->data->min_key) < 0)
return "key before start of btree node";
@@ -72,10 +88,7 @@ const char *bch2_btree_bkey_invalid(struct bch_fs *c, struct btree *b,
if (bkey_cmp(k.k->p, b->data->max_key) > 0)
return "key past end of btree node";
- if (k.k->p.snapshot)
- return "nonzero snapshot";
-
- return bch2_bkey_invalid(c, btree_node_type(b), k);
+ return NULL;
}
void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
@@ -86,7 +99,8 @@ void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
BUG_ON(!k.k->u64s);
- invalid = bch2_btree_bkey_invalid(c, b, k);
+ invalid = bch2_bkey_invalid(c, type, k) ?:
+ bch2_bkey_in_btree_node(b, k);
if (invalid) {
char buf[160];
@@ -100,33 +114,62 @@ void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
ops->key_debugcheck(c, b, k);
}
-char *bch2_val_to_text(struct bch_fs *c, enum bkey_type type,
- char *buf, size_t size, struct bkey_s_c k)
+#define p(...) (out += scnprintf(out, end - out, __VA_ARGS__))
+
+int bch2_bkey_to_text(char *buf, size_t size, const struct bkey *k)
{
- const struct bkey_ops *ops = bch2_bkey_ops[type];
+ char *out = buf, *end = buf + size;
- if (k.k->type >= KEY_TYPE_GENERIC_NR &&
- ops->val_to_text)
- ops->val_to_text(c, buf, size, k);
+ p("u64s %u type %u ", k->u64s, k->type);
+
+ if (bkey_cmp(k->p, POS_MAX))
+ p("%llu:%llu", k->p.inode, k->p.offset);
+ else
+ p("POS_MAX");
- return buf;
+ p(" snap %u len %u ver %llu", k->p.snapshot, k->size, k->version.lo);
+
+ return out - buf;
}
-char *bch2_bkey_val_to_text(struct bch_fs *c, enum bkey_type type,
- char *buf, size_t size, struct bkey_s_c k)
+int bch2_val_to_text(struct bch_fs *c, enum bkey_type type,
+ char *buf, size_t size, struct bkey_s_c k)
{
const struct bkey_ops *ops = bch2_bkey_ops[type];
char *out = buf, *end = buf + size;
- out += bch2_bkey_to_text(out, end - out, k.k);
-
- if (k.k->type >= KEY_TYPE_GENERIC_NR &&
- ops->val_to_text) {
- out += scnprintf(out, end - out, ": ");
- ops->val_to_text(c, out, end - out, k);
+ switch (k.k->type) {
+ case KEY_TYPE_DELETED:
+ p(" deleted");
+ break;
+ case KEY_TYPE_DISCARD:
+ p(" discard");
+ break;
+ case KEY_TYPE_ERROR:
+ p(" error");
+ break;
+ case KEY_TYPE_COOKIE:
+ p(" cookie");
+ break;
+ default:
+ if (k.k->type >= KEY_TYPE_GENERIC_NR && ops->val_to_text)
+ ops->val_to_text(c, buf, size, k);
+ break;
}
- return buf;
+ return out - buf;
+}
+
+int bch2_bkey_val_to_text(struct bch_fs *c, enum bkey_type type,
+ char *buf, size_t size, struct bkey_s_c k)
+{
+ char *out = buf, *end = buf + size;
+
+ out += bch2_bkey_to_text(out, end - out, k.k);
+ out += scnprintf(out, end - out, ": ");
+ out += bch2_val_to_text(c, type, out, end - out, k);
+
+ return out - buf;
}
void bch2_bkey_swab(enum bkey_type type,