Currently we have to read multiple files from initramfs image in kdumpctl, and we are calling lsinitrd for each file individually, and the initramfs image will get decompressed for each lsinitrd call which is a waste of time.
This patch will let kdumpctl extract all required files with a single lsinitrd call, so the image will only get decompressed for once.
This commit relies on following dracut commits:
commit 986b12d391b8de6c820da1af9bfdb4153c340370 Author: Kairui Song kasong@redhat.com
lsinitrd: optimize performance when handling multiple files
commit f81c864eede2a11bfeb849cb2a2634be034ed7fb Author: Kairui Song kasong@redhat.com
lsinitrd: allow to only unpack certain files
Performance compare:
Before: real 0m1.657s user 0m1.401s sys 0m0.223s
After: real 0m1.440s user 0m1.087s sys 0m0.330s --- kdumpctl | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/kdumpctl b/kdumpctl index 6a01c13..c6b52fb 100755 --- a/kdumpctl +++ b/kdumpctl @@ -17,6 +17,13 @@ TARGET_INITRD="" FADUMP_REGISTER_SYS_NODE="/sys/kernel/fadump_registered" #kdump shall be the default dump mode DEFAULT_DUMP_MODE="kdump" +INITRD_PREFETCH_FILES="\ +etc/cmdline.d/00-watchdog.conf \ +usr/lib/dracut/build-parameter.txt \ +usr/lib/dracut/loaded-kernel-modules.txt \ +$DRACUT_MODULES_FILE \ +" +INITRD_TMP_PATH="" image_time=0
[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut @@ -32,6 +39,22 @@ if [ -f /etc/sysconfig/kdump ]; then . /etc/sysconfig/kdump fi
+# Wrapper for lsinitrd +# possible required files in initramfs will be extarcted to a temp directory all at once +# when this script just started, because batch extract is faster +# Will try to read from the temp dir first, fall back to read the image if not found +_lsinitrd() +{ + local file=${1##/} + if [[ -e $INITRD_TMP_PATH/$file ]]; then + cat $INITRD_TMP_PATH/$file + return 0 + else + lsinitrd $TARGET_INITRD -f $file + return 1 + fi +} + single_instance_lock() { local rc timeout=5 @@ -287,6 +310,13 @@ setup_initrd() else TARGET_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img" fi + + INITRD_TMP_PATH="$(mktemp -t -d --suffix=.d kdumpctl.XXXXXX)" + [[ $? -ne 0 ]] && echo "Error: Failed to create temp dir to extract initramfs!" >&2 && exit 1 + [[ -n "$INITRD_TMP_PATH" ]] && trap "rm -rf '$INITRD_TMP_PATH'" EXIT + pushd $INITRD_TMP_PATH &> /dev/null + lsinitrd --unpack $TARGET_INITRD $INITRD_PREFETCH_FILES &> /dev/null + popd &> /dev/null }
check_files_modified() @@ -378,7 +408,7 @@ check_dump_fs_modified() _new_mntpoint="/kdumproot/$(get_mntpoint_from_target $_target)" fi
- _dracut_args=$(lsinitrd $TARGET_INITRD -f usr/lib/dracut/build-parameter.txt) + _dracut_args=$(_lsinitrd usr/lib/dracut/build-parameter.txt) if [[ -z "$_dracut_args" ]];then echo "Warning: No dracut arguments found in initrd" return 0 @@ -451,7 +481,7 @@ check_wdt_modified() # ensure that watchdog module is loaded as early as possible _alldrivers="${!_drivers[*]}" [[ $_alldrivers ]] && wd_new="rd.driver.pre=${_alldrivers// /,}" - wd_old=$(lsinitrd $TARGET_INITRD -f etc/cmdline.d/00-watchdog.conf) + wd_old=$(_lsinitrd etc/cmdline.d/00-watchdog.conf)
[[ "$wd_old" = "$wd_new" ]] && return 0
@@ -461,7 +491,7 @@ check_wdt_modified() check_kmodules_modified() { # always sort again to avoid LANG/LC inconsistent problem - local _old_modules="$(lsinitrd $TARGET_INITRD -f /usr/lib/dracut/loaded-kernel-modules.txt | sort)" + local _old_modules="$(_lsinitrd /usr/lib/dracut/loaded-kernel-modules.txt | sort)" local _new_modules="$(get_loaded_kernel_modules | sort)"
[[ -z $_old_modules ]] && echo "Warning: Previous loaded kernel module list is absent or empty" @@ -580,7 +610,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 $DRACUT_MODULES_FILE | grep ^kdumpbase$ | wc -l) fi fi