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

Re: [lvm-devel] [DRAFT PATCH] Client-side LVMetaD integration



Hi again!

Petr Rockai <prockai redhat com> writes:
> I have a preliminary version (really preliminary, it is full of debug
> junk, excuse me please) of client-side integration of lvmetad. There
> comes an executive summary:

I am attaching a new version that addresses most of the issues outlined
below. I will give more details inline.

> - We do not disable label scanning just yet (which is the major cause of
>   IO hitting disk). We can get there, but two things need to be sorted
>   out first: tracking MDAs (more about that below) and building up
>   lvmcache info structures from lvmetad data. This is required because
>   we are not quite ready to nuke lvmcache right now (but we'll get
>   there, bear with me).

This is still true. There are basically two things that need to happen
to get there:

- better internal handling of orphan PVs (through the orphan VG)
- MDA tracking inside metadata (using PV labels/UUIDs)

> 1. Code fails to notice inconsistencies (VG metadata is cached and not
>    enough manual scanning can happen due to below).
>
>    FAILED: shell/inconsistent-metadata.sh
>    FAILED: shell/unlost-pv.sh

I have changed vgscan to always scan disks and find inconsistencies that
way. It will now also update lvmetad with what it finds on disk. Both
these tests now pass (but inconsistent-metadata needed to be modified to
not expect commands like vgs to notice on-disk inconsistencies).

> 2. Pvscan is not entirely integrated with lvmetad yet. Moreover, even if
>    we fully update the PV status from pvscan (we currently only add PVs,
>    not remove them even if they failed to turn up), there will be a
>    problem that a VG with all PVs missing is currently regarded as
>    existing by lvmetad. This can be fixed (i.e. last PV disappears means
>    the VG ceases to exist), but should be probably discussed first.
>
>    FAILED: shell/lvmcache-exercise.sh

I have compromised on this slightly: VGs will only disappear entirely
when all their PVs were marked missing through a pvscan. This seems to
be a reasonable approach. The test passes now and nothing new broke.

> 3. MDA info is out of band from metadata. Needs to be merged with
>    metadata in lvmetad, otherwise lvmetad can't keep track of this.
>    This will in turn prompt a reform of the format_instance code, which
>    is an utter mess anyway, and needs to be cleaned up ASAP. A central
>    place to obtain the MDA infos is requisite, otherwise we can't
>    disable label scanning.
>
>    FAILED: shell/metadata-balance.sh
>    FAILED: shell/pvcreate-usage.sh
>    FAILED: shell/vgextend-usage.sh

These 3 tests still fail. The MDA info has not been integrated with
metadata yet. I'll work on this next and expect to have a working
version done before FOSDEM starts.

> 4. Wrong format reported (lvm2, but the VG itself is lvm1) due to
>    importing text metadata from lvmetad. Same problem exists with
>    reading text backups of LVM1 VGs, but this is not caught by the
>    testsuite. There is an old FIXME around. Extending LVM2 metadata with
>    a "semantics" version marker saying "this is LVM1 even though you are
>    looking at text metadata" would fix the problem. We can also handle
>    this out of band in lvmetad, but it is inelegant and leaves tho other
>    problem open.
>
>    FAILED: shell/vgcreate-usage.sh

To fix this, I have added an optional field "format" to text-formatted
metadata. It is always produced when the format is known (through the
format instance context). When metadata is obtained from lvmetad, the
format field is used to construct a correct format instance and format
instance context. The relevant test is fixed.

> When all of the above is addressed, plus we can populate lvmcache
> objects from lvmetad, we should be in a position to pull the plug on
> label scans when lvmetad is around. Let's wish for a smooth ride. :-)

This now means basically number 3, and possibly the orphan PV
handling. I'll keep you informed.

Yours,
   Petr

PS: I would like to start merging this code ASAP, since it can be easily
compiled out by default. I fancy that we'll sit down on this with
Alasdair next Monday and get the majority of the changes reviewed and
merged. Flipping the configure switch can wait a bit longer, but when
this is merged we'll be able to add automated builds with lvmetad
enabled to get some more testing coverage.

PPS: I know that the patch is dirty like a zebra. I'll clean it up as
soon as I am finished with deratizing^Wdebugging it. It is a DRAFT for a
reason.

? NOTES
? daemons/dmeventd/Makefile.in.new
? daemons/dmeventd/dmeventd.c.new
? daemons/lvmetad/test.sh.new
? daemons/lvmetad/testclient.c.new
? test/t-pvscan.sh
Index: make.tmpl.in
===================================================================
RCS file: /cvs/lvm2/LVM2/make.tmpl.in,v
retrieving revision 1.127
diff -u -p -r1.127 make.tmpl.in
--- make.tmpl.in	23 Nov 2011 12:19:23 -0000	1.127
+++ make.tmpl.in	30 Jan 2012 16:46:06 -0000
@@ -39,7 +39,7 @@ ELDFLAGS += @ELDFLAGS@
 LDDEPS += @LDDEPS@
 LDFLAGS += @LDFLAGS@
 LIB_SUFFIX = @LIB_SUFFIX@
-LVMINTERNAL_LIBS = -llvm-internal $(UDEV_LIBS) $(DL_LIBS)
+LVMINTERNAL_LIBS = -llvm-internal -L$(top_builddir)/daemons -ldaemon $(UDEV_LIBS) $(DL_LIBS)
 DL_LIBS = @DL_LIBS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
 READLINE_LIBS = @READLINE_LIBS@
Index: daemons/common/daemon-server.c
===================================================================
RCS file: /cvs/lvm2/LVM2/daemons/common/daemon-server.c,v
retrieving revision 1.16
diff -u -p -r1.16 daemon-server.c
--- daemons/common/daemon-server.c	25 Jan 2012 21:30:27 -0000	1.16
+++ daemons/common/daemon-server.c	30 Jan 2012 16:46:06 -0000
@@ -249,6 +249,7 @@ static void *client_thread(void *baton)
 		if (!read_buffer(b->client.socket_fd, &req.buffer))
 			goto fail;
 
+		// fprintf(stderr, "----------- RECEIVING -----------\n%s---------------------------\n", req.buffer);
 		req.cft = dm_config_from_string(req.buffer);
 		if (!req.cft)
 			fprintf(stderr, "error parsing request:\n %s\n", req.buffer);
@@ -264,6 +265,7 @@ static void *client_thread(void *baton)
 			dm_config_destroy(req.cft);
 		dm_free(req.buffer);
 
+		// fprintf(stderr, "----------- SENDING -----------\n%s---------------------------\n", res.buffer);
 		write_buffer(b->client.socket_fd, res.buffer, strlen(res.buffer));
 
 		free(res.buffer);
Index: daemons/dmeventd/plugins/lvm2/Makefile.in
===================================================================
RCS file: /cvs/lvm2/LVM2/daemons/dmeventd/plugins/lvm2/Makefile.in,v
retrieving revision 1.7
diff -u -p -r1.7 Makefile.in
--- daemons/dmeventd/plugins/lvm2/Makefile.in	24 Sep 2011 21:00:52 -0000	1.7
+++ daemons/dmeventd/plugins/lvm2/Makefile.in	30 Jan 2012 16:46:07 -0000
@@ -24,7 +24,7 @@ LIB_VERSION = $(LIB_VERSION_LVM)
 
 include $(top_builddir)/make.tmpl
 
-LIBS += @LVM2CMD_LIB@ -ldevmapper $(PTHREAD_LIBS)
+LIBS += @LVM2CMD_LIB@ -ldevmapper $(PTHREAD_LIBS) -L$(top_builddir)/daemons/common -ldaemon
 
 install_lvm2: install_lib_shared
 
Index: daemons/dmeventd/plugins/mirror/Makefile.in
===================================================================
RCS file: /cvs/lvm2/LVM2/daemons/dmeventd/plugins/mirror/Makefile.in,v
retrieving revision 1.23
diff -u -p -r1.23 Makefile.in
--- daemons/dmeventd/plugins/mirror/Makefile.in	24 Sep 2011 21:00:52 -0000	1.23
+++ daemons/dmeventd/plugins/mirror/Makefile.in	30 Jan 2012 16:46:07 -0000
@@ -30,7 +30,7 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
 
 include $(top_builddir)/make.tmpl
 
-LIBS += -ldevmapper-event-lvm2 -ldevmapper
+LIBS += -ldevmapper-event-lvm2 -ldevmapper -L$(top_builddir)/daemons/common -ldaemon
 
 install_lvm2: install_dm_plugin
 
Index: daemons/dmeventd/plugins/snapshot/Makefile.in
===================================================================
RCS file: /cvs/lvm2/LVM2/daemons/dmeventd/plugins/snapshot/Makefile.in,v
retrieving revision 1.18
diff -u -p -r1.18 Makefile.in
--- daemons/dmeventd/plugins/snapshot/Makefile.in	24 Sep 2011 21:00:53 -0000	1.18
+++ daemons/dmeventd/plugins/snapshot/Makefile.in	30 Jan 2012 16:46:07 -0000
@@ -26,7 +26,7 @@ LIB_VERSION = $(LIB_VERSION_LVM)
 
 include $(top_builddir)/make.tmpl
 
-LIBS += -ldevmapper-event-lvm2 -ldevmapper
+LIBS += -ldevmapper-event-lvm2 -ldevmapper -L$(top_builddir)/daemons/common -ldaemon
 
 install_lvm2: install_dm_plugin
 
Index: daemons/lvmetad/lvmetad-core.c
===================================================================
RCS file: /cvs/lvm2/LVM2/daemons/lvmetad/lvmetad-core.c,v
retrieving revision 1.31
diff -u -p -r1.31 lvmetad-core.c
--- daemons/lvmetad/lvmetad-core.c	25 Jan 2012 21:42:09 -0000	1.31
+++ daemons/lvmetad/lvmetad-core.c	30 Jan 2012 16:46:07 -0000
@@ -198,6 +198,8 @@ static response vg_lookup(lvmetad_state 
 	metadata = cft->root;
 	res.cft = dm_config_create();
 
+	debug("vg_lookup: FORMAT = %s\n", dm_config_find_str(metadata, "metadata/format", "UNKNOWN"));
+
 	/* The response field */
 	res.cft->root = n = dm_config_create_node(res.cft, "response");
 	n->parent = res.cft->root;
@@ -402,6 +404,63 @@ static response pv_gone(lvmetad_state *s
 		return daemon_reply_simple("failed", "reason = %s", "PVID does not exist", NULL);
 }
 
+static response pv_forget_all(lvmetad_state *s, request r)
+{
+	int found = 0;
+	debug("pv_forget_all\n");
+
+	lock_pvs(s);
+	dm_hash_destroy(s->pvs);
+	s->pvs = dm_hash_create(32);
+	unlock_pvs(s);
+
+	return daemon_reply_simple("OK", NULL);
+}
+
+/* You need to be holding the pvid_map lock already to call this. */
+static response vg_forget_missing(lvmetad_state *s, request r)
+{
+	struct dm_hash_node *n;
+	const char *vgid, *vgid_check;
+	lock_vgs(s);
+	lock_pvs(s);
+
+restart:
+	n = dm_hash_get_first(s->vgs);
+	while (n) {
+		struct dm_config_tree *vg = dm_hash_get_data(s->vgs, n);
+		struct dm_config_node *pv = pvs(vg->root);
+		vgid = dm_config_find_str(vg->root->child, "id", NULL);
+		assert(vgid);
+
+		int missing = 1;
+
+		debug("checking VG %s\n", vgid);
+
+		while (pv) {
+			const char *pvid = dm_config_find_str(pv->child, "id", NULL);
+			vgid_check = dm_hash_lookup(s->pvid_map, pvid);
+			if (dm_hash_lookup(s->pvs, pvid) &&
+			    vgid_check && !strcmp(vgid, vgid_check))
+				missing = 0; /* at least one PV is around */
+			debug("checking PV %s/%s: %s\n", vgid, pvid, vgid_check);
+			pv = pv->sib;
+		}
+
+		n = dm_hash_get_next(s->vgs, n);
+		if (missing) {
+			debug("nuking VG %s\n", vgid);
+			dm_hash_remove(s->vgs, vgid);
+			goto restart; /* kind of tricky */
+		}
+	}
+
+	unlock_pvs(s);
+	unlock_vgs(s);
+
+	return daemon_reply_simple("OK", NULL);
+}
+
 static response pv_found(lvmetad_state *s, request r)
 {
 	struct dm_config_node *metadata = dm_config_find_node(r.cft->root, "metadata");
@@ -501,12 +560,18 @@ static response handler(daemon_state s, 
 	if (!strcmp(rq, "pv_gone"))
 		pv_gone(state, r);
 
+	if (!strcmp(rq, "pv_forget_all"))
+		pv_forget_all(state, r);
+
 	if (!strcmp(rq, "vg_update"))
 		return vg_update(state, r);
 
 	if (!strcmp(rq, "vg_remove"))
 		return vg_remove(state, r);
 
+	if (!strcmp(rq, "vg_forget_missing"))
+		vg_forget_missing(state, r);
+
 	if (!strcmp(rq, "vg_lookup"))
 		return vg_lookup(state, r);
 
Index: include/.symlinks.in
===================================================================
RCS file: /cvs/lvm2/LVM2/include/.symlinks.in,v
retrieving revision 1.8
diff -u -p -r1.8 .symlinks.in
--- include/.symlinks.in	11 Nov 2011 15:11:09 -0000	1.8
+++ include/.symlinks.in	30 Jan 2012 16:46:08 -0000
@@ -4,6 +4,7 @@
 @top_srcdir@/lib/activate/activate.h
 @top_srcdir@/lib/activate/targets.h
 @top_srcdir@/lib/cache/lvmcache.h
+ top_srcdir@/lib/cache/lvmetad.h
 @top_srcdir@/lib/commands/errors.h
 @top_srcdir@/lib/commands/toolcontext.h
 @top_srcdir@/lib/config/config.h
Index: lib/Makefile.in
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/Makefile.in,v
retrieving revision 1.114
diff -u -p -r1.114 Makefile.in
--- lib/Makefile.in	11 Nov 2011 15:11:10 -0000	1.114
+++ lib/Makefile.in	30 Jan 2012 16:46:08 -0000
@@ -16,6 +16,8 @@ srcdir = @srcdir@
 top_srcdir = @top_srcdir@
 top_builddir = @top_builddir@
 
+INCLUDES += -I$(top_srcdir)/daemons/common -I$(top_srcdir)/daemons/lvmetad
+
 ifeq ("@LVM1@", "shared")
   SUBDIRS = format1
 endif
@@ -46,6 +48,7 @@ endif
 
 SOURCES =\
 	activate/activate.c \
+	cache/lvmetad.c \
 	cache/lvmcache.c \
 	commands/toolcontext.c \
 	config/config.c \
Index: lib/cache/lvmcache.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/cache/lvmcache.c,v
retrieving revision 1.121
diff -u -p -r1.121 lvmcache.c
--- lib/cache/lvmcache.c	18 Dec 2011 21:56:03 -0000	1.121
+++ lib/cache/lvmcache.c	30 Jan 2012 16:46:09 -0000
@@ -28,6 +28,9 @@
 #include "format1.h"
 #include "config.h"
 
+#include "lvmetad.h"
+#include "assert.h"
+
 static struct dm_hash_table *_pvid_hash = NULL;
 static struct dm_hash_table *_vgid_hash = NULL;
 static struct dm_hash_table *_vgname_hash = NULL;
@@ -70,6 +73,8 @@ int lvmcache_init(void)
 		_vg_global_lock_held = 0;
 	}
 
+	lvmetad_init();
+
 	return 1;
 }
 
@@ -388,7 +393,8 @@ struct lvmcache_vginfo *vginfo_from_vgna
 	return vginfo;
 }
 
-const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels)
+const struct format_type *fmt_from_vgname(struct cmd_context *cmd,
+					  const char *vgname, const char *vgid, unsigned revalidate_labels)
 {
 	struct lvmcache_vginfo *vginfo;
 	struct lvmcache_info *info;
@@ -397,9 +403,24 @@ const struct format_type *fmt_from_vgnam
 	struct dm_list devs;
 	struct device_list *devl;
 	char vgid_found[ID_LEN + 1] __attribute__((aligned(8)));
+	fprintf(stderr, "fmt_from_vgname(%s, %s)\n", vgname, vgid);
 
-	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
+	if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
+		fprintf(stderr, "fmt_from_vgname not found (%s, %s)\n", vgname, vgid);
+		if (!lvmetad_active())
+			return NULL; /* too bad */
+		/* If we don't have the info but we have lvmetad, we can ask
+		 * there before failing. */
+		struct volume_group *vg = lvmetad_vg_lookup(cmd, vgname, vgid);
+		if (vg) {
+			assert(vg->fid);
+			const struct format_type *fmt = vg->fid->fmt;
+			release_vg(vg);
+			fprintf(stderr, "fmt_from_vgname: LVMETAD (%s, %s): %s\n", vgname, vgid, fmt->name);
+			return fmt; // XXX
+		}
 		return NULL;
+	}
 
 	/*
 	 * If this function is called repeatedly, only the first one needs to revalidate.
@@ -585,6 +606,11 @@ int lvmcache_label_scan(struct cmd_conte
 
 	int r = 0;
 
+	/* TODO: if (_using_lvmetad) return 1; We need to fill in info/vginfo
+	   structures in _lvmetad_fetch before we can skip scanning. */
+
+	fprintf(stderr, "-------- LABEL SCAN %d ---------\n", full_scan);
+
 	/* Avoid recursion when a PVID can't be found! */
 	if (_scanning_in_progress)
 		return 0;
@@ -637,13 +663,28 @@ int lvmcache_label_scan(struct cmd_conte
 	return r;
 }
 
-struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
+struct volume_group *lvmcache_get_vg(struct cmd_context *cmd, const char *vgname,
+				     const char *vgid, unsigned precommitted)
 {
 	struct lvmcache_vginfo *vginfo;
 	struct volume_group *vg = NULL;
 	struct format_instance *fid;
 	struct format_instance_ctx fic;
 
+	fprintf(stderr, "lvmcache_get_vg(%s, %s); lvmetad = %d, precommitted = %d\n", vgname, vgid, lvmetad_active(), precommitted);
+	/*
+	 * We currently do not store precommitted metadata in lvmetad at
+	 * all. This means that any request for precommitted metadata is served
+	 * using the classic scanning mechanics, and read from disk or from
+	 * lvmcache.
+	 */
+	if (lvmetad_active() && !precommitted) {
+		/* Still serve the locally cached VG if available */
+		if (vgid && (vginfo = vginfo_from_vgid(vgid)) && vginfo->vgmetadata && (vg = vginfo->cached_vg))
+			goto out;
+		return lvmetad_vg_lookup(cmd, vgname, vgid);
+	}
+
 	if (!vgid || !(vginfo = vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
 		return NULL;
 
@@ -1281,6 +1322,7 @@ int lvmcache_update_vgname_and_id(struct
 				  const char *vgname, const char *vgid,
 				  uint32_t vgstatus, const char *creation_host)
 {
+	log_error("lvmcache_update_vgname_and_id: %s -> %s", dev_name(info->dev), vgname);
 	if (!vgname && !info->vginfo) {
 		log_error(INTERNAL_ERROR "NULL vgname handed to cache");
 		/* FIXME Remove this */
@@ -1288,6 +1330,10 @@ int lvmcache_update_vgname_and_id(struct
 		vgid = vgname;
 	}
 
+	/* When using lvmetad, the PV could not have become orphaned. */
+	if (lvmetad_active() && is_orphan_vg(vgname) && info->vginfo)
+		return 1;
+
 	/* If PV without mdas is already in a real VG, don't make it orphan */
 	if (is_orphan_vg(vgname) && info->vginfo &&
 	    mdas_empty_or_ignored(&info->mdas) &&
@@ -1316,6 +1362,7 @@ int lvmcache_update_vg(struct volume_gro
 	pvid_s[sizeof(pvid_s) - 1] = '\0';
 
 	dm_list_iterate_items(pvl, &vg->pvs) {
+		log_error("lvmcache_update_vg(%s) at %s", vg->name, dev_name(pvl->pv->dev));
 		strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
 		/* FIXME Could pvl->pv->dev->pvid ever be different? */
 		if ((info = info_from_pvid(pvid_s, 0)) &&
@@ -1346,6 +1393,13 @@ struct lvmcache_info *lvmcache_add(struc
 		return NULL;
 	}
 
+	if (lvmetad_active() && vgid == NULL)
+		/* pvid that's passed to lvmcache_add is in fact struct id, and
+		   is not formatted */
+		lvmetad_pv_found(*(struct id *)pvid);
+
+	log_error("lvmcache_add: %s -> %s", dev_name(dev), vgname);
+
 	strncpy(pvid_s, pvid, sizeof(pvid_s) - 1);
 	pvid_s[sizeof(pvid_s) - 1] = '\0';
 
Index: lib/cache/lvmcache.h
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/cache/lvmcache.h,v
retrieving revision 1.41
diff -u -p -r1.41 lvmcache.h
--- lib/cache/lvmcache.h	30 Aug 2011 14:55:16 -0000	1.41
+++ lib/cache/lvmcache.h	30 Jan 2012 16:46:09 -0000
@@ -95,7 +95,7 @@ void lvmcache_unlock_vgname(const char *
 int lvmcache_verify_lock_order(const char *vgname);
 
 /* Queries */
-const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels);
+const struct format_type *fmt_from_vgname(struct cmd_context *cmd, const char *vgname, const char *vgid, unsigned revalidate_labels);
 /* Decrement and test if there are still vg holders in vginfo. */
 int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
 struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
@@ -126,7 +126,8 @@ struct dm_list *lvmcache_get_pvids(struc
 				const char *vgid);
 
 /* Returns cached volume group metadata. */
-struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
+struct volume_group *lvmcache_get_vg(struct cmd_context *cmd, const char *vgname,
+				     const char *vgid, unsigned precommitted);
 void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
 void lvmcache_commit_metadata(const char *vgname);
 
Index: lib/cache/lvmetad.c
===================================================================
RCS file: lib/cache/lvmetad.c
diff -N lib/cache/lvmetad.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/cache/lvmetad.c	30 Jan 2012 16:46:09 -0000
@@ -0,0 +1,162 @@
+#include "lib.h"
+#include "toolcontext.h"
+#include "metadata.h"
+
+#include "lvmetad.h"
+#include "lvmcache.h"
+#include "lvmetad-client.h"
+
+#include "assert.h"
+
+static int _using_lvmetad = 1;
+static daemon_handle _lvmetad;
+
+void lvmetad_init(void)
+{
+	if (_using_lvmetad) {
+		_lvmetad = lvmetad_open(getenv("LVMETAD_SOCKET"));
+		if (_lvmetad.socket_fd < 0) {
+			log_error("[LVMETAC] Failed to connect.");
+			_using_lvmetad = 0; // HMM.
+		}
+	}
+}
+
+static void _lvmetad_reply(daemon_reply reply) {
+	return;
+	const char *repl = daemon_reply_str(reply, "response", NULL);
+	const char *status = daemon_reply_str(reply, "status", NULL);
+	const char *vgid = daemon_reply_str(reply, "vgid", NULL);
+
+	fprintf(stderr, "--------------------------------\n");
+	fprintf(stderr, "[LVMETAC] REPLY: %s\n", repl);
+	if (!strcmp(repl, "failed"))
+		fprintf(stderr, "[LVMETAC] REASON: %s\n", daemon_reply_str(reply, "reason", "unknown"));
+	if (vgid)
+		fprintf(stderr, "[LVMETAC] VGID: %s\n", vgid);
+	if (status)
+	fprintf(stderr, "[LVMETAC] STATUS: %s\n", status);
+	fprintf(stderr, "%s\n--------------------------------\n", reply.buffer);
+}
+
+struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgname, const char *vgid)
+{
+	struct volume_group *vg = NULL;
+	daemon_reply reply;
+	if (vgid) {
+		char uuid[64];
+		id_write_format((struct id*)vgid, uuid, 64);
+		reply = daemon_send_simple(_lvmetad, "vg_lookup", "uuid = %s", uuid, NULL);
+	} else {
+		assert(vgname);
+		reply = daemon_send_simple(_lvmetad, "vg_lookup", "name = %s", vgname, NULL);
+	}
+
+	_lvmetad_reply(reply);
+
+	if (strcmp(daemon_reply_str(reply, "response", ""), "failed")) {
+
+		struct dm_config_node *top = dm_config_find_node(reply.cft->root, "metadata");
+		const char *name = daemon_reply_str(reply, "name", NULL);
+
+		/* This code is extremely sad. */
+		struct format_type *fmt;
+		struct format_instance *fid;
+		struct format_instance_ctx fic;
+
+		/* fall back to lvm2 if we don't know better */
+		const char *fmt_name = dm_config_find_str(top, "metadata/format", "lvm2");
+		fmt = get_format_by_name(cmd, fmt_name);
+		assert(fmt);
+		assert(!strcmp(fmt->name, fmt_name));
+
+		fic.type = FMT_INSTANCE_VG | FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
+		fic.context.vg_ref.vg_name = name;
+		fic.context.vg_ref.vg_id = vgid;
+
+		fprintf(stderr, "-------- LVMETAD FETCH: instance --------\n");
+		if (!(fid = fmt->ops->create_instance(fmt, &fic)))
+			return_NULL;
+
+		top->key = name;
+		fprintf(stderr, "-------- LVMETAD FETCH: import -----------\n");
+		vg = import_vg_from_config_tree(reply.cft, fid);
+		fprintf(stderr, "-------- LVMETAD FETCH: lvmcache ---------\n");
+		lvmcache_update_vg(vg, 0);
+	}
+
+	daemon_reply_destroy(reply);
+	return vg;
+}
+
+int lvmetad_vg_update(struct volume_group *vg)
+{
+	char *buf = NULL;
+	if (!vg)
+		return 0;
+
+	/* TODO. This is not entirely correct, since export_vg_to_buffer
+	 * adds trailing garbage to the buffer. We may need to use
+	 * export_vg_to_config_tree and format the buffer ourselves. It
+	 * does, however, work for now, since the garbage is well
+	 * formatted and has no conflicting keys with the rest of the
+	 * request.  */
+	export_vg_to_buffer(vg, &buf);
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "vg_update", "vgname = %s", vg->name,
+				             "metadata = %b", strchr(buf, '{'),
+				   NULL);
+	_lvmetad_reply(reply);
+	daemon_reply_destroy(reply);
+	return 1;
+}
+
+int lvmetad_vg_remove(struct volume_group *vg)
+{
+	char uuid[64];
+	id_write_format(&vg->id, uuid, 64);
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "vg_remove", "uuid = %s", uuid, NULL);
+	_lvmetad_reply(reply);
+	daemon_reply_destroy(reply);
+	return 1;
+}
+
+int lvmetad_pv_found(struct id pvid)
+{
+	char uuid[64];
+	id_write_format(&pvid, uuid, 64);
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "pv_found", "uuid = %s", uuid, NULL);
+	_lvmetad_reply(reply);
+	daemon_reply_destroy(reply);
+	return 1;
+}
+
+int lvmetad_pv_forget_all()
+{
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "pv_forget_all", NULL);
+	_lvmetad_reply(reply);
+	daemon_reply_destroy(reply);
+	return 1;
+}
+
+int lvmetad_vg_forget_missing()
+{
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "vg_forget_missing", NULL);
+	_lvmetad_reply(reply);
+	daemon_reply_destroy(reply);
+	return 1;
+}
+
+int lvmetad_active()
+{
+	return _using_lvmetad;
+}
+
+void lvmetad_set_active(int active)
+{
+	_using_lvmetad = active;
+}
Index: lib/cache/lvmetad.h
===================================================================
RCS file: lib/cache/lvmetad.h
diff -N lib/cache/lvmetad.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/cache/lvmetad.h	30 Jan 2012 16:46:10 -0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_METAD_H
+#define _LVM_METAD_H
+
+struct volume_group;
+struct cmd_context;
+struct dm_config_tree;
+
+void lvmetad_init(void);
+void lvmetad_set_active(int);
+int lvmetad_active(void);
+int lvmetad_vg_update(struct volume_group *vg);
+int lvmetad_vg_remove(struct volume_group *vg);
+int lvmetad_pv_found(struct id pvid);
+int lvmetad_pv_forget_all(void);
+int lvmetad_vg_forget_missing(void);
+
+struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgname, const char *vgid);
+
+#endif
Index: lib/format_text/export.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/format_text/export.c,v
retrieving revision 1.86
diff -u -p -r1.86 export.c
--- lib/format_text/export.c	25 Jan 2012 22:35:36 -0000	1.86
+++ lib/format_text/export.c	30 Jan 2012 16:46:10 -0000
@@ -395,6 +395,9 @@ static int _print_vg(struct formatter *f
 
 	outf(f, "seqno = %u", vg->seqno);
 
+	if (vg->fid && vg->fid->fmt)
+		outf(f, "format = \"%s\"", vg->fid->fmt->name);
+
 	if (!_print_flag_config(f, vg->status, VG_FLAGS))
 		return_0;
 
Index: lib/format_text/format-text.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/format_text/format-text.c,v
retrieving revision 1.186
diff -u -p -r1.186 format-text.c
--- lib/format_text/format-text.c	18 Nov 2011 19:31:10 -0000	1.186
+++ lib/format_text/format-text.c	30 Jan 2012 16:46:14 -0000
@@ -1415,15 +1415,17 @@ static int _populate_pv_fields(struct lv
 	struct data_area_list *da;
 
 	/* Have we already cached vgname? */
-	if (!scan_label_only && _get_pv_if_in_vg(info, pv))
+	if (!scan_label_only && _get_pv_if_in_vg(info, pv)) {
 		return 1;
+	}
 
 	/* Perform full scan (just the first time) and try again */
 	if (!scan_label_only && !critical_section() && !full_scan_done()) {
 		lvmcache_label_scan(info->fmt->cmd, 2);
 
-		if (_get_pv_if_in_vg(info, pv))
+		if (_get_pv_if_in_vg(info, pv)) {
 			return 1;
+		}
 	}
 
 	/* Orphan */
Index: lib/format_text/import_vsn1.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/format_text/import_vsn1.c,v
retrieving revision 1.99
diff -u -p -r1.99 import_vsn1.c
--- lib/format_text/import_vsn1.c	25 Jan 2012 21:43:51 -0000	1.99
+++ lib/format_text/import_vsn1.c	30 Jan 2012 16:46:14 -0000
@@ -59,6 +59,8 @@ static int _vsn1_check_version(const str
 	const struct dm_config_node *cn;
 	const struct dm_config_value *cv;
 
+	return 1; // XXX
+
 	/*
 	 * Check the contents field.
 	 */
@@ -705,6 +707,8 @@ static struct volume_group *_read_vg(str
 		goto bad;
 	}
 
+	fprintf(stderr, "_read_vg found seqno %d\n", vg->seqno);
+
 	if (!_read_flag_config(vgn, &vg->status, VG_FLAGS)) {
 		log_error("Error reading flags of volume group %s.",
 			  vg->name);
Index: lib/metadata/metadata.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/metadata/metadata.c,v
retrieving revision 1.475
diff -u -p -r1.475 metadata.c
--- lib/metadata/metadata.c	25 Jan 2012 08:50:10 -0000	1.475
+++ lib/metadata/metadata.c	30 Jan 2012 16:46:19 -0000
@@ -20,6 +20,7 @@
 #include "lvm-string.h"
 #include "lvm-file.h"
 #include "lvmcache.h"
+#include "lvmetad.h"
 #include "memlock.h"
 #include "str_list.h"
 #include "pv_alloc.h"
@@ -261,7 +262,7 @@ int add_pv_to_vg(struct volume_group *vg
 			stack;
 			uuid[0] = '\0';
 		}
-		log_error("Physical volume '%s (%s)' listed more than once.",
+		log_error("Physical volume '%s (%s)' already in the VG.",
 			  pv_name, uuid);
 		return 0;
 	}
@@ -363,6 +364,7 @@ int get_pv_from_vg_by_id(const struct fo
 			 vg_name);
 
 	dm_list_iterate_items(pvl, &vg->pvs) {
+		log_error("checking id equality: %60s vs %60s", (char*)&pvl->pv->id, pvid);
 		if (id_equal(&pvl->pv->id, (const struct id *) pvid)) {
 			if (!_copy_pv(fmt->cmd->mem, pv, pvl->pv)) {
 				log_error("internal PV duplication failed");
@@ -619,6 +621,9 @@ int vg_remove(struct volume_group *vg)
 		}
 	}
 
+	if (!lvmetad_vg_remove(vg))
+		stack;
+
 	if (!backup_remove(vg->cmd, vg->name))
 		stack;
 
@@ -1722,9 +1727,13 @@ static struct pv_list *_find_pv_in_vg(co
 {
 	struct pv_list *pvl;
 
-	dm_list_iterate_items(pvl, &vg->pvs)
-		if (pvl->pv->dev == dev_cache_get(pv_name, vg->cmd->filter))
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		fprintf(stderr, "trying %s\n", dev_name(pvl->pv->dev));
+		if (pvl->pv->dev == dev_cache_get(pv_name, vg->cmd->filter)) {
+			fprintf(stderr, "found %s\n", pv_name);
 			return pvl;
+		}
+	}
 
 	return NULL;
 }
@@ -2585,6 +2594,8 @@ int vg_write(struct volume_group *vg)
 	memlock_unlock(vg->cmd);
 	vg->seqno++;
 
+	fprintf(stderr, "-------- WRITE START: %s (seq %d)---------\n", vg->name, vg->seqno);
+
         dm_list_iterate_items(pv_to_create, &vg->pvs_to_create) {
 		if (!_pvcreate_write(vg->cmd, pv_to_create))
 			return 0;
@@ -2668,6 +2679,7 @@ static int _vg_commit_mdas(struct volume
 		/* Update cache first time we succeed */
 		if (!failed && !cache_updated) {
 			lvmcache_update_vg(vg, 0);
+			lvmetad_vg_update(vg);
 			cache_updated = 1;
 		}
 	}
@@ -2685,6 +2697,7 @@ int vg_commit(struct volume_group *vg)
 		return cache_updated;
 	}
 
+	fprintf(stderr, "-------- COMMIT START: %s (seq %d)---------\n", vg->name, vg->seqno);
 	cache_updated = _vg_commit_mdas(vg);
 
 	if (cache_updated) {
@@ -2702,6 +2715,8 @@ int vg_commit(struct volume_group *vg)
 		log_error("Attempt to drop cached metadata failed "
 			  "after commit for VG %s.", vg->name);
 
+	fprintf(stderr, "-------- COMMIT DONE: %s ---------\n", vg->name);
+
 	/* If at least one mda commit succeeded, it was committed */
 	return cache_updated;
 }
@@ -2893,6 +2908,7 @@ static struct volume_group *_vg_read(str
 	struct pv_list *pvl, *pvl2;
 	struct dm_list all_pvs;
 	char uuid[64] __attribute__((aligned(8)));
+	int seqno = 0;
 
 	if (is_orphan_vg(vgname)) {
 		if (use_precommitted) {
@@ -2904,35 +2920,42 @@ static struct volume_group *_vg_read(str
 		return _vg_read_orphans(cmd, warnings, vgname);
 	}
 
+	fprintf(stderr, "Looking for VG, precommited = %d, *consistent = %d\n", use_precommitted, !*consistent);
 	/*
 	 * If cached metadata was inconsistent and *consistent is set
 	 * then repair it now.  Otherwise just return it.
 	 * Also return if use_precommitted is set due to the FIXME in
 	 * the missing PV logic below.
 	 */
-	if ((correct_vg = lvmcache_get_vg(vgid, precommitted)) &&
+	if ((correct_vg = lvmcache_get_vg(cmd, vgname, vgid, precommitted)) &&
 	    (use_precommitted || !*consistent)) {
 		*consistent = 1;
+		fprintf(stderr, "Found cached VG %s, seqno %d\n", correct_vg->name, correct_vg->seqno);
 		return correct_vg;
 	} else {
+		if (correct_vg && correct_vg->seqno > seqno)
+			seqno = correct_vg->seqno;
 		release_vg(correct_vg);
 		correct_vg = NULL;
 	}
 
+	fprintf(stderr, "About to scan for VG.\n");
 	/* Find the vgname in the cache */
 	/* If it's not there we must do full scan to be completely sure */
-	if (!(fmt = fmt_from_vgname(vgname, vgid, 1))) {
+	if (!(fmt = fmt_from_vgname(cmd, vgname, vgid, 1))) {
 		lvmcache_label_scan(cmd, 0);
-		if (!(fmt = fmt_from_vgname(vgname, vgid, 1))) {
+		if (!(fmt = fmt_from_vgname(cmd, vgname, vgid, 1))) {
 			/* Independent MDAs aren't supported under low memory */
 			if (!cmd->independent_metadata_areas && critical_section())
 				return_NULL;
 			lvmcache_label_scan(cmd, 2);
-			if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
+			if (!(fmt = fmt_from_vgname(cmd, vgname, vgid, 0)))
 				return_NULL;
 		}
 	}
 
+	fprintf(stderr, "VG scan done.\n");
+
 	/* Now determine the correct vgname if none was supplied */
 	if (!vgname && !(vgname = vgname_from_vgid(cmd->mem, vgid)))
 		return_NULL;
@@ -2955,6 +2978,8 @@ static struct volume_group *_vg_read(str
 		return_NULL;
 	}
 
+	fprintf(stderr, "found %d pvids\n", dm_list_size(pvids));
+
 	/*
 	 * We use the fid globally here so prevent the release_vg
 	 * call to destroy the fid - we may want to reuse it!
@@ -2963,6 +2988,7 @@ static struct volume_group *_vg_read(str
 	/* Ensure contents of all metadata areas match - else do recovery */
 	inconsistent_mda_count=0;
 	dm_list_iterate_items(mda, &fid->metadata_areas_in_use) {
+		fprintf(stderr, "checking MDA on %s\n", dev_name(mda_get_device(mda)));
 
 		if ((use_precommitted &&
 		     !(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) ||
@@ -2975,8 +3001,10 @@ static struct volume_group *_vg_read(str
 
 		if (!correct_vg) {
 			correct_vg = vg;
+			fprintf(stderr, "Updating correct_vg: %s, seq %d\n", vg->name, vg->seqno);
 			continue;
-		}
+		} else
+			fprintf(stderr, "Current VG: %s, seq %d\n", vg->name, vg->seqno);
 
 		/* FIXME Also ensure contents same - checksum compare? */
 		if (correct_vg->seqno != vg->seqno) {
@@ -2987,6 +3015,7 @@ static struct volume_group *_vg_read(str
 			else
 				inconsistent = 1;
 
+			fprintf(stderr, "Inconsistent VG: seq %d vs %d\n", vg->seqno, correct_vg->seqno);
 			if (vg->seqno > correct_vg->seqno) {
 				release_vg(correct_vg);
 				correct_vg = vg;
@@ -3001,9 +3030,17 @@ static struct volume_group *_vg_read(str
 	}
 	fid->ref_count--;
 
+	fprintf(stderr, "checking correct_vg (%p)\n", correct_vg);
+
 	/* Ensure every PV in the VG was in the cache */
 	if (correct_vg) {
 		/*
+		 * Update the seqno from the cache, for the benefit of
+		 * retro-style metadata formats like LVM1.
+		 */
+		correct_vg->seqno = seqno > correct_vg->seqno ? seqno : correct_vg->seqno;
+
+		/*
 		 * If the VG has PVs without mdas, or ignored mdas, they may
 		 * still be orphans in the cache: update the cache state here,
 		 * and update the metadata lists in the vg.
@@ -3011,6 +3048,7 @@ static struct volume_group *_vg_read(str
 		if (!inconsistent &&
 		    dm_list_size(&correct_vg->pvs) > dm_list_size(pvids)) {
 			dm_list_iterate_items(pvl, &correct_vg->pvs) {
+				fprintf(stderr, "PV %s is in the VG\n", dev_name(pvl->pv->dev));
 				if (!pvl->pv->dev) {
 					inconsistent_pvs = 1;
 					break;
@@ -3101,6 +3139,8 @@ static struct volume_group *_vg_read(str
 		fid->ref_count--;
 	}
 
+	fprintf(stderr, "correct_vg check done\n");
+
 	dm_list_init(&all_pvs);
 
 	/* Failed to find VG where we expected it - full scan and retry */
@@ -3118,7 +3158,7 @@ static struct volume_group *_vg_read(str
 		if (!cmd->independent_metadata_areas && critical_section())
 			return_NULL;
 		lvmcache_label_scan(cmd, 2);
-		if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
+		if (!(fmt = fmt_from_vgname(cmd, vgname, vgid, 0)))
 			return_NULL;
 
 		if (precommitted && !(fmt->features & FMT_PRECOMMIT))
@@ -3204,12 +3244,16 @@ static struct volume_group *_vg_read(str
 		}
 	}
 
+	fprintf(stderr, "doing lvmcache_update_vg\n");
+
 	/*
 	 * If there is no precommitted metadata, committed metadata
 	 * is read and stored in the cache even if use_precommitted is set
 	 */
 	lvmcache_update_vg(correct_vg, (correct_vg->status & PRECOMMITTED));
 
+	fprintf(stderr, "checking inconsistent\n");
+
 	if (inconsistent) {
 		/* FIXME Test should be if we're *using* precommitted metadata not if we were searching for it */
 		if (use_precommitted) {
@@ -4104,9 +4148,9 @@ uint32_t vg_lock_newname(struct cmd_cont
 
 	/* Find the vgname in the cache */
 	/* If it's not there we must do full scan to be completely sure */
-	if (!fmt_from_vgname(vgname, NULL, 1)) {
+	if (!fmt_from_vgname(cmd, vgname, NULL, 1)) {
 		lvmcache_label_scan(cmd, 0);
-		if (!fmt_from_vgname(vgname, NULL, 1)) {
+		if (!fmt_from_vgname(cmd, vgname, NULL, 1)) {
 			/* Independent MDAs aren't supported under low memory */
 			if (!cmd->independent_metadata_areas && critical_section()) {
 				/*
@@ -4117,7 +4161,7 @@ uint32_t vg_lock_newname(struct cmd_cont
 				return FAILED_LOCKING;
 			}
 			lvmcache_label_scan(cmd, 2);
-			if (!fmt_from_vgname(vgname, NULL, 0)) {
+			if (!fmt_from_vgname(cmd, vgname, NULL, 0)) {
 				/* vgname not found after scanning */
 				return SUCCESS;
 			}
Index: lib/mm/memlock.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/mm/memlock.c,v
retrieving revision 1.49
diff -u -p -r1.49 memlock.c
--- lib/mm/memlock.c	25 Jan 2012 13:12:59 -0000	1.49
+++ lib/mm/memlock.c	30 Jan 2012 16:46:19 -0000
@@ -355,6 +355,7 @@ static void _unlock_mem(struct cmd_conte
 		dm_free(_maps_buffer);
 		_maps_buffer = NULL;
 		if (_mstats < unlock_mstats) {
+#if 0
 			if ((_mstats + lvm_getpagesize()) < unlock_mstats)
 				log_error(INTERNAL_ERROR
 					  "Reserved memory (%ld) not enough: used %ld. Increase activation/reserved_memory?",
@@ -363,6 +364,7 @@ static void _unlock_mem(struct cmd_conte
 				/* FIXME Believed due to incorrect use of yes_no_prompt while locks held */
 				log_debug("Suppressed internal error: Maps lock %ld < unlock %ld, a one-page difference.",
 					  (long)_mstats, (long)unlock_mstats);
+#endif
 		}
 	}
 
Index: test/t-covercmd.sh
===================================================================
RCS file: /cvs/lvm2/LVM2/test/Attic/t-covercmd.sh,v
retrieving revision 1.10
diff -u -p -r1.10 t-covercmd.sh
--- test/t-covercmd.sh	5 Jan 2011 00:16:20 -0000	1.10
+++ test/t-covercmd.sh	30 Jan 2012 16:46:21 -0000
@@ -12,6 +12,12 @@
 # tests basic functionality of read-ahead and ra regressions
 #
 
+## XXXX
+rm -f /var/run/lvm/lvmetad.socket
+chmod a+xr `which lvcreate `
+chmod a+xr /srv/build/lvm2/cvs-lvmetad/default/tools/lvm
+## end XXXX
+
 . lib/test
 
 TEST_UUID="aaaaaa-aaaa-aaaa-aaaa-aaaa-aaaa-aaaaaa"
@@ -31,6 +37,7 @@ pvcreate --metadatacopies 0 $dev2
 pvcreate --metadatacopies 0 $dev3
 pvcreate $dev4
 pvcreate --norestorefile -u $TEST_UUID --metadatacopies 0 $dev5
+
 vgcreate -c n $vg $(cat DEVICES)
 lvcreate -n $lv -l 5 -i5 -I256 $vg
 
Index: test/lib/aux.sh
===================================================================
RCS file: /cvs/lvm2/LVM2/test/lib/aux.sh,v
retrieving revision 1.36
diff -u -p -r1.36 aux.sh
--- test/lib/aux.sh	26 Jan 2012 18:25:46 -0000	1.36
+++ test/lib/aux.sh	30 Jan 2012 16:46:21 -0000
@@ -61,16 +61,23 @@ prepare_dmeventd() {
 }
 
 prepare_lvmetad() {
+	echo preparing lvmetad...
+        which lvmetad
+        echo $abs_builddir
 	# skip if we don't have our own lvmetad...
 	(which lvmetad | grep $abs_builddir) || {
+	echo not found
 		touch SKIP_THIS_TEST
 		exit 1
 	}
 
 	lvmconf "global/lvmetad = 1"
 
-	lvmetad -f "$@" &
+	echo running
+        chmod a+rx `which lvmetad`
+	lvmetad -f "$@" -s $TESTDIR/lvmetad.socket &
 	echo "$!" > LOCAL_LVMETAD
+	echo started as `cat LOCAL_LVMETAD`
 
 	sleep 1
 }
Index: test/lib/test.sh
===================================================================
RCS file: /cvs/lvm2/LVM2/test/lib/test.sh,v
retrieving revision 1.7
diff -u -p -r1.7 test.sh
--- test/lib/test.sh	24 Sep 2011 20:54:36 -0000	1.7
+++ test/lib/test.sh	30 Jan 2012 16:46:21 -0000
@@ -59,6 +59,8 @@ ln -s $abs_top_builddir/test/lib/* $TEST
 set -eE -o pipefail
 aux lvmconf
 aux prepare_clvmd
+aux prepare_lvmetad
+export LVMETAD_SOCKET="$TESTDIR/lvmetad.socket"
 echo "@TESTDIR=$TESTDIR"
 echo "@PREFIX=$PREFIX"
 
Index: test/shell/inconsistent-metadata.sh
===================================================================
RCS file: /cvs/lvm2/LVM2/test/shell/inconsistent-metadata.sh,v
retrieving revision 1.1
diff -u -p -r1.1 inconsistent-metadata.sh
--- test/shell/inconsistent-metadata.sh	21 Nov 2011 00:15:46 -0000	1.1
+++ test/shell/inconsistent-metadata.sh	30 Jan 2012 16:46:21 -0000
@@ -40,29 +40,32 @@ vgscan 2>&1 | tee cmd.out
 not grep "Inconsistent metadata found for VG $vg" cmd.out
 check
 
-# vgdisplay fixes
-init
-vgdisplay 2>&1 | tee cmd.out
-grep "Inconsistent metadata found for VG $vg" cmd.out
-vgdisplay 2>&1 | tee cmd.out
-not grep "Inconsistent metadata found for VG $vg" cmd.out
-check
+# only vgscan would have noticed metadata inconsistencies when lvmetad is active
+if !test -e LOCAL_LVMETAD; then
+	# vgdisplay fixes
+	init
+	vgdisplay 2>&1 | tee cmd.out
+	grep "Inconsistent metadata found for VG $vg" cmd.out
+	vgdisplay 2>&1 | tee cmd.out
+	not grep "Inconsistent metadata found for VG $vg" cmd.out
+	check
 
-# lvs fixes up
-init
-lvs 2>&1 | tee cmd.out
-grep "Inconsistent metadata found for VG $vg" cmd.out
-vgdisplay 2>&1 | tee cmd.out
-not grep "Inconsistent metadata found for VG $vg" cmd.out
-check
+	# lvs fixes up
+	init
+	lvs 2>&1 | tee cmd.out
+	grep "Inconsistent metadata found for VG $vg" cmd.out
+	vgdisplay 2>&1 | tee cmd.out
+	not grep "Inconsistent metadata found for VG $vg" cmd.out
+	check
 
-# vgs fixes up as well
-init
-vgs 2>&1 | tee cmd.out
-grep "Inconsistent metadata found for VG $vg" cmd.out
-vgs 2>&1 | tee cmd.out
-not grep "Inconsistent metadata found for VG $vg" cmd.out
-check
+	# vgs fixes up as well
+	init
+	vgs 2>&1 | tee cmd.out
+	grep "Inconsistent metadata found for VG $vg" cmd.out
+	vgs 2>&1 | tee cmd.out
+	not grep "Inconsistent metadata found for VG $vg" cmd.out
+	check
+fi
 
 echo Check auto-repair of failed vgextend - metadata written to original pv but not new pv
 vgremove -f $vg
Index: test/shell/vgsplit-operation.sh
===================================================================
RCS file: /cvs/lvm2/LVM2/test/shell/vgsplit-operation.sh,v
retrieving revision 1.1
diff -u -p -r1.1 vgsplit-operation.sh
--- test/shell/vgsplit-operation.sh	21 Nov 2011 00:15:47 -0000	1.1
+++ test/shell/vgsplit-operation.sh	30 Jan 2012 16:46:22 -0000
@@ -38,7 +38,7 @@ COMM "vgsplit correctly splits single li
 		   vgcreate $vg2 $dev3 $dev4
 		fi 
 		lvcreate -l 4 -n $lv1 $vg1 $dev1 
-		vgchange -an $vg1 
+		sleep 1; vgchange -an $vg1 
 		if [ $j = PV ]; then
 		  vgsplit $vg1 $vg2 $dev1
 		else
@@ -60,7 +60,7 @@ COMM "vgsplit correctly splits single st
 		   vgcreate $vg2 $dev3 $dev4
 		fi 
 		lvcreate -l 4 -i 2 -n $lv1 $vg1 $dev1 $dev2 
-		vgchange -an $vg1 
+		sleep 1; vgchange -an $vg1 
 		if [ $j = PV ]; then
 		  vgsplit $vg1 $vg2 $dev1 $dev2
 		else
@@ -80,7 +80,7 @@ COMM "vgsplit correctly splits mirror LV
 		  vgcreate -c n $vg2 $dev4
 		fi 
 		lvcreate -l 64 -m1 -n $lv1 $vg1 $dev1 $dev2 $dev3 
-		vgchange -an $vg1 
+		sleep 1; vgchange -an $vg1 
 		if [ $j = PV ]; then
 		  vgsplit $vg1 $vg2 $dev1 $dev2 $dev3
 		else
@@ -104,7 +104,7 @@ COMM "vgsplit correctly splits mirror LV
 		lvcreate -l 64 --mirrorlog mirrored -m1 -n $lv1 $vg1 \
 		    $dev1 $dev2 $dev3 $dev4
 
-		vgchange -an $vg1
+		sleep 1; vgchange -an $vg1
 		if [ $j = PV ]; then
 		  vgsplit $vg1 $vg2 $dev1 $dev2 $dev3 $dev4
 		else
@@ -126,7 +126,8 @@ COMM "vgsplit correctly splits origin an
 		fi 
 		lvcreate -l 64 -i 2 -n $lv1 $vg1 $dev1 $dev2 
 		lvcreate -l 4 -i 2 -s -n $lv2 $vg1/$lv1 
-		vgchange -an $vg1 
+
+		sleep 1; vgchange -an $vg1 
 		if [ $j = PV ]; then
 		  vgsplit $vg1 $vg2 $dev1 $dev2
 		else
@@ -150,7 +151,7 @@ COMM "vgsplit correctly splits linear LV
 		lvcreate -l 4 -i 2 -s -n $lv2 $vg1/$lv1 
 		vgextend $vg1 $dev4 
 		lvcreate -l 64 -n $lv3 $vg1 $dev4 
-		vgchange -an $vg1 
+		sleep 1; vgchange -an $vg1 
 		if [ $j = PV ]; then
 		  vgsplit $vg1 $vg2 $dev4
 		else
@@ -177,7 +178,7 @@ COMM "vgsplit correctly splits linear LV
 		lvcreate -l 64 -m1 -n $lv1 $vg1 $dev1 $dev2 $dev3 
 		vgextend $vg1 $dev4 
 		lvcreate -l 64 -n $lv2 $vg1 $dev4 
-		vgchange -an $vg1 
+		sleep 1; vgchange -an $vg1 
 		vgs
 		lvs 
 		pvs
Index: test/unit/Makefile.in
===================================================================
RCS file: /cvs/lvm2/LVM2/test/unit/Makefile.in,v
retrieving revision 1.7
diff -u -p -r1.7 Makefile.in
--- test/unit/Makefile.in	27 Jan 2012 10:55:02 -0000	1.7
+++ test/unit/Makefile.in	30 Jan 2012 16:46:22 -0000
@@ -25,7 +25,7 @@ ifeq ("$(TESTING)", "yes")
 LDLIBS += -ldevmapper @CUNIT_LIBS@
 CFLAGS += @CUNIT_CFLAGS@
 
-all: unit
+check: unit
 
 unit: $(TARGETS)
 	@echo Running unit tests
Index: test/unit/run.c
===================================================================
RCS file: /cvs/lvm2/LVM2/test/unit/run.c,v
retrieving revision 1.3
diff -u -p -r1.3 run.c
--- test/unit/run.c	13 Dec 2011 12:08:42 -0000	1.3
+++ test/unit/run.c	30 Jan 2012 16:46:22 -0000
@@ -1,3 +1,4 @@
+#if 0
 #include <CUnit/CUnit.h>
 #include <CUnit/Basic.h>
 
@@ -18,10 +19,14 @@ CU_SuiteInfo suites[] = {
 	CU_SUITE_INFO_NULL
 };
 
+#endif
 int main(int argc, char **argv) {
+#if 0
 	CU_initialize_registry();
 	CU_register_suites(suites);
 	CU_basic_set_mode(CU_BRM_VERBOSE);
 	CU_basic_run_tests();
 	return CU_get_number_of_failures() != 0;
+#endif
+        return 1;
 }
Index: tools/pvchange.c
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/pvchange.c,v
retrieving revision 1.93
diff -u -p -r1.93 pvchange.c
--- tools/pvchange.c	30 Aug 2011 14:55:19 -0000	1.93
+++ tools/pvchange.c	30 Jan 2012 16:46:22 -0000
@@ -32,6 +32,9 @@ static int _pvchange_single(struct cmd_c
 	int tagargs = 0;
 	int mda_ignore = 0;
 
+	if (!is_orphan(pv))
+		log_print("About to update physical volume \"%s\" in VG %s, seqno %d", pv_name, vg->name, vg->seqno);
+
 	tagargs = arg_count(cmd, addtag_ARG) + arg_count(cmd, deltag_ARG);
 
 	if (arg_count(cmd, allocatable_ARG))
@@ -156,6 +159,7 @@ static int _pvchange_single(struct cmd_c
 
 	log_verbose("Updating physical volume \"%s\"", pv_name);
 	if (!is_orphan(pv)) {
+		log_print("Updating physical volume \"%s\" in VG %s, seqno %d", pv_name, vg->name, vg->seqno);
 		if (!vg_write(vg) || !vg_commit(vg)) {
 			log_error("Failed to store physical volume \"%s\" in "
 				  "volume group \"%s\"", pv_name, vg->name);
@@ -217,6 +221,7 @@ int pvchange(struct cmd_context *cmd, in
 				continue;
 			}
 			vg = vg_read_for_update(cmd, vg_name, NULL, 0);
+			log_print("Loaded VG %s, seqno %d", vg->name, vg->seqno);
 			if (vg_read_error(vg)) {
 				release_vg(vg);
 				stack;
Index: tools/pvremove.c
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/pvremove.c,v
retrieving revision 1.36
diff -u -p -r1.36 pvremove.c
--- tools/pvremove.c	30 Aug 2011 14:55:19 -0000	1.36
+++ tools/pvremove.c	30 Jan 2012 16:46:22 -0000
@@ -60,6 +60,7 @@ static int pvremove_check(struct cmd_con
 
 	/* orphan ? */
 	if (is_orphan(pv)) {
+		log_error("PV %s is an orphan: vgname = %s.", name, pv->vg_name);
 		free_pv_fid(pv);
 		return 1;
 	}
Index: tools/pvscan.c
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/pvscan.c,v
retrieving revision 1.53
diff -u -p -r1.53 pvscan.c
--- tools/pvscan.c	11 Mar 2011 14:56:56 -0000	1.53
+++ tools/pvscan.c	30 Jan 2012 16:46:24 -0000
@@ -14,6 +14,7 @@
  */
 
 #include "tools.h"
+#include "lvmetad.h"
 
 int pv_max_name_len = 0;
 int vg_max_name_len = 0;
@@ -183,11 +184,18 @@ int pvscan(struct cmd_context *cmd, int 
 	pv_max_name_len += 2;
 	vg_max_name_len += 2;
 
+	lvmetad_pv_forget_all();
+
 	dm_list_iterate_items(pvl, pvslist) {
-	    _pvscan_display_single(cmd, pvl->pv, NULL);
-	    free_pv_fid(pvl->pv);
+
+		lvmetad_pv_found(pvl->pv->id);
+
+		_pvscan_display_single(cmd, pvl->pv, NULL);
+		free_pv_fid(pvl->pv);
 	}
 
+	lvmetad_vg_forget_missing();
+
 	if (!pvs_found) {
 		log_print("No matching physical volumes found");
 		unlock_vg(cmd, VG_GLOBAL);
Index: tools/vgck.c
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/vgck.c,v
retrieving revision 1.27
diff -u -p -r1.27 vgck.c
--- tools/vgck.c	27 Jul 2010 20:05:29 -0000	1.27
+++ tools/vgck.c	30 Jan 2012 16:46:24 -0000
@@ -15,8 +15,9 @@
 
 #include "tools.h"
 #include "metadata.h"
+#include "lvmetad.h"
 
-static int vgck_single(struct cmd_context *cmd __attribute__((unused)),
+static int vgck_single(struct cmd_context *cmd,
 		       const char *vg_name,
 		       struct volume_group *vg,
 		       void *handle __attribute__((unused)))
@@ -37,11 +38,27 @@ static int vgck_single(struct cmd_contex
 		return ECMD_FAILED;
 	}
 
+	/* if (lvmetad_active()) {
+		lvmetad_set_active(0);
+		int consistent = 1;
+		char vgid[100];
+		memset(vgid, 100, 0);
+		memcpy(vgid, &vg->id, sizeof(vg->id));
+		lvmcache_unlock_vgname(vg_name); // ick
+		lvmcache_destroy(cmd, 0);
+		lvmcache_lock_vgname(vg_name, 1); // ick
+		struct volume_group *vg_disk = vg_read_internal(cmd, vg_name, vgid, 0, &consistent);
+		// Kind of OK.
+		release_vg(vg_disk);
+		lvmetad_set_active(1);
+		} */
+
 	return ECMD_PROCESSED;
 }
 
 int vgck(struct cmd_context *cmd, int argc, char **argv)
 {
+	lvmetad_set_active(0);
 	return process_each_vg(cmd, argc, argv, 0, NULL,
 			       &vgck_single);
 }
Index: tools/vgmerge.c
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/vgmerge.c,v
retrieving revision 1.74
diff -u -p -r1.74 vgmerge.c
--- tools/vgmerge.c	10 Aug 2011 20:25:31 -0000	1.74
+++ tools/vgmerge.c	30 Jan 2012 16:46:24 -0000
@@ -14,6 +14,7 @@
  */
 
 #include "tools.h"
+#include "lvmetad.h"
 
 static struct volume_group *_vgmerge_vg_read(struct cmd_context *cmd,
 					     const char *vg_name)
@@ -144,6 +145,8 @@ static int _vgmerge_single(struct cmd_co
 	if (!vg_write(vg_to) || !vg_commit(vg_to))
 		goto_bad;
 
+	lvmetad_vg_remove(vg_from);
+
 	/* FIXME Remove /dev/vgfrom */
 
 	backup(vg_to);
Index: tools/vgscan.c
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/vgscan.c,v
retrieving revision 1.38
diff -u -p -r1.38 vgscan.c
--- tools/vgscan.c	9 Jul 2010 15:34:48 -0000	1.38
+++ tools/vgscan.c	30 Jan 2012 16:46:24 -0000
@@ -14,6 +14,7 @@
  */
 
 #include "tools.h"
+#include "lvmetad.h"
 
 static int vgscan_single(struct cmd_context *cmd, const char *vg_name,
 			 struct volume_group *vg,
@@ -24,13 +25,14 @@ static int vgscan_single(struct cmd_cont
 		  vg->fid->fmt->name);
 
 	check_current_backup(vg);
+	lvmetad_vg_update(vg); /* keep lvmetad up to date */
 
 	return ECMD_PROCESSED;
 }
 
 int vgscan(struct cmd_context *cmd, int argc, char **argv)
 {
-	int maxret, ret;
+	int maxret, ret, lvmetad;
 
 	if (argc) {
 		log_error("Too many parameters on command line");
@@ -44,6 +46,8 @@ int vgscan(struct cmd_context *cmd, int 
 
 	persistent_filter_wipe(cmd->filter);
 	lvmcache_destroy(cmd, 1);
+	lvmetad = lvmetad_active();
+	lvmetad_set_active(0); /* do not rely on lvmetad info */
 
 	log_print("Reading all physical volumes.  This may take a while...");
 
@@ -56,6 +60,7 @@ int vgscan(struct cmd_context *cmd, int 
 			maxret = ret;
 	}
 
+	lvmetad_set_active(lvmetad); /* restore */
 	unlock_vg(cmd, VG_GLOBAL);
 	return maxret;
 }
Index: tools/vgsplit.c
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/vgsplit.c,v
retrieving revision 1.110
diff -u -p -r1.110 vgsplit.c
--- tools/vgsplit.c	6 Oct 2011 14:17:45 -0000	1.110
+++ tools/vgsplit.c	30 Jan 2012 16:46:24 -0000
@@ -14,6 +14,7 @@
  */
 
 #include "tools.h"
+#include "lvmetad.h"
 
 /* FIXME Why not (lv->vg == vg) ? */
 static int _lv_is_in_vg(struct volume_group *vg, struct logical_volume *lv)
@@ -470,7 +471,8 @@ int vgsplit(struct cmd_context *cmd, int
 			goto_bad;
 
 		backup(vg_from);
-	}
+	} else
+		lvmetad_vg_remove(vg_from);
 
 	/*
 	 * Finally, remove the EXPORTED flag from the new VG and write it out.
-- 
id' Ash = Ash; id' Dust = Dust; id' _ = undefined

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