mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-22 17:35:59 +03:00
Add infrastructure for running the functional testsuite with locking_type set
to 3, using a local (singlenode) clvmd.
This commit is contained in:
parent
e9e5dbb628
commit
fdefd5eff9
@ -340,6 +340,7 @@ AC_ARG_WITH(clvmd,
|
||||
* cman,gulm (RHEL4 or equivalent)
|
||||
* cman (RHEL5 or equivalent)
|
||||
* cman,corosync,openais (or selection of them)
|
||||
* singlenode (localhost only)
|
||||
* all (autodetect)
|
||||
* none (disable build)
|
||||
[TYPE=none] ],
|
||||
|
@ -71,6 +71,10 @@ ifneq (,$(findstring corosync,, "@CLVMD@,"))
|
||||
DEFS += -DUSE_COROSYNC
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring singlenode,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-singlenode.c
|
||||
DEFS += -DUSE_SINGLENODE
|
||||
endif
|
||||
|
||||
TARGETS = \
|
||||
clvmd
|
||||
|
@ -110,5 +110,12 @@ struct cluster_ops *init_openais_cluster(void);
|
||||
struct cluster_ops *init_corosync_cluster(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SINGLENODE
|
||||
# define SINGLENODE_CSID_LEN (sizeof(int))
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN 64
|
||||
# define SINGLENODE_MAX_CLUSTER_MESSAGE 65535
|
||||
# define MAX_CSID_LEN sizeof(int)
|
||||
struct cluster_ops *init_singlenode_cluster(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
252
daemons/clvmd/clvmd-singlenode.c
Normal file
252
daemons/clvmd/clvmd-singlenode.c
Normal file
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <configure.h>
|
||||
#include <libdevmapper.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "locking.h"
|
||||
#include "lvm-logging.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
#include "clvmd.h"
|
||||
|
||||
static int listen_fd = -1;
|
||||
|
||||
static int init_comms()
|
||||
{
|
||||
listen_fd = open("/dev/null", O_RDWR);
|
||||
|
||||
if (listen_fd < 0)
|
||||
return -1;
|
||||
|
||||
/* Set Close-on-exec */
|
||||
fcntl(listen_fd, F_SETFD, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = init_comms();
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
DEBUGLOG("Single-node cluster initialised.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
close(listen_fd);
|
||||
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
destroy_lvhash();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
sprintf(name, "%x", 0xdead);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
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 int *_locks = NULL;
|
||||
static char **_resources = NULL;
|
||||
static int _lock_max = 1;
|
||||
static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* Real locking */
|
||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int *_locks_1;
|
||||
char **_resources_1;
|
||||
int i, j;
|
||||
|
||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n",
|
||||
resource, flags, mode);
|
||||
|
||||
retry:
|
||||
pthread_mutex_lock(&_lock_mutex);
|
||||
|
||||
/* look for an existing lock for this resource */
|
||||
for (i = 1; i < _lock_max; ++i) {
|
||||
if (!_resources[i])
|
||||
break;
|
||||
if (!strcmp(_resources[i], resource)) {
|
||||
if ((_locks[i] & LCK_WRITE) || (_locks[i] & LCK_EXCL)) {
|
||||
DEBUGLOG("%s already write/exclusively locked...\n", resource);
|
||||
goto maybe_retry;
|
||||
}
|
||||
if ((mode & LCK_WRITE) || (mode & LCK_EXCL)) {
|
||||
DEBUGLOG("%s already locked and WRITE/EXCL lock requested...\n",
|
||||
resource);
|
||||
goto maybe_retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i == _lock_max) { /* out of lock slots, extend */
|
||||
_locks_1 = dm_realloc(_locks, 2 * _lock_max * sizeof(int));
|
||||
if (!_locks_1)
|
||||
return 1; /* fail */
|
||||
_locks = _locks_1;
|
||||
_resources_1 = dm_realloc(_resources, 2 * _lock_max * sizeof(char *));
|
||||
if (!_resources_1) {
|
||||
/* _locks may get realloc'd twice, but that should be safe */
|
||||
return 1; /* fail */
|
||||
}
|
||||
_resources = _resources_1;
|
||||
/* clear the new resource entries */
|
||||
for (j = _lock_max; j < 2 * _lock_max; ++j)
|
||||
_resources[j] = NULL;
|
||||
_lock_max = 2 * _lock_max;
|
||||
}
|
||||
|
||||
/* resource is not currently locked, grab it */
|
||||
|
||||
*lockid = i;
|
||||
_locks[i] = mode;
|
||||
_resources[i] = dm_strdup(resource);
|
||||
|
||||
DEBUGLOG("%s locked -> %d\n", resource, i);
|
||||
|
||||
pthread_mutex_unlock(&_lock_mutex);
|
||||
return 0;
|
||||
maybe_retry:
|
||||
pthread_mutex_unlock(&_lock_mutex);
|
||||
if (!(flags & LCK_NONBLOCK)) {
|
||||
usleep(10000);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return 1; /* fail */
|
||||
}
|
||||
|
||||
static int _unlock_resource(const char *resource, int lockid)
|
||||
{
|
||||
DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
|
||||
if(!_resources[lockid]) {
|
||||
DEBUGLOG("(%s) %d not locked\n", resource, lockid);
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(_resources[lockid], resource)) {
|
||||
DEBUGLOG("%d has wrong resource (requested %s, got %s)\n",
|
||||
lockid, resource, _resources[lockid]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dm_free(_resources[lockid]);
|
||||
_resources[lockid] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _is_quorate()
|
||||
{
|
||||
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)
|
||||
{
|
||||
strncpy(buf, "localcluster", buflen);
|
||||
buf[buflen - 1] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_singlenode_ops = {
|
||||
.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;
|
||||
else
|
||||
return NULL;
|
||||
}
|
@ -110,7 +110,7 @@ static int child_pipe[2];
|
||||
#define DFAIL_TIMEOUT 5
|
||||
#define SUCCESS 0
|
||||
|
||||
typedef enum {IF_AUTO, IF_CMAN, IF_GULM, IF_OPENAIS, IF_COROSYNC} if_type_t;
|
||||
typedef enum {IF_AUTO, IF_CMAN, IF_GULM, IF_OPENAIS, IF_COROSYNC, IF_SINGLENODE} if_type_t;
|
||||
|
||||
typedef void *(lvm_pthread_fn_t)(void*);
|
||||
|
||||
@ -179,6 +179,9 @@ static void usage(char *prog, FILE *file)
|
||||
#endif
|
||||
#ifdef USE_GULM
|
||||
fprintf(file, "gulm ");
|
||||
#endif
|
||||
#ifdef USE_SINGLENODE
|
||||
fprintf(file, "singlenode");
|
||||
#endif
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
@ -434,6 +437,15 @@ int main(int argc, char *argv[])
|
||||
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to OpenAIS");
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SINGLENODE
|
||||
if (!clops)
|
||||
if ((cluster_iface == IF_AUTO || 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");
|
||||
@ -2063,6 +2075,8 @@ static if_type_t parse_cluster_interface(char *ifname)
|
||||
iface = IF_OPENAIS;
|
||||
if (!strcmp(ifname, "corosync"))
|
||||
iface = IF_COROSYNC;
|
||||
if (!strcmp(ifname, "singlenode"))
|
||||
iface = IF_SINGLENODE;
|
||||
|
||||
return iface;
|
||||
}
|
||||
|
@ -270,7 +270,7 @@
|
||||
/* Define to 1 if you have the `strtoul' function. */
|
||||
#undef HAVE_STRTOUL
|
||||
|
||||
/* Define to 1 if `st_rdev' is member of `struct stat'. */
|
||||
/* Define to 1 if `struct stat' is a member of `st_rdev'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_RDEV
|
||||
|
||||
/* Define to 1 if you have the <syslog.h> header file. */
|
||||
@ -407,6 +407,9 @@
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
|
@ -42,7 +42,10 @@ api/vgtest:
|
||||
endif
|
||||
|
||||
all: init.sh
|
||||
./bin/harness t-*.sh
|
||||
@echo Testing with locking_type 1
|
||||
#./bin/harness t-*.sh
|
||||
@echo Testing with locking_type 3
|
||||
LVM_TEST_LOCKING=3 ./bin/harness t-*.sh
|
||||
|
||||
bin/not: $(srcdir)/not.c .bin-dir-stamp
|
||||
$(CC) -o bin/not $<
|
||||
@ -77,6 +80,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
ln -s ../lvm-wrapper bin/$$i; \
|
||||
done
|
||||
ln -s "$(abs_top_builddir)/tools/dmsetup" bin/dmsetup
|
||||
ln -s "$(abs_top_builddir)/daemons/clvmd/clvmd" bin/clvmd
|
||||
touch $@
|
||||
|
||||
lvm-wrapper: Makefile
|
||||
|
@ -54,10 +54,31 @@ finish_udev_transaction() {
|
||||
fi
|
||||
}
|
||||
|
||||
prepare_clvmd() {
|
||||
if test -z "$LVM_TEST_LOCKING" || test "$LVM_TEST_LOCKING" -ne 3 ; then
|
||||
return 0 # not needed
|
||||
fi
|
||||
|
||||
if pgrep clvmd ; then
|
||||
echo "Cannot use fake cluster locking with real clvmd ($(pgrep clvmd)) running."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# skip if we don't have our own clvmd...
|
||||
(which clvmd | grep $abs_builddir) || exit 200
|
||||
|
||||
trap 'aux teardown_' EXIT # don't forget to clean up
|
||||
|
||||
clvmd -Isinglenode -d 1 &
|
||||
LOCAL_CLVMD="$!"
|
||||
}
|
||||
|
||||
teardown() {
|
||||
echo $LOOP
|
||||
echo $PREFIX
|
||||
|
||||
test -n "$LOCAL_CLVMD" && kill -9 "$LOCAL_CLVMD"
|
||||
|
||||
test -n "$PREFIX" && {
|
||||
rm -rf $G_root_/dev/$PREFIX*
|
||||
|
||||
@ -288,6 +309,8 @@ prepare_lvmconf() {
|
||||
local filter="$1"
|
||||
test -z "$filter" && \
|
||||
filter='[ "a/dev\/mirror/", "a/dev\/mapper\/.*pv[0-9_]*$/", "r/.*/" ]'
|
||||
locktype=
|
||||
if test -n "$LVM_TEST_LOCKING"; then locktype="locking_type = $LVM_TEST_LOCKING"; fi
|
||||
cat > $G_root_/etc/lvm.conf <<-EOF
|
||||
devices {
|
||||
dir = "$G_dev_"
|
||||
@ -309,6 +332,7 @@ prepare_lvmconf() {
|
||||
abort_on_internal_errors = 1
|
||||
library_dir = "$G_root_/lib"
|
||||
locking_dir = "$G_root_/var/lock/lvm"
|
||||
$locktype
|
||||
}
|
||||
activation {
|
||||
udev_sync = 1
|
||||
@ -319,4 +343,5 @@ EOF
|
||||
|
||||
set -vexE -o pipefail
|
||||
aux prepare_lvmconf
|
||||
prepare_clvmd
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user