]> git.proxmox.com Git - mirror_corosync.git/blame - exec/vsf_quorum.c
configure: Modernize configure.ac a bit
[mirror_corosync.git] / exec / vsf_quorum.c
CommitLineData
5bb7ca5d 1/*
4eb36297 2 * Copyright (c) 2008-2020 Red Hat, Inc.
5bb7ca5d
CC
3 *
4 * All rights reserved.
5 *
6 * Author: Christine Caulfield (ccaulfie@redhat.com)
7 *
8 * This software licensed under BSD license, the text of which follows:
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
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.
cfc7da35 18 * - Neither the name of Red Hat Inc. nor the names of its
5bb7ca5d
CC
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 *
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.
33 */
34
031c02f5
FDN
35#include <config.h>
36
5bb7ca5d
CC
37#include <pwd.h>
38#include <grp.h>
39#include <sys/types.h>
40#include <sys/poll.h>
41#include <sys/uio.h>
42#include <sys/mman.h>
43#include <sys/socket.h>
44#include <sys/un.h>
45#include <sys/time.h>
46#include <sys/resource.h>
47#include <netinet/in.h>
48#include <arpa/inet.h>
49#include <unistd.h>
50#include <fcntl.h>
51#include <stdlib.h>
52#include <stdio.h>
53#include <errno.h>
5bb7ca5d
CC
54#include <sched.h>
55#include <time.h>
56
7592e3b6 57#include "quorum.h"
8126cf74 58#include <corosync/corotypes.h>
c6895faa 59#include <qb/qbipc_common.h>
8126cf74 60#include <corosync/corodefs.h>
5bb7ca5d 61#include <corosync/swab.h>
b4c06e52 62#include <qb/qblist.h>
8126cf74 63#include <corosync/mar_gen.h>
5bb7ca5d 64#include <corosync/ipc_quorum.h>
e5aba30a 65#include <corosync/coroapi.h>
8ad583a5 66#include <corosync/logsys.h>
7e1c9771 67#include <corosync/icmap.h>
5bb7ca5d 68
0e2f0b87 69#include "service.h"
e423e43b 70#include "votequorum.h"
0e2f0b87 71#include "vsf_ykd.h"
e423e43b 72
c3c75acf 73LOGSYS_DECLARE_SUBSYS ("QUORUM");
5bb7ca5d
CC
74
75struct quorum_pd {
76 unsigned char track_flags;
77 int tracking_enabled;
b4c06e52 78 struct qb_list_head list;
5bb7ca5d 79 void *conn;
4eb36297 80 enum lib_quorum_model model;
5bb7ca5d
CC
81};
82
cfc7da35 83struct internal_callback_pd {
b4c06e52 84 struct qb_list_head list;
cfc7da35
CC
85 quorum_callback_fn_t callback;
86 void *context;
87};
88
4eb36297
JF
89static 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);
95
96static int quorum_sync_process (void);
97
98static void quorum_sync_activate (void);
99
100static void quorum_sync_abort (void);
101
e0021727
JM
102static void message_handler_req_lib_quorum_getquorate (void *conn,
103 const void *msg);
104static void message_handler_req_lib_quorum_trackstart (void *conn,
105 const void *msg);
106static void message_handler_req_lib_quorum_trackstop (void *conn,
107 const void *msg);
e34d509d
FDN
108static void message_handler_req_lib_quorum_gettype (void *conn,
109 const void *msg);
4eb36297
JF
110static void message_handler_req_lib_quorum_model_gettype (void *conn,
111 const void *msg);
cfc7da35
CC
112static void send_library_notification(void *conn);
113static void send_internal_notification(void);
4eb36297 114static void send_nodelist_library_notification(void *conn, int send_joined_left_list);
007e5c94 115static char *quorum_exec_init_fn (struct corosync_api_v1 *api);
5bb7ca5d
CC
116static int quorum_lib_init_fn (void *conn);
117static int quorum_lib_exit_fn (void *conn);
118
119static int primary_designated = 0;
e34d509d 120static int quorum_type = 0;
5bb7ca5d 121static struct corosync_api_v1 *corosync_api;
b4c06e52
MJ
122static struct qb_list_head lib_trackers_list;
123static struct qb_list_head internal_trackers_list;
5bb7ca5d 124static struct memb_ring_id quorum_ring_id;
4eb36297 125static struct memb_ring_id last_sync_ring_id;
4cb431fc 126static size_t quorum_view_list_entries = 0;
0665aca9 127static int quorum_view_list[PROCESSOR_COUNT_MAX];
cfc7da35 128struct quorum_services_api_ver1 *quorum_iface = NULL;
4eb36297 129
2e2581f5
CC
130static char view_buf[64];
131
4eb36297
JF
132static unsigned int my_member_list[PROCESSOR_COUNT_MAX];
133static size_t my_member_list_entries;
134static unsigned int my_old_member_list[PROCESSOR_COUNT_MAX];
135static size_t my_old_member_list_entries = 0;
136static unsigned int my_left_list[PROCESSOR_COUNT_MAX];
137static size_t my_left_list_entries;
138static unsigned int my_joined_list[PROCESSOR_COUNT_MAX];
139static size_t my_joined_list_entries;
140
141static void log_view_list(const unsigned int *view_list, size_t view_list_entries,
142 const char *view_list_type_str)
2e2581f5
CC
143{
144 int total = (int)view_list_entries;
145 int len, pos, ret;
146 int i = 0;
147
148 while (1) {
149 len = sizeof(view_buf);
150 pos = 0;
151 memset(view_buf, 0, len);
152
153 for (; i < total; i++) {
5731af27 154 ret = snprintf(view_buf + pos, len - pos, " " CS_PRI_NODE_ID, view_list[i]);
2e2581f5
CC
155 if (ret >= len - pos)
156 break;
157 pos += ret;
158 }
4eb36297
JF
159 log_printf (LOGSYS_LEVEL_NOTICE, "%s[%d]:%s%s",
160 view_list_type_str, total, view_buf, i < total ? "\\" : "");
2e2581f5
CC
161
162 if (i == total)
163 break;
164 }
165}
5bb7ca5d 166
5bb7ca5d 167/* Internal quorum API function */
db4838bc 168static void quorum_api_set_quorum(const unsigned int *view_list,
4cb431fc 169 size_t view_list_entries,
5bb7ca5d
CC
170 int quorum, struct memb_ring_id *ring_id)
171{
e9adc518 172 int old_quorum = primary_designated;
5bb7ca5d 173 primary_designated = quorum;
cfc7da35 174
e9adc518 175 if (primary_designated && !old_quorum) {
3131601c 176 log_printf (LOGSYS_LEVEL_NOTICE, "This node is within the primary component and will provide service.");
e9adc518 177 } else if (!primary_designated && old_quorum) {
3131601c 178 log_printf (LOGSYS_LEVEL_NOTICE, "This node is within the non-primary component and will NOT provide any services.");
cfc7da35
CC
179 }
180
5bb7ca5d 181 quorum_view_list_entries = view_list_entries;
83aec0b8 182 memcpy(&quorum_ring_id, ring_id, sizeof (quorum_ring_id));
fb833af4 183 memcpy(quorum_view_list, view_list, sizeof(unsigned int)*view_list_entries);
5bb7ca5d 184
4eb36297 185 log_view_list(view_list, view_list_entries, "Members");
827ae57b 186
cfc7da35
CC
187 /* Tell internal listeners */
188 send_internal_notification();
5bb7ca5d 189
cfc7da35
CC
190 /* Tell IPC listeners */
191 send_library_notification(NULL);
5bb7ca5d
CC
192}
193
5bb7ca5d
CC
194static struct corosync_lib_handler quorum_lib_service[] =
195{
196 { /* 0 */
197 .lib_handler_fn = message_handler_req_lib_quorum_getquorate,
56eaee95 198 .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
5bb7ca5d
CC
199 },
200 { /* 1 */
201 .lib_handler_fn = message_handler_req_lib_quorum_trackstart,
56eaee95 202 .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
5bb7ca5d
CC
203 },
204 { /* 2 */
205 .lib_handler_fn = message_handler_req_lib_quorum_trackstop,
56eaee95 206 .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
e34d509d
FDN
207 },
208 { /* 3 */
209 .lib_handler_fn = message_handler_req_lib_quorum_gettype,
210 .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
4eb36297
JF
211 },
212 { /* 4 */
213 .lib_handler_fn = message_handler_req_lib_quorum_model_gettype,
214 .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
5bb7ca5d
CC
215 }
216};
217
218static struct corosync_service_engine quorum_service_handler = {
219 .name = "corosync cluster quorum service v0.1",
220 .id = QUORUM_SERVICE,
9fa83dab 221 .priority = 1,
5bb7ca5d 222 .private_data_size = sizeof (struct quorum_pd),
56eaee95
AS
223 .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED,
224 .allow_inquorate = CS_LIB_ALLOW_INQUORATE,
5bb7ca5d
CC
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,
4eb36297
JF
229 .sync_init = quorum_sync_init,
230 .sync_process = quorum_sync_process,
231 .sync_activate = quorum_sync_activate,
232 .sync_abort = quorum_sync_abort,
8f6e5ff5 233 .lib_engine_count = sizeof (quorum_lib_service) / sizeof (struct corosync_lib_handler)
5bb7ca5d
CC
234};
235
e423e43b 236struct corosync_service_engine *vsf_quorum_get_service_engine_ver0 (void)
5bb7ca5d
CC
237{
238 return (&quorum_service_handler);
239}
240
5bb7ca5d
CC
241/* -------------------------------------------------- */
242
cfc7da35
CC
243
244/*
245 * Internal API functions for corosync
246 */
247
248static int quorum_quorate(void)
249{
250 return primary_designated;
251}
252
253
254static int quorum_register_callback(quorum_callback_fn_t function, void *context)
255{
256 struct internal_callback_pd *pd = malloc(sizeof(struct internal_callback_pd));
257 if (!pd)
258 return -1;
259
260 pd->context = context;
261 pd->callback = function;
b4c06e52 262 qb_list_add (&pd->list, &internal_trackers_list);
cfc7da35
CC
263
264 return 0;
265}
266
267static int quorum_unregister_callback(quorum_callback_fn_t function, void *context)
268{
269 struct internal_callback_pd *pd;
1f90c31b 270 struct qb_list_head *tmp, *tmp_iter;
cfc7da35 271
1f90c31b 272 qb_list_for_each_safe(tmp, tmp_iter, &internal_trackers_list) {
b4c06e52 273 pd = qb_list_entry(tmp, struct internal_callback_pd, list);
cfc7da35 274 if (pd->callback == function && pd->context == context) {
b4c06e52 275 qb_list_del(&pd->list);
fa71067a 276 free(pd);
cfc7da35
CC
277 return 0;
278 }
279 }
280 return -1;
281}
282
283static struct quorum_callin_functions callins = {
284 .quorate = quorum_quorate,
285 .register_callback = quorum_register_callback,
286 .unregister_callback = quorum_unregister_callback
287};
288
289/* --------------------------------------------------------------------- */
290
4eb36297
JF
291static 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)
297{
298 int found;
299 int i, j;
300 int entries;
301 int node_joined;
302
303 memcpy (my_member_list, member_list, member_list_entries *
304 sizeof (unsigned int));
305 my_member_list_entries = member_list_entries;
306
307 last_sync_ring_id = *ring_id;
308
309 /*
310 * Determine left list of nodeids
311 */
312 entries = 0;
313 for (i = 0; i < my_old_member_list_entries; i++) {
314 found = 0;
315 for (j = 0; j < trans_list_entries; j++) {
316 if (my_old_member_list[i] == trans_list[j]) {
317 found = 1;
318 break;
319 }
320 }
321
322 if (found == 0) {
323 my_left_list[entries++] = my_old_member_list[i];
324 } else {
325 /*
326 * Check it is really in new membership
327 */
328 found = 0;
329
330 for (j = 0; j < my_member_list_entries; j++) {
331 if (my_old_member_list[i] == my_member_list[j]) {
332 found = 1;
333 break;
334 }
335 }
336
337 /*
338 * Node is in both old_member_list and trans list but not in my_member_list.
339 * (This shouldn't really happen).
340 */
341 if (!found) {
342 my_left_list[entries++] = my_old_member_list[i];
343 }
344 }
345 }
346 my_left_list_entries = entries;
347
348 /*
349 * Determine joined list of nodeids
350 */
351 entries = 0;
352 for (i = 0; i < my_member_list_entries; i++) {
353 node_joined = 1;
354 for (j = 0; j < my_old_member_list_entries; j++) {
355 if (my_member_list[i] == my_old_member_list[j]) {
356 /*
357 * Node is in member list and also in my_old_member list -> check
358 * if it is in left_list.
359 */
360 node_joined = 0;
361 break;
362 }
363 }
364
365 if (!node_joined) {
366 /*
367 * Check if node is in left list.
368 */
369 for (j = 0; j < my_left_list_entries; j++) {
370 if (my_member_list[i] == my_left_list[j]) {
371 /*
372 * Node is both in left and also in member list -> joined
373 */
374 node_joined = 1;
375 break;
376 }
377 }
378 }
379
380 if (node_joined) {
381 my_joined_list[entries++] = my_member_list[i];
382 }
383 }
384 my_joined_list_entries = entries;
385
386 log_view_list(my_member_list, my_member_list_entries, "Sync members");
387
388 if (my_joined_list_entries > 0) {
389 log_view_list(my_joined_list, my_joined_list_entries, "Sync joined");
390 }
391
392 if (my_left_list_entries > 0) {
393 log_view_list(my_left_list, my_left_list_entries, "Sync left");
394 }
395}
396
397static int quorum_sync_process (void)
398{
399
400 return (0);
401}
402
403static void quorum_sync_activate (void)
404{
405
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;
409
410 /* Tell IPC listeners */
411 send_nodelist_library_notification(NULL, 1);
412}
413
414static void quorum_sync_abort (void)
415{
416
417}
418
007e5c94 419static char *quorum_exec_init_fn (struct corosync_api_v1 *api)
5bb7ca5d 420{
de914ca7 421 char *quorum_module = NULL;
007e5c94 422 char *error;
e423e43b 423
5bb7ca5d 424 corosync_api = api;
b4c06e52
MJ
425 qb_list_init (&lib_trackers_list);
426 qb_list_init (&internal_trackers_list);
cfc7da35
CC
427
428 /*
429 * Tell corosync we have a quorum engine.
430 */
12754324 431 api->quorum_initialize(&callins);
cfc7da35
CC
432
433 /*
434 * Look for a quorum provider
435 */
8a45e2b1 436 if (icmap_get_string("quorum.provider", &quorum_module) == CS_OK) {
8a45e2b1 437 log_printf (LOGSYS_LEVEL_NOTICE,
3131601c 438 "Using quorum provider %s", quorum_module);
94b11502 439
007e5c94
SD
440 error = (char *)"Invalid quorum provider";
441
e423e43b 442 if (strcmp (quorum_module, "corosync_votequorum") == 0) {
007e5c94
SD
443 error = votequorum_init (api, quorum_api_set_quorum);
444 quorum_type = 1;
e423e43b 445 }
0e2f0b87 446 if (strcmp (quorum_module, "corosync_ykd") == 0) {
007e5c94
SD
447 error = ykd_init (api, quorum_api_set_quorum);
448 quorum_type = 1;
0e2f0b87 449 }
007e5c94 450 if (error) {
78edc1f2 451 log_printf (LOGSYS_LEVEL_CRIT,
007e5c94
SD
452 "Quorum provider: %s failed to initialize.",
453 quorum_module);
939a7b2d 454 free(quorum_module);
007e5c94 455 return (error);
78edc1f2 456 }
cfc7da35 457 }
e423e43b 458
de914ca7
FDN
459 if (quorum_module) {
460 free(quorum_module);
461 quorum_module = NULL;
462 }
463
e423e43b
SD
464 /*
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
467 */
468
469 if (quorum_type == 0) {
795e573c
CC
470 primary_designated = 1;
471 }
cfc7da35 472
007e5c94 473 return (NULL);
5bb7ca5d
CC
474}
475
476static int quorum_lib_init_fn (void *conn)
477{
478 struct quorum_pd *pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
479
3131601c 480 log_printf(LOGSYS_LEVEL_DEBUG, "lib_init_fn: conn=%p", conn);
5bb7ca5d 481
b4c06e52 482 qb_list_init (&pd->list);
5bb7ca5d 483 pd->conn = conn;
4eb36297 484 pd->model = LIB_QUORUM_MODEL_V0;
5bb7ca5d
CC
485
486 return (0);
487}
488
489static int quorum_lib_exit_fn (void *conn)
490{
491 struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
492
3131601c 493 log_printf(LOGSYS_LEVEL_DEBUG, "lib_exit_fn: conn=%p", conn);
5bb7ca5d
CC
494
495 if (quorum_pd->tracking_enabled) {
b4c06e52
MJ
496 qb_list_del (&quorum_pd->list);
497 qb_list_init (&quorum_pd->list);
5bb7ca5d
CC
498 }
499 return (0);
500}
501
cfc7da35
CC
502
503static void send_internal_notification(void)
504{
b4c06e52 505 struct qb_list_head *tmp;
cfc7da35 506 struct internal_callback_pd *pd;
1f90c31b
JF
507
508 qb_list_for_each(tmp, &internal_trackers_list) {
b4c06e52 509 pd = qb_list_entry(tmp, struct internal_callback_pd, list);
cfc7da35
CC
510
511 pd->callback(primary_designated, pd->context);
512 }
513}
514
4eb36297 515static void prepare_library_notification_v0(char *buf, size_t size)
5bb7ca5d 516{
5bb7ca5d 517 struct res_lib_quorum_notification *res_lib_quorum_notification = (struct res_lib_quorum_notification *)buf;
5bb7ca5d
CC
518 int i;
519
5bb7ca5d
CC
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];
525 }
526
527 res_lib_quorum_notification->header.id = MESSAGE_RES_QUORUM_NOTIFICATION;
528 res_lib_quorum_notification->header.size = size;
56eaee95 529 res_lib_quorum_notification->header.error = CS_OK;
4eb36297
JF
530}
531
532static void prepare_library_notification_v1(char *buf, size_t size)
533{
534 struct res_lib_quorum_v1_quorum_notification *res_lib_quorum_v1_quorum_notification =
535 (struct res_lib_quorum_v1_quorum_notification *)buf;
536 int i;
537
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];
544 }
545
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;
549}
550
551static void send_library_notification(void *conn)
552{
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;
557
558 char buf_v0[size_v0];
559 char buf_v1[size_v1];
560
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;
565
566 struct quorum_pd *qpd;
567 struct qb_list_head *tmp;
568
569 log_printf(LOGSYS_LEVEL_DEBUG, "sending quorum notification to %p, length = %u/%u", conn, size_v0, size_v1);
570
571 prepare_library_notification_v0(buf_v0, size_v0);
572 prepare_library_notification_v1(buf_v1, size_v1);
5bb7ca5d
CC
573
574 /* Send it to all interested parties */
575 if (conn) {
4eb36297
JF
576 qpd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
577
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);
582 }
5bb7ca5d
CC
583 }
584 else {
4eb36297
JF
585 qb_list_for_each(tmp, &lib_trackers_list) {
586 qpd = qb_list_entry(tmp, struct quorum_pd, list);
587
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);
594 }
595 }
596 }
597 return;
598}
599
600static void send_nodelist_library_notification(void *conn, int send_joined_left_list)
601{
602 int size = sizeof(struct res_lib_quorum_v1_nodelist_notification) +
603 sizeof(mar_uint32_t) * my_member_list_entries;
604 char *buf;
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;
608 mar_uint32_t *ptr;
609 int i;
610
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;
614 }
615
616 buf = alloca(size);
617 memset(buf, 0, size);
618
619 res_lib_quorum_v1_nodelist_notification = (struct res_lib_quorum_v1_nodelist_notification *)buf;
620
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;
624
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;
628 }
629
630 ptr = res_lib_quorum_v1_nodelist_notification->member_list;
631
632 for (i=0; i<my_member_list_entries; i++, ptr++) {
633 *ptr = my_member_list[i];
634 }
5bb7ca5d 635
4eb36297
JF
636 if (send_joined_left_list) {
637 for (i=0; i<my_joined_list_entries; i++, ptr++) {
638 *ptr = my_joined_list[i];
639 }
640
641 for (i=0; i<my_left_list_entries; i++, ptr++) {
642 *ptr = my_left_list[i];
643 }
644 }
645
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;
649
650 log_printf(LOGSYS_LEVEL_DEBUG, "sending nodelist notification to %p, length = %u", conn, size);
651
652 /* Send it to all interested parties */
653 if (conn) {
654 qpd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
655
656 if (qpd->model == LIB_QUORUM_MODEL_V1) {
657 corosync_api->ipc_dispatch_send(conn, res_lib_quorum_v1_nodelist_notification, size);
658 }
659 }
660 else {
1f90c31b 661 qb_list_for_each(tmp, &lib_trackers_list) {
b4c06e52 662 qpd = qb_list_entry(tmp, struct quorum_pd, list);
5bb7ca5d 663
4eb36297
JF
664 if (qpd->model == LIB_QUORUM_MODEL_V1) {
665 corosync_api->ipc_dispatch_send(qpd->conn,
666 res_lib_quorum_v1_nodelist_notification, size);
667 }
5bb7ca5d
CC
668 }
669 }
4eb36297 670
cfc7da35 671 return;
5bb7ca5d
CC
672}
673
e0021727
JM
674static void message_handler_req_lib_quorum_getquorate (void *conn,
675 const void *msg)
5bb7ca5d
CC
676{
677 struct res_lib_quorum_getquorate res_lib_quorum_getquorate;
678
3131601c 679 log_printf(LOGSYS_LEVEL_DEBUG, "got quorate request on %p", conn);
5bb7ca5d
CC
680
681 /* send status */
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;
56eaee95 685 res_lib_quorum_getquorate.header.error = CS_OK;
c0772557 686 corosync_api->ipc_response_send(conn, &res_lib_quorum_getquorate, sizeof(res_lib_quorum_getquorate));
5bb7ca5d
CC
687}
688
e0021727
JM
689static void message_handler_req_lib_quorum_trackstart (void *conn,
690 const void *msg)
5bb7ca5d 691{
e0021727 692 const struct req_lib_quorum_trackstart *req_lib_quorum_trackstart = msg;
c6895faa 693 struct qb_ipc_response_header res;
5bb7ca5d 694 struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
82526d2f 695 cs_error_t error = CS_OK;
5bb7ca5d 696
3131601c 697 log_printf(LOGSYS_LEVEL_DEBUG, "got trackstart request on %p", conn);
5bb7ca5d
CC
698
699 /*
700 * If an immediate listing of the current cluster membership
701 * is requested, generate membership list
702 */
56eaee95
AS
703 if (req_lib_quorum_trackstart->track_flags & CS_TRACK_CURRENT ||
704 req_lib_quorum_trackstart->track_flags & CS_TRACK_CHANGES) {
3131601c 705 log_printf(LOGSYS_LEVEL_DEBUG, "sending initial status to %p", conn);
4eb36297 706 send_nodelist_library_notification(conn, 0);
c0772557 707 send_library_notification(conn);
5bb7ca5d
CC
708 }
709
82526d2f
CC
710 if (quorum_pd->tracking_enabled) {
711 error = CS_ERR_EXIST;
712 goto response_send;
713 }
714
5bb7ca5d
CC
715 /*
716 * Record requests for tracking
717 */
56eaee95
AS
718 if (req_lib_quorum_trackstart->track_flags & CS_TRACK_CHANGES ||
719 req_lib_quorum_trackstart->track_flags & CS_TRACK_CHANGES_ONLY) {
5bb7ca5d
CC
720
721 quorum_pd->track_flags = req_lib_quorum_trackstart->track_flags;
722 quorum_pd->tracking_enabled = 1;
723
b4c06e52 724 qb_list_add (&quorum_pd->list, &lib_trackers_list);
5bb7ca5d
CC
725 }
726
82526d2f 727response_send:
5bb7ca5d
CC
728 /* send status */
729 res.size = sizeof(res);
730 res.id = MESSAGE_RES_QUORUM_TRACKSTART;
82526d2f 731 res.error = error;
c6895faa 732 corosync_api->ipc_response_send(conn, &res, sizeof(struct qb_ipc_response_header));
5bb7ca5d
CC
733}
734
e0021727 735static void message_handler_req_lib_quorum_trackstop (void *conn, const void *msg)
5bb7ca5d 736{
c6895faa 737 struct qb_ipc_response_header res;
5bb7ca5d
CC
738 struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
739
3131601c 740 log_printf(LOGSYS_LEVEL_DEBUG, "got trackstop request on %p", conn);
5bb7ca5d
CC
741
742 if (quorum_pd->tracking_enabled) {
56eaee95 743 res.error = CS_OK;
5bb7ca5d 744 quorum_pd->tracking_enabled = 0;
b4c06e52
MJ
745 qb_list_del (&quorum_pd->list);
746 qb_list_init (&quorum_pd->list);
5bb7ca5d 747 } else {
56eaee95 748 res.error = CS_ERR_NOT_EXIST;
5bb7ca5d
CC
749 }
750
751 /* send status */
752 res.size = sizeof(res);
753 res.id = MESSAGE_RES_QUORUM_TRACKSTOP;
56eaee95 754 res.error = CS_OK;
c6895faa 755 corosync_api->ipc_response_send(conn, &res, sizeof(struct qb_ipc_response_header));
5bb7ca5d 756}
e34d509d
FDN
757
758static void message_handler_req_lib_quorum_gettype (void *conn,
759 const void *msg)
760{
761 struct res_lib_quorum_gettype res_lib_quorum_gettype;
762
3131601c 763 log_printf(LOGSYS_LEVEL_DEBUG, "got quorum_type request on %p", conn);
e34d509d
FDN
764
765 /* send status */
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));
771}
772
4eb36297
JF
773static void message_handler_req_lib_quorum_model_gettype (void *conn,
774 const void *msg)
775{
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);
779 cs_error_t ret_err;
780
781 log_printf(LOGSYS_LEVEL_DEBUG, "got quorum_model_type request on %p", conn);
782
783 ret_err = CS_OK;
784
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);
789
790 ret_err = CS_ERR_INVALID_PARAM;
791 } else {
792 quorum_pd->model = req_lib_quorum_model_gettype->model;
793 }
794
795 /* send status */
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));
801}