summaryrefslogtreecommitdiff
path: root/kmodloader.c
diff options
context:
space:
mode:
authorPavel Merzlyakov <pavel.merzlyakov@gmail.com>2019-03-18 12:53:01 +0200
committerStijn Tintel <stijn@linux-ipv6.be>2019-04-07 19:33:04 +0300
commit5130fa4d9c5d15d643506f906927b209d7690a83 (patch)
treebee1410a3ace9ec1faebe8b1fbeb333fdfa27742 /kmodloader.c
parenta782779552a0d68e3bb588e3039eb95da15ec7b0 (diff)
downloadubox-5130fa4d9c5d15d643506f906927b209d7690a83.tar.gz
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 <pavel.merzlyakov@gmail.com> Acked-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'kmodloader.c')
-rw-r--r--kmodloader.c39
1 files 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",