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(&param, ".");
+
        /* 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, &param, &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/

Reply via email to