* Peter Zijlstra <pet...@infradead.org> wrote: > On Tue, Nov 15, 2016 at 09:43:55AM +0100, Ingo Molnar wrote: > > +atomic variables such atomic_t or struct kref: > > + > > + %pAr atomic_t count > > Why 'r' for atomic_t ? I was expecting 'a' for atomic_t or something. > That then also leaves 'r' available for refcount_t.
'r' was for 'raw atomic count', but you are right - new patch attached below. Thanks, Ingo ========== Subject: printk, locking/atomics, kref: Introduce new %pAa and %pAk format string options for atomic_t and 'struct kref' From: Ingo Molnar <mi...@kernel.org> Date: Tue, 15 Nov 2016 09:43:55 +0100 A decade of kref internals exposed to driver writers has proven that exposing internals to them is a bad idea. Make the bad patterns a bit easier to detect and allow cleaner printouts by offering two new printk format string extensions: %pAa - print the atomic_t count in decimal %pAk - print the struct kref count in decimal Also add printf testcases: [ 0.334919] test_printf: all 268 tests passed Cc: Arnaldo Carvalho de Melo <a...@kernel.org> Cc: Christoph Hellwig <h...@infradead.org> Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: a...@arndb.de Cc: d...@progbits.org Cc: elena.reshet...@intel.com Cc: keesc...@chromium.org Cc: will.dea...@arm.com Link: http://lkml.kernel.org/r/20161115084355.ga24...@gmail.com Signed-off-by: Ingo Molnar <mi...@kernel.org> --- Documentation/printk-formats.txt | 10 +++++++++ lib/test_printf.c | 28 ++++++++++++++++++++++++++ lib/vsprintf.c | 42 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) Index: tip/Documentation/printk-formats.txt =================================================================== --- tip.orig/Documentation/printk-formats.txt +++ tip/Documentation/printk-formats.txt @@ -316,6 +316,16 @@ Flags bitfields such as page flags, gfp_ Passed by reference. +atomic variables such atomic_t or struct kref: + + %pAa atomic_t count + %pAk struct kref count + + For printing the current count value of atomic variables. This is + preferred to accessing the counts directly. + + Passed by reference. + Network device features: %pNF 0x000000000000c000 Index: tip/lib/test_printf.c =================================================================== --- tip.orig/lib/test_printf.c +++ tip/lib/test_printf.c @@ -20,6 +20,8 @@ #include <linux/gfp.h> #include <linux/mm.h> +#include <linux/kref.h> + #define BUF_SIZE 256 #define PAD_SIZE 16 #define FILL_CHAR '$' @@ -462,6 +464,31 @@ flags(void) kfree(cmp_buffer); } +/* + * Testcases for %pAa (atomic_t) and %pAk (struct kref) count printing: + */ +static void __init test_atomics__atomic_t(void) +{ + atomic_t count = ATOMIC_INIT(1); + + test("1", "%pAa", &count); +} + +static void __init test_atomics__kref(void) +{ + struct kref kref; + + kref_init(&kref); + + test("1", "%pAk", &kref); +} + +static void __init test_atomics(void) +{ + test_atomics__atomic_t(); + test_atomics__kref(); +} + static void __init test_pointer(void) { @@ -481,6 +508,7 @@ test_pointer(void) bitmap(); netdev_features(); flags(); + test_atomics(); } static int __init Index: tip/lib/vsprintf.c =================================================================== --- tip.orig/lib/vsprintf.c +++ tip/lib/vsprintf.c @@ -38,6 +38,8 @@ #include "../mm/internal.h" /* For the trace_print_flags arrays */ +#include <linux/kref.h> + #include <asm/page.h> /* for PAGE_SIZE */ #include <asm/sections.h> /* for dereference_function_descriptor() */ #include <asm/byteorder.h> /* cpu_to_le16 */ @@ -1470,6 +1472,40 @@ char *flags_string(char *buf, char *end, return format_flags(buf, end, flags, names); } +static noinline_for_stack +char *atomic_var(char *buf, char *end, void *atomic_ptr, const char *fmt) +{ + unsigned long num; + const struct printf_spec numspec = { + .flags = SPECIAL|SMALL, + .field_width = -1, + .precision = -1, + .base = 10, + }; + + switch (fmt[1]) { + case 'a': + { + atomic_t *count_p = (void *)atomic_ptr; + + num = atomic_read(count_p); + break; + } + case 'k': + { + struct kref *kref_p = (void *)atomic_ptr; + + num = refcount_read(&kref_p->refcount); + break; + } + default: + WARN_ONCE(1, "Unsupported atomics modifier: %c\n", fmt[1]); + return buf; + } + + return number(buf, end, num, numspec); +} + int kptr_restrict __read_mostly; /* @@ -1563,6 +1599,10 @@ int kptr_restrict __read_mostly; * p page flags (see struct page) given as pointer to unsigned long * g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t * v vma flags (VM_*) given as pointer to unsigned long + * - 'A' For the count of atomic variables to be printed. + * Supported flags given by option: + * a atomic_t ('a'tomic count) + * k struct kref ('k'ref count) * * ** Please update also Documentation/printk-formats.txt when making changes ** * @@ -1718,6 +1758,8 @@ char *pointer(const char *fmt, char *buf case 'G': return flags_string(buf, end, ptr, fmt); + case 'A': + return atomic_var(buf, end, ptr, fmt); } spec.flags |= SMALL; if (spec.field_width == -1) {