[PATCH] depmod: initial support for split module directories

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

 



Traditionally, kernel modules lived only in /lib/modules/<kernelversion>. In
the past, we added support for prioritized "update" directories within this
hierarchy so that distributions and their users could insert updates to
existing drivers and have those take precendence. But there are times when
it is also necessary to search a completely different (and kernel specific)
directory, perhaps on a different filesystem, for module updates.

This patch introduces a new depmod.conf configuration option called
"path", which can be used in combination with the existing "search"
option to specify which directories will be searched before building
the kernel specific modules.dep and modules.dep.bin files. Paths are
searched in the order given, with preference within the path determined
by the value of the "search" option, allowing flexible configurations.

Signed-off-by: Jon Masters <jcm@xxxxxxxxxxxxxx>
---
 depmod.c |  208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 184 insertions(+), 24 deletions(-)

diff --git a/depmod.c b/depmod.c
index 5b90b3a..2e58d14 100644
--- a/depmod.c
+++ b/depmod.c
@@ -36,6 +36,10 @@
 #define MODULE_DIR "/lib/modules/"
 #endif
 
+#ifndef CURRENT_KERNEL_KEY
+#define CURRENT_KERNEL_KEY "current-kernel"
+#endif
+
 #ifndef MODULE_BUILTIN_KEY
 #define MODULE_BUILTIN_KEY "built-in"
 #endif
@@ -49,6 +53,16 @@ struct module_overrides
 	char *modfile;
 };
 
+struct module_path
+{
+	/* Next path */
+	struct module_path *next;
+
+	/* module path */
+	char *path;
+	size_t len;
+};
+
 struct module_search
 {
 	/* Next search */
@@ -621,21 +635,28 @@ static struct module *grab_dir(const char *dirname,
 	return next;
 }
 
-static struct module *grab_basedir(const char *dirname,
+static struct module *grab_basedir(struct module_path *modpaths,
 				   struct module_search *search,
 				   struct module_overrides *overrides)
 {
 	DIR *dir;
 	struct module *list;
+	struct module_path *mod_path;
 
-	dir = opendir(dirname);
-	if (!dir) {
-		warn("Couldn't open directory %s: %s\n",
-		     dirname, strerror(errno));
-		return NULL;
+	for (mod_path = modpaths; mod_path != NULL;
+	     mod_path = mod_path->next) {
+	
+		dir = opendir(mod_path->path);
+		if (!dir) {
+			warn("Couldn't open directory %s: %s\n",
+		    	 mod_path->path, strerror(errno));
+			continue;
+		} else {
+			list = grab_dir(mod_path->path, dir, list, do_module,
+					search, overrides);
+			closedir(dir);
+		}
 	}
-	list = grab_dir(dirname, dir, NULL, do_module, search, overrides);
-	closedir(dir);
 
 	return list;
 }
@@ -1030,6 +1051,22 @@ static char *strsep_skipspace(char **string, char *delim)
 	return strsep(string, delim);
 }
 
+static struct module_path *add_path(const char *path,
+				    size_t len,
+				    struct module_path *paths)
+{
+
+	struct module_path *new;
+	
+	new = NOFAIL(malloc(sizeof(*new)));
+	new->path = NOFAIL(strdup(path));
+	new->len = len;
+	new->next = paths;
+
+	return new;
+	
+}
+
 static struct module_search *add_search(const char *search_path,
 					size_t len,
 					struct module_search *search)
@@ -1046,6 +1083,42 @@ static struct module_search *add_search(const char *search_path,
 	
 }
 
+static struct module_search *add_search_tail(const char *search_path,
+					     size_t len,
+					     struct module_search *search)
+{
+
+	struct module_search *new;
+	struct module_search *last;
+
+	new = NOFAIL(malloc(sizeof(*new)));
+	new->search_path = NOFAIL(strdup(search_path));
+	new->len = len;
+	new->next = NULL;
+
+	if (!search) {
+		search = new;
+	} else {
+		for (last = search; (last != NULL) && (last->next != NULL);
+	     	     last = last->next);
+		last->next = new;
+	}
+
+	return search;
+}
+
+struct module_search *free_search(struct module_search *search)
+{
+	if (search) {
+		free_search(search->next);
+		free(search->search_path);
+		free(search);
+		search = NULL;
+	}
+
+	return NULL;
+}
+
 static struct module_overrides *add_override(const char *modfile,
 					     struct module_overrides *overrides)
 {
@@ -1063,12 +1136,14 @@ static struct module_overrides *add_override(const char *modfile,
 static int parse_config_scan(const char *filename,
 			     const char *basedir,
 			     const char *kernelversion,
+			     struct module_path **modpaths,
 			     struct module_search **search,
 			     struct module_overrides **overrides);
 
 static int parse_config_file(const char *filename,
 			     const char *basedir,
 			     const char *kernelversion,
+			     struct module_path **modpaths,
 			     struct module_search **search,
 			     struct module_overrides **overrides)
 {
@@ -1095,7 +1170,30 @@ static int parse_config_file(const char *filename,
 			continue;
 		}
 
-		if (streq(cmd, "search")) {
+		if (streq(cmd, "path")) {
+			char *mod_path, *sstr;
+
+			while ((mod_path = strsep_skipspace(&ptr, "\t "))) {
+
+				if ((sstr = strstr(mod_path,
+						 CURRENT_KERNEL_KEY))) {
+					char *new_path;
+
+					sstr[0] = '\0';
+					nofail_asprintf(&new_path, "%s%s%s",
+					     mod_path,
+					     kernelversion,
+					     &sstr[strlen(CURRENT_KERNEL_KEY)]);
+					*modpaths = add_path(new_path,
+							     strlen(new_path),
+							     *modpaths);
+				} else {
+					*modpaths = add_path(mod_path,
+							     strlen(mod_path),
+							     *modpaths);
+				}
+			}
+		} else if (streq(cmd, "search")) {
 			char *search_path;
 			
 			while ((search_path = strsep_skipspace(&ptr, "\t "))) {
@@ -1108,8 +1206,8 @@ static int parse_config_file(const char *filename,
 							     0, *search);
 					continue;
 				}
-				nofail_asprintf(&dirname, "%s%s%s/%s", basedir,
-					MODULE_DIR, kernelversion, search_path);
+				nofail_asprintf(&dirname, "%s",
+						search_path);
 				len = strlen(dirname);
 				*search = add_search(dirname, len, *search);
 				free(dirname);
@@ -1142,9 +1240,12 @@ static int parse_config_file(const char *filename,
 					warn("\"include /etc/depmod.d\" is "
 					     "the default, ignored\n");
 				} else {
-					if (!parse_config_scan(newfilename, basedir,
+					if (!parse_config_scan(newfilename,
+							       basedir,
 							       kernelversion,
-							       search, overrides))
+							       modpaths,
+							       search,
+							       overrides))
 					warn("Failed to open included"
 					     " config file %s: %s\n",
 					     newfilename, strerror(errno));
@@ -1176,6 +1277,7 @@ static int parse_config_file(const char *filename,
 static int parse_config_scan(const char *filename,
 			     const char *basedir,
 			     const char *kernelversion,
+			     struct module_path **modpaths,
 			     struct module_search **search,
 			     struct module_overrides **overrides)
 {
@@ -1223,7 +1325,7 @@ static int parse_config_scan(const char *filename,
 
 			nofail_asprintf(&cfgfile, "%s/%s", filename, fe->name);
 			if (!parse_config_file(cfgfile, basedir, kernelversion,
-					       search, overrides))
+					       modpaths, search, overrides))
 				warn("Failed to open config file "
 				     "%s: %s\n", fe->name, strerror(errno));
 			free(cfgfile);
@@ -1233,8 +1335,8 @@ static int parse_config_scan(const char *filename,
 
 		ret = 1;
 	} else {
-		if (parse_config_file(filename, basedir, kernelversion, search,
-				      overrides))
+		if (parse_config_file(filename, basedir, kernelversion,
+				      modpaths, search, overrides))
 			ret = 1;
 	}
 
@@ -1244,12 +1346,13 @@ static int parse_config_scan(const char *filename,
 static void parse_toplevel_config(const char *filename,
 				  const char *basedir,
 				  const char *kernelversion,
+				  struct module_path **modpaths,
 				  struct module_search **search,
 				  struct module_overrides **overrides)
 {
 	if (filename) {
-		if (!parse_config_scan(filename, basedir, kernelversion, search,
-				 overrides))
+		if (!parse_config_scan(filename, basedir, kernelversion,
+				       modpaths, search, overrides))
 			fatal("Failed to open config file %s: %s\n",
 			      filename, strerror(errno));
 		return;
@@ -1257,19 +1360,59 @@ static void parse_toplevel_config(const char *filename,
 
 	/* deprecated config file */
 	if (parse_config_file("/etc/depmod.conf", basedir, kernelversion,
-			      search, overrides) > 0)
+			      modpaths, search, overrides) > 0)
 		warn("Deprecated config file /etc/depmod.conf, "
 		      "all config files belong into /etc/depmod.d/.\n");
 
 	/* default config */
 	parse_config_scan("/etc/depmod.d", basedir, kernelversion,
-			  search, overrides);
+			  modpaths, search, overrides);
+}
+
+static struct module_search *expand_search_paths(struct module_search *search,
+					  struct module_path *modpaths)
+{
+	struct module_path *mod_path;
+	struct module_search *new_search, *tmp_search;
+	char *new_path;
+	ssize_t len;
+	int done_builtin = 0;
+
+	for (tmp_search = search; tmp_search != NULL;
+	     tmp_search = tmp_search->next) {
+		for (mod_path = modpaths; mod_path != NULL;
+		     mod_path = mod_path->next) {
+			
+			if (streq(tmp_search->search_path,
+				  MODULE_BUILTIN_KEY)) {
+				if (!done_builtin) {
+				done_builtin = 1;
+				new_search = add_search_tail(MODULE_BUILTIN_KEY,
+							     0, new_search);
+				}
+			} else {
+				nofail_asprintf(&new_path, "%s/%s",
+						mod_path->path,
+						tmp_search->search_path);
+				len = strlen(new_path);
+				new_search = add_search_tail(new_path, len,
+							     new_search);
+				free(new_path);
+			}
+		}
+	}
+
+	/* free old list */
+	search = free_search(search);
+
+	return new_search;
 }
 
 /* Local to main, but not freed on exit.  Keep valgrind quiet. */
 struct module *list = NULL;
 struct module_search *search = NULL;
 struct module_overrides *overrides = NULL;
+struct module_path *modpaths = NULL;
 
 int main(int argc, char *argv[])
 {
@@ -1375,7 +1518,22 @@ int main(int argc, char *argv[])
 		all = 1;
 	}
 
-	parse_toplevel_config(config, basedir, version, &search, &overrides);
+	parse_toplevel_config(config, basedir, version,
+			      &modpaths, &search, &overrides);
+
+	/* For backward compatibility add the current kernel to the head of
+         * the path list here. But only if no "path" option specified.
+         */
+	if (!modpaths) {
+		char *mod_path;
+		size_t len;
+
+		nofail_asprintf(&mod_path, "%s%s%s", basedir,
+				MODULE_DIR, version);
+		
+		len = strlen(mod_path);
+		modpaths = add_path(mod_path, len, modpaths);
+	}
 
 	/* For backward compatibility add "updates" to the head of the search
 	 * list here. But only if there was no "search" option specified.
@@ -1384,11 +1542,13 @@ int main(int argc, char *argv[])
 		char *dirname;
 		size_t len;
 
-		nofail_asprintf(&dirname, "%s%s%s/updates", basedir,
-				MODULE_DIR, version);
+		nofail_asprintf(&dirname, "updates");
 		len = strlen(dirname);
 		search = add_search(dirname, len, search);
 	}
+
+	search = expand_search_paths(search, modpaths);
+
 	if (!all) {
 		/* Do command line args. */
 		for (opt = optind; opt < argc; opt++) {
@@ -1407,7 +1567,7 @@ int main(int argc, char *argv[])
 			list = new;
 		}
 	} else {
-		list = grab_basedir(dirname,search,overrides);
+		list = grab_basedir(modpaths,search,overrides);
 	}
 	list = sort_modules(dirname,list);
 	list = parse_modules(list);
-- 
1.6.0.6

--
To unsubscribe from this list: send the line "unsubscribe linux-modules" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux