public inbox for lvm2-cvs@sourceware.org
help / color / mirror / Atom feed
From: mornfall@sourceware.org
To: lvm-devel@redhat.com, lvm2-cvs@sourceware.org
Subject: LVM2 daemons/dmeventd/plugins/lvm2/Makefile.in ...
Date: Thu, 23 Feb 2012 13:11:00 -0000	[thread overview]
Message-ID: <20120223131117.27092.qmail@sourceware.org> (raw)

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mornfall@sourceware.org	2012-02-23 13:11:11

Modified files:
	daemons/dmeventd/plugins/lvm2: Makefile.in 
	daemons/dmeventd/plugins/mirror: Makefile.in 
	daemons/dmeventd/plugins/snapshot: Makefile.in 
	daemons/lvmetad: lvmetad-client.h 
	lib            : Makefile.in 
	lib/activate   : activate.c 
	lib/cache      : lvmcache.c lvmcache.h 
	lib/commands   : toolcontext.c 
	lib/device     : dev-cache.c dev-cache.h dev-io.c 
	lib/format1    : format1.c 
	lib/format_pool: format_pool.c 
	lib/format_text: export.c format-text.c import_vsn1.c 
	                 text_label.c 
	lib/label      : label.c label.h 
	lib/metadata   : metadata-exported.h metadata.c metadata.h 
	tools          : Makefile.in args.h commands.h pvcreate.c 
	                 pvremove.c pvscan.c toollib.c tools.h 
	                 vgcfgrestore.c vgcreate.c vgrename.c vgscan.c 
	doc            : example.conf.in 
	scripts        : vgimportclone.sh 
	test/lib       : aux.sh 
	test/shell     : inconsistent-metadata.sh lvconvert-mirror.sh 
	                 lvcreate-repair.sh lvmcache-exercise.sh 
	                 pool-labels.sh vgimportclone.sh 
	test/unit      : Makefile.in 
Added files:
	lib/cache      : lvmetad.c lvmetad.h 

Log message:
	The lvmetad client-side integration. Only active when use_lvmetad = 1 is set in
	lvm.conf *and* lvmetad is running.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/lvm2/Makefile.in.diff?cvsroot=lvm2&r1=1.7&r2=1.8
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/mirror/Makefile.in.diff?cvsroot=lvm2&r1=1.23&r2=1.24
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/snapshot/Makefile.in.diff?cvsroot=lvm2&r1=1.18&r2=1.19
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/lvmetad/lvmetad-client.h.diff?cvsroot=lvm2&r1=1.6&r2=1.7
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/Makefile.in.diff?cvsroot=lvm2&r1=1.114&r2=1.115
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/activate.c.diff?cvsroot=lvm2&r1=1.241&r2=1.242
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmetad.c.diff?cvsroot=lvm2&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmetad.h.diff?cvsroot=lvm2&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.c.diff?cvsroot=lvm2&r1=1.126&r2=1.127
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.h.diff?cvsroot=lvm2&r1=1.42&r2=1.43
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/commands/toolcontext.c.diff?cvsroot=lvm2&r1=1.150&r2=1.151
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/device/dev-cache.c.diff?cvsroot=lvm2&r1=1.71&r2=1.72
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/device/dev-cache.h.diff?cvsroot=lvm2&r1=1.14&r2=1.15
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/device/dev-io.c.diff?cvsroot=lvm2&r1=1.81&r2=1.82
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format1/format1.c.diff?cvsroot=lvm2&r1=1.147&r2=1.148
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_pool/format_pool.c.diff?cvsroot=lvm2&r1=1.52&r2=1.53
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/export.c.diff?cvsroot=lvm2&r1=1.86&r2=1.87
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/format-text.c.diff?cvsroot=lvm2&r1=1.193&r2=1.194
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/import_vsn1.c.diff?cvsroot=lvm2&r1=1.100&r2=1.101
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/text_label.c.diff?cvsroot=lvm2&r1=1.41&r2=1.42
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/label/label.c.diff?cvsroot=lvm2&r1=1.56&r2=1.57
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/label/label.h.diff?cvsroot=lvm2&r1=1.20&r2=1.21
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.231&r2=1.232
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.485&r2=1.486
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.h.diff?cvsroot=lvm2&r1=1.266&r2=1.267
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/Makefile.in.diff?cvsroot=lvm2&r1=1.124&r2=1.125
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/args.h.diff?cvsroot=lvm2&r1=1.86&r2=1.87
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/commands.h.diff?cvsroot=lvm2&r1=1.167&r2=1.168
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvcreate.c.diff?cvsroot=lvm2&r1=1.98&r2=1.99
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvremove.c.diff?cvsroot=lvm2&r1=1.36&r2=1.37
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvscan.c.diff?cvsroot=lvm2&r1=1.53&r2=1.54
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/toollib.c.diff?cvsroot=lvm2&r1=1.241&r2=1.242
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/tools.h.diff?cvsroot=lvm2&r1=1.78&r2=1.79
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgcfgrestore.c.diff?cvsroot=lvm2&r1=1.25&r2=1.26
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgcreate.c.diff?cvsroot=lvm2&r1=1.84&r2=1.85
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgrename.c.diff?cvsroot=lvm2&r1=1.77&r2=1.78
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgscan.c.diff?cvsroot=lvm2&r1=1.38&r2=1.39
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/doc/example.conf.in.diff?cvsroot=lvm2&r1=1.43&r2=1.44
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/scripts/vgimportclone.sh.diff?cvsroot=lvm2&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/aux.sh.diff?cvsroot=lvm2&r1=1.37&r2=1.38
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/shell/inconsistent-metadata.sh.diff?cvsroot=lvm2&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/shell/lvconvert-mirror.sh.diff?cvsroot=lvm2&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/shell/lvcreate-repair.sh.diff?cvsroot=lvm2&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/shell/lvmcache-exercise.sh.diff?cvsroot=lvm2&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/shell/pool-labels.sh.diff?cvsroot=lvm2&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/shell/vgimportclone.sh.diff?cvsroot=lvm2&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/unit/Makefile.in.diff?cvsroot=lvm2&r1=1.7&r2=1.8

--- LVM2/daemons/dmeventd/plugins/lvm2/Makefile.in	2011/09/24 21:00:52	1.7
+++ LVM2/daemons/dmeventd/plugins/lvm2/Makefile.in	2012/02/23 13:11:07	1.8
@@ -24,7 +24,7 @@
 
 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
 
--- LVM2/daemons/dmeventd/plugins/mirror/Makefile.in	2011/09/24 21:00:52	1.23
+++ LVM2/daemons/dmeventd/plugins/mirror/Makefile.in	2012/02/23 13:11:07	1.24
@@ -30,7 +30,7 @@
 
 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
 
--- LVM2/daemons/dmeventd/plugins/snapshot/Makefile.in	2011/09/24 21:00:53	1.18
+++ LVM2/daemons/dmeventd/plugins/snapshot/Makefile.in	2012/02/23 13:11:08	1.19
@@ -26,7 +26,7 @@
 
 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
 
--- LVM2/daemons/lvmetad/lvmetad-client.h	2012/02/23 11:40:24	1.6
+++ LVM2/daemons/lvmetad/lvmetad-client.h	2012/02/23 13:11:08	1.7
@@ -64,11 +64,10 @@
 
 static inline daemon_handle lvmetad_open(const char *socket)
 {
-	/* TODO configurable */
 	daemon_info lvmetad_info = {
 		.path = "lvmetad",
 		.socket = socket ?: DEFAULT_RUN_DIR "/lvmetad.socket",
-		.autostart = 1
+		.autostart = 0
 	};
 
 	return daemon_open(lvmetad_info);
--- LVM2/lib/Makefile.in	2011/11/11 15:11:10	1.114
+++ LVM2/lib/Makefile.in	2012/02/23 13:11:08	1.115
@@ -16,6 +16,8 @@
 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 @@
 
 SOURCES =\
 	activate/activate.c \
+	cache/lvmetad.c \
 	cache/lvmcache.c \
 	commands/toolcontext.c \
 	config/config.c \
--- LVM2/lib/activate/activate.c	2012/01/25 22:16:04	1.241
+++ LVM2/lib/activate/activate.c	2012/02/23 13:11:08	1.242
@@ -1883,7 +1883,7 @@
 int pv_uses_vg(struct physical_volume *pv,
 	       struct volume_group *vg)
 {
-	if (!activation())
+	if (!activation() || !pv->dev)
 		return 0;
 
 	if (!dm_is_dm_major(MAJOR(pv->dev->dev)))
/cvs/lvm2/LVM2/lib/cache/lvmetad.c,v  -->  standard output
revision 1.1
--- LVM2/lib/cache/lvmetad.c
+++ -	2012-02-23 13:11:12.722985000 +0000
@@ -0,0 +1,633 @@
+#include "lib.h"
+#include "toolcontext.h"
+#include "metadata.h"
+#include "device.h"
+#include "lvmetad.h"
+#include "lvmcache.h"
+#include "lvmetad-client.h"
+#include "format-text.h" // TODO for disk_locn, used as a DA representation
+#include "filter.h"
+
+static int _using_lvmetad = 0;
+static daemon_handle _lvmetad;
+
+void lvmetad_init(void)
+{
+	const char *socket = getenv("LVM_LVMETAD_SOCKET");
+	if (_using_lvmetad) { /* configured by the toolcontext */
+		_lvmetad = lvmetad_open(socket ?: DEFAULT_RUN_DIR "/lvmetad.socket");
+		if (_lvmetad.socket_fd < 0) {
+			log_warn("Failed to connect to lvmetad. Falling back to scanning.");
+			_using_lvmetad = 0;
+		}
+	}
+}
+
+/*
+ * Helper; evaluate the reply from lvmetad, check for errors, print diagnostics
+ * and return a summary success/failure exit code. Frees up the reply resources
+ * as well.
+ */
+static int _lvmetad_handle_reply(daemon_reply reply, const char *action, const char *object) {
+	if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
+		log_error("Request to %s %s in lvmetad has failed. Reason: %s",
+			  action, object, reply.error ? strerror(reply.error) :
+			  daemon_reply_str(reply, "reason", "Unknown."));
+		daemon_reply_destroy(reply);
+		return 0;
+	}
+
+	daemon_reply_destroy(reply);
+	return 1;
+}
+
+static int _read_mda(struct lvmcache_info *info,
+		     struct format_type *fmt,
+		     const struct dm_config_node *cn)
+{
+	struct metadata_area_ops *ops;
+	struct metadata_area *mda = NULL;
+	dm_list_iterate_items(ops, &fmt->mda_ops) {
+		if (ops->mda_import_text && ops->mda_import_text(info, cn))
+			return 1;
+	}
+	return 0;
+}
+
+static struct lvmcache_info *_pv_populate_lvmcache(
+	struct cmd_context *cmd, struct dm_config_node *cn, dev_t fallback)
+{
+	const char *pvid_txt = dm_config_find_str(cn->child, "id", NULL),
+		   *vgid_txt = dm_config_find_str(cn->child, "vgid", NULL),
+		   *vgname = dm_config_find_str(cn->child, "vgname", NULL),
+		   *fmt_name = dm_config_find_str(cn->child, "format", NULL);
+	dev_t devt = dm_config_find_int(cn->child, "device", 0);
+	uint64_t devsize = dm_config_find_int(cn->child, "dev_size", 0),
+		 label_sector = dm_config_find_int(cn->child, "label_sector", 0);
+
+	struct format_type *fmt = fmt_name ? get_format_by_name(cmd, fmt_name) : NULL;
+
+	if (!fmt) {
+		log_warn("No format for PV %s. It is probably missing.", pvid_txt);
+		return_NULL;
+	}
+
+	struct device *device = dev_cache_get_by_devt(devt, cmd->filter);
+	struct id pvid, vgid;
+
+	if (!device && fallback)
+		device = dev_cache_get_by_devt(fallback, cmd->filter);
+
+	if (!device) {
+		log_warn("No device for PV %s.", pvid_txt);
+		return_NULL;
+	}
+
+	if (!pvid_txt || !id_read_format(&pvid, pvid_txt)) {
+		log_warn("Missing or ill-formatted PVID for PV: %s.", pvid_txt);
+		return_NULL;
+	}
+
+	if (vgid_txt)
+		id_read_format(&vgid, vgid_txt);
+	else
+		strcpy((char*)&vgid, fmt->orphan_vg_name);
+
+	if (!vgname)
+		vgname = fmt->orphan_vg_name;
+
+	struct lvmcache_info *info =
+		lvmcache_add(fmt->labeller, (const char *)&pvid, device,
+			     vgname, (const char *)&vgid, 0);
+
+	lvmcache_get_label(info)->sector = label_sector;
+	lvmcache_set_device_size(info, devsize);
+	lvmcache_del_das(info);
+	lvmcache_del_mdas(info);
+
+	int i = 0;
+	struct dm_config_node *mda = NULL;
+	do {
+		char mda_id[32];
+		sprintf(mda_id, "mda%d", i);
+		mda = dm_config_find_node(cn->child, mda_id);
+		if (mda)
+			_read_mda(info, fmt, mda);
+		++i;
+	} while (mda);
+
+	i = 0;
+	struct dm_config_node *da = NULL;
+	do {
+		char da_id[32];
+		sprintf(da_id, "da%d", i);
+		da = dm_config_find_node(cn->child, da_id);
+		if (da) {
+			uint64_t offset, size;
+			if (!dm_config_get_uint64(da->child, "offset", &offset)) return_0;
+			if (!dm_config_get_uint64(da->child, "size", &size)) return_0;
+			lvmcache_add_da(info, offset, size);
+		}
+		++i;
+	} while (da);
+
+	return info;
+}
+
+struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgname, const char *vgid)
+{
+	if (!_using_lvmetad)
+		return NULL;
+
+	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 {
+		if (!vgname)
+			log_error(INTERNAL_ERROR "VG name required (VGID not available)");
+		reply = daemon_send_simple(_lvmetad, "vg_lookup", "name = %s", vgname, NULL);
+	}
+
+	if (!strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
+
+		struct dm_config_node *top = dm_config_find_node(reply.cft->root, "metadata");
+		const char *name = daemon_reply_str(reply, "name", NULL);
+
+		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");
+		struct format_type *fmt = get_format_by_name(cmd, fmt_name);
+		if (!fmt) {
+			log_error(INTERNAL_ERROR
+				  "We do not know the format (%s) reported by lvmetad.",
+				  fmt_name);
+			return NULL;
+		}
+
+		fic.type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
+		fic.context.vg_ref.vg_name = name;
+		fic.context.vg_ref.vg_id = vgid;
+
+		if (!(fid = fmt->ops->create_instance(fmt, &fic)))
+			return_NULL;
+
+		struct dm_config_node *pvcn =
+			dm_config_find_node(top, "metadata/physical_volumes")->child;
+		while (pvcn) {
+			_pv_populate_lvmcache(cmd, pvcn, 0);
+			pvcn = pvcn->sib;
+		}
+
+		top->key = name;
+		vg = import_vg_from_config_tree(reply.cft, fid);
+
+		struct pv_list *pvl;
+		dm_list_iterate_items(pvl, &vg->pvs) {
+			struct lvmcache_info *info =
+				lvmcache_info_from_pvid((const char *)&pvl->pv->id, 0);
+			if (info) {
+				pvl->pv->label_sector = lvmcache_get_label(info)->sector;
+				pvl->pv->dev = lvmcache_device(info);
+				lvmcache_fid_add_mdas_pv(info, fid);
+			} /* else probably missing */
+		}
+
+		lvmcache_update_vg(vg, 0);
+	}
+
+	daemon_reply_destroy(reply);
+	return vg;
+}
+
+struct _fixup_baton {
+	int i;
+	int find;
+	int ignore;
+};
+
+static int _fixup_ignored(struct metadata_area *mda, void *baton) {
+	struct _fixup_baton *b = baton;
+	if (b->i == b->find)
+		mda_set_ignored(mda, b->ignore);
+	b->i ++;
+	return 1;
+}
+
+int lvmetad_vg_update(struct volume_group *vg)
+{
+	char *buf = NULL;
+	if (!vg)
+		return 0;
+	if (!_using_lvmetad)
+		return 1; /* fake it */
+
+	/* TODO. This is not entirely correct, since export_vg_to_buffer
+	 * adds trailing nodes 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.  */
+	if (!export_vg_to_buffer(vg, &buf)) {
+		log_error("Could not format VG metadata.");
+		return_0;
+	}
+
+	daemon_reply reply;
+
+	reply = daemon_send_simple(_lvmetad, "vg_update", "vgname = %s", vg->name,
+				             "metadata = %b", strchr(buf, '{'),
+				   NULL);
+
+	if (!_lvmetad_handle_reply(reply, "update VG", vg->name))
+		return 0;
+
+	struct dm_hash_node *n = (vg->fid && vg->fid->metadata_areas_index) ?
+		dm_hash_get_first(vg->fid->metadata_areas_index) : NULL;
+	while (n) {
+		struct metadata_area *mda = dm_hash_get_data(vg->fid->metadata_areas_index, n);
+		char mda_id[128], *num;
+		strcpy(mda_id, dm_hash_get_key(vg->fid->metadata_areas_index, n));
+		if ((num = strchr(mda_id, '_'))) {
+			*num = 0;
+			++num;
+			struct lvmcache_info *info =
+				lvmcache_info_from_pvid(mda_id, 0);
+			struct _fixup_baton baton = { .i = 0, .find = atoi(num),
+						      .ignore = mda_is_ignored(mda) };
+			if (info)
+				lvmcache_foreach_mda(info, _fixup_ignored, &baton);
+		}
+		n = dm_hash_get_next(vg->fid->metadata_areas_index, n);
+	}
+
+	struct pv_list *pvl;
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		/* NB. the PV fmt pointer is sometimes wrong during vgconvert */
+		if (pvl->pv->dev && !lvmetad_pv_found(pvl->pv->id, pvl->pv->dev,
+						      vg->fid ? vg->fid->fmt : pvl->pv->fmt,
+						      pvl->pv->label_sector, NULL))
+			return 0;
+	}
+
+	return 1;
+}
+
+int lvmetad_vg_remove(struct volume_group *vg)
+{
+	if (!_using_lvmetad)
+		return 1; /* just fake it */
+	char uuid[64];
+	id_write_format(&vg->id, uuid, 64);
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "vg_remove", "uuid = %s", uuid, NULL);
+
+	return _lvmetad_handle_reply(reply, "remove VG", vg->name);
+}
+
+int lvmetad_pv_lookup(struct cmd_context *cmd, struct id pvid)
+{
+	if (!_using_lvmetad)
+		return_0;
+
+	int result = 1;
+	char uuid[64];
+	id_write_format(&pvid, uuid, 64);
+
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "pv_lookup", "uuid = %s", uuid, NULL);
+
+	if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
+		_lvmetad_handle_reply(reply, "lookup PVs", "");
+		return_0;
+	}
+
+	struct dm_config_node *cn = dm_config_find_node(reply.cft->root, "physical_volume");
+	if (!_pv_populate_lvmcache(cmd, cn, 0))
+		result = 0;
+
+	daemon_reply_destroy(reply);
+	return result;
+}
+
+int lvmetad_pv_lookup_by_devt(struct cmd_context *cmd, dev_t device)
+{
+	if (!_using_lvmetad)
+		return_0;
+
+	int result = 1;
+
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "pv_lookup", "device = %d", device, NULL);
+
+	if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
+		_lvmetad_handle_reply(reply, "lookup PVs", "");
+		return_0;
+	}
+
+	struct dm_config_node *cn = dm_config_find_node(reply.cft->root, "physical_volume");
+	if (!_pv_populate_lvmcache(cmd, cn, device))
+		result = 0;
+
+	daemon_reply_destroy(reply);
+	return result;
+}
+
+int lvmetad_pv_list_to_lvmcache(struct cmd_context *cmd)
+{
+	if (!_using_lvmetad)
+		return_0;
+
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "pv_list", NULL);
+
+	if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
+		_lvmetad_handle_reply(reply, "list PVs", "");
+		return_0;
+	}
+
+	struct dm_config_node *cn = dm_config_find_node(reply.cft->root, "physical_volumes")->child;
+	while (cn) {
+		_pv_populate_lvmcache(cmd, cn, 0);
+		cn = cn->sib;
+	}
+
+	daemon_reply_destroy(reply);
+	return 1;
+}
+
+int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd)
+{
+	if (!_using_lvmetad)
+		return_0;
+
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "vg_list", NULL);
+
+	if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
+		_lvmetad_handle_reply(reply, "list VGs", "");
+		return_0;
+	}
+
+	struct dm_config_node *cn = dm_config_find_node(reply.cft->root, "volume_groups")->child;
+	while (cn) {
+		struct id vgid;
+		const char *vgid_txt = cn->key,
+			   *name = dm_config_find_str(cn->child, "name", NULL);
+		id_read_format(&vgid, vgid_txt);
+
+		cn = cn->sib;
+
+		/* the call to lvmetad_vg_lookup will poke the VG into lvmcache */
+		struct volume_group *tmp = lvmetad_vg_lookup(cmd, NULL, (const char*)&vgid);
+		release_vg(tmp);
+	}
+
+	daemon_reply_destroy(reply);
+	return 1;
+}
+
+struct _print_mda_baton {
+	int i;
+	char *buffer;
+};
+
+static int _print_mda(struct metadata_area *mda, void *baton)
+{
+	int result = 0;
+	struct _print_mda_baton *b = baton;
+
+	if (!mda->ops->mda_export_text) /* do nothing */
+		return 1;
+
+	char *buf = b->buffer;
+	char *mda_txt = mda->ops->mda_export_text(mda);
+	if (!dm_asprintf(&b->buffer, "%s mda%i { %s }", b->buffer ?: "", b->i, mda_txt))
+		goto_out;
+	b->i ++;
+	result = 1;
+out:
+	dm_free(mda_txt);
+	dm_free(buf);
+	return result;
+}
+
+static int _print_da(struct disk_locn *da, void *baton)
+{
+	if (!da)
+		return 1;
+
+	struct _print_mda_baton *b = baton;
+
+	char *buf = b->buffer;
+	if (!dm_asprintf(&b->buffer, "%s da%i { offset = %lld size = %lld }",
+			 b->buffer ?: "", b->i, da->offset, da->size))
+	{
+		dm_free(buf);
+		return_0;
+	}
+	b->i ++;
+	dm_free(buf);
+	return 1;
+}
+
+static const char *_print_mdas(struct lvmcache_info *info)
+{
+	struct _print_mda_baton baton = { .i = 0, .buffer = NULL };
+	if (!lvmcache_foreach_mda(info, &_print_mda, &baton))
+		return NULL;
+	baton.i = 0;
+	if (!lvmcache_foreach_da(info, &_print_da, &baton))
+		return NULL;
+	return baton.buffer;
+}
+
+int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_type *fmt,
+		     uint64_t label_sector, struct volume_group *vg)
+{
+	if (!_using_lvmetad)
+		return 1;
+
+	char uuid[64];
+
+	id_write_format(&pvid, uuid, 64);
+
+	/* FIXME A more direct route would be much preferable. */
+	struct lvmcache_info *info = lvmcache_info_from_pvid((const char *)&pvid, 0);
+	const char *mdas = NULL;
+	if (info)
+		mdas = _print_mdas(info);
+
+	char *pvmeta;
+	if (!dm_asprintf(&pvmeta,
+			 "{ device = %lld\n"
+			 "  dev_size = %lld\n"
+			 "  format = \"%s\"\n"
+			 "  label_sector = %lld\n"
+			 "  id = \"%s\"\n"
+			 "  %s"
+			 "}", device->dev, info ? lvmcache_device_size(info) : 0,
+			 fmt->name, label_sector, uuid, mdas ?: ""))
+		return_0;
+
+	daemon_reply reply;
+
+	if (vg) {
+		char *buf = NULL;
+		/*
+		 * 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);
+		reply = daemon_send_simple(_lvmetad,
+					   "pv_found",
+					   "pvmeta = %b", pvmeta,
+					   "vgname = %s", vg->name,
+					   "metadata = %b", strchr(buf, '{'),
+					   NULL);
+	} else {
+		/* There are no MDAs on this PV. */
+		reply = daemon_send_simple(_lvmetad,
+					   "pv_found",
+					   "pvmeta = %b", pvmeta,
+					   NULL);
+	}
+
+	dm_free(pvmeta);
+	return _lvmetad_handle_reply(reply, "update PV", uuid);
+}
+
+int lvmetad_pv_gone(dev_t device)
+{
+	daemon_reply reply =
+		daemon_send_simple(_lvmetad, "pv_gone", "device = %d", device, NULL);
+
+	return _lvmetad_handle_reply(reply, "drop PV", "");
+}
+
+int lvmetad_active()
+{
+	return _using_lvmetad;
+}
+
+void lvmetad_set_active(int active)
+{
+	_using_lvmetad = active;
+}
+
+/*
+ * The following code implements pvscan --lvmetad.
+ */
+
+struct _pvscan_lvmetad_baton {
+	struct volume_group *vg;
+	struct format_instance *fid;
+};
+
+static int _pvscan_lvmetad_single(struct metadata_area *mda, void *baton)
+{
+	struct _pvscan_lvmetad_baton *b = baton;
+	struct volume_group *this = mda->ops->vg_read(b->fid, "", mda);
+	if ((this && !b->vg) || this->seqno > b->vg->seqno)
+		b->vg = this;
+	else release_vg(this);
+	return 1;
+}
+
+static dev_t _parse_devt(const char *str) { /* Oh. */
+	char *where = (char *) str;
+	int major = strtol(str, &where, 10);
+	if (where == str)
+		return -1;
+	if (*where != ':')
+		return -1;
+	++where;
+	str = where;
+	int minor = strtol(str, &where, 10);
+	if (where == str)
+		return -1;
+	if (*where)
+		return -1;
+
+	return MKDEV(major, minor);
+}
+
+int pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (argc != 1) {
+		log_error("Exactly one device parameter required.");
+		return 0;
+	}
+
+	if (!lvmetad_active()) {
+		log_error("Cannot proceed since lvmetad is not active.");
+		return 0;
+	}
+
+	struct device *dev = dev_cache_get(argv[0], NULL);
+	if (!dev && _parse_devt(argv[0]) != -1)
+		dev = dev_cache_get_by_devt(_parse_devt(argv[0]), NULL);
+
+	if (!dev) {
+		if (_parse_devt(argv[0]) == -1) {
+			log_error("For devices that do not exist, we need a MAJOR:MINOR pair.");
+			return 0;
+		}
+
+		if (!lvmetad_pv_gone(_parse_devt(argv[0])))
+			goto fatal;
+
+		log_info("Device %s not found and was wiped from lvmetad.", argv[0]);
+		return 1;
+	}
+
+	struct label *label;
+	if (!label_read(dev, &label, 0)) {
+		log_warn("No PV label found on %s.", dev_name(dev));
+		if (!lvmetad_pv_gone(dev->dev))
+			goto fatal;
+		return 1;
+	}
+
+	struct lvmcache_info *info = (struct lvmcache_info *) label->info;
+	struct physical_volume pv;
+	memset(&pv, 0, sizeof(pv));
+
+	struct _pvscan_lvmetad_baton baton;
+	baton.vg = NULL;
+
+	/* Create a dummy instance. */
+	struct format_instance_ctx fic = { .type = 0 };
+	baton.fid =
+		lvmcache_fmt(info)->ops->create_instance(lvmcache_fmt(info), &fic);
+	struct metadata_area *mda;
+
+	lvmcache_foreach_mda(info, _pvscan_lvmetad_single, &baton);
+
+	/*
+	 * NB. If this command failed and we are relying on lvmetad to have an
+	 * *exact* image of the system, the lvmetad instance that went out of
+	 * sync needs to be killed.
+	 */
+	if (!lvmetad_pv_found(*(struct id *)dev->pvid, dev, lvmcache_fmt(info),
+			      label->sector, baton.vg))
+		goto fatal;
+
+	release_vg(baton.vg);
+	return 1;
+fatal:
+	release_vg(baton.vg);
+	/* FIXME kill lvmetad automatically if we can */
+	log_error("Update of lvmetad failed. This is a serious problem.\n  "
+		  "It is strongly recommended that you restart lvmetad immediately.");
+	return 0;
+}
+
/cvs/lvm2/LVM2/lib/cache/lvmetad.h,v  -->  standard output
revision 1.1
--- LVM2/lib/cache/lvmetad.h
+++ -	2012-02-23 13:11:12.832074000 +0000
@@ -0,0 +1,99 @@
+/*
+ * 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;
+
+/*
+ * Initialise the communication with lvmetad. Normally called by
+ * lvmcache_init. Sets up a global handle for our process.
+ */
+void lvmetad_init(void);
+
+/*
+ * Override the use of lvmetad for retrieving scan results and metadata.
+ */
+void lvmetad_set_active(int);
+
+/*
+ * Check whether lvmetad is active (where active means both that it is running
+ * and that we have a working connection with it).
+ */
+int lvmetad_active(void);
+
+/*
+ * Send a new version of VG metadata to lvmetad. This is normally called after
+ * vg_write but before vg_commit. After vg_commit, lvmetad_vg_commit is called
+ * to seal the transaction. The result of lvmetad_vg_update is that the new
+ * metadata is stored tentatively in lvmetad, but it is not used until
+ * lvmetad_vg_commit. The request is validated immediately and lvmetad_vg_commit
+ * only constitutes a pointer update.
+ */
+int lvmetad_vg_update(struct volume_group *vg);
+
+/*
+ * Inform lvmetad that a VG has been removed. This is not entirely safe, but is
+ * only needed during vgremove, which does not wipe PV labels and therefore
+ * cannot mark the PVs as gone.
+ */
+int lvmetad_vg_remove(struct volume_group *vg);
+
+/*
+ * Notify lvmetad that a PV has been found. It is not an error if the PV is
+ * already marked as present in lvmetad. If a non-NULL vg pointer is supplied,
+ * it is taken to represent the metadata read from the MDA(s) present on that
+ * PV. It *is* an error if: the VG is already known to lvmetad, the sequence
+ * number on the cached and on the discovered PV match but the metadata content
+ * does not.
+ */
+int lvmetad_pv_found(struct id pvid, struct device *device,
+		     const struct format_type *fmt, uint64_t label_sector,
+		     struct volume_group *vg);
+
+/*
+ * Inform the daemon that the device no longer exists. We do not support
+ * multiple device names, so this needs a unique and stable name, the same as
+ * provided to lvmetad_pv_found.
+ */
+int lvmetad_pv_gone(dev_t device);
+
+/*
+ * Request a list of all PVs available to lvmetad. If requested, this will also
+ * read labels off all the PVs to populate lvmcache.
+ */
+int lvmetad_pv_list_to_lvmcache(struct cmd_context *cmd);
+
+int lvmetad_pv_lookup(struct cmd_context *cmd, struct id pvid);
+int lvmetad_pv_lookup_by_devt(struct cmd_context *cmd, dev_t dev);
+
+/*
+ * Request a list of all VGs available to lvmetad and use it to fill in
+ * lvmcache..
+ */
+int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd);
+
+struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgname, const char *vgid);
+
+/*
+ * Scan a single device and update lvmetad with the result(s). If the device
+ * node does not exist, it must be supplied in a major:minor format.
+ */
+int pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv);
+
+#endif
+
--- LVM2/lib/cache/lvmcache.c	2012/02/13 14:26:15	1.126
+++ LVM2/lib/cache/lvmcache.c	2012/02/23 13:11:08	1.127
@@ -28,6 +28,8 @@
 #include "format1.h"
 #include "config.h"
 
+#include "lvmetad.h"
+
 #define CACHE_INVALID	0x00000001
 #define CACHE_LOCKED	0x00000002
 
@@ -107,9 +109,20 @@
 		_vg_global_lock_held = 0;
 	}
 
+	lvmetad_init();
+
 	return 1;
 }
 
+void lvmcache_seed_infos_from_lvmetad(struct cmd_context *cmd)
+{
+	if (lvmetad_active() && !_has_scanned) {
+		lvmetad_pv_list_to_lvmcache(cmd);
+		_has_scanned = 1;
+	}
+};
+
+
 /* Volume Group metadata cache functions */
 static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
 {
@@ -429,7 +442,9 @@
 	return vginfo;
 }
 
-const struct format_type *lvmcache_fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels)
+const struct format_type *lvmcache_fmt_from_vgname(struct cmd_context *cmd,
+						   const char *vgname, const char *vgid,
+						   unsigned revalidate_labels)
 {
 	struct lvmcache_vginfo *vginfo;
 	struct lvmcache_info *info;
@@ -439,8 +454,19 @@
 	struct device_list *devl;
 	char vgid_found[ID_LEN + 1] __attribute__((aligned(8)));
 
-	if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
+	if (!(vginfo = lvmcache_vginfo_from_vgname(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) {
+			const struct format_type *fmt = vg->fid->fmt;
+			release_vg(vg);
+			return fmt;
+		}
 		return NULL;
+	}
 
 	/*
 	 * If this function is called repeatedly, only the first one needs to revalidate.
@@ -581,6 +607,13 @@
 	return info;
 }
 
+const char *lvmcache_vgname_from_info(struct lvmcache_info *info)
+{
+	if (info->vginfo)
+		return info->vginfo->vgname;
+	return NULL;
+}
+
 char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid)
 {
 	struct lvmcache_info *info;
@@ -626,6 +659,9 @@
 
 	int r = 0;
 
+	if (lvmetad_active())
+		return 1;
+
 	/* Avoid recursion when a PVID can't be found! */
 	if (_scanning_in_progress)
 		return 0;
@@ -678,13 +714,28 @@
 	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;
 
+	/*
+	 * 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 = lvmcache_vginfo_from_vgid(vgid)) &&
+		    vginfo->vgmetadata && (vg = vginfo->cached_vg))
+			goto out;
+		return lvmetad_vg_lookup(cmd, vgname, vgid);
+	}
+
 	if (!vgid || !(vginfo = lvmcache_vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
 		return NULL;
 
@@ -781,6 +832,7 @@
 	struct dm_list *vgids;
 	struct lvmcache_vginfo *vginfo;
 
+	// TODO plug into lvmetad here automagically?
 	lvmcache_label_scan(cmd, 0);
 
 	if (!(vgids = str_list_create(cmd->mem))) {
@@ -862,6 +914,12 @@
 	struct label *label;
 
 	if ((info = lvmcache_info_from_pvid((const char *) pvid, 0))) {
+		if (lvmetad_active()) {
+			if (info->label && label_sector)
+				*label_sector = info->label->sector;
+			return info->dev;
+		}
+
 		if (label_read(info->dev, &label, UINT64_C(0))) {
 			info = (struct lvmcache_info *) label->info;
 			if (id_equal(pvid, (struct id *) &info->dev->pvid)) {
@@ -1333,6 +1391,10 @@
 		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) &&
@@ -1408,6 +1470,9 @@
 		info->label = label;
 		dm_list_init(&info->list);
 		info->dev = dev;
+
+		lvmcache_del_mdas(info);
+		lvmcache_del_das(info);
 	} else {
 		if (existing->dev != dev) {
 			/* Is the existing entry a duplicate pvid e.g. md ? */
@@ -1711,7 +1776,7 @@
 	} else
 		dm_list_init(&info->das);
 
-	if (!add_da(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
+	if (!add_da(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, 0 /*pv->size << SECTOR_SHIFT*/))
 		return_0;
 
 	return 1;
@@ -1749,12 +1814,12 @@
 }
 
 int lvmcache_foreach_da(struct lvmcache_info *info,
-			int (*fun)(struct data_area_list *, void *),
+			int (*fun)(struct disk_locn *, void *),
 			void *baton)
 {
 	struct data_area_list *da;
 	dm_list_iterate_items(da, &info->das) {
-		if (!fun(da, baton))
+		if (!fun(&da->disk_locn, baton))
 			return_0;
 	}
 
@@ -1793,6 +1858,10 @@
 
 int lvmcache_vgid_is_cached(const char *vgid) {
 	struct lvmcache_vginfo *vginfo;
+
+	if (lvmetad_active())
+		return 1;
+
 	vginfo = lvmcache_vginfo_from_vgid(vgid);
 
 	if (!vginfo || !vginfo->vgname)
--- LVM2/lib/cache/lvmcache.h	2012/02/10 01:28:27	1.42
+++ LVM2/lib/cache/lvmcache.h	2012/02/23 13:11:08	1.43
@@ -34,11 +34,13 @@
 struct dm_config_tree;
 struct format_instance;
 struct metadata_area;
-struct data_area_list;
+struct disk_locn;
 
 struct lvmcache_vginfo;
 
 int lvmcache_init(void);
+void lvmcache_allow_reads_with_lvmetad();
+
 void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
 
 /* Set full_scan to 1 to reread every filtered device label or
@@ -64,7 +66,7 @@
 int lvmcache_verify_lock_order(const char *vgname);
 
 /* Queries */
-const struct format_type *lvmcache_fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels);
+const struct format_type *lvmcache_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 lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
@@ -79,9 +81,12 @@
 const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
 			      const char *dev_name);
 char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid);
+const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
 int lvmcache_vgs_locked(void);
 int lvmcache_vgname_is_locked(const char *vgname);
 
+void lvmcache_seed_infos_from_lvmetad(struct cmd_context *cmd);
+
 /* Returns list of struct str_lists containing pool-allocated copy of vgnames */
 /* If include_internal is not set, return only proper vg names. */
 struct dm_list *lvmcache_get_vgnames(struct cmd_context *cmd,
@@ -97,7 +102,8 @@
 				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);
 
@@ -127,7 +133,7 @@
 			 void *baton);
 
 int lvmcache_foreach_da(struct lvmcache_info *info,
-			int (*fun)(struct data_area_list *, void *),
+			int (*fun)(struct disk_locn *, void *),
 			void *baton);
 
 int lvmcache_foreach_pv(struct lvmcache_vginfo *vg,
--- LVM2/lib/commands/toolcontext.c	2012/02/08 13:44:49	1.150
+++ LVM2/lib/commands/toolcontext.c	2012/02/23 13:11:09	1.151
@@ -34,6 +34,7 @@
 #include "str_list.h"
 #include "segtype.h"
 #include "lvmcache.h"
+#include "lvmetad.h"
 #include "dev-cache.h"
 #include "archiver.h"
 
@@ -389,6 +390,8 @@
 		(find_config_tree_int(cmd, "global/detect_internal_vg_cache_corruption()",
 				      DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION));
 
+	lvmetad_set_active(find_config_tree_int(cmd, "global/use_lvmetad", 0));
+
 	return 1;
 }
 
--- LVM2/lib/device/dev-cache.c	2012/02/08 11:05:04	1.71
+++ LVM2/lib/device/dev-cache.c	2012/02/23 13:11:09	1.72
@@ -906,6 +906,39 @@
 		      f->passes_filter(f, d))) ? d : NULL;
 }
 
+static struct device *_dev_cache_seek_devt(dev_t dev)
+{
+	struct device *d = NULL;
+	struct dm_hash_node *n = dm_hash_get_first(_cache.names);
+	while (n) {
+		d = dm_hash_get_data(_cache.names, n);
+		if (d->dev == dev)
+			return d;
+		n = dm_hash_get_next(_cache.names, n);
+	}
+	return NULL;
+}
+
+/*
+ * TODO This is very inefficient. We probably want a hash table indexed by
+ * major:minor for keys to speed up these lookups.
+ */
+struct device *dev_cache_get_by_devt(dev_t dev, struct dev_filter *f)
+{
+	struct device *d = _dev_cache_seek_devt(dev);
+
+	if (d && (d->flags & DEV_REGULAR))
+		return d;
+
+	if (!d) {
+		_full_scan(0);
+		d = _dev_cache_seek_devt(dev);
+	}
+
+	return (d && (!f || (d->flags & DEV_REGULAR) ||
+		      f->passes_filter(f, d))) ? d : NULL;
+}
+
 struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
 {
 	struct dev_iter *di = dm_malloc(sizeof(*di));
--- LVM2/lib/device/dev-cache.h	2011/04/22 12:05:33	1.14
+++ LVM2/lib/device/dev-cache.h	2012/02/23 13:11:09	1.15
@@ -44,6 +44,9 @@
 int dev_cache_add_loopfile(const char *path);
 struct device *dev_cache_get(const char *name, struct dev_filter *f);
 
+// TODO
+struct device *dev_cache_get_by_devt(dev_t device, struct dev_filter *f);
+
 void dev_set_preferred_name(struct str_list *sl, struct device *dev);
 
 /*
--- LVM2/lib/device/dev-io.c	2012/02/10 01:28:27	1.81
+++ LVM2/lib/device/dev-io.c	2012/02/23 13:11:09	1.82
@@ -664,6 +664,8 @@
 	where.start = offset;
 	where.size = len;
 
+	// fprintf(stderr, "READ: %s, %lld, %d\n", dev_name(dev), offset, len);
+
 	ret = _aligned_io(&where, buffer, 0);
 	if (!ret)
 		_dev_inc_error_count(dev);
--- LVM2/lib/format1/format1.c	2012/02/15 01:44:58	1.147
+++ LVM2/lib/format1/format1.c	2012/02/23 13:11:09	1.148
@@ -415,6 +415,7 @@
 
 	lvmcache_update_pv(info, pv, fmt);
 	lvmcache_del_mdas(info);
+	lvmcache_del_das(info);
 
 	dm_list_init(&pvs);
 
@@ -590,6 +591,8 @@
 			FMT_RESTRICTED_READAHEAD;
 	fmt->private = NULL;
 
+	dm_list_init(&fmt->mda_ops);
+
 	if (!(fmt->labeller = lvm1_labeller_create(fmt))) {
 		log_error("Couldn't create lvm1 label handler.");
 		dm_free(fmt);
--- LVM2/lib/format_pool/format_pool.c	2012/02/15 13:46:54	1.52
+++ LVM2/lib/format_pool/format_pool.c	2012/02/23 13:11:09	1.53
@@ -301,6 +301,8 @@
 	fmt->features = 0;
 	fmt->private = NULL;
 
+	dm_list_init(&fmt->mda_ops);
+
 	if (!(fmt->labeller = pool_labeller_create(fmt))) {
 		log_error("Couldn't create pool label handler.");
 		dm_free(fmt);
--- LVM2/lib/format_text/export.c	2012/01/25 22:35:36	1.86
+++ LVM2/lib/format_text/export.c	2012/02/23 13:11:09	1.87
@@ -395,6 +395,9 @@
 
 	outf(f, "seqno = %u", vg->seqno);
 
+	if (vg->fid && vg->fid->fmt)
+		outf(f, "format = \"%s\" # informational", vg->fid->fmt->name);
+
 	if (!_print_flag_config(f, vg->status, VG_FLAGS))
 		return_0;
 
--- LVM2/lib/format_text/format-text.c	2012/02/13 11:09:25	1.193
+++ LVM2/lib/format_text/format-text.c	2012/02/23 13:11:09	1.194
@@ -29,6 +29,7 @@
 #include "label.h"
 #include "memlock.h"
 #include "lvmcache.h"
+#include "lvmetad.h"
 
 #include <unistd.h>
 #include <sys/file.h>
@@ -738,6 +739,7 @@
 			  dev_name(mdac->area.dev), mdac->area.start);
 
 	rlocn_set_ignored(mdah->raw_locns, mda_is_ignored(mda));
+
 	if (!_raw_write_mda_header(fid->fmt, mdac->area.dev, mdac->area.start,
 				   mdah)) {
 		dm_pool_free(fid->fmt->cmd->mem, mdah);
@@ -1430,16 +1432,25 @@
 static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
 		    struct physical_volume *pv, int scan_label_only)
 {
-	struct label *label;
+	struct lvmcache_info *info;
 	struct device *dev;
 
 	if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
 		return_0;
 
-	if (!(label_read(dev, &label, UINT64_C(0))))
-		return_0;
+	if (lvmetad_active()) {
+		info = lvmcache_info_from_pvid(dev->pvid, 0);
+		if (!info && !lvmetad_pv_lookup_by_devt(fmt->cmd, dev->dev))
+			return 0;
+		info = lvmcache_info_from_pvid(dev->pvid, 0);
+	} else {
+		struct label *label;
+		if (!(label_read(dev, &label, UINT64_C(0))))
+			return_0;
+		info = label->info;
+	}
 
-	if (!lvmcache_populate_pv_fields(label->info, pv, scan_label_only))
+	if (!lvmcache_populate_pv_fields(info, pv, scan_label_only))
 		return 0;
 
 	return 1;
@@ -1568,6 +1579,9 @@
 	.vg_commit = _vg_commit_file_backup
 };
 
+static char *_mda_export_text_raw(struct metadata_area *mda);
+static int _mda_import_text_raw(struct lvmcache_info *info, const struct dm_config_node *cn);
+
 static struct metadata_area_ops _metadata_text_raw_ops = {
 	.vg_read = _vg_read_raw,
 	.vg_read_precommit = _vg_read_precommit_raw,
@@ -1584,9 +1598,42 @@
 	.mda_in_vg = _mda_in_vg_raw,
 	.pv_analyze_mda = _pv_analyze_mda_raw,
 	.mda_locns_match = _mda_locns_match_raw,
-	.mda_get_device = _mda_get_device_raw
+	.mda_get_device = _mda_get_device_raw,
+	.mda_export_text = _mda_export_text_raw,
+	.mda_import_text = _mda_import_text_raw
 };
 
+static char *_mda_export_text_raw(struct metadata_area *mda)
+{
+	struct mda_context *mdc = (struct mda_context *) mda->metadata_locn;
+	char *result;
+	dm_asprintf(&result,
+		    "ignore = %d "
+		    "start = %" PRIu64" "
+		    "size = %" PRIu64 " "
+		    "free_sectors = %" PRIu64,
+		    mda_is_ignored(mda), mdc->area.start, mdc->area.size, mdc->free_sectors);
+	return result;
+}
+
+static int _mda_import_text_raw(struct lvmcache_info *info, const struct dm_config_node *cn)
+{
+	if (!cn->child)
+		return 0;
+	cn = cn->child;
+
+	struct device *device = lvmcache_device(info);
+	uint64_t offset = dm_config_find_int(cn, "start", 0);
+	uint64_t size = dm_config_find_int(cn, "size", 0);
+	int ignore = dm_config_find_int(cn, "ignore", 0);
+
+	if (!device || !size)
+		return 0;
+
+	lvmcache_add_mda(info, device, offset, size, ignore);
+	return 1;
+}
+
 static int _text_pv_setup(const struct format_type *fmt,
 			  struct physical_volume *pv,
 			  struct volume_group *vg)
@@ -1619,7 +1666,9 @@
 	 * reread PV mda information from the cache and add it to vg->fid.
 	 */
 	else {
-		if (!(info = lvmcache_info_from_pvid(pv->dev->pvid, 0))) {
+		if (!pv->dev ||
+		    !pv->dev->pvid ||
+		    !(info = lvmcache_info_from_pvid(pv->dev->pvid, 0))) {
 			log_error("PV %s missing from cache", pv_dev_name(pv));
 			return 0;
 		}
@@ -2292,6 +2341,9 @@
 	mda_lists->raw_ops = &_metadata_text_raw_ops;
 	fmt->private = (void *) mda_lists;
 
+	dm_list_init(&fmt->mda_ops);
+	dm_list_add(&fmt->mda_ops, &_metadata_text_raw_ops.list);
+
 	if (!(fmt->labeller = text_labeller_create(fmt))) {
 		log_error("Couldn't create text label handler.");
 		goto bad;
--- LVM2/lib/format_text/import_vsn1.c	2012/02/10 01:28:28	1.100
+++ LVM2/lib/format_text/import_vsn1.c	2012/02/23 13:11:09	1.101
@@ -19,6 +19,7 @@
 #include "display.h"
 #include "toolcontext.h"
 #include "lvmcache.h"
+#include "lvmetad.h"
 #include "lv_alloc.h"
 #include "pv_alloc.h"
 #include "segtype.h"
@@ -59,6 +60,10 @@
 	const struct dm_config_node *cn;
 	const struct dm_config_value *cv;
 
+	// TODO if this is pvscan --lvmetad, we want this check back.
+	if (lvmetad_active())
+		return 1;
+
 	/*
 	 * Check the contents field.
 	 */
@@ -212,7 +217,8 @@
 		return 0;
 	}
 
-	if (!pv->dev)
+	/* TODO is the !lvmetad_active() too coarse here? */
+	if (!pv->dev && !lvmetad_active())
 		pv->status |= MISSING_PV;
 
 	/* Late addition */
--- LVM2/lib/format_text/text_label.c	2012/02/10 01:28:28	1.41
+++ LVM2/lib/format_text/text_label.c	2012/02/23 13:11:09	1.42
@@ -19,6 +19,7 @@
 #include "label.h"
 #include "xlate.h"
 #include "lvmcache.h"
+#include "lvmetad.h"
 
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -40,11 +41,11 @@
 	struct device *dev;
 };
 
-static int _da_setup(struct data_area_list *da, void *baton)
+static int _da_setup(struct disk_locn *da, void *baton)
 {
 	struct _da_setup_baton *p = baton;
-	p->pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
-	p->pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
+	p->pvh_dlocn_xl->offset = xlate64(da->offset);
+	p->pvh_dlocn_xl->size = xlate64(da->size);
 	p->pvh_dlocn_xl++;
 	return 1;
 }
@@ -275,7 +276,7 @@
 	const struct format_type *fmt = p->label->labeller->private; // Oh dear.
 	struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
 	struct mda_header *mdah;
-	const char *vgname;
+	const char *vgname = NULL;
 	struct id vgid;
 	uint64_t vgstatus;
 	char *creation_host;
@@ -337,7 +338,6 @@
 				  FMT_TEXT_ORPHAN_VG_NAME, 0)))
 		return_0;
 
-	/* this one is leaked forever */
 	*label = lvmcache_get_label(info);
 
 	lvmcache_set_device_size(info, xlate64(pvhdr->device_size_xl));
--- LVM2/lib/label/label.c	2012/02/10 01:28:28	1.56
+++ LVM2/lib/label/label.c	2012/02/23 13:11:09	1.57
@@ -18,6 +18,7 @@
 #include "crc.h"
 #include "xlate.h"
 #include "lvmcache.h"
+#include "lvmetad.h"
 #include "metadata.h"
 
 #include <sys/stat.h>
@@ -263,7 +264,7 @@
 
 	if ((info = lvmcache_info_from_pvid(dev->pvid, 1))) {
 		log_debug("Using cached label for %s", dev_name(dev));
-		*result = lvmcache_get_label(info); /* leaked */
+		*result = lvmcache_get_label(info);
 		return 1;
 	}
 
--- LVM2/lib/label/label.h	2007/08/20 20:55:26	1.20
+++ LVM2/lib/label/label.h	2012/02/23 13:11:09	1.21
@@ -26,6 +26,8 @@
 
 struct labeller;
 
+void allow_reads_with_lvmetad(void);
+
 /* On disk - 32 bytes */
 struct label_header {
 	int8_t id[8];		/* LABELONE */
--- LVM2/lib/metadata/metadata-exported.h	2012/02/15 15:18:43	1.231
+++ LVM2/lib/metadata/metadata-exported.h	2012/02/23 13:11:09	1.232
@@ -174,6 +174,7 @@
 	struct dm_list list;
 	struct cmd_context *cmd;
 	struct format_handler *ops;
+	struct dm_list mda_ops; /* List of permissible mda ops. */
 	struct labeller *labeller;
 	const char *name;
 	const char *alias;
--- LVM2/lib/metadata/metadata.c	2012/02/23 00:11:01	1.485
+++ LVM2/lib/metadata/metadata.c	2012/02/23 13:11:10	1.486
@@ -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"
@@ -257,7 +258,7 @@
 			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;
 	}
@@ -615,6 +616,10 @@
 		}
 	}
 
+	/* FIXME Handle partial failures from above. */
+	if (!lvmetad_vg_remove(vg))
+		stack;
+
 	if (!backup_remove(vg->cmd, vg->name))
 		stack;
 
@@ -2678,6 +2683,7 @@
 		/* Update cache first time we succeed */
 		if (!failed && !cache_updated) {
 			lvmcache_update_vg(vg, 0);
+			// lvmetad_vg_commit(vg);
 			cache_updated = 1;
 		}
 	}
@@ -2695,6 +2701,9 @@
 		return cache_updated;
 	}
 
+	if (!lvmetad_vg_update(vg))
+		return 0;
+
 	cache_updated = _vg_commit_mdas(vg);
 
 	if (cache_updated) {
@@ -2750,6 +2759,7 @@
 			    b->vg->fid, b->warnings, 0))) {
 		return 1;
 	}
+
 	if (!(pvl = dm_pool_zalloc(b->vg->vgmem, sizeof(*pvl)))) {
 		log_error("pv_list allocation failed");
 		free_pv_fid(pv);
@@ -2771,11 +2781,12 @@
 	struct _vg_read_orphan_baton baton;
 
 	lvmcache_label_scan(cmd, 0);
+	lvmcache_seed_infos_from_lvmetad(cmd);
 
 	if (!(vginfo = lvmcache_vginfo_from_vgname(orphan_vgname, NULL)))
 		return_NULL;
 
-	if (!(fmt = lvmcache_fmt_from_vgname(orphan_vgname, NULL, 0)))
+	if (!(fmt = lvmcache_fmt_from_vgname(cmd, orphan_vgname, NULL, 0)))
 		return_NULL;
 
 	vg = fmt->orphan_vg;
@@ -2915,6 +2926,7 @@
 	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) {
@@ -2926,31 +2938,39 @@
 		return _vg_read_orphans(cmd, warnings, vgname);
 	}
 
+	if (lvmetad_active() && !use_precommitted) {
+		*consistent = 1;
+		return lvmcache_get_vg(cmd, vgname, vgid, precommitted);
+	}
+
 	/*
 	 * 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;
 		return correct_vg;
 	} else {
+		if (correct_vg && correct_vg->seqno > seqno)
+			seqno = correct_vg->seqno;
 		release_vg(correct_vg);
 		correct_vg = NULL;
 	}
 
+
 	/* Find the vgname in the cache */
 	/* If it's not there we must do full scan to be completely sure */
-	if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 1))) {
+	if (!(fmt = lvmcache_fmt_from_vgname(cmd, vgname, vgid, 1))) {
 		lvmcache_label_scan(cmd, 0);
-		if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 1))) {
+		if (!(fmt = lvmcache_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 = lvmcache_fmt_from_vgname(vgname, vgid, 0)))
+			if (!(fmt = lvmcache_fmt_from_vgname(cmd, vgname, vgid, 0)))
 				return_NULL;
 		}
 	}
@@ -3026,6 +3046,12 @@
 	/* 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.
@@ -3136,7 +3162,7 @@
 		if (!cmd->independent_metadata_areas && critical_section())
 			return_NULL;
 		lvmcache_label_scan(cmd, 2);
-		if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 0)))
+		if (!(fmt = lvmcache_fmt_from_vgname(cmd, vgname, vgid, 0)))
 			return_NULL;
 
 		if (precommitted && !(fmt->features & FMT_PRECOMMIT))
@@ -3582,14 +3608,22 @@
 	if (!(dev = dev_cache_get(pv_name, cmd->filter)))
 		return_NULL;
 
-	if (!(label_read(dev, &label, UINT64_C(0)))) {
-		if (warnings)
-			log_error("No physical volume label read from %s",
-				  pv_name);
-		return NULL;
+	if (lvmetad_active()) {
+		info = lvmcache_info_from_pvid(dev->pvid, 0);
+		if (!info && !lvmetad_pv_lookup_by_devt(cmd, dev->dev))
+			return NULL;
+		info = lvmcache_info_from_pvid(dev->pvid, 0);
+		label = lvmcache_get_label(info);
+	} else {
+		if (!(label_read(dev, &label, UINT64_C(0)))) {
+			if (warnings)
+				log_error("No physical volume label read from %s",
+					  pv_name);
+			return NULL;
+		}
+		info = (struct lvmcache_info *) label->info;
 	}
 
-	info = (struct lvmcache_info *) label->info;
 	fmt = lvmcache_fmt(info);
 
 	pv = _alloc_pv(pvmem, dev);
@@ -3748,6 +3782,9 @@
 	if (!pv->fmt->ops->pv_write(pv->fmt, pv))
 		return_0;
 
+	if (!lvmetad_pv_found(pv->id, pv->dev, pv->fmt, pv->label_sector, NULL))
+		return_0;
+
 	return 1;
 }
 
@@ -4120,9 +4157,9 @@
 
 	/* Find the vgname in the cache */
 	/* If it's not there we must do full scan to be completely sure */
-	if (!lvmcache_fmt_from_vgname(vgname, NULL, 1)) {
+	if (!lvmcache_fmt_from_vgname(cmd, vgname, NULL, 1)) {
 		lvmcache_label_scan(cmd, 0);
-		if (!lvmcache_fmt_from_vgname(vgname, NULL, 1)) {
+		if (!lvmcache_fmt_from_vgname(cmd, vgname, NULL, 1)) {
 			/* Independent MDAs aren't supported under low memory */
 			if (!cmd->independent_metadata_areas && critical_section()) {
 				/*
@@ -4133,7 +4170,7 @@
 				return FAILED_LOCKING;
 			}
 			lvmcache_label_scan(cmd, 2);
-			if (!lvmcache_fmt_from_vgname(vgname, NULL, 0)) {
+			if (!lvmcache_fmt_from_vgname(cmd, vgname, NULL, 0)) {
 				/* vgname not found after scanning */
 				return SUCCESS;
 			}
@@ -4228,8 +4265,9 @@
 		 const char *key, size_t key_len, const unsigned sub_key)
 {
 	static char full_key[PATH_MAX];
+
 	dm_list_add(mda_is_ignored(mda) ? &fid->metadata_areas_ignored :
-					  &fid->metadata_areas_in_use, &mda->list);
+		                          &fid->metadata_areas_in_use, &mda->list);
 
 	/* Return if the mda is not supposed to be indexed. */
 	if (!key)
@@ -4238,7 +4276,7 @@
 	/* Add metadata area to index. */
 	if (!_convert_key_to_string(key, key_len, sub_key,
 				    full_key, sizeof(full_key)))
-	return_0;
+		return_0;
 
 	dm_hash_insert(fid->metadata_areas_index,
 		       full_key, mda);
--- LVM2/lib/metadata/metadata.h	2012/02/08 13:05:39	1.266
+++ LVM2/lib/metadata/metadata.h	2012/02/23 13:11:10	1.267
@@ -70,9 +70,11 @@
 struct dm_config_tree;
 struct metadata_area;
 struct alloc_handle;
+struct lvmcache_info;
 
 /* Per-format per-metadata area operations */
 struct metadata_area_ops {
+	struct dm_list list;
 	struct volume_group *(*vg_read) (struct format_instance * fi,
 					 const char *vg_name,
 					 struct metadata_area * mda);
@@ -145,6 +147,8 @@
 				    struct metadata_area *mda2);
 
 	struct device *(*mda_get_device)(struct metadata_area *mda);
+	char *(*mda_export_text)(struct metadata_area *mda);
+	int (*mda_import_text)(struct lvmcache_info *info, const struct dm_config_node *cn);
 };
 
 #define MDA_IGNORED      0x00000001
--- LVM2/tools/Makefile.in	2011/11/14 21:30:36	1.124
+++ LVM2/tools/Makefile.in	2012/02/23 13:11:10	1.125
@@ -16,6 +16,8 @@
 top_srcdir = @top_srcdir@
 top_builddir = @top_builddir@
 
+INCLUDES += -I$(top_srcdir)/daemons/common -I$(top_srcdir)/daemons/lvmetad
+
 SOURCES =\
 	dumpconfig.c \
 	formats.c \
--- LVM2/tools/args.h	2011/11/30 02:02:12	1.86
+++ LVM2/tools/args.h	2012/02/23 13:11:10	1.87
@@ -61,6 +61,7 @@
 arg(monitor_ARG, '\0', "monitor", yes_no_arg, 0)
 arg(config_ARG, '\0', "config", string_arg, 0)
 arg(trustcache_ARG, '\0', "trustcache", NULL, 0)
+arg(lvmetad_ARG, '\0', "lvmetad", NULL, 0)
 arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", NULL, 0)
 arg(nameprefixes_ARG, '\0', "nameprefixes", NULL, 0)
 arg(unquoted_ARG, '\0', "unquoted", NULL, 0)
--- LVM2/tools/commands.h	2011/11/30 02:02:12	1.167
+++ LVM2/tools/commands.h	2012/02/23 13:11:10	1.168
@@ -670,11 +670,12 @@
    "\t[-P|--partial] " "\n"
    "\t[-s|--short] " "\n"
    "\t[-u|--uuid] " "\n"
+   "\t[--lvmetad DEVICE] " "\n"
    "\t[-v|--verbose] " "\n"
    "\t[--version]\n",
 
    exported_ARG, ignorelockingfailure_ARG, novolumegroup_ARG, partial_ARG,
-   short_ARG, uuid_ARG)
+   short_ARG, uuid_ARG, lvmetad_ARG)
 
 xx(segtypes,
    "List available segment types",
--- LVM2/tools/pvcreate.c	2012/02/13 11:04:00	1.98
+++ LVM2/tools/pvcreate.c	2012/02/23 13:11:10	1.99
@@ -56,6 +56,7 @@
 		if (!id_read_format(&pp->id, uuid))
 			return 0;
 		pp->idp = &pp->id;
+		lvmcache_seed_infos_from_lvmetad(cmd); /* need to check for UUID dups */
 	}
 
 	if (arg_count(cmd, restorefile_ARG)) {
--- LVM2/tools/pvremove.c	2011/08/30 14:55:19	1.36
+++ LVM2/tools/pvremove.c	2012/02/23 13:11:10	1.37
@@ -128,6 +128,8 @@
 		goto error;
 	}
 
+	lvmetad_pv_gone(dev->dev);
+
 	log_print("Labels on physical volume \"%s\" successfully wiped",
 		  pv_name);
 
--- LVM2/tools/pvscan.c	2011/03/11 14:56:56	1.53
+++ LVM2/tools/pvscan.c	2012/02/23 13:11:10	1.54
@@ -15,6 +15,9 @@
 
 #include "tools.h"
 
+#include "lvmetad.h"
+#include "lvmcache.h"
+
 int pv_max_name_len = 0;
 int vg_max_name_len = 0;
 
@@ -96,8 +99,7 @@
 					   pv_pe_size(pv)));
 }
 
-int pvscan(struct cmd_context *cmd, int argc __attribute__((unused)),
-	   char **argv __attribute__((unused)))
+int pvscan(struct cmd_context *cmd, int argc, char **argv)
 {
 	int new_pvs_found = 0;
 	int pvs_found = 0;
@@ -113,6 +115,12 @@
 	pv_max_name_len = 0;
 	vg_max_name_len = 0;
 
+	if (arg_count(cmd, lvmetad_ARG)) {
+		if (!pvscan_lvmetad(cmd, argc, argv))
+			return ECMD_FAILED;
+		return ECMD_PROCESSED;
+	}
+
 	if (arg_count(cmd, novolumegroup_ARG) && arg_count(cmd, exported_ARG)) {
 		log_error("Options -e and -n are incompatible");
 		return EINVALID_CMD_LINE;
@@ -184,8 +192,8 @@
 	vg_max_name_len += 2;
 
 	dm_list_iterate_items(pvl, pvslist) {
-	    _pvscan_display_single(cmd, pvl->pv, NULL);
-	    free_pv_fid(pvl->pv);
+		_pvscan_display_single(cmd, pvl->pv, NULL);
+		free_pv_fid(pvl->pv);
 	}
 
 	if (!pvs_found) {
--- LVM2/tools/toollib.c	2012/02/15 15:18:44	1.241
+++ LVM2/tools/toollib.c	2012/02/23 13:11:10	1.242
@@ -305,6 +305,7 @@
 
 	if (!argc || !dm_list_empty(&tags)) {
 		log_verbose("Finding all logical volumes");
+		lvmetad_vg_list_to_lvmcache(cmd);
 		if (!(vgnames = get_vgnames(cmd, 0)) || dm_list_empty(vgnames)) {
 			log_error("No volume groups found");
 			return ret_max;
@@ -581,6 +582,7 @@
 
 	if (!argc || !dm_list_empty(&tags)) {
 		log_verbose("Finding all volume groups");
+		lvmetad_vg_list_to_lvmcache(cmd);
 		if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) {
 			log_error("No volume groups found");
 			return ret_max;
@@ -837,6 +839,7 @@
 		} else {
 			log_verbose("Scanning for physical volume names");
 
+			lvmcache_seed_infos_from_lvmetad(cmd);
 			if (!(pvslist = get_pvs(cmd)))
 				goto bad;
 
--- LVM2/tools/tools.h	2012/01/05 15:38:19	1.78
+++ LVM2/tools/tools.h	2012/02/23 13:11:10	1.79
@@ -28,6 +28,7 @@
 #include "activate.h"
 #include "archiver.h"
 #include "lvmcache.h"
+#include "lvmetad.h"
 #include "config.h"
 #include "defaults.h"
 #include "dev-cache.h"
--- LVM2/tools/vgcfgrestore.c	2011/02/18 14:47:31	1.25
+++ LVM2/tools/vgcfgrestore.c	2012/02/23 13:11:10	1.26
@@ -45,6 +45,8 @@
 		return ECMD_PROCESSED;
 	}
 
+	lvmcache_seed_infos_from_lvmetad(cmd);
+
 	if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
 		log_error("Unable to lock volume group %s", vg_name);
 		return ECMD_FAILED;
--- LVM2/tools/vgcreate.c	2011/08/10 20:25:31	1.84
+++ LVM2/tools/vgcreate.c	2012/02/23 13:11:10	1.85
@@ -49,6 +49,8 @@
 	if (vgcreate_params_validate(cmd, &vp_new))
 	    return EINVALID_CMD_LINE;
 
+	lvmcache_seed_infos_from_lvmetad(cmd);
+
 	/* Create the new VG */
 	vg = vg_create(cmd, vp_new.vg_name);
 	if (vg_read_error(vg)) {
--- LVM2/tools/vgrename.c	2012/02/10 01:28:29	1.77
+++ LVM2/tools/vgrename.c	2012/02/23 13:11:10	1.78
@@ -79,6 +79,8 @@
 
 	log_verbose("Checking for existing volume group \"%s\"", vg_name_old);
 
+	lvmetad_vg_list_to_lvmcache(cmd); /* populate lvmcache */
+
 	/* Avoid duplicates */
 	if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) {
 		log_error("No complete volume groups found");
--- LVM2/tools/vgscan.c	2010/07/09 15:34:48	1.38
+++ LVM2/tools/vgscan.c	2012/02/23 13:11:10	1.39
@@ -24,13 +24,14 @@
 		  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 +45,8 @@
 
 	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 +59,7 @@
 			maxret = ret;
 	}
 
+	lvmetad_set_active(lvmetad); /* restore */
 	unlock_vg(cmd, VG_GLOBAL);
 	return maxret;
 }
--- LVM2/doc/example.conf.in	2012/01/26 14:02:44	1.43
+++ LVM2/doc/example.conf.in	2012/02/23 13:11:10	1.44
@@ -453,6 +453,16 @@
     # Set to 1 to reinstate the previous format.
     #
     # lvdisplay_shows_full_device_path = 0
+
+    # Whether to use (trust) a running instance of lvmetad. If this is set to
+    # 0, all commands fall back to the usual scanning mechanisms. When set to 1
+    # *and* when lvmetad is running (it is not auto-started), the volume group
+    # metadata and PV state flags are obtained from the lvmetad instance and no
+    # scanning is done by the individual commands. In a setup with lvmetad,
+    # lvmetad udev rules *must* be set up for LVM to work correctly. Without
+    # proper udev rules, all changes in block device configuration will be
+    # *ignored* until a manual 'vgscan' is performed.
+    use_lvmetad = 0
 }
 
 activation {
--- LVM2/scripts/vgimportclone.sh	2011/09/07 08:31:17	1.4
+++ LVM2/scripts/vgimportclone.sh	2012/02/23 13:11:10	1.5
@@ -249,6 +249,7 @@
     '/^[ \t]*filter[ \t]*=/{print ENVIRON["FILTER"];next} \
      /^[ \t]*scan[ \t]*=/{print "scan = [ \"" DEV "\" ]";next} \
      /^[ \t]*cache[ \t]*=/{print "cache = \"" CACHE "\"";next} \
+     /^[ \t]*use_lvmetad[ \t]*=/{print "use_lvmetad = 0";next} \
      /^[ \t]*cache_dir[ \t]*=/{print "cache_dir = \"" CACHE_DIR "\"";next} \
      {print $0}' > ${LVMCONF}
 
--- LVM2/test/lib/aux.sh	2012/02/15 14:24:32	1.37
+++ LVM2/test/lib/aux.sh	2012/02/23 13:11:10	1.38
@@ -70,6 +70,7 @@
 	}
 
 	lvmconf "global/use_lvmetad = 1"
+	lvmconf "devices/md_component_detection = 0"
 
 	lvmetad -f "$@" -s $TESTDIR/lvmetad.socket &
 	echo "$!" > LOCAL_LVMETAD
@@ -323,8 +324,11 @@
 
 	init_udev_transaction
 	for dev in "$@"; do
-        	dmsetup remove -f $dev || true
-		pvscan --lvmetad $dev || true
+	    maj=$(($(stat --printf=0x%t $dev)))
+	    min=$(($(stat --printf=0x%T $dev)))
+	    echo "disabling device $dev ($maj:$min)"
+            dmsetup remove -f $dev || true
+	    pvscan --lvmetad $maj:$min || true
 	done
 	finish_udev_transaction
 
--- LVM2/test/shell/inconsistent-metadata.sh	2011/11/21 00:15:46	1.1
+++ LVM2/test/shell/inconsistent-metadata.sh	2012/02/23 13:11:10	1.2
@@ -40,29 +40,32 @@
 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
--- LVM2/test/shell/lvconvert-mirror.sh	2011/11/21 00:15:46	1.1
+++ LVM2/test/shell/lvconvert-mirror.sh	2012/02/23 13:11:10	1.2
@@ -79,6 +79,7 @@
 lvconvert $vg/$lv1 # wait
 lvconvert -m2 $vg/$lv1 $dev1 $dev2 $dev4 $dev3:0 # If the above "should" failed...
 
+sleep 1
 lvconvert -m-1 $vg/$lv1 $dev1
 check mirror_images_on $lv1 $dev2 $dev4
 lvconvert -m-1 $vg/$lv1 $dev2
--- LVM2/test/shell/lvcreate-repair.sh	2011/11/21 00:15:46	1.1
+++ LVM2/test/shell/lvcreate-repair.sh	2012/02/23 13:11:10	1.2
@@ -14,31 +14,32 @@
 aux prepare_vg 3
 
 # fail multiple devices
-for i in pv1 pv2 pv3 ; do
-	for j in pv2 pv3 ; do
+for i in $dev1 $dev2 $dev3 ; do
+	for j in $dev2 $dev3 ; do
 
 		if test $i = $j ; then continue ; fi
 
 		vgremove -ff $vg
 		vgcreate $vg $dev1 $dev2 $dev3
+		# exit 1
 
 		lvcreate -l1 -n $lv1 $vg $dev1
 
-		aux lvmconf "devices/filter = [ \"r/.*$i$/\", \"r/.*$j$/\", \"a/dev\/mapper\/.*pv[0-9_]*$/\", \"r/.*/\" ]"
+		aux disable_dev $i $j
 
 		vgreduce --removemissing --force $vg
 
 		# check if reduced device was removed
-		test $i = pv1 && dmsetup table | not egrep "$vg-$lv1: *[^ ]+" >/dev/null
+		test $i = $dev1 && dmsetup table | not egrep "$vg-$lv1: *[^ ]+" >/dev/null
 
 		lvcreate -l1 -n $lv2 $vg
 
-		test $i != pv1 && check lv_exists $vg $lv1
+		test $i != $dev1 && check lv_exists $vg $lv1
 		check lv_exists $vg $lv2
 
-		aux lvmconf 'devices/filter = [ "a/dev\/mapper\/.*pv[0-9_]*$/", "r/.*/" ]'
+		aux enable_dev $i $j
 
-		test $i != pv1 && check lv_exists $vg $lv1
+		test $i != $dev1 && check lv_exists $vg $lv1
 		check lv_exists $vg $lv2
 	done
 done
@@ -84,6 +85,7 @@
 
 # dirty game
 dd if=/dev/zero of="$dev3" bs=256K count=1
+pvscan --lvmetad $dev3 || true # udev be watching you
 
 vgreduce --removemissing --force $vg
 
--- LVM2/test/shell/lvmcache-exercise.sh	2011/11/21 00:15:46	1.1
+++ LVM2/test/shell/lvmcache-exercise.sh	2012/02/23 13:11:10	1.2
@@ -19,5 +19,5 @@
 pvscan
 vgcreate $vg1 $dev2
 aux enable_dev $dev1
-pvs
+valgrind --trace-children=yes pvs
 pvs
--- LVM2/test/shell/pool-labels.sh	2011/11/21 00:15:46	1.1
+++ LVM2/test/shell/pool-labels.sh	2012/02/23 13:11:10	1.2
@@ -18,6 +18,7 @@
   # printf comes from coreutils, and is probably not posix either
   env printf "\x01\x16\x70\x06\x5f\xcf\xff\xb9\xf8\x24\x8apool1" | dd of=$2 bs=5 seek=1 conv=notrunc
   env printf "\x04\x01\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x0$1\x68\x01\x16\x70\x00\x00\x00\x00\x00\x06\x5f\xd0" | dd of=$2 bs=273 seek=1 conv=notrunc
+  pvscan --lvmetad "$2" || true
 }
 
 env printf "" || exit 200 # skip if printf is not available
--- LVM2/test/shell/vgimportclone.sh	2011/11/21 00:15:46	1.1
+++ LVM2/test/shell/vgimportclone.sh	2012/02/23 13:11:10	1.2
@@ -17,6 +17,7 @@
 
 # Clone the LUN
 dd if=$dev1 of=$dev2 bs=256K count=1
+pvscan --lvmetad $dev2 || true
 
 # Verify pvs works on each device to give us vgname
 check pv_field $dev1 vg_name $vg1
@@ -25,6 +26,13 @@
 # Import the cloned PV to a new VG
 vgimportclone --basevgname $vg2 $dev2
 
+# We need to re-scan *both* $dev1 and $dev2 since a PV, as far as lvmetad is
+# concerned, can only live on a single device. With the last pvscan, we told it
+# that PV from $dev1 now lives on $dev2, but in fact this is not true anymore,
+# since we wrote a different PV over $dev2.
+pvscan --lvmetad $dev2 || true
+pvscan --lvmetad $dev1 || true
+
 # Verify we can activate / deactivate the LV from both VGs
 lvchange -ay $vg1/$lv1 $vg2/$lv1
 vgchange -an $vg1 $vg2
--- LVM2/test/unit/Makefile.in	2012/01/27 10:55:02	1.7
+++ LVM2/test/unit/Makefile.in	2012/02/23 13:11:11	1.8
@@ -25,7 +25,7 @@
 LDLIBS += -ldevmapper @CUNIT_LIBS@
 CFLAGS += @CUNIT_CFLAGS@
 
-all: unit
+check: unit
 
 unit: $(TARGETS)
 	@echo Running unit tests


                 reply	other threads:[~2012-02-23 13:11 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120223131117.27092.qmail@sourceware.org \
    --to=mornfall@sourceware.org \
    --cc=lvm-devel@redhat.com \
    --cc=lvm2-cvs@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).