From ca01cbdfd5c17e7a6134a1fcfef1a0ceb22476d9 Mon Sep 17 00:00:00 2001 From: Kairui Song Date: Tue, 12 May 2020 18:47:19 +0800 Subject: [PATCH] mkdumprd: generate usable kdump initramfs even target is not mounted Currently kexec-tools always depend on dump target to be mounted, which caused some inconvenience for setup. So for user configured target, allow kdump to start and build initramfs even if target is not mounted. When a mounted user configured target is used, the behavior is not changed. When a unmounted user configured target is used, mkdumprd will look for corresponding mount info in fstab, and a entry with noauto option is founded, mkdumprd will try to mount it inplace with optoins specified in fstab and do basic checks on the device, then umount it. If there is no fstab entry, mkdumprd will try to mount it in temporary path with defaults option, do same basic check and umount it. If there is a fstab entry but "noauto" option is not used, then there must be some reason that the target device is not mounted, mkdumprd will error out. When path based target is used, there is no behavior change. Signed-off-by: Kairui Song Acked-by: Pingfan Liu --- kdump-lib.sh | 33 ++++++------------ mkdumprd | 94 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 92 insertions(+), 35 deletions(-) diff --git a/kdump-lib.sh b/kdump-lib.sh index 691a14d..74dac4c 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -284,12 +284,17 @@ get_kdump_mntpoint_from_target() local _mntpoint=$(get_mntpoint_from_target $1) # mount under /sysroot if dump to root disk or mount under - # /kdumproot/$_mntpoint in other cases in 2nd kernel. systemd - # will be in charge to umount it. - if [ "$_mntpoint" = "/" ];then - _mntpoint="/sysroot" + # mount under /kdumproot if dump target is not mounted in first kernel + # mount under /kdumproot/$_mntpoint in other cases in 2nd kernel. + # systemd will be in charge to umount it. + if [ -z "$_mntpoint" ];then + _mntpoint="/kdumproot" else - _mntpoint="/kdumproot/$_mntpoint" + if [ "$_mntpoint" = "/" ];then + _mntpoint="/sysroot" + else + _mntpoint="/kdumproot/$_mntpoint" + fi fi # strip duplicated "/" @@ -302,24 +307,6 @@ get_option_value() { strip_comments `grep "^$1[[:space:]]\+" /etc/kdump.conf | tail -1 | cut -d\ -f2-` } -check_save_path_fs() -{ - local _path=$1 - - if [ ! -d $_path ]; then - perror_exit "Dump path $_path does not exist." - fi -} - -# Check if path exists within dump target -check_save_path_user_configured() -{ - local _target=$1 _path=$2 - local _mnt=$(get_mntpoint_from_target $_target) - - check_save_path_fs "$_mnt/$_path" -} - is_atomic() { grep -q "ostree" /proc/cmdline diff --git a/mkdumprd b/mkdumprd index 92f091b..aa79541 100644 --- a/mkdumprd +++ b/mkdumprd @@ -19,6 +19,20 @@ OVERRIDE_RESETTABLE=0 extra_modules="" dracut_args="--quiet --hostonly --hostonly-cmdline --hostonly-i18n --hostonly-mode strict -o \"plymouth dash resume ifcfg earlykdump\"" +readonly MKDUMPRD_TMPDIR="$(mktemp -d -t mkdumprd.XXXXXX)" +[ -d "$MKDUMPRD_TMPDIR" ] || perror_exit "dracut: mktemp -p -d -t dracut.XXXXXX failed." +readonly MKDUMPRD_TMPMNT="$MKDUMPRD_TMPDIR/target" + +trap ' + ret=$?; + is_mounted $MKDUMPRD_TMPMNT && umount -f $MKDUMPRD_TMPMNT; + [[ -d $MKDUMPRD_TMPDIR ]] && rm --one-file-system -rf -- "$MKDUMPRD_TMPDIR"; + exit $ret; + ' EXIT + +# clean up after ourselves no matter how we die. +trap 'exit 1;' SIGINT + is_wdt_addition_needed() { local active @@ -51,11 +65,12 @@ add_dracut_sshkey() { # caller should ensure $1 is valid and mounted in 1st kernel to_mount() { - local _target=$1 _new_mntpoint _fstype _options _mntopts _pdev + local _target=$1 _fstype=$2 _options=$3 _new_mntpoint _mntopts _pdev - _fstype=$(get_fs_type_from_target $_target) - _options=$(get_mntopt_from_target $_target) _new_mntpoint=$(get_kdump_mntpoint_from_target $_target) + _fstype="${_fstype:-$(get_fs_type_from_target $_target)}" + _options="${_options:-$(get_mntopt_from_target $_options)}" + _options="${_options:-defaults}" if [[ "$_fstype" == "nfs"* ]]; then _options=$(echo $_options | sed 's/,addr=[^,]*//') @@ -174,6 +189,67 @@ check_size() { fi } +check_save_path_fs() +{ + local _path=$1 + + if [ ! -d $_path ]; then + perror_exit "Dump path $_path does not exist." + fi +} + +check_user_configured_target() +{ + local _target=$1 _cfg_fs_type=$2 _mounted + local _mnt=$(get_mntpoint_from_target $_target) + local _opt=$(get_mntopt_from_target $_target) + local _fstype=$(get_fs_type_from_target $_target) + + if [ -n "$_fstype" ]; then + # In case of nfs4, nfs should be used instead, nfs* options is deprecated in kdump.conf + [[ $_fstype = "nfs"* ]] && _fstype=nfs + + if [ -n "$_cfg_fs_type" ] && [ "$_fstype" != "$_cfg_fs_type" ]; then + perror_exit "\"$_target\" have a wrong type config \"$_cfg_fs_type\", expected \"$_fstype\"" + fi + else + _fstype="$_cfg_fs_type" + _fstype="$_cfg_fs_type" + fi + + # For noauto mount, mount it inplace with default value. + # Else use the temporary target directory + if [ -n "$_mnt" ]; then + if ! is_mounted "$_mnt"; then + if [[ $_opt = *",noauto"* ]]; then + mount $_mnt + [ $? -ne 0 ] && perror_exit "Failed to mount $_target on $_mnt for kdump preflight check." + _mounted=$_mnt + else + perror_exit "$_target is configured in fstab but not mounted, please check its usability." + fi + fi + else + _mnt=$MKDUMPRD_TMPMNT + mkdir -p $_mnt + mount $_target $_mnt -t $_fstype -o defaults + [ $? -ne 0 ] && perror_exit "Failed to mount $_target for kdump preflight check." + _mounted=$_mnt + fi + + # For user configured target, use $SAVE_PATH as the dump path within the target + if [ ! -d "$_mnt/$SAVE_PATH" ]; then + perror_exit "Dump path \"$SAVE_PATH\" does not exist in dump target \"$_target\"" + fi + + check_size fs "$_target" + + # Unmount it early, if function is interrupted and didn't reach here, the shell trap will clear it up anyway + if [ -n "$_mounted" ]; then + umount -f -- $_mounted + fi +} + # $1: core_collector config value verify_core_collector() { local _cmd="${1%% *}" @@ -201,7 +277,7 @@ verify_core_collector() { } add_mount() { - local _mnt=$(to_mount "$1") + local _mnt=$(to_mount $@) if [ $? -ne 0 ]; then exit 1 @@ -354,14 +430,8 @@ do extra_modules="$extra_modules $config_val" ;; ext[234]|xfs|btrfs|minix|nfs) - if ! is_mounted $config_val; then - perror_exit "Dump target $config_val is probably not mounted." - fi - - # User configured target, use $SAVE_PATH as the dump path within the target - check_save_path_user_configured "$config_val" "$SAVE_PATH" - check_size fs "$config_val" - add_mount "$config_val" + check_user_configured_target "$config_val" "$config_opt" + add_mount "$config_val" "$config_opt" ;; raw) # checking raw disk writable