From 9fb48c744ba6a4bf58b666f4e6fdac3008ea1bd4 Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Fri, 27 Apr 2012 14:30:34 -0600 Subject: params: add 3rd arg to option handler callback signature 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 will be needed to handle dyndbg for loadable modules, since params passed by modprobe 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 otherwise available. Minor tweaks: Add param-name to parse_one's pr_debug(), current message doesnt identify the param being handled, add it. Add a pr_info to print current level and level_name of the 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[], its unhelpful in the pr_info() added above. This array is passed into parse_args() by do_initcall_level(). CC: Rusty Russell Signed-off-by: Jim Cromie Acked-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- include/linux/moduleparam.h | 3 ++- init/main.c | 33 ++++++++++++++++++++------------- kernel/params.c | 31 +++++++++++++++++-------------- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index ea36486..1b14d25 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -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 diff --git a/init/main.c b/init/main.c index 9d454f0..11bc6f7 100644 --- a/init/main.c +++ b/init/main.c @@ -229,7 +229,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) { @@ -379,7 +380,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; @@ -722,17 +723,18 @@ 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) +static int __init ignore_unknown_bootoption(char *param, char *val, + const char *doing) { return 0; } @@ -747,7 +749,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); @@ -757,8 +759,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); + } } /* diff --git a/kernel/params.c b/kernel/params.c index f37d826..b60e2c7 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -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; @@ -104,8 +106,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); @@ -114,11 +116,11 @@ 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); + pr_debug("Unknown argument '%s'\n", param); return -ENOENT; } @@ -175,28 +177,29 @@ 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); - /* Chew leading spaces */ args = skip_spaces(args); + if (args && *args) + pr_debug("doing %s, parsing ARGS: '%s'\n", doing, args); + while (*args) { int ret; int irq_was_disabled; 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 +208,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; } } -- cgit v1.1