From 5130fa4d9c5d15d643506f906927b209d7690a83 Mon Sep 17 00:00:00 2001 From: Pavel Merzlyakov Date: Mon, 18 Mar 2019 12:53:01 +0200 Subject: [PATCH] kmodloader: fix and optimize loading of failed modules 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 Acked-by: Jo-Philipp Wich --- kmodloader.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/kmodloader.c b/kmodloader.c index 2e920ef..6a7d7c1 100644 --- a/kmodloader.c +++ b/kmodloader.c @@ -617,12 +617,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) @@ -634,12 +635,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; @@ -647,17 +649,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) @@ -886,7 +895,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", @@ -974,14 +983,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.30.2