From 691f42d76ba583393133302c00ca98280600d855 Mon Sep 17 00:00:00 2001 From: Chunmei Xu Date: Mon, 7 Feb 2022 10:58:02 +0800 Subject: [PATCH] sync from kexec-tools-2.0.20-57.el8.src.rpm rebase kexec-tools to 2.0.21 rebase makedumpfile to 1.6.9 remove -s from KEXEC_ARGS to prevent bzImage verify Signed-off-by: Chunmei Xu --- 60-kdump.install | 36 + 98-kexec.rules.ppc64 | 17 +- dracut-early-kdump-module-setup.sh | 27 +- dracut-early-kdump.sh | 33 +- dracut-kdump.sh | 115 +++- dracut-module-setup.sh | 267 ++++++-- ...move-duplicated-variable-declaration.patch | 33 - fadump-howto.txt | 28 +- kdump-dep-generator.sh | 1 + kdump-lib-initramfs.sh | 94 ++- kdump-lib.sh | 384 +++++++++-- kdump-logger.sh | 348 ++++++++++ kdump-migrate-action.sh | 8 + kdump-restart.sh | 8 + kdump.conf | 10 +- kdump.conf.5 | 21 +- kdump.service | 1 + kdump.sysconfig | 16 + kdump.sysconfig.aarch64 | 16 + kdump.sysconfig.i386 | 16 + kdump.sysconfig.ppc64 | 16 + kdump.sysconfig.ppc64le | 16 + kdump.sysconfig.s390x | 20 +- kdump.sysconfig.x86_64 | 16 + kdumpctl | 641 ++++++++++-------- kdumpctl.8 | 5 + kexec-kdump-howto.txt | 182 ++++- ...move-duplicated-variable-declaration.patch | 25 + ...ss-proc-kcore-when-finding-max_paddr.patch | 60 ++ ...-proc-kcore-when-making-ELF-dumpfile.patch | 43 ++ kexec-tools.spec | 200 +++++- mkdumprd | 85 +-- mkdumprd.8 | 8 +- ...64-Add-support-for-ARMv8.2-LVA-52-bi.patch | 57 +- 34 files changed, 2239 insertions(+), 614 deletions(-) create mode 100755 60-kdump.install delete mode 100644 eppic-remove-duplicated-variable-declaration.patch create mode 100755 kdump-logger.sh create mode 100755 kdump-migrate-action.sh create mode 100644 kdump-restart.sh create mode 100644 kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch create mode 100644 kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch create mode 100644 kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch diff --git a/60-kdump.install b/60-kdump.install new file mode 100755 index 0000000..5b0e021 --- /dev/null +++ b/60-kdump.install @@ -0,0 +1,36 @@ +#!/usr/bin/bash + +COMMAND="$1" +KERNEL_VERSION="$2" +KDUMP_INITRD_DIR_ABS="$3" +KERNEL_IMAGE="$4" + +if ! [[ ${KERNEL_INSTALL_MACHINE_ID-x} ]]; then + exit 0 +fi + +if [[ -d "$KDUMP_INITRD_DIR_ABS" ]]; then + KDUMP_INITRD="initrdkdump" +else + # If `KDUMP_BOOTDIR` is not writable, then the kdump + # initrd must have been placed at `/var/lib/kdump` + if [[ ! -w "/boot" ]]; then + KDUMP_INITRD_DIR_ABS="/var/lib/kdump" + else + KDUMP_INITRD_DIR_ABS="/boot" + fi + KDUMP_INITRD="initramfs-${KERNEL_VERSION}kdump.img" +fi + +ret=0 +case "$COMMAND" in + add) + # Do nothing, kdump initramfs is strictly host only + # and managed by kdump service + ;; + remove) + rm -f -- "$KDUMP_INITRD_DIR_ABS/$KDUMP_INITRD" + ret=$? + ;; +esac +exit $ret diff --git a/98-kexec.rules.ppc64 b/98-kexec.rules.ppc64 index 1a91220..a1c00a9 100644 --- a/98-kexec.rules.ppc64 +++ b/98-kexec.rules.ppc64 @@ -1,15 +1,22 @@ -SUBSYSTEM=="cpu", ACTION=="online", GOTO="kdump_reload" -SUBSYSTEM=="memory", ACTION=="online", GOTO="kdump_reload" -SUBSYSTEM=="memory", ACTION=="offline", GOTO="kdump_reload" +SUBSYSTEM=="cpu", ACTION=="online", GOTO="kdump_reload_cpu" +SUBSYSTEM=="memory", ACTION=="online", GOTO="kdump_reload_mem" +SUBSYSTEM=="memory", ACTION=="offline", GOTO="kdump_reload_mem" GOTO="kdump_reload_end" -LABEL="kdump_reload" - # If kdump is not loaded, calling kdump-udev-throttle will end up # doing nothing, but systemd-run will always generate extra logs for # each call, so trigger the kdump-udev-throttler only if kdump # service is active to avoid unnecessary logs + +LABEL="kdump_reload_mem" + RUN+="/bin/sh -c '/usr/bin/systemctl is-active kdump.service || exit 0; /usr/bin/systemd-run --quiet --no-block /usr/lib/udev/kdump-udev-throttler'" +GOTO="kdump_reload_end" + +LABEL="kdump_reload_cpu" + +RUN+="/bin/sh -c '/usr/bin/systemctl is-active kdump.service || exit 0; ! test -f /sys/kernel/fadump_enabled || cat /sys/kernel/fadump_enabled | grep 0 || exit 0; /usr/bin/systemd-run --quiet --no-block /usr/lib/udev/kdump-udev-throttler'" + LABEL="kdump_reload_end" diff --git a/dracut-early-kdump-module-setup.sh b/dracut-early-kdump-module-setup.sh index e069867..b25d6b5 100755 --- a/dracut-early-kdump-module-setup.sh +++ b/dracut-early-kdump-module-setup.sh @@ -1,7 +1,6 @@ #!/bin/bash . /etc/sysconfig/kdump -. /lib/kdump/kdump-lib.sh KDUMP_KERNEL="" KDUMP_INITRD="" @@ -21,18 +20,15 @@ depends() { } prepare_kernel_initrd() { - KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}") - if [ -z "$KDUMP_KERNELVER" ]; then - kdump_kver=`uname -r` - if [ "$kernel" != "$kdump_kver" ]; then - dwarn "Using current kernel version '$kdump_kver' for early kdump," \ - "but the initramfs is generated for kernel version '$kernel'" - fi - else - kdump_kver=$KDUMP_KERNELVER + . /lib/kdump/kdump-lib.sh + + prepare_kdump_bootinfo + + # $kernel is a variable from dracut + if [ "$KDUMP_KERNELVER" != $kernel ]; then + dwarn "Using kernel version '$KDUMP_KERNELVER' for early kdump," \ + "but the initramfs is generated for kernel version '$kernel'" fi - KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}" - KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img" } install() { @@ -53,13 +49,16 @@ install() { inst_simple "/etc/sysconfig/kdump" inst_binary "/usr/sbin/kexec" inst_binary "/usr/bin/gawk" "/usr/bin/awk" + inst_binary "/usr/bin/logger" "/usr/bin/logger" + inst_binary "/usr/bin/printf" "/usr/bin/printf" inst_script "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh" + inst_script "/lib/kdump/kdump-logger.sh" "/lib/kdump-logger.sh" inst_hook cmdline 00 "$moddir/early-kdump.sh" inst_binary "$KDUMP_KERNEL" inst_binary "$KDUMP_INITRD" - ln_r "$KDUMP_KERNEL" "${KDUMP_BOOTDIR}/${KDUMP_IMG}-earlykdump${KDUMP_IMG_EXT}" - ln_r "$KDUMP_INITRD" "${KDUMP_BOOTDIR}/initramfs-earlykdump.img" + ln_r "$KDUMP_KERNEL" "/boot/kernel-earlykdump" + ln_r "$KDUMP_INITRD" "/boot/initramfs-earlykdump" chmod -x "${initdir}/$KDUMP_KERNEL" } diff --git a/dracut-early-kdump.sh b/dracut-early-kdump.sh index 69a34eb..129841e 100755 --- a/dracut-early-kdump.sh +++ b/dracut-early-kdump.sh @@ -12,14 +12,20 @@ EARLY_KEXEC_ARGS="" . /etc/sysconfig/kdump . /lib/dracut-lib.sh . /lib/kdump-lib.sh +. /lib/kdump-logger.sh + +#initiate the kdump logger +dlog_init +if [ $? -ne 0 ]; then + echo "failed to initiate the kdump logger." + exit 1 +fi prepare_parameters() { EARLY_KDUMP_CMDLINE=$(prepare_cmdline "${KDUMP_COMMANDLINE}" "${KDUMP_COMMANDLINE_REMOVE}" "${KDUMP_COMMANDLINE_APPEND}") - KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}") - - EARLY_KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-earlykdump${KDUMP_IMG_EXT}" - EARLY_KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-earlykdump.img" + EARLY_KDUMP_KERNEL="/boot/kernel-earlykdump" + EARLY_KDUMP_INITRD="/boot/initramfs-earlykdump" } early_kdump_load() @@ -30,7 +36,7 @@ early_kdump_load() fi if is_fadump_capable; then - echo "WARNING: early kdump doesn't support fadump." + dwarn "WARNING: early kdump doesn't support fadump." return 1 fi @@ -44,18 +50,25 @@ early_kdump_load() EARLY_KEXEC_ARGS=$(prepare_kexec_args "${KEXEC_ARGS}") if is_secure_boot_enforced; then - echo "Secure Boot is enabled. Using kexec file based syscall." + dinfo "Secure Boot is enabled. Using kexec file based syscall." EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS -s" fi + # Here, only output the messages, but do not save these messages + # to a file because the target disk may not be mounted yet, the + # earlykdump is too early. + ddebug "earlykdump: $KEXEC ${EARLY_KEXEC_ARGS} $standard_kexec_args \ + --command-line=$EARLY_KDUMP_CMDLINE --initrd=$EARLY_KDUMP_INITRD \ + $EARLY_KDUMP_KERNEL" + $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" + dinfo "kexec: loaded early-kdump kernel" return 0 else - echo "kexec: failed to load early-kdump kernel" + derror "kexec: failed to load early-kdump kernel" return 1 fi } @@ -63,10 +76,10 @@ early_kdump_load() set_early_kdump() { if getargbool 0 rd.earlykdump; then - echo "early-kdump is enabled." + dinfo "early-kdump is enabled." early_kdump_load else - echo "early-kdump is disabled." + dinfo "early-kdump is disabled." fi return 0 diff --git a/dracut-kdump.sh b/dracut-kdump.sh index 6f948fc..c7cf528 100755 --- a/dracut-kdump.sh +++ b/dracut-kdump.sh @@ -5,7 +5,6 @@ if [ -f /etc/fadump.initramfs ] && [ ! -f /proc/device-tree/rtas/ibm,kernel-dump exit 0 fi -exec &> /dev/console . /lib/dracut-lib.sh . /lib/kdump-lib-initramfs.sh @@ -22,7 +21,7 @@ do_dump() _ret=$? if [ $_ret -ne 0 ]; then - echo "kdump: saving vmcore failed" + derror "saving vmcore failed" fi return $_ret @@ -36,7 +35,7 @@ do_kdump_pre() "$KDUMP_PRE" _ret=$? if [ $_ret -ne 0 ]; then - echo "kdump: $KDUMP_PRE exited with $_ret status" + derror "$KDUMP_PRE exited with $_ret status" return $_ret fi fi @@ -47,7 +46,7 @@ do_kdump_pre() "$file" _ret=$? if [ $_ret -ne 0 ]; then - echo "kdump: $file exited with $_ret status" + derror "$file exited with $_ret status" fi done fi @@ -63,7 +62,7 @@ do_kdump_post() "$file" "$1" _ret=$? if [ $_ret -ne 0 ]; then - echo "kdump: $file exited with $_ret status" + derror "$file exited with $_ret status" fi done fi @@ -72,7 +71,7 @@ do_kdump_post() "$KDUMP_POST" "$1" _ret=$? if [ $_ret -ne 0 ]; then - echo "kdump: $KDUMP_POST exited with $_ret status" + derror "$KDUMP_POST exited with $_ret status" fi fi } @@ -88,7 +87,7 @@ dump_raw() [ -b "$_raw" ] || return 1 - echo "kdump: saving to raw disk $_raw" + dinfo "saving to raw disk $_raw" if ! $(echo -n $CORE_COLLECTOR|grep -q makedumpfile); then _src_size=`ls -l /proc/vmcore | cut -d' ' -f5` @@ -96,21 +95,25 @@ dump_raw() monitor_dd_progress $_src_size_mb & fi - echo "kdump: saving vmcore" + dinfo "saving vmcore" $CORE_COLLECTOR /proc/vmcore | dd of=$_raw bs=$DD_BLKSIZE >> /tmp/dd_progress_file 2>&1 || return 1 sync - echo "kdump: saving vmcore complete" + dinfo "saving vmcore complete" return 0 } dump_ssh() { + local _ret=0 + local _exitcode=0 _exitcode2=0 local _opt="-i $1 -o BatchMode=yes -o StrictHostKeyChecking=yes" local _dir="$KDUMP_PATH/$HOST_IP-$DATEDIR" local _host=$2 + local _vmcore="vmcore" + local _ipv6_addr="" _username="" - echo "kdump: saving to $_host:$_dir" + dinfo "saving to $_host:$_dir" cat /var/lib/random-seed > /dev/urandom ssh -q $_opt $_host mkdir -p $_dir || return 1 @@ -118,17 +121,54 @@ dump_ssh() save_vmcore_dmesg_ssh ${DMESG_COLLECTOR} ${_dir} "${_opt}" $_host save_opalcore_ssh ${_dir} "${_opt}" $_host - echo "kdump: saving vmcore" + dinfo "saving vmcore" + + if is_ipv6_address "$_host"; then + _username=${_host%@*} + _ipv6_addr="[${_host#*@}]" + fi if [ "${CORE_COLLECTOR%%[[:blank:]]*}" = "scp" ]; then - scp -q $_opt /proc/vmcore "$_host:$_dir/vmcore-incomplete" || return 1 - ssh $_opt $_host "mv $_dir/vmcore-incomplete $_dir/vmcore" || return 1 + if [ -n "$_username" ] && [ -n "$_ipv6_addr" ]; then + scp -q $_opt /proc/vmcore "$_username@$_ipv6_addr:$_dir/vmcore-incomplete" + else + scp -q $_opt /proc/vmcore "$_host:$_dir/vmcore-incomplete" + fi + _exitcode=$? + else + $CORE_COLLECTOR /proc/vmcore | ssh $_opt $_host "umask 0077 && dd bs=512 of=$_dir/vmcore-incomplete" + _exitcode=$? + _vmcore="vmcore.flat" + fi + + if [ $_exitcode -eq 0 ]; then + ssh $_opt $_host "mv $_dir/vmcore-incomplete $_dir/$_vmcore" + _exitcode2=$? + if [ $_exitcode2 -ne 0 ]; then + derror "moving vmcore failed, _exitcode:$_exitcode2" + else + dinfo "saving vmcore complete" + fi + else + derror "saving vmcore failed, _exitcode:$_exitcode" + fi + + dinfo "saving the $KDUMP_LOG_FILE to $_host:$_dir/" + save_log + if [ -n "$_username" ] && [ -n "$_ipv6_addr" ]; then + scp -q $_opt $KDUMP_LOG_FILE "$_username@$_ipv6_addr:$_dir/" else - $CORE_COLLECTOR /proc/vmcore | ssh $_opt $_host "dd bs=512 of=$_dir/vmcore-incomplete" || return 1 - ssh $_opt $_host "mv $_dir/vmcore-incomplete $_dir/vmcore.flat" || return 1 + scp -q $_opt $KDUMP_LOG_FILE "$_host:$_dir/" + fi + _ret=$? + if [ $_ret -ne 0 ]; then + derror "saving log file failed, _exitcode:$_ret" + fi + + if [ $_exitcode -ne 0 ] || [ $_exitcode2 -ne 0 ];then + return 1 fi - echo "kdump: saving vmcore complete" return 0 } @@ -136,6 +176,9 @@ save_opalcore_ssh() { local _path=$1 local _opts="$2" local _location=$3 + local _user_name="" _ipv6addr="" + + ddebug "_path=$_path _opts=$_opts _location=$_location" if [ ! -f $OPALCORE ]; then # Check if we are on an old kernel that uses a different path @@ -146,15 +189,25 @@ save_opalcore_ssh() { fi fi - echo "kdump: saving opalcore" - scp $_opts $OPALCORE $_location:$_path/opalcore-incomplete + if is_ipv6_address "$_host"; then + _user_name=${_location%@*} + _ipv6addr="[${_location#*@}]" + fi + + dinfo "saving opalcore:$OPALCORE to $_location:$_path" + + if [ -n "$_user_name" ] && [ -n "$_ipv6addr" ]; then + scp $_opts $OPALCORE $_user_name@$_ipv6addr:$_path/opalcore-incomplete + else + scp $_opts $OPALCORE $_location:$_path/opalcore-incomplete + fi if [ $? -ne 0 ]; then - echo "kdump: saving opalcore failed" + derror "saving opalcore failed" return 1 fi ssh $_opts $_location mv $_path/opalcore-incomplete $_path/opalcore - echo "kdump: saving opalcore complete" + dinfo "saving opalcore complete" return 0 } @@ -164,15 +217,15 @@ save_vmcore_dmesg_ssh() { local _opts="$3" local _location=$4 - echo "kdump: saving vmcore-dmesg.txt" - $_dmesg_collector /proc/vmcore | ssh $_opts $_location "dd of=$_path/vmcore-dmesg-incomplete.txt" + dinfo "saving vmcore-dmesg.txt to $_location:$_path" + $_dmesg_collector /proc/vmcore | ssh $_opts $_location "umask 0077 && dd of=$_path/vmcore-dmesg-incomplete.txt" _exitcode=$? if [ $_exitcode -eq 0 ]; then ssh -q $_opts $_location mv $_path/vmcore-dmesg-incomplete.txt $_path/vmcore-dmesg.txt - echo "kdump: saving vmcore-dmesg.txt complete" + dinfo "saving vmcore-dmesg.txt complete" else - echo "kdump: saving vmcore-dmesg.txt failed" + derror "saving vmcore-dmesg.txt failed" fi } @@ -182,12 +235,12 @@ get_host_ip() if is_nfs_dump_target || is_ssh_dump_target then kdumpnic=$(getarg kdumpnic=) - [ -z "$kdumpnic" ] && echo "kdump: failed to get kdumpnic!" && return 1 + [ -z "$kdumpnic" ] && derror "failed to get kdumpnic!" && return 1 _host=`ip addr show dev $kdumpnic|grep '[ ]*inet'` - [ $? -ne 0 ] && echo "kdump: wrong kdumpnic: $kdumpnic" && return 1 + [ $? -ne 0 ] && derror "wrong kdumpnic: $kdumpnic" && return 1 _host=`echo $_host | head -n 1 | cut -d' ' -f2` _host="${_host%%/*}" - [ -z "$_host" ] && echo "kdump: wrong kdumpnic: $kdumpnic" && return 1 + [ -z "$_host" ] && derror "wrong kdumpnic: $kdumpnic" && return 1 HOST_IP=$_host fi return 0 @@ -196,7 +249,7 @@ get_host_ip() read_kdump_conf() { if [ ! -f "$KDUMP_CONF" ]; then - echo "kdump: $KDUMP_CONF not found" + derror "$KDUMP_CONF not found" return fi @@ -240,7 +293,7 @@ fence_kdump_notify get_host_ip if [ $? -ne 0 ]; then - echo "kdump: get_host_ip exited with non-zero status!" + derror "get_host_ip exited with non-zero status!" exit 1 fi @@ -250,7 +303,7 @@ fi do_kdump_pre if [ $? -ne 0 ]; then - echo "kdump: kdump_pre script exited with non-zero status!" + derror "kdump_pre script exited with non-zero status!" do_final_action # During systemd service to reboot the machine, stop this shell script running exit 1 @@ -261,7 +314,7 @@ DUMP_RETVAL=$? do_kdump_post $DUMP_RETVAL if [ $? -ne 0 ]; then - echo "kdump: kdump_post script exited with non-zero status!" + derror "kdump_post script exited with non-zero status!" fi if [ $DUMP_RETVAL -ne 0 ]; then diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 32506ad..dafdad6 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -1,11 +1,12 @@ #!/bin/bash -. $dracutfunctions -. /lib/kdump/kdump-lib.sh +kdump_module_init() { + if ! [[ -d "${initdir}/tmp" ]]; then + mkdir -p "${initdir}/tmp" + fi -if ! [[ -d "${initdir}/tmp" ]]; then - mkdir -p "${initdir}/tmp" -fi + . /lib/kdump/kdump-lib.sh +} check() { [[ $debug ]] && set -x @@ -20,6 +21,12 @@ check() { depends() { local _dep="base shutdown" + kdump_module_init + + add_opt_module() { + [[ " $omit_dracutmodules " != *\ $1\ * ]] && _dep="$_dep $1" + } + is_squash_available() { for kmodule in squashfs overlay loop; do if [ -z "$KDUMP_KERNELVER" ]; then @@ -31,13 +38,26 @@ depends() { } if is_squash_available && ! is_fadump_capable; then - _dep="$_dep squash" + add_opt_module squash else dwarning "Required modules to build a squashed kdump image is missing!" fi + add_opt_module watchdog-modules + if is_wdt_active; then + add_opt_module watchdog + fi + + if is_ssh_dump_target; then + _dep="$_dep ssh-client" + fi + + if [ "$(uname -m)" = "s390x" ]; then + _dep="$_dep znet" + fi + if [ -n "$( find /sys/devices -name drm )" ] || [ -d /sys/module/hyperv_fb ]; then - _dep="$_dep drm" + add_opt_module drm fi if is_generic_fence_kdump || is_pcs_fence_kdump; then @@ -45,7 +65,6 @@ depends() { fi echo $_dep - return 0 } kdump_is_bridge() { @@ -100,12 +119,122 @@ kdump_setup_dns() { done < "/etc/resolv.conf" } +# $1: repeat times +# $2: string to be repeated +# $3: separator +repeatedly_join_str() { + local _count="$1" + local _str="$2" + local _separator="$3" + local i _res + + if [[ "$_count" -le 0 ]]; then + echo -n "" + return + fi + + i=0 + _res="$_str" + ((_count--)) + + while [[ "$i" -lt "$_count" ]]; do + ((i++)) + _res="${_res}${_separator}${_str}" + done + echo -n "$_res" +} + +# $1: prefix +# $2: ipv6_flag="-6" indicates it's IPv6 +# Given a prefix, calculate the netmask (equivalent of "ipcalc -m") +# by concatenating three parts, +# 1) the groups with all bits set 1 +# 2) a group with partial bits set to 0 +# 3) the groups with all bits set to 0 +cal_netmask_by_prefix() { + local _prefix="$1" + local _ipv6_flag="$2" _ipv6 + local _bits_per_octet=8 + local _count _res _octets_per_group _octets_total _seperator _total_groups + local _max_group_value _max_group_value_repr _bits_per_group _tmp _zero_bits + + if [[ "$_ipv6_flag" == "-6" ]]; then + _ipv6=1 + else + _ipv6=0 + fi + + if [[ "$_prefix" -lt 0 || "$_prefix" -gt 128 ]] || \ + ( ((!_ipv6)) && [[ "$_prefix" -gt 32 ]] ); then + derror "Bad prefix:$_prefix for calculating netmask" + exit 1 + fi + + if ((_ipv6)); then + _octets_per_group=2 + _octets_total=16 + _seperator=":" + else + _octets_per_group=1 + _octets_total=4 + _seperator="." + fi + + _total_groups=$((_octets_total/_octets_per_group)) + _bits_per_group=$((_octets_per_group * _bits_per_octet)) + _max_group_value=$(((1 << _bits_per_group) - 1)) + + if ((_ipv6)); then + _max_group_value_repr=$(printf "%x" $_max_group_value) + else + _max_group_value_repr="$_max_group_value" + fi + + _count=$((_prefix/_octets_per_group/_bits_per_octet)) + _first_part=$(repeatedly_join_str "$_count" "$_max_group_value_repr" "$_seperator") + _res="$_first_part" + + _tmp=$((_octets_total*_bits_per_octet-_prefix)) + _zero_bits=$(expr $_tmp % $_bits_per_group) + if [[ "$_zero_bits" -ne 0 ]]; then + _second_part=$((_max_group_value >> _zero_bits << _zero_bits)) + if ((_ipv6)); then + _second_part=$(printf "%x" $_second_part) + fi + ((_count++)) + if [[ -z "$_first_part" ]]; then + _res="$_second_part" + else + _res="${_first_part}${_seperator}${_second_part}" + fi + fi + + _count=$((_total_groups-_count)) + if [[ "$_count" -eq 0 ]]; then + echo -n "$_res" + return + fi + + if ((_ipv6)) && [[ "$_count" -gt 1 ]] ; then + # use condensed notion for IPv6 + _third_part=":" + else + _third_part=$(repeatedly_join_str "$_count" "0" "$_seperator") + fi + + if [[ -z "$_res" ]] && ((!_ipv6)) ; then + echo -n "${_third_part}" + else + echo -n "${_res}${_seperator}${_third_part}" + fi +} + #$1: netdev name #$2: srcaddr #if it use static ip echo it, or echo null kdump_static_ip() { - local _netdev="$1" _srcaddr="$2" _ipv6_flag - local _netmask _gateway _ipaddr _target _nexthop + local _netdev="$1" _srcaddr="$2" kdumpnic="$3" _ipv6_flag + local _netmask _gateway _ipaddr _target _nexthop _prefix _ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr\/.* /{print \$2}") @@ -123,7 +252,12 @@ kdump_static_ip() { _srcaddr="[$_srcaddr]" _gateway="[$_gateway]" else - _netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2) + _prefix=$(cut -d'/' -f2 <<< "$_ipaddr") + _netmask=$(cal_netmask_by_prefix "$_prefix" "$_ipv6_flag") + if [[ "$?" -ne 0 ]]; then + derror "Failed to calculate netmask for $_ipaddr" + exit 1 + fi fi echo -n "${_srcaddr}::${_gateway}:${_netmask}::" fi @@ -136,7 +270,7 @@ kdump_static_ip() { _target="[$_target]" _nexthop="[$_nexthop]" fi - echo "rd.route=$_target:$_nexthop:$_netdev" + echo "rd.route=$_target:$_nexthop:$kdumpnic" done >> ${initdir}/etc/cmdline.d/45route-static.conf } @@ -244,14 +378,10 @@ kdump_setup_vlan() { local _netmac="$(kdump_get_mac_addr $_phydev)" local _kdumpdev - #Just support vlan over bond, it is not easy - #to support all other complex setup + #Just support vlan over bond and team if kdump_is_bridge "$_phydev"; then derror "Vlan over bridge is not supported!" exit 1 - elif kdump_is_team "$_phydev"; then - derror "Vlan over team is not supported!" - exit 1 elif kdump_is_bond "$_phydev"; then kdump_setup_bond "$_phydev" echo " vlan=$(kdump_setup_ifname $_netdev):$_phydev" > ${initdir}/etc/cmdline.d/43vlan.conf @@ -261,6 +391,37 @@ kdump_setup_vlan() { fi } +# find online znet device +# return ifname (_netdev) +# code reaped from the list_configured function of +# https://github.com/hreinecke/s390-tools/blob/master/zconf/znetconf +find_online_znet_device() { + local CCWGROUPBUS_DEVICEDIR="/sys/bus/ccwgroup/devices" + local NETWORK_DEVICES d ifname ONLINE + + [ ! -d "$CCWGROUPBUS_DEVICEDIR" ] && return + NETWORK_DEVICES=$(find $CCWGROUPBUS_DEVICEDIR) + for d in $NETWORK_DEVICES + do + [ ! -f "$d/online" ] && continue + read ONLINE < $d/online + if [ $ONLINE -ne 1 ]; then + continue + fi + # determine interface name, if there (only for qeth and if + # device is online) + if [ -f $d/if_name ] + then + read ifname < $d/if_name + elif [ -d $d/net ] + then + ifname=$(ls $d/net/) + fi + [ -n "$ifname" ] && break + done + echo -n "$ifname" +} + # setup s390 znet cmdline # $1: netdev name kdump_setup_znet() { @@ -278,24 +439,32 @@ kdump_setup_znet() { # Setup dracut to bringup a given network interface kdump_setup_netdev() { local _netdev=$1 _srcaddr=$2 - local _static _proto _ip_conf _ip_opts _ifname_opts + local _static _proto _ip_conf _ip_opts _ifname_opts kdumpnic local _netmac=$(kdump_get_mac_addr $_netdev) + local _znet_netdev - if [ "$(uname -m)" = "s390x" ]; then - kdump_setup_znet $_netdev + kdumpnic=$(kdump_setup_ifname $_netdev) + + _znet_netdev=$(find_online_znet_device) + if [[ -n "$_znet_netdev" ]]; then + $(kdump_setup_znet "$_znet_netdev") + if [[ $? != 0 ]]; then + derror "Failed to set up znet" + exit 1 + fi fi - _static=$(kdump_static_ip $_netdev $_srcaddr) + _static=$(kdump_static_ip $_netdev $_srcaddr $kdumpnic) if [ -n "$_static" ]; then _proto=none elif is_ipv6_address $_srcaddr; then - _proto=either6 + _proto=auto6 else _proto=dhcp fi _ip_conf="${initdir}/etc/cmdline.d/40ip.conf" - _ip_opts=" ip=${_static}$(kdump_setup_ifname $_netdev):${_proto}" + _ip_opts=" ip=${_static}$kdumpnic:${_proto}" # dracut doesn't allow duplicated configuration for same NIC, even they're exactly the same. # so we have to avoid adding duplicates @@ -315,7 +484,7 @@ kdump_setup_netdev() { elif kdump_is_vlan "$_netdev"; then kdump_setup_vlan "$_netdev" else - _ifname_opts=" ifname=$(kdump_setup_ifname $_netdev):$_netmac" + _ifname_opts=" ifname=$kdumpnic:$_netmac" echo "$_ifname_opts" >> $_ip_conf fi @@ -759,9 +928,32 @@ remove_cpu_online_rule() { sed -i '/SUBSYSTEM=="cpu"/d' $file } +kdump_install_systemd_conf() { + local failure_action=$(get_option_value "failure_action") + + # Kdump turns out to require longer default systemd mount timeout + # than 1st kernel(90s by default), we use default 300s for kdump. + grep -r "^[[:space:]]*DefaultTimeoutStartSec=" ${initdir}/etc/systemd/system.conf* &>/dev/null + if [ $? -ne 0 ]; then + mkdir -p ${initdir}/etc/systemd/system.conf.d + echo "[Manager]" > ${initdir}/etc/systemd/system.conf.d/kdump.conf + echo "DefaultTimeoutStartSec=300s" >> ${initdir}/etc/systemd/system.conf.d/kdump.conf + fi + + # Forward logs to console directly, and don't read Kmsg, this avoids + # unneccessary memory consumption and make console output more useful. + # Only do so for non fadump image. + mkdir -p ${initdir}/etc/systemd/journald.conf.d + echo "[Journal]" > ${initdir}/etc/systemd/journald.conf.d/kdump.conf + echo "Storage=volatile" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf + echo "ReadKMsg=no" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf + echo "ForwardToConsole=yes" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf +} + install() { local arch + kdump_module_init kdump_install_conf remove_sysctl_conf @@ -789,11 +981,15 @@ install() { inst "/bin/head" "/bin/head" inst "/sbin/makedumpfile" "/sbin/makedumpfile" inst "/sbin/vmcore-dmesg" "/sbin/vmcore-dmesg" + inst "/usr/bin/printf" "/sbin/printf" + inst "/usr/bin/logger" "/sbin/logger" + inst "/usr/bin/chmod" "/sbin/chmod" inst "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh" inst "/lib/kdump/kdump-lib-initramfs.sh" "/lib/kdump-lib-initramfs.sh" + inst "/lib/kdump/kdump-logger.sh" "/lib/kdump-logger.sh" inst "$moddir/kdump.sh" "/usr/bin/kdump.sh" inst "$moddir/kdump-capture.service" "$systemdsystemunitdir/kdump-capture.service" - ln_r "$systemdsystemunitdir/kdump-capture.service" "$systemdsystemunitdir/initrd.target.wants/kdump-capture.service" + systemctl -q --root "$initdir" add-wants initrd.target kdump-capture.service inst "$moddir/kdump-error-handler.sh" "/usr/bin/kdump-error-handler.sh" inst "$moddir/kdump-error-handler.service" "$systemdsystemunitdir/kdump-error-handler.service" # Replace existing emergency service and emergency target @@ -807,6 +1003,8 @@ install() { # at some point of time. kdump_check_iscsi_targets + kdump_install_systemd_conf + # For the lvm type target under kdump, in /etc/lvm/lvm.conf we can # safely replace "reserved_memory=XXXX"(default value is 8192) with # "reserved_memory=1024" to lower memory pressure under kdump. We do @@ -816,25 +1014,8 @@ install() { 's/\(^[[:space:]]*reserved_memory[[:space:]]*=\)[[:space:]]*[[:digit:]]*/\1 1024/' \ ${initdir}/etc/lvm/lvm.conf &>/dev/null - # Kdump turns out to require longer default systemd mount timeout - # than 1st kernel(90s by default), we use default 300s for kdump. - grep -r "^[[:space:]]*DefaultTimeoutStartSec=" ${initdir}/etc/systemd/system.conf* &>/dev/null - if [ $? -ne 0 ]; then - mkdir -p ${initdir}/etc/systemd/system.conf.d - echo "[Manager]" > ${initdir}/etc/systemd/system.conf.d/kdump.conf - echo "DefaultTimeoutStartSec=300s" >> ${initdir}/etc/systemd/system.conf.d/kdump.conf - fi - + # Save more memory by dropping switch root capability if ! is_fadump_capable; then - # Forward logs to console directly, this avoids unneccessary memory - # consumption and make console output more useful. - # Only do so for non fadump image. - mkdir -p ${initdir}/etc/systemd/journald.conf.d - echo "[Journal]" > ${initdir}/etc/systemd/journald.conf.d/kdump.conf - echo "Storage=none" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf - echo "ForwardToConsole=yes" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf - - # Save more memory by dropping switch root capability dracut_no_switch_root fi } diff --git a/eppic-remove-duplicated-variable-declaration.patch b/eppic-remove-duplicated-variable-declaration.patch deleted file mode 100644 index cb723bc..0000000 --- a/eppic-remove-duplicated-variable-declaration.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 2837fb1f5f8362976c188b30ebe50dc8b0377f64 Mon Sep 17 00:00:00 2001 -From: Kairui Song -Date: Wed, 29 Jan 2020 11:33:18 +0800 -Subject: [PATCH] Remove duplicated variable declaration - -When building on Fedora 32, following error is observed: - -... -/usr/bin/ld: ../eppic/libeppic/libeppic.a(eppic_stat.o):/builddir/build/BUILD/kexec-tools-2.0.20/eppic/libeppic/eppic.h:474: multiple definition of `lastv'; -../eppic/libeppic/libeppic.a(eppic_func.o):/builddir/build/BUILD/kexec-tools-2.0.20/eppic/libeppic/eppic.h:474: first defined here -... - -And apparently, the variable is wrongly declared multiple times. So -remove duplicated declaration. - -Signed-off-by: Kairui Song ---- - libeppic/eppic.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libeppic/eppic.h b/libeppic/eppic.h -index 5664583..836b475 100644 ---- a/libeppic/eppic.h -+++ b/libeppic/eppic.h -@@ -471,7 +471,7 @@ type_t *eppic_addstorage(type_t *t1, type_t *t2); - type_t *eppic_getvoidstruct(int ctype); - - extern int lineno, needvar, instruct, nomacs, eppic_legacy; --node_t *lastv; -+extern node_t *lastv; - - #define NULLNODE ((node_t*)0) - diff --git a/fadump-howto.txt b/fadump-howto.txt index c891e37..433e9a6 100644 --- a/fadump-howto.txt +++ b/fadump-howto.txt @@ -104,6 +104,11 @@ For the recommended value of X, see 'FADump Memory Requirements' section. # grubby --args="fadump=on crashkernel=6G" --update-kernel=/boot/vmlinuz-`uname -r` +By default, FADump reserved memory will be initialized as CMA area to make the +memory available through CMA allocator on the production kernel. We can opt out +of this, making reserved memory unavailable to production kernel, by booting the +linux kernel with 'fadump=nocma' instead of 'fadump=on'. + The term 'boot memory' means size of the low memory chunk that is required for a kernel to boot successfully when booted with restricted memory. By default, the boot memory size will be the larger of 5% of system RAM or 256MB. @@ -219,12 +224,16 @@ Things to remember: dracut_args --add "network" 4) If FADump is configured to capture vmcore to a remote dump target using SSH - or NFS protocol, the network interface is renamed to kdump- - if is generic, for example, *eth#, or net#. This problem - occurs because the vmcore capture scripts in the initial RAM disk (initrd) - add the kdump- prefix to the network interface name to secure persistent - naming. As the same initrd is used for production kernel boot, the interface - name is changed for the production kernel too. + or NFS protocol, the corresponding network interface '' is + renamed to 'kdump-', if it is generic (like *eth# or net#). + It happens because vmcore capture scripts in the initial RAM disk (initrd) + add the 'kdump-' prefix to the network interface name to secure persistent + naming. And as capture kernel and production kernel use the same initrd in + case of FADump, the interface name is changed for the production kernel too. + This is likely to impact network configuration setup for production kernel. + So, it is recommended to use a non-generic name for a network interface, + before setting up FADump to capture vmcore to a remote dump target based on + that network interface, to avoid running into network configuration issues. Dump Triggering methods: @@ -326,9 +335,14 @@ the original command line completely. How to disable FADump: -Remove "fadump=on" from kernel cmdline parameters: +Remove "fadump=on"/"fadump=nocma" from kernel cmdline parameters OR replace +it with "fadump=off" kernel cmdline parameter: # grubby --update-kernel=/boot/vmlinuz-`uname -r` --remove-args="fadump=on" +or + # grubby --update-kernel=/boot/vmlinuz-`uname -r` --remove-args="fadump=nocma" +OR + # grubby --update-kernel=/boot/vmlinuz-`uname -r` --args="fadump=off" If KDump is to be used as the dump capturing mechanism, update the crashkernel parameter (Else, remove "crashkernel=" parameter too, using grubby): diff --git a/kdump-dep-generator.sh b/kdump-dep-generator.sh index b6fab2d..f48c8f6 100644 --- a/kdump-dep-generator.sh +++ b/kdump-dep-generator.sh @@ -4,6 +4,7 @@ # http://www.freedesktop.org/wiki/Software/systemd/Generators/ . /usr/lib/kdump/kdump-lib.sh +. /usr/lib/kdump/kdump-logger.sh # If invokded with no arguments for testing purpose, output to /tmp to # avoid overriding the existing. diff --git a/kdump-lib-initramfs.sh b/kdump-lib-initramfs.sh index 2a7b613..e030fe6 100755 --- a/kdump-lib-initramfs.sh +++ b/kdump-lib-initramfs.sh @@ -1,10 +1,12 @@ # These variables and functions are useful in 2nd kernel . /lib/kdump-lib.sh +. /lib/kdump-logger.sh KDUMP_PATH="/var/crash" +KDUMP_LOG_FILE="/run/initramfs/kexec-dmesg.log" CORE_COLLECTOR="" -DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 1 -d 31" +DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 7 -d 31" DMESG_COLLECTOR="/sbin/vmcore-dmesg" FAILURE_ACTION="systemctl reboot -f" DATEDIR=`date +%Y-%m-%d-%T` @@ -20,6 +22,13 @@ KDUMP_POST="" NEWROOT="/sysroot" OPALCORE="/sys/firmware/opal/mpipl/core" +#initiate the kdump logger +dlog_init +if [ $? -ne 0 ]; then + echo "failed to initiate the kdump logger." + exit 1 +fi + get_kdump_confs() { local config_opt config_val @@ -94,34 +103,37 @@ get_kdump_confs() fi } +# store the kexec kernel log to a file. +save_log() +{ + dmesg -T > $KDUMP_LOG_FILE + + if command -v journalctl > /dev/null; then + journalctl -ab >> $KDUMP_LOG_FILE + fi + chmod 600 $KDUMP_LOG_FILE +} + # dump_fs dump_fs() { + local _exitcode local _mp=$1 - local _dev=$(get_mount_info SOURCE target $_mp -f) - local _op=$(get_mount_info OPTIONS target $_mp -f) - - # If dump path have a corresponding device entry but not mounted, mount it. - if [ -n "$_dev" ] || [ "$_dev" == "rootfs" ]; then - if ! is_mounted "$_mp"; then - echo "kdump: dump target $_dev is not mounted, trying to mount..." - mkdir -p $_mp - mount -o $_op $_dev $_mp - - if [ $? -ne 0 ]; then - echo "kdump: mounting failed (mount point: $_mp, option: $_op)" - return 1 - fi + ddebug "dump_fs _mp=$_mp" + + if ! is_mounted "$_mp"; then + dinfo "dump path \"$_mp\" is not mounted, trying to mount..." + mount --target $_mp + if [ $? -ne 0 ]; then + derror "failed to dump to \"$_mp\", it's not a mount point!" + return 1 fi - else - echo "kdump: failed to dump to \"$_mp\", it's not a mount point!" - return 1 fi # Remove -F in makedumpfile case. We don't want a flat format dump here. [[ $CORE_COLLECTOR = *makedumpfile* ]] && CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e "s/-F//g"` - echo "kdump: saving to $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/" + dinfo "saving to $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/" mount -o remount,rw $_mp || return 1 mkdir -p $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR || return 1 @@ -129,12 +141,23 @@ dump_fs() save_vmcore_dmesg_fs ${DMESG_COLLECTOR} "$_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/" save_opalcore_fs "$_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/" - echo "kdump: saving vmcore" - $CORE_COLLECTOR /proc/vmcore $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore-incomplete || return 1 - mv $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore-incomplete $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore - sync + dinfo "saving vmcore" + $CORE_COLLECTOR /proc/vmcore $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore-incomplete + _exitcode=$? + if [ $_exitcode -eq 0 ]; then + mv $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore-incomplete $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore + sync + dinfo "saving vmcore complete" + else + derror "saving vmcore failed, _exitcode:$_exitcode" + fi - echo "kdump: saving vmcore complete" + dinfo "saving the $KDUMP_LOG_FILE to $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/" + save_log + mv $KDUMP_LOG_FILE $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/ + if [ $_exitcode -ne 0 ]; then + return 1 + fi # improper kernel cmdline can cause the failure of echo, we can ignore this kind of failure return 0 @@ -144,19 +167,20 @@ save_vmcore_dmesg_fs() { local _dmesg_collector=$1 local _path=$2 - echo "kdump: saving vmcore-dmesg.txt" + dinfo "saving vmcore-dmesg.txt to ${_path}" $_dmesg_collector /proc/vmcore > ${_path}/vmcore-dmesg-incomplete.txt _exitcode=$? if [ $_exitcode -eq 0 ]; then mv ${_path}/vmcore-dmesg-incomplete.txt ${_path}/vmcore-dmesg.txt + chmod 600 ${_path}/vmcore-dmesg.txt # Make sure file is on disk. There have been instances where later # saving vmcore failed and system rebooted without sync and there # was no vmcore-dmesg.txt available. sync - echo "kdump: saving vmcore-dmesg.txt complete" + dinfo "saving vmcore-dmesg.txt complete" else - echo "kdump: saving vmcore-dmesg.txt failed" + derror "saving vmcore-dmesg.txt failed" fi } @@ -172,43 +196,47 @@ save_opalcore_fs() { fi fi - echo "kdump: saving opalcore" + dinfo "saving opalcore:$OPALCORE to ${_path}/opalcore" cp $OPALCORE ${_path}/opalcore if [ $? -ne 0 ]; then - echo "kdump: saving opalcore failed" + derror "saving opalcore failed" return 1 fi sync - echo "kdump: saving opalcore complete" + dinfo "saving opalcore complete" return 0 } dump_to_rootfs() { - echo "Kdump: trying to bring up rootfs device" + dinfo "Trying to bring up rootfs device" systemctl start dracut-initqueue - echo "Kdump: waiting for rootfs mount, will timeout after 90 seconds" + dinfo "Waiting for rootfs mount, will timeout after 90 seconds" systemctl start sysroot.mount + ddebug "NEWROOT=$NEWROOT" + dump_fs $NEWROOT } kdump_emergency_shell() { echo "PS1=\"kdump:\\\${PWD}# \"" >/etc/profile + ddebug "Switching to dracut emergency..." /bin/dracut-emergency rm -f /etc/profile } do_failure_action() { - echo "Kdump: Executing failure action $FAILURE_ACTION" + dinfo "Executing failure action $FAILURE_ACTION" eval $FAILURE_ACTION } do_final_action() { + dinfo "Executing final action $FINAL_ACTION" eval $FINAL_ACTION } diff --git a/kdump-lib.sh b/kdump-lib.sh index 3abd707..67ee10e 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -20,14 +20,10 @@ is_fadump_capable() } perror_exit() { - echo $@ >&2 + derror "$@" exit 1 } -perror() { - echo $@ >&2 -} - is_ssh_dump_target() { grep -q "^ssh[[:blank:]].*@" /etc/kdump.conf @@ -326,6 +322,11 @@ is_ipv6_auto() fi } +is_atomic() +{ + grep -q "ostree" /proc/cmdline +} + is_ipv6_address() { echo $1 | grep -q ":" @@ -458,28 +459,33 @@ get_ifcfg_filename() { echo -n "${ifcfg_file}" } -# returns 0 when omission of watchdog module is desired in dracut_args +# returns 0 when omission of a module is desired in dracut_args # returns 1 otherwise -is_wdt_mod_omitted() { - local dracut_args - local ret=1 +is_dracut_mod_omitted() { + local dracut_args dracut_mod=$1 + + set -- $(grep "^dracut_args" /etc/kdump.conf) + while [ $# -gt 0 ]; do + case $1 in + -o|--omit) + [[ " ${2//[^[:alnum:]]/ } " == *" $dracut_mod "* ]] && return 0 + esac + shift + done - dracut_args=$(grep "^dracut_args" /etc/kdump.conf) - [[ -z $dracut_args ]] && return $ret + return 1 +} - eval set -- $dracut_args - while :; do - [[ -z $1 ]] && break - case $1 in - -o|--omit) - echo $2 | grep -qw "watchdog" - [[ $? == 0 ]] && ret=0 - break - esac - shift - done +is_wdt_active() { + local active - return $ret + [ -d /sys/class/watchdog ] || return 1 + for dir in /sys/class/watchdog/*; do + [ -f "$dir/state" ] || continue + active=$(< "$dir/state") + [ "$active" = "active" ] && return 0 + done + return 1 } # If "dracut_args" contains "--mount" information, use it @@ -508,7 +514,7 @@ check_crash_mem_reserved() mem_reserved=$(cat /sys/kernel/kexec_crash_size) if [ $mem_reserved -eq 0 ]; then - echo "No memory reserved for crash kernel" + derror "No memory reserved for crash kernel" return 1 fi @@ -518,7 +524,7 @@ check_crash_mem_reserved() check_kdump_feasibility() { if [ ! -e /sys/kernel/kexec_crash_loaded ]; then - echo "Kdump is not supported on this kernel" + derror "Kdump is not supported on this kernel" return 1 fi check_crash_mem_reserved @@ -528,7 +534,7 @@ check_kdump_feasibility() check_current_kdump_status() { if [ ! -f /sys/kernel/kexec_crash_loaded ];then - echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel" + derror "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel" return 1 fi @@ -611,12 +617,18 @@ is_secure_boot_enforced() local secure_boot_file setup_mode_file local secure_boot_byte setup_mode_byte - # On powerpc, os-secureboot-enforcing DT property indicates whether secureboot - # is enforced. Return success, if it is found. + # On powerpc, secure boot is enforced if: + # host secure boot: /ibm,secure-boot/os-secureboot-enforcing DT property exists + # guest secure boot: /ibm,secure-boot >= 2 if [ -f /proc/device-tree/ibm,secureboot/os-secureboot-enforcing ]; then return 0 fi + if [ -f /proc/device-tree/ibm,secure-boot ] && \ + [ $(lsprop /proc/device-tree/ibm,secure-boot | tail -1) -ge 2 ]; then + return 0 + fi + # Detect secure boot on x86 and arm64 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) @@ -629,6 +641,11 @@ is_secure_boot_enforced() fi fi + # Detect secure boot on s390x + if [[ -e "/sys/firmware/ipl/secure" && "$(cat /sys/firmware/ipl/secure)" == "1" ]]; then + return 0 + fi + return 1 } @@ -650,8 +667,7 @@ prepare_kexec_args() found_elf_args=`echo $kexec_args | grep elf32-core-headers` if [ -n "$found_elf_args" ] then - echo -n "Warning: elf32-core-headers overrides correct elf64 setting" - echo + dwarn "Warning: elf32-core-headers overrides correct elf64 setting" else kexec_args="$kexec_args --elf64-core-headers" fi @@ -666,24 +682,97 @@ prepare_kexec_args() echo $kexec_args } -check_boot_dir() +# +# Detect initrd and kernel location, results are stored in global enviromental variables: +# KDUMP_BOOTDIR, KDUMP_KERNELVER, KDUMP_KERNEL, DEFAULT_INITRD, and KDUMP_INITRD +# +# Expectes KDUMP_BOOTDIR, KDUMP_IMG, KDUMP_IMG_EXT, KDUMP_KERNELVER to be loaded from config already +# and will prefer already set values so user can specify custom kernel/initramfs location +# +prepare_kdump_bootinfo() { - local kdump_bootdir=$1 - #If user specify a boot dir for kdump kernel, let's use it. Otherwise - #check whether it's a atomic host. If yes parse the subdirectory under - #/boot; If not just find it under /boot. - if [ -n "$kdump_bootdir" ]; then - echo "$kdump_bootdir" - return + local boot_imglist boot_dirlist boot_initrdlist curr_kver="$(uname -r)" + local machine_id + + if [ -z "$KDUMP_KERNELVER" ]; then + KDUMP_KERNELVER="$(uname -r)" + fi + + read machine_id < /etc/machine-id + boot_dirlist=${KDUMP_BOOTDIR:-"/boot /boot/efi /efi /"} + boot_imglist="$KDUMP_IMG-$KDUMP_KERNELVER$KDUMP_IMG_EXT $machine_id/$KDUMP_KERNELVER/$KDUMP_IMG" + + # Use BOOT_IMAGE as reference if possible, strip the GRUB root device prefix in (hd0,gpt1) format + local boot_img="$(cat /proc/cmdline | sed "s/^BOOT_IMAGE=\((\S*)\)\?\(\S*\) .*/\2/")" + if [ -n "$boot_img" ]; then + boot_imglist="$boot_img $boot_imglist" fi - if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then - kdump_bootdir="/boot" + for dir in $boot_dirlist; do + for img in $boot_imglist; do + if [ -f "$dir/$img" ]; then + KDUMP_KERNEL=$(echo $dir/$img | tr -s '/') + break 2 + fi + done + done + + if ! [ -e "$KDUMP_KERNEL" ]; then + derror "Failed to detect kdump kernel location" + return 1 + fi + + # Set KDUMP_BOOTDIR to where kernel image is stored + KDUMP_BOOTDIR=$(dirname $KDUMP_KERNEL) + + # Default initrd should just stay aside of kernel image, try to find it in KDUMP_BOOTDIR + boot_initrdlist="initramfs-$KDUMP_KERNELVER.img initrd" + for initrd in $boot_initrdlist; do + if [ -f "$KDUMP_BOOTDIR/$initrd" ]; then + defaut_initrd_base="$initrd" + DEFAULT_INITRD="$KDUMP_BOOTDIR/$defaut_initrd_base" + break + fi + done + + # Create kdump initrd basename from default initrd basename + # initramfs-5.7.9-200.fc32.x86_64.img => initramfs-5.7.9-200.fc32.x86_64kdump.img + # initrd => initrdkdump + if [[ -z "$defaut_initrd_base" ]]; then + kdump_initrd_base=initramfs-${KDUMP_KERNELVER}kdump.img + elif [[ $defaut_initrd_base == *.* ]]; then + kdump_initrd_base=${defaut_initrd_base%.*}kdump.${DEFAULT_INITRD##*.} + else + kdump_initrd_base=${defaut_initrd_base}kdump + fi + + # Place kdump initrd in `/var/lib/kdump` if `KDUMP_BOOTDIR` not writable + if [[ ! -w "$KDUMP_BOOTDIR" ]];then + var_target_initrd_dir="/var/lib/kdump" + mkdir -p "$var_target_initrd_dir" + KDUMP_INITRD="$var_target_initrd_dir/$kdump_initrd_base" else - eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1) - kdump_bootdir="/boot"$(dirname $BOOT_IMAGE) + KDUMP_INITRD="$KDUMP_BOOTDIR/$kdump_initrd_base" fi - echo $kdump_bootdir +} + +get_watchdog_drvs() +{ + local _wdtdrvs _drv _dir + + for _dir in /sys/class/watchdog/*; do + # device/modalias will return driver of this device + [[ -f "$_dir/device/modalias" ]] || continue + _drv=$(< "$_dir/device/modalias") + _drv=$(modprobe --set-version "$KDUMP_KERNELVER" -R $_drv 2>/dev/null) + for i in $_drv; do + if ! [[ " $_wdtdrvs " == *" $i "* ]]; then + _wdtdrvs="$_wdtdrvs $i" + fi + done + done + + echo $_wdtdrvs } # @@ -728,12 +817,209 @@ prepare_cmdline() cmdline=$(append_cmdline "${cmdline}" disable_cpu_apicid ${id}) fi - # Disable efifb if hyperv_fb is in use, hyperv_fb will relocate the framebuffer - # but kexec_file_load always use original screen_info and in second kernel efifb - # will try to access an invalid framebuffer address - if [ -d /sys/module/hyperv_fb ]; then - cmdline=$(append_cmdline "$cmdline" "video=efifb:off") - fi + # If any watchdog is used, set it's pretimeout to 0. pretimeout let + # watchdog panic the kernel first, and reset the system after the + # panic. If the system is already in kdump, panic is not helpful + # and only increase the chance of watchdog failure. + for i in $(get_watchdog_drvs); do + cmdline+=" $i.pretimeout=0" + + if [[ $i == hpwdt ]]; then + # hpwdt have a special parameter kdumptimeout, is's only suppose + # to be set to non-zero in first kernel. In kdump, non-zero + # value could prevent the watchdog from resetting the system. + cmdline+=" $i.kdumptimeout=0" + fi + done echo ${cmdline} } + +#get system memory size in the unit of GB +get_system_size() +{ + result=$(cat /proc/iomem | grep "System RAM" | awk -F ":" '{ print $1 }' | tr [:lower:] [:upper:] | paste -sd+) + result="+$result" + # replace '-' with '+0x' and '+' with '-0x' + sum=$( echo $result | sed -e 's/-/K0x/g' | sed -e 's/+/-0x/g' | sed -e 's/K/+/g' ) + size=$(printf "%d\n" $(($sum))) + + # in MB unit + let size=$size/1024/1024 + # since RHEL-8.5 kernel round up total memory to 128M, so should user space + let size=($size+127)/128 + let size=$size*128 + # in GB unit + let size=$size/1024 + + echo $size +} + +get_recommend_size() +{ + local mem_size=$1 + local _ck_cmdline=$2 + local OLDIFS="$IFS" + + last_sz="" + last_unit="" + + start=${_ck_cmdline: :1} + if [ $mem_size -lt $start ]; then + echo "0M" + return + fi + IFS=',' + for i in $_ck_cmdline; do + end=$(echo $i | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $1 }') + recommend=$(echo $i | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $2 }') + size=${end: : -1} + unit=${end: -1} + if [ $unit == 'T' ]; then + let size=$size*1024 + fi + if [ $mem_size -lt $size ]; then + echo $recommend + IFS="$OLDIFS" + return + fi + done + IFS="$OLDIFS" +} + +# return recommended size based on current system RAM size +kdump_get_arch_recommend_size() +{ + if ! [[ -r "/proc/iomem" ]] ; then + echo "Error, can not access /proc/iomem." + return 1 + fi + arch=$(lscpu | grep Architecture | awk -F ":" '{ print $2 }' | tr [:lower:] [:upper:]) + + if [ $arch == "X86_64" ] || [ $arch == "S390X" ]; then + ck_cmdline="1G-4G:160M,4G-64G:192M,64G-1T:256M,1T-:512M" + elif [ $arch == "AARCH64" ]; then + ck_cmdline="2G-:448M" + elif [ $arch == "PPC64LE" ]; then + if is_fadump_capable; then + ck_cmdline="4G-16G:768M,16G-64G:1G,64G-128G:2G,128G-1T:4G,1T-2T:6G,2T-4T:12G,4T-8T:20G,8T-16T:36G,16T-32T:64G,32T-64T:128G,64T-:180G" + else + ck_cmdline="2G-4G:384M,4G-16G:512M,16G-64G:1G,64G-128G:2G,128G-:4G" + fi + fi + + ck_cmdline=$(echo $ck_cmdline | sed -e 's/-:/-102400T:/g') + sys_mem=$(get_system_size) + result=$(get_recommend_size $sys_mem "$ck_cmdline") + echo $result + return 0 +} + +# Print all underlying crypt devices of a block device +# print nothing if device is not on top of a crypt device +# $1: the block device to be checked in maj:min format +get_luks_crypt_dev() +{ + [[ -b /dev/block/$1 ]] || return 1 + + local _type=$(eval "$(blkid -u filesystem,crypto -o export -- /dev/block/$1); echo \$TYPE") + [[ $_type == "crypto_LUKS" ]] && echo $1 + + for _x in /sys/dev/block/$1/slaves/*; do + [[ -f $_x/dev ]] || continue + [[ $_x/subsystem -ef /sys/class/block ]] || continue + get_luks_crypt_dev "$(< "$_x/dev")" + done +} + +# kdump_get_maj_min +# Prints the major and minor of a device node. +# Example: +# $ get_maj_min /dev/sda2 +# 8:2 +kdump_get_maj_min() { + local _majmin + _majmin="$(stat -L -c '%t:%T' "$1" 2> /dev/null)" + printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))" +} + +get_all_kdump_crypt_dev() +{ + local _dev _crypt + + for _dev in $(get_block_dump_target); do + _crypt=$(get_luks_crypt_dev $(kdump_get_maj_min "$_dev")) + [[ -n "$_crypt" ]] && echo $_crypt + done +} + +check_vmlinux() +{ + # Use readelf to check if it's a valid ELF + readelf -h $1 &>/dev/null || return 1 +} + +get_vmlinux_size() +{ + local size=0 + + while read _type _offset _virtaddr _physaddr _fsize _msize _flg _aln; do + size=$(( $size + $_msize )) + done <<< $(readelf -l -W $1 | grep "^ LOAD" 2>/dev/stderr) + + echo $size +} + +try_decompress() +{ + # The obscure use of the "tr" filter is to work around older versions of + # "grep" that report the byte offset of the line instead of the pattern. + + # Try to find the header ($1) and decompress from here + for pos in `tr "$1\n$2" "\n$2=" < "$4" | grep -abo "^$2"` + do + if ! type -P $3 > /dev/null; then + ddebug "Signiature detected but '$3' is missing, skip this decompressor" + break + fi + + pos=${pos%%:*} + tail -c+$pos "$img" | $3 > $5 2> /dev/null + if check_vmlinux $5; then + ddebug "Kernel is extracted with '$3'" + return 0 + fi + done + + return 1 +} + +# Borrowed from linux/scripts/extract-vmlinux +get_kernel_size() +{ + # Prepare temp files: + local img=$1 tmp=$(mktemp /tmp/vmlinux-XXX) + trap "rm -f $tmp" 0 + + # Try to check if it's a vmlinux already + check_vmlinux $img && get_vmlinux_size $img && return 0 + + # That didn't work, so retry after decompression. + try_decompress '\037\213\010' xy gunzip $img $tmp || \ + try_decompress '\3757zXZ\000' abcde unxz $img $tmp || \ + try_decompress 'BZh' xy bunzip2 $img $tmp || \ + try_decompress '\135\0\0\0' xxx unlzma $img $tmp || \ + try_decompress '\211\114\132' xy 'lzop -d' $img $tmp || \ + try_decompress '\002!L\030' xxx 'lz4 -d' $img $tmp || \ + try_decompress '(\265/\375' xxx unzstd $img $tmp + + # Finally check for uncompressed images or objects: + [[ $? -eq 0 ]] && get_vmlinux_size $tmp && return 0 + + # Fallback to use iomem + local _size=0 + for _seg in $(cat /proc/iomem | grep -E "Kernel (code|rodata|data|bss)" | cut -d ":" -f 1); do + _size=$(( $_size + 0x${_seg#*-} - 0x${_seg%-*} )) + done + echo $_size +} diff --git a/kdump-logger.sh b/kdump-logger.sh new file mode 100755 index 0000000..370e5e8 --- /dev/null +++ b/kdump-logger.sh @@ -0,0 +1,348 @@ +#!/bin/bash +# +# This comes from the dracut-logger.sh +# +# The logger defined 4 logging levels: +# - ddebug (4) +# The DEBUG Level designates fine-grained informational events that are most +# useful to debug an application. +# - dinfo (3) +# The INFO level designates informational messages that highlight the +# progress of the application at coarse-grained level. +# - dwarn (2) +# The WARN level designates potentially harmful situations. +# - derror (1) +# The ERROR level designates error events that might still allow the +# application to continue running. +# +# Logging is controlled by following global variables: +# - @var kdump_stdloglvl - logging level to standard error (console output) +# - @var kdump_sysloglvl - logging level to syslog (by logger command) +# - @var kdump_kmsgloglvl - logging level to /dev/kmsg (only for boot-time) +# +# If any of the variables is not set, the function dlog_init() sets it to default: +# - In the first kernel: +# - @var kdump_stdloglvl = 3 (info) +# - @var kdump_sysloglvl = 0 (no logging) +# - @var kdump_kmsgloglvl = 0 (no logging) +# +# -In the second kernel: +# - @var kdump_stdloglvl = 0 (no logging) +# - @var kdump_sysloglvl = 3 (info) +# - @var kdump_kmsgloglvl = 0 (no logging) +# +# First of all you have to start with dlog_init() function which initializes +# required variables. Don't call any other logging function before that one! +# + +# Define vairables for the log levels in this module. +kdump_stdloglvl="" +kdump_sysloglvl="" +kdump_kmsgloglvl="" + +# The dracut-lib.sh is only available in the second kernel, and it won't +# be used in the first kernel because the dracut-lib.sh is invisible in +# the first kernel. +if [ -f /lib/dracut-lib.sh ]; then + . /lib/dracut-lib.sh +fi + +# @brief Get the log level from kernel command line. +# @retval 1 if something has gone wrong +# @retval 0 on success. +# +get_kdump_loglvl() +{ + (type -p getarg) && kdump_sysloglvl=$(getarg rd.kdumploglvl) + [ -z "$kdump_sysloglvl" ] && return 1; + + (type -p isdigit) && isdigit $kdump_sysloglvl + [ $? -ne 0 ] && return 1; + + return 0 +} + +# @brief Check the log level. +# @retval 1 if something has gone wrong +# @retval 0 on success. +# +check_loglvl() +{ + case "$1" in + 0|1|2|3|4) + return 0 + ;; + *) + return 1 + ;; + esac +} + +# @brief Initializes Logger. +# @retval 1 if something has gone wrong +# @retval 0 on success. +# +dlog_init() { + local ret=0; local errmsg + + if [ -s /proc/vmcore ];then + get_kdump_loglvl + if [ $? -ne 0 ];then + logger -t "kdump[$$]" -p warn -- "Kdump is using the default log level(3)." + kdump_sysloglvl=3 + fi + kdump_stdloglvl=0 + kdump_kmsgloglvl=0 + else + kdump_stdloglvl=$KDUMP_STDLOGLVL + kdump_sysloglvl=$KDUMP_SYSLOGLVL + kdump_kmsgloglvl=$KDUMP_KMSGLOGLVL + fi + + [ -z "$kdump_stdloglvl" ] && kdump_stdloglvl=3 + [ -z "$kdump_sysloglvl" ] && kdump_sysloglvl=0 + [ -z "$kdump_kmsgloglvl" ] && kdump_kmsgloglvl=0 + + for loglvl in "$kdump_stdloglvl" "$kdump_kmsgloglvl" "$kdump_sysloglvl"; do + check_loglvl "$loglvl" + if [ $? -ne 0 ]; then + echo "Illegal log level: $kdump_stdloglvl $kdump_kmsgloglvl $kdump_sysloglvl" + return 1 + fi + done + + # Skip initialization if it's already done. + [ -n "$kdump_maxloglvl" ] && return 0 + + if [[ $UID -ne 0 ]]; then + kdump_kmsgloglvl=0 + kdump_sysloglvl=0 + fi + + if [[ $kdump_sysloglvl -gt 0 ]]; then + if [[ -d /run/systemd/journal ]] \ + && type -P systemd-cat &>/dev/null \ + && systemctl --quiet is-active systemd-journald.socket &>/dev/null; then + readonly _systemdcatfile="/var/tmp/systemd-cat" + mkfifo "$_systemdcatfile" &>/dev/null + readonly _dlogfd=15 + systemd-cat -t 'kdump' --level-prefix=true <"$_systemdcatfile" & + exec 15>"$_systemdcatfile" + elif ! [ -S /dev/log -a -w /dev/log ] || ! command -v logger >/dev/null; then + # We cannot log to syslog, so turn this facility off. + kdump_kmsgloglvl=$kdump_sysloglvl + kdump_sysloglvl=0 + ret=1 + errmsg="No '/dev/log' or 'logger' included for syslog logging" + fi + fi + + local lvl; local maxloglvl_l=0 + for lvl in $kdump_stdloglvl $kdump_sysloglvl $kdump_kmsgloglvl; do + [[ $lvl -gt $maxloglvl_l ]] && maxloglvl_l=$lvl + done + readonly kdump_maxloglvl=$maxloglvl_l + export kdump_maxloglvl + + if [[ $kdump_stdloglvl -lt 4 ]] && [[ $kdump_kmsgloglvl -lt 4 ]] && [[ $kdump_sysloglvl -lt 4 ]]; then + unset ddebug + ddebug() { :; }; + fi + + if [[ $kdump_stdloglvl -lt 3 ]] && [[ $kdump_kmsgloglvl -lt 3 ]] && [[ $kdump_sysloglvl -lt 3 ]]; then + unset dinfo + dinfo() { :; }; + fi + + if [[ $kdump_stdloglvl -lt 2 ]] && [[ $kdump_kmsgloglvl -lt 2 ]] && [[ $kdump_sysloglvl -lt 2 ]]; then + unset dwarn + dwarn() { :; }; + unset dwarning + dwarning() { :; }; + fi + + if [[ $kdump_stdloglvl -lt 1 ]] && [[ $kdump_kmsgloglvl -lt 1 ]] && [[ $kdump_sysloglvl -lt 1 ]]; then + unset derror + derror() { :; }; + fi + + [ -n "$errmsg" ] && derror "$errmsg" + + return $ret +} + +## @brief Converts numeric level to logger priority defined by POSIX.2. +# +# @param lvl Numeric logging level in range from 1 to 4. +# @retval 1 if @a lvl is out of range. +# @retval 0 if @a lvl is correct. +# @result Echoes logger priority. +_lvl2syspri() { + case "$1" in + 1) echo error;; + 2) echo warning;; + 3) echo info;; + 4) echo debug;; + *) return 1;; + esac +} + +## @brief Converts logger numeric level to syslog log level +# +# @param lvl Numeric logging level in range from 1 to 4. +# @retval 1 if @a lvl is out of range. +# @retval 0 if @a lvl is correct. +# @result Echoes kernel console numeric log level +# +# Conversion is done as follows: +# +# +# none -> LOG_EMERG (0) +# none -> LOG_ALERT (1) +# none -> LOG_CRIT (2) +# ERROR(1) -> LOG_ERR (3) +# WARN(2) -> LOG_WARNING (4) +# none -> LOG_NOTICE (5) +# INFO(3) -> LOG_INFO (6) +# DEBUG(4) -> LOG_DEBUG (7) +# +# +# @see /usr/include/sys/syslog.h +_dlvl2syslvl() { + local lvl + + case "$1" in + 1) lvl=3;; + 2) lvl=4;; + 3) lvl=6;; + 4) lvl=7;; + *) return 1;; + esac + + # The number is constructed by multiplying the facility by 8 and then + # adding the level. + # About The Syslog Protocol, please refer to the RFC5424 for more details. + echo $((24+$lvl)) +} + +## @brief Prints to stderr, to syslog and/or /dev/kmsg given message with +# given level (priority). +# +# @param lvl Numeric logging level. +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +# +# @note This function is not supposed to be called manually. Please use +# dinfo(), ddebug(), or others instead which wrap this one. +# +# This is core logging function which logs given message to standard error +# and/or syslog (with POSIX shell command logger) and/or to /dev/kmsg. +# The format is following: +# +# X: some message +# +# where @c X is the first letter of logging level. See module description for +# details on that. +# +# Message to syslog is sent with tag @c kdump. Priorities are mapped as +# following: +# - @c ERROR to @c error +# - @c WARN to @c warning +# - @c INFO to @c info +# - @c DEBUG to @c debug +_do_dlog() { + local lvl="$1"; shift + local msg="$*" + + [[ $lvl -le $kdump_stdloglvl ]] && printf -- 'kdump: %s\n' "$msg" >&2 + + if [[ $lvl -le $kdump_sysloglvl ]]; then + if [[ "$_dlogfd" ]]; then + printf -- "<%s>%s\n" "$(($(_dlvl2syslvl $lvl) & 7))" "$msg" >&$_dlogfd + else + logger -t "kdump[$$]" -p $(_lvl2syspri $lvl) -- "$msg" + fi + fi + + [[ $lvl -le $kdump_kmsgloglvl ]] && \ + echo "<$(_dlvl2syslvl $lvl)>kdump[$$] $msg" >/dev/kmsg +} + +## @brief Internal helper function for _do_dlog() +# +# @param lvl Numeric logging level. +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +# +# @note This function is not supposed to be called manually. Please use +# dinfo(), ddebug(), or others instead which wrap this one. +# +# This function calls _do_dlog() either with parameter msg, or if +# none is given, it will read standard input and will use every line as +# a message. +# +# This enables: +# dwarn "This is a warning" +# echo "This is a warning" | dwarn +dlog() { + [ -z "$kdump_maxloglvl" ] && return 0 + [[ $1 -le $kdump_maxloglvl ]] || return 0 + + if [[ $# -gt 1 ]]; then + _do_dlog "$@" + else + while read line || [ -n "$line" ]; do + _do_dlog "$1" "$line" + done + fi +} + +## @brief Logs message at DEBUG level (4) +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +ddebug() { + set +x + dlog 4 "$@" + [ -n "$debug" ] && set -x || : +} + +## @brief Logs message at INFO level (3) +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +dinfo() { + set +x + dlog 3 "$@" + [ -n "$debug" ] && set -x || : +} + +## @brief Logs message at WARN level (2) +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +dwarn() { + set +x + dlog 2 "$@" + [ -n "$debug" ] && set -x || : +} + +## @brief It's an alias to dwarn() function. +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +dwarning() { + set +x + dwarn "$@" + [ -n "$debug" ] && set -x || : +} + +## @brief Logs message at ERROR level (1) +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +derror() { + set +x + dlog 1 "$@" + [ -n "$debug" ] && set -x || : +} diff --git a/kdump-migrate-action.sh b/kdump-migrate-action.sh new file mode 100755 index 0000000..c516639 --- /dev/null +++ b/kdump-migrate-action.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +systemctl is-active kdump +if [ $? -ne 0 ]; then + exit 0 +fi + +/usr/lib/kdump/kdump-restart.sh diff --git a/kdump-restart.sh b/kdump-restart.sh new file mode 100644 index 0000000..a9ecfc1 --- /dev/null +++ b/kdump-restart.sh @@ -0,0 +1,8 @@ +#!/bin/bash +export PATH="$PATH:/usr/bin:/usr/sbin" + +exec >>/var/log/kdump-migration.log 2>&1 + +echo "kdump: Partition Migration detected. Rebuilding initramfs image to reload." +/usr/bin/kdumpctl rebuild +/usr/bin/kdumpctl reload diff --git a/kdump.conf b/kdump.conf index 76fecd4..a0af268 100644 --- a/kdump.conf +++ b/kdump.conf @@ -21,7 +21,7 @@ # //%HOST-%DATE/, supports DNS. # # ssh -# - Will scp /proc/vmcore to :/%HOST-%DATE/, +# - Will save /proc/vmcore to :/%HOST-%DATE/, # supports DNS. # NOTE: make sure the user has write permissions on the server. # @@ -62,9 +62,9 @@ # as the initrd will automatically be populated with a # config file appropriate for the running kernel. # The default core_collector for raw/ssh dump is: -# "makedumpfile -F -l --message-level 1 -d 31". +# "makedumpfile -F -l --message-level 7 -d 31". # The default core_collector for other targets is: -# "makedumpfile -l --message-level 1 -d 31". +# "makedumpfile -l --message-level 7 -d 31". # # "makedumpfile -F" will create a flattened vmcore. # You need to use "makedumpfile -R" to rearrange the dump data to @@ -166,10 +166,12 @@ #ext4 LABEL=/boot #ext4 UUID=03138356-5e61-4ab3-b58e-27507ac41937 #nfs my.server.com:/export/tmp +#nfs [2001:db8::1:2:3:4]:/export/tmp #ssh user@my.server.com +#ssh user@2001:db8::1:2:3:4 #sshkey /root/.ssh/kdump_id_rsa path /var/crash -core_collector makedumpfile -l --message-level 1 -d 31 +core_collector makedumpfile -l --message-level 7 -d 31 #core_collector scp #kdump_post /var/crash/scripts/kdump-post.sh #kdump_pre /var/crash/scripts/kdump-pre.sh diff --git a/kdump.conf.5 b/kdump.conf.5 index 4aacac8..ce23dea 100644 --- a/kdump.conf.5 +++ b/kdump.conf.5 @@ -85,9 +85,9 @@ for the running kernel. .PP Note 1: About default core collector: The default core_collector for raw/ssh dump is: -"makedumpfile -F -l --message-level 1 -d 31". +"makedumpfile -F -l --message-level 7 -d 31". The default core_collector for other targets is: -"makedumpfile -l --message-level 1 -d 31". +"makedumpfile -l --message-level 7 -d 31". Even if core_collector option is commented out in kdump.conf, makedumpfile is the default core collector and kdump uses it internally. If one does not want makedumpfile as default core_collector, then they @@ -98,6 +98,11 @@ vmcore.flat, you will need to use "makedumpfile -R" to rearrange the dump data from standard input to a normal dumpfile (readable with analysis tools). ie. "makedumpfile -R vmcore < vmcore.flat" +.PP +Note 3: If specified core_collector simply copy the vmcore file to the +dump target (eg: cp, scp), the vmcore could be significantly large. +Please make sure the dump target has enough space, at leaset larger +than the system's RAM. .RE @@ -307,11 +312,11 @@ Above will effectively be translated to: cp --sparse=always /proc/vmcore /vmcore .TP ex2. -core_collector "makedumpfile -l --message-level 1 -d 31" +core_collector "makedumpfile -l --message-level 7 -d 31" Above will effectively be translated to: -makedumpfile -l --message-level 1 -d 31 /proc/vmcore /vmcore +makedumpfile -l --message-level 7 -d 31 /proc/vmcore /vmcore .PP For dump targets like raw and ssh, in general, core collector should expect one argument (source file) and should output the processed core on standard @@ -328,11 +333,11 @@ Above will effectively be translated to. cat /proc/vmcore | dd of= .TP ex4. -core_collector "makedumpfile -F -l --message-level 1 -d 31" +core_collector "makedumpfile -F -l --message-level 7 -d 31" Above will effectively be translated to. -makedumpfile -F -l --message-level 1 -d 31 | dd of= +makedumpfile -F -l --message-level 7 -d 31 | dd of= .PP ssh dumps examples .TP @@ -344,11 +349,11 @@ Above will effectively be translated to. cat /proc/vmcore | ssh "dd of=path/vmcore" .TP ex6. -core_collector "makedumpfile -F -l --message-level 1 -d 31" +core_collector "makedumpfile -F -l --message-level 7 -d 31" Above will effectively be translated to. -makedumpfile -F -l --message-level 1 -d 31 | ssh "dd of=path/vmcore" +makedumpfile -F -l --message-level 7 -d 31 | ssh "dd of=path/vmcore" There is one exception to standard output rule for ssh dumps. And that is scp. As scp can handle ssh destinations for file transfers, one can diff --git a/kdump.service b/kdump.service index f888dd6..99feed8 100644 --- a/kdump.service +++ b/kdump.service @@ -2,6 +2,7 @@ Description=Crash recovery kernel arming After=network.target network-online.target remote-fs.target basic.target DefaultDependencies=no +ConditionKernelCommandLine=crashkernel [Service] Type=oneshot diff --git a/kdump.sysconfig b/kdump.sysconfig index 7c5641a..ae802d2 100644 --- a/kdump.sysconfig +++ b/kdump.sysconfig @@ -35,3 +35,19 @@ KEXEC_ARGS="" #What is the image type used for kdump KDUMP_IMG="vmlinuz" + +# Logging is controlled by following variables in the first kernel: +# - @var KDUMP_STDLOGLVL - logging level to standard error (console output) +# - @var KDUMP_SYSLOGLVL - logging level to syslog (by logger command) +# - @var KDUMP_KMSGLOGLVL - logging level to /dev/kmsg (only for boot-time) +# +# In the second kernel, kdump will use the rd.kdumploglvl option to set the +# log level in the above KDUMP_COMMANDLINE_APPEND. +# - @var rd.kdumploglvl - logging level to syslog (by logger command) +# - for example: add the rd.kdumploglvl=3 option to KDUMP_COMMANDLINE_APPEND +# +# Logging levels: no logging(0), error(1),warn(2),info(3),debug(4) +# +# KDUMP_STDLOGLVL=3 +# KDUMP_SYSLOGLVL=0 +# KDUMP_KMSGLOGLVL=0 diff --git a/kdump.sysconfig.aarch64 b/kdump.sysconfig.aarch64 index 6f55c03..6f7830a 100644 --- a/kdump.sysconfig.aarch64 +++ b/kdump.sysconfig.aarch64 @@ -35,3 +35,19 @@ KEXEC_ARGS="" #What is the image type used for kdump KDUMP_IMG="vmlinuz" + +# Logging is controlled by following variables in the first kernel: +# - @var KDUMP_STDLOGLVL - logging level to standard error (console output) +# - @var KDUMP_SYSLOGLVL - logging level to syslog (by logger command) +# - @var KDUMP_KMSGLOGLVL - logging level to /dev/kmsg (only for boot-time) +# +# In the second kernel, kdump will use the rd.kdumploglvl option to set the +# log level in the above KDUMP_COMMANDLINE_APPEND. +# - @var rd.kdumploglvl - logging level to syslog (by logger command) +# - for example: add the rd.kdumploglvl=3 option to KDUMP_COMMANDLINE_APPEND +# +# Logging levels: no logging(0), error(1),warn(2),info(3),debug(4) +# +# KDUMP_STDLOGLVL=3 +# KDUMP_SYSLOGLVL=0 +# KDUMP_KMSGLOGLVL=0 diff --git a/kdump.sysconfig.i386 b/kdump.sysconfig.i386 index 84f0df1..165d13a 100644 --- a/kdump.sysconfig.i386 +++ b/kdump.sysconfig.i386 @@ -38,3 +38,19 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT="" + +# Logging is controlled by following variables in the first kernel: +# - @var KDUMP_STDLOGLVL - logging level to standard error (console output) +# - @var KDUMP_SYSLOGLVL - logging level to syslog (by logger command) +# - @var KDUMP_KMSGLOGLVL - logging level to /dev/kmsg (only for boot-time) +# +# In the second kernel, kdump will use the rd.kdumploglvl option to set the +# log level in the above KDUMP_COMMANDLINE_APPEND. +# - @var rd.kdumploglvl - logging level to syslog (by logger command) +# - for example: add the rd.kdumploglvl=3 option to KDUMP_COMMANDLINE_APPEND +# +# Logging levels: no logging(0), error(1),warn(2),info(3),debug(4) +# +# KDUMP_STDLOGLVL=3 +# KDUMP_SYSLOGLVL=0 +# KDUMP_KMSGLOGLVL=0 diff --git a/kdump.sysconfig.ppc64 b/kdump.sysconfig.ppc64 index 7ce41e3..00b40ff 100644 --- a/kdump.sysconfig.ppc64 +++ b/kdump.sysconfig.ppc64 @@ -40,3 +40,19 @@ KDUMP_IMG="vmlinuz" KDUMP_IMG_EXT="" #Specify the action after failure + +# Logging is controlled by following variables in the first kernel: +# - @var KDUMP_STDLOGLVL - logging level to standard error (console output) +# - @var KDUMP_SYSLOGLVL - logging level to syslog (by logger command) +# - @var KDUMP_KMSGLOGLVL - logging level to /dev/kmsg (only for boot-time) +# +# In the second kernel, kdump will use the rd.kdumploglvl option to set the +# log level in the above KDUMP_COMMANDLINE_APPEND. +# - @var rd.kdumploglvl - logging level to syslog (by logger command) +# - for example: add the rd.kdumploglvl=3 option to KDUMP_COMMANDLINE_APPEND +# +# Logging levels: no logging(0), error(1),warn(2),info(3),debug(4) +# +# KDUMP_STDLOGLVL=3 +# KDUMP_SYSLOGLVL=0 +# KDUMP_KMSGLOGLVL=0 diff --git a/kdump.sysconfig.ppc64le b/kdump.sysconfig.ppc64le index 7ce41e3..00b40ff 100644 --- a/kdump.sysconfig.ppc64le +++ b/kdump.sysconfig.ppc64le @@ -40,3 +40,19 @@ KDUMP_IMG="vmlinuz" KDUMP_IMG_EXT="" #Specify the action after failure + +# Logging is controlled by following variables in the first kernel: +# - @var KDUMP_STDLOGLVL - logging level to standard error (console output) +# - @var KDUMP_SYSLOGLVL - logging level to syslog (by logger command) +# - @var KDUMP_KMSGLOGLVL - logging level to /dev/kmsg (only for boot-time) +# +# In the second kernel, kdump will use the rd.kdumploglvl option to set the +# log level in the above KDUMP_COMMANDLINE_APPEND. +# - @var rd.kdumploglvl - logging level to syslog (by logger command) +# - for example: add the rd.kdumploglvl=3 option to KDUMP_COMMANDLINE_APPEND +# +# Logging levels: no logging(0), error(1),warn(2),info(3),debug(4) +# +# KDUMP_STDLOGLVL=3 +# KDUMP_SYSLOGLVL=0 +# KDUMP_KMSGLOGLVL=0 diff --git a/kdump.sysconfig.s390x b/kdump.sysconfig.s390x index de0ac49..efa0394 100644 --- a/kdump.sysconfig.s390x +++ b/kdump.sysconfig.s390x @@ -17,7 +17,7 @@ KDUMP_COMMANDLINE="" # This variable lets us remove arguments from the current kdump commandline # as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline # NOTE: some arguments such as crashkernel will always be removed -KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet log_buf_len swiotlb" +KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet log_buf_len swiotlb prot_virt" # This variable lets us append arguments to the current kdump commandline # after processed by KDUMP_COMMANDLINE_REMOVE @@ -31,7 +31,7 @@ MKDUMPRD_ARGS="" # # Example: # KEXEC_ARGS="--elf32-core-headers" -KEXEC_ARGS="" +KEXEC_ARGS="-s" #Where to find the boot image #KDUMP_BOOTDIR="/boot" @@ -41,3 +41,19 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT="" + +# Logging is controlled by following variables in the first kernel: +# - @var KDUMP_STDLOGLVL - logging level to standard error (console output) +# - @var KDUMP_SYSLOGLVL - logging level to syslog (by logger command) +# - @var KDUMP_KMSGLOGLVL - logging level to /dev/kmsg (only for boot-time) +# +# In the second kernel, kdump will use the rd.kdumploglvl option to set the +# log level in the above KDUMP_COMMANDLINE_APPEND. +# - @var rd.kdumploglvl - logging level to syslog (by logger command) +# - for example: add the rd.kdumploglvl=3 option to KDUMP_COMMANDLINE_APPEND +# +# Logging levels: no logging(0), error(1),warn(2),info(3),debug(4) +# +# KDUMP_STDLOGLVL=3 +# KDUMP_SYSLOGLVL=0 +# KDUMP_KMSGLOGLVL=0 diff --git a/kdump.sysconfig.x86_64 b/kdump.sysconfig.x86_64 index 96ac7be..a3995d0 100644 --- a/kdump.sysconfig.x86_64 +++ b/kdump.sysconfig.x86_64 @@ -38,3 +38,19 @@ KDUMP_IMG="vmlinuz" #What is the images extension. Relocatable kernels don't have one KDUMP_IMG_EXT="" + +# Logging is controlled by following variables in the first kernel: +# - @var KDUMP_STDLOGLVL - logging level to standard error (console output) +# - @var KDUMP_SYSLOGLVL - logging level to syslog (by logger command) +# - @var KDUMP_KMSGLOGLVL - logging level to /dev/kmsg (only for boot-time) +# +# In the second kernel, kdump will use the rd.kdumploglvl option to set the +# log level in the above KDUMP_COMMANDLINE_APPEND. +# - @var rd.kdumploglvl - logging level to syslog (by logger command) +# - for example: add the rd.kdumploglvl=3 option to KDUMP_COMMANDLINE_APPEND +# +# Logging levels: no logging(0), error(1),warn(2),info(3),debug(4) +# +# KDUMP_STDLOGLVL=3 +# KDUMP_SYSLOGLVL=0 +# KDUMP_KMSGLOGLVL=0 diff --git a/kdumpctl b/kdumpctl index b4dbef0..e8a7a3a 100755 --- a/kdumpctl +++ b/kdumpctl @@ -2,9 +2,11 @@ KEXEC=/sbin/kexec KDUMP_KERNELVER="" +KDUMP_KERNEL="" KDUMP_COMMANDLINE="" KEXEC_ARGS="" KDUMP_CONFIG_FILE="/etc/kdump.conf" +KDUMP_LOG_PATH="/var/log" MKDUMPRD="/sbin/mkdumprd -f" DRACUT_MODULES_FILE="/usr/lib/dracut/modules.txt" SAVE_PATH=/var/crash @@ -13,17 +15,14 @@ INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum" DUMP_TARGET="" DEFAULT_INITRD="" DEFAULT_INITRD_BAK="" +KDUMP_INITRD="" TARGET_INITRD="" FADUMP_REGISTER_SYS_NODE="/sys/kernel/fadump_registered" #kdump shall be the default dump mode DEFAULT_DUMP_MODE="kdump" image_time=0 -[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut -. $dracutbasedir/dracut-functions.sh -. /lib/kdump/kdump-lib.sh - -standard_kexec_args="-p" +standard_kexec_args="-d -p" # Some default values in case /etc/sysconfig/kdump doesn't include KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug" @@ -32,13 +31,25 @@ if [ -f /etc/sysconfig/kdump ]; then . /etc/sysconfig/kdump fi +[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut +. $dracutbasedir/dracut-functions.sh +. /lib/kdump/kdump-lib.sh +. /lib/kdump/kdump-logger.sh + +#initiate the kdump logger +dlog_init +if [ $? -ne 0 ]; then + echo "failed to initiate the kdump logger." + exit 1 +fi + single_instance_lock() { local rc timeout=5 exec 9>/var/lock/kdump if [ $? -ne 0 ]; then - echo "Create file lock failed" + derror "Create file lock failed" exit 1 fi @@ -46,7 +57,7 @@ single_instance_lock() rc=$? while [ $rc -ne 0 ]; do - echo "Another app is currently holding the kdump lock; waiting for it to exit..." + dinfo "Another app is currently holding the kdump lock; waiting for it to exit..." flock -w $timeout 9 rc=$? done @@ -57,9 +68,10 @@ determine_dump_mode() # Check if firmware-assisted dump is enabled # if yes, set the dump mode as fadump if is_fadump_capable; then - echo "Dump mode is fadump" + dinfo "Dump mode is fadump" DEFAULT_DUMP_MODE="fadump" fi + ddebug "DEFAULT_DUMP_MODE=$DEFAULT_DUMP_MODE" } save_core() @@ -67,22 +79,25 @@ save_core() coredir="/var/crash/`date +"%Y-%m-%d-%H:%M"`" mkdir -p $coredir + ddebug "cp --sparse=always /proc/vmcore $coredir/vmcore-incomplete" cp --sparse=always /proc/vmcore $coredir/vmcore-incomplete if [ $? == 0 ]; then mv $coredir/vmcore-incomplete $coredir/vmcore - echo "saved a vmcore to $coredir" + dinfo "saved a vmcore to $coredir" else - echo "failed to save a vmcore to $coredir" >&2 + derror "failed to save a vmcore to $coredir" fi # pass the dmesg to Abrt tool if exists, in order # to collect the kernel oops message. # https://fedorahosted.org/abrt/ if [ -x /usr/bin/dumpoops ]; then + ddebug "makedumpfile --dump-dmesg $coredir/vmcore $coredir/dmesg" makedumpfile --dump-dmesg $coredir/vmcore $coredir/dmesg >/dev/null 2>&1 + ddebug "dumpoops -d $coredir/dmesg" dumpoops -d $coredir/dmesg >/dev/null 2>&1 if [ $? == 0 ]; then - echo "kernel oops has been collected by abrt tool" + dinfo "kernel oops has been collected by abrt tool" fi fi } @@ -94,16 +109,18 @@ rebuild_fadump_initrd() # this file tells the initrd is fadump enabled touch /tmp/fadump.initramfs target_initrd_tmp="$TARGET_INITRD.tmp" - $MKDUMPRD $target_initrd_tmp --rebuild $DEFAULT_INITRD_BAK --kver $kdump_kver \ + ddebug "rebuild fadump initrd: $target_initrd_tmp $DEFAULT_INITRD_BAK $KDUMP_KERNELVER" + $MKDUMPRD $target_initrd_tmp --rebuild $DEFAULT_INITRD_BAK --kver $KDUMP_KERNELVER \ -i /tmp/fadump.initramfs /etc/fadump.initramfs if [ $? != 0 ]; then - echo "mkdumprd: failed to rebuild initrd with fadump support" >&2 + derror "mkdumprd: failed to rebuild initrd with fadump support" rm -f /tmp/fadump.initramfs return 1 fi rm -f /tmp/fadump.initramfs # updating fadump initrd + ddebug "updating fadump initrd: $target_initrd_tmp $TARGET_INITRD" mv $target_initrd_tmp $TARGET_INITRD sync @@ -118,14 +135,15 @@ check_earlykdump_is_enabled() rebuild_kdump_initrd() { - $MKDUMPRD $TARGET_INITRD $kdump_kver + ddebug "rebuild kdump initrd: $MKDUMPRD $TARGET_INITRD $KDUMP_KERNELVER" + $MKDUMPRD $TARGET_INITRD $KDUMP_KERNELVER if [ $? != 0 ]; then - echo "mkdumprd: failed to make kdump initrd" >&2 + derror "mkdumprd: failed to make kdump initrd" return 1 fi if check_earlykdump_is_enabled; then - echo "Tips: If early kdump is enabled, also require rebuilding the system initramfs to make the changes take effect for early kdump." + dwarn "Tips: If early kdump is enabled, also require rebuilding the system initramfs to make the changes take effect for early kdump." fi return 0 @@ -133,8 +151,8 @@ rebuild_kdump_initrd() rebuild_initrd() { - if [[ ! -w "$KDUMP_BOOTDIR" ]];then - echo "$KDUMP_BOOTDIR does not have write permission. Can not rebuild $TARGET_INITRD" + if [[ ! -w $(dirname $TARGET_INITRD) ]];then + derror "$(dirname $TARGET_INITRD) does not have write permission. Cannot rebuild $TARGET_INITRD" return 1 fi @@ -152,7 +170,7 @@ check_exist() { for file in $1; do if [ ! -e "$file" ]; then - echo -n "Error: $file not found."; echo + derror "Error: $file not found." return 1 fi done @@ -163,7 +181,7 @@ check_executable() { for file in $1; do if [ ! -x "$file" ]; then - echo -n "Error: $file is not executable."; echo + derror "Error: $file is not executable." return 1 fi done @@ -171,17 +189,19 @@ check_executable() backup_default_initrd() { + ddebug "backup default initrd: $DEFAULT_INITRD" + if [ ! -f "$DEFAULT_INITRD" ]; then return fi if [ ! -e $DEFAULT_INITRD_BAK ]; then - echo "Backing up $DEFAULT_INITRD before rebuild." + dinfo "Backing up $DEFAULT_INITRD before rebuild." # save checksum to verify before restoring sha1sum $DEFAULT_INITRD > $INITRD_CHECKSUM_LOCATION cp $DEFAULT_INITRD $DEFAULT_INITRD_BAK if [ $? -ne 0 ]; then - echo "WARNING: failed to backup $DEFAULT_INITRD." + dwarn "WARNING: failed to backup $DEFAULT_INITRD." rm -f $DEFAULT_INITRD_BAK fi fi @@ -189,6 +209,12 @@ backup_default_initrd() restore_default_initrd() { + ddebug "restore default initrd: $DEFAULT_INITRD" + + if [ ! -f "$DEFAULT_INITRD" ]; then + return + fi + # If a backup initrd exists, we must be switching back from # fadump to kdump. Restore the original default initrd. if [ -f $DEFAULT_INITRD_BAK ] && [ -f $INITRD_CHECKSUM_LOCATION ]; then @@ -196,13 +222,12 @@ restore_default_initrd() backup_checksum=`sha1sum $DEFAULT_INITRD_BAK | awk '{ print $1 }'` default_checksum=`cat $INITRD_CHECKSUM_LOCATION | awk '{ print $1 }'` if [ "$default_checksum" != "$backup_checksum" ]; then - echo "WARNING: checksum mismatch! Can't restore original initrd.." + dwarn "WARNING: checksum mismatch! Can't restore original initrd.." else rm -f $INITRD_CHECKSUM_LOCATION mv $DEFAULT_INITRD_BAK $DEFAULT_INITRD if [[ $? -eq 0 ]]; then - echo -n "Restoring original initrd as fadump mode " - echo "is disabled." + derror "Restoring original initrd as fadump mode is disabled." sync fi fi @@ -211,55 +236,61 @@ restore_default_initrd() check_config() { - local nr - - nr=$(awk 'BEGIN{cnt=0} /^raw|^ssh[[:blank:]]|^nfs|^ext[234]|^xfs|^btrfs|^minix|^dracut_args .*\-\-mount/{cnt++} END{print cnt}' $KDUMP_CONFIG_FILE) - [ $nr -gt 1 ] && { - echo "More than one dump targets specified." - return 1 - } - - nr=$(grep "^dracut_args .*\-\-mount" $KDUMP_CONFIG_FILE | grep -o "\-\-mount" | wc -l) - [ $nr -gt 1 ] && { - echo "Multiple mount targets specified in one \"dracut_args\"." - return 1 - } - - # Check if we have any leading spaces (or tabs) before the - # variable name in the kdump conf file - if grep -E -q '^[[:blank:]]+[a-z]' $KDUMP_CONFIG_FILE; then - echo "No whitespaces are allowed before a kdump option name in $KDUMP_CONFIG_FILE" - return 1 - fi - - while read config_opt config_val; do + local -A _opt_rec + while read -r config_opt config_val; do case "$config_opt" in - \#* | "") + dracut_args) + if [[ $config_val == *--mount* ]]; then + if [ $(echo $config_val | grep -o "\-\-mount" | wc -l) -ne 1 ]; then + derror "Multiple mount targets specified in one \"dracut_args\"." + return 1 + fi + config_opt=_target + fi ;; - raw|ext2|ext3|ext4|minix|btrfs|xfs|nfs|ssh|sshkey|path|core_collector|kdump_post|kdump_pre|extra_bins|extra_modules|failure_action|default|final_action|force_rebuild|force_no_rebuild|dracut_args|fence_kdump_args|fence_kdump_nodes) - # remove inline comments after the end of a directive. - [ -z "$config_val" ] && { - echo "Invalid kdump config value for option $config_opt." - return 1; - } - if [ -d "/proc/device-tree/ibm,opal/dump" ] && [ "$config_opt" == "raw" ]; then - echo "WARNING: Won't capture opalcore when 'raw' dump target is used." + raw) + if [ -d "/proc/device-tree/ibm,opal/dump" ]; then + derror "WARNING: Won't capture opalcore when 'raw' dump target is used." + return 1 fi + config_opt=_target + ;; + ext[234]|minix|btrfs|xfs|nfs|ssh) + config_opt=_target + ;; + sshkey|path|core_collector|kdump_post|kdump_pre|extra_bins|extra_modules|failure_action|default|final_action|force_rebuild|force_no_rebuild|fence_kdump_args|fence_kdump_nodes) ;; net|options|link_delay|disk_timeout|debug_mem_level|blacklist) - echo "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives." + derror "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives." return 1 ;; + '') + continue + ;; *) - echo "Invalid kdump config option $config_opt" - return 1; + derror "Invalid kdump config option $config_opt" + return 1 ;; esac + + if [[ -z "$config_val" ]]; then + derror "Invalid kdump config value for option '$config_opt'" + return 1 + fi + + if [ -n "${_opt_rec[$config_opt]}" ]; then + if [ $config_opt == _target ]; then + derror "More than one dump targets specified" + else + derror "Duplicated kdump config value of option $config_opt" + fi + return 1 + fi + _opt_rec[$config_opt]="$config_val" done <<< "$(read_strip_comments $KDUMP_CONFIG_FILE)" check_failure_action_config || return 1 check_final_action_config || return 1 - check_fence_kdump_config || return 1 return 0 @@ -294,22 +325,17 @@ get_pcs_cluster_modified_files() setup_initrd() { - KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}") - - if [ -z "$KDUMP_KERNELVER" ]; then - kdump_kver=`uname -r` - else - kdump_kver=$KDUMP_KERNELVER + prepare_kdump_bootinfo + if [ $? -ne 0 ]; then + derror "failed to prepare for kdump bootinfo." + return 1 fi - kdump_kernel="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}" - - DEFAULT_INITRD="${KDUMP_BOOTDIR}/initramfs-`uname -r`.img" - DEFAULT_INITRD_BAK="${KDUMP_BOOTDIR}/.initramfs-`uname -r`.img.default" + DEFAULT_INITRD_BAK="$KDUMP_BOOTDIR/.$(basename $DEFAULT_INITRD).default" if [ $DEFAULT_DUMP_MODE == "fadump" ]; then TARGET_INITRD="$DEFAULT_INITRD" if [ ! -s "$TARGET_INITRD" ]; then - echo "Error: No initrd found to rebuild!" + derror "Error: No initrd found to rebuild!" return 1 fi @@ -317,7 +343,7 @@ setup_initrd() # with fadump aware initrd backup_default_initrd else - TARGET_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img" + TARGET_INITRD="$KDUMP_INITRD" # check if a backup of default initrd exists. If yes, # it signifies a switch from fadump mode. So, restore @@ -357,26 +383,26 @@ check_files_modified() EXTRA_BINS="$EXTRA_BINS $CHECK_FILES" CHECK_FILES=`grep ^extra_bins $KDUMP_CONFIG_FILE | cut -d\ -f2-` EXTRA_BINS="$EXTRA_BINS $CHECK_FILES" - files="$KDUMP_CONFIG_FILE $kdump_kernel $EXTRA_BINS $CORE_COLLECTOR" + files="$KDUMP_CONFIG_FILE $KDUMP_KERNEL $EXTRA_BINS $CORE_COLLECTOR" [[ -e /etc/fstab ]] && files="$files /etc/fstab" # Check for any updated extra module EXTRA_MODULES="$(grep ^extra_modules $KDUMP_CONFIG_FILE | sed 's/^extra_modules\s*//')" if [ -n "$EXTRA_MODULES" ]; then - if [ -e /lib/modules/$kdump_kver/modules.dep ]; then - files="$files /lib/modules/$kdump_kver/modules.dep" + if [ -e /lib/modules/$KDUMP_KERNELVER/modules.dep ]; then + files="$files /lib/modules/$KDUMP_KERNELVER/modules.dep" fi for _module in $EXTRA_MODULES; do - _module_file="$(modinfo --set-version "$kdump_kver" --filename "$_module" 2>/dev/null)" + _module_file="$(modinfo --set-version "$KDUMP_KERNELVER" --filename "$_module" 2>/dev/null)" if [[ $? -eq 0 ]]; then files="$files $_module_file" for _dep_modules in $(modinfo -F depends $_module | tr ',' ' '); do - files="$files $(modinfo --set-version "$kdump_kver" --filename $_dep_modules 2>/dev/null)" + files="$files $(modinfo --set-version "$KDUMP_KERNELVER" --filename $_dep_modules 2>/dev/null)" done else # If it's not a module nor builtin, give an error - if ! ( modprobe --set-version "$kdump_kver" --dry-run "$_module" &>/dev/null ); then - echo "Module $_module not found" + if ! ( modprobe --set-version "$KDUMP_KERNELVER" --dry-run "$_module" &>/dev/null ); then + dwarn "Module $_module not found" fi fi done @@ -401,27 +427,66 @@ check_files_modified() fi fi else - echo "$file doesn't exist" + dwarn "$file doesn't exist" fi done if [ -n "$modified_files" ]; then - echo "Detected change(s) in the following file(s):" - echo -n " "; echo "$modified_files" | sed 's/\s/\n /g' + dinfo "Detected change(s) in the following file(s): $modified_files" return 1 fi return 0 } -check_dump_fs_modified() +check_drivers_modified() +{ + local _target _new_drivers _old_drivers _module_name _module_filename + + # If it's dump target is on block device, detect the block driver + _target=$(get_block_dump_target) + if [[ -n "$_target" ]]; then + _record_block_drivers() { + local _drivers + _drivers=$(udevadm info -a "/dev/block/$1" | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p') + for _driver in $_drivers; do + if ! [[ " $_new_drivers " == *" $_driver "* ]]; then + _new_drivers="$_new_drivers $_driver" + fi + done + + ddebug "MAJ:MIN=$1 drivers='$_drivers'" + } + check_block_and_slaves_all _record_block_drivers "$(get_maj_min "$_target")" + fi + + # Include watchdog drivers if watchdog module is not omitted + is_dracut_mod_omitted watchdog || is_dracut_mod_omitted watchdog-modules || _new_drivers+=" $(get_watchdog_drvs)" + + [ -z "$_new_drivers" ] && return 0 + _old_drivers="$(lsinitrd $TARGET_INITRD -f /usr/lib/dracut/loaded-kernel-modules.txt | tr '\n' ' ')" + + ddebug "Modules required for kdump: '$_new_drivers'" + ddebug "Modules included in old initramfs: '$_old_drivers'" + for _driver in $_new_drivers; do + # Skip deprecated/invalid driver name or built-in module + _module_name=$(modinfo --set-version "$KDUMP_KERNELVER" -F name $_driver 2>/dev/null) + _module_filename=$(modinfo --set-version "$KDUMP_KERNELVER" -n $_driver 2>/dev/null) + if [ $? -ne 0 ] || [ -z "$_module_name" ] || [[ "$_module_filename" = *"(builtin)"* ]]; then + continue + fi + if ! [[ " $_old_drivers " == *" $_module_name "* ]]; then + dinfo "Detected change in block device driver, new loaded module: $_module_name" + return 1 + fi + done +} + +check_fs_modified() { local _old_dev _old_mntpoint _old_fstype local _new_dev _new_mntpoint _new_fstype - local _target _path _dracut_args - local _target_drivers _module_name - - local _old_drivers="$(lsinitrd $TARGET_INITRD -f /usr/lib/dracut/loaded-kernel-modules.txt | tr '\n' ' ')" + local _target _dracut_args # No need to check in case of mount target specified via "dracut_args". if is_mount_in_dracut_args; then @@ -434,66 +499,24 @@ check_dump_fs_modified() return 0 fi - _target=$(get_user_configured_dump_disk) - - if [[ -n "$_target" ]]; then - _target=$(to_dev_name $_target) - _new_fstype=$(blkid $_target | awk -F"TYPE=" '{print $2}' | cut -d '"' -f 2) - else - _path=$(get_save_path) - _target=$(get_target_from_path $_path) - _target=$(to_dev_name $_target) - _new_fstype=$(get_fs_type_from_target $_target) - if [[ -z "$_target" || -z "$_new_fstype" ]];then - echo "Dump path $_path does not exist" - return 2 - fi + _target=$(get_block_dump_target) + _new_fstype=$(get_fs_type_from_target $_target) + if [[ -z "$_target" ]] || [[ -z "$_new_fstype" ]];then + derror "Dump target is invalid" + return 2 fi - _record_block_drivers() { - local _drivers - if [[ -b /dev/block/$1 ]]; then - _drivers=$(udevadm info -a "/dev/block/$1" | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p') - fi - if [[ -b $1 ]]; then - _drivers=$(udevadm info -a "$1" | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p') - fi - for _driver in $_drivers; do - if ! [[ " $_target_drivers " == *" $_driver "* ]]; then - _target_drivers="$_target_drivers $_driver" - fi - done - return 1 - } - - check_block_and_slaves_all _record_block_drivers "$(get_maj_min "$_target")" - for _driver in $_target_drivers; do - # Target is mounted already, if module is not included by current kernel, - # could be a deprecated/invalid driver name or a built-in module - _module_name=$(modinfo --set-version "$kdump_kver" -F name $_driver 2>/dev/null) - if [ $? -ne 0 ] || [ -z "$_module_name" ]; then - continue - fi - if ! [[ " $_old_drivers " == *" $_module_name "* ]]; then - echo "Detected change in block device driver, new loaded module: $_module_name" - return 1 - fi - done - - if [[ $(expr substr $_new_fstype 1 3) = "nfs" ]];then - _new_dev=$_target - else - _new_dev=$(kdump_get_persistent_dev $_target) - if [ -z "$_new_dev" ]; then - echo "Get persistent device name failed" - return 2 - fi + ddebug "_target=$_target _new_fstype=$_new_fstype" + _new_dev=$(kdump_get_persistent_dev $_target) + if [ -z "$_new_dev" ]; then + perror "Get persistent device name failed" + return 2 fi _new_mntpoint="$(get_kdump_mntpoint_from_target $_target)" _dracut_args=$(lsinitrd $TARGET_INITRD -f usr/lib/dracut/build-parameter.txt) if [[ -z "$_dracut_args" ]];then - echo "Warning: No dracut arguments found in initrd" + dwarn "Warning: No dracut arguments found in initrd" return 0 fi @@ -511,63 +534,7 @@ check_dump_fs_modified() [[ "$_target" = "$(get_root_fs_device)" ]] && return 0 fi - echo "Detected change in File System" - return 1 -} - -check_wdt_modified() -{ - local -A _drivers - local _alldrivers _active _wdtdrv _wdtppath _dir - local wd_old wd_new - - is_wdt_mod_omitted - [[ $? -eq 0 ]] && return 0 - [[ -d /sys/class/watchdog/ ]] || return 0 - - # Copied logic from dracut 04watchdog/module-setup.sh::installkernel() - for _dir in /sys/class/watchdog/*; do - [[ -d "$_dir" ]] || continue - [[ -f "$_dir/state" ]] || continue - _active=$(< "$_dir/state") - [[ "$_active" = "active" ]] || continue - # device/modalias will return driver of this device - _wdtdrv=$(< "$_dir/device/modalias") - # There can be more than one module represented by same - # modalias. Currently load all of them. - # TODO: Need to find a way to avoid any unwanted module - # represented by modalias - _wdtdrv=$(modprobe --set-version "$kdump_kver" -R $_wdtdrv 2>/dev/null) - if [[ $_wdtdrv ]]; then - for i in $_wdtdrv; do - _drivers[$i]=1 - done - fi - # however in some cases, we also need to check that if there is - # a specific driver for the parent bus/device. In such cases - # we also need to enable driver for parent bus/device. - _wdtppath=$(readlink -f "$_dir/device") - while [[ -d "$_wdtppath" ]] && [[ "$_wdtppath" != "/sys" ]]; do - _wdtppath=$(readlink -f "$_wdtppath/..") - [[ -f "$_wdtppath/modalias" ]] || continue - - _wdtdrv=$(< "$_wdtppath/modalias") - _wdtdrv=$(modprobe --set-version "$kdump_kver" -R $_wdtdrv 2>/dev/null) - if [[ $_wdtdrv ]]; then - for i in $_wdtdrv; do - _drivers[$i]=1 - done - fi - done - done - - # ensure that watchdog module is loaded as early as possible - _alldrivers="${!_drivers[*]}" - [[ $_alldrivers ]] && wd_new="rd.driver.pre=${_alldrivers// /,}" - wd_old=$(lsinitrd $TARGET_INITRD -f etc/cmdline.d/00-watchdog.conf) - - [[ "$wd_old" = "$wd_new" ]] && return 0 - + dinfo "Detected change in File System" return 1 } @@ -586,16 +553,16 @@ check_system_modified() return $ret fi - check_dump_fs_modified + check_fs_modified ret=$? if [ $ret -ne 0 ]; then return $ret fi - check_wdt_modified - if [ $? -ne 0 ]; then - echo "Detected change in watchdog state" - return 1 + check_drivers_modified + ret=$? + if [ $ret -ne 0 ]; then + return $ret fi return 0 @@ -618,7 +585,7 @@ check_rebuild() if [ $? -eq 0 ]; then force_no_rebuild=`echo $_force_no_rebuild | cut -d' ' -f2` if [ "$force_no_rebuild" != "0" ] && [ "$force_no_rebuild" != "1" ];then - echo "Error: force_no_rebuild value is invalid" + derror "Error: force_no_rebuild value is invalid" return 1 fi fi @@ -627,13 +594,13 @@ check_rebuild() if [ $? -eq 0 ]; then force_rebuild=`echo $_force_rebuild | cut -d' ' -f2` if [ "$force_rebuild" != "0" ] && [ "$force_rebuild" != "1" ];then - echo "Error: force_rebuild value is invalid" + derror "Error: force_rebuild value is invalid" return 1 fi fi if [[ "$force_no_rebuild" == "1" && "$force_rebuild" == "1" ]]; then - echo "Error: force_rebuild and force_no_rebuild are enabled simultaneously in kdump.conf" + derror "Error: force_rebuild and force_no_rebuild are enabled simultaneously in kdump.conf" return 1 fi @@ -663,27 +630,58 @@ check_rebuild() fi if [ $image_time -eq 0 ]; then - echo -n "No kdump initial ramdisk found."; echo + dinfo "No kdump initial ramdisk found." elif [ "$capture_capable_initrd" == "0" ]; then - echo -n "Rebuild $TARGET_INITRD with dump capture support"; echo + dinfo "Rebuild $TARGET_INITRD with dump capture support" elif [ "$force_rebuild" != "0" ]; then - echo -n "Force rebuild $TARGET_INITRD"; echo + dinfo "Force rebuild $TARGET_INITRD" elif [ "$system_modified" != "0" ]; then : else return 0 fi - echo "Rebuilding $TARGET_INITRD" + dinfo "Rebuilding $TARGET_INITRD" rebuild_initrd return $? } +# On ppc64le LPARs, the keys trusted by firmware do not end up in +# .builtin_trusted_keys. So instead, add the key to the .ima keyring +function load_kdump_kernel_key() +{ + # this is only called inside is_secure_boot_enforced, + # no need to retest + + # this is only required if DT /ibm,secure-boot is a file. + # if it is a dir, we are on OpenPower and don't need this. + if ! [ -f /proc/device-tree/ibm,secure-boot ]; then + return + fi + + KDUMP_KEY_ID=$(cat /usr/share/doc/kernel-keys/$KDUMP_KERNELVER/kernel-signing-ppc.cer | + keyctl padd asymmetric kernelkey-$RANDOM %:.ima) +} + +# remove a previously loaded key. There's no real security implication +# to leaving it around, we choose to do this because it makes it easier +# to be idempotent and so as to reduce the potential for confusion. +function remove_kdump_kernel_key() +{ + if [ -z "$KDUMP_KEY_ID" ]; then + return + fi + + keyctl unlink $KDUMP_KEY_ID %:.ima +} + # 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. load_kdump() { + local ret + KEXEC_ARGS=$(prepare_kexec_args "${KEXEC_ARGS}") KDUMP_COMMANDLINE=$(prepare_cmdline "${KDUMP_COMMANDLINE}" "${KDUMP_COMMANDLINE_REMOVE}" "${KDUMP_COMMANDLINE_APPEND}") @@ -691,18 +689,37 @@ load_kdump() # Old syscall will always fail as it does not have capability to # to kernel signature verification. if is_secure_boot_enforced; then - echo "Secure Boot is enabled. Using kexec file based syscall." + dinfo "Secure Boot is enabled. Using kexec file based syscall." KEXEC_ARGS="$KEXEC_ARGS -s" + load_kdump_kernel_key fi + ddebug "$KEXEC $KEXEC_ARGS $standard_kexec_args --command-line=$KDUMP_COMMANDLINE --initrd=$TARGET_INITRD $KDUMP_KERNEL" + + # The '12' represents an intermediate temporary file descriptor + # to store the standard error file descriptor '2', and later + # restore the error file descriptor with the file descriptor '12' + # and release it. + exec 12>&2 + exec 2>> $KDUMP_LOG_PATH/kdump.log + PS4='+ $(date "+%Y-%m-%d %H:%M:%S") ${BASH_SOURCE}@${LINENO}: ' + set -x + $KEXEC $KEXEC_ARGS $standard_kexec_args \ --command-line="$KDUMP_COMMANDLINE" \ - --initrd=$TARGET_INITRD $kdump_kernel - if [ $? == 0 ]; then - echo "kexec: loaded kdump kernel" + --initrd=$TARGET_INITRD $KDUMP_KERNEL + + ret=$? + set +x + exec 2>&12 12>&- + + remove_kdump_kernel_key + + if [ $ret == 0 ]; then + dinfo "kexec: loaded kdump kernel" return 0 else - echo "kexec: failed to load kdump kernel" >&2 + derror "kexec: failed to load kdump kernel" return 1 fi } @@ -717,7 +734,7 @@ check_ssh_config() # canonicalize the path SSH_KEY_LOCATION=$(/usr/bin/readlink -m $config_val) else - echo "WARNING: '$config_val' doesn't exist, using default value '$SSH_KEY_LOCATION'" + dwarn "WARNING: '$config_val' doesn't exist, using default value '$SSH_KEY_LOCATION'" fi ;; path) @@ -759,22 +776,22 @@ check_and_wait_network_ready() if [ $retval -eq 0 ]; then return 0 elif [ $retval -ne 255 ]; then - echo "Could not create $DUMP_TARGET:$SAVE_PATH, you should check the privilege on server side" >&2 + derror "Could not create $DUMP_TARGET:$SAVE_PATH, you should check the privilege on server side" return 1 fi # if server removes the authorized_keys or, no /root/.ssh/kdump_id_rsa - echo $errmsg | grep -q "Permission denied\|No such file or directory\|Host key verification failed" + ddebug "$errmsg" + echo $errmsg | grep -q "Permission denied\|No such file or directory\|Host key verification failed" &> /dev/null if [ $? -eq 0 ]; then - echo "Could not create $DUMP_TARGET:$SAVE_PATH, you probably need to run \"kdumpctl propagate\"" >&2 + derror "Could not create $DUMP_TARGET:$SAVE_PATH, you probably need to run \"kdumpctl propagate\"" return 1 fi if [ $warn_once -eq 1 ]; then - echo "Network dump target is not usable, waiting for it to be ready" + dwarn "Network dump target is not usable, waiting for it to be ready..." warn_once=0 fi - echo -n . cur=$(date +%s) let "diff = $cur - $start_time" @@ -785,7 +802,7 @@ check_and_wait_network_ready() sleep 1 done - echo "Could not create $DUMP_TARGET:$SAVE_PATH, ipaddr is not ready yet. You should check network connection" >&2 + dinfo "Could not create $DUMP_TARGET:$SAVE_PATH, ipaddr is not ready yet. You should check network connection" return 1 } @@ -802,7 +819,7 @@ propagate_ssh_key() { check_ssh_config if [ $? -ne 0 ]; then - echo "No ssh config specified in $KDUMP_CONFIG_FILE. Can't propagate" >&2 + derror "No ssh config specified in $KDUMP_CONFIG_FILE. Can't propagate" exit 1 fi @@ -811,11 +828,11 @@ propagate_ssh_key() #Check to see if we already created key, if not, create it. if [ -f $KEYFILE ]; then - echo "Using existing keys..." + dinfo "Using existing keys..." else - echo -n "Generating new ssh keys... " + dinfo "Generating new ssh keys... " /usr/bin/ssh-keygen -t rsa -f $KEYFILE -N "" 2>&1 > /dev/null - echo "done." + dinfo "done." fi #now find the target ssh user and server to contact. @@ -826,10 +843,10 @@ propagate_ssh_key() ssh-copy-id -i $KEYFILE $SSH_USER@$SSH_SERVER RET=$? if [ $RET == 0 ]; then - echo $KEYFILE has been added to ~$SSH_USER/.ssh/authorized_keys on $SSH_SERVER + dinfo "$KEYFILE has been added to ~$SSH_USER/.ssh/authorized_keys on $SSH_SERVER" return 0 else - echo $errmsg, $KEYFILE failed in transfer to $SSH_SERVER >&2 + derror "$errmsg, $KEYFILE failed in transfer to $SSH_SERVER" exit 1 fi } @@ -839,7 +856,7 @@ show_reserved_mem() local mem=$(cat /sys/kernel/kexec_crash_size) local mem_mb=$(expr $mem / 1024 / 1024) - echo "Reserved "$mem_mb"MB memory for crash kernel" + dinfo "Reserved "$mem_mb"MB memory for crash kernel" } check_current_fadump_status() @@ -869,7 +886,7 @@ save_raw() raw_target=$(awk '$1 ~ /^raw$/ { print $2; }' $KDUMP_CONFIG_FILE) [ -z "$raw_target" ] && return 0 [ -b "$raw_target" ] || { - echo "raw partition $raw_target not found" + derror "raw partition $raw_target not found" return 1 } kdump_dir=`grep ^path $KDUMP_CONFIG_FILE | cut -d' ' -f2-` @@ -881,12 +898,12 @@ save_raw() mkdir -p "$coredir" [ -d "$coredir" ] || { - echo "failed to create $coredir" + derror "failed to create $coredir" return 1 } if makedumpfile -R $coredir/vmcore <$raw_target >/dev/null 2>&1; then # dump found - echo "Dump saved to $coredir/vmcore" + dinfo "Dump saved to $coredir/vmcore" # wipe makedumpfile header dd if=/dev/zero of=$raw_target bs=1b count=1 2>/dev/null else @@ -959,13 +976,13 @@ check_fence_kdump_config() for node in $nodes; do if [ "$node" = "$hostname" ]; then - echo "Option fence_kdump_nodes cannot contain $hostname" + derror "Option fence_kdump_nodes cannot contain $hostname" return 1 fi # node can be ipaddr - echo $ipaddrs | grep $node > /dev/null + echo "$ipaddrs " | grep "$node " > /dev/null if [ $? -eq 0 ]; then - echo "Option fence_kdump_nodes cannot contain $node" + derror "Option fence_kdump_nodes cannot contain $node" return 1 fi done @@ -987,11 +1004,11 @@ start_fadump() { echo 1 > $FADUMP_REGISTER_SYS_NODE if ! check_current_fadump_status; then - echo "fadump: failed to register" + derror "fadump: failed to register" return 1 fi - echo "fadump: registered successfully" + dinfo "fadump: registered successfully" return 0 } @@ -1018,7 +1035,7 @@ check_failure_action_config() if [ -z "$failure_action" -a -z "$default_option" ]; then return 0 elif [ -n "$failure_action" -a -n "$default_option" ]; then - echo "Cannot specify 'failure_action' and 'default' option together" + derror "Cannot specify 'failure_action' and 'default' option together" return 1 fi @@ -1032,7 +1049,7 @@ check_failure_action_config() return 0 ;; *) - echo $"Usage kdump.conf: $option {reboot|halt|poweroff|shell|dump_to_rootfs}" + dinfo $"Usage kdump.conf: $option {reboot|halt|poweroff|shell|dump_to_rootfs}" return 1 esac } @@ -1050,7 +1067,7 @@ check_final_action_config() return 0 ;; *) - echo $"Usage kdump.conf: final_action {reboot|halt|poweroff}" + dinfo $"Usage kdump.conf: final_action {reboot|halt|poweroff}" return 1 esac fi @@ -1060,13 +1077,13 @@ start() { check_dump_feasibility if [ $? -ne 0 ]; then - echo "Starting kdump: [FAILED]" + derror "Starting kdump: [FAILED]" return 1 fi check_config if [ $? -ne 0 ]; then - echo "Starting kdump: [FAILED]" + derror "Starting kdump: [FAILED]" return 1 fi @@ -1076,43 +1093,43 @@ start() save_raw if [ $? -ne 0 ]; then - echo "Starting kdump: [FAILED]" + derror "Starting kdump: [FAILED]" return 1 fi check_current_status if [ $? == 0 ]; then - echo "Kdump already running: [WARNING]" + dwarn "Kdump already running: [WARNING]" return 0 fi if check_ssh_config; then if ! check_ssh_target; then - echo "Starting kdump: [FAILED]" + derror "Starting kdump: [FAILED]" return 1 fi fi check_rebuild if [ $? != 0 ]; then - echo "Starting kdump: [FAILED]" + derror "Starting kdump: [FAILED]" return 1 fi start_dump if [ $? != 0 ]; then - echo "Starting kdump: [FAILED]" + derror "Starting kdump: [FAILED]" return 1 fi - echo "Starting kdump: [OK]" + dinfo "Starting kdump: [OK]" } reload() { check_current_status if [ $? -ne 0 ]; then - echo "Kdump was not running: [WARNING]" + dwarn "Kdump was not running: [WARNING]" fi if [ $DEFAULT_DUMP_MODE == "fadump" ]; then @@ -1123,36 +1140,36 @@ reload() fi if [ $? -ne 0 ]; then - echo "Stopping kdump: [FAILED]" + derror "Stopping kdump: [FAILED]" return 1 fi - echo "Stopping kdump: [OK]" + dinfo "Stopping kdump: [OK]" setup_initrd if [ $? -ne 0 ]; then - echo "Starting kdump: [FAILED]" + derror "Starting kdump: [FAILED]" return 1 fi start_dump if [ $? -ne 0 ]; then - echo "Starting kdump: [FAILED]" + derror "Starting kdump: [FAILED]" return 1 fi - echo "Starting kdump: [OK]" + dinfo "Starting kdump: [OK]" } stop_fadump() { echo 0 > $FADUMP_REGISTER_SYS_NODE if check_current_fadump_status; then - echo "fadump: failed to unregister" + derror "fadump: failed to unregister" return 1 fi - echo "fadump: unregistered successfully" + dinfo "fadump: unregistered successfully" return 0 } @@ -1165,11 +1182,11 @@ stop_kdump() fi if [ $? != 0 ]; then - echo "kexec: failed to unload kdump kernel" + derror "kexec: failed to unload kdump kernel" return 1 fi - echo "kexec: unloaded kdump kernel" + dinfo "kexec: unloaded kdump kernel" return 0 } @@ -1177,7 +1194,7 @@ reload_fadump() { echo 1 > $FADUMP_REGISTER_SYS_NODE if [ $? == 0 ]; then - echo "fadump: re-registered successfully" + dinfo "fadump: re-registered successfully" return 0 else # FADump could fail on older kernel where re-register @@ -1202,11 +1219,11 @@ stop() fi if [ $? != 0 ]; then - echo "Stopping kdump: [FAILED]" + derror "Stopping kdump: [FAILED]" return 1 fi - echo "Stopping kdump: [OK]" + dinfo "Stopping kdump: [OK]" return 0 } @@ -1227,13 +1244,104 @@ rebuild() { return 1 fi - echo "Rebuilding $TARGET_INITRD" + dinfo "Rebuilding $TARGET_INITRD" rebuild_initrd return $? } +do_estimate() { + local kdump_mods + local -A large_mods + local baseline + local kernel_size mod_size initrd_size baseline_size runtime_size reserved_size estimated_size recommended_size + local size_mb=$(( 1024 * 1024 )) + + setup_initrd + if [ ! -f "$TARGET_INITRD" ]; then + derror "kdumpctl estimate: kdump initramfs is not built yet." + exit 1 + fi + + kdump_mods="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/loaded-kernel-modules.txt | tr '\n' ' ')" + baseline=$(kdump_get_arch_recommend_size) + if [[ "${baseline: -1}" == "M" ]]; then + baseline=${baseline%M} + elif [[ "${baseline: -1}" == "G" ]]; then + baseline=$(( ${baseline%G} * 1024 )) + elif [[ "${baseline: -1}" == "T" ]]; then + baseline=$(( ${baseline%Y} * 1048576 )) + fi + + # The default value when using crashkernel=auto + baseline_size=$((baseline * size_mb)) + # Current reserved crashkernel size + reserved_size=$(cat /sys/kernel/kexec_crash_size) + # A pre-estimated value for userspace usage and kernel + # runtime allocation, 64M should good for most cases + runtime_size=$((64 * size_mb)) + # Kernel image size + kernel_size=$(get_kernel_size "$KDUMP_KERNEL") + # Kdump initramfs size + initrd_size=$(du -b "$TARGET_INITRD" | awk '{print $1}') + # Kernel modules static size after loaded + mod_size=0 + while read -r _name _size _; do + if [[ ! " $kdump_mods " == *" $_name "* ]]; then + continue + fi + mod_size=$((mod_size + _size)) + + # Mark module with static size larger than 2M as large module + if [[ $((_size / size_mb)) -ge 1 ]]; then + large_mods[$_name]=$_size + fi + done <<< "$(< /proc/modules)" + + # Extra memory usage required for LUKS2 decryption + crypt_size=0 + for _dev in $(get_all_kdump_crypt_dev); do + _crypt_info=$(cryptsetup luksDump "/dev/block/$_dev") + [[ $(echo "$_crypt_info" | sed -n "s/^Version:\s*\(.*\)/\1/p" ) == "2" ]] || continue + for _mem in $(echo "$_crypt_info" | sed -n "s/\sMemory:\s*\(.*\)/\1/p" | sort -n ); do + crypt_size=$((crypt_size + _mem * 1024)) + break + done + done + [[ $crypt_size -ne 0 ]] && echo -e "Encrypted kdump target requires extra memory, assuming using the keyslot with minimun memory requirement\n" + + estimated_size=$((kernel_size + mod_size + initrd_size + runtime_size + crypt_size)) + if [[ $baseline_size -gt $estimated_size ]]; then + recommended_size=$baseline_size + else + recommended_size=$estimated_size + fi + + echo "Reserved crashkernel: $((reserved_size / size_mb))M" + echo "Recommended crashkernel: $((recommended_size / size_mb))M" + echo + echo "Kernel image size: $((kernel_size / size_mb))M" + echo "Kernel modules size: $((mod_size / size_mb))M" + echo "Initramfs size: $((initrd_size / size_mb))M" + echo "Runtime reservation: $((runtime_size / size_mb))M" + [[ $crypt_size -ne 0 ]] && \ + echo "LUKS required size: $((crypt_size / size_mb))M" + echo -n "Large modules:" + if [[ "${#large_mods[@]}" -eq 0 ]]; then + echo " " + else + echo "" + for _mod in "${!large_mods[@]}"; do + echo " $_mod: ${large_mods[$_mod]}" + done + fi + + if [[ $reserved_size -lt $recommended_size ]]; then + echo "WARNING: Current crashkernel size is lower than recommended size $((recommended_size / size_mb))M." + fi +} + if [ ! -f "$KDUMP_CONFIG_FILE" ]; then - echo "Error: No kdump config file found!" >&2 + derror "Error: No kdump config file found!" exit 1 fi @@ -1259,11 +1367,11 @@ main () check_current_status case "$?" in 0) - echo "Kdump is operational" + dinfo "Kdump is operational" EXIT_CODE=0 ;; 1) - echo "Kdump is not operational" + dinfo "Kdump is not operational" EXIT_CODE=3 ;; esac @@ -1287,8 +1395,11 @@ main () showmem) show_reserved_mem ;; + estimate) + do_estimate + ;; *) - echo $"Usage: $0 {start|stop|status|restart|reload|rebuild|propagate|showmem}" + dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|propagate|showmem}" exit 1 esac } diff --git a/kdumpctl.8 b/kdumpctl.8 index ae97af7..a32a972 100644 --- a/kdumpctl.8 +++ b/kdumpctl.8 @@ -44,6 +44,11 @@ impossible to use password authentication during kdump. .TP .I showmem Prints the size of reserved memory for crash kernel in megabytes. +.TP +.I estimate +Estimate a suitable crashkernel value for current machine. This is a +best-effort estimate. It will print a recommanded crashkernel value +based on current kdump setup, and list some details of memory usage. .SH "SEE ALSO" .BR kdump.conf (5), diff --git a/kexec-kdump-howto.txt b/kexec-kdump-howto.txt index 50bd316..47e11c2 100644 --- a/kexec-kdump-howto.txt +++ b/kexec-kdump-howto.txt @@ -524,17 +524,91 @@ to send over the necessary ssh key file. Restart the kdump service via Advanced Setups =============== -Kdump boot directory --------------------- +About /etc/sysconfig/kdump +------------------------------ + +Currently, there are a few options in /etc/sysconfig/kdump, which are +usually used to control the behavior of kdump kernel. Basically, all of +these options have default values, usually we do not need to change them, +but sometimes, we may modify them in order to better control the behavior +of kdump kernel such as debug, etc. + +-KDUMP_BOOTDIR Usually kdump kernel is the same as 1st kernel. So kdump will try to find kdump kernel under /boot according to /proc/cmdline. E.g we execute below command and get an output: cat /proc/cmdline BOOT_IMAGE=/xxx/vmlinuz-3.yyy.zzz root=xxxx ..... -Then kdump kernel will be /boot/xxx/vmlinuz-3.yyy.zzz. -However a variable KDUMP_BOOTDIR in /etc/sysconfig/kdump is provided to -user if kdump kernel is put in a different directory. + +Then kdump kernel will be /boot/xxx/vmlinuz-3.yyy.zzz. However, this option +is provided to user if kdump kernel is put in a different directory. + +-KDUMP_IMG + +This represents the image type used for kdump. The default value is "vmlinuz". + +-KDUMP_IMG_EXT + +This represents the images extension. Relocatable kernels don't have one. +Currently, it is a null string by default. + +-KEXEC_ARGS + +Any additional kexec arguments required. For example: +KEXEC_ARGS="--elf32-core-headers". + +In most situations, this should be left empty. But, sometimes we hope to get +additional kexec loading debugging information, we can add the '-d' option +for the debugging. + +-KDUMP_KERNELVER + +This is a kernel version string for the kdump kernel. If the version is not +specified, the init script will try to find a kdump kernel with the same +version number as the running kernel. + +-KDUMP_COMMANDLINE + +The value of 'KDUMP_COMMANDLINE' will be passed to kdump kernel as command +line parameters, this will likely match the contents of the grub kernel line. + +In general, if a command line is not specified, which means that it is a null +string such as KDUMP_COMMANDLINE="", the default will be taken automatically +from the '/proc/cmdline'. + +-KDUMP_COMMANDLINE_REMOVE + +This option allows us to remove arguments from the current kdump command line. +If we don't specify any parameters for the KDUMP_COMMANDLINE, it will inherit +all values from the '/proc/cmdline', which is not expected. As you know, some +default kernel parameters could affect kdump, furthermore, that could cause +the failure of kdump kernel boot. + +In addition, the option is also helpful to debug the kdump kernel, we can use +this option to change kdump kernel command line. + +For more kernel parameters, please refer to kernel document. + +-KDUMP_COMMANDLINE_APPEND + +This option allows us to append arguments to the current kdump command line +after processed by the KDUMP_COMMANDLINE_REMOVE. For kdump kernel, some +specific modules require to be disabled like the mce, cgroup, numa, hest_disable, +etc. Those modules may waste memory or kdump kernel doesn't need them, +furthermore, there may affect kdump kernel boot. + +Just like above option, it can be used to disable or enable some kernel +modules so that we can exclude any errors for kdump kernel, this is very +meaningful for debugging. + +-KDUMP_STDLOGLVL | KDUMP_SYSLOGLVL | KDUMP_KMSGLOGLVL + +These variables are used to control the kdump log level in the first kernel. +In the second kernel, kdump will use the rd.kdumploglvl option to set the log +level in the above KDUMP_COMMANDLINE_APPEND. + +Logging levels: no logging(0), error(1), warn(2), info(3), debug(4) Kdump Post-Capture Executable ----------------------------- @@ -613,7 +687,7 @@ is a dump filtering and compression utility provided with kexec-tools. On some architectures, it can drastically reduce the size of your vmcore files, which becomes very useful on systems with large amounts of memory. -A typical setup is 'core_collector makedumpfile -F -l --message-level 1 -d 31', +A typical setup is 'core_collector makedumpfile -F -l --message-level 7 -d 31', but check the output of '/sbin/makedumpfile --help' for a list of all available options (-i and -g don't need to be specified, they're automatically taken care of). Note that use of makedumpfile requires that the kernel-debuginfo package @@ -633,11 +707,11 @@ First one is source file and second one is target file. For ex. - ex2. - core_collector "makedumpfile -l --message-level 1 -d 31" + core_collector "makedumpfile -l --message-level 7 -d 31" Above will effectively be translated to: - makedumpfile -l --message-level 1 -d 31 /proc/vmcore /vmcore + makedumpfile -l --message-level 7 -d 31 /proc/vmcore /vmcore For dump targets like raw and ssh, in general, core collector should expect one argument (source file) and should output the processed core on standard @@ -656,11 +730,11 @@ raw dumps core_collector examples: - ex4. - core_collector "makedumpfile -F -l --message-level 1 -d 31" + core_collector "makedumpfile -F -l --message-level 7 -d 31" Above will effectively be translated to. - makedumpfile -F -l --message-level 1 -d 31 | dd of= + makedumpfile -F -l --message-level 7 -d 31 | dd of= ssh dumps core_collector examples: @@ -674,11 +748,11 @@ ssh dumps core_collector examples: - ex6. - core_collector "makedumpfile -F -l --message-level 1 -d 31" + core_collector "makedumpfile -F -l --message-level 7 -d 31" Above will effectively be translated to. - makedumpfile -F -l --message-level 1 -d 31 | ssh "dd of=path/vmcore" + makedumpfile -F -l --message-level 7 -d 31 | ssh "dd of=path/vmcore" There is one exception to standard output rule for ssh dumps. And that is scp. As scp can handle ssh destinations for file transfers, one can @@ -696,9 +770,9 @@ About default core collector ---------------------------- Default core_collector for ssh/raw dump is: -"makedumpfile -F -l --message-level 1 -d 31". +"makedumpfile -F -l --message-level 7 -d 31". Default core_collector for other targets is: -"makedumpfile -l --message-level 1 -d 31". +"makedumpfile -l --message-level 7 -d 31". Even if core_collector option is commented out in kdump.conf, makedumpfile is default core collector and kdump uses it internally. @@ -885,3 +959,83 @@ Debugging Tips minicom -C /tmp/console-logs Now minicom should be logging serial console in file console-logs. + +- Using the logger to output kdump log messages + + You can configure the kdump log level for the first kernel in the + /etc/sysconfig/kdump. For example: + + KDUMP_STDLOGLVL=3 + KDUMP_SYSLOGLVL=0 + KDUMP_KMSGLOGLVL=0 + + The above configurations indicate that kdump messages will be printed + to the console, and the KDUMP_STDLOGLVL is set to 3(info), but the + KDUMP_SYSLOGLVL and KDUMP_KMSGLOGLVL are set to 0(no logging). This + is also the current default log levels in the first kernel. + + In the second kernel, you can add the 'rd.kdumploglvl=X' option to the + KDUMP_COMMANDLINE_APPEND in the /etc/sysconfig/kdump so that you can also + set the log levels for the second kernel. The 'X' represents the logging + levels, the default log level is 3(info) in the second kernel, for example: + + # cat /etc/sysconfig/kdump |grep rd.kdumploglvl + KDUMP_COMMANDLINE_APPEND="irqpoll nr_cpus=1 reset_devices cgroup_disable=memory mce=off numa=off udev.children-max=2 panic=10 acpi_no_memhotplug transparent_hugepage=never nokaslr hest_disable novmcoredd rd.kdumploglvl=3" + + Logging levels: no logging(0), error(1),warn(2),info(3),debug(4) + + The ERROR level designates error events that might still allow the application + to continue running. + + The WARN level designates potentially harmful situations. + + The INFO level designates informational messages that highlight the progress + of the application at coarse-grained level. + + The DEBUG level designates fine-grained informational events that are most + useful to debug an application. + + Note: if you set the log level to 0, that will disable the logs at the + corresponding log level, which indicates that it has no log output. + + At present, the logger works in both the first kernel(kdump service debugging) + and the second kernel. + + In the first kernel, you can find the historical logs with the journalctl + command and check kdump service debugging information. In addition, the + 'kexec -d' debugging messages are also saved to /var/log/kdump.log in the + first kernel. For example: + + [root@ibm-z-109 ~]# ls -al /var/log/kdump.log + -rw-r--r--. 1 root root 63238 Oct 28 06:40 /var/log/kdump.log + + If you want to get the debugging information of building kdump initramfs, you + can enable the '--debug' option for the dracut_args in the /etc/kdump.conf, and + then rebuild the kdump initramfs as below: + + # systemctl restart kdump.service + + That will rebuild the kdump initramfs and gerenate some logs to journald, you + can find the dracut logs with the journalctl command. + + In the second kernel, kdump will automatically put the kexec-dmesg.log to a same + directory with the vmcore, the log file includes the debugging messages like dmesg + and journald logs. For example: + + [root@ibm-z-109 ~]# ls -al /var/crash/127.0.0.1-2020-10-28-02\:01\:23/ + drwxr-xr-x. 2 root root 67 Oct 28 02:02 . + drwxr-xr-x. 6 root root 154 Oct 28 02:01 .. + -rw-r--r--. 1 root root 21164 Oct 28 02:01 kexec-dmesg.log + -rw-------. 1 root root 74238698 Oct 28 02:01 vmcore + -rw-r--r--. 1 root root 17532 Oct 28 02:01 vmcore-dmesg.txt + + If you want to get more debugging information in the second kernel, you can add + the 'rd.debug' option to the KDUMP_COMMANDLINE_APPEND in the /etc/sysconfig/kdump, + and then reload them in order to make the changes take effect. + + In addition, you can also add the 'rd.memdebug=X' option to the KDUMP_COMMANDLINE_APPEND + in the /etc/sysconfig/kdump in order to output the additional information about + kernel module memory consumption during loading. + + For more details, please refer to the /etc/sysconfig/kdump, or the man page of + dracut.cmdline and kdump.conf. diff --git a/kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch b/kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch new file mode 100644 index 0000000..892f4fb --- /dev/null +++ b/kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch @@ -0,0 +1,25 @@ +From f54ad866c428ecd64a01cfdf7fc6b0a64f5e0fe5 Mon Sep 17 00:00:00 2001 +From: Pingfan Liu +Date: Tue, 15 Dec 2020 14:13:13 +0800 +Subject: [PATCH] fix + +--- + eppic/libeppic/eppic.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/eppic/libeppic/eppic.h b/eppic/libeppic/eppic.h +index 06320f2..74a3c1c 100644 +--- a/eppic/libeppic/eppic.h ++++ b/eppic/libeppic/eppic.h +@@ -467,7 +467,7 @@ type_t *eppic_addstorage(type_t *t1, type_t *t2); + type_t *eppic_getvoidstruct(int ctype); + + extern int lineno, needvar, instruct, nomacs, eppic_legacy; +-node_t *lastv; ++extern node_t *lastv; + + #define NULLNODE ((node_t*)0) + +-- +2.29.2 + diff --git a/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch b/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch new file mode 100644 index 0000000..f79ea55 --- /dev/null +++ b/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch @@ -0,0 +1,60 @@ +From 38d921a2ef50ebd36258097553626443ffe27496 Mon Sep 17 00:00:00 2001 +From: Coiby Xu +Date: Tue, 15 Jun 2021 18:26:31 +0800 +Subject: [PATCH] check for invalid physical address of /proc/kcore + when finding max_paddr + +Kernel commit 464920104bf7adac12722035bfefb3d772eb04d8 ("/proc/kcore: +update physical address for kcore ram and text") sets an invalid paddr +(0xffffffffffffffff = -1) for PT_LOAD segments of not direct mapped +regions: + + $ readelf -l /proc/kcore + ... + Program Headers: + Type Offset VirtAddr PhysAddr + FileSiz MemSiz Flags Align + NOTE 0x0000000000000120 0x0000000000000000 0x0000000000000000 + 0x0000000000002320 0x0000000000000000 0x0 + LOAD 0x1000000000010000 0xd000000000000000 0xffffffffffffffff + ^^^^^^^^^^^^^^^^^^ + 0x0001f80000000000 0x0001f80000000000 RWE 0x10000 + +makedumpfile uses max_paddr to calculate the number of sections for +sparse memory model thus wrong number is obtained based on max_paddr +(-1). This error could lead to the failure of copying /proc/kcore +for RHEL-8.5 on ppc64le machine [1]: + + $ makedumpfile /proc/kcore vmcore1 + get_mem_section: Could not validate mem_section. + get_mm_sparsemem: Can't get the address of mem_section. + + makedumpfile Failed. + +Let's check if the phys_start of the segment is a valid physical +address to fix this problem. + +[1] https://bugzilla.redhat.com/show_bug.cgi?id=1965267 + +Reported-by: Xiaoying Yan +Signed-off-by: Coiby Xu +--- + elf_info.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/makedumpfile-1.6.9/elf_info.c b/makedumpfile-1.6.9/elf_info.c +index e8affb7..bc24083 100644 +--- a/makedumpfile-1.6.9/elf_info.c ++++ b/makedumpfile-1.6.9/elf_info.c +@@ -628,7 +628,7 @@ get_max_paddr(void) + + for (i = 0; i < num_pt_loads; i++) { + pls = &pt_loads[i]; +- if (max_paddr < pls->phys_end) ++ if (pls->phys_start != NOT_PADDR && max_paddr < pls->phys_end) + max_paddr = pls->phys_end; + } + return max_paddr; +-- +2.29.2 + diff --git a/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch b/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch new file mode 100644 index 0000000..8cf780c --- /dev/null +++ b/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch @@ -0,0 +1,43 @@ +From 9a6f589d99dcef114c89fde992157f5467028c8f Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Fri, 18 Jun 2021 18:28:04 +0800 +Subject: [PATCH] check for invalid physical address of /proc/kcore + when making ELF dumpfile + +Previously when executing makedumpfile with -E option against +/proc/kcore, makedumpfile will fail: + + # makedumpfile -E -d 31 /proc/kcore kcore.dump + ... + write_elf_load_segment: Can't convert physaddr(ffffffffffffffff) to an offset. + + makedumpfile Failed. + +It's because /proc/kcore contains PT_LOAD program headers which have +physaddr (0xffffffffffffffff). With -E option, makedumpfile will +try to convert the physaddr to an offset and fails. + +Skip the PT_LOAD program headers which have such physaddr. + +Signed-off-by: Tao Liu +Signed-off-by: Kazuhito Hagio +--- + makedumpfile.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/makedumpfile-1.6.9/makedumpfile.c b/makedumpfile-1.6.9/makedumpfile.c +index 894c88e..fcb571f 100644 +--- a/makedumpfile-1.6.9/makedumpfile.c ++++ b/makedumpfile-1.6.9/makedumpfile.c +@@ -7764,7 +7764,7 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page) + if (!get_phdr_memory(i, &load)) + return FALSE; + +- if (load.p_type != PT_LOAD) ++ if (load.p_type != PT_LOAD || load.p_paddr == NOT_PADDR) + continue; + + off_memory= load.p_offset; +-- +2.29.2 + diff --git a/kexec-tools.spec b/kexec-tools.spec index 5a5a78d..1697317 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -1,5 +1,6 @@ -%define anolis_release 2 +%define anolis_release 3 %define makedumpfile_version 1.6.9 + Name: kexec-tools Version: 2.0.21 Release: 1.%{anolis_release}%{?dist} @@ -36,6 +37,10 @@ Source28: supported-kdump-targets.txt Source29: kdump-udev-throttler Source30: kdump.sysconfig.aarch64 Source31: fadump-howto.txt +Source32: 60-kdump.install +Source33: kdump-logger.sh +Source34: kdump-migrate-action.sh +Source35: kdump-restart.sh ####################################### # These are sources for mkdumpramfs @@ -52,11 +57,14 @@ Source107: dracut-kdump-emergency.target Source108: dracut-early-kdump.sh Source109: dracut-early-kdump-module-setup.sh +%ifarch ppc64 ppc64le +Requires(post): servicelog +%endif Requires(post): systemd-units Requires(preun): systemd-units Requires(postun): systemd-units Requires(pre): coreutils sed zlib -Requires: dracut >= 049-24 +Requires: dracut >= 049-129 Requires: dracut-network >= 049 Requires: dracut-squash >= 049 Requires: ethtool @@ -96,13 +104,13 @@ ExcludeArch: i686 # Patch601: rhelonly-kexec-tools-2.0.16-koji-build-fail-workaround.patch Patch602: rhelonly-kexec-tools-2.0.18-eppic-fix-issues-with-hardening-flags.patch +Patch603: kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch + # Patches 701 onward for makedumpfile -# Inspired by https://git.centos.org/rpms/kexec-tools/raw/c8s/f/SOURCES/rhelonly-kexec-tools-2.0.20-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch Patch701: rhelonly-kexec-tools-2.0.21-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch - -# backport patch from upstream -Patch1001: eppic-remove-duplicated-variable-declaration.patch +Patch702: kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch +Patch703: kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch %description kexec-tools provides /usr/sbin/kexec binary that facilitates a new @@ -120,14 +128,11 @@ tar -z -x -v -f %{SOURCE19} %patch601 -p1 %patch602 -p1 +%patch603 -p1 -pushd makedumpfile-%{makedumpfile_version} %patch701 -p1 -popd - -pushd eppic -%patch1001 -p1 -popd +%patch702 -p1 +%patch703 -p1 %ifarch ppc %define archdef ARCH=ppc @@ -177,6 +182,7 @@ mkdir -p $RPM_BUILD_ROOT%{_unitdir} mkdir -p -m755 $RPM_BUILD_ROOT%{_bindir} mkdir -p -m755 $RPM_BUILD_ROOT%{_libdir} mkdir -p -m755 $RPM_BUILD_ROOT%{_prefix}/lib/kdump +mkdir -p -m755 $RPM_BUILD_ROOT%{_sharedstatedir}/kdump install -m 755 %{SOURCE1} $RPM_BUILD_ROOT%{_bindir}/kdumpctl install -m 755 build/sbin/kexec $RPM_BUILD_ROOT/usr/sbin/kexec @@ -196,6 +202,7 @@ install -m 644 %{SOURCE12} $RPM_BUILD_ROOT%{_mandir}/man8/mkdumprd.8 install -m 644 %{SOURCE25} $RPM_BUILD_ROOT%{_mandir}/man8/kdumpctl.8 install -m 755 %{SOURCE20} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-lib.sh install -m 755 %{SOURCE23} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-lib-initramfs.sh +install -m 755 %{SOURCE33} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-logger.sh %ifnarch s390x ppc64 ppc64le # For s390x the ELF header is created in the kdump kernel and therefore kexec # udev rules are not required @@ -203,6 +210,8 @@ install -m 644 %{SOURCE13} $RPM_BUILD_ROOT%{_udevrulesdir}/98-kexec.rules %endif %ifarch ppc64 ppc64le install -m 644 %{SOURCE14} $RPM_BUILD_ROOT%{_udevrulesdir}/98-kexec.rules +install -m 755 %{SOURCE34} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-migrate-action.sh +install -m 755 %{SOURCE35} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-restart.sh %endif %ifnarch s390x install -m 755 %{SOURCE29} $RPM_BUILD_ROOT%{_udevrulesdir}/../kdump-udev-throttler @@ -210,6 +219,8 @@ install -m 755 %{SOURCE29} $RPM_BUILD_ROOT%{_udevrulesdir}/../kdump-udev-throttl install -m 644 %{SOURCE15} $RPM_BUILD_ROOT%{_mandir}/man5/kdump.conf.5 install -m 644 %{SOURCE16} $RPM_BUILD_ROOT%{_unitdir}/kdump.service install -m 755 -D %{SOURCE22} $RPM_BUILD_ROOT%{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh +install -m 755 -D %{SOURCE32} $RPM_BUILD_ROOT%{_prefix}/lib/kernel/install.d/60-kdump.install + %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 install -m 755 makedumpfile-%{makedumpfile_version}/makedumpfile $RPM_BUILD_ROOT/usr/sbin/makedumpfile @@ -253,6 +264,13 @@ mv $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/* $RPM_BUILD_ROOT/%{d %systemd_post kdump.service touch /etc/kdump.conf + +%ifarch ppc64 ppc64le +servicelog_notify --remove --command=/usr/lib/kdump/kdump-migrate-action.sh +servicelog_notify --add --command=/usr/lib/kdump/kdump-migrate-action.sh --match='refcode="#MIGRATE" and serviceable=0' --type=EVENT --method=pairs_stdin +%endif + + # This portion of the script is temporary. Its only here # to fix up broken boxes that require special settings # in /etc/sysconfig/kdump. It will be removed when @@ -280,6 +298,9 @@ fi %systemd_postun_with_restart kdump.service %preun +%ifarch ppc64 ppc64le +servicelog_notify --remove --command=/usr/lib/kdump/kdump-migrate-action.sh +%endif # Package removal, not upgrade %systemd_preun kdump.service @@ -338,6 +359,7 @@ done %dir %{_sysconfdir}/kdump %dir %{_sysconfdir}/kdump/pre.d %dir %{_sysconfdir}/kdump/post.d +%dir %{_sharedstatedir}/kdump %{_mandir}/man8/kdumpctl.8.gz %{_mandir}/man8/kexec.8.gz %{_mandir}/man8/makedumpfile.8.gz @@ -346,6 +368,7 @@ done %{_mandir}/man5/* %{_unitdir}/kdump.service %{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh +%{_prefix}/lib/kernel/install.d/60-kdump.install %doc News %license COPYING %doc TODO @@ -361,6 +384,9 @@ done %endif %changelog +* Mon Feb 07 2022 Chunmei Xu - 2.0.21-1.3 +- remove -s from KEXEC_ARGS to prevent bzImange verify + * Mon Sep 27 2021 Weitao Zhou - 2.0.21-1.2 - rebase makedumpfile to 1.6.9 - makedumpfile: migrate to RHEL solution on support for ARMv8.2 LVA 52 bit @@ -372,9 +398,153 @@ done - makedumpfile: support use 'TCR_EL1.T1SZ' to determine va bits - makedumpfile: support read register ID_AA64MMFR2_EL1 to get va bits -* Sat Nov 07 2020 Liwei Ge - 2.0.20-34.1 -- Rebuild for Alibaba Cloud Linux -- Fix gcc10 build issue +* Tue Nov 2 2021 Pingfan Liu - 2.0.20-57.1 +- mkdumprd: Use xz for squash image compression + +* Fri Aug 27 2021 Pingfan Liu - 2.0.20-57 +- kdumpctl: enable secure boot on ppc64le LPARs + +* Fri Aug 6 2021 Pingfan Liu - 2.0.20-56 +- kdumpctl: fix a typo + +* Mon Aug 2 2021 Pingfan Liu - 2.0.20-55 +- kdump/ppc64: migration action registration clean up + +* Fri Jul 23 2021 Pingfan Liu - 2.0.20-54 +- kdump/ppc64: rebuild initramfs image after migration +- Check the existence of /sys/bus/ccwgroup/devices/*/online beforehand +- kdump.sysconfig.s390: Remove "prot_virt" from kdump kernel cmdline + +* Fri Jul 2 2021 Pingfan Liu - 2.0.20-53 +- check for invalid physical address of /proc/kcore when making ELF dumpfile +- check for invalid physical address of /proc/kcore when finding max_paddr +- fix format issue in find_online_znet_device +- check the existence of /sys/bus/ccwgroup/devices before trying to find online network device +- kdump-lib.sh: fix a warning in prepare_kdump_bootinfo() + +* Thu Jun 17 2021 Pingfan Liu - 2.0.20-52 +- Write to `/var/lib/kdump` if $KDUMP_BOOTDIR not writable +- Iterate /sys/bus/ccwgroup/devices to tell if we should set up rd.znet +- mkdumprd: display the absolute path of dump location in the check_user_configured_target() + +* Wed Jun 2 2021 Pingfan Liu - 2.0.20-51 +- Stop reloading kdump service on CPU hotplug event for FADump +- fadump: improve fadump-howto.txt about remote dump target setup + +* Tue May 25 2021 Pingfan Liu - 2.0.20-50 +- rd.route should use the name from kdump_setup_ifname +- get kdump ifname once in kdump_install_netdev + +* Tue May 25 2021 Pingfan Liu - 2.0.20-49 +- kdump-lib.sh: fix the case if no enough total RAM for kdump in get_recommend_size() + +* Thu May 20 2021 Pingfan Liu - 2.0.20-48 +- kdumpctl: Add kdumpctl estimate +- mkdumprd: make use of the new get_luks_crypt_dev helper +- kdump-lib.sh: introduce a helper to get all crypt dev used by kdump +- kdump-lib.sh: introduce a helper to get underlying crypt device +- RHEL-only: keep total memory size coherent to RHEL-only kernel patch +- Show write byte size in report messages +- Add shorthand --show-stats option to show report stats +- Add --dry-run option to prevent writing the dumpfile +- kdump-lib.sh: introduce functions to return recommened mem size + +* Mon May 10 2021 Pingfan Liu - 2.0.20-47 +- Implement IP netmask calculation to replace "ipcalc -m" +- kdumpctl: fix check_config error when kdump.conf is empty +- Fix incorrect vmcore permissions when dumped through ssh +- Fix incorrect permissions on kdump dmesg file + +* Mon Jan 25 2021 Pingfan Liu - 2.0.20-45 +- origin/rhel-8.4.0) Revert "Revert "Append both nofail and x-systemd.before to kdump mount target"" +- kdump.conf: add ipv6 example for nfs and ssh dump +- fix kdump failure of saving vmcore with the scp + ipv6 method + +* Fri Jan 22 2021 Pingfan Liu - 2.0.20-44 +- module-setup.sh: don't polute the namespace unnecessarily +- module-setup.sh: don't source $dracutfunctions +- logger: source the logger file individually +- dracut-module-setup.sh: enable ForwardToConsole=yes in fadump mode + +* Fri Jan 15 2021 Pingfan Liu - 2.0.20-43 +- Always include watchdog-modules +- mkdumprd: Ensure kdumpbase is added +- Move watchdog detect and install code to module-setup.sh +- Add a helper to omit non-mandatory dracut module +- Move some dracut module dependencies checks to module-setup.sh +- Set watchdog's pretimeout to zero in kdump kernel +- kdump-lib.sh: Use a more generic helper to detect omitted dracut module +- Fix the watchdog drivers detection code +- Add a helper for detecting watchdog drivers +- Remove a redundant nfs check +- kdumpctl: split the driver detection from fs dection function +- kdump.service: use ConditionKernelCommandLine=crashkernel +- Revert "Append both nofail and x-systemd.before to kdump mount target" +- Revert "Don's try to restart dracut-initqueue if it's already failed" +- Fix dump_fs mount point detection and fallback mount +- kdump.conf: Update doc about core_collector for ssh target +- Save the final failure information to log file if saving vmcore failed +- Doc: Improve the kdump sysconfig document +- kdumpctl: fix a variable expansion in check_fence_kdump_config() +- Fedora 33 rhpkg build bug + +* Tue Dec 22 2020 Pingfan Liu - 2.0.20-42 +- makedumpfile: add support for ARMv8.2 LVA 52 bits + +* Fri Dec 18 2020 Pingfan Liu - 2.0.20-41 +- Doc: improve mkdumprd man page + +* Tue Dec 15 2020 Pingfan Liu - 2.0.20-40 +- Rework on dracut-module-setup.sh: Use systemctl call to replace ln_r + +* Tue Dec 15 2020 Pingfan Liu - 2.0.20-39 +- dracut-module-setup.sh: Use systemctl call to replace ln_r + +* Fri Dec 11 2020 Pingfan Liu - 2.0.20-38 +- Don's try to restart dracut-initqueue if it's already failed +- fadump-howto: update about 'nocma' and 'off' options for 'fadump=' parameter +- dracut-module-setup.sh: use auto6 for ipv6 +- module-setup.sh: enable vlan on team interface +- Fix rootfs detection in dump_fs +- Remove RHEL-only patch: kexec-tools-2.0.18-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch +- Rebase to makedumpfile-1.6.8 (step1) + +* Fri Nov 13 2020 Pingfan Liu - 2.0.20-37 +- Doc: improve the usage documentation of the logger +- Update the kdump sysconfig +- Capitalize the configuration name of log level +- Add the rd.kdumploglvl option to control log level in the second kernel +- Appropriately converts logger numeric level to syslog log level +- Remove unused log levels for kdump logger +- Add sanity checks for the log levels +- Add code comments to help better understanding +- Doc: add a documentation for the usage of logger +- Improve debugging in the kdump kernel +- kdumpctl: add the '-d' option to enable the kexec loading debugging messages +- kdump.sysconfig: add the kdump logger configurations +- enable the logger for kdump +- introduce the kdump logger from the dracut + +* Fri Nov 6 2020 Pingfan Liu - 2.0.20-36 +- arm64: Enable 'kexec_file_load' by default +- Fix, Add a kernel install hook to clean up kdump initramfs + +* Fri Oct 30 2020 Pingfan Liu - 2.0.20-35 +- module-setup.sh: Instead of drop journalctl log, just don't read kmsg +- s390x: enable the kexec file load by default +- increase makdumpfile default message level to 7 +- Rework check_config and warn on any duplicated option +- kdumpctl: Error out if path is set more than once. +- Don't drop journalctl content if failure action is "shell" +- dracut-module-install: Move systemd conf install code to a function +- kdump-lib.sh: Remove is_atomic +- Refactor kernel image and initrd detection code +- early-kdump: Use consistent symbol link for kernel and initramfs +- kdump-lib: strip grub device from kdump_bootdir +- kdumpctl: fix driver change detection on latest Fedora +- Revert "kdump-lib: disable efifb if hyperv_fb is in use" +- kdump-lib.sh: detect secure boot on s390 +- Add a kernel install hook to clean up kdump initramfs * Wed Aug 19 2020 Pingfan Liu - 2.0.20-34 - kdump-lib: disable efifb if hyperv_fb is in use diff --git a/mkdumprd b/mkdumprd index 8b09710..1bd3d0a 100644 --- a/mkdumprd +++ b/mkdumprd @@ -6,18 +6,30 @@ # Written by Cong Wang # +if [ -f /etc/sysconfig/kdump ]; then + . /etc/sysconfig/kdump +fi + [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut . $dracutbasedir/dracut-functions.sh . /lib/kdump/kdump-lib.sh +. /lib/kdump/kdump-logger.sh export IN_KDUMP=1 +#initiate the kdump logger +dlog_init +if [ $? -ne 0 ]; then + echo "failed to initiate the kdump logger." + exit 1 +fi + conf_file="/etc/kdump.conf" SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" SAVE_PATH=$(get_save_path) OVERRIDE_RESETTABLE=0 extra_modules="" -dracut_args="--quiet --hostonly --hostonly-cmdline --hostonly-i18n --hostonly-mode strict -o \"plymouth dash resume ifcfg earlykdump\"" +dracut_args="--add kdumpbase --quiet --hostonly --hostonly-cmdline --hostonly-i18n --hostonly-mode strict -o \"plymouth dash resume ifcfg earlykdump\" --compress=xz" readonly MKDUMPRD_TMPDIR="$(mktemp -d -t mkdumprd.XXXXXX)" [ -d "$MKDUMPRD_TMPDIR" ] || perror_exit "dracut: mktemp -p -d -t dracut.XXXXXX failed." @@ -33,28 +45,10 @@ trap ' # clean up after ourselves no matter how we die. trap 'exit 1;' SIGINT -is_wdt_addition_needed() { - local active - - is_wdt_mod_omitted - [[ $? -eq 0 ]] && return 1 - [[ -d /sys/class/watchdog/ ]] || return 1 - for dir in /sys/class/watchdog/*; do - [[ -f "$dir/state" ]] || continue - active=$(< "$dir/state") - [[ "$active" = "active" ]] && return 0 - done - return 1 -} - add_dracut_arg() { dracut_args="$dracut_args $@" } -add_dracut_module() { - add_dracut_arg "--add" "\"$1\"" -} - add_dracut_mount() { add_dracut_arg "--mount" "\"$1\"" } @@ -177,8 +171,8 @@ check_size() { fi if [ $avail -lt $memtotal ]; then - echo "Warning: There might not be enough space to save a vmcore." - echo " The size of $2 should be greater than $memtotal kilo bytes." + dwarn "Warning: There might not be enough space to save a vmcore." + dwarn " The size of $2 should be greater than $memtotal kilo bytes." fi } @@ -232,7 +226,7 @@ check_user_configured_target() # For user configured target, use $SAVE_PATH as the dump path within the target if [ ! -d "$_mnt/$SAVE_PATH" ]; then - perror_exit "Dump path \"$SAVE_PATH\" does not exist in dump target \"$_target\"" + perror_exit "Dump path \"$_mnt/$SAVE_PATH\" does not exist in dump target \"$_target\"" fi check_size fs "$_target" @@ -250,7 +244,7 @@ verify_core_collector() { if [ "$_cmd" != "makedumpfile" ]; then if is_raw_dump_target; then - echo "Warning: specifying a non-makedumpfile core collector, you will have to recover the vmcore manually." + dwarn "Warning: specifying a non-makedumpfile core collector, you will have to recover the vmcore manually." fi return fi @@ -311,7 +305,6 @@ get_override_resettable() fi } - # $1: function name for_each_block_target() { @@ -326,8 +319,6 @@ for_each_block_target() return 0 } - - #judge if a specific device with $1 is unresettable #return false if unresettable. is_unresettable() @@ -340,7 +331,7 @@ is_unresettable() resettable="$(cat $path)" [ $resettable -eq 0 -a "$OVERRIDE_RESETTABLE" -eq 0 ] && { local device=$(udevadm info --query=all --path=/sys/dev/block/$1 | awk -F= '/DEVNAME/{print $2}') - echo "Error: Can not save vmcore because device $device is unresettable" + derror "Error: Can not save vmcore because device $device is unresettable" return 0 } fi @@ -364,32 +355,15 @@ check_resettable() return 1 } -# $1: maj:min -is_crypt() -{ - local majmin=$1 dev line ID_FS_TYPE="" - - line=$(udevadm info --query=property --path=/sys/dev/block/$majmin \ - | grep "^ID_FS_TYPE") - eval "$line" - [[ "$ID_FS_TYPE" = "crypto_LUKS" ]] && { - dev=$(udevadm info --query=all --path=/sys/dev/block/$majmin | awk -F= '/DEVNAME/{print $2}') - echo "Device $dev is encrypted." - return 0 - } - return 1 -} - check_crypt() { - local _ret _target - - for_each_block_target is_crypt - _ret=$? - - [ $_ret -eq 0 ] && return + local _dev - return 1 + for _dev in $(get_kdump_targets); do + if [[ -n $(get_luks_crypt_dev "$(get_maj_min "$_dev")") ]]; then + derror "Device $_dev is encrypted." && return 1 + fi + done } if ! check_resettable; then @@ -397,7 +371,7 @@ if ! check_resettable; then fi if ! check_crypt; then - echo "Warning: Encrypted device is in dump path. User will prompted for password during second kernel boot." + dwarn "Warning: Encrypted device is in dump path. User will prompted for password during second kernel boot." fi # firstly get right SSH_KEY_LOCATION @@ -407,14 +381,6 @@ if [ -f "$keyfile" ]; then SSH_KEY_LOCATION=$(/usr/bin/readlink -m $keyfile) fi -if [ "$(uname -m)" = "s390x" ]; then - add_dracut_module "znet" -fi - -if is_wdt_addition_needed; then - add_dracut_arg "-a" "watchdog" -fi - while read config_opt config_val; do # remove inline comments after the end of a directive. @@ -443,7 +409,6 @@ do then mkdir_save_path_ssh $config_val check_size ssh $config_val - add_dracut_module "ssh-client" add_dracut_sshkey "$SSH_KEY_LOCATION" else perror_exit "Bad ssh dump target $config_val" diff --git a/mkdumprd.8 b/mkdumprd.8 index 7faae57..2ac3d5a 100644 --- a/mkdumprd.8 +++ b/mkdumprd.8 @@ -15,7 +15,13 @@ be loaded in the initramfs (based on configuration retrieved from \fI/etc/kdump.conf)\fR \fBmkdumprd\fR add a new \fBdracut\fR module 99kdumpbase and use \fBdracut\fR -utility to generate the initramfs. +utility to generate the initramfs. When generating a kdump initramfs, \fBmkdumprd\fR +will determine how much disk space is available, if the dump target's available +space is not greater than the total system memory, \fBmkdumprd\fR will print a +warning to remind that there might not be enough space to save a vmcore. The +warning covers extreme scenarios such as the slab explodes with non-zero data or +a full vmcore, etc. Therefore, need to prevent users from having minimum disk +space for crash dump. \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 diff --git a/rhelonly-kexec-tools-2.0.21-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch b/rhelonly-kexec-tools-2.0.21-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch index 7bb3b24..7f10b24 100644 --- a/rhelonly-kexec-tools-2.0.21-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch +++ b/rhelonly-kexec-tools-2.0.21-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch @@ -1,24 +1,36 @@ -diff -Naur makedumpfile-1.6.9-origin/arch/arm64.c makedumpfile-1.6.9/arch/arm64.c ---- makedumpfile-1.6.9-origin/arch/arm64.c 2021-09-27 21:52:54.355555558 +0800 -+++ makedumpfile-1.6.9/arch/arm64.c 2021-09-27 21:55:29.086286870 +0800 -@@ -50,6 +50,7 @@ +From 16028a119c85ed73944bcf6ca310a7ee4d2e64fe Mon Sep 17 00:00:00 2001 +From: Pingfan Liu +Date: Mon, 21 Dec 2020 13:35:38 +0800 +Subject: [PATCH] RHEL-only + +--- + makedumpfile-1.6.9/arch/arm64.c | 14 +++++++++++++- + makedumpfile-1.6.9/makedumpfile.c | 2 ++ + makedumpfile-1.6.9/makedumpfile.h | 1 + + 3 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/makedumpfile-1.6.9/arch/arm64.c b/makedumpfile-1.6.9/arch/arm64.c +index 1072178..95beae6 100644 +--- a/makedumpfile-1.6.9/arch/arm64.c ++++ b/makedumpfile-1.6.9/arch/arm64.c +@@ -50,6 +50,7 @@ static int va_bits; static int vabits_actual; static int flipped_va; static unsigned long kimage_voffset; +static int max_user_va_bits; - + #define SZ_4K 4096 #define SZ_16K 16384 -@@ -108,7 +109,7 @@ +@@ -108,7 +109,7 @@ typedef unsigned long pgdval_t; #define PGDIR_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - (pgtable_level)) #define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) -#define PTRS_PER_PGD (1 << ((va_bits) - PGDIR_SHIFT)) -+#define PTRS_PER_PGD (1 << ((max_user_va_bits) - PGDIR_SHIFT)) - ++#define PTRS_PER_PGD (1 << ((max_user_va_bits) - PGDIR_SHIFT)) + /* * Section address mask and size definitions. -@@ -449,6 +450,17 @@ +@@ -449,6 +450,17 @@ get_machdep_info_arm64(void) ERRMSG("Can't determine platform config values\n"); return FALSE; } @@ -33,21 +45,22 @@ diff -Naur makedumpfile-1.6.9-origin/arch/arm64.c makedumpfile-1.6.9/arch/arm64. + max_user_va_bits); + } + - + kimage_voffset = NUMBER(kimage_voffset); info->section_size_bits = SECTIONS_SIZE_BITS; -diff -Naur makedumpfile-1.6.9-origin/makedumpfile.c makedumpfile-1.6.9/makedumpfile.c ---- makedumpfile-1.6.9-origin/makedumpfile.c 2021-09-27 21:52:54.355555558 +0800 -+++ makedumpfile-1.6.9/makedumpfile.c 2021-09-27 21:57:31.326864623 +0800 -@@ -2398,6 +2398,7 @@ - +diff --git a/makedumpfile-1.6.9/makedumpfile.c b/makedumpfile-1.6.9/makedumpfile.c +index 894c88e..0071da8 100644 +--- a/makedumpfile-1.6.9/makedumpfile.c ++++ b/makedumpfile-1.6.9/makedumpfile.c +@@ -2398,6 +2398,7 @@ write_vmcoreinfo_data(void) + WRITE_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR); #ifdef __aarch64__ + WRITE_NUMBER("MAX_USER_VA_BITS", MAX_USER_VA_BITS); WRITE_NUMBER("VA_BITS", VA_BITS); /* WRITE_NUMBER("TCR_EL1_T1SZ", TCR_EL1_T1SZ); should not exists */ WRITE_NUMBER_UNSIGNED("PHYS_OFFSET", PHYS_OFFSET); -@@ -2838,6 +2839,7 @@ +@@ -2838,6 +2839,7 @@ read_vmcoreinfo(void) READ_NUMBER("phys_base", phys_base); READ_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE); #ifdef __aarch64__ @@ -55,10 +68,11 @@ diff -Naur makedumpfile-1.6.9-origin/makedumpfile.c makedumpfile-1.6.9/makedumpf READ_NUMBER("VA_BITS", VA_BITS); READ_NUMBER("TCR_EL1_T1SZ", TCR_EL1_T1SZ); READ_NUMBER_UNSIGNED("PHYS_OFFSET", PHYS_OFFSET); -diff -Naur makedumpfile-1.6.9-origin/makedumpfile.h makedumpfile-1.6.9/makedumpfile.h ---- makedumpfile-1.6.9-origin/makedumpfile.h 2021-09-27 21:52:54.355555558 +0800 -+++ makedumpfile-1.6.9/makedumpfile.h 2021-09-27 21:58:17.287081975 +0800 -@@ -2049,6 +2049,7 @@ +diff --git a/makedumpfile-1.6.9/makedumpfile.h b/makedumpfile-1.6.9/makedumpfile.h +index 93aa774..31319e7 100644 +--- a/makedumpfile-1.6.9/makedumpfile.h ++++ b/makedumpfile-1.6.9/makedumpfile.h +@@ -2049,6 +2049,7 @@ struct number_table { long phys_base; long KERNEL_IMAGE_SIZE; #ifdef __aarch64__ @@ -66,3 +80,6 @@ diff -Naur makedumpfile-1.6.9-origin/makedumpfile.h makedumpfile-1.6.9/makedumpf long VA_BITS; long TCR_EL1_T1SZ; unsigned long PHYS_OFFSET; +-- +2.27.0 + -- Gitee