3 #endif /* HAVE_CONFIG_H */
11 /* sendfd: BSD style file descriptor passing over unix domain sockets
12 * Richard Stevens: Unix Network Programming, Prentice Hall, 1990;
14 #include <sys/types.h>
15 #include <sys/socket.h>
22 #error "SCM_RIGHTS undefined"
25 /* interface to pmxcfs (libqb) */
26 #include <sys/syslog.h>
27 #include <qb/qbdefs.h>
28 #include <qb/qbutil.h>
30 #include <qb/qbipcc.h>
32 #define RESTART_FLAG_FILE "/run/pve-cluster/cfs-restart-flag"
33 #define RESTART_GRACE_PERIOD 5
35 #define PCS_SOCKET_NAME "pve2"
37 #define PCS_SERVICE1 1
38 #define MAX_MSG_SIZE (8192*128)
40 static qb_ipcc_connection_t *conn;
41 static pid_t conn_pid;
43 static char ipcbuffer[MAX_MSG_SIZE];
45 static qb_ipcc_connection_t *init_connection() {
47 static qb_ipcc_connection_t *connection = NULL;
48 struct timespec retry_timeout, now;
49 int cfs_restart_flag_fd = -1;
51 // check if pmxcfs is currently restarting
52 if ((cfs_restart_flag_fd = open(RESTART_FLAG_FILE, 0)) > 0) {
53 clock_gettime(CLOCK_MONOTONIC, &retry_timeout);
54 retry_timeout.tv_sec += RESTART_GRACE_PERIOD;
57 qb_log_init("IPCC.xs", LOG_USER, LOG_EMERG);
58 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
61 connection = qb_ipcc_connect(PCS_SOCKET_NAME, MAX_MSG_SIZE);
64 if (cfs_restart_flag_fd >= 0) {
65 // cfs restarting and hopefully back soon, poll
66 clock_gettime(CLOCK_MONOTONIC, &now);
68 if (now.tv_sec < retry_timeout.tv_sec ||
69 (now.tv_sec == retry_timeout.tv_sec &&
70 now.tv_nsec < retry_timeout.tv_nsec)) {
73 goto retry_connection;
76 // timeout: cleanup flag file if still the same
78 fstat(cfs_restart_flag_fd, &s);
80 unlink(RESTART_FLAG_FILE);
85 if (cfs_restart_flag_fd >= 0) close(cfs_restart_flag_fd);
91 MODULE = PVE::IPCC PACKAGE = PVE::IPCC
94 ipcc_send_rec(msgid, data=NULL)
100 uint8_t retried_cache_connection = 0;
101 pid_t cpid = getpid();
103 /* Each process needs its own ipcc connection,
104 * else the shared memory buffer gets corrupted.
106 if (conn && conn_pid != cpid) {
112 conn = init_connection();
121 char *dataptr = NULL;
122 if (data && SvPOK(data))
123 dataptr = SvPV(data, len);
126 struct iovec iov[iov_len];
128 struct qb_ipc_request_header req_header;
130 req_header.id = msgid;
131 req_header.size = sizeof(req_header) + len;
133 iov[0].iov_base = (char *)&req_header;
134 iov[0].iov_len = sizeof(req_header);
135 iov[1].iov_base = dataptr;
136 iov[1].iov_len = len;
138 int32_t ms_timeout = -1; // fixme:
139 int res = qb_ipcc_sendv_recv(conn, iov, iov_len, ipcbuffer, sizeof(ipcbuffer), ms_timeout);
141 qb_ipcc_disconnect(conn);
143 // requests during cfs restart and the first thereafter will fail, retry
144 if (!retried_cache_connection) {
145 retried_cache_connection = 1;
146 goto recache_connection;
152 struct qb_ipc_response_header *res_header;
154 res_header = (struct qb_ipc_response_header *)ipcbuffer;
155 int dsize = res_header->size - sizeof(struct qb_ipc_response_header);
157 if (res_header->error < 0) {
158 errno = -res_header->error;
163 RETVAL = newSVpv(ipcbuffer + sizeof(struct qb_ipc_response_header), dsize);
171 # helper to pass SCM ACCESS RIGHTS
174 sendfd(sock_fd, send_me_fd, data=NULL)
183 memset(&msg, 0, sizeof(msg));
186 char *dataptr = NULL;
187 if (data && SvPOK(data))
188 dataptr = SvPV(data, len);
190 iov[0].iov_base = dataptr;
191 iov[0].iov_len = len;
197 char control[CMSG_SPACE(sizeof(int))];
198 memset(control, 0, sizeof(control));
200 msg.msg_control = control;
201 msg.msg_controllen = sizeof(control);
204 struct cmsghdr* h = CMSG_FIRSTHDR(&msg);
205 h->cmsg_len = CMSG_LEN(sizeof(int));
206 h->cmsg_level= SOL_SOCKET;
207 h->cmsg_type = SCM_RIGHTS;
208 *((int*)CMSG_DATA(h)) = send_me_fd;
213 ret = sendmsg(sock_fd, &msg, 0);
215 if (errno == EINTR) {
217 } else if (errno == EAGAIN || errno == EWOULDBLOCK) {