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!" @@ -1087,7 +1077,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 27741fb..8e618f8 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 978dae5..26247d1 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 e4f0b02..8fed959 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 ####################################### # These are sources for mkdumpramfs @@ -54,6 +55,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 @@ -183,6 +187,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 @@ -218,6 +223,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 @@ -235,6 +241,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 @@ -316,6 +329,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 6d699c3..89a160d 100644 --- a/mkdumprd +++ b/mkdumprd @@ -452,6 +452,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