2 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
5 * This file is part of LVM2.
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU General Public License v.2.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software Foundation,
13 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * Send a command to a running clvmd from the command-line
20 #include "clvmd-common.h"
23 #include "refresh_clvmd.h"
26 #include <sys/socket.h>
29 typedef struct lvm_response {
37 * This gets stuck at the start of memory we allocate so we
38 * can sanity-check it at deallocation time
40 #define LVM_SIGNATURE 0x434C564D
42 static int _clvmd_sock = -1;
44 /* Open connection to the clvm daemon */
45 static int _open_local_sock(void)
48 struct sockaddr_un sockaddr;
50 /* Open local socket */
51 if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
52 fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
56 memset(&sockaddr, 0, sizeof(sockaddr));
57 memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
59 sockaddr.sun_family = AF_UNIX;
61 if (connect(local_socket,(struct sockaddr *) &sockaddr,
63 int saved_errno = errno;
65 fprintf(stderr, "connect() failed on local socket: %s\n",
67 if (close(local_socket))
77 /* Send a request and return the status */
78 static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_response)
80 char outbuf[PIPE_BUF];
81 struct clvm_header *outheader = (struct clvm_header *) outbuf;
87 /* Send it to CLVMD */
89 if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
90 if (err == -1 && errno == EINTR)
92 fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
98 /* Get the response */
100 if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
103 fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
108 fprintf(stderr, "EOF reading CLVMD");
113 /* Allocate buffer */
114 buflen = len + outheader->arglen;
115 *retbuf = dm_malloc(buflen);
121 /* Copy the header */
122 memcpy(*retbuf, outbuf, len);
123 outheader = (struct clvm_header *) *retbuf;
125 /* Read the returned values */
126 off = 1; /* we've already read the first byte */
127 while (off <= outheader->arglen && len > 0) {
128 len = read(_clvmd_sock, outheader->args + off,
129 buflen - off - offsetof(struct clvm_header, args));
134 /* Was it an error ? */
135 if (outheader->status != 0) {
136 errno = outheader->status;
138 /* Only return an error here if there are no node-specific
139 errors present in the message that might have more detail */
140 if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
141 fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
150 /* Build the structure header and parse-out wildcard node names */
151 static void _build_header(struct clvm_header *head, int cmd, const char *node,
162 * Allow a couple of special node names:
164 * "." for the local node only
166 if (strcmp(node, "*") == 0) {
167 head->node[0] = '\0';
168 } else if (strcmp(node, ".") == 0) {
169 head->node[0] = '\0';
170 head->flags = CLVMD_FLAG_LOCAL;
172 strcpy(head->node, node);
174 head->node[0] = '\0';
178 * Send a message to a(or all) node(s) in the cluster and wait for replies
180 static int _cluster_request(char cmd, const char *node, void *data, int len,
181 lvm_response_t ** response, int *num, int no_response)
183 char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
188 int num_responses = 0;
189 struct clvm_header *head = (struct clvm_header *) outbuf;
190 lvm_response_t *rarray;
194 if (_clvmd_sock == -1)
195 _clvmd_sock = _open_local_sock();
197 if (_clvmd_sock == -1)
200 _build_header(head, cmd, node, len);
201 memcpy(head->node + strlen(head->node) + 1, data, len);
203 status = _send_request(outbuf, sizeof(struct clvm_header) +
204 strlen(head->node) + len, &retbuf, no_response);
205 if (!status || no_response)
208 /* Count the number of responses we got */
209 head = (struct clvm_header *) retbuf;
213 inptr += strlen(inptr) + 1;
214 inptr += sizeof(int);
215 inptr += strlen(inptr) + 1;
219 * Allocate response array.
220 * With an extra pair of INTs on the front to sanity
221 * check the pointer when we are given it back to free
223 *response = dm_malloc(sizeof(lvm_response_t) * num_responses +
233 /* Unpack the response into an lvm_response_t array */
237 strcpy(rarray[i].node, inptr);
238 inptr += strlen(inptr) + 1;
240 memcpy(&rarray[i].status, inptr, sizeof(int));
241 inptr += sizeof(int);
243 rarray[i].response = dm_malloc(strlen(inptr) + 1);
244 if (rarray[i].response == NULL) {
245 /* Free up everything else and return error */
247 for (j = 0; j < i; j++)
248 dm_free(rarray[i].response);
255 strcpy(rarray[i].response, inptr);
256 rarray[i].len = strlen(inptr);
257 inptr += strlen(inptr) + 1;
260 *num = num_responses;
270 /* Free reply array */
271 static int _cluster_free_request(lvm_response_t * response, int num)
275 for (i = 0; i < num; i++) {
276 dm_free(response[i].response);
284 int refresh_clvmd(int all_nodes)
287 char args[1]; // No args really.
288 lvm_response_t *response = NULL;
293 status = _cluster_request(CLVMD_CMD_REFRESH, all_nodes?"*":".", args, 0, &response, &num_responses, 0);
295 /* If any nodes were down then display them and return an error */
296 for (i = 0; i < num_responses; i++) {
297 if (response[i].status == EHOSTDOWN) {
298 fprintf(stderr, "clvmd not running on node %s",
301 errno = response[i].status;
302 } else if (response[i].status) {
303 fprintf(stderr, "Error resetting node %s: %s",
305 response[i].response[0] ?
306 response[i].response :
307 strerror(response[i].status));
309 errno = response[i].status;
314 _cluster_free_request(response, num_responses);
320 int restart_clvmd(int all_nodes)
324 status = _cluster_request(CLVMD_CMD_RESTART, all_nodes?"*":".", NULL, 0, NULL, &dummy, 1);
327 * FIXME: we cannot receive response, clvmd re-exec before it.
328 * but also should not close socket too early (the whole rq is dropped then).
329 * FIXME: This should be handled this way:
330 * - client waits for RESTART ack (and socket close)
332 * - client checks that server is ready again (VERSION command?)
339 int debug_clvmd(int level, int clusterwide)
344 lvm_response_t *response = NULL;
355 status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses, 0);
357 /* If any nodes were down then display them and return an error */
358 for (i = 0; i < num_responses; i++) {
359 if (response[i].status == EHOSTDOWN) {
360 fprintf(stderr, "clvmd not running on node %s",
363 errno = response[i].status;
364 } else if (response[i].status) {
365 fprintf(stderr, "Error setting debug on node %s: %s",
367 response[i].response[0] ?
368 response[i].response :
369 strerror(response[i].status));
371 errno = response[i].status;
376 _cluster_free_request(response, num_responses);