Просмотр исходного кода

qdevice: 2nodelms: don't split-brain when the primary node comes back.

Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
Christine Caulfield 10 лет назад
Родитель
Сommit
9e2fb2492b
1 измененных файлов с 34 добавлено и 2 удалено
  1. 34 2
      qdevices/qnetd-algo-2nodelms.c

+ 34 - 2
qdevices/qnetd-algo-2nodelms.c

@@ -61,6 +61,16 @@ struct qnetd_algo_2nodelms_info {
 	struct tlv_ring_id ring_id;
 };
 
+static int rings_eq(const struct tlv_ring_id *ring_id1, const struct tlv_ring_id *ring_id2)
+{
+	if (ring_id1->node_id == ring_id2->node_id &&
+	    ring_id1->seq == ring_id2->seq) {
+		return 1;
+	}
+	else {
+		return 0;
+	}
+}
 
 enum tlv_reply_error_code
 qnetd_algo_2nodelms_client_init(struct qnetd_client *client)
@@ -72,7 +82,7 @@ qnetd_algo_2nodelms_client_init(struct qnetd_client *client)
 		return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
 	}
 	client->algorithm_data = info;
-	info->last_result = TLV_VOTE_ASK_LATER;
+	info->last_result = 0;
 	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
 }
 
@@ -145,6 +155,23 @@ qnetd_algo_2nodelms_membership_node_list_received(struct qnetd_client *client,
 	/* Save this now */
 	memcpy(&info->ring_id, ring_id, sizeof(*ring_id));
 
+	/* If we're a newcomer and there is another active partition, then we must NACK
+	 * to avoid quorum moving to us from already active nodes.
+	 */
+	if (info->last_result == 0) {
+		TAILQ_FOREACH(other_client, &client->cluster->client_list, cluster_entries) {
+			struct qnetd_algo_2nodelms_info *other_info = other_client->algorithm_data;
+			if (!rings_eq(&info->ring_id, &other_info->ring_id) &&
+			    other_info->last_result == TLV_VOTE_ACK) {
+
+				/* Don't save NACK, we need to know subsequently if we haven't been voting */
+				*result_vote = TLV_VOTE_NACK;
+				qnetd_log(LOG_DEBUG, "algo-2nodelms: we are a new partition and another active partition exists. NACK");
+				return (TLV_REPLY_ERROR_CODE_NO_ERROR);
+			}
+		}
+	}
+
 	/* If both nodes are present, then we're OK. return a vote */
 	TAILQ_FOREACH(node_info, nodes, entries) {
 		if (node_info->node_state == TLV_NODE_STATE_MEMBER) {
@@ -231,7 +258,12 @@ qnetd_algo_2nodelms_ask_for_vote_received(struct qnetd_client *client, uint32_t
 	qnetd_log(LOG_INFO, "algo-2nodelms: Client %p (cluster %s, node_id %"PRIx32") "
 	    "asked for a vote", client, client->cluster_name, client->node_id);
 
-	*result_vote =	info->last_result;
+	if (info->last_result == 0) {
+		*result_vote =	TLV_VOTE_ASK_LATER;
+	}
+	else {
+		*result_vote =	info->last_result;
+	}
 
 	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
 }