]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/watchdog.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2012 Lennart Poettering
10 #include <sys/ioctl.h>
13 #include <linux/watchdog.h>
17 #include "string-util.h"
18 #include "time-util.h"
21 static int watchdog_fd
= -1;
22 static char *watchdog_device
= NULL
;
23 static usec_t watchdog_timeout
= USEC_INFINITY
;
25 static int update_timeout(void) {
31 if (watchdog_timeout
== USEC_INFINITY
)
33 else if (watchdog_timeout
== 0) {
36 flags
= WDIOS_DISABLECARD
;
37 r
= ioctl(watchdog_fd
, WDIOC_SETOPTIONS
, &flags
);
39 return log_warning_errno(errno
, "Failed to disable hardware watchdog: %m");
42 char buf
[FORMAT_TIMESPAN_MAX
];
44 sec
= (int) DIV_ROUND_UP(watchdog_timeout
, USEC_PER_SEC
);
45 r
= ioctl(watchdog_fd
, WDIOC_SETTIMEOUT
, &sec
);
47 return log_warning_errno(errno
, "Failed to set timeout to %is: %m", sec
);
49 watchdog_timeout
= (usec_t
) sec
* USEC_PER_SEC
;
50 log_info("Set hardware watchdog to %s.", format_timespan(buf
, sizeof(buf
), watchdog_timeout
, 0));
52 flags
= WDIOS_ENABLECARD
;
53 r
= ioctl(watchdog_fd
, WDIOC_SETOPTIONS
, &flags
);
55 /* ENOTTY means the watchdog is always enabled so we're fine */
56 log_full(errno
== ENOTTY
? LOG_DEBUG
: LOG_WARNING
,
57 "Failed to enable hardware watchdog: %m");
62 r
= ioctl(watchdog_fd
, WDIOC_KEEPALIVE
, 0);
64 return log_warning_errno(errno
, "Failed to ping hardware watchdog: %m");
70 static int open_watchdog(void) {
71 struct watchdog_info ident
;
76 watchdog_fd
= open(watchdog_device
?: "/dev/watchdog",
81 if (ioctl(watchdog_fd
, WDIOC_GETSUPPORT
, &ident
) >= 0)
82 log_info("Hardware watchdog '%s', version %x",
84 ident
.firmware_version
);
86 return update_timeout();
89 int watchdog_set_device(char *path
) {
90 return free_and_strdup(&watchdog_device
, path
);
93 int watchdog_set_timeout(usec_t
*usec
) {
96 watchdog_timeout
= *usec
;
98 /* If we didn't open the watchdog yet and didn't get any
99 * explicit timeout value set, don't do anything */
100 if (watchdog_fd
< 0 && watchdog_timeout
== USEC_INFINITY
)
106 r
= update_timeout();
108 *usec
= watchdog_timeout
;
113 int watchdog_ping(void) {
116 if (watchdog_fd
< 0) {
122 r
= ioctl(watchdog_fd
, WDIOC_KEEPALIVE
, 0);
124 return log_warning_errno(errno
, "Failed to ping hardware watchdog: %m");
129 void watchdog_close(bool disarm
) {
138 /* Explicitly disarm it */
139 flags
= WDIOS_DISABLECARD
;
140 r
= ioctl(watchdog_fd
, WDIOC_SETOPTIONS
, &flags
);
142 log_warning_errno(errno
, "Failed to disable hardware watchdog: %m");
144 /* To be sure, use magic close logic, too */
146 static const char v
= 'V';
148 if (write(watchdog_fd
, &v
, 1) > 0)
151 if (errno
!= EINTR
) {
152 log_error_errno(errno
, "Failed to disarm watchdog timer: %m");
158 watchdog_fd
= safe_close(watchdog_fd
);