]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/watchdog.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include <linux/watchdog.h>
12 #include "string-util.h"
13 #include "time-util.h"
16 static int watchdog_fd
= -1;
17 static char *watchdog_device
= NULL
;
18 static usec_t watchdog_timeout
= USEC_INFINITY
;
20 static int update_timeout(void) {
26 if (watchdog_timeout
== USEC_INFINITY
)
28 else if (watchdog_timeout
== 0) {
31 flags
= WDIOS_DISABLECARD
;
32 r
= ioctl(watchdog_fd
, WDIOC_SETOPTIONS
, &flags
);
34 return log_warning_errno(errno
, "Failed to disable hardware watchdog: %m");
37 char buf
[FORMAT_TIMESPAN_MAX
];
39 sec
= (int) DIV_ROUND_UP(watchdog_timeout
, USEC_PER_SEC
);
40 r
= ioctl(watchdog_fd
, WDIOC_SETTIMEOUT
, &sec
);
42 return log_warning_errno(errno
, "Failed to set timeout to %is: %m", sec
);
44 watchdog_timeout
= (usec_t
) sec
* USEC_PER_SEC
;
45 log_info("Set hardware watchdog to %s.", format_timespan(buf
, sizeof(buf
), watchdog_timeout
, 0));
47 flags
= WDIOS_ENABLECARD
;
48 r
= ioctl(watchdog_fd
, WDIOC_SETOPTIONS
, &flags
);
50 /* ENOTTY means the watchdog is always enabled so we're fine */
51 log_full(errno
== ENOTTY
? LOG_DEBUG
: LOG_WARNING
,
52 "Failed to enable hardware watchdog: %m");
57 r
= ioctl(watchdog_fd
, WDIOC_KEEPALIVE
, 0);
59 return log_warning_errno(errno
, "Failed to ping hardware watchdog: %m");
65 static int open_watchdog(void) {
66 struct watchdog_info ident
;
71 watchdog_fd
= open(watchdog_device
?: "/dev/watchdog",
76 if (ioctl(watchdog_fd
, WDIOC_GETSUPPORT
, &ident
) >= 0)
77 log_info("Hardware watchdog '%s', version %x",
79 ident
.firmware_version
);
81 return update_timeout();
84 int watchdog_set_device(char *path
) {
85 return free_and_strdup(&watchdog_device
, path
);
88 int watchdog_set_timeout(usec_t
*usec
) {
91 watchdog_timeout
= *usec
;
93 /* If we didn't open the watchdog yet and didn't get any
94 * explicit timeout value set, don't do anything */
95 if (watchdog_fd
< 0 && watchdog_timeout
== USEC_INFINITY
)
101 r
= update_timeout();
103 *usec
= watchdog_timeout
;
108 int watchdog_ping(void) {
111 if (watchdog_fd
< 0) {
117 r
= ioctl(watchdog_fd
, WDIOC_KEEPALIVE
, 0);
119 return log_warning_errno(errno
, "Failed to ping hardware watchdog: %m");
124 void watchdog_close(bool disarm
) {
133 /* Explicitly disarm it */
134 flags
= WDIOS_DISABLECARD
;
135 r
= ioctl(watchdog_fd
, WDIOC_SETOPTIONS
, &flags
);
137 log_warning_errno(errno
, "Failed to disable hardware watchdog: %m");
139 /* To be sure, use magic close logic, too */
141 static const char v
= 'V';
143 if (write(watchdog_fd
, &v
, 1) > 0)
146 if (errno
!= EINTR
) {
147 log_error_errno(errno
, "Failed to disarm watchdog timer: %m");
153 watchdog_fd
= safe_close(watchdog_fd
);