With the move to initramfs and heavily modular configs, which include loading storage drivers from early userspace, it's becoming harder to provide users with a way of overriding module parameters at boot.
Currently, users would have to break into the initramfs, edit the modprobe options, and then let boot continue. They have a much easier time dealing with adding options on the command line from Grub or what have you. I hacked out this patch quickly to re-parse saved_command_line[] when we load a module in an attempt to rectify this. (The specific use-case I was looking at here was HPA commands failing on sata_nv controllers, and needing to pass the adma=0 option to the module... Users had a hard time testing without an easy way of overriding the module.) Clearly this is not entirely optimal, because we're parsing command_line after the module params are parsed. This ends of being a policy decision, whether the /sbin/modprobe commandline should override the kernel command_line, or vice versa. Anyway, please comment... Cheers, Kyle diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index c83588c..e8465db 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -98,7 +98,7 @@ struct kparam_array extern int parse_args(const char *name, char *args, struct kernel_param *params, - unsigned num, + unsigned num, unsigned strip_module, int (*unknown)(char *param, char *val)); /* All the helper functions */ diff --git a/init/main.c b/init/main.c index a92989e..a3d647f 100644 --- a/init/main.c +++ b/init/main.c @@ -478,7 +478,7 @@ void __init parse_early_param(void) /* All fall through to do_early_param. */ strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE); - parse_args("early options", tmp_cmdline, NULL, 0, do_early_param); + parse_args("early options", tmp_cmdline, NULL, 0, 0, do_early_param); done = 1; } @@ -549,7 +549,7 @@ asmlinkage void __init start_kernel(void) printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line); parse_early_param(); parse_args("Booting kernel", static_command_line, __start___param, - __stop___param - __start___param, + __stop___param - __start___param, 0, &unknown_bootoption); if (!irqs_disabled()) { printk(KERN_WARNING "start_kernel(): bug: interrupts were " diff --git a/kernel/module.c b/kernel/module.c index dcdb32b..e576242 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1914,10 +1914,21 @@ static struct module *load_module(void __user *umod, sechdrs[setupindex].sh_addr, sechdrs[setupindex].sh_size / sizeof(struct kernel_param), - NULL); + 0, NULL); if (err < 0) goto arch_cleanup; + /* Allow user to override module params from the command line. */ + err = parse_args(mod->name, saved_command_line, + (struct kernel_param *) + sechdrs[setupindex].sh_addr, + sechdrs[setupindex].sh_size + / sizeof(struct kernel_param), + 1, NULL); + if (err < 0) + printk(KERN_WARNING "%s: Ignoring bad module parameters passed on " + "kernel command line\n", mod->name); + err = mod_sysfs_setup(mod, (struct kernel_param *) sechdrs[setupindex].sh_addr, diff --git a/kernel/params.c b/kernel/params.c index 1fc4ac7..7c9d3a0 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -50,10 +50,17 @@ static int parse_one(char *param, char *val, struct kernel_param *params, unsigned num_params, - int (*handle_unknown)(char *param, char *val)) + int (*handle_unknown)(char *param, char *val), + unsigned strip_module) { unsigned int i; + /* If we're parsing command_line[] for the module, + * strip off the module name before looking the param up. + */ + if (strip_module) + strsep(¶m, "."); + /* Find parameter */ for (i = 0; i < num_params; i++) { if (parameq(param, params[i].name)) { @@ -130,7 +137,7 @@ static char *next_arg(char *args, char **param, char **val) int parse_args(const char *name, char *args, struct kernel_param *params, - unsigned num, + unsigned num, unsigned strip_module, int (*unknown)(char *param, char *val)) { char *param, *val; @@ -147,7 +154,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, unknown); + ret = parse_one(param, val, params, num, unknown, strip_module); if (irq_was_disabled && !irqs_disabled()) { printk(KERN_WARNING "parse_args(): option '%s' enabled " "irq's!\n", param); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/