From 933fad99cbd4fc1706dda143053d8c2579cd3eab Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Mon, 20 Jan 2020 18:56:21 +0200 Subject: [PATCH] weak-modules: Sync with RHEL Signed-off-by: Yauheni Kaliuta --- weak-modules | 99 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 21 deletions(-) diff --git a/weak-modules b/weak-modules index dd163cc..65806d0 100644 --- a/weak-modules +++ b/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() { @@ -473,6 +472,29 @@ prepare_sandbox() { depmod="$depmod_orig -C $conf" } +# 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 +} # finish_sandbox: # restore global state after sandboxing @@ -568,6 +590,7 @@ find_systemmap_file() { # 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" @@ -579,12 +602,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 @@ -600,12 +635,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 @@ -630,7 +669,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 @@ -698,6 +737,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} @@ -715,6 +755,7 @@ validate_weak_links() { local is_configuration_valid=0 tmp=$(mktemp -p $tmpdir) + compatible_modules=() if ! [[ -e $tmpdir/symvers-$krel ]]; then local symvers_path=$(find_symvers_file "$krel") @@ -779,6 +820,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 @@ -877,9 +921,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" @@ -890,6 +937,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 @@ -898,6 +947,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 @@ -915,26 +966,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[@]}" @@ -942,20 +999,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 @@ -976,11 +1033,11 @@ 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