summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ctdb/include/ctdb_private.h3
-rw-r--r--ctdb/include/ctdb_protocol.h2
-rw-r--r--ctdb/protocol/protocol.h6
-rw-r--r--ctdb/server/ctdb_keepalive.c57
-rw-r--r--ctdb/server/ctdb_server.c1
5 files changed, 69 insertions, 0 deletions
diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h
index 7d16c425881..6c7dd7941b7 100644
--- a/ctdb/include/ctdb_private.h
+++ b/ctdb/include/ctdb_private.h
@@ -634,6 +634,9 @@ bool ctdb_db_all_frozen(struct ctdb_context *ctdb);
void ctdb_start_keepalive(struct ctdb_context *ctdb);
void ctdb_stop_keepalive(struct ctdb_context *ctdb);
+void ctdb_request_keepalive(struct ctdb_context *ctdb,
+ struct ctdb_req_header *hdr);
+
/* from server/ctdb_lock.c */
struct lock_request;
diff --git a/ctdb/include/ctdb_protocol.h b/ctdb/include/ctdb_protocol.h
index 2fb3b6d0dca..52ecc456947 100644
--- a/ctdb/include/ctdb_protocol.h
+++ b/ctdb/include/ctdb_protocol.h
@@ -130,6 +130,8 @@ struct ctdb_reply_control_old {
struct ctdb_req_keepalive_old {
struct ctdb_req_header hdr;
+ uint32_t version;
+ uint32_t uptime;
};
/*
diff --git a/ctdb/protocol/protocol.h b/ctdb/protocol/protocol.h
index 7b5a5983be1..13231536917 100644
--- a/ctdb/protocol/protocol.h
+++ b/ctdb/protocol/protocol.h
@@ -979,6 +979,12 @@ struct ctdb_req_message_data {
TDB_DATA data;
};
+struct ctdb_req_keepalive {
+ uint32_t version;
+ uint32_t uptime;
+};
+
+
/* This is equivalent to server_id */
struct ctdb_server_id {
uint64_t pid;
diff --git a/ctdb/server/ctdb_keepalive.c b/ctdb/server/ctdb_keepalive.c
index 5562bffd8ba..1a8f0f4f76e 100644
--- a/ctdb/server/ctdb_keepalive.c
+++ b/ctdb/server/ctdb_keepalive.c
@@ -31,11 +31,24 @@
#include "lib/util/samba_util.h"
#include "ctdb_private.h"
+#include "version.h"
#include "common/common.h"
#include "common/logging.h"
+static uint32_t keepalive_version(void)
+{
+ return (SAMBA_VERSION_MAJOR << 16) | SAMBA_VERSION_MINOR;
+}
+
+static uint32_t keepalive_uptime(struct ctdb_context *ctdb)
+{
+ struct timeval current = tevent_timeval_current();
+
+ return current.tv_sec - ctdb->ctdbd_start_time.tv_sec;
+}
+
/*
send a keepalive packet to the other node
*/
@@ -56,6 +69,9 @@ static void ctdb_send_keepalive(struct ctdb_context *ctdb, uint32_t destnode)
r->hdr.destnode = destnode;
r->hdr.reqid = 0;
+ r->version = keepalive_version();
+ r->uptime = keepalive_uptime(ctdb);
+
CTDB_INCREMENT_STAT(ctdb, keepalive_packets_sent);
ctdb_queue_packet(ctdb, &r->hdr);
@@ -145,3 +161,44 @@ void ctdb_stop_keepalive(struct ctdb_context *ctdb)
ctdb->keepalive_ctx = NULL;
}
+void ctdb_request_keepalive(struct ctdb_context *ctdb,
+ struct ctdb_req_header *hdr)
+{
+ struct ctdb_req_keepalive_old *c =
+ (struct ctdb_req_keepalive_old *)hdr;
+ uint32_t my_version = keepalive_version();
+ uint32_t my_uptime = keepalive_uptime(ctdb);
+
+ if (hdr->length == sizeof(struct ctdb_req_header)) {
+ /* Old keepalive */
+ goto fail1;
+ }
+
+ if (c->version != my_version) {
+ if (c->uptime > my_uptime) {
+ goto fail2;
+ } else if (c->uptime == my_uptime) {
+ if (c->version > my_version) {
+ goto fail2;
+ }
+ }
+ }
+
+ return;
+
+fail1:
+ DEBUG(DEBUG_ERR,
+ ("Keepalive version missing from node %u\n", hdr->srcnode));
+ goto shutdown;
+
+fail2:
+ DEBUG(DEBUG_ERR,
+ ("Keepalive version mismatch 0x%08x != 0x%08x from node %u\n",
+ my_version, c->version, hdr->srcnode));
+ goto shutdown;
+
+shutdown:
+ DEBUG(DEBUG_ERR,
+ ("CTDB Cluster with mixed versions, cannot continue\n"));
+ ctdb_shutdown_sequence(ctdb, 0);
+}
diff --git a/ctdb/server/ctdb_server.c b/ctdb/server/ctdb_server.c
index 1712e39013c..c3d38c4b9da 100644
--- a/ctdb/server/ctdb_server.c
+++ b/ctdb/server/ctdb_server.c
@@ -265,6 +265,7 @@ void ctdb_input_pkt(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
case CTDB_REQ_KEEPALIVE:
CTDB_INCREMENT_STAT(ctdb, keepalive_packets_recv);
+ ctdb_request_keepalive(ctdb, hdr);
break;
default: