Now upon failure kdump script might not be called at all and it might
not be able to execute default action. It results in a hang.
Because we disable emergency shell and rely on kdump.sh being invoked
through dracut-pre-pivot hook. But it might happen that we never call
into dracut-pre-pivot hook because certain systemd targets could not
reach due to failure in their dependencies. In those cases error
handling code does not run and system hangs.
To solve this problem, we need to separate the error handling code from
dracut-pre-pivot hook, and every time when a failure shows up, the
separated code can be called by the emergency service.
By default systemd provides an emergency service which will drop us into
shell every time upon a critical failure. It's very convenient for us to
re-use the framework of systemd emergency, because we don't have to
touch the other parts of systemd. We can use our own script instead of
the default one.
This new scheme will overwrite emergency shell and replace with kdump
error handling code. And this code will do the error handling as needed.
Now, we will not rely on dracut-pre-pivot hook running always. Instead
whenever error happens and it is serious enough that emergency shell
needed to run, now kdump error handler will run.
dracut-emergency is also replaced by kdump error handler and it's
enabled again all the way down. So all the failure (including systemd
and dracut) in 2nd kernel could be captured, and trigger kdump error
handler.
Signed-off-by: WANG Chao <chaowang(a)redhat.com>
---
dracut-kdump-emergency.service | 30 ++++++++++++++++++++++++++++++
dracut-kdump-error-handler.sh | 10 ++++++++++
dracut-kdump.sh | 4 ----
dracut-module-setup.sh | 6 +++++-
kdump-lib-initramfs.sh | 34 ++++++++++++++++++++++++++++++----
kexec-tools.spec | 5 ++++-
6 files changed, 79 insertions(+), 10 deletions(-)
create mode 100644 dracut-kdump-emergency.service
create mode 100755 dracut-kdump-error-handler.sh
diff --git a/dracut-kdump-emergency.service b/dracut-kdump-emergency.service
new file mode 100644
index 0000000..4434b9e
--- /dev/null
+++ b/dracut-kdump-emergency.service
@@ -0,0 +1,30 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Kdump Error Handler
+DefaultDependencies=no
+After=systemd-vconsole-setup.service
+Wants=systemd-vconsole-setup.service
+
+[Service]
+Environment=HOME=/
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+WorkingDirectory=/
+ExecStart=/bin/kdump-error-handler.sh
+ExecStopPost=-/usr/bin/systemctl --fail --no-block default
+Type=oneshot
+StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
+KillMode=process
+IgnoreSIGPIPE=no
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/dracut-kdump-error-handler.sh b/dracut-kdump-error-handler.sh
new file mode 100755
index 0000000..2f0f1d1
--- /dev/null
+++ b/dracut-kdump-error-handler.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+. /lib/kdump-lib-initramfs.sh
+
+set -o pipefail
+export PATH=$PATH:$KDUMP_SCRIPT_DIR
+
+get_kdump_confs
+do_default_action
+do_final_action
diff --git a/dracut-kdump.sh b/dracut-kdump.sh
index a2bfa05..83c1e96 100755
--- a/dracut-kdump.sh
+++ b/dracut-kdump.sh
@@ -9,10 +9,6 @@ exec &> /dev/console
. /lib/dracut-lib.sh
. /lib/kdump-lib-initramfs.sh
-if [ -f "$initdir/lib/dracut/no-emergency-shell" ]; then
- rm -f -- $initdir/lib/dracut/no-emergency-shell
-fi
-
set -o pipefail
DUMP_RETVAL=0
diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh
index 758420b..b9a7000 100755
--- a/dracut-module-setup.sh
+++ b/dracut-module-setup.sh
@@ -563,7 +563,6 @@ kdump_install_random_seed() {
install() {
kdump_install_conf
- >"$initdir/lib/dracut/no-emergency-shell"
if is_ssh_dump_target; then
kdump_install_random_seed
@@ -581,6 +580,11 @@ install() {
inst_hook pre-pivot 9999 "$moddir/kdump.sh"
inst "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh"
inst "/lib/kdump/kdump-lib-initramfs.sh"
"/lib/kdump-lib-initramfs.sh"
+ inst "$moddir/kdump-error-handler.sh"
"/usr/bin/kdump-error-handler.sh"
+ # Replace existing emergency service
+ cp "$moddir/kdump-emergency.service"
"$initdir/$systemdsystemunitdir/emergency.service"
+ # Redirect dracut-emergency to kdump error handler
+ ln_r "$systemdsystemunitdir/emergency.service"
"$systemdsystemunitdir/dracut-emergency.service"
# Check for all the devices and if any device is iscsi, bring up iscsi
# target. Ideally all this should be pushed into dracut iscsi module
diff --git a/kdump-lib-initramfs.sh b/kdump-lib-initramfs.sh
index 9118b64..1517712 100755
--- a/kdump-lib-initramfs.sh
+++ b/kdump-lib-initramfs.sh
@@ -1,6 +1,5 @@
# These variables and functions are useful in 2nd kernel
-. /lib/dracut-lib.sh
. /lib/kdump-lib.sh
KDUMP_PATH="/var/crash"
@@ -23,6 +22,7 @@ NEWROOT="/sysroot"
get_kdump_confs()
{
local config_opt config_val
+ local user_specified_cc
while read config_opt config_val;
do
@@ -34,6 +34,7 @@ get_kdump_confs()
;;
core_collector)
[ -n "$config_val" ] &&
CORE_COLLECTOR="$config_val"
+ user_specified_cc=yes
;;
sshkey)
if [ -f "$config_val" ]; then
@@ -55,7 +56,7 @@ get_kdump_confs()
default)
case $config_val in
shell)
- DEFAULT_ACTION="_emergency_shell kdump"
+ DEFAULT_ACTION="kdump_emergency_shell"
;;
reboot)
DEFAULT_ACTION="do_umount; reboot -f"
@@ -67,12 +68,19 @@ get_kdump_confs()
DEFAULT_ACTION="do_umount; poweroff -f"
;;
dump_to_rootfs)
- DEFAULT_ACTION="dump_fs $NEWROOT"
+ DEFAULT_ACTION="dump_to_rootfs"
;;
esac
;;
esac
done < $KDUMP_CONF
+
+ if is_ssh_dump_target || is_raw_dump_target; then
+ if [ -z "$user_specified_cc" ]; then
+ CORE_COLLECTOR="$CORE_COLLECTOR -F"
+ fi
+ fi
+
}
# dump_fs <mount point| device>
@@ -127,6 +135,24 @@ save_vmcore_dmesg_fs() {
fi
}
+dump_to_rootfs()
+{
+
+ echo "Kdump: trying to bring up rootfs device"
+ systemctl start dracut-initqueue
+ echo "Kdump: waiting for rootfs mount, will timeout after 90 seconds"
+ systemctl start sysroot.mount
+
+ dump_fs $NEWROOT
+}
+
+kdump_emergency_shell()
+{
+ echo "PS1=\"kdump:\\\${PWD}# \"" >/etc/profile
+ /bin/dracut-emergency
+ rm -f /etc/profile
+}
+
do_umount()
{
umount -Rf $NEWROOT
@@ -134,7 +160,7 @@ do_umount()
do_default_action()
{
- wait_for_loginit
+ echo "Kdump: Executing default action $DEFAULT_ACTION"
eval $DEFAULT_ACTION
}
diff --git a/kexec-tools.spec b/kexec-tools.spec
index b55a7f1..91deade 100644
--- a/kexec-tools.spec
+++ b/kexec-tools.spec
@@ -36,6 +36,8 @@ Source24: kdump-lib-initramfs.sh
Source100: dracut-kdump.sh
Source101: dracut-module-setup.sh
Source102: dracut-monitor_dd_progress
+Source103: dracut-kdump-error-handler.sh
+Source104: dracut-kdump-emergency.service
Requires(post): systemd-units
Requires(preun): systemd-units
@@ -210,7 +212,8 @@ mkdir -p -m755
$RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpba
cp %{SOURCE100}
$RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix
%{SOURCE100}}
cp %{SOURCE101}
$RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix
%{SOURCE101}}
cp %{SOURCE102}
$RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix
%{SOURCE102}}
-
+cp %{SOURCE103}
$RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix
%{SOURCE103}}
+cp %{SOURCE104}
$RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix
%{SOURCE104}}
chmod 755
$RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix
%{SOURCE100}}
chmod 755
$RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix
%{SOURCE101}}
--
1.9.3