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.
Symlinking tools to kmod doesn't work because argv[0] is not the name of
the symlink, but rather 'kmod' (since libtool's wrapper script calls the
tools/.libs/kmod directly)
Now we create another binary kmod-nolib that is statically linked to
libkmod so we can call the binary directly and do not worry about
LD_LIBRARY_PATH.
demarchi> scenario is the following:
demarchi> modA depends on modB and modC
demarchi> if there's a race when trying to insert a dependency of a module, say
modB, it will stop loading all the modules
demarchi> it should check by "module already loaded error"
demarchi> like it does for modA
Module aliases can be bigger than NAME_MAX. So, replace with PATH_MAX
that is bigger enough to hold them.
Technically in some places NAME_MAX would be sufficient (those using
module names only), but they use functions that can be called with
alias. So increase the buffers in these cases to PATH_MAX too.
We cannot create a kmod_module for existing module name, it will fail
due existing in the hash table "modules_by_name".
To avoid it, we first delete the existing module, if lower priority,
then add the new one.
kmod_module_new_from_path() is called only when the former module was
deleted or does not exist.
This code was never tested, my bad!
* the prefix should be ignored, as it is not stored in cfg_search/override.
* baselen should not include '/'.
* search length should not include '\0'.
* override path should not include cfg->dirname prefix.
note that the hash algorithm is different thus the output order will
be different as well.
to compare the outputs, sort the files:
depmod -n | grep '^alias symbol:' | sort > /tmp/orig
kmod-depmod -n | grep '^alias symbol:' | sort > /tmp/new
diff /tmp/orig /tmp/new
this is the initial code for depmod, it should:
* use configuration from /run/depmod.d, /etc/depmod.d, /lib/depmod.d
* respect overrides and searches
* resolve symbols and dependencies
* break circular dependencies (dependency loops)
* --errsyms: print out modules with unresolved symbols and incorrect crc
* --symbol-prefix: respect architecture symbol prefix
it will not:
* --quick: does not do quick mode
* --warn: does not warn on duplicates
* --filesyms: does not load symbols from map file
* --symvers: does not load symbol versions from map file
* dump files: does not dump any files at the moment.
it is highly untested, then I appreciate your help with real world
scenarios using overrides and searches. To get output run with -vvvvvv.
next version should fill in the gaps and at least generate the files
If using libtool 2.4.2, running the script generated by libtool will not
work because libtool changes argv[0] to lt-progname.
To test this is necessary to either fix the installed
build-aux/ltmain.sh file or run the binary directly like in:
$ export LD_LIBRARY_PATH=$PWD/libkmod/.libs/
$ ./tools/.libs/kmod help
Commit "e5e2a68 kmod_modprobe: properly handle install/remove commands"
introduced a regression that, while it worked for install/remove
commands, it ceased to work for normal module names. Move the check for
whether it's a install command or a module so both cases work.
Handle install/remove commands just like modprobe does. Test configure
file:
install installme echo "this is a install message"
remove removeme echo "this is a remove message"
Tests:
$ ./tools/kmod-modprobe installme
this is a install message
$ ./tools/kmod-modprobe -r removeme
this is a remove message
$ ./tools/kmod-modprobe removeme
FATAL: Module removeme not found.
./tools/kmod-modprobe -r installme
FATAL: Module installme not found.
The check for remove/install commands must be before the ignore_loaded
check because we will actually run something instead of
removing/inserting a module and the modname might not correspond to a
real module. Otherwise a fake module like "remove removeme echo 'bla'"
would not work.
This also keeps compatibility with modprobe.
Implement soft dependencies in a way similar to module-init-tools
modprobe. Unlike regular dependencies they are allowed to fail
inserting or removing.
The rmmod version walks the lists in reverse order, also doing post
before and pre later.
try to mimic original module-init-tools' modprobe as much as possible,
but this exposed some missing features in libkmod, these are now
listed in TODO.