[OpenWrt-Devel] [PATCH] [ubox] kmodloader: fix and optimize loading of failed modules

pavel.merzlyakov at gmail.com pavel.merzlyakov at gmail.com
Mon Mar 18 06:53:01 EDT 2019


From: Pavel Merzlyakov <pavel.merzlyakov at gmail.com>

1) Restore functionality which was lost in commit 876c7f5b.
   Again at boot time kmodloader can load all modules (/etc/modules.d/*)
   even if dependency information is completely missing.
   This functionality is important in case of hidden dependency (not symbol dependency).
   For example, in kernel 4.4.60 is hidden dependency between nf_nat_ipv6 and nf_conntrack_ipv6.
   We can't load nf_nat_ipv6 before nf_conntrack_ipv6 and modinfo do not show this dependency.
   Two sequential load attempts of nf_nat_ipv6 may not be enough (in my case it's definitely not enough).
   nf_nat_ipv4 has a similar problem.

2) Reduce count of attempts to load failed modules.
   Now kmodloader try to load failed modules after all others are loaded.

main_loader: Count of failed and successful attempts to load nf_nat_ipv6.ko (kernel 4.4.60) depend on ubox version:
   COMMIT        FAILED      SUCCESSFUL     TOTAL
   128bc35f      53          1              54
   876c7f5b      2           0              2
   this          1           1              2

Signed-off-by: Pavel Merzlyakov <pavel.merzlyakov at gmail.com>
---
 kmodloader.c | 39 ++++++++++++++++++++++++---------------
 1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/kmodloader.c b/kmodloader.c
index 3196deb..e0f4e6d 100644
--- a/kmodloader.c
+++ b/kmodloader.c
@@ -615,12 +615,13 @@ static void load_moddeps(struct module *_m)
 	}
 }
 
-static int iterations = 0;
-static int load_modprobe(void)
+static int load_modprobe(bool allow_load_retry)
 {
-	int loaded, todo;
+	int loaded, skipped, failed;
 	struct module_node *mn;
 	struct module *m;
+	bool load_retry = false;
+	static bool first_iteration = true;
 
 	avl_for_each_element(&modules, mn, avl) {
 		if (mn->is_alias)
@@ -632,12 +633,13 @@ static int load_modprobe(void)
 
 	do {
 		loaded = 0;
-		todo = 0;
+		skipped = 0;
+		failed = 0;
 		avl_for_each_element(&modules, mn, avl) {
 			if (mn->is_alias)
 				continue;
 			m = mn->m;
-			if ((m->state == PROBE) && (!deps_available(m, 0)) && m->error < 2) {
+			if ((m->state == PROBE) && (!deps_available(m, 0)) && (!m->error || load_retry)) {
 				if (!insert_module(get_module_path(m->name), (m->opts) ? (m->opts) : (""))) {
 					m->state = LOADED;
 					m->error = 0;
@@ -645,17 +647,24 @@ static int load_modprobe(void)
 					continue;
 				}
 
-				if (++m->error > 1)
-					ULOG_ERR("failed to load %s\n", m->name);
+				m->error = 1;
 			}
 
-			if ((m->state == PROBE) || m->error)
-				todo++;
+			if (m->error)
+				failed++;
+			else if (m->state == PROBE)
+				skipped++;
 		}
-		iterations++;
-	} while (loaded);
 
-	return todo;
+		if (allow_load_retry) {
+			/* if we can't load anything else let's try to load failed modules */
+			load_retry = loaded ? (failed && !skipped) : (failed && !load_retry && !first_iteration);
+		}
+
+		first_iteration = false;
+	} while (loaded || load_retry);
+
+	return skipped + failed;
 }
 
 static int print_insmod_usage(void)
@@ -884,7 +893,7 @@ static int main_modprobe(int argc, char **argv)
 
 		m->state = PROBE;
 
-		fail = load_modprobe();
+		fail = load_modprobe(true);
 
 		if (fail) {
 			ULOG_ERR("%d module%s could not be probed\n",
@@ -972,14 +981,14 @@ static int main_loader(int argc, char **argv)
 				m->opts = strdup(opts);
 			m->state = PROBE;
 			if (basename(gl.gl_pathv[j])[0] - '0' <= 9)
-				load_modprobe();
+				load_modprobe(false);
 
 		}
 		free(mod);
 		fclose(fp);
 	}
 
-	fail = load_modprobe();
+	fail = load_modprobe(true);
 
 	if (fail) {
 		ULOG_ERR("%d module%s could not be probed\n",
-- 
2.21.0


_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list