From 96a3fc1ac8657bbfe9f7fd4961fb3ecbd92c781d Mon Sep 17 00:00:00 2001 From: Kairui Song Date: Jul 20 2021 07:43:11 +0000 Subject: fadump: isolate fadump initramfs image within the default one Resolves: bz1924115 Conflict: None Upstream: Fedora commit fa9201b2400565aca8165b9cd0a5151f1f94c7be (devel) Author: Hari Bathini Date: Wed Jun 23 20:06:48 2021 +0530 fadump: isolate fadump initramfs image within the default one In case of fadump, the initramfs image has to be built to boot into the production environment as well as to offload the active crash dump to the specified dump target (for boot after crash). As the same image would be used for both boot scenarios, it could not be built optimally while accommodating both cases. Use --include to include the initramfs image built for offloading active crash dump to the specified dump target. Also, introduce a new out-of-tree dracut module (99zz-fadumpinit) that installs a customized init program while moving the default /init to /init.dracut. This customized init program is leveraged to isolate fadump image within the default initramfs image by kicking off default boot process (exec /init.dracut) for regular boot scenario and activating fadump initramfs image, if the system is booting after a crash. If squash is available, ensure default initramfs image is also built with squash module to reduce memory consumption in capture kernel. Signed-off-by: Hari Bathini Signed-off-by: Kairui Song Acked-by: Kairui Song Signed-off-by: Kairui Song --- diff --git a/dracut-fadump-init-fadump.sh b/dracut-fadump-init-fadump.sh new file mode 100755 index 0000000..5468d99 --- /dev/null +++ b/dracut-fadump-init-fadump.sh @@ -0,0 +1,44 @@ +#!/bin/sh +export PATH=/usr/bin:/usr/sbin +export SYSTEMD_IN_INITRD=lenient + +[ -e /proc/mounts ] || + (mkdir -p /proc && mount -t proc -o nosuid,noexec,nodev proc /proc) + +grep -q '^sysfs /sys sysfs' /proc/mounts || + (mkdir -p /sys && mount -t sysfs -o nosuid,noexec,nodev sysfs /sys) + +grep -q '^none / ' /proc/mounts || grep -q '^rootfs / ' /proc/mounts && ROOTFS_IS_RAMFS=1 + +if [ -f /proc/device-tree/rtas/ibm,kernel-dump ] || [ -f /proc/device-tree/ibm,opal/dump/mpipl-boot ]; then + mkdir /newroot + mount -t ramfs ramfs /newroot + + if [ $ROOTFS_IS_RAMFS ]; then + for FILE in $(ls -A /fadumproot/); do + mv /fadumproot/$FILE /newroot/ + done + exec switch_root /newroot /init + else + mkdir /newroot/sys /newroot/proc /newroot/oldroot + mount --move /proc /newroot/proc + mount --move /sys /newroot/sys + cp --reflink=auto --sparse=auto --preserve=mode,timestamps,links -dfr /fadumproot/. /newroot/ + cd /newroot && pivot_root . oldroot + + loop=1 + while [ $loop ]; do + unset loop + while read -r _ mp _; do + case $mp in + /oldroot/*) umount "$mp" && loop=1 ;; + esac + done /dev/null || return 1 - else - modprobe -S $KDUMP_KERNELVER --dry-run $kmodule &>/dev/null || return 1 - fi - done - } - - if is_squash_available && ! is_fadump_capable; then + if is_squash_available; then add_opt_module squash else dwarning "Required modules to build a squashed kdump image is missing!" @@ -1084,7 +1074,5 @@ install() { ${initdir}/etc/lvm/lvm.conf &>/dev/null # Save more memory by dropping switch root capability - if ! is_fadump_capable; then - dracut_no_switch_root - fi + dracut_no_switch_root } diff --git a/kdump-lib.sh b/kdump-lib.sh index 6511c4b..e53fee5 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -19,6 +19,16 @@ is_fadump_capable() return 1 } +is_squash_available() { + for kmodule in squashfs overlay loop; do + if [ -z "$KDUMP_KERNELVER" ]; then + modprobe --dry-run $kmodule &>/dev/null || return 1 + else + modprobe -S $KDUMP_KERNELVER --dry-run $kmodule &>/dev/null || return 1 + fi + done +} + perror_exit() { derror "$@" exit 1 diff --git a/kdumpctl b/kdumpctl index fdd8d67..1e908b6 100755 --- a/kdumpctl +++ b/kdumpctl @@ -8,6 +8,7 @@ KEXEC_ARGS="" KDUMP_CONFIG_FILE="/etc/kdump.conf" KDUMP_LOG_PATH="/var/log" MKDUMPRD="/sbin/mkdumprd -f" +MKFADUMPRD="/sbin/mkfadumprd" DRACUT_MODULES_FILE="/usr/lib/dracut/modules.txt" SAVE_PATH=/var/crash SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" @@ -104,25 +105,10 @@ save_core() rebuild_fadump_initrd() { - local target_initrd_tmp - - # this file tells the initrd is fadump enabled - touch /tmp/fadump.initramfs - target_initrd_tmp="$TARGET_INITRD.tmp" - ddebug "rebuild fadump initrd: $target_initrd_tmp $DEFAULT_INITRD_BAK $KDUMP_KERNELVER" - $MKDUMPRD $target_initrd_tmp --rebuild $DEFAULT_INITRD_BAK --kver $KDUMP_KERNELVER \ - -i /tmp/fadump.initramfs /etc/fadump.initramfs - if [ $? != 0 ]; then - derror "mkdumprd: failed to rebuild initrd with fadump support" - rm -f /tmp/fadump.initramfs + if ! $MKFADUMPRD "$DEFAULT_INITRD_BAK" "$TARGET_INITRD" --kver "$KDUMP_KERNELVER"; then + derror "mkfadumprd: failed to make fadump initrd" return 1 fi - rm -f /tmp/fadump.initramfs - - # updating fadump initrd - ddebug "updating fadump initrd: $target_initrd_tmp $TARGET_INITRD" - mv $target_initrd_tmp $TARGET_INITRD - sync return 0 } @@ -612,7 +598,7 @@ check_rebuild() #in case of fadump mode, check whether the default/target #initrd is already built with dump capture capability if [ "$DEFAULT_DUMP_MODE" == "fadump" ]; then - capture_capable_initrd=$(lsinitrd -f $DRACUT_MODULES_FILE $TARGET_INITRD | grep ^kdumpbase$ | wc -l) + capture_capable_initrd=$(lsinitrd -f $DRACUT_MODULES_FILE $TARGET_INITRD | grep -e ^kdumpbase$ -e ^zz-fadumpinit$ | wc -l) fi fi diff --git a/kexec-tools.spec b/kexec-tools.spec index 5dbf72a..42e09dd 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -39,6 +39,7 @@ Source28: kdump-udev-throttler Source29: kdump.sysconfig.aarch64 Source30: 60-kdump.install Source31: kdump-logger.sh +Source32: mkfadumprd Source33: 92-crashkernel.install Source34: crashkernel-howto.txt @@ -56,6 +57,9 @@ Source107: dracut-kdump-emergency.target Source108: dracut-early-kdump.sh Source109: dracut-early-kdump-module-setup.sh +Source200: dracut-fadump-init-fadump.sh +Source201: dracut-fadump-module-setup.sh + Requires(post): systemd-units Requires(preun): systemd-units Requires(postun): systemd-units @@ -186,6 +190,7 @@ SYSCONFIG=$RPM_SOURCE_DIR/kdump.sysconfig.%{_target_cpu} install -m 644 $SYSCONFIG $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/kdump install -m 755 %{SOURCE7} $RPM_BUILD_ROOT/usr/sbin/mkdumprd +install -m 755 %{SOURCE32} $RPM_BUILD_ROOT/usr/sbin/mkfadumprd install -m 644 %{SOURCE8} $RPM_BUILD_ROOT%{_sysconfdir}/kdump.conf install -m 644 kexec/kexec.8 $RPM_BUILD_ROOT%{_mandir}/man8/kexec.8 install -m 644 %{SOURCE12} $RPM_BUILD_ROOT%{_mandir}/man8/mkdumprd.8 @@ -222,6 +227,7 @@ install -m 644 makedumpfile-%{mkdf_ver}/eppic_scripts/* $RPM_BUILD_ROOT/usr/shar %define remove_dracut_prefix() %(echo -n %1|sed 's/.*dracut-//g') %define remove_dracut_early_kdump_prefix() %(echo -n %1|sed 's/.*dracut-early-kdump-//g') +%define remove_dracut_fadump_prefix() %(echo -n %1|sed 's/.*dracut-fadump-//g') # deal with dracut modules mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase @@ -239,6 +245,13 @@ cp %{SOURCE108} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlyk cp %{SOURCE109} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE109}} chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_prefix %{SOURCE108}} chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99earlykdump/%{remove_dracut_early_kdump_prefix %{SOURCE109}} +%ifarch ppc64 ppc64le +mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99zz-fadumpinit +cp %{SOURCE200} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99zz-fadumpinit/%{remove_dracut_fadump_prefix %{SOURCE200}} +cp %{SOURCE201} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99zz-fadumpinit/%{remove_dracut_fadump_prefix %{SOURCE201}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99zz-fadumpinit/%{remove_dracut_fadump_prefix %{SOURCE200}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99zz-fadumpinit/%{remove_dracut_fadump_prefix %{SOURCE201}} +%endif %define dracutlibdir %{_prefix}/lib/dracut @@ -320,6 +333,7 @@ done /usr/sbin/makedumpfile %endif /usr/sbin/mkdumprd +/usr/sbin/mkfadumprd /usr/sbin/vmcore-dmesg %{_bindir}/* %{_datadir}/kdump diff --git a/mkdumprd b/mkdumprd index 5695759..ead2d13 100644 --- a/mkdumprd +++ b/mkdumprd @@ -432,6 +432,11 @@ then add_dracut_arg "--add-drivers" \"$extra_modules\" fi +# TODO: The below check is not needed anymore with the introduction of +# 'zz-fadumpinit' module, that isolates fadump's capture kernel initrd, +# but still sysroot.mount unit gets generated based on 'root=' kernel +# parameter available in fadump case. So, find a way to fix that first +# before removing this check. if ! is_fadump_capable; then # The 2nd rootfs mount stays behind the normal dump target mount, # so it doesn't affect the logic of check_dump_fs_modified(). diff --git a/mkfadumprd b/mkfadumprd new file mode 100644 index 0000000..4af4ae6 --- /dev/null +++ b/mkfadumprd @@ -0,0 +1,60 @@ +#!/bin/bash --norc +# Generate an initramfs image that isolates dump capture capability within +# the default initramfs using zz-fadumpinit dracut module. + +if [ -f /etc/sysconfig/kdump ]; then + . /etc/sysconfig/kdump +fi + +[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut +. $dracutbasedir/dracut-functions.sh +. /lib/kdump/kdump-lib.sh +. /lib/kdump/kdump-logger.sh + +#initiate the kdump logger +if ! dlog_init; then + echo "mkfadumprd: failed to initiate the kdump logger." + exit 1 +fi + +readonly MKFADUMPRD_TMPDIR="$(mktemp -d -t mkfadumprd.XXXXXX)" +[ -d "$MKFADUMPRD_TMPDIR" ] || perror_exit "mkfadumprd: mktemp -d -t mkfadumprd.XXXXXX failed." +trap ' + ret=$?; + [[ -d $MKFADUMPRD_TMPDIR ]] && rm --one-file-system -rf -- "$MKFADUMPRD_TMPDIR"; + exit $ret; + ' EXIT + +# clean up after ourselves no matter how we die. +trap 'exit 1;' SIGINT + +MKDUMPRD="/sbin/mkdumprd -f" +# Default boot initramfs to be rebuilt +REBUILD_INITRD="$1" && shift +TARGET_INITRD="$1" && shift +FADUMP_INITRD="$MKFADUMPRD_TMPDIR/fadump.img" + +### First build an initramfs with dump capture capability +# this file tells the initrd is fadump enabled +touch "$MKFADUMPRD_TMPDIR/fadump.initramfs" +ddebug "rebuild fadump initrd: $FADUMP_INITRD $DEFAULT_INITRD $KDUMP_KERNELVER" +if ! $MKDUMPRD "$FADUMP_INITRD" -i "$MKFADUMPRD_TMPDIR/fadump.initramfs" /etc/fadump.initramfs; then + perror_exit "mkfadumprd: failed to build image with dump capture support" +fi + +### Unpack the initramfs having dump capture capability +mkdir -p "$MKFADUMPRD_TMPDIR/fadumproot" +if ! (pushd "$MKFADUMPRD_TMPDIR/fadumproot" > /dev/null && lsinitrd --unpack "$MKFADUMPRD_TMPDIR/fadump.img" && \ + popd > /dev/null); then + derror "mkfadumprd: failed to unpack '$MKFADUMPRD_TMPDIR'" + exit 1 +fi + +### Pack it into the normal boot initramfs with zz-fadumpinit module +_dracut_isolate_args="--rebuild $REBUILD_INITRD --add zz-fadumpinit -i $MKFADUMPRD_TMPDIR/fadumproot /fadumproot" +if is_squash_available; then + _dracut_isolate_args="$_dracut_isolate_args --add squash" +fi +if ! dracut --force --quiet $_dracut_isolate_args $@ "$TARGET_INITRD"; then + perror_exit "mkfadumprd: failed to setup '$TARGET_INITRD' with dump capture capability" +fi