diff options
Diffstat (limited to 'lib/locking/cluster_locking.c')
-rw-r--r-- | lib/locking/cluster_locking.c | 159 |
1 files changed, 94 insertions, 65 deletions
diff --git a/lib/locking/cluster_locking.c b/lib/locking/cluster_locking.c index eea9974..f9d6328 100644 --- a/lib/locking/cluster_locking.c +++ b/lib/locking/cluster_locking.c @@ -36,7 +36,7 @@ int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags); int query_resource(const char *resource, int *mode); void locking_end(void); -int locking_init(int type, struct config_tree *cf, uint32_t *flags); +int locking_init(int type, struct dm_config_tree *cf, uint32_t *flags); #endif typedef struct lvm_response { @@ -62,28 +62,30 @@ static int _clvmd_sock = -1; /* FIXME Install SIGPIPE handler? */ /* Open connection to the Cluster Manager daemon */ -static int _open_local_sock(void) +static int _open_local_sock(int suppress_messages) { int local_socket; - struct sockaddr_un sockaddr; + struct sockaddr_un sockaddr = { .sun_family = AF_UNIX }; + + if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) { + log_error("%s: clvmd socket name too long.", CLVMD_SOCKNAME); + return -1; + } /* Open local socket */ if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - log_error("Local socket creation failed: %s", strerror(errno)); + log_error_suppress(suppress_messages, "Local socket " + "creation failed: %s", strerror(errno)); return -1; } - memset(&sockaddr, 0, sizeof(sockaddr)); - memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME)); - - sockaddr.sun_family = AF_UNIX; if (connect(local_socket,(struct sockaddr *) &sockaddr, sizeof(sockaddr))) { int saved_errno = errno; - log_error("connect() failed on local socket: %s", - strerror(errno)); + log_error_suppress(suppress_messages, "connect() failed " + "on local socket: %s", strerror(errno)); if (close(local_socket)) stack; @@ -100,7 +102,7 @@ static int _send_request(char *inbuf, int inlen, char **retbuf) char outbuf[PIPE_BUF] __attribute__((aligned(8))); struct clvm_header *outheader = (struct clvm_header *) outbuf; int len; - int off; + unsigned off; int buflen; int err; @@ -173,24 +175,23 @@ static void _build_header(struct clvm_header *head, int clvmd_cmd, const char *n head->cmd = clvmd_cmd; head->status = 0; head->flags = 0; + head->xid = 0; head->clientid = 0; head->arglen = len; - if (node) { - /* - * Allow a couple of special node names: - * "*" for all nodes, - * "." for the local node only - */ - if (strcmp(node, "*") == 0) { - head->node[0] = '\0'; - } else if (strcmp(node, ".") == 0) { - head->node[0] = '\0'; - head->flags = CLVMD_FLAG_LOCAL; - } else - strcpy(head->node, node); - } else + /* + * Handle special node names. + */ + if (!node || !strcmp(node, NODE_ALL)) + head->node[0] = '\0'; + else if (!strcmp(node, NODE_LOCAL)) { + head->node[0] = '\0'; + head->flags = CLVMD_FLAG_LOCAL; + } else if (!strcmp(node, NODE_REMOTE)) { head->node[0] = '\0'; + head->flags = CLVMD_FLAG_REMOTE; + } else + strcpy(head->node, node); } /* @@ -211,16 +212,17 @@ static int _cluster_request(char clvmd_cmd, const char *node, void *data, int le *num = 0; if (_clvmd_sock == -1) - _clvmd_sock = _open_local_sock(); + _clvmd_sock = _open_local_sock(0); if (_clvmd_sock == -1) return 0; - _build_header(head, clvmd_cmd, node, len); + /* 1 byte is used from struct clvm_header.args[1], so -> len - 1 */ + _build_header(head, clvmd_cmd, node, len - 1); memcpy(head->node + strlen(head->node) + 1, data, len); status = _send_request(outbuf, sizeof(struct clvm_header) + - strlen(head->node) + len, &retbuf); + strlen(head->node) + len - 1, &retbuf); if (!status) goto out; @@ -279,8 +281,7 @@ static int _cluster_request(char clvmd_cmd, const char *node, void *data, int le *response = rarray; out: - if (retbuf) - dm_free(retbuf); + dm_free(retbuf); return status; } @@ -318,22 +319,33 @@ static int _lock_for_cluster(struct cmd_context *cmd, unsigned char clvmd_cmd, args = alloca(len); strcpy(args + 2, name); - /* Mask off lock flags */ - args[0] = flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_NONBLOCK | LCK_HOLD); - args[1] = flags & (LCK_LOCAL | LCK_CLUSTER_VG); + /* args[0] holds bottom 8 bits except LCK_LOCAL (0x40). */ + args[0] = flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_NONBLOCK | LCK_HOLD | LCK_CLUSTER_VG); + + args[1] = 0; if (flags & LCK_ORIGIN_ONLY) args[1] |= LCK_ORIGIN_ONLY_MODE; + if (flags & LCK_REVERT) + args[1] |= LCK_REVERT_MODE; + if (mirror_in_sync()) args[1] |= LCK_MIRROR_NOSYNC_MODE; + if (test_mode()) + args[1] |= LCK_TEST_MODE; + /* - * Must handle tri-state return from dmeventd_monitor_mode. - * But DMEVENTD_MONITOR_IGNORE is not propagated across the cluster. + * We propagate dmeventd_monitor_mode() to clvmd faithfully, since + * dmeventd monitoring is tied to activation which happens inside clvmd + * when locking_type = 3. */ dmeventd_mode = dmeventd_monitor_mode(); - if (dmeventd_mode != DMEVENTD_MONITOR_IGNORE && dmeventd_mode) + if (dmeventd_mode == DMEVENTD_MONITOR_IGNORE) + args[1] |= LCK_DMEVENTD_MONITOR_IGNORE; + + if (dmeventd_mode) args[1] |= LCK_DMEVENTD_MONITOR_MODE; if (cmd->partial_activation) @@ -343,17 +355,24 @@ static int _lock_for_cluster(struct cmd_context *cmd, unsigned char clvmd_cmd, * VG locks are just that: locks, and have no side effects * so we only need to do them on the local node because all * locks are cluster-wide. - * Also, if the lock is exclusive it makes no sense to try to - * acquire it on all nodes, so just do that on the local node too. - * One exception, is that P_ locks /do/ get distributed across - * the cluster because they might have side-effects. + * + * P_ locks /do/ get distributed across the cluster because they might + * have side-effects. + * + * SYNC_NAMES and VG_BACKUP use the VG name directly without prefix. */ - if (strncmp(name, "P_", 2) && - (clvmd_cmd == CLVMD_CMD_LOCK_VG || - (flags & LCK_TYPE_MASK) == LCK_EXCL || - (flags & LCK_LOCAL) || - !(flags & LCK_CLUSTER_VG))) - node = "."; + if (clvmd_cmd == CLVMD_CMD_SYNC_NAMES) { + if (flags & LCK_LOCAL) + node = NODE_LOCAL; + } else if (clvmd_cmd != CLVMD_CMD_VG_BACKUP) { + if (strncmp(name, "P_", 2) && + (clvmd_cmd == CLVMD_CMD_LOCK_VG || + (flags & LCK_LOCAL) || + !(flags & LCK_CLUSTER_VG))) + node = NODE_LOCAL; + else if (flags & LCK_REMOTE) + node = NODE_REMOTE; + } status = _cluster_request(clvmd_cmd, node, args, len, &response, &num_responses); @@ -401,6 +420,11 @@ int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags) switch (flags & LCK_SCOPE_MASK) { case LCK_VG: + if (!strcmp(resource, VG_SYNC_NAMES)) { + log_very_verbose("Requesting sync names."); + return _lock_for_cluster(cmd, CLVMD_CMD_SYNC_NAMES, + flags & ~LCK_HOLD, resource); + } if (flags == LCK_VG_BACKUP) { log_very_verbose("Requesting backup of VG metadata for %s", resource); @@ -409,12 +433,14 @@ int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags) } /* If the VG name is empty then lock the unused PVs */ - if (is_orphan_vg(resource) || is_global_vg(resource) || (flags & LCK_CACHE)) - dm_snprintf(lockname, sizeof(lockname), "P_%s", - resource); - else - dm_snprintf(lockname, sizeof(lockname), "V_%s", - resource); + if (dm_snprintf(lockname, sizeof(lockname), "%c_%s", + (is_orphan_vg(resource) || + is_global_vg(resource) || + (flags & LCK_CACHE)) ? 'P' : 'V', + resource) < 0) { + log_error("Locking resource %s too long.", resource); + return 0; + } lock_scope = "VG"; clvmd_cmd = CLVMD_CMD_LOCK_VG; @@ -465,14 +491,16 @@ int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags) return 0; } - log_very_verbose("Locking %s %s %s (%s%s%s%s%s%s%s) (0x%x)", lock_scope, lockname, + log_very_verbose("Locking %s %s %s (%s%s%s%s%s%s%s%s%s) (0x%x)", lock_scope, lockname, lock_type, lock_scope, flags & LCK_NONBLOCK ? "|NONBLOCK" : "", flags & LCK_HOLD ? "|HOLD" : "", - flags & LCK_LOCAL ? "|LOCAL" : "", flags & LCK_CLUSTER_VG ? "|CLUSTER" : "", + flags & LCK_LOCAL ? "|LOCAL" : "", + flags & LCK_REMOTE ? "|REMOTE" : "", flags & LCK_CACHE ? "|CACHE" : "", flags & LCK_ORIGIN_ONLY ? "|ORIGIN_ONLY" : "", + flags & LCK_REVERT ? "|REVERT" : "", flags); /* Send a message to the cluster manager */ @@ -483,11 +511,11 @@ static int decode_lock_type(const char *response) { if (!response) return LCK_NULL; - else if (strcmp(response, "EX")) + else if (!strcmp(response, "EX")) return LCK_EXCL; - else if (strcmp(response, "CR")) + else if (!strcmp(response, "CR")) return LCK_READ; - else if (strcmp(response, "PR")) + else if (!strcmp(response, "PR")) return LCK_PREAD; stack; @@ -511,7 +539,7 @@ int query_resource(const char *resource, int *mode) strcpy(args + 2, resource); args[0] = 0; - args[1] = LCK_CLUSTER_VG; + args[1] = 0; status = _cluster_request(CLVMD_CMD_LOCK_QUERY, node, args, len, &response, &num_responses); @@ -525,8 +553,8 @@ int query_resource(const char *resource, int *mode) /* * All nodes should use CR, or exactly one node - * should held EX. (PR is obsolete) - * If two nodes node reports different locks, + * should hold EX. (PR is obsolete) + * If two nodes report different locks, * something is broken - just return more important mode. */ if (decode_lock_type(response[i].response) > *mode) @@ -563,13 +591,14 @@ void reset_locking(void) if (close(_clvmd_sock)) stack; - _clvmd_sock = _open_local_sock(); + _clvmd_sock = _open_local_sock(0); if (_clvmd_sock == -1) stack; } #ifdef CLUSTER_LOCKING_INTERNAL -int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd) +int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages) { locking->lock_resource = _lock_resource; locking->query_resource = _query_resource; @@ -577,16 +606,16 @@ int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd) locking->reset_locking = _reset_locking; locking->flags = LCK_PRE_MEMLOCK | LCK_CLUSTERED; - _clvmd_sock = _open_local_sock(); + _clvmd_sock = _open_local_sock(suppress_messages); if (_clvmd_sock == -1) return 0; return 1; } #else -int locking_init(int type, struct config_tree *cf, uint32_t *flags) +int locking_init(int type, struct dm_config_tree *cf, uint32_t *flags) { - _clvmd_sock = _open_local_sock(); + _clvmd_sock = _open_local_sock(0); if (_clvmd_sock == -1) return 0; |