summaryrefslogtreecommitdiff
path: root/fs/bcachefs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-11-09 01:24:07 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:11 -0400
commit319f9ac38eaba628d69b6ddbf402b35487315fc1 (patch)
tree01daddd4881b1f09bb4d50087e8b8803e59fea35 /fs/bcachefs
parent75369d4ec3d2dfc52af18a2d20cd0af14c935ac9 (diff)
bcachefs: revamp to_text methods
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs')
-rw-r--r--fs/bcachefs/alloc_background.c14
-rw-r--r--fs/bcachefs/alloc_background.h2
-rw-r--r--fs/bcachefs/bkey.c4
-rw-r--r--fs/bcachefs/bkey_methods.c60
-rw-r--r--fs/bcachefs/bkey_methods.h16
-rw-r--r--fs/bcachefs/bset.c82
-rw-r--r--fs/bcachefs/bset.h4
-rw-r--r--fs/bcachefs/btree_cache.c85
-rw-r--r--fs/bcachefs/btree_cache.h4
-rw-r--r--fs/bcachefs/btree_io.c65
-rw-r--r--fs/bcachefs/btree_iter.c19
-rw-r--r--fs/bcachefs/btree_update_interior.c16
-rw-r--r--fs/bcachefs/debug.c17
-rw-r--r--fs/bcachefs/dirent.c15
-rw-r--r--fs/bcachefs/dirent.h2
-rw-r--r--fs/bcachefs/disk_groups.c56
-rw-r--r--fs/bcachefs/disk_groups.h5
-rw-r--r--fs/bcachefs/extents.c92
-rw-r--r--fs/bcachefs/extents.h5
-rw-r--r--fs/bcachefs/fs.c2
-rw-r--r--fs/bcachefs/fsck.c40
-rw-r--r--fs/bcachefs/inode.c11
-rw-r--r--fs/bcachefs/inode.h2
-rw-r--r--fs/bcachefs/journal.c88
-rw-r--r--fs/bcachefs/journal_io.c7
-rw-r--r--fs/bcachefs/opts.c36
-rw-r--r--fs/bcachefs/opts.h7
-rw-r--r--fs/bcachefs/quota.c15
-rw-r--r--fs/bcachefs/quota.h2
-rw-r--r--fs/bcachefs/rebalance.c34
-rw-r--r--fs/bcachefs/replicas.c51
-rw-r--r--fs/bcachefs/replicas.h3
-rw-r--r--fs/bcachefs/super-io.c25
-rw-r--r--fs/bcachefs/super-io.h6
-rw-r--r--fs/bcachefs/super.c7
-rw-r--r--fs/bcachefs/sysfs.c114
-rw-r--r--fs/bcachefs/util.c89
-rw-r--r--fs/bcachefs/util.h33
-rw-r--r--fs/bcachefs/xattr.c48
-rw-r--r--fs/bcachefs/xattr.h2
40 files changed, 550 insertions, 635 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c
index a4c4a08aed59..291d352ee370 100644
--- a/fs/bcachefs/alloc_background.c
+++ b/fs/bcachefs/alloc_background.c
@@ -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)
diff --git a/fs/bcachefs/alloc_background.h b/fs/bcachefs/alloc_background.h
index 33224070e827..99535fa60214 100644
--- a/fs/bcachefs/alloc_background.h
+++ b/fs/bcachefs/alloc_background.h
@@ -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, \
diff --git a/fs/bcachefs/bkey.c b/fs/bcachefs/bkey.c
index c0e86ada1c53..d7e022ba2027 100644
--- a/fs/bcachefs/bkey.c
+++ b/fs/bcachefs/bkey.c
@@ -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);
diff --git a/fs/bcachefs/bkey_methods.c b/fs/bcachefs/bkey_methods.c
index b3f5f28b8761..7335fbbb3f61 100644
--- a/fs/bcachefs/bkey_methods.c
+++ b/fs/bcachefs/bkey_methods.c
@@ -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;
-
- p("u64s %u type %u ", k->u64s, k->type);
+ pr_buf(out, "u64s %u type %u ", k->u64s, k->type);
- out += bch2_bpos_to_text(out, end - out, k->p);
+ bch2_bpos_to_text(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,
diff --git a/fs/bcachefs/bkey_methods.h b/fs/bcachefs/bkey_methods.h
index 6ee774ba3d7a..be6041e92c05 100644
--- a/fs/bcachefs/bkey_methods.h
+++ b/fs/bcachefs/bkey_methods.h
@@ -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 *);
diff --git a/fs/bcachefs/bset.c b/fs/bcachefs/bset.c
index 7fc8fb85069f..ac84aac4a263 100644
--- a/fs/bcachefs/bset.c
+++ b/fs/bcachefs/bset.c
@@ -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;
}
diff --git a/fs/bcachefs/bset.h b/fs/bcachefs/bset.h
index 1b0122dad2bc..5d03036620b9 100644
--- a/fs/bcachefs/bset.h
+++ b/fs/bcachefs/bset.h
@@ -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 */
diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c
index 3cb3da363d11..846d5e816aa2 100644
--- a/fs/bcachefs/btree_cache.c
+++ b/fs/bcachefs/btree_cache.c
@@ -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);
}
diff --git a/fs/bcachefs/btree_cache.h b/fs/bcachefs/btree_cache.h
index f7b9bcfe09a3..cb7f66fc8bd4 100644
--- a/fs/bcachefs/btree_cache.h
+++ b/fs/bcachefs/btree_cache.h
@@ -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 */
diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c
index 1036b72f1ae6..f1c31e74348a 100644
--- a/fs/bcachefs/btree_io.c
+++ b/fs/bcachefs/btree_io.c
@@ -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;
}
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index 1ba59c53c36f..ea37fa21ed6e 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -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;
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
index 4ec448718fd8..92bacd16fdc3 100644
--- a/fs/bcachefs/btree_update_interior.c
+++ b/fs/bcachefs/btree_update_interior.c
@@ -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)
diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c
index 550bb10bbb7b..0a9efe57d5a9 100644
--- a/fs/bcachefs/debug.c
+++ b/fs/bcachefs/debug.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;
diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c
index 0651f5575131..c1a611b4d9ec 100644
--- a/fs/bcachefs/dirent.c
+++ b/fs/bcachefs/dirent.c
@@ -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,
diff --git a/fs/bcachefs/dirent.h b/fs/bcachefs/dirent.h
index 30d2143d4ca7..2afb0baed11a 100644
--- a/fs/bcachefs/dirent.h
+++ b/fs/bcachefs/dirent.h
@@ -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, \
diff --git a/fs/bcachefs/disk_groups.c b/fs/bcachefs/disk_groups.c
index 48f472a384f1..ee10308131e9 100644
--- a/fs/bcachefs/disk_groups.c
+++ b/fs/bcachefs/disk_groups.c
@@ -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;
}
diff --git a/fs/bcachefs/disk_groups.h b/fs/bcachefs/disk_groups.h
index d202eb3a9de6..ceb75f86b615 100644
--- a/fs/bcachefs/disk_groups.h
+++ b/fs/bcachefs/disk_groups.h
@@ -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 *);
diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c
index 1606826e7802..a7223e7c8793 100644
--- a/fs/bcachefs/extents.c
+++ b/fs/bcachefs/extents.c
@@ -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,
diff --git a/fs/bcachefs/extents.h b/fs/bcachefs/extents.h
index 8754a940a476..d121ce5b3225 100644
--- a/fs/bcachefs/extents.h
+++ b/fs/bcachefs/extents.h
@@ -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 *);
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 88bf88c047ae..b6fe2059fe5f 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -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);
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index 7e08592253a6..74b83201c213 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -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);
diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c
index debdbf58dd79..0a350c6d0932 100644
--- a/fs/bcachefs/inode.c
+++ b/fs/bcachefs/inode.c
@@ -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,
diff --git a/fs/bcachefs/inode.h b/fs/bcachefs/inode.h
index 8713b51d3af7..897ff65d01cb 100644
--- a/fs/bcachefs/inode.h
+++ b/fs/bcachefs/inode.h
@@ -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, \
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index 7499e15a2982..b4d037664628 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -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;
}
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c
index eb2fbe235483..4555d55b23dd 100644
--- a/fs/bcachefs/journal_io.c
+++ b/fs/bcachefs/journal_io.c
@@ -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);
diff --git a/fs/bcachefs/opts.c b/fs/bcachefs/opts.c
index 9351caeb6630..c12af1a86f0b 100644
--- a/fs/bcachefs/opts.c
+++ b/fs/bcachefs/opts.c
@@ -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)
diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h
index 52fb9781d933..47617cd011ff 100644
--- a/fs/bcachefs/opts.h
+++ b/fs/bcachefs/opts.h
@@ -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 *);
diff --git a/fs/bcachefs/quota.c b/fs/bcachefs/quota.c
index 79a7f82868d6..8127f4454dac 100644
--- a/fs/bcachefs/quota.c
+++ b/fs/bcachefs/quota.c
@@ -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
diff --git a/fs/bcachefs/quota.h b/fs/bcachefs/quota.h
index 9650e518cd64..9c06eb07bccb 100644
--- a/fs/bcachefs/quota.h
+++ b/fs/bcachefs/quota.h
@@ -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, \
diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c
index 570dbae5a240..5d246c5b8186 100644
--- a/fs/bcachefs/rebalance.c
+++ b/fs/bcachefs/rebalance.c
@@ -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)
diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c
index a7c3aca1bf01..fb11b97cdeee 100644
--- a/fs/bcachefs/replicas.c
+++ b/fs/bcachefs/replicas.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,
diff --git a/fs/bcachefs/replicas.h b/fs/bcachefs/replicas.h
index ebbb1334cc2c..d3d81a1a39cd 100644
--- a/fs/bcachefs/replicas.h
+++ b/fs/bcachefs/replicas.h
@@ -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 {
diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c
index 58c35d9665eb..0c2b20c9e8c4 100644
--- a/fs/bcachefs/super-io.c
+++ b/fs/bcachefs/super-io.c
@@ -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);
+
+ pr_buf(out, " (size %llu):", vstruct_bytes(f));
- return to_text(buf, size, sb, f);
+ if (ops && ops->to_text)
+ bch2_sb_field_ops[type]->to_text(out, sb, f);
}
diff --git a/fs/bcachefs/super-io.h b/fs/bcachefs/super-io.h
index 1ea91f71f3b0..ceef650d55dd 100644
--- a/fs/bcachefs/super-io.h
+++ b/fs/bcachefs/super-io.h
@@ -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 */
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index 54d23cf46f95..a22beff7cc96 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -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;
diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c
index ee91bcc6433c..4ca84de6ab0e 100644
--- a/fs/bcachefs/sysfs.c
+++ b/fs/bcachefs/sysfs.c
@@ -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)
diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c
index ed90bd3a5d18..bb6b4383d33f 100644
--- a/fs/bcachefs/util.c
+++ b/fs/bcachefs/util.c
@@ -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;
-
- if (!size)
- return 0;
+ size_t n = printbuf_remaining(out);
- 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"
diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h
index cb6bed68abf8..47afd3955c7a 100644
--- a/fs/bcachefs/util.h
+++ b/fs/bcachefs/util.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));
diff --git a/fs/bcachefs/xattr.c b/fs/bcachefs/xattr.c
index 44bf4a2f3c84..7f6258e09a0d 100644
--- a/fs/bcachefs/xattr.c
+++ b/fs/bcachefs/xattr.c
@@ -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);
-
- 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));
+ pr_buf(out, "(unknown type %u)", xattr.v->x_type);
+
+ 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 {
diff --git a/fs/bcachefs/xattr.h b/fs/bcachefs/xattr.h
index b2fe1dc42b83..63be44b02a2b 100644
--- a/fs/bcachefs/xattr.h
+++ b/fs/bcachefs/xattr.h
@@ -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, \