FS#10972 - rc.conf blacklist behaves unintuitively

Attached to Project: Arch Linux
Opened by Thomas Bächler (brain0) - Monday, 21 July 2008, 21:42 GMT
Last edited by Thomas Bächler (brain0) - Friday, 12 September 2008, 21:30 GMT
Task Type Bug Report
Category Packages: Core
Status Closed
Assigned To Tobias Powalowski (tpowa)
Aaron Griffin (phrakture)
Thomas Bächler (brain0)
Architecture All
Severity Medium
Priority Normal
Reported Version None
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 0
Private No

Details

Sometimes, there is more than one module for a specific device and one wants to blacklist one and load the other. When you blacklist a module, not only the module, but instead the whole device is blacklisted, meaning that the module loading is aborted. This is undesirable.
This task depends upon

Closed by  Thomas Bächler (brain0)
Friday, 12 September 2008, 21:30 GMT
Reason for closing:  Implemented
Comment by Aaron Griffin (phrakture) - Monday, 21 July 2008, 23:58 GMT
Can you give me an example of this? It shouldn't happen that way, considering the blacklisting script uses textual matches, and doesn't check anything regarding devices at all.

Comment by Thomas Bächler (brain0) - Tuesday, 22 July 2008, 07:52 GMT
Look at the code: It resolves a modalias to all its modules and their dependencies, and as soon as one of the modules matches the blacklist, it exits with exit 1, thus blacklisting the whole alias.

A correct way would be to first resolve an alias to all its modules (no dependencies). Then for each module resolve the dependencies and check against the blacklist.

A popular example would be: blacklisting 8139cp will blacklist 8139too as well. Blacklisting piix will blacklist ata_piix as well.
Comment by Aaron Griffin (phrakture) - Tuesday, 22 July 2008, 15:56 GMT
That behavior is correct. I'm still a tad unclear here, so can you give me an example where you experienced this?

If I blacklist 8139cp, there is no way that will match 8139too, because they are not dependencies of each other.

$ modprobe --show-depends 8139cp
insmod /lib/modules/2.6.20-15-server/kernel/drivers/net/mii.ko
insmod /lib/modules/2.6.20-15-server/kernel/drivers/net/8139cp.ko

$ modprobe --show-depends 8139too
insmod /lib/modules/2.6.20-15-server/kernel/drivers/net/mii.ko
insmod /lib/modules/2.6.20-15-server/kernel/drivers/net/8139too.ko

In this case, if I were to blacklist mii, then it would blacklist both. But blacklisting one will not blacklist the other.
Comment by Thomas Bächler (brain0) - Tuesday, 22 July 2008, 17:28 GMT
An excerpt from load-modules.sh, with additional comments::

if [ -n "$BLACKLIST" ]; then
#
# In this line, all matches for a certain alias are found including dependencies.
# There may be more than one match for a certain alias if the alias is listed
# in more than one driver. So this may, for example, include 8139too, 8139cp
# and all of their dependencies. One only wants to load exactly one of those two
# including only the dependencies of this module.
#
depmods="$(/sbin/modprobe -i --show-depends $1)"
if [ $? -ne 0 ]; then
/usr/bin/logger -p info "cannot find module $1"
exit 1
fi

#sanitize our module names
depmods="$(echo "$depmods" | sed \
-e "s#^insmod /lib.*/\(.*\)\.ko.*#\1#g" \
-e 's|-|_|g')"

#
# Here we iterate over all modules we found above. If only one of them is blacklisted,
# we exit immediately, and thus don't load any modules. This was originally intended to
# blacklist a module completely, so it isn't autoloaded as a dependency of another module.
# In our above example, this list contains both 8139too and 8139cp, so if either of them
# are blacklisted, we exit and load nothing. This means that the other module is effectively
# blacklisted as well.
#
for mod in $depmods; do
if echo $BLACKLIST | /bin/grep "\<$mod\>" 2>&1 >/dev/null; then
/usr/bin/logger -p info "udev load-modules: $1 is blacklisted"
exit 1
fi
done
fi
/sbin/modprobe $1
Comment by Aaron Griffin (phrakture) - Tuesday, 22 July 2008, 18:12 GMT
The problem here is that it is impossible to just "resolve an alias" with no dependencies. If you can figure that out in a quick manner that doesn't butcher our udev performance, I will gladly incorporate the change. For now I am completely fine with recommending "MODULES=(!8139cp 8139too)" syntax, we'd just have to document this caveat.

Resolving an alias is not possible at the moment with m-i-t. If you'd like to rip out the code that does the alias lookup, you're welcome to, but in that case I'd recommend rewriting the whole load-modules chunk as part of that.

In pseudo-code:
all-modules = resolve-alias $1
for module in $all-modules:
...if is-blacklisted $module:
......remove-from-list $module $all-modules
modprobe $all-modules #remaining modules should be blacklisted
Comment by Thomas Bächler (brain0) - Tuesday, 22 July 2008, 18:31 GMT
Almost exactly what I thought. For each module, all dependencies should be checked as well:

In pseudo-code:
all-modules = resolve-alias $1
for module in $all-modules:
...module-depends = depends $module
...for m in $module-depends:
......if is-blacklisted $module:
.........remove-from-list $module $all-modules
.........break
modprobe $all-modules #remaining modules should be blacklisted

I wrote some C++ code that would find the aliases (basically, m-i-t uses fnmatch on each line in modules.dep). I could make it C code easily, either standalone or as a patch to modprobe. Any preference?
Comment by Aaron Griffin (phrakture) - Tuesday, 22 July 2008, 18:41 GMT
I'd prefer standalone, but if you think that this actually works as a replacement blacklist scheme for modprobe, we can always submit it upstream.

Personally, I think modprobe's blacklisting sucks hard, so maybe we can replace the way it works, convince the lead dev, AND do away with load-modules.sh in one fell swoop.
Comment by Thomas Bächler (brain0) - Tuesday, 22 July 2008, 18:47 GMT
The only thing I'd patch into modprobe would be a --resolve-alias parameter, which does the same as --show-depends, only without resolving dependencies (and without resolving full module paths, only names).
Comment by Thomas Bächler (brain0) - Sunday, 31 August 2008, 20:46 GMT
I completely forgot about this, here is a short modalias-resolver (should probably include some error checking, so it doesn't segfault, but the concept is there).

This way we can create a working blacklist like in my last pseudocode example. The problem is still that modules.dep only contains module with their full paths. I shall hack this together tomorrow evening.

Loading...