cluster: RHEL58 - cman: improve cman/qdisk interactions

Fabio M. Di Nitto fabbione at fedoraproject.org
Tue Sep 13 12:00:08 UTC 2011


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=1a810eac13bb49f85e0e3c5a17e05d06ba6a5037
Commit:        1a810eac13bb49f85e0e3c5a17e05d06ba6a5037
Parent:        0b79766fc2af6b7815a7a3620027f48550728ea8
Author:        Fabio M. Di Nitto <fdinitto at redhat.com>
AuthorDate:    Wed Sep 7 14:26:06 2011 +0200
Committer:     Fabio M. Di Nitto <fdinitto at redhat.com>
CommitterDate: Tue Sep 13 13:58:27 2011 +0200

cman: improve cman/qdisk interactions

- libcman/cman: add new quorum API call to update name and votes of a quorum device
- cman: simplify common code to free quorum_device infrastructure
- cman: do better logging/error reports of the quorum API usage
- cman: use strdup instead of malloc+strcpy (code is more readable)
- libcman: perform better error checking in register_quorum_device/update_quorum_device

- Allow qdisk to update device name in cman using a new libcman quorum API call
- Perform slight better error checking of some update opertaions

Resolves: rhbz#704243

(this backport of commit c79c32e88e from RHEL6 branch)

Acked-by: Lon Hohberger <lhh at redhat.com>
Acked-by: Christine Caulfield <ccaulfie at redhat.com>
Signed-off-by: Fabio M. Di Nitto <fdinitto at redhat.com>
---
 cman/daemon/cnxman-socket.h |    1 +
 cman/daemon/commands.c      |   86 ++++++++++++++++++++++++++++++++++++-------
 cman/lib/libcman.c          |   18 +++++++-
 cman/lib/libcman.h          |    4 ++
 cman/qdisk/main.c           |   35 ++++++++++-------
 5 files changed, 113 insertions(+), 31 deletions(-)

diff --git a/cman/daemon/cnxman-socket.h b/cman/daemon/cnxman-socket.h
index cc1de6a..351c97c 100644
--- a/cman/daemon/cnxman-socket.h
+++ b/cman/daemon/cnxman-socket.h
@@ -45,6 +45,7 @@
 #define CMAN_CMD_REG_QUORUMDEV      0x800000b5
 #define CMAN_CMD_UNREG_QUORUMDEV    0x800000b6
 #define CMAN_CMD_POLL_QUORUMDEV     0x800000b7
+#define CMAN_CMD_UPDATE_QUORUMDEV   0x800000b8
 #define CMAN_CMD_TRY_SHUTDOWN       0x800000bb
 #define CMAN_CMD_SHUTDOWN_REPLY     0x000000bc
 #define CMAN_CMD_UPDATE_FENCE_INFO  0x800000bd
diff --git a/cman/daemon/commands.c b/cman/daemon/commands.c
index 6e0160b..ddc85ec 100644
--- a/cman/daemon/commands.c
+++ b/cman/daemon/commands.c
@@ -971,44 +971,69 @@ static int do_cmd_try_shutdown(struct connection *con, char *cmdbuf)
 	}
 }
 
+static void free_quorum_device(void)
+{
+	if (!quorum_device)
+		return;
+
+	if (quorum_device->name)
+		free(quorum_device->name);
+
+	free(quorum_device);
+
+	quorum_device = NULL;
+}
+
 static int do_cmd_register_quorum_device(char *cmdbuf, int *retlen)
 {
 	int votes;
 	char *name = cmdbuf+sizeof(int);
 
-	if (!ais_running)
+	if (!ais_running) {
+		log_msg(LOG_ERR, "unable to register quorum device: aisexec is not running\n");
 		return -ENOTCONN;
+	}
 
-	if (!we_are_a_cluster_member)
+	if (!we_are_a_cluster_member) {
+		log_msg(LOG_ERR, "unable to register quorum device: this node is not part of a cluster\n");
 		return -ENOENT;
+	}
 
-	if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN)
+	if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN) {
+		log_msg(LOG_ERR, "unable to register quorum device: name is too long\n");
 		return -EINVAL;
+	}
 
 	/* Allow re-registering of a quorum device if the name is the same */
-	if (quorum_device && strcmp(name, quorum_device->name))
+	if (quorum_device && strcmp(name, quorum_device->name)) {
+		log_msg(LOG_ERR, "unable to re-register quorum device: device names do not match\n");
+		log_msg(LOG_DEBUG, "memb: old name: %s new name: %s\n", quorum_device->name, name);
                 return -EBUSY;
+	}
 
-	if (find_node_by_name(name))
+	if (find_node_by_name(name)) {
+		log_msg(LOG_ERR, "unable to register quorum device: a node with the same name (%s) already exists\n", name);
                 return -EALREADY;
+	}
 
 	memcpy(&votes, cmdbuf, sizeof(int));
 
 	if (!quorum_device)
 	{
 		quorum_device = malloc(sizeof(struct cluster_node));
-		if (!quorum_device)
+		if (!quorum_device) {
+			log_msg(LOG_ERR, "unable to register quorum device: not enough memory\n");
 			return -ENOMEM;
+		}
 		memset(quorum_device, 0, sizeof(struct cluster_node));
 
-		quorum_device->name = malloc(strlen(name) + 1);
+		quorum_device->name = strdup(name);
 		if (!quorum_device->name) {
-			free(quorum_device);
-			quorum_device = NULL;
+			log_msg(LOG_ERR, "unable to register quorum device: not enough memory\n");
+			free_quorum_device();
 			return -ENOMEM;
 		}
 
-		strcpy(quorum_device->name, name);
 		quorum_device->state = NODESTATE_DEAD;
 		gettimeofday(&quorum_device->join_time, NULL);
 
@@ -1034,15 +1059,44 @@ static int do_cmd_unregister_quorum_device(char *cmdbuf, int *retlen)
         if (quorum_device->state == NODESTATE_MEMBER)
                 return -EBUSY;
 
-	free(quorum_device->name);
-	free(quorum_device);
-
-        quorum_device = NULL;
+	free_quorum_device();
 
 	log_msg(LOG_INFO, "quorum device unregistered\n");
         return 0;
 }
 
+static int do_cmd_update_quorum_device(char *cmdbuf, int *retlen)
+{
+	int votes, ret = 0;
+	char *name = cmdbuf+sizeof(int);
+
+	if (!quorum_device)
+		return -EINVAL;
+
+	memcpy(&votes, cmdbuf, sizeof(int));
+
+	/* allow name change of the quorum device */
+	if (quorum_device && strcmp(name, quorum_device->name)) {
+		char *newname = NULL;
+		char *oldname = NULL;
+
+		newname = strdup(name);
+		if (!newname) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		oldname = quorum_device->name;
+		quorum_device->name = newname;
+		free(oldname);
+	}
+
+out:
+	quorum_device->votes = votes;
+
+	return ret;
+}
+
 static void ccsd_timer_fn(void *arg)
 {
 	int ccs_err;
@@ -1354,6 +1408,10 @@ int process_command(struct connection *con, int cmd, char *cmdbuf,
 		err = do_cmd_unregister_quorum_device(cmdbuf, retlen);
 		break;
 
+	case CMAN_CMD_UPDATE_QUORUMDEV:
+		err = do_cmd_update_quorum_device(cmdbuf, retlen);
+		break;
+
 	case CMAN_CMD_POLL_QUORUMDEV:
 		err = do_cmd_poll_quorum_device(cmdbuf, retlen);
 		break;
diff --git a/cman/lib/libcman.c b/cman/lib/libcman.c
index 3ce6de4..a4f73d3 100644
--- a/cman/lib/libcman.c
+++ b/cman/lib/libcman.c
@@ -1008,13 +1008,15 @@ int cman_replyto_shutdown(cman_handle_t handle, int yesno)
 }
 
 
-int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
+static int cman_set_quorum_device(cman_handle_t handle,
+				  int ops,
+				  char *name, int votes)
 {
 	struct cman_handle *h = (struct cman_handle *)handle;
 	char buf[strlen(name)+1 + sizeof(int)];
 	VALIDATE_HANDLE(h);
 
-	if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN)
+	if ((!name) || (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN) || (votes < 0))
 	{
 		errno = EINVAL;
 		return -1;
@@ -1022,7 +1024,12 @@ int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
 
 	memcpy(buf, &votes, sizeof(int));
 	strcpy(buf+sizeof(int), name);
-	return info_call(h, CMAN_CMD_REG_QUORUMDEV, buf, strlen(name)+1+sizeof(int), NULL, 0);
+	return info_call(h, ops, buf, strlen(name)+1+sizeof(int), NULL, 0);
+}
+
+int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
+{
+	return cman_set_quorum_device(handle, CMAN_CMD_REG_QUORUMDEV, name, votes);
 }
 
 int cman_unregister_quorum_device(cman_handle_t handle)
@@ -1058,6 +1065,11 @@ int cman_get_quorum_device(cman_handle_t handle, struct cman_qdev_info *info)
 	return ret;
 }
 
+int cman_update_quorum_device(cman_handle_t handle, char *name, int votes)
+{
+	return cman_set_quorum_device(handle, CMAN_CMD_UPDATE_QUORUMDEV, name, votes);
+}
+
 int cman_get_fenceinfo(cman_handle_t handle, int nodeid, uint64_t *time, int *fenced, char *agent)
 {
 	struct cman_handle *h = (struct cman_handle *)handle;
diff --git a/cman/lib/libcman.h b/cman/lib/libcman.h
index 857ba33..3069038 100644
--- a/cman/lib/libcman.h
+++ b/cman/lib/libcman.h
@@ -391,10 +391,14 @@ int cman_barrier_delete(cman_handle_t handle, const char *name);
  * After creating a quorum device you will need to call 'poll_quorum_device'
  * at least once every (default) 10 seconds (this can be changed in CCS)
  * otherwise it will time-out and the cluster will lose its vote.
+ *
+ * register_quorum and update_quorum arguments are mandatory.
+ * name has to be a valid null-terminated string and votes >= 0.
  */
 int cman_register_quorum_device(cman_handle_t handle, char *name, int votes);
 int cman_unregister_quorum_device(cman_handle_t handle);
 int cman_poll_quorum_device(cman_handle_t handle, int isavailable);
+int cman_update_quorum_device(cman_handle_t handle, char *name, int votes);
 
 /*
  * Sets the dirty bit inside cman. This indicates that the node has
diff --git a/cman/qdisk/main.c b/cman/qdisk/main.c
index 153b190..0d7bb3d 100644
--- a/cman/qdisk/main.c
+++ b/cman/qdisk/main.c
@@ -1670,24 +1670,31 @@ main(int argc, char **argv)
 
 	if (!_running)
 		goto out;
-	
-	cman_register_quorum_device(ctx.qc_ch,
+
+	if ((rv = cman_register_quorum_device(ctx.qc_ch,
 				    (ctx.qc_flags&RF_CMAN_LABEL)? 
 				        ctx.qc_cman_label:
                                         ctx.qc_device,
-				    ctx.qc_votes);
-	/*
-		XXX this always returns -1 / EBUSY even when it works?!!!
-		
-	if ((rv = cman_register_quorum_device(ctx.qc_ch, ctx.qc_device,
-					      ctx.qc_votes)) < 0) {
-		clulog_and_print(LOG_CRIT,
-				 "Could not register %s with CMAN; "
-				 "return = %d; error = %s\n",
-				 ctx.qc_device, rv, strerror(errno));
-		goto out;
+				    ctx.qc_votes)) < 0) {
+		if (errno == EBUSY) {
+			if ((rv = cman_update_quorum_device(ctx.qc_ch,
+				    (ctx.qc_flags&RF_CMAN_LABEL)?
+					ctx.qc_cman_label:
+					ctx.qc_device,
+				    ctx.qc_votes)) < 0) {
+				clulog_and_print(LOG_CRIT,
+					 "Could not update %s with CMAN; "
+					 "return = %d; error = %s\n",
+					 ctx.qc_device, rv, strerror(errno));
+			}
+		} else {
+			clulog_and_print(LOG_CRIT,
+					 "Could not register %s with CMAN; "
+					 "return = %d; error = %s\n",
+					 ctx.qc_device, rv, strerror(errno));
+			goto out;
+		}
 	}
-	*/
 
 	io_nanny_start(ctx.qc_tko * ctx.qc_interval);
 


More information about the cluster-commits mailing list