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

[lvm-devel] [DRAFT PATCH] lvmcache and lvmetad



Hi,

I have been working on isolating lvmcache code from the rest of the
codebase. I am making progress slowly, since this is very tedious and
very error-prone. A lot of code is copied out around the code base and
cache internals are manipulated all over the place. I am attaching my
current state of the matters, which do not yet compile. When you expose
the internal structures, you can get things to compile though and pass
the tests as well. I will continue drilling down while trying to avoid
any new bugs.

The plan is to, when the lvmcache is finally walled off, to create a new
implementation (of the APIs) that only does the bare minimum to get LVM
going and passing the testsuite. The following step would then be to
factor this functionality out of lvmcache altogether, as far as that
turns out to be possible. After that is done, finally, I can resume work
on integrating lvmetad, which has been so far blocked out by lvmcache
mis-design. In the meantime, I'll try to integrate some lvmetad tests
into the suite (the daemon can be tested even without full LVM support).

Yours,
   Petr

? ChangeLog
Index: lib/cache/lvmcache.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/cache/lvmcache.c,v
retrieving revision 1.118
diff -u -p -r1.118 lvmcache.c
--- lib/cache/lvmcache.c	1 Sep 2011 10:25:22 -0000	1.118
+++ lib/cache/lvmcache.c	24 Oct 2011 14:17:02 -0000
@@ -28,6 +28,40 @@
 #include "format1.h"
 #include "config.h"
 
+/* 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;
@@ -706,6 +740,7 @@ bad:
 	return NULL;
 }
 
+// #if 0
 int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
 {
 	log_debug("VG %s decrementing %d holder(s) at %p.",
@@ -729,6 +764,7 @@ int vginfo_holders_dec_and_test_for_zero
 
 	return 1;
 }
+// #endif
 
 struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
 				   int include_internal)
@@ -957,6 +993,7 @@ static int _lvmcache_update_pvid(struct 
 	/*
 	 * Nothing to do if already stored with same pvid.
 	 */
+
 	if (((dm_hash_lookup(_pvid_hash, pvid)) == info) &&
 	    !strcmp(info->dev->pvid, pvid))
 		return 1;
@@ -1279,6 +1316,8 @@ int lvmcache_update_vgname_and_id(struct
 				  const char *vgname, const char *vgid,
 				  uint32_t vgstatus, const char *creation_host)
 {
+        log_error("lvmcache_update_vgname_and_id: %s -> %s", dev_name(info->dev), vgname);
+
 	if (!vgname && !info->vginfo) {
 		log_error(INTERNAL_ERROR "NULL vgname handed to cache");
 		/* FIXME Remove this */
@@ -1517,3 +1556,224 @@ void lvmcache_destroy(struct cmd_context
 	if (retain_orphans)
 		init_lvmcache_orphans(cmd);
 }
+
+int lvmcache_pvid_is_locked(const char *pvid) {
+	struct lvmcache_info *info;
+	info = info_from_pvid(pvid, 0);
+	if (!info || !info->vginfo)
+		return 0;
+
+	return 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_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;
+}
+
+void lvmcache_put_label(struct lvmcache_info *info, struct label *label) {
+	/* do nothing, as the label is permanent part of info */
+}
+
+struct label *lvmcache_get_label(struct lvmcache_info *info) {
+	return info->label;
+}
+
+void lvmcache_force_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);
+}
+
+/*
+ * 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);
+}
Index: lib/cache/lvmcache.h
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/cache/lvmcache.h,v
retrieving revision 1.41
diff -u -p -r1.41 lvmcache.h
--- lib/cache/lvmcache.h	30 Aug 2011 14:55:16 -0000	1.41
+++ lib/cache/lvmcache.h	24 Oct 2011 14:17:02 -0000
@@ -33,41 +33,11 @@
 struct cmd_context;
 struct format_type;
 struct volume_group;
+struct physical_volume;
 struct dm_config_tree;
-
-/* 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 format_instance;
+struct metadata_area;
+struct data_area_list;
 
 int lvmcache_init(void);
 void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
@@ -96,8 +66,10 @@ int lvmcache_verify_lock_order(const cha
 
 /* Queries */
 const struct format_type *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,
 					   const char *vgid);
 struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
@@ -130,4 +102,42 @@ struct volume_group *lvmcache_get_vg(con
 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_put_label(struct lvmcache_info *info, struct label *label);
+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);
+
+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_force_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);
+
 #endif
Index: lib/device/dev-io.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/device/dev-io.c,v
retrieving revision 1.78
diff -u -p -r1.78 dev-io.c
--- lib/device/dev-io.c	28 May 2011 09:48:14 -0000	1.78
+++ lib/device/dev-io.c	24 Oct 2011 14:17:02 -0000
@@ -597,7 +597,6 @@ static void _close(struct device *dev)
 
 static int _dev_close(struct device *dev, int immediate)
 {
-	struct lvmcache_info *info;
 
 	if (dev->fd < 0) {
 		log_error("Attempt to close device '%s' "
@@ -619,10 +618,7 @@ static int _dev_close(struct device *dev
 
 	/* 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;
Index: lib/format_text/format-text.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/format_text/format-text.c,v
retrieving revision 1.185
diff -u -p -r1.185 format-text.c
--- lib/format_text/format-text.c	30 Aug 2011 14:55:17 -0000	1.185
+++ lib/format_text/format-text.c	24 Oct 2011 14:17:03 -0000
@@ -1251,6 +1251,33 @@ static int _text_scan(const struct forma
 	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 @@ static int _text_pv_write(const struct f
 	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 @@ static int _text_pv_write(const struct f
 			  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,35 +1341,22 @@ static int _text_pv_write(const struct f
 	 * 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);
+		lvmcache_put_label(info, label);
 		return_0;
 	}
 
@@ -1356,6 +1366,7 @@ static int _text_pv_write(const struct f
 	 *        update the cache afterwards?
 	 */
 
+	lvmcache_put_label(info, label);
 	if (!dev_close(pv->dev))
 		return_0;
 
@@ -1384,68 +1395,6 @@ static int _add_raw(struct dm_list *raw_
 	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 +1434,14 @@ static int _text_pv_read(const struct fo
 {
 	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;
@@ -1675,13 +1622,10 @@ static int _text_pv_setup(const struct f
 			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;
 	}
 
@@ -1737,7 +1681,7 @@ static int _create_pv_text_instance(stru
 
 	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);
+		lvmcache_fid_add_mdas_pv(info, fid);
 
 	return 1;
 }
@@ -1801,7 +1745,6 @@ static int _create_vg_text_instance(stru
 	char path[PATH_MAX];
 	struct text_context tc;
 	struct lvmcache_vginfo *vginfo;
-	struct lvmcache_info *info;
 	const char *vg_name, *vg_id;
 
 	if (!(fidtc = (struct text_fid_context *)
@@ -1875,10 +1818,8 @@ static int _create_vg_text_instance(stru
 			lvmcache_label_scan(fid->fmt->cmd, 0);
 			if (!(vginfo = vginfo_from_vgname(vg_name, vg_id)))
 				goto_out;
-			dm_list_iterate_items(info, &vginfo->infos) {
-				if (!fid_add_mdas(fid, &info->mdas, info->dev->pvid, ID_LEN))
-					return_0;
-			}
+			if (!lvmcache_fid_add_mdas_vg(vginfo, fid))
+				goto_out;
 		}
 
 		/* FIXME Check raw metadata area count - rescan if required */
Index: lib/format_text/format-text.h
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/format_text/format-text.h,v
retrieving revision 1.33
diff -u -p -r1.33 format-text.h
--- lib/format_text/format-text.h	11 Mar 2011 14:45:18 -0000	1.33
+++ lib/format_text/format-text.h	24 Oct 2011 14:17:03 -0000
@@ -62,4 +62,16 @@ int add_mda(const struct format_type *fm
 	    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
Index: lib/format_text/layout.h
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/format_text/layout.h,v
retrieving revision 1.13
diff -u -p -r1.13 layout.h
--- lib/format_text/layout.h	30 Jun 2010 17:13:05 -0000	1.13
+++ lib/format_text/layout.h	24 Oct 2011 14:17:03 -0000
@@ -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 */
Index: lib/format_text/text_label.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/format_text/text_label.c,v
retrieving revision 1.40
diff -u -p -r1.40 text_label.c
--- lib/format_text/text_label.c	28 May 2011 09:48:15 -0000	1.40
+++ lib/format_text/text_label.c	24 Oct 2011 14:17:03 -0000
@@ -35,15 +35,41 @@ static int _text_can_handle(struct label
 	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 @@ static int _text_write(struct label *lab
 
 	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 @@ static int _text_write(struct label *lab
 		  "%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 @@ static int _text_write(struct label *lab
 
 	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 @@ static int _text_initialise_label(struct
 	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 @@ static int _text_read(struct labeller *l
 	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 @@ static int _text_read(struct labeller *l
 				  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_force_valid(info);
 
 	return 1;
 }
@@ -348,10 +373,8 @@ static void _text_destroy_label(struct l
 {
 	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)
Index: lib/label/label.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/label/label.c,v
retrieving revision 1.54
diff -u -p -r1.54 label.c
--- lib/label/label.c	1 Jun 2011 15:30:36 -0000	1.54
+++ lib/label/label.c	24 Oct 2011 14:17:03 -0000
@@ -180,8 +180,8 @@ static struct labeller *_find_labeller(s
       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,
+			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));
 	}
@@ -270,7 +270,7 @@ int label_read(struct device *dev, struc
 
 	if ((info = 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;
 	}
 
@@ -278,8 +278,8 @@ int label_read(struct device *dev, struc
 		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,
+			lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
+						      lvmcache_fmt(info)->orphan_vg_name,
 						      0, NULL);
 
 		return r;
@@ -356,8 +356,8 @@ int label_verify(struct device *dev)
 
 	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,
+			lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
+						      lvmcache_fmt(info)->orphan_vg_name,
 						      0, NULL);
 
 		return_0;
Index: lib/metadata/metadata.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/metadata/metadata.c,v
retrieving revision 1.467
diff -u -p -r1.467 metadata.c
--- lib/metadata/metadata.c	7 Sep 2011 08:34:22 -0000	1.467
+++ lib/metadata/metadata.c	24 Oct 2011 14:17:05 -0000
@@ -2714,6 +2714,7 @@ static struct volume_group *_vg_read_orp
 	struct format_instance *fid;
 	struct lvmcache_vginfo *vginfo;
 	struct lvmcache_info *info;
+	struct dm_list *infol;
 	struct pv_list *pvl;
 	struct volume_group *vg = NULL;
 	struct physical_volume *pv = NULL;
@@ -2736,8 +2737,9 @@ static struct volume_group *_vg_read_orp
 	}
 	vg_set_fid(vg, fid);
 
-	dm_list_iterate_items(info, &vginfo->infos) {
-		if (!(pv = _pv_read(cmd, vg->vgmem, dev_name(info->dev),
+	dm_list_iterate(infol, &vginfo->infos) {
+		info = (struct lvmcache_info *)infol;
+		if (!(pv = _pv_read(cmd, vg->vgmem, dev_name(lvmcache_device(info)),
 				    vg->fid, warnings, 0))) {
 			continue;
 		}
@@ -2836,6 +2838,15 @@ static void check_reappeared_pv(struct v
 					 "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.
@@ -3005,17 +3016,16 @@ static struct volume_group *_vg_read(str
 				 * not ignored.
 				 */
 				if (!(info = info_from_pvid(pvl->pv->dev->pvid, 1)) ||
-				   !info->vginfo || !is_orphan_vg(info->vginfo->vgname)) {
+				    !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)
@@ -3025,11 +3035,8 @@ static struct volume_group *_vg_read(str
 					 * 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);
 				}
 			}
 
@@ -3478,7 +3485,7 @@ const char *find_vgname_from_pvid(struct
 		 * 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.");
@@ -3564,7 +3571,7 @@ static struct physical_volume *_pv_read(
 	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;
@@ -3577,7 +3584,7 @@ static struct physical_volume *_pv_read(
 		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;
@@ -3765,6 +3772,13 @@ int is_real_vg(const char *vg_name)
 	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
@@ -3775,7 +3789,6 @@ int pv_analyze(struct cmd_context *cmd, 
 {
 	struct label *label;
 	struct device *dev;
-	struct metadata_area *mda;
 	struct lvmcache_info *info;
 
 	dev = dev_cache_get(pv_name, cmd->filter);
@@ -3801,8 +3814,7 @@ int pv_analyze(struct cmd_context *cmd, 
 	 * 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;
 }
Index: lib/metadata/pv.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/metadata/pv.c,v
retrieving revision 1.11
diff -u -p -r1.11 pv.c
--- lib/metadata/pv.c	7 Sep 2011 13:42:00 -0000	1.11
+++ lib/metadata/pv.c	24 Oct 2011 14:17:05 -0000
@@ -144,22 +144,26 @@ uint32_t pv_mda_count(const struct physi
 	struct lvmcache_info *info;
 
 	info = info_from_pvid((const char *)&pv->id.uuid, 0);
-	return info ? dm_list_size(&info->mdas) : UINT64_C(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);
 	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;
 }
 
-- 
id' Ash = Ash; id' Dust = Dust; id' _ = undefined

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