On Tue, Apr 19, 2022 at 10:11:51PM +0100, Matthew Wilcox wrote: > On Tue, Apr 19, 2022 at 04:31:59PM -0400, Kent Overstreet wrote: > > +static const char si_units[] = "?kMGTPEZY"; > > + > > +void pr_human_readable_u64(struct printbuf *buf, u64 v) > > The person who wrote string_get_size() spent a lot more time thinking > about corner-cases than you did ;-) Didn't know about that until today :) Just commited this: commit 3cf1cb86ee4c4a7e75bcd52082ba0df1c436d692 Author: Kent Overstreet <kent.overstreet@xxxxxxxxx> Date: Tue Apr 19 17:29:43 2022 -0400 lib/printbuf: Switch to string_get_size() Signed-off-by: Kent Overstreet <kent.overstreet@xxxxxxxxx> diff --git a/include/linux/printbuf.h b/include/linux/printbuf.h index 84a271446d..2d23506114 100644 --- a/include/linux/printbuf.h +++ b/include/linux/printbuf.h @@ -91,11 +91,13 @@ struct printbuf { enum printbuf_units units:8; u8 atomic; bool allocation_failure:1; + /* SI units (10^3), or 2^10: */ + enum string_size_units human_readable_units:1; u8 tabstop; u8 tabstops[4]; }; -#define PRINTBUF ((struct printbuf) { NULL }) +#define PRINTBUF ((struct printbuf) { .human_readable_units = STRING_UNITS_2 }) /** * printbuf_exit - exit a printbuf, freeing memory it owns and poisoning it diff --git a/lib/printbuf.c b/lib/printbuf.c index a9d5dff81e..ecbce6670f 100644 --- a/lib/printbuf.c +++ b/lib/printbuf.c @@ -10,6 +10,7 @@ #include <linux/log2.h> #include <linux/printbuf.h> +#include <linux/string_helpers.h> static inline size_t printbuf_remaining(struct printbuf *buf) { @@ -144,27 +145,11 @@ void pr_tab_rjust(struct printbuf *buf) } EXPORT_SYMBOL(pr_tab_rjust); -static const char si_units[] = "?kMGTPEZY"; - void pr_human_readable_u64(struct printbuf *buf, u64 v) { - int u, t = 0; - - for (u = 0; v >= 1024; u++) { - t = v & ~(~0U << 10); - v >>= 10; - } - - pr_buf(buf, "%llu", v); - - /* - * 103 is magic: t is in the range [-1023, 1023] and we want - * to turn it into [-9, 9] - */ - if (u && t && v < 100 && v > -100) - pr_buf(buf, ".%i", t / 103); - if (u) - pr_char(buf, si_units[u]); + printbuf_realloc(buf, 10); + string_get_size(v, 1, buf->human_readable_units, buf->buf + buf->pos, + printbuf_remaining(buf)); } EXPORT_SYMBOL(pr_human_readable_u64);