From b0c850f308d44ddcdf1a1f881c1e1142ad489385 Mon Sep 17 00:00:00 2001 From: Jan Friesse Date: Tue, 30 Aug 2016 16:57:31 +0200 Subject: [PATCH] Qnetd LMS: Fix two partition use case Solves situation when in 2 node cluster tie-breaker node dies. Because code contains two bugs, other node got NACK instead of ACK. - Algo timer is not stack, so calling abort and schedule in timer callback without setting reschedule is noop. - It's needed to check not only what current node thinks about membership, but also what other nodes thinks. If views diverge -> wait. Thanks Christine Caulfield for fixing the English in the comments somewhat. Signed-off-by: Jan Friesse Reviewed-by: Christine Caulfield --- qdevices/qnetd-algo-lms.c | 12 ++++++++++++ qdevices/qnetd-algo-utils.c | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 0 deletions(-) diff --git a/qdevices/qnetd-algo-lms.c b/qdevices/qnetd-algo-lms.c index 55a1bb2..cdd86c4 100644 --- a/qdevices/qnetd-algo-lms.c +++ b/qdevices/qnetd-algo-lms.c @@ -361,6 +361,18 @@ qnetd_algo_lms_timer_callback(struct qnetd_client *client, int *reschedule_timer (*result_vote == TLV_VOTE_ACK || *result_vote == TLV_VOTE_NACK)) { *send_vote = 1; } + + if (ret == TLV_REPLY_ERROR_CODE_NO_ERROR && + *result_vote == TLV_VOTE_WAIT_FOR_REPLY) { + /* + * Reschedule was called in the do_lms_algorithm but algo_timer is + * not stack based so there can only be one. So if do_lms aborted + * the active timer, and scheduled it again the timer would be aborted + * if reschedule_timer was not set. + */ + *reschedule_timer = 1; + } + return ret; } diff --git a/qdevices/qnetd-algo-utils.c b/qdevices/qnetd-algo-utils.c index 440f81f..e26b40a 100644 --- a/qdevices/qnetd-algo-utils.c +++ b/qdevices/qnetd-algo-utils.c @@ -65,6 +65,19 @@ qnetd_algo_all_ring_ids_match(struct qnetd_client *client, const struct tlv_ring } } + if (in_our_partition == 0) { + /* + * Also try to look from the other side to see if we are + * not in the other node's membership list. + * Because if so it may mean the membership lists are not equal + */ + TAILQ_FOREACH(node_info, &other_client->last_membership_node_list, entries) { + if (node_info->node_id == client->node_id) { + in_our_partition = 1; + } + } + } + /* * If the other nodes on our side of a partition have a different ring ID then * we need to wait until they have all caught up before making a decision @@ -74,6 +87,7 @@ qnetd_algo_all_ring_ids_match(struct qnetd_client *client, const struct tlv_ring return (-1); /* ring IDs don't match */ } } + return (0); } -- 1.7.1