1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-03-12 08:58:20 +03:00

core: Add WatchdogDevice config option and implement it

This option allows a device path to be specified for the systemd
watchdog (both runtime and shutdown).

If a system requires a watchdog other than /dev/watchdog (pointing to
/dev/watchdog0) to be used to reboot the system, this setting should be
changed to the relevant watchdog device path (e.g. /dev/watchdog1).
This commit is contained in:
Edward A. James 2017-12-08 11:26:44 -06:00
parent e4c98db335
commit 8a2c1fbfc3
2 changed files with 41 additions and 2 deletions

View File

@ -120,6 +120,7 @@ static usec_t arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL;
static unsigned arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST;
static usec_t arg_runtime_watchdog = 0;
static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
static char *arg_watchdog_device = NULL;
static char **arg_default_environment = NULL;
static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
static uint64_t arg_capability_bounding_set = CAP_ALL;
@ -461,6 +462,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (arg_default_timeout_start_usec <= 0)
arg_default_timeout_start_usec = USEC_INFINITY;
} else if (proc_cmdline_key_streq(key, "systemd.watchdog_device")) {
if (proc_cmdline_value_missing(key, value))
return 0;
parse_path_argument_and_warn(value, false, &arg_watchdog_device);
} else if (streq(key, "quiet") && !value) {
if (arg_show_status == _SHOW_STATUS_UNSET)
@ -751,6 +759,7 @@ static int parse_config_file(void) {
{ "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
{ "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
{ "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
{ "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device },
{ "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
#if HAVE_SECCOMP
{ "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs },
@ -1521,7 +1530,11 @@ static int become_shutdown(
/* Tell the binary how often to ping, ignore failure */
if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, arg_shutdown_watchdog) > 0)
(void) strv_push(&env_block, e);
(void) strv_consume(&env_block, e);
if (arg_watchdog_device &&
asprintf(&e, "WATCHDOG_DEVICE=%s", arg_watchdog_device) > 0)
(void) strv_consume(&env_block, e);
} else
watchdog_close(true);
@ -1914,6 +1927,13 @@ static int initialize_runtime(
write_container_id();
}
if (arg_system && arg_watchdog_device) {
r = watchdog_set_device(arg_watchdog_device);
if (r < 0)
log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m",
arg_watchdog_device);
}
if (arg_system && arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY)
watchdog_set_timeout(&arg_runtime_watchdog);
@ -2450,8 +2470,13 @@ finish:
* here explicitly. valgrind will only generate nice output on
* exit(), not on exec(), hence let's do the former not the
* latter here. */
if (getpid_cached() == 1 && RUNNING_ON_VALGRIND)
if (getpid_cached() == 1 && RUNNING_ON_VALGRIND) {
/* Cleanup watchdog_device strings for valgrind. We need them
* in become_shutdown() so normally we cannot free them yet. */
watchdog_free_device();
arg_watchdog_device = mfree(arg_watchdog_device);
return 0;
}
#endif
if (shutdown_verb) {
@ -2461,6 +2486,9 @@ finish:
error_message = "Failed to execute shutdown binary";
}
watchdog_free_device();
arg_watchdog_device = mfree(arg_watchdog_device);
if (getpid_cached() == 1) {
if (error_message)
manager_status_printf(NULL, STATUS_TYPE_EMERGENCY,

View File

@ -167,6 +167,7 @@ int main(int argc, char *argv[]) {
unsigned retries;
int cmd, r;
static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL};
char *watchdog_device;
log_parse_environment();
r = parse_argv(argc, argv);
@ -207,6 +208,13 @@ int main(int argc, char *argv[]) {
in_container = detect_container() > 0;
use_watchdog = !!getenv("WATCHDOG_USEC");
watchdog_device = getenv("WATCHDOG_DEVICE");
if (watchdog_device) {
r = watchdog_set_device(watchdog_device);
if (r < 0)
log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m",
watchdog_device);
}
/* Lock us into memory */
mlockall(MCL_CURRENT|MCL_FUTURE);
@ -320,6 +328,9 @@ int main(int argc, char *argv[]) {
initrd_jump:
/* We're done with the watchdog. */
watchdog_free_device();
arguments[0] = NULL;
arguments[1] = arg_verb;
arguments[2] = NULL;