#!/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