mirror of
https://git.freebsd.org/src.git
synced 2026-01-11 19:57:22 +00:00
watchdog: Convert to using sbintime_t format
Summary: Some watchdogs are now based on a countdown timer instead of a bit check. To deal with these, convert the watchdog framework to use sbintime_t instead of power-of-2-nanoseconds. This allows more precision, and more variety of watchdog timeouts. Keep the old method as a compatibility layer, so that drivers can be migrated slowly, as needed. Reviewed by: jhb Sponsored by: Juniper Networks, Inc. Differential Revision: https://reviews.freebsd.org/D49183
This commit is contained in:
parent
69f7d6912a
commit
26d6617f3e
3 changed files with 144 additions and 176 deletions
|
|
@ -50,11 +50,20 @@
|
|||
|
||||
#include <sys/syscallsubr.h> /* kern_clock_gettime() */
|
||||
|
||||
static int wd_set_pretimeout(int newtimeout, int disableiftoolong);
|
||||
#ifdef COMPAT_FREEBSD14
|
||||
#define WDIOCPATPAT_14 _IOW('W', 42, u_int) /* pat the watchdog */
|
||||
#define WDIOC_SETTIMEOUT_14 _IOW('W', 43, int) /* set/reset the timer */
|
||||
#define WDIOC_GETTIMEOUT_14 _IOR('W', 44, int) /* get total timeout */
|
||||
#define WDIOC_GETTIMELEFT_14 _IOR('W', 45, int) /* get time left */
|
||||
#define WDIOC_GETPRETIMEOUT_14 _IOR('W', 46, int) /* get the pre-timeout */
|
||||
#define WDIOC_SETPRETIMEOUT_14 _IOW('W', 47, int) /* set the pre-timeout */
|
||||
#endif
|
||||
|
||||
static int wd_set_pretimeout(sbintime_t newtimeout, int disableiftoolong);
|
||||
static void wd_timeout_cb(void *arg);
|
||||
|
||||
static struct callout wd_pretimeo_handle;
|
||||
static int wd_pretimeout;
|
||||
static sbintime_t wd_pretimeout;
|
||||
static int wd_pretimeout_act = WD_SOFT_LOG;
|
||||
|
||||
static struct callout wd_softtimeo_handle;
|
||||
|
|
@ -63,6 +72,8 @@ static int wd_softtimer; /* true = use softtimer instead of hardware
|
|||
static int wd_softtimeout_act = WD_SOFT_LOG; /* action for the software timeout */
|
||||
|
||||
static struct cdev *wd_dev;
|
||||
static volatile sbintime_t wd_last_sbt; /* last timeout value (sbt) */
|
||||
static sbintime_t wd_last_sbt_sysctl; /* last timeout value (sbt) */
|
||||
static volatile u_int wd_last_u; /* last timeout value set by kern_do_pat */
|
||||
static u_int wd_last_u_sysctl; /* last timeout value set by kern_do_pat */
|
||||
static u_int wd_last_u_sysctl_secs; /* wd_last_u in seconds */
|
||||
|
|
@ -73,6 +84,8 @@ SYSCTL_UINT(_hw_watchdog, OID_AUTO, wd_last_u, CTLFLAG_RD,
|
|||
&wd_last_u_sysctl, 0, "Watchdog last update time");
|
||||
SYSCTL_UINT(_hw_watchdog, OID_AUTO, wd_last_u_secs, CTLFLAG_RD,
|
||||
&wd_last_u_sysctl_secs, 0, "Watchdog last update time");
|
||||
SYSCTL_SBINTIME_MSEC(_hw_watchdog, OID_AUTO, wd_last_msecs, CTLFLAG_RD,
|
||||
&wd_last_sbt_sysctl, "Watchdog last update time (milliseconds)");
|
||||
|
||||
static int wd_lastpat_valid = 0;
|
||||
static time_t wd_lastpat = 0; /* when the watchdog was last patted */
|
||||
|
|
@ -80,41 +93,26 @@ static time_t wd_lastpat = 0; /* when the watchdog was last patted */
|
|||
/* Hook for external software watchdog to register for use if needed */
|
||||
void (*wdog_software_attach)(void);
|
||||
|
||||
static void
|
||||
pow2ns_to_ts(int pow2ns, struct timespec *ts)
|
||||
/* Legacy interface to watchdog. */
|
||||
int
|
||||
wdog_kern_pat(u_int utim)
|
||||
{
|
||||
uint64_t ns;
|
||||
sbintime_t sbt;
|
||||
|
||||
ns = 1ULL << pow2ns;
|
||||
ts->tv_sec = ns / 1000000000ULL;
|
||||
ts->tv_nsec = ns % 1000000000ULL;
|
||||
}
|
||||
if ((utim & WD_LASTVAL) != 0 && (utim & WD_INTERVAL) > 0)
|
||||
return (EINVAL);
|
||||
|
||||
static int
|
||||
pow2ns_to_ticks(int pow2ns)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timespec ts;
|
||||
|
||||
pow2ns_to_ts(pow2ns, &ts);
|
||||
TIMESPEC_TO_TIMEVAL(&tv, &ts);
|
||||
return (tvtohz(&tv));
|
||||
}
|
||||
|
||||
static int
|
||||
seconds_to_pow2ns(int seconds)
|
||||
{
|
||||
uint64_t power;
|
||||
uint64_t ns;
|
||||
uint64_t shifted;
|
||||
|
||||
ns = ((uint64_t)seconds) * 1000000000ULL;
|
||||
power = flsll(ns);
|
||||
shifted = 1ULL << power;
|
||||
if (shifted <= ns) {
|
||||
power++;
|
||||
if ((utim & WD_LASTVAL) != 0) {
|
||||
return (wdog_control(WD_CTRL_RESET));
|
||||
}
|
||||
return (power);
|
||||
|
||||
utim &= WD_INTERVAL;
|
||||
if (utim == WD_TO_NEVER)
|
||||
sbt = 0;
|
||||
else
|
||||
sbt = nstosbt(1 << utim);
|
||||
|
||||
return (wdog_kern_pat_sbt(sbt));
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -126,76 +124,63 @@ wdog_control(int ctrl)
|
|||
}
|
||||
|
||||
if ((ctrl & WD_CTRL_RESET) != 0) {
|
||||
wdog_kern_pat(WD_ACTIVE | WD_LASTVAL);
|
||||
wdog_kern_pat_sbt(wd_last_sbt);
|
||||
} else if ((ctrl & WD_CTRL_ENABLE) != 0) {
|
||||
wdog_kern_pat(WD_ACTIVE | WD_LASTVAL);
|
||||
wdog_kern_pat_sbt(wd_last_sbt);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
wdog_kern_pat(u_int utim)
|
||||
wdog_kern_pat_sbt(sbintime_t sbt)
|
||||
{
|
||||
int error;
|
||||
static int first = 1;
|
||||
sbintime_t error_sbt = 0;
|
||||
int pow2ns = 0;
|
||||
int error = 0;
|
||||
static bool first = true;
|
||||
|
||||
if ((utim & WD_LASTVAL) != 0 && (utim & WD_INTERVAL) > 0)
|
||||
return (EINVAL);
|
||||
|
||||
if ((utim & WD_LASTVAL) != 0) {
|
||||
/*
|
||||
* if WD_LASTVAL is set, fill in the bits for timeout
|
||||
* from the saved value in wd_last_u.
|
||||
*/
|
||||
MPASS((wd_last_u & ~WD_INTERVAL) == 0);
|
||||
utim &= ~WD_LASTVAL;
|
||||
utim |= wd_last_u;
|
||||
} else {
|
||||
/*
|
||||
* Otherwise save the new interval.
|
||||
* This can be zero (to disable the watchdog)
|
||||
*/
|
||||
wd_last_u = (utim & WD_INTERVAL);
|
||||
/* legacy uses power-of-2-nanoseconds time. */
|
||||
if (sbt != 0) {
|
||||
pow2ns = flsl(sbttons(sbt));
|
||||
}
|
||||
if (wd_last_sbt != sbt) {
|
||||
wd_last_u = pow2ns;
|
||||
wd_last_u_sysctl = wd_last_u;
|
||||
wd_last_u_sysctl_secs = pow2ns_to_ticks(wd_last_u) / hz;
|
||||
}
|
||||
if ((utim & WD_INTERVAL) == WD_TO_NEVER) {
|
||||
utim = 0;
|
||||
wd_last_u_sysctl_secs = sbt / SBT_1S;
|
||||
|
||||
/* Assume all is well; watchdog signals failure. */
|
||||
error = 0;
|
||||
} else {
|
||||
/* Assume no watchdog available; watchdog flags success */
|
||||
error = EOPNOTSUPP;
|
||||
wd_last_sbt = sbt;
|
||||
}
|
||||
|
||||
if (sbt != 0)
|
||||
error = EOPNOTSUPP;
|
||||
|
||||
if (wd_softtimer) {
|
||||
if (utim == 0) {
|
||||
if (sbt == 0) {
|
||||
callout_stop(&wd_softtimeo_handle);
|
||||
} else {
|
||||
(void) callout_reset(&wd_softtimeo_handle,
|
||||
pow2ns_to_ticks(utim), wd_timeout_cb, "soft");
|
||||
(void) callout_reset_sbt(&wd_softtimeo_handle,
|
||||
sbt, 0, wd_timeout_cb, "soft", 0);
|
||||
}
|
||||
error = 0;
|
||||
} else {
|
||||
EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
|
||||
EVENTHANDLER_INVOKE(watchdog_sbt_list, sbt, &error_sbt, &error);
|
||||
EVENTHANDLER_INVOKE(watchdog_list, pow2ns, &error);
|
||||
}
|
||||
/*
|
||||
* If we no hardware watchdog responded, we have not tried to
|
||||
* If no hardware watchdog responded, we have not tried to
|
||||
* attach an external software watchdog, and one is available,
|
||||
* attach it now and retry.
|
||||
*/
|
||||
if (error == EOPNOTSUPP && first && *wdog_software_attach != NULL) {
|
||||
if (error == EOPNOTSUPP && first && wdog_software_attach != NULL) {
|
||||
(*wdog_software_attach)();
|
||||
EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
|
||||
EVENTHANDLER_INVOKE(watchdog_sbt_list, sbt, &error_sbt, &error);
|
||||
EVENTHANDLER_INVOKE(watchdog_list, pow2ns, &error);
|
||||
}
|
||||
first = 0;
|
||||
first = false;
|
||||
|
||||
/* TODO: Print a (rate limited?) warning if error_sbt is too far away */
|
||||
wd_set_pretimeout(wd_pretimeout, true);
|
||||
/*
|
||||
* If we were able to arm/strobe the watchdog, then
|
||||
* update the last time it was strobed for WDIOC_GETTIMELEFT
|
||||
*/
|
||||
if (!error) {
|
||||
struct timespec ts;
|
||||
|
||||
|
|
@ -206,6 +191,7 @@ wdog_kern_pat(u_int utim)
|
|||
wd_lastpat_valid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
|
@ -282,16 +268,14 @@ wd_timeout_cb(void *arg)
|
|||
* current actual watchdog timeout.
|
||||
*/
|
||||
static int
|
||||
wd_set_pretimeout(int newtimeout, int disableiftoolong)
|
||||
wd_set_pretimeout(sbintime_t newtimeout, int disableiftoolong)
|
||||
{
|
||||
u_int utime;
|
||||
struct timespec utime_ts;
|
||||
int timeout_ticks;
|
||||
sbintime_t utime;
|
||||
sbintime_t timeout_left;
|
||||
|
||||
utime = wdog_kern_last_timeout();
|
||||
pow2ns_to_ts(utime, &utime_ts);
|
||||
utime = wdog_kern_last_timeout_sbt();
|
||||
/* do not permit a pre-timeout >= than the timeout. */
|
||||
if (newtimeout >= utime_ts.tv_sec) {
|
||||
if (newtimeout >= utime) {
|
||||
/*
|
||||
* If 'disableiftoolong' then just fall through
|
||||
* so as to disable the pre-watchdog
|
||||
|
|
@ -309,7 +293,7 @@ wd_set_pretimeout(int newtimeout, int disableiftoolong)
|
|||
return 0;
|
||||
}
|
||||
|
||||
timeout_ticks = pow2ns_to_ticks(utime) - (hz*newtimeout);
|
||||
timeout_left = utime - newtimeout;
|
||||
#if 0
|
||||
printf("wd_set_pretimeout: "
|
||||
"newtimeout: %d, "
|
||||
|
|
@ -323,8 +307,8 @@ wd_set_pretimeout(int newtimeout, int disableiftoolong)
|
|||
#endif
|
||||
|
||||
/* We determined the value is sane, so reset the callout */
|
||||
(void) callout_reset(&wd_pretimeo_handle,
|
||||
timeout_ticks, wd_timeout_cb, "pre");
|
||||
(void) callout_reset_sbt(&wd_pretimeo_handle,
|
||||
timeout_left, 0, wd_timeout_cb, "pre", 0);
|
||||
wd_pretimeout = newtimeout;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -333,6 +317,7 @@ static int
|
|||
wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
|
||||
int flags __unused, struct thread *td)
|
||||
{
|
||||
sbintime_t sb;
|
||||
u_int u;
|
||||
time_t timeleft;
|
||||
int error;
|
||||
|
|
@ -368,32 +353,55 @@ wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
|
|||
error = EINVAL;
|
||||
}
|
||||
break;
|
||||
case WDIOC_GETPRETIMEOUT:
|
||||
*(int *)data = (int)wd_pretimeout;
|
||||
#ifdef COMPAT_FREEBSD14
|
||||
case WDIOC_GETPRETIMEOUT_14:
|
||||
*(int *)data = (int)(wd_pretimeout / SBT_1S);
|
||||
break;
|
||||
case WDIOC_SETPRETIMEOUT:
|
||||
error = wd_set_pretimeout(*(int *)data, false);
|
||||
case WDIOC_SETPRETIMEOUT_14:
|
||||
error = wd_set_pretimeout(*(int *)data * SBT_1S, false);
|
||||
break;
|
||||
case WDIOC_GETTIMELEFT:
|
||||
case WDIOC_GETTIMELEFT_14:
|
||||
error = wd_get_time_left(td, &timeleft);
|
||||
if (error)
|
||||
break;
|
||||
*(int *)data = (int)timeleft;
|
||||
break;
|
||||
case WDIOC_SETTIMEOUT:
|
||||
case WDIOC_SETTIMEOUT_14:
|
||||
u = *(u_int *)data;
|
||||
error = wdog_kern_pat(seconds_to_pow2ns(u));
|
||||
error = wdog_kern_pat_sbt(mstosbt(u * 1000ULL));
|
||||
break;
|
||||
case WDIOC_GETTIMEOUT:
|
||||
case WDIOC_GETTIMEOUT_14:
|
||||
u = wdog_kern_last_timeout();
|
||||
*(u_int *)data = u;
|
||||
break;
|
||||
case WDIOCPATPAT:
|
||||
case WDIOCPATPAT_14:
|
||||
error = wd_ioctl_patpat(data);
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* New API */
|
||||
case WDIOC_CONTROL:
|
||||
wdog_control(*(int *)data);
|
||||
break;
|
||||
case WDIOC_SETTIMEOUT:
|
||||
sb = *(sbintime_t *)data;
|
||||
error = wdog_kern_pat_sbt(sb);
|
||||
break;
|
||||
case WDIOC_GETTIMEOUT:
|
||||
*(sbintime_t *)data = wdog_kern_last_timeout_sbt();
|
||||
break;
|
||||
case WDIOC_GETTIMELEFT:
|
||||
error = wd_get_time_left(td, &timeleft);
|
||||
if (error)
|
||||
break;
|
||||
*(sbintime_t *)data = (sbintime_t)timeleft * SBT_1S;
|
||||
break;
|
||||
case WDIOC_GETPRETIMEOUT:
|
||||
*(sbintime_t *)data = wd_pretimeout;
|
||||
break;
|
||||
case WDIOC_SETPRETIMEOUT:
|
||||
error = wd_set_pretimeout(*(sbintime_t *)data, false);
|
||||
break;
|
||||
default:
|
||||
error = ENOIOCTL;
|
||||
break;
|
||||
|
|
@ -412,6 +420,12 @@ wdog_kern_last_timeout(void)
|
|||
return (wd_last_u);
|
||||
}
|
||||
|
||||
sbintime_t
|
||||
wdog_kern_last_timeout_sbt(void)
|
||||
{
|
||||
return (wd_last_sbt);
|
||||
}
|
||||
|
||||
static struct cdevsw wd_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_ioctl = wd_ioctl,
|
||||
|
|
|
|||
|
|
@ -32,15 +32,16 @@
|
|||
#define _SYS_WATCHDOG_H
|
||||
|
||||
#include <sys/ioccom.h>
|
||||
#include <sys/_types.h>
|
||||
|
||||
#define _PATH_WATCHDOG "fido"
|
||||
|
||||
#define WDIOCPATPAT _IOW('W', 42, u_int) /* pat the watchdog */
|
||||
#define WDIOC_SETTIMEOUT _IOW('W', 43, int) /* set/reset the timer */
|
||||
#define WDIOC_GETTIMEOUT _IOR('W', 44, int) /* get total timeout */
|
||||
#define WDIOC_GETTIMELEFT _IOR('W', 45, int) /* get time left */
|
||||
#define WDIOC_GETPRETIMEOUT _IOR('W', 46, int) /* get the pre-timeout */
|
||||
#define WDIOC_SETPRETIMEOUT _IOW('W', 47, int) /* set the pre-timeout */
|
||||
#define WDIOC_PATPAT _IOW('W', 52, sbintime_t) /* pat the watchdog */
|
||||
#define WDIOC_SETTIMEOUT _IOW('W', 53, sbintime_t) /* set/reset the timer */
|
||||
#define WDIOC_GETTIMEOUT _IOR('W', 54, sbintime_t) /* get total timeout */
|
||||
#define WDIOC_GETTIMELEFT _IOR('W', 55, sbintime_t) /* get time left */
|
||||
#define WDIOC_GETPRETIMEOUT _IOR('W', 56, sbintime_t) /* get the pre-timeout */
|
||||
#define WDIOC_SETPRETIMEOUT _IOW('W', 57, sbintime_t) /* set the pre-timeout */
|
||||
/* set the action when a pre-timeout occurs see: WD_SOFT_* */
|
||||
#define WDIOC_SETPRETIMEOUTACT _IOW('W', 48, int)
|
||||
|
||||
|
|
@ -112,11 +113,15 @@
|
|||
#include <sys/_eventhandler.h>
|
||||
|
||||
typedef void (*watchdog_fn)(void *, u_int, int *);
|
||||
typedef void (*watchdog_sbt_fn)(void *, sbintime_t, sbintime_t *, int *);
|
||||
|
||||
EVENTHANDLER_DECLARE(watchdog_list, watchdog_fn);
|
||||
EVENTHANDLER_DECLARE(watchdog_sbt_list, watchdog_sbt_fn);
|
||||
|
||||
u_int wdog_kern_last_timeout(void);
|
||||
int wdog_kern_pat(u_int utim);
|
||||
sbintime_t wdog_kern_last_timeout_sbt(void);
|
||||
int wdog_kern_pat_sbt(sbintime_t utim);
|
||||
int wdog_control(int ctrl);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -63,25 +63,25 @@
|
|||
static long fetchtimeout(int opt,
|
||||
const char *longopt, const char *myoptarg, int zero_ok);
|
||||
static void parseargs(int, char *[]);
|
||||
static int seconds_to_pow2ns(int);
|
||||
static void sighandler(int);
|
||||
static void watchdog_loop(void);
|
||||
static int watchdog_init(void);
|
||||
static int watchdog_onoff(int onoff);
|
||||
static int watchdog_patpat(u_int timeout);
|
||||
static int watchdog_patpat(sbintime_t);
|
||||
static void usage(void);
|
||||
static int tstotv(struct timeval *tv, struct timespec *ts);
|
||||
static int tvtohz(struct timeval *tv);
|
||||
|
||||
static int debugging = 0;
|
||||
static int end_program = 0;
|
||||
static const char *pidfile = _PATH_VARRUN "watchdogd.pid";
|
||||
static u_int timeout = WD_TO_128SEC;
|
||||
static sbintime_t timeout = 128 * SBT_1S;
|
||||
static u_int exit_timeout = WD_TO_NEVER;
|
||||
static u_int pretimeout = 0;
|
||||
static u_int timeout_sec;
|
||||
static u_int nap = 10;
|
||||
#ifdef notyet
|
||||
static int passive = 0;
|
||||
#endif
|
||||
static int is_daemon = 0;
|
||||
static int is_dry_run = 0; /* do not arm the watchdog, only
|
||||
report on timing of the watch
|
||||
|
|
@ -174,38 +174,23 @@ main(int argc, char *argv[])
|
|||
pidfile_remove(pfh);
|
||||
return (EX_OK);
|
||||
} else {
|
||||
if (passive)
|
||||
timeout |= WD_PASSIVE;
|
||||
else
|
||||
timeout |= WD_ACTIVE;
|
||||
if (watchdog_patpat(timeout) < 0)
|
||||
err(EX_OSERR, "patting the dog");
|
||||
return (EX_OK);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pow2ns_to_ts(int pow2ns, struct timespec *ts)
|
||||
{
|
||||
uint64_t ns;
|
||||
|
||||
ns = 1ULL << pow2ns;
|
||||
ts->tv_sec = ns / 1000000000ULL;
|
||||
ts->tv_nsec = ns % 1000000000ULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a timeout in seconds to N where 2^N nanoseconds is close to
|
||||
* "seconds".
|
||||
*
|
||||
* The kernel expects the timeouts for watchdogs in "2^N nanosecond format".
|
||||
*/
|
||||
static u_int
|
||||
parse_timeout_to_pow2ns(char opt, const char *longopt, const char *myoptarg)
|
||||
static sbintime_t
|
||||
parse_timeout_to_sbt(char opt, const char *longopt, const char *myoptarg)
|
||||
{
|
||||
double a;
|
||||
u_int rv;
|
||||
struct timespec ts;
|
||||
long a;
|
||||
sbintime_t rv;
|
||||
struct timeval tv;
|
||||
int ticks;
|
||||
char shortopt[] = "- ";
|
||||
|
|
@ -216,19 +201,17 @@ parse_timeout_to_pow2ns(char opt, const char *longopt, const char *myoptarg)
|
|||
a = fetchtimeout(opt, longopt, myoptarg, 1);
|
||||
|
||||
if (a == 0)
|
||||
rv = WD_TO_NEVER;
|
||||
rv = 0;
|
||||
else
|
||||
rv = seconds_to_pow2ns(a);
|
||||
pow2ns_to_ts(rv, &ts);
|
||||
tstotv(&tv, &ts);
|
||||
rv = a * SBT_1S;
|
||||
tv = sbttotv(rv);
|
||||
ticks = tvtohz(&tv);
|
||||
if (debugging) {
|
||||
printf("Timeout for %s%s "
|
||||
"is 2^%d nanoseconds "
|
||||
"(in: %s sec -> out: %jd sec %ld ns -> %d ticks)\n",
|
||||
"is "
|
||||
"(in: %s sec -> out: %jd sec %ld us -> %d ticks)\n",
|
||||
longopt ? "-" : "", longopt ? longopt : shortopt,
|
||||
rv,
|
||||
myoptarg, (intmax_t)ts.tv_sec, ts.tv_nsec, ticks);
|
||||
myoptarg, (intmax_t)tv.tv_sec, tv.tv_usec, ticks);
|
||||
}
|
||||
if (ticks <= 0) {
|
||||
errx(1, "Timeout for %s%s is too small, please choose a higher timeout.", longopt ? "-" : "", longopt ? longopt : shortopt);
|
||||
|
|
@ -364,7 +347,7 @@ watchdog_loop(void)
|
|||
}
|
||||
|
||||
if (failed == 0)
|
||||
watchdog_patpat(timeout|WD_ACTIVE);
|
||||
watchdog_patpat(timeout);
|
||||
|
||||
waited = watchdog_check_dogfunction_time(&ts_start, &ts_end);
|
||||
if (nap - waited > 0)
|
||||
|
|
@ -387,13 +370,13 @@ try_end:
|
|||
* to keep the watchdog from firing.
|
||||
*/
|
||||
static int
|
||||
watchdog_patpat(u_int t)
|
||||
watchdog_patpat(sbintime_t sbt)
|
||||
{
|
||||
|
||||
if (is_dry_run)
|
||||
return 0;
|
||||
|
||||
return ioctl(fd, WDIOCPATPAT, &t);
|
||||
return ioctl(fd, WDIOC_SETTIMEOUT, &sbt);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -429,7 +412,7 @@ watchdog_onoff(int onoff)
|
|||
warn("setting WDIOC_SETSOFT %d", softtimeout_set);
|
||||
return (error);
|
||||
}
|
||||
error = watchdog_patpat((timeout|WD_ACTIVE));
|
||||
error = watchdog_patpat(timeout);
|
||||
if (error) {
|
||||
warn("watchdog_patpat failed");
|
||||
goto failsafe;
|
||||
|
|
@ -461,7 +444,7 @@ watchdog_onoff(int onoff)
|
|||
}
|
||||
}
|
||||
/* pat one more time for good measure */
|
||||
return watchdog_patpat((timeout|WD_ACTIVE));
|
||||
return watchdog_patpat(timeout);
|
||||
} else {
|
||||
return watchdog_control(WD_CTRL_DISABLE);
|
||||
}
|
||||
|
|
@ -576,15 +559,6 @@ timeout_act_str2int(const char *lopt, const char *acts)
|
|||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
tstotv(struct timeval *tv, struct timespec *ts)
|
||||
{
|
||||
|
||||
tv->tv_sec = ts->tv_sec;
|
||||
tv->tv_usec = ts->tv_nsec / 1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a timeval to a number of ticks.
|
||||
* Mostly copied from the kernel.
|
||||
|
|
@ -656,30 +630,6 @@ tvtohz(struct timeval *tv)
|
|||
return ((int)ticks);
|
||||
}
|
||||
|
||||
static int
|
||||
seconds_to_pow2ns(int seconds)
|
||||
{
|
||||
uint64_t power;
|
||||
uint64_t ns;
|
||||
uint64_t shifted;
|
||||
|
||||
if (seconds <= 0)
|
||||
errx(1, "seconds %d < 0", seconds);
|
||||
ns = ((uint64_t)seconds) * 1000000000ULL;
|
||||
power = flsll(ns);
|
||||
shifted = 1ULL << power;
|
||||
if (shifted <= ns) {
|
||||
power++;
|
||||
}
|
||||
if (debugging) {
|
||||
printf("shifted %lld\n", (long long)shifted);
|
||||
printf("seconds_to_pow2ns: seconds: %d, ns %lld, power %d\n",
|
||||
seconds, (long long)ns, (int)power);
|
||||
}
|
||||
return (power);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handle the few command line arguments supported.
|
||||
*/
|
||||
|
|
@ -692,8 +642,7 @@ parseargs(int argc, char *argv[])
|
|||
const char *lopt;
|
||||
|
||||
/* Get the default value of timeout_sec from the default timeout. */
|
||||
pow2ns_to_ts(timeout, &ts);
|
||||
timeout_sec = ts.tv_sec;
|
||||
timeout_sec = sbintime_getsec(timeout);
|
||||
|
||||
/*
|
||||
* if we end with a 'd' aka 'watchdogd' then we are the daemon program,
|
||||
|
|
@ -736,10 +685,10 @@ parseargs(int argc, char *argv[])
|
|||
break;
|
||||
case 't':
|
||||
timeout_sec = atoi(optarg);
|
||||
timeout = parse_timeout_to_pow2ns(c, NULL, optarg);
|
||||
timeout = parse_timeout_to_sbt(c, NULL, optarg);
|
||||
if (debugging)
|
||||
printf("Timeout is 2^%d nanoseconds\n",
|
||||
timeout);
|
||||
printf("Timeout is %d\n",
|
||||
(int)(timeout / SBT_1S));
|
||||
break;
|
||||
case 'T':
|
||||
carp_thresh_seconds =
|
||||
|
|
@ -749,7 +698,7 @@ parseargs(int argc, char *argv[])
|
|||
do_timedog = 1;
|
||||
break;
|
||||
case 'x':
|
||||
exit_timeout = parse_timeout_to_pow2ns(c, NULL, optarg);
|
||||
exit_timeout = parse_timeout_to_sbt(c, NULL, optarg);
|
||||
if (exit_timeout != 0)
|
||||
exit_timeout |= WD_ACTIVE;
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue