]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Update bcachefs sources to d7dbddc450 bcachefs: revamp to_text methods
authorKent Overstreet <kent.overstreet@gmail.com>
Fri, 9 Nov 2018 09:00:42 +0000 (04:00 -0500)
committerKent Overstreet <kent.overstreet@gmail.com>
Fri, 9 Nov 2018 09:06:53 +0000 (04:06 -0500)
43 files changed:
.bcachefs_revision
cmd_debug.c
libbcachefs.c
libbcachefs/alloc_background.c
libbcachefs/alloc_background.h
libbcachefs/bkey.c
libbcachefs/bkey_methods.c
libbcachefs/bkey_methods.h
libbcachefs/bset.c
libbcachefs/bset.h
libbcachefs/btree_cache.c
libbcachefs/btree_cache.h
libbcachefs/btree_io.c
libbcachefs/btree_iter.c
libbcachefs/btree_update_interior.c
libbcachefs/debug.c
libbcachefs/dirent.c
libbcachefs/dirent.h
libbcachefs/disk_groups.c
libbcachefs/disk_groups.h
libbcachefs/extents.c
libbcachefs/extents.h
libbcachefs/fs.c
libbcachefs/fsck.c
libbcachefs/inode.c
libbcachefs/inode.h
libbcachefs/journal.c
libbcachefs/journal_io.c
libbcachefs/opts.c
libbcachefs/opts.h
libbcachefs/quota.c
libbcachefs/quota.h
libbcachefs/rebalance.c
libbcachefs/replicas.c
libbcachefs/replicas.h
libbcachefs/super-io.c
libbcachefs/super-io.h
libbcachefs/super.c
libbcachefs/sysfs.c
libbcachefs/util.c
libbcachefs/util.h
libbcachefs/xattr.c
libbcachefs/xattr.h

index f7a6bdbc6eb0ebaba4324298e2ae206061cf9c27..b4ec318867fe2480db2422539eaa9cc3f7758908 100644 (file)
@@ -1 +1 @@
-7227ff07f14b424e92b13dd5099aba9ece1ec43c
+d7dbddc4504c1bf509f8eb5818b5042342dc9ed1
index d27e95554e9e863c8f13f7e7c6b86cbb54028259..1c5af4d1420351033fa572c67c44ea57f7d07cc0 100644 (file)
@@ -160,8 +160,8 @@ static void list_keys(struct bch_fs *c, enum btree_id btree_id,
                if (bkey_cmp(k.k->p, end) > 0)
                        break;
 
-               bch2_bkey_val_to_text(c, bkey_type(0, btree_id),
-                                     buf, sizeof(buf), k);
+               bch2_bkey_val_to_text(&PBUF(buf), c,
+                               bkey_type(0, btree_id), k);
                puts(buf);
        }
        bch2_btree_iter_unlock(&iter);
@@ -178,7 +178,7 @@ static void list_btree_formats(struct bch_fs *c, enum btree_id btree_id,
                if (bkey_cmp(b->key.k.p, end) > 0)
                        break;
 
-               bch2_print_btree_node(c, b, buf, sizeof(buf));
+               bch2_btree_node_to_text(&PBUF(buf), c, b);
                puts(buf);
        }
        bch2_btree_iter_unlock(&iter);
@@ -198,14 +198,13 @@ static void list_nodes_keys(struct bch_fs *c, enum btree_id btree_id,
                if (bkey_cmp(b->key.k.p, end) > 0)
                        break;
 
-               bch2_print_btree_node(c, b, buf, sizeof(buf));
+               bch2_btree_node_to_text(&PBUF(buf), c, b);
                fputs(buf, stdout);
 
-               buf[0] = '\t';
-
                for_each_btree_node_key_unpack(b, k, &node_iter, &unpacked) {
-                       bch2_bkey_val_to_text(c, bkey_type(0, btree_id),
-                                             buf + 1, sizeof(buf) - 1, k);
+                       bch2_bkey_val_to_text(&PBUF(buf), c,
+                                       bkey_type(0, btree_id), k);
+                       putchar('\t');
                        puts(buf);
                }
        }
index 6c78f282136e34bca890118f889923d2e1f03fef..968748af31dcf9cf3fea1a55cd6bc007f8b5bbca 100644 (file)
@@ -470,17 +470,15 @@ static void bch2_sb_print_members(struct bch_sb *sb, struct bch_sb_field *f,
                        strcpy(group, "(none)");
                }
 
-               bch2_scnprint_flag_list(data_allowed_str,
-                                       sizeof(data_allowed_str),
-                                       bch2_data_types,
-                                       BCH_MEMBER_DATA_ALLOWED(m));
+               bch2_flags_to_text(&PBUF(data_allowed_str),
+                                  bch2_data_types,
+                                  BCH_MEMBER_DATA_ALLOWED(m));
                if (!data_allowed_str[0])
                        strcpy(data_allowed_str, "(none)");
 
-               bch2_scnprint_flag_list(data_has_str,
-                                       sizeof(data_has_str),
-                                       bch2_data_types,
-                                       get_dev_has_data(sb, i));
+               bch2_flags_to_text(&PBUF(data_has_str),
+                                  bch2_data_types,
+                                  get_dev_has_data(sb, i));
                if (!data_has_str[0])
                        strcpy(data_has_str, "(none)");
 
@@ -661,8 +659,8 @@ void bch2_sb_print(struct bch_sb *sb, bool print_layout,
 
        vstruct_for_each(sb, f)
                fields_have |= 1 << le32_to_cpu(f->type);
-       bch2_scnprint_flag_list(fields_have_str, sizeof(fields_have_str),
-                               bch2_sb_fields, fields_have);
+       bch2_flags_to_text(&PBUF(fields_have_str),
+                          bch2_sb_fields, fields_have);
 
        printf("External UUID:                  %s\n"
               "Internal UUID:                  %s\n"
index 9ff61deb1f5d50d5c07265cfb7c5f0bbd7708f59..41ea73aeb33639e64cad616d7b27c4b01fceda6e 100644 (file)
@@ -93,17 +93,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)
index ea07705bd173e933bd64419294f5e0dca73a28bd..2de9357c7b019fc7b9c2ab645c53ad0198c03b8c 100644 (file)
@@ -8,7 +8,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,           \
index 850ba72cc5a102af866a2bfdc88e00933fdef59a..135ecb8df16955a3d9838685cd969f63e3010c85 100644 (file)
@@ -59,8 +59,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);
 
index 21883c57fb616df9b3264459fe7ee33e10da1ecc..43bcbb08367d89eed3f3e502fbb86e10c31b2bc0 100644 (file)
@@ -110,7 +110,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;
        }
@@ -120,73 +120,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,
index cf7a55630ac10a64024b5511911e8713116958bd..11ce12f54c5d9b06a82c524c5bf9754ea6b376bf 100644 (file)
@@ -45,8 +45,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;
@@ -61,12 +61,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 *);
index c631e30aca53e9fa7362100698a3290a5b48ff73..7e572f5ffd706c7697a87d3d261fef1ff1fdffba 100644 (file)
@@ -68,7 +68,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);
 
@@ -118,7 +118,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);
        }
@@ -162,8 +162,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:");
@@ -224,8 +224,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"
@@ -246,8 +246,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"
@@ -1784,8 +1784,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;
@@ -1793,28 +1793,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)
@@ -1829,28 +1830,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;
 }
index 0224bc95fa7648b8cc5489bb1bcfd66b2c1d0736..a27c8a29709cac4a0ec5445984eff78c7b51cfba 100644 (file)
@@ -591,8 +591,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 */
 
index db3712a83dc1453bfcfd42f7f6ae0609b2be0524..28ac862b23d35eeaacfe038d789d20e9da4cc5c8 100644 (file)
@@ -886,55 +886,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);
 }
index 96d134f4d0fc5ae4b1652fc024f66711f5f3651f..399f8b9ad1428de3bafb72eba23156040aafc0bb 100644 (file)
@@ -84,7 +84,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 */
index beab463b51e1221fa52fe33edf503ff4e08beebb..a4da97916c7c672c0e80f805c3889030493cb8cf 100644 (file)
@@ -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);
 
@@ -2059,7 +2054,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;
@@ -2076,18 +2071,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;
 }
index ad31a07c1942b356cfa1dd05bba5b50bb7290e99..1eae181dc9ff436a70cdbc97cc7c798a17b84573 100644 (file)
@@ -426,7 +426,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);
        }
@@ -436,7 +436,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",
@@ -686,7 +686,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);
        }
@@ -1450,18 +1450,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;
index 0a9d6919ccd334f615f952a490ee255ee5804dad..4d34bdca317fd5ab542e43e58d0732fae334e729 100644 (file)
@@ -2149,20 +2149,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)
index f69d76ec1e78480fbe011e487304eabf0550af56..77f90f7db1d71bad4855161dc17ac661e75fd8ec 100644 (file)
@@ -222,8 +222,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';
@@ -271,8 +271,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;
@@ -329,17 +329,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;
index 627870ad8f2c888d5ad2feeee44dd506cc02460b..3ec0b4c5242cda3ff03cd8899104bf9aca57aa32 100644 (file)
@@ -109,26 +109,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,
index 891269f8da1d4bfe2cb946506d5a0dc7f61f366f..a57a5382780b962594006d4295284890dcac00ef 100644 (file)
@@ -6,7 +6,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,          \
index 87f3940e1df5087d3111c518505a154ad10a8acd..eddd8899182bcbe70dc28f6ce91717a000de6677 100644 (file)
@@ -82,11 +82,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;
@@ -96,18 +95,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 = {
@@ -342,10 +337,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;
@@ -373,26 +368,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)
@@ -451,14 +438,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;
 
@@ -470,13 +457,13 @@ int bch2_opt_target_print(struct bch_fs *c, char *buf, size_t len, u64 v)
                if (ca && percpu_ref_tryget(&ca->io_ref)) {
                        char b[BDEVNAME_SIZE];
 
-                       ret = scnprintf(buf, len, "/dev/%s",
-                                       bdevname(ca->disk_sb.bdev, b));
+                       pr_buf(out, "/dev/%s",
+                            bdevname(ca->disk_sb.bdev, b));
                        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();
@@ -484,12 +471,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;
 }
index e92c0dc50970b50df1966b0afd0f11d31becb880..d6047283ddea7b40ca6f111f6059c2a7e1197340 100644 (file)
@@ -58,10 +58,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 *);
 
index 5c48d2d96a5f67adedbbaa274c6b9e11e3116588..72301eab034f3016996950d90cf522151bb7c8be 100644 (file)
@@ -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,
index e04cb5a9839c5882b78838128620dcdcfb159fac..5b786cb29fcdbefc5feb464faec398c259f5d236 100644 (file)
@@ -17,7 +17,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) {                        \
@@ -29,7 +30,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 *);
index 1cf729107b1ec49e971172f57cfea37277faa4de..9bda6212c583bc76fb7057f1c74fd82dd9b3ed59 100644 (file)
@@ -1533,7 +1533,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);
index be7ba06418e4a22c984992b3469dc9b9abd56075..53ee1b0e88053e07dbc440c141929cdc49bb0215 100644 (file)
@@ -233,8 +233,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;
@@ -297,8 +298,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);
@@ -381,8 +383,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)
@@ -524,13 +527,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, BTREE_ID_DIRENTS,
-                                                      buf, sizeof(buf), k), buf)) ||
+                               (bch2_bkey_val_to_text(&PBUF(buf), c,
+                                                      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, BTREE_ID_DIRENTS,
-                                                      buf, sizeof(buf), k), buf))) {
+                               (bch2_bkey_val_to_text(&PBUF(buf), c,
+                                                      BTREE_ID_DIRENTS,
+                                                      k), buf))) {
                        ret = bch2_btree_delete_at(iter, 0);
                        if (ret)
                                goto err;
@@ -579,8 +584,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, BTREE_ID_DIRENTS,
-                                                      buf, sizeof(buf), k), buf))) {
+                               (bch2_bkey_val_to_text(&PBUF(buf), c,
+                                                      BTREE_ID_DIRENTS,
+                                                      k), buf))) {
                        ret = remove_dirent(c, iter, d);
                        if (ret)
                                goto err;
@@ -596,8 +602,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, BTREE_ID_DIRENTS,
-                                                      buf, sizeof(buf), k), buf))) {
+                               (bch2_bkey_val_to_text(&PBUF(buf), c,
+                                                      BTREE_ID_DIRENTS,
+                                                      k), buf))) {
                        ret = remove_dirent(c, iter, d);
                        if (ret)
                                goto err;
@@ -609,8 +616,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, BTREE_ID_DIRENTS,
-                                                      buf, sizeof(buf), k), buf))) {
+                               (bch2_bkey_val_to_text(&PBUF(buf), c,
+                                                      BTREE_ID_DIRENTS,
+                                                      k), buf))) {
                        struct bkey_i_dirent *n;
 
                        n = kmalloc(bkey_bytes(d.k), GFP_KERNEL);
index 4841715ca34f6ef9eb62902f9fd638302932d983..207ca369724cc2a8bd1383fe322ade50323642eb 100644 (file)
@@ -227,10 +227,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;
 
@@ -238,18 +237,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,
index 93dbdaeb7ecbdbc46f939b75f5bb31168d35eb4e..e4495a44b8a48bee53978f3c28be1cbac9ed4d35 100644 (file)
@@ -6,7 +6,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,           \
index f712fd1e425a806193e7a66bbdd85185853b9bd6..26c7ae7d7563650bbd4d28b65757856a160c0f86 100644 (file)
@@ -1023,38 +1023,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]) {
@@ -1063,50 +1063,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;
 }
index f271da764a9199059877404cf7717cb81c19322f..961d8d81e3812aef5234864f8d02a05407f182f5 100644 (file)
@@ -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);
 
index 8e655bc167edccc851945bfeb1150529f32e749a..1dab991bc29b0fa6ac01e8e759d98ebdec334980 100644 (file)
@@ -144,7 +144,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] = {                                               \
@@ -234,38 +234,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)
index 81c660838f57ec87cc2a1298717d98ae33ed1274..c65a8d13636d21e1bb51f2c0d64d110692e7e895 100644 (file)
@@ -225,6 +225,7 @@ enum bch_opt_id {
 };
 
 struct bch_fs;
+struct printbuf;
 
 struct bch_option {
        struct attribute        attr;
@@ -241,7 +242,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);
        };
        };
 
@@ -261,8 +262,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 *);
 
index e16045815822a867120ccd2ad8800b9ee01cd7d1..75104ea98027f449196420148578438a022eb05f 100644 (file)
@@ -45,10 +45,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;
 
@@ -57,14 +56,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
index 14570c8b277920ae5dcf1a098f29f13ba22dc488..325b9fc0213b33ef7a15648104a932c15332ac6a 100644 (file)
@@ -7,7 +7,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,           \
index 85ea4c6bf90fd93b9cef8b1843aab867c34f845e..25d72de64d6a69c53dc20eaf6525cee21df2d2cf 100644 (file)
@@ -251,49 +251,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)
index b0cef995e9e6923907d66d559f0d8729ba20c6bf..4da35d0932ae2e88c15f5756e5f5bf077a1b19d8 100644 (file)
@@ -39,38 +39,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,
@@ -266,6 +259,8 @@ int bch2_mark_bkey_replicas(struct bch_fs *c,
        struct bch_replicas_entry_padded search;
        int ret;
 
+       memset(&search, 0, sizeof(search));
+
        if (type == BKEY_TYPE_EXTENTS) {
                struct bch_devs_list cached = bch2_bkey_cached_devs(k);
                unsigned i;
@@ -507,32 +502,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,
@@ -563,6 +554,8 @@ bool bch2_bkey_replicas_marked(struct bch_fs *c,
        struct bch_replicas_entry_padded search;
        bool ret;
 
+       memset(&search, 0, sizeof(search));
+
        if (type == BKEY_TYPE_EXTENTS) {
                struct bch_devs_list cached = bch2_bkey_cached_devs(k);
                unsigned i;
index 640fe5b269753a89a553d4497a2f24be03e57207..7deca37c30d67b02e79344dfb55ed6a266e8ed4e 100644 (file)
@@ -12,8 +12,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 {
index 8ef5db3dc023b76f900b5cb99086e657c5b1c6ed..d1fca0d649dca7dd28ee9a1648e8c7ebb1e8ae7a 100644 (file)
@@ -948,21 +948,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);
 }
index 7d09d8e45816b7f2ce19aed6bcfa7504d1f1909a..6eb193ac7074805080e632d5dcb0ea836823520d 100644 (file)
@@ -37,7 +37,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 *);
 };
 
@@ -135,7 +135,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 */
index dded527d7d531cac199f0d090132ae895cb72bd1..5b27ead03cd424302eb571344ec0f09f84f79774 100644 (file)
@@ -1274,10 +1274,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;
index 481269201389e0e5f9c1dfee12de15d66b71a3bf..c6a653ac201221bfe25a9f630978bd510f5f85af 100644 (file)
@@ -229,42 +229,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)
@@ -558,16 +550,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)
@@ -741,25 +733,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)
@@ -824,11 +814,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;
@@ -836,19 +826,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);
 
@@ -862,41 +852,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)
index 4df96ef0bcd0a30a1bb03df3088272f4c30a3cd4..bd0247cb68f62a23abc5ad377d019972ac3b5d5b 100644 (file)
@@ -123,47 +123,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[])
@@ -326,50 +310,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 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 time_stats *stats)
@@ -609,18 +593,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"
index 433ba9c14dcbdc7f45bc4b68535fd4db81ea5188..54392957381bb431f233d3e9b9284a5d4b3c716b 100644 (file)
@@ -253,6 +253,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 *);
@@ -329,9 +355,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
@@ -469,96 +496,12 @@ do {                                                                      \
                            (var)->p_term_inverse, 1, INT_MAX);         \
 } while (0)
 
-#define __DIV_SAFE(n, d, zero)                                         \
-({                                                                     \
-       typeof(n) _n = (n);                                             \
-       typeof(d) _d = (d);                                             \
-       _d ? _n / _d : zero;                                            \
-})
-
-#define DIV_SAFE(n, d) __DIV_SAFE(n, d, 0)
-
 #define container_of_or_null(ptr, type, member)                                \
 ({                                                                     \
        typeof(ptr) _ptr = ptr;                                         \
        _ptr ? container_of(_ptr, type, member) : NULL;                 \
 })
 
-#define RB_INSERT(root, new, member, cmp)                              \
-({                                                                     \
-       __label__ dup;                                                  \
-       struct rb_node **n = &(root)->rb_node, *parent = NULL;          \
-       typeof(new) this;                                               \
-       int res, ret = -1;                                              \
-                                                                       \
-       while (*n) {                                                    \
-               parent = *n;                                            \
-               this = container_of(*n, typeof(*(new)), member);        \
-               res = cmp(new, this);                                   \
-               if (!res)                                               \
-                       goto dup;                                       \
-               n = res < 0                                             \
-                       ? &(*n)->rb_left                                \
-                       : &(*n)->rb_right;                              \
-       }                                                               \
-                                                                       \
-       rb_link_node(&(new)->member, parent, n);                        \
-       rb_insert_color(&(new)->member, root);                          \
-       ret = 0;                                                        \
-dup:                                                                   \
-       ret;                                                            \
-})
-
-#define RB_SEARCH(root, search, member, cmp)                           \
-({                                                                     \
-       struct rb_node *n = (root)->rb_node;                            \
-       typeof(&(search)) this, ret = NULL;                             \
-       int res;                                                        \
-                                                                       \
-       while (n) {                                                     \
-               this = container_of(n, typeof(search), member);         \
-               res = cmp(&(search), this);                             \
-               if (!res) {                                             \
-                       ret = this;                                     \
-                       break;                                          \
-               }                                                       \
-               n = res < 0                                             \
-                       ? n->rb_left                                    \
-                       : n->rb_right;                                  \
-       }                                                               \
-       ret;                                                            \
-})
-
-#define RB_GREATER(root, search, member, cmp)                          \
-({                                                                     \
-       struct rb_node *n = (root)->rb_node;                            \
-       typeof(&(search)) this, ret = NULL;                             \
-       int res;                                                        \
-                                                                       \
-       while (n) {                                                     \
-               this = container_of(n, typeof(search), member);         \
-               res = cmp(&(search), this);                             \
-               if (res < 0) {                                          \
-                       ret = this;                                     \
-                       n = n->rb_left;                                 \
-               } else                                                  \
-                       n = n->rb_right;                                \
-       }                                                               \
-       ret;                                                            \
-})
-
-#define RB_FIRST(root, type, member)                                   \
-       container_of_or_null(rb_first(root), type, member)
-
-#define RB_LAST(root, type, member)                                    \
-       container_of_or_null(rb_last(root), type, member)
-
-#define RB_NEXT(ptr, member)                                           \
-       container_of_or_null(rb_next(&(ptr)->member), typeof(*ptr), member)
-
-#define RB_PREV(ptr, member)                                           \
-       container_of_or_null(rb_prev(&(ptr)->member), typeof(*ptr), member)
-
 /* Does linear interpolation between powers of two */
 static inline unsigned fract_exp_two(unsigned x, unsigned fract_bits)
 {
@@ -717,8 +660,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));
index 398bc534cc3c8b230e1607cd8467232132a10e6a..ed62668bb155cc9c064182668409bead1f049f0b 100644 (file)
@@ -110,10 +110,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;
 
@@ -123,26 +122,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,
@@ -353,7 +348,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);
@@ -367,9 +362,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 {
index cd1e7ad3e20a7bc1afe2078723063dcff5a503f9..42b7ba3eeccd44398e8f0cb7a36528f243c706c3 100644 (file)
@@ -6,7 +6,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,           \