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