#9 crashkernel=auto: support fadump and remove crashkernel.default
Merged 2 years ago by coiby. Opened 2 years ago by coiby.
rpms/ coiby/kexec-tools auto_reset_crashkernel  into  rawhide

file modified
+1 -134
@@ -5,142 +5,9 @@ 

  KDUMP_INITRD_DIR_ABS="$3"

  KERNEL_IMAGE="$4"

  

- grub_etc_default="/etc/default/grub"

- 

- ver_lt() {

- 	[[ "$(echo -e "$1\n$2" | sort -V)" == $1$'\n'* ]] && [[ $1 != "$2" ]]

- }

- 

- # Read crashkernel= value in /etc/default/grub

- get_grub_etc_ck() {

- 	[[ -e $grub_etc_default ]] && \

- 	sed -n -e "s/^GRUB_CMDLINE_LINUX=.*\(crashkernel=[^\ \"]*\)[\ \"].*$/\1/p" $grub_etc_default

- }

- 

- # Read crashkernel.default value of specified kernel

- get_ck_default() {

- 	ck_file="/usr/lib/modules/$1/crashkernel.default"

- 	[[ -f "$ck_file" ]] && cat "$ck_file"

- }

- 

- # Iterate installed kernels, find the kernel with the highest version that has a

- # valid crashkernel.default file, exclude current installing/removing kernel

- #

- # $1: a string representing a crashkernel= cmdline. If given, will also check the

- # content of crashkernel.default, only crashkernel.default with the same value will match

- get_highest_ck_default_kver() {

- 	for kernel in $(find /usr/lib/modules -maxdepth 1 -mindepth 1 -printf "%f\n" | sort --version-sort -r); do

- 		[[ $kernel == "$KERNEL_VERSION" ]] && continue

- 		[[ -s "/usr/lib/modules/$kernel/crashkernel.default" ]] || continue

- 

- 		echo "$kernel"

- 		return 0

- 	done

- 

- 	return 1

- }

- 

- set_grub_ck() {

- 	sed -i -e "s/^\(GRUB_CMDLINE_LINUX=.*\)crashkernel=[^\ \"]*\([\ \"].*\)$/\1$1\2/" "$grub_etc_default"

- }

- 

- # Set specified kernel's crashkernel cmdline value

- set_kernel_ck() {

- 	kernel=$1

- 	ck_cmdline=$2

- 

- 	entry=$(grubby --info ALL | grep "^kernel=.*$kernel")

- 	entry=${entry#kernel=}

- 	entry=${entry#\"}

- 	entry=${entry%\"}

- 

- 	if [[ -z "$entry" ]]; then

- 		echo "$0: failed to find boot entry for kernel $kernel"

- 		return 1

- 	fi

- 

- 	[[ -f /etc/zipl.conf ]] && zipl_arg="--zipl"

- 	grubby --args "$ck_cmdline" --update-kernel "$entry" $zipl_arg

- 	[[ $zipl_arg ]] && zipl > /dev/null ||:

- }

- 

  case "$COMMAND" in

  add)

- 	# - If current boot kernel is using default crashkernel value, update

- 	#   installing kernel's crashkernel value to its default value,

- 	# - If intalling a higher version kernel, and /etc/default/grub's

- 	#   crashkernel value is using default value, update it to installing

- 	#   kernel's default value.

- 	inst_ck_default=$(get_ck_default "$KERNEL_VERSION")

- 	# If installing kernel doesn't have crashkernel.default, just exit.

- 	[[ -z "$inst_ck_default" ]] && exit 0

- 

- 	boot_kernel=$(uname -r)

- 	boot_ck_cmdline=$(sed -n -e "s/^.*\(crashkernel=\S*\).*$/\1/p" /proc/cmdline)

- 	highest_ck_default_kver=$(get_highest_ck_default_kver)

- 	highest_ck_default=$(get_ck_default "$highest_ck_default_kver")

- 

- 	# Try update /etc/default/grub if present, else grub2-mkconfig could

- 	# override crashkernel value.

- 	grub_etc_ck=$(get_grub_etc_ck)

- 	if [[ -n "$grub_etc_ck" ]]; then

- 		if [[ -z "$highest_ck_default_kver" ]]; then

- 			# None of installed kernel have a crashkernel.default,

- 			# check for 'crashkernel=auto' in case of legacy kernel

- 			[[ "$grub_etc_ck" == "crashkernel=auto" ]] && \

- 				set_grub_ck "$inst_ck_default"

- 		else

- 			# There is a valid crashkernel.default, check if installing kernel

- 			# have a higher version and grub config is using default value

- 			ver_lt "$highest_ck_default_kver" "$KERNEL_VERSION" && \

- 				[[ "$grub_etc_ck" == "$highest_ck_default" ]] && \

- 				[[ "$grub_etc_ck" != "$inst_ck_default" ]] && \

- 				set_grub_ck "$inst_ck_default"

- 		fi

- 	fi

- 

- 	# Exit if crashkernel is not used in current cmdline

- 	[[ -z $boot_ck_cmdline ]] && exit 0

- 

- 	# Get current boot kernel's default value

- 	boot_ck_default=$(get_ck_default "$boot_kernel")

- 	if [[ $boot_ck_cmdline == "crashkernel=auto" ]]; then

- 		# Legacy RHEL kernel defaults to "auto"

- 		boot_ck_default="$boot_ck_cmdline"

- 	fi

- 

- 	# If boot kernel doesn't have a crashkernel.default, check

- 	# if it's using any installed kernel's crashkernel.default

- 	if [[ -z $boot_ck_default ]]; then

- 		[[ $(get_highest_ck_default_kver "$boot_ck_cmdline") ]] && boot_ck_default="$boot_ck_cmdline"

- 	fi

- 

- 	# If boot kernel is using a default crashkernel, update

- 	# installing kernel's crashkernel to new default value

- 	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)

- 	[[ $grub_etc_ck ]] || exit 0

- 

- 	removing_ck_conf=$(get_ck_default "$KERNEL_VERSION")

- 	[[ $removing_ck_conf ]] || exit 0

- 

- 	highest_ck_default_kver=$(get_highest_ck_default_kver) || exit 0

- 	highest_ck_default=$(get_ck_default "$highest_ck_default_kver")

- 	[[ $highest_ck_default ]] || exit 0

- 

- 	if ver_lt "$highest_ck_default_kver" "$KERNEL_VERSION"; then

- 		if [[ $grub_etc_ck == "$removing_ck_conf" ]] && [[ $grub_etc_ck != "$highest_ck_default" ]]; then

- 			set_grub_ck "$highest_ck_default"

- 		fi

- 	fi

- 

+ 	kdumpctl reset-crashkernel-for-installed_kernel "$KERNEL_VERSION"

  	exit 0

  	;;

  esac

file modified
+20 -105
@@ -13,13 +13,14 @@ 

  Default crashkernel value

  =========================

  

- Latest kernel packages include a `crashkernel.default` file installed in kernel

- modules folder, available as:

+ Latest kexec-tools provides "kdumpctl get-default-crashkernel" to retrieve

+ the default crashkernel value,

  

- 	/usr/lib/modules/<kernel>/crashkernel.default

+ 	$ echo $(kdumpctl get-default-crashkernel)

+ 	1G-4G:192M,4G-64G:256M,64G-102400T:512M

  

- The content of the file will be taken as the default value of 'crashkernel=', or

- take this file as a reference for setting crashkernel value manually.

+ It will be taken as the default value of 'crashkernel=', you can use

+ this value as a reference for setting crashkernel value manually.

  

  

  New installed system
@@ -27,7 +28,7 @@ 

  

  Anaconda is the OS installer which sets all the kernel boot cmdline on a newly

  installed system. If kdump is enabled during Anaconda installation, Anaconda

- will use the `crashkernel.default` file as the default `crashkernel=` value on

+ will use the default crashkernel value as the default `crashkernel=` value on

  the newly installed system.

  

  Users can override the value during Anaconda installation manually.
@@ -36,20 +37,11 @@ 

  Auto update of crashkernel boot parameter

  =========================================

  

- Following context in this section assumes all kernel packages have a

- `crashkernel.default` file bundled, which is true for the latest official kernel

- packages. For kexec-tools behavior with a kernel that doesn't have a

- `crashkernel.default` file, please refer to the “Custom Kernel” section of this

- doc.

- 

- When `crashkernel=` is using the default value, kexec-tools will need to update

- the `crashkernel=` value of new installed kernels, since the default value may

- change in new kernel packages.

- 

- kexec-tools does so by adding a kernel installation hook, which gets triggered

- every time a new kernel is installed, so kexec-tools can do necessary checks and

- updates.

- 

+ A new release of kexec-tools could update the default crashkernel value.

+ By default, kexec-tools would reset crashkernel to the new default value if it

+ detects old default crashkernel value is used by installed kernels. If you don't

+ want kexec-tools to update the old default crashkernel to the new default

+ crashkernel, you can change auto_reset_crashkernel to no in kdump.conf.

  

  Supported Bootloaders

  ---------------------
@@ -59,92 +51,13 @@ 

  `crashkernel=` value manually.

  

  

- Updating kernel package

- -----------------------

- 

- When a new version of package kernel is released in the official repository, the

- package will always come with a `crashkernel.default` file bundled. Kexec-tools

- will act with following rules:

- 

- If current boot kernel is using the default `crashkernel=` boot param value from

- its `crashkernel.default` file, then kexec-tools will update new installed

- kernel’s `crashkernel=` boot param using the value from the new installed

- kernel’s `crashkernel.default` file. This ensures `crashkernel=` is always using

- the latest default value.

- 

- If current boot kernel's `crashkernel=` value is set to a non-default value, the

- new installed kernel simply inherits this value.

- 

- On systems using GRUB2 as the bootloader, each kernel has its own boot entry,

- making it possible to set different `crashkernel=` boot param values for

- different kernels. So kexec-tools won’t touch any already installed kernel's

- boot param, only new installed kernel's `crashkernel=` boot param value will be

- updated.

- 

- But some utilities like `grub2-mkconfig` and `grubby` can override all boot

- entry's boot params with the boot params value from the GRUB config file

- `/etc/defaults/grub`, so kexec-tools will also update the GRUB config file in

- case old `crashkernel=` value overrides new installed kernel’s boot param.

- 

- 

- Downgrading kernel package

- --------------------------

- 

- When upgrading a kernel package, kexec-tools may update the `crashkernel=` value

- in GRUB2 config file to the new value. So when downgrading the kernel package,

- kexec-tools will also try to revert that update by setting GRUB2 config file’s

- `crashkernel=` value back to the default value in the older kernel package. This

- will only occur when the GRUB2 config file is using the default `crashkernel=`

- value.

- 

- 

- Custom kernel

- =============

- 

- To make auto crashkernel update more robust, kexec-tools will try to keep

- tracking the default 'crashkernel=` value with kernels that don’t have a

- `crashkernel.default` file, such kernels are referred to as “custom kernel” in

- this doc. This is only a best-effort support to make it easier debugging and

- testing the system.

- 

- When installing a custom kernel that doesn’t have a `crashkernel.default` file,

- the `crashkernel=` value will be simply inherited from the current boot kernel.

- 

- When installing a new official kernel package and current boot kernel is a

- custom kernel, since the boot kernel doesn’t have a `crashkernel.default` file,

- kexec-tools will iterate installed kernels and check if the boot kernel

- inherited the default value from any other existing kernels’

- `crashkernel.default` file. If a matching `crashkernel.default` file is found,

- kexec-tools will update the new installed kernel `crashkernel=` boot param using

- the value from the new installed kernel’s `crashkernel.default` file, ensures

- the auto crashkernel value update won’t break over one or two custom kernel

- installations.

- 

- It is possible that the auto crashkernel value update will fail when custom

- kernels are used. One example is a custom kernel inheriting the default

- `crashkernel=` value from an older official kernel package, but later that

- kernel package is uninstalled. So when booted with the custom kernel,

- kexec-tools can't determine if the boot kernel is inheriting a default

- `crashkernel=` value from any official build. In such a case, please refer to

- the "Reset crashkernel to default value" section of this doc.

- 

- 

  Reset crashkernel to default value

  ==================================

  

  kexec-tools only perform the auto update of crashkernel value when it can

  confirm the boot kernel's crashkernel value is using its corresponding default

- value or inherited from any installed kernel.

- 

- kexec-tools may fail to determine if the boot kernel is using default

- crashkernel value in some use cases:

- - kexec-tools package is absent during a kernel package upgrade, and the new

-   kernel package’s `crashkernel.default` value has changed.

- - Custom kernel is used and the kernel it inherits `crashkernel=`  value from is

-   uninstalled.

- 

- So it's recommended to reset the crashkernel value if users have uninstalled

- kexec-tools or using a custom kernel.

+ value and auto_reset_crashkernel=yes in kdump.conf. In other cases, the user

+ can reset the crashkernel value by themselves.

  

  Reset using kdumpctl

  --------------------
@@ -152,21 +65,23 @@ 

  To make it easier to reset the `crashkernel=` kernel cmdline to this default

  value properly, `kdumpctl` also provides a sub-command:

  

- 	`kdumpctl reset-crashkernel [<kernel version>]`

+ 	`kdumpctl reset-crashkernel [--kernel=path_to_kernel] [--reboot]`

  

  This command will read from the `crashkernel.default` file and reset

  bootloader's kernel cmdline to the default value. It will also update bootloader

  config if the bootloader has a standalone config file. User will have to reboot

- the machine after this command to make it take effect.

+ the machine after this command to make it take effect if --reboot is not specified.

+ For ppc64le, an optional "[--fadump=[on|off|nocma]]" can also be specified to toggle

+ FADump on/off.

  

  Reset manually

  --------------

  

  To reset the crashkernel value manually, it's recommended to use utils like

  `grubby`. A one liner script for resetting `crashkernel=` value of all installed

- kernels to current boot kernel's  crashkernel.default` is:

+ kernels to current boot kernel's crashkernel.default` is:

  

- 	grubby --update-kernel ALL --args "$(cat /usr/lib/modules/$(uname -r)/crashkernel.default)"

+ 	grubby --update-kernel ALL --args "crashkernel=$(kdumpctl get-default-crashkernel)"

  

  Estimate crashkernel

  ====================

file modified
+36 -24
@@ -822,40 +822,52 @@ 

  	IFS="$OLDIFS"

  }

  

+ # get default crashkernel

+ # $1 dump mode, if not specified, dump_mode will be judged by is_fadump_capable

+ kdump_get_arch_recommend_crashkernel()

+ {

+ 	local _arch _ck_cmdline _dump_mode

+ 

+ 	if [[ -z "$1" ]]; then

+ 		if is_fadump_capable; then

+ 			_dump_mode=fadump

+ 		else

+ 			_dump_mode=kdump

+ 		fi

+ 	else

+ 		_dump_mode=$1

+ 	fi

+ 

+ 	_arch=$(uname -m)

+ 

+ 	if [[ $_arch == "x86_64" ]] || [[ $_arch == "s390x" ]]; then

+ 		_ck_cmdline="1G-4G:192M,4G-64G:256M,64G-:512M"

+ 	elif [[ $_arch == "aarch64" ]]; then

+ 		_ck_cmdline="2G-:448M"

+ 	elif [[ $_arch == "ppc64le" ]]; then

+ 		if [[ $_dump_mode == "fadump" ]]; then

+ 			_ck_cmdline="4G-16G:768M,16G-64G:1G,64G-128G:2G,128G-1T:4G,1T-2T:6G,2T-4T:12G,4T-8T:20G,8T-16T:36G,16T-32T:64G,32T-64T:128G,64T-:180G"

+ 		else

+ 			_ck_cmdline="2G-4G:384M,4G-16G:512M,16G-64G:1G,64G-128G:2G,128G-:4G"

+ 		fi

+ 	fi

+ 

+ 	_ck_cmdline=${_ck_cmdline//-:/-102400T:}

+ 	echo -n "$_ck_cmdline"

+ }

+ 

  # return recommended size based on current system RAM size

  # $1: kernel version, if not set, will defaults to $(uname -r)

  kdump_get_arch_recommend_size()

  {

- 	local kernel=$1 arch

+ 	local _ck_cmdline

  

  	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)

- 

+ 	_ck_cmdline=$(kdump_get_arch_recommend_crashkernel)

  	get_recommend_size "$sys_mem" "$ck_cmdline"

  }

  

file modified
+7
@@ -11,6 +11,12 @@ 

  #

  # Supported options:

  #

+ # auto_reset_crashkernel <yes|no>

+ #           - whether to reset kernel crashkernel to new default value

+ #             or not when kexec-tools updates the default crashkernel value and

+ #             existing kernels using the old default kernel crashkernel value.

+ #             The default value is yes.

+ #

  # raw <partition>

  #           - Will dd /proc/vmcore into <partition>.

  #             Use persistent device names for partition devices,
@@ -170,6 +176,7 @@ 

  #ssh user@my.server.com

  #ssh user@2001:db8::1:2:3:4

  #sshkey /root/.ssh/kdump_id_rsa

+ auto_reset_crashkernel yes

  path /var/crash

  core_collector makedumpfile -l --message-level 7 -d 31

  #core_collector scp

file modified
+6
@@ -26,6 +26,12 @@ 

  

  .SH OPTIONS

  

+ .B auto_reset_crashkernel <yes|no>

+ .RS

+ determine whether to reset kernel crashkernel to new default value

+ or not when kexec-tools updates the default crashkernel value and

+ existing kernels using the old default kernel crashkernel value

+ 

  .B raw <partition>

  .RS

  Will dd /proc/vmcore into <partition>.  Use persistent device names for

file modified
+338 -20
@@ -1273,38 +1273,342 @@ 

  	fi

  }

  

- reset_crashkernel()

+ get_default_crashkernel()

  {

- 	local kernel=$1 entry crashkernel_default

- 	local grub_etc_default="/etc/default/grub"

+ 	local _dump_mode=$1

  

- 	[[ -z $kernel ]] && kernel=$(uname -r)

- 	crashkernel_default=$(cat "/usr/lib/modules/$kernel/crashkernel.default" 2> /dev/null)

+ 	kdump_get_arch_recommend_crashkernel "$_dump_mode"

+ }

  

- 	if [[ -z $crashkernel_default ]]; then

- 		derror "$kernel doesn't have a crashkernel.default"

- 		exit 1

+ # Read kernel cmdline parameter for a specific kernel

+ # $1: kernel path, DEFAULT or kernel path, ALL not accepted

+ # $2: kernel cmldine parameter

+ get_grub_kernel_boot_parameter()

+ {

+ 	local _kernel_path=$1 _para=$2

+ 

+ 	[[ $_kernel_path == ALL ]] && derror "kernel_path=ALL invalid for get_grub_kernel_boot_parameter" && return 1

+ 	grubby --info="$_kernel_path" | sed -En -e "/^args=.*$/{s/^.*(\s|\")${_para}=(\S*).*\"$/\2/p;q}"

+ }

+ 

+ # get dump mode by fadump value

+ # return

+ #  - fadump, if fadump=on or fadump=nocma

+ #  - kdump, if fadump=off or empty fadump, return kdump

+ #  - error if otherwise

+ get_dump_mode_by_fadump_val()

+ {

+ 	local _fadump_val=$1

+ 

+ 	if [[ -z $_fadump_val ]] || [[ $_fadump_val == off ]]; then

+ 		echo -n kdump

+ 	elif [[ $_fadump_val == on ]] || [[ $_fadump_val == nocma ]]; then

+ 		echo -n fadump

+ 	else

+ 		derror "invalid fadump=$_fadump_val"

+ 		return 1

+ 	fi

+ }

+ 

+ # get dump mode of a specific kernel

+ # based on its fadump kernel cmdline parameter

+ get_dump_mode_by_kernel()

+ {

+ 	local _kernel_path=$1 _fadump_val _dump_mode

+ 

+ 	_fadump_val=$(get_grub_kernel_boot_parameter "$_kernel_path" fadump)

+ 	if _dump_mode=$(get_dump_mode_by_fadump_val "$_fadump_val"); then

+ 		echo -n "$_dump_mode"

+ 	else

+ 		derror "failed to get dump mode for kernel $_kernel_path"

+ 		exit

+ 	fi

+ }

+ 

+ _filter_grubby_kernel_str()

+ {

+ 	local _grubby_kernel_str=$1

+ 	echo -n "$_grubby_kernel_str" | sed -n -e 's/^kernel="\(.*\)"/\1/p'

+ }

+ 

+ _find_kernel_path_by_release()

+ {

+ 	local _release="$1" _grubby_kernel_str _kernel_path

+ 	_grubby_kernel_str=$(grubby --info ALL | grep "^kernel=.*$_release")

+ 	_kernel_path=$(_filter_grubby_kernel_str "$_grubby_kernel_str")

+ 	if [[ -z $_kernel_path ]]; then

+ 		derror "kernel $_release doesn't exist"

+ 		return 1

  	fi

+ 	echo -n "$_kernel_path"

+ }

+ 

+ _get_current_running_kernel_path()

+ {

+ 	local _release _path

+ 

+ 	_release=$(uname -r)

+ 	if _path=$(_find_kernel_path_by_release "$_release"); then

+ 		echo -n "$_path"

+ 	else

+ 		return 1

+ 	fi

+ }

+ 

+ _update_grub()

+ {

+ 	local _kernel_path=$1 _crashkernel=$2 _dump_mode=$3 _fadump_val=$4

  

  	if is_atomic; then

  		if rpm-ostree kargs | grep -q "crashkernel="; then

- 			rpm-ostree --replace="crashkernel=$crashkernel_default"

+ 			rpm-ostree kargs --replace="crashkernel=$_crashkernel"

  		else

- 			rpm-ostree --append="crashkernel=$crashkernel_default"

+ 			rpm-ostree kargs --append="crashkernel=$_crashkernel"

  		fi

  	else

- 		entry=$(grubby --info ALL | grep "^kernel=.*$kernel")

- 		entry=${entry#kernel=}

- 		entry=${entry#\"}

- 		entry=${entry%\"}

+ 		[[ -f /etc/zipl.conf ]] && zipl_arg="--zipl"

+ 		grubby --args "crashkernel=$_crashkernel" --update-kernel "$_kernel_path" $zipl_arg

+ 		if [[ $_dump_mode == kdump ]]; then

+ 			grubby --remove-args="fadump" --update-kernel "$_kernel_path"

+ 		else

+ 			grubby --args="fadump=$_fadump_val" --update-kernel "$_kernel_path"

+ 		fi

+ 	fi

+ 	[[ $zipl_arg ]] && zipl > /dev/null

+ }

+ 

+ _valid_grubby_kernel_path()

+ {

+ 	[[ -n "$1" ]] && grubby --info="$1" > /dev/null 2>&1

+ }

+ 

+ _get_all_kernels_from_grubby()

+ {

+ 	local _kernels _line _kernel_path _grubby_kernel_path=$1

+ 

+ 	for _line in $(grubby --info "$_grubby_kernel_path" | grep "^kernel="); do

+ 		_kernel_path=$(_filter_grubby_kernel_str "$_line")

+ 		_kernels="$_kernels $_kernel_path"

+ 	done

+ 	echo -n "$_kernels"

+ }

+ 

+ GRUB_ETC_DEFAULT="/etc/default/grub"

+ # modify the kernel command line parameter in default grub conf

+ #

+ # $1: the name of the kernel command line parameter

+ # $2: new value. If empty, the parameter would be removed

+ _update_kernel_cmdline_in_grub_etc_default()

+ {

+ 	local _para=$1 _val=$2 _para_val _regex

+ 

+ 	if [[ -n $_val ]]; then

+ 		_para_val="$_para=$_val"

+ 	fi

+ 

+ 	_regex='^(GRUB_CMDLINE_LINUX=.*)([[:space:]"])'"$_para"'=[^[:space:]"]*(.*)$'

+ 	if grep -q -E "$_regex" "$GRUB_ETC_DEFAULT"; then

+ 		sed -i -E 's/'"$_regex"'/\1\2'"$_para_val"'\3/' "$GRUB_ETC_DEFAULT"

+ 	elif [[ -n $_para_val ]]; then

+ 		# If the kernel parameter doesn't exist, put it in the first

+ 		sed -i -E 's/^(GRUB_CMDLINE_LINUX=")/\1'"$_para_val"' /' "$GRUB_ETC_DEFAULT"

+ 	fi

+ }

  

- 		if [[ -f $grub_etc_default ]]; then

- 			sed -i -e "s/^\(GRUB_CMDLINE_LINUX=.*\)crashkernel=[^\ \"]*\([\ \"].*\)$/\1$crashkernel_default\2/" "$grub_etc_default"

+ reset_crashkernel()

+ {

+ 	local _opt _val _dump_mode _fadump_val _reboot _grubby_kernel_path _kernel _kernels

+ 	local _old_crashkernel _new_crashkernel _new_dump_mode _crashkernel_changed

+ 	local _new_fadump_val _old_fadump_val _what_is_updated

+ 

+ 	for _opt in "$@"; do

+ 		case "$_opt" in

+ 			--fadump=*)

+ 				_val=${_opt#*=}

+ 				if _dump_mode=$(get_dump_mode_by_fadump_val $_val); then

+ 					_fadump_val=$_val

+ 				else

+ 					derror "failed to determine dump mode"

+ 					exit

+ 				fi

+ 				;;

+ 			--kernel=*)

+ 				_val=${_opt#*=}

+ 				if ! _valid_grubby_kernel_path $_val; then

+ 					derror "Invalid $_opt, please specify a valid kernel path, ALL or DEFAULT"

+ 					exit

+ 				fi

+ 				_grubby_kernel_path=$_val

+ 				;;

+ 			--reboot)

+ 				_reboot=yes

+ 				;;

+ 			*)

+ 				derror "$_opt not recognized"

+ 				exit 1

+ 				;;

+ 		esac

+ 	done

+ 

+ 	# 1. CoreOS uses "rpm-ostree kargs" instead of grubby to manage kernel command

+ 	#    line. --kernel=ALL doesn't make sense for CoreOS.

+ 	# 2. CoreOS doesn't support POWER so the dump mode is always kdump.

+ 	# 3. "rpm-ostree kargs" would prompt the user to reboot the system after

+ 	#    modifying the kernel command line so there is no need for kexec-tools

+ 	#    to repeat it.

+ 	if is_atomic; then

+ 		_old_crashkernel=$(rpm-ostree kargs | sed -n -E 's/.*(^|\s)crashkernel=(\S*).*/\2/p')

+ 		_new_dump_mode=kdump

+ 		_new_crashkernel=$(kdump_get_arch_recommend_crashkernel "$_new_dump_mode")

+ 		if [[ $_old_crashkernel != "$_new_crashkernel" ]]; then

+ 			_update_grub "" "$_new_crashkernel" "$_new_dump_mode" ""

+ 			if [[ $_reboot == yes ]]; then

+ 				systemctl reboot

+ 			fi

  		fi

+ 		return

+ 	fi

  

- 		[[ -f /etc/zipl.conf ]] && zipl_arg="--zipl"

- 		grubby --args "$crashkernel_default" --update-kernel "$entry" $zipl_arg

- 		[[ $zipl_arg ]] && zipl > /dev/null

+ 	# For non-ppc64le systems, the dump mode is always kdump since only ppc64le

+ 	# has FADump.

+ 	if [[ -z $_dump_mode && $(uname -m) != ppc64le ]]; then

+ 		_dump_mode=kdump

+ 		_fadump_val=off

+ 	fi

+ 

+ 	# If the dump mode is determined, we can also know the default crashkernel value

+ 	if [[ -n $_dump_mode ]]; then

+ 		_crashkernel=$(kdump_get_arch_recommend_crashkernel "$_dump_mode")

+ 	fi

+ 

+ 	# If --kernel-path=ALL, update GRUB_CMDLINE_LINUX in /etc/default/grub.

+ 	#

+ 	# An exception case is when the ppc64le user doesn't specify the fadump value.

+ 	# In this case, the dump mode would be determined by parsing the kernel

+ 	# command line of the kernel(s) to be updated thus don't update GRUB_CMDLINE_LINUX.

+ 	#

+ 	# The following code has been simplified because of what has been done early,

+ 	#   - set the dump mode as kdump for non-ppc64le cases

+ 	#   - retrieved the default crashkernel value for given dump mode

+ 	if [[ $_grubby_kernel_path == ALL && -n $_dump_mode ]]; then

+ 		_update_kernel_cmdline_in_grub_etc_default crashkernel "$_crashkernel"

+ 		# remove the fadump if fadump is disabled

+ 		[[ $_fadump_val == off ]] && _fadump_val=""

+ 		_update_kernel_cmdline_in_grub_etc_default fadump "$_fadump_val"

+ 	fi

+ 

+ 	# If kernel-path not specified, either

+ 	#  - use KDUMP_KERNELVER if it's defined

+ 	#  - use current running kernel

+ 	if [[ -z $_grubby_kernel_path ]]; then

+ 		if [[ -z $KDUMP_KERNELVER ]] ||

+ 			! _kernel_path=$(_find_kernel_path_by_release "$KDUMP_KERNELVER"); then

+ 					if ! _kernel_path=$(_get_current_running_kernel_path); then

+ 						derror "no running kernel found"

+ 						exit 1

+ 					fi

+ 		fi

+ 		_kernels=$_kernel_path

+ 	else

+ 		_kernels=$(_get_all_kernels_from_grubby "$_grubby_kernel_path")

+ 	fi

+ 

+ 	for _kernel in $_kernels; do

+ 		if [[ -z $_dump_mode ]]; then

+ 			_new_dump_mode=$(get_dump_mode_by_kernel "$_kernel")

+ 			_new_crashkernel=$(kdump_get_arch_recommend_crashkernel "$_new_dump_mode")

+ 			_new_fadump_val=$(get_grub_kernel_boot_parameter "$_kernel" fadump)

+ 		else

+ 			_new_dump_mode=$_dump_mode

+ 			_new_crashkernel=$_crashkernel

+ 			_new_fadump_val=$_fadump_val

+ 		fi

+ 

+ 		_old_crashkernel=$(get_grub_kernel_boot_parameter "$_kernel" crashkernel)

+ 		_old_fadump_val=$(get_grub_kernel_boot_parameter "$_kernel" fadump)

+ 		if [[ $_old_crashkernel != "$_new_crashkernel" || $_old_fadump_val != "$_new_fadump_val" ]]; then

+ 			_update_grub "$_kernel" "$_new_crashkernel" "$_new_dump_mode" "$_new_fadump_val"

+ 			if [[ $_reboot != yes ]]; then

+ 				if [[ $_old_crashkernel != "$_new_crashkernel" ]]; then

+ 					_what_is_updated="Updated crashkernel=$_new_crashkernel"

+ 				else

+ 					# This case happens only when switching between fadump=on and fadump=nocma

+ 					_what_is_updated="Updated fadump=$_new_fadump_val"

+ 				fi

+ 				dwarn "$_what_is_updated for kernel=$_kernel. Please reboot the system for the change to take effect."

+ 			fi

+ 			_crashkernel_changed=yes

+ 		fi

+ 	done

+ 

+ 	if [[ $_reboot == yes && $_crashkernel_changed == yes ]]; then

+ 		reboot

+ 	fi

+ }

+ 

+ # shellcheck disable=SC2154 # false positive when dereferencing an array

+ reset_crashkernel_after_update()

+ {

+ 	local _kernel _crashkernel _dump_mode _fadump_val _old_default_crashkernel _new_default_crashkernel

+ 	declare -A _crashkernel_vals

+ 

+ 	_crashkernel_vals[old_kdump]=$(cat /tmp/old_default_crashkernel 2> /dev/null)

+ 	_crashkernel_vals[old_fadump]=$(cat /tmp/old_default_crashkernel_fadump 2> /dev/null)

+ 	_crashkernel_vals[new_kdump]=$(get_default_crashkernel kdump)

+ 	_crashkernel_vals[new_fadump]=$(get_default_crashkernel fadump)

+ 

+ 	for _kernel in $(_get_all_kernels_from_grubby); do

+ 		_crashkernel=$(get_grub_kernel_boot_parameter "$_kernel" crashkernel)

+ 		if [[ $_crashkernel == auto ]]; then

+ 			reset_crashkernel "--kernel=$_kernel"

+ 		elif [[ -n $_crashkernel ]]; then

+ 			_dump_mode=$(get_dump_mode_by_kernel "$_kernel")

+ 			_old_default_crashkernel=${_crashkernel_vals[old_${_dump_mode}]}

+ 			_new_default_crashkernel=${_crashkernel_vals[new_${_dump_mode}]}

+ 			if [[ $_crashkernel == "$_old_default_crashkernel" ]] &&

+ 				[[ $_new_default_crashkernel != "$_old_default_crashkernel" ]]; then

+ 				_fadump_val=$(get_grub_kernel_boot_parameter "$_kernel" fadump)

+ 				if _update_grub "$_kernel" "$_new_default_crashkernel" "$_dump_mode" "$_fadump_val"; then

+ 					echo "For kernel=$_kernel, crashkernel=$_new_default_crashkernel now."

+ 				fi

+ 			fi

+ 		fi

+ 	done

+ }

+ 

+ _is_osbuild()

+ {

+ 	[[ $(sed -n -E 's/.*(^|\s)container=(\S*).*/\2/p' < /proc/1/environ) == bwrap-osbuild ]]

+ }

+ 

+ reset_crashkernel_for_installed_kernel()

+ {

+ 	local _installed_kernel _running_kernel _crashkernel _crashkernel_running

+ 	local _dump_mode_running _fadump_val_running

+ 

+ 	if ! _installed_kernel=$(_find_kernel_path_by_release "$1"); then

+ 		exit 1

+ 	fi

+ 

+ 	if _is_osbuild && ! grep -q crashkernel= /etc/kernel/cmdline; then

+ 		reset_crashkernel "--kernel=$_installed_kernel"

+ 		return

+ 	fi

+ 

+ 	if ! _running_kernel=$(_get_current_running_kernel_path); then

+ 		derror "Couldn't find current running kernel"

+ 		exit

+ 	fi

+ 

+ 	_crashkernel=$(get_grub_kernel_boot_parameter "$_installed_kernel" crashkernel)

+ 	_crashkernel_running=$(get_grub_kernel_boot_parameter "$_running_kernel" crashkernel)

+ 	_dump_mode_running=$(get_dump_mode_by_kernel "$_running_kernel")

+ 	_fadump_val_running=$(get_grub_kernel_boot_parameter "$_kernel" fadump)

+ 

+ 	if [[ $_crashkernel != "$_crashkernel_running" ]]; then

+ 		if _update_grub "$_installed_kernel" "$_crashkernel_running" "$_dump_mode_running" "$_fadump_val_running"; then

+ 			echo "kexec-tools has reset $_installed_kernel to use the new default crashkernel value $_crashkernel_running"

+ 		fi

  	fi

  }

  
@@ -1361,8 +1665,22 @@ 

  	estimate)

  		do_estimate

  		;;

+ 	get-default-crashkernel)

+ 		get_default_crashkernel "$2"

+ 		;;

  	reset-crashkernel)

- 		reset_crashkernel "$2"

+ 		shift

+ 		reset_crashkernel "$@"

+ 		;;

+ 	reset-crashkernel-after-update)

+ 		if [[ $(kdump_get_conf_val auto_reset_crashkernel) != no ]]; then

+ 			reset_crashkernel_after_update

+ 		fi

+ 		;;

+ 	reset-crashkernel-for-installed_kernel)

+ 		if [[ $(kdump_get_conf_val auto_reset_crashkernel) != no ]]; then

+ 			reset_crashkernel_for_installed_kernel "$2"

+ 		fi

  		;;

  	*)

  		dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|reset-crashkernel|propagate|showmem}"

file modified
+12 -7
@@ -50,14 +50,19 @@ 

  best-effort estimate. It will print a recommanded crashkernel value

  based on current kdump setup, and list some details of memory usage.

  .TP

- .I reset-crashkernel [KERNEL]

- Reset crashkernel value to default value. kdumpctl will try to read

- from /usr/lib/modules/<KERNEL>/crashkernel.default and reset specified

- kernel's crashkernel cmdline value. If no kernel is

- specified, will reset current running kernel's crashkernel value.

- If /usr/lib/modules/<KERNEL>/crashkernel.default doesn't exist, will

- simply exit return 1.

+ .I reset-crashkernel [--kernel=path_to_kernel] [--reboot]

+ Reset crashkernel to default value recommended by kexec-tools. If no kernel

+ is specified, will reset KDUMP_KERNELVER if it's defined in /etc/sysconfig/kdump

+ or current running kernel's crashkernel value if KDUMP_KERNELVER is empty. You can

+ also specify --kernel=ALL and --kernel=DEFAULT which have the same meaning as

+ grubby's kernel-path=ALL and kernel-path=DEFAULT. ppc64le supports FADump and

+ supports an additonal [--fadump=[on|off|nocma]] parameter to toggle FADump

+ on/off.

  

+ Note: The memory requirements for kdump varies heavily depending on the

+ used hardware and system configuration. Thus the recommended

+ crashkernel might not work for your specific setup. Please test if

+ kdump works after resetting the crashkernel value.

  

  .SH "SEE ALSO"

  .BR kdump.conf (5),

file modified
+22
@@ -258,6 +258,15 @@ 

  mkdir -p $RPM_BUILD_ROOT/%{dracutlibdir}/modules.d/

  mv $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/* $RPM_BUILD_ROOT/%{dracutlibdir}/modules.d/

  

+ %pre

+ # save the old default crashkernel values to /tmp/ when upgrading the package

+ if ! grep -q "ostree" /proc/cmdline && [ $1 == 2 ] && grep -q get-default-crashkernel /usr/bin/kdumpctl; then

+   kdumpctl get-default-crashkernel kdump > /tmp/old_default_crashkernel 2>/dev/null

+ %ifarch ppc64 ppc64le

+   kdumpctl get-default-crashkernel fadump > /tmp/old_default_crashkernel_fadump 2>/dev/null

+ %endif

+ fi

+ 

  %post

  # Initial installation

  %systemd_post kdump.service
@@ -291,6 +300,19 @@ 

  	mv /etc/sysconfig/kdump.new /etc/sysconfig/kdump

  fi

  

+ # try to reset kernel crashkernel value to new default value when upgrading

+ # the package

+ if ! grep -q "ostree" /proc/cmdline && [ $1 == 2 ]; then

+   kdumpctl reset-crashkernel-after-update

+   rm /tmp/old_default_crashkernel 2>/dev/null

+ %ifarch ppc64 ppc64le

+   rm /tmp/old_default_crashkernel_fadump 2>/dev/null

+ %endif

+   # dnf would complain about the exit code not being 0. To keep it happy,

+   # always return 0

+   :

+ fi

+ 

  

  %postun

  %systemd_postun_with_restart kdump.service

The crashkernel=auto implementation in kernel space has been rejected
upstream [1]. The current user space implementation [2] [3] ships a
crashkernel.default but hasn't supported fadump. Meanwhile the
crashkernel.default implementation seems to be overly complex,
- the default kernel crashkernel value rarely changes. This is no
need to ship the same crashkernel.default default for every kernel
package of a architecture;
- when deciding the value of crashkernel for a new kernel, the
crashkernel.default of installed kernels and running kernel
is took into consideration (for the details, check
92-crashnernel.install).

According to Kairui [4], crashkernel.default per kernel package is to
accommodate kernel difference, for example, different kernels could be
built with different configurations thus different crashkernel values
are needed. But these should be minor cases and may not be sufficent to
justify the complexity of 92-crashkernel.install. Currently, we don't
know how a kernel debug/feature config would affect the crashkernel
value. Even if a kernel config may require much larger crashkernel, we
can address it in kexec-tools later.

There are are known cases that could lead to a larger crashkernel
including enabling SME, LUKS encryption and etc. But this patch set
would put them aside since they may be took care of in the kernel
space instead.

So this patch set would simply add support for fadump and move the
default kernel crashkernel from kernel package to kexec-tools,
- provide "kdumpctl get-default-crashkernel" for kdump-anaconda-addon
to get the default kernel crashkernel values for a specific
architecture (fadump is supported as well)
- re-write "kdumpctl reset-crashkernel" to support fadump
- introduce auto_reset_crashkernel which determines whether to reset
kernel crashkernel to new default value or not when kexec-tools updates
the default crashkernel value

Because the kernel hook /usr/lib/kernel/install.d/20-grub.install would
make the installed kernel inherit the kernel cmdline of current running
kernel i.e. /proc/cmdline, we only need to reset crashkernel when
kexec-tools increases the default crashkernel values.

[1] https://lore.kernel.org/linux-mm/20210507010432.IN24PudKT%25akpm@linux-foundation.org/
[2] https://gitlab.com/cki-project/kernel-ark/-/merge_requests/1171
[3] https://lists.fedoraproject.org/archives/list/kexec@lists.fedoraproject.org/thread/PDLFXHJSOOOOKVXBNIX7FUM4DIBFP3S7/#J6DPR6AIHICADPGXD2B75EFJX6AHPUNS
[4] https://lists.fedoraproject.org/archives/list/kexec@lists.fedoraproject.org/message/4GDCW2TUGV347ET4ZH3SJPOKFPFX5AWM/

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci

Pull-Request has been merged by coiby

2 years ago