votequorum: add auto_tie_breaker support (default: off)

this flag (0|1) can be configured via quorum.auto_tie_breaker and when
enabled, support for perfect even split is on.

In case of a 50% of votes loss in one single transition, the partition
with the node that has the lowest node id will remain quorate.

Reviewed-by: Steven Dake <sdake@redhat.com>
Signed-off-by: Fabio M. Di Nitto <fdinitto@redhat.com>
This commit is contained in:
Fabio M. Di Nitto 2012-01-03 14:39:50 +01:00
parent e8d0af0bc8
commit b41372c6b2
2 changed files with 53 additions and 0 deletions

View File

@ -369,6 +369,7 @@ static int main_config_parser_cb(const char *path,
if ((strcmp(path, "quorum.disallowed") == 0) ||
(strcmp(path, "quorum.two_node") == 0) ||
(strcmp(path, "quorum.wait_for_all") == 0) ||
(strcmp(path, "quorum.auto_tie_breaker") == 0) ||
(strcmp(path, "quorum.quorate") == 0)) {
i = atoi(value);
icmap_set_uint8(path, i);

View File

@ -125,6 +125,8 @@ static int first_trans = 1;
static unsigned int quorumdev_poll = DEFAULT_QDEV_POLL;
static unsigned int leaving_timeout = DEFAULT_LEAVE_TMO;
static uint8_t wait_for_all = 0;
static uint8_t auto_tie_breaker = 0;
static int lowest_node_id = -1;
static struct cluster_node *us;
static struct cluster_node *quorum_device = NULL;
@ -387,6 +389,16 @@ static void votequorum_init(struct corosync_api_v1 *api,
set_quorum = report;
icmap_get_uint8("quorum.wait_for_all", &wait_for_all);
icmap_get_uint8("quorum.auto_tie_breaker", &auto_tie_breaker);
/*
* TODO: we need to know the lowest node-id in the cluster
* current lack of node list with node-id's requires us to see all nodes
* to determine which is the lowest.
*/
if (auto_tie_breaker) {
wait_for_all = 1;
}
/* Load the library-servicing part of this module */
api->service_link_and_init(api, "corosync_votequorum_iface", 0);
@ -606,6 +618,39 @@ static void send_expectedvotes_notification(void)
}
}
static void get_lowest_node_id(void)
{
struct cluster_node *node = NULL;
struct list_head *tmp;
lowest_node_id = us->node_id;
list_iterate(tmp, &cluster_members_list) {
node = list_entry(tmp, struct cluster_node, list);
if (node->node_id < lowest_node_id)
lowest_node_id = node->node_id;
}
log_printf(LOGSYS_LEVEL_DEBUG, "lowest node id: %d us: %d\n", lowest_node_id, us->node_id);
}
static int check_low_node_id_partition(void)
{
struct cluster_node *node = NULL;
struct list_head *tmp;
int found = 0;
list_iterate(tmp, &cluster_members_list) {
node = list_entry(tmp, struct cluster_node, list);
if (node->state == NODESTATE_MEMBER) {
if (node->node_id == lowest_node_id) {
found = 1;
}
}
}
return found;
}
static void set_quorate(int total_votes)
{
int quorate;
@ -626,6 +671,7 @@ static void set_quorate(int total_votes)
return;
}
wait_for_all = 0;
get_lowest_node_id();
}
if (quorum > total_votes) {
@ -635,6 +681,12 @@ static void set_quorate(int total_votes)
quorate = 1;
}
if ((auto_tie_breaker) &&
(total_votes == (us->expected_votes / 2)) &&
(check_low_node_id_partition() == 1)) {
quorate = 1;
}
if (cluster_is_quorate && !quorate)
log_printf(LOGSYS_LEVEL_INFO, "quorum lost, blocking activity\n");
if (!cluster_is_quorate && quorate)