2 * Copyright (c) 2008-2020 Red Hat, Inc.
6 * Author: Christine Caulfield (ccaulfie@redhat.com)
8 * This software licensed under BSD license, the text of which follows:
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of Red Hat Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
39 #include <sys/types.h>
43 #include <sys/socket.h>
46 #include <sys/resource.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
58 #include <corosync/corotypes.h>
59 #include <qb/qbipc_common.h>
60 #include <corosync/corodefs.h>
61 #include <corosync/swab.h>
62 #include <qb/qblist.h>
63 #include <corosync/mar_gen.h>
64 #include <corosync/ipc_quorum.h>
65 #include <corosync/coroapi.h>
66 #include <corosync/logsys.h>
67 #include <corosync/icmap.h>
70 #include "votequorum.h"
73 LOGSYS_DECLARE_SUBSYS ("QUORUM");
76 unsigned char track_flags
;
78 struct qb_list_head list
;
80 enum lib_quorum_model model
;
83 struct internal_callback_pd
{
84 struct qb_list_head list
;
85 quorum_callback_fn_t callback
;
89 static void quorum_sync_init (
90 const unsigned int *trans_list
,
91 size_t trans_list_entries
,
92 const unsigned int *member_list
,
93 size_t member_list_entries
,
94 const struct memb_ring_id
*ring_id
);
96 static int quorum_sync_process (void);
98 static void quorum_sync_activate (void);
100 static void quorum_sync_abort (void);
102 static void message_handler_req_lib_quorum_getquorate (void *conn
,
104 static void message_handler_req_lib_quorum_trackstart (void *conn
,
106 static void message_handler_req_lib_quorum_trackstop (void *conn
,
108 static void message_handler_req_lib_quorum_gettype (void *conn
,
110 static void message_handler_req_lib_quorum_model_gettype (void *conn
,
112 static void send_library_notification(void *conn
);
113 static void send_internal_notification(void);
114 static void send_nodelist_library_notification(void *conn
, int send_joined_left_list
);
115 static char *quorum_exec_init_fn (struct corosync_api_v1
*api
);
116 static int quorum_lib_init_fn (void *conn
);
117 static int quorum_lib_exit_fn (void *conn
);
119 static int primary_designated
= 0;
120 static int quorum_type
= 0;
121 static struct corosync_api_v1
*corosync_api
;
122 static struct qb_list_head lib_trackers_list
;
123 static struct qb_list_head internal_trackers_list
;
124 static struct memb_ring_id quorum_ring_id
;
125 static struct memb_ring_id last_sync_ring_id
;
126 static size_t quorum_view_list_entries
= 0;
127 static int quorum_view_list
[PROCESSOR_COUNT_MAX
];
128 struct quorum_services_api_ver1
*quorum_iface
= NULL
;
130 static char view_buf
[64];
132 static unsigned int my_member_list
[PROCESSOR_COUNT_MAX
];
133 static size_t my_member_list_entries
;
134 static unsigned int my_old_member_list
[PROCESSOR_COUNT_MAX
];
135 static size_t my_old_member_list_entries
= 0;
136 static unsigned int my_left_list
[PROCESSOR_COUNT_MAX
];
137 static size_t my_left_list_entries
;
138 static unsigned int my_joined_list
[PROCESSOR_COUNT_MAX
];
139 static size_t my_joined_list_entries
;
141 static void log_view_list(const unsigned int *view_list
, size_t view_list_entries
,
142 const char *view_list_type_str
)
144 int total
= (int)view_list_entries
;
149 len
= sizeof(view_buf
);
151 memset(view_buf
, 0, len
);
153 for (; i
< total
; i
++) {
154 ret
= snprintf(view_buf
+ pos
, len
- pos
, " " CS_PRI_NODE_ID
, view_list
[i
]);
155 if (ret
>= len
- pos
)
159 log_printf (LOGSYS_LEVEL_NOTICE
, "%s[%d]:%s%s",
160 view_list_type_str
, total
, view_buf
, i
< total
? "\\" : "");
167 /* Internal quorum API function */
168 static void quorum_api_set_quorum(const unsigned int *view_list
,
169 size_t view_list_entries
,
170 int quorum
, struct memb_ring_id
*ring_id
)
172 int old_quorum
= primary_designated
;
173 primary_designated
= quorum
;
175 if (primary_designated
&& !old_quorum
) {
176 log_printf (LOGSYS_LEVEL_NOTICE
, "This node is within the primary component and will provide service.");
177 } else if (!primary_designated
&& old_quorum
) {
178 log_printf (LOGSYS_LEVEL_NOTICE
, "This node is within the non-primary component and will NOT provide any services.");
181 quorum_view_list_entries
= view_list_entries
;
182 memcpy(&quorum_ring_id
, ring_id
, sizeof (quorum_ring_id
));
183 memcpy(quorum_view_list
, view_list
, sizeof(unsigned int)*view_list_entries
);
185 log_view_list(view_list
, view_list_entries
, "Members");
187 /* Tell internal listeners */
188 send_internal_notification();
190 /* Tell IPC listeners */
191 send_library_notification(NULL
);
194 static struct corosync_lib_handler quorum_lib_service
[] =
197 .lib_handler_fn
= message_handler_req_lib_quorum_getquorate
,
198 .flow_control
= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
201 .lib_handler_fn
= message_handler_req_lib_quorum_trackstart
,
202 .flow_control
= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
205 .lib_handler_fn
= message_handler_req_lib_quorum_trackstop
,
206 .flow_control
= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
209 .lib_handler_fn
= message_handler_req_lib_quorum_gettype
,
210 .flow_control
= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
213 .lib_handler_fn
= message_handler_req_lib_quorum_model_gettype
,
214 .flow_control
= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
218 static struct corosync_service_engine quorum_service_handler
= {
219 .name
= "corosync cluster quorum service v0.1",
220 .id
= QUORUM_SERVICE
,
222 .private_data_size
= sizeof (struct quorum_pd
),
223 .flow_control
= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
,
224 .allow_inquorate
= CS_LIB_ALLOW_INQUORATE
,
225 .lib_init_fn
= quorum_lib_init_fn
,
226 .lib_exit_fn
= quorum_lib_exit_fn
,
227 .lib_engine
= quorum_lib_service
,
228 .exec_init_fn
= quorum_exec_init_fn
,
229 .sync_init
= quorum_sync_init
,
230 .sync_process
= quorum_sync_process
,
231 .sync_activate
= quorum_sync_activate
,
232 .sync_abort
= quorum_sync_abort
,
233 .lib_engine_count
= sizeof (quorum_lib_service
) / sizeof (struct corosync_lib_handler
)
236 struct corosync_service_engine
*vsf_quorum_get_service_engine_ver0 (void)
238 return (&quorum_service_handler
);
241 /* -------------------------------------------------- */
245 * Internal API functions for corosync
248 static int quorum_quorate(void)
250 return primary_designated
;
254 static int quorum_register_callback(quorum_callback_fn_t function
, void *context
)
256 struct internal_callback_pd
*pd
= malloc(sizeof(struct internal_callback_pd
));
260 pd
->context
= context
;
261 pd
->callback
= function
;
262 qb_list_add (&pd
->list
, &internal_trackers_list
);
267 static int quorum_unregister_callback(quorum_callback_fn_t function
, void *context
)
269 struct internal_callback_pd
*pd
;
270 struct qb_list_head
*tmp
, *tmp_iter
;
272 qb_list_for_each_safe(tmp
, tmp_iter
, &internal_trackers_list
) {
273 pd
= qb_list_entry(tmp
, struct internal_callback_pd
, list
);
274 if (pd
->callback
== function
&& pd
->context
== context
) {
275 qb_list_del(&pd
->list
);
283 static struct quorum_callin_functions callins
= {
284 .quorate
= quorum_quorate
,
285 .register_callback
= quorum_register_callback
,
286 .unregister_callback
= quorum_unregister_callback
289 /* --------------------------------------------------------------------- */
291 static void quorum_sync_init (
292 const unsigned int *trans_list
,
293 size_t trans_list_entries
,
294 const unsigned int *member_list
,
295 size_t member_list_entries
,
296 const struct memb_ring_id
*ring_id
)
303 memcpy (my_member_list
, member_list
, member_list_entries
*
304 sizeof (unsigned int));
305 my_member_list_entries
= member_list_entries
;
307 last_sync_ring_id
= *ring_id
;
310 * Determine left list of nodeids
313 for (i
= 0; i
< my_old_member_list_entries
; i
++) {
315 for (j
= 0; j
< trans_list_entries
; j
++) {
316 if (my_old_member_list
[i
] == trans_list
[j
]) {
323 my_left_list
[entries
++] = my_old_member_list
[i
];
326 * Check it is really in new membership
330 for (j
= 0; j
< my_member_list_entries
; j
++) {
331 if (my_old_member_list
[i
] == my_member_list
[j
]) {
338 * Node is in both old_member_list and trans list but not in my_member_list.
339 * (This shouldn't really happen).
342 my_left_list
[entries
++] = my_old_member_list
[i
];
346 my_left_list_entries
= entries
;
349 * Determine joined list of nodeids
352 for (i
= 0; i
< my_member_list_entries
; i
++) {
354 for (j
= 0; j
< my_old_member_list_entries
; j
++) {
355 if (my_member_list
[i
] == my_old_member_list
[j
]) {
357 * Node is in member list and also in my_old_member list -> check
358 * if it is in left_list.
367 * Check if node is in left list.
369 for (j
= 0; j
< my_left_list_entries
; j
++) {
370 if (my_member_list
[i
] == my_left_list
[j
]) {
372 * Node is both in left and also in member list -> joined
381 my_joined_list
[entries
++] = my_member_list
[i
];
384 my_joined_list_entries
= entries
;
386 log_view_list(my_member_list
, my_member_list_entries
, "Sync members");
388 if (my_joined_list_entries
> 0) {
389 log_view_list(my_joined_list
, my_joined_list_entries
, "Sync joined");
392 if (my_left_list_entries
> 0) {
393 log_view_list(my_left_list
, my_left_list_entries
, "Sync left");
397 static int quorum_sync_process (void)
403 static void quorum_sync_activate (void)
406 memcpy (my_old_member_list
, my_member_list
,
407 my_member_list_entries
* sizeof (unsigned int));
408 my_old_member_list_entries
= my_member_list_entries
;
410 /* Tell IPC listeners */
411 send_nodelist_library_notification(NULL
, 1);
414 static void quorum_sync_abort (void)
419 static char *quorum_exec_init_fn (struct corosync_api_v1
*api
)
421 char *quorum_module
= NULL
;
425 qb_list_init (&lib_trackers_list
);
426 qb_list_init (&internal_trackers_list
);
429 * Tell corosync we have a quorum engine.
431 api
->quorum_initialize(&callins
);
434 * Look for a quorum provider
436 if (icmap_get_string("quorum.provider", &quorum_module
) == CS_OK
) {
437 log_printf (LOGSYS_LEVEL_NOTICE
,
438 "Using quorum provider %s", quorum_module
);
440 error
= (char *)"Invalid quorum provider";
442 if (strcmp (quorum_module
, "corosync_votequorum") == 0) {
443 error
= votequorum_init (api
, quorum_api_set_quorum
);
446 if (strcmp (quorum_module
, "corosync_ykd") == 0) {
447 error
= ykd_init (api
, quorum_api_set_quorum
);
451 log_printf (LOGSYS_LEVEL_CRIT
,
452 "Quorum provider: %s failed to initialize.",
461 quorum_module
= NULL
;
465 * setting quorum_type and primary_designated in the right order is important
466 * always try to lookup/init a quorum module, then revert back to be quorate
469 if (quorum_type
== 0) {
470 primary_designated
= 1;
476 static int quorum_lib_init_fn (void *conn
)
478 struct quorum_pd
*pd
= (struct quorum_pd
*)corosync_api
->ipc_private_data_get (conn
);
480 log_printf(LOGSYS_LEVEL_DEBUG
, "lib_init_fn: conn=%p", conn
);
482 qb_list_init (&pd
->list
);
484 pd
->model
= LIB_QUORUM_MODEL_V0
;
489 static int quorum_lib_exit_fn (void *conn
)
491 struct quorum_pd
*quorum_pd
= (struct quorum_pd
*)corosync_api
->ipc_private_data_get (conn
);
493 log_printf(LOGSYS_LEVEL_DEBUG
, "lib_exit_fn: conn=%p", conn
);
495 if (quorum_pd
->tracking_enabled
) {
496 qb_list_del (&quorum_pd
->list
);
497 qb_list_init (&quorum_pd
->list
);
503 static void send_internal_notification(void)
505 struct qb_list_head
*tmp
;
506 struct internal_callback_pd
*pd
;
508 qb_list_for_each(tmp
, &internal_trackers_list
) {
509 pd
= qb_list_entry(tmp
, struct internal_callback_pd
, list
);
511 pd
->callback(primary_designated
, pd
->context
);
515 static void prepare_library_notification_v0(char *buf
, size_t size
)
517 struct res_lib_quorum_notification
*res_lib_quorum_notification
= (struct res_lib_quorum_notification
*)buf
;
520 res_lib_quorum_notification
->quorate
= primary_designated
;
521 res_lib_quorum_notification
->ring_seq
= quorum_ring_id
.seq
;
522 res_lib_quorum_notification
->view_list_entries
= quorum_view_list_entries
;
523 for (i
=0; i
<quorum_view_list_entries
; i
++) {
524 res_lib_quorum_notification
->view_list
[i
] = quorum_view_list
[i
];
527 res_lib_quorum_notification
->header
.id
= MESSAGE_RES_QUORUM_NOTIFICATION
;
528 res_lib_quorum_notification
->header
.size
= size
;
529 res_lib_quorum_notification
->header
.error
= CS_OK
;
532 static void prepare_library_notification_v1(char *buf
, size_t size
)
534 struct res_lib_quorum_v1_quorum_notification
*res_lib_quorum_v1_quorum_notification
=
535 (struct res_lib_quorum_v1_quorum_notification
*)buf
;
538 res_lib_quorum_v1_quorum_notification
->quorate
= primary_designated
;
539 res_lib_quorum_v1_quorum_notification
->ring_id
.nodeid
= quorum_ring_id
.nodeid
;
540 res_lib_quorum_v1_quorum_notification
->ring_id
.seq
= quorum_ring_id
.seq
;
541 res_lib_quorum_v1_quorum_notification
->view_list_entries
= quorum_view_list_entries
;
542 for (i
=0; i
<quorum_view_list_entries
; i
++) {
543 res_lib_quorum_v1_quorum_notification
->view_list
[i
] = quorum_view_list
[i
];
546 res_lib_quorum_v1_quorum_notification
->header
.id
= MESSAGE_RES_QUORUM_V1_QUORUM_NOTIFICATION
;
547 res_lib_quorum_v1_quorum_notification
->header
.size
= size
;
548 res_lib_quorum_v1_quorum_notification
->header
.error
= CS_OK
;
551 static void send_library_notification(void *conn
)
553 int size_v0
= sizeof(struct res_lib_quorum_notification
) +
554 sizeof(mar_uint32_t
) * quorum_view_list_entries
;
555 int size_v1
= sizeof(struct res_lib_quorum_v1_quorum_notification
) +
556 sizeof(mar_uint32_t
)*quorum_view_list_entries
;
558 char buf_v0
[size_v0
];
559 char buf_v1
[size_v1
];
561 struct res_lib_quorum_notification
*res_lib_quorum_notification
=
562 (struct res_lib_quorum_notification
*)buf_v0
;
563 struct res_lib_quorum_v1_quorum_notification
*res_lib_quorum_v1_quorum_notification
=
564 (struct res_lib_quorum_v1_quorum_notification
*)buf_v1
;
566 struct quorum_pd
*qpd
;
567 struct qb_list_head
*tmp
;
569 log_printf(LOGSYS_LEVEL_DEBUG
, "sending quorum notification to %p, length = %u/%u", conn
, size_v0
, size_v1
);
571 prepare_library_notification_v0(buf_v0
, size_v0
);
572 prepare_library_notification_v1(buf_v1
, size_v1
);
574 /* Send it to all interested parties */
576 qpd
= (struct quorum_pd
*)corosync_api
->ipc_private_data_get (conn
);
578 if (qpd
->model
== LIB_QUORUM_MODEL_V0
) {
579 corosync_api
->ipc_dispatch_send(conn
, res_lib_quorum_notification
, size_v0
);
580 } else if (qpd
->model
== LIB_QUORUM_MODEL_V1
) {
581 corosync_api
->ipc_dispatch_send(conn
, res_lib_quorum_v1_quorum_notification
, size_v1
);
585 qb_list_for_each(tmp
, &lib_trackers_list
) {
586 qpd
= qb_list_entry(tmp
, struct quorum_pd
, list
);
588 if (qpd
->model
== LIB_QUORUM_MODEL_V0
) {
589 corosync_api
->ipc_dispatch_send(qpd
->conn
,
590 res_lib_quorum_notification
, size_v0
);
591 } else if (qpd
->model
== LIB_QUORUM_MODEL_V1
) {
592 corosync_api
->ipc_dispatch_send(qpd
->conn
,
593 res_lib_quorum_v1_quorum_notification
, size_v1
);
600 static void send_nodelist_library_notification(void *conn
, int send_joined_left_list
)
602 int size
= sizeof(struct res_lib_quorum_v1_nodelist_notification
) +
603 sizeof(mar_uint32_t
) * my_member_list_entries
;
605 struct res_lib_quorum_v1_nodelist_notification
*res_lib_quorum_v1_nodelist_notification
;
606 struct quorum_pd
*qpd
;
607 struct qb_list_head
*tmp
;
611 if (send_joined_left_list
) {
612 size
+= sizeof(mar_uint32_t
) * my_joined_list_entries
;
613 size
+= sizeof(mar_uint32_t
) * my_left_list_entries
;
617 memset(buf
, 0, size
);
619 res_lib_quorum_v1_nodelist_notification
= (struct res_lib_quorum_v1_nodelist_notification
*)buf
;
621 res_lib_quorum_v1_nodelist_notification
->ring_id
.nodeid
= last_sync_ring_id
.nodeid
;
622 res_lib_quorum_v1_nodelist_notification
->ring_id
.seq
= last_sync_ring_id
.seq
;
623 res_lib_quorum_v1_nodelist_notification
->member_list_entries
= my_member_list_entries
;
625 if (send_joined_left_list
) {
626 res_lib_quorum_v1_nodelist_notification
->joined_list_entries
= my_joined_list_entries
;
627 res_lib_quorum_v1_nodelist_notification
->left_list_entries
= my_left_list_entries
;
630 ptr
= res_lib_quorum_v1_nodelist_notification
->member_list
;
632 for (i
=0; i
<my_member_list_entries
; i
++, ptr
++) {
633 *ptr
= my_member_list
[i
];
636 if (send_joined_left_list
) {
637 for (i
=0; i
<my_joined_list_entries
; i
++, ptr
++) {
638 *ptr
= my_joined_list
[i
];
641 for (i
=0; i
<my_left_list_entries
; i
++, ptr
++) {
642 *ptr
= my_left_list
[i
];
646 res_lib_quorum_v1_nodelist_notification
->header
.id
= MESSAGE_RES_QUORUM_V1_NODELIST_NOTIFICATION
;
647 res_lib_quorum_v1_nodelist_notification
->header
.size
= size
;
648 res_lib_quorum_v1_nodelist_notification
->header
.error
= CS_OK
;
650 log_printf(LOGSYS_LEVEL_DEBUG
, "sending nodelist notification to %p, length = %u", conn
, size
);
652 /* Send it to all interested parties */
654 qpd
= (struct quorum_pd
*)corosync_api
->ipc_private_data_get (conn
);
656 if (qpd
->model
== LIB_QUORUM_MODEL_V1
) {
657 corosync_api
->ipc_dispatch_send(conn
, res_lib_quorum_v1_nodelist_notification
, size
);
661 qb_list_for_each(tmp
, &lib_trackers_list
) {
662 qpd
= qb_list_entry(tmp
, struct quorum_pd
, list
);
664 if (qpd
->model
== LIB_QUORUM_MODEL_V1
) {
665 corosync_api
->ipc_dispatch_send(qpd
->conn
,
666 res_lib_quorum_v1_nodelist_notification
, size
);
674 static void message_handler_req_lib_quorum_getquorate (void *conn
,
677 struct res_lib_quorum_getquorate res_lib_quorum_getquorate
;
679 log_printf(LOGSYS_LEVEL_DEBUG
, "got quorate request on %p", conn
);
682 res_lib_quorum_getquorate
.quorate
= primary_designated
;
683 res_lib_quorum_getquorate
.header
.size
= sizeof(res_lib_quorum_getquorate
);
684 res_lib_quorum_getquorate
.header
.id
= MESSAGE_RES_QUORUM_GETQUORATE
;
685 res_lib_quorum_getquorate
.header
.error
= CS_OK
;
686 corosync_api
->ipc_response_send(conn
, &res_lib_quorum_getquorate
, sizeof(res_lib_quorum_getquorate
));
689 static void message_handler_req_lib_quorum_trackstart (void *conn
,
692 const struct req_lib_quorum_trackstart
*req_lib_quorum_trackstart
= msg
;
693 struct qb_ipc_response_header res
;
694 struct quorum_pd
*quorum_pd
= (struct quorum_pd
*)corosync_api
->ipc_private_data_get (conn
);
695 cs_error_t error
= CS_OK
;
697 log_printf(LOGSYS_LEVEL_DEBUG
, "got trackstart request on %p", conn
);
700 * If an immediate listing of the current cluster membership
701 * is requested, generate membership list
703 if (req_lib_quorum_trackstart
->track_flags
& CS_TRACK_CURRENT
||
704 req_lib_quorum_trackstart
->track_flags
& CS_TRACK_CHANGES
) {
705 log_printf(LOGSYS_LEVEL_DEBUG
, "sending initial status to %p", conn
);
706 send_nodelist_library_notification(conn
, 0);
707 send_library_notification(conn
);
710 if (quorum_pd
->tracking_enabled
) {
711 error
= CS_ERR_EXIST
;
716 * Record requests for tracking
718 if (req_lib_quorum_trackstart
->track_flags
& CS_TRACK_CHANGES
||
719 req_lib_quorum_trackstart
->track_flags
& CS_TRACK_CHANGES_ONLY
) {
721 quorum_pd
->track_flags
= req_lib_quorum_trackstart
->track_flags
;
722 quorum_pd
->tracking_enabled
= 1;
724 qb_list_add (&quorum_pd
->list
, &lib_trackers_list
);
729 res
.size
= sizeof(res
);
730 res
.id
= MESSAGE_RES_QUORUM_TRACKSTART
;
732 corosync_api
->ipc_response_send(conn
, &res
, sizeof(struct qb_ipc_response_header
));
735 static void message_handler_req_lib_quorum_trackstop (void *conn
, const void *msg
)
737 struct qb_ipc_response_header res
;
738 struct quorum_pd
*quorum_pd
= (struct quorum_pd
*)corosync_api
->ipc_private_data_get (conn
);
740 log_printf(LOGSYS_LEVEL_DEBUG
, "got trackstop request on %p", conn
);
742 if (quorum_pd
->tracking_enabled
) {
744 quorum_pd
->tracking_enabled
= 0;
745 qb_list_del (&quorum_pd
->list
);
746 qb_list_init (&quorum_pd
->list
);
748 res
.error
= CS_ERR_NOT_EXIST
;
752 res
.size
= sizeof(res
);
753 res
.id
= MESSAGE_RES_QUORUM_TRACKSTOP
;
755 corosync_api
->ipc_response_send(conn
, &res
, sizeof(struct qb_ipc_response_header
));
758 static void message_handler_req_lib_quorum_gettype (void *conn
,
761 struct res_lib_quorum_gettype res_lib_quorum_gettype
;
763 log_printf(LOGSYS_LEVEL_DEBUG
, "got quorum_type request on %p", conn
);
766 res_lib_quorum_gettype
.quorum_type
= quorum_type
;
767 res_lib_quorum_gettype
.header
.size
= sizeof(res_lib_quorum_gettype
);
768 res_lib_quorum_gettype
.header
.id
= MESSAGE_RES_QUORUM_GETTYPE
;
769 res_lib_quorum_gettype
.header
.error
= CS_OK
;
770 corosync_api
->ipc_response_send(conn
, &res_lib_quorum_gettype
, sizeof(res_lib_quorum_gettype
));
773 static void message_handler_req_lib_quorum_model_gettype (void *conn
,
776 const struct req_lib_quorum_model_gettype
*req_lib_quorum_model_gettype
= msg
;
777 struct res_lib_quorum_model_gettype res_lib_quorum_model_gettype
;
778 struct quorum_pd
*quorum_pd
= (struct quorum_pd
*)corosync_api
->ipc_private_data_get (conn
);
781 log_printf(LOGSYS_LEVEL_DEBUG
, "got quorum_model_type request on %p", conn
);
785 if (req_lib_quorum_model_gettype
->model
!= LIB_QUORUM_MODEL_V0
&&
786 req_lib_quorum_model_gettype
->model
!= LIB_QUORUM_MODEL_V1
) {
787 log_printf(LOGSYS_LEVEL_ERROR
, "quorum_model_type request for unsupported model %u",
788 req_lib_quorum_model_gettype
->model
);
790 ret_err
= CS_ERR_INVALID_PARAM
;
792 quorum_pd
->model
= req_lib_quorum_model_gettype
->model
;
796 res_lib_quorum_model_gettype
.quorum_type
= quorum_type
;
797 res_lib_quorum_model_gettype
.header
.size
= sizeof(res_lib_quorum_model_gettype
);
798 res_lib_quorum_model_gettype
.header
.id
= MESSAGE_RES_QUORUM_MODEL_GETTYPE
;
799 res_lib_quorum_model_gettype
.header
.error
= ret_err
;
800 corosync_api
->ipc_response_send(conn
, &res_lib_quorum_model_gettype
, sizeof(res_lib_quorum_model_gettype
));