38 #include <sys/types.h>
44 #include <qb/qblist.h>
45 #include <qb/qbipc_common.h>
75 static uint8_t qdevice_can_operate = 1;
76 static void *qdevice_reg_conn = NULL;
77 static uint8_t qdevice_master_wins = 0;
79 static uint8_t two_node = 0;
81 static uint8_t wait_for_all = 0;
82 static uint8_t wait_for_all_status = 0;
85 static int lowest_node_id = -1;
86 static int highest_node_id = -1;
88 #define DEFAULT_LMS_WIN 10000
89 static uint8_t last_man_standing = 0;
92 static uint8_t allow_downscale = 0;
93 static uint32_t ev_barrier = 0;
95 static uint8_t ev_tracking = 0;
96 static uint32_t ev_tracking_barrier = 0;
97 static int ev_tracking_fd = -1;
143 #define MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO 0
144 #define MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE 1
145 #define MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_REG 2
146 #define MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_RECONFIGURE 3
148 static void votequorum_exec_send_expectedvotes_notification(
void);
149 static int votequorum_exec_send_quorum_notification(
void *conn, uint64_t context);
150 static int votequorum_exec_send_nodelist_notification(
void *conn, uint64_t context);
152 #define VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES 1
153 #define VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES 2
154 #define VOTEQUORUM_RECONFIG_PARAM_CANCEL_WFA 3
156 static int votequorum_exec_send_reconfigure(uint8_t
param,
unsigned int nodeid, uint32_t
value);
161 #define VOTEQUORUM_QDEVICE_OPERATION_UNREGISTER 0
162 #define VOTEQUORUM_QDEVICE_OPERATION_REGISTER 1
168 #define NODE_FLAGS_QUORATE 1
169 #define NODE_FLAGS_LEAVING 2
170 #define NODE_FLAGS_WFASTATUS 4
171 #define NODE_FLAGS_FIRST 8
172 #define NODE_FLAGS_QDEVICE_REGISTERED 16
173 #define NODE_FLAGS_QDEVICE_ALIVE 32
174 #define NODE_FLAGS_QDEVICE_CAST_VOTE 64
175 #define NODE_FLAGS_QDEVICE_MASTER_WINS 128
196 static uint8_t quorum;
197 static uint8_t cluster_is_quorate;
204 static struct qb_list_head cluster_members_list;
208 static int quorum_members_entries = 0;
209 static int previous_quorum_members_entries = 0;
210 static int atb_nodelist_entries = 0;
217 static int cluster_nodes_entries = 0;
230 static struct qb_list_head trackers_list;
237 static int qdevice_timer_set = 0;
239 static int last_man_standing_timer_set = 0;
240 static int sync_nodeinfo_sent = 0;
241 static int sync_wait_for_poll_or_timeout = 0;
247 static int sync_in_progress = 0;
249 static void votequorum_sync_init (
250 const unsigned int *trans_list,
251 size_t trans_list_entries,
252 const unsigned int *member_list,
253 size_t member_list_entries,
256 static int votequorum_sync_process (
void);
257 static void votequorum_sync_activate (
void);
258 static void votequorum_sync_abort (
void);
267 static int votequorum_exec_exit_fn (
void);
268 static int votequorum_exec_send_nodeinfo(uint32_t
nodeid);
270 static void message_handler_req_exec_votequorum_nodeinfo (
273 static void exec_votequorum_nodeinfo_endian_convert (
void *message);
275 static void message_handler_req_exec_votequorum_reconfigure (
278 static void exec_votequorum_reconfigure_endian_convert (
void *message);
280 static void message_handler_req_exec_votequorum_qdevice_reg (
283 static void exec_votequorum_qdevice_reg_endian_convert (
void *message);
285 static void message_handler_req_exec_votequorum_qdevice_reconfigure (
288 static void exec_votequorum_qdevice_reconfigure_endian_convert (
void *message);
294 .exec_endian_convert_fn = exec_votequorum_nodeinfo_endian_convert
297 .exec_handler_fn = message_handler_req_exec_votequorum_reconfigure,
298 .exec_endian_convert_fn = exec_votequorum_reconfigure_endian_convert
301 .exec_handler_fn = message_handler_req_exec_votequorum_qdevice_reg,
302 .exec_endian_convert_fn = exec_votequorum_qdevice_reg_endian_convert
305 .exec_handler_fn = message_handler_req_exec_votequorum_qdevice_reconfigure,
306 .exec_endian_convert_fn = exec_votequorum_qdevice_reconfigure_endian_convert
314 static int quorum_lib_init_fn (
void *conn);
316 static int quorum_lib_exit_fn (
void *conn);
318 static void qdevice_timer_fn(
void *arg);
320 static void message_handler_req_lib_votequorum_getinfo (
void *conn,
321 const void *message);
323 static void message_handler_req_lib_votequorum_setexpected (
void *conn,
324 const void *message);
326 static void message_handler_req_lib_votequorum_setvotes (
void *conn,
327 const void *message);
329 static void message_handler_req_lib_votequorum_trackstart (
void *conn,
330 const void *message);
332 static void message_handler_req_lib_votequorum_trackstop (
void *conn,
333 const void *message);
335 static void message_handler_req_lib_votequorum_qdevice_register (
void *conn,
336 const void *message);
338 static void message_handler_req_lib_votequorum_qdevice_unregister (
void *conn,
339 const void *message);
341 static void message_handler_req_lib_votequorum_qdevice_update (
void *conn,
342 const void *message);
344 static void message_handler_req_lib_votequorum_qdevice_poll (
void *conn,
345 const void *message);
347 static void message_handler_req_lib_votequorum_qdevice_master_wins (
void *conn,
348 const void *message);
357 .lib_handler_fn = message_handler_req_lib_votequorum_setexpected,
361 .lib_handler_fn = message_handler_req_lib_votequorum_setvotes,
365 .lib_handler_fn = message_handler_req_lib_votequorum_trackstart,
369 .lib_handler_fn = message_handler_req_lib_votequorum_trackstop,
373 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_register,
377 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_unregister,
381 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_update,
385 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_poll,
389 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_master_wins,
395 .
name =
"corosync vote quorum service v1.0",
398 .private_data_size =
sizeof (
struct quorum_pd),
401 .lib_init_fn = quorum_lib_init_fn,
402 .lib_exit_fn = quorum_lib_exit_fn,
403 .lib_engine = quorum_lib_service,
405 .exec_init_fn = votequorum_exec_init_fn,
406 .exec_exit_fn = votequorum_exec_exit_fn,
407 .exec_engine = votequorum_exec_engine,
409 .sync_init = votequorum_sync_init,
410 .sync_process = votequorum_sync_process,
411 .sync_activate = votequorum_sync_activate,
412 .sync_abort = votequorum_sync_abort
417 return (&votequorum_service_engine);
422 .
name =
"corosync_votequorum",
432 #define max(a,b) (((a) > (b)) ? (a) : (b))
434 static void node_add_ordered(
struct cluster_node *newnode)
437 struct qb_list_head *tmp;
441 qb_list_for_each(tmp, &cluster_members_list) {
449 qb_list_add(&newnode->
list, &cluster_members_list);
451 qb_list_add_tail(&newnode->
list, &node->
list);
460 struct qb_list_head *tmp;
465 cl = (
struct cluster_node *)&cluster_nodes[cluster_nodes_entries];
466 cluster_nodes_entries++;
468 qb_list_for_each(tmp, &cluster_members_list) {
487 node_add_ordered(cl);
499 struct qb_list_head *tmp;
513 qb_list_for_each(tmp, &cluster_members_list) {
525 static void get_lowest_node_id(
void)
528 struct qb_list_head *tmp;
534 qb_list_for_each(tmp, &cluster_members_list) {
537 (node->
node_id < lowest_node_id)) {
538 lowest_node_id = node->
node_id;
547 static void get_highest_node_id(
void)
550 struct qb_list_head *tmp;
556 qb_list_for_each(tmp, &cluster_members_list) {
559 (node->
node_id > highest_node_id)) {
560 highest_node_id = node->
node_id;
569 static int check_low_node_id_partition(
void)
572 struct qb_list_head *tmp;
577 qb_list_for_each(tmp, &cluster_members_list) {
580 (node->
node_id == lowest_node_id)) {
589 static int check_high_node_id_partition(
void)
592 struct qb_list_head *tmp;
597 qb_list_for_each(tmp, &cluster_members_list) {
600 (node->
node_id == highest_node_id)) {
609 static int is_in_nodelist(
int nodeid,
unsigned int *members,
int entries)
614 for (i=0; i<entries; i++) {
615 if (
nodeid == members[i]) {
637 static int check_auto_tie_breaker(
void)
644 res = check_low_node_id_partition();
650 res = check_high_node_id_partition();
657 for (i=0; i < atb_nodelist_entries; i++) {
658 if (is_in_nodelist(atb_nodelist[i], quorum_members, quorum_members_entries)) {
665 for (j=0; j<i; j++) {
666 if (is_in_nodelist(atb_nodelist[j], previous_quorum_members, previous_quorum_members_entries)) {
693 static void parse_atb_string(
char *atb_string)
701 if (!strcmp(atb_string,
"lowest"))
704 if (!strcmp(atb_string,
"highest"))
707 if (atoi(atb_string)) {
709 atb_nodelist_entries = 0;
712 num = strtol(ptr, &ptr, 10);
715 atb_nodelist[atb_nodelist_entries++] = num;
719 if (atb_nodelist_entries) {
728 log_printf(
LOGSYS_LEVEL_WARNING,
"auto_tie_breaker_nodes is not valid. It must be 'lowest', 'highest' or a space-separated list of node IDs. auto_tie_breaker is disabled");
734 static int check_qdevice_master(
void)
737 struct qb_list_head *tmp;
742 qb_list_for_each(tmp, &cluster_members_list) {
755 static void decode_flags(uint32_t
flags)
760 "flags: quorate: %s Leaving: %s WFA Status: %s First: %s Qdevice: %s QdeviceAlive: %s QdeviceCastVote: %s QdeviceMasterWins: %s",
776 static int load_ev_tracking_barrier(
void)
779 char filename[PATH_MAX];
783 snprintf(filename,
sizeof(filename) - 1,
"%s/ev_tracking",
get_state_dir());
785 ev_tracking_fd = open(filename, O_RDWR, 0700);
786 if (ev_tracking_fd != -1) {
787 res = read (ev_tracking_fd, &ev_tracking_barrier,
sizeof(uint32_t));
788 close(ev_tracking_fd);
789 if (res ==
sizeof (uint32_t)) {
795 ev_tracking_barrier = 0;
797 ev_tracking_fd = open (filename, O_CREAT|O_RDWR, 0700);
798 if (ev_tracking_fd != -1) {
799 res = write (ev_tracking_fd, &ev_tracking_barrier,
sizeof (uint32_t));
800 if ((res == -1) || (res !=
sizeof (uint32_t))) {
802 "Unable to write to %s", filename);
804 close(ev_tracking_fd);
809 "Unable to create %s file", filename);
816 static void update_wait_for_all_status(uint8_t wfa_status)
820 wait_for_all_status = wfa_status;
821 if (wait_for_all_status) {
827 wait_for_all_status);
832 static void update_two_node(
void)
851 static void update_qdevice_can_operate(uint8_t status)
855 qdevice_can_operate = status;
856 icmap_set_uint8(
"runtime.votequorum.qdevice_can_operate", qdevice_can_operate);
861 static void update_qdevice_master_wins(uint8_t allow)
865 qdevice_master_wins = allow;
866 icmap_set_uint8(
"runtime.votequorum.qdevice_master_wins", qdevice_master_wins);
871 static void update_ev_tracking_barrier(uint32_t ev_t_barrier)
877 ev_tracking_barrier = ev_t_barrier;
878 icmap_set_uint32(
"runtime.votequorum.ev_tracking_barrier", ev_tracking_barrier);
880 if (lseek (ev_tracking_fd, 0, SEEK_SET) != 0) {
882 "Unable to update ev_tracking_barrier on disk data!!!");
887 res = write (ev_tracking_fd, &ev_tracking_barrier,
sizeof (uint32_t));
888 if (res !=
sizeof (uint32_t)) {
890 "Unable to update ev_tracking_barrier on disk data!!!");
892 #ifdef HAVE_FDATASYNC
893 fdatasync(ev_tracking_fd);
895 fsync(ev_tracking_fd);
905 static int calculate_quorum(
int allow_decrease,
unsigned int max_expected,
unsigned int *ret_total_votes)
907 struct qb_list_head *nodelist;
909 unsigned int total_votes = 0;
910 unsigned int highest_expected = 0;
911 unsigned int newquorum, q1, q2;
912 unsigned int total_nodes = 0;
916 if ((allow_downscale) && (allow_decrease) && (max_expected)) {
917 max_expected =
max(ev_barrier, max_expected);
920 qb_list_for_each(nodelist, &cluster_members_list) {
928 total_votes += node->
votes;
935 total_votes += qdevice->
votes;
939 if (max_expected > 0) {
940 highest_expected = max_expected;
947 q1 = (highest_expected + 2) / 2;
948 q2 = (total_votes + 2) / 2;
949 newquorum =
max(q1, q2);
955 if (!allow_decrease) {
956 newquorum =
max(quorum, newquorum);
966 if (two_node && total_nodes <= 2) {
970 if (ret_total_votes) {
971 *ret_total_votes = total_votes;
978 static void update_node_expected_votes(
int new_expected_votes)
980 struct qb_list_head *nodelist;
983 if (new_expected_votes) {
984 qb_list_for_each(nodelist, &cluster_members_list) {
994 static void are_we_quorate(
unsigned int total_votes)
997 int quorum_change = 0;
1005 if ((wait_for_all) && (wait_for_all_status)) {
1008 "Waiting for all cluster members. "
1009 "Current votes: %d expected_votes: %d",
1011 cluster_is_quorate = 0;
1014 update_wait_for_all_status(0);
1017 if (quorum > total_votes) {
1021 get_lowest_node_id();
1022 get_highest_node_id();
1025 if ((auto_tie_breaker !=
ATB_NONE) &&
1029 (previous_quorum_members_entries - quorum_members_entries < quorum) &&
1030 (check_auto_tie_breaker() == 1)) {
1034 if ((qdevice_master_wins) &&
1036 (check_qdevice_master() == 1)) {
1041 if (cluster_is_quorate && !
quorate) {
1045 if (!cluster_is_quorate &&
quorate) {
1051 if (cluster_is_quorate) {
1059 update_wait_for_all_status(0);
1061 update_wait_for_all_status(1);
1065 if ((quorum_change) &&
1066 (sync_in_progress == 0)) {
1067 quorum_callback(quorum_members, quorum_members_entries,
1068 cluster_is_quorate, &quorum_ringid);
1069 votequorum_exec_send_quorum_notification(NULL, 0L);
1075 static void get_total_votes(
unsigned int *totalvotes,
unsigned int *current_members)
1077 unsigned int total_votes = 0;
1078 unsigned int cluster_members = 0;
1079 struct qb_list_head *nodelist;
1084 qb_list_for_each(nodelist, &cluster_members_list) {
1088 total_votes += node->
votes;
1092 if (qdevice->
votes) {
1093 total_votes += qdevice->
votes;
1097 *totalvotes = total_votes;
1098 *current_members = cluster_members;
1106 static void recalculate_quorum(
int allow_decrease,
int by_current_nodes)
1108 unsigned int total_votes = 0;
1109 unsigned int cluster_members = 0;
1113 get_total_votes(&total_votes, &cluster_members);
1115 if (!by_current_nodes) {
1116 cluster_members = 0;
1125 votequorum_exec_send_expectedvotes_notification();
1128 if ((ev_tracking) &&
1133 quorum = calculate_quorum(allow_decrease, cluster_members, &total_votes);
1134 update_node_expected_votes(cluster_members);
1136 are_we_quorate(total_votes);
1145 static int votequorum_read_nodelist_configuration(uint32_t *
votes,
1150 const char *iter_key;
1152 uint32_t our_pos, node_pos, last_node_pos=-1;
1153 uint32_t nodecount = 0;
1154 uint32_t nodelist_expected_votes = 0;
1155 uint32_t node_votes = 0;
1162 "No nodelist defined or our node is not in the nodelist");
1170 res = sscanf(iter_key,
"nodelist.node.%u.%s", &node_pos, tmp_key);
1180 if (last_node_pos == node_pos) {
1183 last_node_pos = node_pos;
1192 nodelist_expected_votes = nodelist_expected_votes + node_votes;
1194 if (node_pos == our_pos) {
1195 *
votes = node_votes;
1209 static int votequorum_qdevice_is_configured(uint32_t *qdevice_votes)
1211 char *qdevice_model = NULL;
1217 if (strlen(qdevice_model)) {
1219 *qdevice_votes = -1;
1227 update_qdevice_can_operate(1);
1231 free(qdevice_model);
1239 #define VOTEQUORUM_READCONFIG_STARTUP 0
1240 #define VOTEQUORUM_READCONFIG_RUNTIME 1
1242 static char *votequorum_readconfig(
int runtime)
1244 uint32_t node_votes = 0, qdevice_votes = 0;
1246 uint32_t node_count = 0;
1248 int have_nodelist, have_qdevice;
1249 char *atb_string = NULL;
1267 auto_tie_breaker = initial_auto_tie_breaker;
1275 have_nodelist = votequorum_read_nodelist_configuration(&node_votes, &node_count, &node_expected_votes);
1276 have_qdevice = votequorum_qdevice_is_configured(&qdevice_votes);
1285 error = (
char *)
"configuration error: nodelist or quorum.expected_votes must be configured!";
1298 if ((two_node) && (have_qdevice)) {
1300 error = (
char *)
"configuration error: two_node and quorum device cannot be configured at the same time!";
1309 update_qdevice_can_operate(0);
1325 icmap_get_uint32(
"quorum.last_man_standing_window", &last_man_standing_window);
1339 "auto_tie_breaker_node: is meaningless if auto_tie_breaker is set to 0");
1343 if (atb && atb_string) {
1344 parse_atb_string(atb_string);
1347 initial_auto_tie_breaker = auto_tie_breaker;
1350 if (allow_downscale) {
1355 if (load_ev_tracking_barrier() < 0) {
1357 return ((
char *)
"Unable to load ev_tracking file!");
1359 update_ev_tracking_barrier(ev_tracking_barrier);
1367 if (two_node && auto_tie_breaker !=
ATB_NONE) {
1377 if ((auto_tie_breaker !=
ATB_NONE) && (node_expected_votes % 2) &&
1379 if (last_man_standing) {
1388 error = (
char *)
"configuration error: auto_tie_breaker & last_man_standing not available in odd sized cluster";
1407 if ((have_qdevice) && (last_man_standing)) {
1409 error = (
char *)
"configuration error: quorum.device is not compatible with last_man_standing";
1414 update_qdevice_can_operate(0);
1418 if ((have_qdevice) && (auto_tie_breaker !=
ATB_NONE)) {
1420 error = (
char *)
"configuration error: quorum.device is not compatible with auto_tie_breaker";
1425 update_qdevice_can_operate(0);
1429 if ((have_qdevice) && (allow_downscale)) {
1431 error = (
char *)
"configuration error: quorum.device is not compatible with allow_downscale";
1436 update_qdevice_can_operate(0);
1445 if ((
expected_votes) && (have_qdevice) && (qdevice_votes == -1)) {
1447 error = (
char *)
"configuration error: quorum.device.votes must be specified when quorum.expected_votes is set";
1452 update_qdevice_can_operate(0);
1461 if ((have_qdevice) &&
1462 (qdevice_votes == -1) &&
1464 (node_count != node_expected_votes)) {
1466 error = (
char *)
"configuration error: quorum.device.votes must be specified when not all nodes votes 1";
1471 update_qdevice_can_operate(0);
1483 error = (
char *)
"configuration error: quorum.device.votes is too high or expected_votes is too low";
1488 update_qdevice_can_operate(0);
1497 if ((have_qdevice) &&
1498 (qdevice_votes == -1) &&
1501 (node_count == node_expected_votes)) {
1502 qdevice_votes = node_expected_votes - 1;
1503 node_expected_votes = node_expected_votes + qdevice_votes;
1515 if (have_nodelist) {
1516 us->
votes = node_votes;
1531 if (!have_qdevice) {
1535 if (qdevice_votes != -1) {
1536 qdevice->
votes = qdevice_votes;
1542 update_wait_for_all_status(1);
1550 static void votequorum_refresh_config(
1552 const char *key_name,
1557 int old_votes, old_expected_votes;
1567 if (
icmap_get_uint8(
"config.totemconfig_reload_in_progress", &reloading) ==
CS_OK && reloading) {
1572 if (strcmp(key_name,
"quorum.cancel_wait_for_all") == 0 &&
1582 old_votes = us->
votes;
1593 votequorum_exec_send_nodeinfo(us->
node_id);
1595 if (us->
votes != old_votes) {
1611 static void votequorum_exec_add_config_notification(
void)
1621 votequorum_refresh_config,
1623 &icmap_track_nodelist);
1627 votequorum_refresh_config,
1629 &icmap_track_quorum);
1633 votequorum_refresh_config,
1635 &icmap_track_reload);
1644 static int votequorum_exec_send_reconfigure(uint8_t
param,
unsigned int nodeid, uint32_t
value)
1647 struct iovec iov[1];
1671 static int votequorum_exec_send_nodeinfo(uint32_t
nodeid)
1674 struct iovec iov[1];
1680 node = find_node_by_nodeid(
nodeid);
1690 decode_flags(node->
flags);
1705 static int votequorum_exec_send_qdevice_reconfigure(
const char *
oldname,
const char *
newname)
1708 struct iovec iov[1];
1727 static int votequorum_exec_send_qdevice_reg(uint32_t
operation,
const char *qdevice_name_req)
1730 struct iovec iov[1];
1749 static int votequorum_exec_send_quorum_notification(
void *conn, uint64_t context)
1752 struct qb_list_head *tmp;
1755 int cluster_members = 0;
1763 qb_list_for_each(tmp, &cluster_members_list) {
1774 res_lib_votequorum_notification->quorate = cluster_is_quorate;
1775 res_lib_votequorum_notification->context = context;
1776 res_lib_votequorum_notification->node_list_entries = cluster_members;
1778 res_lib_votequorum_notification->header.size = size;
1779 res_lib_votequorum_notification->header.error =
CS_OK;
1782 qb_list_for_each(tmp, &cluster_members_list) {
1784 res_lib_votequorum_notification->node_list[i].nodeid = node->
node_id;
1785 res_lib_votequorum_notification->node_list[i++].state = node->
state;
1789 res_lib_votequorum_notification->node_list[i++].state = qdevice->
state;
1800 qb_list_for_each(tmp, &trackers_list) {
1812 static int votequorum_exec_send_nodelist_notification(
void *
conn, uint64_t context)
1817 struct qb_list_head *tmp;
1827 res_lib_votequorum_notification->node_list_entries = quorum_members_entries;
1828 res_lib_votequorum_notification->ring_id.nodeid = quorum_ringid.
nodeid;
1829 res_lib_votequorum_notification->ring_id.seq = quorum_ringid.
seq;
1830 res_lib_votequorum_notification->context = context;
1832 for (i=0; i<quorum_members_entries; i++) {
1833 res_lib_votequorum_notification->node_list[i] = quorum_members[i];
1837 res_lib_votequorum_notification->header.size = size;
1838 res_lib_votequorum_notification->header.error =
CS_OK;
1848 qb_list_for_each(tmp, &trackers_list) {
1860 static void votequorum_exec_send_expectedvotes_notification(
void)
1864 struct qb_list_head *tmp;
1875 qb_list_for_each(tmp, &trackers_list) {
1876 qpd = qb_list_entry(tmp,
struct quorum_pd, list);
1885 static void exec_votequorum_qdevice_reconfigure_endian_convert (
void *message)
1892 static void message_handler_req_exec_votequorum_qdevice_reconfigure (
1893 const void *message,
1919 static void exec_votequorum_qdevice_reg_endian_convert (
void *message)
1930 static void message_handler_req_exec_votequorum_qdevice_reg (
1931 const void *message,
1936 int wipe_qdevice_name = 1;
1938 struct qb_list_head *tmp;
1951 if (!strlen(qdevice_name)) {
1972 if (!qdevice_reg_conn) {
1981 if (!strlen(qdevice_name)) {
1992 votequorum_exec_send_nodeinfo(us->
node_id);
1995 "A new qdevice with different name (new: %s old: %s) is trying to register!",
2004 qdevice_reg_conn = NULL;
2007 qb_list_for_each(tmp, &cluster_members_list) {
2011 wipe_qdevice_name = 0;
2015 if (wipe_qdevice_name) {
2024 static void exec_votequorum_nodeinfo_endian_convert (
void *message)
2038 static void message_handler_req_exec_votequorum_nodeinfo (
2039 const void *message,
2040 unsigned int sender_nodeid)
2049 int allow_downgrade = 0;
2066 node = find_node_by_nodeid(
nodeid);
2068 node = allocate_node(
nodeid);
2083 old_votes = node->
votes;
2085 old_state = node->
state;
2086 old_flags = node->
flags;
2090 struct cluster_node *sender_node = find_node_by_nodeid(sender_nodeid);
2092 assert(sender_node != NULL);
2094 if ((!cluster_is_quorate) &&
2110 allow_downgrade = 1;
2114 if ((!cluster_is_quorate) &&
2116 allow_downgrade = 1;
2126 if ((last_man_standing) && (node->
votes > 1)) {
2128 "cluster nodes votes are set to 1. Disabling LMS.");
2129 last_man_standing = 0;
2130 if (last_man_standing_timer_set) {
2132 last_man_standing_timer_set = 0;
2140 (old_votes != node->
votes) ||
2142 (old_flags != node->
flags) ||
2143 (old_state != node->
state)) {
2144 recalculate_quorum(allow_downgrade, by_node);
2147 if ((wait_for_all) &&
2150 update_wait_for_all_status(0);
2156 static void exec_votequorum_reconfigure_endian_convert (
void *message)
2168 static void message_handler_req_exec_votequorum_reconfigure (
2169 const void *message,
2184 votequorum_exec_send_expectedvotes_notification();
2189 recalculate_quorum(1, 0);
2199 recalculate_quorum(1, 0);
2203 update_wait_for_all_status(0);
2206 recalculate_quorum(0, 0);
2215 static int votequorum_exec_exit_fn (
void)
2225 if (allow_downscale) {
2227 ret = votequorum_exec_send_nodeinfo(us->
node_id);
2230 if ((ev_tracking) && (ev_tracking_fd != -1)) {
2231 close(ev_tracking_fd);
2239 static void votequorum_set_icmap_ro_keys(
void)
2259 qb_list_init(&cluster_members_list);
2260 qb_list_init(&trackers_list);
2263 memset(cluster_nodes, 0,
sizeof(cluster_nodes));
2271 return ((
char *)
"Could not allocate node.");
2282 return ((
char *)
"Could not allocate node.");
2295 recalculate_quorum(0, 0);
2300 votequorum_set_icmap_ro_keys();
2305 votequorum_exec_add_config_notification();
2310 votequorum_exec_send_nodeinfo(us->
node_id);
2321 static void votequorum_last_man_standing_timer_fn(
void *arg)
2325 last_man_standing_timer_set = 0;
2326 if (cluster_is_quorate) {
2327 recalculate_quorum(1,1);
2333 static void votequorum_sync_init (
2334 const unsigned int *trans_list,
size_t trans_list_entries,
2335 const unsigned int *member_list,
size_t member_list_entries,
2345 sync_in_progress = 1;
2346 sync_nodeinfo_sent = 0;
2347 sync_wait_for_poll_or_timeout = 0;
2349 if (member_list_entries > 1) {
2359 for (i = 0; i < quorum_members_entries; i++) {
2361 for (j = 0; j < member_list_entries; j++) {
2362 if (quorum_members[i] == member_list[j]) {
2369 node = find_node_by_nodeid(quorum_members[i]);
2376 if (last_man_standing) {
2377 if (((member_list_entries >= quorum) && (left_nodes)) ||
2378 ((member_list_entries <= quorum) && (auto_tie_breaker !=
ATB_NONE) && (check_low_node_id_partition() == 1))) {
2379 if (last_man_standing_timer_set) {
2381 last_man_standing_timer_set = 0;
2383 corosync_api->
timer_add_duration((
unsigned long long)last_man_standing_window*1000000,
2384 NULL, votequorum_last_man_standing_timer_fn,
2385 &last_man_standing_timer);
2386 last_man_standing_timer_set = 1;
2390 memcpy(previous_quorum_members, quorum_members,
sizeof(
unsigned int) * quorum_members_entries);
2391 previous_quorum_members_entries = quorum_members_entries;
2393 memcpy(quorum_members, member_list,
sizeof(
unsigned int) * member_list_entries);
2394 quorum_members_entries = member_list_entries;
2401 if (qdevice_timer_set) {
2404 corosync_api->
timer_add_duration((
unsigned long long)qdevice_sync_timeout*1000000, qdevice,
2405 qdevice_timer_fn, &qdevice_timer);
2406 qdevice_timer_set = 1;
2407 sync_wait_for_poll_or_timeout = 1;
2410 qdevice_name, qdevice_sync_timeout);
2416 static int votequorum_sync_process (
void)
2418 if (!sync_nodeinfo_sent) {
2419 votequorum_exec_send_nodeinfo(us->
node_id);
2421 if (strlen(qdevice_name)) {
2425 votequorum_exec_send_nodelist_notification(NULL, 0LL);
2426 sync_nodeinfo_sent = 1;
2440 static void votequorum_sync_activate (
void)
2442 recalculate_quorum(0, 0);
2443 quorum_callback(quorum_members, quorum_members_entries,
2444 cluster_is_quorate, &quorum_ringid);
2445 votequorum_exec_send_quorum_notification(NULL, 0L);
2447 sync_in_progress = 0;
2450 static void votequorum_sync_abort (
void)
2462 if (q_set_quorate_fn == NULL) {
2463 return ((
char *)
"Quorate function not set");
2467 quorum_callback = q_set_quorate_fn;
2470 &votequorum_service[0]);
2484 static int quorum_lib_init_fn (
void *conn)
2490 qb_list_init (&pd->
list);
2497 static int quorum_lib_exit_fn (
void *
conn)
2517 static void qdevice_timer_fn(
void *arg)
2522 (!qdevice_timer_set)) {
2530 votequorum_exec_send_nodeinfo(us->
node_id);
2532 qdevice_timer_set = 0;
2533 sync_wait_for_poll_or_timeout = 0;
2542 static void message_handler_req_lib_votequorum_getinfo (
void *
conn,
const void *message)
2547 unsigned int highest_expected = 0;
2548 unsigned int total_votes = 0;
2560 node = find_node_by_nodeid(
nodeid);
2563 struct qb_list_head *nodelist;
2565 qb_list_for_each(nodelist, &cluster_members_list) {
2566 iternode = qb_list_entry(nodelist,
struct cluster_node, list);
2571 total_votes += iternode->
votes;
2576 total_votes += qdevice->
votes;
2579 switch(node->
state) {
2606 if (cluster_is_quorate) {
2612 if (last_man_standing) {
2615 if (auto_tie_breaker !=
ATB_NONE) {
2618 if (allow_downscale) {
2651 static void message_handler_req_lib_votequorum_setexpected (
void *conn,
const void *message)
2656 unsigned int newquorum;
2657 unsigned int total_votes;
2658 uint8_t allow_downscale_status = 0;
2662 allow_downscale_status = allow_downscale;
2663 allow_downscale = 0;
2669 allow_downscale = allow_downscale_status;
2670 if (newquorum < total_votes / 2 ||
2671 newquorum > total_votes) {
2691 static void message_handler_req_lib_votequorum_setvotes (
void *conn,
const void *message)
2696 unsigned int newquorum;
2697 unsigned int total_votes;
2698 unsigned int saved_votes;
2705 node = find_node_by_nodeid(
nodeid);
2714 saved_votes = node->
votes;
2717 newquorum = calculate_quorum(1, 0, &total_votes);
2719 if (newquorum < total_votes / 2 ||
2720 newquorum > total_votes) {
2721 node->
votes = saved_votes;
2740 static void message_handler_req_lib_votequorum_trackstart (
void *conn,
2741 const void *message)
2788 static void message_handler_req_lib_votequorum_trackstop (
void *
conn,
2789 const void *message)
2814 static void message_handler_req_lib_votequorum_qdevice_register (
void *
conn,
2815 const void *message)
2823 if (!qdevice_can_operate) {
2824 log_printf(
LOGSYS_LEVEL_INFO,
"Registration of quorum device is disabled by incorrect corosync.conf. See logs for more information");
2835 "A new qdevice with different name (new: %s old: %s) is trying to re-register!",
2841 if (qdevice_reg_conn != NULL) {
2843 "Registration request already in progress");
2847 qdevice_reg_conn = conn;
2851 "Unable to send qdevice registration request to cluster");
2853 qdevice_reg_conn = NULL;
2870 static void message_handler_req_lib_votequorum_qdevice_unregister (
void *conn,
2871 const void *message)
2884 if (qdevice_timer_set) {
2886 qdevice_timer_set = 0;
2887 sync_wait_for_poll_or_timeout = 0;
2893 votequorum_exec_send_nodeinfo(us->
node_id);
2909 static void message_handler_req_lib_votequorum_qdevice_update (
void *conn,
2910 const void *message)
2938 static void message_handler_req_lib_votequorum_qdevice_poll (
void *conn,
2939 const void *message)
2948 if (!qdevice_can_operate) {
2957 "ring id (%u.%"PRIu64
"). Ignoring poll call.",
2959 quorum_ringid.
nodeid, quorum_ringid.
seq);
2968 if (qdevice_timer_set) {
2970 qdevice_timer_set = 0;
2973 oldflags = us->
flags;
2983 if (us->
flags != oldflags) {
2984 votequorum_exec_send_nodeinfo(us->
node_id);
2987 corosync_api->
timer_add_duration((
unsigned long long)qdevice_timeout*1000000, qdevice,
2988 qdevice_timer_fn, &qdevice_timer);
2989 qdevice_timer_set = 1;
2990 sync_wait_for_poll_or_timeout = 0;
3004 static void message_handler_req_lib_votequorum_qdevice_master_wins (
void *conn,
3005 const void *message)
3010 uint32_t oldflags = us->
flags;
3014 if (!qdevice_can_operate) {
3031 if (us->
flags != oldflags) {
3032 votequorum_exec_send_nodeinfo(us->
node_id);