modprobe: break dependency loop by checking if module is loaded
authorLucas De Marchi <lucas.demarchi@profusion.mobi>
Wed, 11 Jan 2012 20:29:55 +0000 (18:29 -0200)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Wed, 11 Jan 2012 20:29:55 +0000 (18:29 -0200)
modprobe doesn't have support for handling dependency loop. That happens
with poorly written softdeps that can introduce a loop. We must deal
with them like it's being done in libkmod.

However, we can break a dependency loop when the dependency was already
inserted. This commit fixes this issue, that happens in the following
scenario:

dependencies:
-------------

modA:
modB: modA
modC: modA

config:

softdep modA post: modB modC

This creates the following loop:

modA
    inserted ok
    handle post-soft-deps of modA -> modB modC
        modB
            handle dependencies of modB -> modA
                modA is already inserted
                    handle post-soft-deps of modA -> modB modC

And so on and so forth.

Now we break the loop by checking if module is already inserted, before
handling it. Thus this gives us:

modA
    inserted ok
    handle post-soft-deps of modA -> modB modC
        modB
            handle dependencies of modB -> modA
                modA is already inserted
            inserted ok
        modC
            handle dependencies of modC -> modA
                modA is already inserted
            inserted ok

tools/kmod-modprobe.c

index 35224bb..6ed605c 100644 (file)
@@ -620,6 +620,14 @@ static int insmod_do_deps_list(struct kmod_module *parent,
                const char *cmd, *opts, *dmname = kmod_module_get_name(dm);
                int r;
 
+               if (!ignore_loaded) {
+                       int state = kmod_module_get_initstate(dm);
+                       if (state == KMOD_MODULE_LIVE ||
+                                       state == KMOD_MODULE_COMING ||
+                                       state == KMOD_MODULE_BUILTIN)
+                               continue;
+               }
+
                r = insmod_do_dependencies(dm);
                if (r < 0) {
                        WRN("could not insert dependencies of '%s': %s\n",
@@ -641,14 +649,6 @@ static int insmod_do_deps_list(struct kmod_module *parent,
                        goto dep_error;
                }
 
-               if (!ignore_loaded) {
-                       int state = kmod_module_get_initstate(dm);
-                       if (state == KMOD_MODULE_LIVE ||
-                                       state == KMOD_MODULE_COMING ||
-                                       state == KMOD_MODULE_BUILTIN)
-                               goto dep_done;
-               }
-
                cmd = kmod_module_get_install_commands(dm);
                if (cmd) {
                        r = command_do(dm, "install", cmd, NULL);