Petr Šabata f5bf49
#!/bin/bash
Petr Šabata f5bf49
KEXEC=/sbin/kexec
Petr Šabata f5bf49
Petr Šabata f5bf49
KDUMP_KERNELVER=""
Petr Šabata f5bf49
KDUMP_KERNEL=""
Petr Šabata f5bf49
KDUMP_COMMANDLINE=""
Petr Šabata f5bf49
KEXEC_ARGS=""
DistroBaker 5cac7c
KDUMP_LOG_PATH="/var/log"
Petr Šabata f5bf49
MKDUMPRD="/sbin/mkdumprd -f"
Kairui Song 96a3fc
MKFADUMPRD="/sbin/mkfadumprd"
Petr Šabata f5bf49
DRACUT_MODULES_FILE="/usr/lib/dracut/modules.txt"
Petr Šabata f5bf49
SAVE_PATH=/var/crash
Petr Šabata f5bf49
SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa"
Petr Šabata f5bf49
INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum"
Petr Šabata f5bf49
DUMP_TARGET=""
Petr Šabata f5bf49
DEFAULT_INITRD=""
Petr Šabata f5bf49
DEFAULT_INITRD_BAK=""
Petr Šabata f5bf49
KDUMP_INITRD=""
Petr Šabata f5bf49
TARGET_INITRD=""
Petr Šabata f5bf49
FADUMP_REGISTER_SYS_NODE="/sys/kernel/fadump_registered"
Petr Šabata f5bf49
#kdump shall be the default dump mode
Petr Šabata f5bf49
DEFAULT_DUMP_MODE="kdump"
Petr Šabata f5bf49
image_time=0
Petr Šabata f5bf49
DistroBaker 5cac7c
standard_kexec_args="-d -p"
Petr Šabata f5bf49
Petr Šabata f5bf49
# Some default values in case /etc/sysconfig/kdump doesn't include
Petr Šabata f5bf49
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug"
Petr Šabata f5bf49
dcb59c
if [[ -f /etc/sysconfig/kdump ]]; then
Petr Šabata f5bf49
	. /etc/sysconfig/kdump
Petr Šabata f5bf49
fi
Petr Šabata f5bf49
DistroBaker 5cac7c
[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
DistroBaker 5cac7c
. $dracutbasedir/dracut-functions.sh
DistroBaker 5cac7c
. /lib/kdump/kdump-lib.sh
DistroBaker 624a64
. /lib/kdump/kdump-logger.sh
DistroBaker 5cac7c
DistroBaker 5cac7c
#initiate the kdump logger
f6d6b6
if ! dlog_init; then
DistroBaker 5cac7c
	echo "failed to initiate the kdump logger."
DistroBaker 5cac7c
	exit 1
DistroBaker 5cac7c
fi
DistroBaker 5cac7c
Petr Šabata f5bf49
single_instance_lock()
Petr Šabata f5bf49
{
Coiby Xu 928c38
	local rc timeout=5 lockfile
Petr Šabata f5bf49
Coiby Xu 928c38
	if [[ -d /run/lock ]]; then
Coiby Xu 928c38
		lockfile=/run/lock/kdump
Coiby Xu 928c38
	else
Coiby Xu 928c38
		# when updating package using virt-customize, /run/lock doesn't exist
Coiby Xu 928c38
		lockfile=/tmp/kdump.lock
Coiby Xu 928c38
	fi
Coiby Xu 928c38
Coiby Xu 928c38
	if ! exec 9> $lockfile; then
DistroBaker 5cac7c
		derror "Create file lock failed"
Petr Šabata f5bf49
		exit 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	flock -n 9
Petr Šabata f5bf49
	rc=$?
Petr Šabata f5bf49
dcb59c
	while [[ $rc -ne 0 ]]; do
DistroBaker 5cac7c
		dinfo "Another app is currently holding the kdump lock; waiting for it to exit..."
Petr Šabata f5bf49
		flock -w $timeout 9
Petr Šabata f5bf49
		rc=$?
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
determine_dump_mode()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	# Check if firmware-assisted dump is enabled
Petr Šabata f5bf49
	# if yes, set the dump mode as fadump
Petr Šabata f5bf49
	if is_fadump_capable; then
DistroBaker 5cac7c
		dinfo "Dump mode is fadump"
Petr Šabata f5bf49
		DEFAULT_DUMP_MODE="fadump"
Petr Šabata f5bf49
	fi
DistroBaker 5cac7c
	ddebug "DEFAULT_DUMP_MODE=$DEFAULT_DUMP_MODE"
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
save_core()
Petr Šabata f5bf49
{
16c282
	coredir="/var/crash/$(date +"%Y-%m-%d-%H:%M")"
Petr Šabata f5bf49
bf4667
	mkdir -p "$coredir"
DistroBaker 5cac7c
	ddebug "cp --sparse=always /proc/vmcore $coredir/vmcore-incomplete"
f6d6b6
	if cp --sparse=always /proc/vmcore "$coredir/vmcore-incomplete"; then
bf4667
		mv "$coredir/vmcore-incomplete" "$coredir/vmcore"
DistroBaker 5cac7c
		dinfo "saved a vmcore to $coredir"
Petr Šabata f5bf49
	else
DistroBaker 5cac7c
		derror "failed to save a vmcore to $coredir"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	# pass the dmesg to Abrt tool if exists, in order
Petr Šabata f5bf49
	# to collect the kernel oops message.
Petr Šabata f5bf49
	# https://fedorahosted.org/abrt/
dcb59c
	if [[ -x /usr/bin/dumpoops ]]; then
DistroBaker 5cac7c
		ddebug "makedumpfile --dump-dmesg $coredir/vmcore $coredir/dmesg"
b494b7
		makedumpfile --dump-dmesg "$coredir/vmcore" "$coredir/dmesg" > /dev/null 2>&1
DistroBaker 5cac7c
		ddebug "dumpoops -d $coredir/dmesg"
b494b7
		if dumpoops -d "$coredir/dmesg" > /dev/null 2>&1; then
DistroBaker 5cac7c
			dinfo "kernel oops has been collected by abrt tool"
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
rebuild_fadump_initrd()
Petr Šabata f5bf49
{
Kairui Song 96a3fc
	if ! $MKFADUMPRD "$DEFAULT_INITRD_BAK" "$TARGET_INITRD" --kver "$KDUMP_KERNELVER"; then
Kairui Song 96a3fc
		derror "mkfadumprd: failed to make fadump initrd"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_earlykdump_is_enabled()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	grep -q -w "rd.earlykdump" /proc/cmdline
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
rebuild_kdump_initrd()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
	ddebug "rebuild kdump initrd: $MKDUMPRD $TARGET_INITRD $KDUMP_KERNELVER"
f6d6b6
	if ! $MKDUMPRD "$TARGET_INITRD" "$KDUMP_KERNELVER"; then
DistroBaker 5cac7c
		derror "mkdumprd: failed to make kdump initrd"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if check_earlykdump_is_enabled; then
DistroBaker 5cac7c
		dwarn "Tips: If early kdump is enabled, also require rebuilding the system initramfs to make the changes take effect for early kdump."
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
rebuild_initrd()
Petr Šabata f5bf49
{
b494b7
	if [[ ! -w $(dirname "$TARGET_INITRD") ]]; then
bf4667
		derror "$(dirname "$TARGET_INITRD") does not have write permission. Cannot rebuild $TARGET_INITRD"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
dcb59c
	if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then
Petr Šabata f5bf49
		rebuild_fadump_initrd
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		rebuild_kdump_initrd
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
#$1: the files to be checked with IFS=' '
Petr Šabata f5bf49
check_exist()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	for file in $1; do
b494b7
		if [[ ! -e $file ]]; then
DistroBaker 5cac7c
			derror "Error: $file not found."
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
#$1: the files to be checked with IFS=' '
Petr Šabata f5bf49
check_executable()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	for file in $1; do
b494b7
		if [[ ! -x $file ]]; then
DistroBaker 5cac7c
			derror "Error: $file is not executable."
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
backup_default_initrd()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
	ddebug "backup default initrd: $DEFAULT_INITRD"
DistroBaker 5cac7c
b494b7
	if [[ ! -f $DEFAULT_INITRD ]]; then
Petr Šabata f5bf49
		return
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
dcb59c
	if [[ ! -e $DEFAULT_INITRD_BAK ]]; then
DistroBaker 5cac7c
		dinfo "Backing up $DEFAULT_INITRD before rebuild."
Petr Šabata f5bf49
		# save checksum to verify before restoring
bf4667
		sha1sum "$DEFAULT_INITRD" > "$INITRD_CHECKSUM_LOCATION"
f6d6b6
		if ! cp "$DEFAULT_INITRD" "$DEFAULT_INITRD_BAK"; then
DistroBaker 5cac7c
			dwarn "WARNING: failed to backup $DEFAULT_INITRD."
bf4667
			rm -f "$DEFAULT_INITRD_BAK"
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
restore_default_initrd()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
	ddebug "restore default initrd: $DEFAULT_INITRD"
DistroBaker 5cac7c
b494b7
	if [[ ! -f $DEFAULT_INITRD ]]; then
Petr Šabata f5bf49
		return
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	# If a backup initrd exists, we must be switching back from
Petr Šabata f5bf49
	# fadump to kdump. Restore the original default initrd.
dcb59c
	if [[ -f $DEFAULT_INITRD_BAK ]] && [[ -f $INITRD_CHECKSUM_LOCATION ]]; then
Petr Šabata f5bf49
		# verify checksum before restoring
e07098
		backup_checksum=$(sha1sum "$DEFAULT_INITRD_BAK" | awk '{ print $1 }')
e07098
		default_checksum=$(awk '{ print $1 }' "$INITRD_CHECKSUM_LOCATION")
b494b7
		if [[ $default_checksum != "$backup_checksum" ]]; then
DistroBaker 5cac7c
			dwarn "WARNING: checksum mismatch! Can't restore original initrd.."
Petr Šabata f5bf49
		else
Petr Šabata f5bf49
			rm -f $INITRD_CHECKSUM_LOCATION
f6d6b6
			if mv "$DEFAULT_INITRD_BAK" "$DEFAULT_INITRD"; then
DistroBaker 5cac7c
				derror "Restoring original initrd as fadump mode is disabled."
Petr Šabata f5bf49
				sync
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_config()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
	local -A _opt_rec
ba2668
	while read -r config_opt config_val; do
Petr Šabata f5bf49
		case "$config_opt" in
DistroBaker 5cac7c
		dracut_args)
DistroBaker 5cac7c
			if [[ $config_val == *--mount* ]]; then
bf4667
				if [[ $(echo "$config_val" | grep -o "\-\-mount" | wc -l) -ne 1 ]]; then
b494b7
					derror 'Multiple mount targets specified in one "dracut_args".'
DistroBaker 5cac7c
					return 1
DistroBaker 5cac7c
				fi
DistroBaker 5cac7c
				config_opt=_target
DistroBaker 5cac7c
			fi
Petr Šabata f5bf49
			;;
DistroBaker 5cac7c
		raw)
dcb59c
			if [[ -d "/proc/device-tree/ibm,opal/dump" ]]; then
DistroBaker 5cac7c
				dwarn "WARNING: Won't capture opalcore when 'raw' dump target is used."
Petr Šabata f5bf49
			fi
DistroBaker 5cac7c
			config_opt=_target
DistroBaker 5cac7c
			;;
b494b7
		ext[234] | minix | btrfs | xfs | nfs | ssh)
DistroBaker 5cac7c
			config_opt=_target
DistroBaker 5cac7c
			;;
Coiby Xu 35486b
		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 | auto_reset_crashkernel) ;;
b494b7
b494b7
		net | options | link_delay | disk_timeout | debug_mem_level | blacklist)
DistroBaker 5cac7c
			derror "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives."
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
			;;
ba2668
		'')
ba2668
			continue
ba2668
			;;
Petr Šabata f5bf49
		*)
DistroBaker 5cac7c
			derror "Invalid kdump config option $config_opt"
DistroBaker 5cac7c
			return 1
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		esac
DistroBaker 5cac7c
b494b7
		if [[ -z $config_val ]]; then
ba2668
			derror "Invalid kdump config value for option '$config_opt'"
ba2668
			return 1
ba2668
		fi
ba2668
b494b7
		if [[ -n ${_opt_rec[$config_opt]} ]]; then
dcb59c
			if [[ $config_opt == _target ]]; then
DistroBaker 5cac7c
				derror "More than one dump targets specified"
DistroBaker 5cac7c
			else
DistroBaker 5cac7c
				derror "Duplicated kdump config value of option $config_opt"
DistroBaker 5cac7c
			fi
DistroBaker 5cac7c
			return 1
DistroBaker 5cac7c
		fi
DistroBaker 5cac7c
		_opt_rec[$config_opt]="$config_val"
67b8dd
	done <<< "$(kdump_read_conf)"
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_failure_action_config || return 1
Petr Šabata f5bf49
	check_final_action_config || return 1
Petr Šabata f5bf49
	check_fence_kdump_config || return 1
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
# get_pcs_cluster_modified_files <image timestamp>
Petr Šabata f5bf49
# return list of modified file for fence_kdump modified in Pacemaker cluster
Petr Šabata f5bf49
get_pcs_cluster_modified_files()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local time_stamp
Petr Šabata f5bf49
	local modified_files
Petr Šabata f5bf49
Petr Šabata f5bf49
	is_generic_fence_kdump && return 1
Petr Šabata f5bf49
	is_pcs_fence_kdump || return 1
Petr Šabata f5bf49
16c282
	time_stamp=$(pcs cluster cib | xmllint --xpath 'string(/cib/@cib-last-written)' - | xargs -0 date +%s --date)
Petr Šabata f5bf49
dcb59c
	if [[ -n $time_stamp ]] && [[ $time_stamp -gt $image_time ]]; then
Petr Šabata f5bf49
		modified_files="cluster-cib"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
dcb59c
	if [[ -f $FENCE_KDUMP_CONFIG_FILE ]]; then
bf4667
		time_stamp=$(stat -c "%Y" "$FENCE_KDUMP_CONFIG_FILE")
b494b7
		if [[ $time_stamp -gt $image_time ]]; then
Petr Šabata f5bf49
			modified_files="$modified_files $FENCE_KDUMP_CONFIG_FILE"
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
bf4667
	echo "$modified_files"
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
setup_initrd()
Petr Šabata f5bf49
{
f6d6b6
	if ! prepare_kdump_bootinfo; then
DistroBaker 5cac7c
		derror "failed to prepare for kdump bootinfo."
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
bf4667
	DEFAULT_INITRD_BAK="$KDUMP_BOOTDIR/.$(basename "$DEFAULT_INITRD").default"
dcb59c
	if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then
Petr Šabata f5bf49
		TARGET_INITRD="$DEFAULT_INITRD"
Petr Šabata f5bf49
Petr Šabata f5bf49
		# backup initrd for reference before replacing it
Petr Šabata f5bf49
		# with fadump aware initrd
Petr Šabata f5bf49
		backup_default_initrd
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		TARGET_INITRD="$KDUMP_INITRD"
Petr Šabata f5bf49
Petr Šabata f5bf49
		# check if a backup of default initrd exists. If yes,
Petr Šabata f5bf49
		# it signifies a switch from fadump mode. So, restore
Petr Šabata f5bf49
		# the backed up default initrd.
Petr Šabata f5bf49
		restore_default_initrd
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_files_modified()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local modified_files=""
Petr Šabata f5bf49
Petr Šabata f5bf49
	#also rebuild when Pacemaker cluster conf is changed and fence kdump is enabled.
Petr Šabata f5bf49
	modified_files=$(get_pcs_cluster_modified_files)
Petr Šabata f5bf49
6afe4e
	EXTRA_BINS=$(kdump_get_conf_val kdump_post)
6afe4e
	CHECK_FILES=$(kdump_get_conf_val kdump_pre)
Petr Šabata f5bf49
	HOOKS="/etc/kdump/post.d/ /etc/kdump/pre.d/"
dcb59c
	if [[ -d /etc/kdump/post.d ]]; then
Petr Šabata f5bf49
		for file in /etc/kdump/post.d/*; do
b494b7
			if [[ -x $file ]]; then
Petr Šabata f5bf49
				POST_FILES="$POST_FILES $file"
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		done
Petr Šabata f5bf49
	fi
dcb59c
	if [[ -d /etc/kdump/pre.d ]]; then
Petr Šabata f5bf49
		for file in /etc/kdump/pre.d/*; do
b494b7
			if [[ -x $file ]]; then
Petr Šabata f5bf49
				PRE_FILES="$PRE_FILES $file"
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		done
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
	HOOKS="$HOOKS $POST_FILES $PRE_FILES"
6afe4e
	CORE_COLLECTOR=$(kdump_get_conf_val core_collector | awk '{print $1}')
bf4667
	CORE_COLLECTOR=$(type -P "$CORE_COLLECTOR")
Petr Šabata f5bf49
	# POST_FILES and PRE_FILES are already checked against executable, need not to check again.
Petr Šabata f5bf49
	EXTRA_BINS="$EXTRA_BINS $CHECK_FILES"
6afe4e
	CHECK_FILES=$(kdump_get_conf_val extra_bins)
Petr Šabata f5bf49
	EXTRA_BINS="$EXTRA_BINS $CHECK_FILES"
Petr Šabata f5bf49
	files="$KDUMP_CONFIG_FILE $KDUMP_KERNEL $EXTRA_BINS $CORE_COLLECTOR"
Petr Šabata f5bf49
	[[ -e /etc/fstab ]] && files="$files /etc/fstab"
Petr Šabata f5bf49
Petr Šabata f5bf49
	# Check for any updated extra module
6afe4e
	EXTRA_MODULES="$(kdump_get_conf_val extra_modules)"
b494b7
	if [[ -n $EXTRA_MODULES ]]; then
dcb59c
		if [[ -e /lib/modules/$KDUMP_KERNELVER/modules.dep ]]; then
Petr Šabata f5bf49
			files="$files /lib/modules/$KDUMP_KERNELVER/modules.dep"
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
		for _module in $EXTRA_MODULES; do
b494b7
			if _module_file="$(modinfo --set-version "$KDUMP_KERNELVER" --filename "$_module" 2> /dev/null)"; then
Petr Šabata f5bf49
				files="$files $_module_file"
bf4667
				for _dep_modules in $(modinfo -F depends "$_module" | tr ',' ' '); do
b494b7
					files="$files $(modinfo --set-version "$KDUMP_KERNELVER" --filename "$_dep_modules" 2> /dev/null)"
Petr Šabata f5bf49
				done
Petr Šabata f5bf49
			else
Petr Šabata f5bf49
				# If it's not a module nor builtin, give an error
b494b7
				if ! (modprobe --set-version "$KDUMP_KERNELVER" --dry-run "$_module" &> /dev/null); then
DistroBaker 5cac7c
					dwarn "Module $_module not found"
Petr Šabata f5bf49
				fi
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		done
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	# HOOKS is mandatory and need to check the modification time
Petr Šabata f5bf49
	files="$files $HOOKS"
f6d6b6
	check_exist "$files" && check_executable "$EXTRA_BINS" || return 2
Petr Šabata f5bf49
Petr Šabata f5bf49
	for file in $files; do
b494b7
		if [[ -e $file ]]; then
bf4667
			time_stamp=$(stat -c "%Y" "$file")
b494b7
			if [[ $time_stamp -gt $image_time ]]; then
Petr Šabata f5bf49
				modified_files="$modified_files $file"
Petr Šabata f5bf49
			fi
b494b7
			if [[ -L $file ]]; then
bf4667
				file=$(readlink -m "$file")
bf4667
				time_stamp=$(stat -c "%Y" "$file")
b494b7
				if [[ $time_stamp -gt $image_time ]]; then
Petr Šabata f5bf49
					modified_files="$modified_files $file"
Petr Šabata f5bf49
				fi
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		else
DistroBaker 5cac7c
			dwarn "$file doesn't exist"
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
b494b7
	if [[ -n $modified_files ]]; then
DistroBaker 5cac7c
		dinfo "Detected change(s) in the following file(s): $modified_files"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
DistroBaker a10140
check_drivers_modified()
Petr Šabata f5bf49
{
DistroBaker a10140
	local _target _new_drivers _old_drivers _module_name _module_filename
Petr Šabata f5bf49
DistroBaker a10140
	# If it's dump target is on block device, detect the block driver
DistroBaker a10140
	_target=$(get_block_dump_target)
b494b7
	if [[ -n $_target ]]; then
b494b7
		_record_block_drivers()
b494b7
		{
DistroBaker a10140
			local _drivers
DistroBaker a10140
			_drivers=$(udevadm info -a "/dev/block/$1" | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p')
DistroBaker a10140
			for _driver in $_drivers; do
DistroBaker a10140
				if ! [[ " $_new_drivers " == *" $_driver "* ]]; then
DistroBaker a10140
					_new_drivers="$_new_drivers $_driver"
DistroBaker a10140
				fi
DistroBaker a10140
			done
Petr Šabata f5bf49
DistroBaker a10140
			ddebug "MAJ:MIN=$1 drivers='$_drivers'"
DistroBaker a10140
		}
DistroBaker a10140
		check_block_and_slaves_all _record_block_drivers "$(get_maj_min "$_target")"
DistroBaker a10140
	fi
DistroBaker 5cac7c
DistroBaker a10140
	# Include watchdog drivers if watchdog module is not omitted
DistroBaker a10140
	is_dracut_mod_omitted watchdog || _new_drivers+=" $(get_watchdog_drvs)"
b494b7
	[[ -z $_new_drivers ]] && return 0
Kairui Song 8e51eb
Kairui Song 8e51eb
	if is_fadump_capable; then
Kairui Song 8e51eb
		_old_drivers="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/fadump-kernel-modules.txt | tr '\n' ' ')"
Kairui Song 8e51eb
	else
Kairui Song 8e51eb
		_old_drivers="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/hostonly-kernel-modules.txt | tr '\n' ' ')"
Kairui Song 8e51eb
	fi
Petr Šabata f5bf49
DistroBaker a10140
	ddebug "Modules required for kdump: '$_new_drivers'"
DistroBaker a10140
	ddebug "Modules included in old initramfs: '$_old_drivers'"
DistroBaker a10140
	for _driver in $_new_drivers; do
Petr Šabata f5bf49
		# Skip deprecated/invalid driver name or built-in module
b494b7
		_module_name=$(modinfo --set-version "$KDUMP_KERNELVER" -F name "$_driver" 2> /dev/null)
b494b7
		_module_filename=$(modinfo --set-version "$KDUMP_KERNELVER" -n "$_driver" 2> /dev/null)
b494b7
		if [[ -z $_module_name ]] || [[ -z $_module_filename ]] || [[ $_module_filename == *"(builtin)"* ]]; then
Petr Šabata f5bf49
			continue
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
		if ! [[ " $_old_drivers " == *" $_module_name "* ]]; then
DistroBaker 5cac7c
			dinfo "Detected change in block device driver, new loaded module: $_module_name"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
DistroBaker a10140
}
Petr Šabata f5bf49
DistroBaker a10140
check_fs_modified()
DistroBaker a10140
{
DistroBaker a10140
	local _old_dev _old_mntpoint _old_fstype
DistroBaker a10140
	local _new_dev _new_mntpoint _new_fstype
DistroBaker a10140
	local _target _dracut_args
DistroBaker a10140
DistroBaker a10140
	# No need to check in case of mount target specified via "dracut_args".
DistroBaker a10140
	if is_mount_in_dracut_args; then
DistroBaker a10140
		return 0
DistroBaker a10140
	fi
DistroBaker a10140
DistroBaker a10140
	# No need to check in case of raw target.
DistroBaker a10140
	# Currently we do not check also if ssh/nfs target is specified
DistroBaker a10140
	if is_ssh_dump_target || is_nfs_dump_target || is_raw_dump_target; then
DistroBaker a10140
		return 0
DistroBaker a10140
	fi
DistroBaker a10140
DistroBaker a10140
	_target=$(get_block_dump_target)
bf4667
	_new_fstype=$(get_fs_type_from_target "$_target")
b494b7
	if [[ -z $_target ]] || [[ -z $_new_fstype ]]; then
DistroBaker a10140
		derror "Dump target is invalid"
DistroBaker a10140
		return 2
DistroBaker a10140
	fi
DistroBaker a10140
DistroBaker a10140
	ddebug "_target=$_target _new_fstype=$_new_fstype"
bf4667
	_new_dev=$(kdump_get_persistent_dev "$_target")
b494b7
	if [[ -z $_new_dev ]]; then
DistroBaker a10140
		perror "Get persistent device name failed"
DistroBaker a10140
		return 2
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
bf4667
	_new_mntpoint="$(get_kdump_mntpoint_from_target "$_target")"
bf4667
	_dracut_args=$(lsinitrd "$TARGET_INITRD" -f usr/lib/dracut/build-parameter.txt)
b494b7
	if [[ -z $_dracut_args ]]; then
DistroBaker 5cac7c
		dwarn "Warning: No dracut arguments found in initrd"
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	# if --mount argument present then match old and new target, mount
Petr Šabata f5bf49
	# point and file system. If any of them mismatches then rebuild
f6d6b6
	if echo "$_dracut_args" | grep -q "\-\-mount"; then
bf4667
		# shellcheck disable=SC2046
bf4667
		set -- $(echo "$_dracut_args" | awk -F "--mount '" '{print $2}' | cut -d' ' -f1,2,3)
Petr Šabata f5bf49
		_old_dev=$1
Petr Šabata f5bf49
		_old_mntpoint=$2
Petr Šabata f5bf49
		_old_fstype=$3
b494b7
		[[ $_new_dev == "$_old_dev" && $_new_mntpoint == "$_old_mntpoint" && $_new_fstype == "$_old_fstype" ]] && return 0
Petr Šabata f5bf49
	# otherwise rebuild if target device is not a root device
Petr Šabata f5bf49
	else
b494b7
		[[ $_target == "$(get_root_fs_device)" ]] && return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Detected change in File System"
Petr Šabata f5bf49
	return 1
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
# returns 0 if system is not modified
Petr Šabata f5bf49
# returns 1 if system is modified
Petr Šabata f5bf49
# returns 2 if system modification is invalid
Petr Šabata f5bf49
check_system_modified()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local ret
Petr Šabata f5bf49
Petr Šabata f5bf49
	[[ -f $TARGET_INITRD ]] || return 1
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_files_modified
Petr Šabata f5bf49
	ret=$?
dcb59c
	if [[ $ret -ne 0 ]]; then
Petr Šabata f5bf49
		return $ret
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker a10140
	check_fs_modified
Petr Šabata f5bf49
	ret=$?
dcb59c
	if [[ $ret -ne 0 ]]; then
Petr Šabata f5bf49
		return $ret
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker a10140
	check_drivers_modified
DistroBaker a10140
	ret=$?
dcb59c
	if [[ $ret -ne 0 ]]; then
DistroBaker a10140
		return $ret
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_rebuild()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local capture_capable_initrd="1"
6afe4e
	local force_rebuild force_no_rebuild
Petr Šabata f5bf49
	local ret system_modified="0"
Petr Šabata f5bf49
f6d6b6
	setup_initrd || return 1
Petr Šabata f5bf49
6afe4e
	force_no_rebuild=$(kdump_get_conf_val force_no_rebuild)
6afe4e
	force_no_rebuild=${force_no_rebuild:-0}
b494b7
	if [[ $force_no_rebuild != "0" ]] && [[ $force_no_rebuild != "1" ]]; then
6afe4e
		derror "Error: force_no_rebuild value is invalid"
6afe4e
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
6afe4e
	force_rebuild=$(kdump_get_conf_val force_rebuild)
6afe4e
	force_rebuild=${force_rebuild:-0}
b494b7
	if [[ $force_rebuild != "0" ]] && [[ $force_rebuild != "1" ]]; then
6afe4e
		derror "Error: force_rebuild value is invalid"
6afe4e
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
b494b7
	if [[ $force_no_rebuild == "1" && $force_rebuild == "1" ]]; then
DistroBaker 5cac7c
		derror "Error: force_rebuild and force_no_rebuild are enabled simultaneously in kdump.conf"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	# Will not rebuild kdump initrd
b494b7
	if [[ $force_no_rebuild == "1" ]]; then
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	#check to see if dependent files has been modified
Petr Šabata f5bf49
	#since last build of the image file
dcb59c
	if [[ -f $TARGET_INITRD ]]; then
b494b7
		image_time=$(stat -c "%Y" "$TARGET_INITRD" 2> /dev/null)
Petr Šabata f5bf49
Petr Šabata f5bf49
		#in case of fadump mode, check whether the default/target
Petr Šabata f5bf49
		#initrd is already built with dump capture capability
b494b7
		if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then
e35e40
			capture_capable_initrd=$(lsinitrd -f $DRACUT_MODULES_FILE "$TARGET_INITRD" | grep -c -e ^kdumpbase$ -e ^zz-fadumpinit$)
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_system_modified
Petr Šabata f5bf49
	ret=$?
dcb59c
	if [[ $ret -eq 2 ]]; then
Petr Šabata f5bf49
		return 1
b494b7
	elif [[ $ret -eq 1 ]]; then
Petr Šabata f5bf49
		system_modified="1"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
dcb59c
	if [[ $image_time -eq 0 ]]; then
DistroBaker 5cac7c
		dinfo "No kdump initial ramdisk found."
b494b7
	elif [[ $capture_capable_initrd == "0" ]]; then
DistroBaker 5cac7c
		dinfo "Rebuild $TARGET_INITRD with dump capture support"
b494b7
	elif [[ $force_rebuild != "0" ]]; then
DistroBaker 5cac7c
		dinfo "Force rebuild $TARGET_INITRD"
b494b7
	elif [[ $system_modified != "0" ]]; then
Petr Šabata f5bf49
		:
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Rebuilding $TARGET_INITRD"
Petr Šabata f5bf49
	rebuild_initrd
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Coiby Xu eb95f9
# On ppc64le LPARs, the keys trusted by firmware do not end up in
Coiby Xu eb95f9
# .builtin_trusted_keys. So instead, add the key to the .ima keyring
Coiby Xu eb95f9
function load_kdump_kernel_key()
Coiby Xu eb95f9
{
Coiby Xu eb95f9
	# this is only called inside is_secure_boot_enforced,
Coiby Xu eb95f9
	# no need to retest
Coiby Xu eb95f9
Coiby Xu eb95f9
        # this is only required if DT /ibm,secure-boot is a file.
Coiby Xu eb95f9
        # if it is a dir, we are on OpenPower and don't need this.
Coiby Xu eb95f9
        if ! [[ -f /proc/device-tree/ibm,secure-boot ]]; then
Coiby Xu eb95f9
                return
Coiby Xu eb95f9
        fi
Coiby Xu eb95f9
Coiby Xu eb95f9
	KDUMP_KEY_ID=$(keyctl padd asymmetric kernelkey-$RANDOM %:.ima < "/usr/share/doc/kernel-keys/$KDUMP_KERNELVER/kernel-signing-ppc.cer")
Coiby Xu eb95f9
}
Coiby Xu eb95f9
Coiby Xu eb95f9
# remove a previously loaded key. There's no real security implication
Coiby Xu eb95f9
# to leaving it around, we choose to do this because it makes it easier
Coiby Xu eb95f9
# to be idempotent and so as to reduce the potential for confusion.
Coiby Xu eb95f9
function remove_kdump_kernel_key()
Coiby Xu eb95f9
{
Coiby Xu eb95f9
	if [[ -z $KDUMP_KEY_ID ]]; then
Coiby Xu eb95f9
		return
Coiby Xu eb95f9
	fi
Coiby Xu eb95f9
Coiby Xu eb95f9
	keyctl unlink "$KDUMP_KEY_ID" %:.ima
Coiby Xu eb95f9
}
Coiby Xu eb95f9
Petr Šabata f5bf49
# Load the kdump kernel specified in /etc/sysconfig/kdump
Petr Šabata f5bf49
# If none is specified, try to load a kdump kernel with the same version
Petr Šabata f5bf49
# as the currently running kernel.
Petr Šabata f5bf49
load_kdump()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
	local ret
DistroBaker 5cac7c
Petr Šabata f5bf49
	KEXEC_ARGS=$(prepare_kexec_args "${KEXEC_ARGS}")
Petr Šabata f5bf49
	KDUMP_COMMANDLINE=$(prepare_cmdline "${KDUMP_COMMANDLINE}" "${KDUMP_COMMANDLINE_REMOVE}" "${KDUMP_COMMANDLINE_APPEND}")
Petr Šabata f5bf49
Petr Šabata f5bf49
	# For secureboot enabled machines, use new kexec file based syscall.
Petr Šabata f5bf49
	# Old syscall will always fail as it does not have capability to
Petr Šabata f5bf49
	# to kernel signature verification.
Petr Šabata f5bf49
	if is_secure_boot_enforced; then
DistroBaker 5cac7c
		dinfo "Secure Boot is enabled. Using kexec file based syscall."
Petr Šabata f5bf49
		KEXEC_ARGS="$KEXEC_ARGS -s"
Coiby Xu eb95f9
		load_kdump_kernel_key
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	ddebug "$KEXEC $KEXEC_ARGS $standard_kexec_args --command-line=$KDUMP_COMMANDLINE --initrd=$TARGET_INITRD $KDUMP_KERNEL"
DistroBaker 5cac7c
DistroBaker 17a515
	# The '12' represents an intermediate temporary file descriptor
DistroBaker 17a515
	# to store the standard error file descriptor '2', and later
DistroBaker 17a515
	# restore the error file descriptor with the file descriptor '12'
DistroBaker 17a515
	# and release it.
DistroBaker 5cac7c
	exec 12>&2
DistroBaker 5cac7c
	exec 2>> $KDUMP_LOG_PATH/kdump.log
Lichen Liu bd9212
	chmod 600 $KDUMP_LOG_PATH/kdump.log
DistroBaker 5cac7c
	PS4='+ $(date "+%Y-%m-%d %H:%M:%S") ${BASH_SOURCE}@${LINENO}: '
DistroBaker 5cac7c
	set -x
DistroBaker 5cac7c
bf4667
	# shellcheck disable=SC2086
Petr Šabata f5bf49
	$KEXEC $KEXEC_ARGS $standard_kexec_args \
Petr Šabata f5bf49
		--command-line="$KDUMP_COMMANDLINE" \
bf4667
		--initrd="$TARGET_INITRD" "$KDUMP_KERNEL"
DistroBaker 5cac7c
DistroBaker 5cac7c
	ret=$?
DistroBaker 5cac7c
	set +x
DistroBaker 5cac7c
	exec 2>&12 12>&-
DistroBaker 5cac7c
Coiby Xu eb95f9
	remove_kdump_kernel_key
Coiby Xu eb95f9
dcb59c
	if [[ $ret == 0 ]]; then
DistroBaker 5cac7c
		dinfo "kexec: loaded kdump kernel"
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	else
DistroBaker 5cac7c
		derror "kexec: failed to load kdump kernel"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_ssh_config()
Petr Šabata f5bf49
{
633084
	local SSH_TARGET
633084
67611b
	while read -r config_opt config_val; do
Petr Šabata f5bf49
		case "$config_opt" in
Petr Šabata f5bf49
		sshkey)
Petr Šabata f5bf49
			# remove inline comments after the end of a directive.
b494b7
			if [[ -f $config_val ]]; then
Petr Šabata f5bf49
				# canonicalize the path
bf4667
				SSH_KEY_LOCATION=$(/usr/bin/readlink -m "$config_val")
Petr Šabata f5bf49
			else
DistroBaker 5cac7c
				dwarn "WARNING: '$config_val' doesn't exist, using default value '$SSH_KEY_LOCATION'"
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		path)
Petr Šabata f5bf49
			SAVE_PATH=$config_val
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		ssh)
Petr Šabata f5bf49
			DUMP_TARGET=$config_val
Petr Šabata f5bf49
			;;
b494b7
		*) ;;
b494b7
Petr Šabata f5bf49
		esac
67b8dd
	done <<< "$(kdump_read_conf)"
Petr Šabata f5bf49
Petr Šabata f5bf49
	#make sure they've configured kdump.conf for ssh dumps
633084
	SSH_TARGET=$(echo -n "$DUMP_TARGET" | sed -n '/.*@/p')
b494b7
	if [[ -z $SSH_TARGET ]]; then
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
# ipv6 host address may takes a long time to be ready.
Petr Šabata f5bf49
# Instead of checking against ipv6 address, we just check the network reachable
Petr Šabata f5bf49
# by the return val of 'ssh'
Petr Šabata f5bf49
check_and_wait_network_ready()
Petr Šabata f5bf49
{
633084
	local start_time
Petr Šabata f5bf49
	local warn_once=1
Petr Šabata f5bf49
	local cur
Petr Šabata f5bf49
	local diff
Petr Šabata f5bf49
	local retval
Petr Šabata f5bf49
	local errmsg
Petr Šabata f5bf49
633084
	start_time=$(date +%s)
Petr Šabata f5bf49
	while true; do
bf4667
		errmsg=$(ssh -i "$SSH_KEY_LOCATION" -o BatchMode=yes "$DUMP_TARGET" mkdir -p "$SAVE_PATH" 2>&1)
Petr Šabata f5bf49
		retval=$?
Petr Šabata f5bf49
Petr Šabata f5bf49
		# ssh exits with the exit status of the remote command or with 255 if an error occurred
dcb59c
		if [[ $retval -eq 0 ]]; then
Petr Šabata f5bf49
			return 0
dcb59c
		elif [[ $retval -ne 255 ]]; then
DistroBaker 5cac7c
			derror "Could not create $DUMP_TARGET:$SAVE_PATH, you should check the privilege on server side"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
Petr Šabata f5bf49
		# if server removes the authorized_keys or, no /root/.ssh/kdump_id_rsa
DistroBaker 5cac7c
		ddebug "$errmsg"
f6d6b6
		if echo "$errmsg" | grep -q "Permission denied\|No such file or directory\|Host key verification failed"; then
DistroBaker 5cac7c
			derror "Could not create $DUMP_TARGET:$SAVE_PATH, you probably need to run \"kdumpctl propagate\""
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
dcb59c
		if [[ $warn_once -eq 1 ]]; then
DistroBaker 5cac7c
			dwarn "Network dump target is not usable, waiting for it to be ready..."
Petr Šabata f5bf49
			warn_once=0
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
Petr Šabata f5bf49
		cur=$(date +%s)
480de7
		diff=$((cur - start_time))
Petr Šabata f5bf49
		# 60s time out
dcb59c
		if [[ $diff -gt 180 ]]; then
b494b7
			break
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
		sleep 1
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Could not create $DUMP_TARGET:$SAVE_PATH, ipaddr is not ready yet. You should check network connection"
Petr Šabata f5bf49
	return 1
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_ssh_target()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	check_and_wait_network_ready
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
propagate_ssh_key()
Petr Šabata f5bf49
{
f6d6b6
	if ! check_ssh_config; then
DistroBaker 5cac7c
		derror "No ssh config specified in $KDUMP_CONFIG_FILE.  Can't propagate"
Petr Šabata f5bf49
		exit 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	local KEYFILE=$SSH_KEY_LOCATION
Petr Šabata f5bf49
	local errmsg="Failed to propagate ssh key"
Petr Šabata f5bf49
Petr Šabata f5bf49
	#Check to see if we already created key, if not, create it.
dcb59c
	if [[ -f $KEYFILE ]]; then
DistroBaker 5cac7c
		dinfo "Using existing keys..."
Petr Šabata f5bf49
	else
DistroBaker 5cac7c
		dinfo "Generating new ssh keys... "
bf4667
		/usr/bin/ssh-keygen -t rsa -f "$KEYFILE" -N "" 2>&1 > /dev/null
DistroBaker 5cac7c
		dinfo "done."
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	#now find the target ssh user and server to contact.
bf4667
	SSH_USER=$(echo "$DUMP_TARGET" | cut -d@ -f1)
bf4667
	SSH_SERVER=$(echo "$DUMP_TARGET" | sed -e's/\(.*@\)\(.*$\)/\2/')
Petr Šabata f5bf49
Petr Šabata f5bf49
	#now send the found key to the found server
bf4667
	ssh-copy-id -i "$KEYFILE" "$SSH_USER@$SSH_SERVER"
Petr Šabata f5bf49
	RET=$?
dcb59c
	if [[ $RET == 0 ]]; then
DistroBaker 5cac7c
		dinfo "$KEYFILE has been added to ~$SSH_USER/.ssh/authorized_keys on $SSH_SERVER"
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	else
DistroBaker 5cac7c
		derror "$errmsg, $KEYFILE failed in transfer to $SSH_SERVER"
Petr Šabata f5bf49
		exit 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
show_reserved_mem()
Petr Šabata f5bf49
{
b494b7
	local mem
b494b7
	local mem_mb
e07098
b494b7
	mem=$(< /sys/kernel/kexec_crash_size)
b494b7
	mem_mb=$((mem / 1024 / 1024))
Petr Šabata f5bf49
b494b7
	dinfo "Reserved ${mem_mb}MB memory for crash kernel"
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_current_fadump_status()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	# Check if firmware-assisted dump has been registered.
b494b7
	rc=$(< $FADUMP_REGISTER_SYS_NODE)
dcb59c
	[[ $rc -eq 1 ]] && return 0
Petr Šabata f5bf49
	return 1
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_current_status()
Petr Šabata f5bf49
{
dcb59c
	if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then
Petr Šabata f5bf49
		check_current_fadump_status
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		check_current_kdump_status
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
save_raw()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local kdump_dir
Petr Šabata f5bf49
	local raw_target
Petr Šabata f5bf49
6afe4e
	raw_target=$(kdump_get_conf_val raw)
b494b7
	[[ -z $raw_target ]] && return 0
b494b7
	[[ -b $raw_target ]] || {
DistroBaker 5cac7c
		derror "raw partition $raw_target not found"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	}
bf4667
	check_fs=$(lsblk --nodeps -npo FSTYPE "$raw_target")
bf4667
	if [[ $(echo "$check_fs" | wc -w) -ne 0 ]]; then
DistroBaker 5cac7c
		dwarn "Warning: Detected '$check_fs' signature on $raw_target, data loss is expected."
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
6afe4e
	kdump_dir=$(kdump_get_conf_val path)
b494b7
	if [[ -z ${kdump_dir} ]]; then
16c282
		coredir="/var/crash/$(date +"%Y-%m-%d-%H:%M")"
Petr Šabata f5bf49
	else
16c282
		coredir="${kdump_dir}/$(date +"%Y-%m-%d-%H:%M")"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	mkdir -p "$coredir"
b494b7
	[[ -d $coredir ]] || {
DistroBaker 5cac7c
		derror "failed to create $coredir"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	}
b494b7
	if makedumpfile -R "$coredir/vmcore" < "$raw_target" > /dev/null 2>&1; then
Petr Šabata f5bf49
		# dump found
DistroBaker 5cac7c
		dinfo "Dump saved to $coredir/vmcore"
Petr Šabata f5bf49
		# wipe makedumpfile header
b494b7
		dd if=/dev/zero of="$raw_target" bs=1b count=1 2> /dev/null
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		rm -rf "$coredir"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
local_fs_dump_target()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local _target
Petr Šabata f5bf49
f6d6b6
	if _target=$(grep -E "^ext[234]|^xfs|^btrfs|^minix" /etc/kdump.conf); then
bf4667
		echo "$_target" | awk '{print $2}'
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
path_to_be_relabeled()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local _path _target _mnt="/" _rmnt
Petr Šabata f5bf49
Petr Šabata f5bf49
	if is_user_configured_dump_target; then
Petr Šabata f5bf49
		if is_mount_in_dracut_args; then
b494b7
			return
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
Petr Šabata f5bf49
		_target=$(local_fs_dump_target)
b494b7
		if [[ -n $_target ]]; then
bf4667
			_mnt=$(get_mntpoint_from_target "$_target")
Petr Šabata f5bf49
			if ! is_mounted "$_mnt"; then
Petr Šabata f5bf49
				return
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		else
Petr Šabata f5bf49
			return
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	_path=$(get_save_path)
Petr Šabata f5bf49
	# if $_path is masked by other mount, we will not relabel it.
b494b7
	_rmnt=$(df "$_mnt/$_path" 2> /dev/null | tail -1 | awk '{ print $NF }')
b494b7
	if [[ $_rmnt == "$_mnt" ]]; then
bf4667
		echo "$_mnt/$_path"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
selinux_relabel()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local _path _i _attr
Petr Šabata f5bf49
Petr Šabata f5bf49
	_path=$(path_to_be_relabeled)
b494b7
	if [[ -z $_path ]] || ! [[ -d $_path ]]; then
Petr Šabata f5bf49
		return
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
6c4381
	while IFS= read -r -d '' _i; do
b494b7
		_attr=$(getfattr -m "security.selinux" "$_i" 2> /dev/null)
b494b7
		if [[ -z $_attr ]]; then
b494b7
			restorecon "$_i"
Petr Šabata f5bf49
		fi
6c4381
	done < <(find "$_path" -print0)
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_fence_kdump_config()
Petr Šabata f5bf49
{
633084
	local hostname
633084
	local ipaddrs
633084
	local nodes
633084
633084
	hostname=$(hostname)
633084
	ipaddrs=$(hostname -I)
633084
	nodes=$(kdump_get_conf_val "fence_kdump_nodes")
Petr Šabata f5bf49
Petr Šabata f5bf49
	for node in $nodes; do
b494b7
		if [[ $node == "$hostname" ]]; then
DistroBaker 5cac7c
			derror "Option fence_kdump_nodes cannot contain $hostname"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
		# node can be ipaddr
f6d6b6
		if echo "$ipaddrs " | grep -q "$node "; then
DistroBaker 5cac7c
			derror "Option fence_kdump_nodes cannot contain $node"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_dump_feasibility()
Petr Šabata f5bf49
{
dcb59c
	if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_kdump_feasibility
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
start_fadump()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	echo 1 > $FADUMP_REGISTER_SYS_NODE
Petr Šabata f5bf49
	if ! check_current_fadump_status; then
DistroBaker 5cac7c
		derror "fadump: failed to register"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "fadump: registered successfully"
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
start_dump()
Petr Šabata f5bf49
{
dcb59c
	if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then
Petr Šabata f5bf49
		start_fadump
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		load_kdump
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_failure_action_config()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local default_option
Petr Šabata f5bf49
	local failure_action
Petr Šabata f5bf49
	local option="failure_action"
Petr Šabata f5bf49
6afe4e
	default_option=$(kdump_get_conf_val default)
6afe4e
	failure_action=$(kdump_get_conf_val failure_action)
Petr Šabata f5bf49
b494b7
	if [[ -z $failure_action ]] && [[ -z $default_option ]]; then
Petr Šabata f5bf49
		return 0
b494b7
	elif [[ -n $failure_action ]] && [[ -n $default_option ]]; then
DistroBaker 5cac7c
		derror "Cannot specify 'failure_action' and 'default' option together"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
b494b7
	if [[ -n $default_option ]]; then
Petr Šabata f5bf49
		option="default"
Petr Šabata f5bf49
		failure_action="$default_option"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	case "$failure_action" in
b494b7
	reboot | halt | poweroff | shell | dump_to_rootfs)
Petr Šabata f5bf49
		return 0
b494b7
		;;
b494b7
	*)
DistroBaker 5cac7c
		dinfo $"Usage kdump.conf: $option {reboot|halt|poweroff|shell|dump_to_rootfs}"
Petr Šabata f5bf49
		return 1
b494b7
		;;
Petr Šabata f5bf49
	esac
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_final_action_config()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local final_action
Petr Šabata f5bf49
6afe4e
	final_action=$(kdump_get_conf_val final_action)
b494b7
	if [[ -z $final_action ]]; then
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		case "$final_action" in
b494b7
		reboot | halt | poweroff)
Petr Šabata f5bf49
			return 0
b494b7
			;;
b494b7
		*)
DistroBaker 5cac7c
			dinfo $"Usage kdump.conf: final_action {reboot|halt|poweroff}"
Petr Šabata f5bf49
			return 1
b494b7
			;;
Petr Šabata f5bf49
		esac
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
start()
Petr Šabata f5bf49
{
f6d6b6
	if ! check_dump_feasibility; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
f6d6b6
	if ! check_config; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
b494b7
	if sestatus 2> /dev/null | grep -q "SELinux status.*enabled"; then
Petr Šabata f5bf49
		selinux_relabel
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
f6d6b6
	if ! save_raw; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
f6d6b6
	if check_current_status; then
DistroBaker 5cac7c
		dwarn "Kdump already running: [WARNING]"
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if check_ssh_config; then
Petr Šabata f5bf49
		if ! check_ssh_target; then
DistroBaker 5cac7c
			derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
f6d6b6
	if ! check_rebuild; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
f6d6b6
	if ! start_dump; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Starting kdump: [OK]"
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
reload()
Petr Šabata f5bf49
{
f6d6b6
	if ! check_current_status; then
DistroBaker 5cac7c
		dwarn "Kdump was not running: [WARNING]"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
dcb59c
	if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then
Petr Šabata f5bf49
		reload_fadump
Petr Šabata f5bf49
		return $?
Petr Šabata f5bf49
	else
f6d6b6
		if ! stop_kdump; then
f6d6b6
			derror "Stopping kdump: [FAILED]"
f6d6b6
			return 1
f6d6b6
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Stopping kdump: [OK]"
Petr Šabata f5bf49
f6d6b6
	if ! setup_initrd; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
f6d6b6
	if ! start_dump; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Starting kdump: [OK]"
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
stop_fadump()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	echo 0 > $FADUMP_REGISTER_SYS_NODE
Petr Šabata f5bf49
	if check_current_fadump_status; then
DistroBaker 5cac7c
		derror "fadump: failed to unregister"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "fadump: unregistered successfully"
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
stop_kdump()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	if is_secure_boot_enforced; then
Petr Šabata f5bf49
		$KEXEC -s -p -u
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		$KEXEC -p -u
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
f6d6b6
	# shellcheck disable=SC2181
dcb59c
	if [[ $? != 0 ]]; then
DistroBaker 5cac7c
		derror "kexec: failed to unload kdump kernel"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "kexec: unloaded kdump kernel"
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
reload_fadump()
Petr Šabata f5bf49
{
f6d6b6
	if echo 1 > $FADUMP_REGISTER_SYS_NODE; then
DistroBaker 5cac7c
		dinfo "fadump: re-registered successfully"
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		# FADump could fail on older kernel where re-register
Petr Šabata f5bf49
		# support is not enabled. Try stop/start from userspace
Petr Šabata f5bf49
		# to handle such scenario.
f6d6b6
		if stop_fadump; then
Petr Šabata f5bf49
			start_fadump
Petr Šabata f5bf49
			return $?
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 1
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
stop()
Petr Šabata f5bf49
{
dcb59c
	if [[ $DEFAULT_DUMP_MODE == "fadump" ]]; then
Petr Šabata f5bf49
		stop_fadump
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		stop_kdump
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
f6d6b6
	# shellcheck disable=SC2181
dcb59c
	if [[ $? != 0 ]]; then
DistroBaker 5cac7c
		derror "Stopping kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Stopping kdump: [OK]"
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
b494b7
rebuild()
b494b7
{
f6d6b6
	check_config || return 1
Petr Šabata f5bf49
Petr Šabata f5bf49
	if check_ssh_config; then
Petr Šabata f5bf49
		if ! check_ssh_target; then
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
f6d6b6
	setup_initrd || return 1
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Rebuilding $TARGET_INITRD"
Petr Šabata f5bf49
	rebuild_initrd
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
b494b7
do_estimate()
b494b7
{
Kairui Song a9fda5
	local kdump_mods
Kairui Song a9fda5
	local -A large_mods
Kairui Song a9fda5
	local baseline
Kairui Song 6cc04b
	local kernel_size mod_size initrd_size baseline_size runtime_size reserved_size estimated_size recommended_size
b494b7
	local size_mb=$((1024 * 1024))
Kairui Song a9fda5
Kairui Song a9fda5
	setup_initrd
b494b7
	if [[ ! -f $TARGET_INITRD ]]; then
Kairui Song a9fda5
		derror "kdumpctl estimate: kdump initramfs is not built yet."
Kairui Song a9fda5
		exit 1
Kairui Song a9fda5
	fi
Kairui Song a9fda5
Kairui Song a9fda5
	kdump_mods="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/hostonly-kernel-modules.txt | tr '\n' ' ')"
Kairui Song a9fda5
	baseline=$(kdump_get_arch_recommend_size)
b494b7
	if [[ ${baseline: -1} == "M" ]]; then
Kairui Song a9fda5
		baseline=${baseline%M}
b494b7
	elif [[ ${baseline: -1} == "G" ]]; then
b494b7
		baseline=$((${baseline%G} * 1024))
b494b7
	elif [[ ${baseline: -1} == "T" ]]; then
b494b7
		baseline=$((${baseline%Y} * 1048576))
Kairui Song a9fda5
	fi
Kairui Song a9fda5
Kairui Song f3db4a
	# The default pre-reserved crashkernel value
Kairui Song a9fda5
	baseline_size=$((baseline * size_mb))
Kairui Song a9fda5
	# Current reserved crashkernel size
b494b7
	reserved_size=$(< /sys/kernel/kexec_crash_size)
Kairui Song a9fda5
	# A pre-estimated value for userspace usage and kernel
Kairui Song a9fda5
	# runtime allocation, 64M should good for most cases
Kairui Song a9fda5
	runtime_size=$((64 * size_mb))
Kairui Song a9fda5
	# Kernel image size
Kairui Song a9fda5
	kernel_size=$(get_kernel_size "$KDUMP_KERNEL")
Kairui Song a9fda5
	# Kdump initramfs size
Kairui Song a9fda5
	initrd_size=$(du -b "$TARGET_INITRD" | awk '{print $1}')
Kairui Song a9fda5
	# Kernel modules static size after loaded
Kairui Song a9fda5
	mod_size=0
Kairui Song a9fda5
	while read -r _name _size _; do
b494b7
		if [[ " $kdump_mods " != *" $_name "* ]]; then
Kairui Song a9fda5
			continue
Kairui Song a9fda5
		fi
Kairui Song a9fda5
		mod_size=$((mod_size + _size))
Kairui Song a9fda5
Kairui Song a9fda5
		# Mark module with static size larger than 2M as large module
Kairui Song a9fda5
		if [[ $((_size / size_mb)) -ge 1 ]]; then
Kairui Song a9fda5
			large_mods[$_name]=$_size
Kairui Song a9fda5
		fi
Kairui Song a9fda5
	done <<< "$(< /proc/modules)"
Kairui Song a9fda5
Kairui Song a9fda5
	# Extra memory usage required for LUKS2 decryption
Kairui Song a9fda5
	crypt_size=0
Kairui Song a9fda5
	for _dev in $(get_all_kdump_crypt_dev); do
Kairui Song a9fda5
		_crypt_info=$(cryptsetup luksDump "/dev/block/$_dev")
b494b7
		[[ $(echo "$_crypt_info" | sed -n "s/^Version:\s*\(.*\)/\1/p") == "2" ]] || continue
b494b7
		for _mem in $(echo "$_crypt_info" | sed -n "s/\sMemory:\s*\(.*\)/\1/p" | sort -n); do
Kairui Song a9fda5
			crypt_size=$((crypt_size + _mem * 1024))
Kairui Song a9fda5
			break
Kairui Song a9fda5
		done
Kairui Song a9fda5
	done
Kairui Song a9fda5
	[[ $crypt_size -ne 0 ]] && echo -e "Encrypted kdump target requires extra memory, assuming using the keyslot with minimun memory requirement\n"
Kairui Song a9fda5
Kairui Song a9fda5
	estimated_size=$((kernel_size + mod_size + initrd_size + runtime_size + crypt_size))
Kairui Song a9fda5
	if [[ $baseline_size -gt $estimated_size ]]; then
Kairui Song 6cc04b
		recommended_size=$baseline_size
Kairui Song a9fda5
	else
Kairui Song 6cc04b
		recommended_size=$estimated_size
Kairui Song a9fda5
	fi
Kairui Song a9fda5
Kairui Song a9fda5
	echo "Reserved crashkernel:    $((reserved_size / size_mb))M"
Kairui Song 6cc04b
	echo "Recommended crashkernel: $((recommended_size / size_mb))M"
Kairui Song a9fda5
	echo
Kairui Song a9fda5
	echo "Kernel image size:   $((kernel_size / size_mb))M"
Kairui Song a9fda5
	echo "Kernel modules size: $((mod_size / size_mb))M"
Kairui Song a9fda5
	echo "Initramfs size:      $((initrd_size / size_mb))M"
Kairui Song a9fda5
	echo "Runtime reservation: $((runtime_size / size_mb))M"
b494b7
	[[ $crypt_size -ne 0 ]] &&
b494b7
		echo "LUKS required size:  $((crypt_size / size_mb))M"
Kairui Song a9fda5
	echo -n "Large modules:"
b494b7
	if [[ ${#large_mods[@]} -eq 0 ]]; then
Kairui Song a9fda5
		echo " <none>"
Kairui Song a9fda5
	else
Kairui Song a9fda5
		echo ""
Kairui Song a9fda5
		for _mod in "${!large_mods[@]}"; do
Kairui Song a9fda5
			echo "    $_mod: ${large_mods[$_mod]}"
Kairui Song a9fda5
		done
Kairui Song a9fda5
	fi
Kairui Song a9fda5
Kairui Song 6cc04b
	if [[ $reserved_size -lt $recommended_size ]]; then
Kairui Song 6cc04b
		echo "WARNING: Current crashkernel size is lower than recommended size $((recommended_size / size_mb))M."
Kairui Song a9fda5
	fi
Kairui Song a9fda5
}
Kairui Song a9fda5
Coiby Xu acf9f6
get_default_crashkernel()
Coiby Xu acf9f6
{
Coiby Xu acf9f6
	local _dump_mode=$1
Coiby Xu acf9f6
Coiby Xu acf9f6
	kdump_get_arch_recommend_crashkernel "$_dump_mode"
Coiby Xu acf9f6
}
Coiby Xu acf9f6
Coiby Xu 27b5ab
# Read kernel cmdline parameter for a specific kernel
Coiby Xu 27b5ab
# $1: kernel path, DEFAULT or kernel path, ALL not accepted
Coiby Xu 27b5ab
# $2: kernel cmldine parameter
Coiby Xu 27b5ab
get_grub_kernel_boot_parameter()
Coiby Xu 27b5ab
{
Coiby Xu 27b5ab
	local _kernel_path=$1 _para=$2
Coiby Xu 27b5ab
Coiby Xu 27b5ab
	[[ $_kernel_path == ALL ]] && derror "kernel_path=ALL invalid for get_grub_kernel_boot_parameter" && return 1
Coiby Xu 27b5ab
	grubby --info="$_kernel_path" | sed -En -e "/^args=.*$/{s/^.*(\s|\")${_para}=(\S*).*\"$/\2/p;q}"
Coiby Xu 27b5ab
}
Coiby Xu 27b5ab
Coiby Xu d5cf91
# get dump mode by fadump value
Coiby Xu d5cf91
# return
Coiby Xu d5cf91
#  - fadump, if fadump=on or fadump=nocma
Coiby Xu d5cf91
#  - kdump, if fadump=off or empty fadump, return kdump
Coiby Xu d5cf91
#  - error if otherwise
Coiby Xu d5cf91
get_dump_mode_by_fadump_val()
Coiby Xu d5cf91
{
Coiby Xu d5cf91
	local _fadump_val=$1
Coiby Xu d5cf91
Coiby Xu d5cf91
	if [[ -z $_fadump_val ]] || [[ $_fadump_val == off ]]; then
Coiby Xu d5cf91
		echo -n kdump
Coiby Xu d5cf91
	elif [[ $_fadump_val == on ]] || [[ $_fadump_val == nocma ]]; then
Coiby Xu d5cf91
		echo -n fadump
Coiby Xu d5cf91
	else
Coiby Xu d5cf91
		derror "invalid fadump=$_fadump_val"
Coiby Xu d5cf91
		return 1
Coiby Xu d5cf91
	fi
Coiby Xu d5cf91
}
Coiby Xu d5cf91
Coiby Xu d5cf91
# get dump mode of a specific kernel
Coiby Xu d5cf91
# based on its fadump kernel cmdline parameter
Coiby Xu d5cf91
get_dump_mode_by_kernel()
Coiby Xu d5cf91
{
Coiby Xu d5cf91
	local _kernel_path=$1 _fadump_val _dump_mode
Coiby Xu d5cf91
Coiby Xu d5cf91
	_fadump_val=$(get_grub_kernel_boot_parameter "$_kernel_path" fadump)
Coiby Xu d5cf91
	if _dump_mode=$(get_dump_mode_by_fadump_val "$_fadump_val"); then
Coiby Xu d5cf91
		echo -n "$_dump_mode"
Coiby Xu d5cf91
	else
Coiby Xu d5cf91
		derror "failed to get dump mode for kernel $_kernel_path"
Coiby Xu d5cf91
		exit
Coiby Xu d5cf91
	fi
Coiby Xu d5cf91
}
Coiby Xu d5cf91
Coiby Xu b3d9b9
_filter_grubby_kernel_str()
Coiby Xu b3d9b9
{
Coiby Xu b3d9b9
	local _grubby_kernel_str=$1
Coiby Xu b3d9b9
	echo -n "$_grubby_kernel_str" | sed -n -e 's/^kernel="\(.*\)"/\1/p'
Coiby Xu b3d9b9
}
Coiby Xu b3d9b9
Coiby Xu b3d9b9
_find_kernel_path_by_release()
Coiby Xu b3d9b9
{
Coiby Xu b3d9b9
	local _release="$1" _grubby_kernel_str _kernel_path
Coiby Xu b3d9b9
	_grubby_kernel_str=$(grubby --info ALL | grep "^kernel=.*$_release")
Coiby Xu b3d9b9
	_kernel_path=$(_filter_grubby_kernel_str "$_grubby_kernel_str")
Coiby Xu b3d9b9
	if [[ -z $_kernel_path ]]; then
Coiby Xu b3d9b9
		derror "kernel $_release doesn't exist"
Coiby Xu b3d9b9
		return 1
Coiby Xu b3d9b9
	fi
Coiby Xu b3d9b9
	echo -n "$_kernel_path"
Coiby Xu b3d9b9
}
Coiby Xu b3d9b9
Coiby Xu b3d9b9
_get_current_running_kernel_path()
Coiby Xu b3d9b9
{
Coiby Xu b3d9b9
	local _release _path
Coiby Xu b3d9b9
Coiby Xu b3d9b9
	_release=$(uname -r)
Coiby Xu b3d9b9
	if _path=$(_find_kernel_path_by_release "$_release"); then
Coiby Xu b3d9b9
		echo -n "$_path"
Coiby Xu b3d9b9
	else
Coiby Xu b3d9b9
		return 1
Coiby Xu b3d9b9
	fi
Coiby Xu b3d9b9
}
Coiby Xu b3d9b9
Coiby Xu 3f8281
_update_grub()
b494b7
{
Coiby Xu 3f8281
	local _kernel_path=$1 _crashkernel=$2 _dump_mode=$3 _fadump_val=$4
Kairui Song a0fe51
Coiby Xu 3f8281
	if is_atomic; then
Coiby Xu 3f8281
		if rpm-ostree kargs | grep -q "crashkernel="; then
Coiby Xu 3f8281
			rpm-ostree kargs --replace="crashkernel=$_crashkernel"
Coiby Xu 3f8281
		else
Coiby Xu 3f8281
			rpm-ostree kargs --append="crashkernel=$_crashkernel"
Coiby Xu 3f8281
		fi
Coiby Xu 3f8281
	else
Coiby Xu 3f8281
		[[ -f /etc/zipl.conf ]] && zipl_arg="--zipl"
Coiby Xu 3f8281
		grubby --args "crashkernel=$_crashkernel" --update-kernel "$_kernel_path" $zipl_arg
Coiby Xu 3f8281
		if [[ $_dump_mode == kdump ]]; then
Coiby Xu 3f8281
			grubby --remove-args="fadump" --update-kernel "$_kernel_path"
Coiby Xu 3f8281
		else
Coiby Xu 3f8281
			grubby --args="fadump=$_fadump_val" --update-kernel "$_kernel_path"
Coiby Xu 3f8281
		fi
Coiby Xu 3f8281
	fi
Coiby Xu 3f8281
	[[ $zipl_arg ]] && zipl > /dev/null
Coiby Xu 3f8281
}
Kairui Song a0fe51
Coiby Xu 3f8281
_valid_grubby_kernel_path()
Coiby Xu 3f8281
{
Coiby Xu 3f8281
	[[ -n "$1" ]] && grubby --info="$1" > /dev/null 2>&1
Coiby Xu 3f8281
}
Coiby Xu 3f8281
Coiby Xu 9b4f60
# return all the kernel paths given a grubby kernel-path
Coiby Xu 9b4f60
#
Coiby Xu 9b4f60
# $1: kernel path accepted by grubby, e.g. DEFAULT, ALL,
Coiby Xu 9b4f60
#     /boot/vmlinuz-`uname -r`
Coiby Xu 9b4f60
# return: kernel paths separated by space
Coiby Xu 3f8281
_get_all_kernels_from_grubby()
Coiby Xu 3f8281
{
Coiby Xu 3f8281
	local _kernels _line _kernel_path _grubby_kernel_path=$1
Coiby Xu 3f8281
Coiby Xu 3f8281
	for _line in $(grubby --info "$_grubby_kernel_path" | grep "^kernel="); do
Coiby Xu 3f8281
		_kernel_path=$(_filter_grubby_kernel_str "$_line")
Coiby Xu 3f8281
		_kernels="$_kernels $_kernel_path"
Coiby Xu 3f8281
	done
Coiby Xu 3f8281
	echo -n "$_kernels"
Coiby Xu 3f8281
}
Coiby Xu 3f8281
Coiby Xu 3f8281
GRUB_ETC_DEFAULT="/etc/default/grub"
738bf0
# Update a kernel parameter in default grub conf
738bf0
#
738bf0
# If a value is specified, it will be inserted in the end. Otherwise it
738bf0
# would remove given kernel parameter.
738bf0
#
738bf0
# Note this function doesn't address the following cases,
738bf0
# 1. The kernel ignores everything on the command line after a '--'. So
738bf0
#    simply adding the new entry to the end will fail if the cmdline
738bf0
#    contains a --.
738bf0
# 2. If the value for a parameter contains spaces it can be quoted using
738bf0
#    double quotes, for example param="value with spaces". This will
738bf0
#    break the [^[:space:]\"] regex for the value.
738bf0
# 3. Dashes and underscores in the parameter name are equivalent. So
738bf0
#    some_parameter and some-parameter are identical.
738bf0
# 4. Some parameters, e.g. efivar_ssdt, can be given multiple times.
738bf0
# 5. Some kernel parameters, e.g. quiet, doesn't have value
Coiby Xu 3f8281
#
Coiby Xu 3f8281
# $1: the name of the kernel command line parameter
738bf0
# $2: new value. If empty, given parameter would be removed
738bf0
_update_kernel_arg_in_grub_etc_default()
Coiby Xu 3f8281
{
738bf0
	local _para=$1 _val=$2 _para_val
Coiby Xu 3f8281
Coiby Xu 3f8281
	if [[ -n $_val ]]; then
Coiby Xu 3f8281
		_para_val="$_para=$_val"
Kairui Song a0fe51
	fi
Kairui Song a0fe51
738bf0
	# Update the command line /etc/default/grub, i.e.
738bf0
	# on the line that starts with 'GRUB_CMDLINE_LINUX=',
738bf0
	#       1) remove $para=$val if the it's the first arg
738bf0
	#       2) remove all occurences of $para=$val
738bf0
	#       3) insert $_para_val to end
738bf0
	#       4) remove duplicate spaces left over by 1) or 2) or 3)
738bf0
	#       5) remove space at the beginning of the string left over by 1) or 2) or 3)
738bf0
	#       6) remove space at the end of the string left over by 1) or 2) or 3)
738bf0
	sed -i -E "/^GRUB_CMDLINE_LINUX=/ {
738bf0
         s/\"${_para}=[^[:space:]\"]*/\"/g;
738bf0
         s/[[:space:]]+${_para}=[^[:space:]\"]*/ /g;
738bf0
         s/\"$/ ${_para_val}\"/
738bf0
         s/[[:space:]]+/ /g;
738bf0
         s/(\")[[:space:]]+/\1/g;
738bf0
         s/[[:space:]]+(\")/\1/g;
738bf0
         }" "$GRUB_ETC_DEFAULT"
Coiby Xu 3f8281
}
Coiby Xu 3f8281
dd05af
# Read the kernel arg in default grub conf.
dd05af
dd05af
# Note reading a kernel parameter that doesn't have a value isn't supported.
dd05af
#
dd05af
# $1: the name of the kernel command line parameter
dd05af
_read_kernel_arg_in_grub_etc_default()
dd05af
{
dd05af
	sed -n -E "s/^GRUB_CMDLINE_LINUX=.*[[:space:]\"]${1}=([^[:space:]\"]*).*$/\1/p" "$GRUB_ETC_DEFAULT"
dd05af
}
dd05af
Coiby Xu 3f8281
reset_crashkernel()
Coiby Xu 3f8281
{
Coiby Xu 3f8281
	local _opt _val _dump_mode _fadump_val _reboot _grubby_kernel_path _kernel _kernels
Coiby Xu 3f8281
	local _old_crashkernel _new_crashkernel _new_dump_mode _crashkernel_changed
Coiby Xu 3f8281
	local _new_fadump_val _old_fadump_val _what_is_updated
Coiby Xu 3f8281
Coiby Xu 3f8281
	for _opt in "$@"; do
Coiby Xu 3f8281
		case "$_opt" in
Coiby Xu 3f8281
			--fadump=*)
Coiby Xu 3f8281
				_val=${_opt#*=}
Coiby Xu 3f8281
				if _dump_mode=$(get_dump_mode_by_fadump_val $_val); then
Coiby Xu 3f8281
					_fadump_val=$_val
Coiby Xu 3f8281
				else
Coiby Xu 3f8281
					derror "failed to determine dump mode"
Coiby Xu 3f8281
					exit
Coiby Xu 3f8281
				fi
Coiby Xu 3f8281
				;;
Coiby Xu 3f8281
			--kernel=*)
Coiby Xu 3f8281
				_val=${_opt#*=}
Coiby Xu 3f8281
				if ! _valid_grubby_kernel_path $_val; then
Coiby Xu 3f8281
					derror "Invalid $_opt, please specify a valid kernel path, ALL or DEFAULT"
Coiby Xu 3f8281
					exit
Coiby Xu 3f8281
				fi
Coiby Xu 3f8281
				_grubby_kernel_path=$_val
Coiby Xu 3f8281
				;;
Coiby Xu 3f8281
			--reboot)
Coiby Xu 3f8281
				_reboot=yes
Coiby Xu 3f8281
				;;
Coiby Xu 3f8281
			*)
Coiby Xu 3f8281
				derror "$_opt not recognized"
Coiby Xu 3f8281
				exit 1
Coiby Xu 3f8281
				;;
Coiby Xu 3f8281
		esac
Coiby Xu 3f8281
	done
Coiby Xu 3f8281
Coiby Xu 3f8281
	# 1. CoreOS uses "rpm-ostree kargs" instead of grubby to manage kernel command
Coiby Xu 3f8281
	#    line. --kernel=ALL doesn't make sense for CoreOS.
Coiby Xu 3f8281
	# 2. CoreOS doesn't support POWER so the dump mode is always kdump.
Coiby Xu 3f8281
	# 3. "rpm-ostree kargs" would prompt the user to reboot the system after
Coiby Xu 3f8281
	#    modifying the kernel command line so there is no need for kexec-tools
Coiby Xu 3f8281
	#    to repeat it.
Kairui Song a0fe51
	if is_atomic; then
Coiby Xu 3f8281
		_old_crashkernel=$(rpm-ostree kargs | sed -n -E 's/.*(^|\s)crashkernel=(\S*).*/\2/p')
Coiby Xu 3f8281
		_new_dump_mode=kdump
Coiby Xu 3f8281
		_new_crashkernel=$(kdump_get_arch_recommend_crashkernel "$_new_dump_mode")
Coiby Xu 3f8281
		if [[ $_old_crashkernel != "$_new_crashkernel" ]]; then
Coiby Xu 3f8281
			_update_grub "" "$_new_crashkernel" "$_new_dump_mode" ""
Coiby Xu 3f8281
			if [[ $_reboot == yes ]]; then
Coiby Xu 3f8281
				systemctl reboot
Coiby Xu 3f8281
			fi
Kairui Song a0fe51
		fi
Coiby Xu 3f8281
		return
Coiby Xu 3f8281
	fi
Coiby Xu 3f8281
Coiby Xu 3f8281
	# For non-ppc64le systems, the dump mode is always kdump since only ppc64le
Coiby Xu 3f8281
	# has FADump.
Coiby Xu 3f8281
	if [[ -z $_dump_mode && $(uname -m) != ppc64le ]]; then
Coiby Xu 3f8281
		_dump_mode=kdump
Coiby Xu 3f8281
		_fadump_val=off
Coiby Xu 3f8281
	fi
Coiby Xu 3f8281
Coiby Xu 3f8281
	# If the dump mode is determined, we can also know the default crashkernel value
Coiby Xu 3f8281
	if [[ -n $_dump_mode ]]; then
Coiby Xu 3f8281
		_crashkernel=$(kdump_get_arch_recommend_crashkernel "$_dump_mode")
Coiby Xu 3f8281
	fi
Coiby Xu 3f8281
Coiby Xu 3f8281
	# If --kernel-path=ALL, update GRUB_CMDLINE_LINUX in /etc/default/grub.
Coiby Xu 3f8281
	#
Coiby Xu 3f8281
	# An exception case is when the ppc64le user doesn't specify the fadump value.
Coiby Xu 3f8281
	# In this case, the dump mode would be determined by parsing the kernel
Coiby Xu 3f8281
	# command line of the kernel(s) to be updated thus don't update GRUB_CMDLINE_LINUX.
Coiby Xu 3f8281
	#
Coiby Xu 3f8281
	# The following code has been simplified because of what has been done early,
Coiby Xu 3f8281
	#   - set the dump mode as kdump for non-ppc64le cases
Coiby Xu 3f8281
	#   - retrieved the default crashkernel value for given dump mode
Coiby Xu 3f8281
	if [[ $_grubby_kernel_path == ALL && -n $_dump_mode ]]; then
738bf0
		_update_kernel_arg_in_grub_etc_default crashkernel "$_crashkernel"
Coiby Xu 3f8281
		# remove the fadump if fadump is disabled
738bf0
		if [[ $_fadump_val == off ]]; then
738bf0
			_fadump_val=""
738bf0
		fi
738bf0
		_update_kernel_arg_in_grub_etc_default fadump "$_fadump_val"
Coiby Xu 3f8281
	fi
Coiby Xu 3f8281
Coiby Xu 3f8281
	# If kernel-path not specified, either
Coiby Xu 3f8281
	#  - use KDUMP_KERNELVER if it's defined
Coiby Xu 3f8281
	#  - use current running kernel
Coiby Xu 3f8281
	if [[ -z $_grubby_kernel_path ]]; then
Coiby Xu 3f8281
		if [[ -z $KDUMP_KERNELVER ]] ||
Coiby Xu 3f8281
			! _kernel_path=$(_find_kernel_path_by_release "$KDUMP_KERNELVER"); then
Coiby Xu 3f8281
					if ! _kernel_path=$(_get_current_running_kernel_path); then
Coiby Xu 3f8281
						derror "no running kernel found"
Coiby Xu 3f8281
						exit 1
Coiby Xu 3f8281
					fi
Coiby Xu 3f8281
		fi
Coiby Xu 3f8281
		_kernels=$_kernel_path
Kairui Song a0fe51
	else
Coiby Xu 3f8281
		_kernels=$(_get_all_kernels_from_grubby "$_grubby_kernel_path")
Coiby Xu 3f8281
	fi
Kairui Song a0fe51
Coiby Xu 3f8281
	for _kernel in $_kernels; do
Coiby Xu 3f8281
		if [[ -z $_dump_mode ]]; then
Coiby Xu 3f8281
			_new_dump_mode=$(get_dump_mode_by_kernel "$_kernel")
Coiby Xu 3f8281
			_new_crashkernel=$(kdump_get_arch_recommend_crashkernel "$_new_dump_mode")
Coiby Xu 3f8281
			_new_fadump_val=$(get_grub_kernel_boot_parameter "$_kernel" fadump)
Coiby Xu 3f8281
		else
Coiby Xu 3f8281
			_new_dump_mode=$_dump_mode
Coiby Xu 3f8281
			_new_crashkernel=$_crashkernel
Coiby Xu 3f8281
			_new_fadump_val=$_fadump_val
Kairui Song a0fe51
		fi
Kairui Song a0fe51
Coiby Xu 3f8281
		_old_crashkernel=$(get_grub_kernel_boot_parameter "$_kernel" crashkernel)
Coiby Xu 3f8281
		_old_fadump_val=$(get_grub_kernel_boot_parameter "$_kernel" fadump)
Coiby Xu 3f8281
		if [[ $_old_crashkernel != "$_new_crashkernel" || $_old_fadump_val != "$_new_fadump_val" ]]; then
Coiby Xu 3f8281
			_update_grub "$_kernel" "$_new_crashkernel" "$_new_dump_mode" "$_new_fadump_val"
Coiby Xu 3f8281
			if [[ $_reboot != yes ]]; then
Coiby Xu 3f8281
				if [[ $_old_crashkernel != "$_new_crashkernel" ]]; then
Coiby Xu 3f8281
					_what_is_updated="Updated crashkernel=$_new_crashkernel"
Coiby Xu 3f8281
				else
Coiby Xu 3f8281
					# This case happens only when switching between fadump=on and fadump=nocma
Coiby Xu 3f8281
					_what_is_updated="Updated fadump=$_new_fadump_val"
Coiby Xu 3f8281
				fi
Coiby Xu 3f8281
				dwarn "$_what_is_updated for kernel=$_kernel. Please reboot the system for the change to take effect."
Coiby Xu 3f8281
			fi
Coiby Xu 3f8281
			_crashkernel_changed=yes
Coiby Xu 3f8281
		fi
Coiby Xu 3f8281
	done
Coiby Xu 3f8281
Coiby Xu 3f8281
	if [[ $_reboot == yes && $_crashkernel_changed == yes ]]; then
Coiby Xu 3f8281
		reboot
Kairui Song a0fe51
	fi
67b8dd
}
Kairui Song a0fe51
dd05af
# update the crashkernel value in GRUB_ETC_DEFAULT if necessary
dd05af
#
dd05af
# called by reset_crashkernel_after_update and inherit its array variable
dd05af
# _crashkernel_vals
dd05af
update_crashkernel_in_grub_etc_default_after_update()
dd05af
{
dd05af
	local _crashkernel _fadump_val
dd05af
	local _dump_mode _old_default_crashkernel _new_default_crashkernel
dd05af
dd05af
	_crashkernel=$(_read_kernel_arg_in_grub_etc_default crashkernel)
dd05af
dd05af
	if [[ -z $_crashkernel ]]; then
dd05af
		return
dd05af
	fi
dd05af
dd05af
	_fadump_val=$(_read_kernel_arg_in_grub_etc_default fadump)
dd05af
	_dump_mode=$(get_dump_mode_by_fadump_val "$_fadump_val")
dd05af
dd05af
	_old_default_crashkernel=${_crashkernel_vals[old_${_dump_mode}]}
dd05af
	_new_default_crashkernel=${_crashkernel_vals[new_${_dump_mode}]}
dd05af
dd05af
	if [[ $_crashkernel == auto ]] ||
dd05af
		  [[ $_crashkernel == "$_old_default_crashkernel" &&
dd05af
		     $_new_default_crashkernel != "$_old_default_crashkernel" ]]; then
dd05af
			_update_kernel_arg_in_grub_etc_default crashkernel "$_new_default_crashkernel"
dd05af
	fi
dd05af
}
dd05af
Coiby Xu 224984
# shellcheck disable=SC2154 # false positive when dereferencing an array
Coiby Xu 224984
reset_crashkernel_after_update()
Coiby Xu 224984
{
Coiby Xu 224984
	local _kernel _crashkernel _dump_mode _fadump_val _old_default_crashkernel _new_default_crashkernel
Coiby Xu 224984
	declare -A _crashkernel_vals
Coiby Xu 224984
Coiby Xu 224984
	_crashkernel_vals[old_kdump]=$(cat /tmp/old_default_crashkernel 2> /dev/null)
Coiby Xu 224984
	_crashkernel_vals[old_fadump]=$(cat /tmp/old_default_crashkernel_fadump 2> /dev/null)
Coiby Xu 224984
	_crashkernel_vals[new_kdump]=$(get_default_crashkernel kdump)
Coiby Xu 224984
	_crashkernel_vals[new_fadump]=$(get_default_crashkernel fadump)
Coiby Xu 224984
Coiby Xu 9b4f60
	for _kernel in $(_get_all_kernels_from_grubby ALL); do
Coiby Xu 224984
		_crashkernel=$(get_grub_kernel_boot_parameter "$_kernel" crashkernel)
Coiby Xu 224984
		if [[ $_crashkernel == auto ]]; then
Coiby Xu 224984
			reset_crashkernel "--kernel=$_kernel"
Coiby Xu 224984
		elif [[ -n $_crashkernel ]]; then
Coiby Xu 224984
			_dump_mode=$(get_dump_mode_by_kernel "$_kernel")
Coiby Xu 224984
			_old_default_crashkernel=${_crashkernel_vals[old_${_dump_mode}]}
Coiby Xu 224984
			_new_default_crashkernel=${_crashkernel_vals[new_${_dump_mode}]}
Coiby Xu 224984
			if [[ $_crashkernel == "$_old_default_crashkernel" ]] &&
Coiby Xu 224984
				[[ $_new_default_crashkernel != "$_old_default_crashkernel" ]]; then
Coiby Xu 224984
				_fadump_val=$(get_grub_kernel_boot_parameter "$_kernel" fadump)
Coiby Xu 224984
				if _update_grub "$_kernel" "$_new_default_crashkernel" "$_dump_mode" "$_fadump_val"; then
Coiby Xu 224984
					echo "For kernel=$_kernel, crashkernel=$_new_default_crashkernel now."
Coiby Xu 224984
				fi
Coiby Xu 224984
			fi
Coiby Xu 224984
		fi
Coiby Xu 224984
	done
dd05af
dd05af
	update_crashkernel_in_grub_etc_default_after_update
Coiby Xu 224984
}
Coiby Xu 224984
Coiby Xu e94371
# read the value of an environ variable from given environ file path
Coiby Xu e94371
#
Coiby Xu e94371
# The environment variable entries in /proc/[pid]/environ are separated
Coiby Xu e94371
# by null bytes instead of by spaces.
Coiby Xu 7a61e0
#
Coiby Xu 7a61e0
# $1: environment variable
Coiby Xu 7a61e0
# $2: environ file path
Coiby Xu e94371
read_proc_environ_var()
Coiby Xu e94371
{
Coiby Xu 7a61e0
	local _var=$1 _environ_path=$2
Coiby Xu e94371
	sed -n -E "s/.*(^|\x00)${_var}=([^\x00]*).*/\2/p" < "$_environ_path"
Coiby Xu e94371
}
Coiby Xu e94371
Coiby Xu 7a61e0
_OSBUILD_ENVIRON_PATH='/proc/1/environ'
Coiby Xu fc1362
_is_osbuild()
Coiby Xu fc1362
{
Coiby Xu 7a61e0
	[[ $(read_proc_environ_var container "$_OSBUILD_ENVIRON_PATH") == bwrap-osbuild ]]
Coiby Xu fc1362
}
Coiby Xu fc1362
Coiby Xu 2589c4
reset_crashkernel_for_installed_kernel()
Coiby Xu 2589c4
{
Coiby Xu 2589c4
	local _installed_kernel _running_kernel _crashkernel _crashkernel_running
Coiby Xu 2589c4
	local _dump_mode_running _fadump_val_running
Coiby Xu 2589c4
Coiby Xu 2589c4
	if ! _installed_kernel=$(_find_kernel_path_by_release "$1"); then
Coiby Xu 2589c4
		exit 1
Coiby Xu 2589c4
	fi
Coiby Xu 2589c4
Coiby Xu e94371
	if _is_osbuild; then
Coiby Xu e94371
		if ! grep -qs crashkernel= /etc/kernel/cmdline; then
Coiby Xu e94371
			reset_crashkernel "--kernel=$_installed_kernel"
Coiby Xu e94371
		fi
Coiby Xu fc1362
		return
Coiby Xu fc1362
	fi
Coiby Xu fc1362
Coiby Xu 2589c4
	if ! _running_kernel=$(_get_current_running_kernel_path); then
Coiby Xu 2589c4
		derror "Couldn't find current running kernel"
Coiby Xu 2589c4
		exit
Coiby Xu 2589c4
	fi
Coiby Xu 2589c4
Coiby Xu 2589c4
	_crashkernel=$(get_grub_kernel_boot_parameter "$_installed_kernel" crashkernel)
Coiby Xu 2589c4
	_crashkernel_running=$(get_grub_kernel_boot_parameter "$_running_kernel" crashkernel)
Coiby Xu 2589c4
	_dump_mode_running=$(get_dump_mode_by_kernel "$_running_kernel")
Coiby Xu 2589c4
	_fadump_val_running=$(get_grub_kernel_boot_parameter "$_kernel" fadump)
Coiby Xu 2589c4
Coiby Xu 2589c4
	if [[ $_crashkernel != "$_crashkernel_running" ]]; then
Coiby Xu 2589c4
		if _update_grub "$_installed_kernel" "$_crashkernel_running" "$_dump_mode_running" "$_fadump_val_running"; then
Coiby Xu 2589c4
			echo "kexec-tools has reset $_installed_kernel to use the new default crashkernel value $_crashkernel_running"
Coiby Xu 2589c4
		fi
Coiby Xu 2589c4
	fi
Coiby Xu 2589c4
}
Coiby Xu 2589c4
b494b7
if [[ ! -f $KDUMP_CONFIG_FILE ]]; then
DistroBaker 5cac7c
	derror "Error: No kdump config file found!"
Petr Šabata f5bf49
	exit 1
Petr Šabata f5bf49
fi
Petr Šabata f5bf49
b494b7
main()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	# Determine if the dump mode is kdump or fadump
Petr Šabata f5bf49
	determine_dump_mode
Petr Šabata f5bf49
Petr Šabata f5bf49
	case "$1" in
b494b7
	start)
dcb59c
		if [[ -s /proc/vmcore ]]; then
Petr Šabata f5bf49
			save_core
Petr Šabata f5bf49
			reboot
Petr Šabata f5bf49
		else
Petr Šabata f5bf49
			start
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
		;;
b494b7
	stop)
Petr Šabata f5bf49
		stop
Petr Šabata f5bf49
		;;
b494b7
	status)
Petr Šabata f5bf49
		EXIT_CODE=0
Petr Šabata f5bf49
		check_current_status
Petr Šabata f5bf49
		case "$?" in
b494b7
		0)
DistroBaker 5cac7c
			dinfo "Kdump is operational"
Petr Šabata f5bf49
			EXIT_CODE=0
Petr Šabata f5bf49
			;;
b494b7
		1)
DistroBaker 5cac7c
			dinfo "Kdump is not operational"
Petr Šabata f5bf49
			EXIT_CODE=3
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		esac
Petr Šabata f5bf49
		exit $EXIT_CODE
Petr Šabata f5bf49
		;;
b494b7
	reload)
Petr Šabata f5bf49
		reload
Petr Šabata f5bf49
		;;
b494b7
	restart)
Petr Šabata f5bf49
		stop
Petr Šabata f5bf49
		start
Petr Šabata f5bf49
		;;
b494b7
	rebuild)
Petr Šabata f5bf49
		rebuild
Petr Šabata f5bf49
		;;
b494b7
	condrestart) ;;
b494b7
b494b7
	propagate)
Petr Šabata f5bf49
		propagate_ssh_key
Petr Šabata f5bf49
		;;
b494b7
	showmem)
Petr Šabata f5bf49
		show_reserved_mem
Petr Šabata f5bf49
		;;
b494b7
	estimate)
Kairui Song a9fda5
		do_estimate
Kairui Song a9fda5
		;;
Coiby Xu acf9f6
	get-default-crashkernel)
Coiby Xu acf9f6
		get_default_crashkernel "$2"
Coiby Xu acf9f6
		;;
b494b7
	reset-crashkernel)
Coiby Xu 3f8281
		shift
Coiby Xu 3f8281
		reset_crashkernel "$@"
Kairui Song a0fe51
		;;
Coiby Xu 224984
	reset-crashkernel-after-update)
Coiby Xu 224984
		if [[ $(kdump_get_conf_val auto_reset_crashkernel) != no ]]; then
Coiby Xu 224984
			reset_crashkernel_after_update
Coiby Xu 224984
		fi
Coiby Xu 224984
		;;
Coiby Xu 2589c4
	reset-crashkernel-for-installed_kernel)
Coiby Xu 2589c4
		if [[ $(kdump_get_conf_val auto_reset_crashkernel) != no ]]; then
Coiby Xu 2589c4
			reset_crashkernel_for_installed_kernel "$2"
Coiby Xu 2589c4
		fi
Coiby Xu 2589c4
		;;
b494b7
	*)
Kairui Song a0fe51
		dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|reset-crashkernel|propagate|showmem}"
Petr Šabata f5bf49
		exit 1
b494b7
		;;
Petr Šabata f5bf49
	esac
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
# Other kdumpctl instances will block in queue, until this one exits
Petr Šabata f5bf49
single_instance_lock
Petr Šabata f5bf49
Petr Šabata f5bf49
# To avoid fd 9 leaking, we invoke a subshell, close fd 9 and call main.
Petr Šabata f5bf49
# So that fd isn't leaking when main is invoking a subshell.
b494b7
(
b494b7
	exec 9<&-
b494b7
	main "$@"
b494b7
)
Petr Šabata f5bf49
Petr Šabata f5bf49
exit $?