All of lore.kernel.org
 help / color / mirror / Atom feed
From: mornfall@sourceware.org <mornfall@sourceware.org>
To: lvm-devel@redhat.com
Subject: LVM2 lib/cache/lvmcache.c lib/cache/lvmcache.h ...
Date: 10 Feb 2012 01:28:32 -0000	[thread overview]
Message-ID: <20120210012832.22358.qmail@sourceware.org> (raw)

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mornfall at sourceware.org	2012-02-10 01:28:29

Modified files:
	lib/cache      : lvmcache.c lvmcache.h 
	lib/device     : dev-io.c 
	lib/format1    : disk-rep.c format1.c lvm1-label.c 
	lib/format_pool: disk_rep.c 
	lib/format_text: format-text.c format-text.h import_vsn1.c 
	                 layout.h text_label.c 
	lib/label      : label.c 
	lib/metadata   : metadata.c pv.c vg.c 
	tools          : toollib.c vgrename.c 

Log message:
	Move lvmcache data structures behind an API (making the structures private to
	lvmcache.c). No functional change.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.c.diff?cvsroot=lvm2&r1=1.122&r2=1.123
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.h.diff?cvsroot=lvm2&r1=1.41&r2=1.42
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/device/dev-io.c.diff?cvsroot=lvm2&r1=1.80&r2=1.81
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format1/disk-rep.c.diff?cvsroot=lvm2&r1=1.84&r2=1.85
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format1/format1.c.diff?cvsroot=lvm2&r1=1.140&r2=1.141
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format1/lvm1-label.c.diff?cvsroot=lvm2&r1=1.23&r2=1.24
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_pool/disk_rep.c.diff?cvsroot=lvm2&r1=1.19&r2=1.20
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/format-text.c.diff?cvsroot=lvm2&r1=1.187&r2=1.188
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/format-text.h.diff?cvsroot=lvm2&r1=1.33&r2=1.34
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/import_vsn1.c.diff?cvsroot=lvm2&r1=1.99&r2=1.100
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/layout.h.diff?cvsroot=lvm2&r1=1.13&r2=1.14
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/text_label.c.diff?cvsroot=lvm2&r1=1.40&r2=1.41
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/label/label.c.diff?cvsroot=lvm2&r1=1.55&r2=1.56
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.476&r2=1.477
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/pv.c.diff?cvsroot=lvm2&r1=1.11&r2=1.12
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/vg.c.diff?cvsroot=lvm2&r1=1.14&r2=1.15
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/toollib.c.diff?cvsroot=lvm2&r1=1.239&r2=1.240
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgrename.c.diff?cvsroot=lvm2&r1=1.76&r2=1.77

--- LVM2/lib/cache/lvmcache.c	2012/02/08 12:57:15	1.122
+++ LVM2/lib/cache/lvmcache.c	2012/02/10 01:28:27	1.123
@@ -28,6 +28,43 @@
 #include "format1.h"
 #include "config.h"
 
+#define CACHE_INVALID	0x00000001
+#define CACHE_LOCKED	0x00000002
+
+/* One per device */
+struct lvmcache_info {
+	struct dm_list list;	/* Join VG members together */
+	struct dm_list mdas;	/* list head for metadata areas */
+	struct dm_list das;	/* list head for data areas */
+	struct lvmcache_vginfo *vginfo;	/* NULL == unknown */
+	struct label *label;
+	const struct format_type *fmt;
+	struct device *dev;
+	uint64_t device_size;	/* Bytes */
+	uint32_t status;
+};
+
+/* One per VG */
+struct lvmcache_vginfo {
+	struct dm_list list;	/* Join these vginfos together */
+	struct dm_list infos;	/* List head for lvmcache_infos */
+	const struct format_type *fmt;
+	char *vgname;		/* "" == orphan */
+	uint32_t status;
+	char vgid[ID_LEN + 1];
+	char _padding[7];
+	struct lvmcache_vginfo *next; /* Another VG with same name? */
+	char *creation_host;
+	size_t vgmetadata_size;
+	char *vgmetadata;	/* Copy of VG metadata as format_text string */
+	struct dm_config_tree *cft; /* Config tree created from vgmetadata */
+				    /* Lifetime is directly tied to vgmetadata */
+	struct volume_group *cached_vg;
+	unsigned holders;
+	unsigned vg_use_count;	/* Counter of vg reusage */
+	unsigned precommitted;	/* Is vgmetadata live or precommitted? */
+};
+
 static struct dm_hash_table *_pvid_hash = NULL;
 static struct dm_hash_table *_vgid_hash = NULL;
 static struct dm_hash_table *_vgname_hash = NULL;
@@ -104,7 +141,7 @@
 	char *data;
 	size_t size;
 
-	if (!(vginfo = vginfo_from_vgid((const char *)&vg->id))) {
+	if (!(vginfo = lvmcache_vginfo_from_vgid((const char *)&vg->id))) {
 		stack;
 		return;
 	}
@@ -147,7 +184,7 @@
 	 * Cache becomes invalid whenever lock state changes unless
 	 * exclusive VG_GLOBAL is held (i.e. while scanning).
 	 */
-	if (!vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
+	if (!lvmcache_vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
 		info->status |= CACHE_INVALID;
 		*cached_vgmetadata_valid = 0;
 	}
@@ -176,7 +213,7 @@
 {
 	struct lvmcache_vginfo *vginfo;
 
-	if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
+	if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
 		return;
 
 	_update_cache_vginfo_lock_state(vginfo, locked);
@@ -187,7 +224,7 @@
 	struct lvmcache_vginfo *vginfo;
 	struct lvmcache_info *info;
 
-	if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
+	if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
 		return;
 
 	/*
@@ -220,7 +257,7 @@
 {
 	struct lvmcache_vginfo *vginfo;
 
-	if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
+	if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
 		return;
 
 	if (vginfo->precommitted) {
@@ -240,7 +277,7 @@
 
 		/* Indicate that PVs could now be missing from the cache */
 		init_full_scan_done(0);
-	} else if (!vgname_is_locked(VG_GLOBAL))
+	} else if (!lvmcache_vgname_is_locked(VG_GLOBAL))
 		_drop_metadata(vgname, drop_precommitted);
 }
 
@@ -317,7 +354,7 @@
 		_vgs_locked++;
 }
 
-int vgname_is_locked(const char *vgname)
+int lvmcache_vgname_is_locked(const char *vgname)
 {
 	if (!_lock_hash)
 		return 0;
@@ -340,7 +377,7 @@
 		dev_close_all();
 }
 
-int vgs_locked(void)
+int lvmcache_vgs_locked(void)
 {
 	return _vgs_locked;
 }
@@ -366,12 +403,12 @@
 }
 
 /* If vgid supplied, require a match. */
-struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
+struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname, const char *vgid)
 {
 	struct lvmcache_vginfo *vginfo;
 
 	if (!vgname)
-		return vginfo_from_vgid(vgid);
+		return lvmcache_vginfo_from_vgid(vgid);
 
 	if (!_vgname_hash)
 		return NULL;
@@ -388,7 +425,7 @@
 	return vginfo;
 }
 
-const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels)
+const struct format_type *lvmcache_fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels)
 {
 	struct lvmcache_vginfo *vginfo;
 	struct lvmcache_info *info;
@@ -398,7 +435,7 @@
 	struct device_list *devl;
 	char vgid_found[ID_LEN + 1] __attribute__((aligned(8)));
 
-	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
+	if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
 		return NULL;
 
 	/*
@@ -431,7 +468,7 @@
 	}
 
 	/* If vginfo changed, caller needs to rescan */
-	if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
+	if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid_found)) ||
 	    strncmp(vginfo->vgid, vgid_found, ID_LEN))
 		return NULL;
 
@@ -439,7 +476,7 @@
 	return vginfo->fmt;
 }
 
-struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
+struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid)
 {
 	struct lvmcache_vginfo *vginfo;
 	char id[ID_LEN + 1] __attribute__((aligned(8)));
@@ -457,12 +494,12 @@
 	return vginfo;
 }
 
-const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
+const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid)
 {
 	struct lvmcache_vginfo *vginfo;
 	const char *vgname = NULL;
 
-	if ((vginfo = vginfo_from_vgid(vgid)))
+	if ((vginfo = lvmcache_vginfo_from_vgid(vgid)))
 		vgname = vginfo->vgname;
 
 	if (mem && vgname)
@@ -483,7 +520,7 @@
 	 * So if the VG appears to be unlocked here, it should be safe
 	 * to use the cached value.
 	 */
-	if (info->vginfo && !vgname_is_locked(info->vginfo->vgname))
+	if (info->vginfo && !lvmcache_vgname_is_locked(info->vginfo->vgname))
 		return 1;
 
 	if (!(info->status & CACHE_LOCKED))
@@ -520,7 +557,7 @@
  * If valid_only is set, data will only be returned if the cached data is
  * known still to be valid.
  */
-struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only)
+struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, int valid_only)
 {
 	struct lvmcache_info *info;
 	char id[ID_LEN + 1] __attribute__((aligned(8)));
@@ -545,12 +582,12 @@
 	struct lvmcache_info *info;
 	char *vgname;
 
-	if (!device_from_pvid(cmd, (const struct id *)pvid, NULL, NULL)) {
+	if (!lvmcache_device_from_pvid(cmd, (const struct id *)pvid, NULL, NULL)) {
 		log_error("Couldn't find device with uuid %s.", pvid);
 		return NULL;
 	}
 
-	info = info_from_pvid(pvid, 0);
+	info = lvmcache_info_from_pvid(pvid, 0);
 	if (!info)
 		return_NULL;
 
@@ -644,7 +681,7 @@
 	struct format_instance *fid;
 	struct format_instance_ctx fic;
 
-	if (!vgid || !(vginfo = vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
+	if (!vgid || !(vginfo = lvmcache_vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
 		return NULL;
 
 	if (!_vginfo_is_valid(vginfo))
@@ -708,7 +745,8 @@
 	return NULL;
 }
 
-int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
+// #if 0
+int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
 {
 	log_debug("VG %s decrementing %d holder(s) at %p.",
 		  vginfo->cached_vg->name, vginfo->holders, vginfo->cached_vg);
@@ -731,6 +769,7 @@
 
 	return 1;
 }
+// #endif
 
 struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
 				   int include_internal)
@@ -798,7 +837,7 @@
 		return NULL;
 	}
 
-	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
+	if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
 		return pvids;
 
 	dm_list_iterate_items(info, &vginfo->infos) {
@@ -818,7 +857,7 @@
 	struct lvmcache_info *info;
 	struct label *label;
 
-	if ((info = info_from_pvid((const char *) pvid, 0))) {
+	if ((info = lvmcache_info_from_pvid((const char *) pvid, 0))) {
 		if (label_read(info->dev, &label, UINT64_C(0))) {
 			info = (struct lvmcache_info *) label->info;
 			if (id_equal(pvid, (struct id *) &info->dev->pvid)) {
@@ -831,7 +870,7 @@
 	return NULL;
 }
 
-struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
+struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
 				unsigned *scan_done_once, uint64_t *label_sector)
 {
 	struct device *dev;
@@ -863,7 +902,7 @@
 	return NULL;
 }
 
-const char *pvid_from_devname(struct cmd_context *cmd,
+const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
 			      const char *devname)
 {
 	struct device *dev;
@@ -889,7 +928,7 @@
 
 	_free_cached_vgmetadata(vginfo);
 
-	vginfo2 = primary_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
+	vginfo2 = primary_vginfo = lvmcache_vginfo_from_vgname(vginfo->vgname, NULL);
 
 	if (vginfo == primary_vginfo) {
 		dm_hash_remove(_vgname_hash, vginfo->vgname);
@@ -910,7 +949,7 @@
 	dm_free(vginfo->creation_host);
 
 	if (*vginfo->vgid && _vgid_hash &&
-	    vginfo_from_vgid(vginfo->vgid) == vginfo)
+	    lvmcache_vginfo_from_vgid(vginfo->vgid) == vginfo)
 		dm_hash_remove(_vgid_hash, vginfo->vgid);
 
 	dm_list_del(&vginfo->list);
@@ -959,6 +998,7 @@
 	/*
 	 * Nothing to do if already stored with same pvid.
 	 */
+
 	if (((dm_hash_lookup(_pvid_hash, pvid)) == info) &&
 	    !strcmp(info->dev->pvid, pvid))
 		return 1;
@@ -1110,7 +1150,7 @@
 		_drop_vginfo(info, info->vginfo);
 
 	/* Get existing vginfo or create new one */
-	if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
+	if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
 /*** FIXME - vginfo ends up duplicated instead of renamed.
 		// Renaming?  This lookup fails.
 		if ((vginfo = vginfo_from_vgid(vgid))) {
@@ -1162,9 +1202,9 @@
 		 * If we're scanning and there's an invalidated entry, remove it.
 		 * Otherwise we risk bogus warnings of duplicate VGs.
 		 */
-		while ((primary_vginfo = vginfo_from_vgname(vgname, NULL)) &&
+		while ((primary_vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)) &&
 		       _scanning_in_progress && _vginfo_is_invalid(primary_vginfo)) {
-			orphan_vginfo = vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
+			orphan_vginfo = lvmcache_vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
 			if (!orphan_vginfo) {
 				log_error(INTERNAL_ERROR "Orphan vginfo %s lost from cache.",
 					  primary_vginfo->fmt->orphan_vg_name);
@@ -1212,7 +1252,7 @@
 	else if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) /* Orphans */
 		return_0;
 
-	_update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname));
+	_update_cache_vginfo_lock_state(vginfo, lvmcache_vgname_is_locked(vgname));
 
 	/* FIXME Check consistency of list! */
 	vginfo->fmt = fmt;
@@ -1282,6 +1322,8 @@
 				  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 */
@@ -1319,7 +1361,7 @@
 	dm_list_iterate_items(pvl, &vg->pvs) {
 		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)) &&
+		if ((info = lvmcache_info_from_pvid(pvid_s, 0)) &&
 		    !lvmcache_update_vgname_and_id(info, vg->name,
 						   (char *) &vg->id,
 						   vg->status, NULL))
@@ -1350,8 +1392,8 @@
 	strncpy(pvid_s, pvid, sizeof(pvid_s) - 1);
 	pvid_s[sizeof(pvid_s) - 1] = '\0';
 
-	if (!(existing = info_from_pvid(pvid_s, 0)) &&
-	    !(existing = info_from_pvid(dev->pvid, 0))) {
+	if (!(existing = lvmcache_info_from_pvid(pvid_s, 0)) &&
+	    !(existing = lvmcache_info_from_pvid(dev->pvid, 0))) {
 		if (!(label = label_create(labeller)))
 			return_NULL;
 		if (!(info = dm_zalloc(sizeof(*info)))) {
@@ -1520,3 +1562,259 @@
 	if (retain_orphans)
 		init_lvmcache_orphans(cmd);
 }
+
+int lvmcache_pvid_is_locked(const char *pvid) {
+	struct lvmcache_info *info;
+	info = lvmcache_info_from_pvid(pvid, 0);
+	if (!info || !info->vginfo)
+		return 0;
+
+	return lvmcache_vgname_is_locked(info->vginfo->vgname);
+}
+
+int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
+			  const char *id, int id_len)
+{
+	return fid_add_mdas(fid, &info->mdas, id, id_len);
+}
+
+int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid)
+{
+	return lvmcache_fid_add_mdas(info, fid, info->dev->pvid, ID_LEN);
+}
+
+int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_instance *fid)
+{
+	struct lvmcache_info *info;
+	dm_list_iterate_items(info, &vginfo->infos) {
+		if (!lvmcache_fid_add_mdas_pv(info, fid))
+			return_0;
+	}
+	return 1;
+}
+
+static int _get_pv_if_in_vg(struct lvmcache_info *info,
+			    struct physical_volume *pv)
+{
+	char vgname[NAME_LEN + 1];
+	char vgid[ID_LEN + 1];
+
+	if (info->vginfo && info->vginfo->vgname &&
+	    !is_orphan_vg(info->vginfo->vgname)) {
+		/*
+		 * get_pv_from_vg_by_id() may call
+		 * lvmcache_label_scan() and drop cached
+		 * vginfo so make a local copy of string.
+		 */
+		strcpy(vgname, info->vginfo->vgname);
+		memcpy(vgid, info->vginfo->vgid, sizeof(vgid));
+
+		if (get_pv_from_vg_by_id(info->fmt, vgname, vgid,
+					 info->dev->pvid, pv))
+			return 1;
+	}
+
+	return 0;
+}
+
+int lvmcache_populate_pv_fields(struct lvmcache_info *info,
+				struct physical_volume *pv,
+				int scan_label_only)
+{
+	struct data_area_list *da;
+
+	/* Have we already cached vgname? */
+	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))
+			return 1;
+	}
+
+	/* Orphan */
+	pv->dev = info->dev;
+	pv->fmt = info->fmt;
+	pv->size = info->device_size >> SECTOR_SHIFT;
+	pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
+	memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
+
+	/* Currently only support exactly one data area */
+	if (dm_list_size(&info->das) != 1) {
+		log_error("Must be exactly one data area (found %d) on PV %s",
+			  dm_list_size(&info->das), dev_name(info->dev));
+		return 0;
+	}
+
+	dm_list_iterate_items(da, &info->das)
+		pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
+
+	return 1;
+}
+
+int lvmcache_check_format(struct lvmcache_info *info, const struct format_type *fmt)
+{
+	if (info->fmt != fmt) {
+		log_error("PV %s is a different format (seqno %s)",
+			  dev_name(info->dev), info->fmt->name);
+		return 0;
+	}
+	return 1;
+}
+
+void lvmcache_del_mdas(struct lvmcache_info *info)
+{
+	if (info->mdas.n)
+		del_mdas(&info->mdas);
+	dm_list_init(&info->mdas);
+}
+
+void lvmcache_del_das(struct lvmcache_info *info)
+{
+	if (info->das.n)
+		del_das(&info->das);
+	dm_list_init(&info->das);
+}
+
+int lvmcache_add_mda(struct lvmcache_info *info, struct device *dev,
+		     uint64_t start, uint64_t size, unsigned ignored)
+{
+	return add_mda(info->fmt, NULL, &info->mdas, dev, start, size, ignored);
+}
+
+int lvmcache_add_da(struct lvmcache_info *info, uint64_t start, uint64_t size)
+{
+	return add_da(NULL, &info->das, start, size);
+}
+
+
+void lvmcache_update_pv(struct lvmcache_info *info, struct physical_volume *pv,
+			const struct format_type *fmt)
+{
+	info->device_size = pv->size << SECTOR_SHIFT;
+	info->fmt = fmt;
+}
+
+int lvmcache_update_das(struct lvmcache_info *info, struct physical_volume *pv)
+{
+	struct data_area_list *da;
+	if (info->das.n) {
+		if (!pv->pe_start)
+			dm_list_iterate_items(da, &info->das)
+				pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
+		del_das(&info->das);
+	} else
+		dm_list_init(&info->das);
+
+	if (!add_da(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
+		return_0;
+
+	return 1;
+}
+
+int lvmcache_foreach_pv(struct lvmcache_vginfo *vginfo,
+			int (*fun)(struct lvmcache_info *, void *),
+			void *baton)
+{
+	struct lvmcache_info *info;
+	dm_list_iterate_items(info, &vginfo->infos) {
+		if (!fun(info, baton))
+			return_0;
+	}
+
+	return 1;
+}
+
+int lvmcache_foreach_mda(struct lvmcache_info *info,
+			 int (*fun)(struct metadata_area *, void *),
+			 void *baton)
+{
+	struct metadata_area *mda;
+	dm_list_iterate_items(mda, &info->mdas) {
+		if (!fun(mda, baton))
+			return_0;
+	}
+
+	return 1;
+}
+
+int lvmcache_mda_count(struct lvmcache_info *info)
+{
+	return dm_list_size(&info->mdas);
+}
+
+int lvmcache_foreach_da(struct lvmcache_info *info,
+			int (*fun)(struct data_area_list *, void *),
+			void *baton)
+{
+	struct data_area_list *da;
+	dm_list_iterate_items(da, &info->das) {
+		if (!fun(da, baton))
+			return_0;
+	}
+
+	return 1;
+}
+
+/*
+ * The lifetime of the label returned is tied to the lifetime of the
+ * lvmcache_info which is the same as lvmcache itself.
+ */
+struct label *lvmcache_get_label(struct lvmcache_info *info) {
+	return info->label;
+}
+
+void lvmcache_make_valid(struct lvmcache_info *info) {
+	info->status &= ~CACHE_INVALID;
+}
+
+uint64_t lvmcache_device_size(struct lvmcache_info *info) {
+	return info->device_size;
+}
+
+void lvmcache_set_device_size(struct lvmcache_info *info, uint64_t size) {
+	info->device_size = size;
+}
+
+struct device *lvmcache_device(struct lvmcache_info *info) {
+	return info->dev;
+}
+
+int lvmcache_is_orphan(struct lvmcache_info *info) {
+	if (!info->vginfo)
+		return 1; /* FIXME? */
+	return is_orphan_vg(info->vginfo->vgname);
+}
+
+int lvmcache_vgid_is_cached(const char *vgid) {
+	struct lvmcache_vginfo *vginfo;
+	vginfo = lvmcache_vginfo_from_vgid(vgid);
+
+	if (!vginfo || !vginfo->vgname)
+		return 0;
+
+	if (is_orphan_vg(vginfo->vgname))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Return true iff it is impossible to find out from this info alone whether the
+ * PV in question is or is not an orphan.
+ */
+int lvmcache_uncertain_ownership(struct lvmcache_info *info) {
+	return mdas_empty_or_ignored(&info->mdas);
+}
+
+int lvmcache_smallest_mda_size(struct lvmcache_info *info)
+{
+	return find_min_mda_size(&info->mdas);
+}
+
+const struct format_type *lvmcache_fmt(struct lvmcache_info *info) {
+	return info->fmt;
+}
--- LVM2/lib/cache/lvmcache.h	2011/08/30 14:55:16	1.41
+++ LVM2/lib/cache/lvmcache.h	2012/02/10 01:28:27	1.42
@@ -24,50 +24,19 @@
 #define ORPHAN_PREFIX VG_ORPHANS
 #define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "_" fmt
 
-#define CACHE_INVALID	0x00000001
-#define CACHE_LOCKED	0x00000002
-
 /* LVM specific per-volume info */
 /* Eventual replacement for struct physical_volume perhaps? */
 
 struct cmd_context;
 struct format_type;
 struct volume_group;
+struct physical_volume;
 struct dm_config_tree;
+struct format_instance;
+struct metadata_area;
+struct data_area_list;
 
-/* One per VG */
-struct lvmcache_vginfo {
-	struct dm_list list;	/* Join these vginfos together */
-	struct dm_list infos;	/* List head for lvmcache_infos */
-	const struct format_type *fmt;
-	char *vgname;		/* "" == orphan */
-	uint32_t status;
-	char vgid[ID_LEN + 1];
-	char _padding[7];
-	struct lvmcache_vginfo *next; /* Another VG with same name? */
-	char *creation_host;
-	size_t vgmetadata_size;
-	char *vgmetadata;	/* Copy of VG metadata as format_text string */
-	struct dm_config_tree *cft; /* Config tree created from vgmetadata */
-				    /* Lifetime is directly tied to vgmetadata */
-	struct volume_group *cached_vg;
-	unsigned holders;
-	unsigned vg_use_count;	/* Counter of vg reusage */
-	unsigned precommitted;	/* Is vgmetadata live or precommitted? */
-};
-
-/* One per device */
-struct lvmcache_info {
-	struct dm_list list;	/* Join VG members together */
-	struct dm_list mdas;	/* list head for metadata areas */
-	struct dm_list das;	/* list head for data areas */
-	struct lvmcache_vginfo *vginfo;	/* NULL == unknown */
-	struct label *label;
-	const struct format_type *fmt;
-	struct device *dev;
-	uint64_t device_size;	/* Bytes */
-	uint32_t status;
-};
+struct lvmcache_vginfo;
 
 int lvmcache_init(void);
 void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
@@ -95,21 +64,23 @@
 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 *lvmcache_fmt_from_vgname(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,
+int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
+
+struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
 					   const char *vgid);
-struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
-struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only);
-const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
-struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
+struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
+struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, int valid_only);
+const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
+struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
 				unsigned *scan_done_once, uint64_t *label_sector);
-const char *pvid_from_devname(struct cmd_context *cmd,
+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);
-int vgs_locked(void);
-int vgname_is_locked(const char *vgname);
+int lvmcache_vgs_locked(void);
+int lvmcache_vgname_is_locked(const char *vgname);
 
 /* Returns list of struct str_lists containing pool-allocated copy of vgnames */
 /* If include_internal is not set, return only proper vg names. */
@@ -130,4 +101,46 @@
 void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
 void lvmcache_commit_metadata(const char *vgname);
 
+int lvmcache_pvid_is_locked(const char *pvid);
+int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
+			  const char *id, int id_len);
+int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid);
+int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_instance *fid);
+int lvmcache_populate_pv_fields(struct lvmcache_info *info,
+				struct physical_volume *pv,
+				int scan_label_only);
+int lvmcache_check_format(struct lvmcache_info *info, const struct format_type *fmt);
+void lvmcache_del_mdas(struct lvmcache_info *info);
+void lvmcache_del_das(struct lvmcache_info *info);
+int lvmcache_add_mda(struct lvmcache_info *info, struct device *dev,
+		     uint64_t start, uint64_t size, unsigned ignored);
+int lvmcache_add_da(struct lvmcache_info *info, uint64_t start, uint64_t size);
+
+const struct format_type *lvmcache_fmt(struct lvmcache_info *info);
+struct label *lvmcache_get_label(struct lvmcache_info *info);
+
+void lvmcache_update_pv(struct lvmcache_info *info, struct physical_volume *pv,
+			const struct format_type *fmt);
+int lvmcache_update_das(struct lvmcache_info *info, struct physical_volume *pv);
+int lvmcache_foreach_mda(struct lvmcache_info *info,
+			 int (*fun)(struct metadata_area *, void *),
+			 void *baton);
+
+int lvmcache_foreach_da(struct lvmcache_info *info,
+			int (*fun)(struct data_area_list *, void *),
+			void *baton);
+
+int lvmcache_foreach_pv(struct lvmcache_vginfo *vg,
+			int (*fun)(struct lvmcache_info *, void *), void * baton);
+
+uint64_t lvmcache_device_size(struct lvmcache_info *info);
+void lvmcache_set_device_size(struct lvmcache_info *info, uint64_t size);
+struct device *lvmcache_device(struct lvmcache_info *info);
+void lvmcache_make_valid(struct lvmcache_info *info);
+int lvmcache_is_orphan(struct lvmcache_info *info);
+int lvmcache_uncertain_ownership(struct lvmcache_info *info);
+int lvmcache_mda_count(struct lvmcache_info *info);
+int lvmcache_vgid_is_cached(const char *vgid);
+int lvmcache_smallest_mda_size(struct lvmcache_info *info);
+
 #endif
--- LVM2/lib/device/dev-io.c	2012/02/08 11:15:38	1.80
+++ LVM2/lib/device/dev-io.c	2012/02/10 01:28:27	1.81
@@ -586,7 +586,6 @@
 
 static int _dev_close(struct device *dev, int immediate)
 {
-	struct lvmcache_info *info;
 
 	if (dev->fd < 0) {
 		log_error("Attempt to close device '%s' "
@@ -608,10 +607,7 @@
 
 	/* Close unless device is known to belong to a locked VG */
 	if (immediate ||
-	    (dev->open_count < 1 &&
-	     (!(info = info_from_pvid(dev->pvid, 0)) ||
-	      !info->vginfo ||
-	      !vgname_is_locked(info->vginfo->vgname))))
+	    (dev->open_count < 1 && !lvmcache_pvid_is_locked(dev->pvid)))
 		_close(dev);
 
 	return 1;
--- LVM2/lib/format1/disk-rep.c	2011/05/28 09:48:15	1.84
+++ LVM2/lib/format1/disk-rep.c	2012/02/10 01:28:28	1.85
@@ -335,9 +335,9 @@
 		return;
 	}
 
-	info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
-	dm_list_init(&info->mdas);
-	info->status &= ~CACHE_INVALID;
+	lvmcache_set_device_size(info, xlate32(dl->pvd.pv_size) << SECTOR_SHIFT);
+	lvmcache_del_mdas(info);
+	lvmcache_make_valid(info);
 }
 
 static struct disk_list *__read_disk(const struct format_type *fmt,
@@ -451,6 +451,28 @@
 	dm_list_add(head, &data->list);
 }
 
+struct _read_pvs_in_vg_baton {
+	const char *vg_name;
+	struct dm_list *head;
+	struct disk_list *data;
+	struct dm_pool *mem;
+	int empty;
+};
+
+static int _read_pv_in_vg(struct lvmcache_info *info, void *baton)
+{
+	struct _read_pvs_in_vg_baton *b = baton;
+
+	b->empty = 0;
+
+	if (!lvmcache_device(info) ||
+	    !(b->data = read_disk(lvmcache_fmt(info), lvmcache_device(info), b->mem, b->vg_name)))
+		return 0; /* stop here */
+
+	_add_pv_to_list(b->head, b->data);
+	return 1;
+}
+
 /*
  * Build a list of pv_d's structures, allocated from mem.
  * We keep track of the first object allocated from the pool
@@ -462,29 +484,31 @@
 {
 	struct dev_iter *iter;
 	struct device *dev;
-	struct disk_list *data = NULL;
 	struct lvmcache_vginfo *vginfo;
-	struct lvmcache_info *info;
+	struct _read_pvs_in_vg_baton baton;
+
+	baton.head = head;
+	baton.empty = 1;
+	baton.data = NULL;
+	baton.mem = mem;
+	baton.vg_name = vg_name;
 
 	/* Fast path if we already saw this VG and cached the list of PVs */
-	if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
-	    vginfo->infos.n) {
-		dm_list_iterate_items(info, &vginfo->infos) {
-			dev = info->dev;
-			if (!dev || !(data = read_disk(fmt, dev, mem, vg_name)))
-				break;
-			_add_pv_to_list(head, data);
-		}
+	if (vg_name && (vginfo = lvmcache_vginfo_from_vgname(vg_name, NULL))) {
+
+		lvmcache_foreach_pv(vginfo, _read_pv_in_vg, &baton);
 
-		/* Did we find the whole VG? */
-		if (!vg_name || is_orphan_vg(vg_name) ||
-		    (data && *data->pvd.vg_name &&
-		     dm_list_size(head) == data->vgd.pv_cur))
-			return 1;
-
-		/* Failed */
-		dm_list_init(head);
-		/* vgcache_del(vg_name); */
+		if (!baton.empty) {
+			/* Did we find the whole VG? */
+			if (!vg_name || is_orphan_vg(vg_name) ||
+			    (baton.data && *baton.data->pvd.vg_name &&
+			     dm_list_size(head) == baton.data->vgd.pv_cur))
+				return 1;
+
+			/* Failed */
+			dm_list_init(head);
+			/* vgcache_del(vg_name); */
+		}
 	}
 
 	if (!(iter = dev_iter_create(filter, 1))) {
@@ -494,8 +518,8 @@
 
 	/* Otherwise do a complete scan */
 	for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
-		if ((data = read_disk(fmt, dev, mem, vg_name))) {
-			_add_pv_to_list(head, data);
+		if ((baton.data = read_disk(fmt, dev, mem, vg_name))) {
+			_add_pv_to_list(head, baton.data);
 		}
 	}
 	dev_iter_destroy(iter);
--- LVM2/lib/format1/format1.c	2012/02/08 10:49:36	1.140
+++ LVM2/lib/format1/format1.c	2012/02/10 01:28:28	1.141
@@ -413,10 +413,8 @@
 				  pv->vg_name, NULL, 0)))
 		return_0;
 
-	info->device_size = pv->size << SECTOR_SHIFT;
-	info->fmt = fmt;
-
-	dm_list_init(&info->mdas);
+	lvmcache_update_pv(info, pv, fmt);
+	lvmcache_del_mdas(info);
 
 	dm_list_init(&pvs);
 
--- LVM2/lib/format1/lvm1-label.c	2010/07/09 15:34:44	1.23
+++ LVM2/lib/format1/lvm1-label.c	2012/02/10 01:28:28	1.24
@@ -77,12 +77,11 @@
 	if (!(info = lvmcache_add(l, (char *)pvd->pv_uuid, dev, vgname, vgid,
 				  exported)))
 		return_0;
-	*label = info->label;
+	*label = lvmcache_get_label(info);
 
-	info->device_size = xlate32(pvd->pv_size) << SECTOR_SHIFT;
-	dm_list_init(&info->mdas);
-
-	info->status &= ~CACHE_INVALID;
+	lvmcache_set_device_size(info, xlate32(pvd->pv_size) << SECTOR_SHIFT);
+	lvmcache_del_mdas(info);
+	lvmcache_make_valid(info);
 
 	return 1;
 }
--- LVM2/lib/format_pool/disk_rep.c	2011/05/28 09:48:15	1.19
+++ LVM2/lib/format_pool/disk_rep.c	2012/02/10 01:28:28	1.20
@@ -101,12 +101,11 @@
 				  (char *) &vgid, 0)))
 		return_0;
 	if (label)
-		*label = info->label;
+		*label = lvmcache_get_label(info);
 
-	info->device_size = xlate32_be(pd->pl_blocks) << SECTOR_SHIFT;
-	dm_list_init(&info->mdas);
-
-	info->status &= ~CACHE_INVALID;
+	lvmcache_set_device_size(info, xlate32_be(pd->pl_blocks) << SECTOR_SHIFT);
+	lvmcache_del_mdas(info);
+	lvmcache_make_valid(info);
 
 	pl->dev = dev;
 	pl->pv = NULL;
@@ -236,68 +235,92 @@
 
 }
 
-static int _read_vg_pds(const struct format_type *fmt, struct dm_pool *mem,
-			struct lvmcache_vginfo *vginfo, struct dm_list *head,
-			uint32_t *devcount)
+struct _read_pool_pv_baton {
+	const struct format_type *fmt;
+	struct dm_pool *mem, *tmpmem;
+	struct pool_list *pl;
+	struct dm_list *head;
+	const char *vgname;
+	uint32_t *sp_devs;
+	int sp_count;
+	int failed;
+	int empty;
+};
+
+static int _read_pool_pv(struct lvmcache_info *info, void *baton)
 {
-	struct lvmcache_info *info;
-	struct pool_list *pl = NULL;
-	struct dm_pool *tmpmem;
+	struct _read_pool_pv_baton *b = baton;
+
+	b->empty = 0;
+
+	if (lvmcache_device(info) &&
+	    !(b->pl = read_pool_disk(b->fmt, lvmcache_device(info), b->mem, b->vgname)))
+		return 0;
+
+	/*
+	 * We need to keep track of the total expected number
+	 * of devices per subpool
+	 */
+	if (!b->sp_count) {
+		/* FIXME pl left uninitialised if !info->dev */
+		if (!b->pl) {
+			log_error(INTERNAL_ERROR "device is missing");
+			dm_pool_destroy(b->tmpmem);
+			b->failed = 1;
+			return 0;
+		}
+		b->sp_count = b->pl->pd.pl_subpools;
+		if (!(b->sp_devs =
+		      dm_pool_zalloc(b->tmpmem,
+				     sizeof(uint32_t) * b->sp_count))) {
+			log_error("Unable to allocate %d 32-bit uints",
+				  b->sp_count);
+			dm_pool_destroy(b->tmpmem);
+			b->failed = 1;
+			return 0;
+		}
+	}
+
+	/*
+	 * watch out for a pool label with a different subpool
+	 * count than the original - give up if it does
+	 */
+	if (b->sp_count != b->pl->pd.pl_subpools)
+		return 0;
+
+	_add_pl_to_list(b->head, b->pl);
 
-	uint32_t sp_count = 0;
-	uint32_t *sp_devs = NULL;
+	if (b->sp_count > b->pl->pd.pl_sp_id && b->sp_devs[b->pl->pd.pl_sp_id] == 0)
+		b->sp_devs[b->pl->pd.pl_sp_id] = b->pl->pd.pl_sp_devs;
+
+	return 1;
+}
+
+static int _read_vg_pds(struct _read_pool_pv_baton *b,
+			struct lvmcache_vginfo *vginfo,
+			uint32_t *devcount)
+{
 	uint32_t i;
 
+	b->sp_count = 0;
+	b->sp_devs = NULL;
+	b->failed = 0;
+	b->pl = NULL;
+
 	/* FIXME: maybe should return a different error in memory
 	 * allocation failure */
-	if (!(tmpmem = dm_pool_create("pool read_vg", 512)))
+	if (!(b->tmpmem = dm_pool_create("pool read_vg", 512)))
 		return_0;
 
-	dm_list_iterate_items(info, &vginfo->infos) {
-		if (info->dev &&
-		    !(pl = read_pool_disk(fmt, info->dev, mem, vginfo->vgname)))
-			    break;
-		/*
-		 * We need to keep track of the total expected number
-		 * of devices per subpool
-		 */
-		if (!sp_count) {
-			/* FIXME pl left uninitialised if !info->dev */
-			if (!pl) {
-				log_error(INTERNAL_ERROR "device is missing");
-				dm_pool_destroy(tmpmem);
-				return 0;
-			}
-			sp_count = pl->pd.pl_subpools;
-			if (!(sp_devs =
-			      dm_pool_zalloc(tmpmem,
-					  sizeof(uint32_t) * sp_count))) {
-				log_error("Unable to allocate %d 32-bit uints",
-					  sp_count);
-				dm_pool_destroy(tmpmem);
-				return 0;
-			}
-		}
-		/*
-		 * watch out for a pool label with a different subpool
-		 * count than the original - give up if it does
-		 */
-		if (sp_count != pl->pd.pl_subpools)
-			break;
-
-		_add_pl_to_list(head, pl);
-
-		if (sp_count > pl->pd.pl_sp_id && sp_devs[pl->pd.pl_sp_id] == 0)
-			sp_devs[pl->pd.pl_sp_id] = pl->pd.pl_sp_devs;
-	}
+	lvmcache_foreach_pv(vginfo, _read_pool_pv, b);
 
 	*devcount = 0;
-	for (i = 0; i < sp_count; i++)
-		*devcount += sp_devs[i];
+	for (i = 0; i < b->sp_count; i++)
+		*devcount += b->sp_devs[i];
 
-	dm_pool_destroy(tmpmem);
+	dm_pool_destroy(b->tmpmem);
 
-	if (pl && *pl->pd.pl_pool_name)
+	if (b->pl && *b->pl->pd.pl_pool_name)
 		return 1;
 
 	return 0;
@@ -311,29 +334,36 @@
 	uint32_t totaldevs;
 	int full_scan = -1;
 
+	struct _read_pool_pv_baton baton;
+
+	baton.vgname = vg_name;
+	baton.mem = mem;
+	baton.fmt = fmt;
+	baton.head = pdhead;
+	baton.empty = 1;
+
 	do {
 		/*
 		 * If the cache scanning doesn't work, this will never work
 		 */
-		if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
-		    vginfo->infos.n) {
-
-			if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
-				/*
-				 * If we found all the devices we were
-				 * expecting, return success
-				 */
-				if (dm_list_size(pdhead) == totaldevs)
-					return 1;
-
-				/*
-				 * accept partial pool if we've done a full
-				 * rescan of the cache
-				 */
-				if (full_scan > 0)
-					return 1;
-			}
+		if (vg_name && (vginfo = lvmcache_vginfo_from_vgname(vg_name, NULL)) &&
+		    _read_vg_pds(&baton, vginfo, &totaldevs) && !baton.empty)
+		{
+			/*
+			 * If we found all the devices we were expecting, return
+			 * success
+			 */
+			if (dm_list_size(pdhead) == totaldevs)
+				return 1;
+
+			/*
+			 * accept partial pool if we've done a full rescan of
+			 * the cache
+			 */
+			if (full_scan > 0)
+				return 1;
 		}
+
 		/* Failed */
 		dm_list_init(pdhead);
 
--- LVM2/lib/format_text/format-text.c	2012/02/08 10:49:36	1.187
+++ LVM2/lib/format_text/format-text.c	2012/02/10 01:28:28	1.188
@@ -432,7 +432,7 @@
 			  "not match expected name %s.", vgname);
 
       bad:
-	if ((info = info_from_pvid(dev_area->dev->pvid, 0)))
+	if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, 0)))
 		lvmcache_update_vgname_and_id(info, FMT_TEXT_ORPHAN_VG_NAME,
 					      FMT_TEXT_ORPHAN_VG_NAME, 0, NULL);
 
@@ -1251,6 +1251,33 @@
 	return (_scan_file(fmt, vgname) & _scan_raw(fmt, vgname));
 }
 
+struct _write_single_mda_baton {
+	const struct format_type *fmt;
+	struct physical_volume *pv;
+};
+
+static int _write_single_mda(struct metadata_area *mda, void *baton)
+{
+	struct _write_single_mda_baton *p = baton;
+	struct mda_context *mdac;
+
+	char buf[MDA_HEADER_SIZE] __attribute__((aligned(8)));
+	struct mda_header *mdah = (struct mda_header *) buf;
+
+	mdac = mda->metadata_locn;
+	memset(&buf, 0, sizeof(buf));
+	mdah->size = mdac->area.size;
+	rlocn_set_ignored(mdah->raw_locns, mda_is_ignored(mda));
+
+	if (!_raw_write_mda_header(p->fmt, mdac->area.dev,
+				   mdac->area.start, mdah)) {
+		if (!dev_close(p->pv->dev))
+			stack;
+		return_0;
+	}
+	return 1;
+}
+
 /* Only for orphans */
 static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv)
 {
@@ -1260,27 +1287,21 @@
 	struct lvmcache_info *info;
 	struct mda_context *mdac;
 	struct metadata_area *mda;
+	struct _write_single_mda_baton baton;
 	unsigned mda_index;
-	char buf[MDA_HEADER_SIZE] __attribute__((aligned(8)));
-	struct mda_header *mdah = (struct mda_header *) buf;
-	struct data_area_list *da;
 
 	/* Add a new cache entry with PV info or update existing one. */
 	if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,
 				  pv->dev, pv->vg_name, NULL, 0)))
 		return_0;
 
-	label = info->label;
+	label = lvmcache_get_label(info);
 	label->sector = pv->label_sector;
 
-	info->device_size = pv->size << SECTOR_SHIFT;
-	info->fmt = fmt;
+	lvmcache_update_pv(info, pv, fmt);
 
 	/* Flush all cached metadata areas, we will reenter new/modified ones. */
-	if (info->mdas.n)
-		del_mdas(&info->mdas);
-	else
-		dm_list_init(&info->mdas);
+	lvmcache_del_mdas(info);
 
 	/*
 	 * Add all new or modified metadata areas for this PV stored in
@@ -1299,8 +1320,10 @@
 			  dev_name(mdac->area.dev),
 			  mdac->area.start >> SECTOR_SHIFT,
 			  mdac->area.size >> SECTOR_SHIFT);
-		add_mda(fmt, NULL, &info->mdas, mdac->area.dev,
-			mdac->area.start, mdac->area.size, mda_is_ignored(mda));
+
+		// if fmt is not the same as info->fmt we are in trouble
+		lvmcache_add_mda(info, mdac->area.dev,
+				 mdac->area.start, mdac->area.size, mda_is_ignored(mda));
 	}
 
 	/*
@@ -1318,34 +1341,20 @@
 	 * pvcreate --restorefile. However, we can can have this value in
 	 * metadata which will override the value in the PV header.
 	 */
-	if (info->das.n) {
-		if (!pv->pe_start)
-			dm_list_iterate_items(da, &info->das)
-				pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
-		del_das(&info->das);
-	} else
-		dm_list_init(&info->das);
 
-	if (!add_da(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
+	if (!lvmcache_update_das(info, pv))
 		return_0;
 
 	if (!dev_open(pv->dev))
 		return_0;
 
-	dm_list_iterate_items(mda, &info->mdas) {
-		mdac = mda->metadata_locn;
-		memset(&buf, 0, sizeof(buf));
-		mdah->size = mdac->area.size;
-		rlocn_set_ignored(mdah->raw_locns, mda_is_ignored(mda));
-		if (!_raw_write_mda_header(fmt, mdac->area.dev,
-					   mdac->area.start, mdah)) {
-			if (!dev_close(pv->dev))
-				stack;
-			return_0;
-		}
-	}
+	baton.pv = pv;
+	baton.fmt = fmt;
+
+	if (!lvmcache_foreach_mda(info, _write_single_mda, &baton))
+		return_0;
 
-	if (!label_write(pv->dev, info->label)) {
+	if (!label_write(pv->dev, label)) {
 		dev_close(pv->dev);
 		return_0;
 	}
@@ -1384,68 +1393,6 @@
 	return 1;
 }
 
-static int _get_pv_if_in_vg(struct lvmcache_info *info,
-			    struct physical_volume *pv)
-{
-	char vgname[NAME_LEN + 1];
-	char vgid[ID_LEN + 1];
-
-	if (info->vginfo && info->vginfo->vgname &&
-	    !is_orphan_vg(info->vginfo->vgname)) {
-		/*
-		 * get_pv_from_vg_by_id() may call
-		 * lvmcache_label_scan() and drop cached
-		 * vginfo so make a local copy of string.
-		 */
-		strcpy(vgname, info->vginfo->vgname);
-		memcpy(vgid, info->vginfo->vgid, sizeof(vgid));
-
-		if (get_pv_from_vg_by_id(info->fmt, vgname, vgid,
-					 info->dev->pvid, pv))
-			return 1;
-	}
-
-	return 0;
-}
-
-static int _populate_pv_fields(struct lvmcache_info *info,
-			       struct physical_volume *pv,
-			       int scan_label_only)
-{
-	struct data_area_list *da;
-
-	/* Have we already cached vgname? */
-	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))
-			return 1;
-	}
-
-	/* Orphan */
-	pv->dev = info->dev;
-	pv->fmt = info->fmt;
-	pv->size = info->device_size >> SECTOR_SHIFT;
-	pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
-	memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
-
-	/* Currently only support exactly one data area */
-	if (dm_list_size(&info->das) != 1) {
-		log_error("Must be exactly one data area (found %d) on PV %s",
-			  dm_list_size(&info->das), dev_name(info->dev));
-		return 0;
-	}
-
-	dm_list_iterate_items(da, &info->das)
-		pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
-
-	return 1;
-}
-
 /*
  * Copy constructor for a metadata_locn.
  */
@@ -1485,16 +1432,14 @@
 {
 	struct label *label;
 	struct device *dev;
-	struct lvmcache_info *info;
 
 	if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
 		return_0;
 
 	if (!(label_read(dev, &label, UINT64_C(0))))
 		return_0;
-	info = (struct lvmcache_info *) label->info;
 
-	if (!_populate_pv_fields(info, pv, scan_label_only))
+	if (!lvmcache_populate_pv_fields(label->info, pv, scan_label_only))
 		return 0;
 
 	return 1;
@@ -1670,18 +1615,15 @@
 	 * reread PV mda information from the cache and add it to vg->fid.
 	 */
 	else {
-		if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
+		if (!(info = lvmcache_info_from_pvid(pv->dev->pvid, 0))) {
 			log_error("PV %s missing from cache", pv_dev_name(pv));
 			return 0;
 		}
 
-		if (fmt != info->fmt) {
-			log_error("PV %s is a different format (seqno %s)",
-				  pv_dev_name(pv), info->fmt->name);
-			return 0;
-		}
+		if (!lvmcache_check_format(info, fmt))
+			return_0;
 
-		if (!fid_add_mdas(vg->fid, &info->mdas, pvid, ID_LEN))
+		if (!lvmcache_fid_add_mdas_pv(info, fid))
 			return_0;
 	}
 
@@ -1736,8 +1678,8 @@
 	}
 
 	if (fic->type & FMT_INSTANCE_MDAS &&
-	    (info = info_from_pvid(fic->context.pv_id, 0)))
-		fid_add_mdas(fid, &info->mdas, fic->context.pv_id, ID_LEN);
+	    (info = lvmcache_info_from_pvid(fic->context.pv_id, 0)))
+		lvmcache_fid_add_mdas_pv(info, fid);
 
 	return 1;
 }
@@ -1801,7 +1743,6 @@
 	struct dm_list *dir_list, *raw_list;
 	struct text_context tc;
 	struct lvmcache_vginfo *vginfo;
-	struct lvmcache_info *info;
 	const char *vg_name, *vg_id;
 
 	if (!(fidtc = (struct text_fid_context *)
@@ -1873,12 +1814,10 @@
 		if (type & FMT_INSTANCE_MDAS) {
 			/* Scan PVs in VG for any further MDAs */
 			lvmcache_label_scan(fid->fmt->cmd, 0);
-			if (!(vginfo = vginfo_from_vgname(vg_name, vg_id)))
+			if (!(vginfo = lvmcache_vginfo_from_vgname(vg_name, vg_id)))
+				goto_out;
+			if (!lvmcache_fid_add_mdas_vg(vginfo, fid))
 				goto_out;
-			dm_list_iterate_items(info, &vginfo->infos) {
-				if (!fid_add_mdas(fid, &info->mdas, info->dev->pvid, ID_LEN))
-					return_0;
-			}
 		}
 
 		/* FIXME Check raw metadata area count - rescan if required */
@@ -2314,7 +2253,7 @@
 		return 0;
 	}
 
-	if (!(dev_area.dev = device_from_pvid(cmd, &id, NULL, NULL))) {
+	if (!(dev_area.dev = lvmcache_device_from_pvid(cmd, &id, NULL, NULL))) {
 		char buffer[64] __attribute__((aligned(8)));
 
 		if (!id_write_format(&id, buffer, sizeof(buffer)))
--- LVM2/lib/format_text/format-text.h	2011/03/11 14:45:18	1.33
+++ LVM2/lib/format_text/format-text.h	2012/02/10 01:28:28	1.34
@@ -62,4 +62,16 @@
 	    struct device *dev, uint64_t start, uint64_t size, unsigned ignored);
 void del_mdas(struct dm_list *mdas);
 
+/* On disk */
+struct disk_locn {
+	uint64_t offset;	/* Offset in bytes to start sector */
+	uint64_t size;		/* Bytes */
+} __attribute__ ((packed));
+
+/* Data areas (holding PEs) */
+struct data_area_list {
+	struct dm_list list;
+	struct disk_locn disk_locn;
+};
+
 #endif
--- LVM2/lib/format_text/import_vsn1.c	2012/01/25 21:43:51	1.99
+++ LVM2/lib/format_text/import_vsn1.c	2012/02/10 01:28:28	1.100
@@ -190,7 +190,7 @@
 	/*
 	 * Convert the uuid into a device.
 	 */
-	if (!(pv->dev = device_from_pvid(fid->fmt->cmd, &pv->id, scan_done_once,
+	if (!(pv->dev = lvmcache_device_from_pvid(fid->fmt->cmd, &pv->id, scan_done_once,
                                          &pv->label_sector))) {
 		char buffer[64] __attribute__((aligned(8)));
 
--- LVM2/lib/format_text/layout.h	2010/06/30 17:13:05	1.13
+++ LVM2/lib/format_text/layout.h	2012/02/10 01:28:28	1.14
@@ -21,17 +21,7 @@
 #include "metadata.h"
 #include "uuid.h"
 
-/* On disk */
-struct disk_locn {
-	uint64_t offset;	/* Offset in bytes to start sector */
-	uint64_t size;		/* Bytes */
-} __attribute__ ((packed));
-
-/* Data areas (holding PEs) */
-struct data_area_list {
-	struct dm_list list;
-	struct disk_locn disk_locn;
-};
+/* disk_locn and data_area_list are defined in format-text.h */
 
 /* Fields with the suffix _xl should be xlate'd wherever they appear */
 /* On disk */
--- LVM2/lib/format_text/text_label.c	2011/05/28 09:48:15	1.40
+++ LVM2/lib/format_text/text_label.c	2012/02/10 01:28:28	1.41
@@ -35,15 +35,41 @@
 	return 0;
 }
 
+struct _da_setup_baton {
+	struct disk_locn *pvh_dlocn_xl;
+	struct device *dev;
+};
+
+static int _da_setup(struct data_area_list *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++;
+	return 1;
+}
+
+static int _mda_setup(struct metadata_area *mda, void *baton)
+{
+	struct _da_setup_baton *p = baton;
+	struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
+
+	if (mdac->area.dev != p->dev)
+		return 1;
+
+	p->pvh_dlocn_xl->offset = xlate64(mdac->area.start);
+	p->pvh_dlocn_xl->size = xlate64(mdac->area.size);
+	p->pvh_dlocn_xl++;
+
+	return 1;
+}
+
 static int _text_write(struct label *label, void *buf)
 {
 	struct label_header *lh = (struct label_header *) buf;
 	struct pv_header *pvhdr;
 	struct lvmcache_info *info;
-	struct disk_locn *pvh_dlocn_xl;
-	struct metadata_area *mda;
-	struct mda_context *mdac;
-	struct data_area_list *da;
+	struct _da_setup_baton baton;
 	char buffer[64] __attribute__((aligned(8)));
 	int da1, mda1, mda2;
 
@@ -54,43 +80,31 @@
 
 	pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
 	info = (struct lvmcache_info *) label->info;
-	pvhdr->device_size_xl = xlate64(info->device_size);
-	memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id));
+	pvhdr->device_size_xl = xlate64(lvmcache_device_size(info));
+	memcpy(pvhdr->pv_uuid, &lvmcache_device(info)->pvid, sizeof(struct id));
 	if (!id_write_format((const struct id *)pvhdr->pv_uuid, buffer,
 			     sizeof(buffer))) {
 		stack;
 		buffer[0] = '\0';
 	}
 
-	pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
+	baton.dev = lvmcache_device(info);
 
 	/* List of data areas (holding PEs) */
-	dm_list_iterate_items(da, &info->das) {
-		pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
-		pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
-		pvh_dlocn_xl++;
-	}
+	baton.pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
+	lvmcache_foreach_da(info, _da_setup, &baton);
 
 	/* NULL-termination */
-	pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
-	pvh_dlocn_xl->size = xlate64(UINT64_C(0));
-	pvh_dlocn_xl++;
+	baton.pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
+	baton.pvh_dlocn_xl->size = xlate64(UINT64_C(0));
+	baton.pvh_dlocn_xl++;
 
 	/* List of metadata area header locations */
-	dm_list_iterate_items(mda, &info->mdas) {
-		mdac = (struct mda_context *) mda->metadata_locn;
-
-		if (mdac->area.dev != info->dev)
-			continue;
-
-		pvh_dlocn_xl->offset = xlate64(mdac->area.start);
-		pvh_dlocn_xl->size = xlate64(mdac->area.size);
-		pvh_dlocn_xl++;
-	}
+	lvmcache_foreach_mda(info, _mda_setup, &baton);
 
 	/* NULL-termination */
-	pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
-	pvh_dlocn_xl->size = xlate64(UINT64_C(0));
+	baton.pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
+	baton.pvh_dlocn_xl->size = xlate64(UINT64_C(0));
 
 	/* Create debug message with da and mda locations */
 	if (xlate64(pvhdr->disk_areas_xl[0].offset) ||
@@ -113,7 +127,7 @@
 		  "%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
 		  "%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
 		  "%s%.*" PRIu64 "%s%.*" PRIu64 "%s",
-		  dev_name(info->dev), buffer, info->device_size, 
+		  dev_name(lvmcache_device(info)), buffer, lvmcache_device_size(info),
 		  (da1 > -1) ? " da1 (" : "",
 		  (da1 > -1) ? 1 : 0,
 		  (da1 > -1) ? xlate64(pvhdr->disk_areas_xl[da1].offset) >> SECTOR_SHIFT : 0,
@@ -138,7 +152,7 @@
 
 	if (da1 < 0) {
 		log_error(INTERNAL_ERROR "%s label header currently requires "
-			  "a data area.", dev_name(info->dev));
+			  "a data area.", dev_name(lvmcache_device(info)));
 		return 0;
 	}
 
@@ -250,6 +264,62 @@
 	return 1;
 }
 
+struct _update_mda_baton {
+	struct lvmcache_info *info;
+	struct label *label;
+};
+
+static int _update_mda(struct metadata_area *mda, void *baton)
+{
+	struct _update_mda_baton *p = baton;
+	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;
+	struct id vgid;
+	uint64_t vgstatus;
+	char *creation_host;
+
+	if (!dev_open_readonly(mdac->area.dev)) {
+		mda_set_ignored(mda, 1);
+		stack;
+		return 1;
+	}
+
+	if (!(mdah = raw_read_mda_header(fmt, &mdac->area))) {
+		stack;
+		goto close_dev;
+	}
+
+	mda_set_ignored(mda, rlocn_is_ignored(mdah->raw_locns));
+
+	if (mda_is_ignored(mda)) {
+		log_debug("Ignoring mda on device %s at offset %"PRIu64,
+			  dev_name(mdac->area.dev),
+			  mdac->area.start);
+		if (!dev_close(mdac->area.dev))
+			stack;
+		return 1;
+	}
+
+	if ((vgname = vgname_from_mda(fmt, mdah,
+				      &mdac->area,
+				      &vgid, &vgstatus, &creation_host,
+				      &mdac->free_sectors)) &&
+	    !lvmcache_update_vgname_and_id(p->info, vgname,
+					   (char *) &vgid, vgstatus,
+					   creation_host)) {
+		if (!dev_close(mdac->area.dev))
+			stack;
+		return_0;
+	}
+close_dev:
+	if (!dev_close(mdac->area.dev))
+		stack;
+
+	return 1;
+}
+
 static int _text_read(struct labeller *l, struct device *dev, void *buf,
 		 struct label **label)
 {
@@ -258,13 +328,7 @@
 	struct lvmcache_info *info;
 	struct disk_locn *dlocn_xl;
 	uint64_t offset;
-	struct metadata_area *mda;
-	struct id vgid;
-	struct mda_context *mdac;
-	const char *vgname;
-	uint64_t vgstatus;
-	char *creation_host;
-	struct mda_header *mdah;
+	struct _update_mda_baton baton;
 
 	pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
 
@@ -272,73 +336,34 @@
 				  FMT_TEXT_ORPHAN_VG_NAME,
 				  FMT_TEXT_ORPHAN_VG_NAME, 0)))
 		return_0;
-	*label = info->label;
 
-	info->device_size = xlate64(pvhdr->device_size_xl);
+	/* this one is leaked forever */
+	*label = lvmcache_get_label(info);
 
-	if (info->das.n)
-		del_das(&info->das);
-	dm_list_init(&info->das);
+	lvmcache_set_device_size(info, xlate64(pvhdr->device_size_xl));
 
-	if (info->mdas.n)
-		del_mdas(&info->mdas);
-	dm_list_init(&info->mdas);
+	lvmcache_del_das(info);
+	lvmcache_del_mdas(info);
 
 	/* Data areas holding the PEs */
 	dlocn_xl = pvhdr->disk_areas_xl;
 	while ((offset = xlate64(dlocn_xl->offset))) {
-		add_da(NULL, &info->das, offset,
-		       xlate64(dlocn_xl->size));
+		lvmcache_add_da(info, offset, xlate64(dlocn_xl->size));
 		dlocn_xl++;
 	}
 
 	/* Metadata area headers */
 	dlocn_xl++;
 	while ((offset = xlate64(dlocn_xl->offset))) {
-		add_mda(info->fmt, NULL, &info->mdas, dev, offset,
-			xlate64(dlocn_xl->size), 0);
+		lvmcache_add_mda(info, dev, offset, xlate64(dlocn_xl->size), 0);
 		dlocn_xl++;
 	}
 
-	dm_list_iterate_items(mda, &info->mdas) {
-		mdac = (struct mda_context *) mda->metadata_locn;
-		if (!dev_open_readonly(mdac->area.dev)) {
-			mda_set_ignored(mda, 1);
-			stack;
-			continue;
-		}
-		if (!(mdah = raw_read_mda_header(info->fmt, &mdac->area))) {
-			stack;
-			goto close_dev;
-		}
-		mda_set_ignored(mda, rlocn_is_ignored(mdah->raw_locns));
-
-		if (mda_is_ignored(mda)) {
-			log_debug("Ignoring mda on device %s at offset %"PRIu64,
-				  dev_name(mdac->area.dev),
-				  mdac->area.start);
-			if (!dev_close(mdac->area.dev))
-				stack;
-			continue;
-		}
-
-		if ((vgname = vgname_from_mda(info->fmt, mdah,
-					      &mdac->area,
-					      &vgid, &vgstatus, &creation_host,
-					      &mdac->free_sectors)) &&
-		    !lvmcache_update_vgname_and_id(info, vgname,
-						   (char *) &vgid, vgstatus,
-						   creation_host)) {
-			if (!dev_close(mdac->area.dev))
-					stack;
-			return_0;
-		}
-	close_dev:
-		if (!dev_close(mdac->area.dev))
-			stack;
-	}
+	baton.info = info;
+	baton.label = *label;
 
-	info->status &= ~CACHE_INVALID;
+	lvmcache_foreach_mda(info, _update_mda, &baton);
+	lvmcache_make_valid(info);
 
 	return 1;
 }
@@ -348,10 +373,8 @@
 {
 	struct lvmcache_info *info = (struct lvmcache_info *) label->info;
 
-	if (info->mdas.n)
-		del_mdas(&info->mdas);
-	if (info->das.n)
-		del_das(&info->das);
+	lvmcache_del_mdas(info);
+	lvmcache_del_das(info);
 }
 
 static void _fmt_text_destroy(struct labeller *l)
--- LVM2/lib/label/label.c	2012/02/08 11:12:18	1.55
+++ LVM2/lib/label/label.c	2012/02/10 01:28:28	1.56
@@ -172,9 +172,9 @@
 
       out:
 	if (!found) {
-		if ((info = info_from_pvid(dev->pvid, 0)))
-			lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
-						      info->fmt->orphan_vg_name,
+		if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
+			lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
+						      lvmcache_fmt(info)->orphan_vg_name,
 						      0, NULL);
 		log_very_verbose("%s: No label detected", dev_name(dev));
 	}
@@ -261,18 +261,18 @@
 	struct lvmcache_info *info;
 	int r = 0;
 
-	if ((info = info_from_pvid(dev->pvid, 1))) {
+	if ((info = lvmcache_info_from_pvid(dev->pvid, 1))) {
 		log_debug("Using cached label for %s", dev_name(dev));
-		*result = info->label;
+		*result = lvmcache_get_label(info); /* leaked */
 		return 1;
 	}
 
 	if (!dev_open_readonly(dev)) {
 		stack;
 
-		if ((info = info_from_pvid(dev->pvid, 0)))
-			lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
-						      info->fmt->orphan_vg_name,
+		if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
+			lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
+						      lvmcache_fmt(info)->orphan_vg_name,
 						      0, NULL);
 
 		return r;
@@ -348,9 +348,9 @@
 	int r = 0;
 
 	if (!dev_open_readonly(dev)) {
-		if ((info = info_from_pvid(dev->pvid, 0)))
-			lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
-						      info->fmt->orphan_vg_name,
+		if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
+			lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
+						      lvmcache_fmt(info)->orphan_vg_name,
 						      0, NULL);
 
 		return_0;
--- LVM2/lib/metadata/metadata.c	2012/02/08 12:52:59	1.476
+++ LVM2/lib/metadata/metadata.c	2012/02/10 01:28:28	1.477
@@ -1504,7 +1504,7 @@
 		pp = &default_pp;
 
 	if (pp->idp) {
-		if ((dev = device_from_pvid(cmd, pp->idp, NULL, NULL)) &&
+		if ((dev = lvmcache_device_from_pvid(cmd, pp->idp, NULL, NULL)) &&
 		    (dev != dev_cache_get(pv_name, cmd->filter))) {
 			if (!id_write_format((const struct id*)&pp->idp->uuid,
 			    buffer, sizeof(buffer)))
@@ -2671,7 +2671,7 @@
 {
 	int cache_updated = 0;
 
-	if (!vgname_is_locked(vg->name)) {
+	if (!lvmcache_vgname_is_locked(vg->name)) {
 		log_error(INTERNAL_ERROR "Attempt to write new VG metadata "
 			  "without locking %s", vg->name);
 		return cache_updated;
@@ -2717,6 +2717,31 @@
 	remote_revert_cached_metadata(vg);
 }
 
+struct _vg_read_orphan_baton {
+	struct volume_group *vg;
+	int warnings;
+};
+
+static int _vg_read_orphan_pv(struct lvmcache_info *info, void *baton)
+{
+	struct _vg_read_orphan_baton *b = baton;
+	struct physical_volume *pv = NULL;
+	struct pv_list *pvl;
+
+	if (!(pv = _pv_read(b->vg->cmd, b->vg->vgmem, dev_name(lvmcache_device(info)),
+			    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);
+		return 0;
+	}
+	pvl->pv = pv;
+	add_pvl_to_vgs(b->vg, pvl);
+	return 1;
+}
+
 /* Make orphan PVs look like a VG */
 static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
 					     int warnings,
@@ -2724,15 +2749,17 @@
 {
 	struct format_instance_ctx fic;
 	struct format_instance *fid;
+	const struct format_type *fmt;
 	struct lvmcache_vginfo *vginfo;
-	struct lvmcache_info *info;
-	struct pv_list *pvl;
 	struct volume_group *vg = NULL;
-	struct physical_volume *pv = NULL;
+	struct _vg_read_orphan_baton baton;
 
 	lvmcache_label_scan(cmd, 0);
 
-	if (!(vginfo = vginfo_from_vgname(orphan_vgname, NULL)))
+	if (!(vginfo = lvmcache_vginfo_from_vgname(orphan_vgname, NULL)))
+		return_NULL;
+
+	if (!(fmt = lvmcache_fmt_from_vgname(orphan_vgname, NULL, 0)))
 		return_NULL;
 
 	if (!(vg = alloc_vg("vg_read_orphans", cmd, orphan_vgname)))
@@ -2742,28 +2769,18 @@
 	fic.type = FMT_INSTANCE_VG | FMT_INSTANCE_AUX_MDAS;
 	fic.context.vg_ref.vg_name = orphan_vgname;
 	fic.context.vg_ref.vg_id = NULL;
-	if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt, &fic))) {
+	if (!(fid = fmt->ops->create_instance(fmt, &fic))) {
 		log_error("Failed to create format instance");
 		goto bad;
 	}
 	vg_set_fid(vg, fid);
 
-	dm_list_iterate_items(info, &vginfo->infos) {
-		if (!(pv = _pv_read(cmd, vg->vgmem, dev_name(info->dev),
-				    vg->fid, warnings, 0))) {
-			continue;
-		}
-		if (!(pvl = dm_pool_zalloc(vg->vgmem, sizeof(*pvl)))) {
-			log_error("pv_list allocation failed");
-			goto bad;
-		}
-		pvl->pv = pv;
-		add_pvl_to_vgs(vg, pvl);
-	}
+	baton.warnings = warnings;
+	baton.vg = vg;
+	lvmcache_foreach_pv(vginfo, _vg_read_orphan_pv, &baton);
 
 	return vg;
 bad:
-	free_pv_fid(pv);
 	release_vg(vg);
 	return NULL;
 }
@@ -2848,6 +2865,15 @@
 					 "on it, remove volumes and consider vgreduce --removemissing.");
 		}
 }
+
+static int _check_mda_in_use(struct metadata_area *mda, void *_in_use)
+{
+	int *in_use = _in_use;
+	if (!mda_is_ignored(mda))
+		*in_use = 1;
+	return 1;
+}
+
 /* Caller sets consistent to 1 if it's safe for vg_read_internal to correct
  * inconsistent metadata on disk (i.e. the VG write lock is held).
  * This guarantees only consistent metadata is returned.
@@ -2913,20 +2939,20 @@
 
 	/* 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 = lvmcache_fmt_from_vgname(vgname, vgid, 1))) {
 		lvmcache_label_scan(cmd, 0);
-		if (!(fmt = fmt_from_vgname(vgname, vgid, 1))) {
+		if (!(fmt = lvmcache_fmt_from_vgname(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 = lvmcache_fmt_from_vgname(vgname, vgid, 0)))
 				return_NULL;
 		}
 	}
 
 	/* Now determine the correct vgname if none was supplied */
-	if (!vgname && !(vgname = vgname_from_vgid(cmd->mem, vgid)))
+	if (!vgname && !(vgname = lvmcache_vgname_from_vgid(cmd->mem, vgid)))
 		return_NULL;
 
 	if (use_precommitted && !(fmt->features & FMT_PRECOMMIT))
@@ -3016,18 +3042,17 @@
 				 * Check it's an orphan without metadata area
 				 * not ignored.
 				 */
-				if (!(info = info_from_pvid(pvl->pv->dev->pvid, 1)) ||
-				   !info->vginfo || !is_orphan_vg(info->vginfo->vgname)) {
+				if (!(info = lvmcache_info_from_pvid(pvl->pv->dev->pvid, 1)) ||
+				    !lvmcache_is_orphan(info)) {
 					inconsistent_pvs = 1;
 					break;
 				}
-				if (dm_list_size(&info->mdas)) {
-					if (!fid_add_mdas(fid, &info->mdas,
-							  info->dev->pvid, ID_LEN)) {
+				if (lvmcache_mda_count(info)) {
+					if (!lvmcache_fid_add_mdas_pv(info, fid)) {
 						release_vg(correct_vg);
 						return_NULL;
 					}
-					 
+
 					log_debug("Empty mda found for VG %s.", vgname);
 
 					if (inconsistent_mdas)
@@ -3037,11 +3062,8 @@
 					 * If any newly-added mdas are in-use then their
 					 * metadata needs updating.
 					 */
-					dm_list_iterate_items(mda, &info->mdas)
-						if (!mda_is_ignored(mda)) {
-							inconsistent_mdas = 1;
-							break;
-						}
+					lvmcache_foreach_mda(info, _check_mda_in_use,
+							     &inconsistent_mdas);
 				}
 			}
 
@@ -3110,7 +3132,7 @@
 		if (!cmd->independent_metadata_areas && critical_section())
 			return_NULL;
 		lvmcache_label_scan(cmd, 2);
-		if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
+		if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 0)))
 			return_NULL;
 
 		if (precommitted && !(fmt->features & FMT_PRECOMMIT))
@@ -3383,13 +3405,11 @@
 	const char *vgname;
 	struct dm_list *vgnames;
 	struct volume_group *vg;
-	struct lvmcache_vginfo *vginfo;
 	struct str_list *strl;
 	int consistent = 0;
 
 	/* Is corresponding vgname already cached? */
-	if ((vginfo = vginfo_from_vgid(vgid)) &&
-	    vginfo->vgname && !is_orphan_vg(vginfo->vgname)) {
+	if (lvmcache_vgid_is_cached(vgid)) {
 		if ((vg = _vg_read(cmd, NULL, vgid, 1,
 				   &consistent, precommitted)) &&
 		    id_equal(&vg->id, (const struct id *)vgid)) {
@@ -3480,7 +3500,7 @@
 	vgname = lvmcache_vgname_from_pvid(cmd, pvid);
 
 	if (is_orphan_vg(vgname)) {
-		if (!(info = info_from_pvid(pvid, 0))) {
+		if (!(info = lvmcache_info_from_pvid(pvid, 0))) {
 			return_NULL;
 		}
 		/*
@@ -3490,7 +3510,7 @@
 		 * Detecting this means checking every VG by scanning
 		 * every PV on the system.
 		 */
-		if (mdas_empty_or_ignored(&info->mdas)) {
+		if (lvmcache_uncertain_ownership(info)) {
 			if (!scan_vgs_for_pvs(cmd, 1)) {
 				log_error("Rescan for PVs without "
 					  "metadata areas failed.");
@@ -3512,7 +3532,7 @@
 {
 	const char *pvid;
 
-	pvid = pvid_from_devname(cmd, pvname);
+	pvid = lvmcache_pvid_from_devname(cmd, pvname);
 	if (!pvid)
 		/* Not a PV */
 		return NULL;
@@ -3576,7 +3596,7 @@
 	pv->label_sector = label->sector;
 
 	/* FIXME Move more common code up here */
-	if (!(info->fmt->ops->pv_read(info->fmt, pv_name, pv, scan_label_only))) {
+	if (!(lvmcache_fmt(info)->ops->pv_read(lvmcache_fmt(info), pv_name, pv, scan_label_only))) {
 		log_error("Failed to read existing physical volume '%s'",
 			  pv_name);
 		goto bad;
@@ -3589,7 +3609,7 @@
 		goto_bad;
 
 	if (fid)
-		fid_add_mdas(fid, &info->mdas, (const char *) &pv->id, ID_LEN);
+		lvmcache_fid_add_mdas(info, fid, (const char *) &pv->id, ID_LEN);
 	else {
 		fic.type = FMT_INSTANCE_PV | FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
 		fic.context.pv_id = (const char *) &pv->id;
@@ -3656,7 +3676,7 @@
 		if (!vgid)
 			continue;	/* FIXME Unnecessary? */
 		consistent = 0;
-		if (!(vgname = vgname_from_vgid(NULL, vgid))) {
+		if (!(vgname = lvmcache_vgname_from_vgid(NULL, vgid))) {
 			stack;
 			continue;
 		}
@@ -3777,6 +3797,13 @@
 	return (vg_name && *vg_name != '#');
 }
 
+static int _analyze_mda(struct metadata_area *mda, void *baton)
+{
+	const struct format_type *fmt = baton;
+	mda->ops->pv_analyze_mda(fmt, mda);
+	return 1;
+}
+
 /*
  * Returns:
  *  0 - fail
@@ -3787,7 +3814,6 @@
 {
 	struct label *label;
 	struct device *dev;
-	struct metadata_area *mda;
 	struct lvmcache_info *info;
 
 	dev = dev_cache_get(pv_name, cmd->filter);
@@ -3813,8 +3839,7 @@
 	 * Next, loop through metadata areas
 	 */
 	info = label->info;
-	dm_list_iterate_items(mda, &info->mdas)
-		mda->ops->pv_analyze_mda(info->fmt, mda);
+	lvmcache_foreach_mda(info, _analyze_mda, (void *)lvmcache_fmt(info));
 
 	return 1;
 }
@@ -3932,7 +3957,7 @@
 		return NULL;
 	}
 
-	already_locked = vgname_is_locked(vg_name);
+	already_locked = lvmcache_vgname_is_locked(vg_name);
 
 	if (!already_locked && !(misc_flags & READ_WITHOUT_LOCK) &&
 	    !lock_vol(cmd, vg_name, lock_flags)) {
@@ -4096,9 +4121,9 @@
 
 	/* 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 (!lvmcache_fmt_from_vgname(vgname, NULL, 1)) {
 		lvmcache_label_scan(cmd, 0);
-		if (!fmt_from_vgname(vgname, NULL, 1)) {
+		if (!lvmcache_fmt_from_vgname(vgname, NULL, 1)) {
 			/* Independent MDAs aren't supported under low memory */
 			if (!cmd->independent_metadata_areas && critical_section()) {
 				/*
@@ -4109,7 +4134,7 @@
 				return FAILED_LOCKING;
 			}
 			lvmcache_label_scan(cmd, 2);
-			if (!fmt_from_vgname(vgname, NULL, 0)) {
+			if (!lvmcache_fmt_from_vgname(vgname, NULL, 0)) {
 				/* vgname not found after scanning */
 				return SUCCESS;
 			}
--- LVM2/lib/metadata/pv.c	2011/09/07 13:42:00	1.11
+++ LVM2/lib/metadata/pv.c	2012/02/10 01:28:28	1.12
@@ -143,23 +143,27 @@
 {
 	struct lvmcache_info *info;
 
-	info = info_from_pvid((const char *)&pv->id.uuid, 0);
-	return info ? dm_list_size(&info->mdas) : UINT64_C(0);
+	info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, 0);
+	return info ? lvmcache_mda_count(info) : UINT64_C(0);
+}
+
+static int _count_unignored(struct metadata_area *mda, void *baton)
+{
+	uint32_t *count = baton;
+	if (!mda_is_ignored(mda))
+		(*count) ++;
+	return 1;
 }
 
 uint32_t pv_mda_used_count(const struct physical_volume *pv)
 {
 	struct lvmcache_info *info;
-	struct metadata_area *mda;
 	uint32_t used_count=0;
 
-	info = info_from_pvid((const char *)&pv->id.uuid, 0);
+	info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, 0);
 	if (!info)
 		return 0;
-	dm_list_iterate_items(mda, &info->mdas) {
-		if (!mda_is_ignored(mda))
-			used_count++;
-	}
+	lvmcache_foreach_mda(info, _count_unignored, &used_count);
 	return used_count;
 }
 
@@ -209,29 +213,36 @@
 	const char *pvid = (const char *)(&pv->id.uuid);
 
 	/* PVs could have 2 mdas of different sizes (rounding effect) */
-	if ((info = info_from_pvid(pvid, 0)))
-		min_mda_size = find_min_mda_size(&info->mdas);
+	if ((info = lvmcache_info_from_pvid(pvid, 0)))
+		min_mda_size = lvmcache_smallest_mda_size(info);
 	return min_mda_size;
 }
 
+static int _pv_mda_free(struct metadata_area *mda, void *baton) {
+	uint64_t mda_free;
+	uint64_t *freespace = baton;
+
+	if (!mda->ops->mda_free_sectors)
+		return 1;
+
+	mda_free = mda->ops->mda_free_sectors(mda);
+	if (mda_free < *freespace)
+		*freespace = mda_free;
+	return 1;
+}
+
 uint64_t pv_mda_free(const struct physical_volume *pv)
 {
 	struct lvmcache_info *info;
-	uint64_t freespace = UINT64_MAX, mda_free;
+	uint64_t freespace = UINT64_MAX;
 	const char *pvid = (const char *)&pv->id.uuid;
-	struct metadata_area *mda;
 
-	if ((info = info_from_pvid(pvid, 0)))
-		dm_list_iterate_items(mda, &info->mdas) {
-			if (!mda->ops->mda_free_sectors)
-				continue;
-			mda_free = mda->ops->mda_free_sectors(mda);
-			if (mda_free < freespace)
-				freespace = mda_free;
-		}
+	if ((info = lvmcache_info_from_pvid(pvid, 0)))
+		lvmcache_foreach_mda(info, _pv_mda_free, &freespace);
 
 	if (freespace == UINT64_MAX)
 		freespace = UINT64_C(0);
+
 	return freespace;
 }
 
@@ -246,22 +257,51 @@
 	return used;
 }
 
+struct _pv_mda_set_ignored_baton {
+	unsigned mda_ignored;
+	struct dm_list *mdas_in_use, *mdas_ignored, *mdas_to_change;
+};
+
+static int _pv_mda_set_ignored_one(struct metadata_area *mda, void *baton)
+{
+	struct _pv_mda_set_ignored_baton *b = baton;
+	struct metadata_area *vg_mda, *tmda;
+
+	if (mda_is_ignored(mda) && !b->mda_ignored) {
+		/* Changing an ignored mda to one in_use requires moving it */
+		dm_list_iterate_items_safe(vg_mda, tmda, b->mdas_ignored)
+			if (mda_locns_match(mda, vg_mda)) {
+				mda_set_ignored(vg_mda, b->mda_ignored);
+				dm_list_move(b->mdas_in_use, &vg_mda->list);
+			}
+	}
+
+	dm_list_iterate_items_safe(vg_mda, tmda, b->mdas_in_use)
+		if (mda_locns_match(mda, vg_mda))
+			/* Don't move mda: needs writing to disk. */
+			mda_set_ignored(vg_mda, b->mda_ignored);
+
+	mda_set_ignored(mda, b->mda_ignored);
+	return 1;
+}
+
 unsigned pv_mda_set_ignored(const struct physical_volume *pv, unsigned mda_ignored)
 {
 	struct lvmcache_info *info;
-	struct metadata_area *mda, *vg_mda, *tmda;
-	struct dm_list *mdas_in_use, *mdas_ignored, *mdas_to_change;
+	struct _pv_mda_set_ignored_baton baton;
+	struct metadata_area *mda;
 
-	if (!(info = info_from_pvid((const char *)&pv->id.uuid, 0)))
+	if (!(info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, 0)))
 		return_0;
 
-	mdas_in_use = &pv->fid->metadata_areas_in_use;
-	mdas_ignored = &pv->fid->metadata_areas_ignored;
-	mdas_to_change = mda_ignored ? mdas_in_use : mdas_ignored;
+	baton.mda_ignored = mda_ignored;
+	baton.mdas_in_use = &pv->fid->metadata_areas_in_use;
+	baton.mdas_ignored = &pv->fid->metadata_areas_ignored;
+	baton.mdas_to_change = baton.mda_ignored ? baton.mdas_in_use : baton.mdas_ignored;
 
 	if (is_orphan(pv)) {
-		dm_list_iterate_items(mda, mdas_to_change)
-			mda_set_ignored(mda, mda_ignored);
+		dm_list_iterate_items(mda, baton.mdas_to_change)
+			mda_set_ignored(mda, baton.mda_ignored);
 		return 1;
 	}
 
@@ -288,22 +328,8 @@
 	/* FIXME: Try not to update the cache here! Also, try to iterate over
 	 *	  PV mdas only using the format instance's index somehow
 	 * 	  (i.e. try to avoid using mda_locn_match call). */
-	dm_list_iterate_items(mda, &info->mdas) {
-		if (mda_is_ignored(mda) && !mda_ignored)
-			/* Changing an ignored mda to one in_use requires moving it */
-			dm_list_iterate_items_safe(vg_mda, tmda, mdas_ignored)
-				if (mda_locns_match(mda, vg_mda)) {
-					mda_set_ignored(vg_mda, mda_ignored);
-					dm_list_move(mdas_in_use, &vg_mda->list);
-				}
-
-		dm_list_iterate_items_safe(vg_mda, tmda, mdas_in_use)
-			if (mda_locns_match(mda, vg_mda))
-				/* Don't move mda: needs writing to disk. */
-				mda_set_ignored(vg_mda, mda_ignored);
 
-		mda_set_ignored(mda, mda_ignored);
-	}
+	lvmcache_foreach_mda(info, _pv_mda_set_ignored_one, &baton);
 
 	return 1;
 }
--- LVM2/lib/metadata/vg.c	2012/01/19 15:31:45	1.14
+++ LVM2/lib/metadata/vg.c	2012/02/10 01:28:28	1.15
@@ -84,7 +84,7 @@
 
 	/* Check if there are any vginfo holders */
 	if (vg->vginfo &&
-	    !vginfo_holders_dec_and_test_for_zero(vg->vginfo))
+	    !lvmcache_vginfo_holders_dec_and_test_for_zero(vg->vginfo))
 		return;
 
 	_free_vg(vg);
--- LVM2/tools/toollib.c	2012/02/08 12:52:59	1.239
+++ LVM2/tools/toollib.c	2012/02/10 01:28:28	1.240
@@ -587,7 +587,7 @@
 		}
 		dm_list_iterate_items(sl, vgids) {
 			vgid = sl->str;
-			if (!(vgid) || !(vg_name = vgname_from_vgid(cmd->mem, vgid)))
+			if (!(vgid) || !(vg_name = lvmcache_vgname_from_vgid(cmd->mem, vgid)))
 				continue;
 			ret_max = _process_one_vg(cmd, vg_name, vgid, &tags,
 						  &arg_vgnames,
--- LVM2/tools/vgrename.c	2011/08/10 20:25:31	1.76
+++ LVM2/tools/vgrename.c	2012/02/10 01:28:29	1.77
@@ -87,7 +87,7 @@
 
 	dm_list_iterate_items(sl, vgids) {
 		vgid = sl->str;
-		if (!vgid || !(vg_name = vgname_from_vgid(NULL, vgid)))
+		if (!vgid || !(vg_name = lvmcache_vgname_from_vgid(NULL, vgid)))
 			continue;
 		if (!strcmp(vg_name, vg_name_old)) {
 			if (match) {
@@ -102,7 +102,7 @@
 	log_suppress(2);
 	found_id = id_read_format(&id, vg_name_old);
 	log_suppress(0);
-	if (found_id && (vg_name = vgname_from_vgid(cmd->mem, (char *)id.uuid))) {
+	if (found_id && (vg_name = lvmcache_vgname_from_vgid(cmd->mem, (char *)id.uuid))) {
 		vg_name_old = vg_name;
 		vgid = (char *)id.uuid;
 	} else



                 reply	other threads:[~2012-02-10  1:28 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=20120210012832.22358.qmail@sourceware.org \
    --to=mornfall@sourceware.org \
    --cc=lvm-devel@redhat.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.