2 Copyright (C) 2010 Proxmox Server Solutions GmbH
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Affero General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Affero General Public License for more details.
14 You should have received a copy of the GNU Affero General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 Author: Dietmar Maurer <dietmar@proxmox.com>
21 #define G_LOG_DOMAIN "quorum"
25 #endif /* HAVE_CONFIG_H */
33 #include <corosync/quorum.h>
35 #include "cfs-utils.h"
40 quorum_handle_t handle
;
43 static void quorum_notification_fn(
44 quorum_handle_t handle
,
47 uint32_t view_list_entries
,
52 cfs_debug("quorum notification called, quorate = %d, "
53 "number of nodes = %d", quorate
, view_list_entries
);
55 qs_private_t
*private = NULL
;
57 result
= quorum_context_get(handle
, (gconstpointer
*)&private);
58 if (result
!= CS_OK
|| !private) {
59 cfs_critical("quorum_context_get error: %d (%p)", result
, private);
63 cfs_set_quorate(quorate
, FALSE
);
66 static quorum_callbacks_t quorum_callbacks
= {
67 .quorum_notify_fn
= quorum_notification_fn
,
70 static gboolean
service_quorum_finalize(
71 cfs_service_t
*service
,
74 g_return_val_if_fail(service
!= NULL
, FALSE
);
75 g_return_val_if_fail(context
!= NULL
, FALSE
);
77 qs_private_t
*private = (qs_private_t
*)context
;
78 quorum_handle_t handle
= private->handle
;
82 cfs_set_quorate(0, TRUE
);
84 result
= quorum_finalize(handle
);
86 if (result
!= CS_OK
) {
87 cfs_critical("quorum_finalize failed: %d", result
);
94 static int service_quorum_initialize(
95 cfs_service_t
*service
,
98 g_return_val_if_fail(service
!= NULL
, FALSE
);
99 g_return_val_if_fail(context
!= NULL
, FALSE
);
101 qs_private_t
*private = (qs_private_t
*)context
;
103 quorum_handle_t handle
= private->handle
;
106 if (!private->handle
) {
108 uint32_t quorum_type
;
110 result
= quorum_initialize(&handle
, &quorum_callbacks
, &quorum_type
);
111 if (result
!= CS_OK
) {
112 cfs_critical("quorum_initialize failed: %d", result
);
117 if (quorum_type
!= QUORUM_SET
) {
118 cfs_critical("quorum_initialize returned wron quorum_type: %d", quorum_type
);
119 quorum_finalize(handle
);
124 result
= quorum_context_set(handle
, private);
125 if (result
!= CS_OK
) {
126 cfs_critical("quorum_context_set failed: %d", result
);
127 quorum_finalize(handle
);
132 private->handle
= handle
;
136 result
= quorum_trackstart(handle
, CS_TRACK_CHANGES
);
137 if (result
== CS_ERR_LIBRARY
|| result
== CS_ERR_BAD_HANDLE
) {
138 cfs_critical("quorum_trackstart failed: %d - closing handle", result
);
139 quorum_finalize(handle
);
142 } else if (result
!= CS_OK
) {
143 cfs_critical("quorum_trackstart failed: %d - trying again", result
);
148 if ((result
= quorum_fd_get(handle
, &quorum_fd
)) != CS_OK
) {
149 cfs_critical("quorum_fd_get failed %d - trying again", result
);
156 static gboolean
service_quorum_dispatch(
157 cfs_service_t
*service
,
160 g_return_val_if_fail(service
!= NULL
, FALSE
);
161 g_return_val_if_fail(context
!= NULL
, FALSE
);
163 qs_private_t
*private = (qs_private_t
*)context
;
164 quorum_handle_t handle
= private->handle
;
170 result
= quorum_dispatch(handle
, CS_DISPATCH_ALL
);
171 if (result
== CS_ERR_TRY_AGAIN
) {
174 if ((retries
% 100) == 0)
175 cfs_message("quorum_dispatch retry %d", retries
);
180 if (result
== CS_OK
|| result
== CS_ERR_TRY_AGAIN
)
183 cfs_critical("quorum_dispatch failed: %d", result
);
185 quorum_finalize(handle
);
190 static cfs_service_callbacks_t cfs_quorum_callbacks
= {
191 .cfs_service_initialize_fn
= service_quorum_initialize
,
192 .cfs_service_finalize_fn
= service_quorum_finalize
,
193 .cfs_service_dispatch_fn
= service_quorum_dispatch
,
196 cfs_service_t
*service_quorum_new(void)
198 cfs_service_t
*service
;
200 qs_private_t
*private = g_new0(qs_private_t
, 1);
204 service
= cfs_service_new(&cfs_quorum_callbacks
, G_LOG_DOMAIN
, private);
209 void service_quorum_destroy(cfs_service_t
*service
)
211 g_return_if_fail(service
!= NULL
);
213 qs_private_t
*private =
214 (qs_private_t
*)cfs_service_get_context(service
);