Hi guys, I have been working on the remaining bits before we can drop our load-modules.sh from udev.
I asked around on #udev to see what they thought of moving some of our functionality upstream. Kay Sievers rightly pointed out that the functionality belongs in module-init-tools, not in udev. I made a few patches against module-init-tools which simplifies what we have to do in initscripts/mkinitcpio, and I'd like to ask your opinion about this before submitting upstream. Kernel commandline blacklisting: modprobe will parse /proc/kcmdline in addition to the configuration files to blacklist modules. The syntax is "modprobe.blacklist=mod1,mod2,mod3". rc.conf blacklist compatibility: This is only relevant for initscripts. modprobe will read /run/modprobe.d in addition to /etc/modprobe.d for configuration files, so at boot we can generate a blacklist file directly in /run based on rc.conf. I'm still working on some improvements to this patch that are needed before it can be upstreamed (if two files with the same name exist in different directories one needs to be ignored), but the functionality we care about is already there. Any comments? Does this sound like enough to remove the blacklisting logic provided by modules-load.sh? For an idea of what initscripts will do at boot once this is in modules-init-tools, have a look here: <https://github.com/teg/initscripts-arch/blob/ccac6d93278fe4ce2e8cbf9923c089a272d06bfb/modprobe-blacklist>. Cheers, Tom
From 285c93a4c1d8df94598ded7297b1cde68dd1e30f Mon Sep 17 00:00:00 2001 From: Tom Gundersen <[email protected]> Date: Tue, 24 May 2011 18:38:11 +0200 Subject: [PATCH 2/2] modprobe: use more than one config directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Read config files from the following directories: /run/modprobe.d config files generated at runtime, useful e.g. for compatibility with non-standard config files (such as /etc/rc.conf in Arch) /etc/modprobe.d config files manually created by the administrator /lib/modprobe.d config files installed by third-party packages /usr/local/lib/modprobe.d config files during development of third-party packages This scheme is the same as the one employed by udev, systemd and possibly others. A follow-up patch lets files in one directory override files in others, as done elsewhere. Cc: Kay Sievers <[email protected]> Cc: Aaron Griffin <[email protected]> Cc: Thomas Bächler <[email protected]> Signed-off-by: Tom Gundersen <[email protected]> --- modprobe.c | 137 ++++++++++++++++++++++++++++++++---------------------------- 1 files changed, 73 insertions(+), 64 deletions(-) diff --git a/modprobe.c b/modprobe.c index 65de11a..9c8ba37 100644 --- a/modprobe.c +++ b/modprobe.c @@ -789,10 +789,9 @@ static char *strsep_skipspace(char **string, char *delim) return strsep(string, delim); } -static int parse_config_scan(const char *filename, - struct modprobe_conf *conf, +static int parse_config_scan(struct modprobe_conf *conf, int dump_only, - int removing); + int removing, ...); static int parse_config_file(const char *filename, struct modprobe_conf *conf, @@ -847,9 +846,9 @@ static int parse_config_file(const char *filename, warn("\"include /etc/modprobe.d\" is " "the default, ignored\n"); } else { - if (!parse_config_scan(newfilename, - &newconf, dump_only, - removing)) + if (!parse_config_scan(&newconf, dump_only, + removing, newfilename, + NULL)) warn("Failed to open included" " config file %s: %s\n", newfilename, strerror(errno)); @@ -1044,70 +1043,77 @@ syntax_error: return 1; } -static int parse_config_scan(const char *filename, - struct modprobe_conf *conf, +static int parse_config_scan(struct modprobe_conf *conf, int dump_only, - int removing) + int removing, ...) { + va_list filelist; + char *filename; DIR *dir; int ret = 0; - dir = opendir(filename); - if (dir) { - struct file_entry { - struct list_head node; - char name[]; - }; - LIST_HEAD(files_list); - struct file_entry *fe, *fe_tmp; - struct dirent *i; - - /* sort files from directory into list */ - while ((i = readdir(dir)) != NULL) { - size_t len; - - if (i->d_name[0] == '.') - continue; - if (!config_filter(i->d_name)) - continue; - - len = strlen(i->d_name); - if (len < 6 || - (strcmp(&i->d_name[len-5], ".conf") != 0 && - strcmp(&i->d_name[len-6], ".alias") != 0)) - warn("All config files need .conf: %s/%s, " - "it will be ignored in a future release.\n", - filename, i->d_name); - fe = malloc(sizeof(struct file_entry) + len + 1); - if (fe == NULL) - continue; - strcpy(fe->name, i->d_name); - list_for_each_entry(fe_tmp, &files_list, node) - if (strcmp(fe_tmp->name, fe->name) >= 0) - break; - list_add_tail(&fe->node, &fe_tmp->node); - } - closedir(dir); - - /* parse list of files */ - list_for_each_entry_safe(fe, fe_tmp, &files_list, node) { - char *cfgfile; - - nofail_asprintf(&cfgfile, "%s/%s", filename, fe->name); - if (!parse_config_file(cfgfile, conf, - dump_only, removing)) - warn("Failed to open config file " - "%s: %s\n", fe->name, strerror(errno)); - free(cfgfile); - list_del(&fe->node); - free(fe); - } + va_start(filelist, removing); + + while ((filename = va_arg(filelist, char*))) { + dir = opendir(filename); + if (dir) { + struct file_entry { + struct list_head node; + char name[]; + }; + LIST_HEAD(files_list); + struct file_entry *fe, *fe_tmp; + struct dirent *i; + + /* sort files from directory into list */ + while ((i = readdir(dir)) != NULL) { + size_t len; + + if (i->d_name[0] == '.') + continue; + if (!config_filter(i->d_name)) + continue; + + len = strlen(i->d_name); + if (len < 6 || + (strcmp(&i->d_name[len-5], ".conf") != 0 && + strcmp(&i->d_name[len-6], ".alias") != 0)) + warn("All config files need .conf: %s/%s, " + "it will be ignored in a future release.\n", + filename, i->d_name); + fe = malloc(sizeof(struct file_entry) + len + 1); + if (fe == NULL) + continue; + strcpy(fe->name, i->d_name); + list_for_each_entry(fe_tmp, &files_list, node) + if (strcmp(fe_tmp->name, fe->name) >= 0) + break; + list_add_tail(&fe->node, &fe_tmp->node); + } + closedir(dir); + + /* parse list of files */ + list_for_each_entry_safe(fe, fe_tmp, &files_list, node) { + char *cfgfile; + + nofail_asprintf(&cfgfile, "%s/%s", filename, fe->name); + if (!parse_config_file(cfgfile, conf, + dump_only, removing)) + warn("Failed to open config file " + "%s: %s\n", fe->name, strerror(errno)); + free(cfgfile); + list_del(&fe->node); + free(fe); + } - ret = 1; - } else { - if (parse_config_file(filename, conf, dump_only, removing)) ret = 1; + } else { + if (parse_config_file(filename, conf, dump_only, removing)) + ret = 1; + } } + + va_end(filelist); return ret; } @@ -1117,7 +1123,8 @@ static void parse_toplevel_config(const char *filename, int removing) { if (filename) { - if (!parse_config_scan(filename, conf, dump_only, removing)) + if (!parse_config_scan(conf, dump_only, removing, filename, + NULL)) fatal("Failed to open config file %s: %s\n", filename, strerror(errno)); return; @@ -1130,7 +1137,9 @@ static void parse_toplevel_config(const char *filename, "all config files belong into /etc/modprobe.d/.\n"); /* default config */ - parse_config_scan("/etc/modprobe.d", conf, dump_only, removing); + parse_config_scan(conf, dump_only, removing, "/run/modprobe.d", + "/etc/modprobe.d", "/usr/local/lib/modprobe.d", + "/lib/modprobe.d", NULL); } /* Read possible module arguments from the kernel command line. */ -- 1.7.5.2
From d0ebce5559fd5d0354916e4372d1b327c282c678 Mon Sep 17 00:00:00 2001 From: Tom Gundersen <[email protected]> Date: Thu, 19 May 2011 23:44:02 +0200 Subject: [PATCH 1/2] modprobe: blacklist modules on kernel commandline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modules mod1, mod2 and mod3 can now be blacklisted by passing modprobe.blacklist=mod1,mod2,mod3 on the kernel command line. Cc: Kay Sievers <[email protected]> Cc: Aaron Griffin <[email protected]> Cc: Thomas Bächler <[email protected]> Signed-off-by: Tom Gundersen <[email protected]> --- modprobe.c | 17 +++++++++++++++-- 1 files changed, 15 insertions(+), 2 deletions(-) diff --git a/modprobe.c b/modprobe.c index 4721253..65de11a 100644 --- a/modprobe.c +++ b/modprobe.c @@ -1134,11 +1134,13 @@ static void parse_toplevel_config(const char *filename, } /* Read possible module arguments from the kernel command line. */ -static int parse_kcmdline(int dump_only, struct module_options **options) +static int parse_kcmdline(int dump_only, struct modprobe_conf *conf) { char *line; unsigned int linenum = 0; FILE *kcmdline; + struct module_options **options = &conf->options; + struct module_blacklist **blacklist = &conf->blacklist; kcmdline = fopen("/proc/cmdline", "r"); if (!kcmdline) @@ -1151,6 +1153,17 @@ static int parse_kcmdline(int dump_only, struct module_options **options) while ((arg = strsep_skipspace(&ptr, "\t ")) != NULL) { char *sep, *modname, *opt; + if (strstr(arg, "modprobe.blacklist=") != NULL) { + ptr = strchr(arg,'=') + 1; + + while ((modname = strsep(&ptr, ",")) != NULL) { + if (dump_only) + printf("blacklist %s\n", modname); + + *blacklist = add_blacklist(underscores(modname), *blacklist); + } + } + sep = strchr(arg, '.'); if (sep) { if (!strchr(sep, '=')) @@ -1836,7 +1849,7 @@ int main(int argc, char *argv[]) parse_toplevel_config(configname, &conf, dump_config, flags & mit_remove); /* Read module options from kernel command line */ - parse_kcmdline(dump_config, &conf.options); + parse_kcmdline(dump_config, &conf); if (dump_config) { char *aliasfilename, *symfilename; -- 1.7.5.2
