diff --git a/SOURCES/weak-modules b/SOURCES/weak-modules index bc390f9..4df7642 100644 --- a/SOURCES/weak-modules +++ b/SOURCES/weak-modules @@ -3,15 +3,6 @@ # weak-modules - determine which modules are kABI compatible with installed # kernels and set up the symlinks in /lib/*/weak-updates. # -# This is an updated version of the script which doesn't support -# multiple installation of the same out-of-tree module (stored in the -# 'extra' subdirectory) for multiple kernels. This assumption is -# supposed to be verified at the rpm level of the packages delivering -# these modules. There are some checks for this assumption, however we -# really don't solve this situation. This limitation allows for a much -# simpler version of the script. Previous version tried to work in this -# case but was incorrect in some cases. - unset LANG LC_ALL LC_COLLATE tmpdir=$(mktemp -td ${0##*/}.XXXXXX) @@ -32,6 +23,14 @@ declare -A weak_modules_before declare -A groups declare -A grouped_modules +# output of validate_weak_links, one iteration +# short_name -> path +declare -A compatible_modules + +# state for update_modules_for_krel (needed for add_kernel case) +# short_name -> path +declare -A installed_modules + # doit: # A wrapper used whenever we're going to perform a real operation. doit() { @@ -464,7 +463,7 @@ prepare_sandbox() { #config echo "search external extra built-in weak-updates" >"$conf" - echo "external $krel $dir" >>"$conf" + echo "external * $dir" >>"$conf" depmod="$depmod_orig -C $conf" } @@ -491,6 +490,29 @@ finish_sandbox() { cp -R "${override}"/* "$wa_dir" 2>/dev/null } +# discard_installed: +# remove installed_modules[] from modules[] +discard_installed() +{ + local short_name + + for m in "${!modules[@]}"; do + short_name="$(module_short_name "${modules[$m]}")" + + [[ -z "${installed_modules[$short_name]}" ]] && continue + + unset "modules[$m]" + done +} + +# update_installed: +# add compatible_modules[] to installed_modules[] +update_installed() +{ + for m in "${!compatible_modules[@]}"; do + installed_modules[$m]="${compatible_modules[$m]}" + done +} #### Main logic @@ -506,6 +528,7 @@ finish_sandbox() { # the given kernel) # - check the state after validation to produce needed messages # and trigger initrd regeneration if the list changed. +# update_modules_for_krel() { local krel="$1" local func="$2" @@ -517,12 +540,24 @@ update_modules_for_krel() { global_link_state_save $krel + # remove already installed from modules[] + discard_installed + + # do not run heavy validation procedure if no modules to install + if [[ "${#modules[@]}" -eq 0 ]]; then + finish_sandbox $krel + return + fi + $func $krel if ! validate_weak_links $krel && [[ -z "$force_update" ]]; then global_link_state_restore $krel fi + # add compatible to installed + update_installed + global_link_state_announce_changes $krel finish_sandbox $krel @@ -538,12 +573,16 @@ update_modules() { local func="$1" local force_update="$2" local module_krel + declare -a saved_modules read_modules_list || exit 1 [[ ${#modules[@]} -gt 0 ]] || return + saved_modules=("${modules[@]}") for krel in $(find_installed_kernels); do update_modules_for_krel $krel $func $force_update + modules=("${saved_modules[@]}") + installed_modules=() done for module in "${modules[@]}"; do @@ -568,7 +607,7 @@ add_weak_links() { module_krel="$(krel_of_module $module)" case "$module" in - /lib/modules/$krel/*) + $BASEDIR/lib/modules/$krel/*) # Module already installed to the current kernel continue ;; esac @@ -636,6 +675,7 @@ remove_weak_links() { # # Returns 0 (success) if proposal is fine or # 1 (false) if some incompatible symlinks were removed +# initializes global hashmap compatible_modules with all the valid ones validate_weak_links() { local krel="$1" local basedir=${BASEDIR:+-b $BASEDIR} @@ -653,6 +693,7 @@ validate_weak_links() { local is_configuration_valid=0 tmp=$(mktemp -p $tmpdir) + compatible_modules=() if ! [[ -e $tmpdir/symvers-$krel ]]; then [[ -e $BASEDIR/boot/symvers-$krel.gz ]] || return @@ -715,6 +756,9 @@ validate_weak_links() { module_krel=$(krel_of_module $target) if [[ "$module" == "$target" ]]; then + short_name="$(module_short_name "$module")" + compatible_modules+=([$short_name]="$module") + pr_verbose "Module ${module##*/} from kernel $module_krel is compatible with kernel $krel" fi done @@ -813,9 +857,12 @@ add_modules() { # do_make_groups: # Takes tmp file which contains preprocessed modules.dep # output (or modules.dep) +# # reads modules.dep format information from stdin # produces groups associative array # the group is a maximum subset of modules having at least a link +# +# more fine tuned extra filtering. do_make_groups() { local tmp="$1" @@ -826,6 +873,8 @@ do_make_groups() while read i; do mods=($i) + echo "${mods[0]}" |grep -q "extra/" || continue + # if the module already met, then its dependencies already counted module_group="${grouped_modules[${mods[0]}]}" [[ -n $module_group ]] && continue @@ -834,6 +883,8 @@ do_make_groups() group_name="${mods[0]}" for mod in "${mods[@]}"; do + echo "$mod" |grep -q "extra/" || continue + # if there is already such group, # it is a subset of the one being created # due to depmod output @@ -851,26 +902,32 @@ do_make_groups() # preprocess output for make_groups # depmod -n produces also aliases, so it cuts them off # also it removes colon after the first module -filter_depmod_deps() +cut_depmod_deps() { awk 'BEGIN { pr = 1 } /^#/{ pr = 0 } pr == 1 {sub(":",""); print $0}' } -# make_abs_path: +# filter_extra_absoluted: # Takes kernel version # makes full path from the relative module path # (produced by depmod for in-kernel-dir modules) -make_abs_path() +# filter only extra/ modules +filter_extra_absoluted() { local kver="$1" local mod declare -a mods while read i; do + # skip non-extra. The check is not perfect, but ok + # to speed up handling in general cases + echo "$i" |grep -q "extra/" || continue + mods=($i) for j in "${!mods[@]}"; do mod="${mods[$j]}" - [[ ${mod:0:1} == "/" ]] || mod="/lib/modules/$kver/$mod" + + [[ ${mod:0:1} == "/" ]] || mod="$BASEDIR/lib/modules/$kver/$mod" mods[$j]="$mod" done echo "${mods[@]}" @@ -878,20 +935,20 @@ make_abs_path() } # make_groups: -# takes krel and a file with the list of modules, +# takes k -- kernel version, we are installing extras from # prepares and feeds to do_make_groups # to create the module groups (global) make_groups() { - local krel="$1" - local tmp1="$2" + local k="$1" local tmp2=$(mktemp -p $tmpdir) + local basedir=${BASEDIR:+-b $BASEDIR} groups=() grouped_modules=() - $depmod -n $krel $(cat $tmp1) 2>/dev/null | - filter_depmod_deps | make_abs_path $krel > $tmp2 + $depmod -n $basedir $k 2>/dev/null | + cut_depmod_deps | filter_extra_absoluted $k > $tmp2 do_make_groups $tmp2 @@ -902,6 +959,7 @@ add_kernel() { local krel=${1:-$(uname -r)} local tmp local no_force_update="" + local num tmp=$(mktemp -p $tmpdir) @@ -911,17 +969,36 @@ add_kernel() { exit 1 fi - for k in $(find_kernels_with_extra | rpmsort); do + for k in $(find_kernels_with_extra | rpmsort -r); do [[ "$krel" == "$k" ]] && continue find_modules $k extra > $tmp - is_empty_file "$tmp" || make_groups $krel $tmp + is_empty_file "$tmp" || make_groups $k # reuse tmp + # optimization, check independent modules in one run. + # first try groups with one element in each. + # it means independent modules, so we can safely remove + # incompatible links + # some cut and paste here + + echo > $tmp for g in "${groups[@]}"; do + num="$(echo "$g" | wc -w)" + [ "$num" -gt 1 ] && continue + + printf '%s\n' $g >> $tmp + done + # to avoid subshell, see the read_modules_list comment + read_modules_list < $tmp + update_modules_for_krel $krel add_weak_links force_update + + for g in "${groups[@]}"; do + num="$(echo "$g" | wc -w)" + [ "$num" -eq 1 ] && continue + printf '%s\n' $g > $tmp - # to avoid subshell, see the read_modules_list comment read_modules_list < $tmp update_modules_for_krel $krel add_weak_links $no_force_update done diff --git a/SPECS/kmod.spec b/SPECS/kmod.spec index 651c716..cdab2f2 100644 --- a/SPECS/kmod.spec +++ b/SPECS/kmod.spec @@ -1,6 +1,6 @@ Name: kmod Version: 20 -Release: 25%{?dist} +Release: 25%{?dist}.1 Summary: Linux kernel module management utilities Group: System Environment/Kernel @@ -138,6 +138,10 @@ install -m 0644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/depmod.d/dist.conf %{_libdir}/libkmod.so %changelog +* Thu Feb 6 2020 Yauheni Kaliuta - 20-25.el7_7.1 +- weak-modules: backport extra/ dups fix + Resolves: rhbz#1799046 + * Wed Nov 21 2018 Yauheni Kaliuta - 20-25 - weak-modules: do not make groups if there are no extra modules Related: rhbz#1643299