On 06/30/21 at 02:43pm, Kairui Song wrote:
To track and manage kernel's crashkernel usage by kernel
version,
each kernel package will include a crashkernel.default 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(a)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..2330344
--- /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.default value of specified kernel
+get_ck_conf() {
+ ck_conf="/usr/lib/modules/$KERNEL_VERSION/crashkernel.default"
+ [[ -f "$ck_conf" ]] && cat "$ck_conf"
+}
+
+# Get latest installed kernel that have a crashkernel.default, exclude current
installing/removing kernel
+# $1: If given, search for the kernel that have this value in crashkernel.default value
I guess you are saying the kernel which version is highest and owns a
crashkernel.default, but not the latest on installing time.
Don't get what the given value is used for and its description.
+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.default" ]] || 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,
These 'new installed kernel', 'new installing kernel', 'latest
installed
kernel' are too messy. We may need clean up them to unified the
represented stuff.
+# 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.default, consider latest
installed kernel's crashkernel.default as the default value.
+ new_ck_conf=${new_ck_conf:-$latest_ck_conf}
+ # If new installing kernel doesn't have a crashkernel.default, 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.default, check if it's using a
previous kernel's crashkernel.default
+ 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 8fed959..ec327da 100644
--- a/kexec-tools.spec
+++ b/kexec-tools.spec
@@ -40,6 +40,7 @@ Source29: kdump.sysconfig.aarch64
Source30: 60-kdump.install
Source31: kdump-logger.sh
Source32: mkfadumprd
+Source33: 92-crashkernel.install
#######################################
# These are sources for mkdumpramfs
@@ -66,6 +67,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
@@ -210,6 +212,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
@@ -360,6 +363,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
--
2.31.1