bcachefs: Add tabstops to printbufs
authorKent Overstreet <kent.overstreet@gmail.com>
Tue, 22 Feb 2022 09:53:48 +0000 (04:53 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:24 +0000 (17:09 -0400)
Now, when outputting to printbufs, we can set tabstops and left or right
justify text to them - this is to be used by the userspace 'bcachefs fs
usage' command.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/super-io.c
fs/bcachefs/util.c
fs/bcachefs/util.h

index e1ff14eedaea486e4714c0447d8534aa5d1bef5a..f95c9d754530f0f81bc4ad0f7dc60ab25ffad32a 100644 (file)
@@ -1061,7 +1061,7 @@ static void bch2_sb_members_to_text(struct printbuf *out, struct bch_sb *sb,
                pr_buf(out, "Device:                  %u", i);
                pr_newline(out);
 
-               printbuf_indent_push(out, 2);
+               pr_indent_push(out, 2);
 
                pr_buf(out, "UUID:                  ");
                pr_uuid(out, m->uuid.b);
@@ -1129,7 +1129,7 @@ static void bch2_sb_members_to_text(struct printbuf *out, struct bch_sb *sb,
                       BCH_MEMBER_DISCARD(m));
                pr_newline(out);
 
-               printbuf_indent_pop(out, 2);
+               pr_indent_pop(out, 2);
        }
 }
 
@@ -1471,9 +1471,9 @@ void bch2_sb_field_to_text(struct printbuf *out, struct bch_sb *sb,
        pr_newline(out);
 
        if (ops && ops->to_text) {
-               printbuf_indent_push(out, 2);
+               pr_indent_push(out, 2);
                bch2_sb_field_ops[type]->to_text(out, sb, f);
-               printbuf_indent_pop(out, 2);
+               pr_indent_pop(out, 2);
        }
 }
 
@@ -1656,9 +1656,9 @@ void bch2_sb_to_text(struct printbuf *out, struct bch_sb *sb,
                pr_newline(out);
                pr_buf(out, "layout:");
                pr_newline(out);
-               printbuf_indent_push(out, 2);
+               pr_indent_push(out, 2);
                bch2_sb_layout_to_text(out, &sb->layout);
-               printbuf_indent_pop(out, 2);
+               pr_indent_pop(out, 2);
        }
 
        vstruct_for_each(sb, f)
index f170cf9d505292839016682dbb121bf3684169d8..a330fa30cd79707096bea8032f7f7f1e98d4177e 100644 (file)
@@ -117,17 +117,11 @@ void bch2_hprint(struct printbuf *buf, s64 v)
        if (u && t && v < 100 && v > -100)
                pr_buf(buf, ".%i", t / 103);
        if (u)
-               pr_buf(buf, "%c", si_units[u]);
+               pr_char(buf, si_units[u]);
 }
 
 void bch2_pr_units(struct printbuf *out, s64 raw, s64 bytes)
 {
-       if (raw < 0) {
-               pr_buf(out, "-");
-               raw     = -raw;
-               bytes   = -bytes;
-       }
-
        switch (out->units) {
        case PRINTBUF_UNITS_RAW:
                pr_buf(out, "%llu", raw);
index 3d5a9e04b3adb23364f9805358e791de481d0f5d..426c3009f292734a261c905ced81368b8aca61cf 100644 (file)
@@ -244,8 +244,12 @@ enum printbuf_units {
 struct printbuf {
        char                    *pos;
        char                    *end;
+       char                    *last_newline;
+       char                    *last_field;
        unsigned                indent;
        enum printbuf_units     units;
+       unsigned                tabstop;
+       unsigned                tabstops[4];
 };
 
 static inline size_t printbuf_remaining(struct printbuf *buf)
@@ -253,29 +257,49 @@ static inline size_t printbuf_remaining(struct printbuf *buf)
        return buf->end - buf->pos;
 }
 
+static inline size_t printbuf_linelen(struct printbuf *buf)
+{
+       return buf->pos - buf->last_newline;
+}
+
 #define _PBUF(_buf, _len)                                              \
        ((struct printbuf) {                                            \
-               .pos    = _buf,                                         \
-               .end    = _buf + _len,                                  \
+               .pos            = _buf,                                 \
+               .end            = _buf + _len,                          \
+               .last_newline   = _buf,                                 \
+               .last_field     = _buf,                                 \
        })
 
 #define PBUF(_buf) _PBUF(_buf, sizeof(_buf))
 
+
 #define pr_buf(_out, ...)                                              \
 do {                                                                   \
        (_out)->pos += scnprintf((_out)->pos, printbuf_remaining(_out), \
                                 __VA_ARGS__);                          \
 } while (0)
 
-static inline void printbuf_indent_push(struct printbuf *buf, unsigned spaces)
+static inline void pr_char(struct printbuf *out, char c)
+{
+       if (printbuf_remaining(out) > 1) {
+               *out->pos = c;
+               out->pos++;
+       }
+}
+
+static inline void pr_indent_push(struct printbuf *buf, unsigned spaces)
 {
        buf->indent += spaces;
        while (spaces--)
-               pr_buf(buf, " ");
+               pr_char(buf, ' ');
 }
 
-static inline void printbuf_indent_pop(struct printbuf *buf, unsigned spaces)
+static inline void pr_indent_pop(struct printbuf *buf, unsigned spaces)
 {
+       if (buf->last_newline + buf->indent == buf->pos) {
+               buf->pos -= spaces;
+               buf->pos = '\0';
+       }
        buf->indent -= spaces;
 }
 
@@ -283,14 +307,60 @@ static inline void pr_newline(struct printbuf *buf)
 {
        unsigned i;
 
-       pr_buf(buf, "\n");
+       pr_char(buf, '\n');
+
+       buf->last_newline       = buf->pos;
+
        for (i = 0; i < buf->indent; i++)
-               pr_buf(buf, " ");
+               pr_char(buf, ' ');
+
+       buf->last_field         = buf->pos;
+       buf->tabstop = 0;
+}
+
+static inline void pr_tab(struct printbuf *buf)
+{
+       BUG_ON(buf->tabstop > ARRAY_SIZE(buf->tabstops));
+
+       while (printbuf_remaining(buf) > 1 &&
+              printbuf_linelen(buf) < buf->tabstops[buf->tabstop])
+               pr_char(buf, ' ');
+
+       buf->last_field = buf->pos;
+       buf->tabstop++;
+}
+
+static inline void pr_tab_rjust(struct printbuf *buf)
+{
+       ssize_t shift = min_t(ssize_t, buf->tabstops[buf->tabstop] -
+                             printbuf_linelen(buf),
+                             printbuf_remaining(buf));
+       ssize_t move = min_t(ssize_t, buf->pos - buf->last_field,
+                            printbuf_remaining(buf) - shift);
+
+       BUG_ON(buf->tabstop > ARRAY_SIZE(buf->tabstops));
+
+       if (shift > 0) {
+               memmove(buf->last_field + shift,
+                       buf->last_field,
+                       move);
+               memset(buf->last_field, ' ', shift);
+               buf->pos += shift;
+               *buf->pos = 0;
+       }
+
+       buf->last_field = buf->pos;
+       buf->tabstop++;
 }
 
 void bch2_pr_units(struct printbuf *, s64, s64);
 #define pr_units(...) bch2_pr_units(__VA_ARGS__)
 
+static inline void pr_sectors(struct printbuf *out, u64 v)
+{
+       bch2_pr_units(out, v, v << 9);
+}
+
 #ifdef __KERNEL__
 static inline void pr_time(struct printbuf *out, u64 time)
 {