Kdump service runs too late, so early crashes will have no chance to get kdump kernel booting. A proposal is add a dracut module to load pre-built kernel and initramfs for early kdump, one can provide "rd.early-kdump" in grub commandline to enable, then the service can load those files like original kdump, which is disabled by default.
For the normal kdump service in real root init path, it can check whether the pre-built kernel and initramfs has been loaded. It has no conflict with the early kdump.
Early kdump puts the pre-built kernel and initramfs for kdump into the initramfs for boot, the rebuilt initramfs will become large.
By the way, we move some common functions from kdumpctl to kdump-lib.sh. In addition, early kdump doesn't support fadump.
Signed-off-by: Lianbo Jiang lijiang@redhat.com --- dracut-early-kdump-module-setup.sh | 23 +++++ dracut-early-kdump.service | 24 +++++ dracut-early-kdump.sh | 138 +++++++++++++++++++++++++++++ early-kdump-howto.txt | 58 ++++++++++++ kdump-lib.sh | 123 ++++++++++++++++++++++++++ kdump.sysconfig | 3 + kdump.sysconfig.i386 | 3 + kdump.sysconfig.ppc64 | 3 + kdump.sysconfig.ppc64le | 3 + kdump.sysconfig.s390x | 3 + kdump.sysconfig.x86_64 | 3 + kdumpctl | 177 +++++++++++-------------------------- kexec-tools.spec | 13 +++ mkdumprd.8 | 3 + 14 files changed, 454 insertions(+), 123 deletions(-) create mode 100755 dracut-early-kdump-module-setup.sh create mode 100644 dracut-early-kdump.service create mode 100755 dracut-early-kdump.sh create mode 100644 early-kdump-howto.txt
diff --git a/dracut-early-kdump-module-setup.sh b/dracut-early-kdump-module-setup.sh new file mode 100755 index 0000000..bc4d7dc --- /dev/null +++ b/dracut-early-kdump-module-setup.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +check() { + if [ ! -f /etc/sysconfig/kdump ] || [ ! -f /lib/kdump/kdump-lib.sh ] + then + return 1 + fi + return 0 +} + +depends() { + echo "base shutdown" + return 0 +} + +install() { + inst_simple "/etc/sysconfig/kdump" "/etc/sysconfig/kdump" + inst_simple "/usr/sbin/kexec" "/usr/sbin/kexec" + inst_script "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh" + inst_script "$moddir/early-kdump.sh" "/usr/bin/early-kdump" + inst_simple "$moddir/early-kdump.service" "${systemdsystemunitdir}/early-kdump.service" + ln_r "${systemdsystemunitdir}/early-kdump.service" "${systemdsystemunitdir}/initrd.target.wants/early-kdump.service" +} diff --git a/dracut-early-kdump.service b/dracut-early-kdump.service new file mode 100644 index 0000000..8282c49 --- /dev/null +++ b/dracut-early-kdump.service @@ -0,0 +1,24 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See systemd.special(7) for details + +[Unit] +Description=early kdump +DefaultDependencies=yes +After=dracut-cmdline.service +Before=dracut-pre-mount.service + +[Service] +Environment=DRACUT_SYSTEMD=1 +Type=oneshot +ExecStart=/bin/early-kdump +KillMode=process + +#Bash ignore SIGTERM, so we send SIGHUP instead, to ensure that bash +#terminates cleanly. +KillSignal=SIGHUP diff --git a/dracut-early-kdump.sh b/dracut-early-kdump.sh new file mode 100755 index 0000000..067ad5c --- /dev/null +++ b/dracut-early-kdump.sh @@ -0,0 +1,138 @@ +#! /bin/sh + +KEXEC=/sbin/kexec +standard_kexec_args="-p" + +EARLY_KDUMP_INITRD="" +EARLY_KDUMP_KERNEL="" +EARLY_KDUMP_CMDLINE="" +EARLY_KDUMP_KERNELVER="" +EARLY_KEXEC_ARGS="" + +#source lib and configure +. /lib/dracut-lib.sh +. /lib/kdump-lib.sh +. /etc/sysconfig/kdump + +prepare_parameters() +{ + local cmdline id + + if [ -z "$EARLY_KDUMP_CMDLINE" ]; then + cmdline=$(cat /proc/cmdline) + else + cmdline=${EARLY_KDUMP_CMDLINE} + fi + + cmdline=$(remove_cmdline_param "$cmdline" crashkernel panic_on_warn) + cmdline=$(remove_cmdline_param "$cmdline" ${KDUMP_COMMANDLINE_REMOVE}) + + # Always remove "root=X", as we now explicitly generate all kinds + # of dump target mount information including root fs. + # + # We do this before KDUMP_COMMANDLINE_APPEND, if one really cares + # about it(e.g. for debug purpose), then can pass "root=X" using + # KDUMP_COMMANDLINE_APPEND. + cmdline=$(remove_cmdline_param "$cmdline" root) + + # With the help of "--hostonly-cmdline", we can avoid some interitage. + cmdline=$(remove_cmdline_param "$cmdline" rd.lvm.lv rd.luks.uuid rd.dm.uuid rd.md.uuid fcoe) + cmdline="${cmdline} ${KDUMP_COMMANDLINE_APPEND}" + id=$(get_bootcpu_apicid) + if [ ! -z ${id} ] ; then + cmdline=$(append_cmdline "${cmdline}" disable_cpu_apicid ${id}) + fi + EARLY_KDUMP_CMDLINE=$cmdline + + if [ -z "$KDUMP_BOOTDIR" ]; then + if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then + KDUMP_BOOTDIR="/boot" + else + eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1) + KDUMP_BOOTDIR="/boot"$(dirname $BOOT_IMAGE) + fi + fi + + #make early-kdump kernel string + if [ -z "$EARLY_KDUMP_KERNELVER" ]; then + EARLY_KDUMP_KERNELVER=`uname -r` + fi + EARLY_KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${EARLY_KDUMP_KERNELVER}${KDUMP_IMG_EXT}" + + #make early-kdump initrd string + EARLY_KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${EARLY_KDUMP_KERNELVER}kdump.img" +} + +early_kdump_load() +{ + check_kdump_feasibility + if [ $? -ne 0 ]; then + return 1 + fi + + if is_fadump_capable; then + echo "early kdump doesn't support fadump: [WARNING]" + return 1 + fi + + check_current_kdump_status + if [ $? == 0 ]; then + return 1 + fi + + prepare_parameters + + ARCH=`uname -m` + if [ "$ARCH" == "i686" -o "$ARCH" == "i386" ] + then + need_64bit_headers + if [ $? == 1 ] + then + FOUND_ELF_ARGS=`echo $EARLY_KEXEC_ARGS | grep elf32-core-headers` + if [ -n "$FOUND_ELF_ARGS" ] + then + echo -n "Warning: elf32-core-headers overrides correct elf64 setting" + echo + else + EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS --elf64-core-headers" + fi + else + FOUND_ELF_ARGS=`echo $EARLY_KEXEC_ARGS | grep elf64-core-headers` + if [ -z "$FOUND_ELF_ARGS" ] + then + EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS --elf32-core-headers" + fi + fi + fi + + #secure boot + if is_secure_boot_enforced; then + echo "Secure Boot is enabled. Using kexec file based syscall." + EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS -s" + fi + + $KEXEC ${EARLY_KEXEC_ARGS} $standard_kexec_args \ + --command-line="$EARLY_KDUMP_CMDLINE" \ + --initrd=$EARLY_KDUMP_INITRD $EARLY_KDUMP_KERNEL + if [ $? == 0 ]; then + echo "kexec: loaded early-kdump kernel" + return 0 + else + echo "kexec: failed to load early-kdump kernel" + return 1 + fi +} + +setearlykdump() +{ + if getargbool 0 rd.early-kdump; then + echo "early-kdump is enabled." + early_kdump_load + else + echo "early-kdump is not enabled by default." + fi + + return 0 +} + +setearlykdump diff --git a/early-kdump-howto.txt b/early-kdump-howto.txt new file mode 100644 index 0000000..aae8d7b --- /dev/null +++ b/early-kdump-howto.txt @@ -0,0 +1,58 @@ +Early Kdump HOWTO + +Introduction + +Kdump service runs too late, so early crashes will have no chance to get kdump +kernel booting. A proposal is add a dracut module to load pre-built kernel and +initramfs for early kdump, one can provide "rd.early-kdump" in grub commandline +to enable, then the service can load those files like original kdump, which is +disabled by default. + +For the normal kdump service in real root init path, it can check whether the +prebuilt kernel and initramfs have been loaded. It has no conflict with the early +kdump. + +How to configure early kdump: + +We assume if you're reading this document, you should already have kexec-tools +installed. If not, you install it via the following command: + + # yum install kexec-tools + +For early kdump, you can set "EARLY_KDUMP_SUPPORT=yes" in /etc/sysconfig/kdump +if you want to rebuild the initramfs for early kdump, and then: + # kdumpctl restart + +By the way, the initramfs will become large, early kdump put the kernel and +initramfs for kdump into the initramfs for boot. If you set "EARLY_KDUMP_SUPPORT +=no" in /etc/sysconfig/kdump, which will restore previous initramfs, that is to +say, it doesn't have early kdump. + + +Next up, we need to modify some boot parameters to enable early kdump, it's +very easy to append "rd.early-kdump" to your kernel boot parameters in grub. +After making said changes, reboot your system to take effect. Of course, if +you want to disable early kdump, you can simply remove "rd.early-kdump" from +kernel boot parameters in grub, and reboot system like above. + +Now that you've got some messages about early kdump, you can check whether early +kdump is successful like this: + + # journalctl -x|grep early-kdump + +Then, you will see some useful logs, for exapmles: + +1. if early kdump is successful. +Mar 09 09:57:56 localhost.localdomain early-kdump[477]: early-kdump is enabled. +Mar 09 09:57:56 localhost.localdomain early-kdump[477]: kexec: loaded early- +kdump kernel + +2. if early kdump is disabled. +Mar 09 10:02:47 localhost.localdomain early-kdump[474]: early-kdump is not en- +abled by default. + +Notes: +You will need to make sure that appropriate initramfs and vmlinuz, if early kdump +doesn't find them it will refuse to go on. + +In addition, early kdump doesn't support fadump, maybe it will have this in future. diff --git a/kdump-lib.sh b/kdump-lib.sh index d981c4f..a1a7660 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -485,3 +485,126 @@ get_dracut_args_target() { echo $1 | grep "--mount" | sed "s/.*--mount .(.*)/\1/" | cut -d' ' -f1 } + +check_crash_mem_reserved() +{ + local mem_reserved + + mem_reserved=$(cat /sys/kernel/kexec_crash_size) + if [ $mem_reserved -eq 0 ]; then + echo "No memory reserved for crash kernel" + return 1 + fi + + return 0 +} + +check_kdump_feasibility() +{ + if [ ! -e /sys/kernel/kexec_crash_loaded ]; then + echo "Kdump is not supported on this kernel" + return 1 + fi + check_crash_mem_reserved + return $? +} + +check_current_kdump_status() +{ + if [ ! -f /sys/kernel/kexec_crash_loaded ];then + echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel" + return 1 + fi + + rc=`cat /sys/kernel/kexec_crash_loaded` + if [ $rc == 1 ]; then + return 0 + else + return 1 + fi +} + +# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>] +# Remove a list of kernel parameters from a given kernel cmdline and print the result. +# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists. +remove_cmdline_param() +{ + local cmdline=$1 + shift + + for arg in $@; do + cmdline=`echo $cmdline | \ + sed -e "s/\b$arg=[^ ]*//g" \ + -e "s/^$arg\b//g" \ + -e "s/[[:space:]]$arg\b//g" \ + -e "s/\s+/ /g"` + done + echo $cmdline +} + +# +# This function returns the "apicid" of the boot +# cpu (cpu 0) if present. +# +get_bootcpu_apicid() +{ + awk ' \ + BEGIN { CPU = "-1"; } \ + $1=="processor" && $2==":" { CPU = $NF; } \ + CPU=="0" && /^apicid/ { print $NF; } \ + ' \ + /proc/cpuinfo +} + +# +# This function appends argument "$2=$3" to string ($1) if not already present. +# +append_cmdline() +{ + local cmdline=$1 + local newstr=${cmdline/$2/""} + + # unchanged str implies argument wasn't there + if [ "$cmdline" == "$newstr" ]; then + cmdline="${cmdline} ${2}=${3}" + fi + + echo $cmdline +} + +# This function check iomem and determines if we have more than +# 4GB of ram available. Returns 1 if we do, 0 if we dont +need_64bit_headers() +{ + return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \ + print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'` +} + +# Check if secure boot is being enforced. +# +# Per Peter Jones, we need check efivar SecureBoot-$(the UUID) and +# SetupMode-$(the UUID), they are both 5 bytes binary data. The first four +# bytes are the attributes associated with the variable and can safely be +# ignored, the last bytes are one-byte true-or-false variables. If SecureBoot +# is 1 and SetupMode is 0, then secure boot is being enforced. +# +# Assume efivars is mounted at /sys/firmware/efi/efivars. +is_secure_boot_enforced() +{ + local secure_boot_file setup_mode_file + local secure_boot_byte setup_mode_byte + + secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null) + setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null) + + if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then + secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' $secure_boot_file|cut -d' ' -f 5) + setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' $setup_mode_file|cut -d' ' -f 5) + + if [ "$secure_boot_byte" = "1" ] && [ "$setup_mode_byte" = "0" ]; then + return 0 + fi + fi + + return 1 +} diff --git a/kdump.sysconfig b/kdump.sysconfig index ffe1df8..b95807c 100644 --- a/kdump.sysconfig +++ b/kdump.sysconfig @@ -35,3 +35,6 @@ KEXEC_ARGS=""
#What is the image type used for kdump KDUMP_IMG="vmlinuz" + +#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.i386 b/kdump.sysconfig.i386 index 18c407e..6ece161 100644 --- a/kdump.sysconfig.i386 +++ b/kdump.sysconfig.i386 @@ -38,3 +38,6 @@ KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT="" + +#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.ppc64 b/kdump.sysconfig.ppc64 index be8e794..ac1ae2d 100644 --- a/kdump.sysconfig.ppc64 +++ b/kdump.sysconfig.ppc64 @@ -39,4 +39,7 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" + #Specify the action after failure diff --git a/kdump.sysconfig.ppc64le b/kdump.sysconfig.ppc64le index be8e794..ac1ae2d 100644 --- a/kdump.sysconfig.ppc64le +++ b/kdump.sysconfig.ppc64le @@ -39,4 +39,7 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" + #Specify the action after failure diff --git a/kdump.sysconfig.s390x b/kdump.sysconfig.s390x index b3aec3c..f4e63a5 100644 --- a/kdump.sysconfig.s390x +++ b/kdump.sysconfig.s390x @@ -41,3 +41,6 @@ KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT="" + +#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.x86_64 b/kdump.sysconfig.x86_64 index f269d02..418b240 100644 --- a/kdump.sysconfig.x86_64 +++ b/kdump.sysconfig.x86_64 @@ -38,3 +38,6 @@ KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT="" + +#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdumpctl b/kdumpctl index 4280e7e..d6fc12a 100755 --- a/kdumpctl +++ b/kdumpctl @@ -10,6 +10,7 @@ DRACUT_MODULES_FILE="/usr/lib/dracut/modules.txt" SAVE_PATH=/var/crash SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum" +INITRD_CHECKSUM_EARLYKDUMP="/boot/.earlykdump_initrd_checksum" DUMP_TARGET="" DEFAULT_INITRD="" DEFAULT_INITRD_BAK="" @@ -62,54 +63,6 @@ determine_dump_mode() fi }
-# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>] -# Remove a list of kernel parameters from a given kernel cmdline and print the result. -# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists. -remove_cmdline_param() -{ - local cmdline=$1 - shift - - for arg in $@; do - cmdline=`echo $cmdline | \ - sed -e "s/\b$arg=[^ ]*//g" \ - -e "s/^$arg\b//g" \ - -e "s/[[:space:]]$arg\b//g" \ - -e "s/\s+/ /g"` - done - echo $cmdline -} - -# -# This function returns the "apicid" of the boot -# cpu (cpu 0) if present. -# -get_bootcpu_apicid() -{ - awk ' \ - BEGIN { CPU = "-1"; } \ - $1=="processor" && $2==":" { CPU = $NF; } \ - CPU=="0" && /^apicid/ { print $NF; } \ - ' \ - /proc/cpuinfo -} - -# -# This function appends argument "$2=$3" to string ($1) if not already present. -# -append_cmdline() -{ - local cmdline=$1 - local newstr=${cmdline/$2/""} - - # unchanged str implies argument wasn't there - if [ "$cmdline" == "$newstr" ]; then - cmdline="${cmdline} ${2}=${3}" - fi - - echo $cmdline -} - # This function performs a series of edits on the command line. # Store the final result in global $KDUMP_COMMANDLINE. prepare_cmdline() @@ -208,6 +161,53 @@ rebuild_kdump_initrd() return 0 }
+restore_default_initramfs() +{ + if [ -f ${DEFAULT_INITRD_BAK} ] && [ -f ${INITRD_CHECKSUM_EARLYKDUMP} ]; then + # verify checksum before restoring + backup_checksum=`sha1sum ${DEFAULT_INITRD_BAK} | awk '{ print $1 }'` + default_checksum=`cat ${INITRD_CHECKSUM_EARLYKDUMP} | awk '{ print $1 }'` + if [ "${default_checksum}" != "${backup_checksum}" ]; then + echo "WARNING: checksum mismatch! Can't restore original initrd..." + else + rm -f ${INITRD_CHECKSUM_EARLYKDUMP} + mv ${DEFAULT_INITRD_BAK} ${DEFAULT_INITRD} + if [[ $? -eq 0 ]]; then + echo "Restored original initrd." + sync + fi + fi + fi +} + +rebuild_early_kdump_initrd() +{ + if [ ! -f "${DEFAULT_INITRD_BAK}" ]; then + if [ ! -f "${DEFAULT_INITRD}" ]; then + echo "${DEFAULT_INITRD} is not exist." + return 1 + fi + echo "early kdump is backing up ${DEFAULT_INITRD} ..." + sha1sum ${DEFAULT_INITRD} > ${INITRD_CHECKSUM_EARLYKDUMP} + cp ${DEFAULT_INITRD} ${DEFAULT_INITRD_BAK} + if [ $? -ne 0 ]; then + echo "WARNING: failed to backup ${DEFAULT_INITRD} in early kdump." + rm -f ${DEFAULT_INITRD_BAK} + return 1 + fi + sync + fi + + dracut -I ${kdump_kernel} -I ${TARGET_INITRD} -v ${DEFAULT_INITRD} --force + if [ $? != 0 ]; then + echo "dracut: failed to make early kdump initrd" >&2 + restore_default_initramfs + return 1 + fi + + return 0 +} + rebuild_initrd() { if [ $DEFAULT_DUMP_MODE == "fadump" ]; then @@ -610,6 +610,12 @@ check_rebuild() return 1 fi
+ if [[ $EARLY_KDUMP_SUPPORT = "yes" ]]; then + rebuild_early_kdump_initrd + elif [[ $EARLY_KDUMP_SUPPORT = "no" ]]; then + restore_default_initramfs + fi + _force_no_rebuild=`grep ^force_no_rebuild $KDUMP_CONFIG_FILE 2>/dev/null` if [ $? -eq 0 ]; then force_no_rebuild=`echo $_force_no_rebuild | cut -d' ' -f2` @@ -686,14 +692,6 @@ check_rebuild() return $? }
-# This function check iomem and determines if we have more than -# 4GB of ram available. Returns 1 if we do, 0 if we dont -need_64bit_headers() -{ - return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \ - print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'` -} - # Load the kdump kernel specified in /etc/sysconfig/kdump # If none is specified, try to load a kdump kernel with the same version # as the currently running kernel. @@ -850,21 +848,6 @@ check_current_fadump_status() return 1 }
-check_current_kdump_status() -{ - if [ ! -f /sys/kernel/kexec_crash_loaded ];then - echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel" - return 1 - fi - - rc=`cat /sys/kernel/kexec_crash_loaded` - if [ $rc == 1 ]; then - return 0 - else - return 1 - fi -} - check_current_status() { if [ $DEFAULT_DUMP_MODE == "fadump" ]; then @@ -974,58 +957,6 @@ selinux_relabel() done }
-# Check if secure boot is being enforced. -# -# Per Peter Jones, we need check efivar SecureBoot-$(the UUID) and -# SetupMode-$(the UUID), they are both 5 bytes binary data. The first four -# bytes are the attributes associated with the variable and can safely be -# ignored, the last bytes are one-byte true-or-false variables. If SecureBoot -# is 1 and SetupMode is 0, then secure boot is being enforced. -# -# Assume efivars is mounted at /sys/firmware/efi/efivars. -is_secure_boot_enforced() -{ - local secure_boot_file setup_mode_file - local secure_boot_byte setup_mode_byte - - secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null) - setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null) - - if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then - secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' $secure_boot_file|cut -d' ' -f 5) - setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' $setup_mode_file|cut -d' ' -f 5) - - if [ "$secure_boot_byte" = "1" ] && [ "$setup_mode_byte" = "0" ]; then - return 0 - fi - fi - - return 1 -} - -check_crash_mem_reserved() -{ - local mem_reserved - - mem_reserved=$(cat /sys/kernel/kexec_crash_size) - if [ $mem_reserved -eq 0 ]; then - echo "No memory reserved for crash kernel" - return 1 - fi - - return 0 -} - -check_kdump_feasibility() -{ - if [ ! -e /sys/kernel/kexec_crash_loaded ]; then - echo "Kdump is not supported on this kernel" - return 1 - fi - check_crash_mem_reserved - return $? -} - check_fence_kdump_config() { local hostname=`hostname` diff --git a/kexec-tools.spec b/kexec-tools.spec index f04527c..9ecaefd 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -29,6 +29,7 @@ Source24: kdump-lib-initramfs.sh Source25: kdump.sysconfig.ppc64le Source26: kdumpctl.8 Source27: live-image-kdump-howto.txt +Source28: early-kdump-howto.txt
####################################### # These are sources for mkdumpramfs @@ -42,6 +43,9 @@ Source104: dracut-kdump-emergency.service Source105: dracut-kdump-error-handler.service Source106: dracut-kdump-capture.service Source107: dracut-kdump-emergency.target +Source108: dracut-early-kdump.sh +Source109: dracut-early-kdump.service +Source110: dracut-early-kdump-module-setup.sh
Requires(post): systemd-units Requires(preun): systemd-units @@ -136,6 +140,7 @@ rm -f kexec-tools.spec.in cp %{SOURCE10} . cp %{SOURCE21} . cp %{SOURCE27} . +cp %{SOURCE28} .
make %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 @@ -194,6 +199,7 @@ make -C kdump-anaconda-addon install DESTDIR=$RPM_BUILD_ROOT %find_lang kdump-anaconda-addon
%define remove_dracut_prefix() %(echo -n %1|sed 's/.*dracut-//g') +%define remove_dracut_early_kdump_prefix() %(echo -n %1|sed 's/.*dracut-early-kdump-//g')
# deal with dracut modules mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase @@ -207,6 +213,12 @@ cp %{SOURCE106} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpb cp %{SOURCE107} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE107}} chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE100}} chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE101}} +mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump +cp %{SOURCE108} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} +cp %{SOURCE109} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE109}} +cp %{SOURCE110} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE110}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE110}}
%define dracutlibdir %{_prefix}/lib/dracut @@ -305,6 +317,7 @@ done %license COPYING %doc TODO %doc kexec-kdump-howto.txt +%doc early-kdump-howto.txt %doc kdump-in-cluster-environment.txt %doc live-image-kdump-howto.txt %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 diff --git a/mkdumprd.8 b/mkdumprd.8 index 7faae57..6e22e0a 100644 --- a/mkdumprd.8 +++ b/mkdumprd.8 @@ -17,6 +17,9 @@ be loaded in the initramfs (based on configuration retrieved from \fBmkdumprd\fR add a new \fBdracut\fR module 99kdumpbase and use \fBdracut\fR utility to generate the initramfs.
+\fBmkdumprd\fR add a new \fBdracut\fR module 99earlykdump and use \fBdracut\fR +utility to generate the initramfs. + \fBmkdumprd\fR was not intended for casual use outside of the service initialization script for the kdump utility, and should not be run manually. If you require a custom kdump initramfs image, it is suggested that you use the
Hello Lianbo,
On 03/15/2018 12:32 PM, Lianbo Jiang wrote:
Kdump service runs too late, so early crashes will have no chance to get kdump kernel booting. A proposal is add a dracut module to load pre-built kernel and initramfs for early kdump, one can provide "rd.early-kdump" in grub commandline to enable, then the service can load those files like original kdump, which is disabled by default.
For the normal kdump service in real root init path, it can check whether the pre-built kernel and initramfs has been loaded. It has no conflict with the early kdump.
Hmmm.. not sure I understand the term pre-built kernel and initramfs here. Can you please explain the same better in the git log.
Early kdump puts the pre-built kernel and initramfs for kdump into the initramfs for boot, the rebuilt initramfs will become large.
By the way, we move some common functions from kdumpctl to kdump-lib.sh.
Can you please create a separate patch for the same. It would ease the review.
I have mainly some top-level code arrangement reviews on this version. Will try to review the split version in more details.
In addition, early kdump doesn't support fadump.
Signed-off-by: Lianbo Jiang lijiang@redhat.com
dracut-early-kdump-module-setup.sh | 23 +++++ dracut-early-kdump.service | 24 +++++ dracut-early-kdump.sh | 138 +++++++++++++++++++++++++++++ early-kdump-howto.txt | 58 ++++++++++++ kdump-lib.sh | 123 ++++++++++++++++++++++++++ kdump.sysconfig | 3 + kdump.sysconfig.i386 | 3 + kdump.sysconfig.ppc64 | 3 + kdump.sysconfig.ppc64le | 3 + kdump.sysconfig.s390x | 3 + kdump.sysconfig.x86_64 | 3 + kdumpctl | 177 +++++++++++-------------------------- kexec-tools.spec | 13 +++ mkdumprd.8 | 3 + 14 files changed, 454 insertions(+), 123 deletions(-) create mode 100755 dracut-early-kdump-module-setup.sh
Hmmm. the create mode should be 644 right, instead of 755?
create mode 100644 dracut-early-kdump.service create mode 100755 dracut-early-kdump.sh
Same as above.
create mode 100644 early-kdump-howto.txt
diff --git a/dracut-early-kdump-module-setup.sh b/dracut-early-kdump-module-setup.sh new file mode 100755 index 0000000..bc4d7dc --- /dev/null +++ b/dracut-early-kdump-module-setup.sh @@ -0,0 +1,23 @@ +#!/bin/bash
+check() {
- if [ ! -f /etc/sysconfig/kdump ] || [ ! -f /lib/kdump/kdump-lib.sh ]
- then
return 1
- fi
- return 0
+}
+depends() {
- echo "base shutdown"
- return 0
+}
+install() {
- inst_simple "/etc/sysconfig/kdump" "/etc/sysconfig/kdump"
- inst_simple "/usr/sbin/kexec" "/usr/sbin/kexec"
- inst_script "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh"
- inst_script "$moddir/early-kdump.sh" "/usr/bin/early-kdump"
Let's use MACROs for the file/script path(s), so that we can change the MACRO at one location and the helper shell scripts are modified automatically.
- inst_simple "$moddir/early-kdump.service" "${systemdsystemunitdir}/early-kdump.service"
- ln_r "${systemdsystemunitdir}/early-kdump.service" "${systemdsystemunitdir}/initrd.target.wants/early-kdump.service"
+} diff --git a/dracut-early-kdump.service b/dracut-early-kdump.service new file mode 100644 index 0000000..8282c49 --- /dev/null +++ b/dracut-early-kdump.service @@ -0,0 +1,24 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version.
+# See systemd.special(7) for details
+[Unit] +Description=early kdump +DefaultDependencies=yes +After=dracut-cmdline.service +Before=dracut-pre-mount.service
+[Service] +Environment=DRACUT_SYSTEMD=1 +Type=oneshot +ExecStart=/bin/early-kdump +KillMode=process
+#Bash ignore SIGTERM, so we send SIGHUP instead, to ensure that bash +#terminates cleanly. +KillSignal=SIGHUP diff --git a/dracut-early-kdump.sh b/dracut-early-kdump.sh new file mode 100755 index 0000000..067ad5c --- /dev/null +++ b/dracut-early-kdump.sh @@ -0,0 +1,138 @@ +#! /bin/sh
+KEXEC=/sbin/kexec +standard_kexec_args="-p"
+EARLY_KDUMP_INITRD="" +EARLY_KDUMP_KERNEL="" +EARLY_KDUMP_CMDLINE="" +EARLY_KDUMP_KERNELVER="" +EARLY_KEXEC_ARGS=""
+#source lib and configure +. /lib/dracut-lib.sh +. /lib/kdump-lib.sh +. /etc/sysconfig/kdump
+prepare_parameters() +{
- local cmdline id
- if [ -z "$EARLY_KDUMP_CMDLINE" ]; then
cmdline=$(cat /proc/cmdline)
- else
cmdline=${EARLY_KDUMP_CMDLINE}
- fi
- cmdline=$(remove_cmdline_param "$cmdline" crashkernel panic_on_warn)
- cmdline=$(remove_cmdline_param "$cmdline" ${KDUMP_COMMANDLINE_REMOVE})
- # Always remove "root=X", as we now explicitly generate all kinds
- # of dump target mount information including root fs.
- #
- # We do this before KDUMP_COMMANDLINE_APPEND, if one really cares
- # about it(e.g. for debug purpose), then can pass "root=X" using
- # KDUMP_COMMANDLINE_APPEND.
- cmdline=$(remove_cmdline_param "$cmdline" root)
- # With the help of "--hostonly-cmdline", we can avoid some interitage.
- cmdline=$(remove_cmdline_param "$cmdline" rd.lvm.lv rd.luks.uuid rd.dm.uuid rd.md.uuid fcoe)
- cmdline="${cmdline} ${KDUMP_COMMANDLINE_APPEND}"
- id=$(get_bootcpu_apicid)
- if [ ! -z ${id} ] ; then
cmdline=$(append_cmdline "${cmdline}" disable_cpu_apicid ${id})
- fi
- EARLY_KDUMP_CMDLINE=$cmdline
- if [ -z "$KDUMP_BOOTDIR" ]; then
if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then
KDUMP_BOOTDIR="/boot"
else
eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1)
KDUMP_BOOTDIR="/boot"$(dirname $BOOT_IMAGE)
fi
- fi
- #make early-kdump kernel string
- if [ -z "$EARLY_KDUMP_KERNELVER" ]; then
EARLY_KDUMP_KERNELVER=`uname -r`
- fi
- EARLY_KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${EARLY_KDUMP_KERNELVER}${KDUMP_IMG_EXT}"
- #make early-kdump initrd string
- EARLY_KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${EARLY_KDUMP_KERNELVER}kdump.img"
+}
+early_kdump_load() +{
- check_kdump_feasibility
- if [ $? -ne 0 ]; then
return 1
- fi
- if is_fadump_capable; then
echo "early kdump doesn't support fadump: [WARNING]"
return 1
- fi
- check_current_kdump_status
- if [ $? == 0 ]; then
return 1
- fi
- prepare_parameters
- ARCH=`uname -m`
- if [ "$ARCH" == "i686" -o "$ARCH" == "i386" ]
- then
need_64bit_headers
if [ $? == 1 ]
then
FOUND_ELF_ARGS=`echo $EARLY_KEXEC_ARGS | grep elf32-core-headers`
if [ -n "$FOUND_ELF_ARGS" ]
then
echo -n "Warning: elf32-core-headers overrides correct elf64 setting"
echo
else
EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS --elf64-core-headers"
fi
else
FOUND_ELF_ARGS=`echo $EARLY_KEXEC_ARGS | grep elf64-core-headers`
if [ -z "$FOUND_ELF_ARGS" ]
then
EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS --elf32-core-headers"
fi
fi
- fi
- #secure boot
- if is_secure_boot_enforced; then
echo "Secure Boot is enabled. Using kexec file based syscall."
EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS -s"
- fi
- $KEXEC ${EARLY_KEXEC_ARGS} $standard_kexec_args \
--command-line="$EARLY_KDUMP_CMDLINE" \
--initrd=$EARLY_KDUMP_INITRD $EARLY_KDUMP_KERNEL
- if [ $? == 0 ]; then
echo "kexec: loaded early-kdump kernel"
return 0
- else
echo "kexec: failed to load early-kdump kernel"
return 1
- fi
+}
+setearlykdump()
Let's use underscores '_' for consistency in function names, so something like 'set_early_kdump' instead of setearlykdump.
Please use the same naming conventions throughout the new helper files created.
+{
- if getargbool 0 rd.early-kdump; then
echo "early-kdump is enabled."
early_kdump_load
- else
echo "early-kdump is not enabled by default."
- fi
- return 0
+}
+setearlykdump diff --git a/early-kdump-howto.txt b/early-kdump-howto.txt new file mode 100644 index 0000000..aae8d7b --- /dev/null +++ b/early-kdump-howto.txt @@ -0,0 +1,58 @@ +Early Kdump HOWTO
+Introduction
+Kdump service runs too late, so early crashes will have no chance to get kdump +kernel booting.
May be we can reword this to something like: "Since Kdump service starts to run too late, if we have a early crash before the Kdump service gets a chance to start, the kdump kernel will not be loaded for the crash.
This will cause crash related information to be lost.
A proposal is add a dracut module to load pre-built kernel and
^^^ Since this is the help documentation we can get rid of the wording "A proposal"
+initramfs for early kdump, one can provide "rd.early-kdump" in grub commandline +to enable, then the service can load those files like original kdump, which is +disabled by default.
+For the normal kdump service in real root init path, it can check whether the +prebuilt kernel and initramfs have been loaded. It has no conflict with the early +kdump.
Again we need to probably reword this better, especially to indicate what we mean by the terms pre-built kernel and initramfs here.
+How to configure early kdump:
+We assume if you're reading this document, you should already have kexec-tools +installed. If not, you install it via the following command:
- # yum install kexec-tools
+For early kdump, you can set "EARLY_KDUMP_SUPPORT=yes" in /etc/sysconfig/kdump +if you want to rebuild the initramfs for early kdump, and then:
- # kdumpctl restart
+By the way, the initramfs will become large, early kdump put the kernel and +initramfs for kdump into the initramfs for boot.
May be reword this as "If you enable early kdump support, it will put the kernel and initramfs for kdump into the initramfs for boot, thereby causing the initramfs size to inflate."
Lets add a blank line here for more clarity.
If you set "EARLY_KDUMP_SUPPORT +=no" in /etc/sysconfig/kdump, which will restore previous initramfs, that is to +say, it doesn't have early kdump.
Let's reword this as "If you set "EARLY_KDUMP_SUPPORT=no" in /etc/sysconfig/kdump, early kdump support is disabled."
Please remove extra blank line.
+Next up, we need to modify some boot parameters to enable early kdump, it's +very easy to append "rd.early-kdump" to your kernel boot parameters in grub. +After making said changes, reboot your system to take effect. Of course, if +you want to disable early kdump, you can simply remove "rd.early-kdump" from +kernel boot parameters in grub, and reboot system like above.
Can we instead have boolean values for the same (like we normally have for kernel boot parameters like this one):
rd.early-kdump=true for enabling early kdump support rd.early-kdump=false for disabling early kdump support (which is also the default behavior).
+Now that you've got some messages about early kdump, you can check whether early +kdump is successful like this:
Let's reword this as "Once the boot is complete, we can check the status of early kdump support on the command-prompt, using:"
- # journalctl -x|grep early-kdump
+Then, you will see some useful logs, for exapmles:
s/exapmles/examples
+1. if early kdump is successful. +Mar 09 09:57:56 localhost.localdomain early-kdump[477]: early-kdump is enabled. +Mar 09 09:57:56 localhost.localdomain early-kdump[477]: kexec: loaded early- +kdump kernel
+2. if early kdump is disabled. +Mar 09 10:02:47 localhost.localdomain early-kdump[474]: early-kdump is not en- +abled by default.
+Notes: +You will need to make sure that appropriate initramfs and vmlinuz, if early kdump +doesn't find them it will refuse to go on.
This line appears to be incomplete - where should we make sure that the appropriate initramfs and vmlinuz are?
+In addition, early kdump doesn't support fadump, maybe it will have this in future.
We can create a separate heading for KNOWN LIMITATIONS or TO_DO and add the fadump support item here.
diff --git a/kdump-lib.sh b/kdump-lib.sh index d981c4f..a1a7660 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -485,3 +485,126 @@ get_dracut_args_target() { echo $1 | grep "--mount" | sed "s/.*--mount .(.*)/\1/" | cut -d' ' -f1 }
+check_crash_mem_reserved() +{
local mem_reserved
mem_reserved=$(cat /sys/kernel/kexec_crash_size)
if [ $mem_reserved -eq 0 ]; then
echo "No memory reserved for crash kernel"
return 1
fi
return 0
+}
+check_kdump_feasibility() +{
if [ ! -e /sys/kernel/kexec_crash_loaded ]; then
echo "Kdump is not supported on this kernel"
return 1
fi
check_crash_mem_reserved
return $?
+}
+check_current_kdump_status() +{
if [ ! -f /sys/kernel/kexec_crash_loaded ];then
echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel"
return 1
fi
rc=`cat /sys/kernel/kexec_crash_loaded`
if [ $rc == 1 ]; then
return 0
else
return 1
fi
+}
+# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>] +# Remove a list of kernel parameters from a given kernel cmdline and print the result. +# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists. +remove_cmdline_param() +{
local cmdline=$1
shift
for arg in $@; do
cmdline=`echo $cmdline | \
sed -e "s/\b$arg=[^ ]*//g" \
-e "s/^$arg\b//g" \
-e "s/[[:space:]]$arg\b//g" \
-e "s/\s\+/ /g"`
done
echo $cmdline
+}
+# +# This function returns the "apicid" of the boot +# cpu (cpu 0) if present. +# +get_bootcpu_apicid() +{
- awk ' \
BEGIN { CPU = "-1"; } \
$1=="processor" && $2==":" { CPU = $NF; } \
CPU=="0" && /^apicid/ { print $NF; } \
' \
/proc/cpuinfo
+}
+# +# This function appends argument "$2=$3" to string ($1) if not already present. +# +append_cmdline() +{
local cmdline=$1
local newstr=${cmdline/$2/""}
# unchanged str implies argument wasn't there
if [ "$cmdline" == "$newstr" ]; then
cmdline="${cmdline} ${2}=${3}"
fi
echo $cmdline
+}
+# This function check iomem and determines if we have more than +# 4GB of ram available. Returns 1 if we do, 0 if we dont +need_64bit_headers() +{
return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \
print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'`
+}
+# Check if secure boot is being enforced. +# +# Per Peter Jones, we need check efivar SecureBoot-$(the UUID) and +# SetupMode-$(the UUID), they are both 5 bytes binary data. The first four +# bytes are the attributes associated with the variable and can safely be +# ignored, the last bytes are one-byte true-or-false variables. If SecureBoot +# is 1 and SetupMode is 0, then secure boot is being enforced. +# +# Assume efivars is mounted at /sys/firmware/efi/efivars. +is_secure_boot_enforced() +{
local secure_boot_file setup_mode_file
local secure_boot_byte setup_mode_byte
secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null)
setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null)
if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then
secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' $secure_boot_file|cut -d' ' -f 5)
setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' $setup_mode_file|cut -d' ' -f 5)
if [ "$secure_boot_byte" = "1" ] && [ "$setup_mode_byte" = "0" ]; then
return 0
fi
fi
return 1
+} diff --git a/kdump.sysconfig b/kdump.sysconfig index ffe1df8..b95807c 100644 --- a/kdump.sysconfig +++ b/kdump.sysconfig @@ -35,3 +35,6 @@ KEXEC_ARGS=""
#What is the image type used for kdump KDUMP_IMG="vmlinuz"
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.i386 b/kdump.sysconfig.i386 index 18c407e..6ece161 100644 --- a/kdump.sysconfig.i386 +++ b/kdump.sysconfig.i386 @@ -38,3 +38,6 @@ KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.ppc64 b/kdump.sysconfig.ppc64 index be8e794..ac1ae2d 100644 --- a/kdump.sysconfig.ppc64 +++ b/kdump.sysconfig.ppc64 @@ -39,4 +39,7 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT=""
- #Specify the action after failure
diff --git a/kdump.sysconfig.ppc64le b/kdump.sysconfig.ppc64le index be8e794..ac1ae2d 100644 --- a/kdump.sysconfig.ppc64le +++ b/kdump.sysconfig.ppc64le @@ -39,4 +39,7 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT=""
- #Specify the action after failure
diff --git a/kdump.sysconfig.s390x b/kdump.sysconfig.s390x index b3aec3c..f4e63a5 100644 --- a/kdump.sysconfig.s390x +++ b/kdump.sysconfig.s390x @@ -41,3 +41,6 @@ KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.x86_64 b/kdump.sysconfig.x86_64 index f269d02..418b240 100644 --- a/kdump.sysconfig.x86_64 +++ b/kdump.sysconfig.x86_64 @@ -38,3 +38,6 @@ KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdumpctl b/kdumpctl index 4280e7e..d6fc12a 100755 --- a/kdumpctl +++ b/kdumpctl @@ -10,6 +10,7 @@ DRACUT_MODULES_FILE="/usr/lib/dracut/modules.txt" SAVE_PATH=/var/crash SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum" +INITRD_CHECKSUM_EARLYKDUMP="/boot/.earlykdump_initrd_checksum" DUMP_TARGET="" DEFAULT_INITRD="" DEFAULT_INITRD_BAK="" @@ -62,54 +63,6 @@ determine_dump_mode() fi }
-# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>] -# Remove a list of kernel parameters from a given kernel cmdline and print the result. -# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists. -remove_cmdline_param() -{
- local cmdline=$1
- shift
- for arg in $@; do
cmdline=`echo $cmdline | \
sed -e "s/\b$arg=[^ ]*//g" \
-e "s/^$arg\b//g" \
-e "s/[[:space:]]$arg\b//g" \
-e "s/\s\+/ /g"`
- done
- echo $cmdline
-}
-# -# This function returns the "apicid" of the boot -# cpu (cpu 0) if present. -# -get_bootcpu_apicid() -{
- awk ' \
- BEGIN { CPU = "-1"; } \
- $1=="processor" && $2==":" { CPU = $NF; } \
- CPU=="0" && /^apicid/ { print $NF; } \
- ' \
- /proc/cpuinfo
-}
-# -# This function appends argument "$2=$3" to string ($1) if not already present. -# -append_cmdline() -{
- local cmdline=$1
- local newstr=${cmdline/$2/""}
- # unchanged str implies argument wasn't there
- if [ "$cmdline" == "$newstr" ]; then
cmdline="${cmdline} ${2}=${3}"
- fi
- echo $cmdline
-}
- # This function performs a series of edits on the command line. # Store the final result in global $KDUMP_COMMANDLINE. prepare_cmdline()
@@ -208,6 +161,53 @@ rebuild_kdump_initrd() return 0 }
+restore_default_initramfs() +{
- if [ -f ${DEFAULT_INITRD_BAK} ] && [ -f ${INITRD_CHECKSUM_EARLYKDUMP} ]; then
# verify checksum before restoring
backup_checksum=`sha1sum ${DEFAULT_INITRD_BAK} | awk '{ print $1 }'`
default_checksum=`cat ${INITRD_CHECKSUM_EARLYKDUMP} | awk '{ print $1 }'`
if [ "${default_checksum}" != "${backup_checksum}" ]; then
echo "WARNING: checksum mismatch! Can't restore original initrd..."
else
rm -f ${INITRD_CHECKSUM_EARLYKDUMP}
mv ${DEFAULT_INITRD_BAK} ${DEFAULT_INITRD}
if [[ $? -eq 0 ]]; then
echo "Restored original initrd."
sync
fi
fi
- fi
+}
+rebuild_early_kdump_initrd() +{
- if [ ! -f "${DEFAULT_INITRD_BAK}" ]; then
if [ ! -f "${DEFAULT_INITRD}" ]; then
echo "${DEFAULT_INITRD} is not exist."
return 1
fi
echo "early kdump is backing up ${DEFAULT_INITRD} ..."
sha1sum ${DEFAULT_INITRD} > ${INITRD_CHECKSUM_EARLYKDUMP}
cp ${DEFAULT_INITRD} ${DEFAULT_INITRD_BAK}
if [ $? -ne 0 ]; then
echo "WARNING: failed to backup ${DEFAULT_INITRD} in early kdump."
rm -f ${DEFAULT_INITRD_BAK}
return 1
fi
sync
- fi
- dracut -I ${kdump_kernel} -I ${TARGET_INITRD} -v ${DEFAULT_INITRD} --force
- if [ $? != 0 ]; then
echo "dracut: failed to make early kdump initrd" >&2
restore_default_initramfs
return 1
- fi
- return 0
+}
- rebuild_initrd() { if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
@@ -610,6 +610,12 @@ check_rebuild() return 1 fi
- if [[ $EARLY_KDUMP_SUPPORT = "yes" ]]; then
rebuild_early_kdump_initrd
- elif [[ $EARLY_KDUMP_SUPPORT = "no" ]]; then
restore_default_initramfs
- fi
- _force_no_rebuild=`grep ^force_no_rebuild $KDUMP_CONFIG_FILE 2>/dev/null` if [ $? -eq 0 ]; then force_no_rebuild=`echo $_force_no_rebuild | cut -d' ' -f2`
@@ -686,14 +692,6 @@ check_rebuild() return $? }
-# This function check iomem and determines if we have more than -# 4GB of ram available. Returns 1 if we do, 0 if we dont -need_64bit_headers() -{
- return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \
- print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'`
-}
- # Load the kdump kernel specified in /etc/sysconfig/kdump # If none is specified, try to load a kdump kernel with the same version # as the currently running kernel.
@@ -850,21 +848,6 @@ check_current_fadump_status() return 1 }
-check_current_kdump_status() -{
- if [ ! -f /sys/kernel/kexec_crash_loaded ];then
echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel"
return 1
- fi
- rc=`cat /sys/kernel/kexec_crash_loaded`
- if [ $rc == 1 ]; then
return 0
- else
return 1
- fi
-}
- check_current_status() { if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
@@ -974,58 +957,6 @@ selinux_relabel() done }
-# Check if secure boot is being enforced. -# -# Per Peter Jones, we need check efivar SecureBoot-$(the UUID) and -# SetupMode-$(the UUID), they are both 5 bytes binary data. The first four -# bytes are the attributes associated with the variable and can safely be -# ignored, the last bytes are one-byte true-or-false variables. If SecureBoot -# is 1 and SetupMode is 0, then secure boot is being enforced. -# -# Assume efivars is mounted at /sys/firmware/efi/efivars. -is_secure_boot_enforced() -{
- local secure_boot_file setup_mode_file
- local secure_boot_byte setup_mode_byte
- secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null)
- setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null)
- if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then
secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' $secure_boot_file|cut -d' ' -f 5)
setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' $setup_mode_file|cut -d' ' -f 5)
if [ "$secure_boot_byte" = "1" ] && [ "$setup_mode_byte" = "0" ]; then
return 0
fi
- fi
- return 1
-}
-check_crash_mem_reserved() -{
- local mem_reserved
- mem_reserved=$(cat /sys/kernel/kexec_crash_size)
- if [ $mem_reserved -eq 0 ]; then
echo "No memory reserved for crash kernel"
return 1
- fi
- return 0
-}
-check_kdump_feasibility() -{
- if [ ! -e /sys/kernel/kexec_crash_loaded ]; then
echo "Kdump is not supported on this kernel"
return 1
- fi
- check_crash_mem_reserved
- return $?
-}
- check_fence_kdump_config() { local hostname=`hostname`
diff --git a/kexec-tools.spec b/kexec-tools.spec index f04527c..9ecaefd 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -29,6 +29,7 @@ Source24: kdump-lib-initramfs.sh Source25: kdump.sysconfig.ppc64le Source26: kdumpctl.8 Source27: live-image-kdump-howto.txt +Source28: early-kdump-howto.txt
####################################### # These are sources for mkdumpramfs @@ -42,6 +43,9 @@ Source104: dracut-kdump-emergency.service Source105: dracut-kdump-error-handler.service Source106: dracut-kdump-capture.service Source107: dracut-kdump-emergency.target +Source108: dracut-early-kdump.sh +Source109: dracut-early-kdump.service +Source110: dracut-early-kdump-module-setup.sh
Requires(post): systemd-units Requires(preun): systemd-units @@ -136,6 +140,7 @@ rm -f kexec-tools.spec.in cp %{SOURCE10} . cp %{SOURCE21} . cp %{SOURCE27} . +cp %{SOURCE28} .
make %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 @@ -194,6 +199,7 @@ make -C kdump-anaconda-addon install DESTDIR=$RPM_BUILD_ROOT %find_lang kdump-anaconda-addon
%define remove_dracut_prefix() %(echo -n %1|sed 's/.*dracut-//g') +%define remove_dracut_early_kdump_prefix() %(echo -n %1|sed 's/.*dracut-early-kdump-//g')
# deal with dracut modules mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase @@ -207,6 +213,12 @@ cp %{SOURCE106} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpb cp %{SOURCE107} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE107}} chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE100}} chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE101}} +mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump +cp %{SOURCE108} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} +cp %{SOURCE109} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE109}} +cp %{SOURCE110} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE110}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE110}}
%define dracutlibdir %{_prefix}/lib/dracut @@ -305,6 +317,7 @@ done %license COPYING %doc TODO %doc kexec-kdump-howto.txt +%doc early-kdump-howto.txt %doc kdump-in-cluster-environment.txt %doc live-image-kdump-howto.txt %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 diff --git a/mkdumprd.8 b/mkdumprd.8 index 7faae57..6e22e0a 100644 --- a/mkdumprd.8 +++ b/mkdumprd.8 @@ -17,6 +17,9 @@ be loaded in the initramfs (based on configuration retrieved from \fBmkdumprd\fR add a new \fBdracut\fR module 99kdumpbase and use \fBdracut\fR utility to generate the initramfs.
+\fBmkdumprd\fR add a new \fBdracut\fR module 99earlykdump and use \fBdracut\fR +utility to generate the initramfs.
- \fBmkdumprd\fR was not intended for casual use outside of the service initialization script for the kdump utility, and should not be run manually. If you require a custom kdump initramfs image, it is suggested that you use the
在 2018年03月15日 16:45, Bhupesh Sharma 写道:
Hello Lianbo,
On 03/15/2018 12:32 PM, Lianbo Jiang wrote:
Kdump service runs too late, so early crashes will have no chance to get kdump kernel booting. A proposal is add a dracut module to load pre-built kernel and initramfs for early kdump, one can provide "rd.early-kdump" in grub commandline to enable, then the service can load those files like original kdump, which is disabled by default.
For the normal kdump service in real root init path, it can check whether the pre-built kernel and initramfs has been loaded. It has no conflict with the early kdump.
Hmmm.. not sure I understand the term pre-built kernel and initramfs here. Can you please explain the same better in the git log. That is the kdump kernel(vmlinuz-`uname -r`) and initrafms(initramfs-`uname -r`kdump.img).
Thanks for your advice, maybe I will send V3.
Lianbo
Early kdump puts the pre-built kernel and initramfs for kdump into the initramfs for boot, the rebuilt initramfs will become large.
By the way, we move some common functions from kdumpctl to kdump-lib.sh.
Can you please create a separate patch for the same. It would ease the review.
I have mainly some top-level code arrangement reviews on this version. Will try to review the split version in more details.
In addition, early kdump doesn't support fadump.
Signed-off-by: Lianbo Jiang lijiang@redhat.com
dracut-early-kdump-module-setup.sh | 23 +++++ dracut-early-kdump.service | 24 +++++ dracut-early-kdump.sh | 138 +++++++++++++++++++++++++++++ early-kdump-howto.txt | 58 ++++++++++++ kdump-lib.sh | 123 ++++++++++++++++++++++++++ kdump.sysconfig | 3 + kdump.sysconfig.i386 | 3 + kdump.sysconfig.ppc64 | 3 + kdump.sysconfig.ppc64le | 3 + kdump.sysconfig.s390x | 3 + kdump.sysconfig.x86_64 | 3 + kdumpctl | 177 +++++++++++-------------------------- kexec-tools.spec | 13 +++ mkdumprd.8 | 3 + 14 files changed, 454 insertions(+), 123 deletions(-) create mode 100755 dracut-early-kdump-module-setup.sh
Hmmm. the create mode should be 644 right, instead of 755?
create mode 100644 dracut-early-kdump.service create mode 100755 dracut-early-kdump.sh
Same as above.
create mode 100644 early-kdump-howto.txt
diff --git a/dracut-early-kdump-module-setup.sh b/dracut-early-kdump-module-setup.sh new file mode 100755 index 0000000..bc4d7dc --- /dev/null +++ b/dracut-early-kdump-module-setup.sh @@ -0,0 +1,23 @@ +#!/bin/bash
+check() { + if [ ! -f /etc/sysconfig/kdump ] || [ ! -f /lib/kdump/kdump-lib.sh ] + then + return 1 + fi + return 0 +}
+depends() { + echo "base shutdown" + return 0 +}
+install() { + inst_simple "/etc/sysconfig/kdump" "/etc/sysconfig/kdump" + inst_simple "/usr/sbin/kexec" "/usr/sbin/kexec" + inst_script "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh" + inst_script "$moddir/early-kdump.sh" "/usr/bin/early-kdump"
Let's use MACROs for the file/script path(s), so that we can change the MACRO at one location and the helper shell scripts are modified automatically.
+ inst_simple "$moddir/early-kdump.service" "${systemdsystemunitdir}/early-kdump.service" + ln_r "${systemdsystemunitdir}/early-kdump.service" "${systemdsystemunitdir}/initrd.target.wants/early-kdump.service" +} diff --git a/dracut-early-kdump.service b/dracut-early-kdump.service new file mode 100644 index 0000000..8282c49 --- /dev/null +++ b/dracut-early-kdump.service @@ -0,0 +1,24 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version.
+# See systemd.special(7) for details
+[Unit] +Description=early kdump +DefaultDependencies=yes +After=dracut-cmdline.service +Before=dracut-pre-mount.service
+[Service] +Environment=DRACUT_SYSTEMD=1 +Type=oneshot +ExecStart=/bin/early-kdump +KillMode=process
+#Bash ignore SIGTERM, so we send SIGHUP instead, to ensure that bash +#terminates cleanly. +KillSignal=SIGHUP diff --git a/dracut-early-kdump.sh b/dracut-early-kdump.sh new file mode 100755 index 0000000..067ad5c --- /dev/null +++ b/dracut-early-kdump.sh @@ -0,0 +1,138 @@ +#! /bin/sh
+KEXEC=/sbin/kexec +standard_kexec_args="-p"
+EARLY_KDUMP_INITRD="" +EARLY_KDUMP_KERNEL="" +EARLY_KDUMP_CMDLINE="" +EARLY_KDUMP_KERNELVER="" +EARLY_KEXEC_ARGS=""
+#source lib and configure +. /lib/dracut-lib.sh +. /lib/kdump-lib.sh +. /etc/sysconfig/kdump
+prepare_parameters() +{ + local cmdline id
+ if [ -z "$EARLY_KDUMP_CMDLINE" ]; then + cmdline=$(cat /proc/cmdline) + else + cmdline=${EARLY_KDUMP_CMDLINE} + fi
+ cmdline=$(remove_cmdline_param "$cmdline" crashkernel panic_on_warn) + cmdline=$(remove_cmdline_param "$cmdline" ${KDUMP_COMMANDLINE_REMOVE})
+ # Always remove "root=X", as we now explicitly generate all kinds + # of dump target mount information including root fs. + # + # We do this before KDUMP_COMMANDLINE_APPEND, if one really cares + # about it(e.g. for debug purpose), then can pass "root=X" using + # KDUMP_COMMANDLINE_APPEND. + cmdline=$(remove_cmdline_param "$cmdline" root)
+ # With the help of "--hostonly-cmdline", we can avoid some interitage. + cmdline=$(remove_cmdline_param "$cmdline" rd.lvm.lv rd.luks.uuid rd.dm.uuid rd.md.uuid fcoe) + cmdline="${cmdline} ${KDUMP_COMMANDLINE_APPEND}" + id=$(get_bootcpu_apicid) + if [ ! -z ${id} ] ; then + cmdline=$(append_cmdline "${cmdline}" disable_cpu_apicid ${id}) + fi + EARLY_KDUMP_CMDLINE=$cmdline
+ if [ -z "$KDUMP_BOOTDIR" ]; then + if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then + KDUMP_BOOTDIR="/boot" + else + eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1) + KDUMP_BOOTDIR="/boot"$(dirname $BOOT_IMAGE) + fi + fi
+ #make early-kdump kernel string + if [ -z "$EARLY_KDUMP_KERNELVER" ]; then + EARLY_KDUMP_KERNELVER=`uname -r` + fi + EARLY_KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${EARLY_KDUMP_KERNELVER}${KDUMP_IMG_EXT}"
+ #make early-kdump initrd string + EARLY_KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${EARLY_KDUMP_KERNELVER}kdump.img" +}
+early_kdump_load() +{ + check_kdump_feasibility + if [ $? -ne 0 ]; then + return 1 + fi
+ if is_fadump_capable; then + echo "early kdump doesn't support fadump: [WARNING]" + return 1 + fi
+ check_current_kdump_status + if [ $? == 0 ]; then + return 1 + fi
+ prepare_parameters
+ ARCH=`uname -m` + if [ "$ARCH" == "i686" -o "$ARCH" == "i386" ] + then + need_64bit_headers + if [ $? == 1 ] + then + FOUND_ELF_ARGS=`echo $EARLY_KEXEC_ARGS | grep elf32-core-headers` + if [ -n "$FOUND_ELF_ARGS" ] + then + echo -n "Warning: elf32-core-headers overrides correct elf64 setting" + echo + else + EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS --elf64-core-headers" + fi + else + FOUND_ELF_ARGS=`echo $EARLY_KEXEC_ARGS | grep elf64-core-headers` + if [ -z "$FOUND_ELF_ARGS" ] + then + EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS --elf32-core-headers" + fi + fi + fi
+ #secure boot + if is_secure_boot_enforced; then + echo "Secure Boot is enabled. Using kexec file based syscall." + EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS -s" + fi
+ $KEXEC ${EARLY_KEXEC_ARGS} $standard_kexec_args \ + --command-line="$EARLY_KDUMP_CMDLINE" \ + --initrd=$EARLY_KDUMP_INITRD $EARLY_KDUMP_KERNEL + if [ $? == 0 ]; then + echo "kexec: loaded early-kdump kernel" + return 0 + else + echo "kexec: failed to load early-kdump kernel" + return 1 + fi +}
+setearlykdump()
Let's use underscores '_' for consistency in function names, so something like 'set_early_kdump' instead of setearlykdump.
Please use the same naming conventions throughout the new helper files created.
+{ + if getargbool 0 rd.early-kdump; then + echo "early-kdump is enabled." + early_kdump_load + else + echo "early-kdump is not enabled by default." + fi
+ return 0 +}
+setearlykdump diff --git a/early-kdump-howto.txt b/early-kdump-howto.txt new file mode 100644 index 0000000..aae8d7b --- /dev/null +++ b/early-kdump-howto.txt @@ -0,0 +1,58 @@ +Early Kdump HOWTO
+Introduction
+Kdump service runs too late, so early crashes will have no chance to get kdump +kernel booting.
May be we can reword this to something like: "Since Kdump service starts to run too late, if we have a early crash before the Kdump service gets a chance to start, the kdump kernel will not be loaded for the crash.
This will cause crash related information to be lost.
A proposal is add a dracut module to load pre-built kernel and
^^^ Since this is the help documentation we can get rid of the wording "A proposal"
+initramfs for early kdump, one can provide "rd.early-kdump" in grub commandline +to enable, then the service can load those files like original kdump, which is +disabled by default.
+For the normal kdump service in real root init path, it can check whether the +prebuilt kernel and initramfs have been loaded. It has no conflict with the early +kdump.
Again we need to probably reword this better, especially to indicate what we mean by the terms pre-built kernel and initramfs here.
+How to configure early kdump:
+We assume if you're reading this document, you should already have kexec-tools +installed. If not, you install it via the following command:
+ # yum install kexec-tools
+For early kdump, you can set "EARLY_KDUMP_SUPPORT=yes" in /etc/sysconfig/kdump +if you want to rebuild the initramfs for early kdump, and then: + # kdumpctl restart
+By the way, the initramfs will become large, early kdump put the kernel and +initramfs for kdump into the initramfs for boot.
May be reword this as "If you enable early kdump support, it will put the kernel and initramfs for kdump into the initramfs for boot, thereby causing the initramfs size to inflate."
Lets add a blank line here for more clarity.
If you set "EARLY_KDUMP_SUPPORT +=no" in /etc/sysconfig/kdump, which will restore previous initramfs, that is to +say, it doesn't have early kdump.
Let's reword this as "If you set "EARLY_KDUMP_SUPPORT=no" in /etc/sysconfig/kdump, early kdump support is disabled."
Please remove extra blank line.
+Next up, we need to modify some boot parameters to enable early kdump, it's +very easy to append "rd.early-kdump" to your kernel boot parameters in grub. +After making said changes, reboot your system to take effect. Of course, if +you want to disable early kdump, you can simply remove "rd.early-kdump" from +kernel boot parameters in grub, and reboot system like above.
Can we instead have boolean values for the same (like we normally have for kernel boot parameters like this one):
rd.early-kdump=true for enabling early kdump support rd.early-kdump=false for disabling early kdump support (which is also the default behavior).
+Now that you've got some messages about early kdump, you can check whether early +kdump is successful like this:
Let's reword this as "Once the boot is complete, we can check the status of early kdump support on the command-prompt, using:"
+ # journalctl -x|grep early-kdump
+Then, you will see some useful logs, for exapmles:
s/exapmles/examples
+1. if early kdump is successful. +Mar 09 09:57:56 localhost.localdomain early-kdump[477]: early-kdump is enabled. +Mar 09 09:57:56 localhost.localdomain early-kdump[477]: kexec: loaded early- +kdump kernel
+2. if early kdump is disabled. +Mar 09 10:02:47 localhost.localdomain early-kdump[474]: early-kdump is not en- +abled by default.
+Notes: +You will need to make sure that appropriate initramfs and vmlinuz, if early kdump +doesn't find them it will refuse to go on.
This line appears to be incomplete - where should we make sure that the appropriate initramfs and vmlinuz are?
+In addition, early kdump doesn't support fadump, maybe it will have this in future.
We can create a separate heading for KNOWN LIMITATIONS or TO_DO and add the fadump support item here.
diff --git a/kdump-lib.sh b/kdump-lib.sh index d981c4f..a1a7660 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -485,3 +485,126 @@ get_dracut_args_target() { echo $1 | grep "--mount" | sed "s/.*--mount .(.*)/\1/" | cut -d' ' -f1 }
+check_crash_mem_reserved() +{ + local mem_reserved
+ mem_reserved=$(cat /sys/kernel/kexec_crash_size) + if [ $mem_reserved -eq 0 ]; then + echo "No memory reserved for crash kernel" + return 1 + fi
+ return 0 +}
+check_kdump_feasibility() +{ + if [ ! -e /sys/kernel/kexec_crash_loaded ]; then + echo "Kdump is not supported on this kernel" + return 1 + fi + check_crash_mem_reserved + return $? +}
+check_current_kdump_status() +{ + if [ ! -f /sys/kernel/kexec_crash_loaded ];then + echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel" + return 1 + fi
+ rc=`cat /sys/kernel/kexec_crash_loaded` + if [ $rc == 1 ]; then + return 0 + else + return 1 + fi +}
+# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>] +# Remove a list of kernel parameters from a given kernel cmdline and print the result. +# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists. +remove_cmdline_param() +{ + local cmdline=$1 + shift
+ for arg in $@; do + cmdline=`echo $cmdline | \ + sed -e "s/\b$arg=[^ ]*//g" \ + -e "s/^$arg\b//g" \ + -e "s/[[:space:]]$arg\b//g" \ + -e "s/\s+/ /g"` + done + echo $cmdline +}
+# +# This function returns the "apicid" of the boot +# cpu (cpu 0) if present. +# +get_bootcpu_apicid() +{ + awk ' \ + BEGIN { CPU = "-1"; } \ + $1=="processor" && $2==":" { CPU = $NF; } \ + CPU=="0" && /^apicid/ { print $NF; } \ + ' \ + /proc/cpuinfo +}
+# +# This function appends argument "$2=$3" to string ($1) if not already present. +# +append_cmdline() +{ + local cmdline=$1 + local newstr=${cmdline/$2/""}
+ # unchanged str implies argument wasn't there + if [ "$cmdline" == "$newstr" ]; then + cmdline="${cmdline} ${2}=${3}" + fi
+ echo $cmdline +}
+# This function check iomem and determines if we have more than +# 4GB of ram available. Returns 1 if we do, 0 if we dont +need_64bit_headers() +{ + return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \ + print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'` +}
+# Check if secure boot is being enforced. +# +# Per Peter Jones, we need check efivar SecureBoot-$(the UUID) and +# SetupMode-$(the UUID), they are both 5 bytes binary data. The first four +# bytes are the attributes associated with the variable and can safely be +# ignored, the last bytes are one-byte true-or-false variables. If SecureBoot +# is 1 and SetupMode is 0, then secure boot is being enforced. +# +# Assume efivars is mounted at /sys/firmware/efi/efivars. +is_secure_boot_enforced() +{ + local secure_boot_file setup_mode_file + local secure_boot_byte setup_mode_byte
+ secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null) + setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null)
+ if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then + secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' $secure_boot_file|cut -d' ' -f 5) + setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' $setup_mode_file|cut -d' ' -f 5)
+ if [ "$secure_boot_byte" = "1" ] && [ "$setup_mode_byte" = "0" ]; then + return 0 + fi + fi
+ return 1 +} diff --git a/kdump.sysconfig b/kdump.sysconfig index ffe1df8..b95807c 100644 --- a/kdump.sysconfig +++ b/kdump.sysconfig @@ -35,3 +35,6 @@ KEXEC_ARGS="" #What is the image type used for kdump KDUMP_IMG="vmlinuz"
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.i386 b/kdump.sysconfig.i386 index 18c407e..6ece161 100644 --- a/kdump.sysconfig.i386 +++ b/kdump.sysconfig.i386 @@ -38,3 +38,6 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.ppc64 b/kdump.sysconfig.ppc64 index be8e794..ac1ae2d 100644 --- a/kdump.sysconfig.ppc64 +++ b/kdump.sysconfig.ppc64 @@ -39,4 +39,7 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT="" +#early kdump support +EARLY_KDUMP_SUPPORT=""
#Specify the action after failure diff --git a/kdump.sysconfig.ppc64le b/kdump.sysconfig.ppc64le index be8e794..ac1ae2d 100644 --- a/kdump.sysconfig.ppc64le +++ b/kdump.sysconfig.ppc64le @@ -39,4 +39,7 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT="" +#early kdump support +EARLY_KDUMP_SUPPORT=""
#Specify the action after failure diff --git a/kdump.sysconfig.s390x b/kdump.sysconfig.s390x index b3aec3c..f4e63a5 100644 --- a/kdump.sysconfig.s390x +++ b/kdump.sysconfig.s390x @@ -41,3 +41,6 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.x86_64 b/kdump.sysconfig.x86_64 index f269d02..418b240 100644 --- a/kdump.sysconfig.x86_64 +++ b/kdump.sysconfig.x86_64 @@ -38,3 +38,6 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdumpctl b/kdumpctl index 4280e7e..d6fc12a 100755 --- a/kdumpctl +++ b/kdumpctl @@ -10,6 +10,7 @@ DRACUT_MODULES_FILE="/usr/lib/dracut/modules.txt" SAVE_PATH=/var/crash SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum" +INITRD_CHECKSUM_EARLYKDUMP="/boot/.earlykdump_initrd_checksum" DUMP_TARGET="" DEFAULT_INITRD="" DEFAULT_INITRD_BAK="" @@ -62,54 +63,6 @@ determine_dump_mode() fi } -# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>] -# Remove a list of kernel parameters from a given kernel cmdline and print the result. -# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists. -remove_cmdline_param() -{ - local cmdline=$1 - shift
- for arg in $@; do - cmdline=`echo $cmdline | \ - sed -e "s/\b$arg=[^ ]*//g" \ - -e "s/^$arg\b//g" \ - -e "s/[[:space:]]$arg\b//g" \ - -e "s/\s+/ /g"` - done - echo $cmdline -}
-# -# This function returns the "apicid" of the boot -# cpu (cpu 0) if present. -# -get_bootcpu_apicid() -{ - awk ' \ - BEGIN { CPU = "-1"; } \ - $1=="processor" && $2==":" { CPU = $NF; } \ - CPU=="0" && /^apicid/ { print $NF; } \ - ' \ - /proc/cpuinfo -}
-# -# This function appends argument "$2=$3" to string ($1) if not already present. -# -append_cmdline() -{ - local cmdline=$1 - local newstr=${cmdline/$2/""}
- # unchanged str implies argument wasn't there - if [ "$cmdline" == "$newstr" ]; then - cmdline="${cmdline} ${2}=${3}" - fi
- echo $cmdline -}
# This function performs a series of edits on the command line. # Store the final result in global $KDUMP_COMMANDLINE. prepare_cmdline() @@ -208,6 +161,53 @@ rebuild_kdump_initrd() return 0 } +restore_default_initramfs() +{ + if [ -f ${DEFAULT_INITRD_BAK} ] && [ -f ${INITRD_CHECKSUM_EARLYKDUMP} ]; then + # verify checksum before restoring + backup_checksum=`sha1sum ${DEFAULT_INITRD_BAK} | awk '{ print $1 }'` + default_checksum=`cat ${INITRD_CHECKSUM_EARLYKDUMP} | awk '{ print $1 }'` + if [ "${default_checksum}" != "${backup_checksum}" ]; then + echo "WARNING: checksum mismatch! Can't restore original initrd..." + else + rm -f ${INITRD_CHECKSUM_EARLYKDUMP} + mv ${DEFAULT_INITRD_BAK} ${DEFAULT_INITRD} + if [[ $? -eq 0 ]]; then + echo "Restored original initrd." + sync + fi + fi + fi +}
+rebuild_early_kdump_initrd() +{ + if [ ! -f "${DEFAULT_INITRD_BAK}" ]; then + if [ ! -f "${DEFAULT_INITRD}" ]; then + echo "${DEFAULT_INITRD} is not exist." + return 1 + fi + echo "early kdump is backing up ${DEFAULT_INITRD} ..." + sha1sum ${DEFAULT_INITRD} > ${INITRD_CHECKSUM_EARLYKDUMP} + cp ${DEFAULT_INITRD} ${DEFAULT_INITRD_BAK} + if [ $? -ne 0 ]; then + echo "WARNING: failed to backup ${DEFAULT_INITRD} in early kdump." + rm -f ${DEFAULT_INITRD_BAK} + return 1 + fi + sync + fi
+ dracut -I ${kdump_kernel} -I ${TARGET_INITRD} -v ${DEFAULT_INITRD} --force + if [ $? != 0 ]; then + echo "dracut: failed to make early kdump initrd" >&2 + restore_default_initramfs + return 1 + fi
+ return 0 +}
rebuild_initrd() { if [ $DEFAULT_DUMP_MODE == "fadump" ]; then @@ -610,6 +610,12 @@ check_rebuild() return 1 fi + if [[ $EARLY_KDUMP_SUPPORT = "yes" ]]; then + rebuild_early_kdump_initrd + elif [[ $EARLY_KDUMP_SUPPORT = "no" ]]; then + restore_default_initramfs + fi
_force_no_rebuild=`grep ^force_no_rebuild $KDUMP_CONFIG_FILE 2>/dev/null` if [ $? -eq 0 ]; then force_no_rebuild=`echo $_force_no_rebuild | cut -d' ' -f2` @@ -686,14 +692,6 @@ check_rebuild() return $? } -# This function check iomem and determines if we have more than -# 4GB of ram available. Returns 1 if we do, 0 if we dont -need_64bit_headers() -{ - return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \ - print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'` -}
# Load the kdump kernel specified in /etc/sysconfig/kdump # If none is specified, try to load a kdump kernel with the same version # as the currently running kernel. @@ -850,21 +848,6 @@ check_current_fadump_status() return 1 } -check_current_kdump_status() -{ - if [ ! -f /sys/kernel/kexec_crash_loaded ];then - echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel" - return 1 - fi
- rc=`cat /sys/kernel/kexec_crash_loaded` - if [ $rc == 1 ]; then - return 0 - else - return 1 - fi -}
check_current_status() { if [ $DEFAULT_DUMP_MODE == "fadump" ]; then @@ -974,58 +957,6 @@ selinux_relabel() done } -# Check if secure boot is being enforced. -# -# Per Peter Jones, we need check efivar SecureBoot-$(the UUID) and -# SetupMode-$(the UUID), they are both 5 bytes binary data. The first four -# bytes are the attributes associated with the variable and can safely be -# ignored, the last bytes are one-byte true-or-false variables. If SecureBoot -# is 1 and SetupMode is 0, then secure boot is being enforced. -# -# Assume efivars is mounted at /sys/firmware/efi/efivars. -is_secure_boot_enforced() -{ - local secure_boot_file setup_mode_file - local secure_boot_byte setup_mode_byte
- secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null) - setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null)
- if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then - secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' $secure_boot_file|cut -d' ' -f 5) - setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' $setup_mode_file|cut -d' ' -f 5)
- if [ "$secure_boot_byte" = "1" ] && [ "$setup_mode_byte" = "0" ]; then - return 0 - fi - fi
- return 1 -}
-check_crash_mem_reserved() -{ - local mem_reserved
- mem_reserved=$(cat /sys/kernel/kexec_crash_size) - if [ $mem_reserved -eq 0 ]; then - echo "No memory reserved for crash kernel" - return 1 - fi
- return 0 -}
-check_kdump_feasibility() -{ - if [ ! -e /sys/kernel/kexec_crash_loaded ]; then - echo "Kdump is not supported on this kernel" - return 1 - fi - check_crash_mem_reserved - return $? -}
check_fence_kdump_config() { local hostname=`hostname` diff --git a/kexec-tools.spec b/kexec-tools.spec index f04527c..9ecaefd 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -29,6 +29,7 @@ Source24: kdump-lib-initramfs.sh Source25: kdump.sysconfig.ppc64le Source26: kdumpctl.8 Source27: live-image-kdump-howto.txt +Source28: early-kdump-howto.txt ####################################### # These are sources for mkdumpramfs @@ -42,6 +43,9 @@ Source104: dracut-kdump-emergency.service Source105: dracut-kdump-error-handler.service Source106: dracut-kdump-capture.service Source107: dracut-kdump-emergency.target +Source108: dracut-early-kdump.sh +Source109: dracut-early-kdump.service +Source110: dracut-early-kdump-module-setup.sh Requires(post): systemd-units Requires(preun): systemd-units @@ -136,6 +140,7 @@ rm -f kexec-tools.spec.in cp %{SOURCE10} . cp %{SOURCE21} . cp %{SOURCE27} . +cp %{SOURCE28} . make %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 @@ -194,6 +199,7 @@ make -C kdump-anaconda-addon install DESTDIR=$RPM_BUILD_ROOT %find_lang kdump-anaconda-addon %define remove_dracut_prefix() %(echo -n %1|sed 's/.*dracut-//g') +%define remove_dracut_early_kdump_prefix() %(echo -n %1|sed 's/.*dracut-early-kdump-//g') # deal with dracut modules mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase @@ -207,6 +213,12 @@ cp %{SOURCE106} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpb cp %{SOURCE107} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE107}} chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE100}} chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE101}} +mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump +cp %{SOURCE108} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} +cp %{SOURCE109} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE109}} +cp %{SOURCE110} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE110}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE110}} %define dracutlibdir %{_prefix}/lib/dracut @@ -305,6 +317,7 @@ done %license COPYING %doc TODO %doc kexec-kdump-howto.txt +%doc early-kdump-howto.txt %doc kdump-in-cluster-environment.txt %doc live-image-kdump-howto.txt %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 diff --git a/mkdumprd.8 b/mkdumprd.8 index 7faae57..6e22e0a 100644 --- a/mkdumprd.8 +++ b/mkdumprd.8 @@ -17,6 +17,9 @@ be loaded in the initramfs (based on configuration retrieved from \fBmkdumprd\fR add a new \fBdracut\fR module 99kdumpbase and use \fBdracut\fR utility to generate the initramfs. +\fBmkdumprd\fR add a new \fBdracut\fR module 99earlykdump and use \fBdracut\fR +utility to generate the initramfs.
\fBmkdumprd\fR was not intended for casual use outside of the service initialization script for the kdump utility, and should not be run manually. If you require a custom kdump initramfs image, it is suggested that you use the
kexec mailing list -- kexec@lists.fedoraproject.org To unsubscribe send an email to kexec-leave@lists.fedoraproject.org
Hi Lianbo,
Thanks for the update, I comment on the range I could see.
On 3/15/2018 3:02 AM, Lianbo Jiang wrote:
Kdump service runs too late, so early crashes will have no chance to get kdump kernel booting. A proposal is add a dracut module to load pre-built kernel and initramfs for early kdump, one can provide "rd.early-kdump" in grub commandline to enable, then the service can load those files like original kdump, which is disabled by default.
For the normal kdump service in real root init path, it can check whether the pre-built kernel and initramfs has been loaded. It has no conflict with the early kdump.
Early kdump puts the pre-built kernel and initramfs for kdump into the initramfs for boot, the rebuilt initramfs will become large.
By the way, we move some common functions from kdumpctl to kdump-lib.sh. In addition, early kdump doesn't support fadump.
Signed-off-by: Lianbo Jiang lijiang@redhat.com
dracut-early-kdump-module-setup.sh | 23 +++++ dracut-early-kdump.service | 24 +++++ dracut-early-kdump.sh | 138 +++++++++++++++++++++++++++++ early-kdump-howto.txt | 58 ++++++++++++ kdump-lib.sh | 123 ++++++++++++++++++++++++++ kdump.sysconfig | 3 + kdump.sysconfig.i386 | 3 + kdump.sysconfig.ppc64 | 3 + kdump.sysconfig.ppc64le | 3 + kdump.sysconfig.s390x | 3 + kdump.sysconfig.x86_64 | 3 + kdumpctl | 177 +++++++++++-------------------------- kexec-tools.spec | 13 +++ mkdumprd.8 | 3 + 14 files changed, 454 insertions(+), 123 deletions(-) create mode 100755 dracut-early-kdump-module-setup.sh create mode 100644 dracut-early-kdump.service create mode 100755 dracut-early-kdump.sh create mode 100644 early-kdump-howto.txt
diff --git a/dracut-early-kdump-module-setup.sh b/dracut-early-kdump-module-setup.sh new file mode 100755 index 0000000..bc4d7dc --- /dev/null +++ b/dracut-early-kdump-module-setup.sh @@ -0,0 +1,23 @@ +#!/bin/bash
+check() {
- if [ ! -f /etc/sysconfig/kdump ] || [ ! -f /lib/kdump/kdump-lib.sh ]
It would be better to add '[ -n "$IN_KDUMP" ]' here to exclude early kdump from kdump initramfs.
- then
return 1
- fi
- return 0
+}
+depends() {
- echo "base shutdown"
- return 0
+}
+install() {
- inst_simple "/etc/sysconfig/kdump" "/etc/sysconfig/kdump"
- inst_simple "/usr/sbin/kexec" "/usr/sbin/kexec"
- inst_script "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh"
- inst_script "$moddir/early-kdump.sh" "/usr/bin/early-kdump"
- inst_simple "$moddir/early-kdump.service" "${systemdsystemunitdir}/early-kdump.service"
- ln_r "${systemdsystemunitdir}/early-kdump.service" "${systemdsystemunitdir}/initrd.target.wants/early-kdump.service"
+} diff --git a/dracut-early-kdump.service b/dracut-early-kdump.service new file mode 100644 index 0000000..8282c49 --- /dev/null +++ b/dracut-early-kdump.service @@ -0,0 +1,24 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version.
+# See systemd.special(7) for details
+[Unit] +Description=early kdump +DefaultDependencies=yes +After=dracut-cmdline.service +Before=dracut-pre-mount.service
+[Service] +Environment=DRACUT_SYSTEMD=1 +Type=oneshot +ExecStart=/bin/early-kdump +KillMode=process
+#Bash ignore SIGTERM, so we send SIGHUP instead, to ensure that bash +#terminates cleanly. +KillSignal=SIGHUP diff --git a/dracut-early-kdump.sh b/dracut-early-kdump.sh new file mode 100755 index 0000000..067ad5c --- /dev/null +++ b/dracut-early-kdump.sh @@ -0,0 +1,138 @@ +#! /bin/sh
+KEXEC=/sbin/kexec +standard_kexec_args="-p"
+EARLY_KDUMP_INITRD="" +EARLY_KDUMP_KERNEL="" +EARLY_KDUMP_CMDLINE="" +EARLY_KDUMP_KERNELVER="" +EARLY_KEXEC_ARGS=""
+#source lib and configure +. /lib/dracut-lib.sh +. /lib/kdump-lib.sh +. /etc/sysconfig/kdump
+prepare_parameters() +{
- local cmdline id
- if [ -z "$EARLY_KDUMP_CMDLINE" ]; then
cmdline=$(cat /proc/cmdline)
- else
cmdline=${EARLY_KDUMP_CMDLINE}
- fi
- cmdline=$(remove_cmdline_param "$cmdline" crashkernel panic_on_warn)
- cmdline=$(remove_cmdline_param "$cmdline" ${KDUMP_COMMANDLINE_REMOVE})
- # Always remove "root=X", as we now explicitly generate all kinds
- # of dump target mount information including root fs.
- #
- # We do this before KDUMP_COMMANDLINE_APPEND, if one really cares
- # about it(e.g. for debug purpose), then can pass "root=X" using
- # KDUMP_COMMANDLINE_APPEND.
- cmdline=$(remove_cmdline_param "$cmdline" root)
- # With the help of "--hostonly-cmdline", we can avoid some interitage.
- cmdline=$(remove_cmdline_param "$cmdline" rd.lvm.lv rd.luks.uuid rd.dm.uuid rd.md.uuid fcoe)
- cmdline="${cmdline} ${KDUMP_COMMANDLINE_APPEND}"
- id=$(get_bootcpu_apicid)
- if [ ! -z ${id} ] ; then
cmdline=$(append_cmdline "${cmdline}" disable_cpu_apicid ${id})
- fi
- EARLY_KDUMP_CMDLINE=$cmdline
- if [ -z "$KDUMP_BOOTDIR" ]; then
if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then
KDUMP_BOOTDIR="/boot"
else
eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1)
KDUMP_BOOTDIR="/boot"$(dirname $BOOT_IMAGE)
fi
- fi
- #make early-kdump kernel string
- if [ -z "$EARLY_KDUMP_KERNELVER" ]; then
EARLY_KDUMP_KERNELVER=`uname -r`
- fi
- EARLY_KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${EARLY_KDUMP_KERNELVER}${KDUMP_IMG_EXT}"
- #make early-kdump initrd string
- EARLY_KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${EARLY_KDUMP_KERNELVER}kdump.img"
+}
+early_kdump_load() +{
- check_kdump_feasibility
- if [ $? -ne 0 ]; then
return 1
- fi
- if is_fadump_capable; then
echo "early kdump doesn't support fadump: [WARNING]"
return 1
- fi
- check_current_kdump_status
- if [ $? == 0 ]; then
return 1
- fi
- prepare_parameters
- ARCH=`uname -m`
- if [ "$ARCH" == "i686" -o "$ARCH" == "i386" ]
- then
need_64bit_headers
if [ $? == 1 ]
then
FOUND_ELF_ARGS=`echo $EARLY_KEXEC_ARGS | grep elf32-core-headers`
if [ -n "$FOUND_ELF_ARGS" ]
then
echo -n "Warning: elf32-core-headers overrides correct elf64 setting"
echo
else
EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS --elf64-core-headers"
fi
else
FOUND_ELF_ARGS=`echo $EARLY_KEXEC_ARGS | grep elf64-core-headers`
if [ -z "$FOUND_ELF_ARGS" ]
then
EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS --elf32-core-headers"
fi
fi
- fi
- #secure boot
- if is_secure_boot_enforced; then
echo "Secure Boot is enabled. Using kexec file based syscall."
EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS -s"
- fi
- $KEXEC ${EARLY_KEXEC_ARGS} $standard_kexec_args \
--command-line="$EARLY_KDUMP_CMDLINE" \
--initrd=$EARLY_KDUMP_INITRD $EARLY_KDUMP_KERNEL
- if [ $? == 0 ]; then
echo "kexec: loaded early-kdump kernel"
return 0
- else
echo "kexec: failed to load early-kdump kernel"
return 1
- fi
+}
+setearlykdump() +{
- if getargbool 0 rd.early-kdump; then
echo "early-kdump is enabled."
early_kdump_load
- else
echo "early-kdump is not enabled by default."
- fi
- return 0
+}
+setearlykdump diff --git a/early-kdump-howto.txt b/early-kdump-howto.txt new file mode 100644 index 0000000..aae8d7b --- /dev/null +++ b/early-kdump-howto.txt @@ -0,0 +1,58 @@ +Early Kdump HOWTO
+Introduction
+Kdump service runs too late, so early crashes will have no chance to get kdump +kernel booting. A proposal is add a dracut module to load pre-built kernel and +initramfs for early kdump, one can provide "rd.early-kdump" in grub commandline +to enable, then the service can load those files like original kdump, which is +disabled by default.
+For the normal kdump service in real root init path, it can check whether the +prebuilt kernel and initramfs have been loaded. It has no conflict with the early +kdump.
+How to configure early kdump:
+We assume if you're reading this document, you should already have kexec-tools +installed. If not, you install it via the following command:
- # yum install kexec-tools
+For early kdump, you can set "EARLY_KDUMP_SUPPORT=yes" in /etc/sysconfig/kdump +if you want to rebuild the initramfs for early kdump, and then:
- # kdumpctl restart
+By the way, the initramfs will become large, early kdump put the kernel and +initramfs for kdump into the initramfs for boot. If you set "EARLY_KDUMP_SUPPORT +=no" in /etc/sysconfig/kdump, which will restore previous initramfs, that is to +say, it doesn't have early kdump.
+Next up, we need to modify some boot parameters to enable early kdump, it's +very easy to append "rd.early-kdump" to your kernel boot parameters in grub. +After making said changes, reboot your system to take effect. Of course, if +you want to disable early kdump, you can simply remove "rd.early-kdump" from +kernel boot parameters in grub, and reboot system like above.
+Now that you've got some messages about early kdump, you can check whether early +kdump is successful like this:
- # journalctl -x|grep early-kdump
+Then, you will see some useful logs, for exapmles:
+1. if early kdump is successful. +Mar 09 09:57:56 localhost.localdomain early-kdump[477]: early-kdump is enabled. +Mar 09 09:57:56 localhost.localdomain early-kdump[477]: kexec: loaded early- +kdump kernel
+2. if early kdump is disabled. +Mar 09 10:02:47 localhost.localdomain early-kdump[474]: early-kdump is not en- +abled by default.
+Notes: +You will need to make sure that appropriate initramfs and vmlinuz, if early kdump +doesn't find them it will refuse to go on.
+In addition, early kdump doesn't support fadump, maybe it will have this in future. diff --git a/kdump-lib.sh b/kdump-lib.sh index d981c4f..a1a7660 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -485,3 +485,126 @@ get_dracut_args_target() { echo $1 | grep "--mount" | sed "s/.*--mount .(.*)/\1/" | cut -d' ' -f1 }
+check_crash_mem_reserved() +{
local mem_reserved
mem_reserved=$(cat /sys/kernel/kexec_crash_size)
if [ $mem_reserved -eq 0 ]; then
echo "No memory reserved for crash kernel"
return 1
fi
return 0
+}
+check_kdump_feasibility() +{
if [ ! -e /sys/kernel/kexec_crash_loaded ]; then
echo "Kdump is not supported on this kernel"
return 1
fi
check_crash_mem_reserved
return $?
+}
+check_current_kdump_status() +{
if [ ! -f /sys/kernel/kexec_crash_loaded ];then
echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel"
return 1
fi
rc=`cat /sys/kernel/kexec_crash_loaded`
if [ $rc == 1 ]; then
return 0
else
return 1
fi
+}
+# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>] +# Remove a list of kernel parameters from a given kernel cmdline and print the result. +# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists. +remove_cmdline_param() +{
local cmdline=$1
shift
for arg in $@; do
cmdline=`echo $cmdline | \
sed -e "s/\b$arg=[^ ]*//g" \
-e "s/^$arg\b//g" \
-e "s/[[:space:]]$arg\b//g" \
-e "s/\s\+/ /g"`
done
echo $cmdline
+}
+# +# This function returns the "apicid" of the boot +# cpu (cpu 0) if present. +# +get_bootcpu_apicid() +{
- awk ' \
BEGIN { CPU = "-1"; } \
$1=="processor" && $2==":" { CPU = $NF; } \
CPU=="0" && /^apicid/ { print $NF; } \
' \
/proc/cpuinfo
+}
+# +# This function appends argument "$2=$3" to string ($1) if not already present. +# +append_cmdline() +{
local cmdline=$1
local newstr=${cmdline/$2/""}
# unchanged str implies argument wasn't there
if [ "$cmdline" == "$newstr" ]; then
cmdline="${cmdline} ${2}=${3}"
fi
echo $cmdline
+}
+# This function check iomem and determines if we have more than +# 4GB of ram available. Returns 1 if we do, 0 if we dont +need_64bit_headers() +{
return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \
print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'`
+}
+# Check if secure boot is being enforced. +# +# Per Peter Jones, we need check efivar SecureBoot-$(the UUID) and +# SetupMode-$(the UUID), they are both 5 bytes binary data. The first four +# bytes are the attributes associated with the variable and can safely be +# ignored, the last bytes are one-byte true-or-false variables. If SecureBoot +# is 1 and SetupMode is 0, then secure boot is being enforced. +# +# Assume efivars is mounted at /sys/firmware/efi/efivars. +is_secure_boot_enforced() +{
local secure_boot_file setup_mode_file
local secure_boot_byte setup_mode_byte
secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null)
setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null)
if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then
secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' $secure_boot_file|cut -d' ' -f 5)
setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' $setup_mode_file|cut -d' ' -f 5)
if [ "$secure_boot_byte" = "1" ] && [ "$setup_mode_byte" = "0" ]; then
return 0
fi
fi
return 1
+} diff --git a/kdump.sysconfig b/kdump.sysconfig index ffe1df8..b95807c 100644 --- a/kdump.sysconfig +++ b/kdump.sysconfig @@ -35,3 +35,6 @@ KEXEC_ARGS=""
#What is the image type used for kdump KDUMP_IMG="vmlinuz"
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.i386 b/kdump.sysconfig.i386 index 18c407e..6ece161 100644 --- a/kdump.sysconfig.i386 +++ b/kdump.sysconfig.i386 @@ -38,3 +38,6 @@ KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.ppc64 b/kdump.sysconfig.ppc64 index be8e794..ac1ae2d 100644 --- a/kdump.sysconfig.ppc64 +++ b/kdump.sysconfig.ppc64 @@ -39,4 +39,7 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT=""
#Specify the action after failure diff --git a/kdump.sysconfig.ppc64le b/kdump.sysconfig.ppc64le index be8e794..ac1ae2d 100644 --- a/kdump.sysconfig.ppc64le +++ b/kdump.sysconfig.ppc64le @@ -39,4 +39,7 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT=""
#Specify the action after failure diff --git a/kdump.sysconfig.s390x b/kdump.sysconfig.s390x index b3aec3c..f4e63a5 100644 --- a/kdump.sysconfig.s390x +++ b/kdump.sysconfig.s390x @@ -41,3 +41,6 @@ KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdump.sysconfig.x86_64 b/kdump.sysconfig.x86_64 index f269d02..418b240 100644 --- a/kdump.sysconfig.x86_64 +++ b/kdump.sysconfig.x86_64 @@ -38,3 +38,6 @@ KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT=""
+#early kdump support +EARLY_KDUMP_SUPPORT="" diff --git a/kdumpctl b/kdumpctl index 4280e7e..d6fc12a 100755 --- a/kdumpctl +++ b/kdumpctl @@ -10,6 +10,7 @@ DRACUT_MODULES_FILE="/usr/lib/dracut/modules.txt" SAVE_PATH=/var/crash SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum" +INITRD_CHECKSUM_EARLYKDUMP="/boot/.earlykdump_initrd_checksum" DUMP_TARGET="" DEFAULT_INITRD="" DEFAULT_INITRD_BAK="" @@ -62,54 +63,6 @@ determine_dump_mode() fi }
-# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>] -# Remove a list of kernel parameters from a given kernel cmdline and print the result. -# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists. -remove_cmdline_param() -{
- local cmdline=$1
- shift
- for arg in $@; do
cmdline=`echo $cmdline | \
sed -e "s/\b$arg=[^ ]*//g" \
-e "s/^$arg\b//g" \
-e "s/[[:space:]]$arg\b//g" \
-e "s/\s\+/ /g"`
- done
- echo $cmdline
-}
-# -# This function returns the "apicid" of the boot -# cpu (cpu 0) if present. -# -get_bootcpu_apicid() -{
- awk ' \
- BEGIN { CPU = "-1"; } \
- $1=="processor" && $2==":" { CPU = $NF; } \
- CPU=="0" && /^apicid/ { print $NF; } \
- ' \
- /proc/cpuinfo
-}
-# -# This function appends argument "$2=$3" to string ($1) if not already present. -# -append_cmdline() -{
- local cmdline=$1
- local newstr=${cmdline/$2/""}
- # unchanged str implies argument wasn't there
- if [ "$cmdline" == "$newstr" ]; then
cmdline="${cmdline} ${2}=${3}"
- fi
- echo $cmdline
-}
# This function performs a series of edits on the command line. # Store the final result in global $KDUMP_COMMANDLINE. prepare_cmdline() @@ -208,6 +161,53 @@ rebuild_kdump_initrd() return 0 }
+restore_default_initramfs() +{
- if [ -f ${DEFAULT_INITRD_BAK} ] && [ -f ${INITRD_CHECKSUM_EARLYKDUMP} ]; then
# verify checksum before restoring
backup_checksum=`sha1sum ${DEFAULT_INITRD_BAK} | awk '{ print $1 }'`
default_checksum=`cat ${INITRD_CHECKSUM_EARLYKDUMP} | awk '{ print $1 }'`
if [ "${default_checksum}" != "${backup_checksum}" ]; then
echo "WARNING: checksum mismatch! Can't restore original initrd..."
else
rm -f ${INITRD_CHECKSUM_EARLYKDUMP}
mv ${DEFAULT_INITRD_BAK} ${DEFAULT_INITRD}
if [[ $? -eq 0 ]]; then
echo "Restored original initrd."
sync
fi
fi
- fi
+}
+rebuild_early_kdump_initrd() +{
- if [ ! -f "${DEFAULT_INITRD_BAK}" ]; then
if [ ! -f "${DEFAULT_INITRD}" ]; then
echo "${DEFAULT_INITRD} is not exist."
return 1
fi
echo "early kdump is backing up ${DEFAULT_INITRD} ..."
sha1sum ${DEFAULT_INITRD} > ${INITRD_CHECKSUM_EARLYKDUMP}
cp ${DEFAULT_INITRD} ${DEFAULT_INITRD_BAK}
I think that it might be better to preserve the timestamps at least (e.g., use "cp -p") for something like future troubles.
if [ $? -ne 0 ]; then
echo "WARNING: failed to backup ${DEFAULT_INITRD} in early kdump."
rm -f ${DEFAULT_INITRD_BAK}
return 1
fi
sync
- fi
- dracut -I ${kdump_kernel} -I ${TARGET_INITRD} -v ${DEFAULT_INITRD} --force
- if [ $? != 0 ]; then
echo "dracut: failed to make early kdump initrd" >&2
restore_default_initramfs
return 1
- fi
- return 0
+}
rebuild_initrd() { if [ $DEFAULT_DUMP_MODE == "fadump" ]; then @@ -610,6 +610,12 @@ check_rebuild() return 1 fi
- if [[ $EARLY_KDUMP_SUPPORT = "yes" ]]; then
rebuild_early_kdump_initrd
- elif [[ $EARLY_KDUMP_SUPPORT = "no" ]]; then
restore_default_initramfs
- fi
we might not have a new/rebuilt kdump initramfs yet here? So I think that this could be located later (e.g., after check_build), and if early kdump is already enabled and a kdump initramfs was not rebuilt, it doesn't have to rebuild the boot initramfs?
For example: 1) check_rebuild set REBUILT=1 if it rebuilt the kdump initramfs. 2) check_early_kdump if EARLY_KDUMP_SUPPORT if no backup or REBUILT rebuild_early_kdump else if backup exists restore 3) start_kdump
How about this?
Thanks, Kazu
- _force_no_rebuild=`grep ^force_no_rebuild $KDUMP_CONFIG_FILE 2>/dev/null` if [ $? -eq 0 ]; then force_no_rebuild=`echo $_force_no_rebuild | cut -d' ' -f2`
@@ -686,14 +692,6 @@ check_rebuild() return $? }
-# This function check iomem and determines if we have more than -# 4GB of ram available. Returns 1 if we do, 0 if we dont -need_64bit_headers() -{
- return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \
- print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'`
-}
# Load the kdump kernel specified in /etc/sysconfig/kdump # If none is specified, try to load a kdump kernel with the same version # as the currently running kernel. @@ -850,21 +848,6 @@ check_current_fadump_status() return 1 }
-check_current_kdump_status() -{
- if [ ! -f /sys/kernel/kexec_crash_loaded ];then
echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel"
return 1
- fi
- rc=`cat /sys/kernel/kexec_crash_loaded`
- if [ $rc == 1 ]; then
return 0
- else
return 1
- fi
-}
check_current_status() { if [ $DEFAULT_DUMP_MODE == "fadump" ]; then @@ -974,58 +957,6 @@ selinux_relabel() done }
-# Check if secure boot is being enforced. -# -# Per Peter Jones, we need check efivar SecureBoot-$(the UUID) and -# SetupMode-$(the UUID), they are both 5 bytes binary data. The first four -# bytes are the attributes associated with the variable and can safely be -# ignored, the last bytes are one-byte true-or-false variables. If SecureBoot -# is 1 and SetupMode is 0, then secure boot is being enforced. -# -# Assume efivars is mounted at /sys/firmware/efi/efivars. -is_secure_boot_enforced() -{
- local secure_boot_file setup_mode_file
- local secure_boot_byte setup_mode_byte
- secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null)
- setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null)
- if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then
secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' $secure_boot_file|cut -d' ' -f 5)
setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' $setup_mode_file|cut -d' ' -f 5)
if [ "$secure_boot_byte" = "1" ] && [ "$setup_mode_byte" = "0" ]; then
return 0
fi
- fi
- return 1
-}
-check_crash_mem_reserved() -{
- local mem_reserved
- mem_reserved=$(cat /sys/kernel/kexec_crash_size)
- if [ $mem_reserved -eq 0 ]; then
echo "No memory reserved for crash kernel"
return 1
- fi
- return 0
-}
-check_kdump_feasibility() -{
- if [ ! -e /sys/kernel/kexec_crash_loaded ]; then
echo "Kdump is not supported on this kernel"
return 1
- fi
- check_crash_mem_reserved
- return $?
-}
check_fence_kdump_config() { local hostname=`hostname` diff --git a/kexec-tools.spec b/kexec-tools.spec index f04527c..9ecaefd 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -29,6 +29,7 @@ Source24: kdump-lib-initramfs.sh Source25: kdump.sysconfig.ppc64le Source26: kdumpctl.8 Source27: live-image-kdump-howto.txt +Source28: early-kdump-howto.txt
####################################### # These are sources for mkdumpramfs @@ -42,6 +43,9 @@ Source104: dracut-kdump-emergency.service Source105: dracut-kdump-error-handler.service Source106: dracut-kdump-capture.service Source107: dracut-kdump-emergency.target +Source108: dracut-early-kdump.sh +Source109: dracut-early-kdump.service +Source110: dracut-early-kdump-module-setup.sh
Requires(post): systemd-units Requires(preun): systemd-units @@ -136,6 +140,7 @@ rm -f kexec-tools.spec.in cp %{SOURCE10} . cp %{SOURCE21} . cp %{SOURCE27} . +cp %{SOURCE28} .
make %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 @@ -194,6 +199,7 @@ make -C kdump-anaconda-addon install DESTDIR=$RPM_BUILD_ROOT %find_lang kdump-anaconda-addon
%define remove_dracut_prefix() %(echo -n %1|sed 's/.*dracut-//g') +%define remove_dracut_early_kdump_prefix() %(echo -n %1|sed 's/.*dracut-early-kdump-//g')
# deal with dracut modules mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase @@ -207,6 +213,12 @@ cp %{SOURCE106} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpb cp %{SOURCE107} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE107}} chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE100}} chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE101}} +mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump +cp %{SOURCE108} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} +cp %{SOURCE109} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE109}} +cp %{SOURCE110} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE110}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE110}}
%define dracutlibdir %{_prefix}/lib/dracut @@ -305,6 +317,7 @@ done %license COPYING %doc TODO %doc kexec-kdump-howto.txt +%doc early-kdump-howto.txt %doc kdump-in-cluster-environment.txt %doc live-image-kdump-howto.txt %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 diff --git a/mkdumprd.8 b/mkdumprd.8 index 7faae57..6e22e0a 100644 --- a/mkdumprd.8 +++ b/mkdumprd.8 @@ -17,6 +17,9 @@ be loaded in the initramfs (based on configuration retrieved from \fBmkdumprd\fR add a new \fBdracut\fR module 99kdumpbase and use \fBdracut\fR utility to generate the initramfs.
+\fBmkdumprd\fR add a new \fBdracut\fR module 99earlykdump and use \fBdracut\fR +utility to generate the initramfs.
\fBmkdumprd\fR was not intended for casual use outside of the service initialization script for the kdump utility, and should not be run manually. If you require a custom kdump initramfs image, it is suggested that you use the
Hi Lianbo, On 03/15/18 at 03:02pm, Lianbo Jiang wrote:
Kdump service runs too late, so early crashes will have no chance to get kdump kernel booting. A proposal is add a dracut module to load pre-built kernel and initramfs for early kdump, one can provide "rd.early-kdump" in grub commandline to enable, then the service
rd.earlykdump looks better and easier to use.
can load those files like original kdump, which is disabled by default.
For the normal kdump service in real root init path, it can check whether the pre-built kernel and initramfs has been loaded. It has no conflict with the early kdump.
Early kdump puts the pre-built kernel and initramfs for kdump into the initramfs for boot, the rebuilt initramfs will become large.
By the way, we move some common functions from kdumpctl to kdump-lib.sh. In addition, early kdump doesn't support fadump.
Signed-off-by: Lianbo Jiang lijiang@redhat.com
dracut-early-kdump-module-setup.sh | 23 +++++ dracut-early-kdump.service | 24 +++++ dracut-early-kdump.sh | 138 +++++++++++++++++++++++++++++ early-kdump-howto.txt | 58 ++++++++++++ kdump-lib.sh | 123 ++++++++++++++++++++++++++ kdump.sysconfig | 3 + kdump.sysconfig.i386 | 3 + kdump.sysconfig.ppc64 | 3 + kdump.sysconfig.ppc64le | 3 + kdump.sysconfig.s390x | 3 + kdump.sysconfig.x86_64 | 3 + kdumpctl | 177 +++++++++++-------------------------- kexec-tools.spec | 13 +++ mkdumprd.8 | 3 + 14 files changed, 454 insertions(+), 123 deletions(-) create mode 100755 dracut-early-kdump-module-setup.sh create mode 100644 dracut-early-kdump.service create mode 100755 dracut-early-kdump.sh create mode 100644 early-kdump-howto.txt
diff --git a/dracut-early-kdump-module-setup.sh b/dracut-early-kdump-module-setup.sh new file mode 100755 index 0000000..bc4d7dc --- /dev/null +++ b/dracut-early-kdump-module-setup.sh @@ -0,0 +1,23 @@ +#!/bin/bash
+check() {
- if [ ! -f /etc/sysconfig/kdump ] || [ ! -f /lib/kdump/kdump-lib.sh ]
- then
return 1
- fi
- return 0
+}
+depends() {
- echo "base shutdown"
- return 0
+}
+install() {
- inst_simple "/etc/sysconfig/kdump" "/etc/sysconfig/kdump"
- inst_simple "/usr/sbin/kexec" "/usr/sbin/kexec"
- inst_script "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh"
- inst_script "$moddir/early-kdump.sh" "/usr/bin/early-kdump"
- inst_simple "$moddir/early-kdump.service" "${systemdsystemunitdir}/early-kdump.service"
- ln_r "${systemdsystemunitdir}/early-kdump.service" "${systemdsystemunitdir}/initrd.target.wants/early-kdump.service"
+} diff --git a/dracut-early-kdump.service b/dracut-early-kdump.service new file mode 100644 index 0000000..8282c49 --- /dev/null +++ b/dracut-early-kdump.service @@ -0,0 +1,24 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version.
+# See systemd.special(7) for details
+[Unit] +Description=early kdump +DefaultDependencies=yes +After=dracut-cmdline.service +Before=dracut-pre-mount.service
As we talked offline, since this does not depend on systemd, we can simply install a cmdline hook script without using a service. It will be even early.
+[Service] +Environment=DRACUT_SYSTEMD=1 +Type=oneshot +ExecStart=/bin/early-kdump +KillMode=process
+#Bash ignore SIGTERM, so we send SIGHUP instead, to ensure that bash +#terminates cleanly. +KillSignal=SIGHUP diff --git a/dracut-early-kdump.sh b/dracut-early-kdump.sh new file mode 100755 index 0000000..067ad5c --- /dev/null +++ b/dracut-early-kdump.sh @@ -0,0 +1,138 @@ +#! /bin/sh
+KEXEC=/sbin/kexec +standard_kexec_args="-p"
+EARLY_KDUMP_INITRD="" +EARLY_KDUMP_KERNEL="" +EARLY_KDUMP_CMDLINE="" +EARLY_KDUMP_KERNELVER="" +EARLY_KEXEC_ARGS=""
+#source lib and configure +. /lib/dracut-lib.sh +. /lib/kdump-lib.sh +. /etc/sysconfig/kdump
Not sure if those lib sh depends on variables in sysconfig, it is better to source sysconfig/kdump first.
+prepare_parameters() +{
- local cmdline id
- if [ -z "$EARLY_KDUMP_CMDLINE" ]; then
cmdline=$(cat /proc/cmdline)
- else
cmdline=${EARLY_KDUMP_CMDLINE}
- fi
- cmdline=$(remove_cmdline_param "$cmdline" crashkernel panic_on_warn)
- cmdline=$(remove_cmdline_param "$cmdline" ${KDUMP_COMMANDLINE_REMOVE})
- # Always remove "root=X", as we now explicitly generate all kinds
- # of dump target mount information including root fs.
- #
- # We do this before KDUMP_COMMANDLINE_APPEND, if one really cares
- # about it(e.g. for debug purpose), then can pass "root=X" using
- # KDUMP_COMMANDLINE_APPEND.
- cmdline=$(remove_cmdline_param "$cmdline" root)
- # With the help of "--hostonly-cmdline", we can avoid some interitage.
- cmdline=$(remove_cmdline_param "$cmdline" rd.lvm.lv rd.luks.uuid rd.dm.uuid rd.md.uuid fcoe)
- cmdline="${cmdline} ${KDUMP_COMMANDLINE_APPEND}"
- id=$(get_bootcpu_apicid)
- if [ ! -z ${id} ] ; then
cmdline=$(append_cmdline "${cmdline}" disable_cpu_apicid ${id})
- fi
- EARLY_KDUMP_CMDLINE=$cmdline
- if [ -z "$KDUMP_BOOTDIR" ]; then
if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then
KDUMP_BOOTDIR="/boot"
else
eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1)
KDUMP_BOOTDIR="/boot"$(dirname $BOOT_IMAGE)
fi
- fi
- #make early-kdump kernel string
- if [ -z "$EARLY_KDUMP_KERNELVER" ]; then
EARLY_KDUMP_KERNELVER=`uname -r`
- fi
- EARLY_KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${EARLY_KDUMP_KERNELVER}${KDUMP_IMG_EXT}"
- #make early-kdump initrd string
- EARLY_KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${EARLY_KDUMP_KERNELVER}kdump.img"
+}
Can this prepare cmdline be moved to lib file as well?
+early_kdump_load() +{
- check_kdump_feasibility
- if [ $? -ne 0 ]; then
return 1
- fi
- if is_fadump_capable; then
echo "early kdump doesn't support fadump: [WARNING]"
In kdumpctl we use below style, messages here should be consistent: echo "WARNING: ..."
return 1
- fi
- check_current_kdump_status
- if [ $? == 0 ]; then
return 1
- fi
- prepare_parameters
- ARCH=`uname -m`
- if [ "$ARCH" == "i686" -o "$ARCH" == "i386" ]
- then
need_64bit_headers
if [ $? == 1 ]
then
FOUND_ELF_ARGS=`echo $EARLY_KEXEC_ARGS | grep elf32-core-headers`
if [ -n "$FOUND_ELF_ARGS" ]
then
echo -n "Warning: elf32-core-headers overrides correct elf64 setting"
echo
else
EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS --elf64-core-headers"
fi
else
FOUND_ELF_ARGS=`echo $EARLY_KEXEC_ARGS | grep elf64-core-headers`
if [ -z "$FOUND_ELF_ARGS" ]
then
EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS --elf32-core-headers"
fi
fi
- fi
Above elf header checking can also be a function in kdump-lib.sh to avoid duplicate code.
- #secure boot
No need the comment since it is clear.
- if is_secure_boot_enforced; then
echo "Secure Boot is enabled. Using kexec file based syscall."
EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS -s"
- fi
- $KEXEC ${EARLY_KEXEC_ARGS} $standard_kexec_args \
--command-line="$EARLY_KDUMP_CMDLINE" \
--initrd=$EARLY_KDUMP_INITRD $EARLY_KDUMP_KERNEL
- if [ $? == 0 ]; then
echo "kexec: loaded early-kdump kernel"
return 0
- else
echo "kexec: failed to load early-kdump kernel"
return 1
- fi
+}
+setearlykdump() +{
- if getargbool 0 rd.early-kdump; then
echo "early-kdump is enabled."
early_kdump_load
- else
echo "early-kdump is not enabled by default."
remove "by default"
- fi
- return 0
+}
+setearlykdump diff --git a/early-kdump-howto.txt b/early-kdump-howto.txt new file mode 100644 index 0000000..aae8d7b --- /dev/null +++ b/early-kdump-howto.txt @@ -0,0 +1,58 @@ +Early Kdump HOWTO
+Introduction
+Kdump service runs too late, so early crashes will have no chance to get kdump +kernel booting. A proposal is add a dracut module to load pre-built kernel and +initramfs for early kdump, one can provide "rd.early-kdump" in grub commandline +to enable, then the service can load those files like original kdump, which is +disabled by default.
+For the normal kdump service in real root init path, it can check whether the +prebuilt kernel and initramfs have been loaded. It has no conflict with the early +kdump.
+How to configure early kdump:
+We assume if you're reading this document, you should already have kexec-tools +installed. If not, you install it via the following command:
- # yum install kexec-tools
No need to say about installing kexec-tools
+For early kdump, you can set "EARLY_KDUMP_SUPPORT=yes" in /etc/sysconfig/kdump +if you want to rebuild the initramfs for early kdump, and then:
- # kdumpctl restart
Thinking about this, IMO we can document the steps to generate the new initrd instead of adding it in kdumpctl. I'm not too keen to replace the system initrd automatically. The code will be simpler we do not need add extra options in sysconfig. And include the kernel and initrd in module-setup.sh seems good if it is not too hard to check the kernel version defined in sysconfig.
[snip]
Thanks Dave