all: Add/improve config options

As part of the upstreaming effort, we need to add some extra tunings
in the package. Especially related to GRUB autosetting and Pstore
memory settings:

(a) Currently the ramoops record size and memory amount are hardcoded
in the kdump-load script - we change it here, by having these settings
on the kdump config file;

(b) GRUB autosetting is pretty simple and everything is hardcoded.
We hereby add a bunch of configurable settings in the kdump conf file,
in order we can customize the GRUB handling, to make it work in both
Arch and SteamOS.

While at it, fixed some related comments and renamed some variables,
usually dropping KDUMP_ name when it applies to pstore as well.
Also, bumped the crashkernel memory from 192M to 256M - recent kernels
demand more memory, let's play safe.

Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
This commit is contained in:
Guilherme G. Piccoli
2022-11-25 14:10:04 -03:00
parent 7f212ffb73
commit ecbf6f298f
4 changed files with 100 additions and 72 deletions

View File

@ -9,33 +9,55 @@
# file, it's required to re-create the kdump minimal initramfs by running: # file, it's required to re-create the kdump minimal initramfs by running:
# /usr/lib/kdump/kdump-load.sh initrd # /usr/lib/kdump/kdump-load.sh initrd
# #
#
# Mount-related options - the DEVNODE points to the /home directory link; # Pstore-RAM settings
# this is used to derive the numerical devnode for kdump, since the link # If USE_PSTORE_RAM is set to 1, Kdump won't be loaded. Instead, the Pstore
# is not present so early in the system boot. The KDUMP_FOLDER will be # RAM backend will be configured. In order to have success, this operation
# created if doesn't exist. The KDUMP_MNT is just a temporary file that # relies in having an available RAM buffer on /proc/iomem with at least
# carries the mounted folder path across boot-time scripts. # PSTORE_MEM_AMOUNT (decimal, in MB) in size. Also, kernel must be able to
# allocate a contiguous memory amount of PSTORE_RECORD_SZ (decimal, MB).
USE_PSTORE_RAM=1
PSTORE_MEM_AMOUNT=5242880
PSTORE_RECORD_SZ=2097152
#
#
# Mount-related options
# MOUNT_DEVNODE is the desired mount-point unique link in the /dev/disk
# directory link; this is used to derive the numerical devnode for kdump,
# since the link is not present so early in the system boot. MOUNT_FOLDER
# should live in the filesystem of the devnode (and will be created if
# doesn't exist); this is the place in which both pstore and kdump logs
# will be stored, as well as the kdump initrd and some ancillary data.
# Finally, MNT_TMP is just a temporary file that carries the full path
# of the mounted folder across boot-time scripts.
MOUNT_DEVNODE="/dev/disk/by-partsets/shared/home" MOUNT_DEVNODE="/dev/disk/by-partsets/shared/home"
KDUMP_FOLDER="/.steamos/offload/var/kdump" MOUNT_FOLDER="/.steamos/offload/var/kdump"
KDUMP_MNT="/tmp/kdump.mnt" MNT_TMP="/tmp/.kdump_load.mnt"
#
# Kdump controlling settings - for now we don't have network/iscsi dumps, only #
# local storage dumps. If FULL_COREDUMP is !=0, we collect a full compressed # Kdump controlling settings
# vmcore, which might require a lot of disk space. The *_CMD settings refer # Currently we only do local storage log collection (no network/iscsi dumps).
# to tunings on makedumpfile - we rely on zstd compression and maximum page # If FULL_COREDUMP is !=0, we collect a full compressed vmcore, which might
# exclusion for the full vmcore, mimic'ing Debian kdump. Finally, GRUB_AUTOSET # require a lot of disk space. The MAKEDUMPFILE_*_CMD settings refer to
# determines if the kdump tooling should try to automatically set grub.cfg in # tunings on makedumpfile - we rely on zstd compression and maximum page
# order to reserve memory for kdump (if needed, i.e., when pstore is not in # exclusion for the full vmcore, mimic'ing Debian kdump
# use) - keep it as '1' for enabling the mechanism (this is the default).
FULL_COREDUMP=0 FULL_COREDUMP=0
MAKEDUMPFILE_COREDUMP_CMD="-z -d 31" MAKEDUMPFILE_COREDUMP_CMD="-z -d 31"
MAKEDUMPFILE_DMESG_CMD="--dump-dmesg" MAKEDUMPFILE_DMESG_CMD="--dump-dmesg"
#
#
# GRUB-related settings
# GRUB_AUTOSET determines if the pstore/kdump tooling should try to
# automatically set grub.cfg in order to reserve memory for kdump (if
# needed, i.e., when pstore is not in use) - keep it as '1' for enabling
# the mechanism (this is the default). GRUB_BOOT_FILE is the full path of
# grub.cfg file - this is used in the config update step plus for syncing
# purposes. GRUB_CFG_FILE is the config file we edit in order to add/remove
# the crashkernel parameter. Finally, GRUB_CMDLINE holds the change to be
# made in the grub config file, specially the crashkernel memory reservation
# (notice that a trailing space is required in this line, so we avoid
# messing with other kernel parameters).
GRUB_AUTOSET=1 GRUB_AUTOSET=1
GRUB_BOOT_FILE="/efi/EFI/steamos/grub.cfg"
# Pstore-RAM setting - if enabled, Kdump won't be loaded, instead the Pstore GRUB_CFG_FILE="/etc/default/grub"
# RAM backend will be configured. In order to have success, this operation GRUB_CMDLINE="crashkernel=256M crash_kexec_post_notifiers "
# relies in having an available RAM buffer on /proc/iomem with at least 5MiB
# in size.
USE_PSTORE_RAM=1

View File

@ -23,7 +23,7 @@ done
VMCORE="/proc/vmcore" VMCORE="/proc/vmcore"
KDUMP_TIMESTAMP=$(date -u +"%Y%m%d%H%M") KDUMP_TIMESTAMP=$(date -u +"%Y%m%d%H%M")
KDUMP_FOLDER="/kdump_path/${KDUMP_FOLDER}/crash/${KDUMP_TIMESTAMP}" KDUMP_FOLDER="/kdump_path/${MOUNT_FOLDER}/crash/${KDUMP_TIMESTAMP}"
# Bail out in case we don't have a vmcore, i.e. either we're not kdumping # Bail out in case we don't have a vmcore, i.e. either we're not kdumping
# or something is pretty wrong and we wouldn't be able to progress. # or something is pretty wrong and we wouldn't be able to progress.

View File

@ -9,40 +9,46 @@
# configures the Pstore-RAM mechanism. If the proper parameters are passed # configures the Pstore-RAM mechanism. If the proper parameters are passed
# also, either it creates the minimal kdump initramfs for the running kernel # also, either it creates the minimal kdump initramfs for the running kernel
# or removes all the previously created ones. Since it runs on boot time, # or removes all the previously created ones. Since it runs on boot time,
# avoid failing here to not risk a boot hang. # extra care is required to avoid boot hangs.
# #
# This function has 2 purposes: if 'kdump' is passed as argument and we don't # This function has 2 purposes: if 'kdump' is passed as argument and we don't
# have crashkernel memory reserved, we edit grub config file and recreate # have crashkernel memory reserved, we edit grub config file and recreate
# grub.cfg, so next boot has it reserved; in this case, we also bail-out, # grub.cfg, so next boot has it reserved; in this case, we also bail-out,
# since kdump can't be loaded anyway. # since kdump can't be loaded anyway.
# #
# If 'pstore' is passsed as argument, we try to unset crashkernel iff it's # If 'pstore' is passsed as argument, we try to unset crashkernel iff it's
# already set AND the pattern in grub config is the one added by us - if the # already set AND the pattern in grub config is the one added by us - if the
# users set crashkernel themselves, we don't mess with that. # users set crashkernel themselves, we don't mess with that.
grub_update() { grub_update() {
GRUBCFG="/etc/default/grub"
CRASHK="$(cat /sys/kernel/kexec_crash_size)" CRASHK="$(cat /sys/kernel/kexec_crash_size)"
SED_ADD="s/^GRUB_CMDLINE_LINUX_DEFAULT=\"/GRUB_CMDLINE_LINUX_DEFAULT=\"crashkernel=192M crash_kexec_post_notifiers /g" SED_ADD="s/^GRUB_CMDLINE_LINUX_DEFAULT=\"/GRUB_CMDLINE_LINUX_DEFAULT=\"${GRUB_CMDLINE}/g"
if [ "${GRUB_AUTOSET}" -eq 1 ]; then if [ "${GRUB_AUTOSET}" -eq 1 ]; then
if [ "$1" = "kdump" ] && [ "${CRASHK}" -eq 0 ]; then if [ "$1" = "kdump" ] && [ "${CRASHK}" -eq 0 ]; then
sed -i "${SED_ADD}" "${GRUBCFG}" sed -i "${SED_ADD}" "${GRUB_CFG_FILE}"
update-grub 1>/dev/null
sync "/boot/grub/grub.cfg" 2>/dev/null
sync "/efi/EFI/steamos/grub.cfg" 2>/dev/null
logger "kdump: kexec cannot work, no reserved memory in this boot..." if ! grub-mkconfig -o "${GRUB_BOOT_FILE}" 1>/dev/null; then
logger "kdump: failed to execute command \"${GRUB_CMD}\""
exit 1
fi
sync "${GRUB_BOOT_FILE}" 2>/dev/null
logger "kdump: kexec won't succeed, no reserved memory in this boot..."
logger "kdump: but we automatically set crashkernel for next boot." logger "kdump: but we automatically set crashkernel for next boot."
exit 0 # this is considered a successful run exit 0 # this is considered a successful run
fi fi
if [ "$1" = "pstore" ] && [ "${CRASHK}" -ne 0 ]; then if [ "$1" = "pstore" ] && [ "${CRASHK}" -ne 0 ]; then
sed -i "s/\"crashkernel=192M crash_kexec_post_notifiers /\"/g" "${GRUBCFG}" sed -i "s/\"${GRUB_CMDLINE}/\"/g" "${GRUB_CFG_FILE}"
update-grub 1>/dev/null
sync "/boot/grub/grub.cfg" 2>/dev/null if ! grub-mkconfig -o "${GRUB_BOOT_FILE}" 1>/dev/null; then
sync "/efi/EFI/steamos/grub.cfg" 2>/dev/null logger "kdump: failed to execute command \"${GRUB_CMD}\""
logger "kdump: clearing crashkernel memory previously set..." exit 1
fi
sync "${GRUB_BOOT_FILE}" 2>/dev/null
logger "kdump: cleared crashkernel memory previously set."
fi fi
fi fi
} }
@ -50,27 +56,27 @@ grub_update() {
# This function is responsible for creating the kdump initrd, either # This function is responsible for creating the kdump initrd, either
# via command-line call or in case initrd doesn't exist during kdump load. # via command-line call or in case initrd doesn't exist during kdump load.
create_initrd() { create_initrd() {
rm -f "${KDUMP_FOLDER}/kdump-initrd-$(uname -r).img" rm -f "${MOUNT_FOLDER}/kdump-initrd-$(uname -r).img"
echo "Creating the kdump initramfs for kernel \"$(uname -r)\" ..." echo "Creating the kdump initramfs for kernel \"$(uname -r)\" ..."
DRACUT_NO_XATTR=1 dracut --no-early-microcode --host-only -q -m\ DRACUT_NO_XATTR=1 dracut --no-early-microcode --host-only -q -m\
"bash systemd systemd-initrd systemd-sysusers modsign dbus-daemon kdump dbus udev-rules dracut-systemd base fs-lib shutdown"\ "bash systemd systemd-initrd systemd-sysusers modsign dbus-daemon kdump dbus udev-rules dracut-systemd base fs-lib shutdown"\
--kver "$(uname -r)" "${KDUMP_FOLDER}/kdump-initrd-$(uname -r).img" --kver "$(uname -r)" "${MOUNT_FOLDER}/kdump-initrd-$(uname -r).img"
} }
# This routine performs a clean-up by deleting the old/useless remaining # This routine performs a clean-up by deleting the old/useless remaining
# kdump initrd files. # kdump initrd files.
cleanup_unused_initrd() { cleanup_unused_initrd() {
INSTALLED_KERNELS="${KDUMP_FOLDER}/.installed_kernels" INSTALLED_KERNELS="${MOUNT_FOLDER}/.installed_kernels"
find /lib/modules/* -maxdepth 0 -type d -exec basename {} \;>"${INSTALLED_KERNELS}" find /lib/modules/* -maxdepth 0 -type d -exec basename {} \;>"${INSTALLED_KERNELS}"
find "${KDUMP_FOLDER}"/* -name "kdump-initrd*" -type f -print0 | while IFS= read -r -d '' file find "${MOUNT_FOLDER}"/* -name "kdump-initrd*" -type f -print0 | while IFS= read -r -d '' file
do do
FNAME="$(basename "${file}" .img)" FNAME="$(basename "${file}" .img)"
KVER="${FNAME#kdump-initrd-}" KVER="${FNAME#kdump-initrd-}"
if ! grep -q "${KVER}" "${INSTALLED_KERNELS}" ; then if ! grep -q "${KVER}" "${INSTALLED_KERNELS}" ; then
rm -f "${KDUMP_FOLDER}/${FNAME}.img" rm -f "${MOUNT_FOLDER}/${FNAME}.img"
logger "kdump: removed unused file \"${FNAME}.img\"" logger "kdump: removed unused file \"${FNAME}.img\""
fi fi
done done
@ -97,42 +103,42 @@ fi
# Find the proper mount point expected for kdump collection: # Find the proper mount point expected for kdump collection:
DEVN_MOUNTED="$(findmnt "${MOUNT_DEVNODE}" -fno TARGET)" DEVN_MOUNTED="$(findmnt "${MOUNT_DEVNODE}" -fno TARGET)"
# Create the kdump folder here, as soon as possible, given the # Create the kdump main folder here, as soon as possible, given
# importance of such directory in all kdump/pstore steps. # the importance of such directory in all kdump/pstore steps.
KDUMP_FOLDER="${DEVN_MOUNTED}/${KDUMP_FOLDER}" MOUNT_FOLDER="${DEVN_MOUNTED}/${MOUNT_FOLDER}"
mkdir -p "${KDUMP_FOLDER}" mkdir -p "${MOUNT_FOLDER}"
echo "${KDUMP_FOLDER}" > "${KDUMP_MNT}" echo "${MOUNT_FOLDER}" > "${MNT_TMP}"
sync "${KDUMP_MNT}" sync "${MNT_TMP}"
# Notice that at this point it's required to have the full # Notice that at this point it's required to have the full
# KDUMP_FOLDER, so this must remain after the DEVNODE operations above. # MOUNT_FOLDER, so this must remain after the DEVNODE operations above.
if [ "$1" = "initrd" ]; then if [ "$1" = "initrd" ]; then
create_initrd create_initrd
exit 0 exit 0
fi fi
if [ "$1" = "clear" ]; then if [ "$1" = "clear" ]; then
rm -f "${KDUMP_FOLDER}"/kdump-initrd-* rm -f "${MOUNT_FOLDER}"/kdump-initrd-*
exit 0 exit 0
fi fi
# Pstore-RAM load; if it is configured via /usr/share/kdump/kdump.conf and fails # Pstore-RAM load; if it is configured via the config files and fails
# to configure pstore, we still try to load the kdump. We try to reserve # to configure pstore, we still try to load the kdump. We try to reserve
# here a 5MiB memory region. # here a ${MEM_REQUIRED} memory region.
# Notice that we assume ramoops is a module here - if built-in, we should # Notice that we assume ramoops is a module here - if built-in, users
# properly load it through command-line parameters. # should properly load it through command-line parameters.
if [ "${USE_PSTORE_RAM}" -eq 1 ]; then if [ "${USE_PSTORE_RAM}" -eq 1 ]; then
MEM_REQUIRED=5242880 # 5MiB MEM_REQUIRED="${PSTORE_MEM_AMOUNT}"
RECORD_SIZE=0x200000 # 2MiB RECORD_SIZE="${PSTORE_RECORD_SZ}"
RANGE=$(grep "RAM buffer" /proc/iomem | head -n1 | cut -f1 -d\ ) RANGE=$(grep "RAM buffer" /proc/iomem | head -n1 | cut -f1 -d\ )
MEM_END=$(echo "$RANGE" | cut -f2 -d-) MEM_END=$(echo "$RANGE" | cut -f2 -d-)
MEM_START=$(echo "$RANGE" | cut -f1 -d-) MEM_START=$(echo "$RANGE" | cut -f1 -d-)
MEM_SIZE=$(( 16#${MEM_END} - 16#${MEM_START} )) MEM_SIZE=$(( 16#${MEM_END} - 16#${MEM_START} ))
if [ ${MEM_SIZE} -ge ${MEM_REQUIRED} ]; then if [ ${MEM_SIZE} -ge "${MEM_REQUIRED}" ]; then
if modprobe ramoops mem_address=0x"${MEM_START}" mem_size=${MEM_REQUIRED} record_size=${RECORD_SIZE}; then if modprobe ramoops mem_address=0x"${MEM_START}" mem_size="${MEM_REQUIRED}" record_size="${RECORD_SIZE}"; then
# If Pstore is set, update grub.cfg to avoid reserving crashkernel memory. # If Pstore is set, update grub.cfg to avoid reserving crashkernel memory.
logger "kdump: pstore-RAM was loaded successfully" logger "kdump: pstore-RAM was loaded successfully"
cleanup_unused_initrd cleanup_unused_initrd
@ -159,7 +165,7 @@ VMLINUX="$(grep -o 'BOOT_IMAGE=[^ ]*' /proc/cmdline)"
# In case we don't have a valid initrd, for some reason, try creating # In case we don't have a valid initrd, for some reason, try creating
# one before loading kdump (or else it will fail). # one before loading kdump (or else it will fail).
INITRD_FNAME="${KDUMP_FOLDER}/kdump-initrd-$(uname -r).img" INITRD_FNAME="${MOUNT_FOLDER}/kdump-initrd-$(uname -r).img"
if [ ! -s "${INITRD_FNAME}" ]; then if [ ! -s "${INITRD_FNAME}" ]; then
create_initrd create_initrd
fi fi

View File

@ -25,16 +25,16 @@ if [ ${HAVE_CFG_FILES} -eq 0 ]; then
exit 1 exit 1
fi fi
KDUMP_MAIN_FOLDER="$(cat "${KDUMP_MNT}")" MAIN_FOLDER="$(cat "${MNT_TMP}")"
rm -f "${KDUMP_MNT}" rm -f "${MNT_TMP}"
if [ ! -d "${KDUMP_MAIN_FOLDER}" ]; then if [ ! -d "${MAIN_FOLDER}" ]; then
logger "kdump: invalid folder (${KDUMP_MAIN_FOLDER}) - aborting..." logger "kdump: invalid folder (${MAIN_FOLDER}) - aborting..."
exit 1 exit 1
fi fi
LOGS_FOUND=0 LOGS_FOUND=0
KDUMP_TMP_FOLDER="${KDUMP_MAIN_FOLDER}/.tmp" KDUMP_TMP_FOLDER="${MAIN_FOLDER}/.tmp"
# Use UTC timezone to match kdump collection # Use UTC timezone to match kdump collection
CURRENT_TSTAMP=$(date -u +"%Y%m%d%H%M") CURRENT_TSTAMP=$(date -u +"%Y%m%d%H%M")
@ -67,7 +67,7 @@ if [ "${PSTORE_CNT}" -ne 0 ]; then
fi fi
# Now, we proceed the same way if there are kdump data. # Now, we proceed the same way if there are kdump data.
KDUMP_CRASH_FOLDER="${KDUMP_MAIN_FOLDER}/crash" KDUMP_CRASH_FOLDER="${MAIN_FOLDER}/crash"
KDUMP_CNT=$(find "${KDUMP_CRASH_FOLDER}"/* -type d 2>/dev/null | wc -l) KDUMP_CNT=$(find "${KDUMP_CRASH_FOLDER}"/* -type d 2>/dev/null | wc -l)
if [ "${KDUMP_CNT}" -ne 0 ]; then if [ "${KDUMP_CNT}" -ne 0 ]; then
@ -112,10 +112,10 @@ fi
# If we have pstore and/or kdump logs, let's process them... # If we have pstore and/or kdump logs, let's process them...
KDUMP_LOGS_FOLDER="${KDUMP_MAIN_FOLDER}/logs" LOGS_FOLDER="${MAIN_FOLDER}/logs"
if [ ${LOGS_FOUND} -ne 0 ]; then if [ ${LOGS_FOUND} -ne 0 ]; then
mkdir -p "${KDUMP_LOGS_FOLDER}" mkdir -p "${LOGS_FOLDER}"
# First we collect some more info, like DMI data, os-release, etc; # First we collect some more info, like DMI data, os-release, etc;
DMI_FNAME="${KDUMP_TMP_FOLDER}/dmidecode.${CURRENT_TSTAMP}" DMI_FNAME="${KDUMP_TMP_FOLDER}/dmidecode.${CURRENT_TSTAMP}"
@ -131,7 +131,7 @@ if [ ${LOGS_FOUND} -ne 0 ]; then
# Create the dump compressed pack. # Create the dump compressed pack.
LOG_FNAME="kdump-${CURRENT_TSTAMP}.zip" LOG_FNAME="kdump-${CURRENT_TSTAMP}.zip"
LOG_FNAME="${KDUMP_LOGS_FOLDER}/${LOG_FNAME}" LOG_FNAME="${LOGS_FOLDER}/${LOG_FNAME}"
zip -9 -jq "${LOG_FNAME}" "${KDUMP_TMP_FOLDER}"/* 1>/dev/null zip -9 -jq "${LOG_FNAME}" "${KDUMP_TMP_FOLDER}"/* 1>/dev/null
sync "${LOG_FNAME}" 2>/dev/null sync "${LOG_FNAME}" 2>/dev/null
@ -139,7 +139,7 @@ if [ ${LOGS_FOUND} -ne 0 ]; then
logger "kdump: couldn't create the compressed log archive" logger "kdump: couldn't create the compressed log archive"
logger "kdump: check folder \"${KDUMP_TMP_FOLDER}\" for logs" logger "kdump: check folder \"${KDUMP_TMP_FOLDER}\" for logs"
else else
logger "kdump: logs saved in \"${KDUMP_LOGS_FOLDER}\"" logger "kdump: logs saved in \"${LOGS_FOLDER}\""
fi fi
fi fi