]>
git.proxmox.com Git - pve-ha-manager.git/blob - src/watchdog-mux.c
10 #include <sys/socket.h>
12 #include <sys/epoll.h>
14 #include <linux/types.h>
15 #include <linux/watchdog.h>
17 #include <systemd/sd-daemon.h>
19 #define MY_SOCK_PATH "/run/watchdog-mux.sock"
20 #define LISTEN_BACKLOG 50
23 #define WATCHDOG_DEV "/dev/watchdog"
26 int watchdog_timeout
= 20;
31 if (watchdog_fd
!= -1) {
32 if (write(watchdog_fd
, "V", 1) == -1) {
33 perror("write magic watchdog close");
35 if (close(watchdog_fd
) == -1) {
36 perror("write magic watchdog close");
46 struct sockaddr_un my_addr
, peer_addr
;
47 socklen_t peer_addr_size
;
48 struct epoll_event ev
, events
[MAX_EVENTS
];
49 int socket_count
, listen_sock
, nfds
, epollfd
;
52 if (stat(WATCHDOG_DEV
, &fs
) == -1) {
53 system("modprobe -q softdog soft_noboot=1"); // fixme
56 if ((watchdog_fd
= open(WATCHDOG_DEV
, O_WRONLY
)) == -1) {
57 perror("watchdog open");
61 if (ioctl(watchdog_fd
, WDIOC_SETTIMEOUT
, &watchdog_timeout
) == -1) {
62 perror("watchdog set timeout");
67 /* read and log watchdog identity */
68 struct watchdog_info wdinfo
;
69 if (ioctl(watchdog_fd
, WDIOC_GETSUPPORT
, &wdinfo
) == -1) {
70 perror("read watchdog info");
75 wdinfo
.identity
[sizeof(wdinfo
.identity
) - 1] = 0; // just to be sure
76 fprintf(stderr
, "Watchdog driver '%s', version %x\n",
77 wdinfo
.identity
, wdinfo
.firmware_version
);
79 socket_count
= sd_listen_fds(0);
81 if (socket_count
> 1) {
83 perror("too many file descriptors received.\n");
86 } else if (socket_count
== 1) {
88 listen_sock
= SD_LISTEN_FDS_START
+ 0;
94 listen_sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
95 if (listen_sock
== -1) {
96 perror("socket create");
100 memset(&my_addr
, 0, sizeof(struct sockaddr_un
));
101 my_addr
.sun_family
= AF_UNIX
;
102 strncpy(my_addr
.sun_path
, MY_SOCK_PATH
, sizeof(my_addr
.sun_path
) - 1);
104 if (bind(listen_sock
, (struct sockaddr
*) &my_addr
,
105 sizeof(struct sockaddr_un
)) == -1) {
106 perror("socket bind");
110 if (listen(listen_sock
, LISTEN_BACKLOG
) == -1) {
111 perror("socket listen");
116 epollfd
= epoll_create(10);
118 perror("epoll_create");
123 ev
.data
.fd
= listen_sock
;
124 if (epoll_ctl(epollfd
, EPOLL_CTL_ADD
, listen_sock
, &ev
) == -1) {
125 perror("epoll_ctl: listen_sock");
130 nfds
= epoll_wait(epollfd
, events
, MAX_EVENTS
, 1000);
135 perror("epoll_pwait");
139 if (nfds
== 0) { // timeout
141 if (ioctl(watchdog_fd
, WDIOC_KEEPALIVE
, 0) == -1) {
142 perror("watchdog update failed");
149 for (n
= 0; n
< nfds
; ++n
) {
150 if (events
[n
].data
.fd
== listen_sock
) {
151 int conn_sock
= accept(listen_sock
, (struct sockaddr
*) &peer_addr
, &peer_addr_size
);
152 if (conn_sock
== -1) {
156 if (fcntl(conn_sock
, F_SETFL
, O_NONBLOCK
) == -1) {
157 perror("setnonblocking");
162 ev
.data
.fd
= conn_sock
;
163 if (epoll_ctl(epollfd
, EPOLL_CTL_ADD
, conn_sock
, &ev
) == -1) {
164 perror("epoll_ctl: add conn_sock");
169 int cfd
= events
[n
].data
.fd
;
171 ssize_t bytes
= read(cfd
, buf
, sizeof(buf
));
175 } else if (bytes
> 0) {
176 printf("GOT %zd bytes\n", bytes
);
178 if (events
[n
].events
& EPOLLHUP
|| events
[n
].events
& EPOLLERR
) {
179 printf("GOT %016x event\n", events
[n
].events
);
180 if (epoll_ctl(epollfd
, EPOLL_CTL_DEL
, cfd
, NULL
) == -1) {
181 perror("epoll_ctl: del conn_sock");
184 if (close(cfd
) == -1) {
185 perror("close conn_sock");
199 unlink(MY_SOCK_PATH
);
203 unlink(MY_SOCK_PATH
);