diff options
-rw-r--r-- | ctdb/include/ctdb_private.h | 3 | ||||
-rw-r--r-- | ctdb/include/ctdb_protocol.h | 2 | ||||
-rw-r--r-- | ctdb/protocol/protocol.h | 6 | ||||
-rw-r--r-- | ctdb/server/ctdb_keepalive.c | 57 | ||||
-rw-r--r-- | ctdb/server/ctdb_server.c | 1 |
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: |