summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd-system.conf.xml9
-rw-r--r--src/core/dbus-manager.c1
-rw-r--r--src/core/main.c21
-rw-r--r--src/core/manager.h1
-rw-r--r--src/core/system.conf.in1
-rw-r--r--test/fuzz/fuzz-unit-file/directives.service1
6 files changed, 27 insertions, 7 deletions
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index 5b80479a0a..4dd4bf0ca8 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -128,6 +128,7 @@
<varlistentry>
<term><varname>RuntimeWatchdogSec=</varname></term>
<term><varname>ShutdownWatchdogSec=</varname></term>
+ <term><varname>KExecWatchdogSec=</varname></term>
<listitem><para>Configure the hardware watchdog at runtime and at reboot. Takes a timeout value in seconds (or
in other time units if suffixed with <literal>ms</literal>, <literal>min</literal>, <literal>h</literal>,
@@ -149,7 +150,13 @@
phase of system shutdown, configure <varname>JobTimeoutSec=</varname> and <varname>JobTimeoutAction=</varname>
in the <literal>[Unit]</literal> section of the <filename>shutdown.target</filename> unit. By default
<varname>RuntimeWatchdogSec=</varname> defaults to 0 (off), and <varname>ShutdownWatchdogSec=</varname> to
- 10min. These settings have no effect if a hardware watchdog is not available.</para></listitem>
+ 10min. <varname>KExecWatchdogSec=</varname> may be used to additionally enable the watchdog when kexec
+ is being executed rather than when rebooting. Note that if the kernel does not reset the watchdog on kexec (depending
+ on the specific hardware and/or driver), in this case the watchdog might not get disabled after kexec succeeds
+ and thus the system might get rebooted, unless <varname>RuntimeWatchdogSec=</varname> is also enabled at the same time.
+ For this reason it is recommended to enable <varname>KExecWatchdogSec=</varname> only if
+ <varname>RuntimeWatchdogSec=</varname> is also enabled.
+ These settings have no effect if a hardware watchdog is not available.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 9fb3ed516a..e70c1e132a 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -2410,6 +2410,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
+ SD_BUS_WRITABLE_PROPERTY("KExecWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, kexec_watchdog), 0),
SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0),
SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
diff --git a/src/core/main.c b/src/core/main.c
index 8de3d4753d..ccfa22c814 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -122,6 +122,7 @@ static usec_t arg_default_start_limit_interval;
static unsigned arg_default_start_limit_burst;
static usec_t arg_runtime_watchdog;
static usec_t arg_shutdown_watchdog;
+static usec_t arg_kexec_watchdog;
static char *arg_early_core_pattern;
static char *arg_watchdog_device;
static char **arg_default_environment;
@@ -555,6 +556,7 @@ static int parse_config_file(void) {
{ "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
{ "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
{ "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
+ { "Manager", "KExecWatchdogSec", config_parse_sec, 0, &arg_kexec_watchdog },
{ "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device },
{ "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
{ "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs },
@@ -674,6 +676,7 @@ static void set_manager_settings(Manager *m) {
m->service_watchdogs = arg_service_watchdogs;
m->runtime_watchdog = arg_runtime_watchdog;
m->shutdown_watchdog = arg_shutdown_watchdog;
+ m->kexec_watchdog = arg_kexec_watchdog;
m->cad_burst_action = arg_cad_burst_action;
manager_set_show_status(m, arg_show_status);
@@ -1356,6 +1359,7 @@ static int become_shutdown(
_cleanup_strv_free_ char **env_block = NULL;
size_t pos = 7;
int r;
+ usec_t watchdog_timer = 0;
assert(shutdown_verb);
assert(!command_line[pos]);
@@ -1396,20 +1400,23 @@ static int become_shutdown(
assert(pos < ELEMENTSOF(command_line));
- if (STR_IN_SET(shutdown_verb, "reboot", "kexec") &&
- arg_shutdown_watchdog > 0 &&
- arg_shutdown_watchdog != USEC_INFINITY) {
+ if (streq(shutdown_verb, "reboot"))
+ watchdog_timer = arg_shutdown_watchdog;
+ else if (streq(shutdown_verb, "kexec"))
+ watchdog_timer = arg_kexec_watchdog;
+
+ if (watchdog_timer > 0 && watchdog_timer != USEC_INFINITY) {
char *e;
- /* If we reboot let's set the shutdown
+ /* If we reboot or kexec let's set the shutdown
* watchdog and tell the shutdown binary to
* repeatedly ping it */
- r = watchdog_set_timeout(&arg_shutdown_watchdog);
+ r = watchdog_set_timeout(&watchdog_timer);
watchdog_close(r < 0);
/* Tell the binary how often to ping, ignore failure */
- if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, arg_shutdown_watchdog) > 0)
+ if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, watchdog_timer) > 0)
(void) strv_consume(&env_block, e);
if (arg_watchdog_device &&
@@ -2100,6 +2107,7 @@ static void reset_arguments(void) {
arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST;
arg_runtime_watchdog = 0;
arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
+ arg_kexec_watchdog = 0;
arg_early_core_pattern = NULL;
arg_watchdog_device = NULL;
@@ -2639,6 +2647,7 @@ finish:
if (m) {
arg_shutdown_watchdog = m->shutdown_watchdog;
+ arg_kexec_watchdog = m->kexec_watchdog;
m = manager_free(m);
}
diff --git a/src/core/manager.h b/src/core/manager.h
index 9f2b5a0eb0..9600ab5144 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -229,6 +229,7 @@ struct Manager {
usec_t runtime_watchdog;
usec_t shutdown_watchdog;
+ usec_t kexec_watchdog;
dual_timestamp timestamps[_MANAGER_TIMESTAMP_MAX];
diff --git a/src/core/system.conf.in b/src/core/system.conf.in
index 8617ec20aa..af6e5d9f62 100644
--- a/src/core/system.conf.in
+++ b/src/core/system.conf.in
@@ -27,6 +27,7 @@
#NUMAMask=
#RuntimeWatchdogSec=0
#ShutdownWatchdogSec=10min
+#KExecWatchdogSec=0
#WatchdogDevice=
#CapabilityBoundingSet=
#NoNewPrivileges=no
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
index 2f59585671..d19610fc55 100644
--- a/test/fuzz/fuzz-unit-file/directives.service
+++ b/test/fuzz/fuzz-unit-file/directives.service
@@ -703,6 +703,7 @@ LogTarget=
RuntimeWatchdogSec=
ShowStatus=
ShutdownWatchdogSec=
+KExecWatchdogSec=
SuspendMode=
SuspendState=
SystemCallArchitectures=