Skip to content

Commit

Permalink
Merge pull request #2579 from rear/jsmeix-fail-safe-400_copy_modules
Browse files Browse the repository at this point in the history
Make 400_copy_modules.sh fail-safe for newer modinfo output
(in particular modinfo in kmod-27 since SLES15-SP3) because
otherwise copying builtin kernel "modules" would let "rear mkrescue"
error out with e.g. "ERROR: unix exists but no module file?".
Furthermore ensure that kernel modules that should be loaded
during recovery system startup (i.e. those in MODULES_LOAD)
get always copied into the recovery system.
  • Loading branch information
jsmeix committed Mar 9, 2021
2 parents 9a6b9a1 + d2588e8 commit 4480cc0
Showing 1 changed file with 46 additions and 16 deletions.
62 changes: 46 additions & 16 deletions usr/share/rear/build/GNU/Linux/400_copy_modules.sh
Expand Up @@ -26,23 +26,42 @@ fi
function modinfo_filename () {
local module_name=$1
local module_filename=""
local alias_module_name=$(modprobe -n -R $module_name 2>/dev/null)
# 'modprobe -n -R' prints all module names matching an alias so we have its output in an array
# and use only its first element to consider only the first printed module name:
local alias_module_name=( $( modprobe -n -R $module_name 2>/dev/null ) )
# If the installed modprobe command supports resolving module aliases (-R), use that capability.
test $alias_module_name && module_name=$alias_module_name
# Older modinfo (e.g. the one in SLES10) does not support '-k'
# but that old modinfo returns a zero exit code when called as 'modinfo -k ...'
# and shows a 'modinfo: invalid option -- k ...' message on stderr and nothing on stdout
# so that we need to check if we got a non-empty module filename:
module_filename=$( modinfo -k $KERNEL_VERSION -F filename $module_name )
# so that we need to check if we got a non-empty module filename.
# Older modinfo (in particular modinfo before kmod-27 since SLES15-SP3)
# outputs nothing on stdout for builtin kernel "modules" and exits with exit code 1 like
# # modinfo -F filename unix
# modinfo: ERROR: Module unix not found.
# Newer modinfo (in particular modinfo in kmod-27 since SLES15-SP3)
# outputs on stdout for builtin kernel "modules" and exits with zero exit code like
# # modinfo -F filename unix
# name: unix
# (builtin)
# For real kernel modules the modinfo stdout is one word that is the kernel module filename like
# # modinfo -F filename sg
# /lib/modules/5.3.18-43-default/kernel/drivers/scsi/sg.ko.xz
module_filename="$( modinfo -k $KERNEL_VERSION -F filename $module_name )"
# If 'modinfo -k ...' stdout is empty we retry without '-k' regardless why stdout is empty
# but then we do not discard stderr so that error messages appear in the log file.
# In this case we must additionally ensure that KERNEL_VERSION matches 'uname -r'
# otherwise a module file for a wrong kernel version would be found:
if ! test $module_filename ; then
if ! test "$module_filename" ; then
test "$KERNEL_VERSION" = "$( uname -r )" || Error "modinfo_filename failed because KERNEL_VERSION does not match 'uname -r'"
module_filename=$( modinfo -F filename $module_name )
module_filename="$( modinfo -F filename $module_name )"
fi
test $module_filename && echo $module_filename
# grep for '(builtin)' in the modinfo stdout to get the builtin kernel "module" case and otherwise
# 'readlink -e something' shows the filename when something is one or more files and exits with zero exit code
# 'readlink -e something' shows the symlink target when something is a symlink and exits with zero exit code
# 'readlink -e something' shows nothing when something is no file or a broken symlink and exits with exit code 1
# 'readlink -e something' shows nothing on stdout but an error on stderr when something is empty and exits with exit code 1
grep -q '(builtin)' <<<"$module_filename" && echo '' || readlink -e $module_filename
}

# Artificial 'for' clause that is run only once
Expand Down Expand Up @@ -74,7 +93,8 @@ for dummy in "once" ; do
# Test all MODULES array members to make the 'loaded_modules' functionality work for
# MODULES array contents like MODULES=( 'moduleX' 'loaded_modules' 'moduleY' ):
if IsInArray "loaded_modules" "${MODULES[@]}" ; then
LogPrint "Copying only currently loaded kernel modules (MODULES contains 'loaded_modules')"
# Kernel modules that should be loaded during recovery system startup must be always copied into the recovery system:
LogPrint "Copying only currently loaded kernel modules (MODULES contains 'loaded_modules') and those in MODULES_LOAD"
# The rescue/recovery system cannot work when its kernel modules
# do not match the kernel that gets included in the rescue/recovery system
# so that "rear mkrescue/mkbackup" errors out to be on the safe side
Expand All @@ -84,12 +104,20 @@ for dummy in "once" ; do
if ! test "$KERNEL_VERSION" = "$currently_running_kernel_version" ; then
Error "KERNEL_VERSION='$KERNEL_VERSION' does not match currently running kernel version ('uname -r' shows '$currently_running_kernel_version')"
fi
loaded_modules="$( lsmod | tail -n +2 | cut -d ' ' -f 1 )"
# It can happen that a module is loaded but 'modinfo -F filename' cannot show its filename
# when it is loaded under a module alias name but the above modinfo_filename function
# could not resolve aliases (when the modprobe command does not support -R):
loaded_modules_files="$( for loaded_module in $loaded_modules ; do modinfo_filename $loaded_module || Error "$loaded_module loaded but no module file?" ; done )"
# $loaded_modules_files cannot be empty because modinfo_filename fails when it cannot show a module filename:
# Kernel modules that should be loaded during recovery system startup must be always copied into the recovery system:
loaded_modules="${MODULES_LOAD[@]}"
# The leading blank before $(...) is mandatory (otherwise the last in MODULES_LOAD is concatenated with the first of lsmod):
loaded_modules+=" $( lsmod | tail -n +2 | cut -d ' ' -f 1 )"
# It can happen that a module is loaded or should be loaded but 'modinfo -F filename' cannot show its filename
# when it is loaded or should be loaded under a module alias name but the above modinfo_filename function
# could not resolve aliases (when the modprobe command does not support -R).
# The 'sort -u' removes duplicates only to avoid useless stderr warnings from the subsequent 'cp'
# like "cp: warning: source file '/lib/modules/.../foo.ko' specified more than once"
# regardless that nothing goes wrong when 'cp' gets duplicate source files
# cf. http://blog.schlomo.schapiro.org/2015/04/warning-is-waste-of-my-time.html
loaded_modules_files="$( for loaded_module in $loaded_modules ; do modinfo_filename $loaded_module || Error "$loaded_module loaded or to be loaded but no module file?" ; done | sort -u )"
# $loaded_modules_files could be empty as extreme case because modinfo_filename outputs nothing in the builtin kernel "module" case:
test "$loaded_modules_files" || continue
if ! cp $verbose -t $ROOTFS_DIR -L --preserve=all --parents $loaded_modules_files 1>&2 ; then
Error "Failed to copy '$loaded_modules_files'"
fi
Expand Down Expand Up @@ -127,8 +155,9 @@ for dummy in "once" ; do
sr_mod ide_cd cdrom
zlib zlib-inflate zlib-deflate
libcrc32c crc32c crc32c-intel )
# Include the modules in MODULES plus their dependant modules:
for module in "${MODULES[@]}" ; do
# Include the modules in MODULES plus their dependant modules.
# Kernel modules that should be loaded during recovery system startup must be always copied into the recovery system:
for module in "${MODULES_LOAD[@]}" "${MODULES[@]}" ; do
# Strip trailing ".o" if there:
module=${module#.o}
# Strip trailing ".ko" if there:
Expand Down Expand Up @@ -160,7 +189,8 @@ for dummy in "once" ; do
# could not resolve aliases (when the modprobe command does not support -R):
module_files="$( modinfo_filename $module || Error "$module exists but no module file?" )"
fi
# $module_files cannot be empty because modinfo_filename fails when it cannot show a module filename:
# $module_files can be empty because modinfo_filename outputs nothing in the builtin kernel "module" case:
test "$module_files" || continue
if ! cp $verbose -t $ROOTFS_DIR -L --preserve=all --parents $module_files 1>&2 ; then
Error "Failed to copy '$module_files'"
fi
Expand Down

0 comments on commit 4480cc0

Please sign in to comment.