static usec_t watchdog_timeout = USEC_INFINITY;
static usec_t watchdog_last_ping = USEC_INFINITY;
+static int watchdog_set_enable(bool enable) {
+ int flags = enable ? WDIOS_ENABLECARD : WDIOS_DISABLECARD;
+ int r;
+
+ assert(watchdog_fd >= 0);
+
+ r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags);
+ if (r < 0) {
+ if (!enable)
+ return log_warning_errno(errno, "Failed to disable hardware watchdog, ignoring: %m");
+
+ /* ENOTTY means the watchdog is always enabled so we're fine */
+ log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno,
+ "Failed to enable hardware watchdog, ignoring: %m");
+ if (!ERRNO_IS_NOT_SUPPORTED(errno))
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int watchdog_set_timeout(void) {
+ usec_t t;
+ int sec;
+
+ assert(watchdog_fd >= 0);
+ assert(timestamp_is_set(watchdog_timeout));
+
+ t = DIV_ROUND_UP(watchdog_timeout, USEC_PER_SEC);
+ sec = MIN(t, (usec_t) INT_MAX); /* Saturate */
+
+ if (ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec) < 0)
+ return log_warning_errno(errno, "Failed to set timeout to %is, ignoring: %m", sec);
+
+ /* Just in case the driver is buggy */
+ assert(sec > 0);
+
+ /* watchdog_timeout stores the timeout used by the HW */
+ watchdog_timeout = sec * USEC_PER_SEC;
+
+ log_info("Set hardware watchdog to %s.", FORMAT_TIMESPAN(watchdog_timeout, 0));
+ return 0;
+}
+
+static int watchdog_ping_now(void) {
+ assert(watchdog_fd >= 0);
+
+ if (ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0) < 0)
+ return log_warning_errno(errno, "Failed to ping hardware watchdog, ignoring: %m");
+
+ watchdog_last_ping = now(clock_boottime_or_monotonic());
+
+ return 0;
+}
+
static int update_timeout(void) {
+ int r;
+
if (watchdog_fd < 0)
return 0;
if (watchdog_timeout == USEC_INFINITY)
return 0;
- if (watchdog_timeout == 0) {
- int flags;
+ if (watchdog_timeout == 0)
+ return watchdog_set_enable(false);
- flags = WDIOS_DISABLECARD;
- if (ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags) < 0)
- return log_warning_errno(errno, "Failed to disable hardware watchdog, ignoring: %m");
- } else {
- int sec, flags;
- usec_t t;
-
- t = DIV_ROUND_UP(watchdog_timeout, USEC_PER_SEC);
- sec = MIN(t, (usec_t) INT_MAX); /* Saturate */
- if (ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec) < 0)
- return log_warning_errno(errno, "Failed to set timeout to %is, ignoring: %m", sec);
-
- /* Just in case the driver is buggy */
- assert(sec > 0);
-
- /* watchdog_timeout stores the actual timeout used by the HW */
- watchdog_timeout = sec * USEC_PER_SEC;
- log_info("Set hardware watchdog to %s.", FORMAT_TIMESPAN(watchdog_timeout, 0));
-
- flags = WDIOS_ENABLECARD;
- if (ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags) < 0) {
- /* ENOTTY means the watchdog is always enabled so we're fine */
- log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno,
- "Failed to enable hardware watchdog, ignoring: %m");
- if (!ERRNO_IS_NOT_SUPPORTED(errno))
- return -errno;
- }
-
- if (ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0) < 0)
- return log_warning_errno(errno, "Failed to ping hardware watchdog, ignoring: %m");
+ r = watchdog_set_timeout();
+ if (r < 0)
+ return r;
- watchdog_last_ping = now(clock_boottime_or_monotonic());
- }
+ r = watchdog_set_enable(true);
+ if (r < 0)
+ return r;
- return 0;
+ return watchdog_ping_now();
}
static int open_watchdog(void) {
return 0;
}
- if (ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0) < 0)
- return log_warning_errno(errno, "Failed to ping hardware watchdog, ignoring: %m");
-
- watchdog_last_ping = ntime;
- return 0;
+ return watchdog_ping_now();
}
void watchdog_close(bool disarm) {
return;
if (disarm) {
- int flags;
-
- /* Explicitly disarm it */
- flags = WDIOS_DISABLECARD;
- if (ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags) < 0)
- log_warning_errno(errno, "Failed to disable hardware watchdog, ignoring: %m");
+ (void) watchdog_set_enable(false);
/* To be sure, use magic close logic, too */
for (;;) {