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@xxxxxxxxxx>
---
exec/votequorum.c | 9 +++++++
include/corosync/ipc_votequorum.h | 9 +++++++
include/corosync/votequorum.h | 3 +-
lib/libvotequorum.verso | 2 +-
lib/votequorum.c | 4 ++-
man/votequorum_qdevice_poll.3.in | 5 +++-
test/testvotequorum2.c | 47 ++++++++++++++++++++++++++++++++++--
7 files changed, 72 insertions(+), 7 deletions(-)
diff --git a/exec/votequorum.c b/exec/votequorum.c
index 54b6fbe..dd5bea7 100644
--- a/exec/votequorum.c
+++ b/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;
diff --git a/include/corosync/ipc_votequorum.h b/include/corosync/ipc_votequorum.h
index 0fdcd8b..c06814f 100644
--- a/include/corosync/ipc_votequorum.h
+++ b/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
diff --git a/include/corosync/votequorum.h b/include/corosync/votequorum.h
index bba964b..ef5294a 100644
--- a/include/corosync/votequorum.h
+++ b/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
diff --git a/lib/libvotequorum.verso b/lib/libvotequorum.verso
index 09b254e..66ce77b 100644
--- a/lib/libvotequorum.verso
+++ b/lib/libvotequorum.verso
@@ -1 +1 @@
-6.0.0
+7.0.0
diff --git a/lib/votequorum.c b/lib/votequorum.c
index 20843cf..be4ef43 100644
--- a/lib/votequorum.c
+++ b/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);
diff --git a/man/votequorum_qdevice_poll.3.in b/man/votequorum_qdevice_poll.3.in
index 348b84d..b8299df 100644
--- a/man/votequorum_qdevice_poll.3.in
+++ b/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
diff --git a/test/testvotequorum2.c b/test/testvotequorum2.c
index 3e4bd34..f545070 100644
--- a/test/testvotequorum2.c
+++ b/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);
}