diff options
author | Franck Bui <fbui@suse.com> | 2021-09-27 10:51:28 +0200 |
---|---|---|
committer | Franck Bui <fbui@suse.com> | 2021-10-13 08:58:36 +0200 |
commit | 0ffdfe7d6863e6d479323d90c222f2dcae2ff057 (patch) | |
tree | 45ceaf4ff836d9ee8740ccb318e3f7a27582a32a /src/shared/watchdog.c | |
parent | core: introduce systemd.watchdog_sec=<sec> option (diff) | |
download | systemd-0ffdfe7d6863e6d479323d90c222f2dcae2ff057.tar.xz systemd-0ffdfe7d6863e6d479323d90c222f2dcae2ff057.zip |
watchdog: handle timeout programming errors more safely
If an error happened while the timeout value was being programmed, the error
was ignored and the watchdog module used the new timeout value whereas the
watchdog device was left with the previous one.
Now in cases of error, the device is now disabled and closed if it wasn't
opened already otherwise the previous timeout value is kept so the device is
still pinged at correct intervals.
Diffstat (limited to '')
-rw-r--r-- | src/shared/watchdog.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c index b6fddd193f..4de6003039 100644 --- a/src/shared/watchdog.c +++ b/src/shared/watchdog.c @@ -96,8 +96,8 @@ static int update_timeout(void) { r = watchdog_set_timeout(); if (r < 0) { if (!ERRNO_IS_NOT_SUPPORTED(r)) - return log_warning_errno(r, "Failed to set timeout to %s, ignoring: %m", - FORMAT_TIMESPAN(watchdog_timeout, 0)); + return log_error_errno(r, "Failed to set timeout to %s: %m", + FORMAT_TIMESPAN(watchdog_timeout, 0)); log_info("Modifying watchdog timeout is not supported, reusing the programmed timeout."); watchdog_timeout = USEC_INFINITY; @@ -107,7 +107,7 @@ static int update_timeout(void) { if (watchdog_timeout == USEC_INFINITY) { r = watchdog_get_timeout(); if (r < 0) - return log_warning_errno(errno, "Failed to query watchdog HW timeout, ignoring: %m"); + return log_error_errno(errno, "Failed to query watchdog HW timeout: %m"); } r = watchdog_set_enable(true); @@ -122,6 +122,7 @@ static int update_timeout(void) { static int open_watchdog(void) { struct watchdog_info ident; const char *fn; + int r; if (watchdog_fd >= 0) return 0; @@ -139,7 +140,11 @@ static int open_watchdog(void) { ident.firmware_version, fn); - return update_timeout(); + r = update_timeout(); + if (r < 0) + watchdog_close(true); + + return r; } int watchdog_set_device(const char *path) { @@ -156,6 +161,8 @@ int watchdog_set_device(const char *path) { } int watchdog_setup(usec_t timeout) { + usec_t previous_timeout; + int r; /* timeout=0 closes the device whereas passing timeout=USEC_INFINITY * opens it (if needed) without configuring any particular timeout and @@ -175,12 +182,17 @@ int watchdog_setup(usec_t timeout) { /* Initialize the watchdog timeout with the caller value. This value is * going to be updated by update_timeout() with the closest value * supported by the driver */ + previous_timeout = watchdog_timeout; watchdog_timeout = timeout; if (watchdog_fd < 0) return open_watchdog(); - return update_timeout(); + r = update_timeout(); + if (r < 0) + watchdog_timeout = previous_timeout; + + return r; } usec_t watchdog_runtime_wait(void) { |