From b154ab95212f2a882f9893000a184199baa8fb68 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 8 Jan 2013 14:23:14 -0600 Subject: [PATCH 6/6] wdmd: dynamically select working watchdog device Some watchdog drivers enable both /dev/watchdog0 and /dev/watchdog1. Sometimes, only one of them works, and the working one is not consistent. So, we need to test which works before deciding which to use. Signed-off-by: David Teigland --- wdmd/main.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/wdmd/main.c b/wdmd/main.c index 8a97f04..827d1bb 100644 --- a/wdmd/main.c +++ b/wdmd/main.c @@ -49,6 +49,8 @@ #define DEFAULT_SOCKET_GID 0 #define DEFAULT_SOCKET_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) +#define WDPATH_SIZE 64 + static int test_interval = DEFAULT_TEST_INTERVAL; static int fire_timeout = DEFAULT_FIRE_TIMEOUT; static int high_priority = DEFAULT_HIGH_PRIORITY; @@ -64,7 +66,9 @@ static int shm_fd; static int allow_scripts; static int kill_script_sec; static const char *scripts_dir = "/etc/wdmd.d"; -static const char *watchdog_path = "/dev/watchdog"; +static char watchdog_path[WDPATH_SIZE]; +static char option_path[WDPATH_SIZE]; +static char saved_path[WDPATH_SIZE]; struct script_status { uint64_t start; @@ -928,7 +932,7 @@ static int open_dev(void) fd = open(watchdog_path, O_WRONLY | O_CLOEXEC); if (fd < 0) { - log_error("no %s, load a watchdog driver", watchdog_path); + log_error("open %s error %d", watchdog_path, errno); return fd; } @@ -969,10 +973,18 @@ static void close_watchdog(void) dev_fd = -1; } -static int setup_watchdog(void) +static int _setup_watchdog(char *path) { + struct stat buf; int rv, timeout; + strncpy(watchdog_path, path, WDPATH_SIZE); + watchdog_path[WDPATH_SIZE - 1] = '\0'; + + rv = stat(watchdog_path, &buf); + if (rv < 0) + return -1; + rv = open_dev(); if (rv < 0) return -1; @@ -1006,9 +1018,73 @@ static int setup_watchdog(void) out: log_error("%s armed with fire_timeout %d", watchdog_path, fire_timeout); + /* TODO: save watchdog_path in /var/run/wdmd/saved_path, + * and in startup read that file, copying it to saved_path */ + return 0; } +/* + * Order of preference: + * . saved path (path used before daemon restart) + * . command line option (-w) + * . /dev/watchdog0 + * . /dev/watchdog1 + * . /dev/watchdog + */ + +static int setup_watchdog(void) +{ + int rv; + + if (!saved_path[0]) + goto opt; + + rv = _setup_watchdog(saved_path); + if (!rv) + return 0; + + opt: + if (!option_path[0] || !strcmp(saved_path, option_path)) + goto zero; + + rv = _setup_watchdog(option_path); + if (!rv) + return 0; + + zero: + if (!strcmp(saved_path, "/dev/watchdog0") || + !strcmp(option_path, "/dev/watchdog0")) + goto one; + + rv = _setup_watchdog((char *)"/dev/watchdog0"); + if (!rv) + return 0; + + one: + if (!strcmp(saved_path, "/dev/watchdog1") || + !strcmp(option_path, "/dev/watchdog1")) + goto old; + + rv = _setup_watchdog((char *)"/dev/watchdog1"); + if (!rv) + return 0; + + old: + if (!strcmp(saved_path, "/dev/watchdog") || + !strcmp(option_path, "/dev/watchdog")) + goto out; + + rv = _setup_watchdog((char *)"/dev/watchdog"); + if (!rv) + return 0; + + out: + log_error("no watchdog device, load a watchdog driver"); + return -1; + +} + static void pet_watchdog(void) { int rv, unused; @@ -1327,7 +1403,7 @@ static void print_usage_and_exit(int status) printf("-s path to scripts dir (default %s)\n", scripts_dir); printf("-k kill unfinished scripts after num seconds (default %d)\n", kill_script_sec); - printf("-w /dev/watchdog path to the watchdog device (default %s)\n", watchdog_path); + printf("-w /dev/watchdog path to the watchdog device to try first\n"); exit(status); } @@ -1394,7 +1470,8 @@ int main(int argc, char *argv[]) kill_script_sec = atoi(optarg); break; case 'w': - watchdog_path = strdup(optarg); + snprintf(option_path, WDPATH_SIZE, "%s", optarg); + option_path[WDPATH_SIZE - 1] = '\0'; break; } } -- 1.7.11.7