Merge pull request #7352 from eddiejames/master
Add path configuration for hardware watchdog device
This commit is contained in:
commit
f7757a4993
|
@ -382,6 +382,15 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.watchdog_device=</varname></term>
|
||||
|
||||
<listitem>
|
||||
<para>Overwrites the watchdog device path <varname>WatchdogDevice=</varname>. For details, see
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>modules_load=</varname></term>
|
||||
<term><varname>rd.modules_load=</varname></term>
|
||||
|
|
|
@ -161,8 +161,10 @@
|
|||
<literal>d</literal>, <literal>w</literal>). If
|
||||
<varname>RuntimeWatchdogSec=</varname> is set to a non-zero
|
||||
value, the watchdog hardware
|
||||
(<filename>/dev/watchdog</filename>) will be programmed to
|
||||
automatically reboot the system if it is not contacted within
|
||||
(<filename>/dev/watchdog</filename> or the path specified with
|
||||
<varname>WatchdogDevice=</varname> or the kernel option
|
||||
<varname>systemd.watchdog-device=</varname>) will be programmed
|
||||
to automatically reboot the system if it is not contacted within
|
||||
the specified timeout interval. The system manager will ensure
|
||||
to contact it at least once in half the specified timeout
|
||||
interval. This feature requires a hardware watchdog device to
|
||||
|
@ -179,6 +181,15 @@
|
|||
available.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>WatchdogDevice=</varname></term>
|
||||
|
||||
<listitem><para>Configure the hardware watchdog device that the
|
||||
runtime and shutdown watchdog timers will open and use. Defaults
|
||||
to <filename>/dev/watchdog</filename>. This setting has no
|
||||
effect if a hardware watchdog is not available.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>CapabilityBoundingSet=</varname></term>
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -27,10 +27,12 @@
|
|||
|
||||
#include "fd-util.h"
|
||||
#include "log.h"
|
||||
#include "string-util.h"
|
||||
#include "time-util.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
static int watchdog_fd = -1;
|
||||
static char *watchdog_device = NULL;
|
||||
static usec_t watchdog_timeout = USEC_INFINITY;
|
||||
|
||||
static int update_timeout(void) {
|
||||
|
@ -84,7 +86,8 @@ static int open_watchdog(void) {
|
|||
if (watchdog_fd >= 0)
|
||||
return 0;
|
||||
|
||||
watchdog_fd = open("/dev/watchdog", O_WRONLY|O_CLOEXEC);
|
||||
watchdog_fd = open(watchdog_device ?: "/dev/watchdog",
|
||||
O_WRONLY|O_CLOEXEC);
|
||||
if (watchdog_fd < 0)
|
||||
return -errno;
|
||||
|
||||
|
@ -96,6 +99,10 @@ static int open_watchdog(void) {
|
|||
return update_timeout();
|
||||
}
|
||||
|
||||
int watchdog_set_device(char *path) {
|
||||
return free_and_strdup(&watchdog_device, path);
|
||||
}
|
||||
|
||||
int watchdog_set_timeout(usec_t *usec) {
|
||||
int r;
|
||||
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
#include "time-util.h"
|
||||
#include "util.h"
|
||||
|
||||
int watchdog_set_device(char *path);
|
||||
int watchdog_set_timeout(usec_t *usec);
|
||||
int watchdog_ping(void);
|
||||
void watchdog_close(bool disarm);
|
||||
|
||||
static inline void watchdog_free_device(void) {
|
||||
(void) watchdog_set_device(NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue