This is one of the major changes/refactors so far, touches a lot of files, and more important, it completely changes some premises. With this patch, we now support fully both dracut-based and initcpio initramfs systems. For that to happen, we needed to decouple the initramfs creation from scripts, by using alpm-hooks. These hooks allow scripts to be run on events like kernel package installation or in the installation of the very package responsible to create the initramfs image. We still have the "kdump-load create-initrd" command though. One of the biggest modifications here was in the Makefile, that now composes multiple files by changing keywords (like INITRD) to the respective initramfs system (dracut or mkinitcpio). Notice that this brought some extra complexity to the package. The logic used for supporting both initramfs systems was basically de-duplicate all possible code (having dup code in common files), using Makefile tricks to merge such files and have the unique bits in dracut/initcpio specific files. We currently support dracut and both mkinitcpio and mkinitcpio-git packages. Caveats: currently the initramfs specific package removal is not handled here. So, if the user has dracut and installs kdump, we install the dracut hooks. In case this user decides to remove dracut and installs mkinitcpio, we install the mkinitcpio hooks and all should work, but the previous dracut hooks installed are not unistalled by us; likely the dracut package removal would drop the files itself. This was a deliberate move to avoid even more alpm-hooks, should be a rare case and as said, the package removal should clear the files itself, without requiring our interaction. Also, by using the alpm-hooks, we see "errors" (warnings really) about the other initramfs package not being present - not sure if it's possible to disable this behavior. Finally, while at it: * Added a new approach to dracut initramfs creation to pick the most common block drivers - since it's hostonly, it doesn't add the ones that aren't loaded, hence image is not bloated by that. * Chenged the "command -v makedumpfile" validation to something more elegant - thanks for the suggestion Clayton (@craftyguy). Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
180 lines
5.8 KiB
Bash
180 lines
5.8 KiB
Bash
# 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
|
|
# grub.cfg, so next boot has it reserved; in this case, we also bail-out,
|
|
# since kdump can't be loaded anyway.
|
|
#
|
|
# 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
|
|
# users set crashkernel themselves, we don't mess with that.
|
|
grub_update() {
|
|
CRASHK="$(cat /sys/kernel/kexec_crash_size)"
|
|
SED_ADD="s/^GRUB_CMDLINE_LINUX_DEFAULT=\"/GRUB_CMDLINE_LINUX_DEFAULT=\"${GRUB_CMDLINE}/g"
|
|
|
|
if [ "${GRUB_AUTOSET}" -eq 1 ]; then
|
|
if [ "$1" = "kdump" ] && [ "${CRASHK}" -eq 0 ]; then
|
|
sed -i "${SED_ADD}" "${GRUB_CFG_FILE}"
|
|
|
|
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."
|
|
exit 0 # this is considered a successful run
|
|
fi
|
|
|
|
if [ "$1" = "pstore" ] && [ "${CRASHK}" -ne 0 ]; then
|
|
sed -i "s/\"${GRUB_CMDLINE}/\"/g" "${GRUB_CFG_FILE}"
|
|
|
|
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: cleared crashkernel memory previously set."
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# This function is responsible for creating the kdump initrd, either
|
|
# via command-line call or in case initrd doesn't exist during kdump load.
|
|
# It accounts for both mkinitcpio and dracut users.
|
|
create_initrd() {
|
|
/usr/lib/kdump/kdump-mkinitcpio-hook.sh "$(uname -r)"
|
|
/usr/lib/kdump/kdump-dracut-hook.sh "$(uname -r)"
|
|
}
|
|
|
|
# This routine performs a clean-up by deleting the old/useless remaining
|
|
# kdump initrd files. Even with alpm-hooks, users might install kernels
|
|
# manually so it makes sense to have this fallback to avoid storage waste.
|
|
cleanup_unused_initrd() {
|
|
INSTALLED_KERNELS="${MOUNT_FOLDER}/.installed_kernels"
|
|
|
|
find /lib/modules/* -maxdepth 0 -type d -exec basename {} \; 1> "${INSTALLED_KERNELS}"
|
|
|
|
find "${MOUNT_FOLDER}"/* -name "kdump-initrd*" -type f -print0 2>/dev/null |\
|
|
while IFS= read -r -d '' file
|
|
do
|
|
FNAME="$(basename "${file}" .img)"
|
|
KVER="${FNAME#kdump-initrd-}"
|
|
if ! grep -q "${KVER}" "${INSTALLED_KERNELS}" ; then
|
|
rm -f "${MOUNT_FOLDER}/${FNAME}.img"
|
|
logger "kdump: removed unused file \"${FNAME}.img\""
|
|
fi
|
|
done
|
|
|
|
rm -f "${INSTALLED_KERNELS}"
|
|
}
|
|
|
|
# Now this routine performs a full deletion of all kdump initrd files.
|
|
clear_all_initrds() {
|
|
rm -f "${MOUNT_FOLDER}"/kdump-initrd-*
|
|
}
|
|
|
|
# Function to display basic help about how to use this tool.
|
|
usage() {
|
|
cat <<EOF
|
|
${0##*/} <COMMAND>
|
|
Kdump/Pstore loader.
|
|
|
|
Options:
|
|
load
|
|
Load pstore/kdump according to the configuration file.
|
|
|
|
create-initrd
|
|
Create the minimal kdump initrd for the running kernel.
|
|
|
|
clear-initrd
|
|
Delete all kdump minimal initrd images.
|
|
EOF
|
|
}
|
|
|
|
preamble() {
|
|
load_kdump_config
|
|
|
|
# In case the kdump main folder doesn't exist, create it
|
|
# here, as soon as possible.
|
|
mkdir -p "${MOUNT_FOLDER}"
|
|
}
|
|
|
|
# Entry point of the script.
|
|
case $1 in
|
|
clear-initrd)
|
|
preamble
|
|
clear_all_initrds
|
|
exit 0
|
|
;;
|
|
create-initrd)
|
|
preamble
|
|
create_initrd
|
|
exit 0
|
|
;;
|
|
load)
|
|
# just bail from the case statement, jumping to code below
|
|
;;
|
|
*)
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
# Here starts the main purpose of this script, the load operation.
|
|
preamble
|
|
|
|
# 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
|
|
# here a ${MEM_REQUIRED} memory region.
|
|
# Notice that we assume ramoops is a module here - if built-in, users
|
|
# should properly load it through command-line parameters.
|
|
if [ "${USE_PSTORE_RAM}" -eq 1 ]; then
|
|
MEM_REQUIRED="${PSTORE_MEM_AMOUNT}"
|
|
RECORD_SIZE="${PSTORE_RECORD_SZ}"
|
|
RANGE=$(grep "RAM buffer" /proc/iomem | head -n1 | cut -f1 -d\ )
|
|
|
|
MEM_END=$(echo "$RANGE" | cut -f2 -d-)
|
|
MEM_START=$(echo "$RANGE" | cut -f1 -d-)
|
|
MEM_SIZE=$(( 16#${MEM_END} - 16#${MEM_START} ))
|
|
|
|
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 Pstore is set, update grub.cfg to avoid reserving crashkernel memory.
|
|
logger "kdump: pstore-RAM was loaded successfully"
|
|
cleanup_unused_initrd
|
|
grub_update pstore
|
|
exit 0
|
|
fi
|
|
logger "kdump: pstore-RAM load failed...will try kdump"
|
|
fi
|
|
# Fallback to kdump load - if we fail when configuring pstore, better
|
|
# trying kdump; in case we have crashkernel memory reserved, lucky us.
|
|
# If not, we're going to set that automatically on grub_update().
|
|
# Notice that if it's not set, we bail-out in grub_update() - there's
|
|
# no point in continuing since kdump cannot work.
|
|
fi
|
|
|
|
cleanup_unused_initrd
|
|
grub_update kdump
|
|
|
|
# After some consideration, we've stolen the kdump parameters from
|
|
# Debian/Ubuntu implementation, it makes sense for us.
|
|
KDUMP_CMDLINE=$(sed -re 's/(^| )(crashkernel|hugepages|hugepagesz)=[^ ]*//g;s/"/\\\\"/' /proc/cmdline)
|
|
KDUMP_CMDLINE="${KDUMP_CMDLINE} panic=-1 oops=panic fsck.mode=force fsck.repair=yes nr_cpus=1 reset_devices"
|
|
|
|
VMLINUX="$(grep -o 'BOOT_IMAGE=[^ ]*' /proc/cmdline)"
|
|
|
|
# In case we don't have a valid initrd, for some reason, try creating
|
|
# one before loading kdump (or else it will fail).
|
|
INITRD_FNAME="${MOUNT_FOLDER}/kdump-initrd-$(uname -r).img"
|
|
if [ ! -s "${INITRD_FNAME}" ]; then
|
|
create_initrd
|
|
fi
|
|
|
|
if ! kexec -s -p "${VMLINUX#*BOOT_IMAGE=}" --initrd "${INITRD_FNAME}" --append="${KDUMP_CMDLINE}"; then
|
|
logger "kdump: kexec load failed"
|
|
exit 1
|
|
fi
|
|
logger "kdump: panic kexec loaded successfully"
|