Dynamic debug: Add more flags

Add flags that allow the user to specify via debugfs whether or not the
module name, function name, line number and/or thread ID have to be
included in the printed message.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Greg Banks <gnb@fmeh.org>
Cc: Konrad Rzeszutek Wilk <konrad@darnok.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Bart Van Assche 2011-01-23 17:17:24 +01:00 committed by Greg Kroah-Hartman
parent 9b99b7f84e
commit 8ba6ebf583
3 changed files with 68 additions and 12 deletions

View file

@ -205,12 +205,20 @@ of the characters:
The flags are: The flags are:
f
Include the function name in the printed message
l
Include line number in the printed message
m
Include module name in the printed message
p p
Causes a printk() message to be emitted to dmesg Causes a printk() message to be emitted to dmesg
t
Include thread ID in messages not generated from interrupt context
Note the regexp ^[-+=][scp]+$ matches a flags specification. Note the regexp ^[-+=][flmpt]+$ matches a flags specification.
Note also that there is no convenient syntax to remove all Note also that there is no convenient syntax to remove all
the flags at once, you need to use "-psc". the flags at once, you need to use "-flmpt".
Debug messages during boot process Debug messages during boot process

View file

@ -31,6 +31,10 @@ struct _ddebug {
* writes commands to <debugfs>/dynamic_debug/control * writes commands to <debugfs>/dynamic_debug/control
*/ */
#define _DPRINTK_FLAGS_PRINT (1<<0) /* printk() a message using the format */ #define _DPRINTK_FLAGS_PRINT (1<<0) /* printk() a message using the format */
#define _DPRINTK_FLAGS_INCL_MODNAME (1<<1)
#define _DPRINTK_FLAGS_INCL_FUNCNAME (1<<2)
#define _DPRINTK_FLAGS_INCL_LINENO (1<<3)
#define _DPRINTK_FLAGS_INCL_TID (1<<4)
#define _DPRINTK_FLAGS_DEFAULT 0 #define _DPRINTK_FLAGS_DEFAULT 0
unsigned int flags:8; unsigned int flags:8;
char enabled; char enabled;
@ -42,6 +46,8 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG)
extern int ddebug_remove_module(const char *mod_name); extern int ddebug_remove_module(const char *mod_name);
extern int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
#define dynamic_pr_debug(fmt, ...) do { \ #define dynamic_pr_debug(fmt, ...) do { \
static struct _ddebug descriptor \ static struct _ddebug descriptor \
@ -50,7 +56,7 @@ extern int ddebug_remove_module(const char *mod_name);
{ KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__, \ { KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__, \
_DPRINTK_FLAGS_DEFAULT }; \ _DPRINTK_FLAGS_DEFAULT }; \
if (unlikely(descriptor.enabled)) \ if (unlikely(descriptor.enabled)) \
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ __dynamic_pr_debug(&descriptor, pr_fmt(fmt), ##__VA_ARGS__); \
} while (0) } while (0)

View file

@ -7,6 +7,7 @@
* Copyright (C) 2008 Jason Baron <jbaron@redhat.com> * Copyright (C) 2008 Jason Baron <jbaron@redhat.com>
* By Greg Banks <gnb@melbourne.sgi.com> * By Greg Banks <gnb@melbourne.sgi.com>
* Copyright (c) 2008 Silicon Graphics Inc. All Rights Reserved. * Copyright (c) 2008 Silicon Graphics Inc. All Rights Reserved.
* Copyright (C) 2011 Bart Van Assche. All Rights Reserved.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
@ -27,6 +28,7 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/jump_label.h> #include <linux/jump_label.h>
#include <linux/hardirq.h>
extern struct _ddebug __start___verbose[]; extern struct _ddebug __start___verbose[];
extern struct _ddebug __stop___verbose[]; extern struct _ddebug __stop___verbose[];
@ -63,15 +65,25 @@ static inline const char *basename(const char *path)
return tail ? tail+1 : path; return tail ? tail+1 : path;
} }
static struct { unsigned flag:8; char opt_char; } opt_array[] = {
{ _DPRINTK_FLAGS_PRINT, 'p' },
{ _DPRINTK_FLAGS_INCL_MODNAME, 'm' },
{ _DPRINTK_FLAGS_INCL_FUNCNAME, 'f' },
{ _DPRINTK_FLAGS_INCL_LINENO, 'l' },
{ _DPRINTK_FLAGS_INCL_TID, 't' },
};
/* format a string into buf[] which describes the _ddebug's flags */ /* format a string into buf[] which describes the _ddebug's flags */
static char *ddebug_describe_flags(struct _ddebug *dp, char *buf, static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
size_t maxlen) size_t maxlen)
{ {
char *p = buf; char *p = buf;
int i;
BUG_ON(maxlen < 4); BUG_ON(maxlen < 4);
if (dp->flags & _DPRINTK_FLAGS_PRINT) for (i = 0; i < ARRAY_SIZE(opt_array); ++i)
*p++ = 'p'; if (dp->flags & opt_array[i].flag)
*p++ = opt_array[i].opt_char;
if (p == buf) if (p == buf)
*p++ = '-'; *p++ = '-';
*p = '\0'; *p = '\0';
@ -343,7 +355,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
unsigned int *maskp) unsigned int *maskp)
{ {
unsigned flags = 0; unsigned flags = 0;
int op = '='; int op = '=', i;
switch (*str) { switch (*str) {
case '+': case '+':
@ -358,13 +370,14 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
printk(KERN_INFO "%s: op='%c'\n", __func__, op); printk(KERN_INFO "%s: op='%c'\n", __func__, op);
for ( ; *str ; ++str) { for ( ; *str ; ++str) {
switch (*str) { for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
case 'p': if (*str == opt_array[i].opt_char) {
flags |= _DPRINTK_FLAGS_PRINT; flags |= opt_array[i].flag;
break; break;
default: }
return -EINVAL;
} }
if (i < 0)
return -EINVAL;
} }
if (flags == 0) if (flags == 0)
return -EINVAL; return -EINVAL;
@ -413,6 +426,35 @@ static int ddebug_exec_query(char *query_string)
return 0; return 0;
} }
int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
{
va_list args;
int res;
BUG_ON(!descriptor);
BUG_ON(!fmt);
va_start(args, fmt);
res = printk(KERN_DEBUG);
if (descriptor->flags & _DPRINTK_FLAGS_INCL_TID) {
if (in_interrupt())
res += printk(KERN_CONT "<intr> ");
else
res += printk(KERN_CONT "[%d] ", task_pid_vnr(current));
}
if (descriptor->flags & _DPRINTK_FLAGS_INCL_MODNAME)
res += printk(KERN_CONT "%s:", descriptor->modname);
if (descriptor->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
res += printk(KERN_CONT "%s:", descriptor->function);
if (descriptor->flags & _DPRINTK_FLAGS_INCL_LINENO)
res += printk(KERN_CONT "%d ", descriptor->lineno);
res += vprintk(fmt, args);
va_end(args);
return res;
}
EXPORT_SYMBOL(__dynamic_pr_debug);
static __initdata char ddebug_setup_string[1024]; static __initdata char ddebug_setup_string[1024];
static __init int ddebug_setup_query(char *str) static __init int ddebug_setup_query(char *str)
{ {