Kdump uses currently running kernel as default, but when currently running kernel is a debug kernel, it will consume more memory, which may cause out-of-memory and fail to collect vmcore.
Now we will try to use non-debug kernels first if possible.
Also extract the logic of determine KDUMP_KERNEL from prepare_kdump_bootinfo into a function. This function will return KDUMP_KERNEL given a kernel version.
Signed-off-by: Lichen Liu lichliu@redhat.com --- Update from V1: - extract the logic of determine KDUMP_KERNEL from prepare_kdump_bootinfo into a function.
kdump-lib.sh | 63 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 18 deletions(-)
diff --git a/kdump-lib.sh b/kdump-lib.sh index b137c89..a39e5b1 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -633,40 +633,67 @@ prepare_kexec_args() echo "$kexec_args" }
-# -# Detect initrd and kernel location, results are stored in global enviromental variables: -# KDUMP_BOOTDIR, KDUMP_KERNELVER, KDUMP_KERNEL, DEFAULT_INITRD, and KDUMP_INITRD -# -# Expectes KDUMP_BOOTDIR, KDUMP_IMG, KDUMP_IMG_EXT, KDUMP_KERNELVER to be loaded from config already -# and will prefer already set values so user can specify custom kernel/initramfs location -# -prepare_kdump_bootinfo() +# prepare_kdump_kernel <kdump_kernelver> +# This function return kdump_kernel given a kernel version. +prepare_kdump_kernel() { - local boot_img boot_imglist boot_dirlist boot_initrdlist - local machine_id dir img default_initrd_base var_target_initrd_dir - - if [[ -z $KDUMP_KERNELVER ]]; then - KDUMP_KERNELVER="$(uname -r)" - fi - + local kdump_kernelver=$1 + local boot_dirlist boot_imglist kdump_kernel machine_id read -r machine_id < /etc/machine-id + boot_dirlist=${KDUMP_BOOTDIR:-"/boot /boot/efi /efi /"} - boot_imglist="$KDUMP_IMG-$KDUMP_KERNELVER$KDUMP_IMG_EXT $machine_id/$KDUMP_KERNELVER/$KDUMP_IMG" + boot_imglist="$KDUMP_IMG-$kdump_kernelver$KDUMP_IMG_EXT $machine_id/$kdump_kernelver/$KDUMP_IMG"
# Use BOOT_IMAGE as reference if possible, strip the GRUB root device prefix in (hd0,gpt1) format boot_img="$(sed "s/^BOOT_IMAGE=((\S*))?(\S*) .*/\2/" /proc/cmdline)" - if [[ -n $boot_img ]]; then + if [[ "$boot_img" == *"$kdump_kernelver" ]]; then boot_imglist="$boot_img $boot_imglist" fi
for dir in $boot_dirlist; do for img in $boot_imglist; do if [[ -f "$dir/$img" ]]; then - KDUMP_KERNEL=$(echo "$dir/$img" | tr -s '/') + kdump_kernel=$(echo "$dir/$img" | tr -s '/') break 2 fi done done + echo "$kdump_kernel" +} + +# +# Detect initrd and kernel location, results are stored in global enviromental variables: +# KDUMP_BOOTDIR, KDUMP_KERNELVER, KDUMP_KERNEL, DEFAULT_INITRD, and KDUMP_INITRD +# +# Expectes KDUMP_BOOTDIR, KDUMP_IMG, KDUMP_IMG_EXT, KDUMP_KERNELVER to be loaded from config already +# and will prefer already set values so user can specify custom kernel/initramfs location +# +prepare_kdump_bootinfo() +{ + local boot_initrdlist nondebug_kernelver debug_kernelver + local dir img default_initrd_base var_target_initrd_dir + + if [[ -z $KDUMP_KERNELVER ]]; then + KDUMP_KERNELVER="$(uname -r)" + nondebug_kernelver="$(echo -n "$KDUMP_KERNELVER" | sed -n -e 's/(.*)+debug$/\1/p')" + fi + + # Use nondebug kernel if possible, because debug kernel will consume more memory and may oom. + if [[ -n $nondebug_kernelver ]]; then + dinfo "Trying to use $nondebug_kernelver." + debug_kernelver="$KDUMP_KERNELVER" + KDUMP_KERNELVER="$nondebug_kernelver" + fi + + KDUMP_KERNEL=$(prepare_kdump_kernel "$KDUMP_KERNELVER") + + if ! [[ -e $KDUMP_KERNEL ]]; then + if [[ -n $debug_kernelver ]]; then + dinfo "Fallback to using debug kernel" + KDUMP_KERNELVER="$debug_kernelver" + KDUMP_KERNEL=$(prepare_kdump_kernel "$KDUMP_KERNELVER") + fi + fi
if ! [[ -e $KDUMP_KERNEL ]]; then derror "Failed to detect kdump kernel location"
Hi Lichen,
On Thu, May 26, 2022 at 03:12:18PM +0800, Lichen Liu wrote:
Kdump uses currently running kernel as default, but when currently running kernel is a debug kernel, it will consume more memory, which may cause out-of-memory and fail to collect vmcore.
Now we will try to use non-debug kernels first if possible.
Also extract the logic of determine KDUMP_KERNEL from prepare_kdump_bootinfo into a function. This function will return KDUMP_KERNEL given a kernel version.
Signed-off-by: Lichen Liu lichliu@redhat.com
Update from V1:
- extract the logic of determine KDUMP_KERNEL from prepare_kdump_bootinfo into a function.
kdump-lib.sh | 63 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 18 deletions(-)
diff --git a/kdump-lib.sh b/kdump-lib.sh index b137c89..a39e5b1 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -633,40 +633,67 @@ prepare_kexec_args() echo "$kexec_args" }
-# -# Detect initrd and kernel location, results are stored in global enviromental variables: -# KDUMP_BOOTDIR, KDUMP_KERNELVER, KDUMP_KERNEL, DEFAULT_INITRD, and KDUMP_INITRD -# -# Expectes KDUMP_BOOTDIR, KDUMP_IMG, KDUMP_IMG_EXT, KDUMP_KERNELVER to be loaded from config already -# and will prefer already set values so user can specify custom kernel/initramfs location -# -prepare_kdump_bootinfo() +# prepare_kdump_kernel <kdump_kernelver> +# This function return kdump_kernel given a kernel version. +prepare_kdump_kernel() {
- local boot_img boot_imglist boot_dirlist boot_initrdlist
- local machine_id dir img default_initrd_base var_target_initrd_dir
- if [[ -z $KDUMP_KERNELVER ]]; then
KDUMP_KERNELVER="$(uname -r)"
- fi
- local kdump_kernelver=$1
- local boot_dirlist boot_imglist kdump_kernel machine_id read -r machine_id < /etc/machine-id
- boot_dirlist=${KDUMP_BOOTDIR:-"/boot /boot/efi /efi /"}
- boot_imglist="$KDUMP_IMG-$KDUMP_KERNELVER$KDUMP_IMG_EXT $machine_id/$KDUMP_KERNELVER/$KDUMP_IMG"
- boot_imglist="$KDUMP_IMG-$kdump_kernelver$KDUMP_IMG_EXT $machine_id/$kdump_kernelver/$KDUMP_IMG"
You seem to insert an extra space unintentionally.
# Use BOOT_IMAGE as reference if possible, strip the GRUB root device prefix in (hd0,gpt1) format boot_img="$(sed "s/^BOOT_IMAGE=((\S*))?(\S*) .*/\2/" /proc/cmdline)"
- if [[ -n $boot_img ]]; then
if [[ "$boot_img" == *"$kdump_kernelver" ]]; then boot_imglist="$boot_img $boot_imglist" fi
for dir in $boot_dirlist; do for img in $boot_imglist; do if [[ -f "$dir/$img" ]]; then
KDUMP_KERNEL=$(echo "$dir/$img" | tr -s '/')
done donekdump_kernel=$(echo "$dir/$img" | tr -s '/') break 2 fi
- echo "$kdump_kernel"
+}
+# +# Detect initrd and kernel location, results are stored in global enviromental variables: +# KDUMP_BOOTDIR, KDUMP_KERNELVER, KDUMP_KERNEL, DEFAULT_INITRD, and KDUMP_INITRD +# +# Expectes KDUMP_BOOTDIR, KDUMP_IMG, KDUMP_IMG_EXT, KDUMP_KERNELVER to be loaded from config already +# and will prefer already set values so user can specify custom kernel/initramfs location +# +prepare_kdump_bootinfo() +{
- local boot_initrdlist nondebug_kernelver debug_kernelver
- local dir img default_initrd_base var_target_initrd_dir
dir seems to be only used in prepare_kdump_kernel?
- if [[ -z $KDUMP_KERNELVER ]]; then
KDUMP_KERNELVER="$(uname -r)"
nondebug_kernelver="$(echo -n "$KDUMP_KERNELVER" | sed -n -e 's/\(.*\)+debug$/\1/p')"
How about nondebug_kernelver=$(sed -n -e 's/(.*)+debug$/\1/p' <<< "$KDUMP_KERNELVER")?
- fi
If an user chooses to use a debug kernel for kdump by defining KDUMP_KERNELVER in /etc/sysconfig/kdump, it's better to warn the user that he/she may need to use a larger crashkernel than default crashkernel value.
# Use nondebug kernel if possible, because debug kernel will consume more memory and may oom.
if [[ -n $nondebug_kernelver ]]; then
dinfo "Trying to use $nondebug_kernelver."
debug_kernelver="$KDUMP_KERNELVER"
KDUMP_KERNELVER="$nondebug_kernelver"
fi
KDUMP_KERNEL=$(prepare_kdump_kernel "$KDUMP_KERNELVER")
if ! [[ -e $KDUMP_KERNEL ]]; then
if [[ -n $debug_kernelver ]]; then
dinfo "Fallback to using debug kernel"
KDUMP_KERNELVER="$debug_kernelver"
KDUMP_KERNEL=$(prepare_kdump_kernel "$KDUMP_KERNELVER")
fi
fi
if ! [[ -e $KDUMP_KERNEL ]]; then derror "Failed to detect kdump kernel location"
-- 2.31.1
Hi Coiby,
Thanks for the tip!
On Tue, Jun 7, 2022 at 12:30 PM Coiby Xu coxu@redhat.com wrote:
Hi Lichen,
On Thu, May 26, 2022 at 03:12:18PM +0800, Lichen Liu wrote:
Kdump uses currently running kernel as default, but when currently running kernel is a debug kernel, it will consume more memory, which may cause out-of-memory and fail to collect vmcore.
Now we will try to use non-debug kernels first if possible.
Also extract the logic of determine KDUMP_KERNEL from prepare_kdump_bootinfo into a function. This function will return KDUMP_KERNEL given a kernel version.
Signed-off-by: Lichen Liu lichliu@redhat.com
Update from V1:
- extract the logic of determine KDUMP_KERNEL from prepare_kdump_bootinfo into a function.
kdump-lib.sh | 63 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 18 deletions(-)
diff --git a/kdump-lib.sh b/kdump-lib.sh index b137c89..a39e5b1 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -633,40 +633,67 @@ prepare_kexec_args() echo "$kexec_args" }
-# -# Detect initrd and kernel location, results are stored in global enviromental variables: -# KDUMP_BOOTDIR, KDUMP_KERNELVER, KDUMP_KERNEL, DEFAULT_INITRD, and KDUMP_INITRD -# -# Expectes KDUMP_BOOTDIR, KDUMP_IMG, KDUMP_IMG_EXT, KDUMP_KERNELVER to be loaded from config already -# and will prefer already set values so user can specify custom kernel/initramfs location -# -prepare_kdump_bootinfo() +# prepare_kdump_kernel <kdump_kernelver> +# This function return kdump_kernel given a kernel version. +prepare_kdump_kernel() {
local boot_img boot_imglist boot_dirlist boot_initrdlist
local machine_id dir img default_initrd_base var_target_initrd_dir
if [[ -z $KDUMP_KERNELVER ]]; then
KDUMP_KERNELVER="$(uname -r)"
fi
local kdump_kernelver=$1
local boot_dirlist boot_imglist kdump_kernel machine_id read -r machine_id < /etc/machine-id
boot_dirlist=${KDUMP_BOOTDIR:-"/boot /boot/efi /efi /"}
boot_imglist="$KDUMP_IMG-$KDUMP_KERNELVER$KDUMP_IMG_EXT $machine_id/$KDUMP_KERNELVER/$KDUMP_IMG"
boot_imglist="$KDUMP_IMG-$kdump_kernelver$KDUMP_IMG_EXT $machine_id/$kdump_kernelver/$KDUMP_IMG"
You seem to insert an extra space unintentionally.
# Use BOOT_IMAGE as reference if possible, strip the GRUB root device prefix in (hd0,gpt1) format boot_img="$(sed "s/^BOOT_IMAGE=\((\S*)\)\?\(\S*\) .*/\2/" /proc/cmdline)"
if [[ -n $boot_img ]]; then
if [[ "$boot_img" == *"$kdump_kernelver" ]]; then boot_imglist="$boot_img $boot_imglist" fi for dir in $boot_dirlist; do for img in $boot_imglist; do if [[ -f "$dir/$img" ]]; then
KDUMP_KERNEL=$(echo "$dir/$img" | tr -s '/')
kdump_kernel=$(echo "$dir/$img" | tr -s '/') break 2 fi done done
echo "$kdump_kernel"
+}
+# +# Detect initrd and kernel location, results are stored in global environment variables: +# KDUMP_BOOTDIR, KDUMP_KERNELVER, KDUMP_KERNEL, DEFAULT_INITRD, and KDUMP_INITRD +# +# Expectes KDUMP_BOOTDIR, KDUMP_IMG, KDUMP_IMG_EXT, KDUMP_KERNELVER to be loaded from config already +# and will prefer already set values so user can specify custom kernel/initramfs location +# +prepare_kdump_bootinfo() +{
local boot_initrdlist nondebug_kernelver debug_kernelver
local dir img default_initrd_base var_target_initrd_dir
dir seems to be only used in prepare_kdump_kernel?
I forgot to delete this part when I extracted the function.
if [[ -z $KDUMP_KERNELVER ]]; then
KDUMP_KERNELVER="$(uname -r)"
nondebug_kernelver="$(echo -n "$KDUMP_KERNELVER" | sed -n -e 's/\(.*\)+debug$/\1/p')"
How about nondebug_kernelver=$(sed -n -e 's/(.*)+debug$/\1/p' <<< "$KDUMP_KERNELVER")?
I copied the other code and wrote this line, now I have learned a new way from you. :P
fi
If an user chooses to use a debug kernel for kdump by defining KDUMP_KERNELVER in /etc/sysconfig/kdump, it's better to warn the user that he/she may need to use a larger crashkernel than default crashkernel value.
I think that's a good suggestion.
I'll send the v3 patch when I finish my code work.
Thanks! Lichen
# Use nondebug kernel if possible, because debug kernel will consume more memory and may oom.
if [[ -n $nondebug_kernelver ]]; then
dinfo "Trying to use $nondebug_kernelver."
debug_kernelver="$KDUMP_KERNELVER"
KDUMP_KERNELVER="$nondebug_kernelver"
fi
KDUMP_KERNEL=$(prepare_kdump_kernel "$KDUMP_KERNELVER")
if ! [[ -e $KDUMP_KERNEL ]]; then
if [[ -n $debug_kernelver ]]; then
dinfo "Fallback to using debug kernel"
KDUMP_KERNELVER="$debug_kernelver"
KDUMP_KERNEL=$(prepare_kdump_kernel "$KDUMP_KERNELVER")
fi
fi if ! [[ -e $KDUMP_KERNEL ]]; then derror "Failed to detect kdump kernel location"
-- 2.31.1
-- Best regards, Coiby