summaryrefslogtreecommitdiff
path: root/daemons/clvmd
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2018-06-05 10:47:01 -0500
committerDavid Teigland <teigland@redhat.com>2018-06-05 11:09:13 -0500
commit3e781ea446bb7ddc9a494cbba6b6104dd51c3910 (patch)
tree0cde55ce3fcc898f1d72aceb15c30963c3093d2a /daemons/clvmd
parent11384637fb57c0fdefe5940cf27285ebdcc1dbc6 (diff)
downloadlvm2-3e781ea446bb7ddc9a494cbba6b6104dd51c3910.tar.gz
Remove clvmd and associated code
More code reduction and simplification can follow.
Diffstat (limited to 'daemons/clvmd')
-rw-r--r--daemons/clvmd/.gitignore1
-rw-r--r--daemons/clvmd/Makefile.in94
-rw-r--r--daemons/clvmd/clvm.h85
-rw-r--r--daemons/clvmd/clvmd-cman.c505
-rw-r--r--daemons/clvmd/clvmd-command.c415
-rw-r--r--daemons/clvmd/clvmd-common.h27
-rw-r--r--daemons/clvmd/clvmd-comms.h119
-rw-r--r--daemons/clvmd/clvmd-corosync.c662
-rw-r--r--daemons/clvmd/clvmd-openais.c687
-rw-r--r--daemons/clvmd/clvmd-singlenode.c382
-rw-r--r--daemons/clvmd/clvmd.c2422
-rw-r--r--daemons/clvmd/clvmd.h126
-rw-r--r--daemons/clvmd/lvm-functions.c927
-rw-r--r--daemons/clvmd/lvm-functions.h40
-rw-r--r--daemons/clvmd/refresh_clvmd.c382
-rw-r--r--daemons/clvmd/refresh_clvmd.h19
16 files changed, 0 insertions, 6893 deletions
diff --git a/daemons/clvmd/.gitignore b/daemons/clvmd/.gitignore
deleted file mode 100644
index 816032f97..000000000
--- a/daemons/clvmd/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-clvmd
diff --git a/daemons/clvmd/Makefile.in b/daemons/clvmd/Makefile.in
deleted file mode 100644
index 622a60366..000000000
--- a/daemons/clvmd/Makefile.in
+++ /dev/null
@@ -1,94 +0,0 @@
-#
-# Copyright (C) 2004 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 General Public License v.2.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-top_builddir = @top_builddir@
-
-CMAN_LIBS = @CMAN_LIBS@
-CMAN_CFLAGS = @CMAN_CFLAGS@
-CMAP_LIBS = @CMAP_LIBS@
-CMAP_CFLAGS = @CMAP_CFLAGS@
-CONFDB_LIBS = @CONFDB_LIBS@
-CONFDB_CFLAGS = @CONFDB_CFLAGS@
-CPG_LIBS = @CPG_LIBS@
-CPG_CFLAGS = @CPG_CFLAGS@
-DLM_LIBS = @DLM_LIBS@
-DLM_CFLAGS = @DLM_CFLAGS@
-QUORUM_LIBS = @QUORUM_LIBS@
-QUORUM_CFLAGS = @QUORUM_CFLAGS@
-SALCK_LIBS = @SALCK_LIBS@
-SALCK_CFLAGS = @SALCK_CFLAGS@
-
-SOURCES = \
- clvmd-command.c\
- clvmd.c\
- lvm-functions.c\
- refresh_clvmd.c
-
-ifneq (,$(findstring cman,, "@CLVMD@,"))
- SOURCES += clvmd-cman.c
- LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS)
- CFLAGS += $(CMAN_CFLAGS) $(CONFDB_CFLAGS) $(DLM_CFLAGS)
- DEFS += -DUSE_CMAN
-endif
-
-ifneq (,$(findstring openais,, "@CLVMD@,"))
- SOURCES += clvmd-openais.c
- LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(SALCK_LIBS)
- CFLAGS += $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(SALCK_CFLAGS)
- DEFS += -DUSE_OPENAIS
-endif
-
-ifneq (,$(findstring corosync,, "@CLVMD@,"))
- SOURCES += clvmd-corosync.c
- LMLIBS += $(CMAP_LIBS) $(CONFDB_LIBS) $(CPG_LIBS) $(DLM_LIBS) $(QUORUM_LIBS)
- CFLAGS += $(CMAP_CFLAGS) $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(DLM_CFLAGS) $(QUORUM_CFLAGS)
- DEFS += -DUSE_COROSYNC
-endif
-
-ifneq (,$(findstring singlenode,, &quot;@CLVMD@,&quot;))
- SOURCES += clvmd-singlenode.c
- DEFS += -DUSE_SINGLENODE
-endif
-
-ifeq ($(MAKECMDGOALS),distclean)
- SOURCES += clvmd-cman.c
- SOURCES += clvmd-openais.c
- SOURCES += clvmd-corosync.c
- SOURCES += clvmd-singlenode.c
-endif
-
-TARGETS = \
- clvmd
-
-include $(top_builddir)/make.tmpl
-
-LIBS += $(LVMINTERNAL_LIBS) $(PTHREAD_LIBS) -laio
-CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS)
-
-INSTALL_TARGETS = \
- install_clvmd
-
-clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a $(INTERNAL_LIBS)
- $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) \
- -o clvmd $+ $(LMLIBS) $(LIBS)
-
-.PHONY: install_clvmd
-
-install_clvmd: $(TARGETS)
- $(INSTALL_PROGRAM) -D clvmd $(usrsbindir)/clvmd
-
-install: $(INSTALL_TARGETS)
-
-install_cluster: $(INSTALL_TARGETS)
diff --git a/daemons/clvmd/clvm.h b/daemons/clvmd/clvm.h
deleted file mode 100644
index ae0a13aa4..000000000
--- a/daemons/clvmd/clvm.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 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 General Public License v.2.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/* Definitions for CLVMD server and clients */
-
-/*
- * The protocol spoken over the cluster and across the local socket.
- */
-
-#ifndef _CLVM_H
-#define _CLVM_H
-
-#include "configure.h"
-#include <inttypes.h>
-
-struct clvm_header {
- uint8_t cmd; /* See below */
- uint8_t flags; /* See below */
- uint16_t xid; /* Transaction ID */
- uint32_t clientid; /* Only used in Daemon->Daemon comms */
- int32_t status; /* For replies, whether request succeeded */
- uint32_t arglen; /* Length of argument below.
- If >1500 then it will be passed
- around the cluster in the system LV */
- char node[1]; /* Actually a NUL-terminated string, node name.
- If this is empty then the command is
- forwarded to all cluster nodes unless
- FLAG_LOCAL or FLAG_REMOTE is also set. */
- char args[1]; /* Arguments for the command follow the
- node name, This member is only
- valid if the node name is empty */
-} __attribute__ ((packed));
-
-/* Flags */
-#define CLVMD_FLAG_LOCAL 1 /* Only do this on the local node */
-#define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */
-#define CLVMD_FLAG_NODEERRS 4 /* Reply has errors in node-specific portion */
-#define CLVMD_FLAG_REMOTE 8 /* Do this on all nodes except for the local node */
-
-/* Name of the local socket to communicate between lvm and clvmd */
-#define CLVMD_SOCKNAME DEFAULT_RUN_DIR "/clvmd.sock"
-
-/* Internal commands & replies */
-#define CLVMD_CMD_REPLY 1
-#define CLVMD_CMD_VERSION 2 /* Send version around cluster when we start */
-#define CLVMD_CMD_GOAWAY 3 /* Die if received this - we are running
- an incompatible version */
-#define CLVMD_CMD_TEST 4 /* Just for mucking about */
-
-#define CLVMD_CMD_LOCK 30
-#define CLVMD_CMD_UNLOCK 31
-
-/* Lock/Unlock commands */
-#define CLVMD_CMD_LOCK_LV 50
-#define CLVMD_CMD_LOCK_VG 51
-#define CLVMD_CMD_LOCK_QUERY 52
-
-/* Misc functions */
-#define CLVMD_CMD_REFRESH 40
-#define CLVMD_CMD_GET_CLUSTERNAME 41
-#define CLVMD_CMD_SET_DEBUG 42
-#define CLVMD_CMD_VG_BACKUP 43
-#define CLVMD_CMD_RESTART 44
-#define CLVMD_CMD_SYNC_NAMES 45
-
-/* Used internally by some callers, but not part of the protocol.*/
-#ifndef NODE_ALL
-# define NODE_ALL "*"
-# define NODE_LOCAL "."
-# define NODE_REMOTE "^"
-#endif
-
-#endif
diff --git a/daemons/clvmd/clvmd-cman.c b/daemons/clvmd/clvmd-cman.c
deleted file mode 100644
index 8cf7f176c..000000000
--- a/daemons/clvmd/clvmd-cman.c
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004 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 General Public License v.2.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * CMAN communication layer for clvmd.
- */
-
-#include "clvmd-common.h"
-
-#include <pthread.h>
-
-#include "clvmd-comms.h"
-#include "daemons/clvmd/clvm.h"
-#include "clvmd.h"
-#include "lvm-functions.h"
-
-#include <libdlm.h>
-
-#include <syslog.h>
-
-#define LOCKSPACE_NAME "clvmd"
-
-struct clvmd_node
-{
- struct cman_node *node;
- int clvmd_up;
-};
-
-static int num_nodes;
-static struct cman_node *nodes = NULL;
-static struct cman_node this_node;
-static int count_nodes; /* size of allocated nodes array */
-static struct dm_hash_table *node_updown_hash;
-static dlm_lshandle_t *lockspace;
-static cman_handle_t c_handle;
-
-static void count_clvmds_running(void);
-static void get_members(void);
-static int nodeid_from_csid(const char *csid);
-static int name_from_nodeid(int nodeid, char *name);
-static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
-static void data_callback(cman_handle_t handle, void *private,
- char *buf, int len, uint8_t port, int nodeid);
-
-struct lock_wait {
- pthread_cond_t cond;
- pthread_mutex_t mutex;
- struct dlm_lksb lksb;
-};
-
-static int _init_cluster(void)
-{
- node_updown_hash = dm_hash_create(100);
-
- /* Open the cluster communication socket */
- c_handle = cman_init(NULL);
- if (!c_handle) {
- syslog(LOG_ERR, "Can't open cluster manager socket: %m");
- return -1;
- }
- DEBUGLOG("Connected to CMAN\n");
-
- if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
- syslog(LOG_ERR, "Can't bind cluster socket: %m");
- return -1;
- }
-
- if (cman_start_notification(c_handle, event_callback)) {
- syslog(LOG_ERR, "Can't start cluster event listening");
- return -1;
- }
-
- /* Get the cluster members list */
- get_members();
- count_clvmds_running();
-
- DEBUGLOG("CMAN initialisation complete\n");
-
- /* Create a lockspace for LV & VG locks to live in */
- lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
- if (!lockspace) {
- lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
- if (!lockspace) {
- syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
- return -1;
- }
- DEBUGLOG("Created DLM lockspace for CLVMD.\n");
- } else
- DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
-
- dlm_ls_pthread_init(lockspace);
- DEBUGLOG("DLM initialisation complete\n");
- return 0;
-}
-
-static void _cluster_init_completed(void)
-{
- clvmd_cluster_init_completed();
-}
-
-static int _get_main_cluster_fd(void)
-{
- return cman_get_fd(c_handle);
-}
-
-static int _get_num_nodes(void)
-{
- int i;
- int nnodes = 0;
-
- /* return number of ACTIVE nodes */
- for (i=0; i<num_nodes; i++) {
- if (nodes[i].cn_member && nodes[i].cn_nodeid)
- nnodes++;
- }
- return nnodes;
-}
-
-/* send_message with the fd check removed */
-static int _cluster_send_message(const void *buf, int msglen, const char *csid,
- const char *errtext)
-{
- int nodeid = 0;
-
- if (csid)
- memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
-
- if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
- {
- log_error("%s", errtext);
- }
- return msglen;
-}
-
-static void _get_our_csid(char *csid)
-{
- if (this_node.cn_nodeid == 0) {
- cman_get_node(c_handle, 0, &this_node);
- }
- memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
-}
-
-/* Call a callback routine for each node is that known (down means not running a clvmd) */
-static int _cluster_do_node_callback(struct local_client *client,
- void (*callback) (struct local_client *,
- const char *,
- int))
-{
- int i;
- int somedown = 0;
-
- for (i = 0; i < _get_num_nodes(); i++) {
- if (nodes[i].cn_member && nodes[i].cn_nodeid) {
- int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int));
-
- callback(client, (char *)&nodes[i].cn_nodeid, up);
- if (!up)
- somedown = -1;
- }
- }
- return somedown;
-}
-
-/* Process OOB messages from the cluster socket */
-static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
-{
- char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
-
- switch (reason) {
- case CMAN_REASON_PORTCLOSED:
- name_from_nodeid(arg, namebuf);
- log_notice("clvmd on node %s has died\n", namebuf);
- DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
-
- dm_hash_insert_binary(node_updown_hash, (char *)&arg, sizeof(int), (void *)0);
- break;
-
- case CMAN_REASON_STATECHANGE:
- DEBUGLOG("Got state change message, re-reading members list\n");
- get_members();
- break;
-
-#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
- case CMAN_REASON_PORTOPENED:
- /* Ignore this, wait for startup message from clvmd itself */
- break;
-
- case CMAN_REASON_TRY_SHUTDOWN:
- DEBUGLOG("Got try shutdown, sending OK\n");
- cman_replyto_shutdown(c_handle, 1);
- break;
-#endif
- default:
- /* ERROR */
- DEBUGLOG("Got unknown event callback message: %d\n", reason);
- break;
- }
-}
-
-static struct local_client *cman_client;
-static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
- const char *csid,
- struct local_client **new_client)
-{
-
- /* Save this for data_callback */
- cman_client = fd;
-
- /* We never return a new client */
- *new_client = NULL;
-
- return cman_dispatch(c_handle, 0);
-}
-
-
-static void data_callback(cman_handle_t handle, void *private,
- char *buf, int len, uint8_t port, int nodeid)
-{
- /* Ignore looped back messages */
- if (nodeid == this_node.cn_nodeid)
- return;
- process_message(cman_client, buf, len, (char *)&nodeid);
-}
-
-static void _add_up_node(const char *csid)
-{
- /* It's up ! */
- int nodeid = nodeid_from_csid(csid);
-
- dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1);
- DEBUGLOG("Added new node %d to updown list\n", nodeid);
-}
-
-static void _cluster_closedown(void)
-{
- dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
- cman_finish(c_handle);
-}
-
-static int is_listening(int nodeid)
-{
- int status;
-
- do {
- status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
- if (status < 0 && errno == EBUSY) { /* Don't busywait */
- sleep(1);
- errno = EBUSY; /* In case sleep trashes it */
- }
- }
- while (status < 0 && errno == EBUSY);
-
- return status;
-}
-
-/* Populate the list of CLVMDs running.
- called only at startup time */
-static void count_clvmds_running(void)
-{
- int i;
-
- for (i = 0; i < num_nodes; i++) {
- int nodeid = nodes[i].cn_nodeid;
-
- if (is_listening(nodeid) == 1)
- dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1);
- else
- dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0);
- }
-}
-
-/* Get a list of active cluster members */
-static void get_members(void)
-{
- int retnodes;
- int status;
- int i;
- int high_nodeid = 0;
-
- num_nodes = cman_get_node_count(c_handle);
- if (num_nodes == -1) {
- log_error("Unable to get node count");
- return;
- }
-
- /* Not enough room for new nodes list ? */
- if (num_nodes > count_nodes && nodes) {
- free(nodes);
- nodes = NULL;
- }
-
- if (nodes == NULL) {
- count_nodes = num_nodes + 10; /* Overallocate a little */
- nodes = malloc(count_nodes * sizeof(struct cman_node));
- if (!nodes) {
- log_error("Unable to allocate nodes array\n");
- exit(5);
- }
- }
-
- status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
- if (status < 0) {
- log_error("Unable to get node details");
- exit(6);
- }
-
- /* Get the highest nodeid */
- for (i=0; i<retnodes; i++) {
- if (nodes[i].cn_nodeid > high_nodeid)
- high_nodeid = nodes[i].cn_nodeid;
- }
-}
-
-
-/* Convert a node name to a CSID */
-static int _csid_from_name(char *csid, const char *name)
-{
- int i;
-
- for (i = 0; i < num_nodes; i++) {
- if (strcmp(name, nodes[i].cn_name) == 0) {
- memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
- return 0;
- }
- }
- return -1;
-}
-
-/* Convert a CSID to a node name */
-static int _name_from_csid(const char *csid, char *name)
-{
- int i;
-
- for (i = 0; i < num_nodes; i++) {
- if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
- strcpy(name, nodes[i].cn_name);
- return 0;
- }
- }
- /* Who?? */
- strcpy(name, "Unknown");
- return -1;
-}
-
-/* Convert a node ID to a node name */
-static int name_from_nodeid(int nodeid, char *name)
-{
- int i;
-
- for (i = 0; i < num_nodes; i++) {
- if (nodeid == nodes[i].cn_nodeid) {
- strcpy(name, nodes[i].cn_name);
- return 0;
- }
- }
- /* Who?? */
- strcpy(name, "Unknown");
- return -1;
-}
-
-/* Convert a CSID to a node ID */
-static int nodeid_from_csid(const char *csid)
-{
- int nodeid;
-
- memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
-
- return nodeid;
-}
-
-static int _is_quorate(void)
-{
- return cman_is_quorate(c_handle);
-}
-
-static void sync_ast_routine(void *arg)
-{
- struct lock_wait *lwait = arg;
-
- pthread_mutex_lock(&lwait->mutex);
- pthread_cond_signal(&lwait->cond);
- pthread_mutex_unlock(&lwait->mutex);
-}
-
-static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
-{
- int status;
- struct lock_wait lwait;
-
- if (!lockid) {
- errno = EINVAL;
- return -1;
- }
-
- DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
- /* Conversions need the lockid in the LKSB */
- if (flags & LKF_CONVERT)
- lwait.lksb.sb_lkid = *lockid;
-
- pthread_cond_init(&lwait.cond, NULL);
- pthread_mutex_init(&lwait.mutex, NULL);
- pthread_mutex_lock(&lwait.mutex);
-
- status = dlm_ls_lock(lockspace,
- mode,
- &lwait.lksb,
- flags,
- resource,
- strlen(resource),
- 0, sync_ast_routine, &lwait, NULL, NULL);
- if (status)
- return status;
-
- /* Wait for it to complete */
- pthread_cond_wait(&lwait.cond, &lwait.mutex);
- pthread_mutex_unlock(&lwait.mutex);
-
- *lockid = lwait.lksb.sb_lkid;
-
- errno = lwait.lksb.sb_status;
- DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
- if (lwait.lksb.sb_status)
- return -1;
- else
- return 0;
-}
-
-static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
-{
- int status;
- struct lock_wait lwait;
-
- DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
-
- pthread_cond_init(&lwait.cond, NULL);
- pthread_mutex_init(&lwait.mutex, NULL);
- pthread_mutex_lock(&lwait.mutex);
-
- status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
-
- if (status)
- return status;
-
- /* Wait for it to complete */
- pthread_cond_wait(&lwait.cond, &lwait.mutex);
- pthread_mutex_unlock(&lwait.mutex);
-
- errno = lwait.lksb.sb_status;
- if (lwait.lksb.sb_status != EUNLOCK)
- return -1;
- else
- return 0;
-
-}
-
-static int _get_cluster_name(char *buf, int buflen)
-{
- cman_cluster_t cluster_info;
- int status;
-
- status = cman_get_cluster(c_handle, &cluster_info);
- if (!status) {
- strncpy(buf, cluster_info.ci_name, buflen);
- }
- return status;
-}
-
-static struct cluster_ops _cluster_cman_ops = {
- .name = "cman",
- .cluster_init_completed = _cluster_init_completed,
- .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,
- .cluster_closedown = _cluster_closedown,
- .get_cluster_name = _get_cluster_name,
- .sync_lock = _sync_lock,
- .sync_unlock = _sync_unlock,
-};
-
-struct cluster_ops *init_cman_cluster(void)
-{
- if (!_init_cluster())
- return &_cluster_cman_ops;
- else
- return NULL;
-}
diff --git a/daemons/clvmd/clvmd-command.c b/daemons/clvmd/clvmd-command.c
deleted file mode 100644
index 342addaee..000000000
--- a/daemons/clvmd/clvmd-command.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2011 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 General Public License v.2.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
-
- CLVMD Cluster LVM daemon command processor.
-
- To add commands to the daemon simply add a processor in do_command and return
- and messages back in buf and the length in *retlen. The initial value of
- buflen is the maximum size of the buffer. if buf is not large enough then it
- may be reallocated by the functions in here to a suitable size bearing in
- mind that anything larger than the passed-in size will have to be returned
- using the system LV and so performance will suffer.
-
- The status return will be negated and passed back to the originating node.
-
- pre- and post- command routines are called only on the local node. The
- purpose is primarily to get and release locks, though the pre- routine should
- also do any other local setups required by the command (if any) and can
- return a failure code that prevents the command from being distributed around
- the cluster
-
- The pre- and post- routines are run in their own thread so can block as long
- they like, do_command is run in the main clvmd thread so should not block for
- too long. If the pre-command returns an error code (!=0) then the command
- will not be propogated around the cluster but the post-command WILL be called
-
- Also note that the pre and post routine are *always* called on the local
- node, even if the command to be executed was only requested to run on a
- remote node. It may peek inside the client structure to check the status of
- the command.
-
- The clients of the daemon must, naturally, understand the return messages and
- codes.
-
- Routines in here may only READ the values in the client structure passed in
- apart from client->private which they are free to do what they like with.
-
-*/
-
-#include "clvmd-common.h"
-#include "clvmd-comms.h"
-#include "daemons/clvmd/clvm.h"
-#include "clvmd.h"
-#include "lib/misc/lvm-globals.h"
-#include "lvm-functions.h"
-
-#include "lib/locking/locking.h"
-
-#include <sys/utsname.h>
-
-extern struct cluster_ops *clops;
-static int restart_clvmd(void);
-
-/* This is where all the real work happens:
- NOTE: client will be NULL when this is executed on a remote node */
-int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
- char **buf, int buflen, int *retlen)
-{
- char *args = msg->node + strlen(msg->node) + 1;
- int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
- int status = 0;
- char *lockname;
- const char *locktype;
- struct utsname nodeinfo;
- unsigned char lock_cmd;
- unsigned char lock_flags;
-
- /* Do the command */
- switch (msg->cmd) {
- /* Just a test message */
- case CLVMD_CMD_TEST:
- if (arglen > buflen) {
- char *new_buf;
- buflen = arglen + 200;
- new_buf = realloc(*buf, buflen);
- if (new_buf == NULL) {
- status = errno;
- free (*buf);
- }
- *buf = new_buf;
- }
- if (*buf) {
- if (uname(&nodeinfo))
- memset(&nodeinfo, 0, sizeof(nodeinfo));
-
- *retlen = 1 + dm_snprintf(*buf, buflen,
- "TEST from %s: %s v%s",
- nodeinfo.nodename, args,
- nodeinfo.release);
- }
- break;
-
- case CLVMD_CMD_LOCK_VG:
- lock_cmd = args[0];
- lock_flags = args[1];
- lockname = &args[2];
- /* Check to see if the VG is in use by LVM1 */
- do_lock_vg(lock_cmd, lock_flags, lockname);
- break;
-
- case CLVMD_CMD_LOCK_LV:
- /* This is the biggie */
- lock_cmd = args[0];
- lock_flags = args[1];
- lockname = &args[2];
- status = do_lock_lv(lock_cmd, lock_flags, lockname);
- /* Replace EIO with something less scary */
- if (status == EIO) {
- *retlen = 1 + dm_snprintf(*buf, buflen, "%s",
- get_last_lvm_error());
- return EIO;
- }
- break;
-
- case CLVMD_CMD_LOCK_QUERY:
- lockname = &args[2];
- if (buflen < 3)
- return EIO;
- if ((locktype = do_lock_query(lockname)))
- *retlen = 1 + dm_snprintf(*buf, buflen, "%s", locktype);
- break;
-
- case CLVMD_CMD_REFRESH:
- do_refresh_cache();
- break;
-
- case CLVMD_CMD_SYNC_NAMES:
- lvm_do_fs_unlock();
- break;
-
- case CLVMD_CMD_SET_DEBUG:
- clvmd_set_debug((debug_t) args[0]);
- break;
-
- case CLVMD_CMD_RESTART:
- status = restart_clvmd();
- break;
-
- case CLVMD_CMD_GET_CLUSTERNAME:
- status = clops->get_cluster_name(*buf, buflen);
- if (!status)
- *retlen = strlen(*buf)+1;
- break;
-
- case CLVMD_CMD_VG_BACKUP:
- /*
- * Do not run backup on local node, caller should do that.
- */
- if (!client)
- lvm_do_backup(&args[2]);
- break;
-
- default:
- /* Won't get here because command is validated in pre_command */
- break;
- }
-
- /* Check the status of the command and return the error text */
- if (status) {
- if (*buf)
- *retlen = dm_snprintf(*buf, buflen, "%s", strerror(status)) + 1;
- else
- *retlen = 0;
- }
-
- return status;
-}
-
-static int lock_vg(struct local_client *client)
-{
- struct dm_hash_table *lock_hash;
- struct clvm_header *header =
- (struct clvm_header *) client->bits.localsock.cmd;
- unsigned char lock_cmd;
- int lock_mode;
- char *args = header->node + strlen(header->node) + 1;
- int lkid;
- int status;
- char *lockname;
-
- /*
- * Keep a track of VG locks in our own hash table. In current
- * practice there should only ever be more than two VGs locked
- * if a user tries to merge lots of them at once
- */
- if (!client->bits.localsock.private) {
- if (!(lock_hash = dm_hash_create(3)))
- return ENOMEM;
- client->bits.localsock.private = (void *) lock_hash;
- } else
- lock_hash = (struct dm_hash_table *) client->bits.localsock.private;
-
- lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
- lock_mode = ((int) lock_cmd & LCK_TYPE_MASK);
- /* lock_flags = args[1]; */
- lockname = &args[2];
- DEBUGLOG("(%p) doing PRE command LOCK_VG '%s' at %x\n", client, lockname, lock_cmd);
-
- if (lock_mode == LCK_UNLOCK) {
- if (!(lkid = (int) (long) dm_hash_lookup(lock_hash, lockname)))
- return EINVAL;
-
- if ((status = sync_unlock(lockname, lkid)))
- status = errno;
- else
- dm_hash_remove(lock_hash, lockname);
- } else {
- /* Read locks need to be PR; other modes get passed through */
- if (lock_mode == LCK_READ)
- lock_mode = LCK_PREAD;
-
- if ((status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid)))
- status = errno;
- else if (!dm_hash_insert(lock_hash, lockname, (void *) (long) lkid))
- return ENOMEM;
- }
-
- return status;
-}
-
-
-/* Pre-command is a good place to get locks that are needed only for the duration
- of the commands around the cluster (don't forget to free them in post-command),
- and to sanity check the command arguments */
-int do_pre_command(struct local_client *client)
-{
- struct clvm_header *header =
- (struct clvm_header *) client->bits.localsock.cmd;
- unsigned char lock_cmd;
- unsigned char lock_flags;
- char *args = header->node + strlen(header->node) + 1;
- int lockid = 0;
- int status = 0;
- char *lockname;
-
- switch (header->cmd) {
- case CLVMD_CMD_TEST:
- status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid);
- client->bits.localsock.private = (void *)(long)lockid;
- break;
-
- case CLVMD_CMD_LOCK_VG:
- lockname = &args[2];
- /* We take out a real lock unless LCK_CACHE was set */
- if (!strncmp(lockname, "V_", 2) ||
- !strncmp(lockname, "P_#", 3))
- status = lock_vg(client);
- break;
-
- case CLVMD_CMD_LOCK_LV:
- lock_cmd = args[0];
- lock_flags = args[1];
- lockname = &args[2];
- status = pre_lock_lv(lock_cmd, lock_flags, lockname);
- break;
-
- case CLVMD_CMD_REFRESH:
- case CLVMD_CMD_GET_CLUSTERNAME:
- case CLVMD_CMD_SET_DEBUG:
- case CLVMD_CMD_VG_BACKUP:
- case CLVMD_CMD_SYNC_NAMES:
- case CLVMD_CMD_LOCK_QUERY:
- case CLVMD_CMD_RESTART:
- break;
-
- default:
- log_error("Unknown command %d received\n", header->cmd);
- status = EINVAL;
- }
- return status;
-}
-
-/* Note that the post-command routine is called even if the pre-command or the real command
- failed */
-int do_post_command(struct local_client *client)
-{
- struct clvm_header *header =
- (struct clvm_header *) client->bits.localsock.cmd;
- int status = 0;
- unsigned char lock_cmd;
- unsigned char lock_flags;
- char *args = header->node + strlen(header->node) + 1;
- char *lockname;
-
- switch (header->cmd) {
- case CLVMD_CMD_TEST:
- status = sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
- client->bits.localsock.private = NULL;
- break;
-
- case CLVMD_CMD_LOCK_LV:
- lock_cmd = args[0];
- lock_flags = args[1];
- lockname = &args[2];
- status = post_lock_lv(lock_cmd, lock_flags, lockname);
- break;
-
- default:
- /* Nothing to do here */
- break;
- }
- return status;
-}
-
-
-/* Called when the client is about to be deleted */
-void cmd_client_cleanup(struct local_client *client)
-{
- struct dm_hash_node *v;
- struct dm_hash_table *lock_hash;
- int lkid;
- char *lockname;
-
- DEBUGLOG("(%p) Client thread cleanup\n", client);
- if (!client->bits.localsock.private)
- return;
-
- lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
-
- dm_hash_iterate(v, lock_hash) {
- lkid = (int)(long)dm_hash_get_data(lock_hash, v);
- lockname = dm_hash_get_key(lock_hash, v);
- DEBUGLOG("(%p) Cleanup: Unlocking lock %s %x\n", client, lockname, lkid);
- (void) sync_unlock(lockname, lkid);
- }
-
- dm_hash_destroy(lock_hash);
- client->bits.localsock.private = NULL;
-}
-
-static int restart_clvmd(void)
-{
- const char **argv;
- char *lv_name;
- int argc = 0, max_locks = 0;
- struct dm_hash_node *hn = NULL;
- char debug_arg[16];
- const char *clvmd = getenv("LVM_CLVMD_BINARY") ? : CLVMD_PATH;
-
- DEBUGLOG("clvmd restart requested\n");
-
- /* Count exclusively-open LVs */
- do {
- hn = get_next_excl_lock(hn, &lv_name);
- if (lv_name) {
- max_locks++;
- if (!*lv_name)
- break; /* FIXME: Is this error ? */
- }
- } while (hn);
-
- /* clvmd + locks (-E uuid) + debug (-d X) + NULL */
- if (!(argv = malloc((max_locks * 2 + 6) * sizeof(*argv))))
- goto_out;
-
- /*
- * Build the command-line
- */
- argv[argc++] = "clvmd";
-
- /* Propagate debug options */
- if (clvmd_get_debug()) {
- if (dm_snprintf(debug_arg, sizeof(debug_arg), "-d%u", clvmd_get_debug()) < 0)
- goto_out;
- argv[argc++] = debug_arg;
- }
-
- /* Propagate foreground options */
- if (clvmd_get_foreground())
- argv[argc++] = "-f";
-
- argv[argc++] = "-I";
- argv[argc++] = clops->name;
-
- /* Now add the exclusively-open LVs */
- hn = NULL;
- do {
- hn = get_next_excl_lock(hn, &lv_name);
- if (lv_name) {
- if (!*lv_name)
- break; /* FIXME: Is this error ? */
- argv[argc++] = "-E";
- argv[argc++] = lv_name;
- DEBUGLOG("excl lock: %s\n", lv_name);
- }
- } while (hn);
- argv[argc] = NULL;
-
- /* Exec new clvmd */
- DEBUGLOG("--- Restarting %s ---\n", clvmd);
- for (argc = 1; argv[argc]; argc++) DEBUGLOG("--- %d: %s\n", argc, argv[argc]);
-
- /* NOTE: This will fail when downgrading! */
- execvp(clvmd, (char **)argv);
-out:
- /* We failed */
- DEBUGLOG("Restart of clvmd failed.\n");
-
- free(argv);
-
- return EIO;
-}
diff --git a/daemons/clvmd/clvmd-common.h b/daemons/clvmd/clvmd-common.h
deleted file mode 100644
index fb1c4879b..000000000
--- a/daemons/clvmd/clvmd-common.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * This file must be included first by every clvmd source file.
- */
-#ifndef _LVM_CLVMD_COMMON_H
-#define _LVM_CLVMD_COMMON_H
-
-#define _REENTRANT
-
-#include "tools/tool.h"
-
-#include "lib/log/lvm-logging.h"
-
-#endif
diff --git a/daemons/clvmd/clvmd-comms.h b/daemons/clvmd/clvmd-comms.h
deleted file mode 100644
index f94077ceb..000000000
--- a/daemons/clvmd/clvmd-comms.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2011 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 General Public License v.2.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Abstraction layer for clvmd cluster communications
- */
-
-#ifndef _CLVMD_COMMS_H
-#define _CLVMD_COMMS_H
-
-struct local_client;
-
-struct cluster_ops {
- const char *name;
- void (*cluster_init_completed) (void);
-
- int (*cluster_send_message) (const void *buf, int msglen,
- const char *csid,
- const char *errtext);
- int (*name_from_csid) (const char *csid, char *name);
- int (*csid_from_name) (char *csid, const char *name);
- int (*get_num_nodes) (void);
- int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len,
- const char *csid,
- struct local_client **new_client);
- int (*get_main_cluster_fd) (void); /* gets accept FD or cman cluster socket */
- int (*cluster_do_node_callback) (struct local_client *client,
- void (*callback) (struct local_client *,
- const char *csid,
- int node_up));
- int (*is_quorate) (void);
-
- void (*get_our_csid) (char *csid);
- void (*add_up_node) (const char *csid);
- void (*reread_config) (void);
- void (*cluster_closedown) (void);
-
- int (*get_cluster_name)(char *buf, int buflen);
-
- int (*sync_lock) (const char *resource, int mode,
- int flags, int *lockid);
- int (*sync_unlock) (const char *resource, int lockid);
-
-};
-
-#ifdef USE_CMAN
-# include <netinet/in.h>
-# include "libcman.h"
-# define CMAN_MAX_CSID_LEN 4
-# ifndef MAX_CSID_LEN
-# define MAX_CSID_LEN CMAN_MAX_CSID_LEN
-# endif
-# undef MAX_CLUSTER_MEMBER_NAME_LEN
-# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_NODENAME_LEN
-# define CMAN_MAX_CLUSTER_MESSAGE 1500
-# define CLUSTER_PORT_CLVMD 11
-struct cluster_ops *init_cman_cluster(void);
-#endif
-
-#ifdef USE_OPENAIS
-# include <openais/saAis.h>
-# include <corosync/totem/totem.h>
-# define OPENAIS_CSID_LEN (sizeof(int))
-# define OPENAIS_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
-# define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
-# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
-# define MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
-# endif
-# ifndef CMAN_MAX_CLUSTER_MESSAGE
-# define CMAN_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
-# endif
-# ifndef MAX_CSID_LEN
-# define MAX_CSID_LEN sizeof(int)
-# endif
-struct cluster_ops *init_openais_cluster(void);
-#endif
-
-#ifdef USE_COROSYNC
-# include <corosync/corotypes.h>
-# define COROSYNC_CSID_LEN (sizeof(int))
-# define COROSYNC_MAX_CLUSTER_MESSAGE 65535
-# define COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
-# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
-# define MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
-# endif
-# ifndef CMAN_MAX_CLUSTER_MESSAGE
-# define CMAN_MAX_CLUSTER_MESSAGE 65535
-# endif
-# ifndef MAX_CSID_LEN
-# define MAX_CSID_LEN sizeof(int)
-# endif
-struct cluster_ops *init_corosync_cluster(void);
-#endif
-
-#ifdef USE_SINGLENODE
-# define SINGLENODE_CSID_LEN (sizeof(int))
-# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
-# define MAX_CLUSTER_MEMBER_NAME_LEN 64
-# endif
-# define SINGLENODE_MAX_CLUSTER_MESSAGE 65535
-# ifndef MAX_CSID_LEN
-# define MAX_CSID_LEN sizeof(int)
-# endif
-struct cluster_ops *init_singlenode_cluster(void);
-#endif
-
-#endif
diff --git a/daemons/clvmd/clvmd-corosync.c b/daemons/clvmd/clvmd-corosync.c
deleted file mode 100644
index 6a9705d36..000000000
--- a/daemons/clvmd/clvmd-corosync.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * Copyright (C) 2009-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * This provides the interface between clvmd and corosync/DLM as the cluster
- * and lock manager.
- */
-
-#include "clvmd-common.h"
-
-#include <pthread.h>
-
-#include "daemons/clvmd/clvm.h"
-#include "clvmd-comms.h"
-#include "clvmd.h"
-#include "lvm-functions.h"
-
-#include "lib/locking/locking.h"
-
-#include <corosync/cpg.h>
-#include <corosync/quorum.h>
-
-#ifdef HAVE_COROSYNC_CONFDB_H
-# include <corosync/confdb.h>
-#elif defined HAVE_COROSYNC_CMAP_H
-# include <corosync/cmap.h>
-#else
-# error "Either HAVE_COROSYNC_CONFDB_H or HAVE_COROSYNC_CMAP_H must be defined."
-#endif
-
-#include <libdlm.h>
-
-#include <syslog.h>
-
-/* Timeout value for several corosync calls */
-#define LOCKSPACE_NAME "clvmd"
-
-static void corosync_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 corosync_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;
-
-/* Number of active nodes */
-static int num_nodes;
-static unsigned int our_nodeid;
-
-static struct local_client *cluster_client;
-
-/* Corosync handles */
-static cpg_handle_t cpg_handle;
-static quorum_handle_t quorum_handle;
-
-/* DLM Handle */
-static dlm_lshandle_t *lockspace;
-
-static struct cpg_name cpg_group_name;
-
-/* Corosync callback structs */
-cpg_callbacks_t corosync_cpg_callbacks = {
- .cpg_deliver_fn = corosync_cpg_deliver_callback,
- .cpg_confchg_fn = corosync_cpg_confchg_callback,
-};
-
-quorum_callbacks_t quorum_callbacks = {
- .quorum_notify_fn = NULL,
-};
-
-struct node_info
-{
- enum {NODE_DOWN, NODE_CLVMD} state;
- int nodeid;
-};
-
-
-/* Set errno to something approximating the right value and return 0 or -1 */
-static int cs_to_errno(cs_error_t err)
-{
- switch(err)
- {
- case CS_OK:
- return 0;
- case CS_ERR_LIBRARY:
- errno = EINVAL;
- break;
- case CS_ERR_VERSION:
- errno = EINVAL;
- break;
- case CS_ERR_INIT:
- errno = EINVAL;
- break;
- case CS_ERR_TIMEOUT:
- errno = ETIME;
- break;
- case CS_ERR_TRY_AGAIN:
- errno = EAGAIN;
- break;
- case CS_ERR_INVALID_PARAM:
- errno = EINVAL;
- break;
- case CS_ERR_NO_MEMORY:
- errno = ENOMEM;
- break;
- case CS_ERR_BAD_HANDLE:
- errno = EINVAL;
- break;
- case CS_ERR_BUSY:
- errno = EBUSY;
- break;
- case CS_ERR_ACCESS:
- errno = EPERM;
- break;
- case CS_ERR_NOT_EXIST:
- errno = ENOENT;
- break;
- case CS_ERR_NAME_TOO_LONG:
- errno = ENAMETOOLONG;
- break;
- case CS_ERR_EXIST:
- errno = EEXIST;
- break;
- case CS_ERR_NO_SPACE:
- errno = ENOSPC;
- break;
- case CS_ERR_INTERRUPT:
- errno = EINTR;
- break;
- case CS_ERR_NAME_NOT_FOUND:
- errno = ENOENT;
- break;
- case CS_ERR_NO_RESOURCES:
- errno = ENOMEM;
- break;
- case CS_ERR_NOT_SUPPORTED:
- errno = EOPNOTSUPP;
- break;
- case CS_ERR_BAD_OPERATION:
- errno = EINVAL;
- break;
- case CS_ERR_FAILED_OPERATION:
- errno = EIO;
- break;
- case CS_ERR_MESSAGE_ERROR:
- errno = EIO;
- break;
- case CS_ERR_QUEUE_FULL:
- errno = EXFULL;
- break;
- case CS_ERR_QUEUE_NOT_AVAILABLE:
- errno = EINVAL;
- break;
- case CS_ERR_BAD_FLAGS:
- errno = EINVAL;
- break;
- case CS_ERR_TOO_BIG:
- errno = E2BIG;
- break;
- case CS_ERR_NO_SECTIONS:
- errno = ENOMEM;
- break;
- default:
- errno = EINVAL;
- break;
- }
- return -1;
-}
-
-static char *print_corosync_csid(const char *csid)
-{
- static char buf[128];
- int id;
-
- memcpy(&id, csid, sizeof(int));
- sprintf(buf, "%d", id);
- return buf;
-}
-
-static void corosync_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, COROSYNC_CSID_LEN);
-
- DEBUGLOG("%u got message from nodeid %d for %d. len %zd\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+COROSYNC_CSID_LEN,
- msg_len-COROSYNC_CSID_LEN, (char*)&nodeid);
-}
-
-static void corosync_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. %zd joined, %zd left, %zd 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,
- COROSYNC_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,
- COROSYNC_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,
- COROSYNC_CSID_LEN);
- if (ninfo)
- ninfo->state = NODE_DOWN;
- }
-
- num_nodes = member_list_entries;
-}
-
-static int _init_cluster(void)
-{
- cs_error_t err;
-
-#ifdef QUORUM_SET /* corosync/quorum.h */
- uint32_t quorum_type;
-#endif
-
- node_hash = dm_hash_create(100);
-
- err = cpg_initialize(&cpg_handle,
- &corosync_cpg_callbacks);
- if (err != CS_OK) {
- syslog(LOG_ERR, "Cannot initialise Corosync CPG service: %d",
- err);
- DEBUGLOG("Cannot initialise Corosync CPG service: %d", err);
- return cs_to_errno(err);
- }
-
-#ifdef QUORUM_SET
- err = quorum_initialize(&quorum_handle,
- &quorum_callbacks,
- &quorum_type);
-
- if (quorum_type != QUORUM_SET) {
- syslog(LOG_ERR, "Corosync quorum service is not configured");
- DEBUGLOG("Corosync quorum service is not configured");
- return EINVAL;
- }
-#else
- err = quorum_initialize(&quorum_handle,
- &quorum_callbacks);
-#endif
-
- if (err != CS_OK) {
- syslog(LOG_ERR, "Cannot initialise Corosync quorum service: %d",
- err);
- DEBUGLOG("Cannot initialise Corosync quorum service: %d", err);
- return cs_to_errno(err);
- }
-
- /* Create a lockspace for LV & VG locks to live in */
- lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
- if (!lockspace) {
- lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
- if (!lockspace) {
- syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
- return -1;
- }
- DEBUGLOG("Created DLM lockspace for CLVMD.\n");
- } else
- DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
-
- dlm_ls_pthread_init(lockspace);
- DEBUGLOG("DLM initialisation complete\n");
-
- /* 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 != CS_OK) {
- cpg_finalize(cpg_handle);
- quorum_finalize(quorum_handle);
- dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
- syslog(LOG_ERR, "Cannot join clvmd process group");
- DEBUGLOG("Cannot join clvmd process group: %d\n", err);
- return cs_to_errno(err);
- }
-
- err = cpg_local_get(cpg_handle,
- &our_nodeid);
- if (err != CS_OK) {
- cpg_finalize(cpg_handle);
- quorum_finalize(quorum_handle);
- dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
- syslog(LOG_ERR, "Cannot get local node id\n");
- return cs_to_errno(err);
- }
- DEBUGLOG("Our local node id is %d\n", our_nodeid);
-
- DEBUGLOG("Connected to Corosync\n");
-
- return 0;
-}
-
-static void _cluster_closedown(void)
-{
- dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
- cpg_finalize(cpg_handle);
- quorum_finalize(quorum_handle);
-}
-
-static void _get_our_csid(char *csid)
-{
- memcpy(csid, &our_nodeid, sizeof(int));
-}
-
-/* Corosync 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, COROSYNC_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, COROSYNC_CSID_LEN);
- if (!ninfo)
- {
- sprintf(name, "UNKNOWN %s", print_corosync_csid(csid));
- return -1;
- }
-
- sprintf(name, "%x", ninfo->nodeid);
- return 0;
-}
-
-static int _get_num_nodes(void)
-{
- 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, COROSYNC_CSID_LEN);
- if (!ninfo) {
- DEBUGLOG("corosync_add_up_node no node_hash entry for csid %s\n",
- print_corosync_csid(csid));
- return;
- }
-
- DEBUGLOG("corosync_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;
-
- dm_hash_iterate(hn, node_hash)
- {
- char csid[COROSYNC_CSID_LEN];
-
- ninfo = dm_hash_get_data(node_hash, hn);
- memcpy(csid, dm_hash_get_key(node_hash, hn), COROSYNC_CSID_LEN);
-
- DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
- ninfo->state);
-
- if (ninfo->state == NODE_CLVMD)
- callback(master_client, csid, 1);
- }
- return 0;
-}
-
-/* Real locking */
-static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
-{
- struct dlm_lksb lksb;
- int err;
-
- DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
-
- if (flags & LKF_CONVERT)
- lksb.sb_lkid = *lockid;
-
- err = dlm_ls_lock_wait(lockspace,
- mode,
- &lksb,
- flags,
- resource,
- strlen(resource),
- 0,
- NULL, NULL, NULL);
-
- if (err != 0)
- {
- DEBUGLOG("dlm_ls_lock returned %d\n", errno);
- return err;
- }
- if (lksb.sb_status != 0)
- {
- DEBUGLOG("dlm_ls_lock returns lksb.sb_status %d\n", lksb.sb_status);
- errno = lksb.sb_status;
- return -1;
- }
-
- DEBUGLOG("lock_resource returning %d, lock_id=%x\n", err, lksb.sb_lkid);
-
- *lockid = lksb.sb_lkid;
-
- return 0;
-}
-
-
-static int _unlock_resource(const char *resource, int lockid)
-{
- struct dlm_lksb lksb;
- int err;
-
- DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
- lksb.sb_lkid = lockid;
-
- err = dlm_ls_unlock_wait(lockspace,
- lockid,
- 0,
- &lksb);
- if (err != 0)
- {
- DEBUGLOG("Unlock returned %d\n", err);
- return err;
- }
- if (lksb.sb_status != EUNLOCK)
- {
- DEBUGLOG("dlm_ls_unlock_wait returns lksb.sb_status: %d\n", lksb.sb_status);
- errno = lksb.sb_status;
- return -1;
- }
-
-
- return 0;
-}
-
-static int _is_quorate(void)
-{
- int quorate;
- if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
- return quorate;
- else
- return 0;
-}
-
-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, CS_DISPATCH_ONE);
- return 1;
-}
-
-static int _cluster_send_message(const void *buf, int msglen, const char *csid,
- const char *errtext)
-{
- static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
- struct iovec iov[2];
- cs_error_t err;
- int target_node;
-
- if (csid)
- memcpy(&target_node, csid, COROSYNC_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;
-
- pthread_mutex_lock(&_mutex);
- err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
- pthread_mutex_unlock(&_mutex);
-
- return cs_to_errno(err);
-}
-
-#ifdef HAVE_COROSYNC_CONFDB_H
-/*
- * We are not necessarily connected to a Red Hat Cluster system,
- * but if we are, this returns the cluster name from cluster.conf.
- * I've used confdb rather than ccs to reduce the inter-package
- * dependancies as well as to allow people to set a cluster name
- * for themselves even if they are not running on RH cluster.
- */
-static int _get_cluster_name(char *buf, int buflen)
-{
- confdb_handle_t handle;
- int result;
- size_t namelen = buflen;
- hdb_handle_t cluster_handle;
- confdb_callbacks_t callbacks = {
- .confdb_key_change_notify_fn = NULL,
- .confdb_object_create_change_notify_fn = NULL,
- .confdb_object_delete_change_notify_fn = NULL
- };
-
- /* This is a default in case everything else fails */
- strncpy(buf, "Corosync", buflen);
-
- /* Look for a cluster name in confdb */
- result = confdb_initialize (&handle, &callbacks);
- if (result != CS_OK)
- return 0;
-
- result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
- if (result != CS_OK)
- goto out;
-
- result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle);
- if (result != CS_OK)
- goto out;
-
- result = confdb_key_get(handle, cluster_handle, (void *)"name", strlen("name"), buf, &namelen);
- if (result != CS_OK)
- goto out;
-
- buf[namelen] = '\0';
-
-out:
- confdb_finalize(handle);
- return 0;
-}
-
-#elif defined HAVE_COROSYNC_CMAP_H
-
-static int _get_cluster_name(char *buf, int buflen)
-{
- cmap_handle_t cmap_handle = 0;
- int result;
- char *name = NULL;
-
- /* This is a default in case everything else fails */
- strncpy(buf, "Corosync", buflen);
-
- /* Look for a cluster name in cmap */
- result = cmap_initialize(&cmap_handle);
- if (result != CS_OK)
- return 0;
-
- result = cmap_get_string(cmap_handle, "totem.cluster_name", &name);
- if (result != CS_OK)
- goto out;
-
- memset(buf, 0, buflen);
- strncpy(buf, name, buflen - 1);
-
-out:
- if (name)
- free(name);
- cmap_finalize(cmap_handle);
- return 0;
-}
-
-#endif
-
-static struct cluster_ops _cluster_corosync_ops = {
- .name = "corosync",
- .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 = _lock_resource,
- .sync_unlock = _unlock_resource,
-};
-
-struct cluster_ops *init_corosync_cluster(void)
-{
- if (!_init_cluster())
- return &_cluster_corosync_ops;
- else
- return NULL;
-}
diff --git a/daemons/clvmd/clvmd-openais.c b/daemons/clvmd/clvmd-openais.c
deleted file mode 100644
index 6b4fb10f6..000000000
--- a/daemons/clvmd/clvmd-openais.c
+++ /dev/null
@@ -1,687 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 "lib/locking/locking.h"
-#include "daemons/clvmd/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);
-
- if (!(client = dm_zalloc(sizeof(*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, "
- FMTsize_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)
-{
- 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;
-}
-
-/* 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;
-
- return NULL;
-}
diff --git a/daemons/clvmd/clvmd-singlenode.c b/daemons/clvmd/clvmd-singlenode.c
deleted file mode 100644
index 2d53f1325..000000000
--- a/daemons/clvmd/clvmd-singlenode.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (C) 2009-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "clvmd-common.h"
-
-#include <pthread.h>
-
-#include "lib/locking/locking.h"
-#include "daemons/clvmd/clvm.h"
-#include "clvmd-comms.h"
-#include "clvmd.h"
-
-#include <sys/un.h>
-#include <sys/socket.h>
-#include <fcntl.h>
-
-static const char SINGLENODE_CLVMD_SOCKNAME[] = DEFAULT_RUN_DIR "/clvmd_singlenode.sock";
-static int listen_fd = -1;
-
-static struct dm_hash_table *_locks;
-static int _lockid;
-
-static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
-/* Using one common condition for all locks for simplicity */
-static pthread_cond_t _lock_cond = PTHREAD_COND_INITIALIZER;
-
-struct lock {
- struct dm_list list;
- int lockid;
- int mode;
-};
-
-static void close_comms(void)
-{
- if (listen_fd != -1 && close(listen_fd))
- stack;
- (void)unlink(SINGLENODE_CLVMD_SOCKNAME);
- listen_fd = -1;
-}
-
-static int init_comms(void)
-{
- mode_t old_mask;
- struct sockaddr_un addr = { .sun_family = AF_UNIX };
-
- if (!dm_strncpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME,
- sizeof(addr.sun_path))) {
- DEBUGLOG("%s: singlenode socket name too long.",
- SINGLENODE_CLVMD_SOCKNAME);
- return -1;
- }
-
- close_comms();
-
- (void) dm_prepare_selinux_context(SINGLENODE_CLVMD_SOCKNAME, S_IFSOCK);
- old_mask = umask(0077);
-
- listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
- if (listen_fd < 0) {
- DEBUGLOG("Can't create local socket: %s\n", strerror(errno));
- goto error;
- }
- /* Set Close-on-exec */
- if (fcntl(listen_fd, F_SETFD, 1)) {
- DEBUGLOG("Setting CLOEXEC on client fd failed: %s\n", strerror(errno));
- goto error;
- }
-
- if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
- DEBUGLOG("Can't bind local socket: %s\n", strerror(errno));
- goto error;
- }
- if (listen(listen_fd, 10) < 0) {
- DEBUGLOG("Can't listen local socket: %s\n", strerror(errno));
- goto error;
- }
-
- umask(old_mask);
- (void) dm_prepare_selinux_context(NULL, 0);
- return 0;
-error:
- umask(old_mask);
- (void) dm_prepare_selinux_context(NULL, 0);
- close_comms();
- return -1;
-}
-
-static int _init_cluster(void)
-{
- int r;
-
- if (!(_locks = dm_hash_create(128))) {
- DEBUGLOG("Failed to allocate single-node hash table.\n");
- return 1;
- }
-
- r = init_comms();
- if (r) {
- dm_hash_destroy(_locks);
- _locks = NULL;
- return r;
- }
-
- DEBUGLOG("Single-node cluster initialised.\n");
- return 0;
-}
-
-static void _cluster_closedown(void)
-{
- close_comms();
-
- /* If there is any awaited resource, kill it softly */
- pthread_mutex_lock(&_lock_mutex);
- dm_hash_destroy(_locks);
- _locks = NULL;
- _lockid = 0;
- pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
- pthread_mutex_unlock(&_lock_mutex);
-}
-
-static void _get_our_csid(char *csid)
-{
- int nodeid = 1;
- memcpy(csid, &nodeid, sizeof(int));
-}
-
-static int _csid_from_name(char *csid, const char *name)
-{
- return 1;
-}
-
-static int _name_from_csid(const char *csid, char *name)
-{
- strcpy(name, "SINGLENODE");
- return 0;
-}
-
-static int _get_num_nodes(void)
-{
- return 1;
-}
-
-/* Node is now known to be running a clvmd */
-static void _add_up_node(const char *csid)
-{
-}
-
-/* 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))
-{
- return 0;
-}
-
-int _lock_file(const char *file, uint32_t flags);
-
-static const char *_get_mode(int mode)
-{
- switch (mode) {
- case LCK_NULL: return "NULL";
- case LCK_READ: return "READ";
- case LCK_PREAD: return "PREAD";
- case LCK_WRITE: return "WRITE";
- case LCK_EXCL: return "EXCLUSIVE";
- case LCK_UNLOCK: return "UNLOCK";
- default: return "????";
- }
-}
-
-/* Real locking */
-static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
-{
- /* DLM table of allowed transition states */
- static const int _dlm_table[6][6] = {
- /* Mode NL CR CW PR PW EX */
- /* NL */ { 1, 1, 1, 1, 1, 1},
- /* CR */ { 1, 1, 1, 1, 1, 0},
- /* CW */ { 1, 1, 1, 0, 0, 0},
- /* PR */ { 1, 1, 0, 1, 0, 0},
- /* PW */ { 1, 1, 0, 0, 0, 0},
- /* EX */ { 1, 0, 0, 0, 0, 0}
- };
-
- struct lock *lck = NULL, *lckt;
- struct dm_list *head;
-
- DEBUGLOG("Locking resource %s, flags=0x%02x (%s%s%s), mode=%s (%d)\n",
- resource, flags,
- (flags & LCKF_NOQUEUE) ? "NOQUEUE" : "",
- ((flags & (LCKF_NOQUEUE | LCKF_CONVERT)) ==
- (LCKF_NOQUEUE | LCKF_CONVERT)) ? "|" : "",
- (flags & LCKF_CONVERT) ? "CONVERT" : "",
- _get_mode(mode), mode);
-
- mode &= LCK_TYPE_MASK;
- pthread_mutex_lock(&_lock_mutex);
-
-retry:
- if (!(head = dm_hash_lookup(_locks, resource))) {
- if (flags & LCKF_CONVERT) {
- /* In real DLM, lock is identified only by lockid, resource is not used */
- DEBUGLOG("Unlocked resource %s cannot be converted\n", resource);
- goto_bad;
- }
- /* Add new locked resource */
- if (!(head = dm_malloc(sizeof(struct dm_list))) ||
- !dm_hash_insert(_locks, resource, head)) {
- dm_free(head);
- goto_bad;
- }
-
- dm_list_init(head);
- } else /* Update/convert locked resource */
- dm_list_iterate_items(lck, head) {
- /* Check is all locks are compatible with requested lock */
- if (flags & LCKF_CONVERT) {
- if (lck->lockid != *lockid)
- continue;
-
- DEBUGLOG("Converting resource %s lockid=%d mode:%s -> %s...\n",
- resource, lck->lockid, _get_mode(lck->mode), _get_mode(mode));
- dm_list_iterate_items(lckt, head) {
- if ((lckt->lockid != *lockid) &&
- !_dlm_table[mode][lckt->mode]) {
- if (!(flags & LCKF_NOQUEUE) &&
- /* TODO: Real dlm uses here conversion queues */
- !pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
- _locks) /* End of the game? */
- goto retry;
- goto bad;
- }
- }
- lck->mode = mode; /* Lock is now converted */
- goto out;
- } else if (!_dlm_table[mode][lck->mode]) {
- DEBUGLOG("Resource %s already locked lockid=%d, mode:%s\n",
- resource, lck->lockid, _get_mode(lck->mode));
- if (!(flags & LCKF_NOQUEUE) &&
- !pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
- _locks) { /* End of the game? */
- DEBUGLOG("Resource %s retrying lock in mode:%s...\n",
- resource, _get_mode(mode));
- goto retry;
- }
- goto bad;
- }
- }
-
- if (!(flags & LCKF_CONVERT)) {
- if (!(lck = dm_malloc(sizeof(struct lock))))
- goto_bad;
-
- *lockid = lck->lockid = ++_lockid;
- lck->mode = mode;
- dm_list_add(head, &lck->list);
- }
-out:
- pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
- pthread_mutex_unlock(&_lock_mutex);
- DEBUGLOG("Locked resource %s, lockid=%d, mode=%s\n",
- resource, lck->lockid, _get_mode(lck->mode));
-
- return 0;
-bad:
- pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
- pthread_mutex_unlock(&_lock_mutex);
- DEBUGLOG("Failed to lock resource %s\n", resource);
-
- return 1; /* fail */
-}
-
-static int _unlock_resource(const char *resource, int lockid)
-{
- struct lock *lck;
- struct dm_list *head;
- int r = 1;
-
- if (lockid < 0) {
- DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n",
- resource, lockid);
- return 1;
- }
-
- DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid);
- pthread_mutex_lock(&_lock_mutex);
- pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
-
- if (!(head = dm_hash_lookup(_locks, resource))) {
- pthread_mutex_unlock(&_lock_mutex);
- DEBUGLOG("Resource %s is not locked.\n", resource);
- return 1;
- }
-
- dm_list_iterate_items(lck, head)
- if (lck->lockid == lockid) {
- dm_list_del(&lck->list);
- dm_free(lck);
- r = 0;
- goto out;
- }
-
- DEBUGLOG("Resource %s has wrong lockid %d.\n", resource, lockid);
-out:
- if (dm_list_empty(head)) {
- //DEBUGLOG("Resource %s is no longer hashed (lockid=%d).\n", resource, lockid);
- dm_hash_remove(_locks, resource);
- dm_free(head);
- }
-
- pthread_mutex_unlock(&_lock_mutex);
-
- return r;
-}
-
-static int _is_quorate(void)
-{
- return 1;
-}
-
-static int _get_main_cluster_fd(void)
-{
- return listen_fd;
-}
-
-static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
- const char *csid,
- struct local_client **new_client)
-{
- return 1;
-}
-
-static int _cluster_send_message(const void *buf, int msglen,
- const char *csid,
- const char *errtext)
-{
- return 0;
-}
-
-static int _get_cluster_name(char *buf, int buflen)
-{
- return dm_strncpy(buf, "localcluster", buflen) ? 0 : 1;
-}
-
-static struct cluster_ops _cluster_singlenode_ops = {
- .name = "singlenode",
- .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 = _lock_resource,
- .sync_unlock = _unlock_resource,
-};
-
-struct cluster_ops *init_singlenode_cluster(void)
-{
- if (!_init_cluster())
- return &_cluster_singlenode_ops;
-
- return NULL;
-}
diff --git a/daemons/clvmd/clvmd.c b/daemons/clvmd/clvmd.c
deleted file mode 100644
index 73f471145..000000000
--- a/daemons/clvmd/clvmd.c
+++ /dev/null
@@ -1,2422 +0,0 @@
-/*
- * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2014 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 General Public License v.2.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * CLVMD: Cluster LVM daemon
- */
-
-#include "clvmd-common.h"
-
-#include "clvmd-comms.h"
-#include "daemons/clvmd/clvm.h"
-#include "clvmd.h"
-#include "lvm-functions.h"
-#include "lvm-version.h"
-#include "refresh_clvmd.h"
-
-#ifdef HAVE_COROSYNC_CONFDB_H
-#include <corosync/confdb.h>
-#endif
-
-#include <pthread.h>
-#include <getopt.h>
-#include <ctype.h>
-#include <stdarg.h>
-
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <signal.h>
-#include <stddef.h>
-#include <syslog.h>
-#include <sys/un.h>
-#include <sys/utsname.h>
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#define MAX_RETRIES 4
-#define MAX_MISSING_LEN 8000 /* Max supported clvmd message size ? */
-
-#define ISLOCAL_CSID(c) (memcmp(c, our_csid, max_csid_len) == 0)
-
-/* Head of the fd list. Also contains
- the cluster_socket details */
-static struct local_client local_client_head;
-static int _local_client_count = 0;
-
-static unsigned short global_xid = 0; /* Last transaction ID issued */
-
-struct cluster_ops *clops = NULL;
-
-static char our_csid[MAX_CSID_LEN];
-static unsigned max_csid_len;
-static unsigned max_cluster_message;
-static unsigned max_cluster_member_name_len;
-
-static void _add_client(struct local_client *new_client, struct local_client *existing_client)
-{
- _local_client_count++;
- DEBUGLOG("(%p) Adding listener for fd %d. (Now %d monitored fds.)\n", new_client, new_client->fd, _local_client_count);
- new_client->next = existing_client->next;
- existing_client->next = new_client;
-}
-
-int add_client(struct local_client *new_client)
-{
- _add_client(new_client, &local_client_head);
-
- return 0;
-}
-
-/* Returns 0 if delfd is found and removed from list */
-static int _del_client(struct local_client *delfd)
-{
- struct local_client *lastfd, *thisfd;
-
- for (lastfd = &local_client_head; (thisfd = lastfd->next); lastfd = thisfd)
- if (thisfd == delfd) {
- DEBUGLOG("(%p) Removing listener for fd %d\n", thisfd, thisfd->fd);
- lastfd->next = delfd->next;
- _local_client_count--;
- return 0;
- }
-
- return 1;
-}
-
-/* Structure of items on the LVM thread list */
-struct lvm_thread_cmd {
- struct dm_list list;
-
- struct local_client *client;
- struct clvm_header *msg;
- char csid[MAX_CSID_LEN];
- int remote; /* Flag */
- int msglen;
- unsigned short xid;
-};
-
-struct lvm_startup_params {
- struct dm_hash_table *excl_uuid;
-};
-
-static debug_t debug = DEBUG_OFF;
-static int foreground_mode = 0;
-static pthread_t lvm_thread;
-/* Stack size 128KiB for thread, must be bigger then DEFAULT_RESERVED_STACK */
-static const size_t STACK_SIZE = 128 * 1024;
-static pthread_attr_t stack_attr;
-static int lvm_thread_exit = 0;
-static pthread_mutex_t lvm_thread_mutex;
-static pthread_mutex_t _debuglog_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t lvm_thread_cond;
-static pthread_barrier_t lvm_start_barrier;
-static struct dm_list lvm_cmd_head;
-static volatile sig_atomic_t quit = 0;
-static volatile sig_atomic_t reread_config = 0;
-static int child_pipe[2];
-
-/* Reasons the daemon failed initialisation */
-#define DFAIL_INIT 1
-#define DFAIL_LOCAL_SOCK 2
-#define DFAIL_CLUSTER_IF 3
-#define DFAIL_MALLOC 4
-#define DFAIL_TIMEOUT 5
-#define SUCCESS 0
-
-typedef enum {IF_AUTO, IF_CMAN, IF_OPENAIS, IF_COROSYNC, IF_SINGLENODE} if_type_t;
-
-/* Prototypes for code further down */
-static void sigusr2_handler(int sig);
-static void sighup_handler(int sig);
-static void sigterm_handler(int sig);
-static void send_local_reply(struct local_client *client, int status,
- int clientid);
-static void free_reply(struct local_client *client);
-static void send_version_message(void);
-static void *pre_and_post_thread(void *arg);
-static int send_message(void *buf, int msglen, const char *csid, int fd,
- const char *errtext);
-static int read_from_local_sock(struct local_client *thisfd);
-static int cleanup_zombie(struct local_client *thisfd);
-static int process_local_command(struct clvm_header *msg, int msglen,
- struct local_client *client,
- unsigned short xid);
-static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
- const char *csid);
-static int process_reply(const struct clvm_header *msg, int msglen,
- const char *csid);
-static int open_local_sock(void);
-static void close_local_sock(int local_socket);
-static int check_local_clvmd(void);
-static struct local_client *find_client(int clientid);
-static void main_loop(int cmd_timeout);
-static void be_daemon(int start_timeout);
-static int check_all_clvmds_running(struct local_client *client);
-static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
- int len, const char *csid,
- struct local_client **new_client);
-static void *lvm_thread_fn(void *) __attribute__((noreturn));
-static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
- int msglen, const char *csid);
-static int distribute_command(struct local_client *thisfd);
-static void hton_clvm(struct clvm_header *hdr);
-static void ntoh_clvm(struct clvm_header *hdr);
-static void add_reply_to_list(struct local_client *client, int status,
- const char *csid, const char *buf, int len);
-static if_type_t parse_cluster_interface(char *ifname);
-static if_type_t get_cluster_type(void);
-
-static void usage(const char *prog, FILE *file)
-{
- fprintf(file, "Usage: %s [options]\n"
- " -C Sets debug level (from -d) on all clvmd instances clusterwide\n"
- " -d[<n>] Set debug logging (0:none, 1:stderr (implies -f option), 2:syslog)\n"
- " -E<uuid> Take this lock uuid as exclusively locked resource (for restart)\n"
- " -f Don't fork, run in the foreground\n"
- " -h Show this help information\n"
- " -I<cmgr> Cluster manager (default: auto)\n"
- " Available cluster managers: "
-#ifdef USE_COROSYNC
- "corosync "
-#endif
-#ifdef USE_CMAN
- "cman "
-#endif
-#ifdef USE_OPENAIS
- "openais "
-#endif
-#ifdef USE_SINGLENODE
- "singlenode "
-#endif
- "\n"
- " -R Tell all running clvmds in the cluster to reload their device cache\n"
- " -S Restart clvmd, preserving exclusive locks\n"
- " -t<secs> Command timeout (default: 60 seconds)\n"
- " -T<secs> Startup timeout (default: 0 seconds)\n"
- " -V Show version of clvmd\n"
- "\n", prog);
-}
-
-/* Called to signal the parent how well we got on during initialisation */
-static void child_init_signal(int status)
-{
- if (child_pipe[1]) {
- /* FIXME Use a proper wrapper around write */
- if (write(child_pipe[1], &status, sizeof(status)) < 0)
- log_sys_error("write", "child_pipe");
- if (close(child_pipe[1]))
- log_sys_error("close", "child_pipe");
- }
-}
-
-static __attribute__((noreturn)) void child_init_signal_and_exit(int status)
-{
- child_init_signal(status);
- exit(status);
-}
-
-static void safe_close(int *fd)
-{
- if (*fd >= 0) {
- int to_close = *fd;
- *fd = -1;
- if (close(to_close))
- log_sys_error("close", ""); /* path */
- }
-}
-
-void debuglog(const char *fmt, ...)
-{
- time_t P;
- va_list ap;
- static int syslog_init = 0;
- char buf_ctime[64];
-
- switch (clvmd_get_debug()) {
- case DEBUG_STDERR:
- pthread_mutex_lock(&_debuglog_mutex);
- va_start(ap,fmt);
- time(&P);
- fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime_r(&P, buf_ctime) + 4);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fflush(stderr);
- pthread_mutex_unlock(&_debuglog_mutex);
- break;
- case DEBUG_SYSLOG:
- pthread_mutex_lock(&_debuglog_mutex);
- if (!syslog_init) {
- openlog("clvmd", LOG_PID, LOG_DAEMON);
- syslog_init = 1;
- }
-
- va_start(ap,fmt);
- vsyslog(LOG_DEBUG, fmt, ap);
- va_end(ap);
- pthread_mutex_unlock(&_debuglog_mutex);
- break;
- case DEBUG_OFF:
- break;
- }
-}
-
-void clvmd_set_debug(debug_t new_debug)
-{
- if (!foreground_mode && new_debug == DEBUG_STDERR)
- new_debug = DEBUG_SYSLOG;
-
- if (new_debug > DEBUG_SYSLOG)
- new_debug = DEBUG_SYSLOG;
-
- debug = new_debug;
-}
-
-debug_t clvmd_get_debug(void)
-{
- return debug;
-}
-
-int clvmd_get_foreground(void)
-{
- return foreground_mode;
-}
-
-static const char *decode_cmd(unsigned char cmdl)
-{
- static char buf[128];
- const char *command;
-
- switch (cmdl) {
- case CLVMD_CMD_TEST:
- command = "TEST";
- break;
- case CLVMD_CMD_LOCK_VG:
- command = "LOCK_VG";
- break;
- case CLVMD_CMD_LOCK_LV:
- command = "LOCK_LV";
- break;
- case CLVMD_CMD_REFRESH:
- command = "REFRESH";
- break;
- case CLVMD_CMD_SET_DEBUG:
- command = "SET_DEBUG";
- break;
- case CLVMD_CMD_GET_CLUSTERNAME:
- command = "GET_CLUSTERNAME";
- break;
- case CLVMD_CMD_VG_BACKUP:
- command = "VG_BACKUP";
- break;
- case CLVMD_CMD_REPLY:
- command = "REPLY";
- break;
- case CLVMD_CMD_VERSION:
- command = "VERSION";
- break;
- case CLVMD_CMD_GOAWAY:
- command = "GOAWAY";
- break;
- case CLVMD_CMD_LOCK:
- command = "LOCK";
- break;
- case CLVMD_CMD_UNLOCK:
- command = "UNLOCK";
- break;
- case CLVMD_CMD_LOCK_QUERY:
- command = "LOCK_QUERY";
- break;
- case CLVMD_CMD_RESTART:
- command = "RESTART";
- break;
- case CLVMD_CMD_SYNC_NAMES:
- command = "SYNC_NAMES";
- break;
- default:
- command = "unknown";
- break;
- }
-
- snprintf(buf, sizeof(buf), "%s (0x%x)", command, cmdl);
-
- return buf;
-}
-
-static void remove_lockfile(void)
-{
- if (unlink(CLVMD_PIDFILE))
- log_sys_error("unlink", CLVMD_PIDFILE);
-}
-
-/*
- * clvmd require dm-ioctl capability for operation
- */
-static void check_permissions(void)
-{
- if (getuid() || geteuid()) {
- log_error("Cannot run as a non-root user.");
-
- /*
- * Fail cleanly here if not run as root, instead of failing
- * later when attempting a root-only operation
- * Preferred exit code from an initscript for this.
- */
- exit(4);
- }
-}
-
-int main(int argc, char *argv[])
-{
- int local_sock;
- struct local_client *newfd, *delfd;
- struct lvm_startup_params lvm_params;
- int opt;
- int cmd_timeout = DEFAULT_CMD_TIMEOUT;
- int start_timeout = 0;
- if_type_t cluster_iface = IF_AUTO;
- sigset_t ss;
- debug_t debug_opt = DEBUG_OFF;
- debug_t debug_arg = DEBUG_OFF;
- int clusterwide_opt = 0;
- mode_t old_mask;
- int ret = 1;
-
- struct option longopts[] = {
- { "help", 0, 0, 'h' },
- { NULL, 0, 0, 0 }
- };
-
- if (!(lvm_params.excl_uuid = dm_hash_create(128))) {
- fprintf(stderr, "Failed to allocate hash table\n");
- return 1;
- }
-
- /* Deal with command-line arguments */
- opterr = 0;
- optind = 0;
- while ((opt = getopt_long(argc, argv, "Vhfd:t:RST:CI:E:",
- longopts, NULL)) != -1) {
- switch (opt) {
- case 'h':
- usage(argv[0], stdout);
- exit(0);
-
- case 'R':
- check_permissions();
- ret = (refresh_clvmd(1) == 1) ? 0 : 1;
- goto out;
-
- case 'S':
- check_permissions();
- ret = (restart_clvmd(clusterwide_opt) == 1) ? 0 : 1;
- goto out;
-
- case 'C':
- clusterwide_opt = 1;
- break;
-
- case 'd':
- debug_opt = DEBUG_STDERR;
- debug_arg = (debug_t) atoi(optarg);
- if (debug_arg == DEBUG_STDERR)
- foreground_mode = 1;
- break;
-
- case 'f':
- foreground_mode = 1;
- break;
- case 't':
- cmd_timeout = atoi(optarg);
- if (!cmd_timeout) {
- fprintf(stderr, "command timeout is invalid\n");
- usage(argv[0], stderr);
- exit(1);
- }
- break;
- case 'I':
- cluster_iface = parse_cluster_interface(optarg);
- break;
- case 'E':
- if (!dm_hash_insert(lvm_params.excl_uuid, optarg, optarg)) {
- fprintf(stderr, "Failed to allocate hash entry\n");
- goto out;
- }
- break;
- case 'T':
- start_timeout = atoi(optarg);
- if (start_timeout <= 0) {
- fprintf(stderr, "startup timeout is invalid\n");
- usage(argv[0], stderr);
- exit(1);
- }
- break;
-
- case 'V':
- printf("Cluster LVM daemon version: %s\n", LVM_VERSION);
- printf("Protocol version: %d.%d.%d\n",
- CLVMD_MAJOR_VERSION, CLVMD_MINOR_VERSION,
- CLVMD_PATCH_VERSION);
- exit(0);
- break;
-
- default:
- usage(argv[0], stderr);
- exit(2);
- }
- }
-
- check_permissions();
-
- /*
- * Switch to C locale to avoid reading large locale-archive file
- * used by some glibc (on some distributions it takes over 100MB).
- * Daemon currently needs to use mlockall().
- */
- if (setenv("LC_ALL", "C", 1))
- perror("Cannot set LC_ALL to C");
-
- /* Setting debug options on an existing clvmd */
- if (debug_opt && !check_local_clvmd()) {
- dm_hash_destroy(lvm_params.excl_uuid);
- return debug_clvmd(debug_arg, clusterwide_opt)==1?0:1;
- }
-
- clvmd_set_debug(debug_arg);
-
- /* Fork into the background (unless requested not to) */
- if (!foreground_mode)
- be_daemon(start_timeout);
-
- (void) dm_prepare_selinux_context(DEFAULT_RUN_DIR, S_IFDIR);
- old_mask = umask(0077);
- if (dm_create_dir(DEFAULT_RUN_DIR) == 0) {
- DEBUGLOG("clvmd: unable to create %s directory\n",
- DEFAULT_RUN_DIR);
- umask(old_mask);
- exit(1);
- }
- umask(old_mask);
-
- /* Create pidfile */
- (void) dm_prepare_selinux_context(CLVMD_PIDFILE, S_IFREG);
- if (dm_create_lockfile(CLVMD_PIDFILE) == 0) {
- DEBUGLOG("clvmd: unable to create lockfile\n");
- exit(1);
- }
- (void) dm_prepare_selinux_context(NULL, 0);
-
- atexit(remove_lockfile);
-
- DEBUGLOG("CLVMD started\n");
-
- /* Open the Unix socket we listen for commands on.
- We do this before opening the cluster socket so that
- potential clients will block rather than error if we are running
- but the cluster is not ready yet */
- local_sock = open_local_sock();
- if (local_sock < 0) {
- child_init_signal_and_exit(DFAIL_LOCAL_SOCK);
- /* NOTREACHED */
- }
-
- /* Set up signal handlers, USR1 is for cluster change notifications (in cman)
- USR2 causes child threads to exit.
- (HUP used to cause gulm to re-read the nodes list from CCS.)
- PIPE should be ignored */
- signal(SIGUSR2, sigusr2_handler);
- signal(SIGHUP, sighup_handler);
- signal(SIGPIPE, SIG_IGN);
-
- /* Block SIGUSR2/SIGINT/SIGTERM in process */
- sigemptyset(&ss);
- sigaddset(&ss, SIGUSR2);
- sigaddset(&ss, SIGINT);
- sigaddset(&ss, SIGTERM);
- sigprocmask(SIG_BLOCK, &ss, NULL);
-
- /* Initialise the LVM thread variables */
- dm_list_init(&lvm_cmd_head);
- if (pthread_attr_init(&stack_attr) ||
- pthread_attr_setstacksize(&stack_attr, STACK_SIZE + getpagesize())) {
- log_sys_error("pthread_attr_init", "");
- exit(1);
- }
- pthread_mutex_init(&lvm_thread_mutex, NULL);
- pthread_cond_init(&lvm_thread_cond, NULL);
- pthread_barrier_init(&lvm_start_barrier, NULL, 2);
- init_lvhash();
-
- /* Start the cluster interface */
- if (cluster_iface == IF_AUTO)
- cluster_iface = get_cluster_type();
-
-#ifdef USE_CMAN
- if ((cluster_iface == IF_AUTO || cluster_iface == IF_CMAN) &&
- (clops = init_cman_cluster())) {
- max_csid_len = CMAN_MAX_CSID_LEN;
- max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE;
- max_cluster_member_name_len = CMAN_MAX_NODENAME_LEN;
- syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN");
- }
-#endif
-#ifdef USE_COROSYNC
- if (!clops)
- if (((cluster_iface == IF_AUTO || cluster_iface == IF_COROSYNC) &&
- (clops = init_corosync_cluster()))) {
- max_csid_len = COROSYNC_CSID_LEN;
- max_cluster_message = COROSYNC_MAX_CLUSTER_MESSAGE;
- max_cluster_member_name_len = COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN;
- syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to Corosync");
- }
-#endif
-#ifdef USE_OPENAIS
- if (!clops)
- if ((cluster_iface == IF_AUTO || cluster_iface == IF_OPENAIS) &&
- (clops = init_openais_cluster())) {
- max_csid_len = OPENAIS_CSID_LEN;
- max_cluster_message = OPENAIS_MAX_CLUSTER_MESSAGE;
- max_cluster_member_name_len = OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN;
- syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to OpenAIS");
- }
-#endif
-#ifdef USE_SINGLENODE
- if (!clops)
- if (cluster_iface == IF_SINGLENODE && (clops = init_singlenode_cluster())) {
- max_csid_len = SINGLENODE_CSID_LEN;
- max_cluster_message = SINGLENODE_MAX_CLUSTER_MESSAGE;
- max_cluster_member_name_len = MAX_CLUSTER_MEMBER_NAME_LEN;
- syslog(LOG_NOTICE, "Cluster LVM daemon started - running in single-node mode");
- }
-#endif
-
- if (!clops) {
- DEBUGLOG("Can't initialise cluster interface\n");
- log_error("Can't initialise cluster interface.");
- child_init_signal_and_exit(DFAIL_CLUSTER_IF);
- /* NOTREACHED */
- }
- DEBUGLOG("Cluster ready, doing some more initialisation\n");
-
- /* Save our CSID */
- clops->get_our_csid(our_csid);
-
- /* Initialise the FD list head */
- local_client_head.fd = clops->get_main_cluster_fd();
- local_client_head.type = CLUSTER_MAIN_SOCK;
- local_client_head.callback = clops->cluster_fd_callback;
- _local_client_count++;
-
- /* Add the local socket to the list */
- if (!(newfd = dm_zalloc(sizeof(struct local_client)))) {
- child_init_signal_and_exit(DFAIL_MALLOC);
- /* NOTREACHED */
- }
-
- newfd->fd = local_sock;
- newfd->type = LOCAL_RENDEZVOUS;
- newfd->callback = local_rendezvous_callback;
-
- (void) add_client(newfd);
-
- /* This needs to be started after cluster initialisation
- as it may need to take out locks */
- DEBUGLOG("Starting LVM thread\n");
- DEBUGLOG("(%p) Main cluster socket fd %d with local socket %d (%p)\n",
- &local_client_head, local_client_head.fd, newfd->fd, newfd);
-
- /* Don't let anyone else to do work until we are started */
- if (pthread_create(&lvm_thread, &stack_attr, lvm_thread_fn, &lvm_params)) {
- log_sys_error("pthread_create", "");
- goto out;
- }
-
- /* Don't start until the LVM thread is ready */
- pthread_barrier_wait(&lvm_start_barrier);
-
- /* Tell the rest of the cluster our version number */
- if (clops->cluster_init_completed)
- clops->cluster_init_completed();
-
- DEBUGLOG("clvmd ready for work\n");
- child_init_signal(SUCCESS);
-
- /* Try to shutdown neatly */
- signal(SIGTERM, sigterm_handler);
- signal(SIGINT, sigterm_handler);
-
- /* Do some work */
- main_loop(cmd_timeout);
-
- pthread_mutex_lock(&lvm_thread_mutex);
- lvm_thread_exit = 1;
- pthread_cond_signal(&lvm_thread_cond);
- pthread_mutex_unlock(&lvm_thread_mutex);
- if ((errno = pthread_join(lvm_thread, NULL)))
- log_sys_error("pthread_join", "");
-
- close_local_sock(local_sock);
-
- while ((delfd = local_client_head.next)) {
- local_client_head.next = delfd->next;
- _local_client_count--;
- /* Failing cleanup_zombie leaks... */
- if (delfd->type == LOCAL_SOCK && !cleanup_zombie(delfd))
- cmd_client_cleanup(delfd); /* calls sync_unlock */
- if (delfd->fd != local_sock)
- safe_close(&(delfd->fd));
- dm_free(delfd);
- }
-
- DEBUGLOG("cluster_closedown\n");
- destroy_lvhash();
- clops->cluster_closedown();
-
- ret = 0;
-out:
- dm_hash_destroy(lvm_params.excl_uuid);
-
- return ret;
-}
-
-/* Called when the cluster layer has completed initialisation.
- We send the version message */
-void clvmd_cluster_init_completed(void)
-{
- send_version_message();
-}
-
-/* Data on a connected socket */
-static int local_sock_callback(struct local_client *thisfd, char *buf, int len,
- const char *csid,
- struct local_client **new_client)
-{
- *new_client = NULL;
- return read_from_local_sock(thisfd);
-}
-
-/* Data on a connected socket */
-static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
- int len, const char *csid,
- struct local_client **new_client)
-{
- /* Someone connected to our local socket, accept it. */
-
- struct sockaddr_un socka;
- struct local_client *newfd;
- socklen_t sl = sizeof(socka);
- int client_fd = accept(thisfd->fd, (struct sockaddr *) &socka, &sl);
-
- if (client_fd == -1 && errno == EINTR)
- return 1;
-
- if (client_fd >= 0) {
- if (!(newfd = dm_zalloc(sizeof(*newfd)))) {
- if (close(client_fd))
- log_sys_error("close", "socket");
- return 1;
- }
-
- pthread_cond_init(&newfd->bits.localsock.cond, NULL);
- pthread_mutex_init(&newfd->bits.localsock.mutex, NULL);
-
- if (fcntl(client_fd, F_SETFD, 1))
- DEBUGLOG("(%p) Setting CLOEXEC on client fd %d failed: %s\n", thisfd, client_fd, strerror(errno));
-
- newfd->fd = client_fd;
- newfd->type = LOCAL_SOCK;
- newfd->callback = local_sock_callback;
- newfd->bits.localsock.all_success = 1;
- DEBUGLOG("(%p) Got new connection on fd %d\n", newfd, newfd->fd);
- *new_client = newfd;
- }
- return 1;
-}
-
-static int local_pipe_callback(struct local_client *thisfd, char *buf,
- int maxlen, const char *csid,
- struct local_client **new_client)
-{
- int len;
- char buffer[PIPE_BUF];
- struct local_client *sock_client = thisfd->bits.pipe.client;
- int status = -1; /* in error by default */
-
- len = read(thisfd->fd, buffer, sizeof(int));
- if (len == -1 && errno == EINTR)
- return 1;
-
- if (len == sizeof(int))
- memcpy(&status, buffer, sizeof(int));
-
- DEBUGLOG("(%p) Read on pipe %d, %d bytes, status %d\n",
- thisfd, thisfd->fd, len, status);
-
- /* EOF on pipe or an error, close it */
- if (len <= 0) {
- void *ret = &status;
- if (close(thisfd->fd))
- log_sys_error("close", "local_pipe");
-
- /* Clear out the cross-link */
- if (thisfd->bits.pipe.client)
- thisfd->bits.pipe.client->bits.localsock.pipe_client = NULL;
-
- /* Reap child thread */
- if (thisfd->bits.pipe.threadid) {
- if ((errno = pthread_join(thisfd->bits.pipe.threadid, &ret)))
- log_sys_error("pthread_join", "");
-
- thisfd->bits.pipe.threadid = 0;
- if (thisfd->bits.pipe.client)
- thisfd->bits.pipe.client->bits.localsock.threadid = 0;
- }
- return -1;
- } else {
- DEBUGLOG("(%p) Background routine status was %d, sock_client %p\n",
- thisfd, status, sock_client);
- /* But has the client gone away ?? */
- if (!sock_client) {
- DEBUGLOG("(%p) Got pipe response for dead client, ignoring it\n", thisfd);
- } else {
- /* If error then just return that code */
- if (status)
- send_local_reply(sock_client, status,
- sock_client->fd);
- else {
- /* FIXME: closer inspect this code since state is write thread protected */
- pthread_mutex_lock(&sock_client->bits.localsock.mutex);
- if (sock_client->bits.localsock.state == POST_COMMAND) {
- pthread_mutex_unlock(&sock_client->bits.localsock.mutex);
- send_local_reply(sock_client, 0,
- sock_client->fd);
- } else {
- /* PRE_COMMAND finished. */
- pthread_mutex_unlock(&sock_client->bits.localsock.mutex);
- if ((status = distribute_command(sock_client)))
- send_local_reply(sock_client, EFBIG,
- sock_client->fd);
- }
- }
- }
- }
- return len;
-}
-
-/* If a noed is up, look for it in the reply array, if it's not there then
- add one with "ETIMEDOUT".
- NOTE: This won't race with real replies because they happen in the same thread.
-*/
-static void timedout_callback(struct local_client *client, const char *csid,
- int node_up)
-{
- struct node_reply *reply;
- char nodename[max_cluster_member_name_len];
-
- if (!node_up)
- return;
-
- clops->name_from_csid(csid, nodename);
- DEBUGLOG("(%p) Checking for a reply from %s\n", client, nodename);
- pthread_mutex_lock(&client->bits.localsock.mutex);
-
- reply = client->bits.localsock.replies;
- while (reply && strcmp(reply->node, nodename) != 0)
- reply = reply->next;
-
- pthread_mutex_unlock(&client->bits.localsock.mutex);
-
- if (!reply) {
- DEBUGLOG("(%p) Node %s timed-out\n", client, nodename);
- add_reply_to_list(client, ETIMEDOUT, csid,
- "Command timed out", 18);
- }
-}
-
-/* Called when the request has timed out on at least one node. We fill in
- the remaining node entries with ETIMEDOUT and return.
-
- By the time we get here the node that caused
- the timeout could have gone down, in which case we will never get the expected
- number of replies that triggers the post command so we need to do it here
-*/
-static void request_timed_out(struct local_client *client)
-{
- DEBUGLOG("(%p) Request timed-out. padding\n", client);
- clops->cluster_do_node_callback(client, timedout_callback);
-
- if (!client->bits.localsock.threadid)
- return;
-
- pthread_mutex_lock(&client->bits.localsock.mutex);
-
- if (!client->bits.localsock.finished &&
- (client->bits.localsock.num_replies !=
- client->bits.localsock.expected_replies)) {
- /* Post-process the command */
- client->bits.localsock.state = POST_COMMAND;
- pthread_cond_signal(&client->bits.localsock.cond);
- }
-
- pthread_mutex_unlock(&client->bits.localsock.mutex);
-}
-
-/* This is where the real work happens */
-static void main_loop(int cmd_timeout)
-{
- sigset_t ss;
-
- DEBUGLOG("Using timeout of %d seconds\n", cmd_timeout);
-
- sigemptyset(&ss);
- sigaddset(&ss, SIGINT);
- sigaddset(&ss, SIGTERM);
- pthread_sigmask(SIG_UNBLOCK, &ss, NULL);
- /* Main loop */
- while (!quit) {
- fd_set in;
- int select_status;
- struct local_client *thisfd, *nextfd;
- struct timeval tv = { cmd_timeout, 0 };
- int quorate = clops->is_quorate();
- int client_count = 0;
- int max_fd = 0;
-
- /* Wait on the cluster FD and all local sockets/pipes */
- local_client_head.fd = clops->get_main_cluster_fd();
- FD_ZERO(&in);
-
- for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) {
- client_count++;
- max_fd = max(max_fd, thisfd->fd);
- }
-
- if (max_fd > FD_SETSIZE - 32) {
- fprintf(stderr, "WARNING: There are too many connections to clvmd. Investigate and take action now!\n");
- fprintf(stderr, "WARNING: Your cluster may freeze up if the number of clvmd file descriptors (%d) exceeds %d.\n", max_fd + 1, FD_SETSIZE);
- }
-
- for (thisfd = &local_client_head; thisfd; thisfd = nextfd) {
- nextfd = thisfd->next;
-
- if (thisfd->removeme && !cleanup_zombie(thisfd)) {
- /* cleanup_zombie might have removed the next list element */
- nextfd = thisfd->next;
-
- (void) _del_client(thisfd);
-
- DEBUGLOG("(%p) removeme set with %d monitored fds remaining\n", thisfd, _local_client_count);
-
- /* Queue cleanup, this also frees the client struct */
- add_to_lvmqueue(thisfd, NULL, 0, NULL);
- continue;
- }
-
- if (thisfd->removeme)
- continue;
-
- /* if the cluster is not quorate then don't listen for new requests */
- if ((thisfd->type != LOCAL_RENDEZVOUS &&
- thisfd->type != LOCAL_SOCK) || quorate)
- if (thisfd->fd < FD_SETSIZE)
- FD_SET(thisfd->fd, &in);
- }
-
- select_status = select(FD_SETSIZE, &in, NULL, NULL, &tv);
-
- if (reread_config) {
- int saved_errno = errno;
-
- reread_config = 0;
- DEBUGLOG("got SIGHUP\n");
- if (clops->reread_config)
- clops->reread_config();
- errno = saved_errno;
- }
-
- if (select_status > 0) {
- char csid[MAX_CSID_LEN];
- char buf[max_cluster_message];
-
- for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) {
- if (thisfd->fd < FD_SETSIZE && FD_ISSET(thisfd->fd, &in)) {
- struct local_client *newfd = NULL;
- int ret;
-
- /* FIXME Remove from main thread in case it blocks! */
- /* Do callback */
- ret = thisfd->callback(thisfd, buf, sizeof(buf),
- csid, &newfd);
- /* Ignore EAGAIN */
- if (ret < 0 && (errno == EAGAIN || errno == EINTR)) {
- continue;
- }
-
- /* Got error or EOF: Remove it from the list safely */
- if (ret <= 0) {
- int type = thisfd->type;
-
- /* If the cluster socket shuts down, so do we */
- if (type == CLUSTER_MAIN_SOCK ||
- type == CLUSTER_INTERNAL)
- goto closedown;
-
- DEBUGLOG("(%p) ret == %d, errno = %d. removing client\n",
- thisfd, ret, errno);
- thisfd->removeme = 1;
- continue;
- }
-
- /* New client...simply add it to the list */
- if (newfd) {
- _add_client(newfd, thisfd);
- thisfd = newfd;
- }
- }
- }
- }
-
- /* Select timed out. Check for clients that have been waiting too long for a response */
- if (select_status == 0) {
- time_t the_time = time(NULL);
-
- for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) {
- if (thisfd->type == LOCAL_SOCK &&
- thisfd->bits.localsock.sent_out &&
- (thisfd->bits.localsock.sent_time + cmd_timeout) < the_time &&
- thisfd->bits.localsock.expected_replies !=
- thisfd->bits.localsock.num_replies) {
- /* Send timed out message + replies we already have */
- DEBUGLOG("Request to client %p timed-out (send: %ld, now: %ld)\n",
- thisfd, thisfd->bits.localsock.sent_time, the_time);
-
- thisfd->bits.localsock.all_success = 0;
-
- request_timed_out(thisfd);
- }
- }
- }
- if (select_status < 0) {
- if (errno == EINTR)
- continue;
-
-#ifdef DEBUG
- perror("select error");
- exit(-1);
-#endif
- }
- }
-
- closedown:
- if (quit)
- DEBUGLOG("SIGTERM received\n");
-}
-
-static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout)
-{
- int child_status;
- fd_set fds;
- struct timeval tv = {timeout, 0};
-
- FD_ZERO(&fds);
- FD_SET(c_pipe, &fds);
-
- switch (select(c_pipe+1, &fds, NULL, NULL, timeout? &tv: NULL)) {
- case 0:
- fprintf(stderr, "clvmd startup timed out\n");
- exit(DFAIL_TIMEOUT);
- case 1:
- if (read(c_pipe, &child_status, sizeof(child_status)) !=
- sizeof(child_status)) {
- fprintf(stderr, "clvmd failed in initialisation\n");
- exit(DFAIL_INIT);
- }
-
- switch (child_status) {
- case SUCCESS:
- break;
- case DFAIL_INIT:
- fprintf(stderr, "clvmd failed in initialisation\n");
- break;
- case DFAIL_LOCAL_SOCK:
- fprintf(stderr, "clvmd could not create local socket\n");
- fprintf(stderr, "Another clvmd is probably already running\n");
- break;
- case DFAIL_CLUSTER_IF:
- fprintf(stderr, "clvmd could not connect to cluster manager\n");
- fprintf(stderr, "Consult syslog for more information\n");
- break;
- case DFAIL_MALLOC:
- fprintf(stderr, "clvmd failed, not enough memory\n");
- break;
- default:
- fprintf(stderr, "clvmd failed, error was %d\n", child_status);
- break;
- }
- exit(child_status);
- default:
- fprintf(stderr, "clvmd startup, select failed: %s\n", strerror(errno));
- exit(DFAIL_INIT);
- }
-}
-
-/*
- * Fork into the background and detach from our parent process.
- * In the interests of user-friendliness we wait for the daemon
- * to complete initialisation before returning its status
- * the the user.
- */
-static void be_daemon(int timeout)
-{
- int devnull = open("/dev/null", O_RDWR);
- if (devnull == -1) {
- perror("Can't open /dev/null");
- exit(3);
- }
-
- if (pipe(child_pipe)) {
- perror("Error creating pipe");
- exit(3);
- }
-
- switch (fork()) {
- case -1:
- perror("clvmd: can't fork");
- exit(2);
-
- case 0: /* Child */
- (void) close(child_pipe[0]);
- break;
-
- default: /* Parent */
- (void) close(devnull);
- (void) close(child_pipe[1]);
- wait_for_child(child_pipe[0], timeout); /* noreturn */
- }
-
- /* Detach ourself from the calling environment */
- if ((dup2(devnull, STDIN_FILENO) == -1) ||
- (dup2(devnull, STDOUT_FILENO) == -1) ||
- (dup2(devnull, STDERR_FILENO) == -1)) {
- perror("Error setting terminal FDs to /dev/null");
- log_error("Error setting terminal FDs to /dev/null: %m");
- exit(5);
- }
-
- if ((devnull > STDERR_FILENO) && close(devnull)) {
- log_sys_error("close", "/dev/null");
- exit(7);
- }
-
- if (chdir("/")) {
- log_error("Error setting current directory to /: %m");
- exit(6);
- }
-
- setsid();
-}
-
-static int verify_message(char *buf, int len)
-{
- struct clvm_header *h = (struct clvm_header *)buf;
-
- if (len < (int)sizeof(struct clvm_header)) {
- log_error("verify_message short len %d.", len);
- return -1;
- }
-
- switch (h->cmd) {
- case CLVMD_CMD_REPLY:
- case CLVMD_CMD_VERSION:
- case CLVMD_CMD_GOAWAY:
- case CLVMD_CMD_TEST:
- case CLVMD_CMD_LOCK:
- case CLVMD_CMD_UNLOCK:
- case CLVMD_CMD_LOCK_LV:
- case CLVMD_CMD_LOCK_VG:
- case CLVMD_CMD_LOCK_QUERY:
- case CLVMD_CMD_REFRESH:
- case CLVMD_CMD_GET_CLUSTERNAME:
- case CLVMD_CMD_SET_DEBUG:
- case CLVMD_CMD_VG_BACKUP:
- case CLVMD_CMD_RESTART:
- case CLVMD_CMD_SYNC_NAMES:
- break;
- default:
- log_error("verify_message bad cmd %x.", h->cmd);
- return -1;
- }
-
- /* TODO: we may be able to narrow len/flags/clientid/arglen checks based on cmd */
-
- if (h->flags & ~(CLVMD_FLAG_LOCAL | CLVMD_FLAG_SYSTEMLV | CLVMD_FLAG_NODEERRS | CLVMD_FLAG_REMOTE)) {
- log_error("verify_message bad flags %x.", h->flags);
- return -1;
- }
-
- if (h->arglen > max_cluster_message) {
- log_error("verify_message bad arglen %x max %d.", h->arglen, max_cluster_message);
- return -1;
- }
-
- return 0;
-}
-
-static void dump_message(char *buf, int len)
-{
- unsigned char row[8];
- char str[9];
- int i, j = 0;
-
- str[8] = '\0';
- if (len > 128)
- len = 128;
-
- for (i = 0; i < len; ++i) {
- row[j] = buf[i];
- str[j] = (isprint(buf[i])) ? buf[i] : ' ';
-
- if (i + 1 == len) {
- for (;j < 8; ++j) {
- row[j] = 0;
- str[j] = ' ';
- }
-
- log_error("%02x %02x %02x %02x %02x %02x %02x %02x [%s]",
- row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], str);
- j = 0;
- }
- }
-}
-
-static int cleanup_zombie(struct local_client *thisfd)
-{
- int *status;
- struct local_client *pipe_client;
-
- if (thisfd->type != LOCAL_SOCK)
- return 0;
-
- if (!thisfd->bits.localsock.cleanup_needed)
- return 0;
-
- DEBUGLOG("(%p) EOF on local socket %d: inprogress=%d\n",
- thisfd, thisfd->fd, thisfd->bits.localsock.in_progress);
-
- if ((pipe_client = thisfd->bits.localsock.pipe_client))
- pipe_client = pipe_client->bits.pipe.client;
-
- /* If the client went away in mid command then tidy up */
- if (thisfd->bits.localsock.in_progress) {
- DEBUGLOG("Sending SIGUSR2 to pre&post thread (%p in-progress)\n", pipe_client);
- pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2);
- if (pthread_mutex_trylock(&thisfd->bits.localsock.mutex))
- return 1;
- thisfd->bits.localsock.state = POST_COMMAND;
- thisfd->bits.localsock.finished = 1;
- pthread_cond_signal(&thisfd->bits.localsock.cond);
- pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
-
- /* Free any unsent buffers */
- free_reply(thisfd);
- }
-
- /* Kill the subthread & free resources */
- if (thisfd->bits.localsock.threadid) {
- DEBUGLOG("(%p) Waiting for pre&post thread\n", pipe_client);
- pthread_mutex_lock(&thisfd->bits.localsock.mutex);
- thisfd->bits.localsock.state = PRE_COMMAND;
- thisfd->bits.localsock.finished = 1;
- pthread_cond_signal(&thisfd->bits.localsock.cond);
- pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
-
- if ((errno = pthread_join(thisfd->bits.localsock.threadid,
- (void **) &status)))
- log_sys_error("pthread_join", "");
-
- DEBUGLOG("(%p) Joined pre&post thread\n", pipe_client);
-
- thisfd->bits.localsock.threadid = 0;
-
- /* Remove the pipe client */
- if (thisfd->bits.localsock.pipe_client) {
- struct local_client *delfd = thisfd->bits.localsock.pipe_client;
-
- (void) close(delfd->fd); /* Close pipe */
- (void) close(thisfd->bits.localsock.pipe);
-
- /* Remove pipe client */
- if (!_del_client(delfd)) {
- dm_free(delfd);
- thisfd->bits.localsock.pipe_client = NULL;
- }
- }
- }
-
- /* Free the command buffer */
- dm_free(thisfd->bits.localsock.cmd);
-
- safe_close(&(thisfd->fd));
- thisfd->bits.localsock.cleanup_needed = 0;
-
- return 0;
-}
-
-/* Called when we have a read from the local socket.
- was in the main loop but it's grown up and is a big girl now */
-static int read_from_local_sock(struct local_client *thisfd)
-{
- int len;
- int argslen;
- int missing_len;
- char buffer[PIPE_BUF + 1];
- char csid[MAX_CSID_LEN];
- int comms_pipe[2];
- struct local_client *newfd;
- struct clvm_header *inheader = (struct clvm_header *) buffer;
- int status;
-
- len = read(thisfd->fd, buffer, sizeof(buffer) - 1);
- if (len == -1 && errno == EINTR)
- return 1;
-
- DEBUGLOG("(%p) Read on local socket %d, len = %d\n", thisfd, thisfd->fd, len);
-
- if (len && verify_message(buffer, len) < 0) {
- log_error("read_from_local_sock from %d len %d bad verify.",
- thisfd->fd, len);
- dump_message(buffer, len);
- /* force error handling below */
- len = 0;
- }
-
- /* EOF or error on socket */
- if (len <= 0) {
- thisfd->bits.localsock.cleanup_needed = 1;
- (void) cleanup_zombie(thisfd); /* ignore errors here */
- return 0;
- }
-
- buffer[len] = 0; /* Ensure \0 terminated */
-
- /* Fill in the client ID */
- inheader->clientid = htonl(thisfd->fd);
-
- /* If we are already busy then return an error */
- if (thisfd->bits.localsock.in_progress) {
- struct clvm_header reply = {
- .cmd = CLVMD_CMD_REPLY,
- .status = EBUSY
- };
- send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
- "Error sending EBUSY reply to local user");
- return len;
- }
-
- /* See if we have the whole message */
- argslen = len - strlen(inheader->node) - sizeof(struct clvm_header);
- missing_len = inheader->arglen - argslen;
-
- if (missing_len < 0)
- missing_len = 0;
-
- /* We need at least sizeof(struct clvm_header) bytes in buffer */
- if (len < (int)sizeof(struct clvm_header) || /* Already handled in verify_message() */
- argslen < 0 || missing_len > MAX_MISSING_LEN) {
- struct clvm_header reply = {
- .cmd = CLVMD_CMD_REPLY,
- .status = EINVAL
- };
- send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
- "Error sending EINVAL reply to local user");
- return 0;
- }
-
- /* Free any old buffer space */
- dm_free(thisfd->bits.localsock.cmd);
-
- /* Save the message */
- if (!(thisfd->bits.localsock.cmd = dm_malloc(len + missing_len))) {
- struct clvm_header reply = {
- .cmd = CLVMD_CMD_REPLY,
- .status = ENOMEM
- };
- send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
- "Error sending ENOMEM reply to local user");
- return 0;
- }
- memcpy(thisfd->bits.localsock.cmd, buffer, len);
- thisfd->bits.localsock.cmd_len = len + missing_len;
- inheader = (struct clvm_header *) thisfd->bits.localsock.cmd;
-
- /* If we don't have the full message then read the rest now */
- if (missing_len) {
- char *argptr = inheader->node + strlen(inheader->node) + 1;
-
- while (missing_len > 0) {
- DEBUGLOG("(%p) got %d bytes, need another %d (total %d)\n",
- thisfd, argslen, missing_len, inheader->arglen);
- len = read(thisfd->fd, argptr + argslen, missing_len);
- if (len == -1 && errno == EINTR)
- continue;
-
- if (len <= 0) {
- /* EOF or error on socket */
- DEBUGLOG("(%p) EOF on local socket\n", thisfd);
- dm_free(thisfd->bits.localsock.cmd);
- thisfd->bits.localsock.cmd = NULL;
- return 0;
- }
-
- missing_len -= len;
- argslen += len;
- }
- }
-
- /* Only run the command if all the cluster nodes are running CLVMD */
- if (((inheader->flags & CLVMD_FLAG_LOCAL) == 0) &&
- (check_all_clvmds_running(thisfd) == -1)) {
- thisfd->bits.localsock.expected_replies = 0;
- thisfd->bits.localsock.num_replies = 0;
- send_local_reply(thisfd, EHOSTDOWN, thisfd->fd);
- return len;
- }
-
- /* Check the node name for validity */
- if (inheader->node[0] && clops->csid_from_name(csid, inheader->node)) {
- /* Error, node is not in the cluster */
- struct clvm_header reply = {
- .cmd = CLVMD_CMD_REPLY,
- .status = ENOENT
- };
-
- DEBUGLOG("(%p) Unknown node: '%s'\n", thisfd, inheader->node);
- send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
- "Error sending ENOENT reply to local user");
- thisfd->bits.localsock.expected_replies = 0;
- thisfd->bits.localsock.num_replies = 0;
- thisfd->bits.localsock.in_progress = FALSE;
- thisfd->bits.localsock.sent_out = FALSE;
- return len;
- }
-
- /* If we already have a subthread then just signal it to start */
- if (thisfd->bits.localsock.threadid) {
- pthread_mutex_lock(&thisfd->bits.localsock.mutex);
- thisfd->bits.localsock.state = PRE_COMMAND;
- pthread_cond_signal(&thisfd->bits.localsock.cond);
- pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
- return len;
- }
-
- /* Create a pipe and add the reading end to our FD list */
- if (pipe(comms_pipe)) {
- struct clvm_header reply = {
- .cmd = CLVMD_CMD_REPLY,
- .status = EBUSY
- };
-
- DEBUGLOG("(%p) Creating pipe failed: %s\n", thisfd, strerror(errno));
- send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
- "Error sending EBUSY reply to local user");
- return len;
- }
-
- if (!(newfd = dm_zalloc(sizeof(*newfd)))) {
- struct clvm_header reply = {
- .cmd = CLVMD_CMD_REPLY,
- .status = ENOMEM
- };
-
- (void) close(comms_pipe[0]);
- (void) close(comms_pipe[1]);
-
- send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
- "Error sending ENOMEM reply to local user");
- return len;
- }
-
- DEBUGLOG("(%p) Creating pipe, [%d, %d]\n", thisfd, comms_pipe[0], comms_pipe[1]);
-
- if (fcntl(comms_pipe[0], F_SETFD, 1))
- DEBUGLOG("setting CLOEXEC on pipe[0] failed: %s\n", strerror(errno));
- if (fcntl(comms_pipe[1], F_SETFD, 1))
- DEBUGLOG("setting CLOEXEC on pipe[1] failed: %s\n", strerror(errno));
-
- newfd->fd = comms_pipe[0];
- newfd->type = THREAD_PIPE;
- newfd->callback = local_pipe_callback;
- newfd->bits.pipe.client = thisfd;
-
- _add_client(newfd, thisfd);
-
- /* Store a cross link to the pipe */
- thisfd->bits.localsock.pipe_client = newfd;
- thisfd->bits.localsock.pipe = comms_pipe[1];
-
- /* Make sure the thread has a copy of it's own ID */
- newfd->bits.pipe.threadid = thisfd->bits.localsock.threadid;
-
- /* Run the pre routine */
- thisfd->bits.localsock.in_progress = TRUE;
- thisfd->bits.localsock.state = PRE_COMMAND;
- thisfd->bits.localsock.cleanup_needed = 1;
- DEBUGLOG("(%p) Creating pre&post thread for pipe fd %d\n", newfd, newfd->fd);
- status = pthread_create(&thisfd->bits.localsock.threadid,
- &stack_attr, pre_and_post_thread, thisfd);
- DEBUGLOG("(%p) Created pre&post thread, state = %d\n", newfd, status);
-
- return len;
-}
-
-/* Add a file descriptor from the cluster or comms interface to
- our list of FDs for select
-*/
-
-/* Called when the pre-command has completed successfully - we
- now execute the real command on all the requested nodes */
-static int distribute_command(struct local_client *thisfd)
-{
- struct clvm_header *inheader =
- (struct clvm_header *) thisfd->bits.localsock.cmd;
- int len = thisfd->bits.localsock.cmd_len;
-
- thisfd->xid = global_xid++;
- DEBUGLOG("(%p) distribute command: XID = %d, flags=0x%x (%s%s)\n",
- thisfd, thisfd->xid, inheader->flags,
- (inheader->flags & CLVMD_FLAG_LOCAL) ? "LOCAL" : "",
- (inheader->flags & CLVMD_FLAG_REMOTE) ? "REMOTE" : "");
-
- /* Forward it to other nodes in the cluster if needed */
- if (!(inheader->flags & CLVMD_FLAG_LOCAL)) {
- /* if node is empty then do it on the whole cluster */
- if (inheader->node[0] == '\0') {
- thisfd->bits.localsock.expected_replies =
- clops->get_num_nodes();
- thisfd->bits.localsock.num_replies = 0;
- thisfd->bits.localsock.sent_time = time(NULL);
- thisfd->bits.localsock.in_progress = TRUE;
- thisfd->bits.localsock.sent_out = TRUE;
-
- /*
- * Send to local node first, even if CLVMD_FLAG_REMOTE
- * is set so we still get a reply if this is the
- * only node.
- */
- add_to_lvmqueue(thisfd, inheader, len, NULL);
-
- DEBUGLOG("(%p) Sending message to all cluster nodes\n", thisfd);
- inheader->xid = thisfd->xid;
- send_message(inheader, len, NULL, -1,
- "Error forwarding message to cluster");
- } else {
- /* Do it on a single node */
- char csid[MAX_CSID_LEN];
-
- if (clops->csid_from_name(csid, inheader->node))
- /* This has already been checked so should not happen */
- return 0;
-
- /* OK, found a node... */
- thisfd->bits.localsock.in_progress = TRUE;
- thisfd->bits.localsock.expected_replies = 1;
- thisfd->bits.localsock.num_replies = 0;
-
- /* Are we the requested node ?? */
- if (memcmp(csid, our_csid, max_csid_len) == 0) {
- DEBUGLOG("(%p) Doing command on local node only\n", thisfd);
- add_to_lvmqueue(thisfd, inheader, len, NULL);
- } else {
- DEBUGLOG("(%p) Sending message to single node: %s\n",
- thisfd, inheader->node);
- inheader->xid = thisfd->xid;
- send_message(inheader, len, csid, -1,
- "Error forwarding message to cluster node");
- }
- }
- } else {
- /* Local explicitly requested, ignore nodes */
- thisfd->bits.localsock.in_progress = TRUE;
- thisfd->bits.localsock.expected_replies = 1;
- thisfd->bits.localsock.num_replies = 0;
- DEBUGLOG("(%p) Doing command explicitly on local node only\n", thisfd);
- add_to_lvmqueue(thisfd, inheader, len, NULL);
- }
-
- return 0;
-}
-
-/* Process a command from a remote node and return the result */
-static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
- const char *csid)
-{
- char *replyargs;
- char nodename[max_cluster_member_name_len];
- int replylen = 0;
- int buflen = max_cluster_message - sizeof(struct clvm_header) - 1;
- int status;
-
- /* Get the node name as we /may/ need it later */
- clops->name_from_csid(csid, nodename);
-
- DEBUGLOG("process_remote_command %s for clientid 0x%x XID %d on node %s\n",
- decode_cmd(msg->cmd), msg->clientid, msg->xid, nodename);
-
- /* Check for GOAWAY and sulk */
- if (msg->cmd == CLVMD_CMD_GOAWAY) {
- DEBUGLOG("Told to go away by %s\n", nodename);
- log_error("Told to go away by %s.", nodename);
- exit(99);
- }
-
- /* Version check is internal - don't bother exposing it in clvmd-command.c */
- if (msg->cmd == CLVMD_CMD_VERSION) {
- int version_nums[3];
- char node[256];
-
- memcpy(version_nums, msg->args, sizeof(version_nums));
-
- clops->name_from_csid(csid, node);
- DEBUGLOG("Remote node %s is version %d.%d.%d\n",
- node, ntohl(version_nums[0]),
- ntohl(version_nums[1]), ntohl(version_nums[2]));
-
- if (ntohl(version_nums[0]) != CLVMD_MAJOR_VERSION) {
- struct clvm_header byebyemsg = {
- .cmd = CLVMD_CMD_GOAWAY
- };
-
- DEBUGLOG("Telling node %s to go away because of incompatible version number\n",
- node);
- log_notice("Telling node %s to go away because of incompatible version number %d.%d.%d\n",
- node, ntohl(version_nums[0]),
- ntohl(version_nums[1]), ntohl(version_nums[2]));
-
- clops->cluster_send_message(&byebyemsg, sizeof(byebyemsg), our_csid,
- "Error Sending GOAWAY message");
- } else
- clops->add_up_node(csid);
-
- return;
- }
-
- /* Allocate a default reply buffer */
- if ((replyargs = dm_malloc(max_cluster_message - sizeof(struct clvm_header))))
- /* Run the command */
- /* FIXME: usage of init_test() is unprotected */
- status = do_command(NULL, msg, msglen, &replyargs,
- buflen, &replylen);
- else
- status = ENOMEM;
-
- /* If it wasn't a reply, then reply */
- if (msg->cmd != CLVMD_CMD_REPLY) {
- char *aggreply;
-
- aggreply = dm_realloc(replyargs, replylen + sizeof(struct clvm_header));
- if (aggreply) {
- struct clvm_header *agghead =
- (struct clvm_header *) aggreply;
-
- replyargs = aggreply;
- /* Move it up so there's room for a header in front of the data */
- memmove(aggreply + offsetof(struct clvm_header, args),
- replyargs, replylen);
-
- agghead->xid = msg->xid;
- agghead->cmd = CLVMD_CMD_REPLY;
- agghead->status = status;
- agghead->flags = 0;
- agghead->clientid = msg->clientid;
- agghead->arglen = replylen;
- agghead->node[0] = '\0';
- send_message(aggreply, sizeof(struct clvm_header) + replylen,
- csid, fd, "Error sending command reply");
- } else {
- /* Return a failure response */
- struct clvm_header reply = {
- .cmd = CLVMD_CMD_REPLY,
- .status = ENOMEM,
- .clientid = msg->clientid
- };
- DEBUGLOG("Error attempting to realloc return buffer\n");
- send_message(&reply, sizeof(reply), csid, fd,
- "Error sending ENOMEM command reply");
- }
- }
-
- dm_free(replyargs);
-}
-
-/* Add a reply to a command to the list of replies for this client.
- If we have got a full set then send them to the waiting client down the local
- socket */
-static void add_reply_to_list(struct local_client *client, int status,
- const char *csid, const char *buf, int len)
-{
- struct node_reply *reply;
-
- /* Add it to the list of replies */
- if (!(reply = dm_zalloc(sizeof(*reply)))) {
- /* It's all gone horribly wrong... */
- send_local_reply(client, ENOMEM, client->fd);
- return;
- }
-
- reply->status = status;
- clops->name_from_csid(csid, reply->node);
- DEBUGLOG("(%p) Reply from node %s: %d bytes\n", client, reply->node, len);
-
- if (len > 0) {
- if (!(reply->replymsg = dm_malloc(len)))
- reply->status = ENOMEM;
- else
- memcpy(reply->replymsg, buf, len);
- } else
- reply->replymsg = NULL;
-
- pthread_mutex_lock(&client->bits.localsock.mutex);
-
- if (client->bits.localsock.finished) {
- dm_free(reply->replymsg);
- dm_free(reply);
- } else {
- /* Hook it onto the reply chain */
- reply->next = client->bits.localsock.replies;
- client->bits.localsock.replies = reply;
-
- /* If we have the whole lot then do the post-process */
- /* Post-process the command */
- if (++client->bits.localsock.num_replies ==
- client->bits.localsock.expected_replies) {
- client->bits.localsock.state = POST_COMMAND;
- pthread_cond_signal(&client->bits.localsock.cond);
- }
- DEBUGLOG("(%p) Got %d replies, expecting: %d\n",
- client, client->bits.localsock.num_replies,
- client->bits.localsock.expected_replies);
- }
- pthread_mutex_unlock(&client->bits.localsock.mutex);
-}
-
-/* This is the thread that runs the PRE and post commands for a particular connection */
-static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
-{
- struct local_client *client = (struct local_client *) arg;
- int status;
- int write_status;
- sigset_t ss;
- int pipe_fd = client->bits.localsock.pipe;
-
- DEBUGLOG("(%p) Pre&post thread pipe fd %d\n", client, pipe_fd);
- pthread_mutex_lock(&client->bits.localsock.mutex);
-
- /* Ignore SIGUSR1 (handled by master process) but enable
- SIGUSR2 (kills subthreads) */
- sigemptyset(&ss);
- sigaddset(&ss, SIGUSR1);
- pthread_sigmask(SIG_BLOCK, &ss, NULL);
-
- sigdelset(&ss, SIGUSR1);
- sigaddset(&ss, SIGUSR2);
- pthread_sigmask(SIG_UNBLOCK, &ss, NULL);
-
- /* Loop around doing PRE and POST functions until the client goes away */
- while (!client->bits.localsock.finished) {
- /* Execute the code */
- /* FIXME: usage of init_test() is unprotected as in do_command() */
- if ((status = do_pre_command(client)))
- client->bits.localsock.all_success = 0;
-
- DEBUGLOG("(%p) Pre&post thread writes status %d down to pipe fd %d\n",
- client, status, pipe_fd);
-
- /* Tell the parent process we have finished this bit */
- while ((write_status = write(pipe_fd, &status, sizeof(int))) != sizeof(int))
- if (write_status >=0 || (errno != EINTR && errno != EAGAIN)) {
- log_error("Error sending to pipe: %m");
- break;
- }
-
- if (status) {
- client->bits.localsock.state = POST_COMMAND;
- goto next_pre;
- }
-
- /* We may need to wait for the condition variable before running the post command */
- if (client->bits.localsock.state != POST_COMMAND &&
- !client->bits.localsock.finished) {
- DEBUGLOG("(%p) Pre&post thread waiting to do post command, state = %d\n",
- client, client->bits.localsock.state);
- pthread_cond_wait(&client->bits.localsock.cond,
- &client->bits.localsock.mutex);
- }
-
- DEBUGLOG("(%p) Pre&post thread got post command condition...\n", client);
-
- /* POST function must always run, even if the client aborts */
- status = 0;
- do_post_command(client);
-
- while ((write_status = write(pipe_fd, &status, sizeof(int))) != sizeof(int))
- if (write_status >=0 || (errno != EINTR && errno != EAGAIN)) {
- log_error("Error sending to pipe: %m");
- break;
- }
-next_pre:
- if (client->bits.localsock.state != PRE_COMMAND &&
- !client->bits.localsock.finished) {
- DEBUGLOG("(%p) Pre&post thread waiting for next pre command\n", client);
- pthread_cond_wait(&client->bits.localsock.cond,
- &client->bits.localsock.mutex);
- }
-
- DEBUGLOG("(%p) Pre&post thread got pre command condition...\n", client);
- }
- pthread_mutex_unlock(&client->bits.localsock.mutex);
- DEBUGLOG("(%p) Pre&post thread finished\n", client);
-
- pthread_exit(NULL);
-}
-
-/* Process a command on the local node and store the result */
-static int process_local_command(struct clvm_header *msg, int msglen,
- struct local_client *client,
- unsigned short xid)
-{
- char *replybuf;
- int buflen = max_cluster_message - sizeof(struct clvm_header) - 1;
- int replylen = 0;
- int status;
-
- if (!(replybuf = dm_malloc(max_cluster_message)))
- return -1;
-
- DEBUGLOG("(%p) process_local_command: %s msg=%p, msglen =%d\n",
- client, decode_cmd(msg->cmd), msg, msglen);
-
- /* If remote flag is set, just set a successful status code. */
- if (msg->flags & CLVMD_FLAG_REMOTE)
- status = 0;
- else
- status = do_command(client, msg, msglen, &replybuf, buflen, &replylen);
-
- if (status)
- client->bits.localsock.all_success = 0;
-
- /* If we took too long then discard the reply */
- if (xid == client->xid)
- add_reply_to_list(client, status, our_csid, replybuf, replylen);
- else
- DEBUGLOG("(%p) Local command took too long, discarding xid %d, current is %d\n",
- client, xid, client->xid);
-
- dm_free(replybuf);
-
- return status;
-}
-
-static int process_reply(const struct clvm_header *msg, int msglen, const char *csid)
-{
- struct local_client *client;
-
- if (!(client = find_client(msg->clientid))) {
- DEBUGLOG("Got message for unknown client 0x%x\n",
- msg->clientid);
- log_error("Got message for unknown client 0x%x.",
- msg->clientid);
- return -1;
- }
-
- if (msg->status)
- client->bits.localsock.all_success = 0;
-
- /* Gather replies together for this client id */
- if (msg->xid == client->xid)
- add_reply_to_list(client, msg->status, csid, msg->args,
- msg->arglen);
- else
- DEBUGLOG("Discarding reply with old XID %d, current = %d\n",
- msg->xid, client->xid);
-
- return 0;
-}
-
-/* Send an aggregated reply back to the client */
-static void send_local_reply(struct local_client *client, int status, int fd)
-{
- struct clvm_header *clientreply;
- struct node_reply *thisreply = client->bits.localsock.replies;
- char *replybuf;
- char *ptr;
- int message_len = 0;
-
- DEBUGLOG("(%p) Send local reply\n", client);
-
- /* Work out the total size of the reply */
- while (thisreply) {
- if (thisreply->replymsg)
- message_len += strlen(thisreply->replymsg) + 1;
- else
- message_len++;
-
- message_len += strlen(thisreply->node) + 1 + sizeof(int);
-
- thisreply = thisreply->next;
- }
-
- /* Add in the size of our header */
- message_len = message_len + sizeof(struct clvm_header);
- if (!(replybuf = dm_malloc(message_len))) {
- DEBUGLOG("(%p) Memory allocation fails\n", client);
- return;
- }
-
- clientreply = (struct clvm_header *) replybuf;
- clientreply->status = status;
- clientreply->cmd = CLVMD_CMD_REPLY;
- clientreply->node[0] = '\0';
- clientreply->xid = 0;
- clientreply->clientid = 0;
- clientreply->flags = 0;
-
- ptr = clientreply->args;
-
- /* Add in all the replies, and free them as we go */
- thisreply = client->bits.localsock.replies;
- while (thisreply) {
- struct node_reply *tempreply = thisreply;
-
- strcpy(ptr, thisreply->node);
- ptr += strlen(thisreply->node) + 1;
-
- if (thisreply->status)
- clientreply->flags |= CLVMD_FLAG_NODEERRS;
-
- memcpy(ptr, &thisreply->status, sizeof(int));
- ptr += sizeof(int);
-
- if (thisreply->replymsg) {
- strcpy(ptr, thisreply->replymsg);
- ptr += strlen(thisreply->replymsg) + 1;
- } else {
- ptr[0] = '\0';
- ptr++;
- }
- thisreply = thisreply->next;
-
- dm_free(tempreply->replymsg);
- dm_free(tempreply);
- }
-
- /* Terminate with an empty node name */
- *ptr = '\0';
-
- clientreply->arglen = ptr - clientreply->args;
-
- /* And send it */
- send_message(replybuf, message_len, our_csid, fd,
- "Error sending REPLY to client");
- dm_free(replybuf);
-
- /* Reset comms variables */
- client->bits.localsock.replies = NULL;
- client->bits.localsock.expected_replies = 0;
- client->bits.localsock.in_progress = FALSE;
- client->bits.localsock.sent_out = FALSE;
-}
-
-/* Just free a reply chain baceuse it wasn't used. */
-static void free_reply(struct local_client *client)
-{
- /* Add in all the replies, and free them as we go */
- struct node_reply *thisreply = client->bits.localsock.replies;
- while (thisreply) {
- struct node_reply *tempreply = thisreply;
-
- thisreply = thisreply->next;
-
- dm_free(tempreply->replymsg);
- dm_free(tempreply);
- }
- client->bits.localsock.replies = NULL;
-}
-
-/* Send our version number to the cluster */
-static void send_version_message(void)
-{
- char message[sizeof(struct clvm_header) + sizeof(int) * 3];
- struct clvm_header *msg = (struct clvm_header *) message;
- int version_nums[3] = {
- htonl(CLVMD_MAJOR_VERSION),
- htonl(CLVMD_MINOR_VERSION),
- htonl(CLVMD_PATCH_VERSION)
- };
-
- msg->cmd = CLVMD_CMD_VERSION;
- msg->status = 0;
- msg->flags = 0;
- msg->clientid = 0;
- msg->arglen = sizeof(version_nums);
-
- memcpy(&msg->args, version_nums, sizeof(version_nums));
-
- hton_clvm(msg);
-
- clops->cluster_send_message(message, sizeof(message), NULL,
- "Error Sending version number");
-}
-
-/* Send a message to either a local client or another server */
-static int send_message(void *buf, int msglen, const char *csid, int fd,
- const char *errtext)
-{
- int len = 0;
- int ptr;
- struct timespec delay;
- struct timespec remtime;
- int retry_cnt = 0;
-
- /* Send remote messages down the cluster socket */
- if (!csid || !ISLOCAL_CSID(csid)) {
- hton_clvm((struct clvm_header *) buf);
- return clops->cluster_send_message(buf, msglen, csid, errtext);
- }
-
- if (fd < 0)
- return 0;
-
- /* Make sure it all goes */
- for (ptr = 0; ptr < msglen;) {
- if ((len = write(fd, (char*)buf + ptr, msglen - ptr)) <= 0) {
- if (errno == EINTR)
- continue;
- if ((errno == EAGAIN || errno == EIO || errno == ENOSPC) &&
- ++retry_cnt < MAX_RETRIES) {
- delay.tv_sec = 0;
- delay.tv_nsec = 100000;
- remtime.tv_sec = 0;
- remtime.tv_nsec = 0;
- (void) nanosleep (&delay, &remtime);
- continue;
- }
- DEBUGLOG("%s", errtext);
- log_error("%s", errtext);
- break;
- }
- ptr += len;
- }
-
- return len;
-}
-
-static int process_work_item(struct lvm_thread_cmd *cmd)
-{
- /* If msg is NULL then this is a cleanup request */
- if (cmd->msg == NULL) {
- DEBUGLOG("(%p) process_work_item: free\n", cmd->client);
- cmd_client_cleanup(cmd->client);
- pthread_mutex_destroy(&cmd->client->bits.localsock.mutex);
- pthread_cond_destroy(&cmd->client->bits.localsock.cond);
- dm_free(cmd->client);
- return 0;
- }
-
- if (!cmd->remote) {
- DEBUGLOG("(%p) process_work_item: local\n", cmd->client);
- process_local_command(cmd->msg, cmd->msglen, cmd->client,
- cmd->xid);
- } else {
- DEBUGLOG("(%p) process_work_item: remote\n", cmd->client);
- process_remote_command(cmd->msg, cmd->msglen, cmd->client->fd,
- cmd->csid);
- }
-
- return 0;
-}
-
-/*
- * Routine that runs in the "LVM thread".
- */
-static void *lvm_thread_fn(void *arg)
-{
- sigset_t ss;
- struct lvm_startup_params *lvm_params = arg;
- struct lvm_thread_cmd *cmd;
-
- DEBUGLOG("LVM thread function started\n");
-
- /* Ignore SIGUSR1 & 2 */
- sigemptyset(&ss);
- sigaddset(&ss, SIGUSR1);
- sigaddset(&ss, SIGUSR2);
- pthread_sigmask(SIG_BLOCK, &ss, NULL);
-
- /* Initialise the interface to liblvm */
- init_clvm(lvm_params->excl_uuid);
-
- /* Allow others to get moving */
- pthread_barrier_wait(&lvm_start_barrier);
- DEBUGLOG("LVM thread ready for work.\n");
-
- /* Now wait for some actual work */
- pthread_mutex_lock(&lvm_thread_mutex);
-
- for (;;) {
- while (!dm_list_empty(&lvm_cmd_head)) {
- cmd = dm_list_item(dm_list_first(&lvm_cmd_head),
- struct lvm_thread_cmd);
- dm_list_del(&cmd->list);
- pthread_mutex_unlock(&lvm_thread_mutex);
-
- process_work_item(cmd);
- dm_free(cmd->msg);
- dm_free(cmd);
-
- pthread_mutex_lock(&lvm_thread_mutex);
- }
-
- if (lvm_thread_exit)
- break;
-
- DEBUGLOG("LVM thread waiting for work\n");
- pthread_cond_wait(&lvm_thread_cond, &lvm_thread_mutex);
- }
-
- pthread_mutex_unlock(&lvm_thread_mutex);
- DEBUGLOG("LVM thread exits\n");
-
- destroy_lvm();
-
- pthread_exit(NULL);
-}
-
-/* Pass down some work to the LVM thread */
-static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
- int msglen, const char *csid)
-{
- struct lvm_thread_cmd *cmd;
-
- if (!(cmd = dm_malloc(sizeof(*cmd))))
- return ENOMEM;
-
- if (msglen) {
- if (!(cmd->msg = dm_malloc(msglen))) {
- log_error("Unable to allocate buffer space.");
- dm_free(cmd);
- return -1;
- }
- memcpy(cmd->msg, msg, msglen);
- }
- else
- cmd->msg = NULL;
-
- cmd->client = client;
- cmd->msglen = msglen;
- cmd->xid = client->xid;
-
- if (csid) {
- memcpy(cmd->csid, csid, max_csid_len);
- cmd->remote = 1;
- } else
- cmd->remote = 0;
-
- DEBUGLOG("(%p) add_to_lvmqueue: cmd=%p, msg=%p, len=%d, csid=%p, xid=%d\n",
- client, cmd, msg, msglen, csid, cmd->xid);
- pthread_mutex_lock(&lvm_thread_mutex);
- if (lvm_thread_exit) {
- pthread_mutex_unlock(&lvm_thread_mutex);
- dm_free(cmd->msg);
- dm_free(cmd);
- return -1; /* We are about to exit */
- }
- dm_list_add(&lvm_cmd_head, &cmd->list);
- pthread_cond_signal(&lvm_thread_cond);
- pthread_mutex_unlock(&lvm_thread_mutex);
-
- return 0;
-}
-
-/* Return 0 if we can talk to an existing clvmd */
-/*
- * FIXME:
- *
- * This function returns only -1 or 0, but there are
- * different levels of errors, some of them should stop
- * further execution of clvmd thus another state is needed
- * and some error message need to be only informational.
- */
-static int check_local_clvmd(void)
-{
- int local_socket;
- int ret = 0;
- struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
-
- if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) {
- log_error("%s: clvmd socket name too long.", CLVMD_SOCKNAME);
- return -1;
- }
-
- /* Open local socket */
- if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
- log_sys_error("socket", "local socket");
- return -1;
- }
-
- if (connect(local_socket,(struct sockaddr *) &sockaddr,
- sizeof(sockaddr))) {
- /* connection failure is expected state */
- if (errno == ENOENT)
- log_sys_debug("connect", "local socket");
- else
- log_sys_error("connect", "local socket");
- ret = -1;
- }
-
- if (close(local_socket))
- log_sys_error("close", "local socket");
-
- return ret;
-}
-
-static void close_local_sock(int local_socket)
-{
- if (local_socket != -1 && close(local_socket))
- log_sys_error("close", CLVMD_SOCKNAME);
-
- if (CLVMD_SOCKNAME[0] != '\0' && unlink(CLVMD_SOCKNAME))
- stack;
-}
-
-/* Open the local socket, that's the one we talk to libclvm down */
-static int open_local_sock(void)
-{
- mode_t old_mask;
- int local_socket = -1;
- struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
-
- if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) {
- log_error("%s: clvmd socket name too long.", CLVMD_SOCKNAME);
- return -1;
- }
-
- close_local_sock(local_socket);
-
- (void) dm_prepare_selinux_context(CLVMD_SOCKNAME, S_IFSOCK);
- old_mask = umask(0077);
-
- /* Open local socket */
- if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
- log_error("Can't create local socket: %m");
- goto error;
- }
-
- /* Set Close-on-exec & non-blocking */
- if (fcntl(local_socket, F_SETFD, 1))
- DEBUGLOG("setting CLOEXEC on local_socket failed: %s\n", strerror(errno));
- if (fcntl(local_socket, F_SETFL, fcntl(local_socket, F_GETFL, 0) | O_NONBLOCK))
- DEBUGLOG("setting O_NONBLOCK on local_socket failed: %s\n", strerror(errno));
-
-
- if (bind(local_socket, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
- log_error("can't bind local socket: %m");
- goto error;
- }
- if (listen(local_socket, 1) != 0) {
- log_error("listen local: %m");
- goto error;
- }
-
- umask(old_mask);
- (void) dm_prepare_selinux_context(NULL, 0);
- return local_socket;
-error:
- close_local_sock(local_socket);
- umask(old_mask);
- (void) dm_prepare_selinux_context(NULL, 0);
- return -1;
-}
-
-void process_message(struct local_client *client, char *buf, int len,
- const char *csid)
-{
- char nodename[max_cluster_member_name_len];
- struct clvm_header *inheader = (struct clvm_header *) buf;
- ntoh_clvm(inheader); /* Byteswap fields */
-
- if (verify_message(buf, len) < 0) {
- clops->name_from_csid(csid, nodename);
- log_error("process_message from %s len %d bad verify.", nodename, len);
- dump_message(buf, len);
- return;
- }
-
- if (inheader->cmd == CLVMD_CMD_REPLY)
- process_reply(inheader, len, csid);
- else
- add_to_lvmqueue(client, inheader, len, csid);
-}
-
-
-static void check_all_callback(struct local_client *client, const char *csid,
- int node_up)
-{
- if (!node_up)
- add_reply_to_list(client, EHOSTDOWN, csid, "CLVMD not running", 18);
-}
-
-/* Check to see if all CLVMDs are running (ie one on
- every node in the cluster).
- If not, returns -1 and prints out a list of errant nodes */
-static int check_all_clvmds_running(struct local_client *client)
-{
- DEBUGLOG("(%p) check_all_clvmds_running\n", client);
-
- return clops->cluster_do_node_callback(client, check_all_callback);
-}
-
-/* Return a local_client struct given a client ID.
- client IDs are in network byte order */
-static struct local_client *find_client(int clientid)
-{
- struct local_client *thisfd;
-
- for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next)
- if (thisfd->fd == (int)ntohl(clientid))
- return thisfd;
-
- return NULL;
-}
-
-/* Byte-swapping routines for the header so we
- work in a heterogeneous environment */
-static void hton_clvm(struct clvm_header *hdr)
-{
- hdr->status = htonl(hdr->status);
- hdr->arglen = htonl(hdr->arglen);
- hdr->xid = htons(hdr->xid);
- /* Don't swap clientid as it's only a token as far as
- remote nodes are concerned */
-}
-
-static void ntoh_clvm(struct clvm_header *hdr)
-{
- hdr->status = ntohl(hdr->status);
- hdr->arglen = ntohl(hdr->arglen);
- hdr->xid = ntohs(hdr->xid);
-}
-
-/* Handler for SIGUSR2 - sent to kill subthreads */
-static void sigusr2_handler(int sig)
-{
- DEBUGLOG("SIGUSR2 received\n");
-}
-
-static void sigterm_handler(int sig)
-{
- quit = 1;
-}
-
-static void sighup_handler(int sig)
-{
- reread_config = 1;
-}
-
-int sync_lock(const char *resource, int mode, int flags, int *lockid)
-{
- return clops->sync_lock(resource, mode, flags, lockid);
-}
-
-int sync_unlock(const char *resource, int lockid)
-{
- return clops->sync_unlock(resource, lockid);
-}
-
-static if_type_t parse_cluster_interface(char *ifname)
-{
- if_type_t iface = IF_AUTO;
-
- if (!strcmp(ifname, "auto"))
- iface = IF_AUTO;
- else if (!strcmp(ifname, "cman"))
- iface = IF_CMAN;
- else if (!strcmp(ifname, "openais"))
- iface = IF_OPENAIS;
- else if (!strcmp(ifname, "corosync"))
- iface = IF_COROSYNC;
- else if (!strcmp(ifname, "singlenode"))
- iface = IF_SINGLENODE;
-
- return iface;
-}
-
-/*
- * Try and find a cluster system in corosync's objdb, if it is running. This is
- * only called if the command-line option is not present, and if it fails
- * we still try the interfaces in order.
- */
-static if_type_t get_cluster_type(void)
-{
-#ifdef HAVE_COROSYNC_CONFDB_H
- confdb_handle_t handle;
- if_type_t type = IF_AUTO;
- int result;
- char buf[255];
- size_t namelen = sizeof(buf);
- hdb_handle_t cluster_handle;
- hdb_handle_t clvmd_handle;
- confdb_callbacks_t callbacks = { 0 };
-
- result = confdb_initialize (&handle, &callbacks);
- if (result != CS_OK)
- return type;
-
- result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
- if (result != CS_OK)
- goto out;
-
- result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle);
- if (result != CS_OK)
- goto out;
-
- result = confdb_object_find_start(handle, cluster_handle);
- if (result != CS_OK)
- goto out;
-
- result = confdb_object_find(handle, cluster_handle, (void *)"clvmd", strlen("clvmd"), &clvmd_handle);
- if (result != CS_OK)
- goto out;
-
- result = confdb_key_get(handle, clvmd_handle, (void *)"interface", strlen("interface"), buf, &namelen);
- if (result != CS_OK)
- goto out;
-
- if (namelen >= sizeof(buf))
- namelen = sizeof(buf) - 1;
-
- buf[namelen] = '\0';
- type = parse_cluster_interface(buf);
- DEBUGLOG("got interface type '%s' from confdb\n", buf);
-out:
- confdb_finalize(handle);
- return type;
-#else
- return IF_AUTO;
-#endif
-}
diff --git a/daemons/clvmd/clvmd.h b/daemons/clvmd/clvmd.h
deleted file mode 100644
index edaee8872..000000000
--- a/daemons/clvmd/clvmd.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004 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 General Public License v.2.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _CLVMD_H
-#define _CLVMD_H
-
-#define CLVMD_MAJOR_VERSION 0
-#define CLVMD_MINOR_VERSION 2
-#define CLVMD_PATCH_VERSION 1
-
-/* Default time (in seconds) we will wait for all remote commands to execute
- before declaring them dead */
-#define DEFAULT_CMD_TIMEOUT 60
-
-/* One of these for each reply we get from command execution on a node */
-struct node_reply {
- char node[MAX_CLUSTER_MEMBER_NAME_LEN];
- char *replymsg;
- int status;
- struct node_reply *next;
-};
-
-typedef enum {DEBUG_OFF, DEBUG_STDERR, DEBUG_SYSLOG} debug_t;
-
-/*
- * These exist for the use of local sockets only when we are
- * collecting responses from all cluster nodes
- */
-struct localsock_bits {
- struct node_reply *replies;
- int num_replies;
- int expected_replies;
- time_t sent_time; /* So we can check for timeouts */
- int in_progress; /* Only execute one cmd at a time per client */
- int sent_out; /* Flag to indicate that a command was sent
- to remote nodes */
- void *private; /* Private area for command processor use */
- void *cmd; /* Whole command as passed down local socket */
- int cmd_len; /* Length of above */
- int pipe; /* Pipe to send PRE completion status down */
- int finished; /* Flag to tell subthread to exit */
- int all_success; /* Set to 0 if any node (or the pre_command)
- failed */
- int cleanup_needed; /* helper for cleanup_zombie */
- struct local_client *pipe_client;
- pthread_t threadid;
- enum { PRE_COMMAND, POST_COMMAND } state;
- pthread_mutex_t mutex; /* Main thread and worker synchronisation */
- pthread_cond_t cond;
-};
-
-/* Entries for PIPE clients */
-struct pipe_bits {
- struct local_client *client; /* Actual (localsock) client */
- pthread_t threadid; /* Our own copy of the thread id */
-};
-
-/* Entries for Network socket clients */
-struct netsock_bits {
- void *private;
- int flags;
-};
-
-typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
- const char *csid,
- struct local_client ** new_client);
-
-/* One of these for each fd we are listening on */
-struct local_client {
- int fd;
- enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS,
- LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type;
- struct local_client *next;
- unsigned short xid;
- fd_callback_t callback;
- uint8_t removeme;
-
- union {
- struct localsock_bits localsock;
- struct pipe_bits pipe;
- struct netsock_bits net;
- } bits;
-};
-
-#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args)
-
-#ifndef max
-#define max(a,b) ((a)>(b)?(a):(b))
-#endif
-
-/* The real command processor is in clvmd-command.c */
-extern int do_command(struct local_client *client, struct clvm_header *msg,
- int msglen, char **buf, int buflen, int *retlen);
-
-/* Pre and post command routines are called only on the local node */
-extern int do_pre_command(struct local_client *client);
-extern int do_post_command(struct local_client *client);
-extern void cmd_client_cleanup(struct local_client *client);
-extern int add_client(struct local_client *new_client);
-
-extern void clvmd_cluster_init_completed(void);
-extern void process_message(struct local_client *client, char *buf,
- int len, const char *csid);
-extern void debuglog(const char *fmt, ... )
- __attribute__ ((format(printf, 1, 2)));
-
-void clvmd_set_debug(debug_t new_de);
-debug_t clvmd_get_debug(void);
-int clvmd_get_foreground(void);
-
-int sync_lock(const char *resource, int mode, int flags, int *lockid);
-int sync_unlock(const char *resource, int lockid);
-
-#endif
diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c
deleted file mode 100644
index ed829594a..000000000
--- a/daemons/clvmd/lvm-functions.c
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2012 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 General Public License v.2.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "clvmd-common.h"
-
-#include <pthread.h>
-
-#include "daemons/clvmd/clvm.h"
-#include "clvmd-comms.h"
-#include "clvmd.h"
-#include "lvm-functions.h"
-
-/* LVM2 headers */
-#include "lib/commands/toolcontext.h"
-#include "lib/cache/lvmcache.h"
-#include "lib/misc/lvm-globals.h"
-#include "lib/activate/activate.h"
-#include "lib/format_text/archiver.h"
-#include "lib/mm/memlock.h"
-
-#include <syslog.h>
-
-static struct cmd_context *cmd = NULL;
-static struct dm_hash_table *lv_hash = NULL;
-static pthread_mutex_t lv_hash_lock;
-static pthread_mutex_t lvm_lock;
-static char last_error[1024];
-
-struct lv_info {
- int lock_id;
- int lock_mode;
-};
-
-static const char *decode_full_locking_cmd(uint32_t cmdl)
-{
- static char buf[128];
- const char *type;
- const char *scope;
- const char *command;
-
- switch (cmdl & LCK_TYPE_MASK) {
- case LCK_NULL:
- type = "NULL";
- break;
- case LCK_READ:
- type = "READ";
- break;
- case LCK_PREAD:
- type = "PREAD";
- break;
- case LCK_WRITE:
- type = "WRITE";
- break;
- case LCK_EXCL:
- type = "EXCL";
- break;
- case LCK_UNLOCK:
- type = "UNLOCK";
- break;
- default:
- type = "unknown";
- break;
- }
-
- switch (cmdl & LCK_SCOPE_MASK) {
- case LCK_VG:
- scope = "VG";
- command = "LCK_VG";
- break;
- case LCK_LV:
- scope = "LV";
- switch (cmdl & LCK_MASK) {
- case LCK_LV_EXCLUSIVE & LCK_MASK:
- command = "LCK_LV_EXCLUSIVE";
- break;
- case LCK_LV_SUSPEND & LCK_MASK:
- command = "LCK_LV_SUSPEND";
- break;
- case LCK_LV_RESUME & LCK_MASK:
- command = "LCK_LV_RESUME";
- break;
- case LCK_LV_ACTIVATE & LCK_MASK:
- command = "LCK_LV_ACTIVATE";
- break;
- case LCK_LV_DEACTIVATE & LCK_MASK:
- command = "LCK_LV_DEACTIVATE";
- break;
- default:
- command = "unknown";
- break;
- }
- break;
- default:
- scope = "unknown";
- command = "unknown";
- break;
- }
-
- sprintf(buf, "0x%x %s (%s|%s%s%s%s%s)", cmdl, command, type, scope,
- cmdl & LCK_NONBLOCK ? "|NONBLOCK" : "",
- cmdl & LCK_HOLD ? "|HOLD" : "",
- cmdl & LCK_CLUSTER_VG ? "|CLUSTER_VG" : "",
- cmdl & LCK_CACHE ? "|CACHE" : "");
-
- return buf;
-}
-
-/*
- * Only processes 8 bits: excludes LCK_CACHE.
- */
-static const char *decode_locking_cmd(unsigned char cmdl)
-{
- return decode_full_locking_cmd((uint32_t) cmdl);
-}
-
-static const char *decode_flags(unsigned char flags)
-{
- static char buf[128];
- int len;
-
- len = sprintf(buf, "0x%x ( %s%s%s%s%s%s%s%s)", flags,
- flags & LCK_PARTIAL_MODE ? "PARTIAL_MODE|" : "",
- flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC|" : "",
- flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "",
- flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "",
- flags & LCK_TEST_MODE ? "TEST|" : "",
- flags & LCK_CONVERT_MODE ? "CONVERT|" : "",
- flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "",
- flags & LCK_REVERT_MODE ? "REVERT|" : "");
-
- if (len > 1)
- buf[len - 2] = ' ';
- else
- buf[0] = '\0';
-
- return buf;
-}
-
-char *get_last_lvm_error(void)
-{
- return last_error;
-}
-
-/*
- * Hash lock info helpers
- */
-static struct lv_info *lookup_info(const char *resource)
-{
- struct lv_info *lvi;
-
- pthread_mutex_lock(&lv_hash_lock);
- lvi = dm_hash_lookup(lv_hash, resource);
- pthread_mutex_unlock(&lv_hash_lock);
-
- return lvi;
-}
-
-static int insert_info(const char *resource, struct lv_info *lvi)
-{
- int ret;
-
- pthread_mutex_lock(&lv_hash_lock);
- ret = dm_hash_insert(lv_hash, resource, lvi);
- pthread_mutex_unlock(&lv_hash_lock);
-
- return ret;
-}
-
-static void remove_info(const char *resource)
-{
- int num_open;
-
- pthread_mutex_lock(&lv_hash_lock);
- dm_hash_remove(lv_hash, resource);
-
- /* When last lock is remove, validate there are not left opened devices */
- if (!dm_hash_get_first(lv_hash)) {
- if (critical_section())
- log_error(INTERNAL_ERROR "No volumes are locked however clvmd is in activation mode critical section.");
- if ((num_open = dev_cache_check_for_open_devices()))
- log_error(INTERNAL_ERROR "No volumes are locked however %d devices are still open.", num_open);
- }
-
- pthread_mutex_unlock(&lv_hash_lock);
-}
-
-/*
- * Return the mode a lock is currently held at (or -1 if not held)
- */
-static int get_current_lock(char *resource)
-{
- struct lv_info *lvi;
-
- if ((lvi = lookup_info(resource)))
- return lvi->lock_mode;
-
- return -1;
-}
-
-
-void init_lvhash(void)
-{
- /* Create hash table for keeping LV locks & status */
- lv_hash = dm_hash_create(1024);
- pthread_mutex_init(&lv_hash_lock, NULL);
- pthread_mutex_init(&lvm_lock, NULL);
-}
-
-/* Called at shutdown to tidy the lockspace */
-void destroy_lvhash(void)
-{
- struct dm_hash_node *v;
- struct lv_info *lvi;
- char *resource;
- int status;
-
- pthread_mutex_lock(&lv_hash_lock);
-
- dm_hash_iterate(v, lv_hash) {
- lvi = dm_hash_get_data(lv_hash, v);
- resource = dm_hash_get_key(lv_hash, v);
-
- if ((status = sync_unlock(resource, lvi->lock_id)))
- DEBUGLOG("unlock_all. unlock failed(%d): %s\n",
- status, strerror(errno));
- dm_free(lvi);
- }
-
- dm_hash_destroy(lv_hash);
- lv_hash = NULL;
-
- pthread_mutex_unlock(&lv_hash_lock);
-}
-
-/* Gets a real lock and keeps the info in the hash table */
-static int hold_lock(char *resource, int mode, int flags)
-{
- int status;
- int saved_errno;
- struct lv_info *lvi;
-
- /* Mask off invalid options */
- flags &= LCKF_NOQUEUE | LCKF_CONVERT;
-
- lvi = lookup_info(resource);
-
- if (lvi) {
- if (lvi->lock_mode == mode) {
- DEBUGLOG("hold_lock, lock mode %d already held\n",
- mode);
- return 0;
- }
- if ((lvi->lock_mode == LCK_EXCL) && (mode == LCK_WRITE)) {
- DEBUGLOG("hold_lock, lock already held LCK_EXCL, "
- "ignoring LCK_WRITE request\n");
- return 0;
- }
- }
-
- /* Only allow explicit conversions */
- if (lvi && !(flags & LCKF_CONVERT)) {
- errno = EBUSY;
- return -1;
- }
- if (lvi) {
- /* Already exists - convert it */
- status = sync_lock(resource, mode, flags, &lvi->lock_id);
- saved_errno = errno;
- if (!status)
- lvi->lock_mode = mode;
- else
- DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
- strerror(errno));
- errno = saved_errno;
- } else {
- if (!(lvi = dm_malloc(sizeof(struct lv_info)))) {
- errno = ENOMEM;
- return -1;
- }
-
- lvi->lock_mode = mode;
- lvi->lock_id = 0;
- status = sync_lock(resource, mode, flags & ~LCKF_CONVERT, &lvi->lock_id);
- saved_errno = errno;
- if (status) {
- dm_free(lvi);
- DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
- strerror(errno));
- } else
- if (!insert_info(resource, lvi)) {
- errno = ENOMEM;
- return -1;
- }
-
- errno = saved_errno;
- }
- return status;
-}
-
-/* Unlock and remove it from the hash table */
-static int hold_unlock(char *resource)
-{
- struct lv_info *lvi;
- int status;
- int saved_errno;
-
- if (!(lvi = lookup_info(resource))) {
- DEBUGLOG("hold_unlock, lock not already held\n");
- return 0;
- }
-
- status = sync_unlock(resource, lvi->lock_id);
- saved_errno = errno;
- if (!status) {
- remove_info(resource);
- dm_free(lvi);
- } else {
- DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
- strerror(errno));
- }
-
- errno = saved_errno;
- return status;
-}
-
-/* Watch the return codes here.
- liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno.
- libdlm API functions return 0 for success, -1 for failure and do set errno.
- These functions here return 0 for success or >0 for failure (where the retcode is errno)
-*/
-
-/* Activate LV exclusive or non-exclusive */
-static int do_activate_lv(char *resource, unsigned char command, unsigned char lock_flags, int mode)
-{
- int oldmode;
- int status;
- int activate_lv;
- int exclusive = 0;
- struct lvinfo lvi;
-
- /* Is it already open ? */
- oldmode = get_current_lock(resource);
- if (oldmode == mode && (command & LCK_CLUSTER_VG)) {
- DEBUGLOG("do_activate_lv, lock already held at %d\n", oldmode);
- return 0; /* Nothing to do */
- }
-
- /* Does the config file want us to activate this LV ? */
- if (!lv_activation_filter(cmd, resource, &activate_lv, NULL))
- return EIO;
-
- if (!activate_lv)
- return 0; /* Success, we did nothing! */
-
- /* Do we need to activate exclusively? */
- if ((activate_lv == 2) || (mode == LCK_EXCL)) {
- exclusive = 1;
- mode = LCK_EXCL;
- }
-
- /*
- * Try to get the lock if it's a clustered volume group.
- * Use lock conversion only if requested, to prevent implicit conversion
- * of exclusive lock to shared one during activation.
- */
- if (!test_mode() && command & LCK_CLUSTER_VG) {
- status = hold_lock(resource, mode, LCKF_NOQUEUE | ((lock_flags & LCK_CONVERT_MODE) ? LCKF_CONVERT:0));
- if (status) {
- /* Return an LVM-sensible error for this.
- * Forcing EIO makes the upper level return this text
- * rather than the strerror text for EAGAIN.
- */
- if (errno == EAGAIN) {
- sprintf(last_error, "Volume is busy on another node");
- errno = EIO;
- }
- return errno;
- }
- }
-
- /* If it's suspended then resume it */
- if (!lv_info_by_lvid(cmd, resource, 0, &lvi, 0, 0))
- goto error;
-
- if (lvi.suspended) {
- critical_section_inc(cmd, "resuming");
- if (!lv_resume(cmd, resource, 0, NULL)) {
- critical_section_dec(cmd, "resumed");
- goto error;
- }
- }
-
- /* Now activate it */
- if (!lv_activate(cmd, resource, exclusive, 0, 0, NULL))
- goto error;
-
- return 0;
-
-error:
- if (!test_mode() && (oldmode == -1 || oldmode != mode))
- (void)hold_unlock(resource);
- return EIO;
-}
-
-/* Resume the LV if it was active */
-static int do_resume_lv(char *resource, unsigned char command, unsigned char lock_flags)
-{
- int oldmode, origin_only, exclusive, revert;
-
- /* Is it open ? */
- oldmode = get_current_lock(resource);
- if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
- DEBUGLOG("do_resume_lv, lock not already held\n");
- return 0; /* We don't need to do anything */
- }
- origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
- exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
- revert = (lock_flags & LCK_REVERT_MODE) ? 1 : 0;
-
- if (!lv_resume_if_active(cmd, resource, origin_only, exclusive, revert, NULL))
- return EIO;
-
- return 0;
-}
-
-/* Suspend the device if active */
-static int do_suspend_lv(char *resource, unsigned char command, unsigned char lock_flags)
-{
- int oldmode;
- unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
- unsigned exclusive;
-
- /* Is it open ? */
- oldmode = get_current_lock(resource);
- if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
- DEBUGLOG("do_suspend_lv, lock not already held\n");
- return 0; /* Not active, so it's OK */
- }
-
- exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
-
- /* Always call lv_suspend to read commited and precommited data */
- if (!lv_suspend_if_active(cmd, resource, origin_only, exclusive, NULL, NULL))
- return EIO;
-
- return 0;
-}
-
-static int do_deactivate_lv(char *resource, unsigned char command, unsigned char lock_flags)
-{
- int oldmode;
- int status;
-
- /* Is it open ? */
- oldmode = get_current_lock(resource);
- if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
- DEBUGLOG("do_deactivate_lock, lock not already held\n");
- return 0; /* We don't need to do anything */
- }
-
- if (!lv_deactivate(cmd, resource, NULL))
- return EIO;
-
- if (!test_mode() && command & LCK_CLUSTER_VG) {
- status = hold_unlock(resource);
- if (status)
- return errno;
- }
-
- return 0;
-}
-
-const char *do_lock_query(char *resource)
-{
- int mode;
- const char *type;
-
- mode = get_current_lock(resource);
- switch (mode) {
- case LCK_NULL: type = "NL"; break;
- case LCK_READ: type = "CR"; break;
- case LCK_PREAD:type = "PR"; break;
- case LCK_WRITE:type = "PW"; break;
- case LCK_EXCL: type = "EX"; break;
- default: type = NULL;
- }
-
- DEBUGLOG("do_lock_query: resource '%s', mode %i (%s)\n", resource, mode, type ?: "--");
-
- return type;
-}
-
-/* This is the LOCK_LV part that happens on all nodes in the cluster -
- it is responsible for the interaction with device-mapper and LVM */
-int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
-{
- int status = 0;
-
- DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
- resource, decode_locking_cmd(command), decode_flags(lock_flags), critical_section());
-
- if (!cmd->initialized.config || config_files_changed(cmd)) {
- /* Reinitialise various settings inc. logging, filters */
- if (do_refresh_cache()) {
- log_error("Updated config file invalid. Aborting.");
- return EINVAL;
- }
- }
-
- pthread_mutex_lock(&lvm_lock);
- init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0);
-
- if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
- init_mirror_in_sync(1);
-
- if (lock_flags & LCK_DMEVENTD_MONITOR_IGNORE)
- init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE);
- else {
- if (lock_flags & LCK_DMEVENTD_MONITOR_MODE)
- init_dmeventd_monitor(1);
- else
- init_dmeventd_monitor(0);
- }
-
- cmd->partial_activation = (lock_flags & LCK_PARTIAL_MODE) ? 1 : 0;
-
- /* clvmd should never try to read suspended device */
- init_ignore_suspended_devices(1);
-
- switch (command & LCK_MASK) {
- case LCK_LV_EXCLUSIVE:
- status = do_activate_lv(resource, command, lock_flags, LCK_EXCL);
- break;
-
- case LCK_LV_SUSPEND:
- status = do_suspend_lv(resource, command, lock_flags);
- break;
-
- case LCK_UNLOCK:
- case LCK_LV_RESUME: /* if active */
- status = do_resume_lv(resource, command, lock_flags);
- break;
-
- case LCK_LV_ACTIVATE:
- status = do_activate_lv(resource, command, lock_flags, LCK_READ);
- break;
-
- case LCK_LV_DEACTIVATE:
- status = do_deactivate_lv(resource, command, lock_flags);
- break;
-
- default:
- DEBUGLOG("Invalid LV command 0x%x\n", command);
- status = EINVAL;
- break;
- }
-
- if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
- init_mirror_in_sync(0);
-
- cmd->partial_activation = 0;
-
- /* clean the pool for another command */
- dm_pool_empty(cmd->mem);
- init_test(0);
- pthread_mutex_unlock(&lvm_lock);
-
- DEBUGLOG("Command return is %d, critical_section is %d\n", status, critical_section());
- return status;
-}
-
-/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */
-int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
-{
- /* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
- lock out on this node (because we are the node modifying the metadata)
- before suspending cluster-wide.
- LCKF_CONVERT is used always, local node is going to modify metadata
- */
- if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND &&
- (command & LCK_CLUSTER_VG)) {
- DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
- resource, decode_locking_cmd(command), decode_flags(lock_flags));
-
- if (!(lock_flags & LCK_TEST_MODE) &&
- hold_lock(resource, LCK_WRITE, LCKF_NOQUEUE | LCKF_CONVERT))
- return errno;
- }
- return 0;
-}
-
-/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */
-int post_lock_lv(unsigned char command, unsigned char lock_flags,
- char *resource)
-{
- int status;
- unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
-
- /* Opposite of above, done on resume after a metadata update */
- if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME &&
- (command & LCK_CLUSTER_VG)) {
- int oldmode;
-
- DEBUGLOG("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
- resource, decode_locking_cmd(command), decode_flags(lock_flags));
-
- /* If the lock state is PW then restore it to what it was */
- oldmode = get_current_lock(resource);
- if (oldmode == LCK_WRITE) {
- struct lvinfo lvi;
-
- pthread_mutex_lock(&lvm_lock);
- status = lv_info_by_lvid(cmd, resource, origin_only, &lvi, 0, 0);
- pthread_mutex_unlock(&lvm_lock);
- if (!status)
- return EIO;
-
- if (!(lock_flags & LCK_TEST_MODE)) {
- if (lvi.exists) {
- if (hold_lock(resource, LCK_READ, LCKF_CONVERT))
- return errno;
- } else if (hold_unlock(resource))
- return errno;
- }
- }
- }
- return 0;
-}
-
-int do_refresh_cache(void)
-{
- DEBUGLOG("Refreshing context\n");
- log_notice("Refreshing context");
-
- pthread_mutex_lock(&lvm_lock);
-
- if (!refresh_toolcontext(cmd)) {
- pthread_mutex_unlock(&lvm_lock);
- return -1;
- }
-
- init_ignore_suspended_devices(1);
- lvmcache_label_scan(cmd);
- label_scan_destroy(cmd); /* destroys bcache (to close devs), keeps lvmcache */
- dm_pool_empty(cmd->mem);
-
- pthread_mutex_unlock(&lvm_lock);
-
- return 0;
-}
-
-/*
- * Handle VG lock - drop metadata or update lvmcache state
- */
-void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
-{
- uint32_t lock_cmd = command;
- char *vgname = resource + 2;
-
- lock_cmd &= (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_HOLD);
-
- /*
- * Check if LCK_CACHE should be set. All P_ locks except # are cache related.
- */
- if (strncmp(resource, "P_#", 3) && !strncmp(resource, "P_", 2))
- lock_cmd |= LCK_CACHE;
-
- DEBUGLOG("do_lock_vg: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
- resource, decode_full_locking_cmd(lock_cmd), decode_flags(lock_flags), critical_section());
-
- /* P_#global causes a full cache refresh */
- if (!strcmp(resource, "P_" VG_GLOBAL)) {
- do_refresh_cache();
- return;
- }
-
- pthread_mutex_lock(&lvm_lock);
- init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0);
-
- switch (lock_cmd) {
- case LCK_VG_COMMIT:
- DEBUGLOG("vg_commit notification for VG %s\n", vgname);
- lvmcache_commit_metadata(vgname);
- break;
- case LCK_VG_REVERT:
- DEBUGLOG("vg_revert notification for VG %s\n", vgname);
- lvmcache_drop_metadata(vgname, 1);
- break;
- case LCK_VG_DROP_CACHE:
- default:
- DEBUGLOG("Invalidating cached metadata for VG %s\n", vgname);
- lvmcache_drop_metadata(vgname, 0);
- }
-
- init_test(0);
- pthread_mutex_unlock(&lvm_lock);
-}
-
-/*
- * Ideally, clvmd should be started before any LVs are active
- * but this may not be the case...
- * I suppose this also comes in handy if clvmd crashes, not that it would!
- */
-static int get_initial_state(struct dm_hash_table *excl_uuid)
-{
- int lock_mode;
- char lv[65], vg[65], flags[26], vg_flags[26]; /* with space for '\0' */
- char uuid[65];
- char line[255];
- char *lvs_cmd;
- const char *lvm_binary = getenv("LVM_BINARY") ? : LVM_PATH;
- FILE *lvs;
-
- if (dm_asprintf(&lvs_cmd, "%s lvs --config 'log{command_names=0 prefix=\"\"}' "
- "--nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
- lvm_binary) < 0)
- return_0;
-
- /* FIXME: Maybe link and use liblvm2cmd directly instead of fork */
- if (!(lvs = popen(lvs_cmd, "r"))) {
- dm_free(lvs_cmd);
- return 0;
- }
-
- while (fgets(line, sizeof(line), lvs)) {
- if (sscanf(line, "%64s %64s %25s %25s\n", vg, lv, flags, vg_flags) == 4) {
-
- /* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
- if (strlen(vg) == 38 && /* is is a valid UUID ? */
- (flags[4] == 'a' || flags[4] == 's') && /* is it active or suspended? */
- vg_flags[5] == 'c') { /* is it clustered ? */
- /* Convert hyphen-separated UUIDs into one */
- memcpy(&uuid[0], &vg[0], 6);
- memcpy(&uuid[6], &vg[7], 4);
- memcpy(&uuid[10], &vg[12], 4);
- memcpy(&uuid[14], &vg[17], 4);
- memcpy(&uuid[18], &vg[22], 4);
- memcpy(&uuid[22], &vg[27], 4);
- memcpy(&uuid[26], &vg[32], 6);
- memcpy(&uuid[32], &lv[0], 6);
- memcpy(&uuid[38], &lv[7], 4);
- memcpy(&uuid[42], &lv[12], 4);
- memcpy(&uuid[46], &lv[17], 4);
- memcpy(&uuid[50], &lv[22], 4);
- memcpy(&uuid[54], &lv[27], 4);
- memcpy(&uuid[58], &lv[32], 6);
- uuid[64] = '\0';
-
- /* Look for this lock in the list of EX locks
- we were passed on the command-line */
- lock_mode = (dm_hash_lookup(excl_uuid, uuid)) ?
- LCK_EXCL : LCK_READ;
-
- DEBUGLOG("getting initial lock for %s\n", uuid);
- if (hold_lock(uuid, lock_mode, LCKF_NOQUEUE))
- DEBUGLOG("Failed to hold lock %s\n", uuid);
- }
- }
- }
- if (pclose(lvs))
- DEBUGLOG("lvs pclose failed: %s\n", strerror(errno));
-
- dm_free(lvs_cmd);
-
- return 1;
-}
-
-static void lvm2_log_fn(int level, const char *file, int line, int dm_errno,
- const char *message)
-{
-
- /* Send messages to the normal LVM2 logging system too,
- so we get debug output when it's asked for.
- We need to NULL the function ptr otherwise it will just call
- back into here! */
- init_log_fn(NULL);
- print_log(level, file, line, dm_errno, "%s", message);
- init_log_fn(lvm2_log_fn);
-
- /*
- * Ignore non-error messages, but store the latest one for returning
- * to the user.
- */
- if (level != _LOG_ERR && level != _LOG_FATAL)
- return;
-
- (void) dm_strncpy(last_error, message, sizeof(last_error));
-}
-
-/* This checks some basic cluster-LVM configuration stuff */
-static void check_config(void)
-{
- int locking_type;
-
- locking_type = find_config_tree_int(cmd, global_locking_type_CFG, NULL);
-
- if (locking_type == 3) /* compiled-in cluster support */
- return;
-
- if (locking_type == 2) { /* External library, check name */
- const char *libname;
-
- libname = find_config_tree_str(cmd, global_locking_library_CFG, NULL);
- if (libname && strstr(libname, "liblvm2clusterlock.so"))
- return;
-
- log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
- return;
- }
- log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
-}
-
-/* Backups up the LVM metadata if it's changed */
-void lvm_do_backup(const char *vgname)
-{
- struct volume_group * vg;
- int consistent = 0;
-
- DEBUGLOG("Triggering backup of VG metadata for %s.\n", vgname);
-
- pthread_mutex_lock(&lvm_lock);
-
- vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, 0, WARN_PV_READ, &consistent);
-
- if (vg && consistent)
- check_current_backup(vg);
- else
- log_error("Error backing up metadata, can't find VG for group %s", vgname);
-
- release_vg(vg);
- dm_pool_empty(cmd->mem);
-
- pthread_mutex_unlock(&lvm_lock);
-}
-
-struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name)
-{
- struct lv_info *lvi;
-
- *name = NULL;
- if (!v)
- v = dm_hash_get_first(lv_hash);
-
- do {
- if (v) {
- lvi = dm_hash_get_data(lv_hash, v);
- DEBUGLOG("Looking for EX locks. found %x mode %d\n", lvi->lock_id, lvi->lock_mode);
-
- if (lvi->lock_mode == LCK_EXCL) {
- *name = dm_hash_get_key(lv_hash, v);
- }
- v = dm_hash_get_next(lv_hash, v);
- }
- } while (v && !*name);
-
- if (*name)
- DEBUGLOG("returning EXclusive UUID %s\n", *name);
- return v;
-}
-
-void lvm_do_fs_unlock(void)
-{
- pthread_mutex_lock(&lvm_lock);
- DEBUGLOG("Syncing device names\n");
- fs_unlock();
- pthread_mutex_unlock(&lvm_lock);
-}
-
-/* Called to initialise the LVM context of the daemon */
-int init_clvm(struct dm_hash_table *excl_uuid)
-{
- /* Use LOG_DAEMON for syslog messages instead of LOG_USER */
- init_syslog(LOG_DAEMON);
- openlog("clvmd", LOG_PID, LOG_DAEMON);
-
- /* Initialise already held locks */
- if (!get_initial_state(excl_uuid))
- log_error("Cannot load initial lock states.");
-
- if (!udev_init_library_context())
- stack;
-
- if (!(cmd = create_toolcontext(1, NULL, 0, 1, 1, 1))) {
- log_error("Failed to allocate command context");
- udev_fin_library_context();
- return 0;
- }
-
- if (stored_errno()) {
- destroy_toolcontext(cmd);
- return 0;
- }
-
- cmd->cmd_line = "clvmd";
-
- /* Check lvm.conf is setup for cluster-LVM */
- check_config();
- init_ignore_suspended_devices(1);
-
- /* Trap log messages so we can pass them back to the user */
- init_log_fn(lvm2_log_fn);
- memlock_inc_daemon(cmd);
-
- return 1;
-}
-
-void destroy_lvm(void)
-{
- if (cmd) {
- memlock_dec_daemon(cmd);
- destroy_toolcontext(cmd);
- udev_fin_library_context();
- cmd = NULL;
- }
-}
diff --git a/daemons/clvmd/lvm-functions.h b/daemons/clvmd/lvm-functions.h
deleted file mode 100644
index 6785997a2..000000000
--- a/daemons/clvmd/lvm-functions.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2010 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 General Public License v.2.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/* Functions in lvm-functions.c */
-
-#ifndef _LVM_FUNCTIONS_H
-#define _LVM_FUNCTIONS_H
-
-extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
- char *resource);
-extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
- char *resource);
-extern const char *do_lock_query(char *resource);
-extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
- char *resource);
-extern int do_refresh_cache(void);
-extern int init_clvm(struct dm_hash_table *excl_uuid);
-extern void destroy_lvm(void);
-extern void init_lvhash(void);
-extern void destroy_lvhash(void);
-extern void lvm_do_backup(const char *vgname);
-extern char *get_last_lvm_error(void);
-extern void do_lock_vg(unsigned char command, unsigned char lock_flags,
- char *resource);
-extern struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name);
-void lvm_do_fs_unlock(void);
-
-#endif
diff --git a/daemons/clvmd/refresh_clvmd.c b/daemons/clvmd/refresh_clvmd.c
deleted file mode 100644
index c80e09f5b..000000000
--- a/daemons/clvmd/refresh_clvmd.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2010 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 General Public License v.2.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/* FIXME Remove duplicated functions from this file. */
-
-/*
- * Send a command to a running clvmd from the command-line
- */
-
-#include "clvmd-common.h"
-
-#include "daemons/clvmd/clvm.h"
-#include "refresh_clvmd.h"
-
-#include <stddef.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-typedef struct lvm_response {
- char node[255];
- char *response;
- int status;
- int len;
-} lvm_response_t;
-
-/*
- * This gets stuck at the start of memory we allocate so we
- * can sanity-check it at deallocation time
- */
-#define LVM_SIGNATURE 0x434C564D
-
-static int _clvmd_sock = -1;
-
-/* Open connection to the clvm daemon */
-static int _open_local_sock(void)
-{
- int local_socket;
- struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
-
- if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) {
- fprintf(stderr, "%s: clvmd socket name too long.", CLVMD_SOCKNAME);
- return -1;
- }
-
- /* Open local socket */
- if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
- fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
- return -1;
- }
-
- if (connect(local_socket,(struct sockaddr *) &sockaddr,
- sizeof(sockaddr))) {
- int saved_errno = errno;
-
- fprintf(stderr, "connect() failed on local socket: %s\n",
- strerror(errno));
- if (close(local_socket))
- return -1;
-
- errno = saved_errno;
- return -1;
- }
-
- return local_socket;
-}
-
-/* Send a request and return the status */
-static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_response)
-{
- char outbuf[PIPE_BUF];
- struct clvm_header *outheader = (struct clvm_header *) outbuf;
- int len;
- unsigned off;
- int buflen;
- int err;
-
- /* Send it to CLVMD */
- rewrite:
- if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
- if (err == -1 && errno == EINTR)
- goto rewrite;
- fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
- return 0;
- }
- if (no_response)
- return 1;
-
- /* Get the response */
- reread:
- if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
- if (errno == EINTR)
- goto reread;
- fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
- return 0;
- }
-
- if (len == 0) {
- fprintf(stderr, "EOF reading CLVMD");
- errno = ENOTCONN;
- return 0;
- }
-
- /* Allocate buffer */
- buflen = len + outheader->arglen;
- *retbuf = dm_malloc(buflen);
- if (!*retbuf) {
- errno = ENOMEM;
- return 0;
- }
-
- /* Copy the header */
- memcpy(*retbuf, outbuf, len);
- outheader = (struct clvm_header *) *retbuf;
-
- /* Read the returned values */
- off = 1; /* we've already read the first byte */
- while (off <= outheader->arglen && len > 0) {
- len = read(_clvmd_sock, outheader->args + off,
- buflen - off - offsetof(struct clvm_header, args));
- if (len > 0)
- off += len;
- }
-
- /* Was it an error ? */
- if (outheader->status != 0) {
- errno = outheader->status;
-
- /* Only return an error here if there are no node-specific
- errors present in the message that might have more detail */
- if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
- fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
- return 0;
- }
-
- }
-
- return 1;
-}
-
-/* Build the structure header and parse-out wildcard node names */
-static void _build_header(struct clvm_header *head, int cmd, const char *node,
- unsigned int len)
-{
- head->cmd = cmd;
- head->status = 0;
- head->flags = 0;
- head->xid = 0;
- head->clientid = 0;
- if (len)
- /* 1 byte is used from struct clvm_header.args[1], so -> len - 1 */
- head->arglen = len - 1;
- else {
- head->arglen = 0;
- *head->args = '\0';
- }
-
- /*
- * Translate special node names.
- */
- if (!node || !strcmp(node, NODE_ALL))
- head->node[0] = '\0';
- else if (!strcmp(node, NODE_LOCAL)) {
- head->node[0] = '\0';
- head->flags = CLVMD_FLAG_LOCAL;
- } else
- strcpy(head->node, node);
-}
-
-/*
- * Send a message to a(or all) node(s) in the cluster and wait for replies
- */
-static int _cluster_request(char cmd, const char *node, void *data, int len,
- lvm_response_t ** response, int *num, int no_response)
-{
- char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
- char *inptr;
- char *retbuf = NULL;
- int status;
- int i;
- int num_responses = 0;
- struct clvm_header *head = (struct clvm_header *) outbuf;
- lvm_response_t *rarray;
-
- *num = 0;
-
- if (_clvmd_sock == -1)
- _clvmd_sock = _open_local_sock();
-
- if (_clvmd_sock == -1)
- return 0;
-
- _build_header(head, cmd, node, len);
- if (len)
- memcpy(head->node + strlen(head->node) + 1, data, len);
-
- status = _send_request(outbuf, sizeof(struct clvm_header) +
- strlen(head->node) + len, &retbuf, no_response);
- if (!status || no_response)
- goto out;
-
- /* Count the number of responses we got */
- head = (struct clvm_header *) retbuf;
- inptr = head->args;
- while (inptr[0]) {
- num_responses++;
- inptr += strlen(inptr) + 1;
- inptr += sizeof(int);
- inptr += strlen(inptr) + 1;
- }
-
- /*
- * Allocate response array.
- * With an extra pair of INTs on the front to sanity
- * check the pointer when we are given it back to free
- */
- *response = NULL;
- if (!(rarray = dm_malloc(sizeof(lvm_response_t) * num_responses +
- sizeof(int) * 2))) {
- errno = ENOMEM;
- status = 0;
- goto out;
- }
-
- /* Unpack the response into an lvm_response_t array */
- inptr = head->args;
- i = 0;
- while (inptr[0]) {
- strcpy(rarray[i].node, inptr);
- inptr += strlen(inptr) + 1;
-
- memcpy(&rarray[i].status, inptr, sizeof(int));
- inptr += sizeof(int);
-
- rarray[i].response = dm_malloc(strlen(inptr) + 1);
- if (rarray[i].response == NULL) {
- /* Free up everything else and return error */
- int j;
- for (j = 0; j < i; j++)
- dm_free(rarray[i].response);
- dm_free(rarray);
- errno = ENOMEM;
- status = 0;
- goto out;
- }
-
- strcpy(rarray[i].response, inptr);
- rarray[i].len = strlen(inptr);
- inptr += strlen(inptr) + 1;
- i++;
- }
- *num = num_responses;
- *response = rarray;
-
- out:
- dm_free(retbuf);
-
- return status;
-}
-
-/* Free reply array */
-static int _cluster_free_request(lvm_response_t * response, int num)
-{
- int i;
-
- for (i = 0; i < num; i++) {
- dm_free(response[i].response);
- }
-
- dm_free(response);
-
- return 1;
-}
-
-int refresh_clvmd(int all_nodes)
-{
- int num_responses;
- char args[1]; // No args really.
- lvm_response_t *response = NULL;
- int saved_errno;
- int status;
- int i;
-
- status = _cluster_request(CLVMD_CMD_REFRESH, all_nodes ? NODE_ALL : NODE_LOCAL, args, 0, &response, &num_responses, 0);
-
- /* If any nodes were down then display them and return an error */
- for (i = 0; i < num_responses; i++) {
- if (response[i].status == EHOSTDOWN) {
- fprintf(stderr, "clvmd not running on node %s",
- response[i].node);
- status = 0;
- errno = response[i].status;
- } else if (response[i].status) {
- fprintf(stderr, "Error resetting node %s: %s",
- response[i].node,
- response[i].response[0] ?
- response[i].response :
- strerror(response[i].status));
- status = 0;
- errno = response[i].status;
- }
- }
-
- saved_errno = errno;
- _cluster_free_request(response, num_responses);
- errno = saved_errno;
-
- return status;
-}
-
-int restart_clvmd(int all_nodes)
-{
- int dummy, status;
-
- status = _cluster_request(CLVMD_CMD_RESTART, all_nodes ? NODE_ALL : NODE_LOCAL, NULL, 0, NULL, &dummy, 1);
-
- /*
- * FIXME: we cannot receive response, clvmd re-exec before it.
- * but also should not close socket too early (the whole rq is dropped then).
- * FIXME: This should be handled this way:
- * - client waits for RESTART ack (and socket close)
- * - server restarts
- * - client checks that server is ready again (VERSION command?)
- */
- usleep(500000);
-
- return status;
-}
-
-int debug_clvmd(int level, int clusterwide)
-{
- int num_responses;
- char args[1];
- const char *nodes;
- lvm_response_t *response = NULL;
- int saved_errno;
- int status;
- int i;
-
- args[0] = level;
- if (clusterwide)
- nodes = NODE_ALL;
- else
- nodes = NODE_LOCAL;
-
- status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses, 0);
-
- /* If any nodes were down then display them and return an error */
- for (i = 0; i < num_responses; i++) {
- if (response[i].status == EHOSTDOWN) {
- fprintf(stderr, "clvmd not running on node %s",
- response[i].node);
- status = 0;
- errno = response[i].status;
- } else if (response[i].status) {
- fprintf(stderr, "Error setting debug on node %s: %s",
- response[i].node,
- response[i].response[0] ?
- response[i].response :
- strerror(response[i].status));
- status = 0;
- errno = response[i].status;
- }
- }
-
- saved_errno = errno;
- _cluster_free_request(response, num_responses);
- errno = saved_errno;
-
- return status;
-}
diff --git a/daemons/clvmd/refresh_clvmd.h b/daemons/clvmd/refresh_clvmd.h
deleted file mode 100644
index b9d775e3d..000000000
--- a/daemons/clvmd/refresh_clvmd.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2007 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 General Public License v.2.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-
-int refresh_clvmd(int all_nodes);
-int restart_clvmd(int all_nodes);
-int debug_clvmd(int level, int clusterwide);
-