Home | History | Annotate | Line # | Download | only in clvmd
      1      1.1  haad /*	$NetBSD: clvmd-corosync.c,v 1.1.1.2 2009/12/02 00:27:02 haad Exp $	*/
      2      1.1  haad 
      3  1.1.1.2  haad /*
      4  1.1.1.2  haad  * Copyright (C) 2009 Red Hat, Inc. All rights reserved.
      5  1.1.1.2  haad  *
      6  1.1.1.2  haad  * This file is part of LVM2.
      7  1.1.1.2  haad  *
      8  1.1.1.2  haad  * This copyrighted material is made available to anyone wishing to use,
      9  1.1.1.2  haad  * modify, copy, or redistribute it subject to the terms and conditions
     10  1.1.1.2  haad  * of the GNU Lesser General Public License v.2.1.
     11  1.1.1.2  haad  *
     12  1.1.1.2  haad  * You should have received a copy of the GNU Lesser General Public License
     13  1.1.1.2  haad  * along with this program; if not, write to the Free Software Foundation,
     14  1.1.1.2  haad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     15  1.1.1.2  haad  */
     16      1.1  haad 
     17  1.1.1.2  haad /*
     18  1.1.1.2  haad  * This provides the interface between clvmd and corosync/DLM as the cluster
     19      1.1  haad  * and lock manager.
     20      1.1  haad  */
     21      1.1  haad 
     22      1.1  haad #define _GNU_SOURCE
     23      1.1  haad #define _FILE_OFFSET_BITS 64
     24      1.1  haad 
     25      1.1  haad #include <configure.h>
     26      1.1  haad #include <pthread.h>
     27      1.1  haad #include <sys/types.h>
     28      1.1  haad #include <sys/utsname.h>
     29      1.1  haad #include <sys/ioctl.h>
     30      1.1  haad #include <sys/socket.h>
     31      1.1  haad #include <sys/stat.h>
     32      1.1  haad #include <sys/file.h>
     33      1.1  haad #include <sys/socket.h>
     34      1.1  haad #include <netinet/in.h>
     35      1.1  haad #include <stdio.h>
     36      1.1  haad #include <stdlib.h>
     37      1.1  haad #include <stdint.h>
     38      1.1  haad #include <signal.h>
     39      1.1  haad #include <fcntl.h>
     40      1.1  haad #include <string.h>
     41      1.1  haad #include <stddef.h>
     42      1.1  haad #include <stdint.h>
     43      1.1  haad #include <unistd.h>
     44      1.1  haad #include <errno.h>
     45      1.1  haad #include <utmpx.h>
     46      1.1  haad #include <syslog.h>
     47      1.1  haad #include <assert.h>
     48      1.1  haad #include <libdevmapper.h>
     49      1.1  haad 
     50      1.1  haad #include <corosync/corotypes.h>
     51      1.1  haad #include <corosync/cpg.h>
     52      1.1  haad #include <corosync/quorum.h>
     53  1.1.1.2  haad #include <corosync/confdb.h>
     54      1.1  haad #include <libdlm.h>
     55      1.1  haad 
     56      1.1  haad #include "locking.h"
     57      1.1  haad #include "lvm-logging.h"
     58      1.1  haad #include "clvm.h"
     59      1.1  haad #include "clvmd-comms.h"
     60      1.1  haad #include "lvm-functions.h"
     61      1.1  haad #include "clvmd.h"
     62      1.1  haad 
     63      1.1  haad /* Timeout value for several corosync calls */
     64      1.1  haad #define LOCKSPACE_NAME "clvmd"
     65      1.1  haad 
     66  1.1.1.2  haad static void corosync_cpg_deliver_callback (cpg_handle_t handle,
     67  1.1.1.2  haad 				  const struct cpg_name *groupName,
     68      1.1  haad 				  uint32_t nodeid,
     69      1.1  haad 				  uint32_t pid,
     70      1.1  haad 				  void *msg,
     71  1.1.1.2  haad 				  size_t msg_len);
     72  1.1.1.2  haad static void corosync_cpg_confchg_callback(cpg_handle_t handle,
     73  1.1.1.2  haad 				 const struct cpg_name *groupName,
     74  1.1.1.2  haad 				 const struct cpg_address *member_list, size_t member_list_entries,
     75  1.1.1.2  haad 				 const struct cpg_address *left_list, size_t left_list_entries,
     76  1.1.1.2  haad 				 const struct cpg_address *joined_list, size_t joined_list_entries);
     77      1.1  haad static void _cluster_closedown(void);
     78      1.1  haad 
     79      1.1  haad /* Hash list of nodes in the cluster */
     80      1.1  haad static struct dm_hash_table *node_hash;
     81      1.1  haad 
     82      1.1  haad /* Number of active nodes */
     83      1.1  haad static int num_nodes;
     84      1.1  haad static unsigned int our_nodeid;
     85      1.1  haad 
     86      1.1  haad static struct local_client *cluster_client;
     87      1.1  haad 
     88      1.1  haad /* Corosync handles */
     89      1.1  haad static cpg_handle_t cpg_handle;
     90      1.1  haad static quorum_handle_t quorum_handle;
     91      1.1  haad 
     92      1.1  haad /* DLM Handle */
     93      1.1  haad static dlm_lshandle_t *lockspace;
     94      1.1  haad 
     95      1.1  haad static struct cpg_name cpg_group_name;
     96      1.1  haad 
     97      1.1  haad /* Corosync callback structs */
     98  1.1.1.2  haad cpg_callbacks_t corosync_cpg_callbacks = {
     99  1.1.1.2  haad 	.cpg_deliver_fn =            corosync_cpg_deliver_callback,
    100  1.1.1.2  haad 	.cpg_confchg_fn =            corosync_cpg_confchg_callback,
    101      1.1  haad };
    102      1.1  haad 
    103      1.1  haad quorum_callbacks_t quorum_callbacks = {
    104      1.1  haad 	.quorum_notify_fn = NULL,
    105      1.1  haad };
    106      1.1  haad 
    107      1.1  haad struct node_info
    108      1.1  haad {
    109      1.1  haad 	enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
    110      1.1  haad 	int nodeid;
    111      1.1  haad };
    112      1.1  haad 
    113      1.1  haad 
    114      1.1  haad /* Set errno to something approximating the right value and return 0 or -1 */
    115      1.1  haad static int cs_to_errno(cs_error_t err)
    116      1.1  haad {
    117      1.1  haad 	switch(err)
    118      1.1  haad 	{
    119      1.1  haad 	case CS_OK:
    120      1.1  haad 		return 0;
    121      1.1  haad         case CS_ERR_LIBRARY:
    122      1.1  haad 		errno = EINVAL;
    123      1.1  haad 		break;
    124      1.1  haad         case CS_ERR_VERSION:
    125      1.1  haad 		errno = EINVAL;
    126      1.1  haad 		break;
    127      1.1  haad         case CS_ERR_INIT:
    128      1.1  haad 		errno = EINVAL;
    129      1.1  haad 		break;
    130      1.1  haad         case CS_ERR_TIMEOUT:
    131      1.1  haad 		errno = ETIME;
    132      1.1  haad 		break;
    133      1.1  haad         case CS_ERR_TRY_AGAIN:
    134      1.1  haad 		errno = EAGAIN;
    135      1.1  haad 		break;
    136      1.1  haad         case CS_ERR_INVALID_PARAM:
    137      1.1  haad 		errno = EINVAL;
    138      1.1  haad 		break;
    139      1.1  haad         case CS_ERR_NO_MEMORY:
    140      1.1  haad 		errno = ENOMEM;
    141      1.1  haad 		break;
    142      1.1  haad         case CS_ERR_BAD_HANDLE:
    143      1.1  haad 		errno = EINVAL;
    144      1.1  haad 		break;
    145      1.1  haad         case CS_ERR_BUSY:
    146      1.1  haad 		errno = EBUSY;
    147      1.1  haad 		break;
    148      1.1  haad         case CS_ERR_ACCESS:
    149      1.1  haad 		errno = EPERM;
    150      1.1  haad 		break;
    151      1.1  haad         case CS_ERR_NOT_EXIST:
    152      1.1  haad 		errno = ENOENT;
    153      1.1  haad 		break;
    154      1.1  haad         case CS_ERR_NAME_TOO_LONG:
    155      1.1  haad 		errno = ENAMETOOLONG;
    156      1.1  haad 		break;
    157      1.1  haad         case CS_ERR_EXIST:
    158      1.1  haad 		errno = EEXIST;
    159      1.1  haad 		break;
    160      1.1  haad         case CS_ERR_NO_SPACE:
    161      1.1  haad 		errno = ENOSPC;
    162      1.1  haad 		break;
    163      1.1  haad         case CS_ERR_INTERRUPT:
    164      1.1  haad 		errno = EINTR;
    165      1.1  haad 		break;
    166      1.1  haad 	case CS_ERR_NAME_NOT_FOUND:
    167      1.1  haad 		errno = ENOENT;
    168      1.1  haad 		break;
    169      1.1  haad         case CS_ERR_NO_RESOURCES:
    170      1.1  haad 		errno = ENOMEM;
    171      1.1  haad 		break;
    172      1.1  haad         case CS_ERR_NOT_SUPPORTED:
    173      1.1  haad 		errno = EOPNOTSUPP;
    174      1.1  haad 		break;
    175      1.1  haad         case CS_ERR_BAD_OPERATION:
    176      1.1  haad 		errno = EINVAL;
    177      1.1  haad 		break;
    178      1.1  haad         case CS_ERR_FAILED_OPERATION:
    179      1.1  haad 		errno = EIO;
    180      1.1  haad 		break;
    181      1.1  haad         case CS_ERR_MESSAGE_ERROR:
    182      1.1  haad 		errno = EIO;
    183      1.1  haad 		break;
    184      1.1  haad         case CS_ERR_QUEUE_FULL:
    185      1.1  haad 		errno = EXFULL;
    186      1.1  haad 		break;
    187      1.1  haad         case CS_ERR_QUEUE_NOT_AVAILABLE:
    188      1.1  haad 		errno = EINVAL;
    189      1.1  haad 		break;
    190      1.1  haad         case CS_ERR_BAD_FLAGS:
    191      1.1  haad 		errno = EINVAL;
    192      1.1  haad 		break;
    193      1.1  haad         case CS_ERR_TOO_BIG:
    194      1.1  haad 		errno = E2BIG;
    195      1.1  haad 		break;
    196      1.1  haad         case CS_ERR_NO_SECTIONS:
    197      1.1  haad 		errno = ENOMEM;
    198      1.1  haad 		break;
    199      1.1  haad 	default:
    200      1.1  haad 		errno = EINVAL;
    201      1.1  haad 		break;
    202      1.1  haad 	}
    203      1.1  haad 	return -1;
    204      1.1  haad }
    205      1.1  haad 
    206  1.1.1.2  haad static char *print_corosync_csid(const char *csid)
    207      1.1  haad {
    208      1.1  haad 	static char buf[128];
    209      1.1  haad 	int id;
    210      1.1  haad 
    211      1.1  haad 	memcpy(&id, csid, sizeof(int));
    212      1.1  haad 	sprintf(buf, "%d", id);
    213      1.1  haad 	return buf;
    214      1.1  haad }
    215      1.1  haad 
    216  1.1.1.2  haad static void corosync_cpg_deliver_callback (cpg_handle_t handle,
    217  1.1.1.2  haad 				  const struct cpg_name *groupName,
    218      1.1  haad 				  uint32_t nodeid,
    219      1.1  haad 				  uint32_t pid,
    220      1.1  haad 				  void *msg,
    221  1.1.1.2  haad 				  size_t msg_len)
    222      1.1  haad {
    223      1.1  haad 	int target_nodeid;
    224      1.1  haad 
    225      1.1  haad 	memcpy(&target_nodeid, msg, COROSYNC_CSID_LEN);
    226      1.1  haad 
    227  1.1.1.2  haad 	DEBUGLOG("%u got message from nodeid %d for %d. len %zd\n",
    228      1.1  haad 		 our_nodeid, nodeid, target_nodeid, msg_len-4);
    229      1.1  haad 
    230      1.1  haad 	if (nodeid != our_nodeid)
    231      1.1  haad 		if (target_nodeid == our_nodeid || target_nodeid == 0)
    232      1.1  haad 			process_message(cluster_client, (char *)msg+COROSYNC_CSID_LEN,
    233      1.1  haad 					msg_len-COROSYNC_CSID_LEN, (char*)&nodeid);
    234      1.1  haad }
    235      1.1  haad 
    236  1.1.1.2  haad static void corosync_cpg_confchg_callback(cpg_handle_t handle,
    237  1.1.1.2  haad 				 const struct cpg_name *groupName,
    238  1.1.1.2  haad 				 const struct cpg_address *member_list, size_t member_list_entries,
    239  1.1.1.2  haad 				 const struct cpg_address *left_list, size_t left_list_entries,
    240  1.1.1.2  haad 				 const struct cpg_address *joined_list, size_t joined_list_entries)
    241      1.1  haad {
    242      1.1  haad 	int i;
    243      1.1  haad 	struct node_info *ninfo;
    244      1.1  haad 
    245  1.1.1.2  haad 	DEBUGLOG("confchg callback. %zd joined, %zd left, %zd members\n",
    246      1.1  haad 		 joined_list_entries, left_list_entries, member_list_entries);
    247      1.1  haad 
    248      1.1  haad 	for (i=0; i<joined_list_entries; i++) {
    249      1.1  haad 		ninfo = dm_hash_lookup_binary(node_hash,
    250      1.1  haad 					      (char *)&joined_list[i].nodeid,
    251      1.1  haad 					      COROSYNC_CSID_LEN);
    252      1.1  haad 		if (!ninfo) {
    253      1.1  haad 			ninfo = malloc(sizeof(struct node_info));
    254      1.1  haad 			if (!ninfo) {
    255      1.1  haad 				break;
    256      1.1  haad 			}
    257      1.1  haad 			else {
    258      1.1  haad 				ninfo->nodeid = joined_list[i].nodeid;
    259      1.1  haad 				dm_hash_insert_binary(node_hash,
    260      1.1  haad 						      (char *)&ninfo->nodeid,
    261      1.1  haad 						      COROSYNC_CSID_LEN, ninfo);
    262      1.1  haad 			}
    263      1.1  haad 		}
    264      1.1  haad 		ninfo->state = NODE_CLVMD;
    265      1.1  haad 	}
    266      1.1  haad 
    267      1.1  haad 	for (i=0; i<left_list_entries; i++) {
    268      1.1  haad 		ninfo = dm_hash_lookup_binary(node_hash,
    269      1.1  haad 					      (char *)&left_list[i].nodeid,
    270      1.1  haad 					      COROSYNC_CSID_LEN);
    271      1.1  haad 		if (ninfo)
    272      1.1  haad 			ninfo->state = NODE_DOWN;
    273      1.1  haad 	}
    274      1.1  haad 
    275      1.1  haad 	for (i=0; i<member_list_entries; i++) {
    276      1.1  haad 		if (member_list[i].nodeid == 0) continue;
    277      1.1  haad 		ninfo = dm_hash_lookup_binary(node_hash,
    278      1.1  haad 				(char *)&member_list[i].nodeid,
    279      1.1  haad 				COROSYNC_CSID_LEN);
    280      1.1  haad 		if (!ninfo) {
    281      1.1  haad 			ninfo = malloc(sizeof(struct node_info));
    282      1.1  haad 			if (!ninfo) {
    283      1.1  haad 				break;
    284      1.1  haad 			}
    285      1.1  haad 			else {
    286      1.1  haad 				ninfo->nodeid = member_list[i].nodeid;
    287      1.1  haad 				dm_hash_insert_binary(node_hash,
    288      1.1  haad 						(char *)&ninfo->nodeid,
    289      1.1  haad 						COROSYNC_CSID_LEN, ninfo);
    290      1.1  haad 			}
    291      1.1  haad 		}
    292      1.1  haad 		ninfo->state = NODE_CLVMD;
    293      1.1  haad 	}
    294      1.1  haad 
    295      1.1  haad 	num_nodes = member_list_entries;
    296      1.1  haad }
    297      1.1  haad 
    298      1.1  haad static int _init_cluster(void)
    299      1.1  haad {
    300      1.1  haad 	cs_error_t err;
    301      1.1  haad 
    302      1.1  haad 	node_hash = dm_hash_create(100);
    303      1.1  haad 
    304      1.1  haad 	err = cpg_initialize(&cpg_handle,
    305  1.1.1.2  haad 			     &corosync_cpg_callbacks);
    306      1.1  haad 	if (err != CS_OK) {
    307      1.1  haad 		syslog(LOG_ERR, "Cannot initialise Corosync CPG service: %d",
    308      1.1  haad 		       err);
    309      1.1  haad 		DEBUGLOG("Cannot initialise Corosync CPG service: %d", err);
    310      1.1  haad 		return cs_to_errno(err);
    311      1.1  haad 	}
    312      1.1  haad 
    313      1.1  haad 	err = quorum_initialize(&quorum_handle,
    314      1.1  haad 				&quorum_callbacks);
    315      1.1  haad 	if (err != CS_OK) {
    316      1.1  haad 		syslog(LOG_ERR, "Cannot initialise Corosync quorum service: %d",
    317      1.1  haad 		       err);
    318      1.1  haad 		DEBUGLOG("Cannot initialise Corosync quorum service: %d", err);
    319      1.1  haad 		return cs_to_errno(err);
    320      1.1  haad 	}
    321      1.1  haad 
    322      1.1  haad 
    323      1.1  haad 	/* Create a lockspace for LV & VG locks to live in */
    324      1.1  haad 	lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
    325      1.1  haad 	if (!lockspace) {
    326  1.1.1.2  haad 		if (errno == EEXIST) {
    327  1.1.1.2  haad 			lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
    328  1.1.1.2  haad 		}
    329  1.1.1.2  haad 		if (!lockspace) {
    330  1.1.1.2  haad 			syslog(LOG_ERR, "Unable to create lockspace for CLVM: %m");
    331  1.1.1.2  haad 			quorum_finalize(quorum_handle);
    332  1.1.1.2  haad 			return -1;
    333  1.1.1.2  haad 		}
    334      1.1  haad 	}
    335      1.1  haad 	dlm_ls_pthread_init(lockspace);
    336      1.1  haad 	DEBUGLOG("DLM initialisation complete\n");
    337      1.1  haad 
    338      1.1  haad 	/* Connect to the clvmd group */
    339      1.1  haad 	strcpy((char *)cpg_group_name.value, "clvmd");
    340      1.1  haad 	cpg_group_name.length = strlen((char *)cpg_group_name.value);
    341      1.1  haad 	err = cpg_join(cpg_handle, &cpg_group_name);
    342      1.1  haad 	if (err != CS_OK) {
    343      1.1  haad 		cpg_finalize(cpg_handle);
    344      1.1  haad 		quorum_finalize(quorum_handle);
    345  1.1.1.2  haad 		dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
    346      1.1  haad 		syslog(LOG_ERR, "Cannot join clvmd process group");
    347      1.1  haad 		DEBUGLOG("Cannot join clvmd process group: %d\n", err);
    348      1.1  haad 		return cs_to_errno(err);
    349      1.1  haad 	}
    350      1.1  haad 
    351      1.1  haad 	err = cpg_local_get(cpg_handle,
    352      1.1  haad 			    &our_nodeid);
    353      1.1  haad 	if (err != CS_OK) {
    354      1.1  haad 		cpg_finalize(cpg_handle);
    355      1.1  haad 		quorum_finalize(quorum_handle);
    356  1.1.1.2  haad 		dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
    357      1.1  haad 		syslog(LOG_ERR, "Cannot get local node id\n");
    358      1.1  haad 		return cs_to_errno(err);
    359      1.1  haad 	}
    360      1.1  haad 	DEBUGLOG("Our local node id is %d\n", our_nodeid);
    361      1.1  haad 
    362      1.1  haad 	DEBUGLOG("Connected to Corosync\n");
    363      1.1  haad 
    364      1.1  haad 	return 0;
    365      1.1  haad }
    366      1.1  haad 
    367      1.1  haad static void _cluster_closedown(void)
    368      1.1  haad {
    369      1.1  haad 	DEBUGLOG("cluster_closedown\n");
    370  1.1.1.2  haad 	destroy_lvhash();
    371      1.1  haad 
    372  1.1.1.2  haad 	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
    373      1.1  haad 	cpg_finalize(cpg_handle);
    374      1.1  haad 	quorum_finalize(quorum_handle);
    375      1.1  haad }
    376      1.1  haad 
    377      1.1  haad static void _get_our_csid(char *csid)
    378      1.1  haad {
    379      1.1  haad 	memcpy(csid, &our_nodeid, sizeof(int));
    380      1.1  haad }
    381      1.1  haad 
    382      1.1  haad /* Corosync doesn't really have nmode names so we
    383      1.1  haad    just use the node ID in hex instead */
    384      1.1  haad static int _csid_from_name(char *csid, const char *name)
    385      1.1  haad {
    386      1.1  haad 	int nodeid;
    387      1.1  haad 	struct node_info *ninfo;
    388      1.1  haad 
    389      1.1  haad 	if (sscanf(name, "%x", &nodeid) == 1) {
    390      1.1  haad 		ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
    391      1.1  haad 		if (ninfo)
    392      1.1  haad 			return nodeid;
    393      1.1  haad 	}
    394      1.1  haad 	return -1;
    395      1.1  haad }
    396      1.1  haad 
    397      1.1  haad static int _name_from_csid(const char *csid, char *name)
    398      1.1  haad {
    399      1.1  haad 	struct node_info *ninfo;
    400      1.1  haad 
    401      1.1  haad 	ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
    402      1.1  haad 	if (!ninfo)
    403      1.1  haad 	{
    404  1.1.1.2  haad 		sprintf(name, "UNKNOWN %s", print_corosync_csid(csid));
    405      1.1  haad 		return -1;
    406      1.1  haad 	}
    407      1.1  haad 
    408      1.1  haad 	sprintf(name, "%x", ninfo->nodeid);
    409      1.1  haad 	return 0;
    410      1.1  haad }
    411      1.1  haad 
    412      1.1  haad static int _get_num_nodes()
    413      1.1  haad {
    414      1.1  haad 	DEBUGLOG("num_nodes = %d\n", num_nodes);
    415      1.1  haad 	return num_nodes;
    416      1.1  haad }
    417      1.1  haad 
    418      1.1  haad /* Node is now known to be running a clvmd */
    419      1.1  haad static void _add_up_node(const char *csid)
    420      1.1  haad {
    421      1.1  haad 	struct node_info *ninfo;
    422      1.1  haad 
    423      1.1  haad 	ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
    424      1.1  haad 	if (!ninfo) {
    425      1.1  haad 		DEBUGLOG("corosync_add_up_node no node_hash entry for csid %s\n",
    426  1.1.1.2  haad 			 print_corosync_csid(csid));
    427      1.1  haad 		return;
    428      1.1  haad 	}
    429      1.1  haad 
    430      1.1  haad 	DEBUGLOG("corosync_add_up_node %d\n", ninfo->nodeid);
    431      1.1  haad 
    432      1.1  haad 	ninfo->state = NODE_CLVMD;
    433      1.1  haad 
    434      1.1  haad 	return;
    435      1.1  haad }
    436      1.1  haad 
    437      1.1  haad /* Call a callback for each node, so the caller knows whether it's up or down */
    438      1.1  haad static int _cluster_do_node_callback(struct local_client *master_client,
    439      1.1  haad 				     void (*callback)(struct local_client *,
    440      1.1  haad 						      const char *csid, int node_up))
    441      1.1  haad {
    442      1.1  haad 	struct dm_hash_node *hn;
    443      1.1  haad 	struct node_info *ninfo;
    444      1.1  haad 	int somedown = 0;
    445      1.1  haad 
    446      1.1  haad 	dm_hash_iterate(hn, node_hash)
    447      1.1  haad 	{
    448      1.1  haad 		char csid[COROSYNC_CSID_LEN];
    449      1.1  haad 
    450      1.1  haad 		ninfo = dm_hash_get_data(node_hash, hn);
    451      1.1  haad 		memcpy(csid, dm_hash_get_key(node_hash, hn), COROSYNC_CSID_LEN);
    452      1.1  haad 
    453      1.1  haad 		DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
    454      1.1  haad 			 ninfo->state);
    455      1.1  haad 
    456      1.1  haad 		if (ninfo->state != NODE_DOWN)
    457      1.1  haad 			callback(master_client, csid, ninfo->state == NODE_CLVMD);
    458      1.1  haad 		if (ninfo->state != NODE_CLVMD)
    459      1.1  haad 			somedown = -1;
    460      1.1  haad 	}
    461      1.1  haad 	return somedown;
    462      1.1  haad }
    463      1.1  haad 
    464      1.1  haad /* Real locking */
    465      1.1  haad static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
    466      1.1  haad {
    467      1.1  haad 	struct dlm_lksb lksb;
    468      1.1  haad 	int err;
    469      1.1  haad 
    470      1.1  haad 	DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
    471      1.1  haad 
    472      1.1  haad 	if (flags & LKF_CONVERT)
    473      1.1  haad 		lksb.sb_lkid = *lockid;
    474      1.1  haad 
    475      1.1  haad 	err = dlm_ls_lock_wait(lockspace,
    476      1.1  haad 			       mode,
    477      1.1  haad 			       &lksb,
    478      1.1  haad 			       flags,
    479      1.1  haad 			       resource,
    480      1.1  haad 			       strlen(resource),
    481      1.1  haad 			       0,
    482      1.1  haad 			       NULL, NULL, NULL);
    483      1.1  haad 
    484      1.1  haad 	if (err != 0)
    485      1.1  haad 	{
    486      1.1  haad 		DEBUGLOG("dlm_ls_lock returned %d\n", errno);
    487      1.1  haad 		return err;
    488      1.1  haad 	}
    489  1.1.1.2  haad 	if (lksb.sb_status != 0)
    490  1.1.1.2  haad 	{
    491  1.1.1.2  haad 		DEBUGLOG("dlm_ls_lock returns lksb.sb_status %d\n", lksb.sb_status);
    492  1.1.1.2  haad 		errno = lksb.sb_status;
    493  1.1.1.2  haad 		return -1;
    494  1.1.1.2  haad 	}
    495      1.1  haad 
    496      1.1  haad 	DEBUGLOG("lock_resource returning %d, lock_id=%x\n", err, lksb.sb_lkid);
    497      1.1  haad 
    498      1.1  haad 	*lockid = lksb.sb_lkid;
    499      1.1  haad 
    500      1.1  haad 	return 0;
    501      1.1  haad }
    502      1.1  haad 
    503      1.1  haad 
    504      1.1  haad static int _unlock_resource(const char *resource, int lockid)
    505      1.1  haad {
    506      1.1  haad 	struct dlm_lksb lksb;
    507      1.1  haad 	int err;
    508      1.1  haad 
    509      1.1  haad 	DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
    510      1.1  haad 	lksb.sb_lkid = lockid;
    511      1.1  haad 
    512      1.1  haad 	err = dlm_ls_unlock_wait(lockspace,
    513      1.1  haad 				 lockid,
    514      1.1  haad 				 0,
    515      1.1  haad 				 &lksb);
    516      1.1  haad 	if (err != 0)
    517      1.1  haad 	{
    518      1.1  haad 		DEBUGLOG("Unlock returned %d\n", err);
    519      1.1  haad 		return err;
    520      1.1  haad 	}
    521  1.1.1.2  haad 	if (lksb.sb_status != EUNLOCK)
    522  1.1.1.2  haad 	{
    523  1.1.1.2  haad 		DEBUGLOG("dlm_ls_unlock_wait returns lksb.sb_status: %d\n", lksb.sb_status);
    524  1.1.1.2  haad 		errno = lksb.sb_status;
    525  1.1.1.2  haad 		return -1;
    526  1.1.1.2  haad 	}
    527  1.1.1.2  haad 
    528      1.1  haad 
    529      1.1  haad 	return 0;
    530      1.1  haad }
    531      1.1  haad 
    532      1.1  haad static int _is_quorate()
    533      1.1  haad {
    534      1.1  haad 	int quorate;
    535      1.1  haad 	if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
    536      1.1  haad 		return quorate;
    537      1.1  haad 	else
    538      1.1  haad 		return 0;
    539      1.1  haad }
    540      1.1  haad 
    541      1.1  haad static int _get_main_cluster_fd(void)
    542      1.1  haad {
    543      1.1  haad 	int select_fd;
    544      1.1  haad 
    545      1.1  haad 	cpg_fd_get(cpg_handle, &select_fd);
    546      1.1  haad 	return select_fd;
    547      1.1  haad }
    548      1.1  haad 
    549      1.1  haad static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
    550      1.1  haad 				const char *csid,
    551      1.1  haad 				struct local_client **new_client)
    552      1.1  haad {
    553      1.1  haad 	cluster_client = fd;
    554      1.1  haad 	*new_client = NULL;
    555      1.1  haad 	cpg_dispatch(cpg_handle, CS_DISPATCH_ONE);
    556      1.1  haad 	return 1;
    557      1.1  haad }
    558      1.1  haad 
    559      1.1  haad static int _cluster_send_message(const void *buf, int msglen, const char *csid,
    560      1.1  haad 				 const char *errtext)
    561      1.1  haad {
    562      1.1  haad 	struct iovec iov[2];
    563      1.1  haad 	cs_error_t err;
    564      1.1  haad 	int target_node;
    565      1.1  haad 
    566      1.1  haad 	if (csid)
    567      1.1  haad 		memcpy(&target_node, csid, COROSYNC_CSID_LEN);
    568      1.1  haad 	else
    569      1.1  haad 		target_node = 0;
    570      1.1  haad 
    571      1.1  haad 	iov[0].iov_base = &target_node;
    572      1.1  haad 	iov[0].iov_len = sizeof(int);
    573      1.1  haad 	iov[1].iov_base = (char *)buf;
    574      1.1  haad 	iov[1].iov_len = msglen;
    575      1.1  haad 
    576      1.1  haad 	err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
    577      1.1  haad 	return cs_to_errno(err);
    578      1.1  haad }
    579      1.1  haad 
    580  1.1.1.2  haad /*
    581  1.1.1.2  haad  * We are not necessarily connected to a Red Hat Cluster system,
    582  1.1.1.2  haad  * but if we are, this returns the cluster name from cluster.conf.
    583  1.1.1.2  haad  * I've used confdb rather than ccs to reduce the inter-package
    584  1.1.1.2  haad  * dependancies as well as to allow people to set a cluster name
    585  1.1.1.2  haad  * for themselves even if they are not running on RH cluster.
    586  1.1.1.2  haad  */
    587      1.1  haad static int _get_cluster_name(char *buf, int buflen)
    588      1.1  haad {
    589  1.1.1.2  haad 	confdb_handle_t handle;
    590  1.1.1.2  haad 	int result;
    591  1.1.1.2  haad 	size_t namelen = buflen;
    592  1.1.1.2  haad 	hdb_handle_t cluster_handle;
    593  1.1.1.2  haad 	confdb_callbacks_t callbacks = {
    594  1.1.1.2  haad 		.confdb_key_change_notify_fn = NULL,
    595  1.1.1.2  haad 		.confdb_object_create_change_notify_fn = NULL,
    596  1.1.1.2  haad 		.confdb_object_delete_change_notify_fn = NULL
    597  1.1.1.2  haad 	};
    598  1.1.1.2  haad 
    599  1.1.1.2  haad 	/* This is a default in case everything else fails */
    600      1.1  haad 	strncpy(buf, "Corosync", buflen);
    601  1.1.1.2  haad 
    602  1.1.1.2  haad 	/* Look for a cluster name in confdb */
    603  1.1.1.2  haad 	result = confdb_initialize (&handle, &callbacks);
    604  1.1.1.2  haad         if (result != CS_OK)
    605  1.1.1.2  haad 		return 0;
    606  1.1.1.2  haad 
    607  1.1.1.2  haad         result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
    608  1.1.1.2  haad 	if (result != CS_OK)
    609  1.1.1.2  haad 		goto out;
    610  1.1.1.2  haad 
    611  1.1.1.2  haad         result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle);
    612  1.1.1.2  haad         if (result != CS_OK)
    613  1.1.1.2  haad 		goto out;
    614  1.1.1.2  haad 
    615  1.1.1.2  haad         result = confdb_key_get(handle, cluster_handle, (void *)"name", strlen("name"), buf, &namelen);
    616  1.1.1.2  haad         if (result != CS_OK)
    617  1.1.1.2  haad 		goto out;
    618  1.1.1.2  haad 
    619  1.1.1.2  haad 	buf[namelen] = '\0';
    620  1.1.1.2  haad 
    621  1.1.1.2  haad out:
    622  1.1.1.2  haad 	confdb_finalize(handle);
    623      1.1  haad 	return 0;
    624      1.1  haad }
    625      1.1  haad 
    626      1.1  haad static struct cluster_ops _cluster_corosync_ops = {
    627      1.1  haad 	.cluster_init_completed   = NULL,
    628      1.1  haad 	.cluster_send_message     = _cluster_send_message,
    629      1.1  haad 	.name_from_csid           = _name_from_csid,
    630      1.1  haad 	.csid_from_name           = _csid_from_name,
    631      1.1  haad 	.get_num_nodes            = _get_num_nodes,
    632      1.1  haad 	.cluster_fd_callback      = _cluster_fd_callback,
    633      1.1  haad 	.get_main_cluster_fd      = _get_main_cluster_fd,
    634      1.1  haad 	.cluster_do_node_callback = _cluster_do_node_callback,
    635      1.1  haad 	.is_quorate               = _is_quorate,
    636      1.1  haad 	.get_our_csid             = _get_our_csid,
    637      1.1  haad 	.add_up_node              = _add_up_node,
    638      1.1  haad 	.reread_config            = NULL,
    639      1.1  haad 	.cluster_closedown        = _cluster_closedown,
    640      1.1  haad 	.get_cluster_name         = _get_cluster_name,
    641      1.1  haad 	.sync_lock                = _lock_resource,
    642      1.1  haad 	.sync_unlock              = _unlock_resource,
    643      1.1  haad };
    644      1.1  haad 
    645      1.1  haad struct cluster_ops *init_corosync_cluster(void)
    646      1.1  haad {
    647      1.1  haad 	if (!_init_cluster())
    648      1.1  haad 		return &_cluster_corosync_ops;
    649      1.1  haad 	else
    650      1.1  haad 		return NULL;
    651      1.1  haad }
    652