Provide a function to dump the index files to a certain fd. It could be
more optimized (particularly the functions to dump the index that were
copied and pasted from m-i-t), but it seems like the only user of it is
'modprobe -c', used for debugging purposes. So, keep it as is.
Config iterators are useful to get each configuration list, remember its
type and how to get their key/value pair.
softdeps don't have the value yet, because they are stored as string
vectors.
Just like the module insertion, module removal is remade.
The dependencies line that comes from modules.dep already contains all
the dependencies necessary to remove that module. Therefore modprobe
doesn't have to do the recursion between the modules in order to remove
it. All we have to do is to remove in order:
For the module being removed:
----------------------------
1. softdeps (in reverse order)
2. deps (in reverse order)
3. module
4. postdeps (in reverse order)
For any of the dependencies:
----------------------------
1. softdeps (in reverse order)
2. module
3. softdeps (in reverse order)
The dependencies line that comes from modules.dep already contains all
the dependencies necessary to insert that module. Therefore modprobe
doesn't have to do the recursion between the modules in order to load a
module. All we have to do is to load in order:
For the module being loaded:
----------------------------
1. softdeps
2. deps
3. module
4. postdeps
For any of the dependencies:
----------------------------
1. softdeps
2. module
3. softdeps
Now with './tools/modprobe --show-depends ahci' (ahci is builtin) we have the following
output:
$ ./tools/modprobe --show-depends ahci
builtin ahci
Just like modprobe from m-i-t. Previously we had:
$ ./tools/modprobe --show-depends ahci
FATAL: Module ahci not found.
Deleting modules (we have found replacements) invalidates the indices
because the array collapses removed elements, hitting the assertion.
Since we don't make use of the array until the sorting step, build it from
the modules_by_name hash instead.
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
In line with m-i-t's behavior, we should check to see if each module is:
- loaded
- has any holders
- has a 0 refcnt
Detecting any of these lets us provide a more useful message than the
kernel's EPERM response to delete_module(2).
Additionally, alter the main loop behavior to avoid exiting early on the
first error.