diff options
| author | CoprDistGit <infra@openeuler.org> | 2024-07-26 17:19:39 +0000 |
|---|---|---|
| committer | CoprDistGit <infra@openeuler.org> | 2024-07-26 17:19:39 +0000 |
| commit | 5be00af7c80ed4972c1f3379e6db9937e1a8b7bd (patch) | |
| tree | 7938404f19676c304f68d0d47e475fe4a1440452 | |
| parent | ad07ec0c7538028e4d732f63e34d58150f5ffd42 (diff) | |
automatic import of kexec-tools
41 files changed, 6071 insertions, 0 deletions
@@ -0,0 +1,3 @@ +/eppic-e8844d3.tar.gz +/kexec-tools-2.0.26.tar.xz +/makedumpfile-1.7.3.tar.gz diff --git a/98-kexec.rules b/98-kexec.rules new file mode 100644 index 0000000..b73b701 --- /dev/null +++ b/98-kexec.rules @@ -0,0 +1,16 @@ +SUBSYSTEM=="cpu", ACTION=="add", GOTO="kdump_reload" +SUBSYSTEM=="cpu", ACTION=="remove", GOTO="kdump_reload" +SUBSYSTEM=="memory", ACTION=="online", GOTO="kdump_reload" +SUBSYSTEM=="memory", ACTION=="offline", GOTO="kdump_reload" + +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 +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'" + +LABEL="kdump_reload_end" diff --git a/add-secure-compile-options-for-makedumpfile.patch b/add-secure-compile-options-for-makedumpfile.patch new file mode 100644 index 0000000..a3207c3 --- /dev/null +++ b/add-secure-compile-options-for-makedumpfile.patch @@ -0,0 +1,32 @@ +From 776d8f6355fdf77ec63bae4be09b8f40d0c831ad Mon Sep 17 00:00:00 2001 +From: pengyeqing <pengyeqing@huawei.com> +Date: Sun, 18 Aug 2019 23:59:23 +0000 +Subject: [PATCH] kexec-tools: add secure compile options for makedumpfile + +reason:add secure compile options for makedumpfile + +Signed-off-by: pengyeqing <pengyeqing@huawei.com> +--- + Makefile | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/makedumpfile-1.6.7/Makefile b/makedumpfile-1.6.7/Makefile +index 612b9d0..180a64f 100644 +--- a/makedumpfile-1.7.3/Makefile ++++ b/makedumpfile-1.7.3/Makefile +@@ -10,9 +10,10 @@ endif + + CFLAGS_BASE := $(CFLAGS) -g -O2 -Wall -D_FILE_OFFSET_BITS=64 \ + -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE +-CFLAGS := $(CFLAGS_BASE) -DVERSION='"$(VERSION)"' -DRELEASE_DATE='"$(DATE)"' +-CFLAGS_ARCH := $(CFLAGS_BASE) ++CFLAGS := $(CFLAGS_BASE) -DVERSION='"$(VERSION)"' -DRELEASE_DATE='"$(DATE)"' -fstack-protector-strong -Wl,-z,now -fPIE ++CFLAGS_ARCH := $(CFLAGS_BASE) -fPIE + # LDFLAGS = -L/usr/local/lib -I/usr/local/include ++LDFLAGS += -pie + + HOST_ARCH := $(shell uname -m) + # Use TARGET as the target architecture if specified. +-- +1.8.3.1 + diff --git a/dracut-early-kdump-module-setup.sh b/dracut-early-kdump-module-setup.sh new file mode 100755 index 0000000..e069867 --- /dev/null +++ b/dracut-early-kdump-module-setup.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +. /etc/sysconfig/kdump +. /lib/kdump/kdump-lib.sh + +KDUMP_KERNEL="" +KDUMP_INITRD="" + +check() { + if [ ! -f /etc/sysconfig/kdump ] || [ ! -f /lib/kdump/kdump-lib.sh ]\ + || [ -n "${IN_KDUMP}" ] + then + return 1 + fi + return 255 +} + +depends() { + echo "base shutdown" + return 0 +} + +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 + fi + KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}" + KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img" +} + +install() { + prepare_kernel_initrd + if [ ! -f "$KDUMP_KERNEL" ]; then + derror "Could not find required kernel for earlykdump," \ + "earlykdump will not work!" + return 1 + fi + if [ ! -f "$KDUMP_INITRD" ]; then + derror "Could not find required kdump initramfs for earlykdump," \ + "please ensure kdump initramfs is generated first," \ + "earlykdump will not work!" + return 1 + fi + + inst_multiple tail find cut dirname hexdump + inst_simple "/etc/sysconfig/kdump" + inst_binary "/usr/sbin/kexec" + inst_binary "/usr/bin/gawk" "/usr/bin/awk" + inst_script "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.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" + + chmod -x "${initdir}/$KDUMP_KERNEL" +} diff --git a/dracut-early-kdump.sh b/dracut-early-kdump.sh new file mode 100755 index 0000000..6788a6b --- /dev/null +++ b/dracut-early-kdump.sh @@ -0,0 +1,76 @@ +#! /bin/sh + +KEXEC=/sbin/kexec +standard_kexec_args="-p" +KDUMP_FILE_LOAD="" + +EARLY_KDUMP_INITRD="" +EARLY_KDUMP_KERNEL="" +EARLY_KDUMP_CMDLINE="" +EARLY_KDUMP_KERNELVER="" +EARLY_KEXEC_ARGS="" + +. /etc/sysconfig/kdump +. /lib/dracut-lib.sh +. /lib/kdump-lib.sh + +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_load() +{ + check_kdump_feasibility + if [ $? -ne 0 ]; then + return 1 + fi + + if is_fadump_capable; then + echo "WARNING: early kdump doesn't support fadump." + return 1 + fi + + check_current_kdump_status + if [ $? == 0 ]; then + return 1 + fi + + prepare_parameters + + EARLY_KEXEC_ARGS=$(prepare_kexec_args "${KEXEC_ARGS}") + + if [ "$KDUMP_FILE_LOAD" == "on" ]; then + echo "Using kexec file based syscall." + EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS -s" + fi + + $KEXEC ${EARLY_KEXEC_ARGS} $standard_kexec_args \ + --command-line="$EARLY_KDUMP_CMDLINE" \ + --initrd=$EARLY_KDUMP_INITRD $EARLY_KDUMP_KERNEL + if [ $? == 0 ]; then + echo "kexec: loaded early-kdump kernel" + return 0 + else + echo "kexec: failed to load early-kdump kernel" + return 1 + fi +} + +set_early_kdump() +{ + if getargbool 0 rd.earlykdump; then + echo "early-kdump is enabled." + early_kdump_load + else + echo "early-kdump is disabled." + fi + + return 0 +} + +set_early_kdump diff --git a/dracut-kdump-capture.service b/dracut-kdump-capture.service new file mode 100644 index 0000000..3f20aba --- /dev/null +++ b/dracut-kdump-capture.service @@ -0,0 +1,30 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Kdump Vmcore Save Service +After=initrd.target initrd-parse-etc.service sysroot.mount +After=dracut-initqueue.service dracut-pre-mount.service dracut-mount.service dracut-pre-pivot.service +Before=initrd-cleanup.service +ConditionPathExists=/etc/initrd-release +OnFailure=emergency.target +OnFailureJobMode=isolate + +[Service] +Environment=DRACUT_SYSTEMD=1 +Environment=NEWROOT=/sysroot +Type=oneshot +ExecStart=/bin/kdump.sh +StandardInput=null +StandardOutput=syslog +StandardError=syslog+console +KillMode=process +RemainAfterExit=yes + +# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash +# terminates cleanly. +KillSignal=SIGHUP diff --git a/dracut-kdump-emergency.service b/dracut-kdump-emergency.service new file mode 100644 index 0000000..e023284 --- /dev/null +++ b/dracut-kdump-emergency.service @@ -0,0 +1,28 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# This service will be placed in kdump initramfs and replace both the systemd +# emergency service and dracut emergency shell. IOW, any emergency will be +# kick this service and in turn isolating to kdump error handler. + +[Unit] +Description=Kdump Emergency +DefaultDependencies=no +IgnoreOnIsolate=yes + +[Service] +ExecStart=/usr/bin/systemctl --no-block isolate kdump-error-handler.service +Type=oneshot +StandardInput=tty-force +StandardOutput=inherit +StandardError=inherit +KillMode=process +IgnoreSIGPIPE=no + +# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash +# terminates cleanly. +KillSignal=SIGHUP diff --git a/dracut-kdump-emergency.target b/dracut-kdump-emergency.target new file mode 100644 index 0000000..a1bb493 --- /dev/null +++ b/dracut-kdump-emergency.target @@ -0,0 +1,14 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Emergency Mode +Documentation=man:systemd.special(7) +Requires=emergency.service +After=emergency.service +AllowIsolate=yes +IgnoreOnIsolate=yes diff --git a/dracut-kdump-error-handler.service b/dracut-kdump-error-handler.service new file mode 100644 index 0000000..a23b75e --- /dev/null +++ b/dracut-kdump-error-handler.service @@ -0,0 +1,33 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# This service will run the real kdump error handler code. Executing the +# failure action configured in kdump.conf + +[Unit] +Description=Kdump Error Handler +DefaultDependencies=no +After=systemd-vconsole-setup.service +Wants=systemd-vconsole-setup.service +AllowIsolate=yes + +[Service] +Environment=HOME=/ +Environment=DRACUT_SYSTEMD=1 +Environment=NEWROOT=/sysroot +WorkingDirectory=/ +ExecStart=/bin/kdump-error-handler.sh +Type=oneshot +StandardInput=tty-force +StandardOutput=inherit +StandardError=inherit +KillMode=process +IgnoreSIGPIPE=no + +# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash +# terminates cleanly. +KillSignal=SIGHUP diff --git a/dracut-kdump-error-handler.sh b/dracut-kdump-error-handler.sh new file mode 100755 index 0000000..fc2b932 --- /dev/null +++ b/dracut-kdump-error-handler.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +. /lib/kdump-lib-initramfs.sh + +set -o pipefail +export PATH=$PATH:$KDUMP_SCRIPT_DIR + +get_kdump_confs +do_failure_action +do_final_action diff --git a/dracut-kdump-wait-for-target.sh b/dracut-kdump-wait-for-target.sh new file mode 100755 index 0000000..ce984d0 --- /dev/null +++ b/dracut-kdump-wait-for-target.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# only wait if it's kdump kernel +if [ -f /etc/fadump.initramfs ] && [ ! -f /proc/device-tree/rtas/ibm,kernel-dump ]; then + exit 0 +fi + +. /lib/dracut-lib.sh +. /lib/kdump-lib-initramfs.sh + +# For SSH/NFS target, need to wait for the network to setup +if is_nfs_dump_target; then + get_host_ip + exit $? +fi + +if is_ssh_dump_target; then + get_host_ip + exit $? +fi + +# No need to wait for dump target +exit 0 diff --git a/dracut-kdump.sh b/dracut-kdump.sh new file mode 100755 index 0000000..0f54ddc --- /dev/null +++ b/dracut-kdump.sh @@ -0,0 +1,182 @@ +#!/bin/sh + +# continue here only if we have to save dump. +if [ -f /etc/fadump.initramfs ] && [ ! -f /proc/device-tree/rtas/ibm,kernel-dump ] && [ ! -f /proc/device-tree/ibm,opal/dump/mpipl-boot ]; then + exit 0 +fi + +exec &> /dev/console +. /lib/dracut-lib.sh +. /lib/kdump-lib-initramfs.sh + +set -o pipefail +DUMP_RETVAL=0 + +export PATH=$PATH:$KDUMP_SCRIPT_DIR + +do_dump() +{ + local _ret + + eval $DUMP_INSTRUCTION + _ret=$? + + if [ $_ret -ne 0 ]; then + echo "kdump: saving vmcore failed" + fi + + return $_ret +} + +do_kdump_pre() +{ + if [ -n "$KDUMP_PRE" ]; then + "$KDUMP_PRE" + fi +} + +do_kdump_post() +{ + if [ -n "$KDUMP_POST" ]; then + "$KDUMP_POST" "$1" + fi +} + +add_dump_code() +{ + DUMP_INSTRUCTION=$1 +} + +dump_raw() +{ + local _raw=$1 + + [ -b "$_raw" ] || return 1 + + echo "kdump: saving to raw disk $_raw" + + if ! $(echo -n $CORE_COLLECTOR|grep -q makedumpfile); then + _src_size=`ls -l /proc/vmcore | cut -d' ' -f5` + _src_size_mb=$(($_src_size / 1048576)) + monitor_dd_progress $_src_size_mb & + fi + + echo "kdump: 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" + return 0 +} + +dump_ssh() +{ + local _opt="-i $1 -o BatchMode=yes -o StrictHostKeyChecking=yes" + local _dir="$KDUMP_PATH/$HOST_IP-$DATEDIR" + local _host=$2 + + echo "kdump: saving to $_host:$_dir" + + cat /var/lib/random-seed > /dev/urandom + ssh -q $_opt $_host mkdir -p $_dir || return 1 + + save_vmcore_dmesg_ssh ${DMESG_COLLECTOR} ${_dir} "${_opt}" $_host + save_opalcore_ssh ${_dir} "${_opt}" $_host + + echo "kdump: saving vmcore" + + 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 + 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 + fi + + echo "kdump: saving vmcore complete" + return 0 +} + +save_opalcore_ssh() { + local _path=$1 + local _opts="$2" + local _location=$3 + + if [ ! -f $OPALCORE ]; then + # Check if we are on an old kernel that uses a different path + if [ -f /sys/firmware/opal/core ]; then + OPALCORE="/sys/firmware/opal/core" + else + return 0 + fi + fi + + echo "kdump: saving opalcore" + scp $_opts $OPALCORE $_location:$_path/opalcore-incomplete + if [ $? -ne 0 ]; then + echo "kdump: saving opalcore failed" + return 1 + fi + + ssh $_opts $_location mv $_path/opalcore-incomplete $_path/opalcore + echo "kdump: saving opalcore complete" + return 0 +} + +save_vmcore_dmesg_ssh() { + local _dmesg_collector=$1 + local _path=$2 + 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" + _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" + else + echo "kdump: saving vmcore-dmesg.txt failed" + fi +} + +fence_kdump_notify() +{ + if [ -n "$FENCE_KDUMP_NODES" ]; then + $FENCE_KDUMP_SEND $FENCE_KDUMP_ARGS $FENCE_KDUMP_NODES & + fi +} + +read_kdump_conf +fence_kdump_notify + +get_host_ip +if [ $? -ne 0 ]; then + echo "kdump: get_host_ip exited with non-zero status!" + exit 1 +fi + +if [ -z "$DUMP_INSTRUCTION" ]; then + add_dump_code "dump_fs $NEWROOT" +fi + +do_kdump_pre +if [ $? -ne 0 ]; then + echo "kdump: kdump_pre script exited with non-zero status!" + do_final_action +fi +make_trace_mem "kdump saving vmcore" '1:shortmem' '2+:mem' '3+:slab' +do_dump +DUMP_RETVAL=$? + +do_kdump_post $DUMP_RETVAL +if [ $? -ne 0 ]; then + echo "kdump: kdump_post script exited with non-zero status!" +fi + +if [ $DUMP_RETVAL -ne 0 ]; then + exit 1 +fi + +do_final_action diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh new file mode 100755 index 0000000..899e7ed --- /dev/null +++ b/dracut-module-setup.sh @@ -0,0 +1,846 @@ +#!/bin/bash + +. $dracutfunctions +. /lib/kdump/kdump-lib.sh + +if ! [[ -d "${initdir}/tmp" ]]; then + mkdir -p "${initdir}/tmp" +fi + +check() { + [[ $debug ]] && set -x + #kdumpctl sets this explicitly + if [ -z "$IN_KDUMP" ] || [ ! -f /etc/kdump.conf ] + then + return 1 + fi + return 0 +} + +depends() { + local _dep="base shutdown" + + is_squash_available() { + for kmodule in squashfs overlay loop; do + if [ -z "$KDUMP_KERNELVER" ]; then + modprobe --dry-run $kmodule &>/dev/null || return 1 + else + modprobe -S $KDUMP_KERNELVER --dry-run $kmodule &>/dev/null || return 1 + fi + done + } + + if is_squash_available && ! is_fadump_capable; then + _dep="$_dep squash" + else + dwarning "Required modules to build a squashed kdump image is missing!" + fi + + if [ -n "$( find /sys/devices -name drm )" ] || [ -d /sys/module/hyperv_fb ]; then + _dep="$_dep drm" + fi + + if is_generic_fence_kdump || is_pcs_fence_kdump; then + _dep="$_dep network" + fi + + echo $_dep + return 0 +} + +kdump_get_persistent_dev() { + local dev="${1//\"/}" + + case "$dev" in + UUID=*) + dev=`blkid -U "${dev#UUID=}"` + ;; + LABEL=*) + dev=`blkid -L "${dev#LABEL=}"` + ;; + esac + echo $(get_persistent_dev "$dev") +} + +kdump_is_bridge() { + [ -d /sys/class/net/"$1"/bridge ] +} + +kdump_is_bond() { + [ -d /sys/class/net/"$1"/bonding ] +} + +kdump_is_team() { + [ -f /usr/bin/teamnl ] && teamnl $1 ports &> /dev/null +} + +kdump_is_vlan() { + [ -f /proc/net/vlan/"$1" ] +} + +# $1: netdev name +source_ifcfg_file() { + local ifcfg_file + + ifcfg_file=$(get_ifcfg_filename $1) + if [ -f "${ifcfg_file}" ]; then + . ${ifcfg_file} + else + dwarning "The ifcfg file of $1 is not found!" + fi +} + +# $1: netdev name +kdump_setup_dns() { + local _nameserver _dns + local _dnsfile=${initdir}/etc/cmdline.d/42dns.conf + + source_ifcfg_file $1 + + [ -n "$DNS1" ] && echo "nameserver=$DNS1" > "$_dnsfile" + [ -n "$DNS2" ] && echo "nameserver=$DNS2" >> "$_dnsfile" + + while read content; + do + _nameserver=$(echo $content | grep ^nameserver) + [ -z "$_nameserver" ] && continue + + _dns=$(echo $_nameserver | cut -d' ' -f2) + [ -z "$_dns" ] && continue + + if [ ! -f $_dnsfile ] || [ ! $(cat $_dnsfile | grep -q $_dns) ]; then + echo "nameserver=$_dns" >> "$_dnsfile" + fi + done < "/etc/resolv.conf" +} + +#$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 + + _ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr\/.* /{print \$2}") + + if is_ipv6_address $_srcaddr; then + _ipv6_flag="-6" + fi + + if [ -n "$_ipaddr" ]; then + _gateway=$(ip $_ipv6_flag route list dev $_netdev | \ + awk '/^default /{print $3}' | head -n 1) + + if [ "x" != "x"$_ipv6_flag ]; then + # _ipaddr="2002::56ff:feb6:56d5/64", _netmask is the number after "/" + _netmask=${_ipaddr#*\/} + _srcaddr="[$_srcaddr]" + _gateway="[$_gateway]" + else + _netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2) + fi + echo -n "${_srcaddr}::${_gateway}:${_netmask}::" + fi + + /sbin/ip $_ipv6_flag route show | grep -v default |\ + grep ".*via.* $_netdev " | grep -v "^[[:space:]]*nexthop" |\ + while read _route; do + _target=`echo $_route | cut -d ' ' -f1` + _nexthop=`echo $_route | cut -d ' ' -f3` + if [ "x" != "x"$_ipv6_flag ]; then + _target="[$_target]" + _nexthop="[$_nexthop]" + fi + echo "rd.route=$_target:$_nexthop:$_netdev" + done >> ${initdir}/etc/cmdline.d/45route-static.conf + + kdump_handle_mulitpath_route $_netdev $_srcaddr +} + +kdump_handle_mulitpath_route() { + local _netdev="$1" _srcaddr="$2" _ipv6_flag + local _target _nexthop _route _weight _max_weight _rule + + if is_ipv6_address $_srcaddr; then + _ipv6_flag="-6" + fi + + while IFS="" read _route; do + if [[ "$_route" =~ [[:space:]]+nexthop ]]; then + _route=$(echo "$_route" | sed -e 's/^[[:space:]]*//') + # Parse multipath route, using previous _target + [[ "$_target" == 'default' ]] && continue + [[ "$_route" =~ .*via.*\ $_netdev ]] || continue + + _weight=`echo "$_route" | cut -d ' ' -f7` + if [[ "$_weight" -gt "$_max_weight" ]]; then + _nexthop=`echo "$_route" | cut -d ' ' -f3` + _max_weight=$_weight + if [ "x" != "x"$_ipv6_flag ]; then + _rule="rd.route=[$_target]:[$_nexthop]:$_netdev" + else + _rule="rd.route=$_target:$_nexthop:$_netdev" + fi + fi + else + [[ -n "$_rule" ]] && echo "$_rule" + _target=`echo "$_route" | cut -d ' ' -f1` + _rule="" _max_weight=0 _weight=0 + fi + done >> ${initdir}/etc/cmdline.d/45route-static.conf\ + <<< "$(/sbin/ip $_ipv6_flag route show)" + + [[ -n $_rule ]] && echo $_rule >> ${initdir}/etc/cmdline.d/45route-static.conf +} + +kdump_get_mac_addr() { + cat /sys/class/net/$1/address +} + +#Bonding or team master modifies the mac address +#of its slaves, we should use perm address +kdump_get_perm_addr() { + local addr=$(ethtool -P $1 | sed -e 's/Permanent address: //') + if [ -z "$addr" ] || [ "$addr" = "00:00:00:00:00:00" ] + then + derror "Can't get the permanent address of $1" + else + echo "$addr" + fi +} + +# Prefix kernel assigned names with "kdump-". EX: eth0 -> kdump-eth0 +# Because kernel assigned names are not persistent between 1st and 2nd +# kernel. We could probably end up with eth0 being eth1, eth0 being +# eth1, and naming conflict happens. +kdump_setup_ifname() { + local _ifname + + # If ifname already has 'kdump-' prefix, we must be switching from + # fadump to kdump. Skip prefixing 'kdump-' in this case as adding + # another prefix may truncate the ifname. Since an ifname with + # 'kdump-' is already persistent, this should be fine. + if [[ $1 =~ eth* ]] && [[ ! $1 =~ ^kdump-* ]]; then + _ifname="kdump-$1" + else + _ifname="$1" + fi + + echo "$_ifname" +} + +kdump_setup_bridge() { + local _netdev=$1 + local _brif _dev _mac _kdumpdev + for _dev in /sys/class/net/$_netdev/brif/* ; do + [[ -e "$_dev" ]] || break + _kdumpdev=$_dev + if kdump_is_bond "$_dev"; then + kdump_setup_bond "$_dev" + elif kdump_is_team "$_dev"; then + kdump_setup_team "$_dev" + elif kdump_is_vlan "$_dev"; then + kdump_setup_vlan "$_dev" + else + _mac=$(kdump_get_mac_addr $_dev) + _kdumpdev=$(kdump_setup_ifname $_dev) + echo -n " ifname=$_kdumpdev:$_mac" >> ${initdir}/etc/cmdline.d/41bridge.conf + fi + _brif+="$_kdumpdev," + done + echo " bridge=$_netdev:$(echo $_brif | sed -e 's/,$//')" >> ${initdir}/etc/cmdline.d/41bridge.conf +} + +kdump_setup_bond() { + local _netdev=$1 + local _dev _mac _slaves _kdumpdev + for _dev in `cat /sys/class/net/$_netdev/bonding/slaves`; do + _mac=$(kdump_get_perm_addr $_dev) + _kdumpdev=$(kdump_setup_ifname $_dev) + echo -n " ifname=$_kdumpdev:$_mac" >> ${initdir}/etc/cmdline.d/42bond.conf + _slaves+="$_kdumpdev," + done + echo -n " bond=$_netdev:$(echo $_slaves | sed 's/,$//')" >> ${initdir}/etc/cmdline.d/42bond.conf + # Get bond options specified in ifcfg + + source_ifcfg_file $_netdev + + bondoptions=":$(echo $BONDING_OPTS | xargs echo | tr " " ",")" + echo "$bondoptions" >> ${initdir}/etc/cmdline.d/42bond.conf +} + +kdump_setup_team() { + local _netdev=$1 + local _dev _mac _slaves _kdumpdev + for _dev in `teamnl $_netdev ports | awk -F':' '{print $2}'`; do + _mac=$(kdump_get_perm_addr $_dev) + _kdumpdev=$(kdump_setup_ifname $_dev) + echo -n " ifname=$_kdumpdev:$_mac" >> ${initdir}/etc/cmdline.d/44team.conf + _slaves+="$_kdumpdev," + done + echo " team=$_netdev:$(echo $_slaves | sed -e 's/,$//')" >> ${initdir}/etc/cmdline.d/44team.conf + #Buggy version teamdctl outputs to stderr! + #Try to use the latest version of teamd. + teamdctl "$_netdev" config dump > ${initdir}/tmp/$$-$_netdev.conf + if [ $? -ne 0 ] + then + derror "teamdctl failed." + exit 1 + fi + inst_dir /etc/teamd + inst_simple ${initdir}/tmp/$$-$_netdev.conf "/etc/teamd/$_netdev.conf" + rm -f ${initdir}/tmp/$$-$_netdev.conf +} + +kdump_setup_vlan() { + local _netdev=$1 + local _phydev="$(awk '/^Device:/{print $2}' /proc/net/vlan/"$_netdev")" + local _netmac="$(kdump_get_mac_addr $_phydev)" + local _kdumpdev + + #Just support vlan over bond, it is not easy + #to support all other complex setup + 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 + else + _kdumpdev="$(kdump_setup_ifname $_phydev)" + echo " vlan=$(kdump_setup_ifname $_netdev):$_kdumpdev ifname=$_kdumpdev:$_netmac" > ${initdir}/etc/cmdline.d/43vlan.conf + fi +} + +# setup s390 znet cmdline +# $1: netdev name +kdump_setup_znet() { + local _options="" + + source_ifcfg_file $1 + + for i in $OPTIONS; do + _options=${_options},$i + done + echo rd.znet=${NETTYPE},${SUBCHANNELS}${_options} > ${initdir}/etc/cmdline.d/30znet.conf +} + +kdump_get_ip_route() +{ + local _route=$(/sbin/ip -o route get to $1 2>&1) + [ $? != 0 ] && die "Bad kdump network destination: $1" + echo $_route +} + +kdump_get_ip_route_field() +{ + if `echo $1 | grep -q $2`; then + echo ${1##*$2} | cut -d ' ' -f1 + fi +} + +kdump_get_remote_ip() +{ + local _remote=$(get_remote_host $1) _remote_temp + if is_hostname $_remote; then + _remote_temp=`getent ahosts $_remote | grep -v : | head -n 1` + if [ -z "$_remote_temp" ]; then + _remote_temp=`getent ahosts $_remote | head -n 1` + fi + _remote=`echo $_remote_temp | cut -d' ' -f1` + fi + echo $_remote +} + +# Setup dracut to bring up network interface that enable +# initramfs accessing giving destination +# $1: destination host +kdump_install_net() { + local _destaddr _srcaddr _route _netdev + local _static _proto _ip_conf _ip_opts _ifname_opts + + _destaddr=$(kdump_get_remote_ip $1) + _route=$(kdump_get_ip_route $_destaddr) + _srcaddr=$(kdump_get_ip_route_field "$_route" "src") + _netdev=$(kdump_get_ip_route_field "$_route" "dev") + _netmac=$(kdump_get_mac_addr $_netdev) + + if [ "$(uname -m)" = "s390x" ]; then + kdump_setup_znet $_netdev + fi + + _static=$(kdump_static_ip $_netdev $_srcaddr) + if [ -n "$_static" ]; then + _proto=none + elif is_ipv6_address $_srcaddr; then + _proto=either6 + else + _proto=dhcp + fi + + _ip_conf="${initdir}/etc/cmdline.d/40ip.conf" + _ip_opts=" ip=${_static}$(kdump_setup_ifname $_netdev):${_proto}" + + # dracut doesn't allow duplicated configuration for same NIC, even they're exactly the same. + # so we have to avoid adding duplicates + # We should also check /proc/cmdline for existing ip=xx arg. + # For example, iscsi boot will specify ip=xxx arg in cmdline. + if [ ! -f $_ip_conf ] || ! grep -q $_ip_opts $_ip_conf &&\ + ! grep -q "ip=[^[:space:]]*$_netdev" /proc/cmdline; then + echo "$_ip_opts" >> $_ip_conf + fi + + if kdump_is_bridge "$_netdev"; then + kdump_setup_bridge "$_netdev" + elif kdump_is_bond "$_netdev"; then + kdump_setup_bond "$_netdev" + elif kdump_is_team "$_netdev"; then + kdump_setup_team "$_netdev" + elif kdump_is_vlan "$_netdev"; then + kdump_setup_vlan "$_netdev" + else + _ifname_opts=" ifname=$(kdump_setup_ifname $_netdev):$_netmac" + echo "$_ifname_opts" >> $_ip_conf + fi + + kdump_setup_dns "$_netdev" + + # Save netdev used for kdump as cmdline + # Whoever calling kdump_install_net() is setting up the default gateway, + # ie. bootdev/kdumpnic. So don't override the setting if calling + # kdump_install_net() for another time. For example, after setting eth0 as + # the default gate way for network dump, eth1 in the fence kdump path will + # call kdump_install_net again and we don't want eth1 to be the default + # gateway. + if [ ! -f ${initdir}/etc/cmdline.d/60kdumpnic.conf ] && + [ ! -f ${initdir}/etc/cmdline.d/70bootdev.conf ]; then + echo "kdumpnic=$(kdump_setup_ifname $_netdev)" > ${initdir}/etc/cmdline.d/60kdumpnic.conf + echo "bootdev=$(kdump_setup_ifname $_netdev)" > ${initdir}/etc/cmdline.d/70bootdev.conf + fi +} + +default_dump_target_install_conf() +{ + local _target _fstype + local _mntpoint _save_path + + is_user_configured_dump_target && return + + _save_path=$(get_bind_mount_source $(get_save_path)) + _target=$(get_target_from_path $_save_path) + _mntpoint=$(get_mntpoint_from_target $_target) + + _fstype=$(get_fs_type_from_target $_target) + if is_fs_type_nfs $_fstype; then + kdump_install_net "$_target" + _fstype="nfs" + else + _target=$(kdump_get_persistent_dev $_target) + fi + + echo "$_fstype $_target" >> ${initdir}/tmp/$$-kdump.conf + + # don't touch the path under root mount + if [ "$_mntpoint" != "/" ]; then + _save_path=${_save_path##"$_mntpoint"} + fi + + #erase the old path line, then insert the parsed path + sed -i "/^path/d" ${initdir}/tmp/$$-kdump.conf + echo "path $_save_path" >> ${initdir}/tmp/$$-kdump.conf +} + +#install kdump.conf and what user specifies in kdump.conf +kdump_install_conf() { + local _opt _val _pdev + (read_strip_comments /etc/kdump.conf) > ${initdir}/tmp/$$-kdump.conf + + while read _opt _val; + do + # remove inline comments after the end of a directive. + case "$_opt" in + raw) + _pdev=$(persistent_policy="by-id" kdump_get_persistent_dev $_val) + sed -i -e "s#^${_opt}[[:space:]]\+$_val#$_opt $_pdev#" ${initdir}/tmp/$$-kdump.conf + ;; + ext[234]|xfs|btrfs|minix) + _pdev=$(kdump_get_persistent_dev $_val) + sed -i -e "s#^${_opt}[[:space:]]\+$_val#$_opt $_pdev#" ${initdir}/tmp/$$-kdump.conf + ;; + ssh|nfs) + kdump_install_net "$_val" + ;; + dracut_args) + if [[ $(get_dracut_args_fstype "$_val") = nfs* ]] ; then + kdump_install_net "$(get_dracut_args_target "$_val")" + fi + ;; + kdump_pre|kdump_post|extra_bins) + dracut_install $_val + ;; + core_collector) + dracut_install "${_val%%[[:blank:]]*}" + ;; + esac + done <<< "$(read_strip_comments /etc/kdump.conf)" + + default_dump_target_install_conf + + kdump_configure_fence_kdump "${initdir}/tmp/$$-kdump.conf" + inst "${initdir}/tmp/$$-kdump.conf" "/etc/kdump.conf" + rm -f ${initdir}/tmp/$$-kdump.conf +} + +# Remove user custom configurations sysctl.conf & sysctl.d/* +# and apply some optimization for kdump +overwrite_sysctl_conf() { + # As custom configurations like vm.min_free_kbytes can lead + # to OOM issues in kdump kernel, avoid them + rm -f "${initdir}/etc/sysctl.conf" + rm -rf "${initdir}/etc/sysctl.d" + rm -rf "${initdir}/run/sysctl.d" + rm -rf "${initdir}/usr/lib/sysctl.d" + + mkdir -p "${initdir}/etc/sysctl.d" + echo "vm.zone_reclaim_mode = 3" > "${initdir}/etc/sysctl.d/99-zone-reclaim.conf" +} + +kdump_iscsi_get_rec_val() { + + local result + + # The open-iscsi 742 release changed to using flat files in + # /var/lib/iscsi. + + result=$(/sbin/iscsiadm --show -m session -r ${1} | grep "^${2} = ") + result=${result##* = } + echo $result +} + +kdump_get_iscsi_initiator() { + local _initiator + local initiator_conf="/etc/iscsi/initiatorname.iscsi" + + [ -f "$initiator_conf" ] || return 1 + + while read _initiator; do + [ -z "${_initiator%%#*}" ] && continue # Skip comment lines + + case $_initiator in + InitiatorName=*) + initiator=${_initiator#InitiatorName=} + echo "rd.iscsi.initiator=${initiator}" + return 0;; + *) ;; + esac + done < ${initiator_conf} + + return 1 +} + +# Figure out iBFT session according to session type +is_ibft() { + [ "$(kdump_iscsi_get_rec_val $1 "node.discovery_type")" = fw ] +} + +kdump_setup_iscsi_device() { + local path=$1 + local tgt_name; local tgt_ipaddr; + local username; local password; local userpwd_str; + local username_in; local password_in; local userpwd_in_str; + local netroot_str ; local initiator_str; + local netroot_conf="${initdir}/etc/cmdline.d/50iscsi.conf" + local initiator_conf="/etc/iscsi/initiatorname.iscsi" + + dinfo "Found iscsi component $1" + + # Check once before getting explicit values, so we can bail out early, + # e.g. in case of pure-hardware(all-offload) iscsi. + if ! /sbin/iscsiadm -m session -r ${path} &>/dev/null ; then + return 1 + fi + + if is_ibft ${path}; then + return + fi + + # Remove software iscsi cmdline generated by 95iscsi, + # and let kdump regenerate here. + rm -f ${initdir}/etc/cmdline.d/95iscsi.conf + + tgt_name=$(kdump_iscsi_get_rec_val ${path} "node.name") + tgt_ipaddr=$(kdump_iscsi_get_rec_val ${path} "node.conn\[0\].address") + + # get and set username and password details + username=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.username") + [ "$username" == "<empty>" ] && username="" + password=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.password") + [ "$password" == "<empty>" ] && password="" + username_in=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.username_in") + [ -n "$username" ] && userpwd_str="$username:$password" + + # get and set incoming username and password details + [ "$username_in" == "<empty>" ] && username_in="" + password_in=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.password_in") + [ "$password_in" == "<empty>" ] && password_in="" + + [ -n "$username_in" ] && userpwd_in_str=":$username_in:$password_in" + + kdump_install_net "$tgt_ipaddr" + + # prepare netroot= command line + # FIXME: Do we need to parse and set other parameters like protocol, port + # iscsi_iface_name, netdev_name, LUN etc. + + if is_ipv6_address $tgt_ipaddr; then + tgt_ipaddr="[$tgt_ipaddr]" + fi + netroot_str="netroot=iscsi:${userpwd_str}${userpwd_in_str}@$tgt_ipaddr::::$tgt_name" + + [[ -f $netroot_conf ]] || touch $netroot_conf + + # If netroot target does not exist already, append. + if ! grep -q $netroot_str $netroot_conf; then + echo $netroot_str >> $netroot_conf + dinfo "Appended $netroot_str to $netroot_conf" + fi + + # Setup initator + initiator_str=$(kdump_get_iscsi_initiator) + [ $? -ne "0" ] && derror "Failed to get initiator name" && return 1 + + # If initiator details do not exist already, append. + if ! grep -q "$initiator_str" $netroot_conf; then + echo "$initiator_str" >> $netroot_conf + dinfo "Appended "$initiator_str" to $netroot_conf" + fi +} + +kdump_check_iscsi_targets () { + # If our prerequisites are not met, fail anyways. + type -P iscsistart >/dev/null || return 1 + + kdump_check_setup_iscsi() ( + local _dev + _dev=$1 + + [[ -L /sys/dev/block/$_dev ]] || return + cd "$(readlink -f /sys/dev/block/$_dev)" + until [[ -d sys || -d iscsi_session ]]; do + cd .. + done + [[ -d iscsi_session ]] && kdump_setup_iscsi_device "$PWD" + ) + + [[ $hostonly ]] || [[ $mount_needs ]] && { + for_each_host_dev_and_slaves_all kdump_check_setup_iscsi + } +} + +# hostname -a is deprecated, do it by ourself +get_alias() { + local ips + local entries + local alias_set + + ips=$(hostname -I) + for ip in $ips + do + # in /etc/hosts, alias can come at the 2nd column + entries=$(grep $ip /etc/hosts | awk '{ $1=""; print $0 }') + if [ $? -eq 0 ]; then + alias_set="$alias_set $entries" + fi + done + + echo $alias_set +} + +is_localhost() { + local hostnames=$(hostname -A) + local shortnames=$(hostname -A -s) + local aliasname=$(get_alias) + local nodename=$1 + + hostnames="$hostnames $shortnames $aliasname" + + for name in ${hostnames}; do + if [ "$name" == "$nodename" ]; then + return 0 + fi + done + return 1 +} + +# retrieves fence_kdump nodes from Pacemaker cluster configuration +get_pcs_fence_kdump_nodes() { + local nodes + + # get cluster nodes from cluster cib, get interface and ip address + nodelist=`pcs cluster cib | xmllint --xpath "/cib/status/node_state/@uname" -` + + # nodelist is formed as 'uname="node1" uname="node2" ... uname="nodeX"' + # we need to convert each to node1, node2 ... nodeX in each iteration + for node in ${nodelist}; do + # convert $node from 'uname="nodeX"' to 'nodeX' + eval $node + nodename=$uname + # Skip its own node name + if is_localhost $nodename; then + continue + fi + nodes="$nodes $nodename" + done + + echo $nodes +} + +# retrieves fence_kdump args from config file +get_pcs_fence_kdump_args() { + if [ -f $FENCE_KDUMP_CONFIG_FILE ]; then + . $FENCE_KDUMP_CONFIG_FILE + echo $FENCE_KDUMP_OPTS + fi +} + +get_generic_fence_kdump_nodes() { + local filtered + local nodes + + nodes=$(get_option_value "fence_kdump_nodes") + for node in ${nodes}; do + # Skip its own node name + if is_localhost $node; then + continue + fi + filtered="$filtered $node" + done + echo $filtered +} + +# setup fence_kdump in cluster +# setup proper network and install needed files +kdump_configure_fence_kdump () { + local kdump_cfg_file=$1 + local nodes + local args + + if is_generic_fence_kdump; then + nodes=$(get_generic_fence_kdump_nodes) + + elif is_pcs_fence_kdump; then + nodes=$(get_pcs_fence_kdump_nodes) + + # set appropriate options in kdump.conf + echo "fence_kdump_nodes $nodes" >> ${kdump_cfg_file} + + args=$(get_pcs_fence_kdump_args) + if [ -n "$args" ]; then + echo "fence_kdump_args $args" >> ${kdump_cfg_file} + fi + + else + # fence_kdump not configured + return 1 + fi + + # setup network for each node + for node in ${nodes}; do + kdump_install_net $node + done + + dracut_install /etc/hosts + dracut_install /etc/nsswitch.conf + dracut_install $FENCE_KDUMP_SEND +} + +# Install a random seed used to feed /dev/urandom +# By the time kdump service starts, /dev/uramdom is already fed by systemd +kdump_install_random_seed() { + local poolsize=`cat /proc/sys/kernel/random/poolsize` + + if [ ! -d ${initdir}/var/lib/ ]; then + mkdir -p ${initdir}/var/lib/ + fi + + dd if=/dev/urandom of=${initdir}/var/lib/random-seed \ + bs=$poolsize count=1 2> /dev/null +} + +install() { + kdump_install_conf + overwrite_sysctl_conf + + if is_ssh_dump_target; then + kdump_install_random_seed + fi + dracut_install -o /etc/adjtime /etc/localtime + inst "$moddir/monitor_dd_progress" "/kdumpscripts/monitor_dd_progress" + chmod +x ${initdir}/kdumpscripts/monitor_dd_progress + inst "/bin/dd" "/bin/dd" + inst "/bin/tail" "/bin/tail" + inst "/bin/date" "/bin/date" + inst "/bin/sync" "/bin/sync" + inst "/bin/cut" "/bin/cut" + inst "/bin/head" "/bin/head" + inst "/bin/awk" "/bin/awk" + inst "/bin/sed" "/bin/sed" + inst "/sbin/makedumpfile" "/sbin/makedumpfile" + inst "/sbin/vmcore-dmesg" "/sbin/vmcore-dmesg" + inst "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh" + inst "/lib/kdump/kdump-lib-initramfs.sh" "/lib/kdump-lib-initramfs.sh" + inst "$moddir/kdump.sh" "/usr/bin/kdump.sh" + inst "$moddir/kdump-capture.service" "$systemdsystemunitdir/kdump-capture.service" + mkdir -p "$initdir/$systemdsystemunitdir/initrd.target.wants" + ln_r "$systemdsystemunitdir/kdump-capture.service" "$systemdsystemunitdir/initrd.target.wants/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 + cp "$moddir/kdump-emergency.service" "$initdir/$systemdsystemunitdir/emergency.service" + cp "$moddir/kdump-emergency.target" "$initdir/$systemdsystemunitdir/emergency.target" + # Also redirect dracut-emergency to kdump error handler + ln_r "$systemdsystemunitdir/emergency.service" "$systemdsystemunitdir/dracut-emergency.service" + + # Check for all the devices and if any device is iscsi, bring up iscsi + # target. Ideally all this should be pushed into dracut iscsi module + # at some point of time. + kdump_check_iscsi_targets + + # nfs/ssh dump will need to get host ip in second kernel and need to call 'ip' tool, see get_host_ip for more detail + # also need to let initqueue wait for target to become ready + if is_nfs_dump_target || is_ssh_dump_target; then + inst_hook initqueue/finished 01 $moddir/kdump-wait-for-target.sh + inst "ip" + fi + + # 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 + # it unconditionally here, if "/etc/lvm/lvm.conf" doesn't exist, it + # actually does nothing. + sed -i -e \ + '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 + + # Forward logs to console directly, this avoids unneccessary memory + # consumption and make console output more useful. + # Only do so for non fadump image. + if ! is_fadump_capable; then + 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 + fi +} diff --git a/dracut-monitor_dd_progress b/dracut-monitor_dd_progress new file mode 100644 index 0000000..e139d33 --- /dev/null +++ b/dracut-monitor_dd_progress @@ -0,0 +1,28 @@ +#!/bin/sh + +SRC_FILE_MB=$1 + +while true +do + DD_PID=`pidof dd` + if [ -n "$DD_PID" ]; then + break + fi +done + +while true +do + sleep 5 + if [ ! -d /proc/$DD_PID ]; then + break + fi + + kill -s USR1 $DD_PID + CURRENT_SIZE=`tail -n 1 /tmp/dd_progress_file | sed "s/[^0-9].*//g"` + [ -n "$CURRENT_SIZE" ] && { + CURRENT_MB=$(($CURRENT_SIZE / 1048576)) + echo -e "Copied $CURRENT_MB MB / $SRC_FILE_MB MB\r" + } +done + +rm -f /tmp/dd_progress_file diff --git a/early-kdump-howto.txt b/early-kdump-howto.txt new file mode 100644 index 0000000..68b23c7 --- /dev/null +++ b/early-kdump-howto.txt @@ -0,0 +1,95 @@ +Early Kdump HOWTO + +Introduction +------------ + +Early kdump is a mechanism to make kdump operational earlier than normal kdump +service. The kdump service starts early enough for general crash cases, but +there are some cases where it has no chance to make kdump operational in boot +sequence, such as detecting devices and starting early services. If you hit +such a case, early kdump may allow you to get more information of it. + +Early kdump is implemented as a dracut module. It adds a kernel (vmlinuz) and +initramfs for kdump to your system's initramfs in order to load them as early +as possible. After that, if you provide "rd.earlykdump" in kernel command line, +then in the initramfs, early kdump will load those files like the normal kdump +service. This is disabled by default. + +For the normal kdump service, it can check whether the early kdump has loaded +the crash kernel and initramfs. It has no conflict with the early kdump. + +How to configure early kdump +---------------------------- + +We assume if you're reading this document, you should already have kexec-tools +installed. + +You can rebuild the initramfs with earlykdump support with below steps: + +1. start kdump service to make sure kdump initramfs is created. + + # systemctl start kdump + + NOTE: If a crash occurs during boot process, early kdump captures a vmcore + and reboot the system by default, so the system might go into crash loop. + You can avoid such a crash loop by adding the following settings, which + power off the system after dump capturing, to kdump.conf in advance: + + final_action poweroff + failure_action poweroff + + For the failure_action, you can choose anything other than "reboot". + +2. rebuild system initramfs with earlykdump support. + + # dracut --force --add earlykdump + + NOTE: Recommend to backup the original system initramfs before performing + this step to put it back if something happens during boot-up. + +3. add rd.earlykdump in grub kernel command line. + +After making said changes, reboot your system to take effect. Of course, if you +want to disable early kdump, you can simply remove "rd.earlykdump" from kernel +boot parameters in grub, and reboot system like above. + +Once the boot is completed, you can check the status of the early kdump support +on the command prompt: + + # journalctl -b | grep early-kdump + +Then, you will see some useful logs, for example: + +- if early kdump is successful. + +Mar 09 09:57:56 localhost dracut-cmdline[190]: early-kdump is enabled. +Mar 09 09:57:56 localhost dracut-cmdline[190]: kexec: loaded early-kdump kernel + +- if early kdump is disabled. + +Mar 09 10:02:47 localhost dracut-cmdline[189]: early-kdump is disabled. + +Notes +----- + +- The size of early kdump initramfs will be large because it includes vmlinuz + and kdump initramfs. + +- Early kdump inherits the settings of normal kdump, so any changes that + caused normal kdump rebuilding also require rebuilding the system initramfs + to make sure that the changes take effect for early kdump. Therefore, after + the rebuilding of kdump initramfs is completed, provide a prompt message to + tell the fact. + +- If you install an updated kernel and reboot the system with it, the early + kdump will be disabled by default. To enable it with the new kernel, you + need to take the above steps again. + +Limitation +---------- + +- At present, early kdump doesn't support fadump. + +- Early kdump loads a crash kernel and initramfs at the beginning of the + process in system's initramfs, so a crash at earlier than that (e.g. in + kernel initialization) cannot be captured even with the early kdump. diff --git a/kdump-dep-generator.sh b/kdump-dep-generator.sh new file mode 100644 index 0000000..b6fab2d --- /dev/null +++ b/kdump-dep-generator.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# More details about systemd generator: +# http://www.freedesktop.org/wiki/Software/systemd/Generators/ + +. /usr/lib/kdump/kdump-lib.sh + +# If invokded with no arguments for testing purpose, output to /tmp to +# avoid overriding the existing. +dest_dir="/tmp" + +if [ -n "$1" ]; then + dest_dir=$1 +fi + +systemd_dir=/usr/lib/systemd/system +kdump_wants=$dest_dir/kdump.service.wants + +if is_ssh_dump_target; then + mkdir -p $kdump_wants + ln -sf $systemd_dir/network-online.target $kdump_wants/ +fi diff --git a/kdump-in-cluster-environment.txt b/kdump-in-cluster-environment.txt new file mode 100644 index 0000000..de1eb5e --- /dev/null +++ b/kdump-in-cluster-environment.txt @@ -0,0 +1,91 @@ +Kdump-in-cluster-environment HOWTO + +Introduction + +Kdump is a kexec based crash dumping mechansim for Linux. This docuement +illustrate how to configure kdump in cluster environment to allow the kdump +crash recovery service complete without being preempted by traditional power +fencing methods. + +Overview + +Kexec/Kdump + +Details about Kexec/Kdump are available in Kexec-Kdump-howto file and will not +be described here. + +fence_kdump + +fence_kdump is an I/O fencing agent to be used with the kdump crash recovery +service. When the fence_kdump agent is invoked, it will listen for a message +from the failed node that acknowledges that the failed node is executing the +kdump crash kernel. Note that fence_kdump is not a replacement for traditional +fencing methods. The fence_kdump agent can only detect that a node has entered +the kdump crash recovery service. This allows the kdump crash recovery service +complete without being preempted by traditional power fencing methods. + +fence_kdump_send + +fence_kdump_send is a utility used to send messages that acknowledge that the +node itself has entered the kdump crash recovery service. The fence_kdump_send +utility is typically run in the kdump kernel after a cluster node has +encountered a kernel panic. Once the cluster node has entered the kdump crash +recovery service, fence_kdump_send will periodically send messages to all +cluster nodes. When the fence_kdump agent receives a valid message from the +failed nodes, fencing is complete. + +How to configure Pacemaker cluster environment: + +If we want to use kdump in Pacemaker cluster environment, fence-agents-kdump +should be installed in every nodes in the cluster. You can achieve this via +the following command: + + # yum install -y fence-agents-kdump + +Next is to add kdump_fence to the cluster. Assuming that the cluster consists +of three nodes, they are node1, node2 and node3, and use Pacemaker to perform +resource management and pcs as cli configuration tool. + +With pcs it is easy to add a stonith resource to the cluster. For example, add +a stonith resource named mykdumpfence with fence type of fence_kdump via the +following commands: + + # pcs stonith create mykdumpfence fence_kdump \ + pcmk_host_check=static-list pcmk_host_list="node1 node2 node3" + # pcs stonith update mykdumpfence pcmk_monitor_action=metadata --force + # pcs stonith update mykdumpfence pcmk_status_action=metadata --force + # pcs stonith update mykdumpfence pcmk_reboot_action=off --force + +Then enable stonith + # pcs property set stonith-enabled=true + +How to configure kdump: + +Actually there are two ways how to configure fence_kdump support: + +1) Pacemaker based clusters + If you have successfully configured fence_kdump in Pacemaker, there is + no need to add some special configuration in kdump. So please refer to + Kexec-Kdump-howto file for more information. + +2) Generic clusters + For other types of clusters there are two configuration options in + kdump.conf which enables fence_kdump support: + + fence_kdump_nodes <node(s)> + Contains list of cluster node(s) separated by space to send + fence_kdump notification to (this option is mandatory to enable + fence_kdump) + + fence_kdump_args <arg(s)> + Command line arguments for fence_kdump_send (it can contain + all valid arguments except hosts to send notification to) + + These options will most probably be configured by your cluster software, + so please refer to your cluster documentation how to enable fence_kdump + support. + +Please be aware that these two ways cannot be combined and 2) has precedence +over 1). It means that if fence_kdump is configured using fence_kdump_nodes +and fence_kdump_args options in kdump.conf, Pacemaker configuration is not +used even if it exists. diff --git a/kdump-lib-initramfs.sh b/kdump-lib-initramfs.sh new file mode 100755 index 0000000..03949ea --- /dev/null +++ b/kdump-lib-initramfs.sh @@ -0,0 +1,277 @@ +# These variables and functions are useful in 2nd kernel + +. /lib/kdump-lib.sh + +KDUMP_PATH="/var/crash" +CORE_COLLECTOR="" +DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 1 -d 31" +DMESG_COLLECTOR="/sbin/vmcore-dmesg" +FAILURE_ACTION="systemctl reboot -f" +DATEDIR=`date +%Y-%m-%d-%T` +HOST_IP='127.0.0.1' +DUMP_INSTRUCTION="" +SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" +KDUMP_SCRIPT_DIR="/kdumpscripts" +DD_BLKSIZE=512 +FINAL_ACTION="systemctl reboot -f" +KDUMP_CONF="/etc/kdump.conf" +KDUMP_PRE="" +KDUMP_POST="" +NEWROOT="/sysroot" +OPALCORE="/sys/firmware/opal/mpipl/core" + +get_kdump_confs() +{ + local config_opt config_val + + while read config_opt config_val; + do + # remove inline comments after the end of a directive. + case "$config_opt" in + path) + KDUMP_PATH="$config_val" + ;; + core_collector) + [ -n "$config_val" ] && CORE_COLLECTOR="$config_val" + ;; + sshkey) + if [ -f "$config_val" ]; then + SSH_KEY_LOCATION=$config_val + fi + ;; + kdump_pre) + KDUMP_PRE="$config_val" + ;; + kdump_post) + KDUMP_POST="$config_val" + ;; + fence_kdump_args) + FENCE_KDUMP_ARGS="$config_val" + ;; + fence_kdump_nodes) + FENCE_KDUMP_NODES="$config_val" + ;; + failure_action|default) + case $config_val in + shell) + FAILURE_ACTION="kdump_emergency_shell" + ;; + reboot) + FAILURE_ACTION="systemctl reboot -f && exit" + ;; + halt) + FAILURE_ACTION="halt && exit" + ;; + poweroff) + FAILURE_ACTION="systemctl poweroff -f && exit" + ;; + dump_to_rootfs) + FAILURE_ACTION="dump_to_rootfs" + ;; + esac + ;; + final_action) + case $config_val in + reboot) + FINAL_ACTION="systemctl reboot -f" + ;; + halt) + FINAL_ACTION="halt" + ;; + poweroff) + FINAL_ACTION="systemctl poweroff -f" + ;; + esac + ;; + esac + done <<< "$(read_strip_comments $KDUMP_CONF)" + + if [ -z "$CORE_COLLECTOR" ]; then + CORE_COLLECTOR="$DEFAULT_CORE_COLLECTOR" + if is_ssh_dump_target || is_raw_dump_target; then + CORE_COLLECTOR="$CORE_COLLECTOR -F" + fi + fi +} + +# dump_fs <mount point| device> +dump_fs() +{ + local _do_umount="" + local _dev=$(findmnt -k -f -n -r -o SOURCE $1) + local _mp=$(findmnt -k -f -n -r -o TARGET $1) + local _op=$(findmnt -k -f -n -r -o OPTIONS $1) + + if [ -z "$_mp" ]; then + _dev=$(findmnt -s -f -n -r -o SOURCE $1) + _mp=$(findmnt -s -f -n -r -o TARGET $1) + _op=$(findmnt -s -f -n -r -o OPTIONS $1) + + if [ -n "$_dev" ] && [ -n "$_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 + _do_umount=1 + else + echo "kdump: error: Dump target $_dev is not usable" + fi + else + echo "kdump: dump target is $_dev" + 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/" + + # Only remount to read-write mode if the dump target is mounted read-only. + if [[ "$_op" = "ro"* ]]; then + echo "kdump: Mounting Dump target $_dev in rw mode." + mount -o remount,rw $_dev $_mp || return 1 + fi + + mkdir -p $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR || return 1 + + 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 + + echo "kdump: saving vmcore complete" + + if [ $_do_umount ]; then + umount $_mp || echo "kdump: warn: failed to umount target" + fi + + # improper kernel cmdline can cause the failure of echo, we can ignore this kind of failure + return 0 +} + +save_vmcore_dmesg_fs() { + local _dmesg_collector=$1 + local _path=$2 + + echo "kdump: saving vmcore-dmesg.txt" + $_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 400 ${_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" + else + echo "kdump: saving vmcore-dmesg.txt failed" + fi +} + +save_opalcore_fs() { + local _path=$1 + + if [ ! -f $OPALCORE ]; then + # Check if we are on an old kernel that uses a different path + if [ -f /sys/firmware/opal/core ]; then + OPALCORE="/sys/firmware/opal/core" + else + return 0 + fi + fi + + echo "kdump: saving opalcore" + cp $OPALCORE ${_path}/opalcore + if [ $? -ne 0 ]; then + echo "kdump: saving opalcore failed" + return 1 + fi + + sync + echo "kdump: saving opalcore complete" + return 0 +} + +dump_to_rootfs() +{ + + echo "Kdump: trying to bring up rootfs device" + systemctl start dracut-initqueue + echo "Kdump: waiting for rootfs mount, will timeout after 90 seconds" + systemctl start sysroot.mount + + dump_fs $NEWROOT +} + +kdump_emergency_shell() +{ + echo "PS1=\"kdump:\\\${PWD}# \"" >/etc/profile + /bin/dracut-emergency + rm -f /etc/profile +} + +do_failure_action() +{ + echo "Kdump: Executing failure action $FAILURE_ACTION" + eval $FAILURE_ACTION +} + +do_final_action() +{ + eval $FINAL_ACTION +} + +get_host_ip() +{ + local _host + if is_nfs_dump_target || is_ssh_dump_target + then + kdumpnic=$(getarg kdumpnic=) + [ -z "$kdumpnic" ] && echo "kdump: failed to get kdumpnic!" && return 1 + _host=`ip addr show dev $kdumpnic|grep '[ ]*inet'` + [ $? -ne 0 ] && echo "kdump: 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 + HOST_IP=$_host + fi + return 0 +} + +read_kdump_conf() +{ + if [ ! -f "$KDUMP_CONF" ]; then + echo "kdump: $KDUMP_CONF not found" + return + fi + + get_kdump_confs + + # rescan for add code for dump target + while read config_opt config_val; + do + # remove inline comments after the end of a directive. + case "$config_opt" in + dracut_args) + config_val=$(get_dracut_args_target "$config_val") + [ -n "$config_val" ] && add_dump_code "dump_fs $config_val" + ;; + ext[234]|xfs|btrfs|minix|nfs) + add_dump_code "dump_fs $config_val" + ;; + raw) + add_dump_code "dump_raw $config_val" + ;; + ssh) + add_dump_code "dump_ssh $SSH_KEY_LOCATION $config_val" + ;; + esac + done <<< "$(read_strip_comments $KDUMP_CONF)" +} diff --git a/kdump-lib.sh b/kdump-lib.sh new file mode 100755 index 0000000..efc1a37 --- /dev/null +++ b/kdump-lib.sh @@ -0,0 +1,657 @@ +#!/bin/sh +# +# Kdump common variables and functions +# + +DEFAULT_PATH="/var/crash/" +FENCE_KDUMP_CONFIG_FILE="/etc/sysconfig/fence_kdump" +FENCE_KDUMP_SEND="/usr/libexec/fence_kdump_send" +FADUMP_ENABLED_SYS_NODE="/sys/kernel/fadump_enabled" + +is_fadump_capable() +{ + # Check if firmware-assisted dump is enabled + # if no, fallback to kdump check + if [ -f $FADUMP_ENABLED_SYS_NODE ]; then + rc=`cat $FADUMP_ENABLED_SYS_NODE` + [ $rc -eq 1 ] && return 0 + fi + return 1 +} + +perror_exit() { + echo $@ >&2 + exit 1 +} + +perror() { + echo $@ >&2 +} + +is_fs_type_nfs() +{ + [ "$1" = "nfs" ] || [ "$1" = "nfs4" ] +} + +is_ssh_dump_target() +{ + grep -q "^ssh[[:blank:]].*@" /etc/kdump.conf +} + +is_nfs_dump_target() +{ + if grep -q "^nfs" /etc/kdump.conf; then + return 0; + fi + + if is_fs_type_nfs $(get_dracut_args_fstype "$(grep "^dracut_args .*\-\-mount" /etc/kdump.conf)"); then + return 0 + fi + + local _save_path=$(get_save_path) + local _target=$(get_target_from_path $_save_path) + local _fstype=$(get_fs_type_from_target $_target) + + if is_fs_type_nfs $_fstype; then + return 0 + fi + + return 1 +} + +is_raw_dump_target() +{ + grep -q "^raw" /etc/kdump.conf +} + +is_fs_dump_target() +{ + egrep -q "^ext[234]|^xfs|^btrfs|^minix" /etc/kdump.conf +} + +strip_comments() +{ + echo $@ | sed -e 's/\(.*\)#.*/\1/' +} + +# Read from kdump config file stripping all comments +read_strip_comments() +{ + # strip heading spaces, and print any content starting with + # neither space or #, and strip everything after # + sed -n -e "s/^\s*\([^# \t][^#]\+\).*/\1/gp" $1 +} + +# Check if fence kdump is configured in Pacemaker cluster +is_pcs_fence_kdump() +{ + # no pcs or fence_kdump_send executables installed? + type -P pcs > /dev/null || return 1 + [ -x $FENCE_KDUMP_SEND ] || return 1 + + # fence kdump not configured? + (pcs cluster cib | grep 'type="fence_kdump"') &> /dev/null || return 1 +} + +# Check if fence_kdump is configured using kdump options +is_generic_fence_kdump() +{ + [ -x $FENCE_KDUMP_SEND ] || return 1 + + grep -q "^fence_kdump_nodes" /etc/kdump.conf +} + +to_dev_name() { + local dev="${1//\"/}" + + case "$dev" in + UUID=*) + dev=`blkid -U "${dev#UUID=}"` + ;; + LABEL=*) + dev=`blkid -L "${dev#LABEL=}"` + ;; + esac + echo $dev +} + +is_user_configured_dump_target() +{ + grep -E -q "^ext[234]|^xfs|^btrfs|^minix|^raw|^nfs|^ssh" /etc/kdump.conf || is_mount_in_dracut_args; +} + +get_user_configured_dump_disk() +{ + local _target + + _target=$(egrep "^ext[234]|^xfs|^btrfs|^minix|^raw" /etc/kdump.conf 2>/dev/null |awk '{print $2}') + [ -n "$_target" ] && echo $_target && return + + _target=$(get_dracut_args_target "$(grep "^dracut_args .*\-\-mount" /etc/kdump.conf)") + [ -b "$_target" ] && echo $_target +} + +get_root_fs_device() +{ + findmnt -k -f -n -o SOURCE / +} + +get_save_path() +{ + local _save_path=$(awk '$1 == "path" {print $2}' /etc/kdump.conf) + [ -z "$_save_path" ] && _save_path=$DEFAULT_PATH + + # strip the duplicated "/" + echo $_save_path | tr -s / +} + +get_block_dump_target() +{ + local _target _path + + if is_ssh_dump_target || is_nfs_dump_target; then + return + fi + + _target=$(get_user_configured_dump_disk) + [ -n "$_target" ] && echo $(to_dev_name $_target) && return + + # Get block device name from local save path + _path=$(get_save_path) + _target=$(get_target_from_path $_path) + [ -b "$_target" ] && echo $(to_dev_name $_target) +} + +is_dump_to_rootfs() +{ + grep -E "^(failure_action|default)[[:space:]]dump_to_rootfs" /etc/kdump.conf >/dev/null +} + +get_failure_action_target() +{ + local _target + + if is_dump_to_rootfs; then + # Get rootfs device name + _target=$(get_root_fs_device) + [ -b "$_target" ] && echo $(to_dev_name $_target) && return + # Then, must be nfs root + echo "nfs" + fi +} + +# Get kdump targets(including root in case of dump_to_rootfs). +get_kdump_targets() +{ + local _target _root + local kdump_targets + + _target=$(get_block_dump_target) + if [ -n "$_target" ]; then + kdump_targets=$_target + elif is_ssh_dump_target; then + kdump_targets="ssh" + else + kdump_targets="nfs" + fi + + # Add the root device if dump_to_rootfs is specified. + _root=$(get_failure_action_target) + if [ -n "$_root" -a "$kdump_targets" != "$_root" ]; then + kdump_targets="$kdump_targets $_root" + fi + + echo "$kdump_targets" +} + +# Return the bind mount source path, return the path itself if it's not bind mounted +# Eg. if /path/to/src is bind mounted to /mnt/bind, then: +# /mnt/bind -> /path/to/src, /mnt/bind/dump -> /path/to/src/dump +# +# findmnt uses the option "-v, --nofsroot" to exclusive the [/dir] +# in the SOURCE column for bind-mounts, then if $_mntpoint equals to +# $_mntpoint_nofsroot, the mountpoint is not bind mounted directory. +# +# Below is just an example for mount info +# /dev/mapper/atomicos-root[/ostree/deploy/rhel-atomic-host/var], if the +# directory is bind mounted. The former part represents the device path, rest +# part is the bind mounted directory which quotes by bracket "[]". +get_bind_mount_source() +{ + local _path=$1 + # In case it's a sub path in a mount point, get the mount point first + local _mnt_top=$(df $_path | tail -1 | awk '{print $NF}') + local _mntpoint=$(findmnt $_mnt_top | tail -n 1 | awk '{print $2}') + local _mntpoint_nofsroot=$(findmnt -v $_mnt_top | tail -n 1 | awk '{print $2}') + + if [[ "$_mntpoint" = $_mntpoint_nofsroot ]]; then + echo $_path && return + fi + + _mntpoint=${_mntpoint#*$_mntpoint_nofsroot} + _mntpoint=${_mntpoint#[} + _mntpoint=${_mntpoint%]} + _path=${_path#$_mnt_top} + + echo $_mntpoint$_path +} + +# Return the real underlaying device of a path, ignore bind mounts +get_target_from_path() +{ + local _target + + _target=$(df $1 2>/dev/null | tail -1 | awk '{print $1}') + [[ "$_target" == "/dev/root" ]] && [[ ! -e /dev/root ]] && _target=$(get_root_fs_device) + echo $_target +} + +get_fs_type_from_target() +{ + findmnt -k -f -n -r -o FSTYPE $1 +} + +# Find the general mount point of a dump target, not the bind mount point +get_mntpoint_from_target() +{ + # Expcilitly specify --source to findmnt could ensure non-bind mount is returned + findmnt -k -f -n -r -o TARGET --source $1 +} + +# get_option_value <option_name> +# retrieves value of option defined in kdump.conf +get_option_value() { + strip_comments `grep "^$1[[:space:]]\+" /etc/kdump.conf | tail -1 | cut -d\ -f2-` +} + +check_save_path_fs() +{ + local _path=$1 + + if [ ! -d $_path ]; then + perror_exit "Dump path $_path does not exist." + fi +} + +# Check if path exists within dump target +check_save_path_user_configured() +{ + local _target=$1 _path=$2 + local _mnt=$(get_mntpoint_from_target $_target) + + check_save_path_fs "$_mnt/$_path" +} + +is_atomic() +{ + grep -q "ostree" /proc/cmdline +} + +is_ipv6_address() +{ + echo $1 | grep -q ":" +} + +# get ip address or hostname from nfs/ssh config value +get_remote_host() +{ + local _config_val=$1 + + # ipv6 address in kdump.conf is around with "[]", + # factor out the ipv6 address + _config_val=${_config_val#*@} + _config_val=${_config_val%:/*} + _config_val=${_config_val#[} + _config_val=${_config_val%]} + echo $_config_val +} + +is_hostname() +{ + local _hostname=`echo $1 | grep ":"` + + if [ -n "$_hostname" ]; then + return 1 + fi + echo $1 | grep -q "[a-zA-Z]" +} + +# Copied from "/etc/sysconfig/network-scripts/network-functions" +get_hwaddr() +{ + if [ -f "/sys/class/net/${1}/address" ]; then + awk '{ print toupper($0) }' < /sys/class/net/${1}/address + elif [ -d "/sys/class/net/${1}" ]; then + LC_ALL= LANG= ip -o link show ${1} 2>/dev/null | \ + awk '{ print toupper(gensub(/.*link\/[^ ]* ([[:alnum:]:]*).*/, + "\\1", 1)); }' + fi +} + +get_ifcfg_by_device() +{ + grep -E -i -l "^[[:space:]]*DEVICE=\"*${1}\"*[[:space:]]*$" \ + /etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1 +} + +get_ifcfg_by_hwaddr() +{ + grep -E -i -l "^[[:space:]]*HWADDR=\"*${1}\"*[[:space:]]*$" \ + /etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1 +} + +get_ifcfg_by_uuid() +{ + grep -E -i -l "^[[:space:]]*UUID=\"*${1}\"*[[:space:]]*$" \ + /etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1 +} + +get_ifcfg_by_name() +{ + grep -E -i -l "^[[:space:]]*NAME=\"*${1}\"*[[:space:]]*$" \ + /etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1 +} + +is_nm_running() +{ + [ "$(LANG=C nmcli -t --fields running general status 2>/dev/null)" = "running" ] +} + +is_nm_handling() +{ + LANG=C nmcli -t --fields device,state dev status 2>/dev/null \ + | grep -q "^\(${1}:connected\)\|\(${1}:connecting.*\)$" +} + +# $1: netdev name +get_ifcfg_nmcli() +{ + local nm_uuid nm_name + local ifcfg_file + + # Get the active nmcli config name of $1 + if is_nm_running && is_nm_handling "${1}" ; then + # The configuration "uuid" and "name" generated by nm is wrote to + # the ifcfg file as "UUID=<nm_uuid>" and "NAME=<nm_name>". + nm_uuid=$(LANG=C nmcli -t --fields uuid,device c show --active 2>/dev/null \ + | grep "${1}" | head -1 | cut -d':' -f1) + nm_name=$(LANG=C nmcli -t --fields name,device c show --active 2>/dev/null \ + | grep "${1}" | head -1 | cut -d':' -f1) + ifcfg_file=$(get_ifcfg_by_uuid "${nm_uuid}") + [ -z "${ifcfg_file}" ] && ifcfg_file=$(get_ifcfg_by_name "${nm_name}") + fi + + echo -n "${ifcfg_file}" +} + +# $1: netdev name +get_ifcfg_legacy() +{ + local ifcfg_file + + ifcfg_file="/etc/sysconfig/network-scripts/ifcfg-${1}" + [ -f "${ifcfg_file}" ] && echo -n "${ifcfg_file}" && return + + ifcfg_file=$(get_ifcfg_by_name "${1}") + [ -f "${ifcfg_file}" ] && echo -n "${ifcfg_file}" && return + + local hwaddr=$(get_hwaddr "${1}") + if [ -n "$hwaddr" ]; then + ifcfg_file=$(get_ifcfg_by_hwaddr "${hwaddr}") + [ -f "${ifcfg_file}" ] && echo -n "${ifcfg_file}" && return + fi + + ifcfg_file=$(get_ifcfg_by_device "${1}") + + echo -n "${ifcfg_file}" +} + +# $1: netdev name +# Return the ifcfg file whole name(including the path) of $1 if any. +get_ifcfg_filename() { + local ifcfg_file + + ifcfg_file=$(get_ifcfg_nmcli "${1}") + if [ -z "${ifcfg_file}" ]; then + ifcfg_file=$(get_ifcfg_legacy "${1}") + fi + + echo -n "${ifcfg_file}" +} + +# returns 0 when omission of watchdog module is desired in dracut_args +# returns 1 otherwise +is_wdt_mod_omitted() { + local dracut_args + local ret=1 + + dracut_args=$(grep "^dracut_args" /etc/kdump.conf) + [[ -z $dracut_args ]] && return $ret + + 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 + + return $ret +} + +# If "dracut_args" contains "--mount" information, use it +# directly without any check(users are expected to ensure +# its correctness). +is_mount_in_dracut_args() +{ + grep -q "^dracut_args .*\-\-mount" /etc/kdump.conf +} + +# If $1 contains dracut_args "--mount", return <filesystem type> +get_dracut_args_fstype() +{ + echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f3 +} + +# If $1 contains dracut_args "--mount", return <device> +get_dracut_args_target() +{ + echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f1 +} + +check_crash_mem_reserved() +{ + local mem_reserved + + mem_reserved=$(cat /sys/kernel/kexec_crash_size) + if [ $mem_reserved -eq 0 ]; then + echo "No memory reserved for crash kernel" + return 1 + fi + + return 0 +} + +check_kdump_feasibility() +{ + if [ ! -e /sys/kernel/kexec_crash_loaded ]; then + echo "Kdump is not supported on this kernel" + return 1 + fi + check_crash_mem_reserved + return $? +} + +check_current_kdump_status() +{ + if [ ! -f /sys/kernel/kexec_crash_loaded ];then + echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel" + return 1 + fi + + rc=`cat /sys/kernel/kexec_crash_loaded` + if [ $rc == 1 ]; then + return 0 + else + return 1 + fi +} + +# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>] +# Remove a list of kernel parameters from a given kernel cmdline and print the result. +# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists. +remove_cmdline_param() +{ + local cmdline=$1 + shift + + for arg in $@; do + cmdline=`echo $cmdline | \ + sed -e "s/\b$arg=[^ ]*//g" \ + -e "s/^$arg\b//g" \ + -e "s/[[:space:]]$arg\b//g" \ + -e "s/\s\+/ /g"` + done + echo $cmdline +} + +# +# This function returns the "apicid" of the boot +# cpu (cpu 0) if present. +# +get_bootcpu_apicid() +{ + awk ' \ + BEGIN { CPU = "-1"; } \ + $1=="processor" && $2==":" { CPU = $NF; } \ + CPU=="0" && /^apicid/ { print $NF; } \ + ' \ + /proc/cpuinfo +} + +# +# append_cmdline <kernel cmdline> <parameter name> <parameter value> +# This function appends argument "$2=$3" to string ($1) if not already present. +# +append_cmdline() +{ + local cmdline=$1 + local newstr=${cmdline/$2/""} + + # unchanged str implies argument wasn't there + if [ "$cmdline" == "$newstr" ]; then + cmdline="${cmdline} ${2}=${3}" + fi + + echo $cmdline +} + +# This function check iomem and determines if we have more than +# 4GB of ram available. Returns 1 if we do, 0 if we dont +need_64bit_headers() +{ + return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \ + print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'` +} + +# +# prepare_kexec_args <kexec args> +# This function prepares kexec argument. +# +prepare_kexec_args() +{ + local kexec_args=$1 + local found_elf_args + + ARCH=`uname -m` + if [ "$ARCH" == "i686" -o "$ARCH" == "i386" ] + then + need_64bit_headers + if [ $? == 1 ] + then + 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 + else + kexec_args="$kexec_args --elf64-core-headers" + fi + else + found_elf_args=`echo $kexec_args | grep elf64-core-headers` + if [ -z "$found_elf_args" ] + then + kexec_args="$kexec_args --elf32-core-headers" + fi + fi + fi + echo $kexec_args +} + +check_boot_dir() +{ + local kdump_bootdir=$1 + #If user specify a boot dir for kdump kernel, let's use it. Otherwise + #check whether it's a atomic host. If yes parse the subdirectory under + #/boot; If not just find it under /boot. + if [ -n "$kdump_bootdir" ]; then + echo "$kdump_bootdir" + return + fi + + if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then + kdump_bootdir="/boot" + else + eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1) + kdump_bootdir="/boot"$(dirname ${BOOT_IMAGE#*)}) + fi + echo $kdump_bootdir +} + +# +# prepare_cmdline <commandline> <commandline remove> <commandline append> +# This function performs a series of edits on the command line. +# Store the final result in global $KDUMP_COMMANDLINE. +prepare_cmdline() +{ + local cmdline id + + if [ -z "$1" ]; then + cmdline=$(cat /proc/cmdline) + else + cmdline="$1" + fi + + # These params should always be removed + cmdline=$(remove_cmdline_param "$cmdline" crashkernel panic_on_warn) + # These params can be removed configurably + cmdline=$(remove_cmdline_param "$cmdline" "$2") + + # Always remove "root=X", as we now explicitly generate all kinds + # of dump target mount information including root fs. + # + # We do this before KDUMP_COMMANDLINE_APPEND, if one really cares + # about it(e.g. for debug purpose), then can pass "root=X" using + # KDUMP_COMMANDLINE_APPEND. + cmdline=$(remove_cmdline_param "$cmdline" root) + + # With the help of "--hostonly-cmdline", we can avoid some interitage. + cmdline=$(remove_cmdline_param "$cmdline" rd.luks.uuid rd.dm.uuid rd.md.uuid fcoe) + + # Remove netroot, rd.iscsi.initiator and iscsi_initiator since + # we get duplicate entries for the same in case iscsi code adds + # it as well. + cmdline=$(remove_cmdline_param "$cmdline" netroot rd.iscsi.initiator iscsi_initiator) + + cmdline="${cmdline} $3" + + id=$(get_bootcpu_apicid) + if [ ! -z ${id} ] ; then + cmdline=$(append_cmdline "${cmdline}" disable_cpu_apicid ${id}) + fi + echo ${cmdline} +} diff --git a/kdump-udev-throttler b/kdump-udev-throttler new file mode 100755 index 0000000..cd77a31 --- /dev/null +++ b/kdump-udev-throttler @@ -0,0 +1,42 @@ +#!/bin/bash +# This util helps to reduce the workload of kdump service restarting +# on udev event. When hotplugging memory / CPU, multiple udev +# events may be triggered concurrently, and obviously, we don't want +# to restart kdump service for each event. + +# This script will be called by udev, and make sure kdump service is +# restart after all events we are watching are settled. + +# On each call, this script will update try to aquire the $throttle_lock +# The first instance acquired the file lock will keep waiting for events +# to settle and then reload kdump. Other instances will just exit +# In this way, we can make sure kdump service is restarted immediately +# and for exactly once after udev events are settled. + +throttle_lock="/var/lock/kdump-udev-throttle" + +exec 9>$throttle_lock +if [ $? -ne 0 ]; then + echo "Failed to create the lock file! Fallback to non-throttled kdump service restart" + /bin/kdumpctl reload + exit 1 +fi + +flock -n 9 +if [ $? -ne 0 ]; then + echo "Throttling kdump restart for concurrent udev event" + exit 0 +fi + +# Wait for at least 1 second, at most 4 seconds for udev to settle +# Idealy we will have a less than 1 second lag between udev events settle +# and kdump reload +sleep 1 && udevadm settle --timeout 3 + +# Release the lock, /bin/kdumpctl will block and make the process +# holding two locks at the same time and we might miss some events +exec 9>&- + +/bin/kdumpctl reload + +exit 0 diff --git a/kdump.conf b/kdump.conf new file mode 100644 index 0000000..1f0fc2d --- /dev/null +++ b/kdump.conf @@ -0,0 +1,175 @@ +# This file contains a series of commands to perform (in order) in the kdump +# kernel after a kernel crash in the crash kernel(1st kernel) has happened. +# +# Directives in this file are only applicable to the kdump initramfs, and have +# no effect once the root filesystem is mounted and the normal init scripts are +# processed. +# +# Currently, only one dump target and path can be specified. If the dumping to +# the configured target fails, the failure action which can be configured via +# the "failure_action" directive will be performed. +# +# Supported options: +# +# raw <partition> +# - Will dd /proc/vmcore into <partition>. +# Use persistent device names for partition devices, +# such as /dev/vg/<devname>. +# +# nfs <nfs mount> +# - Will mount nfs to <mnt>, and copy /proc/vmcore to +# <mnt>/<path>/%HOST-%DATE/, supports DNS. +# +# ssh <user@server> +# - Will scp /proc/vmcore to <user@server>:<path>/%HOST-%DATE/, +# supports DNS. +# NOTE: make sure the user has write permissions on the server. +# +# sshkey <path> +# - Will use the sshkey to do ssh dump. +# Specify the path of the ssh key to use when dumping +# via ssh. The default value is /root/.ssh/kdump_id_rsa. +# +# <fs type> <partition> +# - Will mount -t <fs type> <partition> <mnt>, and copy +# /proc/vmcore to <mnt>/<path>/%HOST_IP-%DATE/. +# NOTE: <partition> can be a device node, label or uuid. +# It's recommended to use persistent device names +# such as /dev/vg/<devname>. +# Otherwise it's suggested to use label or uuid. +# +# path <path> +# - "path" represents the file system path in which vmcore +# will be saved. If a dump target is specified in +# kdump.conf, then "path" is relative to the specified +# dump target. +# +# Interpretation of "path" changes a bit if the user didn't +# specify any dump target explicitly in kdump.conf. In this +# case, "path" represents the absolute path from root. The +# dump target and adjusted path are arrived at automatically +# depending on what's mounted in the current system. +# +# Ignored for raw device dumps. If unset, will use the default +# "/var/crash". +# +# core_collector <command> <options> +# - This allows you to specify the command to copy +# the vmcore. The default is makedumpfile, which on +# some architectures can drastically reduce vmcore size. +# See /sbin/makedumpfile --help for a list of options. +# Note that the -i and -g options are not needed here, +# 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". +# The default core_collector for other targets is: +# "makedumpfile -l --message-level 1 -d 31". +# +# "makedumpfile -F" will create a flattened vmcore. +# You need to use "makedumpfile -R" to rearrange the dump data to +# a normal dumpfile readable with analysis tools. For example: +# "makedumpfile -R vmcore < vmcore.flat". +# +# For core_collector format details, you can refer to +# kexec-kdump-howto.txt or kdump.conf manpage. +# +# kdump_post <binary | script> +# - This directive allows you to run a executable binary +# or script after the vmcore dump process terminates. +# The exit status of the current dump process is fed to +# the executable binary or script as its first argument. +# +# kdump_pre <binary | script> +# - Works like the "kdump_post" directive, but instead of running +# after the dump process, runs immediately before it. +# Exit status of this binary is interpreted as follows: +# 0 - continue with dump process as usual +# non 0 - reboot the system +# +# extra_bins <binaries | shell scripts> +# - This directive allows you to specify additional binaries or +# shell scripts to be included in the kdump initrd. +# Generally they are useful in conjunction with a kdump_post +# or kdump_pre binary or script which depends on these extra_bins. +# +# extra_modules <module(s)> +# - This directive allows you to specify extra kernel modules +# that you want to be loaded in the kdump initrd. +# Multiple modules can be listed, separated by spaces, and any +# dependent modules will automatically be included. +# +# failure_action <reboot | halt | poweroff | shell | dump_to_rootfs> +# - Action to perform in case dumping fails. +# reboot: Reboot the system. +# halt: Halt the system. +# poweroff: Power down the system. +# shell: Drop to a bash shell. +# Exiting the shell reboots the system by default, +# or perform "final_action". +# dump_to_rootfs: Dump vmcore to rootfs from initramfs context and +# reboot by default or perform "final_action". +# Useful when non-root dump target is specified. +# The default option is "reboot". +# +# default <reboot | halt | poweroff | shell | dump_to_rootfs> +# - Same as the "failure_action" directive above, but this directive +# is obsolete and will be removed in the future. +# +# final_action <reboot | halt | poweroff> +# - Action to perform in case dumping succeeds. Also performed +# when "shell" or "dump_to_rootfs" failure action finishes. +# Each action is same as the "failure_action" directive above. +# The default is "reboot". +# +# force_rebuild <0 | 1> +# - By default, kdump initrd will only be rebuilt when necessary. +# Specify 1 to force rebuilding kdump initrd every time when kdump +# service starts. +# +# force_no_rebuild <0 | 1> +# - By default, kdump initrd will be rebuilt when necessary. +# Specify 1 to bypass rebuilding of kdump initrd. +# +# force_no_rebuild and force_rebuild options are mutually +# exclusive and they should not be set to 1 simultaneously. +# +# override_resettable <0 | 1> +# - Usually an unresettable block device can't be a dump target. +# Specifying 1 when you want to dump even though the block +# target is unresettable +# By default, it is 0, which will not try dumping destined to fail. +# +# dracut_args <arg(s)> +# - Pass extra dracut options when rebuilding kdump initrd. +# +# fence_kdump_args <arg(s)> +# - Command line arguments for fence_kdump_send (it can contain +# all valid arguments except hosts to send notification to). +# +# fence_kdump_nodes <node(s)> +# - List of cluster node(s) except localhost, separated by spaces, +# to send fence_kdump notifications to. +# (this option is mandatory to enable fence_kdump). +# + +#raw /dev/vg/lv_kdump +#ext4 /dev/vg/lv_kdump +#ext4 LABEL=/boot +#ext4 UUID=03138356-5e61-4ab3-b58e-27507ac41937 +#nfs my.server.com:/export/tmp +#ssh user@my.server.com +#sshkey /root/.ssh/kdump_id_rsa +path /var/crash +core_collector makedumpfile -l --message-level 1 -d 31 +#core_collector scp +#kdump_post /var/crash/scripts/kdump-post.sh +#kdump_pre /var/crash/scripts/kdump-pre.sh +#extra_bins /usr/bin/lftp +#extra_modules gfs2 +#failure_action shell +#force_rebuild 1 +#force_no_rebuild 1 +#dracut_args --omit-drivers "cfg80211 snd" --add-drivers "ext2 ext3" +#fence_kdump_args -p 7410 -f auto -c 0 -i 10 +#fence_kdump_nodes node1 node2 diff --git a/kdump.conf.5 b/kdump.conf.5 new file mode 100644 index 0000000..5a0952b --- /dev/null +++ b/kdump.conf.5 @@ -0,0 +1,360 @@ +.TH KDUMP.CONF 5 "07/23/2008" "kexec-tools" + +.SH NAME +kdump.conf \- configuration file for kdump kernel. + +.SH DESCRIPTION + +kdump.conf is a configuration file for the kdump kernel crash +collection service. + +kdump.conf provides post-kexec instructions to the kdump kernel. It is +stored in the initrd file managed by the kdump service. If you change +this file and do not want to reboot in order for the changes to take +effect, restart the kdump service to rebuild the initrd. + +For most configurations, you can simply review the examples provided +in the stock /etc/kdump.conf. + +.B NOTE: +For filesystem dumps the dump target must be mounted before building +kdump initramfs. + +kdump.conf only affects the behavior of the initramfs. Please read the +kdump operational flow section of kexec-kdump-howto.txt in the docs to better +understand how this configuration file affects the behavior of kdump. + +.SH OPTIONS + +.B raw <partition> +.RS +Will dd /proc/vmcore into <partition>. Use persistent device names for +partition devices, such as /dev/vg/<devname>. +.RE + +.B nfs <nfs mount> +.RS +Will mount nfs to <mnt>, and copy /proc/vmcore to <mnt>/<path>/%HOST-%DATE/, +supports DNS. Note that a fqdn should be used as the server name in the +mount point. +.RE + +.B ssh <user@server> +.RS +Will scp /proc/vmcore to <user@server>:<path>/%HOST-%DATE/, +supports DNS. NOTE: make sure user has necessary write permissions on +server and that a fqdn is used as the server name. +.RE + +.B sshkey <path> +.RS +Specify the path of the ssh key to use when dumping via ssh. +The default value is /root/.ssh/kdump_id_rsa. +.RE + +.B <fs type> <partition> +.RS +Will mount -t <fs type> <partition> <mnt>, and copy /proc/vmcore to +<mnt>/<path>/%HOST_IP-%DATE/. NOTE: <partition> can be a device node, label +or uuid. It's recommended to use persistent device names such as +/dev/vg/<devname>. Otherwise it's suggested to use label or uuid. +.RE + +.B path <path> +.RS +"path" represents the file system path in which vmcore will be saved. +If a dump target is specified in kdump.conf, then "path" is relative to the +specified dump target. +.PP +Interpretation of "path" changes a bit if the user didn't specify any dump +target explicitly in kdump.conf. In this case, "path" represents the +absolute path from root. The dump target and adjusted path are arrived +at automatically depending on what's mounted in the current system. +.PP +Ignored for raw device dumps. If unset, will use the default "/var/crash". +.RE + +.B core_collector <command> <options> +.RS +This allows you to specify the command to copy the vmcore. +The default is makedumpfile, which on some architectures can drastically reduce +core file size. See /sbin/makedumpfile --help for a list of options. +Note that the -i and -g options are not needed here, as the initrd +will automatically be populated with a config file appropriate +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". +The default core_collector for other targets is: +"makedumpfile -l --message-level 1 -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 +need to specify one using core_collector option to change the behavior. +.PP +Note 2: If "makedumpfile -F" is used then you will get a flattened format +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" + +.RE + +.B kdump_post <binary | script> +.RS +This directive allows you to run a specified executable +just after the vmcore dump process terminates. The exit +status of the current dump process is fed to the kdump_post +executable as its first argument($1). Executable can modify +it to indicate the new exit status of succeeding dump process, +.PP +Note that scripts written for use with this directive must use +the /bin/bash interpreter. +.RE + +.B kdump_pre <binary | script> +.RS +Works just like the "kdump_post" directive, but instead +of running after the dump process, runs immediately +before. Exit status of this binary is interpreted +as follows: +.PP +0 - continue with dump process as usual +.PP +non 0 - reboot the system +.PP +Note that scripts written for this directive must use +the /bin/bash interpreter. +.RE + +.B extra_bins <binaries | shell scripts> +.RS +This directive allows you to specify additional +binaries or shell scripts you'd like to include in +your kdump initrd. Generally only useful in +conjunction with a kdump_post binary or script that +relies on other binaries or scripts. +.RE + +.B extra_modules <module(s)> +.RS +This directive allows you to specify extra kernel +modules that you want to be loaded in the kdump +initrd, typically used to set up access to +non-boot-path dump targets that might otherwise +not be accessible in the kdump environment. Multiple +modules can be listed, separated by spaces, and any +dependent modules will automatically be included. +.RE + +.B failure_action <reboot | halt | poweroff | shell | dump_to_rootfs> +.RS +Action to perform in case dumping to the intended target fails. The default is "reboot". +reboot: Reboot the system (this is what most people will want, as it returns the system +to a normal state). halt: Halt the system and lose the vmcore. poweroff: The system +will be powered down. shell: Drop to a shell session inside the initramfs, from which +you can manually perform additional recovery actions. Exiting this shell reboots the +system by default or performs "final_action". +Note: kdump uses bash as the default shell. dump_to_rootfs: If non-root dump +target is specified, the failure action can be set as dump_to_rootfs. That means when +dumping to target fails, dump vmcore to rootfs from initramfs context and reboot +by default or perform "final_action". +.RE + +.B default <reboot | halt | poweroff | shell | dump_to_rootfs> +.RS +Same as the "failure_action" directive above, but this directive is obsolete +and will be removed in the future. +.RE + +.B final_action <reboot | halt | poweroff> +.RS +Action to perform in case dumping to the intended target succeeds. +Also performed when "shell" or "dump_to_rootfs" failure action finishes. +Each action is same as the "failure_action" directive above. +The default is "reboot". +.RE + +.B force_rebuild <0 | 1> +.RS +By default, kdump initrd will only be rebuilt when necessary. +Specify 1 to force rebuilding kdump initrd every time when kdump service starts. +.RE + +.B force_no_rebuild <0 | 1> +.RS +By default, kdump initrd will be rebuilt when necessary. +Specify 1 to bypass rebuilding of kdump initrd. + +.PP +force_no_rebuild and force_rebuild options are mutually exclusive and +they should not be set to 1 simultaneously. +.RE + +.B override_resettable <0 | 1> +.RS +Usually an unresettable block device can't be a dump target. Specifying 1 means +that even though the block target is unresettable, the user wants to try dumping anyway. +By default, it's set to 0, which will not try something destined to fail. +.RE + + +.B dracut_args <arg(s)> +.RS +Kdump uses dracut to generate initramfs for second kernel. This option +allows a user to pass arguments to dracut directly. +.RE + + +.B fence_kdump_args <arg(s)> +.RS +Command line arguments for fence_kdump_send (it can contain all valid +arguments except hosts to send notification to). +.RE + + +.B fence_kdump_nodes <node(s)> +.RS +List of cluster node(s) except localhost, separated by spaces, to send fence_kdump notification +to (this option is mandatory to enable fence_kdump). +.RE + + +.SH DEPRECATED OPTIONS + +.B net <nfs mount>|<user@server> +.RS +net option is replaced by nfs and ssh options. Use nfs or ssh options +directly. +.RE + +.B options <module> <option list> +.RS +Use KDUMP_COMMANDLINE_APPEND in /etc/sysconfig/kdump to add module options as +kernel command line parameters. For example, specify 'loop.max_loop=1' to limit +maximum loop devices to 1. +.RE + +.B link_delay <seconds> +.RS +link_delay was used to wait for a network device to initialize before using it. +Now dracut network module takes care of this issue automatically. +.RE + +.B disk_timeout <seconds> +.RS +Similar to link_delay, dracut ensures disks are ready before kdump uses them. +.RE + +.B debug_mem_level <0-3> +.RS +Turn on verbose debug output of kdump scripts regarding free/used memory at +various points of execution. This feature has been +moved to dracut now. +Use KDUMP_COMMANDLINE_APPEND in /etc/sysconfig/kdump and +append dracut cmdline param rd.memdebug=[0-3] to enable the debug output. + +Higher level means more debugging output. +.PP +0 - no output +.PP +1 - partial /proc/meminfo +.PP +2 - /proc/meminfo +.PP +3 - /proc/meminfo + /proc/slabinfo +.RE + +.B blacklist <list of kernel modules> +.RS +blacklist option was recently being used to prevent loading modules in +initramfs. General terminology for blacklist has been that module is +present in initramfs but it is not actually loaded in kernel. Hence +retaining blacklist option creates more confusing behavior. It has been +deprecated. +.PP +Instead, use rd.driver.blacklist option on second kernel to blacklist +a certain module. One can edit /etc/sysconfig/kdump.conf and edit +KDUMP_COMMANDLINE_APPEND to pass kernel command line options. Refer +to dracut.cmdline man page for more details on module blacklist option. +.RE + +.RE + +.SH EXAMPLES +Here are some examples for core_collector option: +.PP +Core collector command format depends on dump target type. Typically for +filesystem (local/remote), core_collector should accept two arguments. +First one is source file and second one is target file. For ex. +.TP +ex1. +core_collector "cp --sparse=always" + +Above will effectively be translated to: + +cp --sparse=always /proc/vmcore <dest-path>/vmcore +.TP +ex2. +core_collector "makedumpfile -l --message-level 1 -d 31" + +Above will effectively be translated to: + +makedumpfile -l --message-level 1 -d 31 /proc/vmcore <dest-path>/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 +output (There is one exception of "scp", discussed later). This standard +output will be saved to destination using appropriate commands. + +raw dumps examples: +.TP +ex3. +core_collector "cat" + +Above will effectively be translated to. + +cat /proc/vmcore | dd of=<target-device> +.TP +ex4. +core_collector "makedumpfile -F -l --message-level 1 -d 31" + +Above will effectively be translated to. + +makedumpfile -F -l --message-level 1 -d 31 | dd of=<target-device> +.PP +ssh dumps examples +.TP +ex5. +core_collector "cat" + +Above will effectively be translated to. + +cat /proc/vmcore | ssh <options> <remote-location> "dd of=path/vmcore" +.TP +ex6. +core_collector "makedumpfile -F -l --message-level 1 -d 31" + +Above will effectively be translated to. + +makedumpfile -F -l --message-level 1 -d 31 | ssh <options> <remote-location> "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 +specify "scp" as core collector for ssh targets (no output on stdout). +.TP +ex7. +core_collector "scp" + +Above will effectively be translated to. + +scp /proc/vmcore <user@host>:path/vmcore + +.PP +examples for other options please see +.I /etc/kdump.conf + +.SH SEE ALSO + +kexec(8) mkdumprd(8) dracut.cmdline(7) diff --git a/kdump.service b/kdump.service new file mode 100644 index 0000000..f888dd6 --- /dev/null +++ b/kdump.service @@ -0,0 +1,15 @@ +[Unit] +Description=Crash recovery kernel arming +After=network.target network-online.target remote-fs.target basic.target +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/bin/kdumpctl start +ExecStop=/usr/bin/kdumpctl stop +ExecReload=/usr/bin/kdumpctl reload +RemainAfterExit=yes +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target diff --git a/kdump.sysconfig b/kdump.sysconfig new file mode 100644 index 0000000..df518d6 --- /dev/null +++ b/kdump.sysconfig @@ -0,0 +1,37 @@ +# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump +# If no version is specified, then the init script will try to find a +# kdump kernel with the same version number as the running kernel. +KDUMP_KERNELVER="" + +# The kdump commandline is the command line that needs to be passed off to +# the kdump kernel. This will likely match the contents of the grub kernel +# line. For example: +# KDUMP_COMMANDLINE="ro root=LABEL=/" +# Dracut depends on proper root= options, so please make sure that appropriate +# root= options are copied from /proc/cmdline. In general it is best to append +# command line options using "KDUMP_COMMANDLINE_APPEND=". +# If a command line is not specified, the default will be taken from +# /proc/cmdline +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" + +# This variable lets us append arguments to the current kdump commandline +# after processed by KDUMP_COMMANDLINE_REMOVE +KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 reset_devices novmcoredd" + +# Any additional kexec arguments required. In most situations, this should +# be left empty +# +# Example: +# KEXEC_ARGS="--elf32-core-headers" +KEXEC_ARGS="" + +#Where to find the boot image +#KDUMP_BOOTDIR="/boot" + +#What is the image type used for kdump +KDUMP_IMG="vmlinuz" diff --git a/kdump.sysconfig.aarch64 b/kdump.sysconfig.aarch64 new file mode 100644 index 0000000..39a39eb --- /dev/null +++ b/kdump.sysconfig.aarch64 @@ -0,0 +1,37 @@ +# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump +# If no version is specified, then the init script will try to find a +# kdump kernel with the same version number as the running kernel. +KDUMP_KERNELVER="" + +# The kdump commandline is the command line that needs to be passed off to +# the kdump kernel. This will likely match the contents of the grub kernel +# line. For example: +# KDUMP_COMMANDLINE="ro root=LABEL=/" +# Dracut depends on proper root= options, so please make sure that appropriate +# root= options are copied from /proc/cmdline. In general it is best to append +# command line options using "KDUMP_COMMANDLINE_APPEND=". +# If a command line is not specified, the default will be taken from +# /proc/cmdline +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" + +# This variable lets us append arguments to the current kdump commandline +# after processed by KDUMP_COMMANDLINE_REMOVE +KDUMP_COMMANDLINE_APPEND="irqpoll nr_cpus=1 reset_devices cgroup_disable=memory udev.children-max=2 panic=10 swiotlb=noforce novmcoredd numa=off" + +# Any additional kexec arguments required. In most situations, this should +# be left empty +# +# Example: +# KEXEC_ARGS="--elf32-core-headers" +KEXEC_ARGS="" + +#Where to find the boot image +#KDUMP_BOOTDIR="/boot" + +#What is the image type used for kdump +KDUMP_IMG="vmlinuz" diff --git a/kdump.sysconfig.i386 b/kdump.sysconfig.i386 new file mode 100644 index 0000000..c31a8cb --- /dev/null +++ b/kdump.sysconfig.i386 @@ -0,0 +1,40 @@ +# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump +# If no version is specified, then the init script will try to find a +# kdump kernel with the same version number as the running kernel. +KDUMP_KERNELVER="" + +# The kdump commandline is the command line that needs to be passed off to +# the kdump kernel. This will likely match the contents of the grub kernel +# line. For example: +# KDUMP_COMMANDLINE="ro root=LABEL=/" +# Dracut depends on proper root= options, so please make sure that appropriate +# root= options are copied from /proc/cmdline. In general it is best to append +# command line options using "KDUMP_COMMANDLINE_APPEND=". +# If a command line is not specified, the default will be taken from +# /proc/cmdline +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" + +# This variable lets us append arguments to the current kdump commandline +# after processed by KDUMP_COMMANDLINE_REMOVE +KDUMP_COMMANDLINE_APPEND="irqpoll nr_cpus=1 reset_devices numa=off udev.children-max=2 panic=10 transparent_hugepage=never novmcoredd" + +# Any additional kexec arguments required. In most situations, this should +# be left empty +# +# Example: +# KEXEC_ARGS="--elf32-core-headers" +KEXEC_ARGS="" + +#Where to find the boot image +#KDUMP_BOOTDIR="/boot" + +#What is the image type used for kdump +KDUMP_IMG="vmlinuz" + +#What is the images extension. Relocatable kernels don't have one +KDUMP_IMG_EXT="" diff --git a/kdump.sysconfig.loongarch64 b/kdump.sysconfig.loongarch64 new file mode 100755 index 0000000..86c6d89 --- /dev/null +++ b/kdump.sysconfig.loongarch64 @@ -0,0 +1,65 @@ +# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump +# If no version is specified, then the init script will try to find a +# kdump kernel with the same version number as the running kernel. +KDUMP_KERNELVER="" + +# The kdump commandline is the command line that needs to be passed off to +# the kdump kernel. This will likely match the contents of the grub kernel +# line. For example: +# KDUMP_COMMANDLINE="ro root=LABEL=/" +# Dracut depends on proper root= options, so please make sure that appropriate +# root= options are copied from /proc/cmdline. In general it is best to append +# command line options using "KDUMP_COMMANDLINE_APPEND=". +# If a command line is not specified, the default will be taken from +# /proc/cmdline +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 rd_start rd_size initrd resume=UUID" + +# This variable lets us append arguments to the current kdump commandline +# after processed by KDUMP_COMMANDLINE_REMOVE +KDUMP_COMMANDLINE_APPEND="nr_cpus=1 init 3 irqpoll reset_devices cgroup_disable=memory udev.children-max=2 panic=10 novmcoredd" + +# Any additional kexec arguments required. In most situations, this should +# be left empty +# +# Example: +# KEXEC_ARGS="--elf32-core-headers" +KEXEC_ARGS="" + +#Where to find the boot image +#KDUMP_BOOTDIR="/boot" + +#What is the image type used for kdump +KDUMP_IMG="vmlinux" + +#Please replace with the capture kernel to be reboot and the +#the corresponding initrd only for LoongArch architecture +# Example: +# DEFAULT_KDUMP_KERNEL="/boot/vmlinux-4.19.190-4.lns8.loongarch64+kdump" +# DEFAULT_TARGET_INITRD="/boot/initramfs-4.19.190-4.lns8.loongarch64+kdump.img" +# If a DEFAULT_KDUMP_KERNEL is not specified, the default is set to +# "/boot/vmlinux-$(uname -r)+kdump" +DEFAULT_KDUMP_KERNEL="" +# If a DEFAULT_TARGET_INITRD is not specified, the default is set to +# "/boot/initramfs-$(uname -r)+kdump.img" +DEFAULT_TARGET_INITRD="" + +# 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 new file mode 100644 index 0000000..1f95452 --- /dev/null +++ b/kdump.sysconfig.ppc64 @@ -0,0 +1,42 @@ +# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump +# If no version is specified, then the init script will try to find a +# kdump kernel with the same version number as the running kernel. +KDUMP_KERNELVER="" + +# The kdump commandline is the command line that needs to be passed off to +# the kdump kernel. This will likely match the contents of the grub kernel +# line. For example: +# KDUMP_COMMANDLINE="ro root=LABEL=/" +# Dracut depends on proper root= options, so please make sure that appropriate +# root= options are copied from /proc/cmdline. In general it is best to append +# command line options using "KDUMP_COMMANDLINE_APPEND=". +# If a command line is not specified, the default will be taken from +# /proc/cmdline +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" + +# This variable lets us append arguments to the current kdump commandline +# after processed by KDUMP_COMMANDLINE_REMOVE +KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 noirqdistrib reset_devices cgroup_disable=memory numa=off udev.children-max=2 ehea.use_mcs=0 panic=10 kvm_cma_resv_ratio=0 transparent_hugepage=never novmcoredd" + +# Any additional kexec arguments required. In most situations, this should +# be left empty +# +# Example: +# KEXEC_ARGS="--elf32-core-headers" +KEXEC_ARGS="--dt-no-old-root" + +#Where to find the boot image +#KDUMP_BOOTDIR="/boot" + +#What is the image type used for kdump +KDUMP_IMG="vmlinuz" + +#What is the images extension. Relocatable kernels don't have one +KDUMP_IMG_EXT="" + +#Specify the action after failure diff --git a/kdump.sysconfig.ppc64le b/kdump.sysconfig.ppc64le new file mode 100644 index 0000000..1f95452 --- /dev/null +++ b/kdump.sysconfig.ppc64le @@ -0,0 +1,42 @@ +# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump +# If no version is specified, then the init script will try to find a +# kdump kernel with the same version number as the running kernel. +KDUMP_KERNELVER="" + +# The kdump commandline is the command line that needs to be passed off to +# the kdump kernel. This will likely match the contents of the grub kernel +# line. For example: +# KDUMP_COMMANDLINE="ro root=LABEL=/" +# Dracut depends on proper root= options, so please make sure that appropriate +# root= options are copied from /proc/cmdline. In general it is best to append +# command line options using "KDUMP_COMMANDLINE_APPEND=". +# If a command line is not specified, the default will be taken from +# /proc/cmdline +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" + +# This variable lets us append arguments to the current kdump commandline +# after processed by KDUMP_COMMANDLINE_REMOVE +KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 noirqdistrib reset_devices cgroup_disable=memory numa=off udev.children-max=2 ehea.use_mcs=0 panic=10 kvm_cma_resv_ratio=0 transparent_hugepage=never novmcoredd" + +# Any additional kexec arguments required. In most situations, this should +# be left empty +# +# Example: +# KEXEC_ARGS="--elf32-core-headers" +KEXEC_ARGS="--dt-no-old-root" + +#Where to find the boot image +#KDUMP_BOOTDIR="/boot" + +#What is the image type used for kdump +KDUMP_IMG="vmlinuz" + +#What is the images extension. Relocatable kernels don't have one +KDUMP_IMG_EXT="" + +#Specify the action after failure diff --git a/kdump.sysconfig.riscv64 b/kdump.sysconfig.riscv64 new file mode 100644 index 0000000..1e65df8 --- /dev/null +++ b/kdump.sysconfig.riscv64 @@ -0,0 +1,37 @@ +# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump +# If no version is specified, then the init script will try to find a +# kdump kernel with the same version number as the running kernel. +KDUMP_KERNELVER="" + +# The kdump commandline is the command line that needs to be passed off to +# the kdump kernel. This will likely match the contents of the grub kernel +# line. For example: +# KDUMP_COMMANDLINE="ro root=LABEL=/" +# Dracut depends on proper root= options, so please make sure that appropriate +# root= options are copied from /proc/cmdline. In general it is best to append +# command line options using "KDUMP_COMMANDLINE_APPEND=". +# If a command line is not specified, the default will be taken from +# /proc/cmdline +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" + +# This variable lets us append arguments to the current kdump commandline +# after processed by KDUMP_COMMANDLINE_REMOVE +KDUMP_COMMANDLINE_APPEND="irqpoll nr_cpus=1 reset_devices novmcoredd noinitrd" + +# Any additional kexec arguments required. In most situations, this should +# be left empty +# +# Example: +# KEXEC_ARGS="--elf32-core-headers" +KEXEC_ARGS="" + +#Where to find the boot image +#KDUMP_BOOTDIR="/boot" + +#What is the image type used for kdump +KDUMP_IMG="vmlinuz" diff --git a/kdump.sysconfig.s390x b/kdump.sysconfig.s390x new file mode 100644 index 0000000..abd45a2 --- /dev/null +++ b/kdump.sysconfig.s390x @@ -0,0 +1,43 @@ +# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump +# If no version is specified, then the init script will try to find a +# kdump kernel with the same version number as the running kernel. +KDUMP_KERNELVER="" + +# The kdump commandline is the command line that needs to be passed off to +# the kdump kernel. This will likely match the contents of the grub kernel +# line. For example: +# KDUMP_COMMANDLINE="ro root=LABEL=/" +# Dracut depends on proper root= options, so please make sure that appropriate +# root= options are copied from /proc/cmdline. In general it is best to append +# command line options using "KDUMP_COMMANDLINE_APPEND=". +# If a command line is not specified, the default will be taken from +# /proc/cmdline +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" + +# This variable lets us append arguments to the current kdump commandline +# after processed by KDUMP_COMMANDLINE_REMOVE +KDUMP_COMMANDLINE_APPEND="nr_cpus=1 cgroup_disable=memory numa=off udev.children-max=2 panic=10 transparent_hugepage=never novmcoredd" + +# Any additional /sbin/mkdumprd arguments required. +MKDUMPRD_ARGS="" + +# Any additional kexec arguments required. In most situations, this should +# be left empty +# +# Example: +# KEXEC_ARGS="--elf32-core-headers" +KEXEC_ARGS="" + +#Where to find the boot image +#KDUMP_BOOTDIR="/boot" + +#What is the image type used for kdump +KDUMP_IMG="vmlinuz" + +#What is the images extension. Relocatable kernels don't have one +KDUMP_IMG_EXT="" diff --git a/kdump.sysconfig.x86_64 b/kdump.sysconfig.x86_64 new file mode 100644 index 0000000..8217204 --- /dev/null +++ b/kdump.sysconfig.x86_64 @@ -0,0 +1,46 @@ +# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump +# If no version is specified, then the init script will try to find a +# kdump kernel with the same version number as the running kernel. +KDUMP_KERNELVER="" + +# The kdump commandline is the command line that needs to be passed off to +# the kdump kernel. This will likely match the contents of the grub kernel +# line. For example: +# KDUMP_COMMANDLINE="ro root=LABEL=/" +# Dracut depends on proper root= options, so please make sure that appropriate +# root= options are copied from /proc/cmdline. In general it is best to append +# command line options using "KDUMP_COMMANDLINE_APPEND=". +# If a command line is not specified, the default will be taken from +# /proc/cmdline +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" + +# This variable lets us append arguments to the current kdump commandline +# after processed by KDUMP_COMMANDLINE_REMOVE +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" + +# Any additional kexec arguments required. In most situations, this should +# be left empty +# +# Example: +# KEXEC_ARGS="--elf32-core-headers" +KEXEC_ARGS="" + +#Where to find the boot image +#KDUMP_BOOTDIR="/boot" + +#What is the image type used for kdump +KDUMP_IMG="vmlinuz" + +#What is the images extension. Relocatable kernels don't have one +KDUMP_IMG_EXT="" + +# Using kexec file based syscall by default +# +# Here, the "on" is the only valid value to enable the kexec file load and +# anything else is equal to the "off"(disable). +KDUMP_FILE_LOAD="off" diff --git a/kdumpctl b/kdumpctl new file mode 100755 index 0000000..00c0064 --- /dev/null +++ b/kdumpctl @@ -0,0 +1,1301 @@ +#!/bin/bash +KEXEC=/sbin/kexec + +KDUMP_KERNELVER="" +KDUMP_COMMANDLINE="" +KEXEC_ARGS="" +KDUMP_FILE_LOAD="" +KDUMP_CONFIG_FILE="/etc/kdump.conf" +MKDUMPRD="/sbin/mkdumprd -f" +DRACUT_MODULES_FILE="/usr/lib/dracut/modules.txt" +SAVE_PATH=/var/crash +SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" +INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum" +DUMP_TARGET="" +DEFAULT_INITRD="" +DEFAULT_INITRD_BAK="" +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" + +# Some default values in case /etc/sysconfig/kdump doesn't include +KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug" + +if [ -f /etc/sysconfig/kdump ]; then + . /etc/sysconfig/kdump +fi + +single_instance_lock() +{ + local rc timeout=5 + + exec 9>/var/lock/kdump + if [ $? -ne 0 ]; then + echo "Create file lock failed" + exit 1 + fi + + flock -n 9 + rc=$? + + while [ $rc -ne 0 ]; do + echo "Another app is currently holding the kdump lock; waiting for it to exit..." + flock -w $timeout 9 + rc=$? + done +} + +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" + DEFAULT_DUMP_MODE="fadump" + fi +} + +save_core() +{ + coredir="/var/crash/`date +"%Y-%m-%d-%H:%M"`" + + mkdir -p $coredir + cp --sparse=always /proc/vmcore $coredir/vmcore-incomplete + if [ $? == 0 ]; then + mv $coredir/vmcore-incomplete $coredir/vmcore + echo "saved a vmcore to $coredir" + else + echo "failed to save a vmcore to $coredir" >&2 + 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 + makedumpfile --dump-dmesg $coredir/vmcore $coredir/dmesg >/dev/null 2>&1 + dumpoops -d $coredir/dmesg >/dev/null 2>&1 + if [ $? == 0 ]; then + echo "kernel oops has been collected by abrt tool" + fi + fi +} + +rebuild_fadump_initrd() +{ + local target_initrd_tmp + + # 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 \ + -i /tmp/fadump.initramfs /etc/fadump.initramfs + if [ $? != 0 ]; then + echo "mkdumprd: failed to rebuild initrd with fadump support" >&2 + rm -f /tmp/fadump.initramfs + return 1 + fi + rm -f /tmp/fadump.initramfs + + # updating fadump initrd + mv $target_initrd_tmp $TARGET_INITRD + sync + + return 0 +} + +check_earlykdump_is_enabled() +{ + grep -q -w "rd.earlykdump" /proc/cmdline + return $? +} + +rebuild_kdump_initrd() +{ + $MKDUMPRD $TARGET_INITRD $kdump_kver + if [ $? != 0 ]; then + echo "mkdumprd: failed to make kdump initrd" >&2 + 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." + fi + + return 0 +} + +rebuild_initrd() +{ + if [[ ! -w "$KDUMP_BOOTDIR" ]];then + echo "$KDUMP_BOOTDIR does not have write permission. Can not rebuild $TARGET_INITRD" + return 1 + fi + + if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + rebuild_fadump_initrd + else + rebuild_kdump_initrd + fi + + return $? +} + +#$1: the files to be checked with IFS=' ' +check_exist() +{ + for file in $1; do + if [ ! -f "$file" ]; then + echo -n "Error: $file not found."; echo + return 1 + fi + done +} + +#$1: the files to be checked with IFS=' ' +check_executable() +{ + for file in $1; do + if [ ! -x "$file" ]; then + echo -n "Error: $file is not executable."; echo + return 1 + fi + done +} + +backup_default_initrd() +{ + if [ ! -f "$DEFAULT_INITRD" ]; then + return + fi + + if [ ! -e $DEFAULT_INITRD_BAK ]; then + echo "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." + rm -f $DEFAULT_INITRD_BAK + fi + fi +} + +restore_default_initrd() +{ + # 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 + # verify checksum before restoring + 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.." + 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." + sync + fi + fi + fi +} + +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 + } + + # Check if path option is set more than once. + nr=$(awk 'BEGIN{cnt=0} /^path /{cnt++} END{print cnt}' $KDUMP_CONFIG_FILE) + [ $nr -gt 1 ] && { + echo "Mutiple paths specifed in $KDUMP_CONFIG_FILE" + 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 + case "$config_opt" in + \#* | "") + ;; + 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." + fi + ;; + net|options|link_delay|disk_timeout|debug_mem_level|blacklist) + echo "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives." + ;; + *) + echo "Invalid kdump config option $config_opt" + ;; + esac + 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 +} + +# get_pcs_cluster_modified_files <image timestamp> +# return list of modified file for fence_kdump modified in Pacemaker cluster +get_pcs_cluster_modified_files() +{ + local time_stamp + local modified_files + + is_generic_fence_kdump && return 1 + is_pcs_fence_kdump || return 1 + + time_stamp=`pcs cluster cib | xmllint --xpath 'string(/cib/@cib-last-written)' - | \ + xargs -0 date +%s --date` + + if [ -n $time_stamp -a $time_stamp -gt $image_time ]; then + modified_files="cluster-cib" + fi + + if [ -f $FENCE_KDUMP_CONFIG_FILE ]; then + time_stamp=`stat -c "%Y" $FENCE_KDUMP_CONFIG_FILE` + if [ "$time_stamp" -gt "$image_time" ]; then + modified_files="$modified_files $FENCE_KDUMP_CONFIG_FILE" + fi + fi + + echo $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 + 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" + if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + TARGET_INITRD="$DEFAULT_INITRD" + + # backup initrd for reference before replacing it + # with fadump aware initrd + backup_default_initrd + else + TARGET_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img" + + # check if a backup of default initrd exists. If yes, + # it signifies a switch from fadump mode. So, restore + # the backed up default initrd. + restore_default_initrd + fi +} + +check_files_modified() +{ + local modified_files="" + + #also rebuild when Pacemaker cluster conf is changed and fence kdump is enabled. + modified_files=$(get_pcs_cluster_modified_files) + + EXTRA_BINS=`grep ^kdump_post $KDUMP_CONFIG_FILE | cut -d\ -f2` + CHECK_FILES=`grep ^kdump_pre $KDUMP_CONFIG_FILE | cut -d\ -f2` + CORE_COLLECTOR=`grep ^core_collector $KDUMP_CONFIG_FILE | cut -d\ -f2` + CORE_COLLECTOR=`type -P $CORE_COLLECTOR` + 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" + [[ -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" + fi + for _module in $EXTRA_MODULES; do + _module_file="$(modinfo --set-version "$kdump_kver" --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)" + 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" + fi + fi + done + fi + + check_exist "$files" && check_executable "$EXTRA_BINS" + [ $? -ne 0 ] && return 2 + + for file in $files; do + if [ -e "$file" ]; then + time_stamp=`stat -c "%Y" $file` + if [ "$time_stamp" -gt "$image_time" ]; then + modified_files="$modified_files $file" + fi + if [ -L "$file" ]; then + file=$(readlink -m $file) + time_stamp=`stat -c "%Y" $file` + if [ "$time_stamp" -gt "$image_time" ]; then + modified_files="$modified_files $file" + fi + fi + else + echo "$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' + return 1 + fi + + return 0 +} + +check_dump_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 _module_filename + + local _old_drivers="$(lsinitrd $TARGET_INITRD -f /usr/lib/dracut/hostonly-kernel-modules.txt | tr '\n' ' ')" + + # No need to check in case of mount target specified via "dracut_args". + if is_mount_in_dracut_args; then + return 0 + fi + + # No need to check in case of raw target. + # Currently we do not check also if ssh/nfs target is specified + if is_ssh_dump_target || is_nfs_dump_target || is_raw_dump_target; then + 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 + 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 + # Skip deprecated/invalid driver name or built-in module + _module_name=$(modinfo --set-version "$kdump_kver" -F name $_driver 2>/dev/null) + _module_filename=$(modinfo --set-version "$kdump_kver" -n $_driver 2>/dev/null) + if [ $? -ne 0 ] || [ -z "$_module_name" ] || [[ "$_module_filename" = *"(builtin)"* ]]; 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=$(get_persistent_dev $_target) + if [ -z "$_new_dev" ]; then + echo "Get persistent device name failed" + return 2 + fi + fi + + if ! findmnt $_target >/dev/null; then + echo "Dump target $_target is probably not mounted." + return 2 + fi + + if [[ "$_target" = "$(get_root_fs_device)" ]]; then + _new_mntpoint="/sysroot" + else + _new_mntpoint="/kdumproot/$(get_mntpoint_from_target $_target)" + fi + + _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" + return 0 + fi + + # if --mount argument present then match old and new target, mount + # point and file system. If any of them mismatches then rebuild + echo $_dracut_args | grep "\-\-mount" &> /dev/null + if [[ $? -eq 0 ]];then + set -- $(echo $_dracut_args | awk -F "--mount '" '{print $2}' | cut -d' ' -f1,2,3) + _old_dev=$1 + _old_mntpoint=$2 + _old_fstype=$3 + [[ $_new_dev = $_old_dev && $_new_mntpoint = $_old_mntpoint && $_new_fstype = $_old_fstype ]] && return 0 + # otherwise rebuild if target device is not a root device + else + [[ "$_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 + + return 1 +} + +# returns 0 if system is not modified +# returns 1 if system is modified +# returns 2 if system modification is invalid +check_system_modified() +{ + local ret + + [[ -f $TARGET_INITRD ]] || return 1 + + check_files_modified + ret=$? + if [ $ret -ne 0 ]; then + return $ret + fi + + check_dump_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 + fi + + return 0 +} + +check_rebuild() +{ + local capture_capable_initrd="1" + local _force_rebuild force_rebuild="0" + local _force_no_rebuild force_no_rebuild="0" + local ret system_modified="0" + + setup_initrd + + if [ $? -ne 0 ]; then + return 1 + fi + + _force_no_rebuild=`grep ^force_no_rebuild $KDUMP_CONFIG_FILE 2>/dev/null` + if [ $? -eq 0 ]; then + force_no_rebuild=`echo $_force_no_rebuild | cut -d' ' -f2` + if [ "$force_no_rebuild" != "0" ] && [ "$force_no_rebuild" != "1" ];then + echo "Error: force_no_rebuild value is invalid" + return 1 + fi + fi + + _force_rebuild=`grep ^force_rebuild $KDUMP_CONFIG_FILE 2>/dev/null` + 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" + 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" + return 1 + fi + + # Will not rebuild kdump initrd + if [ "$force_no_rebuild" == "1" ]; then + return 0 + fi + + #check to see if dependent files has been modified + #since last build of the image file + if [ -f $TARGET_INITRD ]; then + image_time=`stat -c "%Y" $TARGET_INITRD 2>/dev/null` + + #in case of fadump mode, check whether the default/target + #initrd is already built with dump capture capability + if [ "$DEFAULT_DUMP_MODE" == "fadump" ]; then + capture_capable_initrd=$(lsinitrd -f $DRACUT_MODULES_FILE $TARGET_INITRD | grep ^kdumpbase$ | wc -l) + fi + fi + + check_system_modified + ret=$? + if [ $ret -eq 2 ]; then + return 1 + elif [ $ret -eq 1 ];then + system_modified="1" + fi + + if [ $image_time -eq 0 ]; then + echo -n "No kdump initial ramdisk found."; echo + elif [ "$capture_capable_initrd" == "0" ]; then + echo -n "Rebuild $TARGET_INITRD with dump capture support"; echo + elif [ "$force_rebuild" != "0" ]; then + echo -n "Force rebuild $TARGET_INITRD"; echo + elif [ "$system_modified" != "0" ]; then + : + else + return 0 + fi + + echo "Rebuilding $TARGET_INITRD" + rebuild_initrd + return $? +} + +# 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() +{ + KEXEC_ARGS=$(prepare_kexec_args "${KEXEC_ARGS}") + KDUMP_COMMANDLINE=$(prepare_cmdline "${KDUMP_COMMANDLINE}" "${KDUMP_COMMANDLINE_REMOVE}" "${KDUMP_COMMANDLINE_APPEND}") + + if [ "$KDUMP_FILE_LOAD" == "on" ]; then + echo "Using kexec file based syscall." + KEXEC_ARGS="$KEXEC_ARGS -s" + fi + + $KEXEC $KEXEC_ARGS $standard_kexec_args \ + --command-line="$KDUMP_COMMANDLINE" \ + --initrd=$TARGET_INITRD $kdump_kernel + if [ $? == 0 ]; then + echo "kexec: loaded kdump kernel" + return 0 + else + echo "kexec: failed to load kdump kernel" >&2 + if [ "$KDUMP_FILE_LOAD" == "on" ]; then + echo "kexec_file_load() failed, please try kexec_load()" >&2 + fi + return 1 + fi +} + +check_ssh_config() +{ + while read config_opt config_val; do + case "$config_opt" in + sshkey) + # remove inline comments after the end of a directive. + if [ -f "$config_val" ]; then + # 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'" + fi + ;; + path) + SAVE_PATH=$config_val + ;; + ssh) + DUMP_TARGET=$config_val + ;; + *) + ;; + esac + done <<< "$(read_strip_comments $KDUMP_CONFIG_FILE)" + + #make sure they've configured kdump.conf for ssh dumps + local SSH_TARGET=`echo -n $DUMP_TARGET | sed -n '/.*@/p'` + if [ -z "$SSH_TARGET" ]; then + return 1 + fi + return 0 +} + +# ipv6 host address may takes a long time to be ready. +# Instead of checking against ipv6 address, we just check the network reachable +# by the return val of 'ssh' +check_and_wait_network_ready() +{ + local start_time=$(date +%s) + local warn_once=1 + local cur + local diff + local retval + local errmsg + + while true; do + errmsg=$(ssh -i $SSH_KEY_LOCATION -o BatchMode=yes $DUMP_TARGET mkdir -p $SAVE_PATH 2>&1) + retval=$? + + # ssh exits with the exit status of the remote command or with 255 if an error occurred + 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 + 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" + if [ $? -eq 0 ]; then + echo "Could not create $DUMP_TARGET:$SAVE_PATH, you probably need to run \"kdumpctl propagate\"" >&2 + return 1 + fi + + if [ $warn_once -eq 1 ]; then + echo "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" + # 60s time out + if [ $diff -gt 180 ]; then + break; + fi + sleep 1 + done + + echo "Could not create $DUMP_TARGET:$SAVE_PATH, ipaddr is not ready yet. You should check network connection" >&2 + return 1 +} + +check_ssh_target() +{ + check_and_wait_network_ready + if [ $? -ne 0 ]; then + return 1 + fi + return 0 +} + +propagate_ssh_key() +{ + check_ssh_config + if [ $? -ne 0 ]; then + echo "No ssh config specified in $KDUMP_CONFIG_FILE. Can't propagate" >&2 + exit 1 + fi + + local KEYFILE=$SSH_KEY_LOCATION + local errmsg="Failed to propagate ssh key" + + #Check to see if we already created key, if not, create it. + if [ -f $KEYFILE ]; then + echo "Using existing keys..." + else + echo -n "Generating new ssh keys... " + /usr/bin/ssh-keygen -t rsa -f $KEYFILE -N "" 2>&1 > /dev/null + echo "done." + fi + + #now find the target ssh user and server to contact. + SSH_USER=`echo $DUMP_TARGET | cut -d\ -f2 | cut -d@ -f1` + SSH_SERVER=`echo $DUMP_TARGET | sed -e's/\(.*@\)\(.*$\)/\2/'` + + #now send the found key to the found server + 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 + return 0 + else + echo $errmsg, $KEYFILE failed in transfer to $SSH_SERVER >&2 + exit 1 + fi +} + +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" +} + +check_current_fadump_status() +{ + # Check if firmware-assisted dump has been registered. + rc=`cat $FADUMP_REGISTER_SYS_NODE` + [ $rc -eq 1 ] && return 0 + return 1 +} + +check_current_status() +{ + if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + check_current_fadump_status + else + check_current_kdump_status + fi + + return $? +} + +save_raw() +{ + local kdump_dir + local raw_target + + 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" + return 1 + } + check_fs=$(lsblk --nodeps -npo FSTYPE $raw_target) + if [[ $(echo $check_fs | wc -w) -ne 0 ]]; then + echo "Warning: Detected '$check_fs' signature on $raw_target, data loss is expected." + return 0 + fi + kdump_dir=`grep ^path $KDUMP_CONFIG_FILE | cut -d' ' -f2-` + if [ -z "${kdump_dir}" ]; then + coredir="/var/crash/`date +"%Y-%m-%d-%H:%M"`" + else + coredir="${kdump_dir}/`date +"%Y-%m-%d-%H:%M"`" + fi + + mkdir -p "$coredir" + [ -d "$coredir" ] || { + echo "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" + # wipe makedumpfile header + dd if=/dev/zero of=$raw_target bs=1b count=1 2>/dev/null + else + rm -rf "$coredir" + fi + + return 0 +} + +local_fs_dump_target() +{ + local _target + + _target=$(egrep "^ext[234]|^xfs|^btrfs|^minix" /etc/kdump.conf) + if [ $? -eq 0 ]; then + echo $_target|awk '{print $2}' + fi +} + +path_to_be_relabeled() +{ + local _path _target _mnt="/" _rmnt + + if is_user_configured_dump_target; then + if is_mount_in_dracut_args; then + return; + fi + + _target=$(local_fs_dump_target) + if [[ -n "$_target" ]]; then + _mnt=$(findmnt -k -f -n -r -o TARGET $_target) + if [ -z "$_mnt" ]; then + return + fi + else + return + fi + fi + + _path=$(get_save_path) + # if $_path is masked by other mount, we will not relabel it. + _rmnt=$(df $_mnt/$_path 2>/dev/null | tail -1 | awk '{ print $NF }') + if [ "$_rmnt" == "$_mnt" ]; then + echo $_mnt/$_path + fi +} + +selinux_relabel() +{ + local _path _i _attr + + _path=$(path_to_be_relabeled) + if [ -z "$_path" ] || ! [ -d "$_path" ] ; then + return + fi + + for _i in $(find $_path); do + _attr=$(getfattr -m "security.selinux" $_i 2>/dev/null) + if [ -z "$_attr" ]; then + restorecon $_i; + fi + done +} + +check_fence_kdump_config() +{ + local hostname=`hostname` + local ipaddrs=`hostname -I` + local nodes=$(get_option_value "fence_kdump_nodes") + + for node in $nodes; do + if [ "$node" = "$hostname" ]; then + echo "Option fence_kdump_nodes cannot contain $hostname" + return 1 + fi + # node can be ipaddr + echo $ipaddrs | grep $node > /dev/null + if [ $? -eq 0 ]; then + echo "Option fence_kdump_nodes cannot contain $node" + return 1 + fi + done + + return 0 +} + +check_dump_feasibility() +{ + if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + return 0 + fi + + check_kdump_feasibility + return $? +} + +start_fadump() +{ + echo 1 > $FADUMP_REGISTER_SYS_NODE + if ! check_current_fadump_status; then + echo "fadump: failed to register" + return 1 + fi + + echo "fadump: registered successfully" + return 0 +} + +start_dump() +{ + if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + start_fadump + else + load_kdump + fi + + return $? +} + +check_failure_action_config() +{ + local default_option + local failure_action + local option="failure_action" + + default_option=$(awk '$1 ~ /^default$/ {print $2;}' $KDUMP_CONFIG_FILE) + failure_action=$(awk '$1 ~ /^failure_action$/ {print $2;}' $KDUMP_CONFIG_FILE) + + 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" + return 1 + fi + + if [ -n "$default_option" ]; then + option="default" + failure_action="$default_option" + fi + + case "$failure_action" in + reboot|halt|poweroff|shell|dump_to_rootfs) + return 0 + ;; + *) + echo $"Usage kdump.conf: $option {reboot|halt|poweroff|shell|dump_to_rootfs}" + return 1 + esac +} + +check_final_action_config() +{ + local final_action + + final_action=$(awk '$1 ~ /^final_action$/ {print $2;}' $KDUMP_CONFIG_FILE) + if [ -z "$final_action" ]; then + return 0 + else + case "$final_action" in + reboot|halt|poweroff) + return 0 + ;; + *) + echo $"Usage kdump.conf: final_action {reboot|halt|poweroff}" + return 1 + esac + fi +} + +start() +{ + check_dump_feasibility + if [ $? -ne 0 ]; then + echo "Starting kdump: [FAILED]" + return 1 + fi + + check_config + if [ $? -ne 0 ]; then + echo "Starting kdump: [FAILED]" + return 1 + fi + + if sestatus 2>/dev/null | grep -q "SELinux status.*enabled"; then + selinux_relabel + fi + + save_raw + if [ $? -ne 0 ]; then + echo "Starting kdump: [FAILED]" + return 1 + fi + + check_current_status + if [ $? == 0 ]; then + echo "Kdump already running: [WARNING]" + return 0 + fi + + if check_ssh_config; then + if ! check_ssh_target; then + echo "Starting kdump: [FAILED]" + return 1 + fi + fi + + check_rebuild + if [ $? != 0 ]; then + echo "Starting kdump: [FAILED]" + return 1 + fi + + start_dump + if [ $? != 0 ]; then + echo "Starting kdump: [FAILED]" + return 1 + fi + + echo "Starting kdump: [OK]" +} + +reload() +{ + check_current_status + if [ $? -ne 0 ]; then + echo "Kdump was not running: [WARNING]" + fi + + if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + reload_fadump + return $? + else + stop_kdump + fi + + if [ $? -ne 0 ]; then + echo "Stopping kdump: [FAILED]" + return 1 + fi + + echo "Stopping kdump: [OK]" + + setup_initrd + if [ $? -ne 0 ]; then + echo "Starting kdump: [FAILED]" + return 1 + fi + + start_dump + if [ $? -ne 0 ]; then + echo "Starting kdump: [FAILED]" + return 1 + fi + + echo "Starting kdump: [OK]" +} + +stop_fadump() +{ + echo 0 > $FADUMP_REGISTER_SYS_NODE + if check_current_fadump_status; then + echo "fadump: failed to unregister" + return 1 + fi + + echo "fadump: unregistered successfully" + return 0 +} + +stop_kdump() +{ + if [ "$KDUMP_FILE_LOAD" == "on" ]; then + $KEXEC -s -p -u + else + $KEXEC -p -u + fi + + if [ $? != 0 ]; then + echo "kexec: failed to unload kdump kernel" + return 1 + fi + + echo "kexec: unloaded kdump kernel" + return 0 +} + +reload_fadump() +{ + echo 1 > $FADUMP_REGISTER_SYS_NODE + if [ $? == 0 ]; then + echo "fadump: re-registered successfully" + return 0 + else + # FADump could fail on older kernel where re-register + # support is not enabled. Try stop/start from userspace + # to handle such scenario. + stop_fadump + if [ $? == 0 ]; then + start_fadump + return $? + fi + fi + + return 1 +} + +stop() +{ + if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + stop_fadump + else + stop_kdump + fi + + if [ $? != 0 ]; then + echo "Stopping kdump: [FAILED]" + return 1 + fi + + echo "Stopping kdump: [OK]" + return 0 +} + +rebuild() { + check_config + if [ $? -ne 0 ]; then + return 1 + fi + + if check_ssh_config; then + if ! check_ssh_target; then + return 1 + fi + fi + + setup_initrd + if [ $? -ne 0 ]; then + return 1 + fi + + echo "Rebuilding $TARGET_INITRD" + rebuild_initrd + return $? +} + +if [ ! -f "$KDUMP_CONFIG_FILE" ]; then + echo "Error: No kdump config file found!" >&2 + exit 1 +fi + +main () +{ + # Determine if the dump mode is kdump or fadump + determine_dump_mode + + case "$1" in + start) + if [ -s /proc/vmcore ]; then + save_core + reboot + else + start + fi + ;; + stop) + stop + ;; + status) + EXIT_CODE=0 + check_current_status + case "$?" in + 0) + echo "Kdump is operational" + EXIT_CODE=0 + ;; + 1) + echo "Kdump is not operational" + EXIT_CODE=3 + ;; + esac + exit $EXIT_CODE + ;; + reload) + reload + ;; + restart) + stop + start + ;; + rebuild) + rebuild + ;; + condrestart) + ;; + propagate) + propagate_ssh_key + ;; + showmem) + show_reserved_mem + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|reload|rebuild|propagate|showmem}" + exit 1 + esac +} + +# Other kdumpctl instances will block in queue, until this one exits +single_instance_lock + +# To avoid fd 9 leaking, we invoke a subshell, close fd 9 and call main. +# So that fd isn't leaking when main is invoking a subshell. +(exec 9<&-; main $1) + +exit $? diff --git a/kdumpctl.8 b/kdumpctl.8 new file mode 100644 index 0000000..ae97af7 --- /dev/null +++ b/kdumpctl.8 @@ -0,0 +1,50 @@ +.TH KDUMPCTL 8 2015-07-13 kexec-tools + +.SH NAME +kdumpctl \- control interface for kdump + +.SH SYNOPSIS +.B kdumpctl +.I COMMAND + +.SH DESCRIPTION +.B kdumpctl +is used to check or control the kdump service. +In most cases, you should use +.B systemctl +to start / stop / enable kdump service instead. However, +.B kdumpctl +provides more details for debug and a helper to setup ssh key authentication. + +.SH COMMANDS +.TP +.I start +Start the service. +.TP +.I stop +Stop the service. +.TP +.I status +Prints the current status of kdump service. +It returns non-zero value if kdump is not operational. +.TP +.I restart +Is equal to +.I start; stop +.TP +.I reload +reload crash kernel image and initramfs without triggering a rebuild. +.TP +.I rebuild +rebuild the crash kernel initramfs. +.TP +.I propagate +Helps to setup key authentication for ssh storage since it's +impossible to use password authentication during kdump. +.TP +.I showmem +Prints the size of reserved memory for crash kernel in megabytes. + +.SH "SEE ALSO" +.BR kdump.conf (5), +.BR mkdumprd (8) diff --git a/kexec-Add-quick-kexec-support.patch b/kexec-Add-quick-kexec-support.patch new file mode 100644 index 0000000..b4a7276 --- /dev/null +++ b/kexec-Add-quick-kexec-support.patch @@ -0,0 +1,118 @@ +From 893ef61ca2b1e857b950654c1bb57f3624df5dc5 Mon Sep 17 00:00:00 2001 +From: snoweay <snoweay@163.com> +Date: Wed, 12 Aug 2020 07:53:13 -0400 +Subject: [PATCH] kexec: Add quick kexec support + +Add quick kexec option -q and flags. + +In normal kexec, relocating kernel may cost 5 ~ 10 seconds, to +copy all segments from vmalloced memory to kernel boot memory, +because of disabled mmu. + +We introduce quick kexec to save time of copying memory as above, +just like kdump(kexec on crash), by using reserved memory. + +We also add this support in syscall kexec_load of linux kernel +through flags of KEXEC_QUICK. + +Add KEXEC_FLAGS_MAX to avoid conflicting with KEXEC_LIVE_UPDATE. +--- + kexec/kexec-syscall.h | 2 ++ + kexec/kexec-xen.h | 2 +- + kexec/kexec.c | 10 ++++++++++ + kexec/kexec.h | 4 +++- + 4 files changed, 16 insertions(+), 2 deletion(-) + +diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h +index bea29d4..5f22353 100644 +--- a/kexec/kexec-syscall.h ++++ b/kexec/kexec-syscall.h +@@ -109,6 +109,8 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd, + + #define KEXEC_ON_CRASH 0x00000001 + #define KEXEC_PRESERVE_CONTEXT 0x00000002 ++#define KEXEC_QUICK 0x00000004 ++#define KEXEC_FLAGS_MAX 0x00000010 + #define KEXEC_ARCH_MASK 0xffff0000 + + /* Flags for kexec file based system call */ +diff --git a/kexec/kexec-xen.h b/kexec/kexec-xen.h +index 70fb576..d417c90 100644 +--- a/kexec/kexec-xen.h ++++ b/kexec/kexec-xen.h +@@ -79,7 +79,7 @@ extern int __xc_interface_close(xc_interface *xch); + #endif + + #ifndef KEXEC_LIVE_UPDATE +-#define KEXEC_LIVE_UPDATE 0x00000004 ++#define KEXEC_LIVE_UPDATE KEXEC_FLAGS_MAX + #endif + + int xen_get_kexec_range(int range, uint64_t *start, uint64_t *end); +diff --git a/kexec/kexec.c b/kexec/kexec.c +index f63b36b..5b8beca 100644 +--- a/kexec/kexec.c ++++ b/kexec/kexec.c +@@ -1009,6 +1009,7 @@ void usage(void) + " -l, --load Load the new kernel into the\n" + " current kernel.\n" + " -p, --load-panic Load the new kernel for use on panic.\n" ++ " -q, --load-quick Load the new kernel to quick kexec\n" + " -u, --unload Unload the current kexec target kernel.\n" + " If capture kernel is being unloaded\n" + " specify -p with -u.\n" +@@ -1340,6 +1341,7 @@ int main(int argc, char *argv[]) + int has_opt_load = 0; + int do_load = 1; + int do_exec = 0; ++ int do_quick = 0; + int do_load_jump_back_helper = 0; + int do_shutdown = 1; + int do_sync = 1, skip_sync = 0; +@@ -1460,6 +1462,14 @@ int main(int argc, char *argv[]) + kexec_file_flags |= KEXEC_FILE_ON_CRASH; + kexec_flags = KEXEC_ON_CRASH; + break; ++ case OPT_QUICK: ++ do_load = 1; ++ do_exec = 0; ++ do_shutdown = 0; ++ do_quick = 1; ++ kexec_flags = KEXEC_QUICK; ++ skip_checks = 1; ++ break; + case OPT_MEM_MIN: + mem_min = strtoul(optarg, &endptr, 0); + if (*endptr) { +diff --git a/kexec/kexec.h b/kexec/kexec.h +index 595dd68..9cbc77f 100644 +--- a/kexec/kexec.h ++++ b/kexec/kexec.h +@@ -218,6 +218,7 @@ extern int file_types; + #define OPT_UNLOAD 'u' + #define OPT_TYPE 't' + #define OPT_PANIC 'p' ++#define OPT_QUICK 'q' + #define OPT_KEXEC_FILE_SYSCALL 's' + #define OPT_KEXEC_SYSCALL 'c' + #define OPT_KEXEC_SYSCALL_AUTO 'a' +@@ -249,6 +250,7 @@ extern int file_types; + { "entry", 1, 0, OPT_ENTRY }, \ + { "type", 1, 0, OPT_TYPE }, \ + { "load-panic", 0, 0, OPT_PANIC }, \ ++ { "load-quick", 0, 0, OPT_QUICK }, \ + { "mem-min", 1, 0, OPT_MEM_MIN }, \ + { "mem-max", 1, 0, OPT_MEM_MAX }, \ + { "reuseinitrd", 0, 0, OPT_REUSE_INITRD }, \ +@@ -259,7 +261,7 @@ extern int file_types; + { "status", 0, 0, OPT_STATUS }, \ + { "print-ckr-size", 0, 0, OPT_PRINT_CKR_SIZE }, \ + +-#define KEXEC_OPT_STR "h?vdfixyluet:pscaS" ++#define KEXEC_OPT_STR "h?vdfixyluet:pqscaS" + + extern void dbgprint_mem_range(const char *prefix, struct memory_range *mr, int nr_mr); + extern void die(const char *fmt, ...) +-- +2.30.0 + diff --git a/kexec-Quick-kexec-implementation-for-arm64.patch b/kexec-Quick-kexec-implementation-for-arm64.patch new file mode 100644 index 0000000..19c6338 --- /dev/null +++ b/kexec-Quick-kexec-implementation-for-arm64.patch @@ -0,0 +1,143 @@ +From 5a302cd06079a285cb24a74c0f60b26866ae4e4d Mon Sep 17 00:00:00 2001 +From: snoweay <snoweay@163.com> +Date: Wed, 12 Aug 2020 07:59:06 -0400 +Subject: [PATCH] kexec: Quick kexec implementation for arm64 + +Implement quick kexec on arch/arm64. + +Locate kernel segments from reserved memory of range "Quick kexec". +--- + kexec/arch/arm64/iomem.h | 1 + + kexec/arch/arm64/kexec-arm64.c | 42 +++++++++++++++++++++++++----------- + kexec/arch/arm64/kexec-image-arm64.c | 11 ++++++++++ + 3 files changed, 41 insertions(+), 13 deletions(-) + +diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h +index 45d7953..f283f50 100644 +--- a/kexec/arch/arm64/iomem.h ++++ b/kexec/arch/arm64/iomem.h +@@ -7,5 +7,6 @@ + #define KERNEL_DATA "Kernel data\n" + #define CRASH_KERNEL "Crash kernel\n" + #define IOMEM_RESERVED "reserved\n" ++#define QUICK_KEXEC "Quick kexec\n" + + #endif +diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c +index 219ec49..8a3bb69 100644 +--- a/kexec/arch/arm64/kexec-arm64.c ++++ b/kexec/arch/arm64/kexec-arm64.c +@@ -99,6 +99,9 @@ uint64_t get_vp_offset(void) + return arm64_mem.vp_offset; + } + ++/* Reserved memory for quick kexec. */ ++struct memory_range quick_reserved_mem; ++ + /** + * arm64_process_image_header - Process the arm64 image header. + * +@@ -627,23 +630,33 @@ on_error: + return result; + } + +-unsigned long arm64_locate_kernel_segment(struct kexec_info *info) ++static unsigned long locate_hole_from_range(struct memory_range *range) + { + unsigned long hole; ++ unsigned long hole_end; + +- if (info->kexec_flags & KEXEC_ON_CRASH) { +- unsigned long hole_end; ++ hole = (range->start < mem_min ? mem_min : range->start); ++ hole = _ALIGN_UP(hole, MiB(2)); ++ hole_end = hole + arm64_mem.text_offset + arm64_mem.image_size; + +- hole = (crash_reserved_mem[usablemem_rgns.size - 1].start < mem_min ? +- mem_min : crash_reserved_mem[usablemem_rgns.size - 1].start); +- hole = _ALIGN_UP(hole, MiB(2)); +- hole_end = hole + arm64_mem.text_offset + arm64_mem.image_size; ++ if ((hole_end > mem_max) || ++ (hole_end > range->end)) { ++ dbgprintf("%s: Kexec kernel out of range\n", __func__); ++ hole = ULONG_MAX; ++ } + +- if ((hole_end > mem_max) || +- (hole_end > crash_reserved_mem[usablemem_rgns.size - 1].end)) { +- dbgprintf("%s: Crash kernel out of range\n", __func__); +- hole = ULONG_MAX; +- } ++ return hole; ++} ++ ++unsigned long arm64_locate_kernel_segment(struct kexec_info *info) ++{ ++ unsigned long hole; ++ ++ if (info->kexec_flags & KEXEC_ON_CRASH) { ++ hole = locate_hole_from_range( ++ &crash_reserved_mem[usablemem_rgns.size - 1]); ++ } else if (info->kexec_flags & KEXEC_QUICK) { ++ hole = locate_hole_from_range(&quick_reserved_mem); + } else { + hole = locate_hole(info, + arm64_mem.text_offset + arm64_mem.image_size, +@@ -709,6 +722,8 @@ int arm64_load_other_segments(struct kexec_info *info, + hole_min = image_base + arm64_mem.image_size; + if (info->kexec_flags & KEXEC_ON_CRASH) + hole_max = crash_reserved_mem[usablemem_rgns.size - 1].end; ++ else if (info->kexec_flags & KEXEC_QUICK) ++ hole_max = quick_reserved_mem.end; + else + hole_max = ULONG_MAX; + +@@ -1050,7 +1050,8 @@ static bool to_be_excluded(char *str, unsigned long long start, unsigned long lo + + if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) || + !strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) || +- !strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA))) ++ !strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) || ++ !strncmp(str, QUICK_KEXEC, strlen(QUICK_KEXEC))) + return false; + else + return true; +diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c +index aa8f2e2..f22db62 100644 +--- a/kexec/arch/arm64/kexec-image-arm64.c ++++ b/kexec/arch/arm64/kexec-image-arm64.c +@@ -13,6 +13,9 @@ + #include "kexec-arm64.h" + #include "kexec-syscall.h" + #include "arch/options.h" ++#include "iomem.h" ++ ++extern struct memory_range quick_reserved_mem; + + int image_arm64_probe(const char *kernel_buf, off_t kernel_size) + { +@@ -38,6 +41,7 @@ int image_arm64_load(int argc, char **argv, const char *kernel_buf, + { + const struct arm64_image_header *header; + unsigned long kernel_segment; ++ unsigned long start, end; + int result; + + if (info->file_mode) { +@@ -61,6 +65,13 @@ int image_arm64_load(int argc, char **argv, const char *kernel_buf, + return 0; + } + ++ if (info->kexec_flags & KEXEC_QUICK) ++ parse_iomem_single(QUICK_KEXEC, &start, &end); ++ dbgprintf("%s: Get Quick kexec reserved mem from 0x%016lx to 0x%016lx\n", ++ __func__, start, end); ++ quick_reserved_mem.start = start; ++ quick_reserved_mem.end = end; ++ + header = (const struct arm64_image_header *)(kernel_buf); + + if (arm64_process_image_header(header)) +-- +2.9.5 + diff --git a/kexec-tools.spec b/kexec-tools.spec new file mode 100644 index 0000000..160b456 --- /dev/null +++ b/kexec-tools.spec @@ -0,0 +1,450 @@ +%global eppic_ver e8844d3793471163ae4a56d8f95897be9e5bd554 +%global eppic_shortver %(c=%{eppic_ver}; echo ${c:0:7}) +%global mkdf_ver 1.7.3 + +Name: kexec-tools +Version: 2.0.26 +Release: 6 +License: GPLv2 +Summary: The kexec/kdump userspace component +URL: https://www.kernel.org/ +Source0: http://kernel.org/pub/linux/utils/kernel/kexec/%{name}-%{version}.tar.xz +Source1: kdumpctl +Source2: kdump.sysconfig +Source3: kdump.sysconfig.x86_64 +Source4: kdump.sysconfig.i386 +Source5: kdump.sysconfig.ppc64 +Source7: mkdumprd +Source8: kdump.conf +Source9: https://github.com/makedumpfile/makedumpfile/releases/download/%{mkdf_ver}/makedumpfile-%{mkdf_ver}.tar.gz +Source12: mkdumprd.8 +Source13: 98-kexec.rules +Source15: kdump.conf.5 +Source16: kdump.service +Source18: kdump.sysconfig.s390x +Source19: https://github.com/lucchouina/eppic/archive/%{eppic_ver}/eppic-%{eppic_shortver}.tar.gz +Source20: kdump-lib.sh +Source21: kdump-in-cluster-environment.txt +Source22: kdump-dep-generator.sh +Source23: kdump-lib-initramfs.sh +Source24: kdump.sysconfig.ppc64le +Source25: kdumpctl.8 +Source26: live-image-kdump-howto.txt +Source27: early-kdump-howto.txt +Source28: kdump-udev-throttler +Source29: kdump.sysconfig.aarch64 +Source30: kdump.sysconfig.loongarch64 +Source31: kdump.sysconfig.riscv64 + +Source100: dracut-kdump.sh +Source101: dracut-module-setup.sh +Source102: dracut-monitor_dd_progress +Source103: dracut-kdump-error-handler.sh +Source104: dracut-kdump-emergency.service +Source105: dracut-kdump-error-handler.service +Source106: dracut-kdump-capture.service +Source107: dracut-kdump-emergency.target +Source108: dracut-early-kdump.sh +Source109: dracut-early-kdump-module-setup.sh +Source110: dracut-kdump-wait-for-target.sh + +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd +Requires(pre): coreutils sed zlib +Requires: dracut >= 047-34.git20180604 +Requires: dracut-network >= 044-117 +Requires: dracut-squash >= 049-4 +Requires: ethtool +BuildRequires: zlib-devel elfutils-devel-static glib2-devel bzip2-devel ncurses-devel bison flex lzo-devel snappy-devel +BuildRequires: pkgconfig intltool gettext +BuildRequires: systemd-units +BuildRequires: automake autoconf libtool +%ifarch %{ix86} x86_64 +Obsoletes: diskdumputils netdump kexec-tools-eppic +%endif + +%ifnarch s390x +Requires: systemd-udev%{?_isa} +%endif + +%undefine _hardened_build + +Patch0001: add-secure-compile-options-for-makedumpfile.patch +Patch0002: kexec-Add-quick-kexec-support.patch +Patch0003: kexec-Quick-kexec-implementation-for-arm64.patch + +%ifarch sw_64 +Patch0004: sw_64.patch +Patch0005: makedumpfile-1.7.2-sw.patch +%endif + +%ifarch riscv64 +Patch0006: kexec-tools-Add-riscv-support.patch +Patch0007: riscv-makedumpfile-1.7.3.patch +%endif + +%ifarch loongarch64 +Patch0008: Add-loongarch-iomem.h.patch +%endif + +%description +kexec-tools provides /sbin/kexec binary that facilitates a new +kernel to boot using the kernel's kexec feature either on a +normal or a panic reboot. This package contains the /sbin/kexec +binary and ancillary utilities that together form the userspace +component of the kernel's kexec feature. + +%package help +Summary: Doc files for %{name} +Buildarch: noarch + +%description help +The %{name}-help package contains doc files for %{name}. + +%prep +%setup -q + +mkdir -p -m755 kcp +tar -z -x -v -f %{SOURCE9} +tar -z -x -v -f %{SOURCE19} + +%autopatch -p1 + +%build +autoreconf +%configure --sbindir=/usr/sbin \ + CFLAGS="${CFLAGS} -fstack-protector-strong -Wl,-z,now -pie -fPIC -fPIE" +rm -f kexec-tools.spec.in +# for docs +cp %{SOURCE21} %{SOURCE26} %{SOURCE27} . + +make +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 ppc64le riscv64 +make -C eppic-%{eppic_ver}/libeppic +make -C makedumpfile-%{mkdf_ver} LINKTYPE=dynamic USELZO=on USESNAPPY=on +make -C makedumpfile-%{mkdf_ver} LDFLAGS="$LDFLAGS -I../eppic-%{eppic_ver}/libeppic -L../eppic-%{eppic_ver}/libeppic" eppic_makedumpfile.so +%endif + +%install +mkdir -p -m755 %{buildroot}/usr/sbin +mkdir -p -m755 %{buildroot}%{_sysconfdir}/sysconfig +mkdir -p -m755 %{buildroot}%{_localstatedir}/crash +mkdir -p -m755 %{buildroot}%{_mandir}/man8/ +mkdir -p -m755 %{buildroot}%{_mandir}/man5/ +mkdir -p -m755 %{buildroot}%{_docdir} +mkdir -p -m755 %{buildroot}%{_datadir}/kdump +mkdir -p -m755 %{buildroot}%{_udevrulesdir} +mkdir -p %{buildroot}%{_unitdir} +mkdir -p -m755 %{buildroot}%{_bindir} +mkdir -p -m755 %{buildroot}%{_libdir} +mkdir -p -m755 %{buildroot}%{_prefix}/lib/kdump + +%ifarch riscv64 +sed -i 's/--initrd=$TARGET_INITRD //g' %{SOURCE1} +%endif + +install -m 755 %{SOURCE1} %{buildroot}%{_bindir}/kdumpctl + +install -m 755 build/sbin/kexec %{buildroot}/usr/sbin/kexec +install -m 755 build/sbin/vmcore-dmesg %{buildroot}/usr/sbin/vmcore-dmesg +install -m 644 build/man/man8/kexec.8 %{buildroot}%{_mandir}/man8/ +install -m 644 build/man/man8/vmcore-dmesg.8 %{buildroot}%{_mandir}/man8/ + +SYSCONFIG=%{_sourcedir}/kdump.sysconfig.%{_target_cpu} +[ -f $SYSCONFIG ] || SYSCONFIG=%{_sourcedir}/kdump.sysconfig.%{_arch} +[ -f $SYSCONFIG ] || SYSCONFIG=%{_sourcedir}/kdump.sysconfig +install -m 644 $SYSCONFIG %{buildroot}%{_sysconfdir}/sysconfig/kdump + +install -m 755 %{SOURCE7} %{buildroot}/usr/sbin/mkdumprd +install -m 644 %{SOURCE8} %{buildroot}%{_sysconfdir}/kdump.conf +install -m 644 kexec/kexec.8 %{buildroot}%{_mandir}/man8/kexec.8 +install -m 644 %{SOURCE12} %{buildroot}%{_mandir}/man8/mkdumprd.8 +install -m 644 %{SOURCE25} %{buildroot}%{_mandir}/man8/kdumpctl.8 +install -m 755 %{SOURCE20} %{buildroot}%{_prefix}/lib/kdump/kdump-lib.sh +install -m 755 %{SOURCE23} %{buildroot}%{_prefix}/lib/kdump/kdump-lib-initramfs.sh +install -m 755 %{SOURCE28} $RPM_BUILD_ROOT%{_udevrulesdir}/../kdump-udev-throttler +install -m 644 %{SOURCE15} %{buildroot}%{_mandir}/man5/kdump.conf.5 +install -m 644 %{SOURCE16} %{buildroot}%{_unitdir}/kdump.service +install -m 755 -D %{SOURCE22} %{buildroot}%{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh +install -m 644 %{SOURCE13} $RPM_BUILD_ROOT%{_udevrulesdir}/98-kexec.rules + +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 ppc64le riscv64 +install -m 755 makedumpfile-%{mkdf_ver}/makedumpfile $RPM_BUILD_ROOT/usr/sbin/makedumpfile +install -m 644 makedumpfile-%{mkdf_ver}/makedumpfile.8 $RPM_BUILD_ROOT/%{_mandir}/man8/makedumpfile.8 +install -m 644 makedumpfile-%{mkdf_ver}/makedumpfile.conf.5 $RPM_BUILD_ROOT/%{_mandir}/man5/makedumpfile.conf.5 +install -m 644 makedumpfile-%{mkdf_ver}/makedumpfile.conf $RPM_BUILD_ROOT/%{_sysconfdir}/makedumpfile.conf.sample +install -m 755 makedumpfile-%{mkdf_ver}/eppic_makedumpfile.so $RPM_BUILD_ROOT/%{_libdir}/eppic_makedumpfile.so +mkdir -p $RPM_BUILD_ROOT/usr/share/makedumpfile/eppic_scripts/ +install -m 644 makedumpfile-%{mkdf_ver}/eppic_scripts/* $RPM_BUILD_ROOT/usr/share/makedumpfile/eppic_scripts/ +%endif + +%define remove_dracut_prefix() %(echo -n %1|sed 's/.*dracut-//g') +%define remove_dracut_early_kdump_prefix() %(echo -n %1|sed 's/.*dracut-early-kdump-//g') + +# For dracut modules +mkdir -p -m755 %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase +cp %{SOURCE100} %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE100}} +cp %{SOURCE101} %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE101}} +cp %{SOURCE102} %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE102}} +cp %{SOURCE103} %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE103}} +cp %{SOURCE104} %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE104}} +cp %{SOURCE105} %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE105}} +cp %{SOURCE106} %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE106}} +cp %{SOURCE107} %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE107}} +cp %{SOURCE110} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE110}} +chmod 755 %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE100}} +chmod 755 %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE101}} +mkdir -p -m755 %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump +cp %{SOURCE108} %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} +cp %{SOURCE109} %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE109}} +chmod 755 %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} +chmod 755 %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE109}} +chmod 755 %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE103}} + +%define dracutlibdir %{_prefix}/lib/dracut +# For custom dracut modules +mkdir -p %{buildroot}/%{dracutlibdir}/modules.d/ +mv %{buildroot}/etc/kdump-adv-conf/kdump_dracut_modules/* %{buildroot}/%{dracutlibdir}/modules.d/ + +%post +%systemd_post kdump.service + +touch /etc/kdump.conf +# Fix up broken boxes +if [ -d /proc/bus/mckinley ] +then + # for HP zx1 machines + sed -e's/\(^KDUMP_COMMANDLINE_APPEND.*\)\("$\)/\1 machvec=dig"/' \ + /etc/sysconfig/kdump > /etc/sysconfig/kdump.new + mv /etc/sysconfig/kdump.new /etc/sysconfig/kdump +elif [ -d /proc/sgi_sn ] +then + # for SGI SN boxes + sed -e's/\(^KEXEC_ARGS.*\)\("$\)/\1 --noio"/' \ + /etc/sysconfig/kdump > /etc/sysconfig/kdump.new + mv /etc/sysconfig/kdump.new /etc/sysconfig/kdump +fi + + +%postun +%systemd_postun_with_restart kdump.service + +%preun +%systemd_preun kdump.service + +%triggerun -- kexec-tools < 2.0.2-3 +# Save runlevel info for future migration +/usr/bin/systemd-sysv-convert --save kdump >/dev/null 2>&1 ||: +# Not needed after uninstall +/sbin/chkconfig --del kdump >/dev/null 2>&1 || : +/bin/systemctl try-restart kdump.service >/dev/null 2>&1 || : + +%triggerin -- kernel-kdump +touch %{_sysconfdir}/kdump.conf + +%triggerpostun -- kernel kernel-xen kernel-debug kernel-PAE kernel-kdump +# Search for kernel installs, if not found, remove kdump initrd +IMGDIR=/boot +for i in `ls $IMGDIR/initramfs*kdump.img 2>/dev/null` +do + KDVER=`echo $i | sed -e's/^.*initramfs-//' -e's/kdump.*$//'` + if [ ! -e $IMGDIR/vmlinuz-$KDVER ] + then + rm -f $i + fi +done + + +%files +%doc News +%doc TODO +%license COPYING +%config(noreplace,missingok) %{_sysconfdir}/sysconfig/kdump +%config(noreplace,missingok) %verify(not mtime) %{_sysconfdir}/kdump.conf +%config %{_udevrulesdir} +%{_udevrulesdir}/../kdump-udev-throttler +%dir %{_localstatedir}/crash +/usr/sbin/kexec +/usr/sbin/mkdumprd +/usr/sbin/vmcore-dmesg +%{_bindir}/* +%{_datadir}/kdump +%{_prefix}/lib/kdump +%{dracutlibdir}/modules.d/* +%{_unitdir}/kdump.service +%{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 ppc64le riscv64 +%{_libdir}/eppic_makedumpfile.so +/usr/share/makedumpfile/ +%endif +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 ppc64le riscv64 +%{_sysconfdir}/makedumpfile.conf.sample +%endif +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 ppc64le riscv64 +/usr/sbin/makedumpfile +%endif + +%files help +%doc early-kdump-howto.txt +%doc kdump-in-cluster-environment.txt +%doc live-image-kdump-howto.txt +%{_mandir}/man8/kdumpctl.8.gz +%{_mandir}/man8/kexec.8.gz +%{_mandir}/man8/mkdumprd.8.gz +%{_mandir}/man8/vmcore-dmesg.8.gz +%{_mandir}/man5/* +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 ppc64le riscv64 +%{_mandir}/man8/makedumpfile.8.gz +%endif + +%changelog +* Mon Jul 8 2024 chenhaixiang <chenhaixiang3@huawei.com> - 2.0.26-6 +- Undo the deletion of rd.lvm.lv in cmdline + +* Mon May 13 2024 Wenhua Huang <huangwenhua@kylinos.cn> - 2.0.26-5 +- Add loongarch iomem.h + +* Thu Apr 18 2024 Mingzheng Xing <xingmingzheng@iscas.ac.cn> - 2.0.26-4 +- Add riscv64 support + +* Mon Jan 30 2023 chenhaixiang <chenhaixiang3@huawei.com> - 2.0.26-3 +- update makedumpfile to makedumpfile-1.7.3 + +* Tue Jan 2 2024 peng.zou <peng.zou@shingroup.cn> - 2.0.26-2 +- Add ppc64le support + +* Mon Jan 30 2023 chenhaixiang <chenhaixiang3@huawei.com> - 2.0.26-1 +- update to kexec-tools-2.0.26.1 + +* Fri Dec 30 2022 chenhaixiang <chenhaixiang3@huawei.com> - 2.0.23-11 +- fix shellcheck error in dracut module setup + +* Mon Dec 12 2022 guojiancheng <jiancheng.guo@i-soft.com.cn> - 2.0.23-10 +- Add sw support + +* Tue Nov 17 2022 doupengda <doupengda@loongson.cn> - 2.0.23-9 +- add loongarch64 support + +* Wed Aug 24 2022 chenhaixiang <chenhaixiang3@huawei.com> - 2.0.23-8 +- arm64: fix PAGE_OFFSET calc for flipped mm + +* Tue Aug 23 2022 chenhaixiang <chenhaixiang3@huawei.com> - 2.0.23-7 +- kdumpctl:ignore deprecated and invalid kdump config option + +* Wed Aug 3 2022 chenhaixiang <chenhaixiang3@huawei.com> - 2.0.23-6 +- fix CVE-2021-20269 + +* Fri Mar 11 2022 wangbin <wangbin224@huawei.com> - 2.0.23-5 +- packing 98-kexec.rules instead of 98-kexec.rules.ppc64 + +* Wed Feb 23 2022 wangbin <wangbin224@huawei.com> - 2.0.23-4 +- arm64/crashdump: deduce paddr of _text based on kernel code size + +* Wed Feb 23 2022 snoweay <snoweay@163.com> - 2.0.23-3 +- Fix conflicts between quick kexec and load-live-update with xen. + +* Wed Dec 29 2021 zhouwenpei <zhouwenpei1@huawei.com> - 2.0.23-2 +- modify the patch header + +* Sat Dec 25 2021 zhouwenpei <zhouwenpei1@huawei.com> - 2.0.23-1 +- update to 2.0.23 + +* Tue Jul 27 2021 zhouwenpei <zhouwenpei1@huawei.com> - 2.0.20-7 +- fix build fail caused by file format not recognized + +* Sat Mar 27 2021 yangzhuangzhuang <yangzhuangzhuang1@huawei.com> - 2.0.20-6 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:Fix bug: Filed to generate the vmcore file in the ARM architecture + Fix bug: Filed to generate the vmcore-dmesg.txt file in the ARM architecture + +* Mon Mar 22 2021 yangzhuangzhuang <yangzhuangzhuang1@huawei.com> - 2.0.20-5 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:support more than one crash kernel regions. + Fix bugs of unuseable quick kexec on arm64, becaues of arm64-kexec-allocate-memory-space-avoiding-reserved-regions + excluding QUICK_KEXEC memory region. + +* Mon Sep 14 2020 zhangruifang2020 <zhangruifang1@huawei.com> - 2.0.20-4 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:sychronize git patches to enhance quality + +* Thu Sep 10 2020 zhangruifang2020 <zhangruifang1@huawei.com> - 2.0.20-3 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix issue about iomem file that contains too many contens.As a result,the kdump service failed. + +* Thu Aug 13 2020 snoweay <snoweay@163.com> - 2.0.20-2 +- Add support for quick kexec + kexec: Add quick kexec support + arm64: Quick kexec implementation for arm64 + +* Thu Jul 23 2020 zhangxingliang <zhangxingliang3@huawei.com> - 2.0.20-1 +- Type:update +- ID:NA +- SUG:NA +- DESC:update to 2.0.20 + +* Thu May 14 2020 openEuler Buildteam <buildteam@openeuler.org> - 2.0.17-16 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:fix kdump stuck + +* Wed Jan 1 2020 openEuler Buildteam <buildteam@openeuler.org> - 2.0.17-15 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:modify patch + +* Tue Dec 31 2019 Jialong Chen <chenjialong@huawei.com> - 2.0.17-14 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:modify SECTION_SIZE_BITS to 30 and keep the same as the kernel configuration. + add executable permissions for kdump-error-handler.sh. + +* Thu Dec 19 2019 chengquan <chengquan3@huawei.com> - 2.0.17-13 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:add url for package + +* Wed Sep 25 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.0-17.12 +- add secure compile options and merge bugfix patches from community + xen: Avoid overlapping segments in low memory + x86: Check /proc/mounts before mtab for mounts + x86: Find mounts by FS type, not name + kexec/kexec.c: Add the missing close() for fd used for kexec_file_load() + kexec-uImage-arm64.c: Fix return value of uImage_arm64_probe() + kexec/kexec-zlib.h: Add 'is_zlib_file()' helper function + kexec/arm64: Add support for handling zlib compressed (Image.gz) image + +* Sat Sep 21 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.0-17.11 +- Package init + +* Thu Aug 22 2019 Yeqing Peng<pengyeqing@huawei.com> - 2.0-17.10.h1 +- Type:bugfix +- ID:NA +- SUG:restart +- DESC: fix bugs as follows: + 1.dmesg fix infinite loop if log buffer wraps around. + 2.arm64 error out if kernel command line is too long. + 3.fix an error that can not parse the e820 reserved region. + 4.x86 fix BAD_FREE in get_efi_runtime_map(). + 5.fix check against 'fdt_add_subnode' return value. + 6.arm64 add error handling check against return value of 'set_bootargs()'. + 7.fix adding '/chosen' node for cases where it is not available in dtb + passed via --dtb option. + 8.fix '/chosen' v/s 'chosen' node being passed to fdt helper functions. + 9.arm64 wipe old initrd addresses when patching the DTB. + 10.arm64 increase the command line buf space to 1536. + 11.arm64 bugfix get the paddr of mem_section return error address. + 12.arm64 support more than one crash kernel regions. + 13.modify SECTIONS_SIZE_BITS to 27 for arm64. diff --git a/live-image-kdump-howto.txt b/live-image-kdump-howto.txt new file mode 100644 index 0000000..1695a1c --- /dev/null +++ b/live-image-kdump-howto.txt @@ -0,0 +1,25 @@ +Kdump now works on live images with some manual configurations. Here is the step +by step guide. + +1. Enable crashkernel reservation + +Since there isn't any config file that can be used to configure kernel +parameters for live images before booting them, we have to append 'crashkernel' +argument in boot menu every time we boot a live image. + +2. Change dump target in /etc/kdump.conf + +When kdump kernel boots in a live environment, the default target /var/crash is +in RAM so you need to change the dump target to an external disk or a network +dump target. + +Besides, make sure that "default dump_to_rootfs" is not specified. + +3. Start kdump service + + $ kdumpctl start + +4. Trigger a kdump test + + $ echo 1 > /proc/sys/kernel/sysrq + $ echo c > /proc/sysrq-trigger diff --git a/mkdumprd b/mkdumprd new file mode 100644 index 0000000..35f5eed --- /dev/null +++ b/mkdumprd @@ -0,0 +1,439 @@ +#!/bin/bash --norc +# New mkdumprd +# +# Copyright 2011 Red Hat, Inc. +# +# Written by Cong Wang <amwang@redhat.com> +# + +[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut +. $dracutbasedir/dracut-functions.sh +. /lib/kdump/kdump-lib.sh +export IN_KDUMP=1 + +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\"" + +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\"" +} + +add_dracut_sshkey() { + add_dracut_arg "--sshkey" "\"$1\"" +} + +# caller should ensure $1 is valid and mounted in 1st kernel +to_mount() { + local _dev=$1 _source _target _fstype _options _mntopts _pdev + + _source=$(findmnt -k -f -n -r -o SOURCE $_dev) + _target=$(get_mntpoint_from_target $_dev) + # mount under /sysroot if dump to root disk or mount under + #/kdumproot/$_target in other cases in 2nd kernel. systemd + #will be in charge to umount it. + + if [ "$_target" = "/" ];then + _target="/sysroot" + else + _target="/kdumproot/$_target" + fi + + _fstype=$(findmnt -k -f -n -r -o FSTYPE $_dev) + [[ -e /etc/fstab ]] && _options=$(findmnt --fstab -f -n -r -o OPTIONS $_dev) + if [ -z "$_options" ]; then + _options=$(findmnt -k -f -n -r -o OPTIONS $_dev) + if [[ $_fstype == "nfs"* ]]; then + _options=$(echo $_options | sed 's/,addr=[^,]*//') + _options=$(echo $_options | sed 's/,proto=[^,]*//') + _options=$(echo $_options | sed 's/,clientaddr=[^,]*//') + fi + fi + # mount fs target as rw in 2nd kernel + _options=$(echo $_options | sed 's/\(^\|,\)ro\($\|,\)/\1rw\2/g') + # filter out 'noauto' here, it will be force appended later, avoid duplication + _options=$(echo $_options | sed 's/\(^\|,\)noauto\($\|,\)/\1/g') + # drop nofail or nobootwait + _options=$(echo $_options | sed 's/\(^\|,\)nofail\($\|,\)/\1/g') + _options=$(echo $_options | sed 's/\(^\|,\)nobootwait\($\|,\)/\1/g') + # only mount the dump target when needed. + _options="$_options,noauto" + + _mntopts="$_target $_fstype $_options" + #for non-nfs _dev converting to use udev persistent name + if [ -b "$_source" ]; then + _pdev="$(get_persistent_dev $_source)" + if [ -z "$_pdev" ]; then + return 1 + fi + + else + _pdev=$_dev + fi + + echo "$_pdev $_mntopts" +} + +is_readonly_mount() { + local _mnt + _mnt=$(findmnt -k -f -n -r -o OPTIONS $1) + + #fs/proc_namespace.c: show_mountinfo(): + #seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); + [[ "$_mnt" =~ ^ro ]] +} + +#Function: get_ssh_size +#$1=dump target +#called from while loop and shouldn't read from stdin, so we're using "ssh -n" +get_ssh_size() { + local _opt _out _size + _opt="-i $SSH_KEY_LOCATION -o BatchMode=yes -o StrictHostKeyChecking=yes" + _out=$(ssh -q -n $_opt $1 "df -P $SAVE_PATH") + [ $? -ne 0 ] && { + perror_exit "checking remote ssh server available size failed." + } + + #ssh output removed the line break, so print field NF-2 + _size=$(echo -n $_out| awk '{avail=NF-2; print $avail}') + echo -n $_size +} + +#mkdir if save path does not exist on ssh dump target +#$1=ssh dump target +#caller should ensure write permission on $1:$SAVE_PATH +#called from while loop and shouldn't read from stdin, so we're using "ssh -n" +mkdir_save_path_ssh() +{ + local _opt _dir + _opt="-i $SSH_KEY_LOCATION -o BatchMode=yes -o StrictHostKeyChecking=yes" + ssh -qn $_opt $1 mkdir -p $SAVE_PATH 2>&1 > /dev/null + _ret=$? + if [ $_ret -ne 0 ]; then + perror_exit "mkdir failed on $1:$SAVE_PATH" + fi + + #check whether user has write permission on $1:$SAVE_PATH + _dir=$(ssh -qn $_opt $1 mktemp -dqp $SAVE_PATH 2>/dev/null) + _ret=$? + if [ $_ret -ne 0 ]; then + perror_exit "Could not create temporary directory on $1:$SAVE_PATH. Make sure user has write permission on destination" + fi + ssh -qn $_opt $1 rmdir $_dir + + return 0 +} + +#Function: get_fs_size +#$1=dump target +get_fs_size() { + local _mnt=$(get_mntpoint_from_target $1) + echo -n $(df -P "${_mnt}/$SAVE_PATH"|tail -1|awk '{print $4}') +} + +#Function: get_raw_size +#$1=dump target +get_raw_size() { + echo -n $(fdisk -s "$1") +} + +#Function: check_size +#$1: dump type string ('raw', 'fs', 'ssh') +#$2: dump target +check_size() { + local avail memtotal + + memtotal=$(awk '/MemTotal/{print $2}' /proc/meminfo) + case "$1" in + raw) + avail=$(get_raw_size "$2") + ;; + ssh) + avail=$(get_ssh_size "$2") + ;; + fs) + avail=$(get_fs_size "$2") + ;; + *) + return + esac + + if [ $? -ne 0 ]; then + perror_exit "Check dump target size failed" + 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." + fi +} + +# $1: core_collector config value +verify_core_collector() { + local _cmd="${1%% *}" + local _params="${1#* }" + + 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." + fi + return + fi + + if is_ssh_dump_target || is_raw_dump_target; then + if ! strstr "$_params" "-F"; then + perror_exit "The specified dump target needs makedumpfile \"-F\" option." + fi + _params="$_params vmcore" + else + _params="$_params vmcore dumpfile" + fi + + if ! $_cmd --check-params $_params; then + perror_exit "makedumpfile parameter check failed." + fi +} + +add_mount() { + local _mnt=$(to_mount "$1") + + if [ $? -ne 0 ]; then + exit 1 + fi + + add_dracut_mount "$_mnt" +} + +#handle the case user does not specify the dump target explicitly +handle_default_dump_target() +{ + local _target + local _mntpoint + + is_user_configured_dump_target && return + + check_save_path_fs $SAVE_PATH + + _save_path=$(get_bind_mount_source $SAVE_PATH) + _target=$(get_target_from_path $_save_path) + _mntpoint=$(get_mntpoint_from_target $_target) + + SAVE_PATH=${_save_path##"$_mntpoint"} + add_mount "$_target" + check_size fs $_target +} + +get_override_resettable() +{ + local override_resettable + + override_resettable=$(grep "^override_resettable" $conf_file) + if [ -n "$override_resettable" ]; then + OVERRIDE_RESETTABLE=$(echo $override_resettable | cut -d' ' -f2) + if [ "$OVERRIDE_RESETTABLE" != "0" ] && [ "$OVERRIDE_RESETTABLE" != "1" ];then + perror_exit "override_resettable value $OVERRIDE_RESETTABLE is invalid" + fi + fi +} + + +# $1: function name +for_each_block_target() +{ + local dev majmin + + for dev in $(get_kdump_targets); do + [ -b "$dev" ] || continue + majmin=$(get_maj_min $dev) + check_block_and_slaves $1 $majmin && return 1 + done + + return 0 +} + + + +#judge if a specific device with $1 is unresettable +#return false if unresettable. +is_unresettable() +{ + local path="/sys/$(udevadm info --query=all --path=/sys/dev/block/$1 | awk '/^P:/ {print $2}' | sed -e 's/\(cciss[0-9]\+\/\).*/\1/g' -e 's/\/block\/.*$//')/resettable" + local resettable=1 + + if [ -f "$path" ] + then + 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" + return 0 + } + fi + + return 1 +} + +#check if machine is resettable. +#return true if resettable +check_resettable() +{ + local _ret _target + + get_override_resettable + + for_each_block_target is_unresettable + _ret=$? + + [ $_ret -eq 0 ] && return + + 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 + + return 1 +} + +if ! check_resettable; then + exit 1 +fi + +if ! check_crypt; then + echo "Warning: Encrypted device is in dump path. User will prompted for password during second kernel boot." +fi + +# firstly get right SSH_KEY_LOCATION +keyfile=$(awk '/^sshkey/ {print $2}' $conf_file) +if [ -f "$keyfile" ]; then + # canonicalize the path + 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. + case "$config_opt" in + extra_modules) + extra_modules="$extra_modules $config_val" + ;; + ext[234]|xfs|btrfs|minix|nfs) + if ! findmnt $config_val >/dev/null; then + perror_exit "Dump target $config_val is probably not mounted." + fi + + # User configured target, use $SAVE_PATH as the dump path within the target + check_save_path_user_configured "$config_val" "$SAVE_PATH" + check_size fs "$config_val" + add_mount "$config_val" + ;; + raw) + # checking raw disk writable + dd if=$config_val count=1 of=/dev/null > /dev/null 2>&1 || { + perror_exit "Bad raw disk $config_val" + } + _praw=$(persistent_policy="by-id" get_persistent_dev $config_val) + if [ -z "$_praw" ]; then + exit 1 + fi + add_dracut_arg "--device" "$_praw" + check_size raw $config_val + ;; + ssh) + if strstr "$config_val" "@"; + 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" + fi + ;; + core_collector) + verify_core_collector "$config_val" + ;; + dracut_args) + add_dracut_arg $config_val + ;; + *) + ;; + esac +done <<< "$(read_strip_comments $conf_file)" + +handle_default_dump_target + +if [ -n "$extra_modules" ] +then + add_dracut_arg "--add-drivers" "$extra_modules" +fi + +if ! is_fadump_capable; then + # The 2nd rootfs mount stays behind the normal dump target mount, + # so it doesn't affect the logic of check_dump_fs_modified(). + is_dump_to_rootfs && add_mount "$(to_dev_name $(get_root_fs_device))" + + add_dracut_arg "--no-hostonly-default-device" +fi + +echo "$dracut_args $@" | xargs dracut + +_rc=$? +sync +exit $_rc diff --git a/mkdumprd.8 b/mkdumprd.8 new file mode 100644 index 0000000..7faae57 --- /dev/null +++ b/mkdumprd.8 @@ -0,0 +1,33 @@ +.TH MKDUMRD 8 "Fri Feb 9 2007" +.SH NAME +mkdumprd \- creates initial ramdisk images for kdump crash recovery +.SH SYNOPSIS +\fBmkdumprd\fR [OPTION] + +.SH DESCRIPTION +\fBmkdumprd\fR creates an initial ram file system for use in conjunction with +the booting of a kernel within the kdump framework for crash recovery. +\fBmkdumprds\fR purpose is to create an initial ram filesystem capable of copying +the crashed systems vmcore image to a location specified in \fI/etc/kdump.conf + +\fBmkdumprd\fR interrogates the running system to understand what modules need to +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. + +\fBmkdumprd\fR was not intended for casual use outside of the service +initialization script for the kdump utility, and should not be run manually. If +you require a custom kdump initramfs image, it is suggested that you use the +kdump service infrastructure to create one, and then manually unpack, modify and +repack the image. + + +.SH OPTIONS +.TP +All options here are passed to dracut directly, please refer \fBdracut\fR docs +for the info. + +.SH "SEE ALSO" +.BR dracut (8) @@ -0,0 +1,3 @@ +eff1054d1b1e82128683f6fe7d58d55d eppic-e8844d3.tar.gz +ce3c79e0f639035ef7ddfc39b286a61a kexec-tools-2.0.26.tar.xz +79a6e73fde9293cc335e96df5654c22e makedumpfile-1.7.3.tar.gz |
