From: Edward A. James Date: Fri, 8 Dec 2017 17:26:44 +0000 (-0600) Subject: core: Add WatchdogDevice config option and implement it X-Git-Tag: v236~31^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8a2c1fbfc377b20032ebc4cc287dda848554d61b;p=thirdparty%2Fsystemd.git 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). --- diff --git a/src/core/main.c b/src/core/main.c index 08d9188385b..4995446c512 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -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, diff --git a/src/core/shutdown.c b/src/core/shutdown.c index d54661b6987..d09ef190a28 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -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;