]> git.proxmox.com Git - pve-ha-manager.git/blobdiff - src/watchdog-mux.c
allow to configure watchdog module in /etc/default/pve-ha-manager
[pve-ha-manager.git] / src / watchdog-mux.c
index fb30aa102df709fff82abf734866c5f702d35a1a..2b440131d4fb18aada436cc080a6a7e784792977 100644 (file)
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 #include <systemd/sd-daemon.h>
 
-#define MY_SOCK_PATH "/run/watchdog-mux.sock"
+#define WD_SOCK_PATH "/run/watchdog-mux.sock"
 #define WD_ACTIVE_MARKER "/run/watchdog-mux.active"
 
-#define LISTEN_BACKLOG 50
+#define LISTEN_BACKLOG 32 /* set same value in watchdog-mux.socket */
+
 #define MAX_EVENTS 10
 
 #define WATCHDOG_DEV "/dev/watchdog"
 
 int watchdog_fd = -1;
-int watchdog_timeout = 20;
-
+int watchdog_timeout = 10;
+int client_watchdog_timeout = 60;
+int update_watchdog = 1; 
 
 typedef struct {
     int fd;
@@ -105,7 +108,7 @@ main(void)
     socklen_t peer_addr_size;
     struct epoll_event ev, events[MAX_EVENTS];
     int socket_count, listen_sock, nfds, epollfd, sigfd;
-
+    int unlink_socket = 0;
     
     struct stat fs;
 
@@ -113,9 +116,22 @@ main(void)
         fprintf(stderr, "watchdog active - unable to restart watchdog-mux\n");
         exit(EXIT_FAILURE);       
     }
-    
+
+    /* if you want to debug, set options in /lib/modprobe.d/aliases.conf
+     * options softdog soft_noboot=1
+     */
     if (stat(WATCHDOG_DEV, &fs) == -1) {
-        system("modprobe -q softdog soft_noboot=1"); // fixme
+        char *wd_module = getenv("WATCHDOG_MODULE");
+        if (wd_module) {
+            char *cmd = NULL;
+            if ((asprintf(&cmd, "modprobe -q %s", wd_module) == -1)) {
+                perror("assemble modprobe command failed");
+                exit(EXIT_FAILURE);
+            }
+            system(cmd);
+        } else {
+            system("modprobe -q softdog"); // load softdog by default
+        }
     }
 
     if ((watchdog_fd = open(WATCHDOG_DEV, O_WRONLY)) == -1) {
@@ -142,7 +158,7 @@ main(void)
             wdinfo.identity, wdinfo.firmware_version);
 
     socket_count = sd_listen_fds(0);
-
+    
     if (socket_count > 1) {
 
         perror("too many file descriptors received.\n");
@@ -151,10 +167,12 @@ main(void)
     } else if (socket_count == 1) {
 
         listen_sock = SD_LISTEN_FDS_START + 0;
-           
+       
     } else {
 
-        unlink(MY_SOCK_PATH);
+       unlink_socket = 1;
+       
+        unlink(WD_SOCK_PATH);
 
         listen_sock = socket(AF_UNIX, SOCK_STREAM, 0);
         if (listen_sock == -1) {
@@ -164,7 +182,7 @@ main(void)
 
         memset(&my_addr, 0, sizeof(struct sockaddr_un));
         my_addr.sun_family = AF_UNIX;
-        strncpy(my_addr.sun_path, MY_SOCK_PATH, sizeof(my_addr.sun_path) - 1);
+        strncpy(my_addr.sun_path, WD_SOCK_PATH, sizeof(my_addr.sun_path) - 1);
            
         if (bind(listen_sock, (struct sockaddr *) &my_addr,
                  sizeof(struct sockaddr_un)) == -1) {
@@ -223,13 +241,31 @@ main(void)
 
         if (nfds == 0) { // timeout
 
-            if (ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0) == -1) {
-                perror("watchdog update failed");
+            // check for timeouts
+            if (update_watchdog) {
+                int i;
+                time_t ctime = time(NULL);
+                for (i = 0; i < MAX_CLIENTS; i++) {
+                    if (client_list[i].fd != 0 && client_list[i].time != 0 &&
+                        ((ctime - client_list[i].time) > client_watchdog_timeout)) {
+                        update_watchdog = 0;
+                        fprintf(stderr, "client watchdog expired - disable watchdog updates\n"); 
+                    }
+                }
+            }
+
+            if (update_watchdog) {
+                if (ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0) == -1) {
+                    perror("watchdog update failed");
+                }
             }
             
             continue;
         }
 
+        if (!update_watchdog)
+            break;
+            
         int terminate = 0;
         
         int n;
@@ -307,7 +343,8 @@ main(void)
                         }
 
                         if (!wd_client->magic_close) {
-                            fprintf(stderr, "client did not stop watchdog\n");
+                            fprintf(stderr, "client did not stop watchdog - disable watchdog updates\n");
+                            update_watchdog = 0;
                         } else {
                             free_client(wd_client);
                         }
@@ -331,10 +368,14 @@ main(void)
         watchdog_close();
     }
     
-    unlink(MY_SOCK_PATH);
+    if (unlink_socket)
+           unlink(WD_SOCK_PATH);
+    
     exit(EXIT_SUCCESS);
 
 err:
-    unlink(MY_SOCK_PATH);
+    if (unlink_socket)
+           unlink(WD_SOCK_PATH);
+
     exit(EXIT_FAILURE);
 }