]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/watchdog.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2012 Lennart Poettering
11 #include <linux/watchdog.h>
15 #include "string-util.h"
16 #include "time-util.h"
19 static int watchdog_fd
= -1;
20 static char *watchdog_device
= NULL
;
21 static usec_t watchdog_timeout
= USEC_INFINITY
;
23 static int update_timeout(void) {
29 if (watchdog_timeout
== USEC_INFINITY
)
31 else if (watchdog_timeout
== 0) {
34 flags
= WDIOS_DISABLECARD
;
35 r
= ioctl(watchdog_fd
, WDIOC_SETOPTIONS
, &flags
);
37 return log_warning_errno(errno
, "Failed to disable hardware watchdog: %m");
40 char buf
[FORMAT_TIMESPAN_MAX
];
42 sec
= (int) DIV_ROUND_UP(watchdog_timeout
, USEC_PER_SEC
);
43 r
= ioctl(watchdog_fd
, WDIOC_SETTIMEOUT
, &sec
);
45 return log_warning_errno(errno
, "Failed to set timeout to %is: %m", sec
);
47 watchdog_timeout
= (usec_t
) sec
* USEC_PER_SEC
;
48 log_info("Set hardware watchdog to %s.", format_timespan(buf
, sizeof(buf
), watchdog_timeout
, 0));
50 flags
= WDIOS_ENABLECARD
;
51 r
= ioctl(watchdog_fd
, WDIOC_SETOPTIONS
, &flags
);
53 /* ENOTTY means the watchdog is always enabled so we're fine */
54 log_full(errno
== ENOTTY
? LOG_DEBUG
: LOG_WARNING
,
55 "Failed to enable hardware watchdog: %m");
60 r
= ioctl(watchdog_fd
, WDIOC_KEEPALIVE
, 0);
62 return log_warning_errno(errno
, "Failed to ping hardware watchdog: %m");
68 static int open_watchdog(void) {
69 struct watchdog_info ident
;
74 watchdog_fd
= open(watchdog_device
?: "/dev/watchdog",
79 if (ioctl(watchdog_fd
, WDIOC_GETSUPPORT
, &ident
) >= 0)
80 log_info("Hardware watchdog '%s', version %x",
82 ident
.firmware_version
);
84 return update_timeout();
87 int watchdog_set_device(char *path
) {
88 return free_and_strdup(&watchdog_device
, path
);
91 int watchdog_set_timeout(usec_t
*usec
) {
94 watchdog_timeout
= *usec
;
96 /* If we didn't open the watchdog yet and didn't get any
97 * explicit timeout value set, don't do anything */
98 if (watchdog_fd
< 0 && watchdog_timeout
== USEC_INFINITY
)
104 r
= update_timeout();
106 *usec
= watchdog_timeout
;
111 int watchdog_ping(void) {
114 if (watchdog_fd
< 0) {
120 r
= ioctl(watchdog_fd
, WDIOC_KEEPALIVE
, 0);
122 return log_warning_errno(errno
, "Failed to ping hardware watchdog: %m");
127 void watchdog_close(bool disarm
) {
136 /* Explicitly disarm it */
137 flags
= WDIOS_DISABLECARD
;
138 r
= ioctl(watchdog_fd
, WDIOC_SETOPTIONS
, &flags
);
140 log_warning_errno(errno
, "Failed to disable hardware watchdog: %m");
142 /* To be sure, use magic close logic, too */
144 static const char v
= 'V';
146 if (write(watchdog_fd
, &v
, 1) > 0)
149 if (errno
!= EINTR
) {
150 log_error_errno(errno
, "Failed to disarm watchdog timer: %m");
156 watchdog_fd
= safe_close(watchdog_fd
);