From 35e1f2fc7324fd7d656f55395f87646b1f558105 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 7 May 2023 17:43:27 +0200 Subject: [PATCH] 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 --- modalias.prov | 60 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/modalias.prov b/modalias.prov index f362fd3..525e1df 100755 --- a/modalias.prov +++ b/modalias.prov @@ -51,7 +51,7 @@ print_modaliases() { # replace with # modalias(pci:v0000168Cd0000002[3479]sv*sd*bc*sc*i*) 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 # and this makes our caller think we failed. "|| return 0" prevents this: @@ -59,26 +59,44 @@ combine_modaliases() { # For each line after the first... while IFS=' ' read unused_len tag; do - # For each char in prev line... - for ((n=0; n<${#class}; n++)); do - # If aaaNbbb = aaaMbbb and N isn't "*" - # and N's position is the same as last time... - if [ "*" != "${class:n:1}" -a \ - "${class:0:n}" = "${tag:0:n}" -a \ - "${class:n+1}" = "${tag:n+1}" ] && - [ -z "$pos" -o "$n" = "$pos" ]; then - # Add M (and maybe N) to $variants, go to next line - variants="${variants:-${class:n:1}}${tag:n:1}" - pos=$n + if [ -z "$pos" ]; then + # 2nd line: after "modalias(" prefix, for each char in prev line... + n=9 + end=${#class} + else + # 3rd+ lines: only check the char at the same position + n=$pos + end=$((pos + 1)) + fi + # Search for aaaNbbb,aaaMbbb line pair, where N and M chars differ. + # 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 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 - if [ $n -eq ${#class} ]; then - # This line is not mergeable, print collected merged line - # and reset the state + if [ $n -eq $end ]; then + # This line is not mergeable with the previous one(s), + # print collected merged line and reset the state print_modaliases "$class" "$variants" "$pos" - variants= - pos= + variants="" + pos="" class=$tag fi done @@ -87,10 +105,12 @@ combine_modaliases() { } 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"| head -n1) + modver=$(/sbin/modinfo -F version "$module") + # 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._]/_} - # only add version tag if it has a version + # only add version tag if it indeed has a version [ -z "$modver" ] || modver=" = $modver" /sbin/modinfo -F alias "$module" \