enable pr_debug during module initialization
Subsystems (5)
[email protected]
maintainercover enable pr_debug during module initialization
This is 4th revision of the dyndbg modinit patches, implementing the "fake" module param approach proposed by Thomas Renninger, back in
https://lkml.org/lkml/2010/9/15/397
rev1.1:
stored queries for loadable modules on pending list
http://lkml.indiana.edu/hypermail/linux/kernel/1107.3/00627.html
rev2: http://thread.gmane.org/gmane.linux.kernel/1262934
changes since rev2:
- rev2 Patches 1-17/25 sent Dec 11 were added to driver-core-next, subsequent revs rework 18-25, renumbered.
- reworked onto linux-next, to include Pawel Moll's initcall-level params patch. Im not using this feature, but I didnt know that when I started.
- dropped "protect dyndbg, BUILD_BUG_DECL", which caused compile err if module author added his own dyndbg param declaration, Rusty said:
"if dev added it, he probably meant it"
- dropped noisy pr_* in initcall_level stuff, per Rusty.
rev3:
https://lkml.org/lkml/2012/3/14/469
changes since:
- added comment, commit-msg explaining repeat use of parse-args.
- deprecate "ddebug_query=" rather than remove it.
- refactor 2 callbacks to use common helper.
- more aggressive early_initcall, not core_initcall RFC
- debugfs init via fs_initcall, not module_init RFC
Core of patchset is 2 callbacks, called from parse_args:
For builtin modules, dynamic_debug_init() calls parse_args(..., &ddebug_dyndbg_boot_param_cb) to handle dyndbg and $module.dyndbg params. For loadable modules, load_module() calls parse_args(), passing &ddebug_dyndbg_module_param_cb to handle dyndbg args given by modprobe.
Callbacks get extra arg, which is either modulename or "Booting Kernel" as passed by start_kernel to parse_args(). The arg allows foo.dyndbg="func bar +p; func buz +p" to exclude the "module foo" 2x, saving space in the limited cmdline buffers. Both callbacks call ddebug_exec_queries() to activate the specified pr_debug callsites.
0001-init-trivial-tweaks-to-initcall_levels.patch
This adds pr_info for each initcall-level, yielding 7 lines in dmesg like:
initlevel:6=device, 172 registered initcalls
I dropped the pr_debug added in 2nd rev, which was noisy and not useful, init_debug provides similar info and more. This patch is decoration only, and can be dropped.
0002-dynamic_debug-fix-leading-spaces.patch
whitespace cleanup
0003-dynamic_debug-replace-if-verbose-pr_info-with-macro-.patch I should have done this previously. Ive disregarded a checkpatch complaint about wrapping complex macro args in (), since theres plenty of similar code in include/*, and a couple attempts to add them failed.
0004-dynamic_debug-change-ddebug_query-core-param-to-dynd.patch Change "ddebug_query" to "dyndbg", to match new $module.dyndbg added by this patchset.
0005-params-add-param-name-to-parse_one-s-pr_debug.patch Current message doesnt name the param being handled.
0006-params-add-3rd-arg-to-option-handler-callback-signat.patch Add "doing" to lower levels of param handling callchain, supplying it to callback added next.
0007-dynamic_debug-make-dynamic-debug-work-during-module-.patch add 2 callbacks to parse dydnbg, module.dyndbg params. main patch of set.
0008-dynamic_debug-deprecate-ddebug_query-suggest-dyndbg-.patch adds entry to feature-removal-schedule,
and warning when ddebug_query is used.
0009-dynamic_debug-combine-parse_args-callbacks-together.patch refactor 2 callbacks, add single helper.
0010-dynamic_debug-simplify-dynamic_debug_init-error-exit.patch add return 0 above goto error target, move non-err code above it.
0011-dynamic_debug-print-ram-usage-by-ddebug-tables-if-ve.patch show ram usage due to CONFIG_DYNAMIC_DEBUG.
0012-pnp-if-CONFIG_DYNAMIC_DEBUG-use-pnp.dyndbg-instead-o.patch Adjust pnp for CONFIG_PNP_DEBUG_MESSAGES. Unchanged since Dec 11th
0013-dynamic_debug-add-modname-arg-to-exec_query-callchai.patch This allows parsing $modname.dyndbg=" func foo +p ; func bar +p" without repeating "module $modname" 2x in the value
0014-dynamic_debug-update-Documentation-Kconfig.debug.patch This gets a checkpatch complaint because of long lines in which I tweaked flags. I chose to disregard this cuz the lines show real output for ~out-of-tree code.
0015-dynamic_debug-init-with-early_initcall-not-arch_initc.patch change arch_initcall to early_initcall, and module_init to fs_initcall. This works-for-me, but may be broken on some arches I dont have to test on. I dont know why original design used arch_initcall, perhaps constraints have changed.
0016-dynamic_debug-drop-deprecated-ddebug_query-param-cod.patch Dont apply til v3.6 or v3.7
thanks
Jim Cromie
[email protected]
maintainerPATCH 1/16 init: trivial tweaks to initcall_levels
From: Jim Cromie <[email protected]>
add a pr_info to print current level and level_name of initcall, and number of registered initcalls at that level. This adds 7 lines to dmesg output, like:
initlevel:6=device, 172 registered initcalls
Drop "parameters" from initcall_level_names[], it can be added back in the printk where it clarifies things.
--- init/main.c | 25 +++++++++++++++---------- 1 files changed, 15 insertions(+), 10 deletions(-)
init/main.c +15 -10
@@ -723,14 +723,14 @@ static initcall_t *initcall_levels[] __initdata = { };static char *initcall_level_names[]__initdata = { -"early parameters" , -"core parameters" , -"postcore parameters" , -"arch parameters" , -"subsys parameters" , -"fs parameters" , -"device parameters" , -"late parameters" , +"early" , +"core" , +"postcore" , +"arch" , +"subsys" , +"fs" , +"device" , +"late" , };static int __init ignore_unknown_bootoption (char *param,char *val)
@@ -748,7 +748,7 @@ static void __init do_initcall_level(int level) static_command_line, __start___param, __stop___param - __start___param, level, level, - ignore_unknown_bootoption); + &ignore_unknown_bootoption);for (fn = initcall_levels[level]; fn < initcall_levels[level+1 ]; fn++)do_one_initcall (*fn);
@@ -758,8 +758,13 @@ static void __init do_initcalls(void) {int level; -for (level =0 ; level <ARRAY_SIZE (initcall_levels) -1 ; level++) +for (level =0 ; level <ARRAY_SIZE (initcall_levels) -1 ; level++) { +pr_info ("initlevel:%d=%s, %d registered initcalls\n" , + level, initcall_level_names[level], + (int ) (initcall_levels[level+1 ] + - initcall_levels[level]));do_initcall_level (level); + } }/*
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 2/16 dynamic_debug: fix leading spaces
In reply to [email protected]From: Jim Cromie <[email protected]>
clean up some space-before-tabs problems.
--- include/linux/dynamic_debug.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
include/linux/dynamic_debug.h +2 -2
@@ -17,8 +17,8 @@ struct _ddebug {const char *format; unsigned int lineno:18;/* -* The flags field controls the behaviour at the callsite. -* The bits here are changed dynamically when the user +* The flags field controls the behaviour at the callsite. +* The bits here are changed dynamically when the user * writes commands to <debugfs>/dynamic_debug/control */ #define _DPRINTK_FLAGS_NONE 0
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 3/16 dynamic_debug: replace if (verbose) pr_info with macro vpr_info
In reply to [email protected]From: Jim Cromie <[email protected]>
use new macro to declutter code, reduce indenting. dont use pr_debug in lib/dynamic_debug.c, replace with vpr_info. Disregard checkpatch warning about complex macro arg; there are plenty of examples in include/*
--- lib/dynamic_debug.c | 79 ++++++++++++++++++++++----------------------------- 1 files changed, 34 insertions(+), 45 deletions(-)
lib/dynamic_debug.c +34 -45
@@ -107,20 +107,22 @@ static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,return buf; } -#define vpr_info_dq (q, msg) \ -do { \ - if (verbose) \ -/* trim last char off format print */ \ -pr_info ("%s: func=\"%s\" file=\"%s\" " \ -"module=\"%s\" format=\"%.*s\" " \ -"lineno=%u-%u" , \ - msg, \ - q->function ? q->function :"" , \ - q->filename ? q->filename :"" , \ - q->module ? q->module :"" , \ - (int )(q->format ?strlen (q->format) -1 :0 ), \ - q->format ? q->format :"" , \ - q->first_lineno, q->last_lineno); \ +#define vpr_info (fmt, ...) \ + if (verbose) do { pr_info(fmt, ##__VA_ARGS__); } while (0) + +#define vpr_info_dq (q, msg) \ +do { \ +/* trim last char off format print */ \ +vpr_info ("%s: func=\"%s\" file=\"%s\" " \ +"module=\"%s\" format=\"%.*s\" " \ +"lineno=%u-%u" , \ + msg, \ + q->function ? q->function :"" , \ + q->filename ? q->filename :"" , \ + q->module ? q->module :"" , \ + (int )(q->format ?strlen (q->format) -1 :0 ), \ + q->format ? q->format :"" , \ + q->first_lineno, q->last_lineno); \ }while (0 )/*
@@ -180,12 +182,11 @@ static int ddebug_change(const struct ddebug_query *query,if (newflags == dp->flags)continue ; dp->flags = newflags; -if (verbose) -pr_info ("changed %s:%d [%s]%s =%s\n" , -trim_prefix (dp->filename), dp->lineno, - dt->mod_name, dp->function, -ddebug_describe_flags (dp, flagbuf, -sizeof (flagbuf))); +vpr_info ("changed %s:%d [%s]%s =%s\n" , +trim_prefix (dp->filename), dp->lineno, + dt->mod_name, dp->function, +ddebug_describe_flags (dp, flagbuf, +sizeof (flagbuf))); } }mutex_unlock (&ddebug_lock);
@@ -410,8 +411,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,default :return -EINVAL ; } -if (verbose) -pr_info ("op='%c'\n" , op); +vpr_info ("op='%c'\n" , op);for ( ; *str ; ++str) {for (i =ARRAY_SIZE (opt_array) -1 ; i >=0 ; i--) {
@@ -423,8 +423,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,if (i <0 )return -EINVAL ; } -if (verbose) -pr_info ("flags=0x%x\n" , flags); +vpr_info ("flags=0x%x\n" , flags);/* calculate final *flagsp, *maskp according to mask and op */ switch (op) {
@@ -441,8 +440,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, *flagsp =0 ;break ; } -if (verbose) -pr_info ("*flagsp=0x%x *maskp=0x%x\n" , *flagsp, *maskp); +vpr_info ("*flagsp=0x%x *maskp=0x%x\n" , *flagsp, *maskp);return 0 ; }
@@ -487,8 +485,7 @@ static int ddebug_exec_queries(char *query)if (!query || !*query || *query =='#' )continue ; -if (verbose) -pr_info ("query %d: \"%s\"\n" , i, query); +vpr_info ("query %d: \"%s\"\n" , i, query); rc =ddebug_exec_query (query);if (rc <0 ) {
@@ -653,8 +650,7 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,return -EFAULT ; } tmpbuf[len] ='\0' ; -if (verbose) -pr_info ("read %d bytes from userspace\n" , (int )len); +vpr_info ("read %d bytes from userspace\n" , (int )len); ret =ddebug_exec_queries (tmpbuf);kfree (tmpbuf);
@@ -717,8 +713,7 @@ static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)struct _ddebug *dp;int n = *pos; -if (verbose) -pr_info ("called m=%p *pos=%lld\n" , m, (unsigned long long )*pos); +vpr_info ("called m=%p *pos=%lld\n" , m, (unsigned long long )*pos);mutex_lock (&ddebug_lock);
@@ -742,9 +737,8 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)struct ddebug_iter *iter = m->private;struct _ddebug *dp; -if (verbose) -pr_info ("called m=%p p=%p *pos=%lld\n" , - m, p, (unsigned long long )*pos); +vpr_info ("called m=%p p=%p *pos=%lld\n" , + m, p, (unsigned long long )*pos);if (p ==SEQ_START_TOKEN ) dp =ddebug_iter_first (iter);
@@ -766,8 +760,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)struct _ddebug *dp = p;char flagsbuf[10 ]; -if (verbose) -pr_info ("called m=%p p=%p\n" , m, p); +vpr_info ("called m=%p p=%p\n" , m, p);if (p ==SEQ_START_TOKEN ) { seq_puts(m,
@@ -791,8 +784,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)*/ static void ddebug_proc_stop (struct seq_file *m,void *p) { -if (verbose) -pr_info ("called m=%p p=%p\n" , m, p); +vpr_info ("called m=%p p=%p\n" , m, p);mutex_unlock (&ddebug_lock); }
@@ -815,8 +807,7 @@ static int ddebug_proc_open(struct inode *inode, struct file *file)struct ddebug_iter *iter;int err; -if (verbose) -pr_info ("called\n" ); +vpr_info ("called\n" ); iter =kzalloc (sizeof (*iter),GFP_KERNEL );if (iter ==NULL )
@@ -866,8 +857,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,list_add_tail (&dt->link, &ddebug_tables);mutex_unlock (&ddebug_lock); -if (verbose) -pr_info ("%u debug prints in module %s\n" , n, dt->mod_name); +vpr_info ("%u debug prints in module %s\n" , n, dt->mod_name);return 0 ; }EXPORT_SYMBOL_GPL (ddebug_add_module);
@@ -888,8 +878,7 @@ int ddebug_remove_module(const char *mod_name)struct ddebug_table *dt, *nextdt;int ret = -ENOENT ; -if (verbose) -pr_info ("removing module \"%s\"\n" , mod_name); +vpr_info ("removing module \"%s\"\n" , mod_name);mutex_lock (&ddebug_lock);list_for_each_entry_safe (dt, nextdt, &ddebug_tables, link) {
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 4/16 dynamic_debug: change ddebug_query core param to dyndbg
In reply to [email protected]From: Jim Cromie <[email protected]>
The "ddebug_query" boot-param allows enabling of pr_debug()s in built-in modules. Change it to "dyndbg" to make it consistent with the $module.dyndbg param added soon.
--- lib/dynamic_debug.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
lib/dynamic_debug.c +1 -1
@@ -623,7 +623,7 @@ static __init int ddebug_setup_query(char *str)return 1 ; } -__setup ("ddebug_query=" , ddebug_setup_query); +__setup ("dyndbg=" , ddebug_setup_query);/* * File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 5/16 params: add param-name to parse_one's pr_debug()
In reply to [email protected]From: Jim Cromie <[email protected]>
Current message doesnt identify the param being handled, add it.
--- kernel/params.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
kernel/params.c +2 -2
@@ -104,8 +104,8 @@ static int parse_one(char *param,if (!val && params[i].ops->set != param_set_bool && params[i].ops->set != param_set_bint)return -EINVAL ; -pr_debug ("They are equal! Calling %p\n" , - params[i].ops->set); +pr_debug ("handling %s with %p\n" , param, + params[i].ops->set);mutex_lock (¶m_lock); err = params[i].ops->set (val, ¶ms[i]);mutex_unlock (¶m_lock);
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 6/16 params: add 3rd arg to option handler callback signature
In reply to [email protected]From: Jim Cromie <[email protected]>
Add a 3rd arg, named "doing", to unknown-options callbacks invoked from parse_args(). The arg is passed as:
"Booting kernel" from start_kernel(), initcall_level_names[i] from do_initcall_level(), mod->name from load_module(), via parse_args(), parse_one()
parse_args() already has the "name" parameter, which is renamed to "doing" to better reflect current uses 1,2 above. parse_args() passes it to an altered parse_one(), which now passes it down into the unknown option handler callbacks.
The mod->name is needed for loadable modules, since params passed there are not qualified (they do not have a "$modname." prefix), and by the time the unknown-param callback is called, the module name is not otherwize available.
--- include/linux/moduleparam.h | 3 ++- init/main.c | 8 +++++--- kernel/params.c | 22 ++++++++++++---------- 3 files changed, 19 insertions(+), 14 deletions(-)
include/linux/moduleparam.h +2 -1
@@ -320,7 +320,8 @@ extern int parse_args(const char *name,unsigned num, s16 level_min, s16 level_max, - int (*unknown)(char *param, char *val)); + int (*unknown)(char *param, char *val, + const char *doing));/* Called by module remove. */ #ifdef CONFIG_SYSFS
init/main.c +5 -3
@@ -230,7 +230,8 @@ early_param("loglevel", loglevel);* Unknown boot options get handed to init, unless they look like * unused parameters (modprobe will find them in /proc/cmdline). */ -static int __init unknown_bootoption (char *param,char *val) +static int __init unknown_bootoption (char *param,char *val, +const char *unused) {/* Change NUL term back to "=", to make "param" the whole string. */ if (val) {
@@ -380,7 +381,7 @@ static noinline void __init_refok rest_init(void) }/* Check for early params. */ -static int __init do_early_param (char *param,char *val) +static int __init do_early_param (char *param,char *val,const char *unused) {const struct obs_kernel_param *p;
@@ -733,7 +734,8 @@ static char *initcall_level_names[] __initdata = { "late", }; -static int __init ignore_unknown_bootoption (char *param,char *val) +static int __init ignore_unknown_bootoption (char *param,char *val, +const char *doing) {return 0 ; }
kernel/params.c +12 -10
@@ -85,11 +85,13 @@ bool parameq(const char *a, const char *b)static int parse_one (char *param,char *val, +const char *doing,const struct kernel_param *params,unsigned num_params,s16 min_level,s16 max_level, -int (*handle_unknown)(char *param,char *val)) +int (*handle_unknown)(char *param,char *val, +const char *doing)) {unsigned int i;int err;
@@ -114,8 +116,8 @@ static int parse_one(char *param, }if (handle_unknown) { -pr_debug ("Unknown argument: calling %p\n" , handle_unknown); -return handle_unknown (param, val); +pr_debug ("doing %s: %s = %s\n" , doing, param, val); +return handle_unknown (param, val, doing); }pr_debug ("Unknown argument `%s'\n" , param);
@@ -175,17 +177,17 @@ static char *next_arg(char *args, char **param, char **val) }/* Args looks like "foo=bar,bar2 baz=fuz wiz". */ -int parse_args (const char *name, +int parse_args (const char *doing,char *args,const struct kernel_param *params,unsigned num,s16 min_level,s16 max_level, -int (*unknown)(char *param,char *val)) +int (*unknown)(char *param,char *val,const char *doing)) {char *param, *val; -pr_debug ("Parsing ARGS: %s\n" , args); +pr_debug ("doing %s, parsing ARGS: %s\n" , doing, args);/* Chew leading spaces */ args =skip_spaces (args);
@@ -196,7 +198,7 @@ int parse_args(const char *name, args =next_arg (args, ¶m, &val); irq_was_disabled =irqs_disabled (); - ret =parse_one (param, val, params, num, + ret =parse_one (param, val, doing, params, num, min_level, max_level, unknown);if (irq_was_disabled && !irqs_disabled ()) { printk(KERN_WARNING "parse_args(): option '%s' enabled "
@@ -205,19 +207,19 @@ int parse_args(const char *name,switch (ret) {case -ENOENT :printk (KERN_ERR "%s: Unknown parameter `%s'\n" , - name, param); + doing, param);return ret;case -ENOSPC :printk (KERN_ERR "%s: `%s' too large for parameter `%s'\n" , - name, val ?:"" , param); + doing, val ?:"" , param);return ret;case 0 :break ;default :printk (KERN_ERR "%s: `%s' invalid for parameter `%s'\n" , - name, val ?:"" , param); + doing, val ?:"" , param);return ret; } }
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 7/16 dynamic_debug: make dynamic-debug work for module initialization
In reply to [email protected]From: Jim Cromie <[email protected]>
This introduces a fake module param $module.dyndbg. Its based upon Thomas Renninger's $module.ddebug boot-time debugging patch from
https://lkml.org/lkml/2010/9/15/397
The 'fake' module parameter is provided for all modules, whether or not they need it. It is not explicitly added to each module, but is implemented in callbacks invoked from parse_args.
For builtin modules, dynamic_debug_init() now directly calls parse_args(..., &ddebug_dyndbg_boot_params_cb), to process the params undeclared in the modules, just after the ddebug tables are processed. While its slightly weird to reprocess the boot params, the dyndbg queries (given in dyndbg params) cannot be activated until after the ddebug tables are ready, and reusing parse_args is cleaner than an ad-hoc parse. This reparse would break options like inc_verbosity, but they probably should be params, like verbosity=3.
ddebug_dyndbg_boot_params_cb() handles both bare dyndbg (formerly ddebug_query) and module-prefixed dyndbg params, and ignores all other parameters. For example, the following will enable pr_debug()s in 4 builtin modules, in the order given:
dyndbg="module params +p; module aio +p" module.dyndbg=+p pci.dyndbg
With ddebug_query changed to dyndbg, we also deprecate "ddebug_query". The code handling it will be removed later. For now, both are active.
For loadable modules, parse_args() in load_module() calls ddebug_dyndbg_module_params_cb(). This handles bare dyndbg params as passed from modprobe, and errors on other unknown params.
Note that modprobe reads /proc/cmdline, so "modprobe foo" grabs all foo.params, strips the "foo.", and passes these to the kernel. ddebug_dyndbg_module_params_cb() is again called for the unknown params; it handles dyndbg, and errors on others. The "doing" arg added previously contains the module name.
For non CONFIG_DYNAMIC_DEBUG builds, the stub function accepts and ignores $module.dyndbg params, other unknowns get -ENOENT.
If no param value is given (as in pci.dyndbg example above), "+p" is assumed, which enables all pr_debug callsites in the module.
The dyndbg fake parameter is not shown in /sys/module/*/parameters, thus it does not use any resources. Changes to it are made via the control file.
--- include/linux/dynamic_debug.h | 17 ++++++++++++++ kernel/module.c | 2 +- lib/dynamic_debug.c | 49 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletions(-)
include/linux/dynamic_debug.h +17 -0
@@ -44,6 +44,9 @@ extern int ddebug_remove_module(const char *mod_name); extern __printf(2, 3) int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...); +extern int ddebug_dyndbg_module_param_cb(char *param, char *val, + const char *modname); + struct device; extern __printf(3, 4)
@@ -94,11 +97,25 @@ do { \#else +#include <linux/string.h> +#include <linux/errno.h> +static inline int ddebug_remove_module (const char *mod) {return 0 ; } +static inline int ddebug_dyndbg_module_param_cb (char *param,char *val, +const char *modname) +{ +if (strstr (param,"dyndbg" )) { +pr_warn ("dyndbg supported only in " +"CONFIG_DYNAMIC_DEBUG builds\n" ); +return 0 ;/* allow and ignore */ + } +return -EINVAL ; +} +#define dynamic_pr_debug (fmt, ...) \ do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)#define dynamic_dev_dbg (dev, fmt, ...) \
kernel/module.c +1 -1
@@ -2953,7 +2953,7 @@ static struct module *load_module(void __user *umod,/* Module is ready to execute: parsing args may do that. */ err =parse_args (mod->name, mod->args, mod->kp, mod->num_kp, --32768 ,32767 ,NULL ); +-32768 ,32767 , &ddebug_dyndbg_module_param_cb);if (err <0 ) goto unlink;
lib/dynamic_debug.c +49 -0
72 lines not on this page · raw message
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 8/16 dynamic_debug: deprecate ddebug_query, suggest dyndbg instead
In reply to [email protected]From: Jim Cromie <[email protected]>
Deprecate ddebug_query= in feature-removal-schedule.txt. Add a warning when processing ddebug_query= param to change it to dyndbg=.
--- Documentation/feature-removal-schedule.txt | 9 ++++++++- lib/dynamic_debug.c | 2 ++ 2 files changed, 10 insertions(+), 1 deletions(-)
Documentation/feature-removal-schedule.txt +8 -1
@@ -2,7 +2,14 @@ The following is a list of files and features that are going to be removed in the kernel source tree. Every entry should contain what exactly is going away, why it is happening, and who is going to be doing the work. When the feature is removed from the kernel, it should also -be removed from this file. +be removed from this file. The default deprecation period is 2-3 releases. + +--------------------------- + +What: ddebug_query="query" cmdline param +When: v3.6 +Why: obsoleted by dyndbg="query" and module.dyndbg="query" +Who: Jim Cromie <[email protected]>, Jason Baron <[email protected]> ---------------------------
lib/dynamic_debug.c +2 -0
@@ -993,6 +993,8 @@ static int __init dynamic_debug_init(void)/* ddebug_query boot param got passed -> set it up */ if (ddebug_setup_string[0 ] !='\0' ) { +pr_warn ("ddebug_query param name is deprecated," +" change it to dyndbg\n" ); ret =ddebug_exec_queries (ddebug_setup_string);if (ret <0 ) pr_warn("Invalid ddebug boot param %s",
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 9/16 dynamic_debug: combine parse_args callbacks together
In reply to [email protected]From: Jim Cromie <[email protected]>
Refactor ddebug_dyndbg_boot_param_cb and ddebug_dyndbg_module_param_cb into a common helper function, and call it from both. The handling of foo.dyndbg is unneeded by the latter, but harmless. The 2 callers differ only by pr_info and the return code they pass to the helper for when an unknown param is handled.
--- lib/dynamic_debug.c | 36 ++++++++++++++++++++---------------- 1 files changed, 20 insertions(+), 16 deletions(-)
lib/dynamic_debug.c +20 -16
@@ -862,39 +862,43 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n, }EXPORT_SYMBOL_GPL (ddebug_add_module); -/* handle both dyndbg=".." and $module.dyndbg=".." params at boot */ -static int ddebug_dyndbg_boot_param_cb (char *param,char *val, -const char *unused) +/* helper for ddebug_dyndbg_(boot|module)_param_cb */ +static int ddebug_dyndbg_param_cb (char *param,char *val, +const char *modname,int on_err) { -const char *modname =NULL ;char *sep; sep =strchr (param,'.' );if (sep) { +/* needed only for ddebug_dyndbg_boot_param_cb */ *sep ='\0' ; modname = param; param = sep +1 ; }if (strcmp (param,"dyndbg" )) -return 0 ;/* skip all other params w/o error */ - -vpr_info ("module: %s %s=\"%s\"\n" , modname, param, val); +return on_err;/* determined by caller */ ddebug_exec_queries (val ? val :"+p" );return 0 ;/* query failure shouldnt stop module load */ } -/* handle dyndbg args to modprobe */ -int ddebug_dyndbg_module_param_cb (char *param,char *val,const char *doing) +/* handle both dyndbg and $module.dyndbg params at boot */ +static int ddebug_dyndbg_boot_param_cb (char *param,char *val, +const char *unused) { -if (strcmp (param,"dyndbg" )) -return -ENOENT ; - -vpr_info ("module: %s %s=\"%s\"\n" , doing, param, val); - -ddebug_exec_queries ((val ? val :"+p" ), doing); +vpr_info ("%s=\"%s\"\n" , param, val); +return ddebug_dyndbg_param_cb (param, val,NULL ,0 ); +} -return 0 ;/* query failure shouldnt stop module load */ +/* +* modprobe foo finds foo.params in boot-args, strips "foo.", and +* passes them to load_module(). This callback gets unknown params, +* processes dyndbg params, rejects others. +*/ +int ddebug_dyndbg_module_param_cb (char *param,char *val,const char *module) +{ +vpr_info ("module: %s %s=\"%s\"\n" , module, param, val); +return ddebug_dyndbg_param_cb (param, val, module, -ENOENT ); }static void ddebug_table_free (struct ddebug_table *dt)
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 10/16 dynamic_debug: simplify dynamic_debug_init error exit
In reply to [email protected]From: Jim Cromie <[email protected]>
We dont want errors while parsing ddebug_query to unload ddebug tables, so set success after tables are loaded, and return 0 after query parsing is done.
Simplify error handling code since its no longer used for success, and change goto label to out_err to clarify this.
--- lib/dynamic_debug.c | 19 ++++++++----------- 1 files changed, 8 insertions(+), 11 deletions(-)
lib/dynamic_debug.c +8 -11
@@ -984,7 +984,7 @@ static int __init dynamic_debug_init(void)if (strcmp (modname, iter->modname)) { ret =ddebug_add_module (iter_start, n, modname);if (ret) - goto out_free; + goto out_err; n =0 ; modname = iter->modname; iter_start = iter;
@@ -993,9 +993,11 @@ static int __init dynamic_debug_init(void) } ret =ddebug_add_module (iter_start, n, modname);if (ret) - goto out_free; + goto out_err; -/* ddebug_query boot param got passed -> set it up */ + ddebug_init_success =1 ; + +/* apply ddebug_query boot param, dont unload tables on err */ if (ddebug_setup_string[0 ] !='\0' ) {pr_warn ("ddebug_query param name is deprecated," " change it to dyndbg\n" );
@@ -1005,9 +1007,6 @@ static int __init dynamic_debug_init(void) ddebug_setup_string); else pr_info("%d changes by ddebug_query\n", ret); - -/* keep tables even on ddebug_query parse error */ - ret =0 ; }/* now that ddebug tables are loaded, process all boot args * again to find and activate queries given in dyndbg params.
@@ -1021,12 +1020,10 @@ static int __init dynamic_debug_init(void)parse_args ("dyndbg params" , cmdline,NULL ,0 ,0 ,0 , &ddebug_dyndbg_boot_param_cb);kfree (cmdline); +return 0 ; -out_free: -if (ret) -ddebug_remove_all_tables (); -else - ddebug_init_success =1 ; +out_err: +ddebug_remove_all_tables ();return 0 ; }/* Allow early initialization for boot messages via boot param */
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 11/16 dynamic_debug: print ram usage by ddebug tables if verbose
In reply to [email protected]From: Jim Cromie <[email protected]>
Print ram usage of dynamic-debug so user knows cost of enabling CONFIG_DYNAMIC_DEBUG. Only counts cost of pr_debug in builtins, not those in loadable modules.
--- lib/dynamic_debug.c | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-)
lib/dynamic_debug.c +6 -1
@@ -970,7 +970,7 @@ static int __init dynamic_debug_init(void)const char *modname =NULL ;char *cmdline;int ret =0 ; -int n =0 ; +int n =0 , entries =0 , modct =0 ;if (__start___verbose == __stop___verbose) { pr_warn("_ddebug table is empty in a "
@@ -981,7 +981,9 @@ static int __init dynamic_debug_init(void) modname = iter->modname; iter_start = iter;for (; iter < __stop___verbose; iter++) { + entries++;if (strcmp (modname, iter->modname)) { + modct++; ret =ddebug_add_module (iter_start, n, modname);if (ret) goto out_err;
@@ -996,6 +998,9 @@ static int __init dynamic_debug_init(void) goto out_err; ddebug_init_success =1 ; +vpr_info ("%d modules, %d entries in ddebug tables, %d bytes used\n" , + modct, entries, modct *sizeof (struct ddebug_table ) + + __stop___verbose - __start___verbose);/* apply ddebug_query boot param, dont unload tables on err */ if (ddebug_setup_string[0 ] !='\0' ) {
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 12/16 pnp: if CONFIG_DYNAMIC_DEBUG, use pnp.dyndbg instead of pnp.debug
In reply to [email protected]From: Jim Cromie <[email protected]>
based upon https://lkml.org/lkml/2010/9/15/398
This patch splits control of pnp debug messages for 2 configs:
CONFIG_DYNAMIC_DEBUG:
use pnp.dyndbg, using pnp.debug will warn
!CONFIG_DYNAMIC_DEBUG:
use pnp.debug, using pnp.dyndbg will warn
2 separate boot options is perhaps suboptimal, but dyndbg is a 'fake' parameter, and is special enough that adapting one to another is both more suboptimal and harder to explain succinctly.
Thomas' original comments, still pertinent:
I wonder whether CONFIG_PNP_DEBUG_MESSAGES can vanish totally with this or at some time. Only advantage having it is: If you are restricted and your kernel must not exceed X bytes, you cannot compile in PNP debug messages only, but you have to compile in all debug messages.
--- Documentation/kernel-parameters.txt | 14 ++++++++------ drivers/pnp/base.h | 8 ++++++-- drivers/pnp/core.c | 12 ++++++++++++ 3 files changed, 26 insertions(+), 8 deletions(-)
Documentation/kernel-parameters.txt +8 -6
@@ -2215,12 +2215,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Override pmtimer IOPort with a hex value. e.g. pmtmr=0x508 - pnp.debug=1 [PNP] - Enable PNP debug messages (depends on the - CONFIG_PNP_DEBUG_MESSAGES option). Change at run-time - via /sys/module/pnp/parameters/debug. We always show - current resource usage; turning this on also shows - possible settings and some assignment information. + pnp.debug=1 [PNP] Enable PNP debug messages + (depends on CONFIG_PNP_DEBUG_MESSAGES and + !CONFIG_DYNAMIC_DEBUG options. If latter, use + pnp.dyndbg instead). Change at run-time via + /sys/module/pnp/parameters/debug. We always + show current resource usage; turning this on + also shows possible settings and some + assignment information. pnpacpi= [ACPI] { off }
drivers/pnp/base.h +6 -2
@@ -173,12 +173,16 @@ struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,resource_size_t start, resource_size_t end); -extern int pnp_debug; - +#if defined(CONFIG_DYNAMIC_DEBUG ) +#define pnp_dbg(dev, format, arg...) \ + ({ dev_dbg(dev, format, ## arg); 0; }) +#else #if defined(CONFIG_PNP_DEBUG_MESSAGES ) +extern int pnp_debug; #define pnp_dbg(dev, format, arg...) \ ({ if (pnp_debug) dev_printk(KERN_DEBUG, dev, format, ## arg); 0; })#else #define pnp_dbg(dev, format, arg...) \ ({ if (0) dev_printk(KERN_DEBUG, dev, format, ## arg); 0; })#endif +#endif
drivers/pnp/core.c +12 -0
@@ -219,6 +219,18 @@ subsys_initcall(pnp_init);int pnp_debug; +#if defined(CONFIG_DYNAMIC_DEBUG ) +static int __init pnp_debug_setup (char *__unused) +{ +pr_info ("DYNAMIC_DEBUG enabled, use pnp.dyndbg instead\n" ); +return 1 ; +} +__setup ("pnp.debug" , pnp_debug_setup); + +#else +#if defined(CONFIG_PNP_DEBUG_MESSAGES )module_param_named (debug, pnp_debug, int,0644 );#endif + +#endif
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 13/16 dynamic_debug: add modname arg to exec_query callchain
In reply to [email protected]From: Jim Cromie <[email protected]>
Pass module name into ddebug_exec_queries(), ddebug_exec_query(), and ddebug_parse_query() as separate parameter. In ddebug_parse_query(), the module name is added into the query struct before the query-string is parsed. This allows the query-string to be shorter:
instead of:
$modname.dyndbg="module $modname +fp"
do this:
$modname.dyndbg="+fp"
Omitting "module $modname" from the query string is actually required for $modname.dyndbg rules; the set-only-once check added in a previous patch will throw an error if its added again. ddebug_query="..." has no $modname associated with it, so the query string may include it.
This also fixes redundant "module $modname" otherwise needed to handle multiple queries per string:
$modname.dyndbg="func foo +fp; func bar +fp"
--- lib/dynamic_debug.c | 19 ++++++++++++------- 1 files changed, 12 insertions(+), 7 deletions(-)
lib/dynamic_debug.c +12 -7
@@ -338,7 +338,7 @@ static int check_set(const char **dest, char *src, char *name)* Returns 0 on success, <0 on error. */ static int ddebug_parse_query (char *words[],int nwords, -struct ddebug_query *query) +struct ddebug_query *query,const char *modname) {unsigned int i;int rc;
@@ -348,6 +348,10 @@ static int ddebug_parse_query(char *words[], int nwords,return -EINVAL ;memset (query,0 ,sizeof (*query)); +if (modname) +/* support $modname.dyndbg=<multiple queries> */ + query->module = modname; +for (i =0 ; i < nwords ; i +=2 ) {if (!strcmp (words[i],"func" )) rc =check_set (&query->function, words[i+1 ],"func" );
@@ -444,7 +448,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,return 0 ; } -static int ddebug_exec_query (char *query_string) +static int ddebug_exec_query (char *query_string,const char *modname) {unsigned int flags =0 , mask =0 ;struct ddebug_query query;
@@ -455,7 +459,7 @@ static int ddebug_exec_query(char *query_string) nwords =ddebug_tokenize (query_string, words,MAXWORDS );if (nwords <=0 )return -EINVAL ; -if (ddebug_parse_query (words, nwords-1 , &query)) +if (ddebug_parse_query (words, nwords-1 , &query, modname))return -EINVAL ;if (ddebug_parse_flags (words[nwords-1 ], &flags, &mask))return -EINVAL ;
@@ -471,7 +475,7 @@ static int ddebug_exec_query(char *query_string)last error or number of matching callsites. Module name is either in param (for boot arg) or perhaps in query string. */ -static int ddebug_exec_queries (char *query) +static int ddebug_exec_queries (char *query,const char *modname) {char *split;int i, errs =0 , exitcode =0 , rc, nfound =0 ;
@@ -487,7 +491,7 @@ static int ddebug_exec_queries(char *query)vpr_info ("query %d: \"%s\"\n" , i, query); - rc =ddebug_exec_query (query); + rc =ddebug_exec_query (query, modname);if (rc <0 ) { errs++; exitcode = rc;
@@ -652,7 +656,7 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, tmpbuf[len] ='\0' ;vpr_info ("read %d bytes from userspace\n" , (int )len); - ret =ddebug_exec_queries (tmpbuf); + ret =ddebug_exec_queries (tmpbuf,NULL );kfree (tmpbuf);if (ret <0 )return ret;
@@ -878,7 +882,8 @@ static int ddebug_dyndbg_param_cb(char *param, char *val,if (strcmp (param,"dyndbg" ))return on_err;/* determined by caller */ -ddebug_exec_queries (val ? val :"+p" ); +ddebug_exec_queries ((val ? val :"+p" ), modname); +return 0 ;/* query failure shouldnt stop module load */ }
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 14/16 dynamic_debug: update Documentation/*, Kconfig.debug
In reply to [email protected]From: Jim Cromie <[email protected]>
In dynamic-debug-howto.txt:
- add section: Debug Messages at Module Initialization Time
- update flags indicators in example outputs to include '='
- make flags descriptions tabular
- add item on '_' flag-char
- add dyndbg, boot-args examples
- rewrap some paragraphs with long lines
In Kconfig.debug, note that compiling with -DDEBUG enables all pr_debug()s in that code.
In kernel-parameters.txt, add dyndbg and module.dyndbg items, and deprecate ddebug_query.
--- Documentation/dynamic-debug-howto.txt | 184 +++++++++++++++++++++----------- Documentation/kernel-parameters.txt | 7 +- lib/Kconfig.debug | 17 ++- 3 files changed, 138 insertions(+), 70 deletions(-)
Documentation/dynamic-debug-howto.txt +121 -63
@@ -2,17 +2,17 @@ Introduction ============ -This document describes how to use the dynamic debug (ddebug) feature. +This document describes how to use the dynamic debug (dyndbg) feature. -Dynamic debug is designed to allow you to dynamically enable/disable kernel -code to obtain additional kernel information. Currently, if -CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() calls can be -dynamically enabled per-callsite. +Dynamic debug is designed to allow you to dynamically enable/disable +kernel code to obtain additional kernel information. Currently, if +CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() calls can +be dynamically enabled per-callsite. Dynamic debug has even more useful features: - * Simple query language allows turning on and off debugging statements by - matching any combination of 0 or 1 of: + * Simple query language allows turning on and off debugging + statements by matching any combination of 0 or 1 of: - source filename - function name
@@ -20,17 +20,19 @@ Dynamic debug has even more useful features: - module name - format string - * Provides a debugfs control file: <debugfs>/dynamic_debug/control which can be - read to display the complete list of known debug statements, to help guide you + * Provides a debugfs control file: <debugfs>/dynamic_debug/control + which can be read to display the complete list of known debug + statements, to help guide you Controlling dynamic debug Behaviour =================================== The behaviour of pr_debug()/dev_dbg()s are controlled via writing to a -control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs -filesystem, in order to make use of this feature. Subsequently, we refer to the -control file as: <debugfs>/dynamic_debug/control. For example, if you want to -enable printing from source file 'svcsock.c', line 1603 you simply do: +control file in the 'debugfs' filesystem. Thus, you must first mount +the debugfs filesystem, in order to make use of this feature. +Subsequently, we refer to the control file as: +<debugfs>/dynamic_debug/control. For example, if you want to enable +printing from source file 'svcsock.c', line 1603 you simply do: nullarbor:~ # echo 'file svcsock.c line 1603 +p' > <debugfs>/dynamic_debug/control
@@ -44,15 +46,15 @@ nullarbor:~ # echo 'file svcsock.c wtf 1 +p' > Viewing Dynamic Debug Behaviour =========================== -You can view the currently configured behaviour of all the debug statements -via: +You can view the currently configured behaviour of all the debug +statements via: nullarbor:~ # cat <debugfs>/dynamic_debug/control # filename:lineno [module]function flags format -/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup - "SVCRDMA Module Removed, deregister RPC RDMA transport\012" -/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init - "\011max_inline : %d\012" -/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init - "\011sq_depth : %d\012" -/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init - "\011max_requests : %d\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup =_ "SVCRDMA Module Removed, deregister RPC RDMA transport\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init =_ "\011max_inline : %d\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init =_ "\011sq_depth : %d\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init =_ "\011max_requests : %d\012" ...
@@ -65,12 +67,12 @@ nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control | wc -l nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l 42 -Note in particular that the third column shows the enabled behaviour -flags for each debug statement callsite (see below for definitions of the -flags). The default value, no extra behaviour enabled, is "-". So -you can view all the debug statement callsites with any non-default flags: +The third column shows the currently enabled flags for each debug +statement callsite (see below for definitions of the flags). The +default value, with no flags enabled, is "=_". So you can view all +the debug statement callsites with any non-default flags: -nullarbor:~ # awk '$3 != "-"' <debugfs>/dynamic_debug/control +nullarbor:~ # awk '$3 != "=_"' <debugfs>/dynamic_debug/control # filename:lineno [module]function flags format /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012"
@@ -103,15 +105,14 @@ specifications, followed by a flags change specification. command ::= match-spec* flags-spec -The match-spec's are used to choose a subset of the known dprintk() +The match-spec's are used to choose a subset of the known pr_debug() callsites to which to apply the flags-spec. Think of them as a query with implicit ANDs between each pair. Note that an empty list of -match-specs is possible, but is not very useful because it will not -match any debug statement callsites. +match-specs will select all debug statement callsites. -A match specification comprises a keyword, which controls the attribute -of the callsite to be compared, and a value to compare against. Possible -keywords are: +A match specification comprises a keyword, which controls the +attribute of the callsite to be compared, and a value to compare +against. Possible keywords are: match-spec ::= 'func' string | 'file' string |
@@ -164,15 +165,15 @@ format characters (") or single quote characters ('). Examples: - format svcrdma: // many of the NFS/RDMA server dprintks - format readahead // some dprintks in the readahead cache + format svcrdma: // many of the NFS/RDMA server pr_debugs + format readahead // some pr_debugs in the readahead cache format nfsd:\040SETATTR // one way to match a format with whitespace format "nfsd: SETATTR" // a neater way to match a format with whitespace format 'nfsd: SETATTR' // yet another way to match a format with whitespace line The given line number or range of line numbers is compared - against the line number of each dprintk() callsite. A single + against the line number of each pr_debug() callsite. A single line number matches the callsite line number exactly. A range of line numbers matches any callsite between the first and last line number inclusive. An empty first number means
@@ -188,51 +189,93 @@ The flags specification comprises a change operation followed by one or more flag characters. The change operation is one of the characters: -- - remove the given flags - -+ - add the given flags - -= - set the flags to the given flags + - remove the given flags + + add the given flags + = set the flags to the given flags 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 - Causes a printk() message to be emitted to dmesg -t - Include thread ID in messages not generated from interrupt context + p enables the pr_debug() callsite. + 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 + t Include thread ID in messages not generated from interrupt context + _ No flags are set. (Or'd with others on input) + +For display, the flags are preceded by '=' +(mnemonic: what the flags are currently equal to). -Note the regexp ^[-+=][flmpt]+$ matches a flags specification. -Note also that there is no convenient syntax to remove all -the flags at once, you need to use "-flmpt". +Note the regexp ^[-+=][flmpt_]+$ matches a flags specification. +To clear all flags at once, use "=_" or "-flmpt". -Debug messages during boot process +Debug messages during Boot Process ================================== -To be able to activate debug messages during the boot process, -even before userspace and debugfs exists, use the boot parameter: -ddebug_query="QUERY" +To activate debug messages for core code and built-in modules during +the boot process, even before userspace and debugfs exists, use +dyndbg="QUERY", module.dyndbg="QUERY", or ddebug_query="QUERY" +(ddebug_query is obsoleted by dyndbg, and deprecated). QUERY follows +the syntax described above, but must not exceed 1023 characters. Your +bootloader may impose lower limits. + +These dyndbg params are processed just after the ddebug tables are +processed, as part of the arch_initcall. Thus you can enable debug +messages in all code run after this arch_initcall via this boot +parameter. -QUERY follows the syntax described above, but must not exceed 1023 -characters. The enablement of debug messages is done as an arch_initcall. -Thus you can enable debug messages in all code processed after this -arch_initcall via this boot parameter. On an x86 system for example ACPI enablement is a subsys_initcall and -ddebug_query="file ec.c +p" + dyndbg="file ec.c +p" will show early Embedded Controller transactions during ACPI setup if your machine (typically a laptop) has an Embedded Controller. PCI (or other devices) initialization also is a hot candidate for using this boot parameter for debugging purposes. +If foo module is not built-in, foo.dyndbg will still be processed at +boot time, without effect, but will be reprocessed when module is +loaded later. dyndbg_query= and bare dyndbg= are only processed at +boot. + + +Debug Messages at Module Initialization Time +============================================ + +When "modprobe foo" is called, modprobe scans /proc/cmdline for +foo.params, strips "foo.", and passes them to the kernel along with +params given in modprobe args or /etc/modprob.d/*.conf files, +as follows: + +1. # parameters given via /etc/modprobe.d/*.conf + options foo dyndbg=+pt + options foo dyndbg # defaults to +p + +2. # foo.dyndbg as given in boot args, "foo." is stripped and passed + foo.dyndbg=" func bar +p; func buz +mp" + +3. # as an ordinary module parameter via modprobe + modprobe foo dyndbg==pmf # override previous settings + +These dyndbg queries are applied in the order given above, with last +having final say. This allows boot args to override or supplement +those from /etc/modprobe.d, and modprobe args to override both. + +each to either supplement (dyndbg=+tfl) +or override (dyndbg="=p_") flags given previously. After processing +1-3 as given above, all pr_debug()s in module foo are set to "pmf". + +In the foo.dyndbg="QUERY" form, the query must exclude "module foo". +"foo" is inferred from the param-name, and applied to each query +in "QUERY", and only 1 match-spec of each type is allowed. + +The dyndbg option is not implemented as an ordinary module parameter +and is not in /sys/module/$module_name/parameters/. To see it, grep +the control file, or inspect /proc/cmdline. + +For CONFIG_DYNAMIC_DEBUG kernels, any settings given at boot-time (or +by -DDEBUG flag during compilation) can be disabled later via the +sysfs interface if the debug messages are no longer needed: + + echo "module module_name -p" > <debugfs>/dynamic_debug/control Examples ========
@@ -260,3 +303,18 @@ nullarbor:~ # echo -n 'func svc_process -p' > // enable messages for NFS calls READ, READLINK, READDIR and READDIR+. nullarbor:~ # echo -n 'format "nfsd: READ" +p' > <debugfs>/dynamic_debug/control + +// enable all messages +nullarbor:~ # echo -n '+p' > <debugfs>/dynamic_debug/control + +// add module, function to all enabled messages +nullarbor:~ # echo -n '+mf' > <debugfs>/dynamic_debug/control + +// boot-args example, with newlines and comments for readability +Kernel command line: ... + // see whats going on in dyndbg=value processing + dynamic_debug.verbose=1 + // enable pr_debugs in 2 builtins, #cmt is stripped + dyndbg="module params +p #cmt ; module sys +p" + // enable pr_debugs in 2 functions in a module loaded later + pc87360.dyndbg="func pc87360_init_device +p; func pc87360_find +p"
Documentation/kernel-parameters.txt +6 -1
@@ -610,7 +610,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ddebug_query= [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot time. See Documentation/dynamic-debug-howto.txt for - details. + details. Deprecated, see dyndbg. debug [KNL] Enable kernel debugging (events log level).
@@ -730,6 +730,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. dscc4.setup= [NET] + dyndbg[="val"] [KNL,DYNAMIC_DEBUG] + module.dyndbg[="val"] + Enable debug messages at boot time. See + Documentation/dynamic-debug-howto.txt for details. + earlycon= [KNL] Output early console device and options. uart[8250],io,<addr>[,options] uart[8250],mmio,<addr>[,options]
lib/Kconfig.debug +11 -6
@@ -1204,8 +1204,13 @@ config DYNAMIC_DEBUG otherwise be available at runtime. These messages can then be enabled/disabled based on various levels of scope - per source file, function, module, format string, and line number. This mechanism - implicitly enables all pr_debug() and dev_dbg() calls. The impact of - this compile option is a larger kernel text size of about 2%. + implicitly compiles in all pr_debug() and dev_dbg() calls, which + enlarges the kernel text size by about 2%. + + If a source file is compiled with DEBUG flag set, any + pr_debug() calls in it are enabled by default, but can be + disabled at runtime as below. Note that DEBUG flag is + turned on by many CONFIG_*DEBUG* options. Usage:
@@ -1222,16 +1227,16 @@ config DYNAMIC_DEBUG lineno : line number of the debug statement module : module that contains the debug statement function : function that contains the debug statement - flags : 'p' means the line is turned 'on' for printing + flags : '=p' means the line is turned 'on' for printing format : the format used for the debug statement From a live system: nullarbor:~ # cat <debugfs>/dynamic_debug/control # filename:lineno [module]function flags format - fs/aio.c:222 [aio]__put_ioctx - "__put_ioctx:\040freeing\040%p\012" - fs/aio.c:248 [aio]ioctx_alloc - "ENOMEM:\040nr_events\040too\040high\012" - fs/aio.c:1770 [aio]sys_io_cancel - "calling\040cancel\012" + fs/aio.c:222 [aio]__put_ioctx =_ "__put_ioctx:\040freeing\040%p\012" + fs/aio.c:248 [aio]ioctx_alloc =_ "ENOMEM:\040nr_events\040too\040high\012" + fs/aio.c:1770 [aio]sys_io_cancel =_ "calling\040cancel\012" Example usage:
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 15/16 dynamic_debug: init with early_initcall, not arch_initcall
In reply to [email protected]From: Jim Cromie <[email protected]>
1- Call dynamic_debug_init() from early_initcall, not arch_initcall. 2- Call dynamic_debug_init_debugfs() from fs_initcall, not module_init.
RFC: This works for me on a 64 bit desktop and a i586 SBC, but is untested on other arches. I presume there is or was a reason original code used arch_initcall, maybe the constraints have changed.
This makes facility available as soon as possible.
2nd change has a downside when dynamic_debug.verbose=1; all the vpr_info()s called in the proc-fs code are activated, causing voluminous output from dmesg. TBD: Im unsure of this explanation, but the output is there. This could be fixed by changing those callsites to v2pr_info(if verbose > 1).
1st change is still not early enough to enable pr_debugs in kernel/params, so parsing of boot-args isnt logged. The reparse of those args is however visible after params.dyndbg="+p" is processed.
--- lib/dynamic_debug.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
lib/dynamic_debug.c +2 -2
@@ -1037,7 +1037,7 @@ out_err:return 0 ; }/* Allow early initialization for boot messages via boot param */ -arch_initcall (dynamic_debug_init); +early_initcall (dynamic_debug_init);/* Debugfs setup must be done later */ -module_init (dynamic_debug_init_debugfs); +fs_initcall (dynamic_debug_init_debugfs);
Signature · 1 line
1.7.7.6
[email protected]
maintainerPATCH 16/16 dynamic_debug: drop deprecated ddebug_query param, code
In reply to [email protected]From: Jim Cromie <[email protected]>
DONT APPLY NOW. for v3.6 or v3.7 timeframe.
--- Documentation/dynamic-debug-howto.txt | 7 +++---- lib/dynamic_debug.c | 26 -------------------------- 2 files changed, 3 insertions(+), 30 deletions(-)
Documentation/dynamic-debug-howto.txt +3 -4
@@ -214,10 +214,9 @@ Debug messages during Boot Process To activate debug messages for core code and built-in modules during the boot process, even before userspace and debugfs exists, use -dyndbg="QUERY", module.dyndbg="QUERY", or ddebug_query="QUERY" -(ddebug_query is obsoleted by dyndbg, and deprecated). QUERY follows -the syntax described above, but must not exceed 1023 characters. Your -bootloader may impose lower limits. +dyndbg="QUERY", module.dyndbg="QUERY". QUERY follows the syntax +described above, but must not exceed 1023 characters. Your bootloader +may impose lower limits. These dyndbg params are processed just after the ddebug tables are processed, as part of the arch_initcall. Thus you can enable debug
lib/dynamic_debug.c +0 -26
@@ -614,21 +614,6 @@ EXPORT_SYMBOL(__dynamic_netdev_dbg);#endif -#define DDEBUG_STRING_SIZE 1024 -static __initdata char ddebug_setup_string[DDEBUG_STRING_SIZE ]; - -static __init int ddebug_setup_query (char *str) -{ -if (strlen (str) >=DDEBUG_STRING_SIZE ) { -pr_warn ("ddebug boot param string too large\n" ); -return 0 ; - } -strlcpy (ddebug_setup_string, str,DDEBUG_STRING_SIZE ); -return 1 ; -} - -__setup ("dyndbg=" , ddebug_setup_query); -/* * File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the * command text from userspace, parses and executes it.
@@ -1007,17 +992,6 @@ static int __init dynamic_debug_init(void) modct, entries, modct *sizeof (struct ddebug_table ) + __stop___verbose - __start___verbose); -/* apply ddebug_query boot param, dont unload tables on err */ -if (ddebug_setup_string[0 ] !='\0' ) { -pr_warn ("ddebug_query param name is deprecated," -" change it to dyndbg\n" ); - ret =ddebug_exec_queries (ddebug_setup_string); -if (ret <0 ) -pr_warn ("Invalid ddebug boot param %s" , - ddebug_setup_string); -else -pr_info ("%d changes by ddebug_query\n" , ret); - }/* now that ddebug tables are loaded, process all boot args * again to find and activate queries given in dyndbg params. * While this has already been done for known boot params, it
Signature · 1 line
1.7.7.6