From 1ea4f5b08eb4973891b58c77d4bc90181d5e22bd Mon Sep 17 00:00:00 2001 From: phk Date: Sat, 28 Feb 2004 20:56:35 +0000 Subject: Rename the WATCHDOG option to SW_WATCHDOG and make it use the generic watchdoc(9) interface. Make watchdogd(8) perform as watchdog(8) as well, and make it possible to specify a check command to run, timeout and sleep periods. Update watchdog(4) to talk about the generic interface and add new watchdog(8) page. --- usr.sbin/watchdogd/Makefile | 9 ++- usr.sbin/watchdogd/watchdog.8 | 66 ++++++++++++++++++ usr.sbin/watchdogd/watchdogd.8 | 37 ++++++++-- usr.sbin/watchdogd/watchdogd.c | 155 +++++++++++++++++++++++++++-------------- 4 files changed, 211 insertions(+), 56 deletions(-) create mode 100644 usr.sbin/watchdogd/watchdog.8 (limited to 'usr.sbin') diff --git a/usr.sbin/watchdogd/Makefile b/usr.sbin/watchdogd/Makefile index de6f976..68675c7 100644 --- a/usr.sbin/watchdogd/Makefile +++ b/usr.sbin/watchdogd/Makefile @@ -1,7 +1,14 @@ # $FreeBSD$ PROG= watchdogd -MAN= watchdogd.8 +LINKS= ${BINDIR}/watchdogd ${BINDIR}/watchdog +MAN= watchdogd.8 watchdog.8 WARNS?= 6 +LDADD= -lm +DPADD= ${LIBM} + .include + +test: ${PROG} + ./${PROG} -t 1.0 diff --git a/usr.sbin/watchdogd/watchdog.8 b/usr.sbin/watchdogd/watchdog.8 new file mode 100644 index 0000000..14f0b51 --- /dev/null +++ b/usr.sbin/watchdogd/watchdog.8 @@ -0,0 +1,66 @@ +.\" Copyright (c) 2004 Poul-Henning Kamp +.\" Copyright (c) 2003 Sean M. Kelly +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 28, 2004 +.Dt WATCHDOG 8 +.Os +.Sh NAME +.Nm watchdog +.Nd watchdog control program +.Sh SYNOPSIS +.Nm +.Op Fl d +.Op Fl t Ar timeout +.Sh DESCRIPTION +The +.Nm +utility can be used to control the kernels watchdog facility. +.Pp +The +.Fl t Ar timeout +specifies the desired timeout period in seconds, a value of +zero will disable the watchdog. +.Sh SEE ALSO +.Xr watchdogd 8 , +.Xr watchdog 4 , +.Xr watchdog 9 , +.Sh AUTHORS +.An -nosplit +The +.Nm +utility and manual page were written by +.An Sean Kelly Aq smkelly@FreeBSD.org +and +.An Poul-Henning Kamp Aq phk@FreeBSD.org +.Pp +Some contributions made by +.An Jeff Roberson Aq jeff@FreeBSD.org . +.Sh HISTORY +The +.Nm +utility appeared in +.Fx 5.1 . diff --git a/usr.sbin/watchdogd/watchdogd.8 b/usr.sbin/watchdogd/watchdogd.8 index b8f7ce8..e1c8516 100644 --- a/usr.sbin/watchdogd/watchdogd.8 +++ b/usr.sbin/watchdogd/watchdogd.8 @@ -1,3 +1,4 @@ +.\" Copyright (c) 2004 Poul-Henning Kamp .\" Copyright (c) 2003 Sean M. Kelly .\" All rights reserved. .\" @@ -29,21 +30,46 @@ .Os .Sh NAME .Nm watchdogd -.Nd Software watchdog daemon +.Nd Watchdog daemon .Sh SYNOPSIS .Nm .Op Fl d +.Op Fl e Ar cmd .Op Fl I Ar file +.Op Fl s Ar sleep +.Op Fl t Ar timeout .Sh DESCRIPTION The .Nm -utility interfaces with the kernel's software watchdog facility to ensure +utility interfaces with the kernel's watchdog facility to ensure that the system is in a working state. If .Nm is unable to interface with the kernel over a specific timeout, the kernel will take actions to assist in debugging or restarting the computer. .Pp +If +.Fl e Ar cmd +is specified, +.Nm +will attempt to execute this command with +.Xr system 3 +and only if the command returns with a zero exit code will the +watchdog be reset. +If +.Fl e Ar cmd +is not specified the daemon will perform a trivial filesystem +check instead. +.Pp +The +.Fl -s Ar sleep +argument can be used to control the sleep period between each execution +of the check and defaults to one second. +.Pp +The +.Fl -t Ar timeout +specifies the desired timeout period in seconds. +.Pp One possible circumstance which will cause a watchdog timeout is an interrupt storm. If this occurs, @@ -80,13 +106,16 @@ will not fork into the background at startup. .El .Sh SEE ALSO .Xr watchdog 4 , -.Xr sysctl 8 +.Xr watchdog 8 , +.Xr watchdog 9 , .Sh AUTHORS .An -nosplit The .Nm utility and manual page were written by -.An Sean Kelly Aq smkelly@FreeBSD.org . +.An Sean Kelly Aq smkelly@FreeBSD.org +and +.An Poul-Henning Kamp Aq phk@FreeBSD.org . .Pp Some contributions made by .An Jeff Roberson Aq jeff@FreeBSD.org . diff --git a/usr.sbin/watchdogd/watchdogd.c b/usr.sbin/watchdogd/watchdogd.c index c536734..a382a7c 100644 --- a/usr.sbin/watchdogd/watchdogd.c +++ b/usr.sbin/watchdogd/watchdogd.c @@ -35,12 +35,17 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include +#include +#include #include #include #include #include +#include #include #include @@ -49,7 +54,7 @@ static void sighandler(int); static void watchdog_loop(void); static int watchdog_init(void); static int watchdog_onoff(int onoff); -static int watchdog_tickle(void); +static int watchdog_patpat(void); static void usage(void); int debugging = 0; @@ -57,6 +62,12 @@ int end_program = 0; const char *pidfile = _PATH_VARRUN "watchdogd.pid"; int reset_mib[3]; size_t reset_miblen = 3; +u_int timeout = WD_TO_16SEC; +u_int passive = 0; +int is_daemon = 0; +int fd = -1; +int nap = 1; +char *test_cmd = NULL; /* * Periodically write to the debug.watchdog.reset sysctl OID @@ -81,30 +92,40 @@ main(int argc, char *argv[]) if (watchdog_init() == -1) errx(EX_SOFTWARE, "unable to initialize watchdog"); - if (watchdog_onoff(1) == -1) - exit(EX_SOFTWARE); + if (is_daemon) { + if (watchdog_onoff(1) == -1) + exit(EX_SOFTWARE); - if (debugging == 0 && daemon(0, 0) == -1) { - watchdog_onoff(0); - err(EX_OSERR, "daemon"); - } + if (debugging == 0 && daemon(0, 0) == -1) { + watchdog_onoff(0); + err(EX_OSERR, "daemon"); + } - signal(SIGHUP, SIG_IGN); - signal(SIGINT, sighandler); - signal(SIGTERM, sighandler); + signal(SIGHUP, SIG_IGN); + signal(SIGINT, sighandler); + signal(SIGTERM, sighandler); - fp = fopen(pidfile, "w"); - if (fp != NULL) { - fprintf(fp, "%d\n", getpid()); - fclose(fp); - } + fp = fopen(pidfile, "w"); + if (fp != NULL) { + fprintf(fp, "%d\n", getpid()); + fclose(fp); + } - watchdog_loop(); + watchdog_loop(); - /* exiting */ - watchdog_onoff(0); - unlink(pidfile); - return (EX_OK); + /* exiting */ + watchdog_onoff(0); + unlink(pidfile); + return (EX_OK); + } else { + if (passive) + timeout |= WD_PASSIVE; + else + timeout |= WD_ACTIVE; + if (watchdog_patpat() < 0) + err(EX_OSERR, "patting the dog"); + return (EX_OK); + } } /* @@ -125,15 +146,12 @@ sighandler(int signum) static int watchdog_init() { - int error; - error = sysctlnametomib("debug.watchdog.reset", reset_mib, - &reset_miblen); - if (error == -1) { - warn("could not find reset OID"); - return (error); - } - return watchdog_tickle(); + fd = open("/dev/" _PATH_WATCHDOG, O_RDWR); + if (fd >= 0) + return (0); + warn("Could not open watchdog device"); + return (-1); } /* @@ -148,11 +166,14 @@ watchdog_loop(void) while (end_program == 0) { failed = 0; - failed = stat("/etc", &sb); + if (test_cmd != NULL) + failed = system(test_cmd); + else + failed = stat("/etc", &sb); if (failed == 0) - watchdog_tickle(); - sleep(1); + watchdog_patpat(); + sleep(nap); } } @@ -161,10 +182,10 @@ watchdog_loop(void) * to keep the watchdog from firing. */ int -watchdog_tickle(void) +watchdog_patpat(void) { - return sysctl(reset_mib, reset_miblen, NULL, NULL, NULL, 0); + return ioctl(fd, WDIOCPATPAT, &timeout); } /* @@ -174,22 +195,12 @@ watchdog_tickle(void) static int watchdog_onoff(int onoff) { - int mib[3]; - int error; - size_t len; - len = 3; - - error = sysctlnametomib("debug.watchdog.enabled", mib, &len); - if (error == 0) - error = sysctl(mib, len, NULL, NULL, &onoff, sizeof(onoff)); - - if (error == -1) { - warn("could not %s watchdog", - (onoff > 0) ? "enable" : "disable"); - return (error); - } - return (0); + if (onoff) + timeout |= WD_ACTIVE; + else + timeout &= ~WD_ACTIVE; + return watchdog_patpat(); } /* @@ -198,7 +209,10 @@ watchdog_onoff(int onoff) static void usage() { - fprintf(stderr, "usage: watchdogd [-d] [-I file]\n"); + if (is_daemon) + fprintf(stderr, "usage: watchdogd [-d] [-e cmd] [-I file]\n"); + else + fprintf(stderr, "usage: watchdog [-d] [-t]\n"); exit(EX_USAGE); } @@ -209,8 +223,14 @@ static void parseargs(int argc, char *argv[]) { int c; - - while ((c = getopt(argc, argv, "I:d?")) != -1) { + char *p; + double a; + + c = strlen(argv[0]); + if (argv[0][c - 1] == 'd') + is_daemon = 1; + while ((c = getopt(argc, argv, + is_daemon ? "I:de:s:t:?" : "dt:?")) != -1) { switch (c) { case 'I': pidfile = optarg; @@ -218,10 +238,43 @@ parseargs(int argc, char *argv[]) case 'd': debugging = 1; break; + case 'e': + test_cmd = strdup(optarg); + break; +#ifdef notyet + case 'p': + passive = 1; + break; +#endif + case 's': + p = NULL; + errno = 0; + nap = strtol(optarg, &p, 0); + if ((p != NULL && *p != '\0') || errno != 0) + errx(EX_USAGE, "-s argument is not a number"); + break; + case 't': + p = NULL; + errno = 0; + a = strtod(optarg, &p); + if ((p != NULL && *p != '\0') || errno != 0) + errx(EX_USAGE, "-t argument is not a number"); + if (a < 0) + errx(EX_USAGE, "-t argument must be positive"); + if (a == 0) + timeout = WD_TO_NEVER; + else + timeout = 1.0 + log(a * 1e9) / log(2.0); + if (debugging) + printf("Timeout is 2^%d nanoseconds\n", + timeout); + break; case '?': default: usage(); /* NOTREACHED */ } } + if (is_daemon && timeout < WD_TO_1SEC) + errx(EX_USAGE, "-t argument is less than one second."); } -- cgit v1.1