In RHEL, kernel supports a `crashkernel=auto` param and when it's used, kernel will use its built-in default value as the crashkernel value. But upstream doesn't like this idea. [1]
`crashkernel=auto` was introduced to provide user a default value, and make it possible to update the crashkernel value automatically as kernel package updates if user is using the default `auto` value.
After more discussion, `crashkernel=auto` will be dropped. To track the default crashkernel value, kernel package can include a crashkernel.conf file with it, and kexec-tools can make use of that file, update kernel's boot cmdline accordingly, and help user to reset the crashkernel value to default value.
[1]: https://lore.kernel.org/linux-mm/20210507010432.IN24PudKT%25akpm@linux-found...
Kairui Song (2): kdumpctl: Add kdumpctl reset-crashkernel Add a new hook: 92-crashkernel.install
92-crashkernel.install | 131 +++++++++++++++++++++++++++++++++++++++++ kdumpctl | 32 +++++++++- kdumpctl.8 | 9 +++ kexec-tools.spec | 4 ++ 4 files changed, 174 insertions(+), 2 deletions(-) create mode 100755 92-crashkernel.install
In newer kernel, crashkernel.conf will contain the default crashkernel value of a kernel build. So introduce a new sub command to help user reset kernel crashkernel size to the default value.
Signed-off-by: Kairui Song kasong@redhat.com --- kdumpctl | 33 +++++++++++++++++++++++++++++++-- kdumpctl.8 | 9 +++++++++ 2 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/kdumpctl b/kdumpctl index 978dae5..f5b6a7f 100755 --- a/kdumpctl +++ b/kdumpctl @@ -1340,6 +1340,32 @@ do_estimate() { fi }
+reset_crashkernel() { + local kernel=$1 entry crashkernel_conf + local grub_etc_default="/etc/default/grub" + + [[ -z "$kernel" ]] && kernel=$(uname -r) + crashkernel_conf=$(cat "/usr/lib/modules/$kernel/crashkernel.conf" 2>/dev/null) + + if [[ -z "$crashkernel_conf" ]]; then + derror "$kernel doesn't have a crashkernel.conf" + exit 1 + fi + + entry=$(grubby --info ALL | grep "^kernel=.*$kernel") + entry=${entry#kernel=} + entry=${entry#"} + entry=${entry%"} + + if [[ -f "$grub_etc_default" ]]; then + sed -i -e "s/^(GRUB_CMDLINE_LINUX=.*)crashkernel=[^\ "]*([\ "].*)$/\1$crashkernel_conf\2/" "$grub_etc_default" + fi + + [[ -f /etc/zipl.conf ]] && zipl_arg="--zipl" + grubby --args "$crashkernel_conf" --update-kernel "$entry" $zipl_arg + [[ $zipl_arg ]] && zipl > /dev/null +} + if [ ! -f "$KDUMP_CONFIG_FILE" ]; then derror "Error: No kdump config file found!" exit 1 @@ -1398,8 +1424,11 @@ main () estimate) do_estimate ;; + reset-crashkernel) + reset_crashkernel "$2" + ;; *) - dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|propagate|showmem}" + dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|reset-crashkernel|propagate|showmem}" exit 1 esac } @@ -1409,6 +1438,6 @@ single_instance_lock
# To avoid fd 9 leaking, we invoke a subshell, close fd 9 and call main. # So that fd isn't leaking when main is invoking a subshell. -(exec 9<&-; main $1) +(exec 9<&-; main "$@")
exit $? diff --git a/kdumpctl.8 b/kdumpctl.8 index a32a972..844601e 100644 --- a/kdumpctl.8 +++ b/kdumpctl.8 @@ -49,6 +49,15 @@ Prints the size of reserved memory for crash kernel in megabytes. Estimate a suitable crashkernel value for current machine. This is a best-effort estimate. It will print a recommanded crashkernel value based on current kdump setup, and list some details of memory usage. +.TP +.I reset-crashkernel [KERNEL] +Reset crashkernel value to default value. kdumpctl will try to read +from /usr/lib/modules/<KERNEL>/crashkernel.conf 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.conf doesn't exist, will +simply exit return 1. +
.SH "SEE ALSO" .BR kdump.conf (5),
To track and manage kernel's crashkernel usage by kernel version, each kernel package will include a crashkernel.conf containing the default `crashkernel=` value of that kernel. So we can use a hook to update the kernel cmdline of new installed kernel accordingly.
Put it after all other grub boot loader setup hooks, so it can simply call grubby to modify the kernel cmdline.
Signed-off-by: Kairui Song kasong@redhat.com --- 92-crashkernel.install | 131 +++++++++++++++++++++++++++++++++++++++++ kexec-tools.spec | 4 ++ 2 files changed, 135 insertions(+) create mode 100755 92-crashkernel.install
diff --git a/92-crashkernel.install b/92-crashkernel.install new file mode 100755 index 0000000..036a1c5 --- /dev/null +++ b/92-crashkernel.install @@ -0,0 +1,131 @@ +#!/usr/bin/bash + +COMMAND="$1" +KERNEL_VERSION="$2" +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_default_ck() { + sed -n -e "s/^GRUB_CMDLINE_LINUX=.*(crashkernel=[^\ "]*)[\ "].*$/\1/p" $grub_etc_default +} + +# Read crashkernel.conf value of specified kernel +get_ck_conf() { + ck_conf="/usr/lib/modules/$KERNEL_VERSION/crashkernel.conf" + [[ -f "$ck_conf" ]] && cat "$ck_conf" +} + +# Get latest installed kernel that have a crashkernel.conf, exclude current installing/removing kernel +# $1: If given, search for the kernel that have this value in crashkernel.conf value +get_latest_ck_conf_kernel() { + for kernel in $(find /usr/lib/modules -maxdepth 1 -mindepth 1 -printf "%f\n" | sort --version-sort -r); do + [[ $kernel == "$KERNEL_VERSION" ]] && continue + [[ -f "/usr/lib/modules/$kernel/crashkernel.conf" ]] || continue + + echo "$kernel" + return 0 + done + + return 1 +} + +update_grub_defaults() { + sed -i -e "s/^(GRUB_CMDLINE_LINUX=.*)crashkernel=[^\ "]*([\ "].*)$/\1$1\2/" "$grub_etc_default" +} + +# Update new installed kernel's crashkernel cmdline value, +# new installed kernel inherits boot kernel's cmdline by default, +update_new_kernel_ck() { + kernel=$KERNEL_VERSION + entry=$(grubby --info ALL | grep "^kernel=.*$kernel") + entry=${entry#kernel=} + entry=${entry#"} + entry=${entry%"} + + [[ -f /etc/zipl.conf ]] && zipl_arg="--zipl" + grubby --args "$new_ck_conf" --update-kernel "$entry" $zipl_arg + [[ $zipl_arg ]] && zipl > /dev/null +} + +case "$COMMAND" in +add) + # This install hook does following things: + # 1. Update new installed kernel's crashkernel value to its own default + # value, if current boot kernel is using default value. + # 2. Update /etc/default/grub's crashkernel value, if new installed + # kernel have a higher verison number and /etc/default/grub is using + # default value of latest installed kernel. + boot_kernel=$(uname -r) + boot_ck_cmdline=$(sed -n -e "s/^.*(crashkernel=\S*).*$/\1/p" /proc/cmdline) + new_ck_conf=$(get_ck_conf "$KERNEL_VERSION") + latest_ck_conf_kernel=$(get_latest_ck_conf_kernel) + latest_ck_conf=$(get_ck_conf "$latest_ck_conf_kernel") + + # If new installing kernel doesn't have a crashkernel.conf, consider latest installed kernel's crashkernel.conf as the default value. + new_ck_conf=${new_ck_conf:-$latest_ck_conf} + # If new installing kernel doesn't have a crashkernel.conf, and none of installed kernel have one, nothing to do, just exit. + [[ -z "$new_ck_conf" ]] && exit 0 + + # If upgrading to a newer kernel, try update /etc/default/grub + # + # /etc/default/grub is only used by grub2-mkconfig and anaconda. + # When user trigger grub2-mkconfig, crashkernel value will be + # override with this config file. + # + # Only update it if it's default value or `auto`. + if [[ -e "$grub_etc_default" ]]; then + grub_etc_ck=$(get_grub_default_ck) + if [[ -z "$latest_ck_conf_kernel" ]] || ver_lt "$latest_ck_conf_kernel" "$KERNEL_VERSION"; then + if [[ "$grub_etc_ck" == "$latest_ck_conf" ]] || [[ "$grub_etc_ck" == "crashkernel=auto" ]]; then + [[ "$grub_etc_ck" != "$new_ck_conf" ]] && update_grub_defaults "$new_ck_conf" + fi + fi + fi + + # If crashkernel is not used in current cmdline, just exit + [[ -z "$boot_ck_cmdline" ]] && exit 0 + + # Get boot kernel's default value + boot_ck_conf=$(get_ck_conf "$boot_kernel") + # For legacy RHEL kernel + if [[ $boot_ck_cmdline == "crashkernel=auto" ]]; then + boot_ck_conf="$boot_ck_cmdline" + fi + + # If boot kernel doesn't have a crashkernel.conf, check if it's using a previous kernel's crashkernel.conf + if [[ -z "$boot_ck_conf" ]]; then + if [[ "$boot_ck_cmdline" != "$latest_ck_conf" ]]; then + boot_ck_conf=$(get_latest_ck_conf_kernel "$boot_ck_cmdline") + fi + fi + + # If boot kernel is using default crashkernel, new installed kernel also follow default value + if [[ "$boot_ck_cmdline" != "$new_ck_conf" ]] && [[ "$boot_ck_cmdline" == "$boot_ck_conf" ]]; then + update_new_kernel_ck "$new_ck_conf" + fi + + ;; +remove) + # If grub default value is upgraded when this kernel was installed, try downgrade it + [[ -e "$grub_etc_default" ]] || exit 0 + grub_etc_ck=$(get_grub_default_ck) + removing_ck_conf=$(get_ck_conf "$KERNEL_VERSION") + latest_ck_conf_kernel=$(get_latest_ck_conf_kernel) || exit 0 + latest_ck_conf=$(get_ck_conf "$latest_ck_conf_kernel") + + [[ "$latest_ck_conf" ]] || exit 0 + + if ver_lt "$latest_ck_conf_kernel" "$KERNEL_VERSION"; then + if [[ $grub_etc_ck == "$removing_ck_conf" ]] && [[ $grub_etc_ck != "$latest_ck_conf" ]]; then + update_grub_defaults "$latest_ck_conf" + fi + fi + ;; +esac diff --git a/kexec-tools.spec b/kexec-tools.spec index e94ed02..a01df7c 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -39,6 +39,7 @@ Source28: kdump-udev-throttler Source29: kdump.sysconfig.aarch64 Source30: 60-kdump.install Source31: kdump-logger.sh +Source32: 92-crashkernel.install
####################################### # These are sources for mkdumpramfs @@ -62,6 +63,7 @@ Requires: dracut >= 050 Requires: dracut-network >= 050 Requires: dracut-squash >= 050 Requires: ethtool +Requires: grubby BuildRequires: make BuildRequires: zlib-devel elfutils-devel glib2-devel bzip2-devel ncurses-devel bison flex lzo-devel snappy-devel BuildRequires: pkgconfig intltool gettext @@ -198,6 +200,7 @@ install -m 644 %{SOURCE15} $RPM_BUILD_ROOT%{_mandir}/man5/kdump.conf.5 install -m 644 %{SOURCE16} $RPM_BUILD_ROOT%{_unitdir}/kdump.service install -m 755 -D %{SOURCE22} $RPM_BUILD_ROOT%{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh install -m 755 -D %{SOURCE30} $RPM_BUILD_ROOT%{_prefix}/lib/kernel/install.d/60-kdump.install +install -m 755 -D %{SOURCE32} $RPM_BUILD_ROOT%{_prefix}/lib/kernel/install.d/92-crashkernel.install
%ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 install -m 755 makedumpfile-%{mkdf_ver}/makedumpfile $RPM_BUILD_ROOT/usr/sbin/makedumpfile @@ -339,6 +342,7 @@ done %{_unitdir}/kdump.service %{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh %{_prefix}/lib/kernel/install.d/60-kdump.install +%{_prefix}/lib/kernel/install.d/92-crashkernel.install %doc News %license COPYING %doc TODO