modalias.prov: speed up, explain and make more correct combining code

The time to run on tests/* data decreased from 34.517s to 30.201s.

Do not allow combining of any glob meta characters, either in first
or second line.

The code is still buggy, it may attempt to combine
    modalias(abc[def]123)
    modalias(abc[dXf]123)
into
    modalias(abc[d[eX]f]123)
(presumably there won't be any such cases in real modules, but still).

Eliminate "| head -n1" - do it with bash string ops.

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
This commit is contained in:
Denys Vlasenko 2023-05-07 17:43:27 +02:00
parent c39c0162a0
commit 35e1f2fc73

View File

@ -51,7 +51,7 @@ print_modaliases() {
# replace with # replace with
# modalias(pci:v0000168Cd0000002[3479]sv*sd*bc*sc*i*) # modalias(pci:v0000168Cd0000002[3479]sv*sd*bc*sc*i*)
combine_modaliases() { combine_modaliases() {
local unused_len tag class variants="" pos="" n local unused_len tag class variants="" pos="" n end xc
# Due to set -e, we can exit with exitcode 1 on read EOF # Due to set -e, we can exit with exitcode 1 on read EOF
# and this makes our caller think we failed. "|| return 0" prevents this: # and this makes our caller think we failed. "|| return 0" prevents this:
@ -59,26 +59,44 @@ combine_modaliases() {
# For each line after the first... # For each line after the first...
while IFS=' ' read unused_len tag; do while IFS=' ' read unused_len tag; do
# For each char in prev line... if [ -z "$pos" ]; then
for ((n=0; n<${#class}; n++)); do # 2nd line: after "modalias(" prefix, for each char in prev line...
# If aaaNbbb = aaaMbbb and N isn't "*" n=9
# and N's position is the same as last time... end=${#class}
if [ "*" != "${class:n:1}" -a \ else
"${class:0:n}" = "${tag:0:n}" -a \ # 3rd+ lines: only check the char at the same position
"${class:n+1}" = "${tag:n+1}" ] && n=$pos
[ -z "$pos" -o "$n" = "$pos" ]; then end=$((pos + 1))
# Add M (and maybe N) to $variants, go to next line fi
variants="${variants:-${class:n:1}}${tag:n:1}" # Search for aaaNbbb,aaaMbbb line pair, where N and M chars differ.
pos=$n # sort -u guarantees there are no identical line pairs.
# We assume that lines will not differ only in " = version" suffix.
for ((; n < $end; n++)); do
if [ "${class:0:n}" != "${tag:0:n}" ]; then
# the prefixes already aren't the same: break
n=$end
break break
fi fi
# If suffixes differ, go to next char
[ x"${class:n+1}" != x"${tag:n+1}" ] && continue
# aaaNbbb = aaaMbbb. If N and M aren't special...
xc=x"${class:n:1}"
[ x"[" = "$xc" -o x"]" = "$xc" ] && continue
[ x"?" = "$xc" -o x"*" = "$xc" ] && continue
xc=x"${tag:n:1}"
[ x"[" = "$xc" -o x"]" = "$xc" ] && continue
[ x"?" = "$xc" -o x"*" = "$xc" ] && continue
# Add M (and maybe N) to $variants, go to next line
variants="${variants:-${class:n:1}}${tag:n:1}"
pos=$n
break
done done
if [ $n -eq ${#class} ]; then if [ $n -eq $end ]; then
# This line is not mergeable, print collected merged line # This line is not mergeable with the previous one(s),
# and reset the state # print collected merged line and reset the state
print_modaliases "$class" "$variants" "$pos" print_modaliases "$class" "$variants" "$pos"
variants= variants=""
pos= pos=""
class=$tag class=$tag
fi fi
done done
@ -87,10 +105,12 @@ combine_modaliases() {
} }
for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do
# | head -n1 because some modules have *two* version tags. *cough*b44*cough* modver=$(/sbin/modinfo -F version "$module")
modver=$(/sbin/modinfo -F version "$module"| head -n1) # delete possible extra lines because some modules have *two* version tags. *cough*b44*cough*
modver=${modver%%$'\n'*} # using $'' bashism, avoid running "head -n1" process
# replace any strange chars with underscores.
modver=${modver//[^0-9a-zA-Z._]/_} modver=${modver//[^0-9a-zA-Z._]/_}
# only add version tag if it has a version # only add version tag if it indeed has a version
[ -z "$modver" ] || modver=" = $modver" [ -z "$modver" ] || modver=" = $modver"
/sbin/modinfo -F alias "$module" \ /sbin/modinfo -F alias "$module" \