Refactor kernel image and initrd detection code

kernel installation is not always in a fixed location /boot, there are
multiple different style of kernel installation, and initramfs location
changes with kernel. The two files should be detected together and adapt
to different style.

To do so we use a list of known installation destinations, and a list
of possible kernel image and initrd names. Iterate the two list to
detect the installation location of the two files. If GRUB is in use,
the BOOT_IMAGE= cmdline from GRUB will also be considered. And also
prefers user specified config if given.

Previous atomic workaround is no longer needed as the new detection
method can cover that case.

Signed-off-by: Kairui Song <kasong@redhat.com>
Acked-by: Dave Young <dyoung@redhat.com>
This commit is contained in:
Kairui Song 2020-07-28 02:40:20 +08:00
parent c76820bddd
commit a37f36ad4d
3 changed files with 88 additions and 49 deletions

View File

@ -21,18 +21,13 @@ depends() {
} }
prepare_kernel_initrd() { prepare_kernel_initrd() {
KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}") prepare_kdump_bootinfo
if [ -z "$KDUMP_KERNELVER" ]; then
kdump_kver=`uname -r` # $kernel is a variable from dracut
if [ "$kernel" != "$kdump_kver" ]; then if [ "$KDUMP_KERNELVER" != $kernel ]; then
dwarn "Using current kernel version '$kdump_kver' for early kdump," \ dwarn "Using kernel version '$KDUMP_KERNELVER' for early kdump," \
"but the initramfs is generated for kernel version '$kernel'" "but the initramfs is generated for kernel version '$kernel'"
fi
else
kdump_kver=$KDUMP_KERNELVER
fi fi
KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}"
KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img"
} }
install() { install() {

View File

@ -666,24 +666,68 @@ prepare_kexec_args()
echo $kexec_args echo $kexec_args
} }
check_boot_dir() #
# Detect initrd and kernel location, results are stored in global enviromental variables:
# KDUMP_BOOTDIR, KDUMP_KERNELVER, KDUMP_KERNEL, DEFAULT_INITRD, and KDUMP_INITRD
#
# Expectes KDUMP_BOOTDIR, KDUMP_IMG, KDUMP_IMG_EXT, KDUMP_KERNELVER to be loaded from config already
# and will prefer already set values so user can specify custom kernel/initramfs location
#
prepare_kdump_bootinfo()
{ {
local kdump_bootdir=$1 local boot_imglist boot_dirlist boot_initrdlist curr_kver="$(uname -r)"
#If user specify a boot dir for kdump kernel, let's use it. Otherwise local machine_id
#check whether it's a atomic host. If yes parse the subdirectory under
#/boot; If not just find it under /boot. if [ -z "$KDUMP_KERNELVER"]; then
if [ -n "$kdump_bootdir" ]; then KDUMP_KERNELVER="$(uname -r)"
echo "$kdump_bootdir"
return
fi fi
if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then read machine_id < /etc/machine-id
kdump_bootdir="/boot" boot_dirlist=${KDUMP_BOOTDIR:-"/boot /boot/efi /efi /"}
else boot_imglist="$KDUMP_IMG-$KDUMP_KERNELVER$KDUMP_IMG_EXT $machine_id/$KDUMP_KERNELVER/$KDUMP_IMG"
eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1)
kdump_bootdir="/boot"$(dirname ${BOOT_IMAGE#*)}) # Use BOOT_IMAGE as reference if possible, strip the GRUB root device prefix in (hd0,gpt1) format
local boot_img="$(cat /proc/cmdline | sed "s/^BOOT_IMAGE=\((\S*)\)\?\(\S*\) .*/\2/")"
if [ -n "$boot_img" ]; then
boot_imglist="$boot_img $boot_imglist"
fi
for dir in $boot_dirlist; do
for img in $boot_imglist; do
if [ -f "$dir/$img" ]; then
KDUMP_KERNEL=$(echo $dir/$img | tr -s '/')
break 2
fi
done
done
if ! [ -e "$KDUMP_KERNEL" ]; then
echo "Failed to detect kdump kernel location"
return 1
fi
# Set KDUMP_BOOTDIR to where kernel image is stored
KDUMP_BOOTDIR=$(dirname $KDUMP_KERNEL)
# Default initrd should just stay aside of kernel image, try to find it in KDUMP_BOOTDIR
boot_initrdlist="initramfs-$KDUMP_KERNELVER.img initrd"
for initrd in $boot_initrdlist; do
if [ -f "$KDUMP_BOOTDIR/$initrd" ]; then
DEFAULT_INITRD="$KDUMP_BOOTDIR/$initrd"
break
fi
done
# Get kdump initrd from default initrd filename
# initramfs-5.7.9-200.fc32.x86_64.img => initramfs-5.7.9-200.fc32.x86_64kdump.img
# initrd => initrdkdump
if [[ -z "$DEFAULT_INITRD" ]]; then
KDUMP_INITRD=${KDUMP_BOOTDIR}/initramfs-${KDUMP_KERNELVER}kdump.img
elif [[ $(basename $DEFAULT_INITRD) == *.* ]]; then
KDUMP_INITRD=${DEFAULT_INITRD%.*}kdump.${DEFAULT_INITRD##*.}
else
KDUMP_INITRD=${DEFAULT_INITRD}kdump
fi fi
echo $kdump_bootdir
} }
# #

View File

@ -2,6 +2,7 @@
KEXEC=/sbin/kexec KEXEC=/sbin/kexec
KDUMP_KERNELVER="" KDUMP_KERNELVER=""
KDUMP_KERNEL=""
KDUMP_COMMANDLINE="" KDUMP_COMMANDLINE=""
KEXEC_ARGS="" KEXEC_ARGS=""
KDUMP_CONFIG_FILE="/etc/kdump.conf" KDUMP_CONFIG_FILE="/etc/kdump.conf"
@ -13,6 +14,7 @@ INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum"
DUMP_TARGET="" DUMP_TARGET=""
DEFAULT_INITRD="" DEFAULT_INITRD=""
DEFAULT_INITRD_BAK="" DEFAULT_INITRD_BAK=""
KDUMP_INITRD=""
TARGET_INITRD="" TARGET_INITRD=""
FADUMP_REGISTER_SYS_NODE="/sys/kernel/fadump_registered" FADUMP_REGISTER_SYS_NODE="/sys/kernel/fadump_registered"
#kdump shall be the default dump mode #kdump shall be the default dump mode
@ -94,7 +96,7 @@ rebuild_fadump_initrd()
# this file tells the initrd is fadump enabled # this file tells the initrd is fadump enabled
touch /tmp/fadump.initramfs touch /tmp/fadump.initramfs
target_initrd_tmp="$TARGET_INITRD.tmp" target_initrd_tmp="$TARGET_INITRD.tmp"
$MKDUMPRD $target_initrd_tmp --rebuild $DEFAULT_INITRD_BAK --kver $kdump_kver \ $MKDUMPRD $target_initrd_tmp --rebuild $DEFAULT_INITRD_BAK --kver $KDUMP_KERNELVER \
-i /tmp/fadump.initramfs /etc/fadump.initramfs -i /tmp/fadump.initramfs /etc/fadump.initramfs
if [ $? != 0 ]; then if [ $? != 0 ]; then
echo "mkdumprd: failed to rebuild initrd with fadump support" >&2 echo "mkdumprd: failed to rebuild initrd with fadump support" >&2
@ -118,7 +120,7 @@ check_earlykdump_is_enabled()
rebuild_kdump_initrd() rebuild_kdump_initrd()
{ {
$MKDUMPRD $TARGET_INITRD $kdump_kver $MKDUMPRD $TARGET_INITRD $KDUMP_KERNELVER
if [ $? != 0 ]; then if [ $? != 0 ]; then
echo "mkdumprd: failed to make kdump initrd" >&2 echo "mkdumprd: failed to make kdump initrd" >&2
return 1 return 1
@ -189,6 +191,10 @@ backup_default_initrd()
restore_default_initrd() restore_default_initrd()
{ {
if [ ! -f "$DEFAULT_INITRD" ]; then
return
fi
# If a backup initrd exists, we must be switching back from # If a backup initrd exists, we must be switching back from
# fadump to kdump. Restore the original default initrd. # fadump to kdump. Restore the original default initrd.
if [ -f $DEFAULT_INITRD_BAK ] && [ -f $INITRD_CHECKSUM_LOCATION ]; then if [ -f $DEFAULT_INITRD_BAK ] && [ -f $INITRD_CHECKSUM_LOCATION ]; then
@ -301,18 +307,12 @@ get_pcs_cluster_modified_files()
setup_initrd() setup_initrd()
{ {
KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}") prepare_kdump_bootinfo
if [ $? -ne 0 ]; then
if [ -z "$KDUMP_KERNELVER" ]; then return 1
kdump_kver=`uname -r`
else
kdump_kver=$KDUMP_KERNELVER
fi fi
kdump_kernel="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}" DEFAULT_INITRD_BAK="$KDUMP_BOOTDIR/.$(basename $DEFAULT_INITRD).default"
DEFAULT_INITRD="${KDUMP_BOOTDIR}/initramfs-`uname -r`.img"
DEFAULT_INITRD_BAK="${KDUMP_BOOTDIR}/.initramfs-`uname -r`.img.default"
if [ $DEFAULT_DUMP_MODE == "fadump" ]; then if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
TARGET_INITRD="$DEFAULT_INITRD" TARGET_INITRD="$DEFAULT_INITRD"
@ -320,7 +320,7 @@ setup_initrd()
# with fadump aware initrd # with fadump aware initrd
backup_default_initrd backup_default_initrd
else else
TARGET_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img" TARGET_INITRD="$KDUMP_INITRD"
# check if a backup of default initrd exists. If yes, # check if a backup of default initrd exists. If yes,
# it signifies a switch from fadump mode. So, restore # it signifies a switch from fadump mode. So, restore
@ -360,25 +360,25 @@ check_files_modified()
EXTRA_BINS="$EXTRA_BINS $CHECK_FILES" EXTRA_BINS="$EXTRA_BINS $CHECK_FILES"
CHECK_FILES=`grep ^extra_bins $KDUMP_CONFIG_FILE | cut -d\ -f2-` CHECK_FILES=`grep ^extra_bins $KDUMP_CONFIG_FILE | cut -d\ -f2-`
EXTRA_BINS="$EXTRA_BINS $CHECK_FILES" EXTRA_BINS="$EXTRA_BINS $CHECK_FILES"
files="$KDUMP_CONFIG_FILE $kdump_kernel $EXTRA_BINS $CORE_COLLECTOR" files="$KDUMP_CONFIG_FILE $KDUMP_KERNEL $EXTRA_BINS $CORE_COLLECTOR"
[[ -e /etc/fstab ]] && files="$files /etc/fstab" [[ -e /etc/fstab ]] && files="$files /etc/fstab"
# Check for any updated extra module # Check for any updated extra module
EXTRA_MODULES="$(grep ^extra_modules $KDUMP_CONFIG_FILE | sed 's/^extra_modules\s*//')" EXTRA_MODULES="$(grep ^extra_modules $KDUMP_CONFIG_FILE | sed 's/^extra_modules\s*//')"
if [ -n "$EXTRA_MODULES" ]; then if [ -n "$EXTRA_MODULES" ]; then
if [ -e /lib/modules/$kdump_kver/modules.dep ]; then if [ -e /lib/modules/$KDUMP_KERNELVER/modules.dep ]; then
files="$files /lib/modules/$kdump_kver/modules.dep" files="$files /lib/modules/$KDUMP_KERNELVER/modules.dep"
fi fi
for _module in $EXTRA_MODULES; do for _module in $EXTRA_MODULES; do
_module_file="$(modinfo --set-version "$kdump_kver" --filename "$_module" 2>/dev/null)" _module_file="$(modinfo --set-version "$KDUMP_KERNELVER" --filename "$_module" 2>/dev/null)"
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
files="$files $_module_file" files="$files $_module_file"
for _dep_modules in $(modinfo -F depends $_module | tr ',' ' '); do for _dep_modules in $(modinfo -F depends $_module | tr ',' ' '); do
files="$files $(modinfo --set-version "$kdump_kver" --filename $_dep_modules 2>/dev/null)" files="$files $(modinfo --set-version "$KDUMP_KERNELVER" --filename $_dep_modules 2>/dev/null)"
done done
else else
# If it's not a module nor builtin, give an error # If it's not a module nor builtin, give an error
if ! ( modprobe --set-version "$kdump_kver" --dry-run "$_module" &>/dev/null ); then if ! ( modprobe --set-version "$KDUMP_KERNELVER" --dry-run "$_module" &>/dev/null ); then
echo "Module $_module not found" echo "Module $_module not found"
fi fi
fi fi
@ -472,8 +472,8 @@ check_dump_fs_modified()
check_block_and_slaves_all _record_block_drivers "$(get_maj_min "$_target")" check_block_and_slaves_all _record_block_drivers "$(get_maj_min "$_target")"
for _driver in $_target_drivers; do for _driver in $_target_drivers; do
# Skip deprecated/invalid driver name or built-in module # Skip deprecated/invalid driver name or built-in module
_module_name=$(modinfo --set-version "$kdump_kver" -F name $_driver 2>/dev/null) _module_name=$(modinfo --set-version "$KDUMP_KERNELVER" -F name $_driver 2>/dev/null)
_module_filename=$(modinfo --set-version "$kdump_kver" -n $_driver 2>/dev/null) _module_filename=$(modinfo --set-version "$KDUMP_KERNELVER" -n $_driver 2>/dev/null)
if [ $? -ne 0 ] || [ -z "$_module_name" ] || [[ "$_module_filename" = *"(builtin)"* ]]; then if [ $? -ne 0 ] || [ -z "$_module_name" ] || [[ "$_module_filename" = *"(builtin)"* ]]; then
continue continue
fi fi
@ -540,7 +540,7 @@ check_wdt_modified()
# modalias. Currently load all of them. # modalias. Currently load all of them.
# TODO: Need to find a way to avoid any unwanted module # TODO: Need to find a way to avoid any unwanted module
# represented by modalias # represented by modalias
_wdtdrv=$(modprobe --set-version "$kdump_kver" -R $_wdtdrv 2>/dev/null) _wdtdrv=$(modprobe --set-version "$KDUMP_KERNELVER" -R $_wdtdrv 2>/dev/null)
if [[ $_wdtdrv ]]; then if [[ $_wdtdrv ]]; then
for i in $_wdtdrv; do for i in $_wdtdrv; do
_drivers[$i]=1 _drivers[$i]=1
@ -555,7 +555,7 @@ check_wdt_modified()
[[ -f "$_wdtppath/modalias" ]] || continue [[ -f "$_wdtppath/modalias" ]] || continue
_wdtdrv=$(< "$_wdtppath/modalias") _wdtdrv=$(< "$_wdtppath/modalias")
_wdtdrv=$(modprobe --set-version "$kdump_kver" -R $_wdtdrv 2>/dev/null) _wdtdrv=$(modprobe --set-version "$KDUMP_KERNELVER" -R $_wdtdrv 2>/dev/null)
if [[ $_wdtdrv ]]; then if [[ $_wdtdrv ]]; then
for i in $_wdtdrv; do for i in $_wdtdrv; do
_drivers[$i]=1 _drivers[$i]=1
@ -700,7 +700,7 @@ load_kdump()
$KEXEC $KEXEC_ARGS $standard_kexec_args \ $KEXEC $KEXEC_ARGS $standard_kexec_args \
--command-line="$KDUMP_COMMANDLINE" \ --command-line="$KDUMP_COMMANDLINE" \
--initrd=$TARGET_INITRD $kdump_kernel --initrd=$TARGET_INITRD $KDUMP_KERNEL
if [ $? == 0 ]; then if [ $? == 0 ]; then
echo "kexec: loaded kdump kernel" echo "kexec: loaded kdump kernel"
return 0 return 0