It is often advantageous to pass parameters to built-in kernel modules
at boot time using the convention <module>.<option>. However, this does
not work with loadable modules where modprobe reads its options from the
config files. This patch adds support for modprobe to read /proc/cmdline
and add any options it finds when inserting the modules.
Signed-off-by: Dan Nicholson <dbn.lists(a)gmail.com>
---
This is the patch I sent to Jon a couple days ago. It's working in my
testing. We briefly discussed whether there should be a switch to
modprobe to disable the kernel command line parsing since /proc/cmdline
is read only. Without the switch, only passing an opposing option on the
modprobe command line would override what you booted with. Jon decided
to move along without it for now.
doc/modprobe.sgml | 4 +++-
modprobe.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+), 1 deletions(-)
diff --git a/doc/modprobe.sgml b/doc/modprobe.sgml
index 767582a..fbbe2e8 100644
--- a/doc/modprobe.sgml
+++ b/doc/modprobe.sgml
@@ -77,7 +77,9 @@
<filename>/etc/modprobe.d</filename> directory
(see <citerefentry>
<refentrytitle>modprobe.conf</refentrytitle><manvolnum>5</manvolnum>
- </citerefentry>).
+ </citerefentry>). <command>modprobe</command> will also use module
+ options specified on the kernel command line in the form of
+ <module>.<option>.
</para>
<para>
Note that this version of <command>modprobe</command> does not
diff --git a/modprobe.c b/modprobe.c
index 9b171cc..51b9d64 100644
--- a/modprobe.c
+++ b/modprobe.c
@@ -1257,6 +1257,46 @@ static void read_toplevel_config(const char *filename,
}
}
+/* Read possible module arguments from the kernel command line. */
+static int read_kcmdline(int dump_only, struct module_options **options)
+{
+ char *line;
+ unsigned int linenum = 0;
+ FILE *kcmdline;
+
+ kcmdline = fopen("/proc/cmdline", "r");
+ if (!kcmdline)
+ return 0;
+
+ while ((line = getline_wrapped(kcmdline, &linenum)) != NULL) {
+ char *ptr = line;
+ char *arg;
+
+ while ((arg = strsep_skipspace(&ptr, "\t ")) != NULL) {
+ char *sep, *modname, *opt;
+
+ sep = strchr(arg, '.');
+ if (sep) {
+ if (!strchr(sep, '='))
+ continue;
+ modname = arg;
+ *sep = '\0';
+ opt = ++sep;
+
+ if (dump_only)
+ printf("options %s %s\n", modname, opt);
+
+ *options = add_options(underscores(modname),
+ opt, *options);
+ }
+ }
+
+ free(line);
+ }
+ fclose(kcmdline);
+ return 1;
+}
+
static void add_to_env_var(const char *option)
{
const char *oldenv;
@@ -1586,6 +1626,7 @@ int main(int argc, char *argv[])
read_toplevel_config(config, "", 1, 0,
&modoptions, &commands, &aliases, &blacklist);
+ read_kcmdline(1, &modoptions);
read_config(aliasfilename, "", 1, 0,&modoptions, &commands,
&aliases, &blacklist);
read_config(symfilename, "", 1, 0, &modoptions, &commands,
@@ -1617,6 +1658,9 @@ int main(int argc, char *argv[])
read_toplevel_config(config, modulearg, 0,
remove, &modoptions, &commands, &aliases, &blacklist);
+ /* Read module options from kernel command line */
+ read_kcmdline(0, &modoptions);
+
/* No luck? Try symbol names, if starts with symbol:. */
if (!aliases
&& strncmp(modulearg, "symbol:", strlen("symbol:")) == 0)
--
1.5.5.1