diff --git a/.gitignore b/.gitignore index 5898f16..1d4f2ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ SOURCES/eppic-d84c354.tar.gz -SOURCES/kexec-tools-2.0.22.tar.xz -SOURCES/makedumpfile-1.6.9.tar.gz +SOURCES/kexec-tools-2.0.23.tar.xz +SOURCES/makedumpfile-1.7.0.tar.gz diff --git a/.kexec-tools.metadata b/.kexec-tools.metadata index 5909283..a33dae1 100644 --- a/.kexec-tools.metadata +++ b/.kexec-tools.metadata @@ -1,3 +1,3 @@ b902add474c63fe34c4cdf2eba882d7f8675e04e SOURCES/eppic-d84c354.tar.gz -d23d055fb98f7fa68a2888b52f11530ba3b3a206 SOURCES/kexec-tools-2.0.22.tar.xz -f07e6ce86b1e2e20b27137c26f08cd15e5460aca SOURCES/makedumpfile-1.6.9.tar.gz +c9213672bbc9d08d25f6b1ea0cd9056d2e1c5e73 SOURCES/kexec-tools-2.0.23.tar.xz +a931a40b80df204be1b02bfb502921cc618810fd SOURCES/makedumpfile-1.7.0.tar.gz diff --git a/SOURCES/92-crashkernel.install b/SOURCES/92-crashkernel.install index 7613bc6..90678c8 100755 --- a/SOURCES/92-crashkernel.install +++ b/SOURCES/92-crashkernel.install @@ -120,8 +120,9 @@ add) if [[ "$boot_ck_cmdline" != "$inst_ck_default" ]] && [[ "$boot_ck_cmdline" == "$boot_ck_default" ]]; then set_kernel_ck "$KERNEL_VERSION" "$inst_ck_default" fi - ;; + exit 0 + ;; remove) # If grub default value is upgraded when this kernel was installed, try downgrade it grub_etc_ck=$(get_grub_etc_ck) @@ -139,5 +140,7 @@ remove) set_grub_ck "$highest_ck_default" fi fi + + exit 0 ;; esac diff --git a/SOURCES/dracut-early-kdump-module-setup.sh b/SOURCES/dracut-early-kdump-module-setup.sh index b25d6b5..0e46823 100755 --- a/SOURCES/dracut-early-kdump-module-setup.sh +++ b/SOURCES/dracut-early-kdump-module-setup.sh @@ -6,9 +6,8 @@ KDUMP_KERNEL="" KDUMP_INITRD="" check() { - if [ ! -f /etc/sysconfig/kdump ] || [ ! -f /lib/kdump/kdump-lib.sh ]\ - || [ -n "${IN_KDUMP}" ] - then + if [[ ! -f /etc/sysconfig/kdump ]] || [[ ! -f /lib/kdump/kdump-lib.sh ]] \ + || [[ -n ${IN_KDUMP} ]]; then return 1 fi return 255 @@ -25,7 +24,7 @@ prepare_kernel_initrd() { prepare_kdump_bootinfo # $kernel is a variable from dracut - if [ "$KDUMP_KERNELVER" != $kernel ]; then + if [[ $KDUMP_KERNELVER != "$kernel" ]]; then dwarn "Using kernel version '$KDUMP_KERNELVER' for early kdump," \ "but the initramfs is generated for kernel version '$kernel'" fi @@ -33,12 +32,12 @@ prepare_kernel_initrd() { install() { prepare_kernel_initrd - if [ ! -f "$KDUMP_KERNEL" ]; then + 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 + 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!" diff --git a/SOURCES/dracut-early-kdump.sh b/SOURCES/dracut-early-kdump.sh index 129841e..45ee6dc 100755 --- a/SOURCES/dracut-early-kdump.sh +++ b/SOURCES/dracut-early-kdump.sh @@ -14,9 +14,8 @@ EARLY_KEXEC_ARGS="" . /lib/kdump-lib.sh . /lib/kdump-logger.sh -#initiate the kdump logger -dlog_init -if [ $? -ne 0 ]; then +# initiate the kdump logger +if ! dlog_init; then echo "failed to initiate the kdump logger." exit 1 fi @@ -30,8 +29,7 @@ prepare_parameters() early_kdump_load() { - check_kdump_feasibility - if [ $? -ne 0 ]; then + if ! check_kdump_feasibility; then return 1 fi @@ -40,8 +38,7 @@ early_kdump_load() return 1 fi - check_current_kdump_status - if [ $? == 0 ]; then + if check_current_kdump_status; then return 1 fi @@ -61,10 +58,9 @@ early_kdump_load() --command-line=$EARLY_KDUMP_CMDLINE --initrd=$EARLY_KDUMP_INITRD \ $EARLY_KDUMP_KERNEL" - $KEXEC ${EARLY_KEXEC_ARGS} $standard_kexec_args \ + if $KEXEC $EARLY_KEXEC_ARGS $standard_kexec_args \ --command-line="$EARLY_KDUMP_CMDLINE" \ - --initrd=$EARLY_KDUMP_INITRD $EARLY_KDUMP_KERNEL - if [ $? == 0 ]; then + --initrd=$EARLY_KDUMP_INITRD $EARLY_KDUMP_KERNEL; then dinfo "kexec: loaded early-kdump kernel" return 0 else diff --git a/SOURCES/dracut-kdump-emergency.service b/SOURCES/dracut-kdump-emergency.service index f2f6fad..0cf7051 100644 --- a/SOURCES/dracut-kdump-emergency.service +++ b/SOURCES/dracut-kdump-emergency.service @@ -12,7 +12,7 @@ Environment=HOME=/ Environment=DRACUT_SYSTEMD=1 Environment=NEWROOT=/sysroot WorkingDirectory=/ -ExecStart=/bin/kdump-error-handler.sh +ExecStart=/bin/kdump.sh --error-handler ExecStopPost=-/bin/rm -f -- /.console_lock Type=oneshot StandardInput=tty-force diff --git a/SOURCES/dracut-kdump-error-handler.sh b/SOURCES/dracut-kdump-error-handler.sh deleted file mode 100755 index fc2b932..0000000 --- a/SOURCES/dracut-kdump-error-handler.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/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/SOURCES/dracut-kdump.sh b/SOURCES/dracut-kdump.sh index 3e65c44..b69bc98 100755 --- a/SOURCES/dracut-kdump.sh +++ b/SOURCES/dracut-kdump.sh @@ -1,324 +1,583 @@ #!/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 +# +# The main kdump routine in capture kernel, bash may not be the +# default shell. Any code added must be POSIX compliant. . /lib/dracut-lib.sh +. /lib/kdump-logger.sh . /lib/kdump-lib-initramfs.sh -set -o pipefail +#initiate the kdump logger +if ! dlog_init; then + echo "failed to initiate the kdump logger." + exit 1 +fi + +KDUMP_PATH="/var/crash" +KDUMP_LOG_FILE="/run/initramfs/kexec-dmesg.log" +CORE_COLLECTOR="" +DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 7 -d 31" +DMESG_COLLECTOR="/sbin/vmcore-dmesg" +FAILURE_ACTION="systemctl reboot -f" +DATEDIR=$(date +%Y-%m-%d-%T) +HOST_IP='127.0.0.1' +DUMP_INSTRUCTION="" +SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" +DD_BLKSIZE=512 +FINAL_ACTION="systemctl reboot -f" +KDUMP_PRE="" +KDUMP_POST="" +NEWROOT="/sysroot" +OPALCORE="/sys/firmware/opal/mpipl/core" +KDUMP_CONF_PARSED="/tmp/kdump.conf.$$" + +# POSIX doesn't have pipefail, only apply when using bash +# shellcheck disable=SC3040 +[ -n "$BASH" ] && set -o pipefail + DUMP_RETVAL=0 -export PATH=$PATH:$KDUMP_SCRIPT_DIR +kdump_read_conf > $KDUMP_CONF_PARSED -do_dump() +get_kdump_confs() +{ + while read -r 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 < "$KDUMP_CONF_PARSED" + + 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 +} + +# store the kexec kernel log to a file. +save_log() { - local _ret + dmesg -T > $KDUMP_LOG_FILE + + if command -v journalctl > /dev/null; then + journalctl -ab >> $KDUMP_LOG_FILE + fi + chmod 600 $KDUMP_LOG_FILE +} - eval $DUMP_INSTRUCTION - _ret=$? +# $1: dump path, must be a mount point +dump_fs() +{ + ddebug "dump_fs _mp=$1" + + if ! is_mounted "$1"; then + dinfo "dump path '$1' is not mounted, trying to mount..." + if ! mount --target "$1"; then + derror "failed to dump to '$1', it's not a mount point!" + return 1 + fi + fi + + # Remove -F in makedumpfile case. We don't want a flat format dump here. + case $CORE_COLLECTOR in + *makedumpfile*) + CORE_COLLECTOR=$(echo "$CORE_COLLECTOR" | sed -e "s/-F//g") + ;; + esac + + _dump_fs_path=$(echo "$1/$KDUMP_PATH/$HOST_IP-$DATEDIR/" | tr -s /) + dinfo "saving to $_dump_fs_path" + + # Only remount to read-write mode if the dump target is mounted read-only. + _dump_mnt_op=$(get_mount_info OPTIONS target "$1" -f) + case $_dump_mnt_op in + ro*) + dinfo "Remounting the dump target in rw mode." + mount -o remount,rw "$1" || return 1 + ;; + esac + + mkdir -p "$_dump_fs_path" || return 1 + + save_vmcore_dmesg_fs ${DMESG_COLLECTOR} "$_dump_fs_path" + save_opalcore_fs "$_dump_fs_path" + + dinfo "saving vmcore" + $CORE_COLLECTOR /proc/vmcore "$_dump_fs_path/vmcore-incomplete" + _dump_exitcode=$? + if [ $_dump_exitcode -eq 0 ]; then + mv "$_dump_fs_path/vmcore-incomplete" "$_dump_fs_path/vmcore" + sync + dinfo "saving vmcore complete" + else + derror "saving vmcore failed, exitcode:$_dump_exitcode" + fi + + dinfo "saving the $KDUMP_LOG_FILE to $_dump_fs_path/" + save_log + mv "$KDUMP_LOG_FILE" "$_dump_fs_path/" + if [ $_dump_exitcode -ne 0 ]; then + return 1 + fi + + # improper kernel cmdline can cause the failure of echo, we can ignore this kind of failure + return 0 +} - if [ $_ret -ne 0 ]; then - derror "saving vmcore failed" - fi +# $1: dmesg collector +# $2: dump path +save_vmcore_dmesg_fs() +{ + dinfo "saving vmcore-dmesg.txt to $2" + if $1 /proc/vmcore > "$2/vmcore-dmesg-incomplete.txt"; then + mv "$2/vmcore-dmesg-incomplete.txt" "$2/vmcore-dmesg.txt" + chmod 600 "$2/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 + dinfo "saving vmcore-dmesg.txt complete" + else + if [ -f "$2/vmcore-dmesg-incomplete.txt" ]; then + chmod 600 "$2/vmcore-dmesg-incomplete.txt" + fi + derror "saving vmcore-dmesg.txt failed" + fi +} - return $_ret +# $1: dump path +save_opalcore_fs() +{ + 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 + + dinfo "saving opalcore:$OPALCORE to $1/opalcore" + if ! cp $OPALCORE "$1/opalcore"; then + derror "saving opalcore failed" + return 1 + fi + + sync + dinfo "saving opalcore complete" + return 0 } -do_kdump_pre() +dump_to_rootfs() { - local _ret - - if [ -n "$KDUMP_PRE" ]; then - "$KDUMP_PRE" - _ret=$? - if [ $_ret -ne 0 ]; then - derror "$KDUMP_PRE exited with $_ret status" - return $_ret - fi - fi - - # if any script fails, it just raises warning and continues - if [ -d /etc/kdump/pre.d ]; then - for file in /etc/kdump/pre.d/*; do - "$file" - _ret=$? - if [ $_ret -ne 0 ]; then - derror "$file exited with $_ret status" - fi - done - fi - return 0 + + if [ "$(systemctl status dracut-initqueue | sed -n "s/^\s*Active: \(\S*\)\s.*$/\1/p")" = "inactive" ]; then + dinfo "Trying to bring up initqueue for rootfs mount" + systemctl start dracut-initqueue + fi + + dinfo "Clean up dead systemd services" + systemctl cancel + dinfo "Waiting for rootfs mount, will timeout after 90 seconds" + systemctl start --no-block sysroot.mount + + _loop=0 + while [ $_loop -lt 90 ] && ! is_mounted /sysroot; do + sleep 1 + _loop=$((_loop + 1)) + done + + if ! is_mounted /sysroot; then + derror "Failed to mount rootfs" + return + fi + + ddebug "NEWROOT=$NEWROOT" + dump_fs $NEWROOT } -do_kdump_post() +kdump_emergency_shell() { - local _ret - - if [ -d /etc/kdump/post.d ]; then - for file in /etc/kdump/post.d/*; do - "$file" "$1" - _ret=$? - if [ $_ret -ne 0 ]; then - derror "$file exited with $_ret status" - fi - done - fi - - if [ -n "$KDUMP_POST" ]; then - "$KDUMP_POST" "$1" - _ret=$? - if [ $_ret -ne 0 ]; then - derror "$KDUMP_POST exited with $_ret status" - fi - fi + ddebug "Switching to kdump emergency shell..." + + [ -f /etc/profile ] && . /etc/profile + export PS1='kdump:${PWD}# ' + + . /lib/dracut-lib.sh + if [ -f /dracut-state.sh ]; then + . /dracut-state.sh 2> /dev/null + fi + + source_conf /etc/conf.d + + type plymouth > /dev/null 2>&1 && plymouth quit + + source_hook "emergency" + while read -r _tty rest; do + ( + echo + echo + echo 'Entering kdump emergency mode.' + echo 'Type "journalctl" to view system logs.' + echo 'Type "rdsosreport" to generate a sosreport, you can then' + echo 'save it elsewhere and attach it to a bug report.' + echo + echo + ) > "/dev/$_tty" + done < /proc/consoles + sh -i -l + /bin/rm -f -- /.console_lock } -add_dump_code() +do_failure_action() { - DUMP_INSTRUCTION=$1 + dinfo "Executing failure action $FAILURE_ACTION" + eval $FAILURE_ACTION } -dump_raw() +do_final_action() +{ + dinfo "Executing final action $FINAL_ACTION" + eval $FINAL_ACTION +} + +do_dump() +{ + eval $DUMP_INSTRUCTION + _ret=$? + + if [ $_ret -ne 0 ]; then + derror "saving vmcore failed" + fi + + return $_ret +} + +do_kdump_pre() +{ + if [ -n "$KDUMP_PRE" ]; then + "$KDUMP_PRE" + _ret=$? + if [ $_ret -ne 0 ]; then + derror "$KDUMP_PRE exited with $_ret status" + return $_ret + fi + fi + + # if any script fails, it just raises warning and continues + if [ -d /etc/kdump/pre.d ]; then + for file in /etc/kdump/pre.d/*; do + "$file" + _ret=$? + if [ $_ret -ne 0 ]; then + derror "$file exited with $_ret status" + fi + done + fi + return 0 +} + +do_kdump_post() { - local _raw=$1 + if [ -d /etc/kdump/post.d ]; then + for file in /etc/kdump/post.d/*; do + "$file" "$1" + _ret=$? + if [ $_ret -ne 0 ]; then + derror "$file exited with $_ret status" + fi + done + fi + + if [ -n "$KDUMP_POST" ]; then + "$KDUMP_POST" "$1" + _ret=$? + if [ $_ret -ne 0 ]; then + derror "$KDUMP_POST exited with $_ret status" + fi + fi +} - [ -b "$_raw" ] || return 1 +# $1: block target, eg. /dev/sda +dump_raw() +{ + [ -b "$1" ] || return 1 - dinfo "saving to raw disk $_raw" + dinfo "saving to raw disk $1" - 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 + if ! echo "$CORE_COLLECTOR" | grep -q makedumpfile; then + _src_size=$(stat --format %s /proc/vmcore) + _src_size_mb=$((_src_size / 1048576)) + /kdumpscripts/monitor_dd_progress $_src_size_mb & + fi - dinfo "saving vmcore" - $CORE_COLLECTOR /proc/vmcore | dd of=$_raw bs=$DD_BLKSIZE >> /tmp/dd_progress_file 2>&1 || return 1 - sync + dinfo "saving vmcore" + $CORE_COLLECTOR /proc/vmcore | dd of="$1" bs=$DD_BLKSIZE >> /tmp/dd_progress_file 2>&1 || return 1 + sync - dinfo "saving vmcore complete" - return 0 + dinfo "saving vmcore complete" + return 0 } +# $1: ssh key file +# $2: ssh address in @ format dump_ssh() { - local _ret=0 - local _exitcode=0 _exitcode2=0 - local _opt="-i $1 -o BatchMode=yes -o StrictHostKeyChecking=yes" - local _dir="$KDUMP_PATH/$HOST_IP-$DATEDIR" - local _host=$2 - local _vmcore="vmcore" - local _ipv6_addr="" _username="" - - dinfo "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 - - dinfo "saving vmcore" - - if is_ipv6_address "$_host"; then - _username=${_host%@*} - _ipv6_addr="[${_host#*@}]" - fi - - if [ "${CORE_COLLECTOR%%[[:blank:]]*}" = "scp" ]; then - if [ -n "$_username" ] && [ -n "$_ipv6_addr" ]; then - scp -q $_opt /proc/vmcore "$_username@$_ipv6_addr:$_dir/vmcore-incomplete" - else - scp -q $_opt /proc/vmcore "$_host:$_dir/vmcore-incomplete" - fi - _exitcode=$? - else - $CORE_COLLECTOR /proc/vmcore | ssh $_opt $_host "umask 0077 && dd bs=512 of=$_dir/vmcore-incomplete" - _exitcode=$? - _vmcore="vmcore.flat" - fi - - if [ $_exitcode -eq 0 ]; then - ssh $_opt $_host "mv $_dir/vmcore-incomplete $_dir/$_vmcore" - _exitcode2=$? - if [ $_exitcode2 -ne 0 ]; then - derror "moving vmcore failed, _exitcode:$_exitcode2" - else - dinfo "saving vmcore complete" - fi - else - derror "saving vmcore failed, _exitcode:$_exitcode" - fi - - dinfo "saving the $KDUMP_LOG_FILE to $_host:$_dir/" - save_log - if [ -n "$_username" ] && [ -n "$_ipv6_addr" ]; then - scp -q $_opt $KDUMP_LOG_FILE "$_username@$_ipv6_addr:$_dir/" - else - scp -q $_opt $KDUMP_LOG_FILE "$_host:$_dir/" - fi - _ret=$? - if [ $_ret -ne 0 ]; then - derror "saving log file failed, _exitcode:$_ret" - fi - - if [ $_exitcode -ne 0 ] || [ $_exitcode2 -ne 0 ];then - return 1 - fi - - return 0 + _ret=0 + _ssh_opt="-i $1 -o BatchMode=yes -o StrictHostKeyChecking=yes" + _ssh_dir="$KDUMP_PATH/$HOST_IP-$DATEDIR" + if is_ipv6_address "$2"; then + _scp_address=${2%@*}@"[${2#*@}]" + else + _scp_address=$2 + fi + + dinfo "saving to $2:$_ssh_dir" + + cat /var/lib/random-seed > /dev/urandom + ssh -q $_ssh_opt "$2" mkdir -p "$_ssh_dir" || return 1 + + save_vmcore_dmesg_ssh "$DMESG_COLLECTOR" "$_ssh_dir" "$_ssh_opt" "$2" + dinfo "saving vmcore" + + save_opalcore_ssh "$_ssh_dir" "$_ssh_opt" "$2" "$_scp_address" + + if [ "${CORE_COLLECTOR%%[[:blank:]]*}" = "scp" ]; then + scp -q $_ssh_opt /proc/vmcore "$_scp_address:$_ssh_dir/vmcore-incomplete" + _ret=$? + _vmcore="vmcore" + else + $CORE_COLLECTOR /proc/vmcore | ssh $_ssh_opt "$2" "umask 0077 && dd bs=512 of='$_ssh_dir/vmcore-incomplete'" + _ret=$? + _vmcore="vmcore.flat" + fi + + if [ $_ret -eq 0 ]; then + ssh $_ssh_opt "$2" "mv '$_ssh_dir/vmcore-incomplete' '$_ssh_dir/$_vmcore'" + _ret=$? + if [ $_ret -ne 0 ]; then + derror "moving vmcore failed, exitcode:$_ret" + else + dinfo "saving vmcore complete" + fi + else + derror "saving vmcore failed, exitcode:$_ret" + fi + + dinfo "saving the $KDUMP_LOG_FILE to $2:$_ssh_dir/" + save_log + if ! scp -q $_ssh_opt $KDUMP_LOG_FILE "$_scp_address:$_ssh_dir/"; then + derror "saving log file failed, _exitcode:$_ret" + fi + + return $_ret } -save_opalcore_ssh() { - local _path=$1 - local _opts="$2" - local _location=$3 - local _user_name="" _ipv6addr="" - - ddebug "_path=$_path _opts=$_opts _location=$_location" - - if [ ! -f $OPALCORE ]; then - # Check if we are on an old kernel that uses a different path - if [ -f /sys/firmware/opal/core ]; then - OPALCORE="/sys/firmware/opal/core" - else - return 0 - fi - fi - - if is_ipv6_address "$_host"; then - _user_name=${_location%@*} - _ipv6addr="[${_location#*@}]" - fi - - dinfo "saving opalcore:$OPALCORE to $_location:$_path" - - if [ -n "$_user_name" ] && [ -n "$_ipv6addr" ]; then - scp $_opts $OPALCORE $_user_name@$_ipv6addr:$_path/opalcore-incomplete - else - scp $_opts $OPALCORE $_location:$_path/opalcore-incomplete - fi - if [ $? -ne 0 ]; then - derror "saving opalcore failed" - return 1 - fi - - ssh $_opts $_location mv $_path/opalcore-incomplete $_path/opalcore - dinfo "saving opalcore complete" - return 0 +# $1: dump path +# $2: ssh opts +# $3: ssh address in @ format +# $4: scp address, similar with ssh address but IPv6 addresses are quoted +save_opalcore_ssh() +{ + 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 + + dinfo "saving opalcore:$OPALCORE to $3:$1" + + if ! scp $2 $OPALCORE "$4:$1/opalcore-incomplete"; then + derror "saving opalcore failed" + return 1 + fi + + ssh $2 "$3" mv "$1/opalcore-incomplete" "$1/opalcore" + dinfo "saving opalcore complete" + return 0 } -save_vmcore_dmesg_ssh() { - local _dmesg_collector=$1 - local _path=$2 - local _opts="$3" - local _location=$4 - - dinfo "saving vmcore-dmesg.txt to $_location:$_path" - $_dmesg_collector /proc/vmcore | ssh $_opts $_location "umask 0077 && dd of=$_path/vmcore-dmesg-incomplete.txt" - _exitcode=$? - - if [ $_exitcode -eq 0 ]; then - ssh -q $_opts $_location mv $_path/vmcore-dmesg-incomplete.txt $_path/vmcore-dmesg.txt - dinfo "saving vmcore-dmesg.txt complete" - else - derror "saving vmcore-dmesg.txt failed" - fi +# $1: dmesg collector +# $2: dump path +# $3: ssh opts +# $4: ssh address in @ format +save_vmcore_dmesg_ssh() +{ + dinfo "saving vmcore-dmesg.txt to $4:$2" + if $1 /proc/vmcore | ssh $3 "$4" "umask 0077 && dd of='$2/vmcore-dmesg-incomplete.txt'"; then + ssh -q $3 "$4" mv "$2/vmcore-dmesg-incomplete.txt" "$2/vmcore-dmesg.txt" + dinfo "saving vmcore-dmesg.txt complete" + else + derror "saving vmcore-dmesg.txt failed" + fi } get_host_ip() { - local _host - if is_nfs_dump_target || is_ssh_dump_target - then - kdumpnic=$(getarg kdumpnic=) - [ -z "$kdumpnic" ] && derror "failed to get kdumpnic!" && return 1 - _host=`ip addr show dev $kdumpnic|grep '[ ]*inet'` - [ $? -ne 0 ] && derror "wrong kdumpnic: $kdumpnic" && return 1 - _host=`echo $_host | head -n 1 | cut -d' ' -f2` - _host="${_host%%/*}" - [ -z "$_host" ] && derror "wrong kdumpnic: $kdumpnic" && return 1 - HOST_IP=$_host - fi - return 0 + if is_nfs_dump_target || is_ssh_dump_target; then + kdumpnic=$(getarg kdumpnic=) + if [ -z "$kdumpnic" ]; then + derror "failed to get kdumpnic!" + return 1 + fi + if ! kdumphost=$(ip addr show dev "$kdumpnic" | grep '[ ]*inet'); then + derror "wrong kdumpnic: $kdumpnic" + return 1 + fi + kdumphost=$(echo "$kdumphost" | head -n 1 | awk '{print $2}') + kdumphost="${kdumphost%%/*}" + if [ -z "$kdumphost" ]; then + derror "wrong kdumpnic: $kdumpnic" + return 1 + fi + HOST_IP=$kdumphost + fi + return 0 } -read_kdump_conf() +read_kdump_confs() { - if [ ! -f "$KDUMP_CONF" ]; then - derror "$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") - if [ -n "$config_val" ]; then - config_val=$(get_mntpoint_from_target "$config_val") - add_dump_code "dump_fs $config_val" - fi - ;; - ext[234]|xfs|btrfs|minix|nfs) - config_val=$(get_mntpoint_from_target "$config_val") - 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)" + if [ ! -f "$KDUMP_CONFIG_FILE" ]; then + derror "$KDUMP_CONFIG_FILE not found" + return + fi + + get_kdump_confs + + # rescan for add code for dump target + while read -r 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") + if [ -n "$config_val" ]; then + config_val=$(get_mntpoint_from_target "$config_val") + DUMP_INSTRUCTION="dump_fs $config_val" + fi + ;; + ext[234] | xfs | btrfs | minix | nfs) + config_val=$(get_mntpoint_from_target "$config_val") + DUMP_INSTRUCTION="dump_fs $config_val" + ;; + raw) + DUMP_INSTRUCTION="dump_raw $config_val" + ;; + ssh) + DUMP_INSTRUCTION="dump_ssh $SSH_KEY_LOCATION $config_val" + ;; + esac + done < "$KDUMP_CONF_PARSED" } fence_kdump_notify() { - if [ -n "$FENCE_KDUMP_NODES" ]; then - $FENCE_KDUMP_SEND $FENCE_KDUMP_ARGS $FENCE_KDUMP_NODES & - fi + if [ -n "$FENCE_KDUMP_NODES" ]; then + # shellcheck disable=SC2086 + $FENCE_KDUMP_SEND $FENCE_KDUMP_ARGS $FENCE_KDUMP_NODES & + fi } -read_kdump_conf +if [ "$1" = "--error-handler" ]; then + get_kdump_confs + do_failure_action + do_final_action + + exit $? +fi + +# 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 + +read_kdump_confs fence_kdump_notify -get_host_ip -if [ $? -ne 0 ]; then - derror "get_host_ip exited with non-zero status!" - exit 1 +if ! get_host_ip; then + derror "get_host_ip exited with non-zero status!" + exit 1 fi if [ -z "$DUMP_INSTRUCTION" ]; then - add_dump_code "dump_fs $NEWROOT" + DUMP_INSTRUCTION="dump_fs $NEWROOT" fi -do_kdump_pre -if [ $? -ne 0 ]; then - derror "kdump_pre script exited with non-zero status!" - do_final_action - # During systemd service to reboot the machine, stop this shell script running - exit 1 +if ! do_kdump_pre; then + derror "kdump_pre script exited with non-zero status!" + do_final_action + # During systemd service to reboot the machine, stop this shell script running + exit 1 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 - derror "kdump_post script exited with non-zero status!" +if ! do_kdump_post $DUMP_RETVAL; then + derror "kdump_post script exited with non-zero status!" fi if [ $DUMP_RETVAL -ne 0 ]; then - exit 1 + exit 1 fi do_final_action diff --git a/SOURCES/dracut-module-setup.sh b/SOURCES/dracut-module-setup.sh index c6d6fee..1ea0d95 100755 --- a/SOURCES/dracut-module-setup.sh +++ b/SOURCES/dracut-module-setup.sh @@ -11,8 +11,7 @@ kdump_module_init() { check() { [[ $debug ]] && set -x #kdumpctl sets this explicitly - if [ -z "$IN_KDUMP" ] || [ ! -f /etc/kdump.conf ] - then + if [[ -z $IN_KDUMP ]] || [[ ! -f /etc/kdump.conf ]]; then return 1 fi return 0 @@ -41,11 +40,11 @@ depends() { _dep="$_dep ssh-client" fi - if [ "$(uname -m)" = "s390x" ]; then + if [[ "$(uname -m)" == "s390x" ]]; then _dep="$_dep znet" fi - if [ -n "$( find /sys/devices -name drm )" ] || [ -d /sys/module/hyperv_fb ]; then + if [[ -n "$(ls -A /sys/class/drm 2> /dev/null)" ]] || [[ -d /sys/module/hyperv_fb ]]; then add_opt_module drm fi @@ -53,23 +52,23 @@ depends() { _dep="$_dep network" fi - echo $_dep + echo "$_dep" } kdump_is_bridge() { - [ -d /sys/class/net/"$1"/bridge ] + [[ -d /sys/class/net/"$1"/bridge ]] } kdump_is_bond() { - [ -d /sys/class/net/"$1"/bonding ] + [[ -d /sys/class/net/"$1"/bonding ]] } kdump_is_team() { - [ -f /usr/bin/teamnl ] && teamnl $1 ports &> /dev/null + [[ -f /usr/bin/teamnl ]] && teamnl "$1" ports &> /dev/null } kdump_is_vlan() { - [ -f /proc/net/vlan/"$1" ] + [[ -f /proc/net/vlan/"$1" ]] } # $1: netdev name @@ -77,44 +76,42 @@ source_ifcfg_file() { local ifcfg_file dwarning "Network Scripts are deprecated. You are encouraged to set up network by NetworkManager." - ifcfg_file=$(get_ifcfg_filename $1) - if [ -f "${ifcfg_file}" ]; then - . ${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: nmcli connection show output kdump_setup_dns() { local _netdev="$1" - local _nm_show_cmd="$2" + local _conpath="$2" local _nameserver _dns _tmp array local _dnsfile=${initdir}/etc/cmdline.d/42dns.conf - _tmp=$(get_nmcli_value_by_field "$_nm_show_cmd" "IP4.DNS") + _tmp=$(get_nmcli_field_by_conpath "IP4.DNS" "$_conpath") + # shellcheck disable=SC2206 array=(${_tmp//|/ }) - if [[ ${array[@]} ]]; then - for _dns in "${array[@]}" - do + if [[ ${array[*]} ]]; then + for _dns in "${array[@]}"; do echo "nameserver=$_dns" >> "$_dnsfile" done else dwarning "Failed to get DNS info via nmcli output. Now try sourcing ifcfg script" source_ifcfg_file "$_netdev" - [ -n "$DNS1" ] && echo "nameserver=$DNS1" > "$_dnsfile" - [ -n "$DNS2" ] && echo "nameserver=$DNS2" >> "$_dnsfile" + [[ -n $DNS1 ]] && echo "nameserver=$DNS1" > "$_dnsfile" + [[ -n $DNS2 ]] && echo "nameserver=$DNS2" >> "$_dnsfile" fi - while read content; - do - _nameserver=$(echo $content | grep ^nameserver) - [ -z "$_nameserver" ] && continue + while read -r content; do + _nameserver=$(echo "$content" | grep ^nameserver) + [[ -z $_nameserver ]] && continue - _dns=$(echo $_nameserver | cut -d' ' -f2) - [ -z "$_dns" ] && continue + _dns=$(echo "$_nameserver" | awk '{print $2}') + [[ -z $_dns ]] && continue - if [ ! -f $_dnsfile ] || [ ! $(cat $_dnsfile | grep -q $_dns) ]; then + if [[ ! -f $_dnsfile ]] || ! grep -q "$_dns" "$_dnsfile"; then echo "nameserver=$_dns" >> "$_dnsfile" fi done < "/etc/resolv.conf" @@ -129,7 +126,7 @@ repeatedly_join_str() { local _separator="$3" local i _res - if [[ "$_count" -le 0 ]]; then + if [[ $_count -le 0 ]]; then echo -n "" return fi @@ -138,7 +135,7 @@ repeatedly_join_str() { _res="$_str" ((_count--)) - while [[ "$i" -lt "$_count" ]]; do + while [[ $i -lt $_count ]]; do ((i++)) _res="${_res}${_separator}${_str}" done @@ -159,14 +156,14 @@ cal_netmask_by_prefix() { local _count _res _octets_per_group _octets_total _seperator _total_groups local _max_group_value _max_group_value_repr _bits_per_group _tmp _zero_bits - if [[ "$_ipv6_flag" == "-6" ]]; then + if [[ $_ipv6_flag == "-6" ]]; then _ipv6=1 else _ipv6=0 fi - if [[ "$_prefix" -lt 0 || "$_prefix" -gt 128 ]] || \ - ( ((!_ipv6)) && [[ "$_prefix" -gt 32 ]] ); then + if [[ $_prefix -lt 0 || $_prefix -gt 128 ]] \ + || ( ((!_ipv6)) && [[ $_prefix -gt 32 ]]); then derror "Bad prefix:$_prefix for calculating netmask" exit 1 fi @@ -181,7 +178,7 @@ cal_netmask_by_prefix() { _seperator="." fi - _total_groups=$((_octets_total/_octets_per_group)) + _total_groups=$((_octets_total / _octets_per_group)) _bits_per_group=$((_octets_per_group * _bits_per_octet)) _max_group_value=$(((1 << _bits_per_group) - 1)) @@ -191,39 +188,39 @@ cal_netmask_by_prefix() { _max_group_value_repr="$_max_group_value" fi - _count=$((_prefix/_octets_per_group/_bits_per_octet)) + _count=$((_prefix / _octets_per_group / _bits_per_octet)) _first_part=$(repeatedly_join_str "$_count" "$_max_group_value_repr" "$_seperator") _res="$_first_part" - _tmp=$((_octets_total*_bits_per_octet-_prefix)) - _zero_bits=$(expr $_tmp % $_bits_per_group) - if [[ "$_zero_bits" -ne 0 ]]; then + _tmp=$((_octets_total * _bits_per_octet - _prefix)) + _zero_bits=$((_tmp % _bits_per_group)) + if [[ $_zero_bits -ne 0 ]]; then _second_part=$((_max_group_value >> _zero_bits << _zero_bits)) if ((_ipv6)); then _second_part=$(printf "%x" $_second_part) fi ((_count++)) - if [[ -z "$_first_part" ]]; then + if [[ -z $_first_part ]]; then _res="$_second_part" else _res="${_first_part}${_seperator}${_second_part}" fi fi - _count=$((_total_groups-_count)) - if [[ "$_count" -eq 0 ]]; then + _count=$((_total_groups - _count)) + if [[ $_count -eq 0 ]]; then echo -n "$_res" return fi - if ((_ipv6)) && [[ "$_count" -gt 1 ]] ; then + if ((_ipv6)) && [[ $_count -gt 1 ]]; then # use condensed notion for IPv6 _third_part=":" else _third_part=$(repeatedly_join_str "$_count" "0" "$_seperator") fi - if [[ -z "$_res" ]] && ((!_ipv6)) ; then + if [[ -z $_res ]] && ((!_ipv6)); then echo -n "${_third_part}" else echo -n "${_res}${_seperator}${_third_part}" @@ -237,25 +234,24 @@ kdump_static_ip() { local _netdev="$1" _srcaddr="$2" kdumpnic="$3" _ipv6_flag local _netmask _gateway _ipaddr _target _nexthop _prefix - _ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr\/.* /{print \$2}") + _ipaddr=$(ip addr show dev "$_netdev" permanent | awk "/ $_srcaddr\/.* /{print \$2}") - if is_ipv6_address $_srcaddr; then + 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 [[ -n $_ipaddr ]]; then + _gateway=$(ip $_ipv6_flag route list dev "$_netdev" \ + | awk '/^default /{print $3}' | head -n 1) - if [ "x" != "x"$_ipv6_flag ]; then + if [[ "x" != "x"$_ipv6_flag ]]; then # _ipaddr="2002::56ff:feb6:56d5/64", _netmask is the number after "/" _netmask=${_ipaddr#*\/} _srcaddr="[$_srcaddr]" _gateway="[$_gateway]" else _prefix=$(cut -d'/' -f2 <<< "$_ipaddr") - _netmask=$(cal_netmask_by_prefix "$_prefix" "$_ipv6_flag") - if [[ "$?" -ne 0 ]]; then + if ! _netmask=$(cal_netmask_by_prefix "$_prefix" "$_ipv6_flag"); then derror "Failed to calculate netmask for $_ipaddr" exit 1 fi @@ -263,67 +259,67 @@ kdump_static_ip() { 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:$kdumpnic" - done >> ${initdir}/etc/cmdline.d/45route-static.conf + /sbin/ip $_ipv6_flag route show | grep -v default \ + | grep ".*via.* $_netdev " | grep -v "^[[:space:]]*nexthop" \ + | while read -r _route; do + _target=$(echo "$_route" | awk '{print $1}') + _nexthop=$(echo "$_route" | awk '{print $3}') + if [[ "x" != "x"$_ipv6_flag ]]; then + _target="[$_target]" + _nexthop="[$_nexthop]" + fi + echo "rd.route=$_target:$_nexthop:$kdumpnic" + done >> "${initdir}/etc/cmdline.d/45route-static.conf" - kdump_handle_mulitpath_route $_netdev $_srcaddr $kdumpnic + kdump_handle_mulitpath_route "$_netdev" "$_srcaddr" "$kdumpnic" } kdump_handle_mulitpath_route() { local _netdev="$1" _srcaddr="$2" kdumpnic="$3" _ipv6_flag local _target _nexthop _route _weight _max_weight _rule - if is_ipv6_address $_srcaddr; then + 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:]]*//') + while IFS="" read -r _route; do + if [[ $_route =~ [[:space:]]+nexthop ]]; then + _route=${_route##[[:space:]]} # Parse multipath route, using previous _target - [[ "$_target" == 'default' ]] && continue - [[ "$_route" =~ .*via.*\ $_netdev ]] || continue + [[ $_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` + _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 + if [[ "x" != "x"$_ipv6_flag ]]; then _rule="rd.route=[$_target]:[$_nexthop]:$kdumpnic" else _rule="rd.route=$_target:$_nexthop:$kdumpnic" fi fi else - [[ -n "$_rule" ]] && echo "$_rule" - _target=`echo "$_route" | cut -d ' ' -f1` + [[ -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\ + 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 + [[ -n $_rule ]] && echo "$_rule" >> "${initdir}/etc/cmdline.d/45route-static.conf" } kdump_get_mac_addr() { - cat /sys/class/net/$1/address + 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 + local addr + 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" @@ -353,25 +349,24 @@ kdump_setup_ifname() { kdump_setup_bridge() { local _netdev=$1 local _brif _dev _mac _kdumpdev - for _dev in `ls /sys/class/net/$_netdev/brif/`; do + for _dev in "/sys/class/net/$_netdev/brif/"*; do + [[ -e $_dev ]] || continue + _dev=${_dev##*/} _kdumpdev=$_dev if kdump_is_bond "$_dev"; then - $(kdump_setup_bond "$_dev" "$(get_nmcli_connection_show_cmd_by_ifname "$_dev")") - if [[ $? != 0 ]]; then - exit 1 - fi + (kdump_setup_bond "$_dev" "$(get_nmcli_connection_apath_by_ifname "$_dev")") || exit 1 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 + _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 + echo " bridge=$_netdev:${_brif%,}" >> "${initdir}/etc/cmdline.d/41bridge.conf" } # drauct takes bond=[::[:]] syntax to parse @@ -379,74 +374,72 @@ kdump_setup_bridge() { # bond=bond0:eth0,eth1:mode=balance-rr kdump_setup_bond() { local _netdev="$1" - local _nm_show_cmd="$2" + local _conpath="$2" local _dev _mac _slaves _kdumpdev _bondoptions - 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 + 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 + echo -n " bond=$_netdev:${_slaves%,}" >> "${initdir}/etc/cmdline.d/42bond.conf" - _bondoptions=$(get_nmcli_value_by_field "$_nm_show_cmd" "bond.options") + _bondoptions=$(get_nmcli_field_by_conpath "bond.options" "$_conpath") - if [[ -z "_bondoptions" ]]; then + if [[ -z $_bondoptions ]]; then dwarning "Failed to get bond configuration via nmlci output. Now try sourcing ifcfg script." - source_ifcfg_file $_netdev - _bondoptions="$(echo $BONDING_OPTS | xargs echo | tr " " ",")" + source_ifcfg_file "$_netdev" + _bondoptions="$(echo "$BONDING_OPTS" | xargs echo | tr " " ",")" fi - if [[ -z "_bondoptions" ]]; then + if [[ -z $_bondoptions ]]; then derror "Get empty bond options" exit 1 fi - echo ":$_bondoptions" >> ${initdir}/etc/cmdline.d/42bond.conf + 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 + 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 + echo " team=$_netdev:${_slaves%,}" >> "${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 + if ! teamdctl "$_netdev" config dump > "${initdir}/tmp/$$-$_netdev.conf"; 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 + 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 _phydev + local _netmac local _kdumpdev + _phydev="$(awk '/^Device:/{print $2}' /proc/net/vlan/"$_netdev")" + _netmac="$(kdump_get_mac_addr "$_phydev")" + #Just support vlan over bond and team if kdump_is_bridge "$_phydev"; then derror "Vlan over bridge is not supported!" exit 1 elif kdump_is_bond "$_phydev"; then - $(kdump_setup_bond "$_phydev" "$(get_nmcli_connection_show_cmd_by_ifname "$_phydev")") - if [[ $? != 0 ]]; then - exit 1 - fi - echo " vlan=$(kdump_setup_ifname $_netdev):$_phydev" > ${initdir}/etc/cmdline.d/43vlan.conf + (kdump_setup_bond "$_phydev" "$(get_nmcli_connection_apath_by_ifname "$_phydev")") || exit 1 + 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 + _kdumpdev="$(kdump_setup_ifname "$_phydev")" + echo " vlan=$(kdump_setup_ifname "$_netdev"):$_kdumpdev ifname=$_kdumpdev:$_netmac" > "${initdir}/etc/cmdline.d/43vlan.conf" fi } @@ -455,119 +448,114 @@ kdump_setup_vlan() { # code reaped from the list_configured function of # https://github.com/hreinecke/s390-tools/blob/master/zconf/znetconf find_online_znet_device() { - local CCWGROUPBUS_DEVICEDIR="/sys/bus/ccwgroup/devices" - local NETWORK_DEVICES d ifname ONLINE - - [ ! -d "$CCWGROUPBUS_DEVICEDIR" ] && return - NETWORK_DEVICES=$(find $CCWGROUPBUS_DEVICEDIR) - for d in $NETWORK_DEVICES - do - [ ! -f "$d/online" ] && continue - read ONLINE < $d/online - if [ $ONLINE -ne 1 ]; then - continue - fi - # determine interface name, if there (only for qeth and if - # device is online) - if [ -f $d/if_name ] - then - read ifname < $d/if_name - elif [ -d $d/net ] - then - ifname=$(ls $d/net/) - fi - [ -n "$ifname" ] && break - done - echo -n "$ifname" + local CCWGROUPBUS_DEVICEDIR="/sys/bus/ccwgroup/devices" + local NETWORK_DEVICES d ifname ONLINE + + [[ ! -d $CCWGROUPBUS_DEVICEDIR ]] && return + NETWORK_DEVICES=$(find $CCWGROUPBUS_DEVICEDIR) + for d in $NETWORK_DEVICES; do + [[ ! -f "$d/online" ]] && continue + read -r ONLINE < "$d/online" + if [[ $ONLINE -ne 1 ]]; then + continue + fi + # determine interface name, if there (only for qeth and if + # device is online) + if [[ -f $d/if_name ]]; then + read -r ifname < "$d/if_name" + elif [[ -d $d/net ]]; then + ifname=$(ls "$d/net/") + fi + [[ -n $ifname ]] && break + done + echo -n "$ifname" } # setup s390 znet cmdline # $1: netdev (ifname) -# $2: nmcli connection show output +# $2: nmcli connection path kdump_setup_znet() { local _netdev="$1" - local _nmcli_cmd="$2" + local _conpath="$2" local s390_prefix="802-3-ethernet.s390-" local _options="" local NETTYPE local SUBCHANNELS - NETTYPE=$(get_nmcli_value_by_field "$_nmcli_cmd" "${s390_prefix}nettype") - SUBCHANNELS=$(get_nmcli_value_by_field "$_nmcli_cmd" "${s390_prefix}subchannels") - _options=$(get_nmcli_value_by_field "$_nmcli_cmd" "${s390_prefix}options") + NETTYPE=$(get_nmcli_field_by_conpath "${s390_prefix}nettype" "$_conpath") + SUBCHANNELS=$(get_nmcli_field_by_conpath "${s390_prefix}subchannels" "$_conpath") + _options=$(get_nmcli_field_by_conpath "${s390_prefix}options" "$_conpath") - if [[ -z "$NETTYPE" || -z "$SUBCHANNELS" || -z "$_options" ]]; then + if [[ -z $NETTYPE || -z $SUBCHANNELS || -z $_options ]]; then dwarning "Failed to get znet configuration via nmlci output. Now try sourcing ifcfg script." - source_ifcfg_file $_netdev + source_ifcfg_file "$_netdev" for i in $OPTIONS; do _options=${_options},$i done fi - if [[ -z "$NETTYPE" || -z "$SUBCHANNELS" || -z "$_options" ]]; then + if [[ -z $NETTYPE || -z $SUBCHANNELS || -z $_options ]]; then exit 1 fi - echo rd.znet=${NETTYPE},${SUBCHANNELS},${_options} rd.znet_ifname=$_netdev:${SUBCHANNELS} > ${initdir}/etc/cmdline.d/30znet.conf + echo "rd.znet=${NETTYPE},${SUBCHANNELS},${_options} rd.znet_ifname=$_netdev:${SUBCHANNELS}" > "${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() { + local _route + if ! _route=$(/sbin/ip -o route get to "$1" 2>&1); then + derror "Bad kdump network destination: $1" + exit 1 + fi + echo "$_route" } -kdump_get_ip_route_field() -{ - if `echo $1 | grep -q $2`; then - echo ${1##*$2} | cut -d ' ' -f1 - fi +kdump_get_ip_route_field() { + echo "$1" | sed -n -e "s/^.*\<$2\>\s\+\(\S\+\).*$/\1/p" } -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` +kdump_get_remote_ip() { + local _remote _remote_temp + _remote=$(get_remote_host "$1") + 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` + _remote=$(echo "$_remote_temp" | awk '{print $1}') fi - echo $_remote + 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 _nm_show_cmd kdumpnic + local _destaddr _srcaddr _route _netdev _conpath kdumpnic local _static _proto _ip_conf _ip_opts _ifname_opts - local _znet_netdev _nm_show_cmd_znet + local _znet_netdev _znet_conpath - _destaddr=$(kdump_get_remote_ip $1) - _route=$(kdump_get_ip_route $_destaddr) + _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") - _nm_show_cmd=$(get_nmcli_connection_show_cmd_by_ifname "$_netdev") - _netmac=$(kdump_get_mac_addr $_netdev) - kdumpnic=$(kdump_setup_ifname $_netdev) + _conpath=$(get_nmcli_connection_apath_by_ifname "$_netdev") + _netmac=$(kdump_get_mac_addr "$_netdev") + kdumpnic=$(kdump_setup_ifname "$_netdev") _znet_netdev=$(find_online_znet_device) - if [[ -n "$_znet_netdev" ]]; then - _nm_show_cmd_znet=$(get_nmcli_connection_show_cmd_by_ifname "$_znet_netdev") - $(kdump_setup_znet "$_znet_netdev" "$_nm_show_cmd_znet") - if [[ $? != 0 ]]; then + if [[ -n $_znet_netdev ]]; then + _znet_conpath=$(get_nmcli_connection_apath_by_ifname "$_znet_netdev") + if ! (kdump_setup_znet "$_znet_netdev" "$_znet_conpath"); then derror "Failed to set up znet" exit 1 fi fi - _static=$(kdump_static_ip $_netdev $_srcaddr $kdumpnic) - if [ -n "$_static" ]; then + _static=$(kdump_static_ip "$_netdev" "$_srcaddr" "$kdumpnic") + if [[ -n $_static ]]; then _proto=none - elif is_ipv6_address $_srcaddr; then + elif is_ipv6_address "$_srcaddr"; then _proto=auto6 else _proto=dhcp @@ -580,32 +568,29 @@ kdump_install_net() { # 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 + 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" "$_nm_show_cmd") - if [[ $? != 0 ]]; then - exit 1 - fi + (kdump_setup_bond "$_netdev" "$_conpath") || exit 1 elif kdump_is_team "$_netdev"; then kdump_setup_team "$_netdev" elif kdump_is_vlan "$_netdev"; then kdump_setup_vlan "$_netdev" else _ifname_opts=" ifname=$kdumpnic:$_netmac" - echo "$_ifname_opts" >> $_ip_conf + echo "$_ifname_opts" >> "$_ip_conf" fi - kdump_setup_dns "$_netdev" "$_nm_show_cmd" + kdump_setup_dns "$_netdev" "$_conpath" - if [ ! -f ${initdir}/etc/cmdline.d/50neednet.conf ]; then + if [[ ! -f ${initdir}/etc/cmdline.d/50neednet.conf ]]; then # network-manager module needs this parameter - echo "rd.neednet" >> ${initdir}/etc/cmdline.d/50neednet.conf + echo "rd.neednet" >> "${initdir}/etc/cmdline.d/50neednet.conf" fi # Save netdev used for kdump as cmdline @@ -615,108 +600,108 @@ kdump_install_net() { # 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=$kdumpnic" > ${initdir}/etc/cmdline.d/60kdumpnic.conf - echo "bootdev=$kdumpnic" > ${initdir}/etc/cmdline.d/70bootdev.conf + if [[ ! -f ${initdir}/etc/cmdline.d/60kdumpnic.conf ]] \ + && [[ ! -f ${initdir}/etc/cmdline.d/70bootdev.conf ]]; then + echo "kdumpnic=$kdumpnic" > "${initdir}/etc/cmdline.d/60kdumpnic.conf" + echo "bootdev=$kdumpnic" > "${initdir}/etc/cmdline.d/70bootdev.conf" fi } # install etc/kdump/pre.d and /etc/kdump/post.d kdump_install_pre_post_conf() { - if [ -d /etc/kdump/pre.d ]; then + if [[ -d /etc/kdump/pre.d ]]; then for file in /etc/kdump/pre.d/*; do - if [ -x "$file" ]; then - dracut_install $file - elif [ $file != "/etc/kdump/pre.d/*" ]; then - echo "$file is not executable" + if [[ -x $file ]]; then + dracut_install "$file" + elif [[ $file != "/etc/kdump/pre.d/*" ]]; then + echo "$file is not executable" fi done fi - if [ -d /etc/kdump/post.d ]; then + if [[ -d /etc/kdump/post.d ]]; then for file in /etc/kdump/post.d/*; do - if [ -x "$file" ]; then - dracut_install $file - elif [ $file != "/etc/kdump/post.d/*" ]; then + if [[ -x $file ]]; then + dracut_install "$file" + elif [[ $file != "/etc/kdump/post.d/*" ]]; then echo "$file is not executable" fi done fi } -default_dump_target_install_conf() -{ +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) + _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 + _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) + _target=$(kdump_get_persistent_dev "$_target") fi - echo "$_fstype $_target" >> ${initdir}/tmp/$$-kdump.conf + echo "$_fstype $_target" >> "${initdir}/tmp/$$-kdump.conf" # don't touch the path under root mount - if [ "$_mntpoint" != "/" ]; then + 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 + 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 + kdump_read_conf > "${initdir}/tmp/$$-kdump.conf" + + while read -r _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:]]*}" - ;; + 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) + # shellcheck disable=SC2086 + dracut_install $_val + ;; + core_collector) + dracut_install "${_val%%[[:blank:]]*}" + ;; esac - done <<< "$(read_strip_comments /etc/kdump.conf)" + done <<< "$(kdump_read_conf)" kdump_install_pre_post_conf default_dump_target_install_conf - kdump_configure_fence_kdump "${initdir}/tmp/$$-kdump.conf" + kdump_configure_fence_kdump "${initdir}/tmp/$$-kdump.conf" inst "${initdir}/tmp/$$-kdump.conf" "/etc/kdump.conf" - rm -f ${initdir}/tmp/$$-kdump.conf + rm -f "${initdir}/tmp/$$-kdump.conf" } # Default sysctl parameters should suffice for kdump kernel. @@ -738,25 +723,26 @@ kdump_iscsi_get_rec_val() { # 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=$(/sbin/iscsiadm --show -m session -r "$1" | grep "^${2} = ") result=${result##* = } - echo $result + echo "$result" } kdump_get_iscsi_initiator() { local _initiator local initiator_conf="/etc/iscsi/initiatorname.iscsi" - [ -f "$initiator_conf" ] || return 1 + [[ -f $initiator_conf ]] || return 1 - while read _initiator; do - [ -z "${_initiator%%#*}" ] && continue # Skip comment lines + while read -r _initiator; do + [[ -z ${_initiator%%#*} ]] && continue # Skip comment lines case $_initiator in InitiatorName=*) initiator=${_initiator#InitiatorName=} echo "rd.iscsi.initiator=${initiator}" - return 0;; + return 0 + ;; *) ;; esac done < ${initiator_conf} @@ -766,15 +752,21 @@ kdump_get_iscsi_initiator() { # Figure out iBFT session according to session type is_ibft() { - [ "$(kdump_iscsi_get_rec_val $1 "node.discovery_type")" = fw ] + [[ "$(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 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" @@ -782,35 +774,35 @@ kdump_setup_iscsi_device() { # 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 + if ! /sbin/iscsiadm -m session -r "$path" &> /dev/null; then return 1 fi - if is_ibft ${path}; then + 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 + 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") + 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" == "" ] && username="" - password=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.password") - [ "$password" == "" ] && password="" - username_in=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.username_in") - [ -n "$username" ] && userpwd_str="$username:$password" + username=$(kdump_iscsi_get_rec_val "$path" "node.session.auth.username") + [[ $username == "" ]] && username="" + password=$(kdump_iscsi_get_rec_val "$path" "node.session.auth.password") + [[ $password == "" ]] && 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" == "" ] && username_in="" - password_in=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.password_in") - [ "$password_in" == "" ] && password_in="" + [[ $username_in == "" ]] && username_in="" + password_in=$(kdump_iscsi_get_rec_val "$path" "node.session.auth.password_in") + [[ $password_in == "" ]] && password_in="" - [ -n "$username_in" ] && userpwd_in_str=":$username_in:$password_in" + [[ -n $username_in ]] && userpwd_in_str=":$username_in:$password_in" kdump_install_net "$tgt_ipaddr" @@ -818,40 +810,42 @@ kdump_setup_iscsi_device() { # 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 + 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 + [[ -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" + 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_str=$(kdump_get_iscsi_initiator); then + derror "Failed to get initiator name" + return 1 + fi # 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" + 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 () { +kdump_check_iscsi_targets() { # If our prerequisites are not met, fail anyways. - type -P iscsistart >/dev/null || return 1 + 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)" + cd "$(readlink -f "/sys/dev/block/$_dev")" || return 1 until [[ -d sys || -d iscsi_session ]]; do cd .. done @@ -870,28 +864,29 @@ get_alias() { 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 + for ip in $ips; do + # in /etc/hosts, alias can come at the 2nd column + if entries=$(grep "$ip" /etc/hosts | awk '{ $1=""; print $0 }'); then + alias_set="$alias_set $entries" + fi done - echo $alias_set + echo "$alias_set" } is_localhost() { - local hostnames=$(hostname -A) - local shortnames=$(hostname -A -s) - local aliasname=$(get_alias) + local hostnames + local shortnames + local aliasname local nodename=$1 + hostnames=$(hostname -A) + shortnames=$(hostname -A -s) + aliasname=$(get_alias) hostnames="$hostnames $shortnames $aliasname" for name in ${hostnames}; do - if [ "$name" == "$nodename" ]; then + if [[ $name == "$nodename" ]]; then return 0 fi done @@ -904,29 +899,29 @@ get_pcs_fence_kdump_nodes() { pcs cluster sync > /dev/null 2>&1 && pcs cluster cib-upgrade > /dev/null 2>&1 # get cluster nodes from cluster cib, get interface and ip address - nodelist=`pcs cluster cib | xmllint --xpath "/cib/status/node_state/@uname" -` + 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 + eval "$node" + nodename="$uname" # Skip its own node name - if is_localhost $nodename; then + if is_localhost "$nodename"; then continue fi nodes="$nodes $nodename" done - echo $nodes + 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 + if [[ -f $FENCE_KDUMP_CONFIG_FILE ]]; then + . "$FENCE_KDUMP_CONFIG_FILE" + echo "$FENCE_KDUMP_OPTS" fi } @@ -934,20 +929,20 @@ get_generic_fence_kdump_nodes() { local filtered local nodes - nodes=$(get_option_value "fence_kdump_nodes") + nodes=$(kdump_get_conf_val "fence_kdump_nodes") for node in ${nodes}; do # Skip its own node name - if is_localhost $node; then + if is_localhost "$node"; then continue fi filtered="$filtered $node" done - echo $filtered + echo "$filtered" } # setup fence_kdump in cluster # setup proper network and install needed files -kdump_configure_fence_kdump () { +kdump_configure_fence_kdump() { local kdump_cfg_file=$1 local nodes local args @@ -959,11 +954,11 @@ kdump_configure_fence_kdump () { nodes=$(get_pcs_fence_kdump_nodes) # set appropriate options in kdump.conf - echo "fence_kdump_nodes $nodes" >> ${kdump_cfg_file} + 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} + if [[ -n $args ]]; then + echo "fence_kdump_args $args" >> "${kdump_cfg_file}" fi else @@ -973,47 +968,46 @@ kdump_configure_fence_kdump () { # setup network for each node for node in ${nodes}; do - kdump_install_net $node + kdump_install_net "$node" done dracut_install /etc/hosts dracut_install /etc/nsswitch.conf - dracut_install $FENCE_KDUMP_SEND + 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` + local poolsize + + poolsize=$(< /proc/sys/kernel/random/poolsize) - if [ ! -d ${initdir}/var/lib/ ]; then - mkdir -p ${initdir}/var/lib/ + 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 + dd if=/dev/urandom of="${initdir}/var/lib/random-seed" \ + bs="$poolsize" count=1 2> /dev/null } kdump_install_systemd_conf() { - local failure_action=$(get_option_value "failure_action") - # Kdump turns out to require longer default systemd mount timeout # than 1st kernel(90s by default), we use default 300s for kdump. - grep -r "^[[:space:]]*DefaultTimeoutStartSec=" ${initdir}/etc/systemd/system.conf* &>/dev/null - if [ $? -ne 0 ]; then - mkdir -p ${initdir}/etc/systemd/system.conf.d - echo "[Manager]" > ${initdir}/etc/systemd/system.conf.d/kdump.conf - echo "DefaultTimeoutStartSec=300s" >> ${initdir}/etc/systemd/system.conf.d/kdump.conf + if ! grep -q -r "^[[:space:]]*DefaultTimeoutStartSec=" "${initdir}/etc/systemd/system.conf"*; then + mkdir -p "${initdir}/etc/systemd/system.conf.d" + echo "[Manager]" > "${initdir}/etc/systemd/system.conf.d/kdump.conf" + echo "DefaultTimeoutStartSec=300s" >> "${initdir}/etc/systemd/system.conf.d/kdump.conf" fi # Forward logs to console directly, and don't read Kmsg, this avoids # unneccessary memory consumption and make console output more useful. # Only do so for non fadump image. - mkdir -p ${initdir}/etc/systemd/journald.conf.d - echo "[Journal]" > ${initdir}/etc/systemd/journald.conf.d/kdump.conf - echo "Storage=volatile" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf - echo "ReadKMsg=no" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf - echo "ForwardToConsole=yes" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf + mkdir -p "${initdir}/etc/systemd/journald.conf.d" + echo "[Journal]" > "${initdir}/etc/systemd/journald.conf.d/kdump.conf" + echo "Storage=volatile" >> "${initdir}/etc/systemd/journald.conf.d/kdump.conf" + echo "ReadKMsg=no" >> "${initdir}/etc/systemd/journald.conf.d/kdump.conf" + echo "ForwardToConsole=yes" >> "${initdir}/etc/systemd/journald.conf.d/kdump.conf" } install() { @@ -1026,7 +1020,7 @@ install() { fi dracut_install -o /etc/adjtime /etc/localtime inst "$moddir/monitor_dd_progress" "/kdumpscripts/monitor_dd_progress" - chmod +x ${initdir}/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" @@ -1035,18 +1029,17 @@ install() { inst "/bin/head" "/bin/head" inst "/bin/awk" "/bin/awk" inst "/bin/sed" "/bin/sed" + inst "/bin/stat" "/bin/stat" inst "/sbin/makedumpfile" "/sbin/makedumpfile" inst "/sbin/vmcore-dmesg" "/sbin/vmcore-dmesg" inst "/usr/bin/printf" "/sbin/printf" inst "/usr/bin/logger" "/sbin/logger" inst "/usr/bin/chmod" "/sbin/chmod" - inst "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh" inst "/lib/kdump/kdump-lib-initramfs.sh" "/lib/kdump-lib-initramfs.sh" inst "/lib/kdump/kdump-logger.sh" "/lib/kdump-logger.sh" inst "$moddir/kdump.sh" "/usr/bin/kdump.sh" inst "$moddir/kdump-capture.service" "$systemdsystemunitdir/kdump-capture.service" systemctl -q --root "$initdir" add-wants initrd.target kdump-capture.service - inst "$moddir/kdump-error-handler.sh" "/usr/bin/kdump-error-handler.sh" # 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" @@ -1071,8 +1064,8 @@ install() { # 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 + 's/\(^[[:space:]]*reserved_memory[[:space:]]*=\)[[:space:]]*[[:digit:]]*/\1 1024/' \ + "${initdir}/etc/lvm/lvm.conf" &> /dev/null # Save more memory by dropping switch root capability dracut_no_switch_root diff --git a/SOURCES/kdump-lib-initramfs.sh b/SOURCES/kdump-lib-initramfs.sh index 319f9a0..c1fd75f 100755 --- a/SOURCES/kdump-lib-initramfs.sh +++ b/SOURCES/kdump-lib-initramfs.sh @@ -1,293 +1,130 @@ -# These variables and functions are useful in 2nd kernel +#!/bin/sh +# +# The code in this file will be used in initramfs environment, bash may +# not be the default shell. Any code added must be POSIX compliant. -. /lib/kdump-lib.sh -. /lib/kdump-logger.sh +DEFAULT_PATH="/var/crash/" +KDUMP_CONFIG_FILE="/etc/kdump.conf" -KDUMP_PATH="/var/crash" -KDUMP_LOG_FILE="/run/initramfs/kexec-dmesg.log" -CORE_COLLECTOR="" -DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 7 -d 31" -DMESG_COLLECTOR="/sbin/vmcore-dmesg" -FAILURE_ACTION="systemctl reboot -f" -DATEDIR=`date +%Y-%m-%d-%T` -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" - -#initiate the kdump logger -dlog_init -if [ $? -ne 0 ]; then - echo "failed to initiate the kdump logger." - exit 1 -fi - -get_kdump_confs() +# Read kdump config in well formated style +kdump_read_conf() { - 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 + # Following steps are applied in order: strip trailing comment, strip trailing space, + # strip heading space, match non-empty line, remove duplicated spaces between conf name and value + [ -f "$KDUMP_CONFIG_FILE" ] && sed -n -e "s/#.*//;s/\s*$//;s/^\s*//;s/\(\S\+\)\s*\(.*\)/\1 \2/p" $KDUMP_CONFIG_FILE } -# store the kexec kernel log to a file. -save_log() +# Retrieves config value defined in kdump.conf +# $1: config name, sed regexp compatible +kdump_get_conf_val() { - dmesg -T > $KDUMP_LOG_FILE - - if command -v journalctl > /dev/null; then - journalctl -ab >> $KDUMP_LOG_FILE - fi - chmod 600 $KDUMP_LOG_FILE + # For lines matching "^\s*$1\s+", remove matched part (config name including space), + # remove tailing comment, space, then store in hold space. Print out the hold buffer on last line. + [ -f "$KDUMP_CONFIG_FILE" ] && + sed -n -e "/^\s*\($1\)\s\+/{s/^\s*\($1\)\s\+//;s/#.*//;s/\s*$//;h};\${x;p}" $KDUMP_CONFIG_FILE } -# dump_fs -dump_fs() +is_mounted() { - local _exitcode - local _mp=$1 - local _op=$(get_mount_info OPTIONS target $_mp -f) - ddebug "dump_fs _mp=$_mp _opts=$_op" - - if ! is_mounted "$_mp"; then - dinfo "dump path \"$_mp\" is not mounted, trying to mount..." - mount --target $_mp - if [ $? -ne 0 ]; then - derror "failed to dump to \"$_mp\", it's not a mount point!" - return 1 - fi - 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"` - - local _dump_path=$(echo "$_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/" | tr -s /) - - dinfo "saving to $_dump_path" - - # Only remount to read-write mode if the dump target is mounted read-only. - if [[ "$_op" = "ro"* ]]; then - dinfo "Remounting the dump target in rw mode." - mount -o remount,rw $_mp || return 1 - fi - - mkdir -p $_dump_path || return 1 - - save_vmcore_dmesg_fs ${DMESG_COLLECTOR} "$_dump_path" - save_opalcore_fs "$_dump_path" - - dinfo "saving vmcore" - $CORE_COLLECTOR /proc/vmcore $_dump_path/vmcore-incomplete - _exitcode=$? - if [ $_exitcode -eq 0 ]; then - mv $_dump_path/vmcore-incomplete $_dump_path/vmcore - sync - dinfo "saving vmcore complete" - else - derror "saving vmcore failed, _exitcode:$_exitcode" - fi - - dinfo "saving the $KDUMP_LOG_FILE to $_dump_path/" - save_log - mv $KDUMP_LOG_FILE $_dump_path/ - if [ $_exitcode -ne 0 ]; then - return 1 - fi - - # improper kernel cmdline can cause the failure of echo, we can ignore this kind of failure - return 0 + findmnt -k -n "$1" > /dev/null 2>&1 } -save_vmcore_dmesg_fs() { - local _dmesg_collector=$1 - local _path=$2 +# $1: info type +# $2: mount source type +# $3: mount source +# $4: extra args +get_mount_info() +{ + __kdump_mnt=$(findmnt -k -n -r -o "$1" "--$2" "$3" $4) - dinfo "saving vmcore-dmesg.txt to ${_path}" - $_dmesg_collector /proc/vmcore > ${_path}/vmcore-dmesg-incomplete.txt - _exitcode=$? - if [ $_exitcode -eq 0 ]; then - mv ${_path}/vmcore-dmesg-incomplete.txt ${_path}/vmcore-dmesg.txt - chmod 600 ${_path}/vmcore-dmesg.txt + [ -z "$__kdump_mnt" ] && [ -e "/etc/fstab" ] && __kdump_mnt=$(findmnt -s -n -r -o "$1" "--$2" "$3" $4) - # 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 - dinfo "saving vmcore-dmesg.txt complete" - else - if [ -f ${_path}/vmcore-dmesg-incomplete.txt ]; then - chmod 600 ${_path}/vmcore-dmesg-incomplete.txt - fi - derror "saving vmcore-dmesg.txt failed" - fi + echo "$__kdump_mnt" } -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 +is_ipv6_address() +{ + echo "$1" | grep -q ":" +} - dinfo "saving opalcore:$OPALCORE to ${_path}/opalcore" - cp $OPALCORE ${_path}/opalcore - if [ $? -ne 0 ]; then - derror "saving opalcore failed" - return 1 - fi +is_fs_type_nfs() +{ + [ "$1" = "nfs" ] || [ "$1" = "nfs4" ] +} - sync - dinfo "saving opalcore complete" - return 0 +# If $1 contains dracut_args "--mount", return +get_dracut_args_fstype() +{ + echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f3 } -dump_to_rootfs() +# If $1 contains dracut_args "--mount", return +get_dracut_args_target() { + echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f1 +} - if [[ $(systemctl status dracut-initqueue | sed -n "s/^\s*Active: \(\S*\)\s.*$/\1/p") == "inactive" ]]; then - dinfo "Trying to bring up initqueue for rootfs mount" - systemctl start dracut-initqueue - fi +get_save_path() +{ + __kdump_path=$(kdump_get_conf_val path) + [ -z "$__kdump_path" ] && __kdump_path=$DEFAULT_PATH - dinfo "Clean up dead systemd services" - systemctl cancel - dinfo "Waiting for rootfs mount, will timeout after 90 seconds" - systemctl start --no-block sysroot.mount + # strip the duplicated "/" + echo "$__kdump_path" | tr -s / +} - _loop=0 - while [ $_loop -lt 90 ] && ! is_mounted /sysroot; do - sleep 1 - _loop=$((_loop + 1)) - done +get_root_fs_device() +{ + findmnt -k -f -n -o SOURCE / +} - if ! is_mounted /sysroot; then - derror "Failed to mount rootfs" - return - fi +# Return the current underlying device of a path, ignore bind mounts +get_target_from_path() +{ + __kdump_target=$(df "$1" 2> /dev/null | tail -1 | awk '{print $1}') + [ "$__kdump_target" = "/dev/root" ] && [ ! -e /dev/root ] && __kdump_target=$(get_root_fs_device) + echo "$__kdump_target" +} - ddebug "NEWROOT=$NEWROOT" - dump_fs $NEWROOT +get_fs_type_from_target() +{ + get_mount_info FSTYPE source "$1" -f } -kdump_emergency_shell() +get_mntpoint_from_target() { - ddebug "Switching to kdump emergency shell..." + # --source is applied to ensure non-bind mount is returned + get_mount_info TARGET source "$1" -f +} - [ -f /etc/profile ] && . /etc/profile - export PS1='kdump:${PWD}# ' +is_ssh_dump_target() +{ + kdump_get_conf_val ssh | grep -q @ +} - . /lib/dracut-lib.sh - if [ -f /dracut-state.sh ]; then - . /dracut-state.sh 2>/dev/null - fi +is_raw_dump_target() +{ + [ -n "$(kdump_get_conf_val raw)" ] +} - source_conf /etc/conf.d +is_nfs_dump_target() +{ + if [ -n "$(kdump_get_conf_val nfs)" ]; then + return 0 + fi - type plymouth >/dev/null 2>&1 && plymouth quit + if is_fs_type_nfs "$(get_dracut_args_fstype "$(kdump_get_conf_val dracut_args)")"; then + return 0 + fi - source_hook "emergency" - while read _tty rest; do - ( - echo - echo - echo 'Entering kdump emergency mode.' - echo 'Type "journalctl" to view system logs.' - echo 'Type "rdsosreport" to generate a sosreport, you can then' - echo 'save it elsewhere and attach it to a bug report.' - echo - echo - ) > /dev/$_tty - done < /proc/consoles - sh -i -l - /bin/rm -f -- /.console_lock -} + if is_fs_type_nfs "$(get_fs_type_from_target "$(get_target_from_path "$(get_save_path)")")"; then + return 0 + fi -do_failure_action() -{ - dinfo "Executing failure action $FAILURE_ACTION" - eval $FAILURE_ACTION + return 1 } -do_final_action() +is_fs_dump_target() { - dinfo "Executing final action $FINAL_ACTION" - eval $FINAL_ACTION + [ -n "$(kdump_get_conf_val "ext[234]\|xfs\|btrfs\|minix")" ] } diff --git a/SOURCES/kdump-lib.sh b/SOURCES/kdump-lib.sh index 861f6e4..09e2058 100755 --- a/SOURCES/kdump-lib.sh +++ b/SOURCES/kdump-lib.sh @@ -1,213 +1,151 @@ -#!/bin/sh +#!/bin/bash # # Kdump common variables and functions # -DEFAULT_PATH="/var/crash/" +. /usr/lib/kdump/kdump-lib-initramfs.sh + 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 -} - -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 -} - -perror_exit() { - derror "$@" - exit 1 -} - -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 + # Check if firmware-assisted dump is enabled + # if no, fallback to kdump check + if [[ -f $FADUMP_ENABLED_SYS_NODE ]]; then + rc=$(< $FADUMP_ENABLED_SYS_NODE) + [[ $rc -eq 1 ]] && return 0 + fi + return 1 } -strip_comments() +is_squash_available() { - echo $@ | sed -e 's/\(.*\)#.*/\1/' + 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 } -# Read from kdump config file stripping all comments -read_strip_comments() +perror_exit() { - # 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 + derror "$@" + exit 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 + # 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 + # 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 + [[ -x $FENCE_KDUMP_SEND ]] || return 1 - grep -q "^fence_kdump_nodes" /etc/kdump.conf + [[ $(kdump_get_conf_val fence_kdump_nodes) ]] } -to_dev_name() { - local dev="${1//\"/}" - - case "$dev" in - UUID=*) - dev=`blkid -U "${dev#UUID=}"` - ;; - LABEL=*) - dev=`blkid -L "${dev#LABEL=}"` - ;; - esac - echo $dev +to_dev_name() +{ + local dev="${1//\"/}" + + case "$dev" in + UUID=*) + blkid -U "${dev#UUID=}" + ;; + LABEL=*) + blkid -L "${dev#LABEL=}" + ;; + *) + echo "$dev" + ;; + esac } is_user_configured_dump_target() { - grep -E -q "^ext[234]|^xfs|^btrfs|^minix|^raw|^nfs|^ssh" /etc/kdump.conf || is_mount_in_dracut_args; + [[ $(kdump_get_conf_val "ext[234]\|xfs\|btrfs\|minix\|raw\|nfs\|ssh") ]] || 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 / -} + local _target -get_save_path() -{ - local _save_path=$(awk '$1 == "path" {print $2}' /etc/kdump.conf) - [ -z "$_save_path" ] && _save_path=$DEFAULT_PATH + _target=$(kdump_get_conf_val "ext[234]\|xfs\|btrfs\|minix\|raw") + [[ -n $_target ]] && echo "$_target" && return - # strip the duplicated "/" - echo $_save_path | tr -s / + _target=$(get_dracut_args_target "$(kdump_get_conf_val "dracut_args")") + [[ -b $_target ]] && echo "$_target" } get_block_dump_target() { - local _target _path + local _target _path - if is_ssh_dump_target || is_nfs_dump_target; then - return - fi + 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 + _target=$(get_user_configured_dump_disk) + [[ -n $_target ]] && 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) + # Get block device name from local save path + _path=$(get_save_path) + _target=$(get_target_from_path "$_path") + [[ -b $_target ]] && to_dev_name "$_target" } is_dump_to_rootfs() { - grep -E "^(failure_action|default)[[:space:]]dump_to_rootfs" /etc/kdump.conf >/dev/null + [[ $(kdump_get_conf_val "failure_action|default") == dump_to_rootfs ]] } 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 + local _target + + if is_dump_to_rootfs; then + # Get rootfs device name + _target=$(get_root_fs_device) + [[ -b $_target ]] && 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" + 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 ]] && [[ $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 @@ -224,171 +162,130 @@ get_kdump_targets() # part is the bind mounted directory which quotes by bracket "[]". get_bind_mount_source() { - local _mnt=$(df $1 | tail -1 | awk '{print $NF}') - local _path=${1#$_mnt} - - local _src=$(get_mount_info SOURCE target $_mnt -f) - local _opt=$(get_mount_info OPTIONS target $_mnt -f) - local _fstype=$(get_mount_info FSTYPE target $_mnt -f) - - # bind mount in fstab - if [[ -d "$_src" ]] && [[ "$_fstype" = none ]] && (echo "$_opt" | grep -q "\bbind\b"); then - echo $_src$_path && return - fi - - # direct mount - local _src_nofsroot=$(get_mount_info SOURCE target $_mnt -v -f) - if [[ $_src_nofsroot = $_src ]]; then - echo $_mnt$_path && return - fi - - local _fsroot=${_src#$_src_nofsroot[} - _fsroot=${_fsroot%]} - _mnt=$(get_mount_info TARGET source $_src_nofsroot -f) - - # for btrfs, _fsroot will also contain the subvol value as well, strip it - if [[ "$_fstype" = btrfs ]]; then - local _subvol - _subvol=${_opt#*subvol=} - _subvol=${_subvol%,*} - _fsroot=${_fsroot#$_subvol} - fi - echo $_mnt$_fsroot$_path -} + local _mnt _path _src _opt _fstype + local _fsroot _src_nofsroot -# Return the current underlaying device of a path, ignore bind mounts -get_target_from_path() -{ - local _target + _mnt=$(df "$1" | tail -1 | awk '{print $NF}') + _path=${1#$_mnt} - _target=$(df $1 2>/dev/null | tail -1 | awk '{print $1}') - [[ "$_target" == "/dev/root" ]] && [[ ! -e /dev/root ]] && _target=$(get_root_fs_device) - echo $_target -} + _src=$(get_mount_info SOURCE target "$_mnt" -f) + _opt=$(get_mount_info OPTIONS target "$_mnt" -f) + _fstype=$(get_mount_info FSTYPE target "$_mnt" -f) -is_mounted() -{ - findmnt -k -n $1 &>/dev/null -} + # bind mount in fstab + if [[ -d $_src ]] && [[ $_fstype == none ]] && (echo "$_opt" | grep -q "\bbind\b"); then + echo "$_src$_path" && return + fi -get_mount_info() -{ - local _info_type=$1 _src_type=$2 _src=$3; shift 3 - local _info=$(findmnt -k -n -r -o $_info_type --$_src_type $_src $@) + # direct mount + _src_nofsroot=$(get_mount_info SOURCE target "$_mnt" -v -f) + if [[ $_src_nofsroot == "$_src" ]]; then + echo "$_mnt$_path" && return + fi - [ -z "$_info" ] && [ -e "/etc/fstab" ] && _info=$(findmnt -s -n -r -o $_info_type --$_src_type $_src $@) + _fsroot=${_src#${_src_nofsroot}[} + _fsroot=${_fsroot%]} + _mnt=$(get_mount_info TARGET source "$_src_nofsroot" -f) - echo $_info -} - -get_fs_type_from_target() -{ - get_mount_info FSTYPE source $1 -f + # for btrfs, _fsroot will also contain the subvol value as well, strip it + if [[ $_fstype == btrfs ]]; then + local _subvol + _subvol=${_opt#*subvol=} + _subvol=${_subvol%,*} + _fsroot=${_fsroot#$_subvol} + fi + echo "$_mnt$_fsroot$_path" } get_mntopt_from_target() { - get_mount_info OPTIONS source $1 -f -} -# 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 - get_mount_info TARGET source $1 -f + get_mount_info OPTIONS source "$1" -f } # Get the path where the target will be mounted in kdump kernel # $1: kdump target device get_kdump_mntpoint_from_target() { - local _mntpoint=$(get_mntpoint_from_target $1) - - # mount under /sysroot if dump to root disk or mount under - # mount under /kdumproot if dump target is not mounted in first kernel - # mount under /kdumproot/$_mntpoint in other cases in 2nd kernel. - # systemd will be in charge to umount it. - if [ -z "$_mntpoint" ];then - _mntpoint="/kdumproot" - else - if [ "$_mntpoint" = "/" ];then - _mntpoint="/sysroot" - else - _mntpoint="/kdumproot/$_mntpoint" - fi - fi - - # strip duplicated "/" - echo $_mntpoint | tr -s "/" -} + local _mntpoint -# get_option_value -# retrieves value of option defined in kdump.conf -get_option_value() { - strip_comments `grep "^$1[[:space:]]\+" /etc/kdump.conf | tail -1 | cut -d\ -f2-` -} + _mntpoint=$(get_mntpoint_from_target "$1") + # mount under /sysroot if dump to root disk or mount under + # mount under /kdumproot if dump target is not mounted in first kernel + # mount under /kdumproot/$_mntpoint in other cases in 2nd kernel. + # systemd will be in charge to umount it. + if [[ -z $_mntpoint ]]; then + _mntpoint="/kdumproot" + else + if [[ $_mntpoint == "/" ]]; then + _mntpoint="/sysroot" + else + _mntpoint="/kdumproot/$_mntpoint" + fi + fi -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") + # strip duplicated "/" + echo $_mntpoint | tr -s "/" } -is_atomic() +kdump_get_persistent_dev() { - grep -q "ostree" /proc/cmdline + local dev="${1//\"/}" + + case "$dev" in + UUID=*) + dev=$(blkid -U "${dev#UUID=}") + ;; + LABEL=*) + dev=$(blkid -L "${dev#LABEL=}") + ;; + esac + echo $(get_persistent_dev "$dev") } -is_ipv6_address() +is_atomic() { - echo $1 | grep -q ":" + grep -q "ostree" /proc/cmdline } # 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 + 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 ":"` + local _hostname - if [ -n "$_hostname" ]; then - return 1 - fi - echo $1 | grep -q "[a-zA-Z]" + _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:]:]*).*/, + 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 + fi } - # Get value by a field using "nmcli -g" +# Usage: get_nmcli_value_by_field # # "nmcli --get-values" allows us to retrive value(s) by field, for example, # nmcli --get-values connection show /org/freedesktop/NetworkManager/ActiveConnection/1 @@ -399,12 +296,16 @@ get_hwaddr() # bond.options "mode=balance-rr" get_nmcli_value_by_field() { - local _nm_show_cmd=$1 - local _field=$2 + LANG=C nmcli --get-values "$@" +} - local val=$(LANG=C nmcli --get-values $_field $_nm_show_cmd) +# Get nmcli field value of an connection apath (a D-Bus active connection path) +# Usage: get_nmcli_field_by_apath +get_nmcli_field_by_conpath() +{ + local _field=$1 _apath=$2 - echo -n "$val" + get_nmcli_value_by_field "$_field" connection show "$_apath" } # Get nmcli connection apath (a D-Bus active connection path ) by ifname @@ -413,146 +314,133 @@ get_nmcli_value_by_field() # $ nmcli connection show $apath get_nmcli_connection_apath_by_ifname() { - local _ifname=$1 - local _nm_show_cmd="device show $_ifname" - - local _apath=$(get_nmcli_value_by_field "$_nm_show_cmd" "GENERAL.CON-PATH") + local _ifname=$1 - echo -n "$_apath" -} - -# Get nmcli connection show cmd by ifname -# -# "$_apath" is supposed to not contain any chracter that -# need to be escapded, e.g. space. Otherwise get_nmcli_value_by_field -# would fail. -get_nmcli_connection_show_cmd_by_ifname() -{ - local _ifname="$1" - local _apath=$(get_nmcli_connection_apath_by_ifname "$_ifname") - local _nm_show_cmd="connection show $_apath" - - echo -n "$_nm_show_cmd" + get_nmcli_value_by_field "GENERAL.CON-PATH" device show "$_ifname" } get_ifcfg_by_device() { - grep -E -i -l "^[[:space:]]*DEVICE=\"*${1}\"*[[:space:]]*$" \ - /etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1 + 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 + 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 + 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 + 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" ] + [[ "$(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.*\)$" + 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=" and "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}" + 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=" and "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 + local ifcfg_file hwaddr - ifcfg_file="/etc/sysconfig/network-scripts/ifcfg-${1}" - [ -f "${ifcfg_file}" ] && echo -n "${ifcfg_file}" && return + 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 + 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 + 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}") + ifcfg_file=$(get_ifcfg_by_device "${1}") - echo -n "${ifcfg_file}" + 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 +get_ifcfg_filename() +{ + local ifcfg_file - ifcfg_file=$(get_ifcfg_nmcli "${1}") - if [ -z "${ifcfg_file}" ]; then - ifcfg_file=$(get_ifcfg_legacy "${1}") - fi + ifcfg_file=$(get_ifcfg_nmcli "${1}") + if [[ -z ${ifcfg_file} ]]; then + ifcfg_file=$(get_ifcfg_legacy "${1}") + fi - echo -n "${ifcfg_file}" + echo -n "${ifcfg_file}" } # returns 0 when omission of a module is desired in dracut_args # returns 1 otherwise -is_dracut_mod_omitted() { - local dracut_args dracut_mod=$1 - - set -- $(grep "^dracut_args" /etc/kdump.conf) - while [ $# -gt 0 ]; do - case $1 in - -o|--omit) - [[ " ${2//[^[:alnum:]]/ } " == *" $dracut_mod "* ]] && return 0 - esac - shift - done - - return 1 +is_dracut_mod_omitted() +{ + local dracut_args dracut_mod=$1 + + set -- $(kdump_get_conf_val dracut_args) + while [ $# -gt 0 ]; do + case $1 in + -o | --omit) + [[ " ${2//[^[:alnum:]]/ } " == *" $dracut_mod "* ]] && return 0 + ;; + esac + shift + done + + return 1 } -is_wdt_active() { - local active +is_wdt_active() +{ + local active - [ -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 + [[ -d /sys/class/watchdog ]] || return 1 + for dir in /sys/class/watchdog/*; do + [[ -f "$dir/state" ]] || continue + active=$(< "$dir/state") + [[ $active == "active" ]] && return 0 + done + return 1 } # If "dracut_args" contains "--mount" information, use it @@ -560,57 +448,45 @@ is_wdt_active() { # its correctness). is_mount_in_dracut_args() { - grep -q "^dracut_args .*\-\-mount" /etc/kdump.conf -} - -# If $1 contains dracut_args "--mount", return -get_dracut_args_fstype() -{ - echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f3 -} - -# If $1 contains dracut_args "--mount", return -get_dracut_args_target() -{ - echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f1 + [[ " $(kdump_get_conf_val dracut_args)" =~ .*[[:space:]]--mount[=[:space:]].* ]] } check_crash_mem_reserved() { - local mem_reserved + local mem_reserved - mem_reserved=$(cat /sys/kernel/kexec_crash_size) - if [ $mem_reserved -eq 0 ]; then - derror "No memory reserved for crash kernel" - return 1 - fi + mem_reserved=$(< /sys/kernel/kexec_crash_size) + if [[ $mem_reserved -eq 0 ]]; then + derror "No memory reserved for crash kernel" + return 1 + fi - return 0 + return 0 } check_kdump_feasibility() { - if [ ! -e /sys/kernel/kexec_crash_loaded ]; then - derror "Kdump is not supported on this kernel" - return 1 - fi - check_crash_mem_reserved - return $? + if [[ ! -e /sys/kernel/kexec_crash_loaded ]]; then + derror "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 - derror "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 + if [[ ! -f /sys/kernel/kexec_crash_loaded ]]; then + derror "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel" + return 1 + fi + + rc=$(< /sys/kernel/kexec_crash_loaded) + if [[ $rc == 1 ]]; then + return 0 + else + return 1 + fi } # remove_cmdline_param [] ... [] @@ -618,17 +494,17 @@ check_current_kdump_status() # 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 + 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" } # @@ -637,12 +513,12 @@ remove_cmdline_param() # get_bootcpu_apicid() { - awk ' \ + awk ' \ BEGIN { CPU = "-1"; } \ $1=="processor" && $2==":" { CPU = $NF; } \ CPU=="0" && /^apicid/ { print $NF; } \ - ' \ - /proc/cpuinfo + ' \ + /proc/cpuinfo } # @@ -651,23 +527,23 @@ get_bootcpu_apicid() # append_cmdline() { - local cmdline=$1 - local newstr=${cmdline/$2/""} + local cmdline=$1 + local newstr=${cmdline/$2/""} - # unchanged str implies argument wasn't there - if [ "$cmdline" == "$newstr" ]; then - cmdline="${cmdline} ${2}=${3}" - fi + # unchanged str implies argument wasn't there + if [[ $cmdline == "$newstr" ]]; then + cmdline="${cmdline} ${2}=${3}" + fi - echo $cmdline + 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")); }'` + return "$(tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); + print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }')" } # Check if secure boot is being enforced. @@ -681,34 +557,34 @@ need_64bit_headers() # Assume efivars is mounted at /sys/firmware/efi/efivars. is_secure_boot_enforced() { - local secure_boot_file setup_mode_file - local secure_boot_byte setup_mode_byte + local secure_boot_file setup_mode_file + local secure_boot_byte setup_mode_byte - # On powerpc, os-secureboot-enforcing DT property indicates whether secureboot - # is enforced. Return success, if it is found. - if [ -f /proc/device-tree/ibm,secureboot/os-secureboot-enforcing ]; then + # On powerpc, os-secureboot-enforcing DT property indicates whether secureboot + # is enforced. Return success, if it is found. + if [[ -f /proc/device-tree/ibm,secureboot/os-secureboot-enforcing ]]; then return 0 - fi + fi - # Detect secure boot on x86 and arm64 - secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null) - setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null) + # Detect secure boot on x86 and arm64 + secure_boot_file=$(find /sys/firmware/efi/efivars -name "SecureBoot-*" 2> /dev/null) + setup_mode_file=$(find /sys/firmware/efi/efivars -name "SetupMode-*" 2> /dev/null) - if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then - secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' $secure_boot_file|cut -d' ' -f 5) - setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' $setup_mode_file|cut -d' ' -f 5) + if [[ -f $secure_boot_file ]] && [[ -f $setup_mode_file ]]; then + secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' "$secure_boot_file" | cut -d' ' -f 5) + setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' "$setup_mode_file" | cut -d' ' -f 5) - if [ "$secure_boot_byte" = "1" ] && [ "$setup_mode_byte" = "0" ]; then - return 0 - fi - fi + if [[ $secure_boot_byte == "1" ]] && [[ $setup_mode_byte == "0" ]]; then + return 0 + fi + fi - # Detect secure boot on s390x - if [[ -e "/sys/firmware/ipl/secure" && "$(cat /sys/firmware/ipl/secure)" == "1" ]]; then - return 0 - fi + # Detect secure boot on s390x + if [[ -e "/sys/firmware/ipl/secure" && "$(< /sys/firmware/ipl/secure)" == "1" ]]; then + return 0 + fi - return 1 + return 1 } # @@ -717,31 +593,27 @@ is_secure_boot_enforced() # 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 - dwarn "Warning: elf32-core-headers overrides correct elf64 setting" - 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 + local kexec_args=$1 + local found_elf_args + + ARCH=$(uname -m) + if [[ $ARCH == "i686" ]] || [[ $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 + dwarn "Warning: elf32-core-headers overrides correct elf64 setting" + 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" } # @@ -753,88 +625,88 @@ prepare_kexec_args() # prepare_kdump_bootinfo() { - local boot_imglist boot_dirlist boot_initrdlist curr_kver="$(uname -r)" - local machine_id - - if [ -z "$KDUMP_KERNELVER" ]; then - KDUMP_KERNELVER="$(uname -r)" - fi - - read machine_id < /etc/machine-id - boot_dirlist=${KDUMP_BOOTDIR:-"/boot /boot/efi /efi /"} - boot_imglist="$KDUMP_IMG-$KDUMP_KERNELVER$KDUMP_IMG_EXT $machine_id/$KDUMP_KERNELVER/$KDUMP_IMG" - - # Use BOOT_IMAGE as reference if possible, strip the GRUB root device prefix in (hd0,gpt1) format - local boot_img="$(cat /proc/cmdline | sed "s/^BOOT_IMAGE=\((\S*)\)\?\(\S*\) .*/\2/")" - if [ -n "$boot_img" ]; then - boot_imglist="$boot_img $boot_imglist" - fi - - for dir in $boot_dirlist; do - for img in $boot_imglist; do - if [ -f "$dir/$img" ]; then - KDUMP_KERNEL=$(echo $dir/$img | tr -s '/') - break 2 - fi - done - done - - if ! [ -e "$KDUMP_KERNEL" ]; then - derror "Failed to detect kdump kernel location" - return 1 - fi - - # Set KDUMP_BOOTDIR to where kernel image is stored - KDUMP_BOOTDIR=$(dirname $KDUMP_KERNEL) - - # Default initrd should just stay aside of kernel image, try to find it in KDUMP_BOOTDIR - boot_initrdlist="initramfs-$KDUMP_KERNELVER.img initrd" - for initrd in $boot_initrdlist; do - if [ -f "$KDUMP_BOOTDIR/$initrd" ]; then - defaut_initrd_base="$initrd" - DEFAULT_INITRD="$KDUMP_BOOTDIR/$defaut_initrd_base" - break - fi - done - - # Create kdump initrd basename from default initrd basename - # initramfs-5.7.9-200.fc32.x86_64.img => initramfs-5.7.9-200.fc32.x86_64kdump.img - # initrd => initrdkdump - if [[ -z "$defaut_initrd_base" ]]; then - kdump_initrd_base=initramfs-${KDUMP_KERNELVER}kdump.img - elif [[ $defaut_initrd_base == *.* ]]; then - kdump_initrd_base=${defaut_initrd_base%.*}kdump.${DEFAULT_INITRD##*.} - else - kdump_initrd_base=${defaut_initrd_base}kdump - fi - - # Place kdump initrd in `/var/lib/kdump` if `KDUMP_BOOTDIR` not writable - if [[ ! -w "$KDUMP_BOOTDIR" ]];then - var_target_initrd_dir="/var/lib/kdump" - mkdir -p "$var_target_initrd_dir" - KDUMP_INITRD="$var_target_initrd_dir/$kdump_initrd_base" - else - KDUMP_INITRD="$KDUMP_BOOTDIR/$kdump_initrd_base" - fi + local boot_img boot_imglist boot_dirlist boot_initrdlist + local machine_id + + if [[ -z $KDUMP_KERNELVER ]]; then + KDUMP_KERNELVER="$(uname -r)" + fi + + read -r machine_id < /etc/machine-id + boot_dirlist=${KDUMP_BOOTDIR:-"/boot /boot/efi /efi /"} + boot_imglist="$KDUMP_IMG-$KDUMP_KERNELVER$KDUMP_IMG_EXT $machine_id/$KDUMP_KERNELVER/$KDUMP_IMG" + + # Use BOOT_IMAGE as reference if possible, strip the GRUB root device prefix in (hd0,gpt1) format + boot_img="$(sed "s/^BOOT_IMAGE=\((\S*)\)\?\(\S*\) .*/\2/" /proc/cmdline)" + if [[ -n $boot_img ]]; then + boot_imglist="$boot_img $boot_imglist" + fi + + for dir in $boot_dirlist; do + for img in $boot_imglist; do + if [[ -f "$dir/$img" ]]; then + KDUMP_KERNEL=$(echo "$dir/$img" | tr -s '/') + break 2 + fi + done + done + + if ! [[ -e $KDUMP_KERNEL ]]; then + derror "Failed to detect kdump kernel location" + return 1 + fi + + # Set KDUMP_BOOTDIR to where kernel image is stored + KDUMP_BOOTDIR=$(dirname "$KDUMP_KERNEL") + + # Default initrd should just stay aside of kernel image, try to find it in KDUMP_BOOTDIR + boot_initrdlist="initramfs-$KDUMP_KERNELVER.img initrd" + for initrd in $boot_initrdlist; do + if [[ -f "$KDUMP_BOOTDIR/$initrd" ]]; then + defaut_initrd_base="$initrd" + DEFAULT_INITRD="$KDUMP_BOOTDIR/$defaut_initrd_base" + break + fi + done + + # Create kdump initrd basename from default initrd basename + # initramfs-5.7.9-200.fc32.x86_64.img => initramfs-5.7.9-200.fc32.x86_64kdump.img + # initrd => initrdkdump + if [[ -z $defaut_initrd_base ]]; then + kdump_initrd_base=initramfs-${KDUMP_KERNELVER}kdump.img + elif [[ $defaut_initrd_base == *.* ]]; then + kdump_initrd_base=${defaut_initrd_base%.*}kdump.${DEFAULT_INITRD##*.} + else + kdump_initrd_base=${defaut_initrd_base}kdump + fi + + # Place kdump initrd in $(/var/lib/kdump) if $(KDUMP_BOOTDIR) not writable + if [[ ! -w $KDUMP_BOOTDIR ]]; then + var_target_initrd_dir="/var/lib/kdump" + mkdir -p "$var_target_initrd_dir" + KDUMP_INITRD="$var_target_initrd_dir/$kdump_initrd_base" + else + KDUMP_INITRD="$KDUMP_BOOTDIR/$kdump_initrd_base" + fi } get_watchdog_drvs() { - local _wdtdrvs _drv _dir - - for _dir in /sys/class/watchdog/*; do - # device/modalias will return driver of this device - [[ -f "$_dir/device/modalias" ]] || continue - _drv=$(< "$_dir/device/modalias") - _drv=$(modprobe --set-version "$KDUMP_KERNELVER" -R $_drv 2>/dev/null) - for i in $_drv; do - if ! [[ " $_wdtdrvs " == *" $i "* ]]; then - _wdtdrvs="$_wdtdrvs $i" - fi - done - done - - echo $_wdtdrvs + local _wdtdrvs _drv _dir + + for _dir in /sys/class/watchdog/*; do + # device/modalias will return driver of this device + [[ -f "$_dir/device/modalias" ]] || continue + _drv=$(< "$_dir/device/modalias") + _drv=$(modprobe --set-version "$KDUMP_KERNELVER" -R "$_drv" 2> /dev/null) + for i in $_drv; do + if ! [[ " $_wdtdrvs " == *" $i "* ]]; then + _wdtdrvs="$_wdtdrvs $i" + fi + done + done + + echo "$_wdtdrvs" } # @@ -843,140 +715,143 @@ get_watchdog_drvs() # 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.lvm.lv 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 - - # If any watchdog is used, set it's pretimeout to 0. pretimeout let - # watchdog panic the kernel first, and reset the system after the - # panic. If the system is already in kdump, panic is not helpful - # and only increase the chance of watchdog failure. - for i in $(get_watchdog_drvs); do - cmdline+=" $i.pretimeout=0" - - if [[ $i == hpwdt ]]; then - # hpwdt have a special parameter kdumptimeout, is's only suppose - # to be set to non-zero in first kernel. In kdump, non-zero - # value could prevent the watchdog from resetting the system. - cmdline+=" $i.kdumptimeout=0" - fi - done - - echo ${cmdline} + local cmdline id arg + + if [[ -z $1 ]]; then + cmdline=$(< /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 + while read -r arg; do + cmdline=$(remove_cmdline_param "$cmdline" "$arg") + done <<< "$(echo "$2" | xargs -n 1 echo)" + + # Always remove "root=X", as we now explicitly generate all kinds + # of dump target mount information including root fs. + # + # We do this before KDUMP_COMMANDLINE_APPEND, if one really cares + # about it(e.g. for debug purpose), then can pass "root=X" using + # KDUMP_COMMANDLINE_APPEND. + cmdline=$(remove_cmdline_param "$cmdline" root) + + # With the help of "--hostonly-cmdline", we can avoid some interitage. + cmdline=$(remove_cmdline_param "$cmdline" rd.lvm.lv rd.luks.uuid rd.dm.uuid rd.md.uuid fcoe) + + # 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 [[ -n ${id} ]]; then + cmdline=$(append_cmdline "$cmdline" disable_cpu_apicid "$id") + fi + + # If any watchdog is used, set it's pretimeout to 0. pretimeout let + # watchdog panic the kernel first, and reset the system after the + # panic. If the system is already in kdump, panic is not helpful + # and only increase the chance of watchdog failure. + for i in $(get_watchdog_drvs); do + cmdline+=" $i.pretimeout=0" + + if [[ $i == hpwdt ]]; then + # hpwdt have a special parameter kdumptimeout, is's only suppose + # to be set to non-zero in first kernel. In kdump, non-zero + # value could prevent the watchdog from resetting the system. + cmdline+=" $i.kdumptimeout=0" + fi + done + + # Remove trace_buf_size, trace_event + cmdline=$(remove_cmdline_param "$cmdline" trace_buf_size trace_event) + cmdline="${cmdline} trace_buf_size=1" + + echo "$cmdline" } #get system memory size in the unit of GB get_system_size() { - result=$(cat /proc/iomem | grep "System RAM" | awk -F ":" '{ print $1 }' | tr [:lower:] [:upper:] | paste -sd+) - result="+$result" - # replace '-' with '+0x' and '+' with '-0x' - sum=$( echo $result | sed -e 's/-/K0x/g' | sed -e 's/+/-0x/g' | sed -e 's/K/+/g' ) - size=$(printf "%d\n" $(($sum))) - let size=$size/1024/1024/1024 - - echo $size + result=$(grep "System RAM" /proc/iomem | awk -F ":" '{ print $1 }' | tr "[:lower:]" "[:upper:]" | paste -sd+) + result="+$result" + # replace '-' with '+0x' and '+' with '-0x' + sum=$(echo "$result" | sed -e 's/-/K0x/g' -e 's/+/-0x/g' -e 's/K/+/g') + size=$(printf "%d\n" $((sum))) + size=$((size / 1024 / 1024 / 1024)) + + echo "$size" } get_recommend_size() { - local mem_size=$1 - local _ck_cmdline=$2 - local OLDIFS="$IFS" - - last_sz="" - last_unit="" - - start=${_ck_cmdline: :1} - if [ $mem_size -lt $start ]; then - echo "0M" - return - fi - IFS=',' - for i in $_ck_cmdline; do - end=$(echo $i | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $1 }') - recommend=$(echo $i | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $2 }') - size=${end: : -1} - unit=${end: -1} - if [ $unit == 'T' ]; then - let size=$size*1024 - fi - if [ $mem_size -lt $size ]; then - echo $recommend - IFS="$OLDIFS" - return - fi - done - IFS="$OLDIFS" + local mem_size=$1 + local _ck_cmdline=$2 + local OLDIFS="$IFS" + + start=${_ck_cmdline::1} + if [[ $mem_size -lt $start ]]; then + echo "0M" + return + fi + IFS=',' + for i in $_ck_cmdline; do + end=$(echo "$i" | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $1 }') + recommend=$(echo "$i" | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $2 }') + size=${end::-1} + unit=${end: -1} + if [[ $unit == 'T' ]]; then + size=$((size * 1024)) + fi + if [[ $mem_size -lt $size ]]; then + echo "$recommend" + IFS="$OLDIFS" + return + fi + done + IFS="$OLDIFS" } # return recommended size based on current system RAM size -# $1: kernel version, if not set, will defaults to `uname -r` +# $1: kernel version, if not set, will defaults to $(uname -r) kdump_get_arch_recommend_size() { - local kernel=$1 arch - - if ! [ -r "/proc/iomem" ] ; then - echo "Error, can not access /proc/iomem." - return 1 - fi - - [ -z "$kernel" ] && kernel=$(uname -r) - ck_cmdline=$(cat "/usr/lib/modules/$kernel/crashkernel.default" 2>/dev/null) - - if [ -n "$ck_cmdline" ]; then - ck_cmdline=${ck_cmdline#crashkernel=} - else - arch=$(lscpu | grep Architecture | awk -F ":" '{ print $2 }' | tr '[:lower:]' '[:upper:]') - if [ "$arch" = "X86_64" ] || [ "$arch" = "S390X" ]; then - ck_cmdline="1G-4G:160M,4G-64G:192M,64G-1T:256M,1T-:512M" - elif [ "$arch" = "AARCH64" ]; then - ck_cmdline="2G-:448M" - elif [ "$arch" = "PPC64LE" ]; then - if is_fadump_capable; then - ck_cmdline="4G-16G:768M,16G-64G:1G,64G-128G:2G,128G-1T:4G,1T-2T:6G,2T-4T:12G,4T-8T:20G,8T-16T:36G,16T-32T:64G,32T-64T:128G,64T-:180G" - else - ck_cmdline="2G-4G:384M,4G-16G:512M,16G-64G:1G,64G-128G:2G,128G-:4G" - fi - fi - fi - - ck_cmdline=$(echo $ck_cmdline | sed -e 's/-:/-102400T:/g') - sys_mem=$(get_system_size) - - get_recommend_size "$sys_mem" "$ck_cmdline" + local kernel=$1 arch + + if ! [[ -r "/proc/iomem" ]]; then + echo "Error, can not access /proc/iomem." + return 1 + fi + + [[ -z $kernel ]] && kernel=$(uname -r) + ck_cmdline=$(cat "/usr/lib/modules/$kernel/crashkernel.default" 2> /dev/null) + + if [[ -n $ck_cmdline ]]; then + ck_cmdline=${ck_cmdline#crashkernel=} + else + arch=$(lscpu | grep Architecture | awk -F ":" '{ print $2 }' | tr '[:lower:]' '[:upper:]') + if [[ $arch == "X86_64" ]] || [[ $arch == "S390X" ]]; then + ck_cmdline="1G-4G:160M,4G-64G:192M,64G-1T:256M,1T-:512M" + elif [[ $arch == "AARCH64" ]]; then + ck_cmdline="2G-:448M" + elif [[ $arch == "PPC64LE" ]]; then + if is_fadump_capable; then + ck_cmdline="4G-16G:768M,16G-64G:1G,64G-128G:2G,128G-1T:4G,1T-2T:6G,2T-4T:12G,4T-8T:20G,8T-16T:36G,16T-32T:64G,32T-64T:128G,64T-:180G" + else + ck_cmdline="2G-4G:384M,4G-16G:512M,16G-64G:1G,64G-128G:2G,128G-:4G" + fi + fi + fi + + ck_cmdline=${ck_cmdline//-:/-102400T:} + sys_mem=$(get_system_size) + + get_recommend_size "$sys_mem" "$ck_cmdline" } # Print all underlying crypt devices of a block device @@ -984,16 +859,18 @@ kdump_get_arch_recommend_size() # $1: the block device to be checked in maj:min format get_luks_crypt_dev() { - [[ -b /dev/block/$1 ]] || return 1 + local _type - local _type=$(eval "$(blkid -u filesystem,crypto -o export -- /dev/block/$1); echo \$TYPE") - [[ $_type == "crypto_LUKS" ]] && echo $1 + [[ -b /dev/block/$1 ]] || return 1 - for _x in /sys/dev/block/$1/slaves/*; do - [[ -f $_x/dev ]] || continue - [[ $_x/subsystem -ef /sys/class/block ]] || continue - get_luks_crypt_dev "$(< "$_x/dev")" - done + _type=$(eval "$(blkid -u filesystem,crypto -o export -- "/dev/block/$1"); echo \$TYPE") + [[ $_type == "crypto_LUKS" ]] && echo "$1" + + for _x in "/sys/dev/block/$1/slaves/"*; do + [[ -f $_x/dev ]] || continue + [[ $_x/subsystem -ef /sys/class/block ]] || continue + get_luks_crypt_dev "$(< "$_x/dev")" + done } # kdump_get_maj_min @@ -1001,89 +878,90 @@ get_luks_crypt_dev() # Example: # $ get_maj_min /dev/sda2 # 8:2 -kdump_get_maj_min() { - local _majmin - _majmin="$(stat -L -c '%t:%T' "$1" 2> /dev/null)" - printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))" +kdump_get_maj_min() +{ + local _majmin + _majmin="$(stat -L -c '%t:%T' "$1" 2> /dev/null)" + printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))" } get_all_kdump_crypt_dev() { - local _dev _crypt + local _dev - for _dev in $(get_block_dump_target); do - _crypt=$(get_luks_crypt_dev $(kdump_get_maj_min "$_dev")) - [[ -n "$_crypt" ]] && echo $_crypt - done + for _dev in $(get_block_dump_target); do + get_luks_crypt_dev "$(kdump_get_maj_min "$_dev")" + done } check_vmlinux() { - # Use readelf to check if it's a valid ELF - readelf -h $1 &>/dev/null || return 1 + # Use readelf to check if it's a valid ELF + readelf -h "$1" &> /dev/null || return 1 } get_vmlinux_size() { - local size=0 + local size=0 _msize - while read _type _offset _virtaddr _physaddr _fsize _msize _flg _aln; do - size=$(( $size + $_msize )) - done <<< $(readelf -l -W $1 | grep "^ LOAD" 2>/dev/stderr) + while read -r _msize; do + size=$((size + _msize)) + done <<< "$(readelf -l -W "$1" | awk '/^ LOAD/{print $6}' 2> /dev/stderr)" - echo $size + echo $size } try_decompress() { - # The obscure use of the "tr" filter is to work around older versions of - # "grep" that report the byte offset of the line instead of the pattern. - - # Try to find the header ($1) and decompress from here - for pos in `tr "$1\n$2" "\n$2=" < "$4" | grep -abo "^$2"` - do - if ! type -P $3 > /dev/null; then - ddebug "Signiature detected but '$3' is missing, skip this decompressor" - break - fi - - pos=${pos%%:*} - tail -c+$pos "$img" | $3 > $5 2> /dev/null - if check_vmlinux $5; then - ddebug "Kernel is extracted with '$3'" - return 0 - fi - done - - return 1 + # The obscure use of the "tr" filter is to work around older versions of + # "grep" that report the byte offset of the line instead of the pattern. + + # Try to find the header ($1) and decompress from here + for pos in $(tr "$1\n$2" "\n$2=" < "$4" | grep -abo "^$2"); do + if ! type -P "$3" > /dev/null; then + ddebug "Signiature detected but '$3' is missing, skip this decompressor" + break + fi + + pos=${pos%%:*} + tail "-c+$pos" "$img" | $3 > "$5" 2> /dev/null + if check_vmlinux "$5"; then + ddebug "Kernel is extracted with '$3'" + return 0 + fi + done + + return 1 } # Borrowed from linux/scripts/extract-vmlinux get_kernel_size() { - # Prepare temp files: - local img=$1 tmp=$(mktemp /tmp/vmlinux-XXX) - trap "rm -f $tmp" 0 - - # Try to check if it's a vmlinux already - check_vmlinux $img && get_vmlinux_size $img && return 0 - - # That didn't work, so retry after decompression. - try_decompress '\037\213\010' xy gunzip $img $tmp || \ - try_decompress '\3757zXZ\000' abcde unxz $img $tmp || \ - try_decompress 'BZh' xy bunzip2 $img $tmp || \ - try_decompress '\135\0\0\0' xxx unlzma $img $tmp || \ - try_decompress '\211\114\132' xy 'lzop -d' $img $tmp || \ - try_decompress '\002!L\030' xxx 'lz4 -d' $img $tmp || \ - try_decompress '(\265/\375' xxx unzstd $img $tmp - - # Finally check for uncompressed images or objects: - [[ $? -eq 0 ]] && get_vmlinux_size $tmp && return 0 - - # Fallback to use iomem - local _size=0 - for _seg in $(cat /proc/iomem | grep -E "Kernel (code|rodata|data|bss)" | cut -d ":" -f 1); do - _size=$(( $_size + 0x${_seg#*-} - 0x${_seg%-*} )) - done - echo $_size + # Prepare temp files: + local tmp img=$1 + + tmp=$(mktemp /tmp/vmlinux-XXX) + trap 'rm -f "$tmp"' 0 + + # Try to check if it's a vmlinux already + check_vmlinux "$img" && get_vmlinux_size "$img" && return 0 + + # That didn't work, so retry after decompression. + try_decompress '\037\213\010' xy gunzip "$img" "$tmp" || + try_decompress '\3757zXZ\000' abcde unxz "$img" "$tmp" || + try_decompress 'BZh' xy bunzip2 "$img" "$tmp" || + try_decompress '\135\0\0\0' xxx unlzma "$img" "$tmp" || + try_decompress '\211\114\132' xy 'lzop -d' "$img" "$tmp" || + try_decompress '\002!L\030' xxx 'lz4 -d' "$img" "$tmp" || + try_decompress '(\265/\375' xxx unzstd "$img" "$tmp" + + # Finally check for uncompressed images or objects: + [[ $? -eq 0 ]] && get_vmlinux_size "$tmp" && return 0 + + # Fallback to use iomem + local _size=0 _seg + while read -r _seg; do + _size=$((_size + 0x${_seg#*-} - 0x${_seg%-*})) + done <<< "$(grep -E "Kernel (code|rodata|data|bss)" /proc/iomem | cut -d ":" -f 1)" + echo $_size } diff --git a/SOURCES/kdump-logger.sh b/SOURCES/kdump-logger.sh index 370e5e8..3fd433d 100755 --- a/SOURCES/kdump-logger.sh +++ b/SOURCES/kdump-logger.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # # This comes from the dracut-logger.sh # @@ -34,6 +34,8 @@ # First of all you have to start with dlog_init() function which initializes # required variables. Don't call any other logging function before that one! # +# The code in this file might be run in an environment without bash. +# Any code added must be POSIX compliant. # Define vairables for the log levels in this module. kdump_stdloglvl="" @@ -53,11 +55,12 @@ fi # get_kdump_loglvl() { - (type -p getarg) && kdump_sysloglvl=$(getarg rd.kdumploglvl) + [ -f /lib/dracut-lib.sh ] && kdump_sysloglvl=$(getarg rd.kdumploglvl) [ -z "$kdump_sysloglvl" ] && return 1; - (type -p isdigit) && isdigit $kdump_sysloglvl - [ $? -ne 0 ] && return 1; + if [ -f /lib/dracut-lib.sh ] && ! isdigit "$kdump_sysloglvl"; then + return 1 + fi return 0 } @@ -83,11 +86,10 @@ check_loglvl() # @retval 0 on success. # dlog_init() { - local ret=0; local errmsg + ret=0 if [ -s /proc/vmcore ];then - get_kdump_loglvl - if [ $? -ne 0 ];then + if ! get_kdump_loglvl; then logger -t "kdump[$$]" -p warn -- "Kdump is using the default log level(3)." kdump_sysloglvl=3 fi @@ -104,8 +106,7 @@ dlog_init() { [ -z "$kdump_kmsgloglvl" ] && kdump_kmsgloglvl=0 for loglvl in "$kdump_stdloglvl" "$kdump_kmsgloglvl" "$kdump_sysloglvl"; do - check_loglvl "$loglvl" - if [ $? -ne 0 ]; then + if ! check_loglvl "$loglvl"; then echo "Illegal log level: $kdump_stdloglvl $kdump_kmsgloglvl $kdump_sysloglvl" return 1 fi @@ -114,21 +115,21 @@ dlog_init() { # Skip initialization if it's already done. [ -n "$kdump_maxloglvl" ] && return 0 - if [[ $UID -ne 0 ]]; then + if [ "$UID" -ne 0 ]; then kdump_kmsgloglvl=0 kdump_sysloglvl=0 fi - if [[ $kdump_sysloglvl -gt 0 ]]; then - if [[ -d /run/systemd/journal ]] \ - && type -P systemd-cat &>/dev/null \ - && systemctl --quiet is-active systemd-journald.socket &>/dev/null; then + if [ "$kdump_sysloglvl" -gt 0 ]; then + if [ -d /run/systemd/journal ] \ + && systemd-cat --version 1>/dev/null 2>&1 \ + && systemctl --quiet is-active systemd-journald.socket 1>/dev/null 2>&1; then readonly _systemdcatfile="/var/tmp/systemd-cat" - mkfifo "$_systemdcatfile" &>/dev/null + mkfifo "$_systemdcatfile" 1>/dev/null 2>&1 readonly _dlogfd=15 systemd-cat -t 'kdump' --level-prefix=true <"$_systemdcatfile" & exec 15>"$_systemdcatfile" - elif ! [ -S /dev/log -a -w /dev/log ] || ! command -v logger >/dev/null; then + elif ! [ -S /dev/log ] && [ -w /dev/log ] || ! command -v logger >/dev/null; then # We cannot log to syslog, so turn this facility off. kdump_kmsgloglvl=$kdump_sysloglvl kdump_sysloglvl=0 @@ -137,31 +138,31 @@ dlog_init() { fi fi - local lvl; local maxloglvl_l=0 - for lvl in $kdump_stdloglvl $kdump_sysloglvl $kdump_kmsgloglvl; do - [[ $lvl -gt $maxloglvl_l ]] && maxloglvl_l=$lvl + kdump_maxloglvl=0 + for _dlog_lvl in $kdump_stdloglvl $kdump_sysloglvl $kdump_kmsgloglvl; do + [ $_dlog_lvl -gt $kdump_maxloglvl ] && kdump_maxloglvl=$_dlog_lvl done - readonly kdump_maxloglvl=$maxloglvl_l + readonly kdump_maxloglvl export kdump_maxloglvl - if [[ $kdump_stdloglvl -lt 4 ]] && [[ $kdump_kmsgloglvl -lt 4 ]] && [[ $kdump_sysloglvl -lt 4 ]]; then + if [ $kdump_stdloglvl -lt 4 ] && [ $kdump_kmsgloglvl -lt 4 ] && [ $kdump_sysloglvl -lt 4 ]; then unset ddebug ddebug() { :; }; fi - if [[ $kdump_stdloglvl -lt 3 ]] && [[ $kdump_kmsgloglvl -lt 3 ]] && [[ $kdump_sysloglvl -lt 3 ]]; then + if [ $kdump_stdloglvl -lt 3 ] && [ $kdump_kmsgloglvl -lt 3 ] && [ $kdump_sysloglvl -lt 3 ]; then unset dinfo dinfo() { :; }; fi - if [[ $kdump_stdloglvl -lt 2 ]] && [[ $kdump_kmsgloglvl -lt 2 ]] && [[ $kdump_sysloglvl -lt 2 ]]; then + if [ $kdump_stdloglvl -lt 2 ] && [ $kdump_kmsgloglvl -lt 2 ] && [ $kdump_sysloglvl -lt 2 ]; then unset dwarn dwarn() { :; }; unset dwarning dwarning() { :; }; fi - if [[ $kdump_stdloglvl -lt 1 ]] && [[ $kdump_kmsgloglvl -lt 1 ]] && [[ $kdump_sysloglvl -lt 1 ]]; then + if [ $kdump_stdloglvl -lt 1 ] && [ $kdump_kmsgloglvl -lt 1 ] && [ $kdump_sysloglvl -lt 1 ]; then unset derror derror() { :; }; fi @@ -173,7 +174,7 @@ dlog_init() { ## @brief Converts numeric level to logger priority defined by POSIX.2. # -# @param lvl Numeric logging level in range from 1 to 4. +# @param $1: Numeric logging level in range from 1 to 4. # @retval 1 if @a lvl is out of range. # @retval 0 if @a lvl is correct. # @result Echoes logger priority. @@ -189,7 +190,7 @@ _lvl2syspri() { ## @brief Converts logger numeric level to syslog log level # -# @param lvl Numeric logging level in range from 1 to 4. +# @param $1: Numeric logging level in range from 1 to 4. # @retval 1 if @a lvl is out of range. # @retval 0 if @a lvl is correct. # @result Echoes kernel console numeric log level @@ -209,27 +210,25 @@ _lvl2syspri() { # # @see /usr/include/sys/syslog.h _dlvl2syslvl() { - local lvl - case "$1" in - 1) lvl=3;; - 2) lvl=4;; - 3) lvl=6;; - 4) lvl=7;; + 1) set -- 3;; + 2) set -- 4;; + 3) set -- 6;; + 4) set -- 7;; *) return 1;; esac # The number is constructed by multiplying the facility by 8 and then # adding the level. # About The Syslog Protocol, please refer to the RFC5424 for more details. - echo $((24+$lvl)) + echo $((24 + $1)) } ## @brief Prints to stderr, to syslog and/or /dev/kmsg given message with # given level (priority). # -# @param lvl Numeric logging level. -# @param msg Message. +# @param $1: Numeric logging level. +# @param $2: Message. # @retval 0 It's always returned, even if logging failed. # # @note This function is not supposed to be called manually. Please use @@ -251,27 +250,24 @@ _dlvl2syslvl() { # - @c INFO to @c info # - @c DEBUG to @c debug _do_dlog() { - local lvl="$1"; shift - local msg="$*" + [ "$1" -le $kdump_stdloglvl ] && printf -- 'kdump: %s\n' "$2" >&2 - [[ $lvl -le $kdump_stdloglvl ]] && printf -- 'kdump: %s\n' "$msg" >&2 - - if [[ $lvl -le $kdump_sysloglvl ]]; then - if [[ "$_dlogfd" ]]; then - printf -- "<%s>%s\n" "$(($(_dlvl2syslvl $lvl) & 7))" "$msg" >&$_dlogfd + if [ "$1" -le $kdump_sysloglvl ]; then + if [ "$_dlogfd" ]; then + printf -- "<%s>%s\n" "$(($(_dlvl2syslvl "$1") & 7))" "$2" 1>&$_dlogfd else - logger -t "kdump[$$]" -p $(_lvl2syspri $lvl) -- "$msg" + logger -t "kdump[$$]" -p "$(_lvl2syspri "$1")" -- "$2" fi fi - [[ $lvl -le $kdump_kmsgloglvl ]] && \ - echo "<$(_dlvl2syslvl $lvl)>kdump[$$] $msg" >/dev/kmsg + [ "$1" -le $kdump_kmsgloglvl ] && \ + echo "<$(_dlvl2syslvl "$1")>kdump[$$] $2" >/dev/kmsg } ## @brief Internal helper function for _do_dlog() # -# @param lvl Numeric logging level. -# @param msg Message. +# @param $1: Numeric logging level. +# @param $2 [...]: Message. # @retval 0 It's always returned, even if logging failed. # # @note This function is not supposed to be called manually. Please use @@ -286,12 +282,13 @@ _do_dlog() { # echo "This is a warning" | dwarn dlog() { [ -z "$kdump_maxloglvl" ] && return 0 - [[ $1 -le $kdump_maxloglvl ]] || return 0 + [ "$1" -le "$kdump_maxloglvl" ] || return 0 - if [[ $# -gt 1 ]]; then - _do_dlog "$@" + if [ $# -gt 1 ]; then + _dlog_lvl=$1; shift + _do_dlog "$_dlog_lvl" "$*" else - while read line || [ -n "$line" ]; do + while read -r line || [ -n "$line" ]; do _do_dlog "$1" "$line" done fi @@ -304,7 +301,9 @@ dlog() { ddebug() { set +x dlog 4 "$@" - [ -n "$debug" ] && set -x || : + if [ -n "$debug" ]; then + set -x + fi } ## @brief Logs message at INFO level (3) @@ -314,7 +313,9 @@ ddebug() { dinfo() { set +x dlog 3 "$@" - [ -n "$debug" ] && set -x || : + if [ -n "$debug" ]; then + set -x + fi } ## @brief Logs message at WARN level (2) @@ -324,7 +325,9 @@ dinfo() { dwarn() { set +x dlog 2 "$@" - [ -n "$debug" ] && set -x || : + if [ -n "$debug" ]; then + set -x + fi } ## @brief It's an alias to dwarn() function. @@ -334,7 +337,9 @@ dwarn() { dwarning() { set +x dwarn "$@" - [ -n "$debug" ] && set -x || : + if [ -n "$debug" ]; then + set -x + fi } ## @brief Logs message at ERROR level (1) @@ -344,5 +349,7 @@ dwarning() { derror() { set +x dlog 1 "$@" - [ -n "$debug" ] && set -x || : + if [ -n "$debug" ]; then + set -x + fi } diff --git a/SOURCES/kdumpctl b/SOURCES/kdumpctl index e132d04..7a529e6 100755 --- a/SOURCES/kdumpctl +++ b/SOURCES/kdumpctl @@ -5,7 +5,6 @@ KDUMP_KERNELVER="" KDUMP_KERNEL="" KDUMP_COMMANDLINE="" KEXEC_ARGS="" -KDUMP_CONFIG_FILE="/etc/kdump.conf" KDUMP_LOG_PATH="/var/log" MKDUMPRD="/sbin/mkdumprd -f" MKFADUMPRD="/sbin/mkfadumprd" @@ -28,7 +27,7 @@ standard_kexec_args="-d -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 +if [[ -f /etc/sysconfig/kdump ]]; then . /etc/sysconfig/kdump fi @@ -38,8 +37,7 @@ fi . /lib/kdump/kdump-logger.sh #initiate the kdump logger -dlog_init -if [ $? -ne 0 ]; then +if ! dlog_init; then echo "failed to initiate the kdump logger." exit 1 fi @@ -48,8 +46,7 @@ single_instance_lock() { local rc timeout=5 - exec 9>/var/lock/kdump - if [ $? -ne 0 ]; then + if ! exec 9> /var/lock/kdump; then derror "Create file lock failed" exit 1 fi @@ -57,7 +54,7 @@ single_instance_lock() flock -n 9 rc=$? - while [ $rc -ne 0 ]; do + while [[ $rc -ne 0 ]]; do dinfo "Another app is currently holding the kdump lock; waiting for it to exit..." flock -w $timeout 9 rc=$? @@ -77,13 +74,12 @@ determine_dump_mode() save_core() { - coredir="/var/crash/`date +"%Y-%m-%d-%H:%M"`" + coredir="/var/crash/$(date +"%Y-%m-%d-%H:%M")" - mkdir -p $coredir + mkdir -p "$coredir" ddebug "cp --sparse=always /proc/vmcore $coredir/vmcore-incomplete" - cp --sparse=always /proc/vmcore $coredir/vmcore-incomplete - if [ $? == 0 ]; then - mv $coredir/vmcore-incomplete $coredir/vmcore + if cp --sparse=always /proc/vmcore "$coredir/vmcore-incomplete"; then + mv "$coredir/vmcore-incomplete" "$coredir/vmcore" dinfo "saved a vmcore to $coredir" else derror "failed to save a vmcore to $coredir" @@ -92,12 +88,11 @@ save_core() # 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 + if [[ -x /usr/bin/dumpoops ]]; then ddebug "makedumpfile --dump-dmesg $coredir/vmcore $coredir/dmesg" - makedumpfile --dump-dmesg $coredir/vmcore $coredir/dmesg >/dev/null 2>&1 + makedumpfile --dump-dmesg "$coredir/vmcore" "$coredir/dmesg" > /dev/null 2>&1 ddebug "dumpoops -d $coredir/dmesg" - dumpoops -d $coredir/dmesg >/dev/null 2>&1 - if [ $? == 0 ]; then + if dumpoops -d "$coredir/dmesg" > /dev/null 2>&1; then dinfo "kernel oops has been collected by abrt tool" fi fi @@ -122,8 +117,7 @@ check_earlykdump_is_enabled() rebuild_kdump_initrd() { ddebug "rebuild kdump initrd: $MKDUMPRD $TARGET_INITRD $KDUMP_KERNELVER" - $MKDUMPRD $TARGET_INITRD $KDUMP_KERNELVER - if [ $? != 0 ]; then + if ! $MKDUMPRD "$TARGET_INITRD" "$KDUMP_KERNELVER"; then derror "mkdumprd: failed to make kdump initrd" return 1 fi @@ -137,12 +131,12 @@ rebuild_kdump_initrd() rebuild_initrd() { - if [[ ! -w $(dirname $TARGET_INITRD) ]];then - derror "$(dirname $TARGET_INITRD) does not have write permission. Cannot rebuild $TARGET_INITRD" + if [[ ! -w $(dirname "$TARGET_INITRD") ]]; then + derror "$(dirname "$TARGET_INITRD") does not have write permission. Cannot rebuild $TARGET_INITRD" return 1 fi - if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then rebuild_fadump_initrd else rebuild_kdump_initrd @@ -155,7 +149,7 @@ rebuild_initrd() check_exist() { for file in $1; do - if [ ! -e "$file" ]; then + if [[ ! -e $file ]]; then derror "Error: $file not found." return 1 fi @@ -166,7 +160,7 @@ check_exist() check_executable() { for file in $1; do - if [ ! -x "$file" ]; then + if [[ ! -x $file ]]; then derror "Error: $file is not executable." return 1 fi @@ -177,18 +171,17 @@ backup_default_initrd() { ddebug "backup default initrd: $DEFAULT_INITRD" - if [ ! -f "$DEFAULT_INITRD" ]; then + if [[ ! -f $DEFAULT_INITRD ]]; then return fi - if [ ! -e $DEFAULT_INITRD_BAK ]; then + if [[ ! -e $DEFAULT_INITRD_BAK ]]; then dinfo "Backing up $DEFAULT_INITRD before rebuild." # save checksum to verify before restoring - sha1sum $DEFAULT_INITRD > $INITRD_CHECKSUM_LOCATION - cp $DEFAULT_INITRD $DEFAULT_INITRD_BAK - if [ $? -ne 0 ]; then + sha1sum "$DEFAULT_INITRD" > "$INITRD_CHECKSUM_LOCATION" + if ! cp "$DEFAULT_INITRD" "$DEFAULT_INITRD_BAK"; then dwarn "WARNING: failed to backup $DEFAULT_INITRD." - rm -f $DEFAULT_INITRD_BAK + rm -f "$DEFAULT_INITRD_BAK" fi fi } @@ -197,22 +190,21 @@ restore_default_initrd() { ddebug "restore default initrd: $DEFAULT_INITRD" - if [ ! -f "$DEFAULT_INITRD" ]; then + if [[ ! -f $DEFAULT_INITRD ]]; then return fi # If a backup initrd exists, we must be switching back from # fadump to kdump. Restore the original default initrd. - if [ -f $DEFAULT_INITRD_BAK ] && [ -f $INITRD_CHECKSUM_LOCATION ]; then + 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 + backup_checksum=$(sha1sum "$DEFAULT_INITRD_BAK" | awk '{ print $1 }') + default_checksum=$(awk '{ print $1 }' "$INITRD_CHECKSUM_LOCATION") + if [[ $default_checksum != "$backup_checksum" ]]; then dwarn "WARNING: checksum mismatch! Can't restore original initrd.." else rm -f $INITRD_CHECKSUM_LOCATION - mv $DEFAULT_INITRD_BAK $DEFAULT_INITRD - if [[ $? -eq 0 ]]; then + if mv "$DEFAULT_INITRD_BAK" "$DEFAULT_INITRD"; then derror "Restoring original initrd as fadump mode is disabled." sync fi @@ -227,25 +219,25 @@ check_config() case "$config_opt" in dracut_args) if [[ $config_val == *--mount* ]]; then - if [ $(echo $config_val | grep -o "\-\-mount" | wc -l) -ne 1 ]; then - derror "Multiple mount targets specified in one \"dracut_args\"." + if [[ $(echo "$config_val" | grep -o "\-\-mount" | wc -l) -ne 1 ]]; then + derror 'Multiple mount targets specified in one "dracut_args".' return 1 fi config_opt=_target fi ;; raw) - if [ -d "/proc/device-tree/ibm,opal/dump" ]; then + if [[ -d "/proc/device-tree/ibm,opal/dump" ]]; then dwarn "WARNING: Won't capture opalcore when 'raw' dump target is used." fi config_opt=_target ;; - ext[234]|minix|btrfs|xfs|nfs|ssh) + ext[234] | minix | btrfs | xfs | nfs | ssh) config_opt=_target ;; - sshkey|path|core_collector|kdump_post|kdump_pre|extra_bins|extra_modules|failure_action|default|final_action|force_rebuild|force_no_rebuild|fence_kdump_args|fence_kdump_nodes) - ;; - net|options|link_delay|disk_timeout|debug_mem_level|blacklist) + sshkey | path | core_collector | kdump_post | kdump_pre | extra_bins | extra_modules | failure_action | default | final_action | force_rebuild | force_no_rebuild | fence_kdump_args | fence_kdump_nodes) ;; + + net | options | link_delay | disk_timeout | debug_mem_level | blacklist) derror "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives." return 1 ;; @@ -258,13 +250,13 @@ check_config() ;; esac - if [[ -z "$config_val" ]]; then + if [[ -z $config_val ]]; then derror "Invalid kdump config value for option '$config_opt'" return 1 fi - if [ -n "${_opt_rec[$config_opt]}" ]; then - if [ $config_opt == _target ]; then + if [[ -n ${_opt_rec[$config_opt]} ]]; then + if [[ $config_opt == _target ]]; then derror "More than one dump targets specified" else derror "Duplicated kdump config value of option $config_opt" @@ -272,7 +264,7 @@ check_config() return 1 fi _opt_rec[$config_opt]="$config_val" - done <<< "$(read_strip_comments $KDUMP_CONFIG_FILE)" + done <<< "$(kdump_read_conf)" check_failure_action_config || return 1 check_final_action_config || return 1 @@ -291,33 +283,31 @@ get_pcs_cluster_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` + 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 + if [[ -n $time_stamp ]] && [[ $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 + 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 + echo "$modified_files" } setup_initrd() { - prepare_kdump_bootinfo - if [ $? -ne 0 ]; then + if ! prepare_kdump_bootinfo; then derror "failed to prepare for kdump bootinfo." return 1 fi - DEFAULT_INITRD_BAK="$KDUMP_BOOTDIR/.$(basename $DEFAULT_INITRD).default" - if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + DEFAULT_INITRD_BAK="$KDUMP_BOOTDIR/.$(basename "$DEFAULT_INITRD").default" + if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then TARGET_INITRD="$DEFAULT_INITRD" # backup initrd for reference before replacing it @@ -340,49 +330,48 @@ check_files_modified() #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` + EXTRA_BINS=$(kdump_get_conf_val kdump_post) + CHECK_FILES=$(kdump_get_conf_val kdump_pre) HOOKS="/etc/kdump/post.d/ /etc/kdump/pre.d/" - if [ -d /etc/kdump/post.d ]; then + if [[ -d /etc/kdump/post.d ]]; then for file in /etc/kdump/post.d/*; do - if [ -x "$file" ]; then + if [[ -x $file ]]; then POST_FILES="$POST_FILES $file" fi done fi - if [ -d /etc/kdump/pre.d ]; then + if [[ -d /etc/kdump/pre.d ]]; then for file in /etc/kdump/pre.d/*; do - if [ -x "$file" ]; then + if [[ -x $file ]]; then PRE_FILES="$PRE_FILES $file" fi done fi HOOKS="$HOOKS $POST_FILES $PRE_FILES" - CORE_COLLECTOR=`grep ^core_collector $KDUMP_CONFIG_FILE | cut -d\ -f2` - CORE_COLLECTOR=`type -P $CORE_COLLECTOR` + CORE_COLLECTOR=$(kdump_get_conf_val core_collector | awk '{print $1}') + CORE_COLLECTOR=$(type -P "$CORE_COLLECTOR") # POST_FILES and PRE_FILES are already checked against executable, need not to check again. EXTRA_BINS="$EXTRA_BINS $CHECK_FILES" - CHECK_FILES=`grep ^extra_bins $KDUMP_CONFIG_FILE | cut -d\ -f2-` + CHECK_FILES=$(kdump_get_conf_val extra_bins) 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_KERNELVER/modules.dep ]; then + EXTRA_MODULES="$(kdump_get_conf_val extra_modules)" + if [[ -n $EXTRA_MODULES ]]; then + if [[ -e /lib/modules/$KDUMP_KERNELVER/modules.dep ]]; then files="$files /lib/modules/$KDUMP_KERNELVER/modules.dep" fi for _module in $EXTRA_MODULES; do - _module_file="$(modinfo --set-version "$KDUMP_KERNELVER" --filename "$_module" 2>/dev/null)" - if [[ $? -eq 0 ]]; then + if _module_file="$(modinfo --set-version "$KDUMP_KERNELVER" --filename "$_module" 2> /dev/null)"; then files="$files $_module_file" - for _dep_modules in $(modinfo -F depends $_module | tr ',' ' '); do - files="$files $(modinfo --set-version "$KDUMP_KERNELVER" --filename $_dep_modules 2>/dev/null)" + for _dep_modules in $(modinfo -F depends "$_module" | tr ',' ' '); do + files="$files $(modinfo --set-version "$KDUMP_KERNELVER" --filename "$_dep_modules" 2> /dev/null)" done else # If it's not a module nor builtin, give an error - if ! ( modprobe --set-version "$KDUMP_KERNELVER" --dry-run "$_module" &>/dev/null ); then + if ! (modprobe --set-version "$KDUMP_KERNELVER" --dry-run "$_module" &> /dev/null); then dwarn "Module $_module not found" fi fi @@ -391,19 +380,18 @@ check_files_modified() # HOOKS is mandatory and need to check the modification time files="$files $HOOKS" - check_exist "$files" && check_executable "$EXTRA_BINS" - [ $? -ne 0 ] && return 2 + check_exist "$files" && check_executable "$EXTRA_BINS" || return 2 for file in $files; do - if [ -e "$file" ]; then - time_stamp=`stat -c "%Y" $file` - if [ "$time_stamp" -gt "$image_time" ]; then + 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 + 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 @@ -412,7 +400,7 @@ check_files_modified() fi done - if [ -n "$modified_files" ]; then + if [[ -n $modified_files ]]; then dinfo "Detected change(s) in the following file(s): $modified_files" return 1 fi @@ -426,8 +414,9 @@ check_drivers_modified() # If it's dump target is on block device, detect the block driver _target=$(get_block_dump_target) - if [[ -n "$_target" ]]; then - _record_block_drivers() { + if [[ -n $_target ]]; then + _record_block_drivers() + { local _drivers _drivers=$(udevadm info -a "/dev/block/$1" | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p') for _driver in $_drivers; do @@ -443,7 +432,7 @@ check_drivers_modified() # Include watchdog drivers if watchdog module is not omitted is_dracut_mod_omitted watchdog || _new_drivers+=" $(get_watchdog_drvs)" - [ -z "$_new_drivers" ] && return 0 + [[ -z $_new_drivers ]] && return 0 if is_fadump_capable; then _old_drivers="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/fadump-kernel-modules.txt | tr '\n' ' ')" @@ -455,9 +444,9 @@ check_drivers_modified() ddebug "Modules included in old initramfs: '$_old_drivers'" for _driver in $_new_drivers; do # Skip deprecated/invalid driver name or built-in module - _module_name=$(modinfo --set-version "$KDUMP_KERNELVER" -F name $_driver 2>/dev/null) - _module_filename=$(modinfo --set-version "$KDUMP_KERNELVER" -n $_driver 2>/dev/null) - if [ $? -ne 0 ] || [ -z "$_module_name" ] || [[ "$_module_filename" = *"(builtin)"* ]]; then + _module_name=$(modinfo --set-version "$KDUMP_KERNELVER" -F name "$_driver" 2> /dev/null) + _module_filename=$(modinfo --set-version "$KDUMP_KERNELVER" -n "$_driver" 2> /dev/null) + if [[ -z $_module_name ]] || [[ -z $_module_filename ]] || [[ $_module_filename == *"(builtin)"* ]]; then continue fi if ! [[ " $_old_drivers " == *" $_module_name "* ]]; then @@ -485,38 +474,38 @@ check_fs_modified() fi _target=$(get_block_dump_target) - _new_fstype=$(get_fs_type_from_target $_target) - if [[ -z "$_target" ]] || [[ -z "$_new_fstype" ]];then + _new_fstype=$(get_fs_type_from_target "$_target") + if [[ -z $_target ]] || [[ -z $_new_fstype ]]; then derror "Dump target is invalid" return 2 fi ddebug "_target=$_target _new_fstype=$_new_fstype" - _new_dev=$(kdump_get_persistent_dev $_target) - if [ -z "$_new_dev" ]; then + _new_dev=$(kdump_get_persistent_dev "$_target") + if [[ -z $_new_dev ]]; then perror "Get persistent device name failed" return 2 fi - _new_mntpoint="$(get_kdump_mntpoint_from_target $_target)" - _dracut_args=$(lsinitrd $TARGET_INITRD -f usr/lib/dracut/build-parameter.txt) - if [[ -z "$_dracut_args" ]];then + _new_mntpoint="$(get_kdump_mntpoint_from_target "$_target")" + _dracut_args=$(lsinitrd "$TARGET_INITRD" -f usr/lib/dracut/build-parameter.txt) + if [[ -z $_dracut_args ]]; then dwarn "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) + if echo "$_dracut_args" | grep -q "\-\-mount"; then + # shellcheck disable=SC2046 + 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 + [[ $_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 + [[ $_target == "$(get_root_fs_device)" ]] && return 0 fi dinfo "Detected change in File System" @@ -534,19 +523,19 @@ check_system_modified() check_files_modified ret=$? - if [ $ret -ne 0 ]; then + if [[ $ret -ne 0 ]]; then return $ret fi check_fs_modified ret=$? - if [ $ret -ne 0 ]; then + if [[ $ret -ne 0 ]]; then return $ret fi check_drivers_modified ret=$? - if [ $ret -ne 0 ]; then + if [[ $ret -ne 0 ]]; then return $ret fi @@ -556,71 +545,62 @@ check_system_modified() check_rebuild() { local capture_capable_initrd="1" - local _force_rebuild force_rebuild="0" - local _force_no_rebuild force_no_rebuild="0" + local force_rebuild force_no_rebuild local ret system_modified="0" - setup_initrd + setup_initrd || return 1 - if [ $? -ne 0 ]; then + force_no_rebuild=$(kdump_get_conf_val force_no_rebuild) + force_no_rebuild=${force_no_rebuild:-0} + if [[ $force_no_rebuild != "0" ]] && [[ $force_no_rebuild != "1" ]]; then + derror "Error: force_no_rebuild value is invalid" 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 - derror "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 - derror "Error: force_rebuild value is invalid" - return 1 - fi + force_rebuild=$(kdump_get_conf_val force_rebuild) + force_rebuild=${force_rebuild:-0} + if [[ $force_rebuild != "0" ]] && [[ $force_rebuild != "1" ]]; then + derror "Error: force_rebuild value is invalid" + return 1 fi - if [[ "$force_no_rebuild" == "1" && "$force_rebuild" == "1" ]]; then + if [[ $force_no_rebuild == "1" && $force_rebuild == "1" ]]; then derror "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 + 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` + 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 -e ^kdumpbase$ -e ^zz-fadumpinit$ | wc -l) + if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then + capture_capable_initrd=$(lsinitrd -f $DRACUT_MODULES_FILE "$TARGET_INITRD" | grep -c -e ^kdumpbase$ -e ^zz-fadumpinit$) fi fi check_system_modified ret=$? - if [ $ret -eq 2 ]; then + if [[ $ret -eq 2 ]]; then return 1 - elif [ $ret -eq 1 ];then + elif [[ $ret -eq 1 ]]; then system_modified="1" fi - if [ $image_time -eq 0 ]; then + if [[ $image_time -eq 0 ]]; then dinfo "No kdump initial ramdisk found." - elif [ "$capture_capable_initrd" == "0" ]; then + elif [[ $capture_capable_initrd == "0" ]]; then dinfo "Rebuild $TARGET_INITRD with dump capture support" - elif [ "$force_rebuild" != "0" ]; then + elif [[ $force_rebuild != "0" ]]; then dinfo "Force rebuild $TARGET_INITRD" - elif [ "$system_modified" != "0" ]; then + elif [[ $system_modified != "0" ]]; then : else return 0 @@ -660,15 +640,16 @@ load_kdump() PS4='+ $(date "+%Y-%m-%d %H:%M:%S") ${BASH_SOURCE}@${LINENO}: ' set -x + # shellcheck disable=SC2086 $KEXEC $KEXEC_ARGS $standard_kexec_args \ --command-line="$KDUMP_COMMANDLINE" \ - --initrd=$TARGET_INITRD $KDUMP_KERNEL + --initrd="$TARGET_INITRD" "$KDUMP_KERNEL" ret=$? set +x exec 2>&12 12>&- - if [ $ret == 0 ]; then + if [[ $ret == 0 ]]; then dinfo "kexec: loaded kdump kernel" return 0 else @@ -679,13 +660,15 @@ load_kdump() check_ssh_config() { - while read config_opt config_val; do + local SSH_TARGET + + while read -r config_opt config_val; do case "$config_opt" in sshkey) # remove inline comments after the end of a directive. - if [ -f "$config_val" ]; then + if [[ -f $config_val ]]; then # canonicalize the path - SSH_KEY_LOCATION=$(/usr/bin/readlink -m $config_val) + SSH_KEY_LOCATION=$(/usr/bin/readlink -m "$config_val") else dwarn "WARNING: '$config_val' doesn't exist, using default value '$SSH_KEY_LOCATION'" fi @@ -696,14 +679,14 @@ check_ssh_config() ssh) DUMP_TARGET=$config_val ;; - *) - ;; + *) ;; + esac - done <<< "$(read_strip_comments $KDUMP_CONFIG_FILE)" + done <<< "$(kdump_read_conf)" #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 + SSH_TARGET=$(echo -n "$DUMP_TARGET" | sed -n '/.*@/p') + if [[ -z $SSH_TARGET ]]; then return 1 fi return 0 @@ -714,43 +697,43 @@ check_ssh_config() # by the return val of 'ssh' check_and_wait_network_ready() { - local start_time=$(date +%s) + local start_time local warn_once=1 local cur local diff local retval local errmsg + start_time=$(date +%s) while true; do - errmsg=$(ssh -i $SSH_KEY_LOCATION -o BatchMode=yes $DUMP_TARGET mkdir -p $SAVE_PATH 2>&1) + 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 + if [[ $retval -eq 0 ]]; then return 0 - elif [ $retval -ne 255 ]; then + elif [[ $retval -ne 255 ]]; then derror "Could not create $DUMP_TARGET:$SAVE_PATH, you should check the privilege on server side" return 1 fi # if server removes the authorized_keys or, no /root/.ssh/kdump_id_rsa ddebug "$errmsg" - echo $errmsg | grep -q "Permission denied\|No such file or directory\|Host key verification failed" &> /dev/null - if [ $? -eq 0 ]; then + if echo "$errmsg" | grep -q "Permission denied\|No such file or directory\|Host key verification failed"; then derror "Could not create $DUMP_TARGET:$SAVE_PATH, you probably need to run \"kdumpctl propagate\"" return 1 fi - if [ $warn_once -eq 1 ]; then + if [[ $warn_once -eq 1 ]]; then dwarn "Network dump target is not usable, waiting for it to be ready..." warn_once=0 fi cur=$(date +%s) - let "diff = $cur - $start_time" + diff=$((cur - start_time)) # 60s time out - if [ $diff -gt 180 ]; then - break; + if [[ $diff -gt 180 ]]; then + break fi sleep 1 done @@ -762,16 +745,11 @@ check_and_wait_network_ready() 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 + if ! check_ssh_config; then derror "No ssh config specified in $KDUMP_CONFIG_FILE. Can't propagate" exit 1 fi @@ -780,22 +758,22 @@ propagate_ssh_key() local errmsg="Failed to propagate ssh key" #Check to see if we already created key, if not, create it. - if [ -f $KEYFILE ]; then + if [[ -f $KEYFILE ]]; then dinfo "Using existing keys..." else dinfo "Generating new ssh keys... " - /usr/bin/ssh-keygen -t rsa -f $KEYFILE -N "" 2>&1 > /dev/null + /usr/bin/ssh-keygen -t rsa -f "$KEYFILE" -N "" 2>&1 > /dev/null dinfo "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/'` + SSH_USER=$(echo "$DUMP_TARGET" | 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 + ssh-copy-id -i "$KEYFILE" "$SSH_USER@$SSH_SERVER" RET=$? - if [ $RET == 0 ]; then + if [[ $RET == 0 ]]; then dinfo "$KEYFILE has been added to ~$SSH_USER/.ssh/authorized_keys on $SSH_SERVER" return 0 else @@ -806,23 +784,26 @@ propagate_ssh_key() show_reserved_mem() { - local mem=$(cat /sys/kernel/kexec_crash_size) - local mem_mb=$(expr $mem / 1024 / 1024) + local mem + local mem_mb - dinfo "Reserved "$mem_mb"MB memory for crash kernel" + mem=$(< /sys/kernel/kexec_crash_size) + mem_mb=$((mem / 1024 / 1024)) + + dinfo "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 + rc=$(< $FADUMP_REGISTER_SYS_NODE) + [[ $rc -eq 1 ]] && return 0 return 1 } check_current_status() { - if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then check_current_fadump_status else check_current_kdump_status @@ -836,34 +817,34 @@ 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" ] || { + raw_target=$(kdump_get_conf_val raw) + [[ -z $raw_target ]] && return 0 + [[ -b $raw_target ]] || { derror "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 + check_fs=$(lsblk --nodeps -npo FSTYPE "$raw_target") + if [[ $(echo "$check_fs" | wc -w) -ne 0 ]]; then dwarn "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"`" + kdump_dir=$(kdump_get_conf_val path) + if [[ -z ${kdump_dir} ]]; then + coredir="/var/crash/$(date +"%Y-%m-%d-%H:%M")" else - coredir="${kdump_dir}/`date +"%Y-%m-%d-%H:%M"`" + coredir="${kdump_dir}/$(date +"%Y-%m-%d-%H:%M")" fi mkdir -p "$coredir" - [ -d "$coredir" ] || { + [[ -d $coredir ]] || { derror "failed to create $coredir" return 1 } - if makedumpfile -R $coredir/vmcore <$raw_target >/dev/null 2>&1; then + if makedumpfile -R "$coredir/vmcore" < "$raw_target" > /dev/null 2>&1; then # dump found dinfo "Dump saved to $coredir/vmcore" # wipe makedumpfile header - dd if=/dev/zero of=$raw_target bs=1b count=1 2>/dev/null + dd if=/dev/zero of="$raw_target" bs=1b count=1 2> /dev/null else rm -rf "$coredir" fi @@ -875,9 +856,8 @@ 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}' + if _target=$(grep -E "^ext[234]|^xfs|^btrfs|^minix" /etc/kdump.conf); then + echo "$_target" | awk '{print $2}' fi } @@ -887,12 +867,12 @@ path_to_be_relabeled() if is_user_configured_dump_target; then if is_mount_in_dracut_args; then - return; + return fi _target=$(local_fs_dump_target) - if [[ -n "$_target" ]]; then - _mnt=$(get_mntpoint_from_target $_target) + if [[ -n $_target ]]; then + _mnt=$(get_mntpoint_from_target "$_target") if ! is_mounted "$_mnt"; then return fi @@ -903,9 +883,9 @@ path_to_be_relabeled() _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 + _rmnt=$(df "$_mnt/$_path" 2> /dev/null | tail -1 | awk '{ print $NF }') + if [[ $_rmnt == "$_mnt" ]]; then + echo "$_mnt/$_path" fi } @@ -914,32 +894,35 @@ selinux_relabel() local _path _i _attr _path=$(path_to_be_relabeled) - if [ -z "$_path" ] || ! [ -d "$_path" ] ; then + 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; + while IFS= read -r -d '' _i; do + _attr=$(getfattr -m "security.selinux" "$_i" 2> /dev/null) + if [[ -z $_attr ]]; then + restorecon "$_i" fi - done + done < <(find "$_path" -print0) } check_fence_kdump_config() { - local hostname=`hostname` - local ipaddrs=`hostname -I` - local nodes=$(get_option_value "fence_kdump_nodes") + local hostname + local ipaddrs + local nodes + + hostname=$(hostname) + ipaddrs=$(hostname -I) + nodes=$(kdump_get_conf_val "fence_kdump_nodes") for node in $nodes; do - if [ "$node" = "$hostname" ]; then + if [[ $node == "$hostname" ]]; then derror "Option fence_kdump_nodes cannot contain $hostname" return 1 fi # node can be ipaddr - echo "$ipaddrs " | grep "$node " > /dev/null - if [ $? -eq 0 ]; then + if echo "$ipaddrs " | grep -q "$node "; then derror "Option fence_kdump_nodes cannot contain $node" return 1 fi @@ -950,7 +933,7 @@ check_fence_kdump_config() check_dump_feasibility() { - if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then return 0 fi @@ -972,7 +955,7 @@ start_fadump() start_dump() { - if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then start_fadump else load_kdump @@ -987,28 +970,29 @@ check_failure_action_config() 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) + default_option=$(kdump_get_conf_val default) + failure_action=$(kdump_get_conf_val failure_action) - if [ -z "$failure_action" -a -z "$default_option" ]; then + if [[ -z $failure_action ]] && [[ -z $default_option ]]; then return 0 - elif [ -n "$failure_action" -a -n "$default_option" ]; then + elif [[ -n $failure_action ]] && [[ -n $default_option ]]; then derror "Cannot specify 'failure_action' and 'default' option together" return 1 fi - if [ -n "$default_option" ]; then + if [[ -n $default_option ]]; then option="default" failure_action="$default_option" fi case "$failure_action" in - reboot|halt|poweroff|shell|dump_to_rootfs) + reboot | halt | poweroff | shell | dump_to_rootfs) return 0 - ;; - *) + ;; + *) dinfo $"Usage kdump.conf: $option {reboot|halt|poweroff|shell|dump_to_rootfs}" return 1 + ;; esac } @@ -1016,47 +1000,44 @@ check_final_action_config() { local final_action - final_action=$(awk '$1 ~ /^final_action$/ {print $2;}' $KDUMP_CONFIG_FILE) - if [ -z "$final_action" ]; then + final_action=$(kdump_get_conf_val final_action) + if [[ -z $final_action ]]; then return 0 else case "$final_action" in - reboot|halt|poweroff) + reboot | halt | poweroff) return 0 - ;; - *) + ;; + *) dinfo $"Usage kdump.conf: final_action {reboot|halt|poweroff}" return 1 + ;; esac fi } start() { - check_dump_feasibility - if [ $? -ne 0 ]; then + if ! check_dump_feasibility; then derror "Starting kdump: [FAILED]" return 1 fi - check_config - if [ $? -ne 0 ]; then + if ! check_config; then derror "Starting kdump: [FAILED]" return 1 fi - if sestatus 2>/dev/null | grep -q "SELinux status.*enabled"; then + if sestatus 2> /dev/null | grep -q "SELinux status.*enabled"; then selinux_relabel fi - save_raw - if [ $? -ne 0 ]; then + if ! save_raw; then derror "Starting kdump: [FAILED]" return 1 fi - check_current_status - if [ $? == 0 ]; then + if check_current_status; then dwarn "Kdump already running: [WARNING]" return 0 fi @@ -1068,14 +1049,12 @@ start() fi fi - check_rebuild - if [ $? != 0 ]; then + if ! check_rebuild; then derror "Starting kdump: [FAILED]" return 1 fi - start_dump - if [ $? != 0 ]; then + if ! start_dump; then derror "Starting kdump: [FAILED]" return 1 fi @@ -1085,33 +1064,28 @@ start() reload() { - check_current_status - if [ $? -ne 0 ]; then + if ! check_current_status; then dwarn "Kdump was not running: [WARNING]" fi - if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then reload_fadump return $? else - stop_kdump - fi - - if [ $? -ne 0 ]; then - derror "Stopping kdump: [FAILED]" - return 1 + if ! stop_kdump; then + derror "Stopping kdump: [FAILED]" + return 1 + fi fi dinfo "Stopping kdump: [OK]" - setup_initrd - if [ $? -ne 0 ]; then + if ! setup_initrd; then derror "Starting kdump: [FAILED]" return 1 fi - start_dump - if [ $? -ne 0 ]; then + if ! start_dump; then derror "Starting kdump: [FAILED]" return 1 fi @@ -1139,7 +1113,8 @@ stop_kdump() $KEXEC -p -u fi - if [ $? != 0 ]; then + # shellcheck disable=SC2181 + if [[ $? != 0 ]]; then derror "kexec: failed to unload kdump kernel" return 1 fi @@ -1150,16 +1125,14 @@ stop_kdump() reload_fadump() { - echo 1 > $FADUMP_REGISTER_SYS_NODE - if [ $? == 0 ]; then + if echo 1 > $FADUMP_REGISTER_SYS_NODE; then dinfo "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 + if stop_fadump; then start_fadump return $? fi @@ -1170,13 +1143,14 @@ reload_fadump() stop() { - if [ $DEFAULT_DUMP_MODE == "fadump" ]; then + if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then stop_fadump else stop_kdump fi - if [ $? != 0 ]; then + # shellcheck disable=SC2181 + if [[ $? != 0 ]]; then derror "Stopping kdump: [FAILED]" return 1 fi @@ -1185,11 +1159,9 @@ stop() return 0 } -rebuild() { - check_config - if [ $? -ne 0 ]; then - return 1 - fi +rebuild() +{ + check_config || return 1 if check_ssh_config; then if ! check_ssh_target; then @@ -1197,43 +1169,41 @@ rebuild() { fi fi - setup_initrd - if [ $? -ne 0 ]; then - return 1 - fi + setup_initrd || return 1 dinfo "Rebuilding $TARGET_INITRD" rebuild_initrd return $? } -do_estimate() { +do_estimate() +{ local kdump_mods local -A large_mods local baseline local kernel_size mod_size initrd_size baseline_size runtime_size reserved_size estimated_size recommended_size - local size_mb=$(( 1024 * 1024 )) + local size_mb=$((1024 * 1024)) setup_initrd - if [ ! -f "$TARGET_INITRD" ]; then + if [[ ! -f $TARGET_INITRD ]]; then derror "kdumpctl estimate: kdump initramfs is not built yet." exit 1 fi kdump_mods="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/hostonly-kernel-modules.txt | tr '\n' ' ')" baseline=$(kdump_get_arch_recommend_size) - if [[ "${baseline: -1}" == "M" ]]; then + if [[ ${baseline: -1} == "M" ]]; then baseline=${baseline%M} - elif [[ "${baseline: -1}" == "G" ]]; then - baseline=$(( ${baseline%G} * 1024 )) - elif [[ "${baseline: -1}" == "T" ]]; then - baseline=$(( ${baseline%Y} * 1048576 )) + elif [[ ${baseline: -1} == "G" ]]; then + baseline=$((${baseline%G} * 1024)) + elif [[ ${baseline: -1} == "T" ]]; then + baseline=$((${baseline%Y} * 1048576)) fi # The default pre-reserved crashkernel value baseline_size=$((baseline * size_mb)) # Current reserved crashkernel size - reserved_size=$(cat /sys/kernel/kexec_crash_size) + reserved_size=$(< /sys/kernel/kexec_crash_size) # A pre-estimated value for userspace usage and kernel # runtime allocation, 64M should good for most cases runtime_size=$((64 * size_mb)) @@ -1244,7 +1214,7 @@ do_estimate() { # Kernel modules static size after loaded mod_size=0 while read -r _name _size _; do - if [[ ! " $kdump_mods " == *" $_name "* ]]; then + if [[ " $kdump_mods " != *" $_name "* ]]; then continue fi mod_size=$((mod_size + _size)) @@ -1259,8 +1229,8 @@ do_estimate() { crypt_size=0 for _dev in $(get_all_kdump_crypt_dev); do _crypt_info=$(cryptsetup luksDump "/dev/block/$_dev") - [[ $(echo "$_crypt_info" | sed -n "s/^Version:\s*\(.*\)/\1/p" ) == "2" ]] || continue - for _mem in $(echo "$_crypt_info" | sed -n "s/\sMemory:\s*\(.*\)/\1/p" | sort -n ); do + [[ $(echo "$_crypt_info" | sed -n "s/^Version:\s*\(.*\)/\1/p") == "2" ]] || continue + for _mem in $(echo "$_crypt_info" | sed -n "s/\sMemory:\s*\(.*\)/\1/p" | sort -n); do crypt_size=$((crypt_size + _mem * 1024)) break done @@ -1281,10 +1251,10 @@ do_estimate() { echo "Kernel modules size: $((mod_size / size_mb))M" echo "Initramfs size: $((initrd_size / size_mb))M" echo "Runtime reservation: $((runtime_size / size_mb))M" - [[ $crypt_size -ne 0 ]] && \ - echo "LUKS required size: $((crypt_size / size_mb))M" + [[ $crypt_size -ne 0 ]] && + echo "LUKS required size: $((crypt_size / size_mb))M" echo -n "Large modules:" - if [[ "${#large_mods[@]}" -eq 0 ]]; then + if [[ ${#large_mods[@]} -eq 0 ]]; then echo " " else echo "" @@ -1298,14 +1268,15 @@ do_estimate() { fi } -reset_crashkernel() { +reset_crashkernel() +{ local kernel=$1 entry crashkernel_default local grub_etc_default="/etc/default/grub" - [[ -z "$kernel" ]] && kernel=$(uname -r) - crashkernel_default=$(cat "/usr/lib/modules/$kernel/crashkernel.default" 2>/dev/null) + [[ -z $kernel ]] && kernel=$(uname -r) + crashkernel_default=$(cat "/usr/lib/modules/$kernel/crashkernel.default" 2> /dev/null) - if [[ -z "$crashkernel_default" ]]; then + if [[ -z $crashkernel_default ]]; then derror "$kernel doesn't have a crashkernel.default" exit 1 fi @@ -1322,7 +1293,7 @@ reset_crashkernel() { entry=${entry#\"} entry=${entry%\"} - if [[ -f "$grub_etc_default" ]]; then + if [[ -f $grub_etc_default ]]; then sed -i -e "s/^\(GRUB_CMDLINE_LINUX=.*\)crashkernel=[^\ \"]*\([\ \"].*\)$/\1$crashkernel_default\2/" "$grub_etc_default" fi @@ -1330,72 +1301,73 @@ reset_crashkernel() { grubby --args "$crashkernel_default" --update-kernel "$entry" $zipl_arg [[ $zipl_arg ]] && zipl > /dev/null fi - } +} -if [ ! -f "$KDUMP_CONFIG_FILE" ]; then +if [[ ! -f $KDUMP_CONFIG_FILE ]]; then derror "Error: No kdump config file found!" exit 1 fi -main () +main() { # Determine if the dump mode is kdump or fadump determine_dump_mode case "$1" in - start) - if [ -s /proc/vmcore ]; then + start) + if [[ -s /proc/vmcore ]]; then save_core reboot else start fi ;; - stop) + stop) stop ;; - status) + status) EXIT_CODE=0 check_current_status case "$?" in - 0) + 0) dinfo "Kdump is operational" EXIT_CODE=0 ;; - 1) + 1) dinfo "Kdump is not operational" EXIT_CODE=3 ;; esac exit $EXIT_CODE ;; - reload) + reload) reload ;; - restart) + restart) stop start ;; - rebuild) + rebuild) rebuild ;; - condrestart) - ;; - propagate) + condrestart) ;; + + propagate) propagate_ssh_key ;; - showmem) + showmem) show_reserved_mem ;; - estimate) + estimate) do_estimate ;; - reset-crashkernel) + reset-crashkernel) reset_crashkernel "$2" ;; - *) + *) dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|reset-crashkernel|propagate|showmem}" exit 1 + ;; esac } @@ -1404,6 +1376,9 @@ 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 "$@") +( + exec 9<&- + main "$@" +) exit $? diff --git a/SOURCES/kexec-tools-2.0.22-makedumpfile-Increase-SECTION_MAP_LAST_BIT-to-5.patch b/SOURCES/kexec-tools-2.0.22-makedumpfile-Increase-SECTION_MAP_LAST_BIT-to-5.patch deleted file mode 100644 index a59bef1..0000000 --- a/SOURCES/kexec-tools-2.0.22-makedumpfile-Increase-SECTION_MAP_LAST_BIT-to-5.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 646456862df8926ba10dd7330abf3bf0f887e1b6 Mon Sep 17 00:00:00 2001 -From: Kazuhito Hagio -Date: Wed, 26 May 2021 14:31:26 +0900 -Subject: [PATCH] Increase SECTION_MAP_LAST_BIT to 5 - -* Required for kernel 5.12 - -Kernel commit 1f90a3477df3 ("mm: teach pfn_to_online_page() about -ZONE_DEVICE section collisions") added a section flag -(SECTION_TAINT_ZONE_DEVICE) and causes makedumpfile an error on -some machines like this: - - __vtop4_x86_64: Can't get a valid pmd_pte. - readmem: Can't convert a virtual address(ffffe2bdc2000000) to physical address. - readmem: type_addr: 0, addr:ffffe2bdc2000000, size:32768 - __exclude_unnecessary_pages: Can't read the buffer of struct page. - create_2nd_bitmap: Can't exclude unnecessary pages. - -Increase SECTION_MAP_LAST_BIT to 5 to fix this. The bit had not -been used until the change, so we can just increase the value. - -Signed-off-by: Kazuhito Hagio ---- - makedumpfile.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/makedumpfile-1.6.9/makedumpfile.h b/makedumpfile-1.6.9/makedumpfile.h -index 93aa774..79046f2 100644 ---- a/makedumpfile-1.6.9/makedumpfile.h -+++ b/makedumpfile-1.6.9/makedumpfile.h -@@ -195,7 +195,7 @@ isAnon(unsigned long mapping) - * 2. it has been verified that (1UL<<2) was never set, so it is - * safe to mask that bit off even in old kernels. - */ --#define SECTION_MAP_LAST_BIT (1UL<<4) -+#define SECTION_MAP_LAST_BIT (1UL<<5) - #define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1)) - #define NR_SECTION_ROOTS() divideup(num_section, SECTIONS_PER_ROOT()) - #define SECTION_NR_TO_PFN(sec) ((sec) << PFN_SECTION_SHIFT()) --- -2.29.2 - diff --git a/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch b/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch deleted file mode 100644 index 8cf780c..0000000 --- a/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 9a6f589d99dcef114c89fde992157f5467028c8f Mon Sep 17 00:00:00 2001 -From: Tao Liu -Date: Fri, 18 Jun 2021 18:28:04 +0800 -Subject: [PATCH] check for invalid physical address of /proc/kcore - when making ELF dumpfile - -Previously when executing makedumpfile with -E option against -/proc/kcore, makedumpfile will fail: - - # makedumpfile -E -d 31 /proc/kcore kcore.dump - ... - write_elf_load_segment: Can't convert physaddr(ffffffffffffffff) to an offset. - - makedumpfile Failed. - -It's because /proc/kcore contains PT_LOAD program headers which have -physaddr (0xffffffffffffffff). With -E option, makedumpfile will -try to convert the physaddr to an offset and fails. - -Skip the PT_LOAD program headers which have such physaddr. - -Signed-off-by: Tao Liu -Signed-off-by: Kazuhito Hagio ---- - makedumpfile.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/makedumpfile-1.6.9/makedumpfile.c b/makedumpfile-1.6.9/makedumpfile.c -index 894c88e..fcb571f 100644 ---- a/makedumpfile-1.6.9/makedumpfile.c -+++ b/makedumpfile-1.6.9/makedumpfile.c -@@ -7764,7 +7764,7 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page) - if (!get_phdr_memory(i, &load)) - return FALSE; - -- if (load.p_type != PT_LOAD) -+ if (load.p_type != PT_LOAD || load.p_paddr == NOT_PADDR) - continue; - - off_memory= load.p_offset; --- -2.29.2 - diff --git a/SOURCES/mkdumprd b/SOURCES/mkdumprd index ead2d13..d87d588 100644 --- a/SOURCES/mkdumprd +++ b/SOURCES/mkdumprd @@ -6,7 +6,7 @@ # Written by Cong Wang # -if [ -f /etc/sysconfig/kdump ]; then +if [[ -f /etc/sysconfig/kdump ]]; then . /etc/sysconfig/kdump fi @@ -17,23 +17,21 @@ fi export IN_KDUMP=1 #initiate the kdump logger -dlog_init -if [ $? -ne 0 ]; then +if ! dlog_init; then echo "failed to initiate the kdump logger." exit 1 fi -conf_file="/etc/kdump.conf" SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" SAVE_PATH=$(get_save_path) OVERRIDE_RESETTABLE=0 extra_modules="" -dracut_args="--add kdumpbase --quiet --hostonly --hostonly-cmdline --hostonly-i18n --hostonly-mode strict -o \"plymouth dash resume ifcfg earlykdump\"" +dracut_args=(--add kdumpbase --quiet --hostonly --hostonly-cmdline --hostonly-i18n --hostonly-mode strict -o "plymouth resume ifcfg earlykdump") -readonly MKDUMPRD_TMPDIR="$(mktemp -d -t mkdumprd.XXXXXX)" +MKDUMPRD_TMPDIR="$(mktemp -d -t mkdumprd.XXXXXX)" [ -d "$MKDUMPRD_TMPDIR" ] || perror_exit "dracut: mktemp -p -d -t dracut.XXXXXX failed." -readonly MKDUMPRD_TMPMNT="$MKDUMPRD_TMPDIR/target" +MKDUMPRD_TMPMNT="$MKDUMPRD_TMPDIR/target" trap ' ret=$?; @@ -45,66 +43,71 @@ trap ' # clean up after ourselves no matter how we die. trap 'exit 1;' SIGINT -add_dracut_arg() { - dracut_args="$dracut_args $@" +add_dracut_arg() +{ + dracut_args+=("$@") } -add_dracut_mount() { - add_dracut_arg "--mount" "\"$1\"" +add_dracut_mount() +{ + add_dracut_arg "--mount" "$1" } -add_dracut_sshkey() { - add_dracut_arg "--sshkey" "\"$1\"" +add_dracut_sshkey() +{ + add_dracut_arg "--sshkey" "$1" } # caller should ensure $1 is valid and mounted in 1st kernel -to_mount() { - local _target=$1 _fstype=$2 _options=$3 _new_mntpoint _pdev - - _new_mntpoint=$(get_kdump_mntpoint_from_target $_target) - _fstype="${_fstype:-$(get_fs_type_from_target $_target)}" - _options="${_options:-$(get_mntopt_from_target $_target)}" - _options="${_options:-defaults}" - - if [[ "$_fstype" == "nfs"* ]]; then - _pdev=$_target - _options=$(echo $_options | sed 's/,addr=[^,]*//') - _options=$(echo $_options | sed 's/,proto=[^,]*//') - _options=$(echo $_options | sed 's/,clientaddr=[^,]*//') - else - # for non-nfs _target converting to use udev persistent name - _pdev="$(kdump_get_persistent_dev $_target)" - if [ -z "$_pdev" ]; then - return 1 - fi - fi - - # mount fs target as rw in 2nd kernel - _options=$(echo $_options | sed 's/\(^\|,\)ro\($\|,\)/\1rw\2/g') - # with 'noauto' in fstab nfs and non-root disk mount will fail in 2nd - # kernel, filter it out here. - _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') - - echo "$_pdev $_new_mntpoint $_fstype $_options" +to_mount() +{ + local _target=$1 _fstype=$2 _options=$3 _sed_cmd _new_mntpoint _pdev + + _new_mntpoint=$(get_kdump_mntpoint_from_target "$_target") + _fstype="${_fstype:-$(get_fs_type_from_target "$_target")}" + _options="${_options:-$(get_mntopt_from_target "$_target")}" + _options="${_options:-defaults}" + + if [[ $_fstype == "nfs"* ]]; then + _pdev=$_target + _sed_cmd+='s/,\(mount\)\?addr=[^,]*//g;' + _sed_cmd+='s/,\(mount\)\?proto=[^,]*//g;' + _sed_cmd+='s/,clientaddr=[^,]*//;' + else + # for non-nfs _target converting to use udev persistent name + _pdev="$(kdump_get_persistent_dev "$_target")" + if [[ -z $_pdev ]]; then + return 1 + fi + fi + + # mount fs target as rw in 2nd kernel + _sed_cmd+='s/\(^\|,\)ro\($\|,\)/\1rw\2/g;' + # with 'noauto' in fstab nfs and non-root disk mount will fail in 2nd + # kernel, filter it out here. + _sed_cmd+='s/\(^\|,\)noauto\($\|,\)/\1/g;' + # drop nofail or nobootwait + _sed_cmd+='s/\(^\|,\)nofail\($\|,\)/\1/g;' + _sed_cmd+='s/\(^\|,\)nobootwait\($\|,\)/\1/g;' + + _options=$(echo "$_options" | sed "$_sed_cmd") + + echo "$_pdev $_new_mntpoint $_fstype $_options" } #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 +get_ssh_size() +{ + local _out + local _opt=("-i" "$SSH_KEY_LOCATION" "-o" "BatchMode=yes" "-o" "StrictHostKeyChecking=yes") + + if ! _out=$(ssh -q -n "${_opt[@]}" "$1" "df" "--output=avail" "$SAVE_PATH"); then + perror_exit "checking remote ssh server available size failed." + fi + + echo -n "$_out" | tail -1 } #mkdir if save path does not exist on ssh dump target @@ -113,323 +116,323 @@ get_ssh_size() { #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 + local _opt _dir + _opt=(-i "$SSH_KEY_LOCATION" -o BatchMode=yes -o StrictHostKeyChecking=yes) + ssh -qn "${_opt[@]}" "$1" mkdir -p "$SAVE_PATH" &> /dev/null || + perror_exit "mkdir failed on $1:$SAVE_PATH" + + # check whether user has write permission on $1:$SAVE_PATH + _dir=$(ssh -qn "${_opt[@]}" "$1" mktemp -dqp "$SAVE_PATH" 2> /dev/null) || + perror_exit "Could not create temporary directory on $1:$SAVE_PATH. Make sure user has write permission on destination" + 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}') +get_fs_size() +{ + df --output=avail "$(get_mntpoint_from_target "$1")/$SAVE_PATH" | tail -1 } #Function: get_raw_size #$1=dump target -get_raw_size() { - echo -n $(fdisk -s "$1") +get_raw_size() +{ + 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 - dwarn "Warning: There might not be enough space to save a vmcore." - dwarn " The size of $2 should be greater than $memtotal kilo bytes." - fi +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 || perror_exit "Check dump target size failed" + + if [[ $avail -lt $memtotal ]]; then + dwarn "Warning: There might not be enough space to save a vmcore." + dwarn " The size of $2 should be greater than $memtotal kilo bytes." + fi } check_save_path_fs() { - local _path=$1 + local _path=$1 + + if [[ ! -d $_path ]]; then + perror_exit "Dump path $_path does not exist." + fi +} + +mount_failure() +{ + local _target=$1 + local _mnt=$2 + local _fstype=$3 + local msg="Failed to mount $_target" + + if [[ -n $_mnt ]]; then + msg="$msg on $_mnt" + fi - if [ ! -d $_path ]; then - perror_exit "Dump path $_path does not exist." - fi + msg="$msg for kdump preflight check." + + if [[ $_fstype == "nfs" ]]; then + msg="$msg Please make sure nfs-utils has been installed." + fi + + perror_exit "$msg" } check_user_configured_target() { - local _target=$1 _cfg_fs_type=$2 _mounted - local _mnt=$(get_mntpoint_from_target $_target) - local _opt=$(get_mntopt_from_target $_target) - local _fstype=$(get_fs_type_from_target $_target) - - if [ -n "$_fstype" ]; then - # In case of nfs4, nfs should be used instead, nfs* options is deprecated in kdump.conf - [[ $_fstype = "nfs"* ]] && _fstype=nfs - - if [ -n "$_cfg_fs_type" ] && [ "$_fstype" != "$_cfg_fs_type" ]; then - perror_exit "\"$_target\" have a wrong type config \"$_cfg_fs_type\", expected \"$_fstype\"" - fi - else - _fstype="$_cfg_fs_type" - _fstype="$_cfg_fs_type" - fi - - # For noauto mount, mount it inplace with default value. - # Else use the temporary target directory - if [ -n "$_mnt" ]; then - if ! is_mounted "$_mnt"; then - if [[ $_opt = *",noauto"* ]]; then - mount $_mnt - [ $? -ne 0 ] && perror_exit "Failed to mount $_target on $_mnt for kdump preflight check." - _mounted=$_mnt - else - perror_exit "Dump target \"$_target\" is neither mounted nor configured as \"noauto\"" - fi - fi - else - _mnt=$MKDUMPRD_TMPMNT - mkdir -p $_mnt - mount $_target $_mnt -t $_fstype -o defaults - [ $? -ne 0 ] && perror_exit "Failed to mount $_target for kdump preflight check." - _mounted=$_mnt - fi - - # For user configured target, use $SAVE_PATH as the dump path within the target - if [ ! -d "$_mnt/$SAVE_PATH" ]; then - perror_exit "Dump path \"$SAVE_PATH\" does not exist in dump target \"$_target\"" - fi - - check_size fs "$_target" - - # Unmount it early, if function is interrupted and didn't reach here, the shell trap will clear it up anyway - if [ -n "$_mounted" ]; then - umount -f -- $_mounted - fi + local _target=$1 _cfg_fs_type=$2 _mounted + local _mnt _opt _fstype + + _mnt=$(get_mntpoint_from_target "$_target") + _opt=$(get_mntopt_from_target "$_target") + _fstype=$(get_fs_type_from_target "$_target") + + if [[ -n $_fstype ]]; then + # In case of nfs4, nfs should be used instead, nfs* options is deprecated in kdump.conf + [[ $_fstype == "nfs"* ]] && _fstype=nfs + + if [[ -n $_cfg_fs_type ]] && [[ $_fstype != "$_cfg_fs_type" ]]; then + perror_exit "\"$_target\" have a wrong type config \"$_cfg_fs_type\", expected \"$_fstype\"" + fi + else + _fstype="$_cfg_fs_type" + _fstype="$_cfg_fs_type" + fi + + # For noauto mount, mount it inplace with default value. + # Else use the temporary target directory + if [[ -n $_mnt ]]; then + if ! is_mounted "$_mnt"; then + if [[ $_opt == *",noauto"* ]]; then + mount "$_mnt" || mount_failure "$_target" "$_mnt" "$_fstype" + _mounted=$_mnt + else + perror_exit "Dump target \"$_target\" is neither mounted nor configured as \"noauto\"" + fi + fi + else + _mnt=$MKDUMPRD_TMPMNT + mkdir -p "$_mnt" + mount "$_target" "$_mnt" -t "$_fstype" -o defaults || mount_failure "$_target" "" "$_fstype" + _mounted=$_mnt + fi + + # For user configured target, use $SAVE_PATH as the dump path within the target + if [[ ! -d "$_mnt/$SAVE_PATH" ]]; then + perror_exit "Dump path \"$_mnt/$SAVE_PATH\" does not exist in dump target \"$_target\"" + fi + + check_size fs "$_target" + + # Unmount it early, if function is interrupted and didn't reach here, the shell trap will clear it up anyway + if [[ -n $_mounted ]]; then + umount -f -- "$_mounted" + 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 - dwarn "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 +verify_core_collector() +{ + local _cmd="${1%% *}" + local _params="${1#* }" + + if [[ $_cmd != "makedumpfile" ]]; then + if is_raw_dump_target; then + dwarn "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 + + # shellcheck disable=SC2086 + if ! $_cmd --check-params $_params; then + perror_exit "makedumpfile parameter check failed." + fi } -add_mount() { - local _mnt=$(to_mount $@) +add_mount() +{ + local _mnt - if [ $? -ne 0 ]; then - exit 1 - fi + _mnt=$(to_mount "$@") || exit 1 - add_dracut_mount "$_mnt" + 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 + local _target + local _mntpoint - check_save_path_fs $SAVE_PATH + is_user_configured_dump_target && return - _save_path=$(get_bind_mount_source $SAVE_PATH) - _target=$(get_target_from_path $_save_path) - _mntpoint=$(get_mntpoint_from_target $_target) + check_save_path_fs "$SAVE_PATH" - SAVE_PATH=${_save_path##"$_mntpoint"} - add_mount "$_target" - check_size fs $_target -} + _save_path=$(get_bind_mount_source "$SAVE_PATH") + _target=$(get_target_from_path "$_save_path") + _mntpoint=$(get_mntpoint_from_target "$_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 + SAVE_PATH=${_save_path##"$_mntpoint"} + add_mount "$_target" + check_size fs "$_target" } # $1: function name for_each_block_target() { - local dev majmin + 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 + 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 + 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}') - derror "Error: Can not save vmcore because device $device is unresettable" - return 0 - } - fi - - return 1 + local path device resettable=1 + + 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" + if [[ -f $path ]]; then + resettable="$(< "$path")" + [[ $resettable -eq 0 ]] && [[ $OVERRIDE_RESETTABLE -eq 0 ]] && { + device=$(udevadm info --query=all --path="/sys/dev/block/$1" | awk -F= '/DEVNAME/{print $2}') + derror "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 + local _target _override_resettable - for_each_block_target is_unresettable - _ret=$? + _override_resettable=$(kdump_get_conf_val override_resettable) + OVERRIDE_RESETTABLE=${_override_resettable:-$OVERRIDE_RESETTABLE} + if [ "$OVERRIDE_RESETTABLE" != "0" ] && [ "$OVERRIDE_RESETTABLE" != "1" ]; then + perror_exit "override_resettable value '$OVERRIDE_RESETTABLE' is invalid" + fi - [ $_ret -eq 0 ] && return + for_each_block_target is_unresettable && return - return 1 + return 1 } check_crypt() { - local _dev + local _dev - for _dev in $(get_kdump_targets); do - if [[ -n $(get_luks_crypt_dev "$(get_maj_min "$_dev")") ]]; then - derror "Device $_dev is encrypted." && return 1 - fi - done + for _dev in $(get_kdump_targets); do + if [[ -n $(get_luks_crypt_dev "$(get_maj_min "$_dev")") ]]; then + derror "Device $_dev is encrypted." && return 1 + fi + done } if ! check_resettable; then - exit 1 + exit 1 fi if ! check_crypt; then - dwarn "Warning: Encrypted device is in dump path, which is not recommended, see kexec-kdump-howto.txt for more details." + dwarn "Warning: Encrypted device is in dump path, which is not recommended, see kexec-kdump-howto.txt for more details." 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) +keyfile=$(kdump_get_conf_val sshkey) +if [[ -f $keyfile ]]; then + # canonicalize the path + SSH_KEY_LOCATION=$(/usr/bin/readlink -m "$keyfile") 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) - check_user_configured_target "$config_val" "$config_opt" - add_mount "$config_val" "$config_opt" - ;; - 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" kdump_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_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)" +while read -r 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) + check_user_configured_target "$config_val" "$config_opt" + add_mount "$config_val" "$config_opt" + ;; + 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" kdump_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_sshkey "$SSH_KEY_LOCATION" + else + perror_exit "Bad ssh dump target $config_val" + fi + ;; + core_collector) + verify_core_collector "$config_val" + ;; + dracut_args) + while read -r dracut_arg; do + add_dracut_arg "$dracut_arg" + done <<< "$(echo "$config_val" | xargs -n 1 echo)" + ;; + *) ;; + + esac +done <<< "$(kdump_read_conf)" handle_default_dump_target -if [ -n "$extra_modules" ] -then - add_dracut_arg "--add-drivers" \"$extra_modules\" +if [[ -n $extra_modules ]]; then + add_dracut_arg "--add-drivers" "$extra_modules" fi # TODO: The below check is not needed anymore with the introduction of @@ -438,14 +441,14 @@ fi # parameter available in fadump case. So, find a way to fix that first # before removing this check. 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))" + # 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" + add_dracut_arg "--no-hostonly-default-device" fi -echo "$dracut_args $@" | xargs dracut +dracut "${dracut_args[@]}" "$@" _rc=$? sync diff --git a/SOURCES/mkfadumprd b/SOURCES/mkfadumprd index aecf2a8..b890f83 100644 --- a/SOURCES/mkfadumprd +++ b/SOURCES/mkfadumprd @@ -2,7 +2,7 @@ # Generate an initramfs image that isolates dump capture capability within # the default initramfs using zz-fadumpinit dracut module. -if [ -f /etc/sysconfig/kdump ]; then +if [[ -f /etc/sysconfig/kdump ]]; then . /etc/sysconfig/kdump fi @@ -17,7 +17,7 @@ if ! dlog_init; then exit 1 fi -readonly MKFADUMPRD_TMPDIR="$(mktemp -d -t mkfadumprd.XXXXXX)" +MKFADUMPRD_TMPDIR="$(mktemp -d -t mkfadumprd.XXXXXX)" [ -d "$MKFADUMPRD_TMPDIR" ] || perror_exit "mkfadumprd: mktemp -d -t mkfadumprd.XXXXXX failed." trap ' ret=$?; @@ -44,21 +44,24 @@ fi ### Unpack the initramfs having dump capture capability mkdir -p "$MKFADUMPRD_TMPDIR/fadumproot" -if ! (pushd "$MKFADUMPRD_TMPDIR/fadumproot" > /dev/null && lsinitrd --unpack "$FADUMP_INITRD" && \ +if ! (pushd "$MKFADUMPRD_TMPDIR/fadumproot" > /dev/null && lsinitrd --unpack "$FADUMP_INITRD" && popd > /dev/null); then derror "mkfadumprd: failed to unpack '$MKFADUMPRD_TMPDIR'" exit 1 fi ### Pack it into the normal boot initramfs with zz-fadumpinit module -_dracut_isolate_args="--rebuild $REBUILD_INITRD --add zz-fadumpinit \ - -i $MKFADUMPRD_TMPDIR/fadumproot /fadumproot \ - -i $MKFADUMPRD_TMPDIR/fadumproot/usr/lib/dracut/hostonly-kernel-modules.txt - /usr/lib/dracut/fadump-kernel-modules.txt" +_dracut_isolate_args=( + --rebuild "$REBUILD_INITRD" --add zz-fadumpinit + -i "$MKFADUMPRD_TMPDIR/fadumproot" /fadumproot + -i "$MKFADUMPRD_TMPDIR/fadumproot/usr/lib/dracut/hostonly-kernel-modules.txt" + /usr/lib/dracut/fadump-kernel-modules.txt +) if is_squash_available; then - _dracut_isolate_args="$_dracut_isolate_args --add squash" + _dracut_isolate_args+=(--add squash) fi -if ! dracut --force --quiet $_dracut_isolate_args $@ "$TARGET_INITRD"; then + +if ! dracut --force --quiet "${_dracut_isolate_args[@]}" "$@" "$TARGET_INITRD"; then perror_exit "mkfadumprd: failed to setup '$TARGET_INITRD' with dump capture capability" fi diff --git a/SOURCES/supported-kdump-targets.txt b/SOURCES/supported-kdump-targets.txt new file mode 100644 index 0000000..f540f59 --- /dev/null +++ b/SOURCES/supported-kdump-targets.txt @@ -0,0 +1,128 @@ +Supported Kdump Targets + +This document try to list all supported kdump targets, and those supported +or unknown/tech-preview targets, this can help users to decide whether a dump +solution is available. + +Dump Target support status +========================== +This section tries to come up with some kind of guidelines in terms of +what dump targets are supported/not supported. Whatever is listed here +is not binding in any manner. It is just sharing of current understanding +and if something is not right, this section needs to be edited. + +Following are 3 lists. First one contains supported targets. These are +generic configurations which should work and some configuration most +likely has worked in testing. Second list is known unsupported targets. +These targets we know either don't work or we don't support. And third +list is unknown/tech-preview. We either don't yet know the status of kdump +on these targets or these are under tech-preview. + +Note, these lists are not set in stone and can be changed at any point of +time. Also these lists might not be complete. We will add/remove items to +it as we get more testing information. Also, there are many corner cases +which can't possibly be listed. For example in general we might be +supporting software iscsi but there might be some configurations of it +which don't work. + +So if any target is listed in supported section, it does not mean it works +in all possible configurations. It just means that in common configurations +it should work but there can be issues with particular configurations which +are not supported. As we come to know of particular issues, we will keep on +updating lists accordingly. + + +Supported Dump targets +---------------------- +storage: + LVM volume (no thinp) + FC disks (qla2xxx, lpfc, bnx2fc, bfa) + software initiator based iSCSI + software RAID (mdraid) + hardware RAID (cciss, hpsa, megaraid_sas, mpt2sas, aacraid) + SCSI/SATA disks + iSCSI HBA (all offload) + hardware FCoE (qla2xxx, lpfc) + software FCoE (bnx2fc) (Extra configuration required, + please read "Note on FCoE" section below) + +network: + Hardware using kernel modules: (tg3, igb, ixgbe, sfc, e1000e, bna, + cnic, netxen_nic, qlge, bnx2x, bnx, qlcnic, be2net, enic, + virtio-net, ixgbevf, igbvf) + protocol: ipv4 + bonding + vlan + bridge + team + vlan tagged bonding + bridge over bond/team/vlan + +hypervisor: + kvm + xen (Supported in select configurations only) + +filesystem: + ext[234] + xfs + nfs + +firmware: + BIOS + UEFI + +hypervisor: + VMWare ESXi 4.1 and 5.1 + Hyper-V 2012 R2 (RHEL Gen1 UP Guest only) + +Unsupported Dump targets +------------------------ +storage: + BIOS RAID + Thin provisioning volume + Software iSCSI with iBFT (bnx2i, cxgb3i, cxgb4i) + Software iSCSI with hybrid (be2iscsi) + FCoE + legacy IDE + glusterfs + gfs2/clvm/halvm + +network: + hardware using kernel modules: (sfc SRIOV, cxgb4vf, pch_gbe) + protocol: ipv6 + wireless + Infiniband (IB) + vlan over bridge/team + +filesystem: + btrfs + +Unknown/tech-preview +-------------------- +storage: + PCI Express based SSDs + +hypervisor: + Hyper-V 2008 + Hyper-V 2012 + + +Note on FCoE +===================== +If you are trying to dump to a software FCoE target, you may encounter OOM +issue, because some software FCoE requires more memory to work. In such case, +you may need to increase the kdump reserved memory size in "crashkernel=" +kernel parameter. + +By default, RHEL systems have "crashkernel=auto" in kernel boot arguments. +The auto reserved memory size is designed to balance the coverage of use cases +and an acceptable memory overhead, so not every use case could fit in, software +FCoE is one of the case. + +For hardware FCoE, kdump should work naturally as firmware will do the +initialization job. The capture kernel and kdump tools will run just fine. + +Useful Links +============ +[1] RHEL6: Enabling kdump for full-virt (HVM) Xen DomU + (https://access.redhat.com/knowledge/solutions/92943) diff --git a/SPECS/kexec-tools.spec b/SPECS/kexec-tools.spec index 92284f8..1b9a781 100644 --- a/SPECS/kexec-tools.spec +++ b/SPECS/kexec-tools.spec @@ -1,11 +1,11 @@ %global eppic_ver d84c3541035d95077aa8571f5d5c3e07c6ef510b %global eppic_shortver %(c=%{eppic_ver}; echo ${c:0:7}) -%global mkdf_ver 1.6.9 +%global mkdf_ver 1.7.0 %global mkdf_shortver %(c=%{mkdf_ver}; echo ${c:0:7}) Name: kexec-tools -Version: 2.0.22 -Release: 14%{?dist} +Version: 2.0.23 +Release: 1%{?dist} License: GPLv2 Summary: The kexec/kdump userspace component @@ -42,6 +42,7 @@ Source31: kdump-logger.sh Source32: mkfadumprd Source33: 92-crashkernel.install Source34: crashkernel-howto.txt +Source35: supported-kdump-targets.txt ####################################### # These are sources for mkdumpramfs @@ -50,7 +51,6 @@ Source34: crashkernel-howto.txt 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 Source106: dracut-kdump-capture.service Source107: dracut-kdump-emergency.target @@ -68,9 +68,9 @@ Requires: dracut >= 050 Requires: dracut-network >= 050 Requires: dracut-squash >= 050 Requires: ethtool -Requires: grubby +Recommends: grubby BuildRequires: make -BuildRequires: zlib-devel elfutils-devel glib2-devel bzip2-devel ncurses-devel bison flex lzo-devel snappy-devel +BuildRequires: zlib-devel elfutils-devel glib2-devel bzip2-devel ncurses-devel bison flex lzo-devel snappy-devel libzstd-devel BuildRequires: pkgconfig intltool gettext BuildRequires: systemd-units BuildRequires: automake autoconf libtool @@ -107,8 +107,6 @@ Requires: systemd-udev%{?_isa} # Patches 601 onward are generic patches # Patch601: ./kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch -Patch602: ./kexec-tools-2.0.22-makedumpfile-Increase-SECTION_MAP_LAST_BIT-to-5.patch -Patch603: ./kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch %description kexec-tools provides /sbin/kexec binary that facilitates a new @@ -125,8 +123,6 @@ tar -z -x -v -f %{SOURCE9} tar -z -x -v -f %{SOURCE19} %patch601 -p1 -%patch602 -p1 -%patch603 -p1 %ifarch ppc %define archdef ARCH=ppc @@ -152,11 +148,12 @@ cp %{SOURCE21} . cp %{SOURCE26} . cp %{SOURCE27} . cp %{SOURCE34} . +cp %{SOURCE35} . make %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 make -C eppic-%{eppic_ver}/libeppic -make -C makedumpfile-%{mkdf_ver} LINKTYPE=dynamic USELZO=on USESNAPPY=on +make -C makedumpfile-%{mkdf_ver} LINKTYPE=dynamic USELZO=on USESNAPPY=on USEZSTD=on make -C makedumpfile-%{mkdf_ver} LDFLAGS="$LDFLAGS -I../eppic-%{eppic_ver}/libeppic -L../eppic-%{eppic_ver}/libeppic" eppic_makedumpfile.so %endif @@ -234,7 +231,6 @@ mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpba cp %{SOURCE100} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE100}} cp %{SOURCE101} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE101}} cp %{SOURCE102} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE102}} -cp %{SOURCE103} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE103}} cp %{SOURCE104} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE104}} cp %{SOURCE106} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE106}} cp %{SOURCE107} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE107}} @@ -374,12 +370,86 @@ done %doc kdump-in-cluster-environment.txt %doc live-image-kdump-howto.txt %doc crashkernel-howto.txt +%doc supported-kdump-targets.txt %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 %{_libdir}/eppic_makedumpfile.so /usr/share/makedumpfile/ %endif %changelog +* Thu Nov 11 2021 Tao Liu - 2.0.23-1 +- Enable zstd compression for makedumpfile in kexec-tools.spec +- Update makedumpfile to 1.7.0 + +* Wed Nov 10 2021 Tao Liu - 2.0.22-16 +- fix broken extra_bins when installing multiple binaries +- mkdumprd: drop mountaddr/mountproto nfs mount options +- 92-crashkernel.install: fix exit code +- dracut-early-kdump.sh: make it POSIX compatible +- Add header comment for POSIX compliant scripts +- mkdumprd: allow using dash +- kdump-logger.sh: make it POSIX compatible +- kdump-lib.sh: reformat with shfmt +- kdump-lib.sh: declare and assign separately +- kdump-lib.sh: fix variable quoting issue +- Remove trace_buf_size and trace_event from the kernel bootparameters of the kdump kernel +- kdump-lib.sh: fix a few ambiguous or redundant code +- kdump-lib.sh: fix arithmetic operation syntax +- kdump-lib.sh: remove useless echo and cat +- kdump-lib.sh: rework nmcli related functions +- kdump-lib.sh: replace '[ ]' with '[[ ]]' and get rid of legacy `` +- kdump-lib-initramfs.sh: make it POSIX compatible +- dracut-kdump.sh: reformat with shfmt +- dracut-kdump.sh: make it POSIX compatible +- dracut-kdump.sh: POSIX doesn't support pipefail +- dracut-kdump.sh: Use stat instead of ls to get vmcore size +- dracut-kdump.sh: simplify dump_ssh +- dracut-kdump.sh: remove add_dump_code +- dracut-kdump.sh: don't put KDUMP_SCRIPT_DIR in PATH +- kdump-lib-initramfs.sh: move dump related functions to kdump.sh +- Merge kdump-error-handler.sh into kdump.sh +- kdump-lib-initramfs.sh: prepare to be a POSIX compatible lib +- bash scripts: reformat with shfmt +- bash scripts: declare and assign separately +- bash scripts: fix redundant exit code check +- bash scripts: fix variable quoting issue +- Don't use die in dracut-module-setup.sh +- bash scripts: replace '[ ]' with '[[ ]]' for bash scripts +- mkdumprd: display the absolute path of dump location in the check_user_configured_target() +- Don't iterate the whole /sys/devices just to find drm device +- mkdumprd: prompt the user to install nfs-utils when mounting NFS fs failed +- bash scripts: use $(...) notation instead of legacy `...` +- bash scripts: always use "read -r" +- bash scripts: get rid of unnecessary sed calls +- bash scripts: get rid of expr and let +- bash scripts: remove useless cat +- dracut-module-setup.sh: remove surrounding $() for subshell +- dracut-module-setup.sh: make iscsi check fail early if cd failed +- dracut-module-setup.sh: fix a loop over ls issue +- dracut-module-setup.sh: fix a ambiguous variable reference +- dracut-module-setup.sh: use "*" to expend array as string +- dracut-module-setup.sh: fix _bondoptions wrong references +- dracut-module-setup.sh: remove an unused variable +- dracut-module-setup.sh: rework kdump_get_ip_route_field +- mkfadumprd: make _dracut_isolate_args an array +- mkdumprd: use array to store ssh arguments in mkdir_save_path_ssh +- mkdumprd: remove an awk call in get_fs_size +- mkdumprd: fix multiple issues with get_ssh_size +- mkdumprd: remove some redundant echo +- mkdumprd: make dracut_args an array again +- mkdumprd: use kdump_get_conf_val to read config values +- kdumpctl: refine grep usage +- kdumpctl: fix fragile loops over find output +- kdumpctl: use kdump_get_conf_val to read config values +- kdump-lib.sh: use kdump_get_conf_val to read config values +- kdump-lib.sh: add a config value retrive helper +- kdump-lib.sh: add a config format and read helper +- Add a .editorconfig file +- Remove hard requirement on grubby + +* Wed Sep 8 2021 Tao Liu - 2.0.22-15 +- Add file supported-kdump-targets.txt to kexec-tools + * Mon Aug 09 2021 Mohan Boddu - 2.0.22-14 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags Related: rhbz#1991688