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/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]