diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2022-08-12 14:00:46 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2022-10-05 16:49:14 -0400 |
commit | f07be1e3598ae59da9a6e38f7310c51fd13b74e4 (patch) | |
tree | dfa0c0be7c94b7f716d59e49d2a2244f5a5ea737 | |
parent | ff521443e648985642d2b01ee061fcf3290b894b (diff) |
lib/printbuf: Tabstop improvements
- Add a flag, has_indent_or_tabstops, that is set if indent level or
tabstops are set.
- Tabstops can no longer be set by modifying the tabstop array
directly: instead, the new functions are provided:
printbuf_tabstop_push() - add a new tabstop, n spaces after
previous tabstop
printbuf_tabtstop_pop() - remove previous tabstop
printbuf_tabstops_reset() - remove all tabstops
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/debug.c | 3 | ||||
-rw-r--r-- | fs/bcachefs/journal.c | 3 | ||||
-rw-r--r-- | fs/bcachefs/rebalance.c | 3 | ||||
-rw-r--r-- | fs/bcachefs/super-io.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/sysfs.c | 3 | ||||
-rw-r--r-- | fs/bcachefs/util.c | 3 | ||||
-rw-r--r-- | include/linux/printbuf.h | 25 | ||||
-rw-r--r-- | lib/printbuf.c | 122 |
8 files changed, 121 insertions, 49 deletions
diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c index 938740544469..448a3ee27038 100644 --- a/fs/bcachefs/debug.c +++ b/fs/bcachefs/debug.c @@ -409,7 +409,8 @@ static const struct file_operations bfloat_failed_debug_ops = { static void bch2_cached_btree_node_to_text(struct printbuf *out, struct bch_fs *c, struct btree *b) { - out->tabstops[0] = 32; + if (!out->nr_tabstops) + printbuf_tabstop_push(out, 32); prt_printf(out, "%px btree=%s l=%u ", b, diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c index d77092aa069e..3f1cf1ac921a 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c @@ -1255,8 +1255,9 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) u64 seq; unsigned i; + if (!out->nr_tabstops) + printbuf_tabstop_push(out, 24); out->atomic++; - out->tabstops[0] = 24; rcu_read_lock(); s = READ_ONCE(j->reservations); diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c index ecc64dd92b05..17b289b051f2 100644 --- a/fs/bcachefs/rebalance.c +++ b/fs/bcachefs/rebalance.c @@ -268,7 +268,8 @@ void bch2_rebalance_work_to_text(struct printbuf *out, struct bch_fs *c) struct bch_fs_rebalance *r = &c->rebalance; struct rebalance_work w = rebalance_work(c); - out->tabstops[0] = 20; + if (!out->nr_tabstops) + printbuf_tabstop_push(out, 20); prt_printf(out, "fullest_dev (%i):", w.dev_most_full_idx); prt_tab(out); diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index 3dacb8ffbe56..414c40cf3614 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -1425,8 +1425,8 @@ void bch2_sb_field_to_text(struct printbuf *out, struct bch_sb *sb, const struct bch_sb_field_ops *ops = type < BCH_SB_FIELD_NR ? bch2_sb_field_ops[type] : NULL; - if (!out->tabstops[0]) - out->tabstops[0] = 32; + if (!out->nr_tabstops) + printbuf_tabstop_push(out, 32); if (ops) prt_printf(out, "%s", bch2_sb_fields[type]); @@ -1474,8 +1474,8 @@ void bch2_sb_to_text(struct printbuf *out, struct bch_sb *sb, u64 fields_have = 0; unsigned nr_devices = 0; - if (!out->tabstops[0]) - out->tabstops[0] = 32; + if (!out->nr_tabstops) + printbuf_tabstop_push(out, 32); mi = bch2_sb_get_members(sb); if (mi) { diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index 2c650055f530..2dfed1ffadd7 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -560,7 +560,8 @@ SHOW(bch2_fs_counters) u64 counter = 0; u64 counter_since_mount = 0; - out->tabstops[0] = 32; + printbuf_tabstop_push(out, 32); + #define x(t, ...) \ if (attr == &sysfs_##t) { \ counter = percpu_u64_get(&c->counters[BCH_COUNTER_##t]);\ diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c index ee2c7d9e7050..2f7d73170f35 100644 --- a/fs/bcachefs/util.c +++ b/fs/bcachefs/util.c @@ -526,7 +526,8 @@ void bch2_pd_controller_init(struct bch_pd_controller *pd) void bch2_pd_controller_debug_to_text(struct printbuf *out, struct bch_pd_controller *pd) { - out->tabstops[0] = 20; + if (!out->nr_tabstops) + printbuf_tabstop_push(out, 20); prt_printf(out, "rate:"); prt_tab(out); diff --git a/include/linux/printbuf.h b/include/linux/printbuf.h index eb2edb86b22c..24e62e56d18c 100644 --- a/include/linux/printbuf.h +++ b/include/linux/printbuf.h @@ -71,6 +71,8 @@ enum printbuf_si { PRINTBUF_UNITS_10, /* use powers of 10^3 (standard SI) */ }; +#define PRINTBUF_INLINE_TABSTOPS 4 + struct printbuf { char *buf; unsigned size; @@ -86,19 +88,33 @@ struct printbuf { bool heap_allocated:1; enum printbuf_si si_units:1; bool human_readable_units:1; - u8 tabstop; - u8 tabstops[4]; + bool has_indent_or_tabstops:1; + bool suppress_indent_tabstop_handling:1; + u8 nr_tabstops; + + /* + * Do not modify directly: use printbuf_tabstop_add(), + * printbuf_tabstop_get() + */ + u8 cur_tabstop; + u8 _tabstops[PRINTBUF_INLINE_TABSTOPS]; }; int printbuf_make_room(struct printbuf *, unsigned); const char *printbuf_str(const struct printbuf *); void printbuf_exit(struct printbuf *); -void prt_newline(struct printbuf *); +void printbuf_tabstops_reset(struct printbuf *); +void printbuf_tabstop_pop(struct printbuf *); +int printbuf_tabstop_push(struct printbuf *, unsigned); + void printbuf_indent_add(struct printbuf *, unsigned); void printbuf_indent_sub(struct printbuf *, unsigned); + +void prt_newline(struct printbuf *); void prt_tab(struct printbuf *); void prt_tab_rjust(struct printbuf *); + void prt_bytes_indented(struct printbuf *, const char *, unsigned); void prt_human_readable_u64(struct printbuf *, u64); void prt_human_readable_s64(struct printbuf *, s64); @@ -241,7 +257,8 @@ static inline void printbuf_reset(struct printbuf *buf) buf->pos = 0; buf->allocation_failure = 0; buf->indent = 0; - buf->tabstop = 0; + buf->nr_tabstops = 0; + buf->cur_tabstop = 0; } /** diff --git a/lib/printbuf.c b/lib/printbuf.c index 3fbb74754b48..2aa4a1b7294e 100644 --- a/lib/printbuf.c +++ b/lib/printbuf.c @@ -13,7 +13,7 @@ #include <linux/string_helpers.h> #include <linux/printbuf.h> -static inline size_t printbuf_linelen(struct printbuf *buf) +static inline unsigned printbuf_linelen(struct printbuf *buf) { return buf->pos - buf->last_newline; } @@ -81,25 +81,43 @@ void printbuf_exit(struct printbuf *buf) } EXPORT_SYMBOL(printbuf_exit); -void prt_newline(struct printbuf *buf) +void printbuf_tabstops_reset(struct printbuf *buf) { - unsigned i; - - printbuf_make_room(buf, 1 + buf->indent); - - __prt_char(buf, '\n'); + buf->nr_tabstops = 0; +} +EXPORT_SYMBOL(printbuf_tabstops_reset); - buf->last_newline = buf->pos; +void printbuf_tabstop_pop(struct printbuf *buf) +{ + if (buf->nr_tabstops) + --buf->nr_tabstops; +} +EXPORT_SYMBOL(printbuf_tabstop_pop); - for (i = 0; i < buf->indent; i++) - __prt_char(buf, ' '); +/* + * printbuf_tabstop_set - add a tabstop, n spaces from the previous tabstop + * + * @buf: printbuf to control + * @spaces: number of spaces from previous tabpstop + * + * In the future this function may allocate memory if setting more than + * PRINTBUF_INLINE_TABSTOPS or setting tabstops more than 255 spaces from start + * of line. + */ +int printbuf_tabstop_push(struct printbuf *buf, unsigned spaces) +{ + unsigned prev_tabstop = buf->nr_tabstops + ? buf->_tabstops[buf->nr_tabstops - 1] + : 0; - printbuf_nul_terminate(buf); + if (WARN_ON(buf->nr_tabstops >= ARRAY_SIZE(buf->_tabstops))) + return -EINVAL; - buf->last_field = buf->pos; - buf->tabstop = 0; + buf->_tabstops[buf->nr_tabstops++] = prev_tabstop + spaces; + buf->has_indent_or_tabstops = true; + return 0; } -EXPORT_SYMBOL(prt_newline); +EXPORT_SYMBOL(printbuf_tabstop_push); /** * printbuf_indent_add - add to the current indent level @@ -116,8 +134,9 @@ void printbuf_indent_add(struct printbuf *buf, unsigned spaces) spaces = 0; buf->indent += spaces; - while (spaces--) - prt_char(buf, ' '); + prt_chars(buf, ' ', spaces); + + buf->has_indent_or_tabstops = true; } EXPORT_SYMBOL(printbuf_indent_add); @@ -140,23 +159,50 @@ void printbuf_indent_sub(struct printbuf *buf, unsigned spaces) printbuf_nul_terminate(buf); } buf->indent -= spaces; + + if (!buf->indent && !buf->nr_tabstops) + buf->has_indent_or_tabstops = false; } EXPORT_SYMBOL(printbuf_indent_sub); -static inline bool tabstop_is_set(struct printbuf *buf) +void prt_newline(struct printbuf *buf) { - return buf->tabstop < ARRAY_SIZE(buf->tabstops) && - buf->tabstops[buf->tabstop]; + unsigned i; + + printbuf_make_room(buf, 1 + buf->indent); + + __prt_char(buf, '\n'); + + buf->last_newline = buf->pos; + + for (i = 0; i < buf->indent; i++) + __prt_char(buf, ' '); + + printbuf_nul_terminate(buf); + + buf->last_field = buf->pos; + buf->cur_tabstop = 0; +} +EXPORT_SYMBOL(prt_newline); + +/* + * Returns spaces from start of line, if set, or 0 if unset: + */ +static inline unsigned cur_tabstop(struct printbuf *buf) +{ + return buf->cur_tabstop < buf->nr_tabstops + ? buf->_tabstops[buf->cur_tabstop] + : 0; } static void __prt_tab(struct printbuf *out) { - int spaces = max_t(int, 0, out->tabstops[out->tabstop] - printbuf_linelen(out)); + int spaces = max_t(int, 0, cur_tabstop(out) - printbuf_linelen(out)); prt_chars(out, ' ', spaces); out->last_field = out->pos; - out->tabstop++; + out->cur_tabstop++; } /** @@ -168,7 +214,7 @@ static void __prt_tab(struct printbuf *out) */ void prt_tab(struct printbuf *out) { - if (WARN_ON(!tabstop_is_set(out))) + if (WARN_ON(!cur_tabstop(out))) return; __prt_tab(out); @@ -177,28 +223,27 @@ EXPORT_SYMBOL(prt_tab); static void __prt_tab_rjust(struct printbuf *buf) { - if (printbuf_linelen(buf) < buf->tabstops[buf->tabstop]) { - unsigned move = buf->pos - buf->last_field; - unsigned shift = buf->tabstops[buf->tabstop] - - printbuf_linelen(buf); + unsigned move = buf->pos - buf->last_field; + int pad = (int) cur_tabstop(buf) - (int) printbuf_linelen(buf); - printbuf_make_room(buf, shift); + if (pad > 0) { + printbuf_make_room(buf, pad); - if (buf->last_field + shift < buf->size) - memmove(buf->buf + buf->last_field + shift, + if (buf->last_field + pad < buf->size) + memmove(buf->buf + buf->last_field + pad, buf->buf + buf->last_field, - min(move, buf->size - 1 - buf->last_field - shift)); + min(move, buf->size - 1 - buf->last_field - pad)); if (buf->last_field < buf->size) memset(buf->buf + buf->last_field, ' ', - min(shift, buf->size - buf->last_field)); + min((unsigned) pad, buf->size - buf->last_field)); - buf->pos += shift; + buf->pos += pad; printbuf_nul_terminate(buf); } buf->last_field = buf->pos; - buf->tabstop++; + buf->cur_tabstop++; } /** @@ -212,7 +257,7 @@ static void __prt_tab_rjust(struct printbuf *buf) */ void prt_tab_rjust(struct printbuf *buf) { - if (WARN_ON(!tabstop_is_set(buf))) + if (WARN_ON(!cur_tabstop(buf))) return; __prt_tab_rjust(buf); @@ -236,6 +281,11 @@ void prt_bytes_indented(struct printbuf *out, const char *str, unsigned count) const char *unprinted_start = str; const char *end = str + count; + if (!out->has_indent_or_tabstops || out->suppress_indent_tabstop_handling) { + prt_bytes(out, str, count); + return; + } + while (str != end) { switch (*str) { case '\n': @@ -244,14 +294,14 @@ void prt_bytes_indented(struct printbuf *out, const char *str, unsigned count) prt_newline(out); break; case '\t': - if (likely(tabstop_is_set(out))) { + if (likely(cur_tabstop(out))) { prt_bytes(out, unprinted_start, str - unprinted_start); unprinted_start = str + 1; __prt_tab(out); } break; case '\r': - if (likely(tabstop_is_set(out))) { + if (likely(cur_tabstop(out))) { prt_bytes(out, unprinted_start, str - unprinted_start); unprinted_start = str + 1; __prt_tab_rjust(out); |