bcachefs: revamp to_text methods
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
75369d4ec3
commit
319f9ac38e
@ -94,17 +94,17 @@ const char *bch2_alloc_invalid(const struct bch_fs *c, struct bkey_s_c k)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int bch2_alloc_to_text(struct bch_fs *c, char *buf,
|
||||
size_t size, struct bkey_s_c k)
|
||||
void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct bkey_s_c k)
|
||||
{
|
||||
buf[0] = '\0';
|
||||
|
||||
switch (k.k->type) {
|
||||
case BCH_ALLOC:
|
||||
case BCH_ALLOC: {
|
||||
struct bkey_s_c_alloc a = bkey_s_c_to_alloc(k);
|
||||
|
||||
pr_buf(out, "gen %u", a.v->gen);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned get_alloc_field(const u8 **p, unsigned bytes)
|
||||
|
@ -9,7 +9,7 @@
|
||||
#define ALLOC_SCAN_BATCH(ca) max_t(size_t, 1, (ca)->mi.nbuckets >> 9)
|
||||
|
||||
const char *bch2_alloc_invalid(const struct bch_fs *, struct bkey_s_c);
|
||||
int bch2_alloc_to_text(struct bch_fs *, char *, size_t, struct bkey_s_c);
|
||||
void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||
|
||||
#define bch2_bkey_alloc_ops (struct bkey_ops) { \
|
||||
.key_invalid = bch2_alloc_invalid, \
|
||||
|
@ -60,8 +60,8 @@ static void bch2_bkey_pack_verify(const struct bkey_packed *packed,
|
||||
char buf1[160], buf2[160];
|
||||
char buf3[160], buf4[160];
|
||||
|
||||
bch2_bkey_to_text(buf1, sizeof(buf1), unpacked);
|
||||
bch2_bkey_to_text(buf2, sizeof(buf2), &tmp);
|
||||
bch2_bkey_to_text(&PBUF(buf1), unpacked);
|
||||
bch2_bkey_to_text(&PBUF(buf2), &tmp);
|
||||
bch2_to_binary(buf3, (void *) unpacked, 80);
|
||||
bch2_to_binary(buf4, high_word(format, packed), 80);
|
||||
|
||||
|
@ -111,7 +111,7 @@ void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
|
||||
if (invalid) {
|
||||
char buf[160];
|
||||
|
||||
bch2_bkey_val_to_text(c, type, buf, sizeof(buf), k);
|
||||
bch2_bkey_val_to_text(&PBUF(buf), c, type, k);
|
||||
bch2_fs_bug(c, "invalid bkey %s: %s", buf, invalid);
|
||||
return;
|
||||
}
|
||||
@ -121,73 +121,57 @@ void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
|
||||
ops->key_debugcheck(c, b, k);
|
||||
}
|
||||
|
||||
#define p(...) (out += scnprintf(out, end - out, __VA_ARGS__))
|
||||
|
||||
int bch2_bpos_to_text(char *buf, size_t size, struct bpos pos)
|
||||
void bch2_bpos_to_text(struct printbuf *out, struct bpos pos)
|
||||
{
|
||||
char *out = buf, *end = buf + size;
|
||||
|
||||
if (!bkey_cmp(pos, POS_MIN))
|
||||
p("POS_MIN");
|
||||
pr_buf(out, "POS_MIN");
|
||||
else if (!bkey_cmp(pos, POS_MAX))
|
||||
p("POS_MAX");
|
||||
pr_buf(out, "POS_MAX");
|
||||
else
|
||||
p("%llu:%llu", pos.inode, pos.offset);
|
||||
|
||||
return out - buf;
|
||||
pr_buf(out, "%llu:%llu", pos.inode, pos.offset);
|
||||
}
|
||||
|
||||
int bch2_bkey_to_text(char *buf, size_t size, const struct bkey *k)
|
||||
void bch2_bkey_to_text(struct printbuf *out, const struct bkey *k)
|
||||
{
|
||||
char *out = buf, *end = buf + size;
|
||||
pr_buf(out, "u64s %u type %u ", k->u64s, k->type);
|
||||
|
||||
p("u64s %u type %u ", k->u64s, k->type);
|
||||
bch2_bpos_to_text(out, k->p);
|
||||
|
||||
out += bch2_bpos_to_text(out, end - out, k->p);
|
||||
|
||||
p(" snap %u len %u ver %llu", k->p.snapshot, k->size, k->version.lo);
|
||||
|
||||
return out - buf;
|
||||
pr_buf(out, " snap %u len %u ver %llu",
|
||||
k->p.snapshot, k->size, k->version.lo);
|
||||
}
|
||||
|
||||
int bch2_val_to_text(struct bch_fs *c, enum bkey_type type,
|
||||
char *buf, size_t size, struct bkey_s_c k)
|
||||
void bch2_val_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
enum bkey_type type, struct bkey_s_c k)
|
||||
{
|
||||
const struct bkey_ops *ops = &bch2_bkey_ops[type];
|
||||
char *out = buf, *end = buf + size;
|
||||
|
||||
switch (k.k->type) {
|
||||
case KEY_TYPE_DELETED:
|
||||
p(" deleted");
|
||||
pr_buf(out, " deleted");
|
||||
break;
|
||||
case KEY_TYPE_DISCARD:
|
||||
p(" discard");
|
||||
pr_buf(out, " discard");
|
||||
break;
|
||||
case KEY_TYPE_ERROR:
|
||||
p(" error");
|
||||
pr_buf(out, " error");
|
||||
break;
|
||||
case KEY_TYPE_COOKIE:
|
||||
p(" cookie");
|
||||
pr_buf(out, " cookie");
|
||||
break;
|
||||
default:
|
||||
if (k.k->type >= KEY_TYPE_GENERIC_NR && ops->val_to_text)
|
||||
out += ops->val_to_text(c, out, end - out, k);
|
||||
ops->val_to_text(out, c, k);
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
void bch2_bkey_val_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
enum bkey_type type, 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;
|
||||
bch2_bkey_to_text(out, k.k);
|
||||
pr_buf(out, ": ");
|
||||
bch2_val_to_text(out, c, type, k);
|
||||
}
|
||||
|
||||
void bch2_bkey_swab(enum bkey_type type,
|
||||
|
@ -46,8 +46,8 @@ struct bkey_ops {
|
||||
struct bkey_s_c);
|
||||
void (*key_debugcheck)(struct bch_fs *, struct btree *,
|
||||
struct bkey_s_c);
|
||||
int (*val_to_text)(struct bch_fs *, char *,
|
||||
size_t, struct bkey_s_c);
|
||||
void (*val_to_text)(struct printbuf *, struct bch_fs *,
|
||||
struct bkey_s_c);
|
||||
void (*swab)(const struct bkey_format *, struct bkey_packed *);
|
||||
key_filter_fn key_normalize;
|
||||
key_merge_fn key_merge;
|
||||
@ -62,12 +62,12 @@ const char *bch2_bkey_in_btree_node(struct btree *, struct bkey_s_c);
|
||||
|
||||
void bch2_bkey_debugcheck(struct bch_fs *, struct btree *, struct bkey_s_c);
|
||||
|
||||
int bch2_bpos_to_text(char *, size_t, struct bpos);
|
||||
int bch2_bkey_to_text(char *, size_t, const struct bkey *);
|
||||
int bch2_val_to_text(struct bch_fs *, enum bkey_type,
|
||||
char *, size_t, struct bkey_s_c);
|
||||
int bch2_bkey_val_to_text(struct bch_fs *, enum bkey_type,
|
||||
char *, size_t, struct bkey_s_c);
|
||||
void bch2_bpos_to_text(struct printbuf *, struct bpos);
|
||||
void bch2_bkey_to_text(struct printbuf *, const struct bkey *);
|
||||
void bch2_val_to_text(struct printbuf *, struct bch_fs *, enum bkey_type,
|
||||
struct bkey_s_c);
|
||||
void bch2_bkey_val_to_text(struct printbuf *, struct bch_fs *,
|
||||
enum bkey_type, struct bkey_s_c);
|
||||
|
||||
void bch2_bkey_swab(enum bkey_type, const struct bkey_format *,
|
||||
struct bkey_packed *);
|
||||
|
@ -56,7 +56,7 @@ void bch2_dump_bset(struct btree *b, struct bset *i, unsigned set)
|
||||
_k = _n, k = n) {
|
||||
_n = bkey_next(_k);
|
||||
|
||||
bch2_bkey_to_text(buf, sizeof(buf), &k);
|
||||
bch2_bkey_to_text(&PBUF(buf), &k);
|
||||
printk(KERN_ERR "block %u key %5u: %s\n", set,
|
||||
__btree_node_key_to_offset(b, _k), buf);
|
||||
|
||||
@ -106,7 +106,7 @@ void bch2_dump_btree_node_iter(struct btree *b,
|
||||
struct bkey uk = bkey_unpack_key(b, k);
|
||||
char buf[100];
|
||||
|
||||
bch2_bkey_to_text(buf, sizeof(buf), &uk);
|
||||
bch2_bkey_to_text(&PBUF(buf), &uk);
|
||||
printk(KERN_ERR "set %zu key %zi/%u: %s\n", t - b->set,
|
||||
k->_data - bset(b, t)->_data, bset(b, t)->u64s, buf);
|
||||
}
|
||||
@ -150,8 +150,8 @@ static void bch2_btree_node_iter_next_check(struct btree_node_iter *_iter,
|
||||
char buf1[80], buf2[80];
|
||||
|
||||
bch2_dump_btree_node(b);
|
||||
bch2_bkey_to_text(buf1, sizeof(buf1), &ku);
|
||||
bch2_bkey_to_text(buf2, sizeof(buf2), &nu);
|
||||
bch2_bkey_to_text(&PBUF(buf1), &ku);
|
||||
bch2_bkey_to_text(&PBUF(buf2), &nu);
|
||||
printk(KERN_ERR "out of order/overlapping:\n%s\n%s\n",
|
||||
buf1, buf2);
|
||||
printk(KERN_ERR "iter was:");
|
||||
@ -212,8 +212,8 @@ void bch2_verify_insert_pos(struct btree *b, struct bkey_packed *where,
|
||||
char buf2[100];
|
||||
|
||||
bch2_dump_btree_node(b);
|
||||
bch2_bkey_to_text(buf1, sizeof(buf1), &k1);
|
||||
bch2_bkey_to_text(buf2, sizeof(buf2), &k2);
|
||||
bch2_bkey_to_text(&PBUF(buf1), &k1);
|
||||
bch2_bkey_to_text(&PBUF(buf2), &k2);
|
||||
|
||||
panic("prev > insert:\n"
|
||||
"prev key %5u %s\n"
|
||||
@ -234,8 +234,8 @@ void bch2_verify_insert_pos(struct btree *b, struct bkey_packed *where,
|
||||
char buf2[100];
|
||||
|
||||
bch2_dump_btree_node(b);
|
||||
bch2_bkey_to_text(buf1, sizeof(buf1), &k1);
|
||||
bch2_bkey_to_text(buf2, sizeof(buf2), &k2);
|
||||
bch2_bkey_to_text(&PBUF(buf1), &k1);
|
||||
bch2_bkey_to_text(&PBUF(buf2), &k2);
|
||||
|
||||
panic("insert > next:\n"
|
||||
"insert key %5u %s\n"
|
||||
@ -1767,8 +1767,8 @@ void bch2_btree_keys_stats(struct btree *b, struct bset_stats *stats)
|
||||
}
|
||||
}
|
||||
|
||||
int bch2_bkey_print_bfloat(struct btree *b, struct bkey_packed *k,
|
||||
char *buf, size_t size)
|
||||
void bch2_bfloat_to_text(struct printbuf *out, struct btree *b,
|
||||
struct bkey_packed *k)
|
||||
{
|
||||
struct bset_tree *t = bch2_bkey_to_bset(b, k);
|
||||
struct bkey_packed *l, *r, *p;
|
||||
@ -1776,28 +1776,29 @@ int bch2_bkey_print_bfloat(struct btree *b, struct bkey_packed *k,
|
||||
char buf1[200], buf2[200];
|
||||
unsigned j, inorder;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
if (out->pos != out->end)
|
||||
*out->pos = '\0';
|
||||
|
||||
if (!bset_has_ro_aux_tree(t))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
inorder = bkey_to_cacheline(b, t, k);
|
||||
if (!inorder || inorder >= t->size)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
j = __inorder_to_eytzinger1(inorder, t->size, t->extra);
|
||||
if (k != tree_to_bkey(b, t, j))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
switch (bkey_float(b, t, j)->exponent) {
|
||||
case BFLOAT_FAILED_UNPACKED:
|
||||
uk = bkey_unpack_key(b, k);
|
||||
return scnprintf(buf, size,
|
||||
" failed unpacked at depth %u\n"
|
||||
"\t%llu:%llu\n",
|
||||
ilog2(j),
|
||||
uk.p.inode, uk.p.offset);
|
||||
pr_buf(out,
|
||||
" failed unpacked at depth %u\n"
|
||||
"\t%llu:%llu\n",
|
||||
ilog2(j),
|
||||
uk.p.inode, uk.p.offset);
|
||||
break;
|
||||
case BFLOAT_FAILED_PREV:
|
||||
p = tree_to_prev_bkey(b, t, j);
|
||||
l = is_power_of_2(j)
|
||||
@ -1812,28 +1813,27 @@ int bch2_bkey_print_bfloat(struct btree *b, struct bkey_packed *k,
|
||||
bch2_to_binary(buf1, high_word(&b->format, p), b->nr_key_bits);
|
||||
bch2_to_binary(buf2, high_word(&b->format, k), b->nr_key_bits);
|
||||
|
||||
return scnprintf(buf, size,
|
||||
" failed prev at depth %u\n"
|
||||
"\tkey starts at bit %u but first differing bit at %u\n"
|
||||
"\t%llu:%llu\n"
|
||||
"\t%llu:%llu\n"
|
||||
"\t%s\n"
|
||||
"\t%s\n",
|
||||
ilog2(j),
|
||||
bch2_bkey_greatest_differing_bit(b, l, r),
|
||||
bch2_bkey_greatest_differing_bit(b, p, k),
|
||||
uk.p.inode, uk.p.offset,
|
||||
up.p.inode, up.p.offset,
|
||||
buf1, buf2);
|
||||
pr_buf(out,
|
||||
" failed prev at depth %u\n"
|
||||
"\tkey starts at bit %u but first differing bit at %u\n"
|
||||
"\t%llu:%llu\n"
|
||||
"\t%llu:%llu\n"
|
||||
"\t%s\n"
|
||||
"\t%s\n",
|
||||
ilog2(j),
|
||||
bch2_bkey_greatest_differing_bit(b, l, r),
|
||||
bch2_bkey_greatest_differing_bit(b, p, k),
|
||||
uk.p.inode, uk.p.offset,
|
||||
up.p.inode, up.p.offset,
|
||||
buf1, buf2);
|
||||
break;
|
||||
case BFLOAT_FAILED_OVERFLOW:
|
||||
uk = bkey_unpack_key(b, k);
|
||||
return scnprintf(buf, size,
|
||||
" failed overflow at depth %u\n"
|
||||
"\t%llu:%llu\n",
|
||||
ilog2(j),
|
||||
uk.p.inode, uk.p.offset);
|
||||
pr_buf(out,
|
||||
" failed overflow at depth %u\n"
|
||||
"\t%llu:%llu\n",
|
||||
ilog2(j),
|
||||
uk.p.inode, uk.p.offset);
|
||||
break;
|
||||
}
|
||||
out:
|
||||
*buf = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
@ -607,8 +607,8 @@ struct bset_stats {
|
||||
};
|
||||
|
||||
void bch2_btree_keys_stats(struct btree *, struct bset_stats *);
|
||||
int bch2_bkey_print_bfloat(struct btree *, struct bkey_packed *,
|
||||
char *, size_t);
|
||||
void bch2_bfloat_to_text(struct printbuf *, struct btree *,
|
||||
struct bkey_packed *);
|
||||
|
||||
/* Debug stuff */
|
||||
|
||||
|
@ -888,55 +888,54 @@ void bch2_btree_node_prefetch(struct bch_fs *c, struct btree_iter *iter,
|
||||
bch2_btree_node_fill(c, iter, k, level, SIX_LOCK_read, false);
|
||||
}
|
||||
|
||||
int bch2_print_btree_node(struct bch_fs *c, struct btree *b,
|
||||
char *buf, size_t len)
|
||||
void bch2_btree_node_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct btree *b)
|
||||
{
|
||||
const struct bkey_format *f = &b->format;
|
||||
struct bset_stats stats;
|
||||
char ptrs[100];
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
bch2_val_to_text(c, BKEY_TYPE_BTREE, ptrs, sizeof(ptrs),
|
||||
bkey_i_to_s_c(&b->key));
|
||||
bch2_btree_keys_stats(b, &stats);
|
||||
|
||||
return scnprintf(buf, len,
|
||||
"l %u %llu:%llu - %llu:%llu:\n"
|
||||
" ptrs: %s\n"
|
||||
" format: u64s %u fields %u %u %u %u %u\n"
|
||||
" unpack fn len: %u\n"
|
||||
" bytes used %zu/%zu (%zu%% full)\n"
|
||||
" sib u64s: %u, %u (merge threshold %zu)\n"
|
||||
" nr packed keys %u\n"
|
||||
" nr unpacked keys %u\n"
|
||||
" floats %zu\n"
|
||||
" failed unpacked %zu\n"
|
||||
" failed prev %zu\n"
|
||||
" failed overflow %zu\n",
|
||||
b->level,
|
||||
b->data->min_key.inode,
|
||||
b->data->min_key.offset,
|
||||
b->data->max_key.inode,
|
||||
b->data->max_key.offset,
|
||||
ptrs,
|
||||
f->key_u64s,
|
||||
f->bits_per_field[0],
|
||||
f->bits_per_field[1],
|
||||
f->bits_per_field[2],
|
||||
f->bits_per_field[3],
|
||||
f->bits_per_field[4],
|
||||
b->unpack_fn_len,
|
||||
b->nr.live_u64s * sizeof(u64),
|
||||
btree_bytes(c) - sizeof(struct btree_node),
|
||||
b->nr.live_u64s * 100 / btree_max_u64s(c),
|
||||
b->sib_u64s[0],
|
||||
b->sib_u64s[1],
|
||||
BTREE_FOREGROUND_MERGE_THRESHOLD(c),
|
||||
b->nr.packed_keys,
|
||||
b->nr.unpacked_keys,
|
||||
stats.floats,
|
||||
stats.failed_unpacked,
|
||||
stats.failed_prev,
|
||||
stats.failed_overflow);
|
||||
pr_buf(out,
|
||||
"l %u %llu:%llu - %llu:%llu:\n"
|
||||
" ptrs: ",
|
||||
b->level,
|
||||
b->data->min_key.inode,
|
||||
b->data->min_key.offset,
|
||||
b->data->max_key.inode,
|
||||
b->data->max_key.offset);
|
||||
bch2_val_to_text(out, c, BKEY_TYPE_BTREE,
|
||||
bkey_i_to_s_c(&b->key));
|
||||
pr_buf(out, "\n"
|
||||
" format: u64s %u fields %u %u %u %u %u\n"
|
||||
" unpack fn len: %u\n"
|
||||
" bytes used %zu/%zu (%zu%% full)\n"
|
||||
" sib u64s: %u, %u (merge threshold %zu)\n"
|
||||
" nr packed keys %u\n"
|
||||
" nr unpacked keys %u\n"
|
||||
" floats %zu\n"
|
||||
" failed unpacked %zu\n"
|
||||
" failed prev %zu\n"
|
||||
" failed overflow %zu\n",
|
||||
f->key_u64s,
|
||||
f->bits_per_field[0],
|
||||
f->bits_per_field[1],
|
||||
f->bits_per_field[2],
|
||||
f->bits_per_field[3],
|
||||
f->bits_per_field[4],
|
||||
b->unpack_fn_len,
|
||||
b->nr.live_u64s * sizeof(u64),
|
||||
btree_bytes(c) - sizeof(struct btree_node),
|
||||
b->nr.live_u64s * 100 / btree_max_u64s(c),
|
||||
b->sib_u64s[0],
|
||||
b->sib_u64s[1],
|
||||
BTREE_FOREGROUND_MERGE_THRESHOLD(c),
|
||||
b->nr.packed_keys,
|
||||
b->nr.unpacked_keys,
|
||||
stats.floats,
|
||||
stats.failed_unpacked,
|
||||
stats.failed_prev,
|
||||
stats.failed_overflow);
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ static inline unsigned btree_blocks(struct bch_fs *c)
|
||||
|
||||
#define btree_node_root(_c, _b) ((_c)->btree_roots[(_b)->btree_id].b)
|
||||
|
||||
int bch2_print_btree_node(struct bch_fs *, struct btree *,
|
||||
char *, size_t);
|
||||
void bch2_btree_node_to_text(struct printbuf *, struct bch_fs *,
|
||||
struct btree *);
|
||||
|
||||
#endif /* _BCACHEFS_BTREE_CACHE_H */
|
||||
|
@ -913,26 +913,20 @@ static void bset_encrypt(struct bch_fs *c, struct bset *i, unsigned offset)
|
||||
vstruct_end(i) - (void *) i->_data);
|
||||
}
|
||||
|
||||
static int btree_err_msg(struct bch_fs *c, struct btree *b, struct bset *i,
|
||||
unsigned offset, int write, char *buf, size_t len)
|
||||
static void btree_err_msg(struct printbuf *out, struct bch_fs *c,
|
||||
struct btree *b, struct bset *i,
|
||||
unsigned offset, int write)
|
||||
{
|
||||
char *out = buf, *end = buf + len;
|
||||
|
||||
out += scnprintf(out, end - out,
|
||||
"error validating btree node %s"
|
||||
"at btree %u level %u/%u\n"
|
||||
"pos %llu:%llu node offset %u",
|
||||
write ? "before write " : "",
|
||||
b->btree_id, b->level,
|
||||
c->btree_roots[b->btree_id].level,
|
||||
b->key.k.p.inode, b->key.k.p.offset,
|
||||
b->written);
|
||||
pr_buf(out, "error validating btree node %s"
|
||||
"at btree %u level %u/%u\n"
|
||||
"pos %llu:%llu node offset %u",
|
||||
write ? "before write " : "",
|
||||
b->btree_id, b->level,
|
||||
c->btree_roots[b->btree_id].level,
|
||||
b->key.k.p.inode, b->key.k.p.offset,
|
||||
b->written);
|
||||
if (i)
|
||||
out += scnprintf(out, end - out,
|
||||
" bset u64s %u",
|
||||
le16_to_cpu(i->u64s));
|
||||
|
||||
return out - buf;
|
||||
pr_buf(out, " bset u64s %u", le16_to_cpu(i->u64s));
|
||||
}
|
||||
|
||||
enum btree_err_type {
|
||||
@ -949,10 +943,11 @@ enum btree_validate_ret {
|
||||
#define btree_err(type, c, b, i, msg, ...) \
|
||||
({ \
|
||||
__label__ out; \
|
||||
char _buf[300], *out = _buf, *end = out + sizeof(_buf); \
|
||||
char _buf[300]; \
|
||||
struct printbuf out = PBUF(_buf); \
|
||||
\
|
||||
out += btree_err_msg(c, b, i, b->written, write, out, end - out);\
|
||||
out += scnprintf(out, end - out, ": " msg, ##__VA_ARGS__); \
|
||||
btree_err_msg(&out, c, b, i, b->written, write); \
|
||||
pr_buf(&out, ": " msg, ##__VA_ARGS__); \
|
||||
\
|
||||
if (type == BTREE_ERR_FIXABLE && \
|
||||
write == READ && \
|
||||
@ -1117,7 +1112,7 @@ static int validate_bset(struct bch_fs *c, struct btree *b,
|
||||
if (invalid) {
|
||||
char buf[160];
|
||||
|
||||
bch2_bkey_val_to_text(c, type, buf, sizeof(buf), u);
|
||||
bch2_bkey_val_to_text(&PBUF(buf), c, type, u);
|
||||
btree_err(BTREE_ERR_FIXABLE, c, b, i,
|
||||
"invalid bkey:\n%s\n%s", invalid, buf);
|
||||
|
||||
@ -1302,7 +1297,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct btree *b, bool have_retry
|
||||
!bversion_cmp(u.k->version, MAX_VERSION))) {
|
||||
char buf[160];
|
||||
|
||||
bch2_bkey_val_to_text(c, type, buf, sizeof(buf), u);
|
||||
bch2_bkey_val_to_text(&PBUF(buf), c, type, u);
|
||||
btree_err(BTREE_ERR_FIXABLE, c, b, i,
|
||||
"invalid bkey %s: %s", buf, invalid);
|
||||
|
||||
@ -2060,7 +2055,7 @@ void bch2_btree_verify_flushed(struct bch_fs *c)
|
||||
|
||||
ssize_t bch2_dirty_btree_nodes_print(struct bch_fs *c, char *buf)
|
||||
{
|
||||
char *out = buf, *end = buf + PAGE_SIZE;
|
||||
struct printbuf out = _PBUF(buf, PAGE_SIZE);
|
||||
struct bucket_table *tbl;
|
||||
struct rhash_head *pos;
|
||||
struct btree *b;
|
||||
@ -2077,18 +2072,18 @@ ssize_t bch2_dirty_btree_nodes_print(struct bch_fs *c, char *buf)
|
||||
!(b->will_make_reachable & 1))
|
||||
continue;
|
||||
|
||||
out += scnprintf(out, end - out, "%p d %u l %u w %u b %u r %u:%lu c %u p %u\n",
|
||||
b,
|
||||
(flags & (1 << BTREE_NODE_dirty)) != 0,
|
||||
b->level,
|
||||
b->written,
|
||||
!list_empty_careful(&b->write_blocked),
|
||||
b->will_make_reachable != 0,
|
||||
b->will_make_reachable & 1,
|
||||
b->writes[ idx].wait.list.first != NULL,
|
||||
b->writes[!idx].wait.list.first != NULL);
|
||||
pr_buf(&out, "%p d %u l %u w %u b %u r %u:%lu c %u p %u\n",
|
||||
b,
|
||||
(flags & (1 << BTREE_NODE_dirty)) != 0,
|
||||
b->level,
|
||||
b->written,
|
||||
!list_empty_careful(&b->write_blocked),
|
||||
b->will_make_reachable != 0,
|
||||
b->will_make_reachable & 1,
|
||||
b->writes[ idx].wait.list.first != NULL,
|
||||
b->writes[!idx].wait.list.first != NULL);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return out - buf;
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ static void __bch2_btree_iter_verify(struct btree_iter *iter,
|
||||
char buf[100];
|
||||
struct bkey uk = bkey_unpack_key(b, k);
|
||||
|
||||
bch2_bkey_to_text(buf, sizeof(buf), &uk);
|
||||
bch2_bkey_to_text(&PBUF(buf), &uk);
|
||||
panic("prev key should be before iter pos:\n%s\n%llu:%llu\n",
|
||||
buf, iter->pos.inode, iter->pos.offset);
|
||||
}
|
||||
@ -437,7 +437,7 @@ static void __bch2_btree_iter_verify(struct btree_iter *iter,
|
||||
char buf[100];
|
||||
struct bkey uk = bkey_unpack_key(b, k);
|
||||
|
||||
bch2_bkey_to_text(buf, sizeof(buf), &uk);
|
||||
bch2_bkey_to_text(&PBUF(buf), &uk);
|
||||
panic("iter should be after current key:\n"
|
||||
"iter pos %llu:%llu\n"
|
||||
"cur key %s\n",
|
||||
@ -687,7 +687,7 @@ static void btree_iter_verify_new_node(struct btree_iter *iter, struct btree *b)
|
||||
char buf[100];
|
||||
struct bkey uk = bkey_unpack_key(b, k);
|
||||
|
||||
bch2_bkey_to_text(buf, sizeof(buf), &uk);
|
||||
bch2_bkey_to_text(&PBUF(buf), &uk);
|
||||
panic("parent iter doesn't point to new node:\n%s\n%llu:%llu\n",
|
||||
buf, b->key.k.p.inode, b->key.k.p.offset);
|
||||
}
|
||||
@ -1451,18 +1451,7 @@ recheck:
|
||||
: KEY_OFFSET_MAX) -
|
||||
n.p.offset));
|
||||
|
||||
//EBUG_ON(!n.size);
|
||||
if (!n.size) {
|
||||
char buf[100];
|
||||
bch2_dump_btree_node(iter->l[0].b);
|
||||
|
||||
bch2_bkey_to_text(buf, sizeof(buf), k.k);
|
||||
panic("iter at %llu:%llu\n"
|
||||
"next key %s\n",
|
||||
iter->pos.inode,
|
||||
iter->pos.offset,
|
||||
buf);
|
||||
}
|
||||
EBUG_ON(!n.size);
|
||||
|
||||
iter->k = n;
|
||||
iter->uptodate = BTREE_ITER_UPTODATE;
|
||||
|
@ -2150,20 +2150,20 @@ void bch2_btree_root_alloc(struct bch_fs *c, enum btree_id id)
|
||||
|
||||
ssize_t bch2_btree_updates_print(struct bch_fs *c, char *buf)
|
||||
{
|
||||
char *out = buf, *end = buf + PAGE_SIZE;
|
||||
struct printbuf out = _PBUF(buf, PAGE_SIZE);
|
||||
struct btree_update *as;
|
||||
|
||||
mutex_lock(&c->btree_interior_update_lock);
|
||||
list_for_each_entry(as, &c->btree_interior_update_list, list)
|
||||
out += scnprintf(out, end - out, "%p m %u w %u r %u j %llu\n",
|
||||
as,
|
||||
as->mode,
|
||||
as->nodes_written,
|
||||
atomic_read(&as->cl.remaining) & CLOSURE_REMAINING_MASK,
|
||||
as->journal.seq);
|
||||
pr_buf(&out, "%p m %u w %u r %u j %llu\n",
|
||||
as,
|
||||
as->mode,
|
||||
as->nodes_written,
|
||||
atomic_read(&as->cl.remaining) & CLOSURE_REMAINING_MASK,
|
||||
as->journal.seq);
|
||||
mutex_unlock(&c->btree_interior_update_lock);
|
||||
|
||||
return out - buf;
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
size_t bch2_btree_interior_updates_nr_pending(struct bch_fs *c)
|
||||
|
@ -223,8 +223,8 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
|
||||
k = bch2_btree_iter_peek(&iter);
|
||||
|
||||
while (k.k && !(err = btree_iter_err(k))) {
|
||||
bch2_bkey_val_to_text(i->c, bkey_type(0, i->id),
|
||||
i->buf, sizeof(i->buf), k);
|
||||
bch2_bkey_val_to_text(&PBUF(i->buf), i->c,
|
||||
bkey_type(0, i->id), k);
|
||||
i->bytes = strlen(i->buf);
|
||||
BUG_ON(i->bytes >= PAGE_SIZE);
|
||||
i->buf[i->bytes] = '\n';
|
||||
@ -272,8 +272,8 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
|
||||
return i->ret;
|
||||
|
||||
for_each_btree_node(&iter, i->c, i->id, i->from, 0, b) {
|
||||
i->bytes = bch2_print_btree_node(i->c, b, i->buf,
|
||||
sizeof(i->buf));
|
||||
bch2_btree_node_to_text(&PBUF(i->buf), i->c, b);
|
||||
i->bytes = strlen(i->buf);
|
||||
err = flush_buf(i);
|
||||
if (err)
|
||||
break;
|
||||
@ -330,17 +330,16 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
|
||||
bch2_btree_node_iter_peek(&l->iter, l->b);
|
||||
|
||||
if (l->b != prev_node) {
|
||||
i->bytes = bch2_print_btree_node(i->c, l->b, i->buf,
|
||||
sizeof(i->buf));
|
||||
bch2_btree_node_to_text(&PBUF(i->buf), i->c, l->b);
|
||||
i->bytes = strlen(i->buf);
|
||||
err = flush_buf(i);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
prev_node = l->b;
|
||||
|
||||
i->bytes = bch2_bkey_print_bfloat(l->b, _k, i->buf,
|
||||
sizeof(i->buf));
|
||||
|
||||
bch2_bfloat_to_text(&PBUF(i->buf), l->b, _k);
|
||||
i->bytes = strlen(i->buf);
|
||||
err = flush_buf(i);
|
||||
if (err)
|
||||
break;
|
||||
|
@ -110,26 +110,23 @@ const char *bch2_dirent_invalid(const struct bch_fs *c, struct bkey_s_c k)
|
||||
}
|
||||
}
|
||||
|
||||
int bch2_dirent_to_text(struct bch_fs *c, char *buf,
|
||||
size_t size, struct bkey_s_c k)
|
||||
void bch2_dirent_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct bkey_s_c k)
|
||||
{
|
||||
char *out = buf, *end = buf + size;
|
||||
struct bkey_s_c_dirent d;
|
||||
|
||||
switch (k.k->type) {
|
||||
case BCH_DIRENT:
|
||||
d = bkey_s_c_to_dirent(k);
|
||||
|
||||
out += bch_scnmemcpy(out, end - out, d.v->d_name,
|
||||
bch2_dirent_name_bytes(d));
|
||||
out += scnprintf(out, end - out, " -> %llu", d.v->d_inum);
|
||||
bch_scnmemcpy(out, d.v->d_name,
|
||||
bch2_dirent_name_bytes(d));
|
||||
pr_buf(out, " -> %llu", d.v->d_inum);
|
||||
break;
|
||||
case BCH_DIRENT_WHITEOUT:
|
||||
out += scnprintf(out, end - out, "whiteout");
|
||||
pr_buf(out, "whiteout");
|
||||
break;
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
static struct bkey_i_dirent *dirent_create_key(struct btree_trans *trans,
|
||||
|
@ -7,7 +7,7 @@
|
||||
extern const struct bch_hash_desc bch2_dirent_hash_desc;
|
||||
|
||||
const char *bch2_dirent_invalid(const struct bch_fs *, struct bkey_s_c);
|
||||
int bch2_dirent_to_text(struct bch_fs *, char *, size_t, struct bkey_s_c);
|
||||
void bch2_dirent_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||
|
||||
#define bch2_bkey_dirent_ops (struct bkey_ops) { \
|
||||
.key_invalid = bch2_dirent_invalid, \
|
||||
|
@ -83,11 +83,10 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static size_t bch2_sb_disk_groups_to_text(char *buf, size_t size,
|
||||
static void bch2_sb_disk_groups_to_text(struct printbuf *out,
|
||||
struct bch_sb *sb,
|
||||
struct bch_sb_field *f)
|
||||
{
|
||||
char *out = buf, *end = buf + size;
|
||||
struct bch_sb_field_disk_groups *groups =
|
||||
field_to_type(f, disk_groups);
|
||||
struct bch_disk_group *g;
|
||||
@ -97,18 +96,14 @@ static size_t bch2_sb_disk_groups_to_text(char *buf, size_t size,
|
||||
g < groups->entries + nr_groups;
|
||||
g++) {
|
||||
if (g != groups->entries)
|
||||
out += scnprintf(out, end - out, " ");
|
||||
pr_buf(out, " ");
|
||||
|
||||
if (BCH_GROUP_DELETED(g))
|
||||
out += scnprintf(out, end - out, "[deleted]");
|
||||
pr_buf(out, "[deleted]");
|
||||
else
|
||||
out += scnprintf(out, end - out,
|
||||
"[parent %llu name %s]",
|
||||
BCH_GROUP_PARENT(g),
|
||||
g->label);
|
||||
pr_buf(out, "[parent %llu name %s]",
|
||||
BCH_GROUP_PARENT(g), g->label);
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
const struct bch_sb_field_ops bch_sb_field_ops_disk_groups = {
|
||||
@ -343,10 +338,10 @@ int bch2_disk_path_find_or_create(struct bch_sb_handle *sb, const char *name)
|
||||
return v;
|
||||
}
|
||||
|
||||
int bch2_disk_path_print(struct bch_sb_handle *sb,
|
||||
char *buf, size_t len, unsigned v)
|
||||
void bch2_disk_path_to_text(struct printbuf *out,
|
||||
struct bch_sb_handle *sb,
|
||||
unsigned v)
|
||||
{
|
||||
char *out = buf, *end = out + len;
|
||||
struct bch_sb_field_disk_groups *groups =
|
||||
bch2_sb_get_disk_groups(sb->sb);
|
||||
struct bch_disk_group *g;
|
||||
@ -374,26 +369,18 @@ int bch2_disk_path_print(struct bch_sb_handle *sb,
|
||||
}
|
||||
|
||||
while (nr) {
|
||||
unsigned b = 0;
|
||||
|
||||
v = path[--nr];
|
||||
g = groups->entries + v;
|
||||
|
||||
if (end != out)
|
||||
b = min_t(size_t, end - out,
|
||||
strnlen(g->label, sizeof(g->label)));
|
||||
memcpy(out, g->label, b);
|
||||
if (b < end - out)
|
||||
out[b] = '\0';
|
||||
out += b;
|
||||
bch_scnmemcpy(out, g->label,
|
||||
strnlen(g->label, sizeof(g->label)));
|
||||
|
||||
if (nr)
|
||||
out += scnprintf(out, end - out, ".");
|
||||
pr_buf(out, ".");
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
return;
|
||||
inval:
|
||||
return scnprintf(buf, len, "invalid group %u", v);
|
||||
pr_buf(out, "invalid group %u", v);
|
||||
}
|
||||
|
||||
int bch2_dev_group_set(struct bch_fs *c, struct bch_dev *ca, const char *name)
|
||||
@ -452,14 +439,14 @@ int bch2_opt_target_parse(struct bch_fs *c, const char *buf, u64 *v)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int bch2_opt_target_print(struct bch_fs *c, char *buf, size_t len, u64 v)
|
||||
void bch2_opt_target_to_text(struct printbuf *out, struct bch_fs *c, u64 v)
|
||||
{
|
||||
struct target t = target_decode(v);
|
||||
int ret;
|
||||
|
||||
switch (t.type) {
|
||||
case TARGET_NULL:
|
||||
return scnprintf(buf, len, "none");
|
||||
pr_buf(out, "none");
|
||||
break;
|
||||
case TARGET_DEV: {
|
||||
struct bch_dev *ca;
|
||||
|
||||
@ -469,13 +456,12 @@ int bch2_opt_target_print(struct bch_fs *c, char *buf, size_t len, u64 v)
|
||||
: NULL;
|
||||
|
||||
if (ca && percpu_ref_tryget(&ca->io_ref)) {
|
||||
ret = scnprintf(buf, len, "/dev/%pg",
|
||||
ca->disk_sb.bdev);
|
||||
pr_buf(out, "/dev/%pg", ca->disk_sb.bdev);
|
||||
percpu_ref_put(&ca->io_ref);
|
||||
} else if (ca) {
|
||||
ret = scnprintf(buf, len, "offline device %u", t.dev);
|
||||
pr_buf(out, "offline device %u", t.dev);
|
||||
} else {
|
||||
ret = scnprintf(buf, len, "invalid device %u", t.dev);
|
||||
pr_buf(out, "invalid device %u", t.dev);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
@ -483,12 +469,10 @@ int bch2_opt_target_print(struct bch_fs *c, char *buf, size_t len, u64 v)
|
||||
}
|
||||
case TARGET_GROUP:
|
||||
mutex_lock(&c->sb_lock);
|
||||
ret = bch2_disk_path_print(&c->disk_sb, buf, len, t.group);
|
||||
bch2_disk_path_to_text(out, &c->disk_sb, t.group);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -59,10 +59,11 @@ bool bch2_dev_in_target(struct bch_fs *, unsigned, unsigned);
|
||||
|
||||
int bch2_disk_path_find(struct bch_sb_handle *, const char *);
|
||||
int bch2_disk_path_find_or_create(struct bch_sb_handle *, const char *);
|
||||
int bch2_disk_path_print(struct bch_sb_handle *, char *, size_t, unsigned);
|
||||
void bch2_disk_path_to_text(struct printbuf *, struct bch_sb_handle *,
|
||||
unsigned);
|
||||
|
||||
int bch2_opt_target_parse(struct bch_fs *, const char *, u64 *);
|
||||
int bch2_opt_target_print(struct bch_fs *, char *, size_t, u64);
|
||||
void bch2_opt_target_to_text(struct printbuf *, struct bch_fs *, u64);
|
||||
|
||||
int bch2_sb_disk_groups_to_cpu(struct bch_fs *);
|
||||
|
||||
|
@ -464,21 +464,18 @@ static const char *extent_ptr_invalid(const struct bch_fs *c,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static size_t extent_print_ptrs(struct bch_fs *c, char *buf,
|
||||
size_t size, struct bkey_s_c_extent e)
|
||||
static void extent_print_ptrs(struct printbuf *out, struct bch_fs *c,
|
||||
struct bkey_s_c_extent e)
|
||||
{
|
||||
char *out = buf, *end = buf + size;
|
||||
const union bch_extent_entry *entry;
|
||||
struct bch_extent_crc_unpacked crc;
|
||||
const struct bch_extent_ptr *ptr;
|
||||
struct bch_dev *ca;
|
||||
bool first = true;
|
||||
|
||||
#define p(...) (out += scnprintf(out, end - out, __VA_ARGS__))
|
||||
|
||||
extent_for_each_entry(e, entry) {
|
||||
if (!first)
|
||||
p(" ");
|
||||
pr_buf(out, " ");
|
||||
|
||||
switch (__extent_entry_type(entry)) {
|
||||
case BCH_EXTENT_ENTRY_crc32:
|
||||
@ -486,12 +483,12 @@ static size_t extent_print_ptrs(struct bch_fs *c, char *buf,
|
||||
case BCH_EXTENT_ENTRY_crc128:
|
||||
crc = bch2_extent_crc_unpack(e.k, entry_to_crc(entry));
|
||||
|
||||
p("crc: c_size %u size %u offset %u nonce %u csum %u compress %u",
|
||||
crc.compressed_size,
|
||||
crc.uncompressed_size,
|
||||
crc.offset, crc.nonce,
|
||||
crc.csum_type,
|
||||
crc.compression_type);
|
||||
pr_buf(out, "crc: c_size %u size %u offset %u nonce %u csum %u compress %u",
|
||||
crc.compressed_size,
|
||||
crc.uncompressed_size,
|
||||
crc.offset, crc.nonce,
|
||||
crc.csum_type,
|
||||
crc.compression_type);
|
||||
break;
|
||||
case BCH_EXTENT_ENTRY_ptr:
|
||||
ptr = entry_to_ptr(entry);
|
||||
@ -499,14 +496,14 @@ static size_t extent_print_ptrs(struct bch_fs *c, char *buf,
|
||||
? bch_dev_bkey_exists(c, ptr->dev)
|
||||
: NULL;
|
||||
|
||||
p("ptr: %u:%llu gen %u%s%s", ptr->dev,
|
||||
(u64) ptr->offset, ptr->gen,
|
||||
ptr->cached ? " cached" : "",
|
||||
ca && ptr_stale(ca, ptr)
|
||||
? " stale" : "");
|
||||
pr_buf(out, "ptr: %u:%llu gen %u%s%s", ptr->dev,
|
||||
(u64) ptr->offset, ptr->gen,
|
||||
ptr->cached ? " cached" : "",
|
||||
ca && ptr_stale(ca, ptr)
|
||||
? " stale" : "");
|
||||
break;
|
||||
default:
|
||||
p("(invalid extent entry %.16llx)", *((u64 *) entry));
|
||||
pr_buf(out, "(invalid extent entry %.16llx)", *((u64 *) entry));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -514,9 +511,7 @@ static size_t extent_print_ptrs(struct bch_fs *c, char *buf,
|
||||
}
|
||||
out:
|
||||
if (bkey_extent_is_cached(e.k))
|
||||
p(" cached");
|
||||
#undef p
|
||||
return out - buf;
|
||||
pr_buf(out, " cached");
|
||||
}
|
||||
|
||||
static struct bch_dev_io_failures *dev_io_failures(struct bch_io_failures *f,
|
||||
@ -681,8 +676,7 @@ void bch2_btree_ptr_debugcheck(struct bch_fs *c, struct btree *b,
|
||||
|
||||
if (!test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) &&
|
||||
!bch2_bkey_replicas_marked(c, btree_node_type(b), e.s_c)) {
|
||||
bch2_bkey_val_to_text(c, btree_node_type(b),
|
||||
buf, sizeof(buf), k);
|
||||
bch2_bkey_val_to_text(&PBUF(buf), c, btree_node_type(b), k);
|
||||
bch2_fs_bug(c,
|
||||
"btree key bad (replicas not marked in superblock):\n%s",
|
||||
buf);
|
||||
@ -691,29 +685,23 @@ void bch2_btree_ptr_debugcheck(struct bch_fs *c, struct btree *b,
|
||||
|
||||
return;
|
||||
err:
|
||||
bch2_bkey_val_to_text(c, btree_node_type(b), buf, sizeof(buf), k);
|
||||
bch2_fs_bug(c, "%s btree pointer %s: bucket %zi "
|
||||
"gen %i mark %08x",
|
||||
err, buf, PTR_BUCKET_NR(ca, ptr),
|
||||
mark.gen, (unsigned) mark.v.counter);
|
||||
bch2_bkey_val_to_text(&PBUF(buf), c, btree_node_type(b), k);
|
||||
bch2_fs_bug(c, "%s btree pointer %s: bucket %zi gen %i mark %08x",
|
||||
err, buf, PTR_BUCKET_NR(ca, ptr),
|
||||
mark.gen, (unsigned) mark.v.counter);
|
||||
}
|
||||
|
||||
int bch2_btree_ptr_to_text(struct bch_fs *c, char *buf,
|
||||
size_t size, struct bkey_s_c k)
|
||||
void bch2_btree_ptr_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct bkey_s_c k)
|
||||
{
|
||||
char *out = buf, *end = buf + size;
|
||||
const char *invalid;
|
||||
|
||||
#define p(...) (out += scnprintf(out, end - out, __VA_ARGS__))
|
||||
|
||||
if (bkey_extent_is_data(k.k))
|
||||
out += extent_print_ptrs(c, buf, size, bkey_s_c_to_extent(k));
|
||||
extent_print_ptrs(out, c, bkey_s_c_to_extent(k));
|
||||
|
||||
invalid = bch2_btree_ptr_invalid(c, k);
|
||||
if (invalid)
|
||||
p(" invalid: %s", invalid);
|
||||
#undef p
|
||||
return out - buf;
|
||||
pr_buf(out, " invalid: %s", invalid);
|
||||
}
|
||||
|
||||
int bch2_btree_pick_ptr(struct bch_fs *c, const struct btree *b,
|
||||
@ -1112,8 +1100,8 @@ static void verify_extent_nonoverlapping(struct btree *b,
|
||||
char buf1[100];
|
||||
char buf2[100];
|
||||
|
||||
bch2_bkey_to_text(buf1, sizeof(buf1), &insert->k);
|
||||
bch2_bkey_to_text(buf2, sizeof(buf2), &uk);
|
||||
bch2_bkey_to_text(&PBUF(buf1), &insert->k);
|
||||
bch2_bkey_to_text(&PBUF(buf2), &uk);
|
||||
|
||||
bch2_dump_btree_node(b);
|
||||
panic("insert > next :\n"
|
||||
@ -1705,8 +1693,8 @@ static void bch2_extent_debugcheck_extent(struct bch_fs *c, struct btree *b,
|
||||
}
|
||||
|
||||
if (replicas > BCH_REPLICAS_MAX) {
|
||||
bch2_bkey_val_to_text(c, btree_node_type(b), buf,
|
||||
sizeof(buf), e.s_c);
|
||||
bch2_bkey_val_to_text(&PBUF(buf), c, btree_node_type(b),
|
||||
e.s_c);
|
||||
bch2_fs_bug(c,
|
||||
"extent key bad (too many replicas: %u): %s",
|
||||
replicas, buf);
|
||||
@ -1715,8 +1703,8 @@ static void bch2_extent_debugcheck_extent(struct bch_fs *c, struct btree *b,
|
||||
|
||||
if (!test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) &&
|
||||
!bch2_bkey_replicas_marked(c, btree_node_type(b), e.s_c)) {
|
||||
bch2_bkey_val_to_text(c, btree_node_type(b),
|
||||
buf, sizeof(buf), e.s_c);
|
||||
bch2_bkey_val_to_text(&PBUF(buf), c, btree_node_type(b),
|
||||
e.s_c);
|
||||
bch2_fs_bug(c,
|
||||
"extent key bad (replicas not marked in superblock):\n%s",
|
||||
buf);
|
||||
@ -1726,12 +1714,11 @@ static void bch2_extent_debugcheck_extent(struct bch_fs *c, struct btree *b,
|
||||
return;
|
||||
|
||||
bad_ptr:
|
||||
bch2_bkey_val_to_text(c, btree_node_type(b), buf,
|
||||
sizeof(buf), e.s_c);
|
||||
bch2_bkey_val_to_text(&PBUF(buf), c, btree_node_type(b),
|
||||
e.s_c);
|
||||
bch2_fs_bug(c, "extent pointer bad gc mark: %s:\nbucket %zu "
|
||||
"gen %i type %u", buf,
|
||||
PTR_BUCKET_NR(ca, ptr), mark.gen, mark.data_type);
|
||||
return;
|
||||
}
|
||||
|
||||
void bch2_extent_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
|
||||
@ -1748,22 +1735,17 @@ void bch2_extent_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k
|
||||
}
|
||||
}
|
||||
|
||||
int bch2_extent_to_text(struct bch_fs *c, char *buf,
|
||||
size_t size, struct bkey_s_c k)
|
||||
void bch2_extent_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct bkey_s_c k)
|
||||
{
|
||||
char *out = buf, *end = buf + size;
|
||||
const char *invalid;
|
||||
|
||||
#define p(...) (out += scnprintf(out, end - out, __VA_ARGS__))
|
||||
|
||||
if (bkey_extent_is_data(k.k))
|
||||
out += extent_print_ptrs(c, buf, size, bkey_s_c_to_extent(k));
|
||||
extent_print_ptrs(out, c, bkey_s_c_to_extent(k));
|
||||
|
||||
invalid = bch2_extent_invalid(c, k);
|
||||
if (invalid)
|
||||
p(" invalid: %s", invalid);
|
||||
#undef p
|
||||
return out - buf;
|
||||
pr_buf(out, " invalid: %s", invalid);
|
||||
}
|
||||
|
||||
static void bch2_extent_crc_init(union bch_extent_crc *crc,
|
||||
|
@ -18,7 +18,8 @@ union bch_extent_crc;
|
||||
const char *bch2_btree_ptr_invalid(const struct bch_fs *, struct bkey_s_c);
|
||||
void bch2_btree_ptr_debugcheck(struct bch_fs *, struct btree *,
|
||||
struct bkey_s_c);
|
||||
int bch2_btree_ptr_to_text(struct bch_fs *, char *, size_t, struct bkey_s_c);
|
||||
void bch2_btree_ptr_to_text(struct printbuf *, struct bch_fs *,
|
||||
struct bkey_s_c);
|
||||
void bch2_ptr_swab(const struct bkey_format *, struct bkey_packed *);
|
||||
|
||||
#define bch2_bkey_btree_ops (struct bkey_ops) { \
|
||||
@ -30,7 +31,7 @@ void bch2_ptr_swab(const struct bkey_format *, struct bkey_packed *);
|
||||
|
||||
const char *bch2_extent_invalid(const struct bch_fs *, struct bkey_s_c);
|
||||
void bch2_extent_debugcheck(struct bch_fs *, struct btree *, struct bkey_s_c);
|
||||
int bch2_extent_to_text(struct bch_fs *, char *, size_t, struct bkey_s_c);
|
||||
void bch2_extent_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||
bool bch2_ptr_normalize(struct bch_fs *, struct btree *, struct bkey_s);
|
||||
enum merge_result bch2_extent_merge(struct bch_fs *, struct btree *,
|
||||
struct bkey_i *, struct bkey_i *);
|
||||
|
@ -1619,7 +1619,7 @@ static int bch2_show_options(struct seq_file *seq, struct dentry *root)
|
||||
if (v == bch2_opt_get_by_id(&bch2_opts_default, i))
|
||||
continue;
|
||||
|
||||
bch2_opt_to_text(c, buf, sizeof(buf), opt, v,
|
||||
bch2_opt_to_text(&PBUF(buf), c, opt, v,
|
||||
OPT_SHOW_MOUNT_STYLE);
|
||||
seq_putc(seq, ',');
|
||||
seq_puts(seq, buf);
|
||||
|
@ -234,8 +234,9 @@ static int hash_check_duplicates(const struct bch_hash_desc desc,
|
||||
if (fsck_err_on(k2.k->type == desc.key_type &&
|
||||
!desc.cmp_bkey(k, k2), c,
|
||||
"duplicate hash table keys:\n%s",
|
||||
(bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id),
|
||||
buf, sizeof(buf), k), buf))) {
|
||||
(bch2_bkey_val_to_text(&PBUF(buf), c,
|
||||
bkey_type(0, desc.btree_id),
|
||||
k), buf))) {
|
||||
ret = fsck_hash_delete_at(desc, &h->info, k_iter);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -298,8 +299,9 @@ static int hash_check_key(const struct bch_hash_desc desc,
|
||||
"hashed to %llu chain starts at %llu\n%s",
|
||||
desc.btree_id, k.k->p.offset,
|
||||
hashed, h->chain->pos.offset,
|
||||
(bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id),
|
||||
buf, sizeof(buf), k), buf))) {
|
||||
(bch2_bkey_val_to_text(&PBUF(buf), c,
|
||||
bkey_type(0, desc.btree_id),
|
||||
k), buf))) {
|
||||
ret = hash_redo_key(desc, h, c, k_iter, k, hashed);
|
||||
if (ret) {
|
||||
bch_err(c, "hash_redo_key err %i", ret);
|
||||
@ -382,8 +384,9 @@ err_redo:
|
||||
"hashed to %llu chain starts at %llu\n%s",
|
||||
buf, strlen(buf), BTREE_ID_DIRENTS,
|
||||
k->k->p.offset, hash, h->chain->pos.offset,
|
||||
(bch2_bkey_val_to_text(c, bkey_type(0, BTREE_ID_DIRENTS),
|
||||
buf, sizeof(buf), *k), buf))) {
|
||||
(bch2_bkey_val_to_text(&PBUF(buf), c,
|
||||
bkey_type(0, BTREE_ID_DIRENTS),
|
||||
*k), buf))) {
|
||||
ret = hash_redo_key(bch2_dirent_hash_desc,
|
||||
h, c, iter, *k, hash);
|
||||
if (ret)
|
||||
@ -525,13 +528,15 @@ static int check_dirents(struct bch_fs *c)
|
||||
|
||||
if (fsck_err_on(!w.have_inode, c,
|
||||
"dirent in nonexisting directory:\n%s",
|
||||
(bch2_bkey_val_to_text(c, (enum bkey_type) BTREE_ID_DIRENTS,
|
||||
buf, sizeof(buf), k), buf)) ||
|
||||
(bch2_bkey_val_to_text(&PBUF(buf), c,
|
||||
(enum bkey_type) BTREE_ID_DIRENTS,
|
||||
k), buf)) ||
|
||||
fsck_err_on(!S_ISDIR(w.inode.bi_mode), c,
|
||||
"dirent in non directory inode type %u:\n%s",
|
||||
mode_to_type(w.inode.bi_mode),
|
||||
(bch2_bkey_val_to_text(c, (enum bkey_type) BTREE_ID_DIRENTS,
|
||||
buf, sizeof(buf), k), buf))) {
|
||||
(bch2_bkey_val_to_text(&PBUF(buf), c,
|
||||
(enum bkey_type) BTREE_ID_DIRENTS,
|
||||
k), buf))) {
|
||||
ret = bch2_btree_delete_at(iter, 0);
|
||||
if (ret)
|
||||
goto err;
|
||||
@ -580,8 +585,9 @@ static int check_dirents(struct bch_fs *c)
|
||||
|
||||
if (fsck_err_on(d_inum == d.k->p.inode, c,
|
||||
"dirent points to own directory:\n%s",
|
||||
(bch2_bkey_val_to_text(c, (enum bkey_type) BTREE_ID_DIRENTS,
|
||||
buf, sizeof(buf), k), buf))) {
|
||||
(bch2_bkey_val_to_text(&PBUF(buf), c,
|
||||
(enum bkey_type) BTREE_ID_DIRENTS,
|
||||
k), buf))) {
|
||||
ret = remove_dirent(c, iter, d);
|
||||
if (ret)
|
||||
goto err;
|
||||
@ -597,8 +603,9 @@ static int check_dirents(struct bch_fs *c)
|
||||
|
||||
if (fsck_err_on(!have_target, c,
|
||||
"dirent points to missing inode:\n%s",
|
||||
(bch2_bkey_val_to_text(c, (enum bkey_type) BTREE_ID_DIRENTS,
|
||||
buf, sizeof(buf), k), buf))) {
|
||||
(bch2_bkey_val_to_text(&PBUF(buf), c,
|
||||
(enum bkey_type) BTREE_ID_DIRENTS,
|
||||
k), buf))) {
|
||||
ret = remove_dirent(c, iter, d);
|
||||
if (ret)
|
||||
goto err;
|
||||
@ -610,8 +617,9 @@ static int check_dirents(struct bch_fs *c)
|
||||
mode_to_type(target.bi_mode), c,
|
||||
"incorrect d_type: should be %u:\n%s",
|
||||
mode_to_type(target.bi_mode),
|
||||
(bch2_bkey_val_to_text(c, (enum bkey_type) BTREE_ID_DIRENTS,
|
||||
buf, sizeof(buf), k), buf))) {
|
||||
(bch2_bkey_val_to_text(&PBUF(buf), c,
|
||||
(enum bkey_type) BTREE_ID_DIRENTS,
|
||||
k), buf))) {
|
||||
struct bkey_i_dirent *n;
|
||||
|
||||
n = kmalloc(bkey_bytes(d.k), GFP_KERNEL);
|
||||
|
@ -228,10 +228,9 @@ const char *bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k)
|
||||
}
|
||||
}
|
||||
|
||||
int bch2_inode_to_text(struct bch_fs *c, char *buf,
|
||||
size_t size, struct bkey_s_c k)
|
||||
void bch2_inode_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct bkey_s_c k)
|
||||
{
|
||||
char *out = buf, *end = out + size;
|
||||
struct bkey_s_c_inode inode;
|
||||
struct bch_inode_unpacked unpacked;
|
||||
|
||||
@ -239,18 +238,16 @@ int bch2_inode_to_text(struct bch_fs *c, char *buf,
|
||||
case BCH_INODE_FS:
|
||||
inode = bkey_s_c_to_inode(k);
|
||||
if (bch2_inode_unpack(inode, &unpacked)) {
|
||||
out += scnprintf(out, end - out, "(unpack error)");
|
||||
pr_buf(out, "(unpack error)");
|
||||
break;
|
||||
}
|
||||
|
||||
#define BCH_INODE_FIELD(_name, _bits) \
|
||||
out += scnprintf(out, end - out, #_name ": %llu ", (u64) unpacked._name);
|
||||
pr_buf(out, #_name ": %llu ", (u64) unpacked._name);
|
||||
BCH_INODE_FIELDS()
|
||||
#undef BCH_INODE_FIELD
|
||||
break;
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
void bch2_inode_init(struct bch_fs *c, struct bch_inode_unpacked *inode_u,
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <linux/math64.h>
|
||||
|
||||
const char *bch2_inode_invalid(const struct bch_fs *, struct bkey_s_c);
|
||||
int bch2_inode_to_text(struct bch_fs *, char *, size_t, struct bkey_s_c);
|
||||
void bch2_inode_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||
|
||||
#define bch2_bkey_inode_ops (struct bkey_ops) { \
|
||||
.key_invalid = bch2_inode_invalid, \
|
||||
|
@ -1027,38 +1027,38 @@ out:
|
||||
|
||||
ssize_t bch2_journal_print_debug(struct journal *j, char *buf)
|
||||
{
|
||||
struct printbuf out = _PBUF(buf, PAGE_SIZE);
|
||||
struct bch_fs *c = container_of(j, struct bch_fs, journal);
|
||||
union journal_res_state *s = &j->reservations;
|
||||
struct bch_dev *ca;
|
||||
unsigned iter;
|
||||
ssize_t ret = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
spin_lock(&j->lock);
|
||||
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"active journal entries:\t%llu\n"
|
||||
"seq:\t\t\t%llu\n"
|
||||
"last_seq:\t\t%llu\n"
|
||||
"last_seq_ondisk:\t%llu\n"
|
||||
"reservation count:\t%u\n"
|
||||
"reservation offset:\t%u\n"
|
||||
"current entry u64s:\t%u\n"
|
||||
"io in flight:\t\t%i\n"
|
||||
"need write:\t\t%i\n"
|
||||
"dirty:\t\t\t%i\n"
|
||||
"replay done:\t\t%i\n",
|
||||
fifo_used(&j->pin),
|
||||
journal_cur_seq(j),
|
||||
journal_last_seq(j),
|
||||
j->last_seq_ondisk,
|
||||
journal_state_count(*s, s->idx),
|
||||
s->cur_entry_offset,
|
||||
j->cur_entry_u64s,
|
||||
s->prev_buf_unwritten,
|
||||
test_bit(JOURNAL_NEED_WRITE, &j->flags),
|
||||
journal_entry_is_open(j),
|
||||
test_bit(JOURNAL_REPLAY_DONE, &j->flags));
|
||||
pr_buf(&out,
|
||||
"active journal entries:\t%llu\n"
|
||||
"seq:\t\t\t%llu\n"
|
||||
"last_seq:\t\t%llu\n"
|
||||
"last_seq_ondisk:\t%llu\n"
|
||||
"reservation count:\t%u\n"
|
||||
"reservation offset:\t%u\n"
|
||||
"current entry u64s:\t%u\n"
|
||||
"io in flight:\t\t%i\n"
|
||||
"need write:\t\t%i\n"
|
||||
"dirty:\t\t\t%i\n"
|
||||
"replay done:\t\t%i\n",
|
||||
fifo_used(&j->pin),
|
||||
journal_cur_seq(j),
|
||||
journal_last_seq(j),
|
||||
j->last_seq_ondisk,
|
||||
journal_state_count(*s, s->idx),
|
||||
s->cur_entry_offset,
|
||||
j->cur_entry_u64s,
|
||||
s->prev_buf_unwritten,
|
||||
test_bit(JOURNAL_NEED_WRITE, &j->flags),
|
||||
journal_entry_is_open(j),
|
||||
test_bit(JOURNAL_REPLAY_DONE, &j->flags));
|
||||
|
||||
for_each_member_device_rcu(ca, c, iter,
|
||||
&c->rw_devs[BCH_DATA_JOURNAL]) {
|
||||
@ -1067,50 +1067,46 @@ ssize_t bch2_journal_print_debug(struct journal *j, char *buf)
|
||||
if (!ja->nr)
|
||||
continue;
|
||||
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"dev %u:\n"
|
||||
"\tnr\t\t%u\n"
|
||||
"\tcur_idx\t\t%u (seq %llu)\n"
|
||||
"\tlast_idx\t%u (seq %llu)\n",
|
||||
iter, ja->nr,
|
||||
ja->cur_idx, ja->bucket_seq[ja->cur_idx],
|
||||
ja->last_idx, ja->bucket_seq[ja->last_idx]);
|
||||
pr_buf(&out,
|
||||
"dev %u:\n"
|
||||
"\tnr\t\t%u\n"
|
||||
"\tcur_idx\t\t%u (seq %llu)\n"
|
||||
"\tlast_idx\t%u (seq %llu)\n",
|
||||
iter, ja->nr,
|
||||
ja->cur_idx, ja->bucket_seq[ja->cur_idx],
|
||||
ja->last_idx, ja->bucket_seq[ja->last_idx]);
|
||||
}
|
||||
|
||||
spin_unlock(&j->lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
return ret;
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
ssize_t bch2_journal_print_pins(struct journal *j, char *buf)
|
||||
{
|
||||
struct printbuf out = _PBUF(buf, PAGE_SIZE);
|
||||
struct journal_entry_pin_list *pin_list;
|
||||
struct journal_entry_pin *pin;
|
||||
ssize_t ret = 0;
|
||||
u64 i;
|
||||
|
||||
spin_lock(&j->lock);
|
||||
fifo_for_each_entry_ptr(pin_list, &j->pin, i) {
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"%llu: count %u\n",
|
||||
i, atomic_read(&pin_list->count));
|
||||
pr_buf(&out, "%llu: count %u\n",
|
||||
i, atomic_read(&pin_list->count));
|
||||
|
||||
list_for_each_entry(pin, &pin_list->list, list)
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"\t%p %pf\n",
|
||||
pin, pin->flush);
|
||||
pr_buf(&out, "\t%p %pf\n",
|
||||
pin, pin->flush);
|
||||
|
||||
if (!list_empty(&pin_list->flushed))
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"flushed:\n");
|
||||
pr_buf(&out, "flushed:\n");
|
||||
|
||||
list_for_each_entry(pin, &pin_list->flushed, list)
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"\t%p %pf\n",
|
||||
pin, pin->flush);
|
||||
pr_buf(&out, "\t%p %pf\n",
|
||||
pin, pin->flush);
|
||||
}
|
||||
spin_unlock(&j->lock);
|
||||
|
||||
return ret;
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
@ -146,7 +146,6 @@ static int journal_validate_key(struct bch_fs *c, struct jset *jset,
|
||||
{
|
||||
void *next = vstruct_next(entry);
|
||||
const char *invalid;
|
||||
char buf[160];
|
||||
int ret = 0;
|
||||
|
||||
if (journal_entry_err_on(!k->k.u64s, c,
|
||||
@ -179,8 +178,10 @@ static int journal_validate_key(struct bch_fs *c, struct jset *jset,
|
||||
|
||||
invalid = bch2_bkey_invalid(c, key_type, bkey_i_to_s_c(k));
|
||||
if (invalid) {
|
||||
bch2_bkey_val_to_text(c, key_type, buf, sizeof(buf),
|
||||
bkey_i_to_s_c(k));
|
||||
char buf[160];
|
||||
|
||||
bch2_bkey_val_to_text(&PBUF(buf), c, key_type,
|
||||
bkey_i_to_s_c(k));
|
||||
mustfix_fsck_err(c, "invalid %s in journal: %s\n%s",
|
||||
type, invalid, buf);
|
||||
|
||||
|
@ -145,7 +145,7 @@ const struct bch_option bch2_opt_table[] = {
|
||||
#define OPT_STR(_choices) .type = BCH_OPT_STR, .choices = _choices
|
||||
#define OPT_FN(_fn) .type = BCH_OPT_FN, \
|
||||
.parse = _fn##_parse, \
|
||||
.print = _fn##_print
|
||||
.to_text = _fn##_to_text
|
||||
|
||||
#define BCH_OPT(_name, _bits, _mode, _type, _sb_opt, _default) \
|
||||
[Opt_##_name] = { \
|
||||
@ -235,38 +235,38 @@ int bch2_opt_parse(struct bch_fs *c, const struct bch_option *opt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bch2_opt_to_text(struct bch_fs *c, char *buf, size_t len,
|
||||
const struct bch_option *opt, u64 v,
|
||||
unsigned flags)
|
||||
void bch2_opt_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
const struct bch_option *opt, u64 v,
|
||||
unsigned flags)
|
||||
{
|
||||
char *out = buf, *end = buf + len;
|
||||
|
||||
if (flags & OPT_SHOW_MOUNT_STYLE) {
|
||||
if (opt->type == BCH_OPT_BOOL)
|
||||
return scnprintf(out, end - out, "%s%s",
|
||||
v ? "" : "no",
|
||||
opt->attr.name);
|
||||
if (opt->type == BCH_OPT_BOOL) {
|
||||
pr_buf(out, "%s%s",
|
||||
v ? "" : "no",
|
||||
opt->attr.name);
|
||||
return;
|
||||
}
|
||||
|
||||
out += scnprintf(out, end - out, "%s=", opt->attr.name);
|
||||
pr_buf(out, "%s=", opt->attr.name);
|
||||
}
|
||||
|
||||
switch (opt->type) {
|
||||
case BCH_OPT_BOOL:
|
||||
case BCH_OPT_UINT:
|
||||
out += scnprintf(out, end - out, "%lli", v);
|
||||
pr_buf(out, "%lli", v);
|
||||
break;
|
||||
case BCH_OPT_STR:
|
||||
out += (flags & OPT_SHOW_FULL_LIST)
|
||||
? bch2_scnprint_string_list(out, end - out, opt->choices, v)
|
||||
: scnprintf(out, end - out, opt->choices[v]);
|
||||
if (flags & OPT_SHOW_FULL_LIST)
|
||||
bch2_string_opt_to_text(out, opt->choices, v);
|
||||
else
|
||||
pr_buf(out, opt->choices[v]);
|
||||
break;
|
||||
case BCH_OPT_FN:
|
||||
return opt->print(c, out, end - out, v);
|
||||
opt->to_text(out, c, v);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
int bch2_parse_mount_opts(struct bch_opts *opts, char *options)
|
||||
|
@ -229,6 +229,7 @@ enum bch_opt_id {
|
||||
};
|
||||
|
||||
struct bch_fs;
|
||||
struct printbuf;
|
||||
|
||||
struct bch_option {
|
||||
struct attribute attr;
|
||||
@ -245,7 +246,7 @@ struct bch_option {
|
||||
};
|
||||
struct {
|
||||
int (*parse)(struct bch_fs *, const char *, u64 *);
|
||||
int (*print)(struct bch_fs *, char *, size_t, u64);
|
||||
void (*to_text)(struct printbuf *, struct bch_fs *, u64);
|
||||
};
|
||||
};
|
||||
|
||||
@ -265,8 +266,8 @@ int bch2_opt_parse(struct bch_fs *, const struct bch_option *, const char *, u64
|
||||
#define OPT_SHOW_FULL_LIST (1 << 0)
|
||||
#define OPT_SHOW_MOUNT_STYLE (1 << 1)
|
||||
|
||||
int bch2_opt_to_text(struct bch_fs *, char *, size_t,
|
||||
const struct bch_option *, u64, unsigned);
|
||||
void bch2_opt_to_text(struct printbuf *, struct bch_fs *,
|
||||
const struct bch_option *, u64, unsigned);
|
||||
|
||||
int bch2_parse_mount_opts(struct bch_opts *, char *);
|
||||
|
||||
|
@ -46,10 +46,9 @@ static const char * const bch2_quota_counters[] = {
|
||||
"inodes",
|
||||
};
|
||||
|
||||
int bch2_quota_to_text(struct bch_fs *c, char *buf,
|
||||
size_t size, struct bkey_s_c k)
|
||||
void bch2_quota_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct bkey_s_c k)
|
||||
{
|
||||
char *out = buf, *end = buf + size;
|
||||
struct bkey_s_c_quota dq;
|
||||
unsigned i;
|
||||
|
||||
@ -58,14 +57,12 @@ int bch2_quota_to_text(struct bch_fs *c, char *buf,
|
||||
dq = bkey_s_c_to_quota(k);
|
||||
|
||||
for (i = 0; i < Q_COUNTERS; i++)
|
||||
out += scnprintf(out, end - out, "%s hardlimit %llu softlimit %llu",
|
||||
bch2_quota_counters[i],
|
||||
le64_to_cpu(dq.v->c[i].hardlimit),
|
||||
le64_to_cpu(dq.v->c[i].softlimit));
|
||||
pr_buf(out, "%s hardlimit %llu softlimit %llu",
|
||||
bch2_quota_counters[i],
|
||||
le64_to_cpu(dq.v->c[i].hardlimit),
|
||||
le64_to_cpu(dq.v->c[i].softlimit));
|
||||
break;
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCACHEFS_QUOTA
|
||||
|
@ -8,7 +8,7 @@
|
||||
extern const struct bch_sb_field_ops bch_sb_field_ops_quota;
|
||||
|
||||
const char *bch2_quota_invalid(const struct bch_fs *, struct bkey_s_c);
|
||||
int bch2_quota_to_text(struct bch_fs *, char *, size_t, struct bkey_s_c);
|
||||
void bch2_quota_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||
|
||||
#define bch2_bkey_quota_ops (struct bkey_ops) { \
|
||||
.key_invalid = bch2_quota_invalid, \
|
||||
|
@ -252,49 +252,43 @@ static int bch2_rebalance_thread(void *arg)
|
||||
|
||||
ssize_t bch2_rebalance_work_show(struct bch_fs *c, char *buf)
|
||||
{
|
||||
char *out = buf, *end = out + PAGE_SIZE;
|
||||
struct printbuf out = _PBUF(buf, PAGE_SIZE);
|
||||
struct bch_fs_rebalance *r = &c->rebalance;
|
||||
struct rebalance_work w = rebalance_work(c);
|
||||
char h1[21], h2[21];
|
||||
|
||||
bch2_hprint(h1, w.dev_most_full_work << 9);
|
||||
bch2_hprint(h2, w.dev_most_full_capacity << 9);
|
||||
out += scnprintf(out, end - out,
|
||||
"fullest_dev (%i):\t%s/%s\n",
|
||||
w.dev_most_full_idx, h1, h2);
|
||||
pr_buf(&out, "fullest_dev (%i):\t%s/%s\n",
|
||||
w.dev_most_full_idx, h1, h2);
|
||||
|
||||
bch2_hprint(h1, w.total_work << 9);
|
||||
bch2_hprint(h2, c->capacity << 9);
|
||||
out += scnprintf(out, end - out,
|
||||
"total work:\t\t%s/%s\n",
|
||||
h1, h2);
|
||||
pr_buf(&out, "total work:\t\t%s/%s\n", h1, h2);
|
||||
|
||||
out += scnprintf(out, end - out,
|
||||
"rate:\t\t\t%u\n",
|
||||
r->pd.rate.rate);
|
||||
pr_buf(&out, "rate:\t\t\t%u\n", r->pd.rate.rate);
|
||||
|
||||
switch (r->state) {
|
||||
case REBALANCE_WAITING:
|
||||
out += scnprintf(out, end - out, "waiting\n");
|
||||
pr_buf(&out, "waiting\n");
|
||||
break;
|
||||
case REBALANCE_THROTTLED:
|
||||
bch2_hprint(h1,
|
||||
(r->throttled_until_iotime -
|
||||
atomic_long_read(&c->io_clock[WRITE].now)) << 9);
|
||||
out += scnprintf(out, end - out,
|
||||
"throttled for %lu sec or %s io\n",
|
||||
(r->throttled_until_cputime - jiffies) / HZ,
|
||||
h1);
|
||||
pr_buf(&out, "throttled for %lu sec or %s io\n",
|
||||
(r->throttled_until_cputime - jiffies) / HZ,
|
||||
h1);
|
||||
break;
|
||||
case REBALANCE_RUNNING:
|
||||
out += scnprintf(out, end - out, "running\n");
|
||||
out += scnprintf(out, end - out, "pos %llu:%llu\n",
|
||||
r->move_stats.iter.pos.inode,
|
||||
r->move_stats.iter.pos.offset);
|
||||
pr_buf(&out, "running\n");
|
||||
pr_buf(&out, "pos %llu:%llu\n",
|
||||
r->move_stats.iter.pos.inode,
|
||||
r->move_stats.iter.pos.offset);
|
||||
break;
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
void bch2_rebalance_stop(struct bch_fs *c)
|
||||
|
@ -40,38 +40,31 @@ static void bch2_cpu_replicas_sort(struct bch_replicas_cpu *r)
|
||||
eytzinger0_sort(r->entries, r->nr, r->entry_size, memcmp, NULL);
|
||||
}
|
||||
|
||||
static int replicas_entry_to_text(struct bch_replicas_entry *e,
|
||||
char *buf, size_t size)
|
||||
static void replicas_entry_to_text(struct printbuf *out,
|
||||
struct bch_replicas_entry *e)
|
||||
{
|
||||
char *out = buf, *end = out + size;
|
||||
unsigned i;
|
||||
|
||||
out += scnprintf(out, end - out, "%u: [", e->data_type);
|
||||
pr_buf(out, "%u: [", e->data_type);
|
||||
|
||||
for (i = 0; i < e->nr_devs; i++)
|
||||
out += scnprintf(out, end - out,
|
||||
i ? " %u" : "%u", e->devs[i]);
|
||||
out += scnprintf(out, end - out, "]");
|
||||
|
||||
return out - buf;
|
||||
pr_buf(out, i ? " %u" : "%u", e->devs[i]);
|
||||
pr_buf(out, "]");
|
||||
}
|
||||
|
||||
int bch2_cpu_replicas_to_text(struct bch_replicas_cpu *r,
|
||||
char *buf, size_t size)
|
||||
void bch2_cpu_replicas_to_text(struct printbuf *out,
|
||||
struct bch_replicas_cpu *r)
|
||||
{
|
||||
char *out = buf, *end = out + size;
|
||||
struct bch_replicas_entry *e;
|
||||
bool first = true;
|
||||
|
||||
for_each_cpu_replicas_entry(r, e) {
|
||||
if (!first)
|
||||
out += scnprintf(out, end - out, " ");
|
||||
pr_buf(out, " ");
|
||||
first = false;
|
||||
|
||||
out += replicas_entry_to_text(e, out, end - out);
|
||||
replicas_entry_to_text(out, e);
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
static void extent_to_replicas(struct bkey_s_c k,
|
||||
@ -510,32 +503,28 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct bch_sb_field_ops bch_sb_field_ops_replicas = {
|
||||
.validate = bch2_sb_validate_replicas,
|
||||
};
|
||||
|
||||
int bch2_sb_replicas_to_text(struct bch_sb_field_replicas *r, char *buf, size_t size)
|
||||
static void bch2_sb_replicas_to_text(struct printbuf *out,
|
||||
struct bch_sb *sb,
|
||||
struct bch_sb_field *f)
|
||||
{
|
||||
char *out = buf, *end = out + size;
|
||||
struct bch_sb_field_replicas *r = field_to_type(f, replicas);
|
||||
struct bch_replicas_entry *e;
|
||||
bool first = true;
|
||||
|
||||
if (!r) {
|
||||
out += scnprintf(out, end - out, "(no replicas section found)");
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
for_each_replicas_entry(r, e) {
|
||||
if (!first)
|
||||
out += scnprintf(out, end - out, " ");
|
||||
pr_buf(out, " ");
|
||||
first = false;
|
||||
|
||||
out += replicas_entry_to_text(e, out, end - out);
|
||||
replicas_entry_to_text(out, e);
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
const struct bch_sb_field_ops bch_sb_field_ops_replicas = {
|
||||
.validate = bch2_sb_validate_replicas,
|
||||
.to_text = bch2_sb_replicas_to_text,
|
||||
};
|
||||
|
||||
/* Query replicas: */
|
||||
|
||||
bool bch2_replicas_marked(struct bch_fs *c,
|
||||
|
@ -13,8 +13,7 @@ int bch2_mark_replicas(struct bch_fs *, enum bch_data_type,
|
||||
int bch2_mark_bkey_replicas(struct bch_fs *, enum bkey_type,
|
||||
struct bkey_s_c);
|
||||
|
||||
int bch2_cpu_replicas_to_text(struct bch_replicas_cpu *, char *, size_t);
|
||||
int bch2_sb_replicas_to_text(struct bch_sb_field_replicas *, char *, size_t);
|
||||
void bch2_cpu_replicas_to_text(struct printbuf *, struct bch_replicas_cpu *);
|
||||
|
||||
struct replicas_status {
|
||||
struct {
|
||||
|
@ -951,21 +951,20 @@ static const char *bch2_sb_field_validate(struct bch_sb *sb,
|
||||
: NULL;
|
||||
}
|
||||
|
||||
size_t bch2_sb_field_to_text(char *buf, size_t size,
|
||||
struct bch_sb *sb, struct bch_sb_field *f)
|
||||
void bch2_sb_field_to_text(struct printbuf *out, struct bch_sb *sb,
|
||||
struct bch_sb_field *f)
|
||||
{
|
||||
unsigned type = le32_to_cpu(f->type);
|
||||
size_t (*to_text)(char *, size_t, struct bch_sb *,
|
||||
struct bch_sb_field *) =
|
||||
type < BCH_SB_FIELD_NR
|
||||
? bch2_sb_field_ops[type]->to_text
|
||||
: NULL;
|
||||
const struct bch_sb_field_ops *ops = type < BCH_SB_FIELD_NR
|
||||
? bch2_sb_field_ops[type] : NULL;
|
||||
|
||||
if (!to_text) {
|
||||
if (size)
|
||||
buf[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
if (ops)
|
||||
pr_buf(out, "%s", bch2_sb_fields[type]);
|
||||
else
|
||||
pr_buf(out, "(unknown field %u)", type);
|
||||
|
||||
return to_text(buf, size, sb, f);
|
||||
pr_buf(out, " (size %llu):", vstruct_bytes(f));
|
||||
|
||||
if (ops && ops->to_text)
|
||||
bch2_sb_field_ops[type]->to_text(out, sb, f);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ extern const char * const bch2_sb_fields[];
|
||||
|
||||
struct bch_sb_field_ops {
|
||||
const char * (*validate)(struct bch_sb *, struct bch_sb_field *);
|
||||
size_t (*to_text)(char *, size_t, struct bch_sb *,
|
||||
void (*to_text)(struct printbuf *, struct bch_sb *,
|
||||
struct bch_sb_field *);
|
||||
};
|
||||
|
||||
@ -136,7 +136,7 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
|
||||
|
||||
void bch2_fs_mark_clean(struct bch_fs *, bool);
|
||||
|
||||
size_t bch2_sb_field_to_text(char *, size_t, struct bch_sb *,
|
||||
struct bch_sb_field *);
|
||||
void bch2_sb_field_to_text(struct printbuf *, struct bch_sb *,
|
||||
struct bch_sb_field *);
|
||||
|
||||
#endif /* _BCACHEFS_SUPER_IO_H */
|
||||
|
@ -1236,10 +1236,9 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
|
||||
data = bch2_dev_has_data(c, ca);
|
||||
if (data) {
|
||||
char data_has_str[100];
|
||||
bch2_scnprint_flag_list(data_has_str,
|
||||
sizeof(data_has_str),
|
||||
bch2_data_types,
|
||||
data);
|
||||
|
||||
bch2_string_opt_to_text(&PBUF(data_has_str),
|
||||
bch2_data_types, data);
|
||||
bch_err(ca, "Remove failed, still has data (%s)", data_has_str);
|
||||
ret = -EBUSY;
|
||||
goto err;
|
||||
|
@ -230,42 +230,34 @@ static size_t bch2_btree_cache_size(struct bch_fs *c)
|
||||
|
||||
static ssize_t show_fs_alloc_debug(struct bch_fs *c, char *buf)
|
||||
{
|
||||
char *out = buf, *end = buf + PAGE_SIZE;
|
||||
struct printbuf out = _PBUF(buf, PAGE_SIZE);
|
||||
struct bch_fs_usage stats = bch2_fs_usage_read(c);
|
||||
unsigned replicas, type;
|
||||
|
||||
out += scnprintf(out, end - out,
|
||||
"capacity:\t\t%llu\n",
|
||||
c->capacity);
|
||||
pr_buf(&out, "capacity:\t\t%llu\n", c->capacity);
|
||||
|
||||
for (replicas = 0; replicas < ARRAY_SIZE(stats.replicas); replicas++) {
|
||||
out += scnprintf(out, end - out,
|
||||
"%u replicas:\n",
|
||||
replicas + 1);
|
||||
pr_buf(&out, "%u replicas:\n", replicas + 1);
|
||||
|
||||
for (type = BCH_DATA_SB; type < BCH_DATA_NR; type++)
|
||||
out += scnprintf(out, end - out,
|
||||
"\t%s:\t\t%llu\n",
|
||||
bch2_data_types[type],
|
||||
stats.replicas[replicas].data[type]);
|
||||
out += scnprintf(out, end - out,
|
||||
"\treserved:\t%llu\n",
|
||||
stats.replicas[replicas].persistent_reserved);
|
||||
pr_buf(&out, "\t%s:\t\t%llu\n",
|
||||
bch2_data_types[type],
|
||||
stats.replicas[replicas].data[type]);
|
||||
pr_buf(&out, "\treserved:\t%llu\n",
|
||||
stats.replicas[replicas].persistent_reserved);
|
||||
}
|
||||
|
||||
out += scnprintf(out, end - out, "bucket usage\n");
|
||||
pr_buf(&out, "bucket usage\n");
|
||||
|
||||
for (type = BCH_DATA_SB; type < BCH_DATA_NR; type++)
|
||||
out += scnprintf(out, end - out,
|
||||
"\t%s:\t\t%llu\n",
|
||||
bch2_data_types[type],
|
||||
stats.buckets[type]);
|
||||
pr_buf(&out, "\t%s:\t\t%llu\n",
|
||||
bch2_data_types[type],
|
||||
stats.buckets[type]);
|
||||
|
||||
out += scnprintf(out, end - out,
|
||||
"online reserved:\t%llu\n",
|
||||
stats.online_reserved);
|
||||
pr_buf(&out, "online reserved:\t%llu\n",
|
||||
stats.online_reserved);
|
||||
|
||||
return out - buf;
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf)
|
||||
@ -559,16 +551,16 @@ struct attribute *bch2_fs_internal_files[] = {
|
||||
|
||||
SHOW(bch2_fs_opts_dir)
|
||||
{
|
||||
char *out = buf, *end = buf + PAGE_SIZE;
|
||||
struct printbuf out = _PBUF(buf, PAGE_SIZE);
|
||||
struct bch_fs *c = container_of(kobj, struct bch_fs, opts_dir);
|
||||
const struct bch_option *opt = container_of(attr, struct bch_option, attr);
|
||||
int id = opt - bch2_opt_table;
|
||||
u64 v = bch2_opt_get_by_id(&c->opts, id);
|
||||
|
||||
out += bch2_opt_to_text(c, out, end - out, opt, v, OPT_SHOW_FULL_LIST);
|
||||
out += scnprintf(out, end - out, "\n");
|
||||
bch2_opt_to_text(&out, c, opt, v, OPT_SHOW_FULL_LIST);
|
||||
pr_buf(&out, "\n");
|
||||
|
||||
return out - buf;
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
STORE(bch2_fs_opts_dir)
|
||||
@ -742,25 +734,23 @@ static ssize_t show_quantiles(struct bch_fs *c, struct bch_dev *ca,
|
||||
|
||||
static ssize_t show_reserve_stats(struct bch_dev *ca, char *buf)
|
||||
{
|
||||
struct printbuf out = _PBUF(buf, PAGE_SIZE);
|
||||
enum alloc_reserve i;
|
||||
ssize_t ret;
|
||||
|
||||
spin_lock(&ca->freelist_lock);
|
||||
|
||||
ret = scnprintf(buf, PAGE_SIZE,
|
||||
"free_inc:\t%zu\t%zu\n",
|
||||
fifo_used(&ca->free_inc),
|
||||
ca->free_inc.size);
|
||||
pr_buf(&out, "free_inc:\t%zu\t%zu\n",
|
||||
fifo_used(&ca->free_inc),
|
||||
ca->free_inc.size);
|
||||
|
||||
for (i = 0; i < RESERVE_NR; i++)
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"free[%u]:\t%zu\t%zu\n", i,
|
||||
fifo_used(&ca->free[i]),
|
||||
ca->free[i].size);
|
||||
pr_buf(&out, "free[%u]:\t%zu\t%zu\n", i,
|
||||
fifo_used(&ca->free[i]),
|
||||
ca->free[i].size);
|
||||
|
||||
spin_unlock(&ca->freelist_lock);
|
||||
|
||||
return ret;
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
static ssize_t show_dev_alloc_debug(struct bch_dev *ca, char *buf)
|
||||
@ -825,11 +815,11 @@ static const char * const bch2_rw[] = {
|
||||
|
||||
static ssize_t show_dev_iodone(struct bch_dev *ca, char *buf)
|
||||
{
|
||||
char *out = buf, *end = buf + PAGE_SIZE;
|
||||
struct printbuf out = _PBUF(buf, PAGE_SIZE);
|
||||
int rw, i, cpu;
|
||||
|
||||
for (rw = 0; rw < 2; rw++) {
|
||||
out += scnprintf(out, end - out, "%s:\n", bch2_rw[rw]);
|
||||
pr_buf(&out, "%s:\n", bch2_rw[rw]);
|
||||
|
||||
for (i = 1; i < BCH_DATA_NR; i++) {
|
||||
u64 n = 0;
|
||||
@ -837,19 +827,19 @@ static ssize_t show_dev_iodone(struct bch_dev *ca, char *buf)
|
||||
for_each_possible_cpu(cpu)
|
||||
n += per_cpu_ptr(ca->io_done, cpu)->sectors[rw][i];
|
||||
|
||||
out += scnprintf(out, end - out, "%-12s:%12llu\n",
|
||||
bch2_data_types[i], n << 9);
|
||||
pr_buf(&out, "%-12s:%12llu\n",
|
||||
bch2_data_types[i], n << 9);
|
||||
}
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
SHOW(bch2_dev)
|
||||
{
|
||||
struct bch_dev *ca = container_of(kobj, struct bch_dev, kobj);
|
||||
struct bch_fs *c = ca->fs;
|
||||
char *out = buf, *end = buf + PAGE_SIZE;
|
||||
struct printbuf out = _PBUF(buf, PAGE_SIZE);
|
||||
|
||||
sysfs_printf(uuid, "%pU\n", ca->uuid.b);
|
||||
|
||||
@ -863,41 +853,39 @@ SHOW(bch2_dev)
|
||||
if (attr == &sysfs_label) {
|
||||
if (ca->mi.group) {
|
||||
mutex_lock(&c->sb_lock);
|
||||
out += bch2_disk_path_print(&c->disk_sb, out, end - out,
|
||||
ca->mi.group - 1);
|
||||
bch2_disk_path_to_text(&out, &c->disk_sb,
|
||||
ca->mi.group - 1);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
} else {
|
||||
out += scnprintf(out, end - out, "none");
|
||||
pr_buf(&out, "none");
|
||||
}
|
||||
|
||||
out += scnprintf(out, end - out, "\n");
|
||||
return out - buf;
|
||||
pr_buf(&out, "\n");
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
if (attr == &sysfs_has_data) {
|
||||
out += bch2_scnprint_flag_list(out, end - out,
|
||||
bch2_data_types,
|
||||
bch2_dev_has_data(c, ca));
|
||||
out += scnprintf(out, end - out, "\n");
|
||||
return out - buf;
|
||||
bch2_flags_to_text(&out, bch2_data_types,
|
||||
bch2_dev_has_data(c, ca));
|
||||
pr_buf(&out, "\n");
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
sysfs_pd_controller_show(copy_gc, &ca->copygc_pd);
|
||||
|
||||
if (attr == &sysfs_cache_replacement_policy) {
|
||||
out += bch2_scnprint_string_list(out, end - out,
|
||||
bch2_cache_replacement_policies,
|
||||
ca->mi.replacement);
|
||||
out += scnprintf(out, end - out, "\n");
|
||||
return out - buf;
|
||||
bch2_string_opt_to_text(&out,
|
||||
bch2_cache_replacement_policies,
|
||||
ca->mi.replacement);
|
||||
pr_buf(&out, "\n");
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
if (attr == &sysfs_state_rw) {
|
||||
out += bch2_scnprint_string_list(out, end - out,
|
||||
bch2_dev_state,
|
||||
ca->mi.state);
|
||||
out += scnprintf(out, end - out, "\n");
|
||||
return out - buf;
|
||||
bch2_string_opt_to_text(&out, bch2_dev_state,
|
||||
ca->mi.state);
|
||||
pr_buf(&out, "\n");
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
if (attr == &sysfs_iodone)
|
||||
|
@ -124,47 +124,31 @@ ssize_t bch2_hprint(char *buf, s64 v)
|
||||
return sprintf(buf, "%lli%s%c", v, dec, si_units[u]);
|
||||
}
|
||||
|
||||
ssize_t bch2_scnprint_string_list(char *buf, size_t size,
|
||||
const char * const list[],
|
||||
size_t selected)
|
||||
void bch2_string_opt_to_text(struct printbuf *out,
|
||||
const char * const list[],
|
||||
size_t selected)
|
||||
{
|
||||
char *out = buf;
|
||||
size_t i;
|
||||
|
||||
if (size)
|
||||
*out = '\0';
|
||||
|
||||
for (i = 0; list[i]; i++)
|
||||
out += scnprintf(out, buf + size - out,
|
||||
i == selected ? "[%s] " : "%s ", list[i]);
|
||||
|
||||
if (out != buf)
|
||||
*--out = '\0';
|
||||
|
||||
return out - buf;
|
||||
pr_buf(out, i == selected ? "[%s] " : "%s ", list[i]);
|
||||
}
|
||||
|
||||
ssize_t bch2_scnprint_flag_list(char *buf, size_t size,
|
||||
const char * const list[], u64 flags)
|
||||
void bch2_flags_to_text(struct printbuf *out,
|
||||
const char * const list[], u64 flags)
|
||||
{
|
||||
char *out = buf, *end = buf + size;
|
||||
unsigned bit, nr = 0;
|
||||
|
||||
if (out->pos != out->end)
|
||||
*out->pos = '\0';
|
||||
|
||||
while (list[nr])
|
||||
nr++;
|
||||
|
||||
if (size)
|
||||
*out = '\0';
|
||||
|
||||
while (flags && (bit = __ffs(flags)) < nr) {
|
||||
out += scnprintf(out, end - out, "%s,", list[bit]);
|
||||
pr_buf(out, "%s,", list[bit]);
|
||||
flags ^= 1 << bit;
|
||||
}
|
||||
|
||||
if (out != buf)
|
||||
*--out = '\0';
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
u64 bch2_read_flag_list(char *opt, const char * const list[])
|
||||
@ -329,50 +313,50 @@ static const struct time_unit *pick_time_units(u64 ns)
|
||||
return u;
|
||||
}
|
||||
|
||||
static size_t pr_time_units(char *buf, size_t len, u64 ns)
|
||||
static void pr_time_units(struct printbuf *out, u64 ns)
|
||||
{
|
||||
const struct time_unit *u = pick_time_units(ns);
|
||||
|
||||
return scnprintf(buf, len, "%llu %s", div_u64(ns, u->nsecs), u->name);
|
||||
pr_buf(out, "%llu %s", div_u64(ns, u->nsecs), u->name);
|
||||
}
|
||||
|
||||
size_t bch2_time_stats_print(struct bch2_time_stats *stats, char *buf, size_t len)
|
||||
{
|
||||
char *out = buf, *end = buf + len;
|
||||
struct printbuf out = _PBUF(buf, len);
|
||||
const struct time_unit *u;
|
||||
u64 freq = READ_ONCE(stats->average_frequency);
|
||||
u64 q, last_q = 0;
|
||||
int i;
|
||||
|
||||
out += scnprintf(out, end - out, "count:\t\t%llu\n",
|
||||
pr_buf(&out, "count:\t\t%llu\n",
|
||||
stats->count);
|
||||
out += scnprintf(out, end - out, "rate:\t\t%llu/sec\n",
|
||||
freq ? div64_u64(NSEC_PER_SEC, freq) : 0);
|
||||
pr_buf(&out, "rate:\t\t%llu/sec\n",
|
||||
freq ? div64_u64(NSEC_PER_SEC, freq) : 0);
|
||||
|
||||
out += scnprintf(out, end - out, "frequency:\t");
|
||||
out += pr_time_units(out, end - out, freq);
|
||||
pr_buf(&out, "frequency:\t");
|
||||
pr_time_units(&out, freq);
|
||||
|
||||
out += scnprintf(out, end - out, "\navg duration:\t");
|
||||
out += pr_time_units(out, end - out, stats->average_duration);
|
||||
pr_buf(&out, "\navg duration:\t");
|
||||
pr_time_units(&out, stats->average_duration);
|
||||
|
||||
out += scnprintf(out, end - out, "\nmax duration:\t");
|
||||
out += pr_time_units(out, end - out, stats->max_duration);
|
||||
pr_buf(&out, "\nmax duration:\t");
|
||||
pr_time_units(&out, stats->max_duration);
|
||||
|
||||
i = eytzinger0_first(NR_QUANTILES);
|
||||
u = pick_time_units(stats->quantiles.entries[i].m);
|
||||
|
||||
out += scnprintf(out, end - out, "\nquantiles (%s):\t", u->name);
|
||||
pr_buf(&out, "\nquantiles (%s):\t", u->name);
|
||||
eytzinger0_for_each(i, NR_QUANTILES) {
|
||||
bool is_last = eytzinger0_next(i, NR_QUANTILES) == -1;
|
||||
|
||||
q = max(stats->quantiles.entries[i].m, last_q);
|
||||
out += scnprintf(out, end - out, "%llu%s",
|
||||
div_u64(q, u->nsecs),
|
||||
is_last ? "\n" : " ");
|
||||
pr_buf(&out, "%llu%s",
|
||||
div_u64(q, u->nsecs),
|
||||
is_last ? "\n" : " ");
|
||||
last_q = q;
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
||||
void bch2_time_stats_exit(struct bch2_time_stats *stats)
|
||||
@ -615,18 +599,17 @@ void memcpy_from_bio(void *dst, struct bio *src, struct bvec_iter src_iter)
|
||||
}
|
||||
}
|
||||
|
||||
size_t bch_scnmemcpy(char *buf, size_t size, const char *src, size_t len)
|
||||
void bch_scnmemcpy(struct printbuf *out,
|
||||
const char *src, size_t len)
|
||||
{
|
||||
size_t n;
|
||||
size_t n = printbuf_remaining(out);
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
n = min(size - 1, len);
|
||||
memcpy(buf, src, n);
|
||||
buf[n] = '\0';
|
||||
|
||||
return n;
|
||||
if (n) {
|
||||
n = min(n - 1, len);
|
||||
memcpy(out->pos, src, n);
|
||||
out->pos += n;
|
||||
*out->pos = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#include "eytzinger.h"
|
||||
|
@ -235,6 +235,32 @@ do { \
|
||||
#define ANYSINT_MAX(t) \
|
||||
((((t) 1 << (sizeof(t) * 8 - 2)) - (t) 1) * (t) 2 + (t) 1)
|
||||
|
||||
struct printbuf {
|
||||
char *pos;
|
||||
char *end;
|
||||
};
|
||||
|
||||
static inline size_t printbuf_remaining(struct printbuf *buf)
|
||||
{
|
||||
return buf->end - buf->pos;
|
||||
}
|
||||
|
||||
#define _PBUF(_buf, _len) \
|
||||
((struct printbuf) { \
|
||||
.pos = _buf, \
|
||||
.end = _buf + _len, \
|
||||
})
|
||||
|
||||
#define PBUF(_buf) _PBUF(_buf, sizeof(_buf))
|
||||
|
||||
#define pr_buf(_out, ...) \
|
||||
do { \
|
||||
(_out)->pos += scnprintf((_out)->pos, printbuf_remaining(_out), \
|
||||
__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
void bch_scnmemcpy(struct printbuf *, const char *, size_t);
|
||||
|
||||
int bch2_strtoint_h(const char *, int *);
|
||||
int bch2_strtouint_h(const char *, unsigned int *);
|
||||
int bch2_strtoll_h(const char *, long long *);
|
||||
@ -311,9 +337,10 @@ ssize_t bch2_hprint(char *buf, s64 v);
|
||||
|
||||
bool bch2_is_zero(const void *, size_t);
|
||||
|
||||
ssize_t bch2_scnprint_string_list(char *, size_t, const char * const[], size_t);
|
||||
void bch2_string_opt_to_text(struct printbuf *,
|
||||
const char * const [], size_t);
|
||||
|
||||
ssize_t bch2_scnprint_flag_list(char *, size_t, const char * const[], u64);
|
||||
void bch2_flags_to_text(struct printbuf *, const char * const[], u64);
|
||||
u64 bch2_read_flag_list(char *, const char * const[]);
|
||||
|
||||
#define NR_QUANTILES 15
|
||||
@ -629,8 +656,6 @@ static inline struct bio_vec next_contig_bvec(struct bio *bio,
|
||||
#define bio_for_each_contig_segment(bv, bio, iter) \
|
||||
__bio_for_each_contig_segment(bv, bio, iter, (bio)->bi_iter)
|
||||
|
||||
size_t bch_scnmemcpy(char *, size_t, const char *, size_t);
|
||||
|
||||
void sort_cmp_size(void *base, size_t num, size_t size,
|
||||
int (*cmp_func)(const void *, const void *, size_t),
|
||||
void (*swap_func)(void *, void *, size_t));
|
||||
|
@ -111,10 +111,9 @@ const char *bch2_xattr_invalid(const struct bch_fs *c, struct bkey_s_c k)
|
||||
}
|
||||
}
|
||||
|
||||
int bch2_xattr_to_text(struct bch_fs *c, char *buf,
|
||||
size_t size, struct bkey_s_c k)
|
||||
void bch2_xattr_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct bkey_s_c k)
|
||||
{
|
||||
char *out = buf, *end = buf + size;
|
||||
const struct xattr_handler *handler;
|
||||
struct bkey_s_c_xattr xattr;
|
||||
|
||||
@ -124,26 +123,22 @@ int bch2_xattr_to_text(struct bch_fs *c, char *buf,
|
||||
|
||||
handler = bch2_xattr_type_to_handler(xattr.v->x_type);
|
||||
if (handler && handler->prefix)
|
||||
out += scnprintf(out, end - out, "%s", handler->prefix);
|
||||
pr_buf(out, "%s", handler->prefix);
|
||||
else if (handler)
|
||||
out += scnprintf(out, end - out, "(type %u)",
|
||||
xattr.v->x_type);
|
||||
pr_buf(out, "(type %u)", xattr.v->x_type);
|
||||
else
|
||||
out += scnprintf(out, end - out, "(unknown type %u)",
|
||||
xattr.v->x_type);
|
||||
pr_buf(out, "(unknown type %u)", xattr.v->x_type);
|
||||
|
||||
out += bch_scnmemcpy(out, end - out, xattr.v->x_name,
|
||||
xattr.v->x_name_len);
|
||||
out += scnprintf(out, end - out, ":");
|
||||
out += bch_scnmemcpy(out, end - out, xattr_val(xattr.v),
|
||||
le16_to_cpu(xattr.v->x_val_len));
|
||||
bch_scnmemcpy(out, xattr.v->x_name,
|
||||
xattr.v->x_name_len);
|
||||
pr_buf(out, ":");
|
||||
bch_scnmemcpy(out, xattr_val(xattr.v),
|
||||
le16_to_cpu(xattr.v->x_val_len));
|
||||
break;
|
||||
case BCH_XATTR_WHITEOUT:
|
||||
out += scnprintf(out, end - out, "whiteout");
|
||||
pr_buf(out, "whiteout");
|
||||
break;
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
int bch2_xattr_get(struct bch_fs *c, struct bch_inode_info *inode,
|
||||
@ -355,7 +350,7 @@ static int bch2_xattr_bcachefs_get(const struct xattr_handler *handler,
|
||||
struct bch_opts opts =
|
||||
bch2_inode_opts_to_opts(bch2_inode_opts_get(&inode->ei_inode));
|
||||
const struct bch_option *opt;
|
||||
int ret, id;
|
||||
int id;
|
||||
u64 v;
|
||||
|
||||
id = bch2_opt_lookup(name);
|
||||
@ -369,9 +364,22 @@ static int bch2_xattr_bcachefs_get(const struct xattr_handler *handler,
|
||||
|
||||
v = bch2_opt_get_by_id(&opts, id);
|
||||
|
||||
ret = bch2_opt_to_text(c, buffer, size, opt, v, 0);
|
||||
if (!buffer) {
|
||||
char buf[512];
|
||||
struct printbuf out = PBUF(buf);
|
||||
|
||||
return ret < size || !buffer ? ret : -ERANGE;
|
||||
bch2_opt_to_text(&out, c, opt, v, 0);
|
||||
|
||||
return out.pos - buf;
|
||||
} else {
|
||||
struct printbuf out = _PBUF(buffer, size);
|
||||
|
||||
bch2_opt_to_text(&out, c, opt, v, 0);
|
||||
|
||||
return printbuf_remaining(&out)
|
||||
? (void *) out.pos - buffer
|
||||
: -ERANGE;
|
||||
}
|
||||
}
|
||||
|
||||
struct inode_opt_set {
|
||||
|
@ -7,7 +7,7 @@
|
||||
extern const struct bch_hash_desc bch2_xattr_hash_desc;
|
||||
|
||||
const char *bch2_xattr_invalid(const struct bch_fs *, struct bkey_s_c);
|
||||
int bch2_xattr_to_text(struct bch_fs *, char *, size_t, struct bkey_s_c);
|
||||
void bch2_xattr_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||
|
||||
#define bch2_bkey_xattr_ops (struct bkey_ops) { \
|
||||
.key_invalid = bch2_xattr_invalid, \
|
||||
|
Loading…
Reference in New Issue
Block a user