From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756855AbcANWYD (ORCPT ); Thu, 14 Jan 2016 17:24:03 -0500 Received: from mga02.intel.com ([134.134.136.20]:61215 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756805AbcANWX7 (ORCPT ); Thu, 14 Jan 2016 17:23:59 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.22,296,1449561600"; d="scan'208";a="860771299" From: Andy Shevchenko To: Robert Elliott , Matt Fleming , Andrew Morton , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , linux-kernel@vger.kernel.org, Rasmus Villemoes , Brian Norris , Hariprasad S Cc: Andy Shevchenko Subject: [PATCH v2 06/11] lib/vsprintf: introduce %pl to print in human-readable form Date: Fri, 15 Jan 2016 00:23:36 +0200 Message-Id: <1452810221-116505-7-git-send-email-andriy.shevchenko@linux.intel.com> X-Mailer: git-send-email 2.6.4 In-Reply-To: <1452810221-116505-1-git-send-email-andriy.shevchenko@linux.intel.com> References: <1452810221-116505-1-git-send-email-andriy.shevchenko@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Introduce a new extension for printing given unsigned long long value in human-readable form with automatically choosen IEC binary prefix. The value is passed by reference. Signed-off-by: Andy Shevchenko --- Documentation/printk-formats.txt | 11 +++++++++++ lib/test_printf.c | 21 +++++++++++++++++++++ lib/vsprintf.c | 26 +++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index 5d1128b..8e8b4c0 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -287,6 +287,17 @@ struct clk: Passed by reference. +unsigned long long value in human-readable form (with IEC binary prefix): + + %pl 1023 KiB (1047552) + %pl 1048575 B (1048575) + %pl 1 MiB (1048576) + + For printing given unsigned long long value in human-readable form with + automatically choosen IEC binary prefix. + + Passed by reference. + bitmap and its derivatives such as cpumask and nodemask: %*pb 0779 diff --git a/lib/test_printf.c b/lib/test_printf.c index fd985f6..1e078c2 100644 --- a/lib/test_printf.c +++ b/lib/test_printf.c @@ -407,6 +407,26 @@ bitmap(void) } static void __init +human_readable(void) +{ + struct hr_test_data { + unsigned long long v; + const char *r; + }; + struct hr_test_data htdpl[] = { + { .v = 1097364144128ULL, .r = "1022 GiB" }, + { .v = 1097364144125ULL, .r = "1097364144125 B" }, + { .v = 1048576ULL, .r = "1 MiB" }, + { .v = 1048575ULL, .r = "1048575 B" }, + { .v = 1047552ULL, .r = "1023 KiB" }, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(htdpl); i++) + test(htdpl[i].r, "%pl", &htdpl[i].v); +} + +static void __init netdev_features(void) { } @@ -428,6 +448,7 @@ test_pointer(void) struct_va_format(); struct_clk(); bitmap(); + human_readable(); netdev_features(); } diff --git a/lib/vsprintf.c b/lib/vsprintf.c index f0789e3..8288470 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1306,6 +1306,28 @@ char *uuid_string(char *buf, char *end, const u8 *addr, } static noinline_for_stack +char *human_readable(char *buf, char *end, const void *addr, + struct printf_spec spec, const char *fmt) +{ + unsigned long long value = *(unsigned long long *)addr; + unsigned long index; + + if (value) + index = __ffs64(value) / 10; + else + index = 0; + + /* Print numeric part */ + buf = number(buf, end, value >> (index * 10), default_dec_spec); + + /* Space between numeric part and units */ + buf = put_one_char(buf, end, ' '); + + /* Print units */ + return string(buf, end, string_units_2[index], default_str_spec); +} + +static noinline_for_stack char *netdev_bits(char *buf, char *end, const void *addr, const char *fmt) { unsigned long long num; @@ -1437,6 +1459,7 @@ int kptr_restrict __read_mostly; * Do not use this feature without some mechanism to verify the * correctness of the format string and va_list arguments. * - 'K' For a kernel pointer that should be hidden from unprivileged users + * - 'l' For a value in human-readable form (with IEC binary prefix) * - 'NF' For a netdev_features_t * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with * a certain separator (' ' by default): @@ -1590,7 +1613,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, break; } break; - + case 'l': + return human_readable(buf, end, ptr, spec, fmt); case 'N': return netdev_bits(buf, end, ptr, fmt); case 'a': -- 2.6.4