init.d/wdmd | 23 ++++++++--
wdmd/main.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
wdmd/wdmd.8 | 10 ++++
3 files changed, 158 insertions(+), 5 deletions(-)
New commits:
commit 7507b61f3539a2c688c96faa4b7153fd4d62251d
Author: David Teigland <teigland(a)redhat.com>
Date: Thu Jan 2 13:04:13 2014 -0600
wdmd: add probe option
The probe option will look for a watchdog device that the
daemon can use. If a good device is found, the path is printed
and the command exits with 0. If a good device is not found,
the command exits with 1.
The init script uses this new probe function to determine
if it needs to load the softdog module or not.
Signed-off-by: David Teigland <teigland(a)redhat.com>
diff --git a/init.d/wdmd b/init.d/wdmd
index af45561..6ca9279 100644
--- a/init.d/wdmd
+++ b/init.d/wdmd
@@ -3,7 +3,7 @@
# wdmd - watchdog multiplexing daemon
#
# chkconfig: 2345 97 03
-# description: starts and stops sanlock daemon
+# description: starts and stops wdmd daemon
#
@@ -31,12 +31,27 @@ WDMDOPTS="-G $WDMDGROUP"
[ -f /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
+watchdog_probe() {
+ $exec --probe > /dev/null 2>&1
+ retval=$?
+ return $retval
+}
+
watchdog_check() {
- if [ ! -c /dev/watchdog ]; then
+ watchdog_probe
+ retval=$?
+
+ if [ $retval -ne 0 ]; then
echo -n $"Loading the softdog kernel module: "
modprobe softdog && udevadm settle
- [ -c /dev/watchdog ] && success || failure
- echo
+
+ watchdog_probe
+ retval=$?
+ if [ $retval -ne 0 ]; then
+ failure; echo
+ return 1
+ fi
+ success; echo
fi
}
diff --git a/wdmd/main.c b/wdmd/main.c
index 529b563..8a09632 100644
--- a/wdmd/main.c
+++ b/wdmd/main.c
@@ -1085,6 +1085,120 @@ static int setup_watchdog(void)
}
+static int probe_dev(const char *path)
+{
+ struct stat buf;
+ int fd, err, rv, timeout;
+
+ rv = stat(path, &buf);
+ if (rv < 0) {
+ fprintf(stderr, "error %d stat %s\n", errno, path);
+ return -1;
+ }
+
+ fd = open(path, O_WRONLY | O_CLOEXEC);
+ if (fd < 0) {
+ fprintf(stderr, "error %d open %s\n", errno, path);
+ return fd;
+ }
+
+ timeout = 0;
+
+ rv = ioctl(fd, WDIOC_GETTIMEOUT, &timeout);
+ if (rv < 0) {
+ fprintf(stderr, "error %d ioctl gettimeout %s\n", errno, path);
+ rv = -1;
+ goto out;
+ }
+
+ if (timeout == fire_timeout) {
+ printf("%s\n", path);
+ rv = 0;
+ goto out;
+ }
+
+ timeout = fire_timeout;
+
+ rv = ioctl(fd, WDIOC_SETTIMEOUT, &timeout);
+ if (rv < 0) {
+ fprintf(stderr, "error %d ioctl settimeout %s\n", errno, path);
+ rv = -1;
+ goto out;
+ }
+
+ if (timeout != fire_timeout) {
+ fprintf(stderr, "error %d invalid timeout %s\n", errno, path);
+ rv = -1;
+ goto out;
+ }
+
+ printf("%s\n", path);
+ rv = 0;
+
+ out:
+ err = write(fd, "V", 1);
+ if (err < 0) {
+ fprintf(stderr, "probe failed to disarm %s error %d %d\n", path, err,
errno);
+ openlog("wdmd", LOG_CONS | LOG_PID, LOG_DAEMON);
+ syslog(LOG_ERR, "probe failed to disarm %s error %d %d\n", path, err,
errno);
+ }
+
+ close(fd);
+ return rv;
+}
+
+static int probe_watchdog(void)
+{
+ int rv;
+
+ if (!saved_path[0])
+ goto opt;
+
+ rv = probe_dev(saved_path);
+ if (!rv)
+ return 0;
+
+ opt:
+ if (!option_path[0] || !strcmp(saved_path, option_path))
+ goto zero;
+
+ rv = probe_dev(option_path);
+ if (!rv)
+ return 0;
+
+ zero:
+ if (!strcmp(saved_path, "/dev/watchdog0") ||
+ !strcmp(option_path, "/dev/watchdog0"))
+ goto one;
+
+ rv = probe_dev((char *)"/dev/watchdog0");
+ if (!rv)
+ return 0;
+
+ one:
+ if (!strcmp(saved_path, "/dev/watchdog1") ||
+ !strcmp(option_path, "/dev/watchdog1"))
+ goto old;
+
+ rv = probe_dev((char *)"/dev/watchdog1");
+ if (!rv)
+ return 0;
+
+ old:
+ if (!strcmp(saved_path, "/dev/watchdog") ||
+ !strcmp(option_path, "/dev/watchdog"))
+ goto out;
+
+ rv = probe_dev((char *)"/dev/watchdog");
+ if (!rv)
+ return 0;
+
+ out:
+ fprintf(stderr, "no watchdog device, load a watchdog driver\n");
+ return -1;
+
+}
+
static void pet_watchdog(void)
{
int rv, unused;
@@ -1397,6 +1511,7 @@ static void print_usage_and_exit(int status)
printf("--version, -V print version\n");
printf("--help, -h print usage\n");
printf("--dump, -d print debug from daemon\n");
+ printf("--probe, -p print path of functional watchdog device\n");
printf("-D debug: no fork and print all logging to
stderr\n");
printf("-H 0|1 use high priority features (1 yes, 0 no, default
%d)\n",
DEFAULT_HIGH_PRIORITY);
@@ -1425,6 +1540,7 @@ static void print_version_and_exit(void)
int main(int argc, char *argv[])
{
+ int do_probe = 0;
int rv;
while (1) {
@@ -1433,12 +1549,13 @@ int main(int argc, char *argv[])
static struct option long_options[] = {
{"help", no_argument, 0, 'h' },
+ {"probe", no_argument, 0, 'p' },
{"dump", no_argument, 0, 'd' },
{"version", no_argument, 0, 'V' },
{0, 0, 0, 0 }
};
- c = getopt_long(argc, argv, "hdVDH:G:S:s:k:w:",
+ c = getopt_long(argc, argv, "hpdVDH:G:S:s:k:w:",
long_options, &option_index);
if (c == -1)
break;
@@ -1447,6 +1564,9 @@ int main(int argc, char *argv[])
case 'h':
print_usage_and_exit(0);
break;
+ case 'p':
+ do_probe = 1;
+ break;
case 'd':
print_debug_and_exit();
break;
@@ -1478,6 +1598,14 @@ int main(int argc, char *argv[])
}
}
+ if (do_probe) {
+ rv = probe_watchdog();
+ if (rv < 0)
+ exit(EXIT_FAILURE);
+ else
+ exit(EXIT_SUCCESS);
+ }
+
if (!daemon_debug) {
if (daemon(0, 0) < 0) {
fprintf(stderr, "cannot fork daemon\n");
diff --git a/wdmd/wdmd.8 b/wdmd/wdmd.8
index 7e11562..cc03be7 100644
--- a/wdmd/wdmd.8
+++ b/wdmd/wdmd.8
@@ -79,6 +79,12 @@ it is considered a failure.
Print debug information from the daemon.
.TP
+.B \-\-probe, \-p
+ Print path of functional watchdog device. Exit code 0 indicates a
+ functional device was found. Exit code 1 indicates a functional device
+ was not found.
+
+.TP
.B \-D
Enable debugging to stderr and don't fork.
@@ -103,4 +109,8 @@ it is considered a failure.
.BI \-k " num"
Kill unfinished scripts after num seconds.
+.TP
+.BI \-w " path"
+ The path to the watchdog device to try first.
+