summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-05-09 20:51:07 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2022-08-08 11:04:45 -0400
commita29b0a69f800fc7b753840bbdb530e5be620babe (patch)
treeae9addf5a6d39defb8a4a57c913d34fa3d70ea28
parent38852d8775fa27ec4e45bb0789a80af35c42657f (diff)
lib/printbuf: Unit specifiers
This adds options to printbuf for specifying whether units should be printed raw (default) or with human readable units, and for controlling whether human-readable units should be base 2 (default), or base 10. This also adds new helpers that obey these options: - pr_human_readable_u64 - pr_human_readable_s64 These obey printbuf->si_units - pr_units_u64 - pr_units_s64 These obey both printbuf-human_readable_units and printbuf->si_units Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--include/linux/printbuf.h15
-rw-r--r--lib/printbuf.c57
2 files changed, 72 insertions, 0 deletions
diff --git a/include/linux/printbuf.h b/include/linux/printbuf.h
index c1a482b6c0a8..ebbc4a55fc04 100644
--- a/include/linux/printbuf.h
+++ b/include/linux/printbuf.h
@@ -57,11 +57,20 @@
*
* Make sure you use prt_newline() instead of \n in the format string for indent
* level and tabstops to work corretly.
+ *
+ * Output units: printbuf->units exists to tell pretty-printers how to output
+ * numbers: a raw value (e.g. directly from a superblock field), as bytes, or as
+ * human readable bytes. prt_units() obeys it.
*/
#include <linux/kernel.h>
#include <linux/string.h>
+enum printbuf_si {
+ PRINTBUF_UNITS_2, /* use binary powers of 2^10 */
+ PRINTBUF_UNITS_10, /* use powers of 10^3 (standard SI) */
+};
+
struct printbuf {
char *buf;
unsigned size;
@@ -75,6 +84,8 @@ struct printbuf {
u8 atomic;
bool allocation_failure:1;
bool heap_allocated:1;
+ enum printbuf_si si_units:1;
+ bool human_readable_units:1;
u8 tabstop;
u8 tabstops[4];
};
@@ -88,6 +99,10 @@ void printbuf_indent_add(struct printbuf *, unsigned);
void printbuf_indent_sub(struct printbuf *, unsigned);
void prt_tab(struct printbuf *);
void prt_tab_rjust(struct printbuf *);
+void prt_human_readable_u64(struct printbuf *, u64);
+void prt_human_readable_s64(struct printbuf *, s64);
+void prt_units_u64(struct printbuf *, u64);
+void prt_units_s64(struct printbuf *, s64);
/* Initializer for a heap allocated printbuf: */
#define PRINTBUF ((struct printbuf) { .heap_allocated = true })
diff --git a/lib/printbuf.c b/lib/printbuf.c
index 395c681e3acb..047470025748 100644
--- a/lib/printbuf.c
+++ b/lib/printbuf.c
@@ -10,6 +10,7 @@
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/string_helpers.h>
#include <linux/printbuf.h>
static inline size_t printbuf_linelen(struct printbuf *buf)
@@ -199,3 +200,59 @@ void prt_tab_rjust(struct printbuf *buf)
buf->tabstop++;
}
EXPORT_SYMBOL(prt_tab_rjust);
+
+/**
+ * prt_human_readable_u64 - Print out a u64 in human readable units
+ *
+ * Units of 2^10 (default) or 10^3 are controlled via @buf->si_units
+ */
+void prt_human_readable_u64(struct printbuf *buf, u64 v)
+{
+ printbuf_make_room(buf, 10);
+ buf->pos += string_get_size(v, 1, !buf->si_units,
+ buf->buf + buf->pos,
+ printbuf_remaining_size(buf));
+}
+EXPORT_SYMBOL(prt_human_readable_u64);
+
+/**
+ * prt_human_readable_s64 - Print out a s64 in human readable units
+ *
+ * Units of 2^10 (default) or 10^3 are controlled via @buf->si_units
+ */
+void prt_human_readable_s64(struct printbuf *buf, s64 v)
+{
+ if (v < 0)
+ prt_char(buf, '-');
+ prt_human_readable_u64(buf, abs(v));
+}
+EXPORT_SYMBOL(prt_human_readable_s64);
+
+/**
+ * prt_units_u64 - Print out a u64 according to printbuf unit options
+ *
+ * Units are either raw (default), or human reabable units (controlled via
+ * @buf->human_readable_units)
+ */
+void prt_units_u64(struct printbuf *out, u64 v)
+{
+ if (out->human_readable_units)
+ prt_human_readable_u64(out, v);
+ else
+ prt_printf(out, "%llu", v);
+}
+EXPORT_SYMBOL(prt_units_u64);
+
+/**
+ * prt_units_s64 - Print out a s64 according to printbuf unit options
+ *
+ * Units are either raw (default), or human reabable units (controlled via
+ * @buf->human_readable_units)
+ */
+void prt_units_s64(struct printbuf *out, s64 v)
+{
+ if (v < 0)
+ prt_char(out, '-');
+ prt_units_u64(out, abs(v));
+}
+EXPORT_SYMBOL(prt_units_s64);