diff --git a/92-crashkernel.install b/92-crashkernel.install new file mode 100755 index 0000000..7613bc6 --- /dev/null +++ b/92-crashkernel.install @@ -0,0 +1,143 @@ +#!/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_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 + ;; + +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 + ;; +esac diff --git a/kexec-tools.spec b/kexec-tools.spec index 8fed959..9848c2d 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 %{SOURCE33} $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