Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 1a810eac13bb49f85e0e3c5a17e05d06ba6a5037
Parent: 0b79766fc2af6b7815a7a3620027f48550728ea8
Author: Fabio M. Di Nitto <fdinitto(a)redhat.com>
AuthorDate: Wed Sep 7 14:26:06 2011 +0200
Committer: Fabio M. Di Nitto <fdinitto(a)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(a)redhat.com>
Acked-by: Christine Caulfield <ccaulfie(a)redhat.com>
Signed-off-by: Fabio M. Di Nitto <fdinitto(a)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);