[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[lvm-devel] [PATCH DRAFT] Automatic testing with locking_type = 3.



Hi,

this patch adds the option to run our automatic testsuite with a clvmd
configured for single-machine operation. There are still couple things
that need to be done for this patch before checkin though:

- rename fake to (probably) singlenode
- clean up and double-check the _resource_(un)lock implementation

Currently, we only keep the locks in memory. This is wholly appropriate
as long as clvmd is running and being used -- since all locking goes
through this clvmd instance, there's no need for external coordination.

As things are (with the current locking implementation) the full
testsuite passes. You can try with yourself with 

# LVM_TEST_LOCKING=3 make check

The next step, other than above, is to integrate this into make check,
so make check will run all the tests twice, once with locking_type 1 and
once with locking_type 3.

I will send a revised patch later.

Yours,
   Petr.

diff -rN -u -p old-upstream/configure.in new-upstream/configure.in
--- old-upstream/configure.in	2010-03-10 17:02:33.000000000 +0100
+++ new-upstream/configure.in	2010-03-10 17:02:33.000000000 +0100
@@ -342,6 +342,7 @@ AC_ARG_WITH(clvmd,
                            * cman,corosync,openais (or selection of them)
                            * all                   (autodetect)
                            * none                  (disable build)
+                           * fake                  (debugging only)
                           [TYPE=none] ],
   [ CLVMD="$withval" ],
   [ CLVMD="none" ])
diff -rN -u -p old-upstream/daemons/clvmd/clvmd.c new-upstream/daemons/clvmd/clvmd.c
--- old-upstream/daemons/clvmd/clvmd.c	2010-03-10 17:02:33.000000000 +0100
+++ new-upstream/daemons/clvmd/clvmd.c	2010-03-10 17:02:33.000000000 +0100
@@ -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_FAKE} if_type_t;
 
 typedef void *(lvm_pthread_fn_t)(void*);
 
@@ -180,6 +180,9 @@ static void usage(char *prog, FILE *file
 #ifdef USE_GULM
 	fprintf(file, "gulm ");
 #endif
+#ifdef USE_FAKE
+	fprintf(file, "fake ");
+#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_FAKE
+	if (!clops)
+		if ((cluster_iface == IF_AUTO || cluster_iface == IF_FAKE) && (clops = init_fake_cluster())) {
+			max_csid_len = FAKE_CSID_LEN;
+			max_cluster_message = FAKE_MAX_CLUSTER_MESSAGE;
+			max_cluster_member_name_len = MAX_CLUSTER_MEMBER_NAME_LEN;
+			syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to FakeCluster");
+		}
+#endif
 
 	if (!clops) {
 		DEBUGLOG("Can't initialise cluster interface\n");
@@ -2063,6 +2075,8 @@ static if_type_t parse_cluster_interface
 		iface = IF_OPENAIS;
 	if (!strcmp(ifname, "corosync"))
 		iface = IF_COROSYNC;
+	if (!strcmp(ifname, "fake"))
+		iface = IF_FAKE;
 
 	return iface;
 }
diff -rN -u -p old-upstream/daemons/clvmd/clvmd-comms.h new-upstream/daemons/clvmd/clvmd-comms.h
--- old-upstream/daemons/clvmd/clvmd-comms.h	2010-03-10 17:02:33.000000000 +0100
+++ new-upstream/daemons/clvmd/clvmd-comms.h	2010-03-10 17:02:33.000000000 +0100
@@ -110,5 +110,12 @@ struct cluster_ops *init_openais_cluster
 struct cluster_ops *init_corosync_cluster(void);
 #endif
 
+#ifdef USE_FAKE
+#  define FAKE_CSID_LEN (sizeof(int))
+#  define MAX_CLUSTER_MEMBER_NAME_LEN       64
+#  define FAKE_MAX_CLUSTER_MESSAGE          65535
+#  define MAX_CSID_LEN sizeof(int)
+struct cluster_ops *init_fake_cluster(void);
+#endif
 
 #endif
diff -rN -u -p old-upstream/daemons/clvmd/clvmd-fake.c new-upstream/daemons/clvmd/clvmd-fake.c
--- old-upstream/daemons/clvmd/clvmd-fake.c	1970-01-01 01:00:00.000000000 +0100
+++ new-upstream/daemons/clvmd/clvmd-fake.c	2010-03-10 17:02:33.000000000 +0100
@@ -0,0 +1,231 @@
+/*
+ * 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
+ */
+
+/*
+ * This provides the fake interface for locking manager
+ */
+
+#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 "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[128];
+static char *_resources[128];
+
+/* Real locking */
+static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
+{
+	int i;
+
+	DEBUGLOG("XXX lock_resource '%s', flags=%d, mode=%d\n",
+		 resource, flags, mode);
+
+ retry:
+
+	for (i = 1; i < 128; ++i) {
+		if (!_resources[i])
+			break;
+		if (!strcmp(_resources[i], resource)) {
+			if ((_locks[i] & LCK_WRITE) || (_locks[i] & LCK_EXCL)) {
+				DEBUGLOG("XXX %s already write/exclusively locked.\n", resource);
+				goto maybe_retry;
+			}
+			if ((mode & LCK_WRITE) || (mode & LCK_EXCL)) {
+				DEBUGLOG("XXX %s already locked, cannot grant lock.\n", resource);
+				goto maybe_retry;
+			}
+		}
+	}
+	if (i == 128) {
+		DEBUGLOG("LOCK CAPACITY EXCEEDED");
+		return 1;
+	}
+
+	*lockid = i;
+	_locks[i] = mode;
+	_resources[i] = dm_strdup(resource);
+
+	DEBUGLOG("XXX %s locked -> %d\n",
+		 resource, i);
+
+	return 0;
+ maybe_retry:
+	if (!(flags & LCK_NONBLOCK)) {
+		usleep(10000);
+		goto retry;
+	}
+
+	return 1; /* fail */
+}
+
+static int _unlock_resource(const char *resource, int lockid)
+{
+	DEBUGLOG("XXX unlock_resource: %s lockid: %x\n", resource, lockid);
+	if(!_resources[lockid]) {
+		DEBUGLOG("XXX (%s) %d not locked\n", resource, lockid);
+		return 1;
+	}
+	if(strcmp(_resources[lockid], resource)) {
+		DEBUGLOG("XXX %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_fake_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_fake_cluster(void)
+{
+	if (!_init_cluster())
+		return &_cluster_fake_ops;
+	else
+		return NULL;
+}
diff -rN -u -p old-upstream/daemons/clvmd/Makefile.in new-upstream/daemons/clvmd/Makefile.in
--- old-upstream/daemons/clvmd/Makefile.in	2010-03-10 17:02:33.000000000 +0100
+++ new-upstream/daemons/clvmd/Makefile.in	2010-03-10 17:02:33.000000000 +0100
@@ -71,6 +71,10 @@ ifneq (,$(findstring corosync,, "@CLVMD@
 	DEFS += -DUSE_COROSYNC
 endif
 
+ifneq (,$(findstring fake,, &quot;@CLVMD@,&quot;))
+	SOURCES += clvmd-fake.c
+	DEFS += -DUSE_FAKE
+endif
 
 TARGETS = \
 	clvmd
diff -rN -u -p old-upstream/test/Makefile.in new-upstream/test/Makefile.in
--- old-upstream/test/Makefile.in	2010-03-10 17:02:33.000000000 +0100
+++ new-upstream/test/Makefile.in	2010-03-10 17:02:33.000000000 +0100
@@ -77,6 +77,7 @@ Makefile: $(srcdir)/Makefile.in $(top_bu
 	  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
diff -rN -u -p old-upstream/test/test-utils.sh new-upstream/test/test-utils.sh
--- old-upstream/test/test-utils.sh	2010-03-10 17:02:33.000000000 +0100
+++ new-upstream/test/test-utils.sh	2010-03-10 17:02:33.000000000 +0100
@@ -39,10 +39,28 @@ 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
+
+	trap 'aux teardown_' EXIT # don't forget to clean up
+
+	clvmd -Ifake -d 1 & # >clvmd.log 2>&1 &
+	FAKE_CLVMD="$!"
+}
+
 teardown() {
 	echo $LOOP
 	echo $PREFIX
 
+	test -n "$FAKE_CLVMD" && kill -9 "$FAKE_CLVMD"
+
 	test -n "$PREFIX" && {
 		rm -rf $G_root_/dev/$PREFIX*
 
@@ -273,6 +291,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_"
@@ -294,6 +314,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
@@ -304,4 +325,5 @@ EOF
 
 set -vexE -o pipefail
 aux prepare_lvmconf
+prepare_clvmd
 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]