Ver Fonte

votequorum: Add ring id to poll call

If votequorum service receives incorrect (not current) ringid, call is
ignored and CS_ERR_MESSAGE_ERROR is returned.

This and previous commits makes incompatible changes in votequorum
API/ABI, so library version is increased.

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
Jan Friesse há 11 anos atrás
pai
commit
b8902464d1

+ 9 - 0
exec/votequorum.c

@@ -2741,6 +2741,15 @@ static void message_handler_req_lib_votequorum_qdevice_poll (void *conn,
 	}
 
 	if (us->flags & NODE_FLAGS_QDEVICE_REGISTERED) {
+		if (!(req_lib_votequorum_qdevice_poll->ring_id.nodeid == quorum_ringid.rep.nodeid &&
+		      req_lib_votequorum_qdevice_poll->ring_id.seq == quorum_ringid.seq)) {
+			log_printf(LOGSYS_LEVEL_DEBUG, "Received poll ring id (%u.%"PRIu64") != last sync "
+			    "ring id (%u.%"PRIu64"). Ignoring poll call.",
+			    req_lib_votequorum_qdevice_poll->ring_id.nodeid, req_lib_votequorum_qdevice_poll->ring_id.seq,
+			    quorum_ringid.rep.nodeid, quorum_ringid.seq);
+			error = CS_ERR_MESSAGE_ERROR;
+			goto out;
+		}
 		if (strncmp(req_lib_votequorum_qdevice_poll->name, qdevice_name, VOTEQUORUM_QDEVICE_MAX_NAME_LEN)) {
 			error = CS_ERR_INVALID_PARAM;
 			goto out;

+ 9 - 0
include/corosync/ipc_votequorum.h

@@ -86,6 +86,7 @@ struct req_lib_votequorum_qdevice_poll {
 	struct qb_ipc_request_header header __attribute__((aligned(8)));
 	char name[VOTEQUORUM_QDEVICE_MAX_NAME_LEN];
 	int cast_vote;
+	struct mar_votequorum_ring_id ring_id __attribute__((aligned(8)));
 };
 
 struct req_lib_votequorum_qdevice_master_wins {
@@ -181,4 +182,12 @@ static inline void marshall_from_mar_votequorum_ring_id (
 	dest->seq = src->seq;
 };
 
+static inline void marshall_to_mar_votequorum_ring_id (
+	struct mar_votequorum_ring_id *dest,
+	const votequorum_ring_id_t *src)
+{
+	dest->nodeid = src->nodeid;
+	dest->seq = src->seq;
+};
+
 #endif

+ 2 - 1
include/corosync/votequorum.h

@@ -211,7 +211,8 @@ cs_error_t votequorum_qdevice_update (
 cs_error_t votequorum_qdevice_poll (
 	votequorum_handle_t handle,
 	const char *name,
-	unsigned int cast_vote);
+	unsigned int cast_vote,
+	votequorum_ring_id_t ring_id);
 
 /**
  * Allow qdevice to tell votequorum if master_wins can be enabled or not

+ 1 - 1
lib/libvotequorum.verso

@@ -1 +1 @@
-6.0.0
+7.0.0

+ 3 - 1
lib/votequorum.c

@@ -607,7 +607,8 @@ error_exit:
 cs_error_t votequorum_qdevice_poll (
 	votequorum_handle_t handle,
 	const char *name,
-	unsigned int cast_vote)
+	unsigned int cast_vote,
+	votequorum_ring_id_t ring_id)
 {
 	cs_error_t error;
 	struct votequorum_inst *votequorum_inst;
@@ -629,6 +630,7 @@ cs_error_t votequorum_qdevice_poll (
 	req_lib_votequorum_qdevice_poll.header.id = MESSAGE_REQ_VOTEQUORUM_QDEVICE_POLL;
 	strcpy(req_lib_votequorum_qdevice_poll.name, name);
 	req_lib_votequorum_qdevice_poll.cast_vote = cast_vote;
+	marshall_to_mar_votequorum_ring_id(&req_lib_votequorum_qdevice_poll.ring_id, &ring_id);
 
 	iov.iov_base = (char *)&req_lib_votequorum_qdevice_poll;
 	iov.iov_len = sizeof (struct req_lib_votequorum_qdevice_poll);

+ 4 - 1
man/votequorum_qdevice_poll.3.in

@@ -37,7 +37,7 @@ votequorum_qdevice_poll \- Tells votequorum the result of the quorum device poll
 .SH SYNOPSIS
 .B #include <corosync/votequorum.h>
 .sp
-.BI "int votequorum_qdevice_poll(votequorum_handle_t " handle ", const char * " name ", unsigned int " cast_vote ");"
+.BI "int votequorum_qdevice_poll(votequorum_handle_t " handle ", const char * " name ", unsigned int " cast_vote ", votequorum_ring_id_t " ring_id ");"
 .SH DESCRIPTION
 The
 .B votequorum_qdevice_poll
@@ -45,6 +45,9 @@ is called by the quorum device subsystem (not provided as part of votequorum) to
 the voting system if the quorum device is present/active or not. If
 .B cast_vote
 is 1 then the votes for the device are included in the quorum calculation, otherwise not.
+Current
+.B ring_id
+must be set (one get in votequorum_notification_fn callback) otherwise poll is ignored.
 This routine should be called at regular intervals to ensure that the device status
 is always known to votequorum. If
 .B votequorum_qdevice_poll

+ 44 - 3
test/testvotequorum2.c

@@ -35,6 +35,7 @@
 #include <config.h>
 
 #include <sys/types.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <string.h>
@@ -45,6 +46,8 @@
 
 static votequorum_handle_t handle;
 
+static votequorum_ring_id_t last_received_ring_id;
+
 static int print_info(int ok_to_fail)
 {
 	struct votequorum_info info;
@@ -71,6 +74,22 @@ static int print_info(int ok_to_fail)
 	return 0;
 }
 
+static void votequorum_notification_fn(
+	votequorum_handle_t vq_handle,
+	uint64_t context,
+	uint32_t quorate,
+	votequorum_ring_id_t ring_id,
+	uint32_t node_list_entries,
+	votequorum_node_t node_list[])
+{
+
+	printf("votequorum notification called \n");
+	printf("  current ringid  = (%u.%"PRIu64")\n", ring_id.nodeid, ring_id.seq);
+	printf("\n");
+
+	memcpy(&last_received_ring_id, &ring_id, sizeof(ring_id));
+}
+
 static void usage(const char *command)
 {
   printf("%s [-p <num>] [-t <time>] [-n <name>] [-c] [-m]\n", command);
@@ -90,9 +109,13 @@ int main(int argc, char *argv[])
 	int pollcount=0, polltime=1, quiet=0, once=0;
 	int err;
 	int opt;
+	votequorum_callbacks_t callbacks;
 	const char *devicename = "QDEVICE";
 	const char *options = "n:p:t:cmq1h";
-	
+
+	memset(&callbacks, 0, sizeof(callbacks));
+	callbacks.votequorum_notify_fn = votequorum_notification_fn;
+
 	while ((opt = getopt(argc, argv, options)) != -1) {
 		switch (opt) {
 		case 'm':
@@ -122,7 +145,7 @@ int main(int argc, char *argv[])
 		}
 	}
 
-	if ( (err=votequorum_initialize(&handle, NULL)) != CS_OK) {
+	if ( (err=votequorum_initialize(&handle, &callbacks)) != CS_OK) {
 		fprintf(stderr, "votequorum_initialize FAILED: %d\n", err);
 		return -1;
 	}
@@ -141,6 +164,12 @@ int main(int argc, char *argv[])
 	}
 
 	if (argc >= 2) {
+		if ( (err = votequorum_trackstart(handle, handle, CS_TRACK_CHANGES)) != CS_OK) {
+			fprintf(stderr, "votequorum_trackstart FAILED: %d\n", err);
+			ret = -1;
+			goto out;
+		}
+
 		if ( (err=votequorum_qdevice_register(handle, devicename)) != CS_OK) {
 			fprintf(stderr, "qdevice_register FAILED: %d\n", err);
 			ret = -1;
@@ -153,13 +182,25 @@ int main(int argc, char *argv[])
 			goto out;
 		}
 
+
 		while (--pollcount) {
+			if (votequorum_dispatch(handle, CS_DISPATCH_ALL) != CS_OK) {
+				fprintf(stderr, "votequorum_dispatch error\n");
+                                ret = -1;
+                                goto out;
+                        }
+
 		        if (!quiet) print_info(0);
-			if ((err=votequorum_qdevice_poll(handle, devicename, cast_vote)) != CS_OK) {
+			if ((err=votequorum_qdevice_poll(handle, devicename, cast_vote, last_received_ring_id)) != CS_OK &&
+			     err != CS_ERR_MESSAGE_ERROR) {
 				fprintf(stderr, "qdevice poll FAILED: %d\n", err);
 				ret = -1;
 				goto out;
 			}
+			if (err == CS_ERR_MESSAGE_ERROR) {
+				fprintf(stderr, "qdevice poll passed OLD ring_id\n");
+			}
+
 			if (!quiet) print_info(0);
 			sleep(polltime);
 		}