[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20161115094145.GA19425@gmail.com>
Date: Tue, 15 Nov 2016 10:41:45 +0100
From: Ingo Molnar <mingo@...nel.org>
To: Peter Zijlstra <peterz@...radead.org>
Cc: Greg KH <gregkh@...uxfoundation.org>,
Christoph Hellwig <hch@...radead.org>, keescook@...omium.org,
will.deacon@....com, elena.reshetova@...el.com, arnd@...db.de,
tglx@...utronix.de, hpa@...or.com,
Linus Torvalds <torvalds@...ux-foundation.org>,
dave@...gbits.org, linux-kernel@...r.kernel.org
Subject: [PATCH v3] printk, locking/atomics, kref: Introduce new %pAa and
%pAk format string options for atomic_t and 'struct kref'
* Peter Zijlstra <peterz@...radead.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 <mingo@...nel.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 <acme@...nel.org>
Cc: Christoph Hellwig <hch@...radead.org>
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Cc: Linus Torvalds <torvalds@...ux-foundation.org>
Cc: Peter Zijlstra <peterz@...radead.org>
Cc: Thomas Gleixner <tglx@...utronix.de>
Cc: arnd@...db.de
Cc: dave@...gbits.org
Cc: elena.reshetova@...el.com
Cc: keescook@...omium.org
Cc: will.deacon@....com
Link: http://lkml.kernel.org/r/20161115084355.GA24175@gmail.com
Signed-off-by: Ingo Molnar <mingo@...nel.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) {
Powered by blists - more mailing lists