summaryrefslogtreecommitdiff
path: root/daemons/clvmd/clvmd-openais.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemons/clvmd/clvmd-openais.c')
-rw-r--r--daemons/clvmd/clvmd-openais.c694
1 files changed, 0 insertions, 694 deletions
diff --git a/daemons/clvmd/clvmd-openais.c b/daemons/clvmd/clvmd-openais.c
deleted file mode 100644
index 9ce73d6..0000000
--- a/daemons/clvmd/clvmd-openais.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * Copyright (C) 2007-2009 Red Hat, Inc. All rights reserved.
- *
- * This file is part of LVM2.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License v.2.1.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * This provides the interface between clvmd and OpenAIS as the cluster
- * and lock manager.
- */
-
-#include "clvmd-common.h"
-
-#include <pthread.h>
-#include <fcntl.h>
-#include <syslog.h>
-
-#include <openais/saAis.h>
-#include <openais/saLck.h>
-
-#include <corosync/corotypes.h>
-#include <corosync/cpg.h>
-
-#include "locking.h"
-#include "clvm.h"
-#include "clvmd-comms.h"
-#include "lvm-functions.h"
-#include "clvmd.h"
-
-/* Timeout value for several openais calls */
-#define TIMEOUT 10
-
-static void openais_cpg_deliver_callback (cpg_handle_t handle,
- const struct cpg_name *groupName,
- uint32_t nodeid,
- uint32_t pid,
- void *msg,
- size_t msg_len);
-static void openais_cpg_confchg_callback(cpg_handle_t handle,
- const struct cpg_name *groupName,
- const struct cpg_address *member_list, size_t member_list_entries,
- const struct cpg_address *left_list, size_t left_list_entries,
- const struct cpg_address *joined_list, size_t joined_list_entries);
-
-static void _cluster_closedown(void);
-
-/* Hash list of nodes in the cluster */
-static struct dm_hash_table *node_hash;
-
-/* For associating lock IDs & resource handles */
-static struct dm_hash_table *lock_hash;
-
-/* Number of active nodes */
-static int num_nodes;
-static unsigned int our_nodeid;
-
-static struct local_client *cluster_client;
-
-/* OpenAIS handles */
-static cpg_handle_t cpg_handle;
-static SaLckHandleT lck_handle;
-
-static struct cpg_name cpg_group_name;
-
-/* Openais callback structs */
-cpg_callbacks_t openais_cpg_callbacks = {
- .cpg_deliver_fn = openais_cpg_deliver_callback,
- .cpg_confchg_fn = openais_cpg_confchg_callback,
-};
-
-struct node_info
-{
- enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
- int nodeid;
-};
-
-struct lock_info
-{
- SaLckResourceHandleT res_handle;
- SaLckLockIdT lock_id;
- SaNameT lock_name;
-};
-
-/* Set errno to something approximating the right value and return 0 or -1 */
-static int ais_to_errno(SaAisErrorT err)
-{
- switch(err)
- {
- case SA_AIS_OK:
- return 0;
- case SA_AIS_ERR_LIBRARY:
- errno = EINVAL;
- break;
- case SA_AIS_ERR_VERSION:
- errno = EINVAL;
- break;
- case SA_AIS_ERR_INIT:
- errno = EINVAL;
- break;
- case SA_AIS_ERR_TIMEOUT:
- errno = ETIME;
- break;
- case SA_AIS_ERR_TRY_AGAIN:
- errno = EAGAIN;
- break;
- case SA_AIS_ERR_INVALID_PARAM:
- errno = EINVAL;
- break;
- case SA_AIS_ERR_NO_MEMORY:
- errno = ENOMEM;
- break;
- case SA_AIS_ERR_BAD_HANDLE:
- errno = EINVAL;
- break;
- case SA_AIS_ERR_BUSY:
- errno = EBUSY;
- break;
- case SA_AIS_ERR_ACCESS:
- errno = EPERM;
- break;
- case SA_AIS_ERR_NOT_EXIST:
- errno = ENOENT;
- break;
- case SA_AIS_ERR_NAME_TOO_LONG:
- errno = ENAMETOOLONG;
- break;
- case SA_AIS_ERR_EXIST:
- errno = EEXIST;
- break;
- case SA_AIS_ERR_NO_SPACE:
- errno = ENOSPC;
- break;
- case SA_AIS_ERR_INTERRUPT:
- errno = EINTR;
- break;
- case SA_AIS_ERR_NAME_NOT_FOUND:
- errno = ENOENT;
- break;
- case SA_AIS_ERR_NO_RESOURCES:
- errno = ENOMEM;
- break;
- case SA_AIS_ERR_NOT_SUPPORTED:
- errno = EOPNOTSUPP;
- break;
- case SA_AIS_ERR_BAD_OPERATION:
- errno = EINVAL;
- break;
- case SA_AIS_ERR_FAILED_OPERATION:
- errno = EIO;
- break;
- case SA_AIS_ERR_MESSAGE_ERROR:
- errno = EIO;
- break;
- case SA_AIS_ERR_QUEUE_FULL:
- errno = EXFULL;
- break;
- case SA_AIS_ERR_QUEUE_NOT_AVAILABLE:
- errno = EINVAL;
- break;
- case SA_AIS_ERR_BAD_FLAGS:
- errno = EINVAL;
- break;
- case SA_AIS_ERR_TOO_BIG:
- errno = E2BIG;
- break;
- case SA_AIS_ERR_NO_SECTIONS:
- errno = ENOMEM;
- break;
- default:
- errno = EINVAL;
- break;
- }
- return -1;
-}
-
-static char *print_openais_csid(const char *csid)
-{
- static char buf[128];
- int id;
-
- memcpy(&id, csid, sizeof(int));
- sprintf(buf, "%d", id);
- return buf;
-}
-
-static int add_internal_client(int fd, fd_callback_t callback)
-{
- struct local_client *client;
-
- DEBUGLOG("Add_internal_client, fd = %d\n", fd);
-
- client = calloc(1, sizeof(struct local_client));
- if (!client)
- {
- DEBUGLOG("malloc failed\n");
- return -1;
- }
-
- client->fd = fd;
- client->type = CLUSTER_INTERNAL;
- client->callback = callback;
- add_client(client);
-
- /* Set Close-on-exec */
- fcntl(fd, F_SETFD, 1);
-
- return 0;
-}
-
-static void openais_cpg_deliver_callback (cpg_handle_t handle,
- const struct cpg_name *groupName,
- uint32_t nodeid,
- uint32_t pid,
- void *msg,
- size_t msg_len)
-{
- int target_nodeid;
-
- memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
-
- DEBUGLOG("%u got message from nodeid %d for %d. len %" PRIsize_t "\n",
- our_nodeid, nodeid, target_nodeid, msg_len-4);
-
- if (nodeid != our_nodeid)
- if (target_nodeid == our_nodeid || target_nodeid == 0)
- process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
- msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
-}
-
-static void openais_cpg_confchg_callback(cpg_handle_t handle,
- const struct cpg_name *groupName,
- const struct cpg_address *member_list, size_t member_list_entries,
- const struct cpg_address *left_list, size_t left_list_entries,
- const struct cpg_address *joined_list, size_t joined_list_entries)
-{
- int i;
- struct node_info *ninfo;
-
- DEBUGLOG("confchg callback. %" PRIsize_t " joined, "
- "%" PRIsize_t " left, %" PRIsize_t " members\n",
- joined_list_entries, left_list_entries, member_list_entries);
-
- for (i=0; i<joined_list_entries; i++) {
- ninfo = dm_hash_lookup_binary(node_hash,
- (char *)&joined_list[i].nodeid,
- OPENAIS_CSID_LEN);
- if (!ninfo) {
- ninfo = malloc(sizeof(struct node_info));
- if (!ninfo) {
- break;
- }
- else {
- ninfo->nodeid = joined_list[i].nodeid;
- dm_hash_insert_binary(node_hash,
- (char *)&ninfo->nodeid,
- OPENAIS_CSID_LEN, ninfo);
- }
- }
- ninfo->state = NODE_CLVMD;
- }
-
- for (i=0; i<left_list_entries; i++) {
- ninfo = dm_hash_lookup_binary(node_hash,
- (char *)&left_list[i].nodeid,
- OPENAIS_CSID_LEN);
- if (ninfo)
- ninfo->state = NODE_DOWN;
- }
-
- for (i=0; i<member_list_entries; i++) {
- if (member_list[i].nodeid == 0) continue;
- ninfo = dm_hash_lookup_binary(node_hash,
- (char *)&member_list[i].nodeid,
- OPENAIS_CSID_LEN);
- if (!ninfo) {
- ninfo = malloc(sizeof(struct node_info));
- if (!ninfo) {
- break;
- }
- else {
- ninfo->nodeid = member_list[i].nodeid;
- dm_hash_insert_binary(node_hash,
- (char *)&ninfo->nodeid,
- OPENAIS_CSID_LEN, ninfo);
- }
- }
- ninfo->state = NODE_CLVMD;
- }
-
- num_nodes = member_list_entries;
-}
-
-static int lck_dispatch(struct local_client *client, char *buf, int len,
- const char *csid, struct local_client **new_client)
-{
- *new_client = NULL;
- saLckDispatch(lck_handle, SA_DISPATCH_ONE);
- return 1;
-}
-
-static int _init_cluster(void)
-{
- SaAisErrorT err;
- SaVersionT ver = { 'B', 1, 1 };
- int select_fd;
-
- node_hash = dm_hash_create(100);
- lock_hash = dm_hash_create(10);
-
- err = cpg_initialize(&cpg_handle,
- &openais_cpg_callbacks);
- if (err != SA_AIS_OK) {
- syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
- err);
- DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err);
- return ais_to_errno(err);
- }
-
- err = saLckInitialize(&lck_handle,
- NULL,
- &ver);
- if (err != SA_AIS_OK) {
- cpg_initialize(&cpg_handle, &openais_cpg_callbacks);
- syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
- err);
- DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
- return ais_to_errno(err);
- }
-
- /* Connect to the clvmd group */
- strcpy((char *)cpg_group_name.value, "clvmd");
- cpg_group_name.length = strlen((char *)cpg_group_name.value);
- err = cpg_join(cpg_handle, &cpg_group_name);
- if (err != SA_AIS_OK) {
- cpg_finalize(cpg_handle);
- saLckFinalize(lck_handle);
- syslog(LOG_ERR, "Cannot join clvmd process group");
- DEBUGLOG("Cannot join clvmd process group: %d\n", err);
- return ais_to_errno(err);
- }
-
- err = cpg_local_get(cpg_handle,
- &our_nodeid);
- if (err != SA_AIS_OK) {
- cpg_finalize(cpg_handle);
- saLckFinalize(lck_handle);
- syslog(LOG_ERR, "Cannot get local node id\n");
- return ais_to_errno(err);
- }
- DEBUGLOG("Our local node id is %d\n", our_nodeid);
-
- saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd);
- add_internal_client(select_fd, lck_dispatch);
-
- DEBUGLOG("Connected to OpenAIS\n");
-
- return 0;
-}
-
-static void _cluster_closedown(void)
-{
- DEBUGLOG("cluster_closedown\n");
- destroy_lvhash();
-
- saLckFinalize(lck_handle);
- cpg_finalize(cpg_handle);
-}
-
-static void _get_our_csid(char *csid)
-{
- memcpy(csid, &our_nodeid, sizeof(int));
-}
-
-/* OpenAIS doesn't really have nmode names so we
- just use the node ID in hex instead */
-static int _csid_from_name(char *csid, const char *name)
-{
- int nodeid;
- struct node_info *ninfo;
-
- if (sscanf(name, "%x", &nodeid) == 1) {
- ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
- if (ninfo)
- return nodeid;
- }
- return -1;
-}
-
-static int _name_from_csid(const char *csid, char *name)
-{
- struct node_info *ninfo;
-
- ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
- if (!ninfo)
- {
- sprintf(name, "UNKNOWN %s", print_openais_csid(csid));
- return -1;
- }
-
- sprintf(name, "%x", ninfo->nodeid);
- return 0;
-}
-
-static int _get_num_nodes()
-{
- DEBUGLOG("num_nodes = %d\n", num_nodes);
- return num_nodes;
-}
-
-/* Node is now known to be running a clvmd */
-static void _add_up_node(const char *csid)
-{
- struct node_info *ninfo;
-
- ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
- if (!ninfo) {
- DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
- print_openais_csid(csid));
- return;
- }
-
- DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
-
- ninfo->state = NODE_CLVMD;
-
- return;
-}
-
-/* Call a callback for each node, so the caller knows whether it's up or down */
-static int _cluster_do_node_callback(struct local_client *master_client,
- void (*callback)(struct local_client *,
- const char *csid, int node_up))
-{
- struct dm_hash_node *hn;
- struct node_info *ninfo;
- int somedown = 0;
-
- dm_hash_iterate(hn, node_hash)
- {
- char csid[OPENAIS_CSID_LEN];
-
- ninfo = dm_hash_get_data(node_hash, hn);
- memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN);
-
- DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
- ninfo->state);
-
- if (ninfo->state != NODE_DOWN)
- callback(master_client, csid, ninfo->state == NODE_CLVMD);
- if (ninfo->state != NODE_CLVMD)
- somedown = -1;
- }
- return somedown;
-}
-
-/* Real locking */
-static int _lock_resource(char *resource, int mode, int flags, int *lockid)
-{
- struct lock_info *linfo;
- SaLckResourceHandleT res_handle;
- SaAisErrorT err;
- SaLckLockIdT lock_id;
- SaLckLockStatusT lockStatus;
-
- /* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
- if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
-
- linfo = malloc(sizeof(struct lock_info));
- if (!linfo)
- return -1;
-
- DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
-
- linfo->lock_name.length = strlen(resource)+1;
- strcpy((char *)linfo->lock_name.value, resource);
-
- err = saLckResourceOpen(lck_handle, &linfo->lock_name,
- SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle);
- if (err != SA_AIS_OK)
- {
- DEBUGLOG("ResourceOpen returned %d\n", err);
- free(linfo);
- return ais_to_errno(err);
- }
-
- err = saLckResourceLock(
- res_handle,
- &lock_id,
- mode,
- flags,
- 0,
- SA_TIME_END,
- &lockStatus);
- if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED)
- {
- free(linfo);
- saLckResourceClose(res_handle);
- return ais_to_errno(err);
- }
-
- /* Wait for it to complete */
-
- DEBUGLOG("lock_resource returning %d, lock_id=%" PRIx64 "\n",
- err, lock_id);
-
- linfo->lock_id = lock_id;
- linfo->res_handle = res_handle;
-
- dm_hash_insert(lock_hash, resource, linfo);
-
- return ais_to_errno(err);
-}
-
-
-static int _unlock_resource(char *resource, int lockid)
-{
- SaAisErrorT err;
- struct lock_info *linfo;
-
- DEBUGLOG("unlock_resource %s\n", resource);
- linfo = dm_hash_lookup(lock_hash, resource);
- if (!linfo)
- return 0;
-
- DEBUGLOG("unlock_resource: lockid: %" PRIx64 "\n", linfo->lock_id);
- err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END);
- if (err != SA_AIS_OK)
- {
- DEBUGLOG("Unlock returned %d\n", err);
- return ais_to_errno(err);
- }
-
- /* Release the resource */
- dm_hash_remove(lock_hash, resource);
- saLckResourceClose(linfo->res_handle);
- free(linfo);
-
- return ais_to_errno(err);
-}
-
-static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
-{
- int status;
- char lock1[strlen(resource)+3];
- char lock2[strlen(resource)+3];
-
- snprintf(lock1, sizeof(lock1), "%s-1", resource);
- snprintf(lock2, sizeof(lock2), "%s-2", resource);
-
- switch (mode)
- {
- case LCK_EXCL:
- status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid);
- if (status)
- goto out;
-
- /* If we can't get this lock too then bail out */
- status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK,
- lockid);
- if (status == SA_LCK_LOCK_NOT_QUEUED)
- {
- _unlock_resource(lock1, *lockid);
- status = -1;
- errno = EAGAIN;
- }
- break;
-
- case LCK_PREAD:
- case LCK_READ:
- status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid);
- if (status)
- goto out;
- _unlock_resource(lock2, *lockid);
- break;
-
- case LCK_WRITE:
- status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid);
- if (status)
- goto out;
- _unlock_resource(lock1, *lockid);
- break;
-
- default:
- status = -1;
- errno = EINVAL;
- break;
- }
-out:
- *lockid = mode;
- return status;
-}
-
-static int _sync_unlock(const char *resource, int lockid)
-{
- int status = 0;
- char lock1[strlen(resource)+3];
- char lock2[strlen(resource)+3];
-
- snprintf(lock1, sizeof(lock1), "%s-1", resource);
- snprintf(lock2, sizeof(lock2), "%s-2", resource);
-
- _unlock_resource(lock1, lockid);
- _unlock_resource(lock2, lockid);
-
- return status;
-}
-
-/* We are always quorate ! */
-static int _is_quorate()
-{
- return 1;
-}
-
-static int _get_main_cluster_fd(void)
-{
- int select_fd;
-
- cpg_fd_get(cpg_handle, &select_fd);
- return select_fd;
-}
-
-static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
- const char *csid,
- struct local_client **new_client)
-{
- cluster_client = fd;
- *new_client = NULL;
- cpg_dispatch(cpg_handle, SA_DISPATCH_ONE);
- return 1;
-}
-
-static int _cluster_send_message(const void *buf, int msglen, const char *csid,
- const char *errtext)
-{
- struct iovec iov[2];
- SaAisErrorT err;
- int target_node;
-
- if (csid)
- memcpy(&target_node, csid, OPENAIS_CSID_LEN);
- else
- target_node = 0;
-
- iov[0].iov_base = &target_node;
- iov[0].iov_len = sizeof(int);
- iov[1].iov_base = (char *)buf;
- iov[1].iov_len = msglen;
-
- err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
- return ais_to_errno(err);
-}
-
-/* We don't have a cluster name to report here */
-static int _get_cluster_name(char *buf, int buflen)
-{
- strncpy(buf, "OpenAIS", buflen);
- return 0;
-}
-
-static struct cluster_ops _cluster_openais_ops = {
- .name = "openais",
- .cluster_init_completed = NULL,
- .cluster_send_message = _cluster_send_message,
- .name_from_csid = _name_from_csid,
- .csid_from_name = _csid_from_name,
- .get_num_nodes = _get_num_nodes,
- .cluster_fd_callback = _cluster_fd_callback,
- .get_main_cluster_fd = _get_main_cluster_fd,
- .cluster_do_node_callback = _cluster_do_node_callback,
- .is_quorate = _is_quorate,
- .get_our_csid = _get_our_csid,
- .add_up_node = _add_up_node,
- .reread_config = NULL,
- .cluster_closedown = _cluster_closedown,
- .get_cluster_name = _get_cluster_name,
- .sync_lock = _sync_lock,
- .sync_unlock = _sync_unlock,
-};
-
-struct cluster_ops *init_openais_cluster(void)
-{
- if (!_init_cluster())
- return &_cluster_openais_ops;
- else
- return NULL;
-}