This patch series refactor kernel image and initrd detection, fix kdump service failure on some Fedora machines which use /boot/<machine-id>/<kver>/vmlinuz as kernel installation destination.
Also cover the atomic corner case properly by refering BOOT_IMAGE= cmdline param for kernel image location.
Kairui Song (3): early-kdump: Use consistent symbol link for kernel and initramfs Refactor kernel image and initrd detection code kdump-lib.sh: Remove is_atomic
dracut-early-kdump-module-setup.sh | 21 +++----- dracut-early-kdump.sh | 6 +-- kdump-lib.sh | 78 +++++++++++++++++++++++------- kdumpctl | 44 ++++++++--------- 4 files changed, 90 insertions(+), 59 deletions(-)
There is no need to follow user's configuration when installtion the kernel and initramfs for early kdump, just use a fixed a symbol link is enough, this help avoid a check_boot_dir call.
Signed-off-by: Kairui Song kasong@redhat.com --- dracut-early-kdump-module-setup.sh | 4 ++-- dracut-early-kdump.sh | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/dracut-early-kdump-module-setup.sh b/dracut-early-kdump-module-setup.sh index e069867..626ca0e 100755 --- a/dracut-early-kdump-module-setup.sh +++ b/dracut-early-kdump-module-setup.sh @@ -58,8 +58,8 @@ install() { inst_binary "$KDUMP_KERNEL" inst_binary "$KDUMP_INITRD"
- ln_r "$KDUMP_KERNEL" "${KDUMP_BOOTDIR}/${KDUMP_IMG}-earlykdump${KDUMP_IMG_EXT}" - ln_r "$KDUMP_INITRD" "${KDUMP_BOOTDIR}/initramfs-earlykdump.img" + ln_r "$KDUMP_KERNEL" "/boot/kernel-earlykdump" + ln_r "$KDUMP_INITRD" "/boot/initramfs-earlykdump"
chmod -x "${initdir}/$KDUMP_KERNEL" } diff --git a/dracut-early-kdump.sh b/dracut-early-kdump.sh index 69a34eb..92913fb 100755 --- a/dracut-early-kdump.sh +++ b/dracut-early-kdump.sh @@ -16,10 +16,8 @@ EARLY_KEXEC_ARGS="" prepare_parameters() { EARLY_KDUMP_CMDLINE=$(prepare_cmdline "${KDUMP_COMMANDLINE}" "${KDUMP_COMMANDLINE_REMOVE}" "${KDUMP_COMMANDLINE_APPEND}") - KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}") - - EARLY_KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-earlykdump${KDUMP_IMG_EXT}" - EARLY_KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-earlykdump.img" + EARLY_KDUMP_KERNEL="/boot/kernel-earlykdump" + EARLY_KDUMP_INITRD="/boot/initramfs-earlykdump" }
early_kdump_load()
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 potential 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 --- dracut-early-kdump-module-setup.sh | 17 +++---- kdump-lib.sh | 75 ++++++++++++++++++++++++------ kdumpctl | 44 ++++++++---------- 3 files changed, 87 insertions(+), 49 deletions(-)
diff --git a/dracut-early-kdump-module-setup.sh b/dracut-early-kdump-module-setup.sh index 626ca0e..f30bd67 100755 --- a/dracut-early-kdump-module-setup.sh +++ b/dracut-early-kdump-module-setup.sh @@ -21,18 +21,13 @@ depends() { }
prepare_kernel_initrd() { - KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}") - if [ -z "$KDUMP_KERNELVER" ]; then - kdump_kver=`uname -r` - if [ "$kernel" != "$kdump_kver" ]; then - dwarn "Using current kernel version '$kdump_kver' for early kdump," \ - "but the initramfs is generated for kernel version '$kernel'" - fi - else - kdump_kver=$KDUMP_KERNELVER + prepare_kdump_bootinfo + + # $kernel is a variable from dracut + if [ "$KDUMP_KERNELVER" != $kernel ]; then + dwarn "Using kernel version '$KDUMP_KERNELVER' for early kdump," \ + "but the initramfs is generated for kernel version '$kernel'" fi - KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}" - KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img" }
install() { diff --git a/kdump-lib.sh b/kdump-lib.sh index f632f65..c35b904 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -666,24 +666,71 @@ prepare_kexec_args() echo $kexec_args }
-check_boot_dir() -{ - local kdump_bootdir=$1 - #If user specify a boot dir for kdump kernel, let's use it. Otherwise - #check whether it's a atomic host. If yes parse the subdirectory under - #/boot; If not just find it under /boot. - if [ -n "$kdump_bootdir" ]; then - echo "$kdump_bootdir" - return +# +# 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 boot_imglist boot_dirlist boot_initrdlist curr_kver="$(uname -r)" + local machine_id + + if [ -z "$KDUMP_KERNELVER"]; then + KDUMP_KERNELVER="$(uname -r)" + fi + + read machine_id < /etc/machine-id + boot_dirlist=${KDUMP_BOOTDIR:-"/boot /boot/efi /efi /"} + boot_imglist="$KDUMP_IMG-$KDUMP_KERNELVER$KDUMP_IMG_EXT $machine_id/$KDUMP_KERNELVER/$KDUMP_IMG" + + # 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 + + if ! [ -e "$DEFAULT_INITRD" ]; then + echo "Failed to detect default initrd location" + return 1 fi
- if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then - kdump_bootdir="/boot" + # 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 [[ $(basename $DEFAULT_INITRD) == *.* ]]; then + KDUMP_INITRD=${DEFAULT_INITRD%.*}kdump.${DEFAULT_INITRD##*.} else - eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1) - kdump_bootdir="/boot"$(dirname ${BOOT_IMAGE#*)}) + KDUMP_INITRD=${DEFAULT_INITRD}kdump fi - echo $kdump_bootdir }
# diff --git a/kdumpctl b/kdumpctl index 42c11d3..9069326 100755 --- a/kdumpctl +++ b/kdumpctl @@ -2,6 +2,7 @@ KEXEC=/sbin/kexec
KDUMP_KERNELVER="" +KDUMP_KERNEL="" KDUMP_COMMANDLINE="" KEXEC_ARGS="" KDUMP_CONFIG_FILE="/etc/kdump.conf" @@ -13,6 +14,7 @@ INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum" DUMP_TARGET="" DEFAULT_INITRD="" DEFAULT_INITRD_BAK="" +KDUMP_INITRD="" TARGET_INITRD="" FADUMP_REGISTER_SYS_NODE="/sys/kernel/fadump_registered" #kdump shall be the default dump mode @@ -94,7 +96,7 @@ rebuild_fadump_initrd() # this file tells the initrd is fadump enabled touch /tmp/fadump.initramfs 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 if [ $? != 0 ]; then echo "mkdumprd: failed to rebuild initrd with fadump support" >&2 @@ -118,7 +120,7 @@ check_earlykdump_is_enabled()
rebuild_kdump_initrd() { - $MKDUMPRD $TARGET_INITRD $kdump_kver + $MKDUMPRD $TARGET_INITRD $KDUMP_KERNELVER if [ $? != 0 ]; then echo "mkdumprd: failed to make kdump initrd" >&2 return 1 @@ -301,18 +303,12 @@ get_pcs_cluster_modified_files()
setup_initrd() { - KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}") - - if [ -z "$KDUMP_KERNELVER" ]; then - kdump_kver=`uname -r` - else - kdump_kver=$KDUMP_KERNELVER + prepare_kdump_bootinfo + if [ $? -ne 0 ]; then + return 1 fi
- kdump_kernel="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}" - - DEFAULT_INITRD="${KDUMP_BOOTDIR}/initramfs-`uname -r`.img" - DEFAULT_INITRD_BAK="${KDUMP_BOOTDIR}/.initramfs-`uname -r`.img.default" + DEFAULT_INITRD_BAK="$KDUMP_BOOTDIR/.$(basename $DEFAULT_INITRD).default" if [ $DEFAULT_DUMP_MODE == "fadump" ]; then TARGET_INITRD="$DEFAULT_INITRD"
@@ -320,7 +316,7 @@ setup_initrd() # with fadump aware initrd backup_default_initrd else - TARGET_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img" + TARGET_INITRD="$KDUMP_INITRD"
# check if a backup of default initrd exists. If yes, # it signifies a switch from fadump mode. So, restore @@ -360,25 +356,25 @@ check_files_modified() EXTRA_BINS="$EXTRA_BINS $CHECK_FILES" CHECK_FILES=`grep ^extra_bins $KDUMP_CONFIG_FILE | cut -d\ -f2-` 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"
# Check for any updated extra module EXTRA_MODULES="$(grep ^extra_modules $KDUMP_CONFIG_FILE | sed 's/^extra_modules\s*//')" if [ -n "$EXTRA_MODULES" ]; then - if [ -e /lib/modules/$kdump_kver/modules.dep ]; then - files="$files /lib/modules/$kdump_kver/modules.dep" + if [ -e /lib/modules/$KDUMP_KERNELVER/modules.dep ]; then + files="$files /lib/modules/$KDUMP_KERNELVER/modules.dep" fi 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 files="$files $_module_file" 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 else # 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" fi fi @@ -472,8 +468,8 @@ check_dump_fs_modified() check_block_and_slaves_all _record_block_drivers "$(get_maj_min "$_target")" for _driver in $_target_drivers; do # Skip deprecated/invalid driver name or built-in module - _module_name=$(modinfo --set-version "$kdump_kver" -F name $_driver 2>/dev/null) - _module_filename=$(modinfo --set-version "$kdump_kver" -n $_driver 2>/dev/null) + _module_name=$(modinfo --set-version "$KDUMP_KERNELVER" -F name $_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 continue fi @@ -540,7 +536,7 @@ check_wdt_modified() # modalias. Currently load all of them. # TODO: Need to find a way to avoid any unwanted module # 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 for i in $_wdtdrv; do _drivers[$i]=1 @@ -555,7 +551,7 @@ check_wdt_modified() [[ -f "$_wdtppath/modalias" ]] || continue
_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 for i in $_wdtdrv; do _drivers[$i]=1 @@ -700,7 +696,7 @@ load_kdump()
$KEXEC $KEXEC_ARGS $standard_kexec_args \ --command-line="$KDUMP_COMMANDLINE" \ - --initrd=$TARGET_INITRD $kdump_kernel + --initrd=$TARGET_INITRD $KDUMP_KERNEL if [ $? == 0 ]; then echo "kexec: loaded kdump kernel" return 0
Now all atomic special workaround is removed, we can remove the atomic detection function.
Signed-off-by: Kairui Song kasong@redhat.com --- kdump-lib.sh | 5 ----- 1 file changed, 5 deletions(-)
diff --git a/kdump-lib.sh b/kdump-lib.sh index c35b904..b2c48ef 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -321,11 +321,6 @@ kdump_get_persistent_dev() { echo $(get_persistent_dev "$dev") }
-is_atomic() -{ - grep -q "ostree" /proc/cmdline -} - is_ipv6_address() { echo $1 | grep -q ":"