4 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU General Public License v.2.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * CMAN communication layer for clvmd.
23 #define _FILE_OFFSET_BITS 64
25 #include <configure.h>
27 #include <sys/types.h>
29 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <sys/utsname.h>
36 #include <netinet/in.h>
45 #include <libdevmapper.h>
48 #include "clvmd-comms.h"
50 #include "lvm-logging.h"
52 #include "lvm-functions.h"
54 #define LOCKSPACE_NAME "clvmd"
58 struct cman_node
*node
;
63 static struct cman_node
*nodes
= NULL
;
64 static struct cman_node this_node
;
65 static int count_nodes
; /* size of allocated nodes array */
66 static struct dm_hash_table
*node_updown_hash
;
67 static dlm_lshandle_t
*lockspace
;
68 static cman_handle_t c_handle
;
70 static void count_clvmds_running(void);
71 static void get_members(void);
72 static int nodeid_from_csid(const char *csid
);
73 static int name_from_nodeid(int nodeid
, char *name
);
74 static void event_callback(cman_handle_t handle
, void *private, int reason
, int arg
);
75 static void data_callback(cman_handle_t handle
, void *private,
76 char *buf
, int len
, uint8_t port
, int nodeid
);
80 pthread_mutex_t mutex
;
84 static int _init_cluster(void)
86 node_updown_hash
= dm_hash_create(100);
88 /* Open the cluster communication socket */
89 c_handle
= cman_init(NULL
);
91 syslog(LOG_ERR
, "Can't open cluster manager socket: %m");
94 DEBUGLOG("Connected to CMAN\n");
96 if (cman_start_recv_data(c_handle
, data_callback
, CLUSTER_PORT_CLVMD
)) {
97 syslog(LOG_ERR
, "Can't bind cluster socket: %m");
101 if (cman_start_notification(c_handle
, event_callback
)) {
102 syslog(LOG_ERR
, "Can't start cluster event listening");
106 /* Get the cluster members list */
108 count_clvmds_running();
110 DEBUGLOG("CMAN initialisation complete\n");
112 /* Create a lockspace for LV & VG locks to live in */
113 lockspace
= dlm_create_lockspace(LOCKSPACE_NAME
, 0600);
115 if (errno
== EEXIST
) {
116 lockspace
= dlm_open_lockspace(LOCKSPACE_NAME
);
119 syslog(LOG_ERR
, "Unable to create lockspace for CLVM: %m");
123 dlm_ls_pthread_init(lockspace
);
124 DEBUGLOG("DLM initialisation complete\n");
128 static void _cluster_init_completed(void)
130 clvmd_cluster_init_completed();
133 static int _get_main_cluster_fd()
135 return cman_get_fd(c_handle
);
138 static int _get_num_nodes()
143 /* return number of ACTIVE nodes */
144 for (i
=0; i
<num_nodes
; i
++) {
145 if (nodes
[i
].cn_member
&& nodes
[i
].cn_nodeid
)
151 /* send_message with the fd check removed */
152 static int _cluster_send_message(const void *buf
, int msglen
, const char *csid
,
158 memcpy(&nodeid
, csid
, CMAN_MAX_CSID_LEN
);
160 if (cman_send_data(c_handle
, buf
, msglen
, 0, CLUSTER_PORT_CLVMD
, nodeid
) <= 0)
162 log_error("%s", errtext
);
167 static void _get_our_csid(char *csid
)
169 if (this_node
.cn_nodeid
== 0) {
170 cman_get_node(c_handle
, 0, &this_node
);
172 memcpy(csid
, &this_node
.cn_nodeid
, CMAN_MAX_CSID_LEN
);
175 /* Call a callback routine for each node is that known (down means not running a clvmd) */
176 static int _cluster_do_node_callback(struct local_client
*client
,
177 void (*callback
) (struct local_client
*,
184 for (i
= 0; i
< _get_num_nodes(); i
++) {
185 if (nodes
[i
].cn_member
&& nodes
[i
].cn_nodeid
) {
186 int up
= (int)(long)dm_hash_lookup_binary(node_updown_hash
, (char *)&nodes
[i
].cn_nodeid
, sizeof(int));
188 callback(client
, (char *)&nodes
[i
].cn_nodeid
, up
);
196 /* Process OOB messages from the cluster socket */
197 static void event_callback(cman_handle_t handle
, void *private, int reason
, int arg
)
199 char namebuf
[MAX_CLUSTER_MEMBER_NAME_LEN
];
202 case CMAN_REASON_PORTCLOSED
:
203 name_from_nodeid(arg
, namebuf
);
204 log_notice("clvmd on node %s has died\n", namebuf
);
205 DEBUGLOG("Got port closed message, removing node %s\n", namebuf
);
207 dm_hash_insert_binary(node_updown_hash
, (char *)&arg
, sizeof(int), (void *)0);
210 case CMAN_REASON_STATECHANGE
:
211 DEBUGLOG("Got state change message, re-reading members list\n");
215 #if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
216 case CMAN_REASON_PORTOPENED
:
217 /* Ignore this, wait for startup message from clvmd itself */
220 case CMAN_REASON_TRY_SHUTDOWN
:
221 DEBUGLOG("Got try shutdown, sending OK\n");
222 cman_replyto_shutdown(c_handle
, 1);
227 DEBUGLOG("Got unknown event callback message: %d\n", reason
);
232 static struct local_client
*cman_client
;
233 static int _cluster_fd_callback(struct local_client
*fd
, char *buf
, int len
,
235 struct local_client
**new_client
)
238 /* Save this for data_callback */
241 /* We never return a new client */
244 return cman_dispatch(c_handle
, 0);
248 static void data_callback(cman_handle_t handle
, void *private,
249 char *buf
, int len
, uint8_t port
, int nodeid
)
251 /* Ignore looped back messages */
252 if (nodeid
== this_node
.cn_nodeid
)
254 process_message(cman_client
, buf
, len
, (char *)&nodeid
);
257 static void _add_up_node(const char *csid
)
260 int nodeid
= nodeid_from_csid(csid
);
262 dm_hash_insert_binary(node_updown_hash
, (char *)&nodeid
, sizeof(int), (void *)1);
263 DEBUGLOG("Added new node %d to updown list\n", nodeid
);
266 static void _cluster_closedown()
269 dlm_release_lockspace(LOCKSPACE_NAME
, lockspace
, 1);
270 cman_finish(c_handle
);
273 static int is_listening(int nodeid
)
278 status
= cman_is_listening(c_handle
, nodeid
, CLUSTER_PORT_CLVMD
);
279 if (status
< 0 && errno
== EBUSY
) { /* Don't busywait */
281 errno
= EBUSY
; /* In case sleep trashes it */
284 while (status
< 0 && errno
== EBUSY
);
289 /* Populate the list of CLVMDs running.
290 called only at startup time */
291 static void count_clvmds_running(void)
295 for (i
= 0; i
< num_nodes
; i
++) {
296 int nodeid
= nodes
[i
].cn_nodeid
;
298 if (is_listening(nodeid
) == 1)
299 dm_hash_insert_binary(node_updown_hash
, (void *)&nodeid
, sizeof(int), (void*)1);
301 dm_hash_insert_binary(node_updown_hash
, (void *)&nodeid
, sizeof(int), (void*)0);
305 /* Get a list of active cluster members */
306 static void get_members()
313 num_nodes
= cman_get_node_count(c_handle
);
314 if (num_nodes
== -1) {
315 log_error("Unable to get node count");
319 /* Not enough room for new nodes list ? */
320 if (num_nodes
> count_nodes
&& nodes
) {
326 count_nodes
= num_nodes
+ 10; /* Overallocate a little */
327 nodes
= malloc(count_nodes
* sizeof(struct cman_node
));
329 log_error("Unable to allocate nodes array\n");
334 status
= cman_get_nodes(c_handle
, count_nodes
, &retnodes
, nodes
);
336 log_error("Unable to get node details");
340 /* Get the highest nodeid */
341 for (i
=0; i
<retnodes
; i
++) {
342 if (nodes
[i
].cn_nodeid
> high_nodeid
)
343 high_nodeid
= nodes
[i
].cn_nodeid
;
348 /* Convert a node name to a CSID */
349 static int _csid_from_name(char *csid
, const char *name
)
353 for (i
= 0; i
< num_nodes
; i
++) {
354 if (strcmp(name
, nodes
[i
].cn_name
) == 0) {
355 memcpy(csid
, &nodes
[i
].cn_nodeid
, CMAN_MAX_CSID_LEN
);
362 /* Convert a CSID to a node name */
363 static int _name_from_csid(const char *csid
, char *name
)
367 for (i
= 0; i
< num_nodes
; i
++) {
368 if (memcmp(csid
, &nodes
[i
].cn_nodeid
, CMAN_MAX_CSID_LEN
) == 0) {
369 strcpy(name
, nodes
[i
].cn_name
);
374 strcpy(name
, "Unknown");
378 /* Convert a node ID to a node name */
379 static int name_from_nodeid(int nodeid
, char *name
)
383 for (i
= 0; i
< num_nodes
; i
++) {
384 if (nodeid
== nodes
[i
].cn_nodeid
) {
385 strcpy(name
, nodes
[i
].cn_name
);
390 strcpy(name
, "Unknown");
394 /* Convert a CSID to a node ID */
395 static int nodeid_from_csid(const char *csid
)
399 memcpy(&nodeid
, csid
, CMAN_MAX_CSID_LEN
);
404 static int _is_quorate()
406 return cman_is_quorate(c_handle
);
409 static void sync_ast_routine(void *arg
)
411 struct lock_wait
*lwait
= arg
;
413 pthread_mutex_lock(&lwait
->mutex
);
414 pthread_cond_signal(&lwait
->cond
);
415 pthread_mutex_unlock(&lwait
->mutex
);
418 static int _sync_lock(const char *resource
, int mode
, int flags
, int *lockid
)
421 struct lock_wait lwait
;
428 DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource
,mode
,flags
);
429 /* Conversions need the lockid in the LKSB */
430 if (flags
& LKF_CONVERT
)
431 lwait
.lksb
.sb_lkid
= *lockid
;
433 pthread_cond_init(&lwait
.cond
, NULL
);
434 pthread_mutex_init(&lwait
.mutex
, NULL
);
435 pthread_mutex_lock(&lwait
.mutex
);
437 status
= dlm_ls_lock(lockspace
,
443 0, sync_ast_routine
, &lwait
, NULL
, NULL
);
447 /* Wait for it to complete */
448 pthread_cond_wait(&lwait
.cond
, &lwait
.mutex
);
449 pthread_mutex_unlock(&lwait
.mutex
);
451 *lockid
= lwait
.lksb
.sb_lkid
;
453 errno
= lwait
.lksb
.sb_status
;
454 DEBUGLOG("sync_lock: returning lkid %x\n", *lockid
);
455 if (lwait
.lksb
.sb_status
)
461 static int _sync_unlock(const char *resource
/* UNUSED */, int lockid
)
464 struct lock_wait lwait
;
466 DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource
, lockid
);
468 pthread_cond_init(&lwait
.cond
, NULL
);
469 pthread_mutex_init(&lwait
.mutex
, NULL
);
470 pthread_mutex_lock(&lwait
.mutex
);
472 status
= dlm_ls_unlock(lockspace
, lockid
, 0, &lwait
.lksb
, &lwait
);
477 /* Wait for it to complete */
478 pthread_cond_wait(&lwait
.cond
, &lwait
.mutex
);
479 pthread_mutex_unlock(&lwait
.mutex
);
481 errno
= lwait
.lksb
.sb_status
;
482 if (lwait
.lksb
.sb_status
!= EUNLOCK
)
489 static int _get_cluster_name(char *buf
, int buflen
)
491 cman_cluster_t cluster_info
;
494 status
= cman_get_cluster(c_handle
, &cluster_info
);
496 strncpy(buf
, cluster_info
.ci_name
, buflen
);
501 static struct cluster_ops _cluster_cman_ops
= {
502 .cluster_init_completed
= _cluster_init_completed
,
503 .cluster_send_message
= _cluster_send_message
,
504 .name_from_csid
= _name_from_csid
,
505 .csid_from_name
= _csid_from_name
,
506 .get_num_nodes
= _get_num_nodes
,
507 .cluster_fd_callback
= _cluster_fd_callback
,
508 .get_main_cluster_fd
= _get_main_cluster_fd
,
509 .cluster_do_node_callback
= _cluster_do_node_callback
,
510 .is_quorate
= _is_quorate
,
511 .get_our_csid
= _get_our_csid
,
512 .add_up_node
= _add_up_node
,
513 .cluster_closedown
= _cluster_closedown
,
514 .get_cluster_name
= _get_cluster_name
,
515 .sync_lock
= _sync_lock
,
516 .sync_unlock
= _sync_unlock
,
519 struct cluster_ops
*init_cman_cluster(void)
521 if (!_init_cluster())
522 return &_cluster_cman_ops
;