Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / daemons / clvmd / refresh_clvmd.c
blob57ef8b329ccdf8f3df96b4b8e531c3aad3761f25
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU General Public License v.2.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * Tell all clvmds in a cluster to refresh their toolcontext
22 #define _GNU_SOURCE
23 #define _FILE_OFFSET_BITS 64
25 #include <configure.h>
26 #include <stddef.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <libdevmapper.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <limits.h>
36 #include "clvm.h"
37 #include "refresh_clvmd.h"
39 typedef struct lvm_response {
40 char node[255];
41 char *response;
42 int status;
43 int len;
44 } lvm_response_t;
47 * This gets stuck at the start of memory we allocate so we
48 * can sanity-check it at deallocation time
50 #define LVM_SIGNATURE 0x434C564D
52 static int _clvmd_sock = -1;
54 /* Open connection to the clvm daemon */
55 static int _open_local_sock(void)
57 int local_socket;
58 struct sockaddr_un sockaddr;
60 /* Open local socket */
61 if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
62 fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
63 return -1;
66 memset(&sockaddr, 0, sizeof(sockaddr));
67 memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
69 sockaddr.sun_family = AF_UNIX;
71 if (connect(local_socket,(struct sockaddr *) &sockaddr,
72 sizeof(sockaddr))) {
73 int saved_errno = errno;
75 fprintf(stderr, "connect() failed on local socket: %s\n",
76 strerror(errno));
77 if (close(local_socket))
78 return -1;
80 errno = saved_errno;
81 return -1;
84 return local_socket;
87 /* Send a request and return the status */
88 static int _send_request(const char *inbuf, int inlen, char **retbuf)
90 char outbuf[PIPE_BUF];
91 struct clvm_header *outheader = (struct clvm_header *) outbuf;
92 int len;
93 int off;
94 int buflen;
95 int err;
97 /* Send it to CLVMD */
98 rewrite:
99 if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
100 if (err == -1 && errno == EINTR)
101 goto rewrite;
102 fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
103 return 0;
106 /* Get the response */
107 reread:
108 if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
109 if (errno == EINTR)
110 goto reread;
111 fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
112 return 0;
115 if (len == 0) {
116 fprintf(stderr, "EOF reading CLVMD");
117 errno = ENOTCONN;
118 return 0;
121 /* Allocate buffer */
122 buflen = len + outheader->arglen;
123 *retbuf = dm_malloc(buflen);
124 if (!*retbuf) {
125 errno = ENOMEM;
126 return 0;
129 /* Copy the header */
130 memcpy(*retbuf, outbuf, len);
131 outheader = (struct clvm_header *) *retbuf;
133 /* Read the returned values */
134 off = 1; /* we've already read the first byte */
135 while (off <= outheader->arglen && len > 0) {
136 len = read(_clvmd_sock, outheader->args + off,
137 buflen - off - offsetof(struct clvm_header, args));
138 if (len > 0)
139 off += len;
142 /* Was it an error ? */
143 if (outheader->status != 0) {
144 errno = outheader->status;
146 /* Only return an error here if there are no node-specific
147 errors present in the message that might have more detail */
148 if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
149 fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
150 return 0;
155 return 1;
158 /* Build the structure header and parse-out wildcard node names */
159 static void _build_header(struct clvm_header *head, int cmd, const char *node,
160 int len)
162 head->cmd = cmd;
163 head->status = 0;
164 head->flags = 0;
165 head->clientid = 0;
166 head->arglen = len;
168 if (node) {
170 * Allow a couple of special node names:
171 * "*" for all nodes,
172 * "." for the local node only
174 if (strcmp(node, "*") == 0) {
175 head->node[0] = '\0';
176 } else if (strcmp(node, ".") == 0) {
177 head->node[0] = '\0';
178 head->flags = CLVMD_FLAG_LOCAL;
179 } else
180 strcpy(head->node, node);
181 } else
182 head->node[0] = '\0';
186 * Send a message to a(or all) node(s) in the cluster and wait for replies
188 static int _cluster_request(char cmd, const char *node, void *data, int len,
189 lvm_response_t ** response, int *num)
191 char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
192 char *inptr;
193 char *retbuf = NULL;
194 int status;
195 int i;
196 int num_responses = 0;
197 struct clvm_header *head = (struct clvm_header *) outbuf;
198 lvm_response_t *rarray;
200 *num = 0;
202 if (_clvmd_sock == -1)
203 _clvmd_sock = _open_local_sock();
205 if (_clvmd_sock == -1)
206 return 0;
208 _build_header(head, cmd, node, len);
209 memcpy(head->node + strlen(head->node) + 1, data, len);
211 status = _send_request(outbuf, sizeof(struct clvm_header) +
212 strlen(head->node) + len, &retbuf);
213 if (!status)
214 goto out;
216 /* Count the number of responses we got */
217 head = (struct clvm_header *) retbuf;
218 inptr = head->args;
219 while (inptr[0]) {
220 num_responses++;
221 inptr += strlen(inptr) + 1;
222 inptr += sizeof(int);
223 inptr += strlen(inptr) + 1;
227 * Allocate response array.
228 * With an extra pair of INTs on the front to sanity
229 * check the pointer when we are given it back to free
231 *response = dm_malloc(sizeof(lvm_response_t) * num_responses +
232 sizeof(int) * 2);
233 if (!*response) {
234 errno = ENOMEM;
235 status = 0;
236 goto out;
239 rarray = *response;
241 /* Unpack the response into an lvm_response_t array */
242 inptr = head->args;
243 i = 0;
244 while (inptr[0]) {
245 strcpy(rarray[i].node, inptr);
246 inptr += strlen(inptr) + 1;
248 memcpy(&rarray[i].status, inptr, sizeof(int));
249 inptr += sizeof(int);
251 rarray[i].response = dm_malloc(strlen(inptr) + 1);
252 if (rarray[i].response == NULL) {
253 /* Free up everything else and return error */
254 int j;
255 for (j = 0; j < i; j++)
256 dm_free(rarray[i].response);
257 free(*response);
258 errno = ENOMEM;
259 status = -1;
260 goto out;
263 strcpy(rarray[i].response, inptr);
264 rarray[i].len = strlen(inptr);
265 inptr += strlen(inptr) + 1;
266 i++;
268 *num = num_responses;
269 *response = rarray;
271 out:
272 if (retbuf)
273 dm_free(retbuf);
275 return status;
278 /* Free reply array */
279 static int _cluster_free_request(lvm_response_t * response, int num)
281 int i;
283 for (i = 0; i < num; i++) {
284 dm_free(response[i].response);
287 dm_free(response);
289 return 1;
292 int refresh_clvmd()
294 int num_responses;
295 char args[1]; // No args really.
296 lvm_response_t *response;
297 int saved_errno;
298 int status;
299 int i;
301 status = _cluster_request(CLVMD_CMD_REFRESH, "*", args, 0, &response, &num_responses);
303 /* If any nodes were down then display them and return an error */
304 for (i = 0; i < num_responses; i++) {
305 if (response[i].status == EHOSTDOWN) {
306 fprintf(stderr, "clvmd not running on node %s",
307 response[i].node);
308 status = 0;
309 errno = response[i].status;
310 } else if (response[i].status) {
311 fprintf(stderr, "Error resetting node %s: %s",
312 response[i].node,
313 response[i].response[0] ?
314 response[i].response :
315 strerror(response[i].status));
316 status = 0;
317 errno = response[i].status;
321 saved_errno = errno;
322 _cluster_free_request(response, num_responses);
323 errno = saved_errno;
325 return status;
328 int debug_clvmd(int level, int clusterwide)
330 int num_responses;
331 char args[1];
332 const char *nodes;
333 lvm_response_t *response;
334 int saved_errno;
335 int status;
336 int i;
338 args[0] = level;
339 if (clusterwide)
340 nodes = "*";
341 else
342 nodes = ".";
344 status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses);
346 /* If any nodes were down then display them and return an error */
347 for (i = 0; i < num_responses; i++) {
348 if (response[i].status == EHOSTDOWN) {
349 fprintf(stderr, "clvmd not running on node %s",
350 response[i].node);
351 status = 0;
352 errno = response[i].status;
353 } else if (response[i].status) {
354 fprintf(stderr, "Error setting debug on node %s: %s",
355 response[i].node,
356 response[i].response[0] ?
357 response[i].response :
358 strerror(response[i].status));
359 status = 0;
360 errno = response[i].status;
364 saved_errno = errno;
365 _cluster_free_request(response, num_responses);
366 errno = saved_errno;
368 return status;