From 94009c27f44b5fa623355e72205bda8ea71581c1 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Fri, 16 Apr 2021 18:42:00 +0200 Subject: [PATCH] test: rewrite kernel module handling This code was partially broken, since the firmware directory was undefined. Also, some of the parts were a dead code, since they relied on code from the original dracut test suite. --- test/test-functions | 250 +++++++++++++++----------------------------- 1 file changed, 85 insertions(+), 165 deletions(-) diff --git a/test/test-functions b/test/test-functions index 851b2aab3eb..8f2ffb13232 100644 --- a/test/test-functions +++ b/test/test-functions @@ -2076,53 +2076,37 @@ dracut_install() { # Install a single kernel module along with any firmware it may require. # $1 = full path to kernel module to install install_kmod_with_fw() { + local module="${1:?}" # no need to go further if the module is already installed + [[ -e "${initdir:?}/lib/modules/${KERNEL_VER:?}/${module##*/lib/modules/$KERNEL_VER/}" ]] && return 0 + [[ -e "$initdir/.kernelmodseen/${module##*/}" ]] && return 0 - [[ -e "${initdir}/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" ]] \ - && return 0 + [ -d "$initdir/.kernelmodseen" ] && : >"$initdir/.kernelmodseen/${module##*/}" - [[ -e "$initdir/.kernelmodseen/${1##*/}" ]] && return 0 + inst_simple "$module" "/lib/modules/$KERNEL_VER/${module##*/lib/modules/$KERNEL_VER/}" || return $? - if [[ $omit_drivers ]]; then - local _kmod=${1##*/} - _kmod=${_kmod%.ko} - _kmod=${_kmod/-/_} - if [[ "$_kmod" =~ $omit_drivers ]]; then - dinfo "Omitting driver $_kmod" - return 1 - fi - if [[ "${1##*/lib/modules/$KERNEL_VER/}" =~ $omit_drivers ]]; then - dinfo "Omitting driver $_kmod" - return 1 - fi - fi + local modname="${module##*/}" + local fwdir found fw + modname="${modname%.ko*}" - [ -d "$initdir/.kernelmodseen" ] && \ - >"$initdir/.kernelmodseen/${1##*/}" - - inst_simple "$1" "/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" \ - || return $? - - local _modname=${1##*/} _fwdir _found _fw - _modname=${_modname%.ko*} - for _fw in $(modinfo -k $KERNEL_VER -F firmware $1 2>/dev/null); do - _found='' - for _fwdir in $fw_dir; do - if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then - inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw" - _found=yes + while read -r fw; do + found= + for fwdir in /lib/firmware/updates /lib/firmware; do + if [[ -d "$fwdir" && -f "$fwdir/$fw" ]]; then + inst_simple "$fwdir/$fw" "/lib/firmware/$fw" + found=yes fi done - if [[ $_found != yes ]]; then - if ! grep -qe "\<${_modname//-/_}\>" /proc/modules; then - dinfo "Possible missing firmware \"${_fw}\" for kernel module" \ - "\"${_modname}.ko\"" + if [[ $found != yes ]]; then + if ! grep -qe "\<${modname//-/_}\>" /proc/modules; then + dinfo "Possible missing firmware \"${fw}\" for kernel module" \ + "\"${modname}.ko\"" else - dwarn "Possible missing firmware \"${_fw}\" for kernel module" \ - "\"${_modname}.ko\"" + dwarn "Possible missing firmware \"${fw}\" for kernel module" \ + "\"${modname}.ko\"" fi fi - done + done < <(modinfo -k "$KERNEL_VER" -F firmware "$module" 2>/dev/null) return 0 } @@ -2132,168 +2116,104 @@ install_kmod_with_fw() { # It will be passed the full path to the found kernel module # $2 = module to get dependencies for # rest of args = arguments to modprobe -# _fderr specifies FD passed from surrounding scope for_each_kmod_dep() { - local _func=$1 _kmod=$2 _cmd _modpath _options _found=0 + local func="${1:?}" + local kmod="${2:?}" + local found=0 + local cmd modpath shift 2 - modprobe "$@" --ignore-install --show-depends $_kmod 2>&${_fderr} | ( - while read _cmd _modpath _options; do - [[ $_cmd = insmod ]] || continue - $_func ${_modpath} || exit $? - _found=1 - done - [[ $_found -eq 0 ]] && exit 1 - exit 0 - ) -} -# filter kernel modules to install certain modules that meet specific -# requirements. -# $1 = search only in subdirectory of /kernel/$1 -# $2 = function to call with module name to filter. -# This function will be passed the full path to the module to test. -# The behavior of this function can vary depending on whether $hostonly is set. -# If it is, we will only look at modules that are already in memory. -# If it is not, we will look at all kernel modules -# This function returns the full filenames of modules that match $1 -filter_kernel_modules_by_path () ( - local _modname _filtercmd - if ! [[ $hostonly ]]; then - _filtercmd='find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra"' - _filtercmd+=' "$KERNEL_MODS/weak-updates" -name "*.ko" -o -name "*.ko.gz"' - _filtercmd+=' -o -name "*.ko.xz"' - _filtercmd+=' 2>/dev/null' - else - _filtercmd='cut -d " " -f 1 $initdir/$$.ko - $2 $initdir/$$.ko && echo "$_modname" - rm -f $initdir/$$.ko - ;; - *.ko.xz) xz -dc "$_modname" >$initdir/$$.ko - $2 $initdir/$$.ko && echo "$_modname" - rm -f $initdir/$$.ko - ;; - esac - done -) -find_kernel_modules_by_path () ( - if ! [[ $hostonly ]]; then - find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra" "$KERNEL_MODS/weak-updates" \ - -name "*.ko" -o -name "*.ko.gz" -o -name "*.ko.xz" 2>/dev/null - else - cut -d " " -f 1 /dev/null - fi -) + while read -r cmd modpath _; do + [[ "$cmd" = insmod ]] || continue + "$func" "$modpath" || return $? + found=1 + done < <(modprobe "$@" --ignore-install --show-depends "$kmod") -filter_kernel_modules () { - filter_kernel_modules_by_path drivers "$1" -} - -find_kernel_modules () { - find_kernel_modules_by_path drivers + [[ $found -eq 0 ]] && return 1 + return 0 } # instmods [-c] [ ... ] # instmods [-c] # install kernel modules along with all their dependencies. # can be e.g. "=block" or "=drivers/usb/storage" +# FIXME(?): dracutdevs/dracut@f4e38c0da8d6bf3764c1ad753d9d52aef63050e5 instmods() { - [[ $no_kernel = yes ]] && return - # called [sub]functions inherit _fderr - local _fderr=9 - local _check=no - if [[ $1 = '-c' ]]; then - _check=yes + local check=no + if [[ $# -ge 0 && "$1" = '-c' ]]; then + check=yes shift fi - function inst1mod() { - local _ret=0 _mod="$1" - case $_mod in + inst1mod() { + local mod="${1:?}" + local ret=0 + local mod_dir="/lib/modules/${KERNEL_VER:?}/" + + case "$mod" in =*) - if [ -f $KERNEL_MODS/modules.${_mod#=} ]; then - ( [[ "$_mpargs" ]] && echo $_mpargs - cat "${KERNEL_MODS}/modules.${_mod#=}" ) \ - | instmods + if [ -f "${mod_dir}/modules.${mod#=}" ]; then + ( + [[ "$mpargs" ]] && echo "$mpargs" + cat "${mod_dir}/modules.${mod#=}" + ) | instmods else - ( [[ "$_mpargs" ]] && echo $_mpargs - find "$KERNEL_MODS" -path "*/${_mod#=}/*" -type f -printf '%f\n' ) \ - | instmods + ( + [[ "$mpargs" ]] && echo "$mpargs" + find "$mod_dir" -path "*/${mod#=}/*" -type f -printf '%f\n' + ) | instmods fi ;; - --*) _mpargs+=" $_mod" ;; - i2o_scsi) return ;; # Do not load this diagnostic-only module + --*) + mpargs+=" $mod" + ;; + i2o_scsi) + # Do not load this diagnostic-only module + return + ;; *) - _mod=${_mod##*/} + mod=${mod##*/} # if we are already installed, skip this module and go on # to the next one. - [[ -f "$initdir/.kernelmodseen/${_mod%.ko}.ko" ]] && return - - if [[ $omit_drivers ]] && [[ "$1" =~ $omit_drivers ]]; then - dinfo "Omitting driver ${_mod##$KERNEL_MODS}" - return - fi - # If we are building a host-specific initramfs and this - # module is not already loaded, move on to the next one. - [[ $hostonly ]] && ! grep -qe "\<${_mod//-/_}\>" /proc/modules \ - && ! echo $add_drivers | grep -qe "\<${_mod}\>" \ - && return + [[ -f "${initdir:?}/.kernelmodseen/${mod%.ko}.ko" ]] && return # We use '-d' option in modprobe only if modules prefix path # differs from default '/'. This allows us to use Dracut with # old version of modprobe which doesn't have '-d' option. - local _moddirname=${KERNEL_MODS%%/lib/modules/*} - [[ -n ${_moddirname} ]] && _moddirname="-d ${_moddirname}/" + local mod_dirname=${mod_dir%%/lib/modules/*} + [[ -n ${mod_dirname} ]] && mod_dirname="-d ${mod_dirname}/" # ok, load the module, all its dependencies, and any firmware # it may require - for_each_kmod_dep install_kmod_with_fw $_mod \ - --set-version $KERNEL_VER ${_moddirname} $_mpargs - ((_ret+=$?)) + for_each_kmod_dep install_kmod_with_fw "$mod" \ + --set-version "$KERNEL_VER" \ + ${mod_dirname:+"$mod_dirname"} \ + ${mpargs:+"$mpargs"} + ((ret+=$?)) ;; esac - return $_ret + return $ret } - function instmods_1() { - local _mod _mpargs - if (($# == 0)); then # filenames from stdin - while read _mod; do - inst1mod "${_mod%.ko*}" || { - if [ "$_check" = "yes" ]; then - dfatal "Failed to install $_mod" - return 1 - fi - } - done - fi - while (($# > 0)); do # filenames as arguments - inst1mod ${1%.ko*} || { - if [ "$_check" = "yes" ]; then - dfatal "Failed to install $1" - return 1 - fi - } - shift + local mod mpargs + + if [[ $# -eq 0 ]]; then # filenames from stdin + while read -r mod; do + if ! inst1mod "${mod%.ko*}" && [ "$check" = "yes" ]; then + dfatal "Failed to install $mod" + return 1 + fi done - return 0 - } + fi - local _ret _filter_not_found='FATAL: Module .* not found.' - set -o pipefail - # Capture all stderr from modprobe to _fderr. We could use {var}>... - # redirections, but that would make dracut require bash4 at least. - eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \ - | while read line; do [[ "$line" =~ $_filter_not_found ]] && echo $line || echo $line >&2 ;done | derror - _ret=$? - set +o pipefail - return $_ret + for mod in "$@"; do # filenames as arguments + if ! inst1mod "${mod%.ko*}" && [ "$check" = "yes" ]; then + dfatal "Failed to install $mod" + return 1 + fi + done + + return 0 } setup_suse() {