[RFC] [PATCH] Allow overriding module parameters from kernel command_line

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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/

[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]
  Powered by Linux