38 #include <sys/types.h>
41 #include <qb/qbipc_common.h>
69 static uint8_t qdevice_can_operate = 1;
70 static void *qdevice_reg_conn = NULL;
71 static uint8_t qdevice_master_wins = 0;
73 static uint8_t two_node = 0;
75 static uint8_t wait_for_all = 0;
76 static uint8_t wait_for_all_status = 0;
78 static uint8_t auto_tie_breaker = 0;
79 static int lowest_node_id = -1;
81 #define DEFAULT_LMS_WIN 10000
82 static uint8_t last_man_standing = 0;
85 static uint8_t allow_downscale = 0;
86 static uint32_t ev_barrier = 0;
93 struct qb_ipc_request_header header __attribute__((aligned(8)));
117 struct qb_ipc_request_header header __attribute__((aligned(8)));
132 #define MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO 0
133 #define MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE 1
134 #define MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_REG 2
135 #define MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_RECONFIGURE 3
137 static void votequorum_exec_send_expectedvotes_notification(
void);
138 static int votequorum_exec_send_quorum_notification(
void *conn, uint64_t context);
140 #define VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES 1
141 #define VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES 2
143 static int votequorum_exec_send_reconfigure(uint8_t
param,
unsigned int nodeid, uint32_t
value);
148 #define VOTEQUORUM_QDEVICE_OPERATION_UNREGISTER 0
149 #define VOTEQUORUM_QDEVICE_OPERATION_REGISTER 1
155 #define NODE_FLAGS_QUORATE 1
156 #define NODE_FLAGS_LEAVING 2
157 #define NODE_FLAGS_WFASTATUS 4
158 #define NODE_FLAGS_FIRST 8
159 #define NODE_FLAGS_QDEVICE_REGISTERED 16
160 #define NODE_FLAGS_QDEVICE_ALIVE 32
161 #define NODE_FLAGS_QDEVICE_CAST_VOTE 64
162 #define NODE_FLAGS_QDEVICE_MASTER_WINS 128
183 static uint8_t quorum;
184 static uint8_t cluster_is_quorate;
191 static struct list_head cluster_members_list;
193 static int quorum_members_entries = 0;
200 static int cluster_nodes_entries = 0;
220 static int qdevice_timer_set = 0;
222 static int last_man_standing_timer_set = 0;
228 static int sync_in_progress = 0;
230 static void votequorum_sync_init (
231 const unsigned int *trans_list,
232 size_t trans_list_entries,
233 const unsigned int *member_list,
234 size_t member_list_entries,
237 static int votequorum_sync_process (
void);
238 static void votequorum_sync_activate (
void);
239 static void votequorum_sync_abort (
void);
248 static int votequorum_exec_exit_fn (
void);
249 static int votequorum_exec_send_nodeinfo(uint32_t
nodeid);
251 static void message_handler_req_exec_votequorum_nodeinfo (
254 static void exec_votequorum_nodeinfo_endian_convert (
void *message);
256 static void message_handler_req_exec_votequorum_reconfigure (
259 static void exec_votequorum_reconfigure_endian_convert (
void *message);
261 static void message_handler_req_exec_votequorum_qdevice_reg (
264 static void exec_votequorum_qdevice_reg_endian_convert (
void *message);
266 static void message_handler_req_exec_votequorum_qdevice_reconfigure (
269 static void exec_votequorum_qdevice_reconfigure_endian_convert (
void *message);
275 .exec_endian_convert_fn = exec_votequorum_nodeinfo_endian_convert
278 .exec_handler_fn = message_handler_req_exec_votequorum_reconfigure,
279 .exec_endian_convert_fn = exec_votequorum_reconfigure_endian_convert
282 .exec_handler_fn = message_handler_req_exec_votequorum_qdevice_reg,
283 .exec_endian_convert_fn = exec_votequorum_qdevice_reg_endian_convert
286 .exec_handler_fn = message_handler_req_exec_votequorum_qdevice_reconfigure,
287 .exec_endian_convert_fn = exec_votequorum_qdevice_reconfigure_endian_convert
295 static int quorum_lib_init_fn (
void *conn);
297 static int quorum_lib_exit_fn (
void *conn);
299 static void message_handler_req_lib_votequorum_getinfo (
void *conn,
300 const void *message);
302 static void message_handler_req_lib_votequorum_setexpected (
void *conn,
303 const void *message);
305 static void message_handler_req_lib_votequorum_setvotes (
void *conn,
306 const void *message);
308 static void message_handler_req_lib_votequorum_trackstart (
void *conn,
309 const void *message);
311 static void message_handler_req_lib_votequorum_trackstop (
void *conn,
312 const void *message);
314 static void message_handler_req_lib_votequorum_qdevice_register (
void *conn,
315 const void *message);
317 static void message_handler_req_lib_votequorum_qdevice_unregister (
void *conn,
318 const void *message);
320 static void message_handler_req_lib_votequorum_qdevice_update (
void *conn,
321 const void *message);
323 static void message_handler_req_lib_votequorum_qdevice_poll (
void *conn,
324 const void *message);
326 static void message_handler_req_lib_votequorum_qdevice_master_wins (
void *conn,
327 const void *message);
336 .lib_handler_fn = message_handler_req_lib_votequorum_setexpected,
340 .lib_handler_fn = message_handler_req_lib_votequorum_setvotes,
344 .lib_handler_fn = message_handler_req_lib_votequorum_trackstart,
348 .lib_handler_fn = message_handler_req_lib_votequorum_trackstop,
352 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_register,
356 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_unregister,
360 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_update,
364 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_poll,
368 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_master_wins,
374 .
name =
"corosync vote quorum service v1.0",
377 .private_data_size =
sizeof (
struct quorum_pd),
380 .lib_init_fn = quorum_lib_init_fn,
381 .lib_exit_fn = quorum_lib_exit_fn,
382 .lib_engine = quorum_lib_service,
384 .exec_init_fn = votequorum_exec_init_fn,
385 .exec_exit_fn = votequorum_exec_exit_fn,
386 .exec_engine = votequorum_exec_engine,
388 .sync_init = votequorum_sync_init,
389 .sync_process = votequorum_sync_process,
390 .sync_activate = votequorum_sync_activate,
391 .sync_abort = votequorum_sync_abort
396 return (&votequorum_service_engine);
401 .
name =
"corosync_votequorum",
411 #define max(a,b) (((a) > (b)) ? (a) : (b))
413 #define list_iterate(v, head) \
414 for (v = (head)->next; v != head; v = v->next)
416 static void node_add_ordered(
struct cluster_node *newnode)
432 list_add(&newnode->
list, &cluster_members_list);
451 cl = (
struct cluster_node *)&cluster_nodes[cluster_nodes_entries];
452 cluster_nodes_entries++;
473 node_add_ordered(cl);
482 static struct cluster_node *find_node_by_nodeid(
unsigned int nodeid)
511 static void get_lowest_node_id(
void)
523 (node->
node_id < lowest_node_id)) {
524 lowest_node_id = node->
node_id;
533 static int check_low_node_id_partition(
void)
544 (node->
node_id == lowest_node_id)) {
553 static int check_qdevice_master(
void)
574 static void decode_flags(uint32_t
flags)
579 "flags: quorate: %s Leaving: %s WFA Status: %s First: %s Qdevice: %s QdeviceAlive: %s QdeviceCastVote: %s QdeviceMasterWins: %s",
592 static void update_wait_for_all_status(uint8_t wfa_status)
596 wait_for_all_status = wfa_status;
597 if (wait_for_all_status) {
600 us->
flags &= ~NODE_FLAGS_WFASTATUS;
603 wait_for_all_status);
608 static void update_two_node(
void)
627 static void update_qdevice_can_operate(uint8_t status)
631 qdevice_can_operate = status;
632 icmap_set_uint8(
"runtime.votequorum.qdevice_can_operate", qdevice_can_operate);
637 static void update_qdevice_master_wins(uint8_t allow)
641 qdevice_master_wins = allow;
642 icmap_set_uint8(
"runtime.votequorum.qdevice_master_wins", qdevice_master_wins);
651 static int calculate_quorum(
int allow_decrease,
unsigned int max_expected,
unsigned int *ret_total_votes)
655 unsigned int total_votes = 0;
656 unsigned int highest_expected = 0;
657 unsigned int newquorum, q1, q2;
658 unsigned int total_nodes = 0;
662 if ((allow_downscale) && (allow_decrease) && (max_expected)) {
663 max_expected =
max(ev_barrier, max_expected);
678 total_votes += node->
votes;
685 total_votes += qdevice->
votes;
689 if (max_expected > 0) {
690 highest_expected = max_expected;
697 q1 = (highest_expected + 2) / 2;
698 q2 = (total_votes + 2) / 2;
699 newquorum =
max(q1, q2);
705 if (!allow_decrease) {
706 newquorum =
max(quorum, newquorum);
716 if (two_node && total_nodes <= 2) {
720 if (ret_total_votes) {
721 *ret_total_votes = total_votes;
728 static void are_we_quorate(
unsigned int total_votes)
731 int quorum_change = 0;
739 if ((wait_for_all) && (wait_for_all_status)) {
742 "Waiting for all cluster members. "
743 "Current votes: %d expected_votes: %d",
745 cluster_is_quorate = 0;
748 update_wait_for_all_status(0);
751 if (quorum > total_votes) {
755 get_lowest_node_id();
758 if ((auto_tie_breaker) &&
760 (check_low_node_id_partition() == 1)) {
764 if ((qdevice_master_wins) &&
766 (check_qdevice_master() == 1)) {
771 if (cluster_is_quorate && !quorate) {
775 if (!cluster_is_quorate && quorate) {
781 if (cluster_is_quorate) {
784 us->
flags &= ~NODE_FLAGS_QUORATE;
789 update_wait_for_all_status(0);
791 update_wait_for_all_status(1);
795 if ((quorum_change) &&
796 (sync_in_progress == 0)) {
797 quorum_callback(quorum_members, quorum_members_entries,
798 cluster_is_quorate, &quorum_ringid);
804 static void get_total_votes(
unsigned int *totalvotes,
unsigned int *current_members)
806 unsigned int total_votes = 0;
807 unsigned int cluster_members = 0;
817 total_votes += node->
votes;
821 if (qdevice->
votes) {
822 total_votes += qdevice->
votes;
826 *totalvotes = total_votes;
827 *current_members = cluster_members;
835 static void recalculate_quorum(
int allow_decrease,
int by_current_nodes)
837 unsigned int total_votes = 0;
838 unsigned int cluster_members = 0;
842 get_total_votes(&total_votes, &cluster_members);
844 if (!by_current_nodes) {
854 votequorum_exec_send_expectedvotes_notification();
857 quorum = calculate_quorum(allow_decrease, cluster_members, &total_votes);
858 are_we_quorate(total_votes);
860 votequorum_exec_send_quorum_notification(NULL, 0L);
869 static int votequorum_read_nodelist_configuration(uint32_t *
votes,
874 const char *iter_key;
876 uint32_t our_pos, node_pos;
877 uint32_t nodecount = 0;
878 uint32_t nodelist_expected_votes = 0;
879 uint32_t node_votes = 0;
886 "No nodelist defined or our node is not in the nodelist");
894 res = sscanf(iter_key,
"nodelist.node.%u.%s", &node_pos, tmp_key);
899 if (strcmp(tmp_key,
"ring0_addr") != 0) {
910 nodelist_expected_votes = nodelist_expected_votes + node_votes;
912 if (node_pos == our_pos) {
917 *expected_votes = nodelist_expected_votes;
927 static int votequorum_qdevice_is_configured(uint32_t *qdevice_votes)
929 char *qdevice_model = NULL;
935 if (strlen(qdevice_model)) {
942 update_qdevice_can_operate(1);
954 #define VOTEQUORUM_READCONFIG_STARTUP 0
955 #define VOTEQUORUM_READCONFIG_RUNTIME 1
957 static char *votequorum_readconfig(
int runtime)
959 uint32_t node_votes = 0, qdevice_votes = 0;
960 uint32_t node_expected_votes = 0, expected_votes = 0;
961 uint32_t node_count = 0;
962 int have_nodelist, have_qdevice;
973 have_nodelist = votequorum_read_nodelist_configuration(&node_votes, &node_count, &node_expected_votes);
974 have_qdevice = votequorum_qdevice_is_configured(&qdevice_votes);
981 if ((!have_nodelist) && (!expected_votes)) {
983 error = (
char *)
"configuration error: nodelist or quorum.expected_votes must be configured!";
996 if ((two_node) && (have_qdevice)) {
998 error = (
char *)
"configuration error: two_node and quorum device cannot be configured at the same time!";
1002 if (us->
flags & NODE_FLAGS_QDEVICE_REGISTERED) {
1007 update_qdevice_can_operate(0);
1024 icmap_get_uint32(
"quorum.last_man_standing_window", &last_man_standing_window);
1034 if ((have_qdevice) && (last_man_standing)) {
1036 error = (
char *)
"configuration error: quorum.device is not compatible with last_man_standing";
1041 update_qdevice_can_operate(0);
1045 if ((have_qdevice) && (auto_tie_breaker)) {
1047 error = (
char *)
"configuration error: quorum.device is not compatible with auto_tie_breaker";
1052 update_qdevice_can_operate(0);
1056 if ((have_qdevice) && (wait_for_all)) {
1058 error = (
char *)
"configuration error: quorum.device is not compatible with wait_for_all";
1063 update_qdevice_can_operate(0);
1067 if ((have_qdevice) && (allow_downscale)) {
1069 error = (
char *)
"configuration error: quorum.device is not compatible with allow_downscale";
1074 update_qdevice_can_operate(0);
1083 if ((expected_votes) && (have_qdevice) && (qdevice_votes == -1)) {
1085 error = (
char *)
"configuration error: quorum.device.votes must be specified when quorum.expected_votes is set";
1090 update_qdevice_can_operate(0);
1099 if ((have_qdevice) &&
1100 (qdevice_votes == -1) &&
1102 (node_count != node_expected_votes)) {
1104 error = (
char *)
"configuration error: quorum.device.votes must be specified when not all nodes votes 1";
1109 update_qdevice_can_operate(0);
1117 if ((qdevice_votes > 0) && (expected_votes)) {
1118 int delta = expected_votes - qdevice_votes;
1121 error = (
char *)
"configuration error: quorum.device.votes is too high or expected_votes is too low";
1126 update_qdevice_can_operate(0);
1135 if ((have_qdevice) &&
1136 (qdevice_votes == -1) &&
1137 (!expected_votes) &&
1139 (node_count == node_expected_votes)) {
1140 qdevice_votes = node_expected_votes - 1;
1141 node_expected_votes = node_expected_votes + qdevice_votes;
1148 if (have_nodelist) {
1149 us->
votes = node_votes;
1156 if (expected_votes) {
1164 if (!have_qdevice) {
1168 if (qdevice_votes != -1) {
1169 qdevice->
votes = qdevice_votes;
1175 update_wait_for_all_status(1);
1183 static void votequorum_refresh_config(
1185 const char *key_name,
1190 int old_votes, old_expected_votes;
1194 old_votes = us->
votes;
1205 votequorum_exec_send_nodeinfo(us->
node_id);
1207 if (us->
votes != old_votes) {
1219 static void votequorum_exec_add_config_notification(
void)
1228 votequorum_refresh_config,
1230 &icmap_track_nodelist);
1234 votequorum_refresh_config,
1236 &icmap_track_quorum);
1245 static int votequorum_exec_send_reconfigure(uint8_t
param,
unsigned int nodeid, uint32_t
value)
1248 struct iovec iov[1];
1272 static int votequorum_exec_send_nodeinfo(uint32_t nodeid)
1275 struct iovec iov[1];
1281 node = find_node_by_nodeid(nodeid);
1291 decode_flags(node->
flags);
1306 static int votequorum_exec_send_qdevice_reconfigure(
const char *
oldname,
const char *
newname)
1309 struct iovec iov[1];
1328 static int votequorum_exec_send_qdevice_reg(uint32_t
operation,
const char *qdevice_name_req)
1331 struct iovec iov[1];
1350 static int votequorum_exec_send_quorum_notification(
void *conn, uint64_t context)
1355 int cluster_members = 0;
1366 if (us->
flags & NODE_FLAGS_QDEVICE_REGISTERED) {
1370 size =
sizeof(
struct res_lib_votequorum_notification) + sizeof(struct
votequorum_node) * cluster_members;
1372 res_lib_votequorum_notification = (
struct res_lib_votequorum_notification *)&buf;
1373 res_lib_votequorum_notification->quorate = cluster_is_quorate;
1374 res_lib_votequorum_notification->node_list_entries = cluster_members;
1375 res_lib_votequorum_notification->context = context;
1378 res_lib_votequorum_notification->node_list[i].nodeid = node->
node_id;
1379 res_lib_votequorum_notification->node_list[i++].state = node->
state;
1381 if (us->
flags & NODE_FLAGS_QDEVICE_REGISTERED) {
1383 res_lib_votequorum_notification->node_list[i++].state = qdevice->
state;
1386 res_lib_votequorum_notification->header.size = size;
1387 res_lib_votequorum_notification->header.error =
CS_OK;
1409 static void votequorum_exec_send_expectedvotes_notification(
void)
1434 static void exec_votequorum_qdevice_reconfigure_endian_convert (
void *message)
1441 static void message_handler_req_exec_votequorum_qdevice_reconfigure (
1442 const void *message,
1443 unsigned int nodeid)
1451 req_exec_quorum_qdevice_reconfigure->
oldname,
1452 req_exec_quorum_qdevice_reconfigure->
newname);
1454 if (!strcmp(req_exec_quorum_qdevice_reconfigure->
oldname, qdevice_name)) {
1457 strcpy(qdevice_name, req_exec_quorum_qdevice_reconfigure->
newname);
1468 static void exec_votequorum_qdevice_reg_endian_convert (
void *message)
1479 static void message_handler_req_exec_votequorum_qdevice_reg (
1480 const void *message,
1481 unsigned int nodeid)
1485 int wipe_qdevice_name = 1;
1496 switch(req_exec_quorum_qdevice_reg->
operation)
1500 if (!strlen(qdevice_name)) {
1502 strcpy(qdevice_name, req_exec_quorum_qdevice_reg->
qdevice_name);
1513 if (us->
flags & NODE_FLAGS_QDEVICE_REGISTERED) {
1521 if (!qdevice_reg_conn) {
1530 if (!strlen(qdevice_name)) {
1531 strcpy(qdevice_name, req_exec_quorum_qdevice_reg->
qdevice_name);
1537 if ((!strncmp(req_exec_quorum_qdevice_reg->
qdevice_name,
1541 votequorum_exec_send_nodeinfo(us->
node_id);
1544 "A new qdevice with different name (new: %s old: %s) is trying to register!",
1545 req_exec_quorum_qdevice_reg->
qdevice_name, qdevice_name);
1553 qdevice_reg_conn = NULL;
1559 (node->
flags & NODE_FLAGS_QDEVICE_REGISTERED)) {
1560 wipe_qdevice_name = 0;
1564 if (wipe_qdevice_name) {
1573 static void exec_votequorum_nodeinfo_endian_convert (
void *message)
1587 static void message_handler_req_exec_votequorum_nodeinfo (
1588 const void *message,
1589 unsigned int sender_nodeid)
1598 int allow_downgrade = 0;
1600 unsigned int nodeid = req_exec_quorum_nodeinfo->
nodeid;
1607 req_exec_quorum_nodeinfo->
votes,
1609 req_exec_quorum_nodeinfo->
flags);
1612 decode_flags(req_exec_quorum_nodeinfo->
flags);
1615 node = find_node_by_nodeid(nodeid);
1617 node = allocate_node(nodeid);
1632 old_votes = node->
votes;
1634 old_state = node->
state;
1635 old_flags = node->
flags;
1639 struct cluster_node *sender_node = find_node_by_nodeid(sender_nodeid);
1641 assert(sender_node != NULL);
1643 if ((!cluster_is_quorate) &&
1644 (sender_node->
flags & NODE_FLAGS_QUORATE)) {
1645 node->
votes = req_exec_quorum_nodeinfo->
votes;
1653 node->
flags = req_exec_quorum_nodeinfo->
flags;
1654 node->
votes = req_exec_quorum_nodeinfo->
votes;
1657 if (node->
flags & NODE_FLAGS_LEAVING) {
1659 allow_downgrade = 1;
1663 if ((!cluster_is_quorate) &&
1664 (node->
flags & NODE_FLAGS_QUORATE)) {
1665 allow_downgrade = 1;
1669 if (node->
flags & NODE_FLAGS_QUORATE) {
1675 if ((last_man_standing) && (node->
votes > 1)) {
1677 "cluster nodes votes are set to 1. Disabling LMS.");
1678 last_man_standing = 0;
1679 if (last_man_standing_timer_set) {
1681 last_man_standing_timer_set = 0;
1689 (node->
flags & NODE_FLAGS_FIRST) ||
1690 (old_votes != node->
votes) ||
1692 (old_flags != node->
flags) ||
1693 (old_state != node->
state)) {
1694 recalculate_quorum(allow_downgrade, by_node);
1697 if ((wait_for_all) &&
1698 (!(node->
flags & NODE_FLAGS_WFASTATUS)) &&
1699 (node->
flags & NODE_FLAGS_QUORATE)) {
1700 update_wait_for_all_status(0);
1706 static void exec_votequorum_reconfigure_endian_convert (
void *message)
1718 static void message_handler_req_exec_votequorum_reconfigure (
1719 const void *message,
1720 unsigned int nodeid)
1729 nodeid, req_exec_quorum_reconfigure->
nodeid);
1731 switch(req_exec_quorum_reconfigure->
param)
1740 votequorum_exec_send_expectedvotes_notification();
1741 update_ev_barrier(req_exec_quorum_reconfigure->
value);
1742 recalculate_quorum(1, 0);
1746 node = find_node_by_nodeid(req_exec_quorum_reconfigure->
nodeid);
1751 node->
votes = req_exec_quorum_reconfigure->
value;
1752 recalculate_quorum(1, 0);
1760 static int votequorum_exec_exit_fn (
void)
1770 if (allow_downscale) {
1772 ret = votequorum_exec_send_nodeinfo(us->
node_id);
1788 list_init(&cluster_members_list);
1789 list_init(&trackers_list);
1792 memset(cluster_nodes, 0,
sizeof(cluster_nodes));
1800 return ((
char *)
"Could not allocate node.");
1811 return ((
char *)
"Could not allocate node.");
1824 recalculate_quorum(0, 0);
1829 votequorum_exec_add_config_notification();
1834 votequorum_exec_send_nodeinfo(us->
node_id);
1845 static void votequorum_last_man_standing_timer_fn(
void *arg)
1849 last_man_standing_timer_set = 0;
1850 if (cluster_is_quorate) {
1851 recalculate_quorum(1,1);
1857 static void votequorum_sync_init (
1858 const unsigned int *trans_list,
size_t trans_list_entries,
1859 const unsigned int *member_list,
size_t member_list_entries,
1869 sync_in_progress = 1;
1871 if (member_list_entries > 1) {
1872 us->
flags &= ~NODE_FLAGS_FIRST;
1881 for (i = 0; i < quorum_members_entries; i++) {
1883 for (j = 0; j < member_list_entries; j++) {
1884 if (quorum_members[i] == member_list[j]) {
1891 node = find_node_by_nodeid(quorum_members[i]);
1898 if (last_man_standing) {
1899 if (((member_list_entries >= quorum) && (left_nodes)) ||
1900 ((member_list_entries <= quorum) && (auto_tie_breaker) && (check_low_node_id_partition() == 1))) {
1901 if (last_man_standing_timer_set) {
1903 last_man_standing_timer_set = 0;
1905 corosync_api->
timer_add_duration((
unsigned long long)last_man_standing_window*1000000,
1906 NULL, votequorum_last_man_standing_timer_fn,
1907 &last_man_standing_timer);
1908 last_man_standing_timer_set = 1;
1912 memcpy(quorum_members, member_list,
sizeof(
unsigned int) * member_list_entries);
1913 quorum_members_entries = member_list_entries;
1914 memcpy(&quorum_ringid, ring_id,
sizeof(*ring_id));
1919 static int votequorum_sync_process (
void)
1921 votequorum_exec_send_nodeinfo(us->
node_id);
1923 if (strlen(qdevice_name)) {
1930 static void votequorum_sync_activate (
void)
1932 recalculate_quorum(0, 0);
1933 quorum_callback(quorum_members, quorum_members_entries,
1934 cluster_is_quorate, &quorum_ringid);
1935 sync_in_progress = 0;
1938 static void votequorum_sync_abort (
void)
1950 if (q_set_quorate_fn == NULL) {
1951 return ((
char *)
"Quorate function not set");
1955 quorum_callback = q_set_quorate_fn;
1958 &votequorum_service[0]);
1972 static int quorum_lib_init_fn (
void *conn)
1978 list_init (&pd->
list);
1985 static int quorum_lib_exit_fn (
void *conn)
1992 list_del (&quorum_pd->
list);
1993 list_init (&quorum_pd->
list);
2005 static void qdevice_timer_fn(
void *arg)
2009 if ((!(us->
flags & NODE_FLAGS_QDEVICE_ALIVE)) ||
2010 (!qdevice_timer_set)) {
2015 us->
flags &= ~NODE_FLAGS_QDEVICE_ALIVE;
2018 votequorum_exec_send_nodeinfo(us->
node_id);
2020 qdevice_timer_set = 0;
2029 static void message_handler_req_lib_votequorum_getinfo (
void *conn,
const void *message)
2034 unsigned int highest_expected = 0;
2035 unsigned int total_votes = 0;
2037 uint32_t nodeid = req_lib_votequorum_getinfo->
nodeid;
2047 node = find_node_by_nodeid(nodeid);
2058 total_votes += iternode->
votes;
2063 total_votes += qdevice->
votes;
2066 switch(node->
state) {
2093 if (cluster_is_quorate) {
2099 if (last_man_standing) {
2102 if (auto_tie_breaker) {
2105 if (allow_downscale) {
2113 if (node->
flags & NODE_FLAGS_QDEVICE_REGISTERED) {
2116 if (node->
flags & NODE_FLAGS_QDEVICE_ALIVE) {
2138 static void message_handler_req_lib_votequorum_setexpected (
void *conn,
const void *message)
2143 unsigned int newquorum;
2144 unsigned int total_votes;
2145 uint8_t allow_downscale_status = 0;
2149 allow_downscale_status = allow_downscale;
2150 allow_downscale = 0;
2155 newquorum = calculate_quorum(1, req_lib_votequorum_setexpected->
expected_votes, &total_votes);
2156 allow_downscale = allow_downscale_status;
2157 if (newquorum < total_votes / 2 ||
2158 newquorum > total_votes) {
2175 static void message_handler_req_lib_votequorum_setvotes (
void *conn,
const void *message)
2180 unsigned int newquorum;
2181 unsigned int total_votes;
2182 unsigned int saved_votes;
2188 nodeid = req_lib_votequorum_setvotes->
nodeid;
2189 node = find_node_by_nodeid(nodeid);
2198 saved_votes = node->
votes;
2199 node->
votes = req_lib_votequorum_setvotes->
votes;
2201 newquorum = calculate_quorum(1, 0, &total_votes);
2203 if (newquorum < total_votes / 2 ||
2204 newquorum > total_votes) {
2205 node->
votes = saved_votes;
2211 req_lib_votequorum_setvotes->
votes);
2222 static void message_handler_req_lib_votequorum_trackstart (
void *conn,
2223 const void *message)
2237 votequorum_exec_send_quorum_notification(conn, req_lib_votequorum_trackstart->
context);
2250 list_add (&quorum_pd->
list, &trackers_list);
2261 static void message_handler_req_lib_votequorum_trackstop (
void *conn,
2262 const void *message)
2273 list_del (&quorum_pd->
list);
2274 list_init (&quorum_pd->
list);
2287 static void message_handler_req_lib_votequorum_qdevice_register (
void *conn,
2288 const void *message)
2296 if (!qdevice_can_operate) {
2297 log_printf(
LOGSYS_LEVEL_INFO,
"Registration of quorum device is disabled by incorrect corosync.conf. See logs for more information");
2302 if (us->
flags & NODE_FLAGS_QDEVICE_REGISTERED) {
2303 if ((!strncmp(req_lib_votequorum_qdevice_register->
name,
2308 "A new qdevice with different name (new: %s old: %s) is trying to re-register!",
2309 req_lib_votequorum_qdevice_register->
name, qdevice_name);
2314 if (qdevice_reg_conn != NULL) {
2316 "Registration request already in progress");
2320 qdevice_reg_conn = conn;
2322 req_lib_votequorum_qdevice_register->
name) != 0) {
2324 "Unable to send qdevice registration request to cluster");
2326 qdevice_reg_conn = NULL;
2343 static void message_handler_req_lib_votequorum_qdevice_unregister (
void *conn,
2344 const void *message)
2352 if (us->
flags & NODE_FLAGS_QDEVICE_REGISTERED) {
2357 if (qdevice_timer_set) {
2359 qdevice_timer_set = 0;
2361 us->
flags &= ~NODE_FLAGS_QDEVICE_REGISTERED;
2362 us->
flags &= ~NODE_FLAGS_QDEVICE_ALIVE;
2365 votequorum_exec_send_nodeinfo(us->
node_id);
2367 req_lib_votequorum_qdevice_unregister->
name);
2381 static void message_handler_req_lib_votequorum_qdevice_update (
void *conn,
2382 const void *message)
2390 if (us->
flags & NODE_FLAGS_QDEVICE_REGISTERED) {
2395 votequorum_exec_send_qdevice_reconfigure(req_lib_votequorum_qdevice_update->
oldname,
2396 req_lib_votequorum_qdevice_update->
newname);
2410 static void message_handler_req_lib_votequorum_qdevice_poll (
void *conn,
2411 const void *message)
2420 if (!qdevice_can_operate) {
2425 if (us->
flags & NODE_FLAGS_QDEVICE_REGISTERED) {
2431 if (qdevice_timer_set) {
2433 qdevice_timer_set = 0;
2436 oldflags = us->
flags;
2440 if (req_lib_votequorum_qdevice_poll->
cast_vote) {
2446 if (us->
flags != oldflags) {
2447 votequorum_exec_send_nodeinfo(us->
node_id);
2450 corosync_api->
timer_add_duration((
unsigned long long)qdevice_timeout*1000000, qdevice,
2451 qdevice_timer_fn, &qdevice_timer);
2452 qdevice_timer_set = 1;
2466 static void message_handler_req_lib_votequorum_qdevice_master_wins (
void *conn,
2467 const void *message)
2472 uint32_t oldflags = us->
flags;
2476 if (!qdevice_can_operate) {
2481 if (us->
flags & NODE_FLAGS_QDEVICE_REGISTERED) {
2487 if (req_lib_votequorum_qdevice_master_wins->
allow) {
2493 if (us->
flags != oldflags) {
2494 votequorum_exec_send_nodeinfo(us->
node_id);
2497 update_qdevice_master_wins(req_lib_votequorum_qdevice_master_wins->
allow);