1*7c604eeaShaad /* $NetBSD: cluster_locking.c,v 1.1.1.3 2009/12/02 00:26:24 haad Exp $ */
256a34939Shaad
356a34939Shaad /*
456a34939Shaad * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
5*7c604eeaShaad * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
656a34939Shaad *
756a34939Shaad * This file is part of LVM2.
856a34939Shaad *
956a34939Shaad * This copyrighted material is made available to anyone wishing to use,
1056a34939Shaad * modify, copy, or redistribute it subject to the terms and conditions
1156a34939Shaad * of the GNU Lesser General Public License v.2.1.
1256a34939Shaad *
1356a34939Shaad * You should have received a copy of the GNU Lesser General Public License
1456a34939Shaad * along with this program; if not, write to the Free Software Foundation,
1556a34939Shaad * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1656a34939Shaad */
1756a34939Shaad
1856a34939Shaad /*
1956a34939Shaad * Locking functions for LVM.
2056a34939Shaad * The main purpose of this part of the library is to serialise LVM
2156a34939Shaad * management operations across a cluster.
2256a34939Shaad */
2356a34939Shaad
2456a34939Shaad #include "lib.h"
2556a34939Shaad #include "clvm.h"
2656a34939Shaad #include "lvm-string.h"
2756a34939Shaad #include "locking.h"
2856a34939Shaad #include "locking_types.h"
29*7c604eeaShaad #include "toolcontext.h"
3056a34939Shaad
3156a34939Shaad #include <assert.h>
3256a34939Shaad #include <stddef.h>
3356a34939Shaad #include <sys/socket.h>
3456a34939Shaad #include <sys/un.h>
3556a34939Shaad #include <unistd.h>
3656a34939Shaad
3756a34939Shaad #ifndef CLUSTER_LOCKING_INTERNAL
3856a34939Shaad int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags);
39*7c604eeaShaad int query_resource(const char *resource, int *mode);
4056a34939Shaad void locking_end(void);
4156a34939Shaad int locking_init(int type, struct config_tree *cf, uint32_t *flags);
4256a34939Shaad #endif
4356a34939Shaad
4456a34939Shaad typedef struct lvm_response {
4556a34939Shaad char node[255];
4656a34939Shaad char *response;
4756a34939Shaad int status;
4856a34939Shaad int len;
4956a34939Shaad } lvm_response_t;
5056a34939Shaad
5156a34939Shaad /*
5256a34939Shaad * This gets stuck at the start of memory we allocate so we
5356a34939Shaad * can sanity-check it at deallocation time
5456a34939Shaad */
5556a34939Shaad #define LVM_SIGNATURE 0x434C564D
5656a34939Shaad
5756a34939Shaad /*
5856a34939Shaad * NOTE: the LVMD uses the socket FD as the client ID, this means
5956a34939Shaad * that any client that calls fork() will inherit the context of
6056a34939Shaad * it's parent.
6156a34939Shaad */
6256a34939Shaad static int _clvmd_sock = -1;
6356a34939Shaad
6456a34939Shaad /* FIXME Install SIGPIPE handler? */
6556a34939Shaad
6656a34939Shaad /* Open connection to the Cluster Manager daemon */
_open_local_sock(void)6756a34939Shaad static int _open_local_sock(void)
6856a34939Shaad {
6956a34939Shaad int local_socket;
7056a34939Shaad struct sockaddr_un sockaddr;
7156a34939Shaad
7256a34939Shaad /* Open local socket */
7356a34939Shaad if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
7456a34939Shaad log_error("Local socket creation failed: %s", strerror(errno));
7556a34939Shaad return -1;
7656a34939Shaad }
7756a34939Shaad
7856a34939Shaad memset(&sockaddr, 0, sizeof(sockaddr));
7956a34939Shaad memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
8056a34939Shaad
8156a34939Shaad sockaddr.sun_family = AF_UNIX;
8256a34939Shaad
8356a34939Shaad if (connect(local_socket,(struct sockaddr *) &sockaddr,
8456a34939Shaad sizeof(sockaddr))) {
8556a34939Shaad int saved_errno = errno;
8656a34939Shaad
8756a34939Shaad log_error("connect() failed on local socket: %s",
8856a34939Shaad strerror(errno));
8956a34939Shaad if (close(local_socket))
9056a34939Shaad stack;
9156a34939Shaad
9256a34939Shaad errno = saved_errno;
9356a34939Shaad return -1;
9456a34939Shaad }
9556a34939Shaad
9656a34939Shaad return local_socket;
9756a34939Shaad }
9856a34939Shaad
9956a34939Shaad /* Send a request and return the status */
_send_request(char * inbuf,int inlen,char ** retbuf)10056a34939Shaad static int _send_request(char *inbuf, int inlen, char **retbuf)
10156a34939Shaad {
10256a34939Shaad char outbuf[PIPE_BUF] __attribute((aligned(8)));
10356a34939Shaad struct clvm_header *outheader = (struct clvm_header *) outbuf;
10456a34939Shaad int len;
10556a34939Shaad int off;
10656a34939Shaad int buflen;
10756a34939Shaad int err;
10856a34939Shaad
10956a34939Shaad /* Send it to CLVMD */
11056a34939Shaad rewrite:
11156a34939Shaad if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
11256a34939Shaad if (err == -1 && errno == EINTR)
11356a34939Shaad goto rewrite;
11456a34939Shaad log_error("Error writing data to clvmd: %s", strerror(errno));
11556a34939Shaad return 0;
11656a34939Shaad }
11756a34939Shaad
11856a34939Shaad /* Get the response */
11956a34939Shaad reread:
12056a34939Shaad if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
12156a34939Shaad if (errno == EINTR)
12256a34939Shaad goto reread;
12356a34939Shaad log_error("Error reading data from clvmd: %s", strerror(errno));
12456a34939Shaad return 0;
12556a34939Shaad }
12656a34939Shaad
12756a34939Shaad if (len == 0) {
12856a34939Shaad log_error("EOF reading CLVMD");
12956a34939Shaad errno = ENOTCONN;
13056a34939Shaad return 0;
13156a34939Shaad }
13256a34939Shaad
13356a34939Shaad /* Allocate buffer */
13456a34939Shaad buflen = len + outheader->arglen;
13556a34939Shaad *retbuf = dm_malloc(buflen);
13656a34939Shaad if (!*retbuf) {
13756a34939Shaad errno = ENOMEM;
13856a34939Shaad return 0;
13956a34939Shaad }
14056a34939Shaad
14156a34939Shaad /* Copy the header */
14256a34939Shaad memcpy(*retbuf, outbuf, len);
14356a34939Shaad outheader = (struct clvm_header *) *retbuf;
14456a34939Shaad
14556a34939Shaad /* Read the returned values */
14656a34939Shaad off = 1; /* we've already read the first byte */
14756a34939Shaad while (off <= outheader->arglen && len > 0) {
14856a34939Shaad len = read(_clvmd_sock, outheader->args + off,
14956a34939Shaad buflen - off - offsetof(struct clvm_header, args));
15056a34939Shaad if (len > 0)
15156a34939Shaad off += len;
15256a34939Shaad }
15356a34939Shaad
15456a34939Shaad /* Was it an error ? */
15556a34939Shaad if (outheader->status != 0) {
15656a34939Shaad errno = outheader->status;
15756a34939Shaad
15856a34939Shaad /* Only return an error here if there are no node-specific
15956a34939Shaad errors present in the message that might have more detail */
16056a34939Shaad if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
16156a34939Shaad log_error("cluster request failed: %s", strerror(errno));
16256a34939Shaad return 0;
16356a34939Shaad }
16456a34939Shaad
16556a34939Shaad }
16656a34939Shaad
16756a34939Shaad return 1;
16856a34939Shaad }
16956a34939Shaad
17056a34939Shaad /* Build the structure header and parse-out wildcard node names */
171bec4d750Shaad /* FIXME: Cleanup implicit casts of clvmd_cmd (int, char, uint8_t, etc). */
_build_header(struct clvm_header * head,int clvmd_cmd,const char * node,int len)172bec4d750Shaad static void _build_header(struct clvm_header *head, int clvmd_cmd, const char *node,
17356a34939Shaad int len)
17456a34939Shaad {
175bec4d750Shaad head->cmd = clvmd_cmd;
17656a34939Shaad head->status = 0;
17756a34939Shaad head->flags = 0;
17856a34939Shaad head->clientid = 0;
17956a34939Shaad head->arglen = len;
18056a34939Shaad
18156a34939Shaad if (node) {
18256a34939Shaad /*
18356a34939Shaad * Allow a couple of special node names:
18456a34939Shaad * "*" for all nodes,
18556a34939Shaad * "." for the local node only
18656a34939Shaad */
18756a34939Shaad if (strcmp(node, "*") == 0) {
18856a34939Shaad head->node[0] = '\0';
18956a34939Shaad } else if (strcmp(node, ".") == 0) {
19056a34939Shaad head->node[0] = '\0';
19156a34939Shaad head->flags = CLVMD_FLAG_LOCAL;
19256a34939Shaad } else
19356a34939Shaad strcpy(head->node, node);
19456a34939Shaad } else
19556a34939Shaad head->node[0] = '\0';
19656a34939Shaad }
19756a34939Shaad
19856a34939Shaad /*
19956a34939Shaad * Send a message to a(or all) node(s) in the cluster and wait for replies
20056a34939Shaad */
_cluster_request(char clvmd_cmd,const char * node,void * data,int len,lvm_response_t ** response,int * num)201bec4d750Shaad static int _cluster_request(char clvmd_cmd, const char *node, void *data, int len,
20256a34939Shaad lvm_response_t ** response, int *num)
20356a34939Shaad {
20456a34939Shaad char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1] __attribute((aligned(8)));
20556a34939Shaad char *inptr;
20656a34939Shaad char *retbuf = NULL;
20756a34939Shaad int status;
20856a34939Shaad int i;
20956a34939Shaad int num_responses = 0;
21056a34939Shaad struct clvm_header *head = (struct clvm_header *) outbuf;
21156a34939Shaad lvm_response_t *rarray;
21256a34939Shaad
21356a34939Shaad *num = 0;
21456a34939Shaad
21556a34939Shaad if (_clvmd_sock == -1)
21656a34939Shaad _clvmd_sock = _open_local_sock();
21756a34939Shaad
21856a34939Shaad if (_clvmd_sock == -1)
21956a34939Shaad return 0;
22056a34939Shaad
221bec4d750Shaad _build_header(head, clvmd_cmd, node, len);
22256a34939Shaad memcpy(head->node + strlen(head->node) + 1, data, len);
22356a34939Shaad
22456a34939Shaad status = _send_request(outbuf, sizeof(struct clvm_header) +
22556a34939Shaad strlen(head->node) + len, &retbuf);
22656a34939Shaad if (!status)
22756a34939Shaad goto out;
22856a34939Shaad
22956a34939Shaad /* Count the number of responses we got */
23056a34939Shaad head = (struct clvm_header *) retbuf;
23156a34939Shaad inptr = head->args;
23256a34939Shaad while (inptr[0]) {
23356a34939Shaad num_responses++;
23456a34939Shaad inptr += strlen(inptr) + 1;
23556a34939Shaad inptr += sizeof(int);
23656a34939Shaad inptr += strlen(inptr) + 1;
23756a34939Shaad }
23856a34939Shaad
23956a34939Shaad /*
24056a34939Shaad * Allocate response array.
24156a34939Shaad * With an extra pair of INTs on the front to sanity
24256a34939Shaad * check the pointer when we are given it back to free
24356a34939Shaad */
24456a34939Shaad *response = dm_malloc(sizeof(lvm_response_t) * num_responses);
24556a34939Shaad if (!*response) {
24656a34939Shaad errno = ENOMEM;
24756a34939Shaad status = 0;
24856a34939Shaad goto out;
24956a34939Shaad }
25056a34939Shaad
25156a34939Shaad rarray = *response;
25256a34939Shaad
25356a34939Shaad /* Unpack the response into an lvm_response_t array */
25456a34939Shaad inptr = head->args;
25556a34939Shaad i = 0;
25656a34939Shaad while (inptr[0]) {
25756a34939Shaad strcpy(rarray[i].node, inptr);
25856a34939Shaad inptr += strlen(inptr) + 1;
25956a34939Shaad
26056a34939Shaad memcpy(&rarray[i].status, inptr, sizeof(int));
26156a34939Shaad inptr += sizeof(int);
26256a34939Shaad
26356a34939Shaad rarray[i].response = dm_malloc(strlen(inptr) + 1);
26456a34939Shaad if (rarray[i].response == NULL) {
26556a34939Shaad /* Free up everything else and return error */
26656a34939Shaad int j;
26756a34939Shaad for (j = 0; j < i; j++)
26856a34939Shaad dm_free(rarray[i].response);
26956a34939Shaad free(*response);
27056a34939Shaad errno = ENOMEM;
27156a34939Shaad status = -1;
27256a34939Shaad goto out;
27356a34939Shaad }
27456a34939Shaad
27556a34939Shaad strcpy(rarray[i].response, inptr);
27656a34939Shaad rarray[i].len = strlen(inptr);
27756a34939Shaad inptr += strlen(inptr) + 1;
27856a34939Shaad i++;
27956a34939Shaad }
28056a34939Shaad *num = num_responses;
28156a34939Shaad *response = rarray;
28256a34939Shaad
28356a34939Shaad out:
28456a34939Shaad if (retbuf)
28556a34939Shaad dm_free(retbuf);
28656a34939Shaad
28756a34939Shaad return status;
28856a34939Shaad }
28956a34939Shaad
29056a34939Shaad /* Free reply array */
_cluster_free_request(lvm_response_t * response,int num)29156a34939Shaad static int _cluster_free_request(lvm_response_t * response, int num)
29256a34939Shaad {
29356a34939Shaad int i;
29456a34939Shaad
29556a34939Shaad for (i = 0; i < num; i++) {
29656a34939Shaad dm_free(response[i].response);
29756a34939Shaad }
29856a34939Shaad
29956a34939Shaad dm_free(response);
30056a34939Shaad
30156a34939Shaad return 1;
30256a34939Shaad }
30356a34939Shaad
_lock_for_cluster(struct cmd_context * cmd,unsigned char clvmd_cmd,uint32_t flags,const char * name)304*7c604eeaShaad static int _lock_for_cluster(struct cmd_context *cmd, unsigned char clvmd_cmd,
305*7c604eeaShaad uint32_t flags, const char *name)
30656a34939Shaad {
30756a34939Shaad int status;
30856a34939Shaad int i;
30956a34939Shaad char *args;
31056a34939Shaad const char *node = "";
31156a34939Shaad int len;
31256a34939Shaad int saved_errno = errno;
31356a34939Shaad lvm_response_t *response = NULL;
31456a34939Shaad int num_responses;
31556a34939Shaad
31656a34939Shaad assert(name);
31756a34939Shaad
31856a34939Shaad len = strlen(name) + 3;
31956a34939Shaad args = alloca(len);
32056a34939Shaad strcpy(args + 2, name);
32156a34939Shaad
32256a34939Shaad args[0] = flags & 0x7F; /* Maskoff lock flags */
32356a34939Shaad args[1] = flags & 0xC0; /* Bitmap flags */
32456a34939Shaad
32556a34939Shaad if (mirror_in_sync())
32656a34939Shaad args[1] |= LCK_MIRROR_NOSYNC_MODE;
32756a34939Shaad
32856a34939Shaad if (dmeventd_monitor_mode())
32956a34939Shaad args[1] |= LCK_DMEVENTD_MONITOR_MODE;
33056a34939Shaad
331*7c604eeaShaad if (cmd->partial_activation)
332*7c604eeaShaad args[1] |= LCK_PARTIAL_MODE;
333*7c604eeaShaad
33456a34939Shaad /*
33556a34939Shaad * VG locks are just that: locks, and have no side effects
33656a34939Shaad * so we only need to do them on the local node because all
33756a34939Shaad * locks are cluster-wide.
33856a34939Shaad * Also, if the lock is exclusive it makes no sense to try to
33956a34939Shaad * acquire it on all nodes, so just do that on the local node too.
34056a34939Shaad * One exception, is that P_ locks /do/ get distributed across
34156a34939Shaad * the cluster because they might have side-effects.
34256a34939Shaad */
34356a34939Shaad if (strncmp(name, "P_", 2) &&
344bec4d750Shaad (clvmd_cmd == CLVMD_CMD_LOCK_VG ||
34556a34939Shaad (flags & LCK_TYPE_MASK) == LCK_EXCL ||
34656a34939Shaad (flags & LCK_LOCAL) ||
34756a34939Shaad !(flags & LCK_CLUSTER_VG)))
34856a34939Shaad node = ".";
34956a34939Shaad
350bec4d750Shaad status = _cluster_request(clvmd_cmd, node, args, len,
35156a34939Shaad &response, &num_responses);
35256a34939Shaad
35356a34939Shaad /* If any nodes were down then display them and return an error */
35456a34939Shaad for (i = 0; i < num_responses; i++) {
35556a34939Shaad if (response[i].status == EHOSTDOWN) {
35656a34939Shaad log_error("clvmd not running on node %s",
35756a34939Shaad response[i].node);
35856a34939Shaad status = 0;
35956a34939Shaad errno = response[i].status;
36056a34939Shaad } else if (response[i].status) {
36156a34939Shaad log_error("Error locking on node %s: %s",
36256a34939Shaad response[i].node,
36356a34939Shaad response[i].response[0] ?
36456a34939Shaad response[i].response :
36556a34939Shaad strerror(response[i].status));
36656a34939Shaad status = 0;
36756a34939Shaad errno = response[i].status;
36856a34939Shaad }
36956a34939Shaad }
37056a34939Shaad
37156a34939Shaad saved_errno = errno;
37256a34939Shaad _cluster_free_request(response, num_responses);
37356a34939Shaad errno = saved_errno;
37456a34939Shaad
37556a34939Shaad return status;
37656a34939Shaad }
37756a34939Shaad
37856a34939Shaad /* API entry point for LVM */
37956a34939Shaad #ifdef CLUSTER_LOCKING_INTERNAL
_lock_resource(struct cmd_context * cmd,const char * resource,uint32_t flags)38056a34939Shaad static int _lock_resource(struct cmd_context *cmd, const char *resource,
38156a34939Shaad uint32_t flags)
38256a34939Shaad #else
38356a34939Shaad int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags)
38456a34939Shaad #endif
38556a34939Shaad {
38656a34939Shaad char lockname[PATH_MAX];
387bec4d750Shaad int clvmd_cmd = 0;
38856a34939Shaad const char *lock_scope;
38956a34939Shaad const char *lock_type = "";
39056a34939Shaad
39156a34939Shaad assert(strlen(resource) < sizeof(lockname));
39256a34939Shaad assert(resource);
39356a34939Shaad
39456a34939Shaad switch (flags & LCK_SCOPE_MASK) {
39556a34939Shaad case LCK_VG:
396*7c604eeaShaad if (flags == LCK_VG_BACKUP) {
397*7c604eeaShaad log_very_verbose("Requesting backup of VG metadata for %s",
398*7c604eeaShaad resource);
399*7c604eeaShaad return _lock_for_cluster(cmd, CLVMD_CMD_VG_BACKUP,
400*7c604eeaShaad LCK_CLUSTER_VG, resource);
401*7c604eeaShaad }
402*7c604eeaShaad
40356a34939Shaad /* If the VG name is empty then lock the unused PVs */
40456a34939Shaad if (*resource == '#' || (flags & LCK_CACHE))
40556a34939Shaad dm_snprintf(lockname, sizeof(lockname), "P_%s",
40656a34939Shaad resource);
40756a34939Shaad else
40856a34939Shaad dm_snprintf(lockname, sizeof(lockname), "V_%s",
40956a34939Shaad resource);
41056a34939Shaad
41156a34939Shaad lock_scope = "VG";
412bec4d750Shaad clvmd_cmd = CLVMD_CMD_LOCK_VG;
41356a34939Shaad flags &= LCK_TYPE_MASK;
41456a34939Shaad break;
41556a34939Shaad
41656a34939Shaad case LCK_LV:
417bec4d750Shaad clvmd_cmd = CLVMD_CMD_LOCK_LV;
41856a34939Shaad strcpy(lockname, resource);
41956a34939Shaad lock_scope = "LV";
42056a34939Shaad flags &= 0xffdf; /* Mask off HOLD flag */
42156a34939Shaad break;
42256a34939Shaad
42356a34939Shaad default:
42456a34939Shaad log_error("Unrecognised lock scope: %d",
42556a34939Shaad flags & LCK_SCOPE_MASK);
42656a34939Shaad return 0;
42756a34939Shaad }
42856a34939Shaad
42956a34939Shaad switch(flags & LCK_TYPE_MASK) {
43056a34939Shaad case LCK_UNLOCK:
43156a34939Shaad lock_type = "UN";
43256a34939Shaad break;
43356a34939Shaad case LCK_NULL:
43456a34939Shaad lock_type = "NL";
43556a34939Shaad break;
43656a34939Shaad case LCK_READ:
43756a34939Shaad lock_type = "CR";
43856a34939Shaad break;
43956a34939Shaad case LCK_PREAD:
44056a34939Shaad lock_type = "PR";
44156a34939Shaad break;
44256a34939Shaad case LCK_WRITE:
44356a34939Shaad lock_type = "PW";
44456a34939Shaad break;
44556a34939Shaad case LCK_EXCL:
44656a34939Shaad lock_type = "EX";
44756a34939Shaad break;
44856a34939Shaad default:
44956a34939Shaad log_error("Unrecognised lock type: %u",
45056a34939Shaad flags & LCK_TYPE_MASK);
45156a34939Shaad return 0;
45256a34939Shaad }
45356a34939Shaad
45456a34939Shaad log_very_verbose("Locking %s %s %s %s%s%s%s (0x%x)", lock_scope, lockname,
45556a34939Shaad lock_type,
45656a34939Shaad flags & LCK_NONBLOCK ? "" : "B",
45756a34939Shaad flags & LCK_HOLD ? "H" : "",
45856a34939Shaad flags & LCK_LOCAL ? "L" : "",
45956a34939Shaad flags & LCK_CLUSTER_VG ? "C" : "",
46056a34939Shaad flags);
46156a34939Shaad
46256a34939Shaad /* Send a message to the cluster manager */
463*7c604eeaShaad return _lock_for_cluster(cmd, clvmd_cmd, flags, lockname);
464*7c604eeaShaad }
465*7c604eeaShaad
decode_lock_type(const char * response)466*7c604eeaShaad static int decode_lock_type(const char *response)
467*7c604eeaShaad {
468*7c604eeaShaad if (!response)
469*7c604eeaShaad return LCK_NULL;
470*7c604eeaShaad else if (strcmp(response, "EX"))
471*7c604eeaShaad return LCK_EXCL;
472*7c604eeaShaad else if (strcmp(response, "CR"))
473*7c604eeaShaad return LCK_READ;
474*7c604eeaShaad else if (strcmp(response, "PR"))
475*7c604eeaShaad return LCK_PREAD;
476*7c604eeaShaad
477*7c604eeaShaad stack;
478*7c604eeaShaad return 0;
479*7c604eeaShaad }
480*7c604eeaShaad
481*7c604eeaShaad #ifdef CLUSTER_LOCKING_INTERNAL
_query_resource(const char * resource,int * mode)482*7c604eeaShaad static int _query_resource(const char *resource, int *mode)
483*7c604eeaShaad #else
484*7c604eeaShaad int query_resource(const char *resource, int *mode)
485*7c604eeaShaad #endif
486*7c604eeaShaad {
487*7c604eeaShaad int i, status, len, num_responses, saved_errno;
488*7c604eeaShaad const char *node = "";
489*7c604eeaShaad char *args;
490*7c604eeaShaad lvm_response_t *response = NULL;
491*7c604eeaShaad
492*7c604eeaShaad saved_errno = errno;
493*7c604eeaShaad len = strlen(resource) + 3;
494*7c604eeaShaad args = alloca(len);
495*7c604eeaShaad strcpy(args + 2, resource);
496*7c604eeaShaad
497*7c604eeaShaad args[0] = 0;
498*7c604eeaShaad args[1] = LCK_CLUSTER_VG;
499*7c604eeaShaad
500*7c604eeaShaad status = _cluster_request(CLVMD_CMD_LOCK_QUERY, node, args, len,
501*7c604eeaShaad &response, &num_responses);
502*7c604eeaShaad *mode = LCK_NULL;
503*7c604eeaShaad for (i = 0; i < num_responses; i++) {
504*7c604eeaShaad if (response[i].status == EHOSTDOWN)
505*7c604eeaShaad continue;
506*7c604eeaShaad
507*7c604eeaShaad if (!response[i].response[0])
508*7c604eeaShaad continue;
509*7c604eeaShaad
510*7c604eeaShaad /*
511*7c604eeaShaad * All nodes should use CR, or exactly one node
512*7c604eeaShaad * should held EX. (PR is obsolete)
513*7c604eeaShaad * If two nodes node reports different locks,
514*7c604eeaShaad * something is broken - just return more important mode.
515*7c604eeaShaad */
516*7c604eeaShaad if (decode_lock_type(response[i].response) > *mode)
517*7c604eeaShaad *mode = decode_lock_type(response[i].response);
518*7c604eeaShaad
519*7c604eeaShaad log_debug("Lock held for %s, node %s : %s", resource,
520*7c604eeaShaad response[i].node, response[i].response);
521*7c604eeaShaad }
522*7c604eeaShaad
523*7c604eeaShaad _cluster_free_request(response, num_responses);
524*7c604eeaShaad errno = saved_errno;
525*7c604eeaShaad
526*7c604eeaShaad return status;
52756a34939Shaad }
52856a34939Shaad
52956a34939Shaad #ifdef CLUSTER_LOCKING_INTERNAL
_locking_end(void)53056a34939Shaad static void _locking_end(void)
53156a34939Shaad #else
53256a34939Shaad void locking_end(void)
53356a34939Shaad #endif
53456a34939Shaad {
53556a34939Shaad if (_clvmd_sock != -1 && close(_clvmd_sock))
53656a34939Shaad stack;
53756a34939Shaad
53856a34939Shaad _clvmd_sock = -1;
53956a34939Shaad }
54056a34939Shaad
54156a34939Shaad #ifdef CLUSTER_LOCKING_INTERNAL
_reset_locking(void)54256a34939Shaad static void _reset_locking(void)
54356a34939Shaad #else
54456a34939Shaad void reset_locking(void)
54556a34939Shaad #endif
54656a34939Shaad {
54756a34939Shaad if (close(_clvmd_sock))
54856a34939Shaad stack;
54956a34939Shaad
55056a34939Shaad _clvmd_sock = _open_local_sock();
55156a34939Shaad if (_clvmd_sock == -1)
55256a34939Shaad stack;
55356a34939Shaad }
55456a34939Shaad
55556a34939Shaad #ifdef CLUSTER_LOCKING_INTERNAL
init_cluster_locking(struct locking_type * locking,struct cmd_context * cmd)55656a34939Shaad int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd)
55756a34939Shaad {
55856a34939Shaad locking->lock_resource = _lock_resource;
559*7c604eeaShaad locking->query_resource = _query_resource;
56056a34939Shaad locking->fin_locking = _locking_end;
56156a34939Shaad locking->reset_locking = _reset_locking;
56256a34939Shaad locking->flags = LCK_PRE_MEMLOCK | LCK_CLUSTERED;
56356a34939Shaad
56456a34939Shaad _clvmd_sock = _open_local_sock();
56556a34939Shaad if (_clvmd_sock == -1)
56656a34939Shaad return 0;
56756a34939Shaad
56856a34939Shaad return 1;
56956a34939Shaad }
57056a34939Shaad #else
locking_init(int type,struct config_tree * cf,uint32_t * flags)57156a34939Shaad int locking_init(int type, struct config_tree *cf, uint32_t *flags)
57256a34939Shaad {
57356a34939Shaad _clvmd_sock = _open_local_sock();
57456a34939Shaad if (_clvmd_sock == -1)
57556a34939Shaad return 0;
57656a34939Shaad
57756a34939Shaad /* Ask LVM to lock memory before calling us */
57856a34939Shaad *flags |= LCK_PRE_MEMLOCK;
57956a34939Shaad *flags |= LCK_CLUSTERED;
58056a34939Shaad
58156a34939Shaad return 1;
58256a34939Shaad }
58356a34939Shaad #endif
584