1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-30 06:25:37 +03:00

watchdog: saturate to kernel's max watchdog timeout

Since version 4.5, the max possible timeout is UINT_MAX / 1000 since it
does calculations in milliseconds. A small helper function is added to
make this conversion and saturation and will be used more in the next
commit.

Also document the usage of signed integers by the kernel userspace API.
This commit is contained in:
Curtis Klein 2021-10-09 18:18:54 -07:00 committed by Lennart Poettering
parent 9eb0583feb
commit d6463a399d

View File

@ -20,6 +20,20 @@ static char *watchdog_device;
static usec_t watchdog_timeout; /* 0 → close device and USEC_INFINITY → don't change timeout */
static usec_t watchdog_last_ping = USEC_INFINITY;
/* Starting from kernel version 4.5, the maximum allowable watchdog timeout is
* UINT_MAX/1000U seconds (since internal calculations are done in milliseconds
* using unsigned integers. However, the kernel's userspace API for the watchdog
* uses signed integers for its ioctl parameters (even for timeout values and
* bit flags) so this is why we must consider the maximum signed integer value
* as well.
*/
#define WATCHDOG_TIMEOUT_MAX_SEC (CONST_MIN(UINT_MAX/1000U, (unsigned)INT_MAX))
static int saturated_usec_to_sec(usec_t val) {
usec_t t = DIV_ROUND_UP(val, USEC_PER_SEC);
return MIN(t, (usec_t) WATCHDOG_TIMEOUT_MAX_SEC); /* Saturate to watchdog max */
}
static int watchdog_set_enable(bool enable) {
int flags = enable ? WDIOS_ENABLECARD : WDIOS_DISABLECARD;
@ -54,14 +68,12 @@ static int watchdog_get_timeout(void) {
}
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 */
sec = saturated_usec_to_sec(watchdog_timeout);
if (ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec) < 0)
return -errno;