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
23 #define _FILE_OFFSET_BITS 64
25 #include <configure.h>
27 #include <sys/socket.h>
31 #include <libdevmapper.h>
37 #include "refresh_clvmd.h"
39 typedef struct lvm_response
{
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)
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
));
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
,
73 int saved_errno
= errno
;
75 fprintf(stderr
, "connect() failed on local socket: %s\n",
77 if (close(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
;
97 /* Send it to CLVMD */
99 if ( (err
= write(_clvmd_sock
, inbuf
, inlen
)) != inlen
) {
100 if (err
== -1 && errno
== EINTR
)
102 fprintf(stderr
, "Error writing data to clvmd: %s", strerror(errno
));
106 /* Get the response */
108 if ((len
= read(_clvmd_sock
, outbuf
, sizeof(struct clvm_header
))) < 0) {
111 fprintf(stderr
, "Error reading data from clvmd: %s", strerror(errno
));
116 fprintf(stderr
, "EOF reading CLVMD");
121 /* Allocate buffer */
122 buflen
= len
+ outheader
->arglen
;
123 *retbuf
= dm_malloc(buflen
);
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
));
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
));
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
,
170 * Allow a couple of special node names:
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
;
180 strcpy(head
->node
, node
);
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];
196 int num_responses
= 0;
197 struct clvm_header
*head
= (struct clvm_header
*) outbuf
;
198 lvm_response_t
*rarray
;
202 if (_clvmd_sock
== -1)
203 _clvmd_sock
= _open_local_sock();
205 if (_clvmd_sock
== -1)
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
);
216 /* Count the number of responses we got */
217 head
= (struct clvm_header
*) retbuf
;
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
+
241 /* Unpack the response into an lvm_response_t array */
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 */
255 for (j
= 0; j
< i
; j
++)
256 dm_free(rarray
[i
].response
);
263 strcpy(rarray
[i
].response
, inptr
);
264 rarray
[i
].len
= strlen(inptr
);
265 inptr
+= strlen(inptr
) + 1;
268 *num
= num_responses
;
278 /* Free reply array */
279 static int _cluster_free_request(lvm_response_t
* response
, int num
)
283 for (i
= 0; i
< num
; i
++) {
284 dm_free(response
[i
].response
);
295 char args
[1]; // No args really.
296 lvm_response_t
*response
;
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",
309 errno
= response
[i
].status
;
310 } else if (response
[i
].status
) {
311 fprintf(stderr
, "Error resetting node %s: %s",
313 response
[i
].response
[0] ?
314 response
[i
].response
:
315 strerror(response
[i
].status
));
317 errno
= response
[i
].status
;
322 _cluster_free_request(response
, num_responses
);
328 int debug_clvmd(int level
, int clusterwide
)
333 lvm_response_t
*response
;
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",
352 errno
= response
[i
].status
;
353 } else if (response
[i
].status
) {
354 fprintf(stderr
, "Error setting debug on node %s: %s",
356 response
[i
].response
[0] ?
357 response
[i
].response
:
358 strerror(response
[i
].status
));
360 errno
= response
[i
].status
;
365 _cluster_free_request(response
, num_responses
);