diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f69a918
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+SOURCES/LVM2.2.02.186.tgz
+SOURCES/boom-0.9.tar.gz
diff --git a/.lvm2.metadata b/.lvm2.metadata
new file mode 100644
index 0000000..e9512fd
--- /dev/null
+++ b/.lvm2.metadata
@@ -0,0 +1,2 @@
+7a3834ca1ddaa7c4edc3863f18ec604f45722c65 SOURCES/LVM2.2.02.186.tgz
+dd96613e238f342641b5be8977ee8598662e8ab9 SOURCES/boom-0.9.tar.gz
diff --git a/SOURCES/lvm2-2_02_187-WHATS_NEW-vgcreate-vgextend-logical-block-size.patch b/SOURCES/lvm2-2_02_187-WHATS_NEW-vgcreate-vgextend-logical-block-size.patch
new file mode 100644
index 0000000..586bfbe
--- /dev/null
+++ b/SOURCES/lvm2-2_02_187-WHATS_NEW-vgcreate-vgextend-logical-block-size.patch
@@ -0,0 +1,33 @@
+From c5515908de62c3c68e12effad1aed7adc9e235f6 Mon Sep 17 00:00:00 2001
+From: David Teigland <teigland@redhat.com>
+Date: Thu, 1 Aug 2019 10:15:27 -0500
+Subject: [PATCH 3/6] WHATS_NEW: vgcreate/vgextend logical block size
+
+(cherry picked from commit 3a0d493d918510d863ddbdbc63d8a8ccb6ca2dd9)
+
+Conflicts:
+	WHATS_NEW
+
+(cherry picked from commit 9fcda0d9752bf06b619d29aa6738b4ac52acedfc)
+
+Conflicts:
+	WHATS_NEW
+---
+ WHATS_NEW | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index cf2ec3e..d99f183 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,3 +1,7 @@
++Version 2.02.187 - 
++===================================
++  Prevent creating VGs with PVs with different logical block sizes.
++
+ Version 2.02.186 - 27th August 2019
+ ===================================
+   Improve internal removal of cached devices.
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_187-cov-Fix-memory-leak.patch b/SOURCES/lvm2-2_02_187-cov-Fix-memory-leak.patch
new file mode 100644
index 0000000..243bc2d
--- /dev/null
+++ b/SOURCES/lvm2-2_02_187-cov-Fix-memory-leak.patch
@@ -0,0 +1,26 @@
+From a76bab1d408d75acc95a6ea8faaaaa298008b63e Mon Sep 17 00:00:00 2001
+From: Marian Csontos <mcsontos@redhat.com>
+Date: Wed, 28 Aug 2019 10:45:04 +0200
+Subject: [PATCH 1/6] cov: Fix memory leak
+
+---
+ libdm/libdm-common.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
+index c300223..b06e678 100644
+--- a/libdm/libdm-common.c
++++ b/libdm/libdm-common.c
+@@ -2012,7 +2012,8 @@ static int _sysfs_get_kernel_name(uint32_t major, uint32_t minor, char *buf, siz
+ 			log_sys_error("readlink", sysfs_path);
+ 		else {
+ 			log_sys_debug("readlink", sysfs_path);
+-			return _sysfs_find_kernel_name(major, minor, buf, buf_size);
++			r = _sysfs_find_kernel_name(major, minor, buf, buf_size);
++			goto bad;
+ 		}
+ 		goto bad;
+ 	}
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_187-lvconvert-improve-validation-thin-and-cache-pool-con.patch b/SOURCES/lvm2-2_02_187-lvconvert-improve-validation-thin-and-cache-pool-con.patch
new file mode 100644
index 0000000..2ba05aa
--- /dev/null
+++ b/SOURCES/lvm2-2_02_187-lvconvert-improve-validation-thin-and-cache-pool-con.patch
@@ -0,0 +1,109 @@
+From 0cef052646dc4a1338a3febf38c3085cfa636cca Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Fri, 6 Sep 2019 18:09:40 +0200
+Subject: [PATCH 5/6] lvconvert: improve validation thin and cache pool
+ conversion
+
+Limit convertible LVs to thin-pool and cache-pools.
+Also fix return code on  interal error path to return ECMD_FAILED.
+
+(cherry picked from commit e147786bac52fea240955329963c9eed0eebfb18)
+
+Conflicts:
+	WHATS_NEW
+---
+ WHATS_NEW         |  1 +
+ tools/lvconvert.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 48 insertions(+), 5 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 399864d..d1f4530 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -2,6 +2,7 @@ Version 2.02.187 -
+ ===================================
+   Prevent creating VGs with PVs with different logical block sizes.
+   Pvmove runs in exlusively activating mode for exclusively active LVs.
++  Enhance validation for thin and cache pool conversion and swapping.
+ 
+ Version 2.02.186 - 27th August 2019
+ ===================================
+diff --git a/tools/lvconvert.c b/tools/lvconvert.c
+index e66f063..799e746 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -4309,24 +4309,66 @@ static int _lvconvert_to_pool_or_swap_metadata_single(struct cmd_context *cmd,
+ 	struct dm_list *use_pvh = NULL;
+ 	int to_thinpool = 0;
+ 	int to_cachepool = 0;
++	int lvt_enum = get_lvt_enum(lv);
++	struct lv_type *lvtype;
+ 
+ 	switch (cmd->command->command_enum) {
+ 	case lvconvert_to_thinpool_or_swap_metadata_CMD:
++		if (lv_is_cache(lv))
++			/* For cached LV check the cache origin LV type */
++			lvt_enum = get_lvt_enum(seg_lv(first_seg(lv), 0));
+ 		to_thinpool = 1;
+ 		break;
+ 	case lvconvert_to_cachepool_or_swap_metadata_CMD:
++		if (lv_is_cache(lv))
++			goto_bad; /* Cache over cache is not supported */
+ 		to_cachepool = 1;
+ 		break;
+ 	default:
+-		log_error(INTERNAL_ERROR "Invalid lvconvert pool command");
+-		return 0;
+-	};
++		log_error(INTERNAL_ERROR "Invalid lvconvert pool command.");
++		return ECMD_FAILED;
++	}
++
++	switch (lvt_enum) {
++	case thinpool_LVT:
++		if (!to_thinpool)
++			goto_bad; /* can't accept cache-pool */
++		break; /* swap thin-pool */
++	case cachepool_LVT:
++		if (!to_cachepool)
++			goto_bad; /* can't accept thin-pool */
++		break; /* swap cache-pool */
++	case linear_LVT:
++	case raid_LVT:
++	case striped_LVT:
++	case zero_LVT:
++		break;
++	default:
++bad:
++		lvtype = get_lv_type(lvt_enum);
++		log_error("LV %s with type %s cannot be used as a %s pool LV.",
++			  display_lvname(lv), lvtype ? lvtype->name : "unknown",
++			  to_thinpool ? "thin" : "cache");
++		return ECMD_FAILED;
++	}
+ 
+ 	if (lv_is_origin(lv)) {
+ 		log_error("Cannot convert logical volume %s under snapshot.",
+ 			  display_lvname(lv));
+-		return 0;
+-	};
++		return ECMD_FAILED;
++	}
++
++	if (!lv_is_visible(lv)) {
++		log_error("Can't convert internal LV %s.",
++			  display_lvname(lv));
++		return ECMD_FAILED;
++	}
++
++	if (lv_is_locked(lv)) {
++		log_error("Can't convert locked LV %s.",
++			  display_lvname(lv));
++		return ECMD_FAILED;
++	}
+ 
+ 	if (cmd->position_argc > 1) {
+ 		/* First pos arg is required LV, remaining are optional PVs. */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_187-pvmove-check-if-participating-LV-is-already-exlcusiv.patch b/SOURCES/lvm2-2_02_187-pvmove-check-if-participating-LV-is-already-exlcusiv.patch
new file mode 100644
index 0000000..2bd795d
--- /dev/null
+++ b/SOURCES/lvm2-2_02_187-pvmove-check-if-participating-LV-is-already-exlcusiv.patch
@@ -0,0 +1,52 @@
+From 36265f58ae0def19b2bbe55443d77a10bad8eeca Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Wed, 18 Sep 2019 12:42:50 +0200
+Subject: [PATCH 4/6] pvmove: check if participating LV is already exlcusively
+ active
+
+When running pvmove, we need to decide whether pvmove has to be doing
+exlusive or non-exclusive activations for LV.
+
+Whenever LV that requires exlusive activation is present, it makes
+pvmove exlusive. But when there is already activate i.e. linear LV
+in exclusive mode it also needs to switch pvmove into 'exlusively
+activating' pvmove.
+
+(cherry picked from commit 1349b61bb72d3a42636053ede0d6fa71cd4f2d93)
+
+Conflicts:
+	WHATS_NEW
+---
+ WHATS_NEW      | 1 +
+ tools/pvmove.c | 3 ++-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index d99f183..399864d 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,6 +1,7 @@
+ Version 2.02.187 - 
+ ===================================
+   Prevent creating VGs with PVs with different logical block sizes.
++  Pvmove runs in exlusively activating mode for exclusively active LVs.
+ 
+ Version 2.02.186 - 27th August 2019
+ ===================================
+diff --git a/tools/pvmove.c b/tools/pvmove.c
+index 754bd58..3a447c4 100644
+--- a/tools/pvmove.c
++++ b/tools/pvmove.c
+@@ -674,7 +674,8 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
+ 		dm_list_iterate_items(lvl, lvs_changed) {
+ 			lvh = lv_lock_holder(lvl->lv);
+ 			/* Exclusive LV decides whether pvmove must be also exclusive */
+-			if (lv_is_origin(lvh) || seg_only_exclusive(first_seg(lvh)))
++			if (lv_is_origin(lvh) || seg_only_exclusive(first_seg(lvh)) ||
++			    lv_is_active_exclusive(lvh))
+ 				exclusive = 1;
+ 		}
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_187-thin-activate-layer-pool-aas-read-only-LV.patch b/SOURCES/lvm2-2_02_187-thin-activate-layer-pool-aas-read-only-LV.patch
new file mode 100644
index 0000000..41c70e3
--- /dev/null
+++ b/SOURCES/lvm2-2_02_187-thin-activate-layer-pool-aas-read-only-LV.patch
@@ -0,0 +1,55 @@
+From c1a6e218334ac561a695fa4cefd69208ba93107e Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Sat, 14 Sep 2019 01:08:14 +0200
+Subject: [PATCH 6/6] thin: activate layer pool aas read-only LV
+
+When lvm2 is activating layered pool LV (to basically keep pool opened,
+the other function used to be 'locking' be in sync with DM table)
+use this LV in read-only mode - this prevents 'write' access into
+data volume content of thin-pool.
+
+Note: since EMPTY/unused thin-pool is created as 'public LV' for generic
+use by any user who i.e. wish to maintain thin-pool and thins himself.
+At this moment, thin-pool appears as writable LV.  As soon as the 1st.
+thinLV is created, layer volume will appear is 'read-only' LV from this moment.
+
+(cherry picked from commit 2e51535b18f3a05428f087f3916ebce5c08d58d1)
+
+Conflicts:
+	WHATS_NEW
+---
+ WHATS_NEW                  | 1 +
+ lib/activate/dev_manager.c | 5 +++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index d1f4530..00b84f9 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -2,6 +2,7 @@ Version 2.02.187 -
+ ===================================
+   Prevent creating VGs with PVs with different logical block sizes.
+   Pvmove runs in exlusively activating mode for exclusively active LVs.
++  Activate thin-pool layered volume as 'read-only' device.
+   Enhance validation for thin and cache pool conversion and swapping.
+ 
+ Version 2.02.186 - 27th August 2019
+diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
+index dc64159..56608e3 100644
+--- a/lib/activate/dev_manager.c
++++ b/lib/activate/dev_manager.c
+@@ -84,6 +84,11 @@ int read_only_lv(const struct logical_volume *lv, const struct lv_activate_opts
+ 	if (lv_is_raid_image(lv) || lv_is_raid_metadata(lv))
+ 		return 0; /* Keep RAID SubLvs writable */
+ 
++	if (!layer) {
++		if (lv_is_thin_pool(lv))
++			return 1;
++	}
++
+ 	return (laopts->read_only || !(lv->status & LVM_WRITE));
+ }
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_187-vgcreate-vgextend-restrict-PVs-with-mixed-block-size.patch b/SOURCES/lvm2-2_02_187-vgcreate-vgextend-restrict-PVs-with-mixed-block-size.patch
new file mode 100644
index 0000000..7a1f31f
--- /dev/null
+++ b/SOURCES/lvm2-2_02_187-vgcreate-vgextend-restrict-PVs-with-mixed-block-size.patch
@@ -0,0 +1,231 @@
+From f450ffed18936a3b9a6249ad46b24741f7e7b2a3 Mon Sep 17 00:00:00 2001
+From: David Teigland <teigland@redhat.com>
+Date: Thu, 1 Aug 2019 10:06:47 -0500
+Subject: [PATCH 2/6] vgcreate/vgextend: restrict PVs with mixed block sizes
+
+Avoid having PVs with different logical block sizes in the same VG.
+This prevents LVs from having mixed block sizes, which can produce
+file system errors.
+
+The new config setting devices/allow_mixed_block_sizes (default 0)
+can be changed to 1 to return to the unrestricted mode.
+
+(cherry picked from commit 0404539edb25e4a9d3456bb3e6b402aa2767af6b)
+
+Conflicts:
+	tools/lvmcmdline.c
+	tools/toollib.c
+
+(cherry picked from commit a57b92dec396ac79c57e02e54c04e205aa85f084)
+---
+ lib/commands/toolcontext.h       |  1 +
+ lib/config/config_settings.h     |  5 +++++
+ lib/metadata/metadata-exported.h |  1 +
+ lib/metadata/metadata.c          | 44 +++++++++++++++++++++++++++++++++++++
+ tools/lvmcmdline.c               |  2 ++
+ tools/toollib.c                  | 47 ++++++++++++++++++++++++++++++++++++++++
+ tools/vgcreate.c                 |  2 ++
+ 7 files changed, 102 insertions(+)
+
+diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
+index 4b2a079..497f4bd 100644
+--- a/lib/commands/toolcontext.h
++++ b/lib/commands/toolcontext.h
+@@ -155,6 +155,7 @@ struct cmd_context {
+ 	unsigned include_shared_vgs:1;		/* report/display cmds can reveal lockd VGs */
+ 	unsigned include_active_foreign_vgs:1;	/* cmd should process foreign VGs with active LVs */
+ 	unsigned vg_read_print_access_error:1;	/* print access errors from vg_read */
++	unsigned allow_mixed_block_sizes:1;
+ 	unsigned force_access_clustered:1;
+ 	unsigned lockd_gl_disable:1;
+ 	unsigned lockd_vg_disable:1;
+diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
+index 9904a62..622e982 100644
+--- a/lib/config/config_settings.h
++++ b/lib/config/config_settings.h
+@@ -470,6 +470,11 @@ cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_
+ 	"Enabling this setting allows the VG to be used as usual even with\n"
+ 	"uncertain devices.\n")
+ 
++cfg(devices_allow_mixed_block_sizes_CFG, "allow_mixed_block_sizes", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 3, 6), NULL, 0, NULL,
++	"Allow PVs in the same VG with different logical block sizes.\n"
++	"When allowed, the user is responsible to ensure that an LV is\n"
++	"using PVs with matching block sizes when necessary.\n")
++
+ cfg_array(allocation_cling_tag_list_CFG, "cling_tag_list", allocation_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 77), NULL, 0, NULL,
+ 	"Advise LVM which PVs to use when searching for new space.\n"
+ 	"When searching for free space to extend an LV, the 'cling' allocation\n"
+diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
+index 2245c29..5674545 100644
+--- a/lib/metadata/metadata-exported.h
++++ b/lib/metadata/metadata-exported.h
+@@ -593,6 +593,7 @@ struct pvcreate_params {
+ 	unsigned is_remove : 1;         /* is removing PVs, not creating */
+ 	unsigned preserve_existing : 1;
+ 	unsigned check_failed : 1;
++	unsigned check_consistent_block_size : 1;
+ };
+ 
+ struct lvresize_params {
+diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
+index 3620240..123f7f5 100644
+--- a/lib/metadata/metadata.c
++++ b/lib/metadata/metadata.c
+@@ -699,12 +699,40 @@ int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
+ {
+ 	struct pv_list *pvl;
+ 	unsigned int max_phys_block_size = 0;
++	unsigned int physical_block_size, logical_block_size;
++	unsigned int prev_lbs = 0;
++	int inconsistent_existing_lbs = 0;
+ 
+ 	log_debug_metadata("Adding PVs to VG %s.", vg->name);
+ 
+ 	if (vg_bad_status_bits(vg, RESIZEABLE_VG))
+ 		return_0;
+ 
++	/*
++	 * Check if existing PVs have inconsistent block sizes.
++	 * If so, do not enforce new devices to be consistent.
++	 */
++	dm_list_iterate_items(pvl, &vg->pvs) {
++		logical_block_size = 0;
++		physical_block_size = 0;
++
++		if (!dev_get_direct_block_sizes(pvl->pv->dev, &physical_block_size, &logical_block_size))
++			continue;
++
++		if (!logical_block_size)
++			continue;
++
++		if (!prev_lbs) {
++			prev_lbs = logical_block_size;
++			continue;
++		}
++		
++		if (prev_lbs != logical_block_size) {
++			inconsistent_existing_lbs = 1;
++			break;
++		}
++	}
++
+ 	dm_list_iterate_items(pvl, &pp->pvs) {
+ 		log_debug_metadata("Adding PV %s to VG %s.", pv_dev_name(pvl->pv), vg->name);
+ 
+@@ -715,6 +743,22 @@ int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
+ 			return 0;
+ 		}
+ 
++		logical_block_size = 0;
++		physical_block_size = 0;
++
++		if (!dev_get_direct_block_sizes(pvl->pv->dev, &physical_block_size, &logical_block_size))
++			log_warn("WARNING: PV %s has unknown block size.", pv_dev_name(pvl->pv));
++
++		else if (prev_lbs && logical_block_size && (logical_block_size != prev_lbs)) {
++			if (vg->cmd->allow_mixed_block_sizes || inconsistent_existing_lbs)
++				log_debug("Devices have inconsistent block sizes (%u and %u)", prev_lbs, logical_block_size);
++			else {
++				log_error("Devices have inconsistent logical block sizes (%u and %u).",
++					  prev_lbs, logical_block_size);
++				return 0;
++			}
++		}
++
+ 		if (!add_pv_to_vg(vg, pv_dev_name(pvl->pv), pvl->pv, 0)) {
+ 			log_error("PV %s cannot be added to VG %s.",
+ 				  pv_dev_name(pvl->pv), vg->name);
+diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
+index f238b64..f82827d 100644
+--- a/tools/lvmcmdline.c
++++ b/tools/lvmcmdline.c
+@@ -2308,6 +2308,8 @@ static int _get_current_settings(struct cmd_context *cmd)
+ 	if (cmd->cname->flags & CAN_USE_ONE_SCAN)
+ 		cmd->can_use_one_scan = 1;
+ 
++	cmd->allow_mixed_block_sizes = find_config_tree_bool(cmd, devices_allow_mixed_block_sizes_CFG, NULL);
++
+ 	cmd->partial_activation = 0;
+ 	cmd->degraded_activation = 0;
+ 	activation_mode = find_config_tree_str(cmd, activation_mode_CFG, NULL);
+diff --git a/tools/toollib.c b/tools/toollib.c
+index 81953ee..0b957cc 100644
+--- a/tools/toollib.c
++++ b/tools/toollib.c
+@@ -5506,6 +5506,8 @@ int pvcreate_each_device(struct cmd_context *cmd,
+ 	struct device_list *devl;
+ 	const char *pv_name;
+ 	int consistent = 0;
++	unsigned int physical_block_size, logical_block_size;
++	unsigned int prev_pbs = 0, prev_lbs = 0;
+ 	int must_use_all = (cmd->cname->flags & MUST_USE_ALL_ARGS);
+ 	int found;
+ 	unsigned i;
+@@ -5584,6 +5586,51 @@ int pvcreate_each_device(struct cmd_context *cmd,
+ 		pd->dev = dev_cache_get(pd->name, cmd->full_filter);
+ 
+ 	/*
++	 * Check for consistent block sizes.
++	 */
++	if (pp->check_consistent_block_size) {
++		dm_list_iterate_items(pd, &pp->arg_devices) {
++			if (!pd->dev)
++				continue;
++
++			logical_block_size = 0;
++			physical_block_size = 0;
++
++			if (!dev_get_direct_block_sizes(pd->dev, &physical_block_size, &logical_block_size)) {
++				log_warn("WARNING: Unknown block size for device %s.", dev_name(pd->dev));
++				continue;
++			}
++
++			if (!logical_block_size) {
++				log_warn("WARNING: Unknown logical_block_size for device %s.", dev_name(pd->dev));
++				continue;
++			}
++
++			if (!prev_lbs) {
++				prev_lbs = logical_block_size;
++				prev_pbs = physical_block_size;
++				continue;
++			}
++
++			if (prev_lbs == logical_block_size) {
++				/* Require lbs to match, just warn about unmatching pbs. */
++				if (!cmd->allow_mixed_block_sizes && prev_pbs && physical_block_size &&
++				    (prev_pbs != physical_block_size))
++					log_warn("WARNING: Devices have inconsistent physical block sizes (%u and %u).",
++						  prev_pbs, physical_block_size);
++				continue;
++			}
++
++			if (!cmd->allow_mixed_block_sizes) {
++				log_error("Devices have inconsistent logical block sizes (%u and %u).",
++					  prev_lbs, logical_block_size);
++				log_print("See lvm.conf allow_mixed_block_sizes.");
++				return 0;
++			}
++		}
++	}
++
++	/*
+ 	 * Use process_each_pv to search all existing PVs and devices.
+ 	 *
+ 	 * This is a slightly different way to use process_each_pv, because the
+diff --git a/tools/vgcreate.c b/tools/vgcreate.c
+index 4356d99..7add53b 100644
+--- a/tools/vgcreate.c
++++ b/tools/vgcreate.c
+@@ -48,6 +48,8 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
+ 	/* Don't create a new PV on top of an existing PV like pvcreate does. */
+ 	pp.preserve_existing = 1;
+ 
++	pp.check_consistent_block_size = 1;
++
+ 	if (!vgcreate_params_set_defaults(cmd, &vp_def, NULL))
+ 		return EINVALID_CMD_LINE;
+ 	vp_def.vg_name = vg_name;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-default-allow-changes-with-duplicate-pvs.patch b/SOURCES/lvm2-default-allow-changes-with-duplicate-pvs.patch
new file mode 100644
index 0000000..72b7d21
--- /dev/null
+++ b/SOURCES/lvm2-default-allow-changes-with-duplicate-pvs.patch
@@ -0,0 +1,30 @@
+ conf/example.conf.in  | 2 +-
+ lib/config/defaults.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/conf/example.conf.in b/conf/example.conf.in
+index 7ccf928..4418f56 100644
+--- a/conf/example.conf.in
++++ b/conf/example.conf.in
+@@ -325,7 +325,7 @@ devices {
+ 	# or activating LVs in it while a PV appears on multiple devices.
+ 	# Enabling this setting allows the VG to be used as usual even with
+ 	# uncertain devices.
+-	allow_changes_with_duplicate_pvs = 0
++	allow_changes_with_duplicate_pvs = 1
+ }
+ 
+ # Configuration section allocation.
+diff --git a/lib/config/defaults.h b/lib/config/defaults.h
+index 6d3c37c..0d55928 100644
+--- a/lib/config/defaults.h
++++ b/lib/config/defaults.h
+@@ -45,7 +45,7 @@
+ #define DEFAULT_DATA_ALIGNMENT_DETECTION 1
+ #define DEFAULT_ISSUE_DISCARDS 0
+ #define DEFAULT_PV_MIN_SIZE_KB 2048
+-#define DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS 0
++#define DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS 1
+ 
+ #define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
+ #define DEFAULT_ERROR_WHEN_FULL 0
diff --git a/SOURCES/lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection.patch b/SOURCES/lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection.patch
new file mode 100644
index 0000000..d3207da
--- /dev/null
+++ b/SOURCES/lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection.patch
@@ -0,0 +1,114 @@
+From e8b1625c56aa1e2017cbcf8f7dfba30ac79396ce Mon Sep 17 00:00:00 2001
+From: Marian Csontos <mcsontos@redhat.com>
+Date: Wed, 29 Mar 2017 15:38:54 +0200
+Subject: [PATCH 4/7] 
+ lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection
+
+---
+ configure             | 20 ++++++++++----------
+ configure.ac          |  4 ++--
+ lib/device/dev-type.c |  3 +--
+ 3 files changed, 13 insertions(+), 14 deletions(-)
+
+diff --git a/configure b/configure
+index 4d2fb2f..f357462 100755
+--- a/configure
++++ b/configure
+@@ -12111,12 +12111,12 @@ if test -n "$BLKID_CFLAGS"; then
+     pkg_cv_BLKID_CFLAGS="$BLKID_CFLAGS"
+  elif test -n "$PKG_CONFIG"; then
+     if test -n "$PKG_CONFIG" && \
+-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid >= 2.24\""; } >&5
+-  ($PKG_CONFIG --exists --print-errors "blkid >= 2.24") 2>&5
++    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid >= 2.23\""; } >&5
++  ($PKG_CONFIG --exists --print-errors "blkid >= 2.23") 2>&5
+   ac_status=$?
+   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }; then
+-  pkg_cv_BLKID_CFLAGS=`$PKG_CONFIG --cflags "blkid >= 2.24" 2>/dev/null`
++  pkg_cv_BLKID_CFLAGS=`$PKG_CONFIG --cflags "blkid >= 2.23" 2>/dev/null`
+ 		      test "x$?" != "x0" && pkg_failed=yes
+ else
+   pkg_failed=yes
+@@ -12128,12 +12128,12 @@ if test -n "$BLKID_LIBS"; then
+     pkg_cv_BLKID_LIBS="$BLKID_LIBS"
+  elif test -n "$PKG_CONFIG"; then
+     if test -n "$PKG_CONFIG" && \
+-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid >= 2.24\""; } >&5
+-  ($PKG_CONFIG --exists --print-errors "blkid >= 2.24") 2>&5
++    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid >= 2.23\""; } >&5
++  ($PKG_CONFIG --exists --print-errors "blkid >= 2.23") 2>&5
+   ac_status=$?
+   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }; then
+-  pkg_cv_BLKID_LIBS=`$PKG_CONFIG --libs "blkid >= 2.24" 2>/dev/null`
++  pkg_cv_BLKID_LIBS=`$PKG_CONFIG --libs "blkid >= 2.23" 2>/dev/null`
+ 		      test "x$?" != "x0" && pkg_failed=yes
+ else
+   pkg_failed=yes
+@@ -12154,9 +12154,9 @@ else
+         _pkg_short_errors_supported=no
+ fi
+         if test $_pkg_short_errors_supported = yes; then
+-	        BLKID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "blkid >= 2.24" 2>&1`
++	        BLKID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "blkid >= 2.23" 2>&1`
+         else
+-	        BLKID_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "blkid >= 2.24" 2>&1`
++	        BLKID_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "blkid >= 2.23" 2>&1`
+         fi
+ 	# Put the nasty error message in config.log where it belongs
+ 	echo "$BLKID_PKG_ERRORS" >&5
+@@ -12164,7 +12164,7 @@ fi
+ 	if test "$BLKID_WIPING" = maybe; then
+ 				BLKID_WIPING=no
+ 			   else
+-			        as_fn_error $? "bailing out... blkid library >= 2.24 is required" "$LINENO" 5
++			        as_fn_error $? "bailing out... blkid library >= 2.23 is required" "$LINENO" 5
+ 			   fi
+ elif test $pkg_failed = untried; then
+      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+@@ -12172,7 +12172,7 @@ $as_echo "no" >&6; }
+ 	if test "$BLKID_WIPING" = maybe; then
+ 				BLKID_WIPING=no
+ 			   else
+-			        as_fn_error $? "bailing out... blkid library >= 2.24 is required" "$LINENO" 5
++			        as_fn_error $? "bailing out... blkid library >= 2.23 is required" "$LINENO" 5
+ 			   fi
+ else
+ 	BLKID_CFLAGS=$pkg_cv_BLKID_CFLAGS
+diff --git a/configure.ac b/configure.ac
+index 379d37f..e6bb905 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1235,7 +1235,7 @@ AC_ARG_ENABLE(blkid_wiping,
+ DEFAULT_USE_BLKID_WIPING=0
+ if test "$BLKID_WIPING" != no; then
+ 	pkg_config_init
+-	PKG_CHECK_MODULES(BLKID, blkid >= 2.24,
++	PKG_CHECK_MODULES(BLKID, blkid >= 2.23,
+ 			  [ BLKID_WIPING=yes
+ 			    BLKID_PC="blkid"
+ 			    DEFAULT_USE_BLKID_WIPING=1
+@@ -1243,7 +1243,7 @@ if test "$BLKID_WIPING" != no; then
+ 			  ], [if test "$BLKID_WIPING" = maybe; then
+ 				BLKID_WIPING=no
+ 			   else
+-			        AC_MSG_ERROR([bailing out... blkid library >= 2.24 is required])
++			        AC_MSG_ERROR([bailing out... blkid library >= 2.23 is required])
+ 			   fi])
+ fi
+ AC_MSG_CHECKING([whether to enable libblkid detection of signatures when wiping])
+diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
+index 14a28dc..c2e2365 100644
+--- a/lib/device/dev-type.c
++++ b/lib/device/dev-type.c
+@@ -711,8 +711,7 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
+ 						 BLKID_SUBLKS_TYPE |
+ 						 BLKID_SUBLKS_USAGE |
+ 						 BLKID_SUBLKS_VERSION |
+-						 BLKID_SUBLKS_MAGIC |
+-						 BLKID_SUBLKS_BADCSUM);
++						 BLKID_SUBLKS_MAGIC);
+ 
+ 	while (!blkid_do_probe(probe)) {
+ 		if ((r_wipe = _blkid_wipe(probe, dev, name, types_to_exclude, types_no_prompt, yes, force)) == 1) {
diff --git a/SOURCES/lvm2-fix-libdm-versioning-for-dm_tree_node_size_changed-symbol.patch b/SOURCES/lvm2-fix-libdm-versioning-for-dm_tree_node_size_changed-symbol.patch
new file mode 100644
index 0000000..5a941ea
--- /dev/null
+++ b/SOURCES/lvm2-fix-libdm-versioning-for-dm_tree_node_size_changed-symbol.patch
@@ -0,0 +1,21 @@
+ libdm/.exported_symbols.DM_1_02_107 | 1 +
+ libdm/.exported_symbols.DM_1_02_110 | 1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libdm/.exported_symbols.DM_1_02_107 b/libdm/.exported_symbols.DM_1_02_107
+index 89d3464..0c7b7af 100644
+--- a/libdm/.exported_symbols.DM_1_02_107
++++ b/libdm/.exported_symbols.DM_1_02_107
+@@ -13,3 +13,4 @@ dm_stats_create_region
+ dm_stats_driver_supports_histogram
+ dm_stats_get_histogram
+ dm_stats_get_region_nr_histogram_bins
++dm_tree_node_size_changed
+diff --git a/libdm/.exported_symbols.DM_1_02_110 b/libdm/.exported_symbols.DM_1_02_110
+index eba5625..da742ee 100644
+--- a/libdm/.exported_symbols.DM_1_02_110
++++ b/libdm/.exported_symbols.DM_1_02_110
+@@ -1,3 +1,2 @@
+ dm_report_compact_given_fields
+ dm_hold_control_dev
+-dm_tree_node_size_changed
diff --git a/SOURCES/lvm2-make-generate.patch b/SOURCES/lvm2-make-generate.patch
new file mode 100644
index 0000000..ac74f50
--- /dev/null
+++ b/SOURCES/lvm2-make-generate.patch
@@ -0,0 +1,239 @@
+ conf/example.conf.in      | 20 ++++++++++++++++----
+ man/pvcreate.8_pregen     |  7 ++++---
+ man/vgcfgrestore.8_pregen |  9 +++++----
+ man/vgconvert.8_pregen    | 14 +++++++++-----
+ man/vgcreate.8_pregen     |  7 ++++---
+ man/vgextend.8_pregen     |  7 ++++---
+ man/vgsplit.8_pregen      |  7 ++++---
+ 7 files changed, 46 insertions(+), 25 deletions(-)
+
+diff --git a/conf/example.conf.in b/conf/example.conf.in
+index 4418f56..6f7b161 100644
+--- a/conf/example.conf.in
++++ b/conf/example.conf.in
+@@ -716,17 +716,29 @@ global {
+ 	activation = 1
+ 
+ 	# Configuration option global/fallback_to_lvm1.
+-	# This setting is no longer used.
++	# Try running LVM1 tools if LVM cannot communicate with DM.
++	# This option only applies to 2.4 kernels and is provided to help
++	# switch between device-mapper kernels and LVM1 kernels. The LVM1
++	# tools need to be installed with .lvm1 suffices, e.g. vgscan.lvm1.
++	# They will stop working once the lvm2 on-disk metadata format is used.
+ 	# This configuration option has an automatic default value.
+-	# fallback_to_lvm1 = 0
++	# fallback_to_lvm1 = @DEFAULT_FALLBACK_TO_LVM1@
+ 
+ 	# Configuration option global/format.
+-	# This setting is no longer used.
++	# The default metadata format that commands should use.
++	# The -M 1|2 option overrides this setting.
++	# 
++	# Accepted values:
++	#   lvm1
++	#   lvm2
++	# 
+ 	# This configuration option has an automatic default value.
+ 	# format = "lvm2"
+ 
+ 	# Configuration option global/format_libraries.
+-	# This setting is no longer used.
++	# Shared libraries that process different metadata formats.
++	# If support for LVM1 metadata was compiled as a shared library use
++	# format_libraries = "liblvm2format1.so"
+ 	# This configuration option does not have a default value defined.
+ 
+ 	# Configuration option global/segment_libraries.
+diff --git a/man/pvcreate.8_pregen b/man/pvcreate.8_pregen
+index c4b03da..abceb82 100644
+--- a/man/pvcreate.8_pregen
++++ b/man/pvcreate.8_pregen
+@@ -38,7 +38,7 @@ normally prevent it, e.g. if the PV is already in a VG.
+ .ad b
+ .br
+ .ad l
+-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ]
++[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ]
+ .ad b
+ .br
+ .ad l
+@@ -266,11 +266,12 @@ The size may be rounded.
+ .ad b
+ .HP
+ .ad l
+-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP
++\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP
+ .br
+ Specifies the type of on-disk metadata to use.
+ \fBlvm2\fP (or just \fB2\fP) is the current, standard format.
+-\fBlvm1\fP (or just \fB1\fP) is no longer used.
++\fBlvm1\fP (or just \fB1\fP) is a historical format that
++can be used for accessing old data.
+ .ad b
+ .HP
+ .ad l
+diff --git a/man/vgcfgrestore.8_pregen b/man/vgcfgrestore.8_pregen
+index cffd44b..e028103 100644
+--- a/man/vgcfgrestore.8_pregen
++++ b/man/vgcfgrestore.8_pregen
+@@ -51,7 +51,7 @@ vgcfgrestore - Restore volume group configuration
+ .ad b
+ .br
+ .ad l
+- \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP
++ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP
+ .ad b
+ .br
+ .ad l
+@@ -141,7 +141,7 @@ Common options for command:
+ .
+ .RS 4
+ .ad l
+-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ]
++[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ]
+ .ad b
+ .br
+ .ad l
+@@ -280,11 +280,12 @@ Display long help text.
+ .ad b
+ .HP
+ .ad l
+-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP
++\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP
+ .br
+ Specifies the type of on-disk metadata to use.
+ \fBlvm2\fP (or just \fB2\fP) is the current, standard format.
+-\fBlvm1\fP (or just \fB1\fP) is no longer used.
++\fBlvm1\fP (or just \fB1\fP) is a historical format that
++can be used for accessing old data.
+ .ad b
+ .HP
+ .ad l
+diff --git a/man/vgconvert.8_pregen b/man/vgconvert.8_pregen
+index 5e7f8a9..6228087 100644
+--- a/man/vgconvert.8_pregen
++++ b/man/vgconvert.8_pregen
+@@ -8,9 +8,12 @@ vgconvert - Change volume group metadata format
+     [ \fIoption_args\fP ]
+ .br
+ .SH DESCRIPTION
+-vgconvert converts VG metadata from one format to another.  This command
+-is no longer used because this version of lvm no longer supports the LVM1
++vgconvert converts VG metadata from one format to another.  The new
++metadata format must be able to fit into the space provided by the old
+ format.
++
++Because the LVM1 format should no longer be used, this command is no
++longer needed in general.
+ .SH USAGE
+ \fBvgconvert\fP \fIVG\fP ...
+ .br
+@@ -20,7 +23,7 @@ format.
+ .ad b
+ .br
+ .ad l
+-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ]
++[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ]
+ .ad b
+ .br
+ .ad l
+@@ -191,11 +194,12 @@ The size may be rounded.
+ .ad b
+ .HP
+ .ad l
+-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP
++\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP
+ .br
+ Specifies the type of on-disk metadata to use.
+ \fBlvm2\fP (or just \fB2\fP) is the current, standard format.
+-\fBlvm1\fP (or just \fB1\fP) is no longer used.
++\fBlvm1\fP (or just \fB1\fP) is a historical format that
++can be used for accessing old data.
+ .ad b
+ .HP
+ .ad l
+diff --git a/man/vgcreate.8_pregen b/man/vgcreate.8_pregen
+index 09bf126..ddad391 100644
+--- a/man/vgcreate.8_pregen
++++ b/man/vgcreate.8_pregen
+@@ -33,7 +33,7 @@ devices are also available with vgcreate.
+ .ad b
+ .br
+ .ad l
+-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ]
++[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ]
+ .ad b
+ .br
+ .ad l
+@@ -324,11 +324,12 @@ The size may be rounded.
+ .ad b
+ .HP
+ .ad l
+-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP
++\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP
+ .br
+ Specifies the type of on-disk metadata to use.
+ \fBlvm2\fP (or just \fB2\fP) is the current, standard format.
+-\fBlvm1\fP (or just \fB1\fP) is no longer used.
++\fBlvm1\fP (or just \fB1\fP) is a historical format that
++can be used for accessing old data.
+ .ad b
+ .HP
+ .ad l
+diff --git a/man/vgextend.8_pregen b/man/vgextend.8_pregen
+index a6a30e9..ee805a8 100644
+--- a/man/vgextend.8_pregen
++++ b/man/vgextend.8_pregen
+@@ -36,7 +36,7 @@ will initialize them. In this case pvcreate options can be used, e.g.
+ .ad b
+ .br
+ .ad l
+-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ]
++[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ]
+ .ad b
+ .br
+ .ad l
+@@ -237,11 +237,12 @@ The size may be rounded.
+ .ad b
+ .HP
+ .ad l
+-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP
++\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP
+ .br
+ Specifies the type of on-disk metadata to use.
+ \fBlvm2\fP (or just \fB2\fP) is the current, standard format.
+-\fBlvm1\fP (or just \fB1\fP) is no longer used.
++\fBlvm1\fP (or just \fB1\fP) is a historical format that
++can be used for accessing old data.
+ .ad b
+ .HP
+ .ad l
+diff --git a/man/vgsplit.8_pregen b/man/vgsplit.8_pregen
+index 6c3e6ec..210c266 100644
+--- a/man/vgsplit.8_pregen
++++ b/man/vgsplit.8_pregen
+@@ -62,7 +62,7 @@ Common options for command:
+ .ad b
+ .br
+ .ad l
+-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ]
++[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ]
+ .ad b
+ .br
+ .ad l
+@@ -230,11 +230,12 @@ and --vgmetadatacopies for improving performance.
+ .ad b
+ .HP
+ .ad l
+-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP
++\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP
+ .br
+ Specifies the type of on-disk metadata to use.
+ \fBlvm2\fP (or just \fB2\fP) is the current, standard format.
+-\fBlvm1\fP (or just \fB1\fP) is no longer used.
++\fBlvm1\fP (or just \fB1\fP) is a historical format that
++can be used for accessing old data.
+ .ad b
+ .HP
+ .ad l
diff --git a/SOURCES/lvm2-rhel7-add-lvm1-and-pool-back.patch b/SOURCES/lvm2-rhel7-add-lvm1-and-pool-back.patch
new file mode 100644
index 0000000..a16d52e
--- /dev/null
+++ b/SOURCES/lvm2-rhel7-add-lvm1-and-pool-back.patch
@@ -0,0 +1,6368 @@
+ configure                         |  93 ++++-
+ configure.ac                      |  58 +++
+ daemons/clvmd/clvmd-command.c     |   1 +
+ daemons/clvmd/lvm-functions.c     |  10 +
+ daemons/clvmd/lvm-functions.h     |   1 +
+ daemons/lvmetad/lvmetad-client.h  |   1 +
+ daemons/lvmetad/lvmetad-core.c    |   9 +-
+ include/configure.h.in            |  14 +
+ lib/Makefile.in                   |  29 ++
+ lib/activate/activate.c           |  13 +
+ lib/activate/activate.h           |   1 +
+ lib/cache/lvmcache.c              |   4 +
+ lib/cache/lvmetad.c               |  23 +-
+ lib/commands/toolcontext.c        |  24 ++
+ lib/config/config_settings.h      |  22 +-
+ lib/display/display.c             |   9 +-
+ lib/format1/.exported_symbols     |   1 +
+ lib/format1/Makefile.in           |  33 ++
+ lib/format1/disk-rep.c            | 761 ++++++++++++++++++++++++++++++++++++++
+ lib/format1/disk-rep.h            | 250 +++++++++++++
+ lib/format1/format1.c             | 630 +++++++++++++++++++++++++++++++
+ lib/format1/format1.h             |  29 ++
+ lib/format1/import-export.c       | 680 ++++++++++++++++++++++++++++++++++
+ lib/format1/import-extents.c      | 377 +++++++++++++++++++
+ lib/format1/layout.c              | 172 +++++++++
+ lib/format1/lvm1-label.c          | 129 +++++++
+ lib/format1/lvm1-label.h          |  23 ++
+ lib/format1/vg_number.c           |  60 +++
+ lib/format_pool/.exported_symbols |   1 +
+ lib/format_pool/Makefile.in       |  30 ++
+ lib/format_pool/disk_rep.c        | 409 ++++++++++++++++++++
+ lib/format_pool/disk_rep.h        | 156 ++++++++
+ lib/format_pool/format_pool.c     | 337 +++++++++++++++++
+ lib/format_pool/format_pool.h     |  28 ++
+ lib/format_pool/import_export.c   | 285 ++++++++++++++
+ lib/format_pool/pool_label.c      | 104 ++++++
+ lib/format_pool/pool_label.h      |  23 ++
+ lib/format_pool/sptype_names.h    |  42 +++
+ lib/format_text/export.c          |   2 +
+ lib/format_text/format-text.c     |   4 +-
+ lib/format_text/import_vsn1.c     |   9 +-
+ lib/locking/locking.c             |  40 ++
+ lib/metadata/lv_manip.c           |  26 ++
+ lib/metadata/metadata-exported.h  |  10 +-
+ lib/metadata/metadata.c           |  18 +-
+ lib/metadata/segtype.h            |   2 +-
+ lib/metadata/snapshot_manip.c     |  11 +
+ lib/metadata/vg.c                 |  17 +-
+ lib/metadata/vg.h                 |   1 +
+ lib/report/report.c               |   4 +-
+ lib/striped/striped.c             |   3 +-
+ man/vgconvert.8_des               |   7 +-
+ test/shell/format-lvm1.sh         |  38 ++
+ test/shell/lvm1-basic.sh          |  36 ++
+ test/shell/snapshot-lvm1.sh       |  35 ++
+ tools/args.h                      |   3 +-
+ tools/lvconvert.c                 |   5 +
+ tools/lvmcmdline.c                |  59 ++-
+ tools/pvscan.c                    |   5 +-
+ tools/stub.h                      |   1 +
+ tools/toollib.c                   |  29 +-
+ tools/vals.h                      |   4 +-
+ tools/vgchange.c                  |  10 +
+ tools/vgconvert.c                 |  53 ++-
+ tools/vgscan.c                    |   4 +-
+ 65 files changed, 5255 insertions(+), 53 deletions(-)
+ create mode 100644 lib/format1/.exported_symbols
+ create mode 100644 lib/format1/Makefile.in
+ create mode 100644 lib/format1/disk-rep.c
+ create mode 100644 lib/format1/disk-rep.h
+ create mode 100644 lib/format1/format1.c
+ create mode 100644 lib/format1/format1.h
+ create mode 100644 lib/format1/import-export.c
+ create mode 100644 lib/format1/import-extents.c
+ create mode 100644 lib/format1/layout.c
+ create mode 100644 lib/format1/lvm1-label.c
+ create mode 100644 lib/format1/lvm1-label.h
+ create mode 100644 lib/format1/vg_number.c
+ create mode 100644 lib/format_pool/.exported_symbols
+ create mode 100644 lib/format_pool/Makefile.in
+ create mode 100644 lib/format_pool/disk_rep.c
+ create mode 100644 lib/format_pool/disk_rep.h
+ create mode 100644 lib/format_pool/format_pool.c
+ create mode 100644 lib/format_pool/format_pool.h
+ create mode 100644 lib/format_pool/import_export.c
+ create mode 100644 lib/format_pool/pool_label.c
+ create mode 100644 lib/format_pool/pool_label.h
+ create mode 100644 lib/format_pool/sptype_names.h
+ create mode 100644 test/shell/format-lvm1.sh
+ create mode 100644 test/shell/lvm1-basic.sh
+ create mode 100644 test/shell/snapshot-lvm1.sh
+
+diff --git a/configure b/configure
+index f357462..2585e58 100755
+--- a/configure
++++ b/configure
+@@ -675,6 +675,7 @@ PYTHON_BINDINGS
+ PYTHON3
+ PTHREAD_LIBS
+ M_LIBS
++POOL
+ PKGCONFIG
+ ODIRECT
+ OCFDIR
+@@ -689,6 +690,8 @@ LVM_MINOR
+ LVM_MAJOR
+ LVM_LIBAPI
+ LVM_VERSION
++LVM1_FALLBACK
++LVM1
+ LIB_SUFFIX
+ LDDEPS
+ JOBS
+@@ -716,6 +719,7 @@ DEFAULT_RAID10_SEGTYPE
+ DEFAULT_PROFILE_SUBDIR
+ DEFAULT_PID_DIR
+ DEFAULT_MIRROR_SEGTYPE
++DEFAULT_FALLBACK_TO_LVM1
+ DEFAULT_LOCK_DIR
+ DEFAULT_DM_RUN_DIR
+ DEFAULT_DATA_ALIGNMENT
+@@ -908,6 +912,9 @@ with_device_gid
+ with_device_mode
+ with_device_nodes_on
+ with_default_name_mangling
++enable_lvm1_fallback
++with_lvm1
++with_pool
+ with_cluster
+ with_snapshots
+ with_mirrors
+@@ -1673,6 +1680,8 @@ Optional Features:
+                           speeds up one-time build.
+   --enable-static_link    use this to link the tools to their libraries
+                           statically (default is dynamic linking
++  --enable-lvm1_fallback  use this to fall back and use LVM1 binaries if
++                          device-mapper is missing from the kernel
+   --disable-thin_check_needs_check
+                           required if thin_check version is < 0.3.0
+   --disable-cache_check_needs_check
+@@ -1739,6 +1748,10 @@ Optional Packages:
+                           create nodes on resume or create [ON=resume]
+   --with-default-name-mangling=MANGLING
+                           default name mangling: auto/none/hex [auto]
++  --with-lvm1=TYPE        LVM1 metadata support: internal/shared/none
++                          [internal]
++  --with-pool=TYPE        GFS pool read-only support: internal/shared/none
++                          [internal]
+   --with-cluster=TYPE     cluster LVM locking support: internal/shared/none
+                           [internal]
+   --with-snapshots=TYPE   snapshot support: internal/shared/none [internal]
+@@ -8372,6 +8385,78 @@ _ACEOF
+ 
+ 
+ ################################################################################
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable lvm1 fallback" >&5
++$as_echo_n "checking whether to enable lvm1 fallback... " >&6; }
++# Check whether --enable-lvm1_fallback was given.
++if test "${enable_lvm1_fallback+set}" = set; then :
++  enableval=$enable_lvm1_fallback; LVM1_FALLBACK=$enableval
++else
++  LVM1_FALLBACK=no
++fi
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LVM1_FALLBACK" >&5
++$as_echo "$LVM1_FALLBACK" >&6; }
++
++if test "$LVM1_FALLBACK" = yes; then
++	DEFAULT_FALLBACK_TO_LVM1=1
++
++$as_echo "#define LVM1_FALLBACK 1" >>confdefs.h
++
++else
++	DEFAULT_FALLBACK_TO_LVM1=0
++fi
++
++cat >>confdefs.h <<_ACEOF
++#define DEFAULT_FALLBACK_TO_LVM1 $DEFAULT_FALLBACK_TO_LVM1
++_ACEOF
++
++
++################################################################################
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include support for lvm1 metadata" >&5
++$as_echo_n "checking whether to include support for lvm1 metadata... " >&6; }
++
++# Check whether --with-lvm1 was given.
++if test "${with_lvm1+set}" = set; then :
++  withval=$with_lvm1; LVM1=$withval
++else
++  LVM1=internal
++fi
++
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LVM1" >&5
++$as_echo "$LVM1" >&6; }
++
++case "$LVM1" in
++  none|shared) ;;
++  internal)
++$as_echo "#define LVM1_INTERNAL 1" >>confdefs.h
++ ;;
++  *) as_fn_error $? "--with-lvm1 parameter invalid" "$LINENO" 5 ;;
++esac
++
++################################################################################
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include support for GFS pool metadata" >&5
++$as_echo_n "checking whether to include support for GFS pool metadata... " >&6; }
++
++# Check whether --with-pool was given.
++if test "${with_pool+set}" = set; then :
++  withval=$with_pool; POOL=$withval
++else
++  POOL=internal
++fi
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $POOL" >&5
++$as_echo "$POOL" >&6; }
++
++case "$POOL" in
++  none|shared) ;;
++  internal)
++$as_echo "#define POOL_INTERNAL 1" >>confdefs.h
++ ;;
++  *) as_fn_error $? "--with-pool parameter invalid" "$LINENO" 5
++esac
++
++################################################################################
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include support for cluster locking" >&5
+ $as_echo_n "checking whether to include support for cluster locking... " >&6; }
+ 
+@@ -15558,8 +15643,12 @@ _ACEOF
+ 
+ 
+ 
++
++
++
++
+ ################################################################################
+-ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmeventd/plugins/vdo/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile device_mapper/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/locking/Makefile include/lvm-version.h libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/api/python_lvm_unit.py test/unit/Makefile tools/Makefile udev/Makefile"
++ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmeventd/plugins/vdo/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile device_mapper/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile include/lvm-version.h libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/api/python_lvm_unit.py test/unit/Makefile tools/Makefile udev/Makefile"
+ 
+ cat >confcache <<\_ACEOF
+ # This file is a shell script that caches the results of configure
+@@ -16286,6 +16375,8 @@ do
+     "include/.symlinks") CONFIG_FILES="$CONFIG_FILES include/.symlinks" ;;
+     "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+     "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
++    "lib/format1/Makefile") CONFIG_FILES="$CONFIG_FILES lib/format1/Makefile" ;;
++    "lib/format_pool/Makefile") CONFIG_FILES="$CONFIG_FILES lib/format_pool/Makefile" ;;
+     "lib/locking/Makefile") CONFIG_FILES="$CONFIG_FILES lib/locking/Makefile" ;;
+     "include/lvm-version.h") CONFIG_FILES="$CONFIG_FILES include/lvm-version.h" ;;
+     "libdaemon/Makefile") CONFIG_FILES="$CONFIG_FILES libdaemon/Makefile" ;;
+diff --git a/configure.ac b/configure.ac
+index e6bb905..ad356b8 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -283,6 +283,58 @@ AC_MSG_RESULT($MANGLING)
+ AC_DEFINE_UNQUOTED([DEFAULT_DM_NAME_MANGLING], $mangling, [Define default name mangling behaviour])
+ 
+ ################################################################################
++dnl -- LVM1 tool fallback option
++AC_MSG_CHECKING(whether to enable lvm1 fallback)
++AC_ARG_ENABLE(lvm1_fallback,
++	      AC_HELP_STRING([--enable-lvm1_fallback],
++			     [use this to fall back and use LVM1 binaries if
++			      device-mapper is missing from the kernel]),
++	      LVM1_FALLBACK=$enableval, LVM1_FALLBACK=no)
++AC_MSG_RESULT($LVM1_FALLBACK)
++
++if test "$LVM1_FALLBACK" = yes; then
++	DEFAULT_FALLBACK_TO_LVM1=1
++	AC_DEFINE([LVM1_FALLBACK], 1, [Define to 1 if 'lvm' should fall back to using LVM1 binaries if device-mapper is missing from the kernel])
++else
++	DEFAULT_FALLBACK_TO_LVM1=0
++fi
++AC_DEFINE_UNQUOTED(DEFAULT_FALLBACK_TO_LVM1, [$DEFAULT_FALLBACK_TO_LVM1],
++		   [Fall back to LVM1 by default if device-mapper is missing from the kernel.])
++
++################################################################################
++dnl -- format1 inclusion type
++AC_MSG_CHECKING(whether to include support for lvm1 metadata)
++AC_ARG_WITH(lvm1,
++	    AC_HELP_STRING([--with-lvm1=TYPE],
++			   [LVM1 metadata support: internal/shared/none [internal]]),
++	    LVM1=$withval, LVM1=internal)
++
++AC_MSG_RESULT($LVM1)
++
++case "$LVM1" in
++  none|shared) ;;
++  internal) AC_DEFINE([LVM1_INTERNAL], 1,
++		      [Define to 1 to include built-in support for LVM1 metadata.]) ;;
++  *) AC_MSG_ERROR([--with-lvm1 parameter invalid]) ;;
++esac
++
++################################################################################
++dnl -- format_pool inclusion type
++AC_MSG_CHECKING(whether to include support for GFS pool metadata)
++AC_ARG_WITH(pool,
++	    AC_HELP_STRING([--with-pool=TYPE],
++			   [GFS pool read-only support: internal/shared/none [internal]]),
++	    POOL=$withval, POOL=internal)
++AC_MSG_RESULT($POOL)
++
++case "$POOL" in
++  none|shared) ;;
++  internal) AC_DEFINE([POOL_INTERNAL], 1,
++		      [Define to 1 to include built-in support for GFS pool metadata.]) ;;
++  *) AC_MSG_ERROR([--with-pool parameter invalid])
++esac
++
++################################################################################
+ dnl -- cluster_locking inclusion type
+ AC_MSG_CHECKING(whether to include support for cluster locking)
+ AC_ARG_WITH(cluster,
+@@ -1967,6 +2019,7 @@ AC_SUBST(DEFAULT_CACHE_SUBDIR)
+ AC_SUBST(DEFAULT_DATA_ALIGNMENT)
+ AC_SUBST(DEFAULT_DM_RUN_DIR)
+ AC_SUBST(DEFAULT_LOCK_DIR)
++AC_SUBST(DEFAULT_FALLBACK_TO_LVM1)
+ AC_SUBST(DEFAULT_MIRROR_SEGTYPE)
+ AC_SUBST(DEFAULT_PID_DIR)
+ AC_SUBST(DEFAULT_PROFILE_SUBDIR)
+@@ -1997,6 +2050,8 @@ AC_SUBST(JOBS)
+ AC_SUBST(LDDEPS)
+ AC_SUBST(LIBS)
+ AC_SUBST(LIB_SUFFIX)
++AC_SUBST(LVM1)
++AC_SUBST(LVM1_FALLBACK)
+ AC_SUBST(LVM_VERSION)
+ AC_SUBST(LVM_LIBAPI)
+ AC_SUBST(LVM_MAJOR)
+@@ -2013,6 +2068,7 @@ AC_SUBST(OCF)
+ AC_SUBST(OCFDIR)
+ AC_SUBST(ODIRECT)
+ AC_SUBST(PKGCONFIG)
++AC_SUBST(POOL)
+ AC_SUBST(M_LIBS)
+ AC_SUBST(PTHREAD_LIBS)
+ AC_SUBST(PYTHON2)
+@@ -2118,6 +2174,8 @@ conf/metadata_profile_template.profile
+ include/.symlinks
+ include/Makefile
+ lib/Makefile
++lib/format1/Makefile
++lib/format_pool/Makefile
+ lib/locking/Makefile
+ include/lvm-version.h
+ libdaemon/Makefile
+diff --git a/daemons/clvmd/clvmd-command.c b/daemons/clvmd/clvmd-command.c
+index ce7f500..2971ecb 100644
+--- a/daemons/clvmd/clvmd-command.c
++++ b/daemons/clvmd/clvmd-command.c
+@@ -108,6 +108,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
+ 		lock_flags = args[1];
+ 		lockname = &args[2];
+ 		/* Check to see if the VG is in use by LVM1 */
++		status = do_check_lvm1(lockname);
+ 		do_lock_vg(lock_cmd, lock_flags, lockname);
+ 		break;
+ 
+diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c
+index d6d395f..477c252 100644
+--- a/daemons/clvmd/lvm-functions.c
++++ b/daemons/clvmd/lvm-functions.c
+@@ -639,6 +639,16 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
+ 	return 0;
+ }
+ 
++/* Check if a VG is in use by LVM1 so we don't stomp on it */
++int do_check_lvm1(const char *vgname)
++{
++	int status;
++
++	status = check_lvm1_vg_inactive(cmd, vgname);
++
++	return status == 1 ? 0 : EBUSY;
++}
++
+ int do_refresh_cache(void)
+ {
+ 	DEBUGLOG("Refreshing context\n");
+diff --git a/daemons/clvmd/lvm-functions.h b/daemons/clvmd/lvm-functions.h
+index 6785997..eac966f 100644
+--- a/daemons/clvmd/lvm-functions.h
++++ b/daemons/clvmd/lvm-functions.h
+@@ -25,6 +25,7 @@ extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
+ extern const char *do_lock_query(char *resource);
+ extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
+ 			char *resource);
++extern int do_check_lvm1(const char *vgname);
+ extern int do_refresh_cache(void);
+ extern int init_clvm(struct dm_hash_table *excl_uuid);
+ extern void destroy_lvm(void);
+diff --git a/daemons/lvmetad/lvmetad-client.h b/daemons/lvmetad/lvmetad-client.h
+index be2623a..a2adfe6 100644
+--- a/daemons/lvmetad/lvmetad-client.h
++++ b/daemons/lvmetad/lvmetad-client.h
+@@ -22,6 +22,7 @@
+ #define LVMETAD_TOKEN_UPDATE_IN_PROGRESS "update in progress"
+ 
+ #define LVMETAD_DISABLE_REASON_DIRECT		"DIRECT"
++#define LVMETAD_DISABLE_REASON_LVM1		"LVM1"
+ #define LVMETAD_DISABLE_REASON_DUPLICATES	"DUPLICATES"
+ #define LVMETAD_DISABLE_REASON_VGRESTORE	"VGRESTORE"
+ #define LVMETAD_DISABLE_REASON_REPAIR		"REPAIR"
+diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
+index 9ae359b..3e379fe 100644
+--- a/daemons/lvmetad/lvmetad-core.c
++++ b/daemons/lvmetad/lvmetad-core.c
+@@ -200,12 +200,12 @@ struct vg_info {
+ #define GLFL_INVALID                   0x00000001
+ #define GLFL_DISABLE                   0x00000002
+ #define GLFL_DISABLE_REASON_DIRECT     0x00000004
+-				    /* 0x00000008 */
++#define GLFL_DISABLE_REASON_LVM1       0x00000008
+ #define GLFL_DISABLE_REASON_DUPLICATES 0x00000010
+ #define GLFL_DISABLE_REASON_VGRESTORE  0x00000020
+ #define GLFL_DISABLE_REASON_REPAIR     0x00000040
+ 
+-#define GLFL_DISABLE_REASON_ALL (GLFL_DISABLE_REASON_DIRECT | GLFL_DISABLE_REASON_REPAIR | GLFL_DISABLE_REASON_DUPLICATES | GLFL_DISABLE_REASON_VGRESTORE)
++#define GLFL_DISABLE_REASON_ALL (GLFL_DISABLE_REASON_DIRECT | GLFL_DISABLE_REASON_REPAIR | GLFL_DISABLE_REASON_LVM1 | GLFL_DISABLE_REASON_DUPLICATES | GLFL_DISABLE_REASON_VGRESTORE)
+ 
+ #define VGFL_INVALID 0x00000001
+ 
+@@ -2369,6 +2369,8 @@ static response set_global_info(lvmetad_state *s, request r)
+ 			reason_flags |= GLFL_DISABLE_REASON_DIRECT;
+ 		if (strstr(reason, LVMETAD_DISABLE_REASON_REPAIR))
+ 			reason_flags |= GLFL_DISABLE_REASON_REPAIR;
++		if (strstr(reason, LVMETAD_DISABLE_REASON_LVM1))
++			reason_flags |= GLFL_DISABLE_REASON_LVM1;
+ 		if (strstr(reason, LVMETAD_DISABLE_REASON_DUPLICATES))
+ 			reason_flags |= GLFL_DISABLE_REASON_DUPLICATES;
+ 		if (strstr(reason, LVMETAD_DISABLE_REASON_VGRESTORE))
+@@ -2427,9 +2429,10 @@ static response get_global_info(lvmetad_state *s, request r)
+ 	pid = (int)daemon_request_int(r, "pid", 0);
+ 
+ 	if (s->flags & GLFL_DISABLE) {
+-		snprintf(reason, REASON_BUF_SIZE, "%s%s%s%s",
++		snprintf(reason, REASON_BUF_SIZE, "%s%s%s%s%s",
+ 			 (s->flags & GLFL_DISABLE_REASON_DIRECT)     ? LVMETAD_DISABLE_REASON_DIRECT "," : "",
+ 			 (s->flags & GLFL_DISABLE_REASON_REPAIR)     ? LVMETAD_DISABLE_REASON_REPAIR "," : "",
++			 (s->flags & GLFL_DISABLE_REASON_LVM1)       ? LVMETAD_DISABLE_REASON_LVM1 "," : "",
+ 			 (s->flags & GLFL_DISABLE_REASON_DUPLICATES) ? LVMETAD_DISABLE_REASON_DUPLICATES "," : "",
+ 			 (s->flags & GLFL_DISABLE_REASON_VGRESTORE)  ? LVMETAD_DISABLE_REASON_VGRESTORE "," : "");
+ 	}
+diff --git a/include/configure.h.in b/include/configure.h.in
+index 812cacc..bbeb565 100644
+--- a/include/configure.h.in
++++ b/include/configure.h.in
+@@ -72,6 +72,10 @@
+ /* Default system configuration directory. */
+ #undef DEFAULT_ETC_DIR
+ 
++/* Fall back to LVM1 by default if device-mapper is missing from the kernel.
++   */
++#undef DEFAULT_FALLBACK_TO_LVM1
++
+ /* Name of default locking directory. */
+ #undef DEFAULT_LOCK_DIR
+ 
+@@ -619,6 +623,13 @@
+    slash. */
+ #undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+ 
++/* Define to 1 if 'lvm' should fall back to using LVM1 binaries if
++   device-mapper is missing from the kernel */
++#undef LVM1_FALLBACK
++
++/* Define to 1 to include built-in support for LVM1 metadata. */
++#undef LVM1_INTERNAL
++
+ /* Path to lvmetad pidfile. */
+ #undef LVMETAD_PIDFILE
+ 
+@@ -681,6 +692,9 @@
+ /* Define to the version of this package. */
+ #undef PACKAGE_VERSION
+ 
++/* Define to 1 to include built-in support for GFS pool metadata. */
++#undef POOL_INTERNAL
++
+ /* Define to 1 to include built-in support for raid. */
+ #undef RAID_INTERNAL
+ 
+diff --git a/lib/Makefile.in b/lib/Makefile.in
+index 1d42235..241cf09 100644
+--- a/lib/Makefile.in
++++ b/lib/Makefile.in
+@@ -16,6 +16,14 @@ srcdir = @srcdir@
+ top_srcdir = @top_srcdir@
+ top_builddir = @top_builddir@
+ 
++ifeq ("@LVM1@", "shared")
++  SUBDIRS = format1
++endif
++
++ifeq ("@POOL@", "shared")
++  SUBDIRS += format_pool
++endif
++
+ ifeq ("@CLUSTER@", "shared")
+   SUBDIRS += locking
+ endif
+@@ -107,6 +115,25 @@ SOURCES =\
+ 	uuid/uuid.c \
+ 	zero/zero.c
+ 
++ifeq ("@LVM1@", "internal")
++  SOURCES +=\
++	format1/disk-rep.c \
++	format1/format1.c \
++	format1/import-export.c \
++	format1/import-extents.c \
++	format1/layout.c \
++	format1/lvm1-label.c \
++	format1/vg_number.c
++endif
++
++ifeq ("@POOL@", "internal")
++  SOURCES +=\
++	format_pool/disk_rep.c \
++	format_pool/format_pool.c \
++	format_pool/import_export.c \
++	format_pool/pool_label.c
++endif
++
+ ifeq ("@CLUSTER@", "internal")
+   SOURCES += locking/cluster_locking.c
+ endif
+@@ -143,6 +170,8 @@ LIB_STATIC = $(LIB_NAME).a
+ 
+ ifeq ($(MAKECMDGOALS),distclean)
+   SUBDIRS =\
++	format1 \
++	format_pool \
+ 	notify \
+ 	locking
+ endif
+diff --git a/lib/activate/activate.c b/lib/activate/activate.c
+index 561a965..0790817 100644
+--- a/lib/activate/activate.c
++++ b/lib/activate/activate.c
+@@ -37,6 +37,19 @@
+ 
+ #define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
+ 
++int lvm1_present(struct cmd_context *cmd)
++{
++	static char path[PATH_MAX];
++
++	if (dm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
++	    < 0) {
++		log_error("LVM1 proc global snprintf failed");
++		return 0;
++	}
++
++	return (path_exists(path)) ? 1 : 0;
++}
++
+ int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
+ 			 struct dm_list *modules)
+ {
+diff --git a/lib/activate/activate.h b/lib/activate/activate.h
+index 524d2bf..43d26d1 100644
+--- a/lib/activate/activate.h
++++ b/lib/activate/activate.h
+@@ -91,6 +91,7 @@ int activation(void);
+ 
+ int driver_version(char *version, size_t size);
+ int library_version(char *version, size_t size);
++int lvm1_present(struct cmd_context *cmd);
+ 
+ int module_present(struct cmd_context *cmd, const char *target_name);
+ int target_present_version(struct cmd_context *cmd, const char *target_name,
+diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
+index 9890325..0bec548 100644
+--- a/lib/cache/lvmcache.c
++++ b/lib/cache/lvmcache.c
+@@ -22,6 +22,8 @@
+ #include "memlock.h"
+ #include "str_list.h"
+ #include "format-text.h"
++#include "format_pool.h"
++#include "format1.h"
+ #include "config.h"
+ 
+ #include "lvmetad.h"
+@@ -545,6 +547,8 @@ void lvmcache_drop_metadata(const char *vgname, int drop_precommitted)
+ 	/* For VG_ORPHANS, we need to invalidate all labels on orphan PVs. */
+ 	if (!strcmp(vgname, VG_ORPHANS)) {
+ 		_drop_metadata(FMT_TEXT_ORPHAN_VG_NAME, 0);
++		_drop_metadata(FMT_LVM1_ORPHAN_VG_NAME, 0);
++		_drop_metadata(FMT_POOL_ORPHAN_VG_NAME, 0);
+ 	} else
+ 		_drop_metadata(vgname, drop_precommitted);
+ }
+diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
+index d7e798d..1eda567 100644
+--- a/lib/cache/lvmetad.c
++++ b/lib/cache/lvmetad.c
+@@ -38,6 +38,8 @@ static const char *_lvmetad_socket = NULL;
+ static struct cmd_context *_lvmetad_cmd = NULL;
+ static int64_t _lvmetad_update_timeout;
+ 
++static int _found_lvm1_metadata = 0;
++
+ static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg, const char *vgid, struct format_type *fmt);
+ 
+ static uint64_t _monotonic_seconds(void)
+@@ -2290,6 +2292,18 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
+ 	if (!baton.fid)
+ 		goto_bad;
+ 
++	if (fmt->features & FMT_OBSOLETE) {
++		fmt->ops->destroy_instance(baton.fid);
++		log_warn("WARNING: Disabling lvmetad cache which does not support obsolete (lvm1) metadata.");
++		lvmetad_set_disabled(cmd, LVMETAD_DISABLE_REASON_LVM1);
++		_found_lvm1_metadata = 1;
++		/*
++		 * return 1 (success) so that we'll continue to populate lvmetad
++		 * instead of leaving the update incomplete.
++		 */
++		return 1;
++	}
++
+ 	lvmcache_foreach_mda(info, _lvmetad_pvscan_single, &baton);
+ 
+ 	if (!baton.vg)
+@@ -2454,9 +2468,11 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
+ 	}
+ 
+ 	/*
+-	 * If lvmetad is disabled, and no duplicate PVs were seen, then re-enable lvmetad.
++	 * If lvmetad is disabled, and no lvm1 metadata was seen and no
++	 * duplicate PVs were seen, then re-enable lvmetad.
+ 	 */
+-	if (lvmetad_is_disabled(cmd, &reason) && !lvmcache_found_duplicate_pvs()) {
++	if (lvmetad_is_disabled(cmd, &reason) &&
++	    !lvmcache_found_duplicate_pvs() && !_found_lvm1_metadata) {
+ 		log_debug_lvmetad("Enabling lvmetad which was previously disabled.");
+ 		lvmetad_clear_disabled(cmd);
+ 	}
+@@ -3104,6 +3120,9 @@ int lvmetad_is_disabled(struct cmd_context *cmd, const char **reason)
+ 		} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_REPAIR)) {
+ 			*reason = "a repair command was run";
+ 
++		} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_LVM1)) {
++			*reason = "LVM1 metadata was found";
++
+ 		} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_DUPLICATES)) {
+ 			*reason = "duplicate PVs were found";
+ 
+diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
+index 95fb343..3db9bb3 100644
+--- a/lib/commands/toolcontext.c
++++ b/lib/commands/toolcontext.c
+@@ -36,6 +36,14 @@
+ #include "sharedlib.h"
+ #endif
+ 
++#ifdef LVM1_INTERNAL
++#include "format1.h"
++#endif
++
++#ifdef POOL_INTERNAL
++#include "format_pool.h"
++#endif
++
+ #include <locale.h>
+ #include <sys/stat.h>
+ #include <sys/syscall.h>
+@@ -1138,12 +1146,14 @@ static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
+ 	}
+ 	nr_filt++;
+ 
++#if 0
+ 	/* signature filter. Required. */
+ 	if (!(filters[nr_filt] = signature_filter_create(cmd->dev_types))) {
+ 		log_error("Failed to create signature device filter");
+ 		goto bad;
+ 	}
+ 	nr_filt++;
++#endif
+ 
+ 	/* md component filter. Optional, non-critical. */
+ 	if (find_config_tree_bool(cmd, devices_md_component_detection_CFG, NULL)) {
+@@ -1344,6 +1354,20 @@ static int _init_formats(struct cmd_context *cmd)
+ 	const struct dm_config_node *cn;
+ #endif
+ 
++#ifdef LVM1_INTERNAL
++	if (!(fmt = init_lvm1_format(cmd)))
++		return 0;
++	fmt->library = NULL;
++	dm_list_add(&cmd->formats, &fmt->list);
++#endif
++
++#ifdef POOL_INTERNAL
++	if (!(fmt = init_pool_format(cmd)))
++		return 0;
++	fmt->library = NULL;
++	dm_list_add(&cmd->formats, &fmt->list);
++#endif
++
+ #ifdef HAVE_LIBDL
+ 	/* Load any formats in shared libs if not static */
+ 	if (!is_static() &&
+diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
+index 02e2b29..9904a62 100644
+--- a/lib/config/config_settings.h
++++ b/lib/config/config_settings.h
+@@ -780,14 +780,26 @@ cfg(global_activation_CFG, "activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, D
+ 	"is not present in the kernel, disabling this should suppress\n"
+ 	"the error messages.\n")
+ 
+-cfg(global_fallback_to_lvm1_CFG, "fallback_to_lvm1", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 18), NULL, 0, NULL,
+-	"This setting is no longer used.\n")
++cfg(global_fallback_to_lvm1_CFG, "fallback_to_lvm1", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LVM1, vsn(1, 0, 18), "@DEFAULT_FALLBACK_TO_LVM1@", 0, NULL,
++	"Try running LVM1 tools if LVM cannot communicate with DM.\n"
++	"This option only applies to 2.4 kernels and is provided to help\n"
++	"switch between device-mapper kernels and LVM1 kernels. The LVM1\n"
++	"tools need to be installed with .lvm1 suffices, e.g. vgscan.lvm1.\n"
++	"They will stop working once the lvm2 on-disk metadata format is used.\n")
+ 
+ cfg(global_format_CFG, "format", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FORMAT, vsn(1, 0, 0), NULL, 0, NULL,
+-	"This setting is no longer used.\n")
+-
++	"The default metadata format that commands should use.\n"
++	"The -M 1|2 option overrides this setting.\n"
++	"#\n"
++	"Accepted values:\n"
++	"  lvm1\n"
++	"  lvm2\n"
++	"#\n")
++ 
+ cfg_array(global_format_libraries_CFG, "format_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
+-	"This setting is no longer used.")
++	"Shared libraries that process different metadata formats.\n"
++	"If support for LVM1 metadata was compiled as a shared library use\n"
++	"format_libraries = \"liblvm2format1.so\"\n")
+ 
+ cfg_array(global_segment_libraries_CFG, "segment_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL, 0, NULL, NULL)
+ 
+diff --git a/lib/display/display.c b/lib/display/display.c
+index 9b4be88..9a928d9 100644
+--- a/lib/display/display.c
++++ b/lib/display/display.c
+@@ -705,10 +705,13 @@ void vgdisplay_full(const struct volume_group *vg)
+ 
+ 	log_print("--- Volume group ---");
+ 	log_print("VG Name               %s", vg->name);
+-	log_print("System ID             %s", (vg->system_id && *vg->system_id) ? vg->system_id : "");
++	log_print("System ID             %s", (vg->system_id && *vg->system_id) ? vg->system_id : vg->lvm1_system_id ? : "");
+ 	log_print("Format                %s", vg->fid->fmt->name);
+-	log_print("Metadata Areas        %d", vg_mda_count(vg));
+-	log_print("Metadata Sequence No  %d", vg->seqno);
++	if (vg->fid->fmt->features & FMT_MDAS) {
++		log_print("Metadata Areas        %d",
++			  vg_mda_count(vg));
++		log_print("Metadata Sequence No  %d", vg->seqno);
++	}
+ 	access_str = vg->status & (LVM_READ | LVM_WRITE);
+ 	log_print("VG Access             %s%s%s%s",
+ 		  access_str == (LVM_READ | LVM_WRITE) ? "read/write" : "",
+diff --git a/lib/format1/.exported_symbols b/lib/format1/.exported_symbols
+new file mode 100644
+index 0000000..e9fac2e
+--- /dev/null
++++ b/lib/format1/.exported_symbols
+@@ -0,0 +1 @@
++init_format
+diff --git a/lib/format1/Makefile.in b/lib/format1/Makefile.in
+new file mode 100644
+index 0000000..4a905c0
+--- /dev/null
++++ b/lib/format1/Makefile.in
+@@ -0,0 +1,33 @@
++#
++# Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
++# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
++#
++# This file is part of LVM2.
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions
++# of the GNU General Public License v.2.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software Foundation,
++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++
++srcdir = @srcdir@
++top_srcdir = @top_srcdir@
++top_builddir = @top_builddir@
++
++SOURCES =\
++	disk-rep.c \
++	format1.c \
++	import-export.c \
++	import-extents.c \
++	layout.c \
++	lvm1-label.c \
++	vg_number.c
++
++LIB_SHARED = liblvm2format1.$(LIB_SUFFIX)
++LIB_VERSION = $(LIB_VERSION_LVM)
++
++include $(top_builddir)/make.tmpl
++
++install: install_lvm2_plugin
+diff --git a/lib/format1/disk-rep.c b/lib/format1/disk-rep.c
+new file mode 100644
+index 0000000..9169d82
+--- /dev/null
++++ b/lib/format1/disk-rep.c
+@@ -0,0 +1,761 @@
++/*
++ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "lib.h"
++#include "disk-rep.h"
++#include "xlate.h"
++#include "lvmcache.h"
++#include "metadata-exported.h"
++
++#include <fcntl.h>
++
++#define xx16(v) disk->v = xlate16(disk->v)
++#define xx32(v) disk->v = xlate32(disk->v)
++#define xx64(v) disk->v = xlate64(disk->v)
++
++/*
++ * Functions to perform the endian conversion
++ * between disk and core.  The same code works
++ * both ways of course.
++ */
++static void _xlate_pvd(struct pv_disk *disk)
++{
++	xx16(version);
++
++	xx32(pv_on_disk.base);
++	xx32(pv_on_disk.size);
++	xx32(vg_on_disk.base);
++	xx32(vg_on_disk.size);
++	xx32(pv_uuidlist_on_disk.base);
++	xx32(pv_uuidlist_on_disk.size);
++	xx32(lv_on_disk.base);
++	xx32(lv_on_disk.size);
++	xx32(pe_on_disk.base);
++	xx32(pe_on_disk.size);
++
++	xx32(pv_major);
++	xx32(pv_number);
++	xx32(pv_status);
++	xx32(pv_allocatable);
++	xx32(pv_size);
++	xx32(lv_cur);
++	xx32(pe_size);
++	xx32(pe_total);
++	xx32(pe_allocated);
++	xx32(pe_start);
++}
++
++static void _xlate_lvd(struct lv_disk *disk)
++{
++	xx32(lv_access);
++	xx32(lv_status);
++	xx32(lv_open);
++	xx32(lv_dev);
++	xx32(lv_number);
++	xx32(lv_mirror_copies);
++	xx32(lv_recovery);
++	xx32(lv_schedule);
++	xx32(lv_size);
++	xx32(lv_snapshot_minor);
++	xx16(lv_chunk_size);
++	xx16(dummy);
++	xx32(lv_allocated_le);
++	xx32(lv_stripes);
++	xx32(lv_stripesize);
++	xx32(lv_badblock);
++	xx32(lv_allocation);
++	xx32(lv_io_timeout);
++	xx32(lv_read_ahead);
++}
++
++static void _xlate_vgd(struct vg_disk *disk)
++{
++	xx32(vg_number);
++	xx32(vg_access);
++	xx32(vg_status);
++	xx32(lv_max);
++	xx32(lv_cur);
++	xx32(lv_open);
++	xx32(pv_max);
++	xx32(pv_cur);
++	xx32(pv_act);
++	xx32(dummy);
++	xx32(vgda);
++	xx32(pe_size);
++	xx32(pe_total);
++	xx32(pe_allocated);
++	xx32(pvg_total);
++}
++
++static void _xlate_extents(struct pe_disk *extents, uint32_t count)
++{
++	unsigned i;
++
++	for (i = 0; i < count; i++) {
++		extents[i].lv_num = xlate16(extents[i].lv_num);
++		extents[i].le_num = xlate16(extents[i].le_num);
++	}
++}
++
++/*
++ * Handle both minor metadata formats.
++ */
++static int _munge_formats(struct pv_disk *pvd)
++{
++	uint32_t pe_start;
++	unsigned b, e;
++
++	switch (pvd->version) {
++	case 1:
++		pvd->pe_start = ((pvd->pe_on_disk.base +
++				  pvd->pe_on_disk.size) >> SECTOR_SHIFT);
++		break;
++
++	case 2:
++		pvd->version = 1;
++		pe_start = pvd->pe_start << SECTOR_SHIFT;
++		pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
++		break;
++
++	default:
++		return 0;
++	}
++
++	/* UUID too long? */
++	if (pvd->pv_uuid[ID_LEN]) {
++		/* Retain ID_LEN chars from end */
++		for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
++			if (!pvd->pv_uuid[e]) {
++				e--;
++				break;
++			}
++		}
++		for (b = 0; b < ID_LEN; b++) {
++			pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
++			/* FIXME Remove all invalid chars */
++			if (pvd->pv_uuid[b] == '/')
++				pvd->pv_uuid[b] = '#';
++		}
++		memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
++	}
++
++	/* If UUID is missing, create one */
++	if (pvd->pv_uuid[0] == '\0') {
++		uuid_from_num((char *)pvd->pv_uuid, pvd->pv_number);
++		pvd->pv_uuid[ID_LEN] = '\0';
++	}
++
++	return 1;
++}
++
++/*
++ * If exported, remove "PV_EXP" from end of VG name
++ */
++static void _munge_exported_vg(struct pv_disk *pvd)
++{
++	int l;
++	size_t s;
++
++	/* Return if PV not in a VG */
++	if ((!*pvd->vg_name))
++		return;
++	/* FIXME also check vgd->status & VG_EXPORTED? */
++
++	l = strlen((char *)pvd->vg_name);
++	s = sizeof(EXPORTED_TAG);
++	if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
++		pvd->vg_name[l - s + 1] = '\0';
++		pvd->pv_status |= VG_EXPORTED;
++	}
++}
++
++int munge_pvd(struct device *dev, struct pv_disk *pvd)
++{
++	_xlate_pvd(pvd);
++
++	if (pvd->id[0] != 'H' || pvd->id[1] != 'M') {
++		log_very_verbose("%s does not have a valid LVM1 PV identifier",
++				 dev_name(dev));
++		return 0;
++	}
++
++	if (!_munge_formats(pvd)) {
++		log_very_verbose("format1: Unknown metadata version %d "
++				 "found on %s", pvd->version, dev_name(dev));
++		return 0;
++	}
++
++	/* If VG is exported, set VG name back to the real name */
++	_munge_exported_vg(pvd);
++
++	return 1;
++}
++
++static int _read_pvd(struct device *dev, struct pv_disk *pvd)
++{
++	if (!dev_read_bytes(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
++		log_very_verbose("Failed to read PV data from %s",
++				 dev_name(dev));
++		return 0;
++	}
++
++	return munge_pvd(dev, pvd);
++}
++
++static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
++{
++	if (!dev_read_bytes(dev, pos, sizeof(*disk), disk))
++		return_0;
++
++	_xlate_lvd(disk);
++
++	return 1;
++}
++
++int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
++{
++	uint64_t pos = pvd->vg_on_disk.base;
++
++	if (!dev_read_bytes(dev, pos, sizeof(*vgd), vgd))
++		return_0;
++
++	_xlate_vgd(vgd);
++
++	if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
++		return_0;
++		
++	/* If UUID is missing, create one */
++	if (vgd->vg_uuid[0] == '\0')
++		uuid_from_num((char *)vgd->vg_uuid, vgd->vg_number);
++
++	return 1;
++}
++
++static int _read_uuids(struct disk_list *data)
++{
++	unsigned num_read = 0;
++	struct uuid_list *ul;
++	char buffer[NAME_LEN] __attribute__((aligned(8)));
++	uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
++	uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
++
++	while (pos < end && num_read < data->vgd.pv_cur) {
++		if (!dev_read_bytes(data->dev, pos, sizeof(buffer), buffer))
++			return_0;
++
++		if (!(ul = dm_pool_alloc(data->mem, sizeof(*ul))))
++			return_0;
++
++		memcpy(ul->uuid, buffer, NAME_LEN);
++		ul->uuid[NAME_LEN - 1] = '\0';
++
++		dm_list_add(&data->uuids, &ul->list);
++
++		pos += NAME_LEN;
++		num_read++;
++	}
++
++	return 1;
++}
++
++static int _check_lvd(struct lv_disk *lvd)
++{
++	return !(lvd->lv_name[0] == '\0');
++}
++
++static int _read_lvs(struct disk_list *data)
++{
++	unsigned int i, lvs_read = 0;
++	uint64_t pos;
++	struct lvd_list *ll;
++	struct vg_disk *vgd = &data->vgd;
++
++	for (i = 0; (i < vgd->lv_max) && (lvs_read < vgd->lv_cur); i++) {
++		pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
++		ll = dm_pool_alloc(data->mem, sizeof(*ll));
++
++		if (!ll)
++			return_0;
++
++		if (!_read_lvd(data->dev, pos, &ll->lvd))
++			return_0;
++
++		if (!_check_lvd(&ll->lvd))
++			continue;
++
++		lvs_read++;
++		dm_list_add(&data->lvds, &ll->list);
++	}
++
++	return 1;
++}
++
++static int _read_extents(struct disk_list *data)
++{
++	size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
++	struct pe_disk *extents = dm_pool_alloc(data->mem, len);
++	uint64_t pos = data->pvd.pe_on_disk.base;
++
++	if (!extents)
++		return_0;
++
++	if (!dev_read_bytes(data->dev, pos, len, extents))
++		return_0;
++
++	_xlate_extents(extents, data->pvd.pe_total);
++	data->extents = extents;
++
++	return 1;
++}
++
++static void __update_lvmcache(const struct format_type *fmt,
++			      struct disk_list *dl,
++			      struct device *dev, const char *vgid,
++			      unsigned exported)
++{
++	struct lvmcache_info *info;
++	const char *vgname = *((char *)dl->pvd.vg_name) ?
++			     (char *)dl->pvd.vg_name : fmt->orphan_vg_name;
++
++	if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
++				  vgname, vgid, exported ? EXPORTED_VG : 0))) {
++		stack;
++		return;
++	}
++
++	lvmcache_set_device_size(info, ((uint64_t)xlate32(dl->pvd.pv_size)) << SECTOR_SHIFT);
++	lvmcache_del_mdas(info);
++}
++
++static struct disk_list *__read_disk(const struct format_type *fmt,
++				     struct device *dev, struct dm_pool *mem,
++				     const char *vg_name)
++{
++	struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
++	const char *name = dev_name(dev);
++
++	if (!dl)
++		return_NULL;
++
++	dl->dev = dev;
++	dl->mem = mem;
++	dm_list_init(&dl->uuids);
++	dm_list_init(&dl->lvds);
++
++	if (!_read_pvd(dev, &dl->pvd))
++		goto_bad;
++
++	/*
++	 * is it an orphan ?
++	 */
++	if (!*dl->pvd.vg_name) {
++		log_very_verbose("%s is not a member of any format1 VG", name);
++
++		__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
++		return (vg_name) ? NULL : dl;
++	}
++
++	if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
++		log_error("Failed to read VG data from PV (%s)", name);
++		__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
++		goto bad;
++	}
++
++	if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
++		log_very_verbose("%s is not a member of the VG %s",
++				 name, vg_name);
++		__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
++		goto bad;
++	}
++
++	__update_lvmcache(fmt, dl, dev, (char *)dl->vgd.vg_uuid,
++			  dl->vgd.vg_status & VG_EXPORTED);
++
++	if (!_read_uuids(dl)) {
++		log_error("Failed to read PV uuid list from %s", name);
++		goto bad;
++	}
++
++	if (!_read_lvs(dl)) {
++		log_error("Failed to read LV's from %s", name);
++		goto bad;
++	}
++
++	if (!_read_extents(dl)) {
++		log_error("Failed to read extents from %s", name);
++		goto bad;
++	}
++
++	log_very_verbose("Found %s in %sVG %s", name,
++			 (dl->vgd.vg_status & VG_EXPORTED) ? "exported " : "",
++			 dl->pvd.vg_name);
++
++	return dl;
++
++      bad:
++	dm_pool_free(dl->mem, dl);
++	return NULL;
++}
++
++struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
++			    struct dm_pool *mem, const char *vg_name)
++{
++	struct disk_list *dl;
++
++	if (!dev_open_readonly(dev))
++		return_NULL;
++
++	dl = __read_disk(fmt, dev, mem, vg_name);
++
++	if (!dev_close(dev))
++		stack;
++
++	return dl;
++}
++
++static void _add_pv_to_list(struct cmd_context *cmd, struct dm_list *head, struct disk_list *data)
++{
++	struct pv_disk *pvd;
++	struct disk_list *diskl;
++
++	dm_list_iterate_items(diskl, head) {
++		pvd = &diskl->pvd;
++		if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid,
++			     sizeof(pvd->pv_uuid))) {
++			if (!dev_subsystem_part_major(cmd->dev_types, data->dev)) {
++				log_very_verbose("Ignoring duplicate PV %s on "
++						 "%s", pvd->pv_uuid,
++						 dev_name(data->dev));
++				return;
++			}
++			log_very_verbose("Duplicate PV %s - using %s %s",
++					 pvd->pv_uuid, dev_subsystem_name(cmd->dev_types, data->dev),
++					 dev_name(data->dev));
++			dm_list_del(&diskl->list);
++			break;
++		}
++	}
++	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(lvmcache_fmt(info)->cmd, 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
++ * so we can free off all the memory if something goes wrong.
++ */
++int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
++		   struct dev_filter *filter, struct dm_pool *mem,
++		   struct dm_list *head)
++{
++	struct dev_iter *iter;
++	struct device *dev;
++	struct lvmcache_vginfo *vginfo;
++	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 = lvmcache_vginfo_from_vgname(vg_name, NULL))) {
++
++		lvmcache_foreach_pv(vginfo, _read_pv_in_vg, &baton);
++
++		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))) {
++		log_error("read_pvs_in_vg: dev_iter_create failed");
++		return 0;
++	}
++
++	/* Otherwise do a complete scan */
++	for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
++		if ((baton.data = read_disk(fmt, dev, mem, vg_name))) {
++			_add_pv_to_list(fmt->cmd, head, baton.data);
++		}
++	}
++	dev_iter_destroy(iter);
++
++	if (dm_list_empty(head))
++		return 0;
++
++	return 1;
++}
++
++static int _write_vgd(struct disk_list *data)
++{
++	struct vg_disk *vgd = &data->vgd;
++	uint64_t pos = data->pvd.vg_on_disk.base;
++
++	log_debug_metadata("Writing %s VG metadata to %s at %" PRIu64 " len %" PRIsize_t,
++			   data->pvd.vg_name, dev_name(data->dev), pos, sizeof(*vgd));
++
++	_xlate_vgd(vgd);
++	if (!dev_write(data->dev, pos, sizeof(*vgd), DEV_IO_FMT1, vgd))
++		return_0;
++
++	_xlate_vgd(vgd);
++
++	return 1;
++}
++
++static int _write_uuids(struct disk_list *data)
++{
++	struct uuid_list *ul;
++	uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
++	uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
++
++	dm_list_iterate_items(ul, &data->uuids) {
++		if (pos >= end) {
++			log_error("Too many uuids to fit on %s",
++				  dev_name(data->dev));
++			return 0;
++		}
++
++		log_debug_metadata("Writing %s uuidlist to %s at %" PRIu64 " len %d",
++				   data->pvd.vg_name, dev_name(data->dev),
++				   pos, NAME_LEN);
++
++		if (!dev_write(data->dev, pos, NAME_LEN, DEV_IO_FMT1, ul->uuid))
++			return_0;
++
++		pos += NAME_LEN;
++	}
++
++	return 1;
++}
++
++static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
++{
++	log_debug_metadata("Writing %s LV %s metadata to %s at %" PRIu64 " len %"
++			   PRIsize_t, disk->vg_name, disk->lv_name, dev_name(dev),
++			   pos, sizeof(*disk));
++
++	_xlate_lvd(disk);
++	if (!dev_write(dev, pos, sizeof(*disk), DEV_IO_FMT1, disk))
++		return_0;
++
++	_xlate_lvd(disk);
++
++	return 1;
++}
++
++static int _write_lvs(struct disk_list *data)
++{
++	struct lvd_list *ll;
++	uint64_t pos, offset;
++
++	pos = data->pvd.lv_on_disk.base;
++
++	if (!dev_set(data->dev, pos, data->pvd.lv_on_disk.size, DEV_IO_FMT1, 0)) {
++		log_error("Couldn't zero lv area on device '%s'",
++			  dev_name(data->dev));
++		return 0;
++	}
++
++	dm_list_iterate_items(ll, &data->lvds) {
++		offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
++		if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
++			log_error("lv_number %d too large", ll->lvd.lv_number);
++			return 0;
++		}
++
++		if (!_write_lvd(data->dev, pos + offset, &ll->lvd))
++			return_0;
++	}
++
++	return 1;
++}
++
++static int _write_extents(struct disk_list *data)
++{
++	size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
++	struct pe_disk *extents = data->extents;
++	uint64_t pos = data->pvd.pe_on_disk.base;
++
++	log_debug_metadata("Writing %s extents metadata to %s at %" PRIu64 " len %"
++			   PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
++			   pos, len);
++
++	_xlate_extents(extents, data->pvd.pe_total);
++	if (!dev_write(data->dev, pos, len, DEV_IO_FMT1, extents))
++		return_0;
++
++	_xlate_extents(extents, data->pvd.pe_total);
++
++	return 1;
++}
++
++static int _write_pvd(struct disk_list *data)
++{
++	char *buf;
++	uint64_t pos = data->pvd.pv_on_disk.base;
++	size_t size = data->pvd.pv_on_disk.size;
++
++	if (size < sizeof(struct pv_disk)) {
++		log_error("Invalid PV structure size.");
++		return 0;
++	}
++
++	/* Make sure that the gap between the PV structure and
++	   the next one is zeroed in order to make non LVM tools
++	   happy (idea from AED) */
++	buf = dm_zalloc(size);
++	if (!buf) {
++		log_error("Couldn't allocate temporary PV buffer.");
++		return 0;
++	}
++
++	memcpy(buf, &data->pvd, sizeof(struct pv_disk));
++
++	log_debug_metadata("Writing %s PV metadata to %s at %" PRIu64 " len %"
++			   PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
++			   pos, size);
++
++	_xlate_pvd((struct pv_disk *) buf);
++	if (!dev_write(data->dev, pos, size, DEV_IO_FMT1, buf)) {
++		dm_free(buf);
++		return_0;
++	}
++
++	dm_free(buf);
++	return 1;
++}
++
++/*
++ * assumes the device has been opened.
++ */
++static int __write_all_pvd(const struct format_type *fmt __attribute__((unused)),
++			   struct disk_list *data, int write_vg_metadata)
++{
++	const char *pv_name = dev_name(data->dev);
++
++	if (!_write_pvd(data)) {
++		log_error("Failed to write PV structure onto %s", pv_name);
++		return 0;
++	}
++
++	/* vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, fmt); */
++	/*
++	 * Stop here for orphan PVs or if VG metadata write not requested.
++	 */
++	if ((data->pvd.vg_name[0] == '\0') || !write_vg_metadata) {
++		/* if (!test_mode())
++		   vgcache_add(data->pvd.vg_name, NULL, data->dev, fmt); */
++		return 1;
++	}
++
++	/* if (!test_mode())
++	   vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev,
++	   fmt); */
++
++	if (!_write_vgd(data)) {
++		log_error("Failed to write VG data to %s", pv_name);
++		return 0;
++	}
++
++	if (!_write_uuids(data)) {
++		log_error("Failed to write PV uuid list to %s", pv_name);
++		return 0;
++	}
++
++	if (!_write_lvs(data)) {
++		log_error("Failed to write LV's to %s", pv_name);
++		return 0;
++	}
++
++	if (!_write_extents(data)) {
++		log_error("Failed to write extents to %s", pv_name);
++		return 0;
++	}
++
++	return 1;
++}
++
++/*
++ * opens the device and hands to the above fn.
++ */
++static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data, int write_vg_metadata)
++{
++	int r;
++
++	if (!data->dev)
++		return_0;
++
++	if (!dev_open(data->dev))
++		return_0;
++
++	r = __write_all_pvd(fmt, data, write_vg_metadata);
++
++	if (!dev_close(data->dev))
++		stack;
++
++	return r;
++}
++
++/*
++ * Writes all the given pv's to disk.  Does very
++ * little sanity checking, so make sure correct
++ * data is passed to here.
++ */
++int write_disks(const struct format_type *fmt, struct dm_list *pvs, int write_vg_metadata)
++{
++	struct disk_list *dl;
++
++	dm_list_iterate_items(dl, pvs) {
++		if (!(_write_all_pvd(fmt, dl, write_vg_metadata)))
++			return_0;
++
++		log_very_verbose("Successfully wrote data to %s",
++				 dev_name(dl->dev));
++	}
++
++	return 1;
++}
+diff --git a/lib/format1/disk-rep.h b/lib/format1/disk-rep.h
+new file mode 100644
+index 0000000..221ae8e
+--- /dev/null
++++ b/lib/format1/disk-rep.h
+@@ -0,0 +1,250 @@
++/*
++ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
++ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef DISK_REP_FORMAT1_H
++#define DISK_REP_FORMAT1_H
++
++#include "metadata.h"
++#include "toolcontext.h"
++
++#define MAX_PV 256
++#define MAX_LV 256
++#define MAX_VG 99
++
++#define LVM_BLK_MAJOR 58
++
++#define MAX_PV_SIZE	((uint32_t) -1)	/* 2TB in sectors - 1 */
++#define PE_SIZE_PV_SIZE_REL 5	/* PV size must be at least 5 times PE size */
++#define	MAX_LE_TOTAL	65534	/* 2^16 - 2 */
++#define	MAX_PE_TOTAL	((uint32_t) -2)
++
++#define UNMAPPED_EXTENT 0
++
++/* volume group */
++#define	VG_ACTIVE            0x01	/* vg_status */
++#define	VG_EXPORTED          0x02	/*     "     */
++#define	VG_EXTENDABLE        0x04	/*     "     */
++
++#define	VG_READ              0x01	/* vg_access */
++#define	VG_WRITE             0x02	/*     "     */
++#define	VG_CLUSTERED         0x04	/*     "     */
++#define	VG_SHARED            0x08	/*     "     */
++
++/* logical volume */
++#define	LV_ACTIVE            0x01	/* lv_status */
++#define	LV_SPINDOWN          0x02	/*     "     */
++#define LV_PERSISTENT_MINOR  0x04	/*     "     */
++
++#define	LV_READ              0x01	/* lv_access */
++#define	LV_WRITE             0x02	/*     "     */
++#define	LV_SNAPSHOT          0x04	/*     "     */
++#define	LV_SNAPSHOT_ORG      0x08	/*     "     */
++
++#define	LV_BADBLOCK_ON       0x01	/* lv_badblock */
++
++#define	LV_STRICT            0x01	/* lv_allocation */
++#define	LV_CONTIGUOUS        0x02	/*       "       */
++
++/* physical volume */
++#define	PV_ACTIVE            0x01	/* pv_status */
++#define	PV_ALLOCATABLE       0x02	/* pv_allocatable */
++
++#define EXPORTED_TAG "PV_EXP"	/* Identifier for exported PV */
++#define IMPORTED_TAG "PV_IMP"	/* Identifier for imported PV */
++
++struct data_area {
++	uint32_t base;
++	uint32_t size;
++} __attribute__ ((packed));
++
++struct pv_disk {
++	int8_t id[2];
++	uint16_t version;	/* lvm version */
++	struct data_area pv_on_disk;
++	struct data_area vg_on_disk;
++	struct data_area pv_uuidlist_on_disk;
++	struct data_area lv_on_disk;
++	struct data_area pe_on_disk;
++	int8_t pv_uuid[NAME_LEN];
++	int8_t vg_name[NAME_LEN];
++	int8_t system_id[NAME_LEN];	/* for vgexport/vgimport */
++	uint32_t pv_major;
++	uint32_t pv_number;
++	uint32_t pv_status;
++	uint32_t pv_allocatable;
++	uint32_t pv_size;
++	uint32_t lv_cur;
++	uint32_t pe_size;
++	uint32_t pe_total;
++	uint32_t pe_allocated;
++
++	/* only present on version == 2 pv's */
++	uint32_t pe_start;
++} __attribute__ ((packed));
++
++struct lv_disk {
++	int8_t lv_name[NAME_LEN];
++	int8_t vg_name[NAME_LEN];
++	uint32_t lv_access;
++	uint32_t lv_status;
++	uint32_t lv_open;
++	uint32_t lv_dev;
++	uint32_t lv_number;
++	uint32_t lv_mirror_copies;	/* for future use */
++	uint32_t lv_recovery;	/*       "        */
++	uint32_t lv_schedule;	/*       "        */
++	uint32_t lv_size;
++	uint32_t lv_snapshot_minor;	/* minor number of original */
++	uint16_t lv_chunk_size;	/* chunk size of snapshot */
++	uint16_t dummy;
++	uint32_t lv_allocated_le;
++	uint32_t lv_stripes;
++	uint32_t lv_stripesize;
++	uint32_t lv_badblock;	/* for future use */
++	uint32_t lv_allocation;
++	uint32_t lv_io_timeout;	/* for future use */
++	uint32_t lv_read_ahead;
++} __attribute__ ((packed));
++
++struct vg_disk {
++	int8_t vg_uuid[ID_LEN];	/* volume group UUID */
++	int8_t vg_name_dummy[NAME_LEN - ID_LEN];	/* rest of v1 VG name */
++	uint32_t vg_number;	/* volume group number */
++	uint32_t vg_access;	/* read/write */
++	uint32_t vg_status;	/* active or not */
++	uint32_t lv_max;	/* maximum logical volumes */
++	uint32_t lv_cur;	/* current logical volumes */
++	uint32_t lv_open;	/* open logical volumes */
++	uint32_t pv_max;	/* maximum physical volumes */
++	uint32_t pv_cur;	/* current physical volumes FU */
++	uint32_t pv_act;	/* active physical volumes */
++	uint32_t dummy;
++	uint32_t vgda;		/* volume group descriptor arrays FU */
++	uint32_t pe_size;	/* physical extent size in sectors */
++	uint32_t pe_total;	/* total of physical extents */
++	uint32_t pe_allocated;	/* allocated physical extents */
++	uint32_t pvg_total;	/* physical volume groups FU */
++} __attribute__ ((packed));
++
++struct pe_disk {
++	uint16_t lv_num;
++	uint16_t le_num;
++} __attribute__ ((packed));
++
++struct uuid_list {
++	struct dm_list list;
++	char uuid[NAME_LEN] __attribute__((aligned(8)));
++};
++
++struct lvd_list {
++	struct dm_list list;
++	struct lv_disk lvd;
++};
++
++struct disk_list {
++	struct dm_list list;
++	struct dm_pool *mem;
++	struct device *dev;
++
++	struct pv_disk pvd __attribute__((aligned(8)));
++	struct vg_disk vgd __attribute__((aligned(8)));
++	struct dm_list uuids __attribute__((aligned(8)));
++	struct dm_list lvds __attribute__((aligned(8)));
++	struct pe_disk *extents __attribute__((aligned(8)));
++};
++
++/*
++ * Layout constants.
++ */
++#define METADATA_ALIGN 4096UL
++#define LVM1_PE_ALIGN (65536UL >> SECTOR_SHIFT)      /* PE alignment */
++
++#define	METADATA_BASE 0UL
++#define	PV_SIZE 1024UL
++#define	VG_SIZE 4096UL
++
++/*
++ * Functions to calculate layout info.
++ */
++int calculate_layout(struct disk_list *dl);
++int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
++			   uint32_t max_extent_count, uint64_t pe_start);
++
++/*
++ * Low level io routines which read/write
++ * disk_lists.
++ */
++
++struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
++			    struct dm_pool *mem, const char *vg_name);
++
++int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
++		   struct dev_filter *filter,
++		   struct dm_pool *mem, struct dm_list *results);
++
++int write_disks(const struct format_type *fmt, struct dm_list *pvds,
++		int write_vg_metadata);
++
++/*
++ * Functions to translate to between disk and in
++ * core structures.
++ */
++int import_pv(const struct format_type *fmt, struct dm_pool *mem,
++	      struct device *dev, struct volume_group *vg,
++	      struct physical_volume *pv, struct pv_disk *pvd,
++	      struct vg_disk *vgd);
++int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
++	      struct volume_group *vg,
++	      struct pv_disk *pvd, struct physical_volume *pv);
++
++int import_vg(struct dm_pool *mem,
++	      struct volume_group *vg, struct disk_list *dl);
++int export_vg(struct vg_disk *vgd, struct volume_group *vg);
++
++int import_lv(struct cmd_context *cmd, struct dm_pool *mem,
++	      struct logical_volume *lv, struct lv_disk *lvd);
++
++int import_extents(struct cmd_context *cmd, struct volume_group *vg,
++		   struct dm_list *pvds);
++int export_extents(struct disk_list *dl, uint32_t lv_num,
++		   struct logical_volume *lv, struct physical_volume *pv);
++
++int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
++	       struct volume_group *vg, struct dm_list *pvds);
++
++int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct dm_list *pvds);
++int export_lvs(struct disk_list *dl, struct volume_group *vg,
++	       struct physical_volume *pv, const char *dev_dir);
++
++int import_snapshots(struct dm_pool *mem, struct volume_group *vg,
++		     struct dm_list *pvds);
++
++int export_uuids(struct disk_list *dl, struct volume_group *vg);
++
++void export_numbers(struct dm_list *pvds, struct volume_group *vg);
++
++void export_pv_act(struct dm_list *pvds);
++int munge_pvd(struct device *dev, struct pv_disk *pvd);
++int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd);
++
++/* blech */
++int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
++		       const char *candidate_vg, int *result);
++int export_vg_number(struct format_instance *fid, struct dm_list *pvds,
++		     const char *vg_name, struct dev_filter *filter);
++
++int generate_lvm1_system_id(struct cmd_context *cmd, char *s, const char *prefix);
++
++#endif
+diff --git a/lib/format1/format1.c b/lib/format1/format1.c
+new file mode 100644
+index 0000000..6e7e888
+--- /dev/null
++++ b/lib/format1/format1.c
+@@ -0,0 +1,630 @@
++/*
++ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "lib.h"
++#include "disk-rep.h"
++#include "limits.h"
++#include "display.h"
++#include "toolcontext.h"
++#include "lvm1-label.h"
++#include "format1.h"
++#include "segtype.h"
++#include "pv_alloc.h"
++
++/* VG consistency checks */
++static int _check_vgs(struct dm_list *pvs, struct volume_group *vg)
++{
++	struct dm_list *pvh, *t;
++	struct disk_list *dl = NULL;
++	struct disk_list *first = NULL;
++
++	uint32_t pv_count = 0;
++	uint32_t exported = 0;
++	int first_time = 1;
++
++	/*
++	 * If there are exported and unexported PVs, ignore exported ones.
++	 * This means an active VG won't be affected if disks are inserted
++	 * bearing an exported VG with the same name.
++	 */
++	dm_list_iterate_items(dl, pvs) {
++		if (first_time) {
++			exported = dl->pvd.pv_status & VG_EXPORTED;
++			first_time = 0;
++			continue;
++		}
++
++		if (exported != (dl->pvd.pv_status & VG_EXPORTED)) {
++			/* Remove exported PVs */
++			dm_list_iterate_safe(pvh, t, pvs) {
++				dl = dm_list_item(pvh, struct disk_list);
++				if (dl->pvd.pv_status & VG_EXPORTED)
++					dm_list_del(pvh);
++			}
++			break;
++		}
++	}
++
++	/* Remove any PVs with VG structs that differ from the first */
++	dm_list_iterate_safe(pvh, t, pvs) {
++		dl = dm_list_item(pvh, struct disk_list);
++
++		if (!first)
++			first = dl;
++
++		else if (memcmp(&first->vgd, &dl->vgd, sizeof(first->vgd))) {
++			log_error("VG data differs between PVs %s and %s",
++				  dev_name(first->dev), dev_name(dl->dev));
++			log_debug_metadata("VG data on %s: %s %s %" PRIu32 " %" PRIu32
++					   "  %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
++					   PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32
++					   " %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
++					   PRIu32 " %" PRIu32 " %" PRIu32,
++					   dev_name(first->dev), first->vgd.vg_uuid,
++					   first->vgd.vg_name_dummy,
++					   first->vgd.vg_number, first->vgd.vg_access,
++					   first->vgd.vg_status, first->vgd.lv_max,
++					   first->vgd.lv_cur, first->vgd.lv_open,
++					   first->vgd.pv_max, first->vgd.pv_cur,
++					   first->vgd.pv_act, first->vgd.dummy,
++					   first->vgd.vgda, first->vgd.pe_size,
++					   first->vgd.pe_total, first->vgd.pe_allocated,
++					   first->vgd.pvg_total);
++			log_debug_metadata("VG data on %s: %s %s %" PRIu32 " %" PRIu32
++					   "  %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
++					   PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32
++					   " %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
++					   PRIu32 " %" PRIu32 " %" PRIu32,
++					   dev_name(dl->dev), dl->vgd.vg_uuid,
++					   dl->vgd.vg_name_dummy, dl->vgd.vg_number,
++					   dl->vgd.vg_access, dl->vgd.vg_status,
++					   dl->vgd.lv_max, dl->vgd.lv_cur,
++					   dl->vgd.lv_open, dl->vgd.pv_max,
++					   dl->vgd.pv_cur, dl->vgd.pv_act, dl->vgd.dummy,
++					   dl->vgd.vgda, dl->vgd.pe_size,
++					   dl->vgd.pe_total, dl->vgd.pe_allocated,
++					   dl->vgd.pvg_total);
++			dm_list_del(pvh);
++			return 0;
++		}
++		pv_count++;
++	}
++
++	/* On entry to fn, list known to be non-empty */
++	if (pv_count != first->vgd.pv_cur) {
++		log_error("%d PV(s) found for VG %s: expected %d",
++			  pv_count, first->pvd.vg_name, first->vgd.pv_cur);
++		vg->status |= PARTIAL_VG;
++	}
++
++	return 1;
++}
++
++static int _fix_partial_vg(struct volume_group *vg, struct dm_list *pvs)
++{
++	uint32_t extent_count = 0;
++	struct disk_list *dl;
++	struct dm_list *pvh;
++	struct pv_list *pvl;
++	struct lv_list *ll;
++	struct lv_segment *seg;
++
++	/*
++	 * FIXME: code should remap missing segments to error segment.
++	 * Also current mapping code allocates 1 segment per missing extent.
++	 * For now bail out completely - allocated structures are not complete
++	 */
++	dm_list_iterate_items(ll, &vg->lvs)
++		dm_list_iterate_items(seg, &ll->lv->segments) {
++
++			/* area_count is always 1 here, s == 0 */
++			if (seg_type(seg, 0) != AREA_PV)
++				continue;
++
++			if (seg_pv(seg, 0))
++				continue;
++
++			log_error("Partial mode support for missing lvm1 PVs and "
++				  "partially available LVs is currently not implemented.");
++			return 0;
++	}
++
++	dm_list_iterate(pvh, pvs) {
++		dl = dm_list_item(pvh, struct disk_list);
++		extent_count += dl->pvd.pe_total;
++	}
++
++	/* FIXME: move this to one place to pv_manip */
++	if (!(pvl = dm_pool_zalloc(vg->vgmem, sizeof(*pvl))) ||
++	    !(pvl->pv = dm_pool_zalloc(vg->vgmem, sizeof(*pvl->pv))))
++		return_0;
++
++	/* Use vg uuid with replaced first chars to "missing" as missing PV UUID */
++	memcpy(&pvl->pv->id.uuid, vg->id.uuid, sizeof(pvl->pv->id.uuid));
++	memcpy(&pvl->pv->id.uuid, "missing", 7);
++
++	if (!(pvl->pv->vg_name = dm_pool_strdup(vg->vgmem, vg->name)))
++		goto_out;
++	memcpy(&pvl->pv->vgid, &vg->id, sizeof(vg->id));
++	pvl->pv->status |= MISSING_PV;
++	dm_list_init(&pvl->pv->tags);
++	dm_list_init(&pvl->pv->segments);
++
++	pvl->pv->pe_size = vg->extent_size;
++	pvl->pv->pe_count = vg->extent_count - extent_count;
++	if (!alloc_pv_segment_whole_pv(vg->vgmem, pvl->pv))
++		goto_out;
++
++	add_pvl_to_vgs(vg, pvl);
++	log_debug_metadata("%s: partial VG, allocated missing PV using %d extents.",
++			   vg->name, pvl->pv->pe_count);
++
++	return 1;
++out:
++	dm_pool_free(vg->vgmem, pvl);
++	return 0;
++}
++
++static struct volume_group *_format1_vg_read(struct format_instance *fid,
++				     const char *vg_name,
++				     struct metadata_area *mda __attribute__((unused)),
++				     struct cached_vg_fmtdata **vg_fmtdata __attribute__((unused)),
++				     unsigned *use_previous_vg __attribute__((unused)))
++{
++	struct volume_group *vg;
++	struct disk_list *dl;
++	DM_LIST_INIT(pvs);
++
++	/* Strip dev_dir if present */
++	if (vg_name)
++		vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
++
++	if (!(vg = alloc_vg("format1_vg_read", fid->fmt->cmd, NULL)))
++		return_NULL;
++
++	if (!read_pvs_in_vg(fid->fmt, vg_name, fid->fmt->cmd->filter,
++			    vg->vgmem, &pvs))
++		goto_bad;
++
++	if (dm_list_empty(&pvs))
++		goto_bad;
++
++	if (!_check_vgs(&pvs, vg))
++		goto_bad;
++
++	dl = dm_list_item(pvs.n, struct disk_list);
++
++	if (!import_vg(vg->vgmem, vg, dl))
++		goto_bad;
++
++	if (!import_pvs(fid->fmt, vg->vgmem, vg, &pvs))
++		goto_bad;
++
++	if (!import_lvs(vg->vgmem, vg, &pvs))
++		goto_bad;
++
++	if (!import_extents(fid->fmt->cmd, vg, &pvs))
++		goto_bad;
++
++	/* FIXME: workaround - temporary assignment of fid */
++	vg->fid = fid;
++	if (!import_snapshots(vg->vgmem, vg, &pvs)) {
++		vg->fid = NULL;
++		goto_bad;
++	}
++	vg->fid = NULL;
++
++	/* Fix extents counts by adding missing PV if partial VG */
++	if ((vg->status & PARTIAL_VG) && !_fix_partial_vg(vg, &pvs))
++		goto_bad;
++
++	vg_set_fid(vg, fid);
++
++	return vg;
++
++bad:
++	release_vg(vg);
++
++	return NULL;
++}
++
++static struct disk_list *_flatten_pv(struct format_instance *fid,
++				     struct dm_pool *mem, struct volume_group *vg,
++				     struct physical_volume *pv,
++				     const char *dev_dir)
++{
++	struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
++
++	if (!dl)
++		return_NULL;
++
++	dl->mem = mem;
++	dl->dev = pv->dev;
++
++	dm_list_init(&dl->uuids);
++	dm_list_init(&dl->lvds);
++
++	if (!export_pv(fid->fmt->cmd, mem, vg, &dl->pvd, pv) ||
++	    !export_vg(&dl->vgd, vg) ||
++	    !export_uuids(dl, vg) ||
++	    !export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
++		dm_pool_free(mem, dl);
++		return_NULL;
++	}
++
++	return dl;
++}
++
++static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
++		       struct volume_group *vg,
++		       struct dm_list *pvds, const char *dev_dir,
++		       struct dev_filter *filter)
++{
++	struct pv_list *pvl;
++	struct disk_list *data;
++
++	dm_list_iterate_items(pvl, &vg->pvs) {
++		if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir)))
++			return_0;
++
++		dm_list_add(pvds, &data->list);
++	}
++
++	export_numbers(pvds, vg);
++	export_pv_act(pvds);
++
++	if (!export_vg_number(fid, pvds, vg->name, filter))
++		return_0;
++
++	return 1;
++}
++
++static int _format1_vg_write(struct format_instance *fid, struct volume_group *vg,
++		     struct metadata_area *mda __attribute__((unused)))
++{
++	struct dm_pool *mem = dm_pool_create("lvm1 vg_write", VG_MEMPOOL_CHUNK);
++	struct dm_list pvds;
++	int r = 0;
++
++	if (!mem)
++		return_0;
++
++	dm_list_init(&pvds);
++
++	r = (_flatten_vg(fid, mem, vg, &pvds, fid->fmt->cmd->dev_dir,
++			 fid->fmt->cmd->filter) &&
++	     write_disks(fid->fmt, &pvds, 1));
++
++	lvmcache_update_vg(vg, 0);
++	dm_pool_destroy(mem);
++	return r;
++}
++
++static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
++		    struct physical_volume *pv, int scan_label_only __attribute__((unused)))
++{
++	struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
++	struct disk_list *dl;
++	struct device *dev;
++	int r = 0;
++
++	log_very_verbose("Reading physical volume data %s from disk", pv_name);
++
++	if (!mem)
++		return_0;
++
++	if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
++		goto_out;
++
++	if (!(dl = read_disk(fmt, dev, mem, NULL)))
++		goto_out;
++
++	if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd))
++		goto_out;
++
++	pv->fmt = fmt;
++
++	r = 1;
++
++      out:
++	dm_pool_destroy(mem);
++	return r;
++}
++
++static int _format1_pv_initialise(const struct format_type * fmt,
++				  struct pv_create_args *pva,
++				  struct physical_volume * pv)
++{
++	if (pv->size > MAX_PV_SIZE)
++		pv->size--;
++	if (pv->size > MAX_PV_SIZE) {
++		log_error("Physical volumes cannot be bigger than %s",
++			  display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE));
++		return 0;
++	}
++
++	/* Nothing more to do if extent size isn't provided */
++	if (!pva->extent_size)
++		return 1;
++
++	/*
++	 * This works out pe_start and pe_count.
++	 */
++	if (!calculate_extent_count(pv, pva->extent_size, pva->extent_count, pva->pe_start))
++		return_0;
++
++	/* Retain existing extent locations exactly */
++	if (((pva->pe_start || pva->extent_count) && (pva->pe_start != pv->pe_start)) ||
++	    (pva->extent_count && (pva->extent_count != pv->pe_count))) {
++		log_error("Metadata would overwrite physical extents");
++		return 0;
++	}
++
++	return 1;
++}
++
++static int _format1_pv_setup(const struct format_type *fmt,
++			     struct physical_volume *pv,
++			     struct volume_group *vg)
++{
++	struct pv_create_args pva = { .id = {{0}},
++				      .idp = NULL,
++				      .ba_start = 0,
++				      .ba_size = 0,
++				      .pe_start = 0,
++				      .extent_count = 0,
++				      .extent_size = vg->extent_size};
++
++	return _format1_pv_initialise(fmt, &pva, pv);
++}
++
++static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
++{
++	uint64_t max_size = UINT_MAX;
++
++	if (!*lv->lvid.s)
++		lvid_from_lvnum(&lv->lvid, &lv->vg->id, find_free_lvnum(lv));
++
++	if (lv->le_count > MAX_LE_TOTAL) {
++		log_error("logical volumes cannot contain more than "
++			  "%d extents.", MAX_LE_TOTAL);
++		return 0;
++	}
++	if (lv->size > max_size) {
++		log_error("logical volumes cannot be larger than %s",
++			  display_size(fid->fmt->cmd, max_size));
++		return 0;
++	}
++
++	return 1;
++}
++
++static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv)
++{
++	struct dm_pool *mem;
++	struct disk_list *dl;
++	struct dm_list pvs;
++	struct lvmcache_info *info;
++	int pe_count, pe_size, pe_start;
++	int r = 1;
++
++	if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
++				  pv->vg_name, NULL, 0)))
++		return_0;
++
++	lvmcache_update_pv(info, pv, fmt);
++	lvmcache_del_mdas(info);
++	lvmcache_del_das(info);
++	lvmcache_del_bas(info);
++
++	dm_list_init(&pvs);
++
++	pe_count = pv->pe_count;
++	pe_size = pv->pe_size;
++	pe_start = pv->pe_start;
++
++	/* Ensure any residual PE structure is gone */
++	pv->pe_size = pv->pe_count = 0;
++	pv->pe_start = LVM1_PE_ALIGN;
++
++	if (!(mem = dm_pool_create("lvm1 pv_write", 1024)))
++		return_0;
++
++	if (!(dl = dm_pool_alloc(mem, sizeof(*dl))))
++		goto_bad;
++
++	dl->mem = mem;
++	dl->dev = pv->dev;
++	dm_list_init(&dl->uuids);
++	dm_list_init(&dl->lvds);
++
++	if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv))
++		goto_bad;
++
++	/* must be set to be able to zero gap after PV structure in
++	   dev_write in order to make other disk tools happy */
++	dl->pvd.pv_on_disk.base = METADATA_BASE;
++	dl->pvd.pv_on_disk.size = PV_SIZE;
++	dl->pvd.pe_on_disk.base = LVM1_PE_ALIGN << SECTOR_SHIFT;
++
++	dm_list_add(&pvs, &dl->list);
++	if (!write_disks(fmt, &pvs, 0))
++		goto_bad;
++
++	goto out;
++
++      bad:
++	r = 0;
++
++      out:
++	pv->pe_size = pe_size;
++	pv->pe_count = pe_count;
++	pv->pe_start = pe_start;
++
++	dm_pool_destroy(mem);
++	return r;
++}
++
++static int _format1_vg_setup(struct format_instance *fid, struct volume_group *vg)
++{
++	/* just check max_pv and max_lv */
++	if (!vg->max_lv || vg->max_lv >= MAX_LV)
++		vg->max_lv = MAX_LV - 1;
++
++	if (!vg->max_pv || vg->max_pv >= MAX_PV)
++		vg->max_pv = MAX_PV - 1;
++
++	if (!vg_check_new_extent_size(vg->fid->fmt, vg->extent_size))
++		return_0;
++
++        /* Generate lvm1_system_id if not yet set */
++        if (!*vg->lvm1_system_id &&
++            !generate_lvm1_system_id(vg->cmd, vg->lvm1_system_id, ""))
++		return_0;
++
++	return 1;
++}
++
++static int _format1_segtype_supported(struct format_instance *fid __attribute__((unused)),
++				      const struct segment_type *segtype)
++{
++	if (!(segtype->flags & SEG_FORMAT1_SUPPORT))
++		return_0;
++
++	return 1;
++}
++
++static struct metadata_area_ops _metadata_format1_ops = {
++	.vg_read = _format1_vg_read,
++	.vg_write = _format1_vg_write,
++};
++
++static struct format_instance *_format1_create_instance(const struct format_type *fmt,
++							const struct format_instance_ctx *fic)
++{
++	struct format_instance *fid;
++	struct metadata_area *mda;
++
++	if (!(fid = alloc_fid(fmt, fic)))
++		return_NULL;
++
++	/* Define a NULL metadata area */
++	if (!(mda = dm_pool_zalloc(fid->mem, sizeof(*mda)))) {
++		log_error("Unable to allocate metadata area structure "
++			  "for lvm1 format");
++		goto bad;
++	}
++
++	mda->ops = &_metadata_format1_ops;
++	mda->metadata_locn = NULL;
++	mda->status = 0;
++	dm_list_add(&fid->metadata_areas_in_use, &mda->list);
++
++	return fid;
++
++bad:
++	dm_pool_destroy(fid->mem);
++	return NULL;
++}
++
++static void _format1_destroy_instance(struct format_instance *fid)
++{
++	if (--fid->ref_count <= 1)
++		dm_pool_destroy(fid->mem);
++}
++
++static void _format1_destroy(struct format_type *fmt)
++{
++	if (fmt->orphan_vg)
++		free_orphan_vg(fmt->orphan_vg);
++
++	dm_free(fmt);
++}
++
++static struct format_handler _format1_ops = {
++	.pv_read = _format1_pv_read,
++	.pv_initialise = _format1_pv_initialise,
++	.pv_setup = _format1_pv_setup,
++	.pv_write = _format1_pv_write,
++	.lv_setup = _format1_lv_setup,
++	.vg_setup = _format1_vg_setup,
++	.segtype_supported = _format1_segtype_supported,
++	.create_instance = _format1_create_instance,
++	.destroy_instance = _format1_destroy_instance,
++	.destroy = _format1_destroy,
++};
++
++#ifdef LVM1_INTERNAL
++struct format_type *init_lvm1_format(struct cmd_context *cmd)
++#else				/* Shared */
++struct format_type *init_format(struct cmd_context *cmd);
++struct format_type *init_format(struct cmd_context *cmd)
++#endif
++{
++	struct format_type *fmt = dm_malloc(sizeof(*fmt));
++	struct format_instance_ctx fic;
++	struct format_instance *fid;
++
++	if (!fmt) {
++		log_error("Failed to allocate format1 format type structure.");
++		return NULL;
++	}
++
++	fmt->cmd = cmd;
++	fmt->ops = &_format1_ops;
++	fmt->name = FMT_LVM1_NAME;
++	fmt->alias = NULL;
++	fmt->orphan_vg_name = FMT_LVM1_ORPHAN_VG_NAME;
++	fmt->features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE |
++			FMT_RESTRICTED_READAHEAD | FMT_OBSOLETE |
++			FMT_SYSTEMID_ON_PVS;
++	fmt->private = NULL;
++
++	dm_list_init(&fmt->mda_ops);
++
++	if (!(fmt->labeller = lvm1_labeller_create(fmt))) {
++		log_error("Couldn't create lvm1 label handler.");
++		dm_free(fmt);
++		return NULL;
++	}
++
++	if (!(label_register_handler(fmt->labeller))) {
++		log_error("Couldn't register lvm1 label handler.");
++		fmt->labeller->ops->destroy(fmt->labeller);
++		dm_free(fmt);
++		return NULL;
++	}
++
++	if (!(fmt->orphan_vg = alloc_vg("format1_orphan", cmd, fmt->orphan_vg_name))) {
++		log_error("Couldn't create lvm1 orphan VG.");
++		dm_free(fmt);
++		return NULL;
++	}
++
++	fic.type = FMT_INSTANCE_AUX_MDAS;
++	fic.context.vg_ref.vg_name = fmt->orphan_vg_name;
++	fic.context.vg_ref.vg_id = NULL;
++
++	if (!(fid = _format1_create_instance(fmt, &fic))) {
++		_format1_destroy(fmt);
++		return_NULL;
++	}
++
++	vg_set_fid(fmt->orphan_vg, fid);
++
++	log_very_verbose("Initialised format: %s", fmt->name);
++
++	return fmt;
++}
+diff --git a/lib/format1/format1.h b/lib/format1/format1.h
+new file mode 100644
+index 0000000..42ddc66
+--- /dev/null
++++ b/lib/format1/format1.h
+@@ -0,0 +1,29 @@
++/*
++ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
++ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef _LVM_FORMAT1_H
++#define _LVM_FORMAT1_H
++
++#include "metadata.h"
++#include "lvmcache.h"
++
++#define FMT_LVM1_NAME "lvm1"
++#define FMT_LVM1_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_LVM1_NAME)
++
++#ifdef LVM1_INTERNAL
++struct format_type *init_lvm1_format(struct cmd_context *cmd);
++#endif
++
++#endif
+diff --git a/lib/format1/import-export.c b/lib/format1/import-export.c
+new file mode 100644
+index 0000000..c29527b
+--- /dev/null
++++ b/lib/format1/import-export.c
+@@ -0,0 +1,680 @@
++/*
++ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * Translates between disk and in-core formats.
++ */
++
++#include "lib.h"
++#include "disk-rep.h"
++#include "lvm-string.h"
++#include "toolcontext.h"
++#include "segtype.h"
++#include "pv_alloc.h"
++#include "display.h"
++#include "metadata.h"
++
++#include <time.h>
++
++static int _check_vg_name(const char *name)
++{
++	return strlen(name) < NAME_LEN;
++}
++
++/*
++ * Extracts the last part of a path.
++ */
++static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
++{
++	const char *ptr = strrchr(full_name, '/');
++
++	if (!ptr)
++		ptr = full_name;
++	else
++		ptr++;
++
++	return dm_pool_strdup(mem, ptr);
++}
++
++int import_pv(const struct format_type *fmt, struct dm_pool *mem,
++	      struct device *dev, struct volume_group *vg,
++	      struct physical_volume *pv, struct pv_disk *pvd,
++	      struct vg_disk *vgd)
++{
++	uint64_t size;
++
++	memset(pv, 0, sizeof(*pv));
++	memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
++
++	pv->dev = dev;
++	if (!*pvd->vg_name)
++		pv->vg_name = fmt->orphan_vg_name;
++	else if (!(pv->vg_name = dm_pool_strdup(mem, (char *)pvd->vg_name))) {
++		log_error("Volume Group name allocation failed.");
++		return 0;
++	}
++
++	memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id));
++
++	/* Store system_id from first PV if PV belongs to a VG */
++	if (vg && !*vg->lvm1_system_id)
++		strncpy(vg->lvm1_system_id, (char *)pvd->system_id, NAME_LEN);
++
++	if (vg &&
++	    strncmp(vg->lvm1_system_id, (char *)pvd->system_id, sizeof(pvd->system_id)))
++		    log_very_verbose("System ID %s on %s differs from %s for "
++				     "volume group", pvd->system_id,
++				     pv_dev_name(pv), vg->lvm1_system_id);
++
++	/*
++	 * If exported, we still need to flag in pv->status too because
++	 * we don't always have a struct volume_group when we need this.
++	 */
++	if (pvd->pv_status & VG_EXPORTED)
++		pv->status |= EXPORTED_VG;
++
++	if (pvd->pv_allocatable)
++		pv->status |= ALLOCATABLE_PV;
++
++	pv->size = pvd->pv_size;
++	pv->pe_size = pvd->pe_size;
++	pv->pe_start = pvd->pe_start;
++	pv->pe_count = pvd->pe_total;
++	pv->pe_alloc_count = 0;
++	pv->pe_align = 0;
++        pv->is_labelled = 0; /* format1 PVs have no label */
++        pv->label_sector = 0;
++
++	/* Fix up pv size if missing or impossibly large */
++	if (!pv->size || pv->size > (1ULL << 62)) {
++		if (!dev_get_size(dev, &pv->size)) {
++			log_error("%s: Couldn't get size.", pv_dev_name(pv));
++			return 0;
++		}
++		log_verbose("Fixing up missing format1 size (%s) "
++			    "for PV %s", display_size(fmt->cmd, pv->size),
++			    pv_dev_name(pv));
++		if (vg) {
++			size = pv->pe_count * (uint64_t) vg->extent_size +
++			       pv->pe_start;
++			if (size > pv->size)
++				log_warn("WARNING: Physical Volume %s is too "
++					 "large for underlying device",
++					 pv_dev_name(pv));
++		}
++	}
++
++	dm_list_init(&pv->tags);
++	dm_list_init(&pv->segments);
++
++	if (!alloc_pv_segment_whole_pv(mem, pv))
++		return_0;
++
++	return 1;
++}
++
++int generate_lvm1_system_id(struct cmd_context *cmd, char *s, const char *prefix)
++{
++
++	if (dm_snprintf(s, NAME_LEN, "%s%s" FMTu64,
++			prefix, cmd->hostname, (uint64_t)time(NULL)) < 0) {
++		log_error("Generated LVM1 format system_id too long");
++		return 0;
++	}
++
++	return 1;
++}
++
++int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute__((unused)),
++	      struct volume_group *vg,
++	      struct pv_disk *pvd, struct physical_volume *pv)
++{
++	memset(pvd, 0, sizeof(*pvd));
++
++	pvd->id[0] = 'H';
++	pvd->id[1] = 'M';
++	pvd->version = 1;
++
++	memcpy(pvd->pv_uuid, pv->id.uuid, ID_LEN);
++
++	if (pv->vg_name && !is_orphan(pv) && !(pv->status & UNLABELLED_PV)) {
++		if (!_check_vg_name(pv->vg_name))
++			return_0;
++		strncpy((char *)pvd->vg_name, pv->vg_name, sizeof(pvd->vg_name));
++	}
++
++	/* Preserve existing system_id if it exists */
++	if (vg && vg->lvm1_system_id && *vg->lvm1_system_id)
++		strncpy((char *)pvd->system_id, vg->lvm1_system_id, sizeof(pvd->system_id));
++	else if (vg && vg->system_id && *vg->system_id)
++		strncpy((char *)pvd->system_id, vg->system_id, sizeof(pvd->system_id));
++
++	/* Is VG already exported or being exported? */
++	if (vg && vg_is_exported(vg)) {
++		/* Does system_id need setting? */
++		if (!vg->lvm1_system_id || !*vg->lvm1_system_id ||
++		    strncmp(vg->lvm1_system_id, EXPORTED_TAG,
++			    sizeof(EXPORTED_TAG) - 1)) {
++			if (!generate_lvm1_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG))
++				return_0;
++		}
++		if (strlen((char *)pvd->vg_name) + sizeof(EXPORTED_TAG) >
++		    sizeof(pvd->vg_name)) {
++			log_error("Volume group name %s too long to export",
++				  pvd->vg_name);
++			return 0;
++		}
++		strcat((char *)pvd->vg_name, EXPORTED_TAG);
++	}
++
++	/* Is VG being imported? */
++	if (vg && !vg_is_exported(vg) && vg->lvm1_system_id && *vg->lvm1_system_id &&
++	    !strncmp(vg->lvm1_system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
++		if (!generate_lvm1_system_id(cmd, (char *)pvd->system_id, IMPORTED_TAG))
++			return_0;
++	}
++
++	/* Generate system_id if PV is in VG */
++	if (!pvd->system_id[0])
++		if (!generate_lvm1_system_id(cmd, (char *)pvd->system_id, ""))
++			return_0;
++
++	/* Update internal system_id if we changed it */
++	if (vg && vg->lvm1_system_id &&
++	    (!*vg->lvm1_system_id ||
++	     strncmp(vg->lvm1_system_id, (char *)pvd->system_id, sizeof(pvd->system_id))))
++		    strncpy(vg->lvm1_system_id, (char *)pvd->system_id, NAME_LEN);
++
++	//pvd->pv_major = MAJOR(pv->dev);
++
++	if (pv->status & ALLOCATABLE_PV)
++		pvd->pv_allocatable = PV_ALLOCATABLE;
++
++	pvd->pv_size = pv->size;
++	pvd->lv_cur = 0;	/* this is set when exporting the lv list */
++	if (vg)
++		pvd->pe_size = vg->extent_size;
++	else
++		pvd->pe_size = pv->pe_size;
++	pvd->pe_total = pv->pe_count;
++	pvd->pe_allocated = pv->pe_alloc_count;
++	pvd->pe_start = pv->pe_start;
++
++	return 1;
++}
++
++int import_vg(struct dm_pool *mem,
++	      struct volume_group *vg, struct disk_list *dl)
++{
++	struct vg_disk *vgd = &dl->vgd;
++	memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
++
++	if (!_check_vg_name((char *)dl->pvd.vg_name))
++		return_0;
++
++	if (!(vg->name = dm_pool_strdup(mem, (char *)dl->pvd.vg_name)))
++		return_0;
++
++	if (!(vg->lvm1_system_id = dm_pool_zalloc(mem, NAME_LEN + 1)))
++		return_0;
++
++	if (vgd->vg_status & VG_EXPORTED)
++		vg->status |= EXPORTED_VG;
++
++	if (vgd->vg_status & VG_EXTENDABLE)
++		vg->status |= RESIZEABLE_VG;
++
++	if (vgd->vg_access & VG_READ)
++		vg->status |= LVM_READ;
++
++	if (vgd->vg_access & VG_WRITE)
++		vg->status |= LVM_WRITE;
++
++	if (vgd->vg_access & VG_CLUSTERED)
++		vg->status |= CLUSTERED;
++
++	if (vgd->vg_access & VG_SHARED)
++		vg->status |= SHARED;
++
++	vg->extent_size = vgd->pe_size;
++	vg->extent_count = vgd->pe_total;
++	vg->free_count = vgd->pe_total;
++	vg->max_lv = vgd->lv_max;
++	vg->max_pv = vgd->pv_max;
++	vg->alloc = ALLOC_NORMAL;
++
++	return 1;
++}
++
++int export_vg(struct vg_disk *vgd, struct volume_group *vg)
++{
++	memset(vgd, 0, sizeof(*vgd));
++	memcpy(vgd->vg_uuid, vg->id.uuid, ID_LEN);
++
++	if (vg->status & LVM_READ)
++		vgd->vg_access |= VG_READ;
++
++	if (vg->status & LVM_WRITE)
++		vgd->vg_access |= VG_WRITE;
++
++	if (vg_is_clustered(vg))
++		vgd->vg_access |= VG_CLUSTERED;
++
++	if (vg->status & SHARED)
++		vgd->vg_access |= VG_SHARED;
++
++	if (vg_is_exported(vg))
++		vgd->vg_status |= VG_EXPORTED;
++
++	if (vg_is_resizeable(vg))
++		vgd->vg_status |= VG_EXTENDABLE;
++
++	vgd->lv_max = vg->max_lv;
++	vgd->lv_cur = vg_visible_lvs(vg) + snapshot_count(vg);
++
++	vgd->pv_max = vg->max_pv;
++	vgd->pv_cur = vg->pv_count;
++
++	vgd->pe_size = vg->extent_size;
++	vgd->pe_total = vg->extent_count;
++	vgd->pe_allocated = vg->extent_count - vg->free_count;
++
++	return 1;
++}
++
++int import_lv(struct cmd_context *cmd, struct dm_pool *mem,
++	      struct logical_volume *lv, struct lv_disk *lvd)
++{
++	if (!(lv->name = _create_lv_name(mem, (char *)lvd->lv_name)))
++		return_0;
++
++	lv->status |= VISIBLE_LV;
++
++	if (lvd->lv_status & LV_SPINDOWN)
++		lv->status |= SPINDOWN_LV;
++
++	if (lvd->lv_status & LV_PERSISTENT_MINOR) {
++		lv->status |= FIXED_MINOR;
++		lv->minor = MINOR(lvd->lv_dev);
++		lv->major = MAJOR(lvd->lv_dev);
++	} else {
++		lv->major = -1;
++		lv->minor = -1;
++	}
++
++	if (lvd->lv_access & LV_READ)
++		lv->status |= LVM_READ;
++
++	if (lvd->lv_access & LV_WRITE)
++		lv->status |= LVM_WRITE;
++
++	if (lvd->lv_badblock)
++		lv->status |= BADBLOCK_ON;
++
++	/* Drop the unused LV_STRICT here */
++	if (lvd->lv_allocation & LV_CONTIGUOUS)
++		lv->alloc = ALLOC_CONTIGUOUS;
++	else
++		lv->alloc = ALLOC_NORMAL;
++
++	if (!lvd->lv_read_ahead)
++		lv->read_ahead = cmd->default_settings.read_ahead;
++	else
++		lv->read_ahead = lvd->lv_read_ahead;
++
++	lv->size = lvd->lv_size;
++	lv->le_count = lvd->lv_allocated_le;
++
++	return 1;
++}
++
++static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
++		       struct logical_volume *lv, const char *dev_dir)
++{
++	memset(lvd, 0, sizeof(*lvd));
++	snprintf((char *)lvd->lv_name, sizeof(lvd->lv_name), "%s%s/%s",
++		 dev_dir, vg->name, lv->name);
++
++	(void) dm_strncpy((char *)lvd->vg_name, vg->name, sizeof(lvd->vg_name));
++
++	if (lv->status & LVM_READ)
++		lvd->lv_access |= LV_READ;
++
++	if (lv->status & LVM_WRITE)
++		lvd->lv_access |= LV_WRITE;
++
++	if (lv->status & SPINDOWN_LV)
++		lvd->lv_status |= LV_SPINDOWN;
++
++	if (lv->status & FIXED_MINOR) {
++		lvd->lv_status |= LV_PERSISTENT_MINOR;
++		lvd->lv_dev = MKDEV(lv->major, lv->minor);
++	} else {
++		lvd->lv_dev = MKDEV(LVM_BLK_MAJOR, lvnum_from_lvid(&lv->lvid));
++	}
++
++	if (lv->read_ahead == DM_READ_AHEAD_AUTO ||
++	    lv->read_ahead == DM_READ_AHEAD_NONE)
++		lvd->lv_read_ahead = 0;
++	else
++		lvd->lv_read_ahead = lv->read_ahead;
++
++	lvd->lv_stripes =
++	    dm_list_item(lv->segments.n, struct lv_segment)->area_count;
++	lvd->lv_stripesize =
++	    dm_list_item(lv->segments.n, struct lv_segment)->stripe_size;
++
++	lvd->lv_size = lv->size;
++	lvd->lv_allocated_le = lv->le_count;
++
++	if (lv->status & BADBLOCK_ON)
++		lvd->lv_badblock = LV_BADBLOCK_ON;
++
++	if (lv->alloc == ALLOC_CONTIGUOUS)
++		lvd->lv_allocation |= LV_CONTIGUOUS;
++}
++
++int export_extents(struct disk_list *dl, uint32_t lv_num,
++		   struct logical_volume *lv, struct physical_volume *pv)
++{
++	struct pe_disk *ped;
++	struct lv_segment *seg;
++	uint32_t pe, s;
++
++	dm_list_iterate_items(seg, &lv->segments) {
++		for (s = 0; s < seg->area_count; s++) {
++			if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
++				log_error("Segment type %s in LV %s: "
++					  "unsupported by format1",
++					  lvseg_name(seg), lv->name);
++				return 0;
++			}
++			if (seg_type(seg, s) != AREA_PV) {
++				log_error("Non-PV stripe found in LV %s: "
++					  "unsupported by format1", lv->name);
++				return 0;
++			}
++			if (seg_pv(seg, s) != pv)
++				continue;	/* not our pv */
++
++			for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
++				ped = &dl->extents[pe + seg_pe(seg, s)];
++				ped->lv_num = lv_num;
++				ped->le_num = (seg->le / seg->area_count) + pe +
++				    s * (lv->le_count / seg->area_count);
++			}
++		}
++	}
++
++	return 1;
++}
++
++int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
++	       struct volume_group *vg, struct dm_list *pvds)
++{
++	struct disk_list *dl;
++	struct pv_list *pvl;
++
++	vg->pv_count = 0;
++	dm_list_iterate_items(dl, pvds) {
++		if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
++		    !(pvl->pv = dm_pool_alloc(mem, sizeof(*pvl->pv))))
++			return_0;
++
++		if (!import_pv(fmt, mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd))
++			return_0;
++
++		pvl->pv->fmt = fmt;
++		add_pvl_to_vgs(vg, pvl);
++	}
++
++	return 1;
++}
++
++static struct logical_volume *_add_lv(struct dm_pool *mem,
++				      struct volume_group *vg,
++				      struct lv_disk *lvd)
++{
++	struct logical_volume *lv;
++
++	if (!(lv = alloc_lv(mem)))
++		return_NULL;
++
++	lvid_from_lvnum(&lv->lvid, &vg->id, lvd->lv_number);
++
++	if (!import_lv(vg->cmd, mem, lv, lvd)) 
++		goto_bad;
++
++	if (!link_lv_to_vg(vg, lv))
++		goto_bad;
++
++	return lv;
++bad:
++	dm_pool_free(mem, lv);
++	return NULL;
++}
++
++int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct dm_list *pvds)
++{
++	struct disk_list *dl;
++	struct lvd_list *ll;
++	struct lv_disk *lvd;
++
++	dm_list_iterate_items(dl, pvds) {
++		dm_list_iterate_items(ll, &dl->lvds) {
++			lvd = &ll->lvd;
++
++			if (!find_lv(vg, (char *)lvd->lv_name) &&
++			    !_add_lv(mem, vg, lvd))
++				return_0;
++		}
++	}
++
++	return 1;
++}
++
++/* FIXME: tidy */
++int export_lvs(struct disk_list *dl, struct volume_group *vg,
++	       struct physical_volume *pv, const char *dev_dir)
++{
++	int r = 0;
++	struct lv_list *ll;
++	struct lvd_list *lvdl;
++	size_t len;
++	uint32_t lv_num;
++	struct dm_hash_table *lvd_hash;
++
++	if (!_check_vg_name(vg->name))
++		return_0;
++
++	if (!(lvd_hash = dm_hash_create(32)))
++		return_0;
++
++	/*
++	 * setup the pv's extents array
++	 */
++	len = sizeof(struct pe_disk) * dl->pvd.pe_total;
++	if (!(dl->extents = dm_pool_zalloc(dl->mem, len)))
++		goto_out;
++
++	dm_list_iterate_items(ll, &vg->lvs) {
++		if (lv_is_snapshot(ll->lv))
++			continue;
++
++		if (!(lvdl = dm_pool_alloc(dl->mem, sizeof(*lvdl))))
++			goto_out;
++
++		_export_lv(&lvdl->lvd, vg, ll->lv, dev_dir);
++
++		lv_num = lvnum_from_lvid(&ll->lv->lvid);
++		lvdl->lvd.lv_number = lv_num;
++
++		if (!dm_hash_insert(lvd_hash, ll->lv->name, &lvdl->lvd))
++			goto_out;
++
++		if (!export_extents(dl, lv_num + 1, ll->lv, pv))
++			goto_out;
++
++		if (lv_is_origin(ll->lv))
++			lvdl->lvd.lv_access |= LV_SNAPSHOT_ORG;
++
++		if (lv_is_cow(ll->lv)) {
++			lvdl->lvd.lv_access |= LV_SNAPSHOT;
++			lvdl->lvd.lv_chunk_size = ll->lv->snapshot->chunk_size;
++			lvdl->lvd.lv_snapshot_minor =
++			    lvnum_from_lvid(&ll->lv->snapshot->origin->lvid);
++		}
++
++		dm_list_add(&dl->lvds, &lvdl->list);
++		dl->pvd.lv_cur++;
++	}
++
++	r = 1;
++
++      out:
++	dm_hash_destroy(lvd_hash);
++	return r;
++}
++
++/*
++ * FIXME: More inefficient code.
++ */
++int import_snapshots(struct dm_pool *mem __attribute__((unused)), struct volume_group *vg,
++		     struct dm_list *pvds)
++{
++	struct logical_volume *lvs[MAX_LV] = { 0 };
++	struct disk_list *dl;
++	struct lvd_list *ll;
++	struct lv_disk *lvd;
++	int lvnum;
++	struct logical_volume *org, *cow;
++
++	/* build an index of lv numbers */
++	dm_list_iterate_items(dl, pvds) {
++		dm_list_iterate_items(ll, &dl->lvds) {
++			lvd = &ll->lvd;
++
++			lvnum = lvd->lv_number;
++
++			if (lvnum >= MAX_LV) {
++				log_error("Logical volume number "
++					  "out of bounds.");
++				return 0;
++			}
++
++			if (!lvs[lvnum] &&
++			    !(lvs[lvnum] = find_lv(vg, (char *)lvd->lv_name))) {
++				log_error("Couldn't find logical volume '%s'.",
++					  lvd->lv_name);
++				return 0;
++			}
++		}
++	}
++
++	/*
++	 * Now iterate through yet again adding the snapshots.
++	 */
++	dm_list_iterate_items(dl, pvds) {
++		dm_list_iterate_items(ll, &dl->lvds) {
++			lvd = &ll->lvd;
++
++			if (!(lvd->lv_access & LV_SNAPSHOT))
++				continue;
++
++			lvnum = lvd->lv_number;
++			cow = lvs[lvnum];
++			if (!(org = lvs[lvd->lv_snapshot_minor])) {
++				log_error("Couldn't find origin logical volume "
++					  "for snapshot '%s'.", lvd->lv_name);
++				return 0;
++			}
++
++			/* we may have already added this snapshot */
++			if (lv_is_cow(cow))
++				continue;
++
++			/* insert the snapshot */
++			if (!vg_add_snapshot(org, cow, NULL,
++					     org->le_count,
++					     lvd->lv_chunk_size)) {
++				log_error("Couldn't add snapshot.");
++				return 0;
++			}
++		}
++	}
++
++	return 1;
++}
++
++int export_uuids(struct disk_list *dl, struct volume_group *vg)
++{
++	struct uuid_list *ul;
++	struct pv_list *pvl;
++
++	dm_list_iterate_items(pvl, &vg->pvs) {
++		if (!(ul = dm_pool_alloc(dl->mem, sizeof(*ul))))
++			return_0;
++
++		memset(ul->uuid, 0, sizeof(ul->uuid));
++		memcpy(ul->uuid, pvl->pv->id.uuid, ID_LEN);
++
++		dm_list_add(&dl->uuids, &ul->list);
++	}
++	return 1;
++}
++
++/*
++ * This calculates the nasty pv_number field
++ * used by LVM1.
++ */
++void export_numbers(struct dm_list *pvds, struct volume_group *vg __attribute__((unused)))
++{
++	struct disk_list *dl;
++	int pv_num = 1;
++
++	dm_list_iterate_items(dl, pvds)
++		dl->pvd.pv_number = pv_num++;
++}
++
++/*
++ * Calculate vg_disk->pv_act.
++ */
++void export_pv_act(struct dm_list *pvds)
++{
++	struct disk_list *dl;
++	int act = 0;
++
++	dm_list_iterate_items(dl, pvds)
++		if (dl->pvd.pv_status & PV_ACTIVE)
++			act++;
++
++	dm_list_iterate_items(dl, pvds)
++		dl->vgd.pv_act = act;
++}
++
++int export_vg_number(struct format_instance *fid, struct dm_list *pvds,
++		     const char *vg_name, struct dev_filter *filter)
++{
++	struct disk_list *dl;
++	int vg_num;
++
++	if (!get_free_vg_number(fid, filter, vg_name, &vg_num))
++		return_0;
++
++	dm_list_iterate_items(dl, pvds)
++		dl->vgd.vg_number = vg_num;
++
++	return 1;
++}
+diff --git a/lib/format1/import-extents.c b/lib/format1/import-extents.c
+new file mode 100644
+index 0000000..c583741
+--- /dev/null
++++ b/lib/format1/import-extents.c
+@@ -0,0 +1,377 @@
++/*
++ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "lib.h"
++#include "metadata.h"
++#include "disk-rep.h"
++#include "lv_alloc.h"
++#include "display.h"
++#include "segtype.h"
++
++/*
++ * After much thought I have decided it is easier,
++ * and probably no less efficient, to convert the
++ * pe->le map to a full le->pe map, and then
++ * process this to get the segments form that
++ * we're after.  Any code which goes directly from
++ * the pe->le map to segments would be gladly
++ * accepted, if it is less complicated than this
++ * file.
++ */
++struct pe_specifier {
++	struct physical_volume *pv;
++	uint32_t pe;
++};
++
++struct lv_map {
++	struct logical_volume *lv;
++	uint32_t stripes;
++	uint32_t stripe_size;
++	struct pe_specifier *map;
++};
++
++static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem,
++					  struct volume_group *vg)
++{
++	struct dm_hash_table *maps = dm_hash_create(32);
++	struct lv_list *ll;
++	struct lv_map *lvm;
++
++	if (!maps) {
++		log_error("Unable to create hash table for holding "
++			  "extent maps.");
++		return NULL;
++	}
++
++	dm_list_iterate_items(ll, &vg->lvs) {
++		if (lv_is_snapshot(ll->lv))
++			continue;
++
++		if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm))))
++			goto_bad;
++
++		lvm->lv = ll->lv;
++		/*
++		 * Alloc 1 extra element, so the loop in _area_length() and
++		 * _check_stripe() finds the last map member as noncontinuous.
++		 */
++		if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
++					     * (ll->lv->le_count + 1))))
++			goto_bad;
++
++		if (!dm_hash_insert(maps, ll->lv->name, lvm))
++			goto_bad;
++	}
++
++	return maps;
++
++      bad:
++	dm_hash_destroy(maps);
++	return NULL;
++}
++
++static int _fill_lv_array(struct lv_map **lvs,
++			  struct dm_hash_table *maps, struct disk_list *dl)
++{
++	struct lvd_list *ll;
++	struct lv_map *lvm;
++
++	memset(lvs, 0, sizeof(*lvs) * MAX_LV);
++
++	dm_list_iterate_items(ll, &dl->lvds) {
++		if (!(lvm = dm_hash_lookup(maps, strrchr((char *)ll->lvd.lv_name, '/')
++					+ 1))) {
++			log_error("Physical volume (%s) contains an "
++				  "unknown logical volume (%s).",
++				dev_name(dl->dev), ll->lvd.lv_name);
++			return 0;
++		}
++
++		lvm->stripes = ll->lvd.lv_stripes;
++		lvm->stripe_size = ll->lvd.lv_stripesize;
++
++		lvs[ll->lvd.lv_number] = lvm;
++	}
++
++	return 1;
++}
++
++static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
++		      struct dm_list *pvds)
++{
++	struct disk_list *dl;
++	struct physical_volume *pv;
++	struct lv_map *lvms[MAX_LV], *lvm;
++	struct pe_disk *e;
++	uint32_t i, lv_num, le;
++
++	dm_list_iterate_items(dl, pvds) {
++		if (!(pv = find_pv(vg, dl->dev))) {
++			log_error("PV %s not found.", dl->dev->pvid);
++			return 0;
++		}
++		e = dl->extents;
++
++		/* build an array of lv's for this pv */
++		if (!_fill_lv_array(lvms, maps, dl))
++			return_0;
++
++		for (i = 0; i < dl->pvd.pe_total; i++) {
++			lv_num = e[i].lv_num;
++
++			if (lv_num == UNMAPPED_EXTENT)
++				continue;
++
++			lv_num--;
++			lvm = lvms[lv_num];
++
++			if (!lvm) {
++				log_error("Invalid LV in extent map "
++					  "(PV %s, PE %" PRIu32
++					  ", LV %" PRIu32
++					  ", LE %" PRIu32 ")",
++					  dev_name(pv->dev), i,
++					  lv_num, e[i].le_num);
++				return 0;
++			}
++
++			le = e[i].le_num;
++
++			if (le >= lvm->lv->le_count) {
++				log_error("logical extent number "
++					  "out of bounds");
++				return 0;
++			}
++
++			if (lvm->map[le].pv) {
++				log_error("logical extent (%u) "
++					  "already mapped.", le);
++				return 0;
++			}
++
++			lvm->map[le].pv = pv;
++			lvm->map[le].pe = i;
++		}
++	}
++
++	return 1;
++}
++
++static int _check_single_map(struct lv_map *lvm)
++{
++	uint32_t i;
++
++	for (i = 0; i < lvm->lv->le_count; i++) {
++		if (!lvm->map[i].pv) {
++			log_error("Logical volume (%s) contains an incomplete "
++				  "mapping table.", lvm->lv->name);
++			return 0;
++		}
++	}
++
++	return 1;
++}
++
++static int _check_maps_are_complete(struct dm_hash_table *maps)
++{
++	struct dm_hash_node *n;
++	struct lv_map *lvm;
++
++	for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
++		lvm = (struct lv_map *) dm_hash_get_data(maps, n);
++
++		if (!_check_single_map(lvm))
++			return_0;
++	}
++	return 1;
++}
++
++static uint32_t _area_length(struct lv_map *lvm, uint32_t le)
++{
++	uint32_t len = 0;
++
++	do
++		len++;
++	while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
++		 (lvm->map[le].pv &&
++		  lvm->map[le + len].pe == lvm->map[le].pe + len));
++
++	return len;
++}
++
++static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
++{
++	uint32_t le = 0, len;
++	struct lv_segment *seg;
++	struct segment_type *segtype;
++
++	if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED)))
++		return_0;
++
++	while (le < lvm->lv->le_count) {
++		len = _area_length(lvm, le);
++
++		if (!(seg = alloc_lv_segment(segtype, lvm->lv, le, len, 0, 0, 0,
++					     NULL, 1, len, 0, 0, 0, 0, NULL))) {
++			log_error("Failed to allocate linear segment.");
++			return 0;
++		}
++
++		if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
++					    lvm->map[le].pe))
++			return_0;
++
++		dm_list_add(&lvm->lv->segments, &seg->list);
++
++		le += seg->len;
++	}
++
++	return 1;
++}
++
++static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
++			 uint32_t area_len, uint32_t base_le,
++			 uint32_t total_area_len)
++{
++	uint32_t st;
++
++	/*
++	 * Is the next physical extent in every stripe adjacent to the last?
++	 */
++	for (st = 0; st < area_count; st++)
++		if ((lvm->map[base_le + st * total_area_len + area_len].pv !=
++		     lvm->map[base_le + st * total_area_len].pv) ||
++		    (lvm->map[base_le + st * total_area_len].pv &&
++		     lvm->map[base_le + st * total_area_len + area_len].pe !=
++		     lvm->map[base_le + st * total_area_len].pe + area_len))
++			return 0;
++
++	return 1;
++}
++
++static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
++{
++	uint32_t st, first_area_le = 0, total_area_len;
++	uint32_t area_len;
++	struct lv_segment *seg;
++	struct segment_type *segtype;
++
++	/*
++	 * Work out overall striped length
++	 */
++	if (lvm->lv->le_count % lvm->stripes) {
++		log_error("Number of stripes (%u) incompatible "
++			  "with logical extent count (%u) for %s",
++			  lvm->stripes, lvm->lv->le_count, lvm->lv->name);
++	}
++
++	total_area_len = lvm->lv->le_count / lvm->stripes;
++
++	if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED)))
++		return_0;
++
++	while (first_area_le < total_area_len) {
++		area_len = 1;
++
++		/*
++		 * Find how many extents are contiguous in all stripes
++		 * and so can form part of this segment
++		 */
++		while (_check_stripe(lvm, lvm->stripes,
++				     area_len, first_area_le, total_area_len))
++			area_len++;
++
++		if (!(seg = alloc_lv_segment(segtype, lvm->lv,
++					     lvm->stripes * first_area_le,
++					     lvm->stripes * area_len, 0,
++					     0, lvm->stripe_size, NULL,
++					     lvm->stripes,
++					     area_len, 0, 0, 0, 0, NULL))) {
++			log_error("Failed to allocate striped segment.");
++			return 0;
++		}
++
++		/*
++		 * Set up start positions of each stripe in this segment
++		 */
++		for (st = 0; st < seg->area_count; st++)
++			if (!set_lv_segment_area_pv(seg, st,
++			      lvm->map[first_area_le + st * total_area_len].pv,
++			      lvm->map[first_area_le + st * total_area_len].pe))
++				return_0;
++
++		dm_list_add(&lvm->lv->segments, &seg->list);
++
++		first_area_le += area_len;
++	}
++
++	return 1;
++}
++
++static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
++{
++	return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) :
++		_read_linear(cmd, lvm));
++}
++
++static int _build_all_segments(struct cmd_context *cmd, struct dm_hash_table *maps)
++{
++	struct dm_hash_node *n;
++	struct lv_map *lvm;
++
++	for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
++		lvm = (struct lv_map *) dm_hash_get_data(maps, n);
++		if (!_build_segments(cmd, lvm))
++			return_0;
++	}
++
++	return 1;
++}
++
++int import_extents(struct cmd_context *cmd, struct volume_group *vg,
++		   struct dm_list *pvds)
++{
++	int r = 0;
++	struct dm_pool *scratch = dm_pool_create("lvm1 import_extents", 10 * 1024);
++	struct dm_hash_table *maps;
++
++	if (!scratch)
++		return_0;
++
++	if (!(maps = _create_lv_maps(scratch, vg))) {
++		log_error("Couldn't allocate logical volume maps.");
++		goto out;
++	}
++
++	if (!_fill_maps(maps, vg, pvds)) {
++		log_error("Couldn't fill logical volume maps.");
++		goto out;
++	}
++
++	if (!_check_maps_are_complete(maps) && !(vg->status & PARTIAL_VG))
++		goto_out;
++
++	if (!_build_all_segments(cmd, maps)) {
++		log_error("Couldn't build extent segments.");
++		goto out;
++	}
++	r = 1;
++
++      out:
++	if (maps)
++		dm_hash_destroy(maps);
++	dm_pool_destroy(scratch);
++	return r;
++}
+diff --git a/lib/format1/layout.c b/lib/format1/layout.c
+new file mode 100644
+index 0000000..380a983
+--- /dev/null
++++ b/lib/format1/layout.c
+@@ -0,0 +1,172 @@
++/*
++ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "lib.h"
++#include "disk-rep.h"
++
++/*
++ * Only works with powers of 2.
++ */
++static uint32_t _round_up(uint32_t n, uint32_t size)
++{
++	size--;
++	return (n + size) & ~size;
++}
++
++/* Unused.
++static uint32_t _div_up(uint32_t n, uint32_t size)
++{
++	return _round_up(n, size) / size;
++}
++*/
++
++/*
++ * Each chunk of metadata should be aligned to
++ * METADATA_ALIGN.
++ */
++static uint32_t _next_base(struct data_area *area)
++{
++	return _round_up(area->base + area->size, METADATA_ALIGN);
++}
++
++/*
++ * Quick calculation based on pe_start.
++ */
++static int _adjust_pe_on_disk(struct pv_disk *pvd)
++{
++	uint32_t pe_start = pvd->pe_start << SECTOR_SHIFT;
++
++	if (pe_start < pvd->pe_on_disk.base + pvd->pe_on_disk.size)
++		return 0;
++
++	pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
++	return 1;
++}
++
++static void _calc_simple_layout(struct pv_disk *pvd)
++{
++	pvd->pv_on_disk.base = METADATA_BASE;
++	pvd->pv_on_disk.size = PV_SIZE;
++
++	pvd->vg_on_disk.base = _next_base(&pvd->pv_on_disk);
++	pvd->vg_on_disk.size = VG_SIZE;
++
++	pvd->pv_uuidlist_on_disk.base = _next_base(&pvd->vg_on_disk);
++	pvd->pv_uuidlist_on_disk.size = MAX_PV * NAME_LEN;
++
++	pvd->lv_on_disk.base = _next_base(&pvd->pv_uuidlist_on_disk);
++	pvd->lv_on_disk.size = MAX_LV * sizeof(struct lv_disk);
++
++	pvd->pe_on_disk.base = _next_base(&pvd->lv_on_disk);
++	pvd->pe_on_disk.size = pvd->pe_total * sizeof(struct pe_disk);
++}
++
++static int _check_vg_limits(struct disk_list *dl)
++{
++	if (dl->vgd.lv_max > MAX_LV) {
++		log_error("MaxLogicalVolumes of %d exceeds format limit of %d "
++			  "for VG '%s'", dl->vgd.lv_max, MAX_LV - 1,
++			  dl->pvd.vg_name);
++		return 0;
++	}
++
++	if (dl->vgd.pv_max > MAX_PV) {
++		log_error("MaxPhysicalVolumes of %d exceeds format limit of %d "
++			  "for VG '%s'", dl->vgd.pv_max, MAX_PV - 1,
++			  dl->pvd.vg_name);
++		return 0;
++	}
++
++	return 1;
++}
++
++/*
++ * This assumes pe_count and pe_start have already
++ * been calculated correctly.
++ */
++int calculate_layout(struct disk_list *dl)
++{
++	struct pv_disk *pvd = &dl->pvd;
++
++	_calc_simple_layout(pvd);
++	if (!_adjust_pe_on_disk(pvd)) {
++		log_error("Insufficient space for metadata and PE's.");
++		return 0;
++	}
++
++	if (!_check_vg_limits(dl))
++		return 0;
++
++	return 1;
++}
++
++/*
++ * The number of extents that can fit on a disk is metadata format dependant.
++ * pe_start is any existing value for pe_start
++ */
++int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
++			   uint32_t max_extent_count, uint64_t pe_start)
++{
++	struct pv_disk *pvd = dm_malloc(sizeof(*pvd));
++	uint32_t end;
++
++	if (!pvd)
++		return_0;
++
++	/*
++	 * Guess how many extents will fit, bearing in mind that
++	 * one is going to be knocked off at the start of the
++	 * next loop.
++	 */
++	if (max_extent_count)
++		pvd->pe_total = max_extent_count + 1;
++	else
++		pvd->pe_total = (pv->size / extent_size);
++
++	if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) {
++		log_error("Too few extents on %s.  Try smaller extent size.",
++			  pv_dev_name(pv));
++		dm_free(pvd);
++		return 0;
++	}
++
++	do {
++		pvd->pe_total--;
++		_calc_simple_layout(pvd);
++		end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size +
++			SECTOR_SIZE - 1) >> SECTOR_SHIFT);
++
++		if (pe_start && end < pe_start)
++			end = pe_start;
++
++		pvd->pe_start = _round_up(end, LVM1_PE_ALIGN);
++
++	} while ((pvd->pe_start + ((uint64_t)pvd->pe_total * extent_size))
++		 > pv->size);
++
++	if (pvd->pe_total > MAX_PE_TOTAL) {
++		log_error("Metadata extent limit (%u) exceeded for %s - "
++			  "%u required", MAX_PE_TOTAL, pv_dev_name(pv),
++			  pvd->pe_total);
++		dm_free(pvd);
++		return 0;
++	}
++
++	pv->pe_count = pvd->pe_total;
++	pv->pe_start = pvd->pe_start;
++	/* We can't set pe_size here without breaking LVM1 compatibility */
++	dm_free(pvd);
++	return 1;
++}
+diff --git a/lib/format1/lvm1-label.c b/lib/format1/lvm1-label.c
+new file mode 100644
+index 0000000..691a05a
+--- /dev/null
++++ b/lib/format1/lvm1-label.c
+@@ -0,0 +1,129 @@
++/*
++ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "lib.h"
++#include "lvm1-label.h"
++#include "disk-rep.h"
++#include "label.h"
++#include "metadata.h"
++#include "xlate.h"
++#include "format1.h"
++
++#include <sys/stat.h>
++#include <fcntl.h>
++
++static void _not_supported(const char *op)
++{
++	log_error("The '%s' operation is not supported for the lvm1 labeller.",
++		  op);
++}
++
++static int _lvm1_can_handle(struct labeller *l __attribute__((unused)), void *buf, uint64_t sector)
++{
++	struct pv_disk *pvd = (struct pv_disk *) buf;
++	uint32_t version;
++
++	/* LVM1 label must always be in first sector */
++	if (sector)
++		return 0;
++
++	version = xlate16(pvd->version);
++
++	if (pvd->id[0] == 'H' && pvd->id[1] == 'M' &&
++	    (version == 1 || version == 2))
++		return 1;
++
++	return 0;
++}
++
++static int _lvm1_write(struct label *label __attribute__((unused)), void *buf __attribute__((unused)))
++{
++	_not_supported("write");
++	return 0;
++}
++
++static int _lvm1_read(struct labeller *l, struct device *dev, void *buf,
++		 struct label **label)
++{
++	struct pv_disk *pvd = (struct pv_disk *) buf;
++	struct vg_disk vgd;
++	struct lvmcache_info *info;
++	const char *vgid = FMT_LVM1_ORPHAN_VG_NAME;
++	const char *vgname = FMT_LVM1_ORPHAN_VG_NAME;
++	unsigned exported = 0;
++
++	munge_pvd(dev, pvd);
++
++	if (*pvd->vg_name) {
++		if (!read_vgd(dev, &vgd, pvd))
++			return_0;
++		vgid = (char *) vgd.vg_uuid;
++		vgname = (char *) pvd->vg_name;
++		exported = pvd->pv_status & VG_EXPORTED;
++	}
++
++	if (!(info = lvmcache_add(l, (char *)pvd->pv_uuid, dev, vgname, vgid,
++				  exported)))
++		return_0;
++	*label = lvmcache_get_label(info);
++
++	lvmcache_set_device_size(info, ((uint64_t)xlate32(pvd->pv_size)) << SECTOR_SHIFT);
++	lvmcache_set_ext_version(info, 0);
++	lvmcache_set_ext_flags(info, 0);
++	lvmcache_del_mdas(info);
++	lvmcache_del_bas(info);
++
++	return 1;
++}
++
++static int _lvm1_initialise_label(struct labeller *l __attribute__((unused)), struct label *label)
++{
++	strcpy(label->type, "LVM1");
++
++	return 1;
++}
++
++static void _lvm1_destroy_label(struct labeller *l __attribute__((unused)), struct label *label __attribute__((unused)))
++{
++}
++
++static void _lvm1_destroy(struct labeller *l)
++{
++	dm_free(l);
++}
++
++struct label_ops _lvm1_ops = {
++	.can_handle = _lvm1_can_handle,
++	.write = _lvm1_write,
++	.read = _lvm1_read,
++	.initialise_label = _lvm1_initialise_label,
++	.destroy_label = _lvm1_destroy_label,
++	.destroy = _lvm1_destroy,
++};
++
++struct labeller *lvm1_labeller_create(struct format_type *fmt)
++{
++	struct labeller *l;
++
++	if (!(l = dm_malloc(sizeof(*l)))) {
++		log_error("Couldn't allocate labeller object.");
++		return NULL;
++	}
++
++	l->ops = &_lvm1_ops;
++	l->fmt = fmt;
++
++	return l;
++}
+diff --git a/lib/format1/lvm1-label.h b/lib/format1/lvm1-label.h
+new file mode 100644
+index 0000000..27f2f51
+--- /dev/null
++++ b/lib/format1/lvm1-label.h
+@@ -0,0 +1,23 @@
++/*
++ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
++ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef _LVM_LVM1_LABEL_H
++#define _LVM_LVM1_LABEL_H
++
++#include "metadata.h"
++
++struct labeller *lvm1_labeller_create(struct format_type *fmt);
++
++#endif
+diff --git a/lib/format1/vg_number.c b/lib/format1/vg_number.c
+new file mode 100644
+index 0000000..8b1a803
+--- /dev/null
++++ b/lib/format1/vg_number.c
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "lib.h"
++#include "disk-rep.h"
++
++/*
++ * FIXME: Quick hack.  We can use caching to
++ * prevent a total re-read, even so vg_number
++ * causes the tools to check *every* pv.  Yuck.
++ * Put in separate file so it wouldn't contaminate
++ * other code.
++ */
++int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
++		       const char *candidate_vg, int *result)
++{
++	struct dm_list all_pvs;
++	struct disk_list *dl;
++	struct dm_pool *mem = dm_pool_create("lvm1 vg_number", 10 * 1024);
++	int i, r = 0, numbers[MAX_VG] = { 0 };
++
++	dm_list_init(&all_pvs);
++
++	if (!mem)
++		return_0;
++
++	if (!read_pvs_in_vg(fid->fmt, NULL, filter, mem, &all_pvs))
++		goto_out;
++
++	dm_list_iterate_items(dl, &all_pvs) {
++		if (!*dl->pvd.vg_name || !strcmp((char *)dl->pvd.vg_name, candidate_vg))
++			continue;
++
++		numbers[dl->vgd.vg_number] = 1;
++	}
++
++	for (i = 0; i < MAX_VG; i++) {
++		if (!numbers[i]) {
++			r = 1;
++			*result = i;
++			break;
++		}
++	}
++
++      out:
++	dm_pool_destroy(mem);
++	return r;
++}
+diff --git a/lib/format_pool/.exported_symbols b/lib/format_pool/.exported_symbols
+new file mode 100644
+index 0000000..e9fac2e
+--- /dev/null
++++ b/lib/format_pool/.exported_symbols
+@@ -0,0 +1 @@
++init_format
+diff --git a/lib/format_pool/Makefile.in b/lib/format_pool/Makefile.in
+new file mode 100644
+index 0000000..05d1b0c
+--- /dev/null
++++ b/lib/format_pool/Makefile.in
+@@ -0,0 +1,30 @@
++#
++# Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
++# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
++#
++# This file is part of LVM2.
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions
++# of the GNU General Public License v.2.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software Foundation,
++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++
++srcdir = @srcdir@
++top_srcdir = @top_srcdir@
++top_builddir = @top_builddir@
++
++SOURCES =\
++	disk_rep.c \
++	format_pool.c \
++	import_export.c \
++	pool_label.c
++
++LIB_SHARED = liblvm2formatpool.$(LIB_SUFFIX)
++LIB_VERSION = $(LIB_VERSION_LVM)
++
++include $(top_builddir)/make.tmpl
++
++install: install_lvm2_plugin
+diff --git a/lib/format_pool/disk_rep.c b/lib/format_pool/disk_rep.c
+new file mode 100644
+index 0000000..fe9b03e
+--- /dev/null
++++ b/lib/format_pool/disk_rep.c
+@@ -0,0 +1,409 @@
++/*
++ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "lib.h"
++#include "label.h"
++#include "metadata.h"
++#include "lvmcache.h"
++#include "xlate.h"
++#include "disk_rep.h"
++#include "toolcontext.h"
++
++#include <assert.h>
++
++/* FIXME: memcpy might not be portable */
++#define CPIN_8(x, y, z) {memcpy((x), (y), (z));}
++#define CPOUT_8(x, y, z) {memcpy((y), (x), (z));}
++#define CPIN_16(x, y) {(x) = xlate16_be((y));}
++#define CPOUT_16(x, y) {(y) = xlate16_be((x));}
++#define CPIN_32(x, y) {(x) = xlate32_be((y));}
++#define CPOUT_32(x, y) {(y) = xlate32_be((x));}
++#define CPIN_64(x, y) {(x) = xlate64_be((y));}
++#define CPOUT_64(x, y) {(y) = xlate64_be((x));}
++
++static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
++			    struct dm_pool *mem __attribute__((unused)), struct pool_list *pl,
++			    const char *vg_name __attribute__((unused)))
++{
++	char buf[512] __attribute__((aligned(8)));
++
++	/* FIXME: Need to check the cache here first */
++	if (!dev_read(dev, UINT64_C(0), 512, DEV_IO_POOL, buf)) {
++		log_very_verbose("Failed to read PV data from %s",
++				 dev_name(dev));
++		return 0;
++	}
++
++	if (!read_pool_label(pl, fmt->labeller, dev, buf, NULL))
++		return_0;
++
++	return 1;
++}
++
++static void _add_pl_to_list(struct cmd_context *cmd, struct dm_list *head, struct pool_list *data)
++{
++	struct pool_list *pl;
++
++	dm_list_iterate_items(pl, head) {
++		if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
++			char uuid[ID_LEN + 7] __attribute__((aligned(8)));
++
++			if (!id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7))
++				stack;
++
++			if (!dev_subsystem_part_major(cmd->dev_types, data->dev)) {
++				log_very_verbose("Ignoring duplicate PV %s on "
++						 "%s", uuid,
++						 dev_name(data->dev));
++				return;
++			}
++			log_very_verbose("Duplicate PV %s - using %s %s",
++					 uuid, dev_subsystem_name(cmd->dev_types, data->dev),
++					 dev_name(data->dev));
++			dm_list_del(&pl->list);
++			break;
++		}
++	}
++	dm_list_add(head, &data->list);
++}
++
++int read_pool_label(struct pool_list *pl, struct labeller *l,
++		    struct device *dev, char *buf, struct label **label)
++{
++	struct lvmcache_info *info;
++	struct id pvid;
++	struct id vgid;
++	char uuid[ID_LEN + 7] __attribute__((aligned(8)));
++	struct pool_disk *pd = &pl->pd;
++
++	pool_label_in(pd, buf);
++
++	get_pool_pv_uuid(&pvid, pd);
++	if (!id_write_format(&pvid, uuid, ID_LEN + 7))
++		stack;
++	log_debug_metadata("Calculated uuid %s for %s", uuid, dev_name(dev));
++
++	get_pool_vg_uuid(&vgid, pd);
++	if (!id_write_format(&vgid, uuid, ID_LEN + 7))
++		stack;
++	log_debug_metadata("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
++
++	if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
++				  (char *) &vgid, 0)))
++		return_0;
++	if (label)
++		*label = lvmcache_get_label(info);
++
++	lvmcache_set_device_size(info, ((uint64_t)xlate32_be(pd->pl_blocks)) << SECTOR_SHIFT);
++	lvmcache_set_ext_version(info, 0);
++	lvmcache_set_ext_flags(info, 0);
++	lvmcache_del_mdas(info);
++	lvmcache_del_bas(info);
++
++	pl->dev = dev;
++	pl->pv = NULL;
++	memcpy(&pl->pv_uuid, &pvid, sizeof(pvid));
++
++	return 1;
++}
++
++/**
++ * pool_label_out - copies a pool_label_t into a char buffer
++ * @pl: ptr to a pool_label_t struct
++ * @buf: ptr to raw space where label info will be copied
++ *
++ * This function is important because it takes care of all of
++ * the endian issues when copying to disk.  This way, when
++ * machines of different architectures are used, they will
++ * be able to interpret ondisk labels correctly.  Always use
++ * this function before writing to disk.
++ */
++void pool_label_out(struct pool_disk *pl, void *buf)
++{
++	struct pool_disk *bufpl = (struct pool_disk *) buf;
++
++	CPOUT_64(pl->pl_magic, bufpl->pl_magic);
++	CPOUT_64(pl->pl_pool_id, bufpl->pl_pool_id);
++	CPOUT_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
++	CPOUT_32(pl->pl_version, bufpl->pl_version);
++	CPOUT_32(pl->pl_subpools, bufpl->pl_subpools);
++	CPOUT_32(pl->pl_sp_id, bufpl->pl_sp_id);
++	CPOUT_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
++	CPOUT_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
++	CPOUT_32(pl->pl_sp_type, bufpl->pl_sp_type);
++	CPOUT_64(pl->pl_blocks, bufpl->pl_blocks);
++	CPOUT_32(pl->pl_striping, bufpl->pl_striping);
++	CPOUT_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
++	CPOUT_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
++	CPOUT_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
++	CPOUT_32(pl->pl_minor, bufpl->pl_minor);
++	CPOUT_32(pl->pl_padding, bufpl->pl_padding);
++	CPOUT_8(pl->pl_reserve, bufpl->pl_reserve, 184);
++}
++
++/**
++ * pool_label_in - copies a char buffer into a pool_label_t
++ * @pl: ptr to a pool_label_t struct
++ * @buf: ptr to raw space where label info is copied from
++ *
++ * This function is important because it takes care of all of
++ * the endian issues when information from disk is about to be
++ * used.  This way, when machines of different architectures
++ * are used, they will be able to interpret ondisk labels
++ * correctly.  Always use this function before using labels that
++ * were read from disk.
++ */
++void pool_label_in(struct pool_disk *pl, void *buf)
++{
++	struct pool_disk *bufpl = (struct pool_disk *) buf;
++
++	CPIN_64(pl->pl_magic, bufpl->pl_magic);
++	CPIN_64(pl->pl_pool_id, bufpl->pl_pool_id);
++	CPIN_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
++	CPIN_32(pl->pl_version, bufpl->pl_version);
++	CPIN_32(pl->pl_subpools, bufpl->pl_subpools);
++	CPIN_32(pl->pl_sp_id, bufpl->pl_sp_id);
++	CPIN_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
++	CPIN_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
++	CPIN_32(pl->pl_sp_type, bufpl->pl_sp_type);
++	CPIN_64(pl->pl_blocks, bufpl->pl_blocks);
++	CPIN_32(pl->pl_striping, bufpl->pl_striping);
++	CPIN_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
++	CPIN_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
++	CPIN_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
++	CPIN_32(pl->pl_minor, bufpl->pl_minor);
++	CPIN_32(pl->pl_padding, bufpl->pl_padding);
++	CPIN_8(pl->pl_reserve, bufpl->pl_reserve, 184);
++}
++
++static char _calc_char(unsigned int id)
++{
++	/*
++	 * [0-9A-Za-z!#] - 64 printable chars (6-bits)
++	 */
++
++	if (id < 10)
++		return id + 48;
++	if (id < 36)
++		return (id - 10) + 65;
++	if (id < 62)
++		return (id - 36) + 97;
++	if (id == 62)
++		return '!';
++	if (id == 63)
++		return '#';
++
++	return '%';
++}
++
++void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
++{
++	int i;
++	unsigned shifter = 0x003F;
++
++	assert(ID_LEN == 32);
++	memset(uuid, 0, ID_LEN);
++	strcat(uuid, "POOL0000000000");
++
++	/* We grab the entire 64 bits (+2 that get shifted in) */
++	for (i = 13; i < 24; i++) {
++		uuid[i] = _calc_char(((unsigned) poolid) & shifter);
++		poolid = poolid >> 6;
++	}
++
++	/* We grab the entire 32 bits (+4 that get shifted in) */
++	for (i = 24; i < 30; i++) {
++		uuid[i] = _calc_char((unsigned) (spid & shifter));
++		spid = spid >> 6;
++	}
++
++	/*
++	 * Since we can only have 128 devices, we only worry about the
++	 * last 12 bits
++	 */
++	for (i = 30; i < 32; i++) {
++		uuid[i] = _calc_char((unsigned) (devid & shifter));
++		devid = devid >> 6;
++	}
++
++}
++
++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;
++	uint32_t sp_count;
++	int failed;
++	int empty;
++};
++
++static int _read_pool_pv(struct lvmcache_info *info, void *baton)
++{
++	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(lvmcache_fmt(info)->cmd, b->head, b->pl);
++
++	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 (!(b->tmpmem = dm_pool_create("pool read_vg", 512)))
++		return_0;
++
++	lvmcache_foreach_pv(vginfo, _read_pool_pv, b);
++
++	*devcount = 0;
++	for (i = 0; i < b->sp_count; i++)
++		*devcount += b->sp_devs[i];
++
++	dm_pool_destroy(b->tmpmem);
++
++	if (b->pl && *b->pl->pd.pl_pool_name)
++		return 1;
++
++	return 0;
++
++}
++
++int read_pool_pds(const struct format_type *fmt, const char *vg_name,
++		  struct dm_pool *mem, struct dm_list *pdhead)
++{
++	struct lvmcache_vginfo *vginfo;
++	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 = 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);
++
++		full_scan++;
++		if (full_scan > 1) {
++			log_debug_metadata("No devices for vg %s found in cache",
++					   vg_name);
++			return 0;
++		}
++		lvmcache_label_scan(fmt->cmd);
++
++	} while (1);
++
++}
++
++struct pool_list *read_pool_disk(const struct format_type *fmt,
++				 struct device *dev, struct dm_pool *mem,
++				 const char *vg_name)
++{
++	struct pool_list *pl;
++
++	if (!dev_open_readonly(dev))
++		return_NULL;
++
++	if (!(pl = dm_pool_zalloc(mem, sizeof(*pl)))) {
++		log_error("Unable to allocate pool list structure");
++		return 0;
++	}
++
++	if (!__read_pool_disk(fmt, dev, mem, pl, vg_name))
++		return_NULL;
++
++	if (!dev_close(dev))
++		stack;
++
++	return pl;
++
++}
+diff --git a/lib/format_pool/disk_rep.h b/lib/format_pool/disk_rep.h
+new file mode 100644
+index 0000000..37e942e
+--- /dev/null
++++ b/lib/format_pool/disk_rep.h
+@@ -0,0 +1,156 @@
++/*
++ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.  
++ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef DISK_REP_FORMAT_POOL_H
++#define DISK_REP_FORMAT_POOL_H
++
++#include "label.h"
++#include "metadata.h"
++
++#define MINOR_OFFSET 65536
++
++/* From NSP.cf */
++#define NSPMajorVersion	4
++#define NSPMinorVersion	1
++#define NSPUpdateLevel	3
++
++/* From pool_std.h */
++#define POOL_NAME_SIZE          (256)
++#define POOL_MAGIC 		0x011670
++#define POOL_MAJOR              (121)
++#define POOL_MAX_DEVICES 	128
++
++/* When checking for version matching, the first two numbers **
++** are important for metadata formats, a.k.a pool labels.   **
++** All the numbers are important when checking if the user  **
++** space tools match up with the kernel module............. */
++#define POOL_VERSION		(NSPMajorVersion << 16 | \
++				 NSPMinorVersion <<  8 | \
++				 NSPUpdateLevel)
++
++/* Pool label is at the head of every pool disk partition */
++#define SIZEOF_POOL_LABEL       (8192)
++
++/* in sectors */
++#define POOL_PE_SIZE     (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
++#define POOL_PE_START    (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
++
++/* Helper fxns */
++#define get_pool_vg_uuid(id, pd) do { get_pool_uuid((char *)(id), \
++                                                    (pd)->pl_pool_id, 0, 0); \
++                                    } while(0)
++#define get_pool_pv_uuid(id, pd) do { get_pool_uuid((char *)(id), \
++                                                    (pd)->pl_pool_id, \
++                                                    (pd)->pl_sp_id, \
++                                                    (pd)->pl_sp_devid); \
++                                    } while(0)
++#define get_pool_lv_uuid(id, pd) do { get_pool_uuid((char *)&(id)[0], \
++                                                    (pd)->pl_pool_id, 0, 0); \
++                                      get_pool_uuid((char*)&(id)[1], \
++                                                    (pd)->pl_pool_id, 0, 0); \
++                                    } while(0)
++
++struct pool_disk;
++struct pool_list;
++struct user_subpool;
++struct user_device;
++
++struct pool_disk {
++	uint64_t pl_magic;	/* Pool magic number */
++	uint64_t pl_pool_id;	/* Unique pool identifier */
++	char pl_pool_name[POOL_NAME_SIZE];	/* Name of pool */
++	uint32_t pl_version;	/* Pool version */
++	uint32_t pl_subpools;	/* Number of subpools in this pool */
++	uint32_t pl_sp_id;	/* Subpool number within pool */
++	uint32_t pl_sp_devs;	/* Number of data partitions in this subpool */
++	uint32_t pl_sp_devid;	/* Partition number within subpool */
++	uint32_t pl_sp_type;	/* Partition type */
++	uint64_t pl_blocks;	/* Number of blocks in this partition */
++	uint32_t pl_striping;	/* Striping size within subpool */
++	/*
++	 * If the number of DMEP devices is zero, then the next field **
++	 * ** (pl_sp_dmepid) becomes the subpool ID for redirection.  In **
++	 * ** other words, if this subpool does not have the capability  **
++	 * ** to do DMEP, then it must specify which subpool will do it  **
++	 * ** in it's place
++	 */
++
++	/*
++	 * While the next 3 field are no longer used, they must stay to keep **
++	 * ** backward compatibility...........................................
++	 */
++	uint32_t pl_sp_dmepdevs;/* Number of dmep devices in this subpool */
++	uint32_t pl_sp_dmepid;	/* Dmep device number within subpool */
++	uint32_t pl_sp_weight;	/* if dmep dev, pref to using it */
++
++	uint32_t pl_minor;	/* the pool minor number */
++	uint32_t pl_padding;	/* reminder - think about alignment */
++
++	/*
++	 * Even though we're zeroing out 8k at the front of the disk before
++	 * writing the label, putting this in
++	 */
++	char pl_reserve[184];	/* bump the structure size out to 512 bytes */
++};
++
++struct pool_list {
++	struct dm_list list;
++	struct pool_disk pd;
++	struct physical_volume *pv;
++	struct id pv_uuid;
++	struct device *dev;
++};
++
++struct user_subpool {
++	uint32_t initialized;
++	uint32_t id;
++	uint32_t striping;
++	uint32_t num_devs;
++	uint32_t type;
++	uint32_t dummy;
++	struct user_device *devs;
++};
++
++struct user_device {
++	uint32_t initialized;
++	uint32_t sp_id;
++	uint32_t devid;
++	uint32_t dummy;
++	uint64_t blocks;
++	struct physical_volume *pv;
++};
++
++int read_pool_label(struct pool_list *pl, struct labeller *l,
++		    struct device *dev, char *buf, struct label **label);
++void pool_label_out(struct pool_disk *pl, void *buf);
++void pool_label_in(struct pool_disk *pl, void *buf);
++void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid);
++int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct dm_list *pls);
++int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem,
++		    struct dm_list *pls);
++int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
++		    struct dm_pool *mem, struct dm_list *pls);
++int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
++		   struct volume_group *vg, struct physical_volume *pv,
++		   struct pool_list *pl);
++int import_pool_segments(struct dm_list *lvs, struct dm_pool *mem,
++			 struct user_subpool *usp, int sp_count);
++int read_pool_pds(const struct format_type *fmt, const char *vgname,
++		  struct dm_pool *mem, struct dm_list *head);
++struct pool_list *read_pool_disk(const struct format_type *fmt,
++				 struct device *dev, struct dm_pool *mem,
++				 const char *vg_name);
++
++#endif				/* DISK_REP_POOL_FORMAT_H */
+diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
+new file mode 100644
+index 0000000..f8223a3
+--- /dev/null
++++ b/lib/format_pool/format_pool.c
+@@ -0,0 +1,337 @@
++/*
++ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "lib.h"
++#include "label.h"
++#include "metadata.h"
++#include "limits.h"
++#include "display.h"
++#include "toolcontext.h"
++#include "lvmcache.h"
++#include "disk_rep.h"
++#include "format_pool.h"
++#include "pool_label.h"
++
++/* Must be called after pvs are imported */
++static struct user_subpool *_build_usp(struct dm_list *pls, struct dm_pool *mem,
++				       int *sps)
++{
++	struct pool_list *pl;
++	struct user_subpool *usp = NULL, *cur_sp = NULL;
++	struct user_device *cur_dev = NULL;
++
++	/*
++	 * FIXME: Need to do some checks here - I'm tempted to add a
++	 * user_pool structure and build the entire thing to check against.
++	 */
++	dm_list_iterate_items(pl, pls) {
++		*sps = pl->pd.pl_subpools;
++		if (!usp && (!(usp = dm_pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
++			log_error("Unable to allocate %d subpool structures",
++				  *sps);
++			return 0;
++		}
++
++		if (cur_sp != &usp[pl->pd.pl_sp_id]) {
++			cur_sp = &usp[pl->pd.pl_sp_id];
++
++			cur_sp->id = pl->pd.pl_sp_id;
++			cur_sp->striping = pl->pd.pl_striping;
++			cur_sp->num_devs = pl->pd.pl_sp_devs;
++			cur_sp->type = pl->pd.pl_sp_type;
++			cur_sp->initialized = 1;
++		}
++
++		if (!cur_sp->devs &&
++		    (!(cur_sp->devs =
++		       dm_pool_zalloc(mem,
++				   sizeof(*usp->devs) * pl->pd.pl_sp_devs)))) {
++
++			log_error("Unable to allocate %d pool_device "
++				  "structures", pl->pd.pl_sp_devs);
++			return 0;
++		}
++
++		cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
++		cur_dev->sp_id = cur_sp->id;
++		cur_dev->devid = pl->pd.pl_sp_id;
++		cur_dev->blocks = pl->pd.pl_blocks;
++		cur_dev->pv = pl->pv;
++		cur_dev->initialized = 1;
++	}
++
++	return usp;
++}
++
++static int _check_usp(const char *vgname, struct user_subpool *usp, int sp_count)
++{
++	int i;
++	unsigned j;
++
++	for (i = 0; i < sp_count; i++) {
++		if (!usp[i].initialized) {
++			log_error("Missing subpool %d in pool %s", i, vgname);
++			return 0;
++		}
++		for (j = 0; j < usp[i].num_devs; j++) {
++			if (!usp[i].devs[j].initialized) {
++				log_error("Missing device %u for subpool %d"
++					  " in pool %s", j, i, vgname);
++				return 0;
++			}
++
++		}
++	}
++
++	return 1;
++}
++
++static struct volume_group *_pool_vg_read(struct format_instance *fid,
++					  const char *vg_name,
++					  struct metadata_area *mda __attribute__((unused)),
++					  struct cached_vg_fmtdata **vg_fmtdata __attribute__((unused)),
++					  unsigned *use_previous_vg __attribute__((unused)))
++{
++	struct volume_group *vg;
++	struct user_subpool *usp;
++	int sp_count;
++	DM_LIST_INIT(pds);
++
++	/* We can safely ignore the mda passed in */
++
++	/* Strip dev_dir if present */
++	if (vg_name)
++		vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
++
++	/* Set vg_name through read_pool_pds() */
++	if (!(vg = alloc_vg("pool_vg_read", fid->fmt->cmd, NULL)))
++		return_NULL;
++
++	/* Read all the pvs in the vg */
++	if (!read_pool_pds(fid->fmt, vg_name, vg->vgmem, &pds))
++		goto_bad;
++
++	/* Setting pool seqno to 1 because the code always did this,
++	 * although we don't think it's needed. */
++	vg->seqno = 1;
++
++	if (!import_pool_vg(vg, vg->vgmem, &pds))
++		goto_bad;
++
++	if (!import_pool_pvs(fid->fmt, vg, vg->vgmem, &pds))
++		goto_bad;
++
++	if (!import_pool_lvs(vg, vg->vgmem, &pds))
++		goto_bad;
++
++	/*
++	 * I need an intermediate subpool structure that contains all the
++	 * relevant info for this.  Then i can iterate through the subpool
++	 * structures for checking, and create the segments
++	 */
++	if (!(usp = _build_usp(&pds, vg->vgmem, &sp_count)))
++		goto_bad;
++
++	/*
++	 * check the subpool structures - we can't handle partial VGs in
++	 * the pool format, so this will error out if we're missing PVs
++	 */
++	if (!_check_usp(vg->name, usp, sp_count))
++		goto_bad;
++
++	if (!import_pool_segments(&vg->lvs, vg->vgmem, usp, sp_count))
++		goto_bad;
++
++	vg_set_fid(vg, fid);
++
++	return vg;
++
++bad:
++	release_vg(vg);
++
++	return NULL;
++}
++
++static int _pool_pv_initialise(const struct format_type *fmt __attribute__((unused)),
++			       struct pv_create_args *pva __attribute__((unused)),
++			       struct physical_volume *pv __attribute__((unused)))
++{
++	return 1;
++}
++
++static int _pool_pv_setup(const struct format_type *fmt __attribute__((unused)),
++			  struct physical_volume *pv __attribute__((unused)),
++			  struct volume_group *vg __attribute__((unused)))
++{
++	return 1;
++}
++
++static int _pool_pv_read(const struct format_type *fmt, const char *pv_name,
++			 struct physical_volume *pv,
++			 int scan_label_only __attribute__((unused)))
++{
++	struct dm_pool *mem = dm_pool_create("pool pv_read", 1024);
++	struct pool_list *pl;
++	struct device *dev;
++	int r = 0;
++
++	log_very_verbose("Reading physical volume data %s from disk", pv_name);
++
++	if (!mem)
++		return_0;
++
++	if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
++		goto_out;
++
++	/*
++	 * I need to read the disk and populate a pv structure here
++	 * I'll probably need to abstract some of this later for the
++	 * vg_read code
++	 */
++	if (!(pl = read_pool_disk(fmt, dev, mem, NULL)))
++		goto_out;
++
++	if (!import_pool_pv(fmt, fmt->cmd->mem, NULL, pv, pl))
++		goto_out;
++
++	pv->fmt = fmt;
++
++	r = 1;
++
++      out:
++	dm_pool_destroy(mem);
++	return r;
++}
++
++/* *INDENT-OFF* */
++static struct metadata_area_ops _metadata_format_pool_ops = {
++	.vg_read = _pool_vg_read,
++};
++/* *INDENT-ON* */
++
++static struct format_instance *_pool_create_instance(const struct format_type *fmt,
++						     const struct format_instance_ctx *fic)
++{
++	struct format_instance *fid;
++	struct metadata_area *mda;
++
++	if (!(fid = alloc_fid(fmt, fic)))
++		return_NULL;
++
++	/* Define a NULL metadata area */
++	if (!(mda = dm_pool_zalloc(fid->mem, sizeof(*mda)))) {
++		log_error("Unable to allocate metadata area structure "
++			  "for pool format");
++		goto bad;
++	}
++
++	mda->ops = &_metadata_format_pool_ops;
++	mda->metadata_locn = NULL;
++	mda->status = 0;
++	dm_list_add(&fid->metadata_areas_in_use, &mda->list);
++
++	return fid;
++
++bad:
++	dm_pool_destroy(fid->mem);
++	return NULL;
++}
++
++static void _pool_destroy_instance(struct format_instance *fid)
++{
++	if (--fid->ref_count <= 1)
++		dm_pool_destroy(fid->mem);
++}
++
++static void _pool_destroy(struct format_type *fmt)
++{
++	if (fmt->orphan_vg)
++		free_orphan_vg(fmt->orphan_vg);
++
++	dm_free(fmt);
++}
++
++/* *INDENT-OFF* */
++static struct format_handler _format_pool_ops = {
++	.pv_read = _pool_pv_read,
++	.pv_initialise = _pool_pv_initialise,
++	.pv_setup = _pool_pv_setup,
++	.create_instance = _pool_create_instance,
++	.destroy_instance = _pool_destroy_instance,
++	.destroy = _pool_destroy,
++};
++/* *INDENT-ON */
++
++#ifdef POOL_INTERNAL
++struct format_type *init_pool_format(struct cmd_context *cmd)
++#else				/* Shared */
++struct format_type *init_format(struct cmd_context *cmd);
++struct format_type *init_format(struct cmd_context *cmd)
++#endif
++{
++	struct format_type *fmt = dm_malloc(sizeof(*fmt));
++	struct format_instance_ctx fic;
++	struct format_instance *fid;
++
++	if (!fmt) {
++		log_error("Unable to allocate format type structure for pool "
++			  "format");
++		return NULL;
++	}
++
++	fmt->cmd = cmd;
++	fmt->ops = &_format_pool_ops;
++	fmt->name = FMT_POOL_NAME;
++	fmt->alias = NULL;
++	fmt->orphan_vg_name = FMT_POOL_ORPHAN_VG_NAME;
++	fmt->features = FMT_OBSOLETE;
++	fmt->private = NULL;
++
++	dm_list_init(&fmt->mda_ops);
++
++	if (!(fmt->labeller = pool_labeller_create(fmt))) {
++		log_error("Couldn't create pool label handler.");
++		dm_free(fmt);
++		return NULL;
++	}
++
++	if (!(label_register_handler(fmt->labeller))) {
++		log_error("Couldn't register pool label handler.");
++		fmt->labeller->ops->destroy(fmt->labeller);
++		dm_free(fmt);
++		return NULL;
++	}
++
++	if (!(fmt->orphan_vg = alloc_vg("pool_orphan", cmd, fmt->orphan_vg_name))) {
++		log_error("Couldn't create pool orphan VG.");
++		dm_free(fmt);
++		return NULL;
++	}
++
++	fic.type = FMT_INSTANCE_AUX_MDAS;
++	fic.context.vg_ref.vg_name = fmt->orphan_vg_name;
++	fic.context.vg_ref.vg_id = NULL;
++
++	if (!(fid = _pool_create_instance(fmt, &fic))) {
++		_pool_destroy(fmt);
++		return NULL;
++	}
++
++	vg_set_fid(fmt->orphan_vg, fid);
++
++	log_very_verbose("Initialised format: %s", fmt->name);
++
++	return fmt;
++}
+diff --git a/lib/format_pool/format_pool.h b/lib/format_pool/format_pool.h
+new file mode 100644
+index 0000000..8ad7eb5
+--- /dev/null
++++ b/lib/format_pool/format_pool.h
+@@ -0,0 +1,28 @@
++/*
++ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef _LVM_FORMAT_POOL_H
++#define _LVM_FORMAT_POOL_H
++
++#include "metadata.h"
++
++#define FMT_POOL_NAME "pool"
++#define FMT_POOL_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_POOL_NAME)
++
++#ifdef POOL_INTERNAL
++struct format_type *init_pool_format(struct cmd_context *cmd);
++#endif
++
++#endif
+diff --git a/lib/format_pool/import_export.c b/lib/format_pool/import_export.c
+new file mode 100644
+index 0000000..f4097a7
+--- /dev/null
++++ b/lib/format_pool/import_export.c
+@@ -0,0 +1,285 @@
++/*
++ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "lib.h"
++#include "label.h"
++#include "metadata.h"
++#include "disk_rep.h"
++#include "sptype_names.h"
++#include "lv_alloc.h"
++#include "pv_alloc.h"
++#include "str_list.h"
++#include "display.h"
++#include "segtype.h"
++#include "toolcontext.h"
++
++/* This file contains only imports at the moment... */
++
++int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct dm_list *pls)
++{
++	struct pool_list *pl;
++
++	dm_list_iterate_items(pl, pls) {
++		vg->extent_count +=
++		    ((pl->pd.pl_blocks) / POOL_PE_SIZE);
++
++		vg->free_count = vg->extent_count;
++
++		if (vg->name)
++			continue;
++
++		vg->name = dm_pool_strdup(mem, pl->pd.pl_pool_name);
++		get_pool_vg_uuid(&vg->id, &pl->pd);
++		vg->extent_size = POOL_PE_SIZE;
++		vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
++		vg->max_lv = 1;
++		vg->max_pv = POOL_MAX_DEVICES;
++		vg->alloc = ALLOC_NORMAL;
++	}
++
++	return 1;
++}
++
++int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem, struct dm_list *pls)
++{
++	struct pool_list *pl;
++	struct logical_volume *lv;
++
++	if (!(lv = alloc_lv(mem)))
++		return_0;
++
++	lv->status = 0;
++	lv->alloc = ALLOC_NORMAL;
++	lv->size = 0;
++	lv->name = NULL;
++	lv->le_count = 0;
++	lv->read_ahead = vg->cmd->default_settings.read_ahead;
++
++	dm_list_iterate_items(pl, pls) {
++		lv->size += pl->pd.pl_blocks;
++
++		if (lv->name)
++			continue;
++
++		if (!(lv->name = dm_pool_strdup(mem, pl->pd.pl_pool_name)))
++			return_0;
++
++		get_pool_lv_uuid(lv->lvid.id, &pl->pd);
++		log_debug_metadata("Calculated lv uuid for lv %s: %s", lv->name,
++				   lv->lvid.s);
++
++		lv->status |= VISIBLE_LV | LVM_READ | LVM_WRITE;
++		lv->major = POOL_MAJOR;
++
++		/* for pool a minor of 0 is dynamic */
++		if (pl->pd.pl_minor) {
++			lv->status |= FIXED_MINOR;
++			lv->minor = pl->pd.pl_minor + MINOR_OFFSET;
++		} else {
++			lv->minor = -1;
++		}
++	}
++
++	lv->le_count = lv->size / POOL_PE_SIZE;
++
++	return link_lv_to_vg(vg, lv);
++}
++
++int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
++		    struct dm_pool *mem, struct dm_list *pls)
++{
++	struct pv_list *pvl;
++	struct pool_list *pl;
++
++	dm_list_iterate_items(pl, pls) {
++		if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
++			log_error("Unable to allocate pv list structure");
++			return 0;
++		}
++		if (!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv)))) {
++			log_error("Unable to allocate pv structure");
++			return 0;
++		}
++		if (!import_pool_pv(fmt, mem, vg, pvl->pv, pl)) {
++			return 0;
++		}
++		pl->pv = pvl->pv;
++		pvl->mdas = NULL;
++		pvl->pe_ranges = NULL;
++		add_pvl_to_vgs(vg, pvl);
++	}
++
++	return 1;
++}
++
++int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
++		   struct volume_group *vg, struct physical_volume *pv,
++		   struct pool_list *pl)
++{
++	struct pool_disk *pd = &pl->pd;
++
++	memset(pv, 0, sizeof(*pv));
++
++	get_pool_pv_uuid(&pv->id, pd);
++	pv->fmt = fmt;
++
++	pv->dev = pl->dev;
++	if (!(pv->vg_name = dm_pool_strdup(mem, pd->pl_pool_name))) {
++		log_error("Unable to duplicate vg_name string");
++		return 0;
++	}
++	if (vg != NULL)
++		memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
++	pv->status = 0;
++	pv->size = pd->pl_blocks;
++	pv->pe_size = POOL_PE_SIZE;
++	pv->pe_start = POOL_PE_START;
++	pv->pe_count = pv->size / POOL_PE_SIZE;
++	pv->pe_alloc_count = 0;
++	pv->pe_align = 0;
++
++	dm_list_init(&pv->tags);
++	dm_list_init(&pv->segments);
++
++	if (!alloc_pv_segment_whole_pv(mem, pv))
++		return_0;
++
++	return 1;
++}
++
++static const char *_cvt_sptype(uint32_t sptype)
++{
++	int i;
++	for (i = 0; sptype_names[i].name[0]; i++) {
++		if (sptype == sptype_names[i].label) {
++			break;
++		}
++	}
++	log_debug_metadata("Found sptype %X and converted it to %s",
++			   sptype, sptype_names[i].name);
++	return sptype_names[i].name;
++}
++
++static int _add_stripe_seg(struct dm_pool *mem,
++			   struct user_subpool *usp, struct logical_volume *lv,
++			   uint32_t *le_cur)
++{
++	struct lv_segment *seg;
++	struct segment_type *segtype;
++	unsigned j;
++	uint32_t area_len;
++
++	if (!is_power_of_2(usp->striping)) {
++		log_error("Stripe size must be a power of 2");
++		return 0;
++	}
++
++	area_len = (usp->devs[0].blocks) / POOL_PE_SIZE;
++
++	if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
++		return_0;
++
++	if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
++				     area_len * usp->num_devs, 0, 0,
++				     usp->striping, NULL, usp->num_devs,
++				     area_len, 0, 0, 0, 0, NULL))) {
++		log_error("Unable to allocate striped lv_segment structure");
++		return 0;
++	}
++
++	for (j = 0; j < usp->num_devs; j++)
++		if (!set_lv_segment_area_pv(seg, j, usp->devs[j].pv, 0))
++			return_0;
++
++	/* add the subpool type to the segment tag list */
++	if (!str_list_add(mem, &seg->tags, _cvt_sptype(usp->type))) {
++		log_error("Allocation failed for str_list.");
++		return 0;
++	}
++
++	dm_list_add(&lv->segments, &seg->list);
++
++	*le_cur += seg->len;
++
++	return 1;
++}
++
++static int _add_linear_seg(struct dm_pool *mem,
++			   struct user_subpool *usp, struct logical_volume *lv,
++			   uint32_t *le_cur)
++{
++	struct lv_segment *seg;
++	struct segment_type *segtype;
++	unsigned j;
++	uint32_t area_len;
++
++	if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
++		return_0;
++
++	for (j = 0; j < usp->num_devs; j++) {
++		area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
++
++		if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
++					     area_len, 0, 0, usp->striping,
++					     NULL, 1, area_len, 0,
++					     POOL_PE_SIZE, 0, 0, NULL))) {
++			log_error("Unable to allocate linear lv_segment "
++				  "structure");
++			return 0;
++		}
++
++		/* add the subpool type to the segment tag list */
++		if (!str_list_add(mem, &seg->tags, _cvt_sptype(usp->type))) {
++			log_error("Allocation failed for str_list.");
++			return 0;
++		}
++
++		if (!set_lv_segment_area_pv(seg, 0, usp->devs[j].pv, 0))
++			return_0;
++		dm_list_add(&lv->segments, &seg->list);
++
++		*le_cur += seg->len;
++	}
++
++	return 1;
++}
++
++int import_pool_segments(struct dm_list *lvs, struct dm_pool *mem,
++			 struct user_subpool *usp, int subpools)
++{
++	struct lv_list *lvl;
++	struct logical_volume *lv;
++	uint32_t le_cur = 0;
++	int i;
++
++	dm_list_iterate_items(lvl, lvs) {
++		lv = lvl->lv;
++
++		if (lv_is_snapshot(lv))
++			continue;
++
++		for (i = 0; i < subpools; i++) {
++			if (usp[i].striping) {
++				if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur))
++					return_0;
++			} else {
++				if (!_add_linear_seg(mem, &usp[i], lv, &le_cur))
++					return_0;
++			}
++		}
++	}
++
++	return 1;
++}
+diff --git a/lib/format_pool/pool_label.c b/lib/format_pool/pool_label.c
+new file mode 100644
+index 0000000..2e30a7b
+--- /dev/null
++++ b/lib/format_pool/pool_label.c
+@@ -0,0 +1,104 @@
++/*
++ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
++ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "lib.h"
++#include "label.h"
++#include "metadata.h"
++#include "disk_rep.h"
++#include "pool_label.h"
++
++#include <sys/stat.h>
++#include <fcntl.h>
++
++static void _pool_not_supported(const char *op)
++{
++	log_error("The '%s' operation is not supported for the pool labeller.",
++		  op);
++}
++
++static int _pool_can_handle(struct labeller *l __attribute__((unused)), void *buf, uint64_t sector)
++{
++
++	struct pool_disk pd;
++
++	/*
++	 * POOL label must always be in first sector
++	 */
++	if (sector)
++		return 0;
++
++	pool_label_in(&pd, buf);
++
++	/* can ignore 8 rightmost bits for ondisk format check */
++	if ((pd.pl_magic == POOL_MAGIC) &&
++	    (pd.pl_version >> 8 == POOL_VERSION >> 8))
++		return 1;
++
++	return 0;
++}
++
++static int _pool_write(struct label *label __attribute__((unused)), void *buf __attribute__((unused)))
++{
++	_pool_not_supported("write");
++	return 0;
++}
++
++static int _pool_read(struct labeller *l, struct device *dev, void *buf,
++		 struct label **label)
++{
++	struct pool_list pl;
++
++	return read_pool_label(&pl, l, dev, buf, label);
++}
++
++static int _pool_initialise_label(struct labeller *l __attribute__((unused)), struct label *label)
++{
++	strcpy(label->type, "POOL");
++
++	return 1;
++}
++
++static void _pool_destroy_label(struct labeller *l __attribute__((unused)), struct label *label __attribute__((unused)))
++{
++}
++
++static void _label_pool_destroy(struct labeller *l)
++{
++	dm_free(l);
++}
++
++struct label_ops _pool_ops = {
++      .can_handle = _pool_can_handle,
++      .write = _pool_write,
++      .read = _pool_read,
++      .initialise_label = _pool_initialise_label,
++      .destroy_label = _pool_destroy_label,
++      .destroy = _label_pool_destroy,
++};
++
++struct labeller *pool_labeller_create(struct format_type *fmt)
++{
++	struct labeller *l;
++
++	if (!(l = dm_malloc(sizeof(*l)))) {
++		log_error("Couldn't allocate labeller object.");
++		return NULL;
++	}
++
++	l->ops = &_pool_ops;
++	l->fmt = fmt;
++
++	return l;
++}
+diff --git a/lib/format_pool/pool_label.h b/lib/format_pool/pool_label.h
+new file mode 100644
+index 0000000..1a529a4
+--- /dev/null
++++ b/lib/format_pool/pool_label.h
+@@ -0,0 +1,23 @@
++/*
++ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.  
++ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef _LVM_POOL_LABEL_H
++#define _LVM_POOL_LABEL_H
++
++#include "metadata.h"
++
++struct labeller *pool_labeller_create(struct format_type *fmt);
++
++#endif
+diff --git a/lib/format_pool/sptype_names.h b/lib/format_pool/sptype_names.h
+new file mode 100644
+index 0000000..5812adb
+--- /dev/null
++++ b/lib/format_pool/sptype_names.h
+@@ -0,0 +1,42 @@
++/*
++ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.  
++ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
++ *
++ * This file is part of LVM2.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU Lesser General Public License v.2.1.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef SPTYPE_NAMES_H
++#define SPTYPE_NAMES_H
++
++/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
++
++/*  Generic Labels  */
++#define SPTYPE_DATA                (0x00000000)
++
++/*  GFS specific labels  */
++#define SPTYPE_GFS_DATA            (0x68011670)
++#define SPTYPE_GFS_JOURNAL         (0x69011670)
++
++struct sptype_name {
++	const char *name;
++	uint32_t label;
++};
++
++static const struct sptype_name sptype_names[] = {
++	{"data",	SPTYPE_DATA},
++
++	{"gfs_data",	SPTYPE_GFS_DATA},
++	{"gfs_journal",	SPTYPE_GFS_JOURNAL},
++
++	{"", 0x0}		/*  This must be the last flag.  */
++};
++
++#endif
+diff --git a/lib/format_text/export.c b/lib/format_text/export.c
+index 7866d56..e535237 100644
+--- a/lib/format_text/export.c
++++ b/lib/format_text/export.c
+@@ -467,6 +467,8 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
+  
+ 	if (vg->system_id && *vg->system_id)
+ 		outf(f, "system_id = \"%s\"", vg->system_id);
++	else if (vg->lvm1_system_id && *vg->lvm1_system_id)
++		outf(f, "system_id = \"%s\"", vg->lvm1_system_id);
+ 
+ 	if (vg->lock_type) {
+ 		outf(f, "lock_type = \"%s\"", vg->lock_type);
+diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
+index f39051c..4d0f6d5 100644
+--- a/lib/format_text/format-text.c
++++ b/lib/format_text/format-text.c
+@@ -2568,9 +2568,9 @@ struct format_type *create_text_format(struct cmd_context *cmd)
+ 	fmt->name = FMT_TEXT_NAME;
+ 	fmt->alias = FMT_TEXT_ALIAS;
+ 	fmt->orphan_vg_name = ORPHAN_VG_NAME(FMT_TEXT_NAME);
+-	fmt->features = FMT_SEGMENTS | FMT_TAGS | FMT_PRECOMMIT |
++	fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_PRECOMMIT |
+ 			FMT_UNLIMITED_VOLS | FMT_RESIZE_PV |
+-			FMT_UNLIMITED_STRIPESIZE | FMT_CONFIG_PROFILE |
++			FMT_UNLIMITED_STRIPESIZE | FMT_BAS | FMT_CONFIG_PROFILE |
+ 			FMT_NON_POWER2_EXTENTS | FMT_PV_FLAGS;
+ 
+ 	if (!(mda_lists = dm_malloc(sizeof(struct mda_lists)))) {
+diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
+index 58f517e..e038a27 100644
+--- a/lib/format_text/import_vsn1.c
++++ b/lib/format_text/import_vsn1.c
+@@ -1084,8 +1084,15 @@ static struct volume_group *_read_vg(struct format_instance *fid,
+ 		goto bad;
+ 	}
+ 
++	/*
++	 * A system id without WRITE_LOCKED is an old lvm1 system id.
++	 */
+ 	if (dm_config_get_str(vgn, "system_id", &system_id)) {
+-		if (!(vg->system_id = dm_pool_strdup(vg->vgmem, system_id))) {
++		if (!(vgstatus & LVM_WRITE_LOCKED)) {
++			if (!(vg->lvm1_system_id = dm_pool_zalloc(vg->vgmem, NAME_LEN + 1)))
++				goto_bad;
++			strncpy(vg->lvm1_system_id, system_id, NAME_LEN);
++		} else if (!(vg->system_id = dm_pool_strdup(vg->vgmem, system_id))) {
+ 			log_error("Failed to allocate memory for system_id in _read_vg.");
+ 			goto bad;
+ 		}
+diff --git a/lib/locking/locking.c b/lib/locking/locking.c
+index 2584227..2b53553 100644
+--- a/lib/locking/locking.c
++++ b/lib/locking/locking.c
+@@ -221,6 +221,42 @@ void fin_locking(void)
+ }
+ 
+ /*
++ * Does the LVM1 driver know of this VG name?
++ */
++int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
++{
++	struct stat info;
++	char path[PATH_MAX];
++
++	/* We'll allow operations on orphans */
++	if (!is_real_vg(vgname))
++		return 1;
++
++	/* LVM1 is only present in 2.4 kernels. */
++	if (strncmp(cmd->kernel_vsn, "2.4.", 4))
++		return 1;
++
++	if (dm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir,
++			 vgname) < 0) {
++		log_error("LVM1 proc VG pathname too long for %s", vgname);
++		return 0;
++	}
++
++	if (stat(path, &info) == 0) {
++		log_error("%s exists: Is the original LVM driver using "
++			  "this volume group?", path);
++		return 0;
++	}
++
++	if (errno != ENOENT && errno != ENOTDIR) {
++		log_sys_error("stat", path);
++		return 0;
++	}
++
++	return 1;
++}
++
++/*
+  * VG locking is by VG name.
+  * FIXME This should become VG uuid.
+  */
+@@ -332,6 +368,10 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str
+ 			lvmcache_drop_metadata(vol, 0);
+ 		}
+ 
++		/* Lock VG to change on-disk metadata. */
++		/* If LVM1 driver knows about the VG, it can't be accessed. */
++		if (!check_lvm1_vg_inactive(cmd, vol))
++			return_0;
+ 		break;
+ 	case LCK_LV:
+ 		/* All LV locks are non-blocking. */
+diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
+index 76451ea..9af90f9 100644
+--- a/lib/metadata/lv_manip.c
++++ b/lib/metadata/lv_manip.c
+@@ -6011,6 +6011,8 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
+ 		     force_t force, int suppress_remove_message)
+ {
+ 	struct volume_group *vg;
++	struct logical_volume *format1_origin = NULL;
++	int format1_reload_required = 0;
+ 	int visible, historical;
+ 	struct logical_volume *pool_lv = NULL;
+ 	struct logical_volume *lock_lv = lv;
+@@ -6163,6 +6165,10 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
+ 		}
+ 
+ 	if (lv_is_cow(lv)) {
++		/* Old format1 code */
++		if (!(lv->vg->fid->fmt->features & FMT_MDAS))
++			format1_origin = origin_from_cow(lv);
++
+ 		log_verbose("Removing snapshot volume %s.", display_lvname(lv));
+ 		/* vg_remove_snapshot() will preload origin/former snapshots */
+ 		if (!vg_remove_snapshot(lv))
+@@ -6218,10 +6224,30 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
+ 		}
+ 	}
+ 
++	/*
++	 * Old format1 code: If no snapshots left reload without -real.
++	 */
++	if (format1_origin && !lv_is_origin(format1_origin)) {
++		log_warn("WARNING: Support for snapshots with old LVM1-style metadata is deprecated.");
++		log_warn("WARNING: Please use lvconvert to update to lvm2 metadata at your convenience.");
++		format1_reload_required = 1;
++	}
++
+ 	/* store it on disks */
+ 	if (!vg_write(vg) || !vg_commit(vg))
+ 		return_0;
+ 
++	/* format1 */
++	if (format1_reload_required) {
++		if (!suspend_lv(cmd, format1_origin))
++			log_error("Failed to refresh %s without snapshot.", format1_origin->name);
++
++		if (!resume_lv(cmd, format1_origin)) {
++			log_error("Failed to resume %s.", format1_origin->name);
++			return 0;
++		}
++	}
++
+ 	/* Release unneeded blocks in thin pool */
+ 	/* TODO: defer when multiple LVs relased at once */
+ 	if (pool_lv && !update_pool_lv(pool_lv, 1)) {
+diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
+index 75caba1..2245c29 100644
+--- a/lib/metadata/metadata-exported.h
++++ b/lib/metadata/metadata-exported.h
+@@ -149,7 +149,7 @@
+ 
+ /* Format features flags */
+ #define FMT_SEGMENTS		0x00000001U	/* Arbitrary segment params? */
+-// #define FMT_MDAS		0x00000002U	/* Proper metadata areas? */
++#define FMT_MDAS		0x00000002U	/* Proper metadata areas? */
+ #define FMT_TAGS		0x00000004U	/* Tagging? */
+ #define FMT_UNLIMITED_VOLS	0x00000008U	/* Unlimited PVs/LVs? */
+ #define FMT_RESTRICTED_LVIDS	0x00000010U	/* LVID <= 255 */
+@@ -158,13 +158,15 @@
+ #define FMT_RESIZE_PV		0x00000080U	/* Supports pvresize? */
+ #define FMT_UNLIMITED_STRIPESIZE 0x00000100U	/* Unlimited stripe size? */
+ #define FMT_RESTRICTED_READAHEAD 0x00000200U	/* Readahead restricted to 2-120? */
+-// #define FMT_BAS			0x000000400U	/* Supports bootloader areas? */
++#define FMT_BAS			0x000000400U	/* Supports bootloader areas? */
+ #define FMT_CONFIG_PROFILE	0x000000800U	/* Supports configuration profiles? */
+-// #define FMT_OBSOLETE		0x000001000U	/* Obsolete format? */
++#define FMT_OBSOLETE		0x000001000U	/* Obsolete format? */
+ #define FMT_NON_POWER2_EXTENTS	0x000002000U	/* Non-power-of-2 extent sizes? */
+-// #define FMT_SYSTEMID_ON_PVS	0x000004000U	/* System ID is stored on PVs not VG */
++#define FMT_SYSTEMID_ON_PVS	0x000004000U	/* System ID is stored on PVs not VG */
+ #define FMT_PV_FLAGS		0x000008000U	/* Supports PV flags */
+ 
++#define systemid_on_pvs(vg)	((vg)->fid->fmt->features & FMT_SYSTEMID_ON_PVS)
++
+ /* Mirror conversion type flags */
+ #define MIRROR_BY_SEG		0x00000001U	/* segment-by-segment mirror */
+ #define MIRROR_BY_LV		0x00000002U	/* mirror using whole mimage LVs */
+diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
+index cb38f66..3620240 100644
+--- a/lib/metadata/metadata.c
++++ b/lib/metadata/metadata.c
+@@ -1011,6 +1011,8 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
+ 
+ 	vg->status = (RESIZEABLE_VG | LVM_READ | LVM_WRITE);
+ 	vg->system_id = NULL;
++	if (!(vg->lvm1_system_id = dm_pool_zalloc(vg->vgmem, NAME_LEN + 1)))
++		goto_bad;
+ 
+ 	vg->extent_size = DEFAULT_EXTENT_SIZE * 2;
+ 	vg->max_lv = DEFAULT_MAX_LV;
+@@ -2969,7 +2971,7 @@ int vg_write(struct volume_group *vg)
+ 		return 0;
+ 	}
+ 
+-	if (!_vg_adjust_ignored_mdas(vg))
++	if ((vg->fid->fmt->features & FMT_MDAS) && !_vg_adjust_ignored_mdas(vg))
+ 		return_0;
+ 
+ 	if (!vg_mda_used_count(vg)) {
+@@ -5373,6 +5375,15 @@ int is_system_id_allowed(struct cmd_context *cmd, const char *system_id)
+ static int _access_vg_systemid(struct cmd_context *cmd, struct volume_group *vg)
+ {
+ 	/*
++	 * LVM1 VGs must not be accessed if a new-style LVM2 system ID is set.
++	 */
++	if (cmd->system_id && systemid_on_pvs(vg)) {
++		log_error("Cannot access VG %s with LVM1 system ID %s when host system ID is set.",
++			  vg->name, vg->lvm1_system_id);
++		return 0;
++	}
++
++	/*
+ 	 * A few commands allow read-only access to foreign VGs.
+ 	 */
+ 	if (cmd->include_foreign_vgs)
+@@ -5424,6 +5435,11 @@ static int _vg_access_permitted(struct cmd_context *cmd, struct volume_group *vg
+ 				uint32_t lockd_state, uint32_t *failure)
+ {
+ 	if (!is_real_vg(vg->name)) {
++		/* Disallow use of LVM1 orphans when a host system ID is set. */
++		if (cmd->system_id && *cmd->system_id && systemid_on_pvs(vg)) {
++			*failure |= FAILED_SYSTEMID;
++			return_0;
++		}
+ 		return 1;
+ 	}
+ 
+diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
+index 9c05836..309a246 100644
+--- a/lib/metadata/segtype.h
++++ b/lib/metadata/segtype.h
+@@ -32,7 +32,7 @@ struct dev_manager;
+ #define SEG_AREAS_STRIPED	(1ULL <<  1)
+ #define SEG_AREAS_MIRRORED	(1ULL <<  2)
+ #define SEG_SNAPSHOT		(1ULL <<  3)
+-/* #define SEG_FORMAT1_SUPPORT	(1ULL <<  4) */
++#define SEG_FORMAT1_SUPPORT	(1ULL <<  4)
+ #define SEG_VIRTUAL		(1ULL <<  5)
+ #define SEG_CANNOT_BE_ZEROED	(1ULL <<  6)
+ #define SEG_MONITORED		(1ULL <<  7)
+diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c
+index aeb739c..156b4c8 100644
+--- a/lib/metadata/snapshot_manip.c
++++ b/lib/metadata/snapshot_manip.c
+@@ -337,6 +337,17 @@ int vg_remove_snapshot(struct logical_volume *cow)
+ 	cow->snapshot = NULL;
+ 	lv_set_visible(cow);
+ 
++	/* format1 must do the change in one step, with the commit last. */
++	if (!(origin->vg->fid->fmt->features & FMT_MDAS)) {
++		/* Get the lock for COW volume */
++		if (is_origin_active && !activate_lv(cow->vg->cmd, cow)) {
++			log_error("Unable to activate logical volume \"%s\"",
++				  cow->name);
++			return 0;
++		}
++		return 1;
++	}
++
+ 	if (!vg_write(origin->vg))
+ 		return_0;
+ 
+diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c
+index 42801b9..8585013 100644
+--- a/lib/metadata/vg.c
++++ b/lib/metadata/vg.c
+@@ -41,6 +41,12 @@ struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
+ 		return NULL;
+ 	}
+ 
++	if (!(vg->lvm1_system_id = dm_pool_zalloc(vgmem, NAME_LEN + 1))) {
++		log_error("Failed to allocate VG systemd id.");
++		dm_pool_destroy(vgmem);
++		return NULL;
++	}
++
+ 	vg->system_id = "";
+ 
+ 	vg->cmd = cmd;
+@@ -171,7 +177,7 @@ char *vg_name_dup(const struct volume_group *vg)
+ 
+ char *vg_system_id_dup(const struct volume_group *vg)
+ {
+-	return dm_pool_strdup(vg->vgmem, vg->system_id ? : "");
++	return dm_pool_strdup(vg->vgmem, vg->system_id ? : vg->lvm1_system_id ? : "");
+ }
+ 
+ char *vg_lock_type_dup(const struct volume_group *vg)
+@@ -670,11 +676,20 @@ int vg_set_system_id(struct volume_group *vg, const char *system_id)
+ 		return 1;
+ 	}
+ 
++	if (systemid_on_pvs(vg)) {
++		log_error("Metadata format %s does not support this type of system ID.",
++			  vg->fid->fmt->name);
++		return 0;
++	}
++
+ 	if (!(vg->system_id = dm_pool_strdup(vg->vgmem, system_id))) {
+ 		log_error("Failed to allocate memory for system_id in vg_set_system_id.");
+ 		return 0;
+ 	}
+ 
++	if (vg->lvm1_system_id)
++		*vg->lvm1_system_id = '\0';
++
+ 	return 1;
+ }
+ 
+diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h
+index 7ecfafe..29d88f8 100644
+--- a/lib/metadata/vg.h
++++ b/lib/metadata/vg.h
+@@ -70,6 +70,7 @@ struct volume_group {
+ 	const char *name;
+ 	const char *old_name;		/* Set during vgrename and vgcfgrestore */
+ 	const char *system_id;
++	char *lvm1_system_id;
+ 	const char *lock_type;
+ 	const char *lock_args;
+ 
+diff --git a/lib/report/report.c b/lib/report/report.c
+index 19f0f5c..8905d26 100644
+--- a/lib/report/report.c
++++ b/lib/report/report.c
+@@ -2845,7 +2845,7 @@ static int _vgsystemid_disp(struct dm_report *rh, struct dm_pool *mem,
+ 			    const void *data, void *private)
+ {
+ 	const struct volume_group *vg = (const struct volume_group *) data;
+-	const char *repstr = (vg->system_id && *vg->system_id) ? vg->system_id : "";
++	const char *repstr = (vg->system_id && *vg->system_id) ? vg->system_id : vg->lvm1_system_id ? : "";
+ 
+ 	return _field_string(rh, field, repstr);
+ }
+@@ -3830,6 +3830,7 @@ static struct volume_group _dummy_vg = {
+ 	.fid = &_dummy_fid,
+ 	.name = "",
+ 	.system_id = (char *) "",
++	.lvm1_system_id = (char *) "",
+ 	.pvs = DM_LIST_HEAD_INIT(_dummy_vg.pvs),
+ 	.lvs = DM_LIST_HEAD_INIT(_dummy_vg.lvs),
+ 	.historical_lvs = DM_LIST_HEAD_INIT(_dummy_vg.historical_lvs),
+@@ -3840,6 +3841,7 @@ static struct volume_group _unknown_vg = {
+ 	.fid = &_dummy_fid,
+ 	.name = "[unknown]",
+ 	.system_id = (char *) "",
++	.lvm1_system_id = (char *) "",
+ 	.pvs = DM_LIST_HEAD_INIT(_unknown_vg.pvs),
+ 	.lvs = DM_LIST_HEAD_INIT(_unknown_vg.lvs),
+ 	.historical_lvs = DM_LIST_HEAD_INIT(_unknown_vg.historical_lvs),
+diff --git a/lib/striped/striped.c b/lib/striped/striped.c
+index 498b202..a2eaf80 100644
+--- a/lib/striped/striped.c
++++ b/lib/striped/striped.c
+@@ -239,7 +239,8 @@ static struct segment_type *_init_segtype(struct cmd_context *cmd, const char *n
+ 
+ 	segtype->ops = &_striped_ops;
+ 	segtype->name = name;
+-	segtype->flags = target | SEG_CAN_SPLIT | SEG_AREAS_STRIPED;
++	segtype->flags = target | SEG_CAN_SPLIT | SEG_AREAS_STRIPED |
++	    SEG_FORMAT1_SUPPORT;
+ 
+ 	log_very_verbose("Initialised segtype: %s", segtype->name);
+ 	return segtype;
+diff --git a/man/vgconvert.8_des b/man/vgconvert.8_des
+index 8519063..a0d34fd 100644
+--- a/man/vgconvert.8_des
++++ b/man/vgconvert.8_des
+@@ -1,3 +1,6 @@
+-vgconvert converts VG metadata from one format to another.  This command
+-is no longer used because this version of lvm no longer supports the LVM1
++vgconvert converts VG metadata from one format to another.  The new
++metadata format must be able to fit into the space provided by the old
+ format.
++
++Because the LVM1 format should no longer be used, this command is no
++longer needed in general.
+diff --git a/test/shell/format-lvm1.sh b/test/shell/format-lvm1.sh
+new file mode 100644
+index 0000000..b88579f
+--- /dev/null
++++ b/test/shell/format-lvm1.sh
+@@ -0,0 +1,38 @@
++#!/usr/bin/env bash
++
++# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions
++# of the GNU General Public License v.2.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software Foundation,
++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++
++test_description='Test lvm1 format'
++
++SKIP_WITH_LVMPOLLD=1
++
++. lib/inittest
++
++aux prepare_devs 1
++
++if test -n "$LVM_TEST_LVM1" ; then
++pvcreate -M1 "$dev1"
++vgcreate -M1 $vg "$dev1"
++check vg_field $vg fmt "lvm1"
++fi
++
++# TODO: if we decide to make using lvm1 with lvmetad an error,
++# then if lvmetad is being used, then verify:
++# not pvcreate -M1 "$dev1"
++# not vgcreate -M1 $vg "$dev1"
++#
++# TODO: if we decide to allow using lvm1 with lvmetad, but disable lvmetad
++# when it happens, then verify:
++# pvcreate -M1 "$dev1" | tee err
++# grep "disabled" err
++# vgcreate -M1 $vg "$dev1" | tee err
++# grep "disabled" err
++
+diff --git a/test/shell/lvm1-basic.sh b/test/shell/lvm1-basic.sh
+new file mode 100644
+index 0000000..93509c4
+--- /dev/null
++++ b/test/shell/lvm1-basic.sh
+@@ -0,0 +1,36 @@
++#!/usr/bin/env bash
++
++# Copyright (C) 2012 Red Hat, Inc. All rights reserved.
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions
++# of the GNU General Public License v.2.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software Foundation,
++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++
++SKIP_WITH_LVMLOCKD=1
++SKIP_WITHOUT_LVMETAD=1
++SKIP_WITH_LVMPOLLD=1
++
++. lib/inittest
++
++aux prepare_devs 2
++pvcreate --metadatatype 1 "$dev1"
++pvs | tee out
++grep "$dev1" out
++vgcreate --metadatatype 1 $vg1 "$dev1"
++vgs | tee out
++grep $vg1 out
++pvs | tee out
++grep "$dev1" out
++
++# check for RHBZ 1080189 -- SEGV in lvremove/vgremove
++pvcreate -ff -y --metadatatype 1 "$dev1" "$dev2"
++vgcreate --metadatatype 1 $vg1 "$dev1" "$dev2"
++lvcreate -l1 $vg1 "$dev1"
++pvremove -ff -y "$dev2"
++vgchange -an $vg1
++not lvremove $vg1
++not vgremove -ff -y $vg1
+diff --git a/test/shell/snapshot-lvm1.sh b/test/shell/snapshot-lvm1.sh
+new file mode 100644
+index 0000000..75c97cb
+--- /dev/null
++++ b/test/shell/snapshot-lvm1.sh
+@@ -0,0 +1,35 @@
++#!/usr/bin/env bash
++
++# Copyright (C) 2013 Red Hat, Inc. All rights reserved.
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions
++# of the GNU General Public License v.2.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software Foundation,
++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++
++# regression test for lvmetad reporting error:
++# Internal error: LV snap_with_lvm1_meta (00000000000000000000000000000001) missing from preload metadata
++
++SKIP_WITH_LVMLOCKD=1
++SKIP_WITH_LVMPOLLD=1
++
++. lib/inittest
++
++aux prepare_devs 2
++get_devs
++
++vgcreate --metadatatype 1 "$vg" "${DEVICES[@]}"
++
++# Make origin volume
++lvcreate -ae -l5 $vg -n origin
++
++# Create a snap of origin
++lvcreate -s $vg/origin -n snap_with_lvm1_meta -l4
++
++# Remove volume snapper/snap_with_lvm1_meta
++lvremove -f $vg/snap_with_lvm1_meta
++
++vgremove -ff $vg
+diff --git a/tools/args.h b/tools/args.h
+index c2fbac6..abe193c 100644
+--- a/tools/args.h
++++ b/tools/args.h
+@@ -1211,7 +1211,8 @@ arg(mirrors_ARG, 'm', "mirrors", number_VAL, 0, 0,
+ arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_VAL, 0, 0,
+     "Specifies the type of on-disk metadata to use.\n"
+     "\\fBlvm2\\fP (or just \\fB2\\fP) is the current, standard format.\n"
+-    "\\fBlvm1\\fP (or just \\fB1\\fP) is no longer used.\n")
++    "\\fBlvm1\\fP (or just \\fB1\\fP) is a historical format that\n"
++    "can be used for accessing old data.\n")
+ 
+ arg(name_ARG, 'n', "name", string_VAL, 0, 0,
+     "#lvcreate\n"
+diff --git a/tools/lvconvert.c b/tools/lvconvert.c
+index 8a07a84..e66f063 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -1816,6 +1816,11 @@ static int _lvconvert_splitsnapshot(struct cmd_context *cmd, struct logical_volu
+ 		return 0;
+ 	}
+ 
++	if (!(vg->fid->fmt->features & FMT_MDAS)) {
++		log_error("Unable to split off snapshot %s using old LVM1-style metadata.", cow_name);
++		return 0;
++	}
++
+ 	if (is_lockd_type(vg->lock_type)) {
+ 		/* FIXME: we need to create a lock for the new LV. */
+ 		log_error("Unable to split snapshots in VG with lock_type %s.", vg->lock_type);
+diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
+index 0840c65..f238b64 100644
+--- a/tools/lvmcmdline.c
++++ b/tools/lvmcmdline.c
+@@ -19,9 +19,11 @@
+ #include "label.h"
+ #include "lvm-version.h"
+ #include "lvmlockd.h"
++#include "lvmetad-client.h"
+ 
+ #include "stub.h"
+ #include "last-path-component.h"
++#include "format1.h"
+ 
+ #include <signal.h>
+ #include <sys/stat.h>
+@@ -2912,6 +2914,13 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
+ 		goto out;
+ 	}
+ 
++	if (!strcmp(cmd->fmt->name, FMT_LVM1_NAME) && lvmetad_used()) {
++		log_warn("WARNING: Disabling lvmetad cache which does not support obsolete metadata.");
++		lvmetad_set_disabled(cmd, LVMETAD_DISABLE_REASON_LVM1);
++		log_warn("WARNING: Not using lvmetad because lvm1 format is used.");
++		lvmetad_make_unused(cmd);
++	}
++
+ 	if (cmd->command->command_enum == lvconvert_repair_CMD) {
+ 		log_warn("WARNING: Not using lvmetad because of repair.");
+ 		lvmetad_make_unused(cmd);
+@@ -2974,7 +2983,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
+ 	 *   by different token values.)
+ 	 *
+ 	 * lvmetad may have been previously disabled (or disabled during the
+-	 * rescan done here) because duplicate devices were seen.
++	 * rescan done here) because duplicate devices or lvm1 metadata were seen.
+ 	 * In this case, disable the *use* of lvmetad by this command, reverting to
+ 	 * disk scanning.
+ 	 */
+@@ -3399,6 +3408,41 @@ static int _run_script(struct cmd_context *cmd, int argc, char **argv)
+ 	return ret;
+ }
+ 
++/*
++ * Determine whether we should fall back and exec the equivalent LVM1 tool
++ */
++static int _lvm1_fallback(struct cmd_context *cmd)
++{
++	char vsn[80];
++	int dm_present;
++
++	if (!find_config_tree_bool(cmd, global_fallback_to_lvm1_CFG, NULL) ||
++	    strncmp(cmd->kernel_vsn, "2.4.", 4))
++		return 0;
++
++	log_suppress(1);
++	dm_present = driver_version(vsn, sizeof(vsn));
++	log_suppress(0);
++
++	if (dm_present || !lvm1_present(cmd))
++		return 0;
++
++	return 1;
++}
++
++static void _exec_lvm1_command(char **argv)
++{
++	char path[PATH_MAX];
++
++	if (dm_snprintf(path, sizeof(path), "%s.lvm1", argv[0]) < 0) {
++		log_error("Failed to create LVM1 tool pathname");
++		return;
++	}
++
++	execvp(path, argv);
++	log_sys_error("execvp", path);
++}
++
+ static void _nonroot_warning(void)
+ {
+ 	if (getuid() || geteuid())
+@@ -3488,6 +3532,19 @@ int lvm2_main(int argc, char **argv)
+ 	} else
+ 		run_name = dm_basename(argv[0]);
+ 
++	if (_lvm1_fallback(cmd)) {
++		/* Attempt to run equivalent LVM1 tool instead */
++		if (!argc) {
++			log_error("Falling back to LVM1 tools, but no "
++				  "command specified.");
++			ret = ECMD_FAILED;
++			goto out;
++		}
++		_exec_lvm1_command(argv);
++		ret = ECMD_FAILED;
++		goto_out;
++	}
++
+ 	/*
+ 	 * Decide if we are running a shell or a command or a script.  When
+ 	 * there is no run_name, it's a shell, when run_name is a recognized
+diff --git a/tools/pvscan.c b/tools/pvscan.c
+index c21845c..e5afe0c 100644
+--- a/tools/pvscan.c
++++ b/tools/pvscan.c
+@@ -748,7 +748,7 @@ out:
+  * display the PV info.
+  *
+  * iii. If lvmetad is being used, but has been disabled (because of
+- * duplicate devs), or has a non-matching token
++ * duplicate devs or lvm1 metadata), or has a non-matching token
+  * (because the device filter is different from the device filter last
+  * used to populate lvmetad), then 'pvscan' will begin by rescanning
+  * devices to repopulate lvmetad.  If lvmetad is enabled after the
+@@ -761,7 +761,8 @@ out:
+  * attempt to repopulate the lvmetad cache by rescanning all devs
+  * (regardless of whether lvmetad was previously disabled or had an
+  * unmatching token.)  lvmetad may be enabled or disabled after the
+- * rescan (depending on whether duplicate devs).
++ * rescan (depending on whether duplicate devs or lvm1 metadata was
++ * found).
+  *
+  * 3. The 'pvscan --cache <dev>' command will attempt to repopulate the
+  * lvmetad cache by rescanning all devs if lvmetad has a non-matching
+diff --git a/tools/stub.h b/tools/stub.h
+index 1d58387..f03e5d3 100644
+--- a/tools/stub.h
++++ b/tools/stub.h
+@@ -37,6 +37,7 @@ int pvdata(struct cmd_context *cmd __attribute__((unused)),
+ {
+ 	log_error("There's no 'pvdata' command in LVM2.");
+ 	log_error("Use lvs, pvs, vgs instead; or use vgcfgbackup and read the text file backup.");
++	log_error("Metadata in LVM1 format can still be displayed using LVM1's pvdata command.");
+ 	return ECMD_FAILED;
+ }
+ 
+diff --git a/tools/toollib.c b/tools/toollib.c
+index 1b01ccc..81953ee 100644
+--- a/tools/toollib.c
++++ b/tools/toollib.c
+@@ -14,6 +14,7 @@
+  */
+ 
+ #include "tools.h"
++#include "format1.h"
+ #include "format-text.h"
+ 
+ #include <sys/stat.h>
+@@ -4168,6 +4169,7 @@ static int _process_duplicate_pvs(struct cmd_context *cmd,
+ 		.fid = &dummy_fid,
+ 		.name = "",
+ 		.system_id = (char *) "",
++		.lvm1_system_id = (char *) "",
+ 		.pvs = DM_LIST_HEAD_INIT(dummy_vg.pvs),
+ 		.lvs = DM_LIST_HEAD_INIT(dummy_vg.lvs),
+ 		.historical_lvs = DM_LIST_HEAD_INIT(dummy_vg.historical_lvs),
+@@ -4805,6 +4807,23 @@ int pvcreate_params_from_args(struct cmd_context *cmd, struct pvcreate_params *p
+ 	pp->pva.label_sector = arg_int64_value(cmd, labelsector_ARG,
+ 					       DEFAULT_LABELSECTOR);
+ 
++	if (!(cmd->fmt->features & FMT_MDAS) &&
++	    (arg_is_set(cmd, pvmetadatacopies_ARG) ||
++	     arg_is_set(cmd, metadatasize_ARG)   ||
++	     arg_is_set(cmd, dataalignment_ARG)  ||
++	     arg_is_set(cmd, dataalignmentoffset_ARG))) {
++		log_error("Metadata and data alignment parameters only "
++			  "apply to text format.");
++		return 0;
++	}
++
++	if (!(cmd->fmt->features & FMT_BAS) &&
++	    arg_is_set(cmd, bootloaderareasize_ARG)) {
++		log_error("Bootloader area parameters only "
++			  "apply to text format.");
++		return 0;
++	}
++
+ 	if (arg_is_set(cmd, metadataignore_ARG))
+ 		pp->pva.metadataignore = arg_int_value(cmd, metadataignore_ARG,
+ 						   DEFAULT_PVMETADATAIGNORE);
+@@ -5164,7 +5183,10 @@ static int _pvcreate_check_single(struct cmd_context *cmd,
+ 			pd->is_orphan_pv = 1;
+ 		}
+ 
+-		pp->orphan_vg_name = FMT_TEXT_ORPHAN_VG_NAME;
++		if (!strcmp(vg->name, FMT_LVM1_ORPHAN_VG_NAME))
++			pp->orphan_vg_name = FMT_LVM1_ORPHAN_VG_NAME;
++		else
++			pp->orphan_vg_name = FMT_TEXT_ORPHAN_VG_NAME;
+ 	} else {
+ 		log_debug("Found pvcreate arg %s: device is not a PV.", pd->name);
+ 		/* Device is not a PV. */
+@@ -5393,7 +5415,10 @@ static int _pvremove_check_single(struct cmd_context *cmd,
+ 			pd->is_orphan_pv = 1;
+ 		}
+ 
+-		pp->orphan_vg_name = FMT_TEXT_ORPHAN_VG_NAME;
++		if (!strcmp(vg->name, FMT_LVM1_ORPHAN_VG_NAME))
++			pp->orphan_vg_name = FMT_LVM1_ORPHAN_VG_NAME;
++		else
++			pp->orphan_vg_name = FMT_TEXT_ORPHAN_VG_NAME;
+ 	} else {
+ 		/* FIXME: is it possible to reach here? */
+ 		log_debug("Found pvremove arg %s: device is not a PV.", pd->name);
+diff --git a/tools/vals.h b/tools/vals.h
+index 79c48b5..95dc8b2 100644
+--- a/tools/vals.h
++++ b/tools/vals.h
+@@ -77,7 +77,7 @@
+  *
+  * FIXME: are there some specialized or irrelevant
+  * options included in the usage text below that should
+- * be removed?
++ * be removed?  Should "lvm1" be removed?
+  *
+  * Size is a Number that takes an optional unit.
+  * A full usage could be "Size[b|B|s|S|k|K|m|M|g|G|t|T|p|P|e|E]"
+@@ -126,7 +126,7 @@ val(sextents_VAL, sextents_arg, "SExtents", "[+|-]Number[PERCENT]")
+ val(pextents_VAL, pextents_arg, "PExtents", "[+]Number[PERCENT]")
+ val(nextents_VAL, nextents_arg, "NExtents", "[-]Number[PERCENT]")
+ val(permission_VAL, permission_arg, "Permission", "rw|r")
+-val(metadatatype_VAL, metadatatype_arg, "MetadataType", "lvm2")
++val(metadatatype_VAL, metadatatype_arg, "MetadataType", "lvm2|lvm1")
+ val(units_VAL, string_arg, "Units", "r|R|h|H|b|B|s|S|k|K|m|M|g|G|t|T|p|P|e|E")
+ val(segtype_VAL, segtype_arg, "SegType", "linear|striped|snapshot|mirror|raid|thin|cache|thin-pool|cache-pool")
+ val(alloc_VAL, alloc_arg, "Alloc", "contiguous|cling|cling_by_tags|normal|anywhere|inherit")
+diff --git a/tools/vgchange.c b/tools/vgchange.c
+index 52abc11..1736faf 100644
+--- a/tools/vgchange.c
++++ b/tools/vgchange.c
+@@ -558,6 +558,13 @@ static int _vgchange_system_id(struct cmd_context *cmd, struct volume_group *vg)
+ 	const char *system_id;
+ 	const char *system_id_arg_str = arg_str_value(cmd, systemid_ARG, NULL);
+ 
++	/* FIXME Merge with vg_set_system_id() */
++	if (systemid_on_pvs(vg)) {
++		log_error("Metadata format %s does not support this type of system ID.",
++			  vg->fid->fmt->name);
++		return 0;
++	}
++
+ 	if (!(system_id = system_id_from_string(cmd, system_id_arg_str))) {
+ 		log_error("Unable to set system ID.");
+ 		return 0;
+@@ -607,6 +614,9 @@ static int _vgchange_system_id(struct cmd_context *cmd, struct volume_group *vg)
+ 
+ 	vg->system_id = system_id;
+ 	
++	if (vg->lvm1_system_id)
++		*vg->lvm1_system_id = '\0';
++
+ 	return 1;
+ }
+ 
+diff --git a/tools/vgconvert.c b/tools/vgconvert.c
+index ca9615c..8bdf8be 100644
+--- a/tools/vgconvert.c
++++ b/tools/vgconvert.c
+@@ -34,25 +34,29 @@ static int _vgconvert_single(struct cmd_context *cmd, const char *vg_name,
+ 		return ECMD_FAILED;
+ 	}
+ 
+-	if (arg_sign_value(cmd, metadatasize_ARG, SIGN_NONE) == SIGN_MINUS) {
+-		log_error("Metadata size may not be negative");
+-		return EINVALID_CMD_LINE;
+-	}
+-
+-	pva.pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, UINT64_C(0));
+-	if (!pva.pvmetadatasize)
+-		pva.pvmetadatasize = find_config_tree_int(cmd, metadata_pvmetadatasize_CFG, NULL);
++	if (cmd->fmt->features & FMT_MDAS) {
++		if (arg_sign_value(cmd, metadatasize_ARG, SIGN_NONE) == SIGN_MINUS) {
++			log_error("Metadata size may not be negative");
++			return EINVALID_CMD_LINE;
++		}
+ 
+-	pva.pvmetadatacopies = arg_int_value(cmd, pvmetadatacopies_ARG, -1);
+-	if (pva.pvmetadatacopies < 0)
+-		pva.pvmetadatacopies = find_config_tree_int(cmd, metadata_pvmetadatacopies_CFG, NULL);
++		pva.pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, UINT64_C(0));
++		if (!pva.pvmetadatasize)
++			pva.pvmetadatasize = find_config_tree_int(cmd, metadata_pvmetadatasize_CFG, NULL);
+ 
+-	if (arg_sign_value(cmd, bootloaderareasize_ARG, SIGN_NONE) == SIGN_MINUS) {
+-		log_error("Bootloader area size may not be negative");
+-		return EINVALID_CMD_LINE;
++		pva.pvmetadatacopies = arg_int_value(cmd, pvmetadatacopies_ARG, -1);
++		if (pva.pvmetadatacopies < 0)
++			pva.pvmetadatacopies = find_config_tree_int(cmd, metadata_pvmetadatacopies_CFG, NULL);
+ 	}
+ 
+-	pva.ba_size = arg_uint64_value(cmd, bootloaderareasize_ARG, UINT64_C(0));
++	if (cmd->fmt->features & FMT_BAS) {
++		if (arg_sign_value(cmd, bootloaderareasize_ARG, SIGN_NONE) == SIGN_MINUS) {
++			log_error("Bootloader area size may not be negative");
++			return EINVALID_CMD_LINE;
++		}
++
++		pva.ba_size = arg_uint64_value(cmd, bootloaderareasize_ARG, UINT64_C(0));
++	}
+ 
+ 	if (!vg_check_new_extent_size(cmd->fmt, vg->extent_size))
+ 		return_ECMD_FAILED;
+@@ -82,6 +86,13 @@ static int _vgconvert_single(struct cmd_context *cmd, const char *vg_name,
+ 				return ECMD_FAILED;
+ 			}
+ 
++	/* New-style system ID supported? */ 
++	if (vg->system_id && *vg->system_id && (cmd->fmt->features & FMT_SYSTEMID_ON_PVS)) {
++		log_error("Unable to convert VG %s while it has a system ID set (%s).", vg->name,
++			  vg->system_id);
++		return ECMD_FAILED;
++	}
++
+ 	/* Attempt to change any LVIDs that are too big */
+ 	if (cmd->fmt->features & FMT_RESTRICTED_LVIDS) {
+ 		dm_list_iterate_items(lvl, &vg->lvs) {
+@@ -146,6 +157,18 @@ int vgconvert(struct cmd_context *cmd, int argc, char **argv)
+ 		return EINVALID_CMD_LINE;
+ 	}
+ 
++	if (!(cmd->fmt->features & FMT_MDAS) &&
++	    arg_is_set(cmd, pvmetadatacopies_ARG)) {
++		log_error("Metadata parameters only apply to text format");
++		return EINVALID_CMD_LINE;
++	}
++
++	if (!(cmd->fmt->features & FMT_BAS) &&
++		arg_is_set(cmd, bootloaderareasize_ARG)) {
++		log_error("Bootloader area parameters only apply to text format");
++		return EINVALID_CMD_LINE;
++	}
++
+ 	return process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, 0, NULL,
+ 			       &_vgconvert_single);
+ }
+diff --git a/tools/vgscan.c b/tools/vgscan.c
+index f9fa382..1ec9083 100644
+--- a/tools/vgscan.c
++++ b/tools/vgscan.c
+@@ -44,7 +44,7 @@ static int _vgscan_single(struct cmd_context *cmd, const char *vg_name,
+  * display the VG info.
+  *
+  * iii. If lvmetad is being used, but has been disabled (because of
+- * duplicate devs), or has a non-matching token
++ * duplicate devs or lvm1 metadata), or has a non-matching token
+  * (because the device filter is different from the device filter last
+  * used to populate lvmetad), then 'vgscan' will begin by rescanning
+  * devices to repopulate lvmetad.  If lvmetad is enabled after the
+@@ -57,7 +57,7 @@ static int _vgscan_single(struct cmd_context *cmd, const char *vg_name,
+  * the lvmetad cache by rescanning all devs (regardless of whether
+  * lvmetad was previously disabled or had an unmatching token.)
+  * lvmetad may be enabled or disabled after the rescan (depending
+- * on whether duplicate devs were found).
++ * on whether duplicate devs or lvm1 metadata was found).
+  * If enabled, then it will simply read and display VG info from the
+  * lvmetad cache (like case 1.i.).  If disabled, then it will
+  * read all devices to display VG info (like case 1.ii.)
diff --git a/SOURCES/lvm2-rhel7.patch b/SOURCES/lvm2-rhel7.patch
new file mode 100644
index 0000000..b7df03d
--- /dev/null
+++ b/SOURCES/lvm2-rhel7.patch
@@ -0,0 +1,18 @@
+ VERSION    | 2 +-
+ VERSION_DM | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/VERSION b/VERSION
+index 7f0e456..0c3bfac 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-2.02.186(2) (2019-08-27)
++2.02.186(2)-RHEL7 (2019-08-27)
+diff --git a/VERSION_DM b/VERSION_DM
+index 864ceb8..5093e13 100644
+--- a/VERSION_DM
++++ b/VERSION_DM
+@@ -1 +1 @@
+-1.02.164 (2019-08-27)
++1.02.164-RHEL7 (2019-08-27)
diff --git a/SOURCES/lvm2-set-default-preferred_names.patch b/SOURCES/lvm2-set-default-preferred_names.patch
new file mode 100644
index 0000000..205dd10
--- /dev/null
+++ b/SOURCES/lvm2-set-default-preferred_names.patch
@@ -0,0 +1,30 @@
+ conf/example.conf.in         | 2 +-
+ lib/config/config_settings.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/conf/example.conf.in b/conf/example.conf.in
+index 38855e9..7ccf928 100644
+--- a/conf/example.conf.in
++++ b/conf/example.conf.in
+@@ -106,7 +106,7 @@ devices {
+ 	# Example
+ 	# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
+ 	# 
+-	# This configuration option does not have a default value defined.
++	preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
+ 
+ 	# Configuration option devices/filter.
+ 	# Limit the block devices that are used by LVM commands.
+diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
+index 0e81252..02e2b29 100644
+--- a/lib/config/config_settings.h
++++ b/lib/config/config_settings.h
+@@ -255,7 +255,7 @@ cfg(devices_external_device_info_source_CFG, "external_device_info_source", devi
+ 	"    compiled with udev support.\n"
+ 	"#\n")
+ 
+-cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED , CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL, 0, NULL,
++cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#S^/dev/mpath/#S^/dev/mapper/mpath#S^/dev/[hs]d", vsn(1, 2, 19), NULL, 0, NULL,
+ 	"Select which path name to display for a block device.\n"
+ 	"If multiple path names exist for a block device, and LVM needs to\n"
+ 	"display a name for the device, the path names are matched against\n"
diff --git a/SPECS/lvm2.spec b/SPECS/lvm2.spec
new file mode 100644
index 0000000..11056b7
--- /dev/null
+++ b/SPECS/lvm2.spec
@@ -0,0 +1,4090 @@
+%global device_mapper_version 1.02.164
+
+%global enable_cache 1
+%global enable_cluster 1
+%global enable_cmirror 1
+%global enable_lvmetad 1
+%global enable_lvmlockd 1
+%global enable_lvmpolld 1
+%global enable_python 1
+%global enable_thin 1
+%global enable_dmfilemapd 1
+
+%global systemd_version 189-3
+%global dracut_version 002-18
+%global util_linux_version 2.23
+%global bash_version 4.0
+%global corosync_version 1.99.9-1
+%global resource_agents_version 3.9.5-25
+%global dlm_version 4.0.6-2
+%global libselinux_version 1.30.19-4
+%global persistent_data_version 0.7.0-0.1.rc6
+%global sanlock_version 3.3.0-1
+%global boom_version 0.9
+
+%global enable_lockd_sanlock %{enable_lvmlockd}
+%global enable_lockd_dlm %{enable_lvmlockd}
+
+%global boom_pkgname lvm2-python-boom
+%global boom_version 0.9
+%global boom_release 20
+%global boom_summary A set of libraries and tools for managing boot loader entries
+%global boom_dir boom-%{boom_version}
+
+#%%global scratch .bz1628529_4
+
+%if 0%{?rhel}
+  %ifnarch i686 x86_64 ppc64le s390x
+    %global enable_cluster 0
+    %global enable_cmirror 0
+    %global enable_lockd_dlm 0
+  %endif
+
+  %ifnarch x86_64 ppc64 aarch64
+    %global enable_lockd_sanlock 0
+  %endif
+%endif
+
+%ifnarch s390x s390
+    %global enable_boom 1
+%else
+    %global enable_boom 0
+%endif
+
+%if %{enable_cluster}
+  %global configure_cluster --with-cluster=internal --with-clvmd=corosync
+  %if %{enable_cmirror}
+    %global configure_cmirror --enable-cmirrord
+  %endif
+%else
+    %global configure_cluster --with-cluster=internal --with-clvmd=none
+%endif
+
+# Do not reset Release to 1 unless both lvm2 and device-mapper 
+# versions are increased together.
+
+Summary: Userland logical volume management tools 
+Name: lvm2
+Epoch: 7
+Version: 2.02.186
+Release: 2%{?dist}%{?scratch}
+License: GPLv2
+Group: System Environment/Base
+URL: http://sources.redhat.com/lvm2
+Source0: ftp://sources.redhat.com/pub/lvm2/releases/LVM2.%{version}.tgz
+Source1: https://github.com/bmr-cymru/boom/archive/%{boom_version}/boom-%{boom_version}.tar.gz
+Patch0: lvm2-rhel7.patch
+Patch1: lvm2-set-default-preferred_names.patch
+Patch2: lvm2-fix-libdm-versioning-for-dm_tree_node_size_changed-symbol.patch
+Patch3: lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection.patch
+Patch4: lvm2-default-allow-changes-with-duplicate-pvs.patch
+#Patch5: lvm2-rhel7-fix-StartLimitInterval.patch
+Patch6: lvm2-rhel7-add-lvm1-and-pool-back.patch
+Patch7: lvm2-make-generate.patch
+Patch8: lvm2-2_02_187-cov-Fix-memory-leak.patch
+# BZ 1669751:
+Patch9: lvm2-2_02_187-vgcreate-vgextend-restrict-PVs-with-mixed-block-size.patch
+Patch10: lvm2-2_02_187-WHATS_NEW-vgcreate-vgextend-logical-block-size.patch
+# BZ 1622813:
+Patch11: lvm2-2_02_187-pvmove-check-if-participating-LV-is-already-exlcusiv.patch
+# BZ 1697823:
+Patch12: lvm2-2_02_187-lvconvert-improve-validation-thin-and-cache-pool-con.patch
+Patch13: lvm2-2_02_187-thin-activate-layer-pool-aas-read-only-LV.patch
+
+
+BuildRequires: libselinux-devel >= %{libselinux_version}, libsepol-devel
+BuildRequires: libblkid-devel >= %{util_linux_version}
+BuildRequires: ncurses-devel
+BuildRequires: readline-devel
+BuildRequires: libaio-devel
+%if %{enable_cluster}
+BuildRequires: corosynclib-devel >= %{corosync_version}
+%endif
+%if %{enable_cluster} || %{enable_lockd_dlm}
+BuildRequires: dlm-devel >= %{dlm_version}
+%endif
+BuildRequires: module-init-tools
+BuildRequires: pkgconfig
+BuildRequires: systemd-devel
+BuildRequires: systemd-units
+%if %{enable_python} || %{enable_boom}
+BuildRequires: python2-devel
+BuildRequires: python-setuptools
+%endif
+%if %{enable_thin} || %{enable_cache}
+BuildRequires: device-mapper-persistent-data >= %{persistent_data_version}
+%endif
+%if %{enable_lockd_sanlock}
+BuildRequires: sanlock-devel >= %{sanlock_version}
+%endif
+
+Requires: %{name}-libs = %{epoch}:%{version}-%{release}
+Requires: bash >= %{bash_version}
+Requires(post): systemd-units >= %{systemd_version}
+Requires(preun): systemd-units >= %{systemd_version}
+Requires(postun): systemd-units >= %{systemd_version}
+Requires: module-init-tools
+%if %{enable_thin} || %{enable_cache}
+Requires: device-mapper-persistent-data >= %{persistent_data_version}
+%endif
+# BZ https://bugzilla.redhat.com/show_bug.cgi?id=1523288
+
+%description
+LVM2 includes all of the support for handling read/write operations on
+physical volumes (hard disks, RAID-Systems, magneto optical, etc.,
+multiple devices (MD), see mdadm(8) or even loop devices, see
+losetup(8)), creating volume groups (kind of virtual disks) from one
+or more physical volumes and creating one or more logical volumes
+(kind of logical partitions) in volume groups.
+
+%prep
+%if %{enable_boom}
+%setup -q -b 1 -n %{boom_dir}
+%endif
+
+%setup -q -n LVM2.%{version}
+%patch0 -p1 -b .rhel7
+%patch1 -p1 -b .preferred_names
+%patch2 -p1 -b .libdm_symbol_versioning
+%patch3 -p1 -b .blkid_sublks_badcsum
+%patch4 -p1 -b .default_allow_dup
+#%%patch5 -p1 -b .startlimitinterval
+%patch6 -p1 -b .add_lvm1_and_pool
+%patch7 -p1 -b .generate
+%patch8 -p1 -b .cov_Fix_memory_leak
+%patch9 -p1 -b .vgcreate_vgextend_restrict_PVs_with_mixed_block_size
+%patch10 -p1 -b .WHATS_NEW_vgcreate_vgextend_logical_block_size
+%patch11 -p1 -b .pvmove_check_if_participating_LV_is_already_exlcusiv
+%patch12 -p1 -b .lvconvert_improve_validation_thin_and_cache_pool_con
+%patch13 -p1 -b .thin_activate_layer_pool_aas_read_only_LV
+
+%build
+%global _default_pid_dir /run
+%global _default_dm_run_dir /run
+%global _default_run_dir /run/lvm
+%global _default_locking_dir /run/lock/lvm
+
+%global _udevdir %{_prefix}/lib/udev/rules.d
+%global _tmpfilesdir %{_prefix}/lib/tmpfiles.d
+
+%global configure_udev --with-udevdir=%{_udevdir} --enable-udev_sync
+
+%if %{enable_cache}
+%global configure_cache --with-cache=internal
+%endif
+
+%if %{enable_thin}
+%global configure_thin --with-thin=internal
+%endif
+
+%if %{enable_lvmetad}
+%global configure_lvmetad --enable-lvmetad
+%endif
+
+%if %{enable_lockd_dlm}
+%global configure_lockd_dlm --enable-lvmlockd-dlm
+%endif
+
+%if %{enable_lockd_sanlock}
+%global configure_lockd_sanlock --enable-lvmlockd-sanlock
+%endif
+
+%if %{enable_lvmpolld}
+%global configure_lvmpolld --enable-lvmpolld
+%endif
+
+%if %{enable_python}
+%global configure_python --enable-python2-bindings
+%endif
+
+%if %{enable_dmfilemapd}
+%global configure_dmfilemapd --enable-dmfilemapd
+%endif
+
+%configure --with-default-dm-run-dir=%{_default_dm_run_dir} --with-default-run-dir=%{_default_run_dir} --with-default-pid-dir=%{_default_pid_dir} --with-default-locking-dir=%{_default_locking_dir} --with-usrlibdir=%{_libdir} --enable-lvm1_fallback --enable-fsadm --with-pool=internal --enable-write_install --with-user= --with-group= --with-device-uid=0 --with-device-gid=6 --with-device-mode=0660 --enable-pkgconfig --enable-applib --enable-cmdlib --enable-dmeventd --enable-blkid_wiping %{?configure_python} %{?configure_cluster} %{?configure_cmirror} %{?configure_udev} %{?configure_thin} %{?configure_lvmetad} %{?configure_cache} %{?configure_lvmpolld} %{?configure_lockd_dlm} %{?configure_lockd_sanlock} %{?configure_dmfilemapd}
+
+make %{?_smp_mflags}
+
+%if %{enable_boom}
+(
+cd ../%{boom_dir}
+%py2_build
+)
+%endif
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+make install_system_dirs DESTDIR=$RPM_BUILD_ROOT
+make install_initscripts DESTDIR=$RPM_BUILD_ROOT
+make install_systemd_units DESTDIR=$RPM_BUILD_ROOT
+make install_systemd_generators DESTDIR=$RPM_BUILD_ROOT
+make install_tmpfiles_configuration DESTDIR=$RPM_BUILD_ROOT
+
+%if %{enable_boom}
+(
+cd ../%{boom_dir}
+%py2_install
+
+# Install Grub2 integration scripts
+install -d -m 700 ${RPM_BUILD_ROOT}/etc/grub.d
+install -d -m 755 ${RPM_BUILD_ROOT}/etc/default
+install -m 755 etc/grub.d/42_boom ${RPM_BUILD_ROOT}/etc/grub.d
+install -m 644 etc/default/boom ${RPM_BUILD_ROOT}/etc/default
+
+# Make configuration directories
+install -d -m 700 ${RPM_BUILD_ROOT}/boot/boom/profiles
+install -d -m 700 ${RPM_BUILD_ROOT}/boot/loader/entries
+install -m 644 examples/profiles/*.profile ${RPM_BUILD_ROOT}/boot/boom/profiles
+
+install -d -m 755 ${RPM_BUILD_ROOT}/%{_mandir}/man8
+install -m 644 man/man8/boom.8 ${RPM_BUILD_ROOT}/%{_mandir}/man8
+)
+%endif
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+/sbin/ldconfig
+%systemd_post lvm2-monitor.service
+if [ "$1" = "1" ] ; then
+	# enable and start lvm2-monitor.service on completely new installation only, not on upgrades
+	systemctl enable lvm2-monitor.service
+	systemctl start lvm2-monitor.service
+fi
+%if %{enable_lvmetad}
+%systemd_post lvm2-lvmetad.socket
+# lvm2-lvmetad.socket is always enabled and started and ready to serve if lvmetad is used
+# replace direct systemctl calls with systemd rpm macro once this is provided in the macro:
+# http://cgit.freedesktop.org/systemd/systemd/commit/?id=57ab2eabb8f92fad5239c7d4492e9c6e23ee0678
+systemctl enable lvm2-lvmetad.socket
+systemctl start lvm2-lvmetad.socket
+%endif
+
+%if %{enable_lvmpolld}
+%systemd_post lvm2-lvmpolld.socket
+# lvm2-lvmpolld socket is always enabled and started and ready to serve if lvmpolld is used
+# replace direct systemctl calls with systemd rpm macro once this is provided in the macro:
+# http://cgit.freedesktop.org/systemd/systemd/commit/?id=57ab2eabb8f92fad5239c7d4492e9c6e23ee0678
+systemctl enable lvm2-lvmpolld.socket
+systemctl start lvm2-lvmpolld.socket
+%endif
+
+%preun
+%systemd_preun lvm2-monitor.service
+%if %{enable_lvmetad}
+%systemd_preun lvm2-lvmetad.service lvm2-lvmetad.socket
+%endif
+
+%if %{enable_lvmpolld}
+%systemd_preun lvm2-lvmpolld.service lvm2-lvmpolld.socket
+%endif
+
+%postun
+%systemd_postun lvm2-monitor.service
+%if %{enable_lvmetad}
+%systemd_postun_with_restart lvm2-lvmetad.service
+%endif
+
+%if %{enable_lvmpolld}
+%systemd_postun_with_restart lvm2-lvmpolld.service
+%endif
+
+%triggerun -- %{name} < 2.02.86-2
+%{_bindir}/systemd-sysv-convert --save lvm2-monitor >/dev/null 2>&1 || :
+/bin/systemctl --no-reload enable lvm2-monitor.service > /dev/null 2>&1 || :
+/sbin/chkconfig --del lvm2-monitor > /dev/null 2>&1 || :
+/bin/systemctl try-restart lvm2-monitor.service > /dev/null 2>&1 || :
+
+%files
+%defattr(-,root,root,755)
+%{!?_licensedir:%global license %%doc}
+%license COPYING COPYING.LIB
+%doc README VERSION WHATS_NEW
+%doc doc/lvm_fault_handling.txt
+
+# Main binaries
+%defattr(555,root,root,-)
+%{_sbindir}/fsadm
+%{_sbindir}/lvm
+%{_sbindir}/lvmconf
+%{_sbindir}/lvmconfig
+%{_sbindir}/lvmdump
+%if %{enable_lvmetad}
+%{_sbindir}/lvmetad
+%endif
+%if %{enable_lvmpolld}
+%{_sbindir}/lvmpolld
+%endif
+
+# Other files
+%defattr(444,root,root,-)
+%{_sbindir}/lvchange
+%{_sbindir}/lvconvert
+%{_sbindir}/lvcreate
+%{_sbindir}/lvdisplay
+%{_sbindir}/lvextend
+%{_sbindir}/lvmdiskscan
+%{_sbindir}/lvmsadc
+%{_sbindir}/lvmsar
+%{_sbindir}/lvreduce
+%{_sbindir}/lvremove
+%{_sbindir}/lvrename
+%{_sbindir}/lvresize
+%{_sbindir}/lvs
+%{_sbindir}/lvscan
+%{_sbindir}/pvchange
+%{_sbindir}/pvck
+%{_sbindir}/pvcreate
+%{_sbindir}/pvdisplay
+%{_sbindir}/pvmove
+%{_sbindir}/pvremove
+%{_sbindir}/pvresize
+%{_sbindir}/pvs
+%{_sbindir}/pvscan
+%{_sbindir}/vgcfgbackup
+%{_sbindir}/vgcfgrestore
+%{_sbindir}/vgchange
+%{_sbindir}/vgck
+%{_sbindir}/vgconvert
+%{_sbindir}/vgcreate
+%{_sbindir}/vgdisplay
+%{_sbindir}/vgexport
+%{_sbindir}/vgextend
+%{_sbindir}/vgimport
+%{_sbindir}/vgimportclone
+%{_sbindir}/vgmerge
+%{_sbindir}/vgmknodes
+%{_sbindir}/vgreduce
+%{_sbindir}/vgremove
+%{_sbindir}/vgrename
+%{_sbindir}/vgs
+%{_sbindir}/vgscan
+%{_sbindir}/vgsplit
+%{_mandir}/man5/lvm.conf.5.gz
+%{_mandir}/man7/lvmcache.7.gz
+%{_mandir}/man7/lvmraid.7.gz
+%{_mandir}/man7/lvmreport.7.gz
+%{_mandir}/man7/lvmthin.7.gz
+%{_mandir}/man7/lvmsystemid.7.gz
+%{_mandir}/man8/fsadm.8.gz
+%{_mandir}/man8/lvchange.8.gz
+%{_mandir}/man8/lvconvert.8.gz
+%{_mandir}/man8/lvcreate.8.gz
+%{_mandir}/man8/lvdisplay.8.gz
+%{_mandir}/man8/lvextend.8.gz
+%{_mandir}/man8/lvm.8.gz
+%{_mandir}/man8/lvm2-activation-generator.8.gz
+%{_mandir}/man8/lvm-config.8.gz
+%{_mandir}/man8/lvmconfig.8.gz
+%{_mandir}/man8/lvm-dumpconfig.8.gz
+%{_mandir}/man8/lvmconf.8.gz
+%{_mandir}/man8/lvmdiskscan.8.gz
+%{_mandir}/man8/lvmdump.8.gz
+%{_mandir}/man8/lvm-fullreport.8.gz
+%{_mandir}/man8/lvmsadc.8.gz
+%{_mandir}/man8/lvmsar.8.gz
+%{_mandir}/man8/lvreduce.8.gz
+%{_mandir}/man8/lvremove.8.gz
+%{_mandir}/man8/lvrename.8.gz
+%{_mandir}/man8/lvresize.8.gz
+%{_mandir}/man8/lvs.8.gz
+%{_mandir}/man8/lvscan.8.gz
+%{_mandir}/man8/pvchange.8.gz
+%{_mandir}/man8/pvck.8.gz
+%{_mandir}/man8/pvcreate.8.gz
+%{_mandir}/man8/pvdisplay.8.gz
+%{_mandir}/man8/pvmove.8.gz
+%{_mandir}/man8/pvremove.8.gz
+%{_mandir}/man8/pvresize.8.gz
+%{_mandir}/man8/pvs.8.gz
+%{_mandir}/man8/pvscan.8.gz
+%{_mandir}/man8/vgcfgbackup.8.gz
+%{_mandir}/man8/vgcfgrestore.8.gz
+%{_mandir}/man8/vgchange.8.gz
+%{_mandir}/man8/vgck.8.gz
+%{_mandir}/man8/vgconvert.8.gz
+%{_mandir}/man8/vgcreate.8.gz
+%{_mandir}/man8/vgdisplay.8.gz
+%{_mandir}/man8/vgexport.8.gz
+%{_mandir}/man8/vgextend.8.gz
+%{_mandir}/man8/vgimport.8.gz
+%{_mandir}/man8/vgimportclone.8.gz
+%{_mandir}/man8/vgmerge.8.gz
+%{_mandir}/man8/vgmknodes.8.gz
+%{_mandir}/man8/vgreduce.8.gz
+%{_mandir}/man8/vgremove.8.gz
+%{_mandir}/man8/vgrename.8.gz
+%{_mandir}/man8/vgs.8.gz
+%{_mandir}/man8/vgscan.8.gz
+%{_mandir}/man8/vgsplit.8.gz
+%{_udevdir}/11-dm-lvm.rules
+%if %{enable_lvmetad}
+%{_mandir}/man8/lvmetad.8.gz
+%{_udevdir}/69-dm-lvm-metad.rules
+%endif
+%if %{enable_lvmpolld}
+%{_mandir}/man8/lvmpolld.8.gz
+%{_mandir}/man8/lvm-lvpoll.8.gz
+%endif
+%attr(755, -, -) %dir %{_sysconfdir}/lvm
+%ghost %{_sysconfdir}/lvm/cache/.cache
+%attr(644, -, -) %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/lvm.conf
+%attr(644, -, -) %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/lvmlocal.conf
+%attr(755, -, -) %dir %{_sysconfdir}/lvm/profile
+%{_sysconfdir}/lvm/profile/command_profile_template.profile
+%{_sysconfdir}/lvm/profile/metadata_profile_template.profile
+%{_sysconfdir}/lvm/profile/thin-generic.profile
+%{_sysconfdir}/lvm/profile/thin-performance.profile
+%{_sysconfdir}/lvm/profile/cache-mq.profile
+%{_sysconfdir}/lvm/profile/cache-smq.profile
+%{_sysconfdir}/lvm/profile/lvmdbusd.profile
+%attr(700, -, -) %dir %{_sysconfdir}/lvm/backup
+%attr(700, -, -) %dir %{_sysconfdir}/lvm/cache
+%attr(700, -, -) %dir %{_sysconfdir}/lvm/archive
+%ghost %attr(700, -, -) %dir %{_default_locking_dir}
+%ghost %attr(700, -, -) %dir %{_default_run_dir}
+%{_tmpfilesdir}/%{name}.conf
+%{_unitdir}/lvm2-monitor.service
+%attr(555, -, -) %{_prefix}/lib/systemd/system-generators/lvm2-activation-generator
+%if %{enable_lvmetad}
+%{_unitdir}/lvm2-lvmetad.socket
+%{_unitdir}/lvm2-lvmetad.service
+%{_unitdir}/lvm2-pvscan@.service
+%endif
+%if %{enable_lvmpolld}
+%{_unitdir}/lvm2-lvmpolld.socket
+%{_unitdir}/lvm2-lvmpolld.service
+%endif
+
+##############################################################################
+# Library and Development subpackages
+##############################################################################
+%package devel
+Summary: Development libraries and headers
+Group: Development/Libraries
+License: LGPLv2
+Requires: %{name} = %{epoch}:%{version}-%{release}
+Requires: device-mapper-devel = %{epoch}:%{device_mapper_version}-%{release}
+Requires: device-mapper-event-devel = %{epoch}:%{device_mapper_version}-%{release}
+Requires: pkgconfig
+
+%description devel
+This package contains files needed to develop applications that use
+the lvm2 libraries.
+
+%files devel
+%defattr(444,root,root,-)
+%{_libdir}/liblvm2app.so
+%{_libdir}/liblvm2cmd.so
+%{_libdir}/libdevmapper-event-lvm2.so
+%{_includedir}/lvm2app.h
+%{_includedir}/lvm2cmd.h
+%{_libdir}/pkgconfig/lvm2app.pc
+
+%package libs
+Summary: Shared libraries for lvm2
+License: LGPLv2
+Group: System Environment/Libraries
+Requires: device-mapper-event = %{epoch}:%{device_mapper_version}-%{release}
+
+%description libs
+This package contains shared lvm2 libraries for applications.
+
+%post libs -p /sbin/ldconfig
+
+%postun libs -p /sbin/ldconfig
+
+%files libs
+%defattr(555,root,root,555)
+%{!?_licensedir:%global license %%doc}
+%license COPYING.LIB
+%{_libdir}/liblvm2app.so.*
+%{_libdir}/liblvm2cmd.so.*
+%{_libdir}/libdevmapper-event-lvm2.so.*
+%dir %{_libdir}/device-mapper
+%{_libdir}/device-mapper/libdevmapper-event-lvm2mirror.so
+%{_libdir}/device-mapper/libdevmapper-event-lvm2snapshot.so
+%{_libdir}/device-mapper/libdevmapper-event-lvm2raid.so
+%{_libdir}/libdevmapper-event-lvm2mirror.so
+%{_libdir}/libdevmapper-event-lvm2snapshot.so
+%{_libdir}/libdevmapper-event-lvm2raid.so
+
+%if %{enable_thin}
+%{_libdir}/libdevmapper-event-lvm2thin.so
+%{_libdir}/device-mapper/libdevmapper-event-lvm2thin.so
+%endif
+
+%{_libdir}/device-mapper/libdevmapper-event-lvm2vdo.so
+%{_libdir}/libdevmapper-event-lvm2vdo.so
+
+
+%if %{enable_python}
+
+%package python-libs
+Summary: Python module to access LVM
+License: LGPLv2
+Group: Development/Libraries
+Provides: python-lvm = %{epoch}:%{version}-%{release}
+Obsoletes: python-lvm < 2.02.98-3
+Requires: %{name}-libs = %{epoch}:%{version}-%{release}
+
+%description python-libs
+Python module to allow the creation and use of LVM
+logical volumes, physical volumes, and volume groups.
+
+%files python-libs
+%{python_sitearch}/lvm*
+
+%endif
+
+##############################################################################
+# LVM locking daemon
+##############################################################################
+%if %{enable_lockd_dlm} || %{enable_lockd_sanlock}
+%package lockd
+Summary: LVM locking daemon
+Group: System Environment/Base
+Requires: lvm2 = %{epoch}:%{version}-%{release}
+%if %{enable_lockd_sanlock}
+Requires: sanlock-lib >= %{sanlock_version}
+%endif
+%if %{enable_lockd_dlm}
+Requires: dlm-lib >= %{dlm_version}
+%endif
+Requires(post): systemd-units >= %{systemd_version}
+Requires(preun): systemd-units >= %{systemd_version}
+Requires(postun): systemd-units >= %{systemd_version}
+
+%description lockd
+
+LVM commands use lvmlockd to coordinate access to shared storage.
+
+%post lockd
+%systemd_post lvm2-lvmlockd.service lvm2-lvmlocking.service
+
+%preun lockd
+%systemd_preun lvm2-lvmlockd.service lvm2-lvmlocking.service
+
+%postun lockd
+%systemd_postun lvm2-lvmlockd.service lvm2-lvmlocking.service
+
+%files lockd
+%defattr(444,root,root,-)
+%%attr(555, -, -) %{_sbindir}/lvmlockd
+%%attr(555, -, -) %{_sbindir}/lvmlockctl
+%{_mandir}/man8/lvmlockd.8.gz
+%{_mandir}/man8/lvmlockctl.8.gz
+%{_unitdir}/lvm2-lvmlockd.service
+%{_unitdir}/lvm2-lvmlocking.service
+
+%endif
+
+##############################################################################
+# Cluster subpackage
+# The 'clvm' OCF script to manage clvmd instance is part of resource-agents.
+##############################################################################
+%if %{enable_cluster}
+
+%package cluster
+Summary: Cluster extensions for userland logical volume management tools
+License: GPLv2
+Group: System Environment/Base
+Requires: lvm2 = %{epoch}:%{version}-%{release}
+Requires(preun): device-mapper = %{epoch}:%{device_mapper_version}
+Requires(preun): lvm2 >= 2.02
+Requires: corosync >= %{corosync_version}
+Requires: dlm >= %{dlm_version}
+Requires: resource-agents >= %{resource_agents_version}
+
+%description cluster
+
+Extensions to LVM2 to support clusters.
+
+%post cluster
+if [ -e %{_default_pid_dir}/clvmd.pid ]; then
+	/usr/sbin/clvmd -S || echo "Failed to restart clvmd daemon. Please, try manual restart."
+fi
+
+%preun cluster
+if [ "$1" = "0" ]; then
+	/sbin/lvmconf --disable-cluster
+fi
+
+%files cluster
+%defattr(555,root,root,-)
+%{_sbindir}/clvmd
+%attr(444, -, -) %{_mandir}/man8/clvmd.8.gz
+
+##############################################################################
+# Cluster-standalone subpackage
+##############################################################################
+%package cluster-standalone
+Summary: Additional files to support clustered LVM2 in standalone mode
+License: GPLv2
+Group: System Environment/Base
+Requires: lvm2-cluster = %{epoch}:%{version}-%{release}
+
+%description cluster-standalone
+
+Additional files needed to run clustered LVM2 daemon and clustered volume
+activation in standalone mode as services without cluster resource manager
+involvement (e.g. pacemaker).
+
+%post cluster-standalone
+%systemd_post lvm2-clvmd.service lvm2-cluster-activation.service
+
+%preun cluster-standalone
+%systemd_preun lvm2-clvmd.service lvm2-cluster-activation.service
+
+%postun cluster-standalone
+%systemd_postun lvm2-clvmd.service lvm2-cluster-activation.service
+
+%files cluster-standalone
+%defattr(555,root,root,-)
+%{_prefix}/lib/systemd/lvm2-cluster-activation
+%defattr(444,root,root,-)
+%{_unitdir}/lvm2-clvmd.service
+%{_unitdir}/lvm2-cluster-activation.service
+
+%endif
+
+###############################################################################
+# Cluster mirror subpackage
+# The 'clvm' OCF script to manage cmirrord instance is part of resource-agents.
+###############################################################################
+%if %{enable_cluster}
+%if %{enable_cmirror}
+
+%package -n cmirror
+Summary: Daemon for device-mapper-based clustered mirrors
+Group: System Environment/Base
+Requires: corosync >= %{corosync_version}
+Requires: device-mapper = %{epoch}:%{device_mapper_version}-%{release}
+Requires: resource-agents >= %{resource_agents_version}
+
+%description -n cmirror
+Daemon providing device-mapper-based mirrors in a shared-storage cluster.
+
+%files -n cmirror
+%defattr(555,root,root,-)
+%{_sbindir}/cmirrord
+%attr(444, -, -) %{_mandir}/man8/cmirrord.8.gz
+
+##############################################################################
+# Cmirror-standalone subpackage
+##############################################################################
+%package -n cmirror-standalone
+Summary: Additional files to support device-mapper-based clustered mirrors in standalone mode
+License: GPLv2
+Group: System Environment/Base
+Requires: cmirror >= %{epoch}:%{version}-%{release}
+
+%description -n cmirror-standalone
+
+Additional files needed to run daemon for device-mapper-based clustered
+mirrors in standalone mode as a service without cluster resource manager
+involvement (e.g. pacemaker).
+
+%post -n cmirror-standalone
+%systemd_post lvm2-cmirrord.service
+
+%preun -n cmirror-standalone
+%systemd_preun lvm2-cmirrord.service
+
+%postun -n cmirror-standalone
+%systemd_postun lvm2-cmirrord.service
+
+%files -n cmirror-standalone
+%defattr(444,root,root,-)
+%{_unitdir}/lvm2-cmirrord.service
+
+%endif
+%endif
+
+##############################################################################
+# Legacy SysV init subpackage
+##############################################################################
+%package sysvinit
+Summary: SysV style init script for LVM2.
+Group: System Environment/Base
+Requires: %{name} = %{epoch}:%{version}-%{release}
+Requires: initscripts
+
+%description sysvinit
+SysV style init script for LVM2. It needs to be installed only if systemd
+is not used as the system init process.
+
+%files sysvinit
+%defattr(555,root,root,-)
+%{_sysconfdir}/rc.d/init.d/blk-availability
+%{_sysconfdir}/rc.d/init.d/lvm2-monitor
+%if %{enable_cluster}
+%{_sysconfdir}/rc.d/init.d/clvmd
+%if %{enable_cmirror}
+%{_sysconfdir}/rc.d/init.d/cmirrord
+%endif
+%endif
+%if %{enable_lvmetad}
+%{_sysconfdir}/rc.d/init.d/lvm2-lvmetad
+%endif
+%if %{enable_lvmpolld}
+%{_sysconfdir}/rc.d/init.d/lvm2-lvmpolld
+%endif
+
+##############################################################################
+# Device-mapper subpackages
+##############################################################################
+%package -n device-mapper
+Summary: Device mapper utility
+Version: %{device_mapper_version}
+License: GPLv2
+Group: System Environment/Base
+URL: http://sources.redhat.com/dm
+Requires: device-mapper-libs = %{epoch}:%{device_mapper_version}-%{release}
+Requires: util-linux >= %{util_linux_version}
+Requires: systemd >= %{systemd_version}
+# We need dracut to install required udev rules if udev_sync
+# feature is turned on so we don't lose required notifications.
+Conflicts: dracut < %{dracut_version}
+
+%description -n device-mapper
+This package contains the supporting userspace utility, dmsetup,
+for the kernel device-mapper.
+
+%post -n device-mapper
+%systemd_post blk-availability.service
+
+%preun -n device-mapper
+%systemd_preun blk-availability.service
+
+%files -n device-mapper
+%defattr(-,root,root,-)
+%doc COPYING COPYING.LIB WHATS_NEW_DM VERSION_DM README INSTALL
+%doc udev/12-dm-permissions.rules
+%defattr(444,root,root,-)
+%attr(555, -, -) %{_sbindir}/dmsetup
+%attr(555, -, -) %{_sbindir}/blkdeactivate
+# dmstats is a symlink
+%{_sbindir}/dmstats
+%{_mandir}/man8/dmsetup.8.gz
+%{_mandir}/man8/dmstats.8.gz
+%{_mandir}/man8/blkdeactivate.8.gz
+%if %{enable_dmfilemapd}
+%attr(555, -, -) %{_sbindir}/dmfilemapd
+%{_mandir}/man8/dmfilemapd.8.gz
+%endif
+%{_udevdir}/10-dm.rules
+%{_udevdir}/13-dm-disk.rules
+%{_udevdir}/95-dm-notify.rules
+%{_unitdir}/blk-availability.service
+
+%package -n device-mapper-devel
+Summary: Development libraries and headers for device-mapper
+Version: %{device_mapper_version}
+License: LGPLv2
+Group: Development/Libraries
+Requires: device-mapper = %{epoch}:%{device_mapper_version}-%{release}
+Requires: pkgconfig
+
+%description -n device-mapper-devel
+This package contains files needed to develop applications that use
+the device-mapper libraries.
+
+%files -n device-mapper-devel
+%defattr(444,root,root,-)
+%{_libdir}/libdevmapper.so
+%{_includedir}/libdevmapper.h
+%{_libdir}/pkgconfig/devmapper.pc
+
+%package -n device-mapper-libs
+Summary: Device-mapper shared library
+Version: %{device_mapper_version}
+License: LGPLv2
+Group: System Environment/Libraries
+Requires: device-mapper = %{epoch}:%{device_mapper_version}-%{release}
+
+%description -n device-mapper-libs
+This package contains the device-mapper shared library, libdevmapper.
+
+%post -n device-mapper-libs -p /sbin/ldconfig
+
+%postun -n device-mapper-libs -p /sbin/ldconfig
+
+%files -n device-mapper-libs
+%defattr(555,root,root,555)
+%{!?_licensedir:%global license %%doc}
+%license COPYING COPYING.LIB
+%{_libdir}/libdevmapper.so.*
+
+%package -n device-mapper-event
+Summary: Device-mapper event daemon
+Group: System Environment/Base
+Version: %{device_mapper_version}
+# Older lvm2 versions had incorrect dependency on device-mapper-event
+# package where lvm2-libs had "Requires: device-mapper-event >="
+# instead of "Requires: device-mapper-event =". This was fixed in
+# lvm2-2.02.111-1 and later.
+Conflicts: lvm2-libs < 7:2.02.111
+Requires: device-mapper = %{epoch}:%{device_mapper_version}-%{release}
+Requires: device-mapper-event-libs = %{epoch}:%{device_mapper_version}-%{release}
+Requires(post): systemd-units
+Requires(preun): systemd-units
+Requires(postun): systemd-units
+
+%description -n device-mapper-event
+This package contains the dmeventd daemon for monitoring the state
+of device-mapper devices.
+
+%post -n device-mapper-event
+%systemd_post dm-event.socket
+# dm-event.socket is always enabled and started and ready to serve if dmeventd is used
+# replace direct systemctl calls with systemd rpm macro once this is provided in the macro:
+# http://cgit.freedesktop.org/systemd/systemd/commit/?id=57ab2eabb8f92fad5239c7d4492e9c6e23ee0678
+systemctl enable dm-event.socket
+systemctl start dm-event.socket
+
+%preun -n device-mapper-event
+%systemd_preun dm-event.service dm-event.socket
+
+%posttrans -n device-mapper-event
+if [ -e %{_default_pid_dir}/dmeventd.pid ]; then
+	%{_sbindir}/dmeventd -R || echo "Failed to restart dmeventd daemon. Please, try manual restart."
+fi
+
+%files -n device-mapper-event
+%defattr(444,root,root,-)
+%attr(555, -, -) %{_sbindir}/dmeventd
+%{_mandir}/man8/dmeventd.8.gz
+%{_unitdir}/dm-event.socket
+%{_unitdir}/dm-event.service
+
+%package -n device-mapper-event-libs
+Summary: Device-mapper event daemon shared library
+Version: %{device_mapper_version}
+License: LGPLv2
+Group: System Environment/Libraries
+
+%description -n device-mapper-event-libs
+This package contains the device-mapper event daemon shared library,
+libdevmapper-event.
+
+%post -n device-mapper-event-libs -p /sbin/ldconfig
+
+%postun -n device-mapper-event-libs -p /sbin/ldconfig
+
+%files -n device-mapper-event-libs
+%defattr(555,root,root,555)
+%{!?_licensedir:%global license %%doc}
+%license COPYING.LIB
+%{_libdir}/libdevmapper-event.so.*
+
+%package -n device-mapper-event-devel
+Summary: Development libraries and headers for the device-mapper event daemon
+Version: %{device_mapper_version}
+License: LGPLv2
+Group: Development/Libraries
+Requires: device-mapper-event = %{epoch}:%{device_mapper_version}-%{release}
+Requires: pkgconfig
+
+%description -n device-mapper-event-devel
+This package contains files needed to develop applications that use
+the device-mapper event library.
+
+%files -n device-mapper-event-devel
+%defattr(444,root,root,-)
+%{_libdir}/libdevmapper-event.so
+%{_includedir}/libdevmapper-event.h
+%{_libdir}/pkgconfig/devmapper-event.pc
+
+%if %{enable_boom}
+##############################################################################
+# boom subpackages
+##############################################################################
+%package -n %{boom_pkgname}
+Summary: %{boom_summary}
+Version: %{boom_version}
+Release: %{boom_release}%{?dist}%{?scratch}
+License: GPLv2
+Group: System Environment/Base
+BuildArch: noarch
+%{?python_provide:%python_provide python2-boom}
+Requires: grub2
+
+%description -n %{boom_pkgname}
+Boom is a boot manager for Linux systems using boot loaders that support
+the BootLoader Specification for boot entry configuration.
+
+Boom requires a BLS compatible boot loader to function: either the
+systemd-boot project, or Grub2 with the bls patch (Red Hat Grub2 builds
+include this support in both Red Hat Enterprise Linux 7 and Fedora).
+
+This package provides the python2 version of boom.
+
+%files -n %{boom_pkgname}
+%license COPYING
+%{_mandir}/man8/boom.*
+%{python2_sitelib}/boom*
+%{_bindir}/boom
+/etc/grub.d/42_boom
+%config(noreplace) /etc/default/boom
+/boot/*
+%doc ../%{boom_dir}/README.md
+%doc ../%{boom_dir}/examples/
+%doc ../%{boom_dir}/tests/
+%endif
+
+%changelog
+* Tue Sep 24 2019 Marian Csontos <mcsontos@redhat.com> - 7:2.02.186-2
+- Prevent creating VGs with PVs with different logical block sizes.
+- Pvmove runs in exlusively activating mode for exclusively active LVs.
+- Activate thin-pool layered volume as 'read-only' device.
+- Enhance validation for thin and cache pool conversion and swapping.
+
+* Tue Aug 27 2019 Marian Csontos <mcsontos@redhat.com> - 7:2.02.186-1
+- Improve removal of cached devices.
+- Synchronize with udev when dropping snapshot.
+- Add missing device synchronization point before removing pvmove node.
+- Correctly set read_ahead for LVs when pvmove is finished.
+- Fix metadata writes from corrupting with large physical block size.
+
+* Fri Jun 21 2019 Marian Csontos <mcsontos@redhat.com> - 7:2.02.185-2
+- Fix cluster conversions from linear to mirror.
+- Report no_discard_passdown for cache LVs with lvs -o+kernel_discards.
+- Prevent shared active mirror LVs with lvmlockd.
+- Parsing of cache status understand no_discard_passdown.
+
+* Mon May 13 2019 Marian Csontos <mcsontos@redhat.com> - 7:2.02.185-1
+- Fix change of monitoring in clustered volumes.
+- Improve -lXXX%VG modifier which improves cache segment estimation.
+- Add synchronization with udev before removing cached devices.
+- Fix missing growth of _pmspare volume when extending _tmeta volume.
+- Automatically grow thin metadata, when thin data gets too big.
+
+* Mon Apr 29 2019 Marian Csontos <mcsontos@redhat.com> - 7:2.02.184-3
+- Fix shutdown of deamons.
+
+* Wed Apr 17 2019 Marian Csontos <mcsontos@redhat.com> - 7:2.02.184-2
+- Add support for vgsplit with cached devices.
+- Fix conversion of cache pool to RAID1 (2.02.184).
+- Fix signal delivery checking race in libdaemon (lvmetad).
+- Add missing Before=shutdown.target to LVM2 services to fix shutdown ordering.
+
+* Fri Mar 22 2019 Marian Csontos <mcsontos@redhat.com> - 7:2.02.184-1
+- See WHATS_NEW and WHATS_NEW_DM in the documentation directory for details.
+
+* Mon Mar 18 2019 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-10.el7_6.5
+- boom: Bump release.
+
+* Mon Mar 18 2019 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-10.el7_6.4
+- Apply obtain_device_list_from_udev to all libudev calls.
+
+* Mon Dec 17 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-10.el7_6.3
+- Fix component detection for MD RAID version 1.0 and 0.90.
+- Use sync io if async io_setup fails, or when use_aio=0 is set in config.
+- Fix dmstats report printing no output.
+
+* Wed Oct 31 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-10.el7_6.2
+- Fix possible write beyond metadata area.
+
+* Wed Oct 10 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-10.el7_6.1
+- Fix clustered mirror repair.
+
+* Mon Sep 10 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-8
+- Fix lvconvert striped/raid0/raid0_meta to raid6 regression.
+
+* Wed Sep 05 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-7
+- Fix ordering of lvm2 activation and rbdmap services.
+- Fix to avoid locking collisions when monitoring thin-pools.
+
+* Fri Aug 24 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-6
+- Fix direct RAID0 to striped conversion.
+
+* Tue Aug 21 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-5
+- Fix direct RAID0 to striped conversion.
+
+* Tue Aug 21 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-3
+- Fix lvconvert --splitmirror for mirror type (2.02.178).
+- Do not pair cache policy and cache metadata format.
+- Fix mirrors honoring read_only_volume_list.
+- Fix vgcreate with sanlock when PVs are created automatically.
+
+* Tue Jul 31 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-2
+- Add vdo plugin for monitoring VDO devices.
+- Reject conversions on raid1 LVs with split tracked SubLVs.
+- Reject conversions on raid1 split tracked SubLVs.
+- Fix dmstats list failing when no regions exist.
+- Reject conversions of LVs under snapshot.
+- Limit suggested options on incorrect option for lvconvert subcommand.
+
+* Fri Jul 20 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.180-1
+- Never send any discard ioctl with test mode.
+- Fix thin-pool alloc which needs same PV for data and metadata.
+- Enhance vgcfgrestore to check for active LVs in restored VG.
+- Cache can use metadata format 2 with cleaner policy.
+- Fix lvmetad hanging on shutdown.
+- Fix check if resized PV can also fit metadata area.
+
+* Tue Jun 26 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.179-4
+- Rebuild man pages and config file (make generate.)
+
+* Tue Jun 26 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.179-3
+- Add convenient conversions between stripe and linear.
+- Fix snapshot hanging on shutdown.
+- Fix internal error in lvs while pvmove in progress.
+- Fix more coverity issues.
+- Improve message for pvresize.
+
+* Thu Jun 21 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.179-2
+- Fix issue caused by udev considering device open in RW mode a change.
+- Fix leaks and buffer overflow.
+- boom: Update to new minor release.
+
+* Mon Jun 18 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.179-1
+- Fixing known problems with cache and lvmlockd.
+
+* Thu Jun 14 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.178-1
+- Rework disk scanning and when it is used.
+- Add new io layer using libaio for faster scanning.
+- Support activation of component LVs in read-only mode.
+- Avoid non-exclusive activation of exclusive segment types.
+- Restore pvmove support for clusterwide active volumes (2.02.177).
+- Add prioritized_section() to restore cookie boundaries (2.02.177).
+- Again accept striped LV as COW LV with lvconvert -s (2.02.169).
+- Restore usability of thin LV to be again external origin for another thin (2.02.169).
+- See WHATS_NEW and WHATS_NEW_DM in the documentation directory for more.
+
+* Fri Feb 16 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.177-4
+- pvmove enhance accepted states of active LVs.
+- boom: Remove debug output.
+
+* Wed Feb 14 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.177-3
+- boom: Handle LVs passed in --root-device.
+- boom: Allow /dev/VG/LV notation for --root-lv.
+- boom: Detection of invalid root devices.
+- boom: Support long options without dash separator.
+- Add deprecation warning for mirrored mirror log.
+
+* Wed Feb 07 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.177-2
+- boom: Better error handling.
+- boom: Warn user when grub2 integration is missing.
+- Reenable clustered pvmove.
+
+* Tue Jan 23 2018 Marian Csontos <mcsontos@redhat.com> - 7:2.02.177-1
+- boom: Add missing profiles
+- Avoid non-exclusive activation of exclusive segment types.
+- Fix trimming sibling PVs when doing a pvmove of raid subLVs.
+- Preserve exclusive activation during thin snaphost merge.
+- Check array boundaries in allocation tag processing.
+- When writing metadata, consistently skip mdas marked as failed.
+- Reduce checks for active LVs in vgchange before background polling.
+- Ensure _node_send_message always uses clean status of thin pool.
+- Activation tree of thin pool skips duplicated check of pool status.
+
+* Wed Dec 06 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.176-5
+- boom: Update man page.
+- boom: Allow users to disable grub2 configuration.
+- boom: Do not add snapshots submenu unless entries exist.
+- boom: Use fdatasync() for profile and entry files.
+- Fix lvmlockd to use pool lock when accessing _tmeta volume.
+- Report expected sanlock_convert errors only when retries fail.
+- Avoid blocking in sanlock_convert on SH to EX lock conversion.
+- Deactivate missing raid LV legs (_rimage_X-missing_Y_Z) on decativation.
+- Allow extending of raid LVs created with --nosync after a failed repair.
+- Merge adjacent segments when pvmove is finished.
+- Ensure very large numbers used as arguments are not casted to lower values. 
+- Enhance reading and validation of options stripes and stripes_size.
+- Fix printing of default stripe size when user is not using stripes.
+- Activation code for pvmove automatically discovers holding LVs for resume.
+- Make a pvmove LV locking holder.
+- Enhance activation code to automatically suspend pvmove participants.
+- Prevent conversion of thin volumes to snapshot origin when lvmlockd is used.
+- Correct the steps to change lock type in lvmlockd man page.
+- Retry lock acquisition on recognized sanlock errors.
+- Fix lock manager error codes in lvmlockd.
+- Check raid reshape flags in vg_validate().
+- Add support for pvmove of cache and snapshot origins.
+- Ehnance pvmove locking.
+- Deactivate activated LVs on error path when pvmove activation fails.
+
+* Wed Nov 15 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.176-4
+- Avoid importing persistent filter in vgscan/pvscan/vgrename.
+- Fix memleak of string buffer when vgcfgbackup runs in secure mode.
+- Do not print error when clvmd cannot find running clvmd.
+- Prevent start of new merge of snapshot if origin is already being merged.
+- Suppress integrity encryption keys in 'table' output unless --showkeys supplied.
+- Fix offered type for raid6_n_6 to raid5 conversion (raid5_n).
+- Deactivate sub LVs when removing unused cache-pool.
+- Do not take backup with suspended devices.
+- Avoid RAID4 activation on incompatible kernels under all circumstances.
+- Reject conversion request to striped/raid0 on 2-legged raid4/5.
+
+* Thu Nov 09 2017 Bryn M. Reeves <bmr@redhat.com> - 7:2.02.176-3
+- Disable boom package build on s390x.
+
+* Fri Nov 03 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.176-2
+- Add "boom" boot manager.
+
+* Fri Nov 03 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.176-1
+- Fix segfault in lvm_pv_remove in liblvm. (2.02.173)
+- Do not allow storing VG metadata with LV without any segment.
+- Fix printed message when thin snapshot was already merged.
+- Remove created spare LV when creation of thin-pool failed.
+- Avoid reading ignored metadata when MDA gets used again.
+- Fix detection of moved PVs in vgsplit. (2.02.175)
+- Ignore --stripes/--stripesize on RAID takeover
+- Disallow creation of snapshot of mirror/raid subLV (was never supported).
+- Keep Install section only in *.socket systemd units.
+- Improve used paths for generated systemd units and init shells.
+
+* Wed Oct 25 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.175-3
+- Fix regression in more advanced vgname extraction in lvconvert (2.02.169).
+- Allow lvcreate to be used for caching of _tdata LV.
+- Avoid internal error when resizing cache type _tdata LV (not yet supported).
+- Show original converted names when lvconverting LV to pool volume.
+- Distinguish between device not found and excluded by filter.
+- Monitor external origin LVs.
+- Remove unused replicator code, including configure --with-replicators.
+
+* Fri Oct 13 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.175-2
+- Allow lvcreate --type mirror to work with 100%%FREE.
+- Improve selection of resource name for complex volume activation lock.
+- Avoid cutting first character of resource name for activation lock.
+- Support for encrypted devices in fsadm.
+- Improve thin pool overprovisioning and repair warning messages.
+- Fix incorrect adjustment of region size on striped RaidLVs.
+
+* Mon Oct 09 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.175-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
+* Wed Jun 28 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-8
+- Fix reusing of dm_task structure for status reading (used by dmeventd).
+
+* Thu Jun 22 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-7
+- Fix a segfault in RAID.
+
+* Wed Jun 21 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-6
+- Reenable conversion of data and metadata thin-pool volumes to raid.
+- Improve handling of RAID status in lvs.
+- Disable RAID reshape/take-over in a cluster or when snapshot exists.
+
+* Wed Jun 14 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-5
+- Improve lvcreate --cachepool arg validation.
+- Limit maximal size of thin-pool for specific chunk size.
+- Accept truncated files in calls to dm_stats_update_regions_from_fd().
+
+* Wed Jun 07 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-4
+- Converting linear to raid1 using "recover" not "resync".
+- Print a warning about in-use PVs with no VG using them.
+- Disable automatic clearing of PVs that look like in-use orphans.
+
+* Wed Jun 07 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-4
+- Converting linear to raid1 using "recover" not "resync".
+- Print a warning about in-use PVs with no VG using them.
+- Disable automatic clearing of PVs that look like in-use orphans.
+
+* Wed May 31 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-3
+- Cache format2 flag is now using segment name type field compatible with
+  previous versions.
+
+* Wed May 24 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-2
+- Stop using '--yes' mode when fsadm runs without terminal.
+- Extend validation of filesystems resized by fsadm.
+- Enhance lvconvert automatic settings of possible (raid) LV types.
+- Allow lvchange to change properties on a thin pool data sub LV.
+- Fix lvcreate extent percentage calculation for mirrors.
+- Don't reinstate still-missing devices when correcting inconsistent metadata.
+- Properly handle subshell return codes in fsadm.
+- Disallow cachepool creation with policy cleaner and mode writeback.
+
+* Wed May 03 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-1
+- Fix dmstats and dmfilemapd permissions.
+- Fix memory warnings by using mempools for command definition processing.
+- Fix running commands from a script file.
+- Adjust pvresize/pvcreate messages and prompt if underlying device size
+  differs.
+- Preserve region size on raid1 image count changes.
+- Handle insufficient space on RAID takeover.
+- Raise mirror/raid default regionsize to 2MiB.
+
+* Thu Apr 13 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.170-2
+- Fix RPM build - missing upstrem and sources.
+
+* Thu Apr 13 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.170-1
+- Introduce global/fsadm_executable to make fsadm path configurable.
+- Look for limited thin pool metadata size when using 16G metadata.
+- Fix missing lvmlockd LV locks in lvchange and lvconvert.
+- Allow valid lvconvert --regionsize change.
+- Handle insufficient PVs on lvconvert takeover.
+- Fix SIGINT blocking to prevent corrupted metadata.
+- Fix systemd unit existence check for lvmconf --services --startstopservices.
+
+* Wed Mar 29 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.169-3
+- Fix dmfilemapd's Makefile.
+- Update dependencies.
+
+* Wed Mar 29 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.169-2
+- Enable dmfilemapd.
+
+* Tue Mar 28 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.169-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
+* Thu Mar 23 2017 Alasdair Kergon <agk@redhat.com> - 7:2.02.166-2
+- Add clustered ppc64le support to build.
+
+* Thu Feb 09 2017 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.166-1.el7_3.3
+- Fix segfault in lvmetad from missing NULL in daemon_reply_simple.
+
+* Wed Nov 16 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.166-1.el7_3.2
+- Prevent raid4 creation/conversion on non-supporting kernels
+- Add direct striped -> raid4 conversion
+- Fix raid4 parity image pair position on conversions from striped/raid0*
+
+* Wed Oct 12 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.166-1.el7_3.1
+- Fix lvconvert to allow repair for cache raid LVs.
+- Fix time when dmeventd is reloaded on package upgrade to start using new code.
+- Fix libdm versioning for dm_tree_node_size_changed symbol.
+
+* Wed Sep 28 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.166-1
+- Disable lvconvert of thin pool to raid while active.
+- Use dm_config_parse_without_dup_node_check() to speedup metadata reading.
+- Fix lvm2-activation-generator to read all LVM2 config sources. (2.02.155)
+- Fix man entry for dmsetup status.
+- Introduce new dm_config_parse_without_dup_node_check().
+
+* Thu Sep 22 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.165-4
+- Revert lvconvert --repair fix for RAID LVs.
+
+* Wed Sep 21 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.165-3
+- Fix lvchange --discard|--zero for active thin-pool.
+- Fix lvconvert --repair regression for RAID LVs.
+- Always specify snapshot cow LV for monitoring not internal LV. (2.02.165)
+- Ensure memory allocated internally for --filemap histogram bounds are freed.
+- Fix missing display of last created dmstats file map.
+- Use --alloc normal for mirror logs even if the mimages were stricter.
+- Fix reported origin lv field for cache volumes. (2.02.133)
+- Fix lock-holder device for thin pool with inactive thin volumes.
+- Enforce 4MiB or 25% metadata free space for thin pool operations.
+- Fix lvmetad metadata validation when rescanning VG.
+
+* Wed Sep 14 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.165-2
+- Fix possible NULL pointer dereference when checking for monitoring.
+- Add lvmreport(7) man page.
+- Report 0% as dirty (copy%) for cache without any used block.
+- Fix lvm2api reporting of cache data and metadata percent.
+- Restore reporting of metadata usage for cache volumes (2.02.155).
+
+* Wed Sep 07 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.165-1
+- Support raid scrubbing on cache origin LV.
+- Add lvmraid(7) man page.
+- Use udev db to check for mpath components before running pvscan for lvmetad.
+- Improve explanation of udev fallback in libdevmapper.h.
+
+* Mon Sep 05 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.164-5
+- Use udev db to check for mpath components before running pvscan for lvmetad.
+- Use devices/allow_changes_with_duplicate_pvs=1 by default.
+
+* Wed Aug 31 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.164-4
+- Use lsblk -s and lsblk -O in lvmdump only if these options are supported.
+- Fix typo in report/columns_as_rows config option name recognition (2.02.99).
+- Do not monitor cache-pool metadata when LV is just being cleared.
+- Add allocation/cache_pool_max_chunks to prevent misuse of cache target.
+- Fix number of stripes shown in lvcreate raid10 message when too many.
+- Give error not segfault in lvconvert --splitmirrors when PV lies outside LV.
+- Avoid PV tags when checking allocation against parallel PVs. 
+
+* Wed Aug 24 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.164-3
+- Disallow segtype and mirror conversions of raid10 volumes.
+- Fix dmeventd unmonitoring when segment type (and dso) changes.
+- Don't allow lvconvert --repair on raid0 devices or attempt to monitor them.
+- No longer adjust incorrect number of raid stripes supplied to lvcreate.
+- Move lcm and gcd to lib/misc.
+- Suppress some unnecessary --stripesize parameter warnings.
+- Fix 'pvmove -n name ...' to prohibit collocation of RAID SubLVs
+
+* Tue Aug 16 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.164-2
+- Suppress some unnecessary --stripesize parameter warnings.
+- Fix selection of PVs when allocating raid0_meta.
+- Specify max stripes for raid LV types: raid0:64; 1:10; 4,5:63; 6:62; 10:32.
+- Avoid double suffix when naming _rmeta LV paired with _rimage LV.
+
+* Wed Aug 10 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.163-1
+- Add profile for lvmdbusd which uses lvm shell json report output.
+- Restrict in-command modification of some parms in lvm shell.
+- Apply LVM_COMMAND_PROFILE early for lvm shell.
+- Refactor reporting so lvm shell log report collects whole of cmd execution.
+- Support LVM_*_FD envvars to redirect output to file descriptors.
+- Limit use of --corelog and --mirrorlog to mirrors in lvconvert.
+- Reject --nosync option for RAID6 LVs in lvcreate.
+- Do not refresh whole cmd context if profile dropped after processing LVM cmd.
+- Support straightforward lvconvert between striped and raid4 LVs. 
+- Support straightforward lvconvert between raid1 and mirror LVs. 
+- Report supported conversions when asked for unsupported raid lvconvert.
+- Add "--rebuild PV" option to lvchange to allow for PV selective rebuilds.
+- Preserve existing mirror region size when using --repair.
+- Forbid stripe parameters with lvconvert --repair.
+- Unify stripe size validation into get_stripe_params to catch missing cases.
+- Further lvconvert validation logic refactoring.
+- Add "lvm fullreport" man page.
+- Add dm_report_destroy_rows/dm_report_group_output_and_pop_all for lvm shell.
+- Adjust group handling and json production for lvm shell.
+
+* Fri Jul 29 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.162-1
+- Extend vg_validate also to check raid configurations thoroughly.
+- Support lvconvert -Zn also when doing full cache pool conversion.
+- Suppress not zeroing warn when converting to thin LV for non-zeroing tpool.
+- Fix automatic updates of PV extension headers to newest version.
+- Improve lvconvert --trackchanges validation to require --splitmirrors 1.
+- Add note about lastlog built-in command to lvm man page.
+- Fix unrecognised segtype flag message.
+- lvconvert not clears cache pool metadata ONLY with -Zn. 
+- Add allocation/raid_stripe_all_devices to reinstate previous behaviour.
+- Create raid stripes across fixed small numbers of PVs instead of all PVs. 
+- Disallow lvconvert --replace with raid0* LVs. 
+- Fix some lvmetad changed VG metadata notifications that sent uncommitted data.
+- Fix json reporting to escape '"' character that may appear in reported string.
+
+* Thu Jul 28 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.161-3
+- Improve lvmlockd message for lock-start.
+- Improve lvmlockd activation locking error message.
+- Improve lvmlockd error message about missing global lock.
+- Allow lvconvert with implied cache pool.
+- Fix vgsplit with external origin LV. (2.02.161)
+
+* Wed Jul 20 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.161-2
+- Fix output redirection while executing blkdeactivate -m disablequeueing.
+
+* Wed Jul 20 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.161-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
+* Wed Jul 06 2016 Alasdair Kergon <agk@redhat.com> - 7:2.02.160-1
+- Minor fixes from coverity.
+- vgimportclone is now a symlink.
+
+* Wed Jul 06 2016 Alasdair Kergon <agk@redhat.com> - 7:2.02.159-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
+* Mon Jun 13 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.156-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
+* Wed May 04 2016 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.152-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
+* Wed Oct 14 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.130-5
+- Fixup /etc/lvm/archive ownership.
+
+* Wed Oct 14 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.130-4
+- Reinstate /etc/lvm dir content permissions after change in defaults.
+
+* Wed Oct 14 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.130-3
+- Enforce writethrough mode for cleaner policy.
+- Check for enough space in thin-pool in command before creating new thin.
+
+* Tue Sep 15 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.130-2
+- Fix vgimportclone cache_dir path name (2.02.115).
+- Disallow usage of --stripe and --stripesize when creating cache pool.
+- Swapping of LV identifiers handles more complex LVs.
+- Fix VG metadata comparison failure while scanning the VG for lvmetad.
+- Ignore persistent cache if configuration changed. (2.02.127)
+- Do not check for full thin pool when activating without messages (1.02.107).
+
+* Wed Sep 09 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.130-1
+- Fix use of uninitialized device status if reading outdated .cache record.
+- Restore support for --monitor option in lvcreate (2.02.112).
+- Read thin-pool data and metadata percent without flush.
+- Detect blocked thin-pool and avoid scanning their thin volumes.
+- Check if dm device is usable before checking its size (2.02.116).
+- Extend parsing of cache_check version in configure.
+- Make lvpoll error messages visible in lvmpolld's stderr and in syslog.
+- Add 'make install_full_man' to install all man pages regardless of config.
+- Parse thin-pool status with one single routine internally.
+- Add --histogram to select default histogram fields for list and report.
+- Add report fields for displaying latency histogram configuration and data.
+- Add dmstats --bounds to specify histogram boundaries for a new region.
+- Add dm_histogram_to_string() to format histogram data in string form.
+- Add public methods to libdm to access numerical histogram config and data.
+- Parse and store histogram data in dm_stats_list() and dm_stats_populate().
+- Add an argument to specify histogram bounds to dm_stats_create_region().
+- Add dm_histogram_bounds_from_{string,uint64_t}() to parse histogram bounds.
+- Add dm_histogram handle type to represent a latency histogram and its bounds.
+
+* Wed Sep 02 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.129-2
+- Reinstate dm_task_get_info@Base to libdevmapper exports. (1.02.106)
+
+* Mon Aug 31 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.129-1
+- Drop error message when vgdisplay encounters an exported VG. (2.02.27)
+- Fix shared library generation to stop exporting internal functions.(2.02.120)
+- Accept --cachemode with lvconvert.
+- Fix and improve reporting properties of cache-pool.
+- Enable usage of --cachepolicy and --cachesetting with lvconvert.
+- Don't allow to reduce size of thin-pool metadata.
+- Fix debug buffer overflows in cmirrord logging.
+- Add --foreground and --help to cmirrord.
+- Add 'precise' column to statistics reports.
+- Add --precise switch to 'dmstats create' to request nanosecond counters.
+- Add precise argument to dm_stats_create_region().
+- Add support to libdm-stats for precise_timestamps
+- Fix devmapper.pc pkgconfig file to declare -lrt dependency properly.
+
+* Tue Aug 18 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.128-1
+- Allocation setting cache_pool_cachemode is replaced by cache_mode.
+- Don't attempt to close config file that couldn't be opened.
+- Check for valid cache mode in validation of cache segment.
+- Change internal interface handling cache mode and policy.
+- When no cache policy specified, prefer smq (if available) over mq.
+- Add demo cache-mq and cache-smq profiles.
+- Add cmd profilable allocation/cache_policy,cache_settings,cache_mode.
+- Require cache_check 0.5.4 for use of --clear-needs-check-flag.
+- Fix lvmetad udev rules to not override SYSTEMD_WANTS, add the service instead.
+- Fix 'dmstats list -o all' segfault.
+- Separate dmstats statistics fields from region information fields.
+- Add interval and interval_ns fields to dmstats reports.
+- Do not include internal glibc headers in libdm-timestamp.c (1.02.104)
+- Exit immediately if no device is supplied to dmsetup wipe_table.
+- Suppress dmsetup report headings when no data is output. (1.02.104)
+- Adjust dmsetup usage/help output selection to match command invoked.
+- Fix dmsetup -o all to select correct fields in splitname report.
+- Restructure internal dmsetup argument handling across all commands.
+- Add dm_report_is_empty() to indicate there is no data awaiting output.
+- Add more arg validation for dm_tree_node_add_cache_target().
+- Add --alldevices switch to replace use of --force for stats create / delete.
+
+* Mon Aug 10 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.127-1
+- Do not init filters, locking, lvmetad, lvmpolld if command doesn't use it.
+- Order fields in struct cmd_context more logically.
+- Add lock_type to lvmcache VG summary and info structs.
+- Fix regression in cache causing some PVs to bypass filters (2.02.105).
+- Make configure --enable-realtime the default now.
+- Add dmstats.8 man page.
+- Add dmstats --segments switch to create one region per device segment.
+- Add dmstats --regionid, --allregions to specify a single / all stats regions.
+- Add dmstats --allprograms for stats commands that filter by program ID.
+- Add dmstats --auxdata and --programid args to specify aux data and program ID.
+- Add report stats sub-command to provide repeating stats reports.
+- Add clear, delete, list, and print stats sub-commands.
+- Add create stats sub-command and --start, --length, --areas and --areasize.
+- Recognize 'dmstats' as an alias for 'dmsetup stats' when run with this name.
+- Add a 'stats' command to dmsetup to configure, manage and report stats data.
+- Add statistics fields to dmsetup -o.
+- Add libdm-stats library to allow management of device-mapper statistics.
+- Add --nosuffix to suppress dmsetup unit suffixes in report output.
+- Add --units to control dmsetup report field output units.
+- Add support to redisplay column headings for repeating column reports.
+- Fix report header and row resource leaks.
+- Report timestamps of ioctls with dmsetup -vvv.
+- Recognize report field name variants without any underscores too.
+- Add dmsetup --interval and --count to repeat reports at specified intervals.
+- Add dm_timestamp functions to libdevmapper.
+- Recognise vg/lv name format in dmsetup.
+- Move size display code to libdevmapper as dm_size_to_string.
+
+* Tue Jul 28 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.126-1
+- Fix long option hyphen removal. (2.02.122)
+- Fix clvmd freeze if client disappears without first releasing its locks.
+- Fix lvconvert segfaults while performing snapshots merge.
+- Ignore errors during detection if use_blkid_wiping=1 and --force is used.
+- Recognise DM_ABORT_ON_INTERNAL_ERRORS env var override in lvm logging fn.
+- Fix alloc segfault when extending LV with fewer stripes than in first seg.
+- Fix handling of cache policy name.
+- Set cache policy before with the first lvm2 cache pool metadata commit.
+- Fix detection of thin-pool overprovisioning (2.02.124).
+- Fix lvmpolld segfaults on 32 bit architectures.
+- Add lvmlockd lock_args validation to vg_validate.
+- Fix ignored --startstopservices option if running lvmconf with systemd.
+- Hide sanlock LVs when processing LVs in VG unless named or --all used.
+- Introduce libdevmapper wrappers for all malloc-related functions.
+
+* Fri Jul 10 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.125-2
+- lvm2-lockd subpackage requires dlm-lib or sanlock-lib or both
+  based on which support is compiled in.
+- lvm2-lockd subpackage requires dlm-lib instead of former dlm
+  for lvmlockd daemon with dlm support.
+
+* Tue Jul 07 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.125-1
+- Fix getline memory usage in lvmpolld.
+- Add support --clear-needs-check-flag for cache_check of cache pool metadata.
+- Add lvmetactl for developer use only.
+- Rename global/lock_retries to lvmlockd_retries.
+- Replace --enable-lvmlockd by --enable-lockd-sanlock and --enable-lockd-dlm.
+
+* Mon Jul 06 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.124-1
+- Add lvm2-lockd subpackage with technical preview of lvm locking daemon.
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
+* Wed Jan 28 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.115-3
+- Preserve chunk size with repair and metadata swap of a thin pool.
+- Fix raid --splitmirror 1 functionality (2.02.112).
+- Fix tree preload to handle splitting raid images.
+
+* Thu Jan 22 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.115-2
+- Remove rules from 10-dm.rules which handle multipath, rules for handling
+  multipath devices are directly part of device-mapper-multipath package.
+
+* Wed Jan 21 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.115-1
+- Report segment types without monitoring support as undefined.
+- Support lvchange --errorwhenfull for thin pools.
+- Improve the processing and reporting of duplicate PVs.
+- Add support for lvcreate --errorwhenfull y|n for thin pools
+- Fix lvconvert --repair to honour resilience requirement for segmented RAID LV.
+- Also call lvscan --cache in dmeventd for mirror device update in lvmetad.
+- Filter out partitioned device-mapper devices as unsuitable for use as PVs.
+- Also notify lvmetad about filtered device if using pvscan --cache DevicePath.
+- Add report/compact_output to lvm.conf to enable/disable compact report output.
+- Rename lv_error_when_full reporting field to lv_when_full.
+- Reduce severity of ioctl error message when dmeventd waitevent is interrupted.
+- Report 'unknown version' when incompatible version numbers were not obtained.
+- Add dm_report_compact_fields to remove empty fields from report output.
+- Add BuildRequires: device-mapper-persistent-data for proper thin_check configuration.
+
+* Wed Jan 14 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.114-5
+- Report lv_health_status and health attribute also for thin pool.
+- Add lv_error_when_full reporting field.
+- Add support for lvcreate --errorwhenfull y|n for thin pools.
+- Report more info from thin pool status (out of data, metadata-ro, fail).
+- Support error_if_no_space for thin pool target.
+- Do not filter out snapshot origin LVs as unusable devices for an LVM stack.
+- Fix process_each_pv to match item by device not by its PV device name only.
+
+* Wed Jan 07 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.114-4
+- Fix incorrect rimage names when converting from mirror to raid1 LV (2.02.112).
+- Avoid excessive re-reading of metadata and related error messages in pvremove.
+- Check for cmirror availability during cluster mirror creation and activation.
+- Fix possible segfault when using cache_policy and cache_settings fields.
+- Fix reserved values recognition for cache_policy and cache_settings fields.
+
+* Wed Dec 17 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.114-3
+- Add cache_policy and cache_settings reporting fields.
+- Add missing recognition for --binary option with {pv,vg,lv}display -C.
+- Fix vgimportclone to notify lvmetad about changes done if lvmetad is used.
+- Fix vgimportclone to properly override config if it is missing in lvm.conf.
+- Fix automatic use of configure --enable-udev-systemd-background-jobs.
+- Correctly rename active split LV with -splitmirrors for raid1.
+- Still restrict mirror region size to power of 2 when VG extent size is not.
+- Fix segfault while using selection with regex and unbuffered reporting.
+- Remove unimplemented dm_report_set_output_selection from libdevmapper.h.
+
+* Mon Dec 01 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.114-2
+- Release socket in daemon_close and protocol string in daemon_open error path.
+- Add --cachepolicy and --cachesettings to lvcreate.
+- Fix regression when parsing /dev/mapper dir (2.02.112).
+- Fix typo in clvmd initscript causing CLVMD_STOP_TIMEOUT var to be ignored.
+
+* Wed Nov 26 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.113-1
+- Fix missing rounding to 64KB when estimating optimal thin pool chunk size.
+- Fix size in pvresize "Resizing to ..." verbose msg to show proper result size.
+- Add --cachepolicy and --cachesettings options to lvchange.
+- Validate that converted volume and specified pool volume differ in lvconvert.
+- Fix regression in vgscan --mknodes usage (2.02.112).
+- Respect --prefix when setting CLMVD_PATH configure (2.02.89).
+- Default to configure --enable-udev-systemd-background-jobs for systemd>=205.
+- Fix ignore_vg() to properly react on various vg_read errors (2.02.112).
+- Failed recovery returns FAILED_RECOVERY status flag for vg_read().
+- Exit with non-zero status code when pvck encounters a problem.
+- Fix clean_tree after activation/resume for cache target (2.02.112).
+- Fix memory corruption with sorting empty string lists (1.02.86).
+- Fix man dmsetup.8 syntax warning of Groff
+- Accept unquoted strings and / in place of {} when parsing configs.
+
+* Tue Nov 11 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.112-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
+* Mon Sep 29 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.111-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
+* Wed Mar 26 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-14
+- Increase wait time for finishing initial lvmetad scan that's run in parallel.
+- Reinitialise lvmcache properly on fork to fix polldaemon exiting prematurely.
+- Add more cleanup for stray "cpg_dispatch_failed" cmirror messages.
+
+* Wed Mar 19 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-13
+- Use VG read lock during 'pvscan --cache -aay' autoactivation.
+- Issue a VG refresh before autoactivation only if the PV has changed/is new.
+- Add flag to lvmetad protocol to indicate the PV scanned has changed/is new.
+- Also add vgname to lvmetad protocol when referencing VGs for PVs scanned.
+- Use correct PATH_MAX for locking dir path.
+
+* Wed Mar 12 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-12
+- Do not try to check empty pool with scheduled messages.
+- Fix return value in pool_has_message() when quering for any message.
+- Fix dmeventd logging with parallel wait event processing.
+
+* Thu Mar 06 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-11
+- Cleanup stray "cpg_dispatch failed: CS_ERR_BAD_HANDLE" messages for cmirror.
+
+* Wed Mar 05 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-10
+- Fix cache consistency in lvmetad when PV moves around.
+- Fix memleak when lvmetad discovers PV to appear on another device.
+- Fix invalid memory read in lvmetad that could cause a deadlock.
+
+* Fri Feb 28 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-9
+- Use configure --with-cache=internal to enable cache support code.
+
+* Thu Feb 27 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-8
+- Fix incorrect calculation of snapshot cow size.
+
+* Wed Feb 26 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-7
+- Fix previous build that reinstated obsoleted multipath rule in 10-dm.rules.
+
+* Wed Feb 26 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-6
+- Add initial support for LVM cache and cachepool segment types.
+- Include various bug fixes from upcoming lvm2 v2.02.106 release
+  detailed in WHATS_NEW and WHATS_NEW_DM file.
+
+* Fri Feb 21 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-5
+- Avoid a PV label scan while in a critical section.
+- Add Requires: resource-agents to lvm2-cluster and cmirror subpackage.
+- Add new lvm2-cluster-standalone and cmirror-standalone subpackages.
+- Add systemd native service for clvmd, cmirrord and clustered LV activation.
+- Move obsolete clvmd/cmirrord initscripts to lvm2-sysvinit subpackage.
+- Use --ignoreskippedcluster in lvm2-monitor initscript/systemd unit.
+- Use --ignoreskippedcluster in activation systemd units if use_lvmetad=0.
+
+* Wed Feb 19 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-4
+- Fix unwanted drop of hold flocks on forked children.
+- Fix merging of old snapshot into thin volume origin.
+- Exit dmeventd with pidfile cleanup instead of raising SIGKILL on DIE request.
+- Add new DM_EVENT_GET_PARAMETERS request to dmeventd protocol.
+- Do not use systemd's reload for dmeventd restart, use dmeventd -R instead.
+
+* Wed Feb 05 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-3
+- Drop obsolete multipath rules from 10-dm.rules.
+- Drop cryptsetup rules from 10-dm.rules - cryptsetup >= 1.1.3 sets them.
+- Avoid trying to convert single to thin pool and volume at the same time.
+- Detect thin feature external_origin_extend and limit extend when missing.
+
+* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 7:2.02.105-2
+- Mass rebuild 2014-01-24
+
+* Wed Jan 22 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-1
+- Online thin pool metadata resize requires 1.10 kernel thin pool target.
+- Fix thin LV flagging for udev to skip scanning only if the LV is wiped.
+- Replace use of xfs_check with xfs_repair in fsadm.
+- Mark lvm1 format metadata as FMT_OBSOLETE. Do not use it with lvmetad.
+- Invalidate cached VG struct after a PV in it gets orphaned. (2.02.87)
+- Mark pool format metadata as FMT_OBSOLETE.
+- Syntax and spelling fixes in some man pages.
+- Dependency scan counts with snapshots and external origins.
+- Make sure VG extent size is always greater or equal to PV phys. block size.
+- Optimize double call of stat() for cached devices.
+- Enable support for thin provisioning for default configuration.
+- Return success when inserting dirs and links into device cache.
+- Test for remote exclusive activation after activation fails.
+- Support lvconvert --merge for thin snapshots.
+- Add support to read thin device id from table line entry.
+- Extend lv_remove_single() to not print info about removed LV.
+- Replace open_count check with lv_check_not_in_use() for snapshot open test.
+- Add error messages with LV names for failing lv refresh.
+- Add --splitsnapshot to lvconvert to separate out cow LV.
+- Reinstate origin reload to complete lvconvert -s with active LVs. (2.02.98)
+- Select only active volume groups if vgdisplay -A is used.
+- Add -p and LVM_LVMETAD_PID env var to lvmetad to change pid file.
+- Allow lvmetad to reuse stale socket.
+- Only unlink lvmetad socket on error if created by the same process.
+- Append missing newline to lvmetad missing socket path error message.
+- Check for non-zero aligment in _text_pv_add_metadata_area() to not div by 0.
+- Add allocation/use_blkid_wiping to lvm.conf to enable blkid wiping.
+- Enable blkid_wiping by default if the blkid library is present.
+- Add configure --disable-blkid_wiping to disable libblkid signature detection.
+- Add -W/--wipesignatures lvcreate option to support wiping on new LVs.
+- Add allocation/wipe_signatures_when_zeroing_new_lvs to lvm.conf.
+- Do not connect to lvmetad on vg/lvchange --sysinit -aay and socket absent.
+- Use lv_check_not_in_use() when testing device in use before merging.
+- Check for failure of lvmcache_add_mda() when writing pv.
+- Check for failure of dev_get_size() when reporting device size.
+- Drop extra unneeded '/' when scanning sysfs directory.
+- Fix undef value if skipped clustered VG ignored for toollib PV seg. (2.02.103)
+- Support validation of VG/LV names in liblvm/python.
+- Allow creation of PVs with arguments to liblvm/python.
+- Ensure sufficient metadata copies retained in liblvm/python vgreduce.
+- Fix installation of profiles from conf subdir when not building in srcdir.
+- Show UUIDs for missing PVs in reports.
+- Add reporting of thin_id device id for thin volumes.
+- Fix reporting of empty numerical values for recently-added fields.
+- Use _field_set_percent/value in reporting code.
+- Return success when LV cannot be activated because of volume_list filter.
+- Return proper error state for remote exclusive activation.
+- Fix clvmd message verification to not reject REMOTE flag. (2.02.100)
+- Compare equality of double values with DBL_EPSILON predefined constant.
+- Use additional gcc warning flags by default.
+- Add ignore_lvm_mirrors to config file to read/ignore labels on mirrors.
+- Fix endless loop in blkdeactivate <device>... if unable to umount/deactivate.
+- Remove 2>/dev/null from three lvm commands executed by vgimportclone.
+- Check for open count with a timeout before removal/deactivation of an LV.
+- Report RAID images split with tracking as out-of-sync ("I").
+- Add workaround for deactivation problem of opened virtual snapshot.
+- Disable unsupported merge for virtual snapshot.
+- Revert activation of activated nodes if a node preload callback fails.
+- Avoid busy looping on CPU when dmeventd reads event DM_WAIT_RETRY.
+- Ensure global mutex is held when working with dmeventd thread.
+- Drop taking timeout mutex for un/registering dmeventd monitor.
+- Allow section names in config file data to be quoted strings.
+- Close fifos before exiting in dmeventd restart() error path.
+- Catch invalid use of string sort values when reporting numerical fields.
+- Consistently report on stderr when device is not found for dmsetup info.
+- Skip race errors when non-udev dmsetup build runs on udev-enabled system.
+- Skip error message when holders are not present in sysfs.
+- Require libpthread to build now.
+- Add BuildRequires: libblkid-devel for blkid wiping functionality.
+
+* Wed Jan 15 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.103-11
+- Do not drop SYSTEMD_READY for non-activating events (LVM on MD or loop).
+- Add missing AC_TRY_CCFLAG defined in acinclude.m4 for configuration checks.
+
+* Tue Jan 07 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.103-10
+- Properly apply RELRO and PIE compiler and linker options.
+
+* Tue Jan 07 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.103-9
+- Consolidate file permissions for all packaged files.
+
+* Mon Jan 06 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.103-8
+- Use major:minor in lvm2-pvscan@.service for proper global_filter application.
+- Fix SYSTEMD_READY assignment for foreign devices in lvmetad udev rules.
+- Handle failures in temporary mirror used when adding images to mirrors.
+- Compile/link executables with new RELRO and PIE options (non-static builds).
+- Replace hardcoded sbin dir value with rpm variable for clvmd and cmirrord.
+- Install all binary executables with 0555 permissions.
+- Configure with --enable-write_install for writeable executables
+  during rpm processing of debug info.
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 7:2.02.103-7
+- Mass rebuild 2013-12-27
+
+* Wed Nov 27 2013 Peter Rajnoha <prajnoha@redhat.com> - 2.02.103-6
+- Do not fail the whole autoactivation if the VG refresh done before fails.
+
+* Tue Nov 12 2013 Peter Rajnoha <prajnoha@redhat.com> - 2.02.103-5
+- Fix missing lvmetad scan for PVs found on MD partitions.
+- Add internal flag for temporary LVs to properly direct udev to not interfere.
+- Respect DM_UDEV_DISABLE_OTHER_RULES_FLAG in lvmetad udev rules.
+- Workaround VG refresh race during autoactivation by retrying the refresh.
+
+* Thu Oct 24 2013 Peter Rajnoha <prajnoha@redhat.com> - 2.02.103-4
+- Add dev-block-<major>:<minor>.device systemd alias for complete PV tracking.
+- Use major:minor as short form of --major and --minor arg for pvscan --cache.
+- Fix lvconvert swap of poolmetadata volume for active thin pool.
+
+* Fri Oct 18 2013 Peter Rajnoha <prajnoha@redhat.com> - 2.02.103-3
+- Add configure --enable-udev-systemd-background-jobs.
+- Add lvm2-pvscan@.service to run pvscan as a service for lvmetad/autoactivation.
+
+* Thu Oct 10 2013 Peter Rajnoha <prajnoha@redhat.com> - 2.02.103-2
+- Fix LV_NOSCAN flag so it's properly recognized as internal LV flag.
+
+* Thu Oct 10 2013 Peter Rajnoha <prajnoha@redhat.com> - 2.02.103-1
+- Fix possible race during daemon worker thread creation (lvmetad).
+- Fix possible deadlock while clearing lvmetad cache for full rescan.
+- Fix possible race while creating/destroying memory pools.
+- Fix failing metadata repair when lvmetad is used.
+- Fix incorrect memory handling when reading messages from lvmetad.
+- Fix locking in lvmetad when handling the PV which is gone.
+- Run full scan before vgrename operation to avoid any cache name collision.
+- Recognize new flag to skip udev scanning in udev rules and act appropriately.
+- Add support for flagging an LV to skip udev scanning during activation.
+- Improve message when unable to change discards setting on active thin pool.
+- Fix lvconvert when converting to a thin pool and thin LV at once.
+- Ensure vgid matches before removing vgname entry from lvmetad cache.
+- Add --ignoreskippedcluster for exit status success when clustered VGs skipped.
+- Fix 3 minute udev timeout so that it is applied for all LVM volumes.
+- Fix thin/raid & activation config defaults with configure --disable-devmapper.
+- Fix RAID calculation for sufficient allocatable space.
+- lvconvert from linear to mirror or RAID1 now honors mirror_segtype_default.
+- Add thin-performance configuration profile.
+- Add lvm.conf allocation/thin_pool_chunk_size_policy option.
+- Fix contiguous & cling allocation policies for parity RAID.  (2.02.100)
+- Have lvmconf --enable/disable-cluster reset/set use_lvmetad.
+- Add seg_size_pe field to reports.
+- Support start+length notation with command line PE ranges.
+- Exit cleanly with message when pvmove cannot restart because LV is inactive.
+- Define symbolic names for subsystem udev flags in libdevmapper for easier use.
+- Make subsystem udev rules responsible for importing DM_SUBSYSTEM_UDEV_FLAG*.
+- Start using a distinct Epoch number in pkg version for major RHEL release.
+
+* Tue Sep 24 2013 Peter Rajnoha <prajnoha@redhat.com> - 2.02.102-1
+- Fix missing build dependency for scripts subdir in Makefile.
+- Fix node up/down handling in clvmd corosync module.
+- Fix 3-thread clvmd deadlock triggered by cleanup on EOF from client.
+- Remove VG from lvmetad before restoring it with vgcfgrestore.
+- Add devtypes report command to display built-in recognised block device types.
+- Fix CC Makefile override which had reverted to using built-in value. (2.02.75)
+- Recognise bcache block devices in filter (experimental).
+- Run lvm2-activation-net after lvm2-activation service to prevent parallel run.
+- Add man page entries for lvmdump's -u and -l options.
+- Fix lvm2app segfault while using lvm_list_pvs_free fn if there are no PVs.
+- Improve of clvmd singlenode locking simulation.
+- lvconvert no longer converts LVs of "mirror" segment type to thinpool.
+- lvconvert no longer converts thinpool sub-LVs to "mirror" segment type.
+- Direct udev to use 3min timeout for LVM devices. Recent udev has default 30s.
+- Do not scan multipath or RAID components and avoid incorrect autoactivation.
+- Fix MD/loop udev handling to fire autoactivation after setup or coldplug only.
+- Make RAID capable of single-machine exclusive operations in a cluster.
+- Drop calculation of read ahead for deactivated volume.
+- Check for exactly one lv segment in validation of thin pools and volumes.
+- Fix dmeventd unmonitoring of thin pools.
+- Fix lvresize for stacked thin pool volumes (i.e. mirrors).
+- Write Completed debug message before reinstating log defaults after command.
+- Refresh existing VG before autoactivation (event retrigger/device reappeared).
+- Use pvscan -b in udev rules to avoid a deadlock on udev process count limit.
+- Add pvscan -b/--background for the command to be processed in the background.
+- Don't assume stdin file descriptor is readable.
+- Avoid unlimited recursion when creating dtree containing inactive pvmove LV.
+- Require exactly 3 arguments for lvm2-activation-generator. Remove defaults.
+- Inform lvmetad about any lost PV label to make it in sync with system state.
+- Support most of lvchange operations on stacked thin pool meta/data LVs.
+- Enable non-clustered pvmove of snapshots and snapshot origins.
+- Add ability to pvmove non-clustered RAID, mirror, and thin volumes.
+- Make lvm2-activation-generator silent unless it's in error state.
+- Remove "mpath major is not dm major" msg for mpath component scan (2.02.94).
+- Prevent cluster mirror logs from being corrupted by redundant checkpoints.
+- Fix ignored lvmetad update on loop device configuration (2.02.99).
+- Use LVM_PATH instead of hardcoded value in lvm2 activation systemd generator.
+- Fix vgck to notice on-disk corruption even if lvmetad is used.
+- Move mpath device filter before partitioned filter (which opens devices).
+- Require confirmation for vgchange -c when no VGs listed explicitly.
+- Also skip /var and /var/log by default in blkdeactivate when unmounting.
+- Add support for bind mounts in blkdeactivate.
+- Add blkdeactivate -v/--verbose for debug output from external tools used.
+- Add blkdeactivate -e/--errors for error messages from external tools used.
+- Suppress messages from external tools called in blkdeactivate by default.
+- Fix inability to remove a VG's cluster flag if it contains a mirror.
+- Fix bug making lvchange unable to change recovery rate for RAID.
+- Prohibit conversion of thin pool to external origin.
+- Workaround gcc v4.8 -O2 bug causing failures if config/checks=1 (32bit arch).
+- Verify clvmd message validity before processing and log error if incorrect.
+- When creating PV on existing LV don't forbid reserved LV names on LVs below.
+- When converting mirrors, default segtype should be the same unless specified.
+- Make "raid1" the default mirror segment type.
+- Fix clogd descriptor leak when daemonizing.
+- Fix clvmd descriptor leak on restart.
+- Add pipe_open/close() to use instead of less efficient/secure popen().
+- Inherit and apply any profile attached to a VG if creating new thin pool.
+- Ignore previous LV seg with alloc contiguous & cling when num stripes varies.
+- Set use_lvmetad=0 on lvmconf --enable-cluster, reset to default on --disable-cluster.
+- Tidy dmeventd fifo initialisation.
+- Detect invalid sector supplied to 'dmsetup message'.
+- Free any previously-set string if a dm_task_set_* function is called again.
+- Do not allow passing empty new name for dmsetup rename.
+- Display any output returned by 'dmsetup message'.
+- Add dm_task_get_message_response to libdevmapper.
+- Create dmeventd timeout threads as "detached" so exit status is freed.
+- Add DM_ABORT_ON_INTERNAL_ERRORS env var support to abort on internal errors.
+
+* Wed Jul 31 2013 Peter Rajnoha <prajnoha@redhat.com> - 2.02.99-1
+- o Features/Extensions/Additions:
+- Add initial support thin pool lvconvert --repair.
+- Add support for poolmetadataspare LV, that will be used for pool recovery.
+- Improve activation order when creating thin pools in non-clustered VG.
+- Add lvm2-activation-net systemd unit to activate LVs on net-attached storage.
+- Automatically flag thin snapshots to be skipped during activation.
+- Add support for persistent flagging of LVs to be skipped during activation.
+- Make selected thinp settings customizable by a profile.
+- Support storing profile name in metadata for both VGs and LVs.
+- Add support for configuration profiles.
+- Add support for thin volumes in vgsplit.
+- Add lvresize support for online thin pool metadata volume resize.
+- Add detection for thin pool metadata resize kernel support.
+- Add vg->vg_ondisk / lv_ondisk() holding committed metadata.
+- Add detection of mounted fs also for vgchange deactivation.
+- Avoid a global lock in pvs when lvmetad is in use.
+- Detect maximum usable size for snapshot for lvresize.
+- Improve RAID kernel status retrieval to include sync_action/mismatch_cnt.
+- Add external origin support for lvcreate.
+- Support automatic config validation.
+- Add PV header extension: extension version, flags and bootloader areas.
+- Initial support for lvconvert of thin external origin.
+- Improve activation code for better support of stacked devices.
+- vgimport '--force' now allows import of VGs with missing PVs.
+- Allow removal or replacement of RAID LV components that are error segments.
+- Make 'vgreduce --removemissing' able to handle RAID LVs with missing PVs.
+- Add lvconvert support to swap thin pool metadata volume.
+- Allow vgcfgrestore of lvm2 metadata with thin volumes if --force is used.
+- Give precedence to EMC power2 devices with duplicate PVIDs.
+- Recognise Storage Class Memory (IBM S/390) devices in filter.
+- Recognise STEC skd devices in filter.
+- Recognise Violin Memory vtms devices in filter.
+- Support discards for non-power-of-2 thin pool chunks.
+- Automatically restore MISSING PVs with no MDAs.
+- Support allocation of pool metadata with lvconvert command.
+- Detect mounted fs also via reading /proc/self/mountinfo.
+- o Command Interface/Options:
+- Support ARG_GROUPABLE with merge_synonym (for --raidwritemostly).
+- Add --ignoreactivationskip to lvcreate/vgchange/lvchange to ignore skip flag.
+- Add --setactivationskip to lvcreate/lvchange to set activation skip flag.
+- Add --type profilable to lvm dumpconfig to show profilable config settings.
+- Add --mergedconfig to lvm dumpconfig for merged --config/--profile/lvm.conf.
+- Support changing VG/LV profiles: vgchange/lvchange --profile/--detachprofile.
+- Add new --profile command line arg to select a configuration profile for use.
+- For creation of snapshot require size for at least 3 chunks.
+- Do not accept size parameters bigger then 16EiB.
+- Accept --yes in all commands so test scripts can be simpler.
+- Add lvcreate/lvchange --[raid]{min|max}recoveryrate for raid LVs.
+- Add lvchange --[raid]writemostly/writebehind support for RAID1
+- Add lvchange --[raid]syncaction for scrubbing of RAID LVs.
+- Add --validate option to lvm dumpconfig to validate current config on demand.
+- Add --ignoreadvanced and --ignoreunsupported switch to lvm dumpconfig.
+- Add --withcomments and --withversions switch to lvm dumpconfig.
+- Add --type {current|default|missing|new} and --atversion to lvm dumpconfig.
+- Add --bootloaderareasize to pvcreate and vgconvert to create bootloader area.
+- Do not take a free lv name argument for lvconvert --thinpool option.
+- Allow lvconvert --stripes/stripesize only with --mirrors/--repair/--thinpool.
+- Do not ignore -f in lvconvert --repair -y -f for mirror and raid volumes.
+- Support use of option --yes for lvchange --persistent.
+- Fix clvmd support for option -d and properly use its argument.
+- o Reporting:
+- Issue an error msg if lvconvert --type used incorrectly with other options.
+- Use LOG_DEBUG/ERR msg severity instead default for lvm2-activation-generator.
+- Add LV report fields: raid_mismatch_count/raid_sync_action/raid_write_behind.
+- Add LV reporting fields raid_min_recovery_rate, raid_max_recovery_rate.
+- Add sync_percent as alias for copy_percent LV reporting field.
+- Add lv_ prefix to modules reporting field.
+- Use units B or b (never E) with no decimal places when displaying sizes < 1k.
+- List thin-pool and thin modules for thin volumes.
+- Add 's(k)ip activation' bit to lvs -o lv_attr to indicate skip flag attached.
+- Improve error loging when user tries to interrupt commands.
+- Add vgs/lvs -o vg_profile/lv_profile to report profiles attached to VG/LV.
+- Report lvs volume type 'e' with higher priority.
+- Report lvs volume type 'o' also for external origin volumes.
+- Report lvs target type 't' only for thin pools and thin volumes.
+- Add "active" LV reporting field to show activation state.
+- Add "monitor" segment reporting field to show dmevent monitoring status.
+- Add explicit message about unsupported pvmove for thin/thinpool volumes.
+- Add pvs -o pv_ba_start,pv_ba_size to report bootloader area start and size.
+- Fix pvs -o pv_free reporting for PVs with zero PE count.
+- Report blank origin_size field if the LV doesn't have an origin instead of 0.
+- Report partial and in-sync RAID attribute based on kernel status
+- Log output also to syslog when abort_on_internal_error is set.
+- Change lvs heading Copy% to Cpy%%Sync and print RAID4/5/6 sync% there too.
+- Report error for nonexisting devices in dmeventd communication.
+- Reduce some log_error messages to log_warn where we don't fail.
+- o Configuration:
+- Add lvm.conf thin_repair/dump_executable and thin_repair_options.
+- Add activation/auto_set_activation_skip to control activation skip flagging.
+- Add default.profile configuration profile and install it on make install.
+- Add config/profile_dir to set working directory to load profiles from.
+- Use mirror_segtype_default if type not specified for linear->mirror upconvert.
+- Refine lvm.conf and man page documentation for autoactivation feature.
+- Override system's global_filter settings for vgimportclone.
+- Find newest timestamp of merged config files.
+- Add 'config' section to lvm.conf to set the way the LVM configuration is handled.
+- Add global/raid10_segtype_default to lvm.conf.
+- Accept activation/raid_region_size in preference to mirror_region_size config.
+- Add log/debug_classes to lvm.conf to control debug log messages.
+- Allow empty activation/{auto_activation|read_only|}_volume_list config option.
+- Add lvm.conf option global/thin_disabled_features.
+- Add lvm.conf thin pool allocation settings thin_pool_{chunk_size|discards|zero}.
+- Relax ignore_suspended_devices to read from mirrors that don't have a device marked failed.
+- o Documentation:
+- Add man page entries for profile configuration and related options.
+- Document lvextend --use-policies option in man.
+- Improve lvcreate, lvconvert and lvm man pages.
+- o API/interfaces:
+- liblvm/python API: Additions: PV create/removal/resize/listing
+- liblvm/python API: Additions: LV attr/origin/Thin pool/Thin LV creation
+- Fix exported symbols regex for non-GNU busybox sed.
+- Add LV snapshot support to liblvm and python-lvm.
+- Fix lvm2app to return all property sizes in bytes (not sectors).
+- Fix lvm2app and return lvseg discards property as string.
+- Remove python liblvm object. systemdir can only be changed using env var now.
+- Add DM_DISABLE_UDEV environment variable to manage dev nodes by libdm only.
+- Add dm_get_status_snapshot() for parsing snapshot status.
+- Append discards and read-only fields to exported struct dm_status_thin_pool.
+- Validate passed params to dm_get_status_raid/thin/thin_pool().
+- Fix dm_task_set_cookie to properly process udev flags if udev_sync disabled.
+- Add dm_mountinfo_read() for parsing /proc/self/mountinfo.
+- Add dm_config_write_{node_out/one_node_out} for enhanced config output.
+- Add dm_config_value_is_bool to check for boolean value in supported formats.
+- Add DM_ARRAY_SIZE public macro.
+- Add DM_TO_STRING public macro.
+- Implement ref-counting for parents in python lib.
+- o Fixes (general)
+- Do not zero init 4KB of thin snapshot for non-zeroing thin pool (2.02.94).
+- Correct thin creation error paths.
+- Add whole log_lv and metadata_lv sub volumes when creating partial tree.
+- Properly use snapshot layer for origin which is also thin volume.
+- Avoid generating metadata backup when calling update_pool_lv().
+- Send thin messages also for active thin pool and inactive thin volume.
+- Avoid creation of multiple archives for one command.
+- Avoid flushing thin pool when just requesting transaction_id.
+- Fix use of too big chunks of memory when communication with lvmetad.
+- Also filter partitions on mpath components if multipath_component_detection=1.
+- Do not use persistent filter with lvmetad.
+- Move syslog code out of signal handle in dmeventd.
+- Fix lvresize --use-policies of VALID but 100% full snapshot.
+- Skip monitoring of snapshots that are already bigger then origin.
+- Refuse to init a snapshot merge in lvconvert if there's no kernel support.
+- Fix alignment of PV data area if detected alignment less than 1 MB (2.02.74).
+- Fix premature DM version checking which caused useless mapper/control access.
+- Fix creation and removal of clustered snapshot.
+- Fix clvmd caching of metadata when suspending inactive volumes.
+- Fix lvmetad error path in lvmetad_vg_lookup() for null vgname.
+- Fix clvmd _cluster_request() return code in memory fail path.
+- Fix vgextend to not allow a PV with 0 MDAs to be used while already in a VG.
+- Fix PV alignment to incorporate alignment offset if the PV has zero MDAs.
+- Fix missing cleanup of flags when the LV is detached from pool.
+- Fix check for some forbidden discards conversion of thin pools.
+- Fix blkdeactivate to handle nested mountpoints and mangled mount paths.
+- Synchronize with udev in pvscan --cache and fix dangling udev_sync cookies.
+- Fix autoactivation to not autoactivate VG/LV on each change of the PVs used.
+- Limit RAID device replacement to repair only if LV is not in-sync.
+- Disallow RAID device replacement or repair on inactive LVs.
+- Unlock vg mutex in error path when lvmetad tries to lock_vg.
+- Detect key string duplication failure in config_make_nodes_v in libdaemon.
+- Disallow pvmove on RAID LVs until they are addressed properly
+- Recognize DM_DISABLE_UDEV environment variable for a complete fallback.
+- Do not verify udev operations if --noudevsync command option is used.
+- When no --stripes argument is given when creating a RAID10 volume, default to 2 stripes.
+- Do not allow lvconvert --splitmirrors on RAID10 logical volumes.
+- Skip mlocking [vectors] on arm architecture.
+- Repair a mirrored log before the mirror itself when both fail.
+- Don't use lvmetad in lvm2-monitor.service ExecStop to avoid a systemd issue.
+- Avoid trying to read a mirror that has a failed device in its mirrored log.
+- Fix 'dmsetup splitname -o' to not fail if used without '-c' switch (1.02.68).
+- Fix segfault for truncated string token in config file after the first '"'.
+- Fix config node lookup inside empty sections to not return the section itself.
+- Fix parsing of 64bit snapshot status in dmeventd snapshot plugin.
+- Always return success on dmeventd -V command call.
+- o Fixes (segfaults/crashes/deadlocks/races):
+- Fix segfault if devices/global_filter is not specified correctly.
+- Fix segfault when reporting raid_syncaction for older kernels.
+- Fix vgcfgrestore crash when specified incorrect vg name.
+- Avoid crash-inducing race in lvmetad when VG disappears during rename.
+- Fix possible race while removing metadata from lvmetad.
+- Fix possible deadlock when querying and updating lvmetad at the same time.
+- Check for memory failure of dm_config_write_node() in lvmetad.
+- Fix crash in pvscan --cache -aay triggered by non-mda PV.
+- Prevent double free error after dmeventd call of _fill_device_data().
+- o Fixes (resource leaks/memleaks):
+- Release memory allocated with _cached_info().
+- Release memory and unblock signals in lock_vol error path.
+- Fix memory resource leak in memlocking error path.
+- Fix memleak in dmeventd thin plugin in device list obtaining err path.
+- Fix socket leak on error path in lvmetad's handle_connect.
+- Fix memleak on error path for lvmetad's pv_found.
+- Fix memleak in device_is_usable mirror testing function.
+- Fix memory leak on error path for pvcreate with invalid uuid.
+- Fix resource leak in error path of dmeventd's umount of thin volume.
+- Close open dmeventd FIFO file descriptors on exec (FD_CLOEXEC).
+- o Testing:
+- Fix test for active snapshot in cluster before resizing it.
+- Add python-lvm unit test case
+- o Other:
+- Add --with-thin-repair and --with-thin-dump configure options.
+- Require 1.9 thin pool target version for online thin pool metadata resize.
+- Use local activation for clearing snapshot COW device.
+- Add configure --with-default-profile-subdir to select dir to keep profiles in.
+- Creation of snapshot takes at most 100% origin coverage.
+- Use LC_ALL to set locale in daemons and fsadm instead of lower priority LANG.
+- Remove dependency on fedora-storage-init.service in lvm2 systemd units.
+- Depend on lvm2-lvmetad.socket in lvm2-monitor.service systemd unit.
+- Optimize out setting the same value of read_ahead.
+- Automatically deactivate failed preloaded dm tree node.
+- Process thin messages once to active thin pool target for dm_tree.
+- Move common functionality for thin lvcreate and lvconvert to toollib.
+- o Packaging:
+- Add /etc/lvm/profile dir and /etc/lvm/profile/default.profile to lvm2 package.
+- Do not include /lib/udev and /lib/udev/rules.d in device-mapper package.
+- Fix spec file's util-linux version definition for proper expansion when used.
+- Fix some incorrect changelog dates.
+
+* Fri Jun 07 2013 Peter Rajnoha <prajnoha@redhat.com> - 2.02.98-6
+- Add pidfile reference to clvmd and cmirrord initscript for systemd
+  to not assume RemainAfterExit=yes which would end up with inconsistent
+  state for these services if daemon is killed.
+
+* Thu Apr 11 2013 Peter Rajnoha <prajnoha@redhat.com> - 2.02.98-5
+- Add lvm2-activation-generator systemd generator to automatically generate
+  systemd units to activate LVM2 volumes even if lvmetad is not used.
+  This replaces lvm activation part of the former fedora-storage-init
+  script that was included in the initscripts package before.
+
+* Tue Nov 27 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.98-4
+- Apply the patch for pvscan --cache exit if cluster locking used or lvmetad not used.
+
+* Tue Nov 27 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.98-3
+- Incorporate former python-lvm package in lvm2 as lvm2-python-libs subpackage.
+- Do not use lvmetad by default if lvm.conf missing or use_lvmetad not defined.
+- Exit pvscan --cache immediately if cluster locking used or lvmetad not used.
+
+* Wed Nov 07 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.98-2
+- Fix ExecStop line in lvm2-monitor.service systemd unit - remove quotes.
+
+* Thu Nov 01 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.98-1
+- Don't use lvmetad in lvm2-monitor.service ExecStop to avoid a systemd issue.
+- Depend on lvm2-lvmetad.socket in lvm2-monitor.service systemd unit.
+- Init lvmetad lazily to avoid early socket access on config overrides.
+- Hardcode use_lvmetad=0 if cluster locking used and issue a warning msg.
+- Fix dm_task_set_cookie to properly process udev flags if udev_sync disabled.
+- Don't try to issue discards to a missing PV to avoid segfault.
+- Fix vgchange -aay not to activate non-matching LVs that follow a matching LV.
+- Fix lvchange --resync for RAID LVs which had no effect.
+- Add RAID10 support (--type raid10).
+- Introduce blkdeactivate script to deactivate block devs with dependencies.
+- Apply 'dmsetup mangle' for dm UUIDs besides dm names.
+- Use -q as short form of --quiet.
+- Suppress non-essential stdout with -qq.
+- Add log/silent to lvm.conf equivalent to -qq.
+- Add (p)artial attribute to lvs.
+- Implement devices/global_filter to hide devices from lvmetad.
+- Add lvmdump -l, to collect a state dump from lvmetad.
+- Add --discards to lvconvert.
+- Add support for lvcreate --discards.
+- Add --poolmetadata to lvconvert and support thin meta/data dev stacking.
+- Support creation of read-only thin volumes (lvcreate -p r).
+- Support changes of permissions for thin snapshot volumes.
+- Make lvremove ask before discarding data areas.
+- Prohibit not yet supported change of thin-pool to read-only.
+- Using autoextend percent 0 for thin pool fails 'lvextend --use-policies'.
+- Make vgscan --cache an alias for pvscan --cache.
+- Clear lvmetad metadata/PV cache before a rescan.
+- Fix a segmentation fault upon receiving a corrupt lvmetad response.
+- Give inconsistent metadata warnings in pvscan --cache.
+- Avoid overlapping locks that could cause a deadlock in lvmetad.
+- Fix memory leaks in libdaemon and lvmetad.
+- Optimize libdaemon logging for a fast no-output path.
+- Only create lvmetad pidfile when running as a daemon (no -f).
+- Warn if lvmetad is running but disabled.
+- Warn about running lvmetad with use_lvmetad = 0 in example.conf.
+- Update lvmetad help output (flags and their meaning).
+- Make pvscan --cache read metadata from LVM1 PVs.
+- Make libdaemon buffer handling asymptotically more efficient.
+- Make --sysinit suppress lvmetad connection failure warnings.
+- Prohibit usage of lvcreate --thinpool with --mirrors.
+- Fix lvm2api origin reporting for thin snapshot volume.
+- Add implementation of lvm2api function lvm_percent_to_float.
+- Allow non power of 2 thin chunk sizes if thin pool driver supports that.
+- Allow limited metadata changes when PVs are missing via [vg|lv]change.
+- Do not start dmeventd for lvchange --resync when monitoring is off.
+- Remove pvscan --cache from lvm2-lvmetad init script.
+- Remove ExecStartPost with pvscan --cache from lvm2-lvmetad.service.
+- Report invalid percentage for property snap_percent of non-snaphot LVs.
+- Disallow conversion of thin LVs to mirrors.
+- Fix lvm2api data_percent reporting for thin volumes.
+- Do not allow RAID LVs in a clustered volume group.
+- Enhance insert_layer_for_lv() with recursive rename for _tdata LVs.
+- Skip building dm tree for thin pool when called with origin_only flag.
+- Ensure descriptors 0,1,2 are always available, using /dev/null if necessary.
+- Use /proc/self/fd when available for closing opened descriptors efficiently.
+- Fix inability to create, extend or convert to a large (> 1TiB) RAID LV.
+- Update lvmetad communications to cope with clients using different filters.
+- Clear LV_NOSYNCED flag when a RAID1 LV is converted to a linear LV.
+- Disallow RAID1 upconvert if the LV was created with --nosync.
+- Depend on systemd-udev-settle in units generated by activation generator.
+- Disallow addition of RAID images until the array is in-sync.
+- Fix RAID LV creation with '--test' so valid commands do not fail.
+- Add lvm_lv_rename() to lvm2api.
+- Fix setvbuf code by closing and reopening stream before changing buffer.
+- Disable private buffering when using liblvm.
+- When private stdin/stdout buffering is not used always use silent mode.
+- Fix 32-bit device size arithmetic needing 64-bit casting throughout tree.
+- Fix dereference of NULL in lvmetad error path logging.
+- Fix buffer memory leak in lvmetad logging.
+- Correct the discards field in the lvs manpage (2.02.97).
+- Use proper condition to check for discards settings unsupported by kernel.
+- Reinstate correct default to ignore discards for thin metadata from old tools.
+- Issue error message when -i and -m args do not match specified RAID type.
+- Change lvmetad logging syntax from -ddd to -l {all|wire|debug}.
+- Add new libdaemon logging infrastructure.
+- Support unmount of thin volumes from pool above thin pool threshold.
+- Update man page to reflect that dm UUIDs are being mangled as well.
+- Add 'mangled_uuid' and 'unmangled_uuid' fields to dmsetup info -c -o.
+- Mangle device UUID on dm_task_set_uuid/newuuid call if necessary.
+- Add dm_task_get_uuid_mangled/unmangled to libdevmapper.
+- Always reset delay_resume_if_new flag when stacking thin pool over anything.
+- Don't create value for dm_config_node and require dm_config_create_value call.
+- Check for existing new_name for dmsetup rename.
+- Fix memory leak in dmsetup _get_split_name() error path.
+- Clean up spec file and keep support only for Fedora 18 upwards.
+- Use systemd macros in rpm scriptlets to set up systemd units.
+- Add Requires: bash >= 4.0 for blkdeactivate script.
+
+* Tue Aug 07 2012 Alasdair Kergon <agk@redhat.com> - 2.02.97-1
+- Improve documention of allocation policies in lvm.8.
+- Increase limit for major:minor to 4095:1048575 when using -My option.
+- Add generator for lvm2 activation systemd units.
+- Add lvm_config_find_bool lvm2app fn to retrieve bool value from config tree.
+- Respect --test when using lvmetad.
+- No longer capitalise first LV attribute char for invalid snapshots.
+- Allow vgextend to add PVs to a VG that is missing PVs.
+- Recognise Micron PCIe SSDs in filter and move array out to device-types.h.
+- Fix dumpconfig <node> to print only <node> without its siblings. (2.02.89)
+- Do not issue "Failed to handle a client connection" error if lvmetad killed.
+- Support lvchange --discards and -Z with thin pools.
+- Add discard LV segment field to reports.
+- Add --discards to lvcreate --thin.
+- Set discard and external snapshot features if thin pool target is vsn 1.1+.
+- Count percentage of completeness upwards not downwards when merging snapshot.
+- Skip activation when using vg/lvchange --sysinit -a ay and lvmetad is active.
+- Fix extending RAID 4/5/6 logical volumes
+- Fix test for PV with unknown VG in process_each_pv to ignore ignored mdas.
+- Fix _alloc_parallel_area to avoid picking already-full areas for raid devices.
+- Never issue discards when LV extents are being reconfigured, not deleted.
+- Allow release_lv_segment_area to fail as functions it calls can fail.
+- Fix missing sync of filesystem when creating thin volume snapshot.
+- Allow --noflush with dmsetup status and wait (for thin target).
+- Add dm_config_write_one_node to libdevmapper.
+- Add dm_vasprintf to libdevmapper.
+- Support thin pool message release/reserve_metadata_snap in libdevmapper.
+- Support thin pool discards and external origin features in libdevmapper.
+
+* Thu Jul 19 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.02.96-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Wed Jul 04 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.96-3
+- Use configure --with-default-pid-dir=/run.
+- Use globally set prefix for udev rules path.
+
+* Mon Jul 02 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.96-2
+- Compile with lvmetad support enabled.
+- Add support for volume autoactivation using lvmetad.
+- Update man pages with --activate ay option and auto_activation_volume_list.
+- Use vgchange -aay instead of vgchange -ay in clmvd init script.
+- Add activation/auto_activation_volume_list to lvm.conf.
+- Add --activate ay to lvcreate, lvchange, pvscan and vgchange.
+- Add --activate synonym for --available arg and prefer --activate.
+- Open device read-only to obtain readahead value.
+- Add configure --enable-udev-rule-exec-detection to detect exec path in rules.
+- Use sbindir in udev rules by default and remove executable path detection.
+- Remove hard-coded paths for dmeventd fifos and use default-dm-run-dir.
+- Add configure --with-lvmetad-pidfile to remove hard-coded value.
+- Add configure --with-default-pid-dir for common directory with pid files.
+- Add configure --with-default-dm-run-dir to set run directory for dm tools.
+- Add documentation references in systemd units.
+- Clean up spec file and keep support only for Fedora 17 upwards.
+
+* Mon Jun 18 2012 Alasdair Kergon <agk@redhat.com> - 2.02.96-1
+- Require device-mapper-persistent-data package for thin provisioning.
+- Set delay_resume_if_new on deptree snapshot origin.
+- Log value chosen in _find_config_bool like other variable types do.
+- Wait for dmeventd to exit after sending it DM_EVENT_CMD_DIE when restarting.
+- Append 'Used' to {Blk}DevNames/DevNos dmsetup report headers for clarity.
+- Remove dmeventd fifos on exit if they are not managed by systemd.
+- Use SD_ACTIVATION environment variable in systemd units to detect systemd.
+- Only start a new dmeventd instance on restart if one was already running.
+- Extend the time waited for input from dmeventd fifo to 5 secs. (1.02.73)
+- Fix error paths for regex filter initialization.
+- Re-enable partial activation of non-thin LVs until it can be fixed. (2.02.90)
+- Fix alloc cling to cling to PVs already found with contiguous policy.
+- Fix cling policy not to behave like normal policy if no previous LV seg.
+- Fix allocation loop not to use later policies when --alloc cling without tags.
+- Fix division by zero if PV with zero PE count is used during vgcfgrestore.
+- Add initial support for thin pool lvconvert.
+- Fix lvrename for thin volumes (regression in for_each_sub_lv). (2.02.89)
+- Fix up-convert when mirror activation is controlled by volume_list and tags.
+- Warn of deadlock risk when using snapshots of mirror segment type.
+- Fix bug in cmirror that caused incorrect status info to print on some nodes.
+- Remove statement that snapshots cannot be tagged from lvm man page.
+- Disallow changing cluster attribute of VG while RAID LVs are active.
+- Fix lvconvert error message for non-mergeable volumes.
+- Allow subset of failed devices to be replaced in RAID LVs.
+- Prevent resume from creating error devices that already exist from suspend.
+- Update and correct lvs man page with supported column names.
+- Handle replacement of an active device that goes missing with an error device.
+- Change change raid1 segtype always to request a flush when suspending.
+- Add udev info and context to lvmdump.
+- Add lvmetad man page.
+- Fix RAID device replacement code so that it works under snapshot.
+- Fix inability to split RAID1 image while specifying a particular PV.
+- Update man pages to give them all the same look&feel.
+- Fix lvresize of thin pool for striped devices.
+- For lvresize round upward when specifying number of extents.
+- For lvcreate with %%FREE support rounding downward stripe alignment.
+- Change message severity to log_very_verbose for missing dev info in udev db.
+- Fix lvconvert when specifying removal of a RAID device other than last one.
+- Fix ability to handle failures in mirrored log in dmeventd plugin. (2.02.89)
+- Fix unlocking volume group in vgreduce in error path.
+- Cope when VG name is part of the supplied name in lvconvert --splitmirrors -n.
+- Fix exclusive lvchange running from other node. (2.02.89)
+- Add 'vgscan --cache' functionality for consistency with 'pvscan --cache'.
+- Keep exclusive activation in pvmove if LV is already active.
+- Disallow exclusive pvmove if some affected LVs are not exclusively activated.
+- Remove unused and wrongly set cluster VG flag from clvmd lock query command.
+- Fix pvmove for exclusively activated LV pvmove in clustered VG. (2.02.86)
+- Update and fix monitoring of thin pool devices.
+- Check hash insert success in lock_vg in clvmd.
+- Check for buffer overwrite in get_cluster_type() in clvmd.
+- Fix global/detect_internal_vg_cache_corruption config check.
+- Fix initializiation of thin monitoring. (2.02.92)
+- Cope with improperly formatted device numbers in /proc/devices. (2.02.91)
+- Exit if LISTEN_PID environment variable incorrect in lvmetad systemd handover.
+- Fix fsadm propagation of -e option.
+- Fix fsadm parsing of /proc/mounts files (don't check for substrings).
+- Fix fsadm usage of arguments with space.
+- Fix arg_int_value alongside ARG_GROUPABLE --major/--minor for lvcreate/change.
+- Fix name conflicts that prevent down-converting RAID1 when specifying a device
+- Improve thin_check option passing and use configured path.
+- Add --with-thin-check configure option for path to thin_check.
+- Fix error message when pvmove LV activation fails with name already in use.
+- Better structure layout for device_info in dev_subsystem_name().
+- Change message severity for creation of VG over uninitialised devices.
+- Fix error path for failed toolcontext creation.
+- Don't unlink socket on lvmetad shutdown if instantiated from systemd.
+- Restart lvmetad automatically from systemd if it exits from uncaught signal.
+- Fix warn msg for thin pool chunk size and update man for chunksize. (2.02.89)
+
+* Thu Jun 07 2012 Kay Sievers - 2.02.95-8
+- Remove explicit Requires: libudev, rpm takes care of that:
+    $ rpm -q --requires device-mapper | grep udev
+    libudev.so...
+
+* Tue Jun 05 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.95-7
+- Use BuildRequires: systemd-devel instead of BuildRequires: libudev-devel.
+- Remove unsupported udev_get_dev_path libudev call used for checking udev dir.
+
+* Thu Mar 29 2012 Fabio M. Di Nitto <fdinitto@redhat.com> - 2.02.95-6
+- BuildRequires and Requires on newer version of corosync and dlm.
+- Restart clvmd on upgrades.
+
+* Mon Mar 19 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.95-5
+- Do not strictly require openais for cmirror subpackage.
+
+* Mon Mar 19 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.95-4
+- Reinstate cmirror support.
+- Detect lvm binary path in lvmetad udev rules.
+- Use pvscan --cache instead of vgscan in systemd units/init scripts.
+
+* Fri Mar 16 2012 Fabio M. Di Nitto <fdinitto@redhat.com> - 2.02.95-3
+- Rebuild against new corosync (soname change).
+- BuildRequires and Requires on newer version of corosync.
+
+* Thu Mar 08 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.95-2
+- Reload dm-event systemd service on upgrade.
+
+* Tue Mar 06 2012 Alasdair Kergon <agk@redhat.com> - 2.02.95-1
+- If unspecified, adjust thin pool metadata and chunk size to fit into 128MB.
+- Deactivation of failed thin check on thin pool returns success.
+- Check for multiply-mangled names in auto mangling mode.
+- Fix dm_task_get_name_unmangled to not unmangle already unmangled name.
+- Check whether device names are properly mangled on ioctl return.
+
+* Sat Mar 03 2012 Alasdair Kergon <agk@redhat.com> - 2.02.94-1
+- Add support to execute thin_check with each de/active of thin pool.
+- Fix automatic estimation of metadata device size for thin pool.
+- Wipe initial 4KiB of non zeroed thin volumes.
+- Update code-base to incorporate new metadata daemon. (Not used in Fedora yet.)
+- Numerous minor cleanups across the code-base.
+- Fix dmsetup / dm_task_set_name to properly resolve path to dm name. (2.02.93)
+
+* Thu Feb 23 2012 Alasdair Kergon <agk@redhat.com> - 2.02.93-1
+- Moved systemd tmpfiles installation upstream for lvm2 lock and run dirs.
+- Require number of stripes to be greater than parity devices in higher RAID.
+- Fix allocation code to allow replacement of single RAID 4/5/6 device.
+- Check all tags and LV names are in a valid form before writing any metadata.
+- Allow 'lvconvert --repair' to operate on RAID 4/5/6.
+- Fix build_parallel_areas_from_lv to account correctly for raid parity devices.
+- Print message when faulty raid devices have been replaced.
+
+* Mon Feb 20 2012 Alasdair Kergon <agk@redhat.com> - 2.02.92-1
+- Read dmeventd monitoring config settings for every lvm command.
+- For thin devices, initialize monitoring only for thin pools not thin volumes.
+- Make conversion from a synced 'mirror' to 'raid1' not cause a full resync.
+- Add clvmd init dependency on dlm service when running with new corosync.
+- Switch to using built-in blkid in 13-dm-disk.rules.
+- Add "watch" rule to 13-dm-disk.rules.
+- Detect failing fifo and skip 20s retry communication period.
+- Replace any '\' char with '\\' in dm table specification on input.
+- New 'mangle' options in dmsetup/libdevmapper for transparent reversible 
+  encoding of characters that udev forbids in device names.
+- Add --manglename option to dmsetup to select the name mangling mode.
+- Add mangle command to dmsetup to provide renaming to correct mangled form.
+- Add 'mangled_name' and 'unmangled_name' fields to dmsetup info -c -o.
+- Mangle device name on dm_task_set_name/newname call if necessary.
+- Add dm_task_get_name_mangled/unmangled to libdevmapper.
+- Add dm_set/get_name_mangling_mode to set/get name mangling in libdevmapper.
+
+* Mon Feb 13 2012 Peter Rajnoha <prajnoha@redhat.com> - 2.02.91-2
+- Add configure --with-systemdsystemunitdir.
+
+* Sun Feb 12 2012 Alasdair Kergon <agk@redhat.com> - 2.02.91-1
+- New upstream with trivial fixes and refactoring of some lvmcache and orphan code.
+
+* Wed Feb 1 2012 Alasdair Kergon <agk@redhat.com> - 2.02.90-1
+- Drop support for cman, openais and cmirror for f17. Require dlm not cluster.
+- Automatically detect whether corosync clvmd needs to use confdb or cmap.
+- Disable partial activation for thin LVs and LVs with all missing segments.
+- sync_local_dev_names before (re)activating mirror log for initialisation.
+- Do not print warning for pv_min_size between 512KB and 2MB.
+- Clean up systemd unit ordering and requirements.
+- Allow ALLOC_NORMAL to track reserved extents for log and data on same PV.
+- Fix data% report for thin volume used as origin for non-thin snapshot.
+
+* Thu Jan 26 2012 Alasdair Kergon <agk@redhat.com> - 2.02.89-2
+- New upstream release with experimental support for thinly-provisioned devices.
+- The changelog for this release is quite long and contained in 
+  WHATS_NEW and WHATS_NEW_DM in the documentation directory.
+
+* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.02.88-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Fri Dec 30 2011 Peter Robinson <pbrobinson@fedoraproject.org> - 2.02.88-2
+- update util-linux-ng -> util-linux dependency as it changed long ago.
+
+* Mon Aug 22 2011 Alasdair Kergon <agk@redhat.com> - 2.02.88-1
+- Remove incorrect 'Breaking' error message from allocation code. (2.02.87)
+- Add lvconvert --merge support for raid1 devices split with --trackchanges.
+- Add --trackchanges support to lvconvert --splitmirrors option for raid1.
+- Add dm_tree_node_add_null_area for temporarily-missing raid devs tracked.
+- Support lvconvert of -m1 raid1 devices to a higher number.
+- Support splitting off a single raid1 rimage in lvconvert --splitmirrors.
+- Add -V as short form of --virtualsize in lvcreate.
+
+* Fri Aug 12 2011 Peter Rajnoha <prajnoha@redhat.com> - 2.02.87-1
+- Cache and share generated VG structs to improve performance.
+- Suppress locking error messages in monitoring init scripts.
+- Add global/detect_internal_vg_cache_corruption to lvm.conf.
+- If pipe in clvmd fails return busy instead of using uninitialised descriptors.
+- Initialise clvmd locks before lvm context to avoid open descriptor leaks.
+- Suppress low-level locking errors and warnings while using --sysinit.
+- Add test for fcntl error in singlenode client code.
+- Compare file size (as well as timestamp) to detect changed config file.
+- Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used if there is no config file.
+- Update udev rules to skip DM flags decoding for removed devices.
+- Remove device name prefix from dmsetup line output if -j & -m or -u supplied.
+- Add new segtype 'raid' for MD RAID 1/4/5/6 support with dmeventd plugin.
+- Add ability to reduce the number of mirrors in raid1 arrays to lvconvert.
+- Add support for systemd file descriptor handover in dmeventd.
+- Add systemd unit file to provide lvm2 monitoring.
+- Add systemd unit files for dmeventd.
+- Use new oom killer adjustment interface (oom_score_adj) when available.
+- Fix read-only identical table reload supression.
+- Remove --force option from lvrename manpage.
+
+* Wed Aug 03 2011 Peter Rajnoha <prajnoha@redhat.com> - 2.02.86-5
+- Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used even without any config.
+
+* Thu Jul 28 2011 Peter Rajnoha <prajnoha@redhat.com> - 2.02.86-4
+- Add support for systemd file descriptor handover to dmeventd.
+- Add support for new oom killer adjustment interface (oom_score_adj).
+
+* Wed Jul 20 2011 Peter Rajnoha <prajnoha@redhat.com> - 2.02.86-3
+- Fix broken lvm2-sysinit Requires: lvm2 dependency.
+
+* Mon Jul 18 2011 Peter Rajnoha <prajnoha@redhat.com> - 2.02.86-2
+- Add dm-event and lvm2-monitor unit files for use with systemd.
+- Add sysvinit subpackage for legacy SysV init script support.
+
+* Fri Jul 8 2011 Alasdair Kergon <agk@redhat.com> - 2.02.86-1
+- Fix activation sequences to avoid trapped I/O with multiple LVs.
+- Fix activation sequences to avoid allocating tables while devs suspended.
+- Remove unnecessary warning in pvcreate for MD linear devices.
+- Add activation/checks to lvm.conf to perform additional ioctl validation.
+- Append 'm' attribute to pv_attr for missing PVs.
+- Fix to preserve exclusive activation of mirror while up-converting.
+- Reject allocation if number of extents is not divisible by area count.
+- Fix cluster mirror creation to work with new mirror allocation algorithm.
+- Ignore activation/verify_udev_operations if dm kernel driver vsn < 4.18.
+- Add activation/verify_udev_operations to lvm.conf, disabled by default.
+- Ignore inconsistent pre-commit metadata on MISSING_PV devs while activating.
+- Add proper udev library context initialization and finalization to liblvm.
+- Downgrade critical_section errors to debug level until it is moved to libdm.
+- Fix ignored background polling default in vgchange -ay.
+- Fix reduction of mirrors with striped segments to always align to stripe size.
+- Validate mirror segments size.
+- Fix extent rounding for striped volumes never to reduce more than requested.
+- Fix create_temp_name to replace any '/' found in the hostname with '?'.
+- Always use append to file in lvmdump. selinux policy may ban file truncation.
+- Propagate test mode to clvmd to skip activation and changes to held locks.
+- Permit --available with lvcreate so non-snapshot LVs need not be activated.
+- Clarify error message when unable to convert an LV into a snapshot of an LV.
+- Do not issue an error message when unable to remove .cache on read-only fs.
+- Avoid memlock size mismatch by preallocating stdio line buffers.
+- Report internal error if suspending a device using an already-suspended dev.
+- Report internal error if any table is loaded while any dev is known suspended.
+- Report error if a table load requiring target parameters has none supplied.
+- Add dmsetup --checks and dm_task_enable_checks framework to validate ioctls.
+- Add age_in_minutes parameter to dmsetup udevcomplete_all.
+- Disable udev fallback by default and add --verifyudev option to dmsetup.
+- Add dm_get_suspended_counter() for number of devs in suspended state by lib.
+- Fix "all" report field prefix matching to include label fields with pv_all.
+- Delay resuming new preloaded mirror devices with core logs in deptree code.
+
+* Wed Jun 22 2011 Zdenek Kabelac <zkabelac@redhat.com> - 2.02.84-3
+- Updated uname string test.
+
+* Sat Jun 4 2011 Milan Broz <mbroz@redhat.com> - 2.02.84-2
+- Accept kernel 3.0 uname string in libdevmapper initialization.
+- Make systemd initscripts configurable.
+
+* Wed Feb 9 2011 Alasdair Kergon <agk@redhat.com> - 2.02.84-1
+- Fix big-endian CRC32 checksumming broken since 2.02.75.  If affected,
+  ensure metadata backups in /etc/lvm/backup are up-to-date (vgcfgbackup)
+  then after updating to 2.02.84 restore metadata from them (using pvcreate
+  with -Zn --restorefile and -u if PVs can no longer be seen, then
+  vgcfgrestore -f).
+- Reinstate libdevmapper DEBUG_MEM support. (Removed in 1.02.62.)
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.02.83-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Fri Feb 4 2011 Alasdair Kergon <agk@redhat.com> - 2.02.83-1
+- Allow exclusive activation of snapshots in a cluster.
+- Don't lose LV exclusive lock state when suspending clustered devices.
+- Fix fs operation stack handling when multiple operations on same device.
+- Increase hash table sizes to 1024 LV names and 64 PV uuids.
+- When setting up mda wipe first 4k of it as was intended.
+- Remove unneeded checks for open_count in lv_info().
+- Synchronize with udev before checking open_count in lv_info().
+- Add "dmsetup ls --tree" output to lvmdump.
+- Fix udev synchronization with no-locking --sysinit (2.02.80).
+- Improve man page style consistency for pvcreate, pvremove, pvresize, pvscan.
+- Avoid rebuilding of uuid validation table.
+- Improve lvcreate error text from insufficient "extents" to "free space".
+- Always use O_DIRECT when opening block devices to check for partitioning.
+- Move creation of device nodes from 'create' to 'resume'.
+- Add --addnodeonresume and --addnodeoncreate options to dmsetup.
+- Add dm_task_set_add_node to libdevmapper to control dev node creation time.
+- Add dm_task_secure_data to libdevmapper to wipe ioctl buffers in kernel.
+- Log debug message when expected uevent is not generated.
+- Set DM_UDEV_DISABLE_OTHER_RULES_FLAG for suspended DM devices in udev rules.
+- Begin a new pool object for each row in _output_as_rows() correctly.
+
+* Mon Jan 24 2011 Alasdair Kergon <agk@redhat.com> - 2.02.82-2
+- Bring lvscan man page up-to-date.
+- Fix lvchange --test to exit cleanly.
+- Add change_tag to toollib.
+- Allow multiple pvchange command line options to be specified together.
+- Do not fail pvmove polling if another process cleaned up first.
+- Avoid clvmd incrementing dlm lockspace reference count more than once.
+- Add -f (don't fork) option to clvmd and fix clvmd -d<num> description.
+
+* Mon Jan 17 2011 Alasdair Kergon <agk@redhat.com> - 2.02.81-1
+- Add disk to allowed mirrored log type conversions.
+- Accept fusion fio in device type filter.
+- Speed up command processing by caching resolved config tree.
+- Use same dm cookie for consecutive dm ops in same VG to reduce udev waits.
+- Do not scan devices in dev_reset_error_count() when forking.
+- Skip unnecessary LOCK_NULL unlock call during volume deactivation.
+- Skip fs_unlock when calling exec_cmd within activation code (for modprobe).
+- Replace fs_unlock by sync_local_dev_names to notify local clvmd. (2.02.80)
+- Fix wrongly paired unlocking of VG_GLOBAL in pvchange. (2.02.66)
+- Return 0 from cmirrord initscript 'start' if daemon is already running.
+- Add DM_COOKIE_AUTO_CREATE to libdevmapper.h.
+- Improve general lvconvert man page description.
+- Detect NULL handle in get_property().
+- Fix memory leak in persistent filter creation error path.
+- Check for errors setting up dm_task struct in _setup_task().
+- Fail polldaemon creation when lvmcache_init() fails.
+- Return PERCENT_INVALID for errors in _copy_percent() and _snap_percent().
+- Detect errors from dm_task_set calls in _get_device_info (dmeventd).
+- Fix memory leak in debug mode of restart_clvmd() error path.
+- Log error message for pthread_join() failure in clvmd.
+- Use tmpfiles.d/lvm2.conf to create /var/lock/lvm and /var/run/lvm at boot.
+- Require initscripts for tmpfiles.d/lvm2.conf.
+
+* Tue Dec 21 2010 Alasdair Kergon <agk@redhat.com> - 2.02.79-1
+- Create /var/run/lvm directory during clvmd initialisation if missing.
+- Avoid revalidating the label cache immediately after scanning.
+- Support scanning for a single VG in independent mdas.
+- Don't skip full scan when independent mdas are present even if memlock is set.
+- Add copy_percent and snap_percent to liblvm.
+- Add new dm_prepare_selinux_context fn to libdevmapper and use it throughout.
+- Enhance vg_validate to ensure integrity of LV and PV structs referenced.
+- Enhance vg_validate to check composition of pvmove LVs.
+- Avoid writing to freed memory in vg_release.  (2.02.78)
+- Add missing test for reallocation error in _find_parallel_space().
+- Add checks for allocation errors in config node cloning.
+- Fix error path if regex engine cannot be created in _build_matcher().
+- Check read() and close() results in _get_cmdline().
+- Fix NULL pointer check in error path in clvmd do_command(). (2.02.78)
+- Check for unlink failure in remove_lockfile() in dmeventd.
+- Use dm_free for dm_malloc-ed areas in _clog_ctr/_clog_dtr in cmirrord.
+- Change dm_regex_create() API to accept const char * const *patterns.
+
+* Mon Dec 6 2010 Alasdair Kergon <agk@redhat.com> - 2.02.78-1
+- Miscellaneous error path corrections and minor leaks fixed.
+- Avoid misleading PV missing warnings in vgextend --restoremissing.
+- Ignore unrecognised allocation policy found in metadata instead of aborting.
+- Disallow lvconvert ops that both allocate & free supplied PEs in a single cmd.
+- Fix liblvm seg_size to give bytes not sectors.
+- Add functions to look up LV/PV by name/uuid to liblvm.
+- Suppress 'No PV label' message when removing several PVs without mdas.
+- Fix default /etc/lvm permissions to be 0755. (2.02.66)
+
+* Mon Nov 22 2010 Alasdair Kergon <agk@redhat.com> - 2.02.77-1
+- Add PV and LV segment types and functions to liblvm.
+- Add set_property functions to liblvm.
+- Remove tag length restriction and allow / = ! : # & characters.
+- Support repetition of --addtag and --deltag arguments.
+- Add infrastructure for specific cmdline arguments to be repeated in groups.
+- Fix fsadm no longer to require '-f' to resize an unmounted filesystem.
+- Fix fsadm to detect mounted filesystems on older systems. (2.0.75)
+- Extend cling allocation policy to recognise PV tags (cling_by_tags).
+- Add allocation/cling_tag_list to lvm.conf.
+
+* Tue Nov 9 2010 Alasdair Kergon <agk@redhat.com> - 2.02.76-1
+- Clarify error messages when activation fails due to activation filter use.
+- Fix handling of online filesystem resize (using new fsadm return code).
+- Modify fsadm to return different status code for check of mounted filesystem.
+- Add DIAGNOSTICS section to fsadm man page.
+- Update VG metadata only once in vgchange when making multiple changes.
+- Allow independent vgchange arguments to be used together.
+- Fix vgchange to process -a, --refresh, --monitor and --poll like lvchange.
+- Add dmeventd -R to restart dmeventd without losing monitoring state. (1.02.56)
+- Automatically unmount invalidated snapshots in dmeventd.
+- Add lvm2app functions to query any pv, vg, or lv property / report field.
+- Fix a deadlock caused by double close in clvmd.
+- Fix NULL pointer dereference on too-large MDA error path in _vg_read_raw_area.
+- Fix regex optimiser not to ignore RHS of OR nodes in _find_leftmost_common.
+- Fix memory leak of field_id in _output_field function.
+- Allocate buffer for reporting functions dynamically to support long outputs.
+
+* Mon Oct 25 2010 Alasdair Kergon <agk@redhat.com> - 2.02.75-1
+- Fix pthread mutex usage deadlock in clvmd.
+- Avoid segfault by limiting partial mode for lvm1 metadata. (2.02.74)
+- Skip dm devices in scan if they contain only error targets or are empty.
+- Don't take write lock in vgchange --refresh, --poll or --monitor.
+- Fix hang when repairing a mirrored-log that had both devs fail.
+- Speed up unquoting of quoted double quotes and backslashes.
+- Speed up CRC32 calculations by using a larger lookup table.
+- Implement dmeventd -R to restart without state loss.
+- Add --setuuid to dmsetup rename.
+- Add global/metadata_read_only to use unrepaired metadata in read-only cmds.
+- Automatically extend snapshots with dmeventd according to policy in lvm.conf.
+- Add activation/snapshot_autoextend_threshold/percent to lvm.conf.
+- Add devices/disable_after_error_count config to limit access to failing devs.
+- Implement vgextend --restoremissing to reinstate missing devs that return.
+- Read whole /proc/self/maps file before working with maps entries.
+- Convey need for snapshot-merge target in lvconvert error message and man page.
+- Give correct error message when creating a too-small snapshot.
+- Make lvconvert respect --yes and --force when converting an inactive log.
+- Better support of noninteractive shell execution of fsadm.
+- Fix usage of --yes flag for ReiserFS resize in fsadm.
+- Fix detection of mounted filesystems for fsadm when udev is used.
+- Fix assignment of default value to LVM variable in fsadm.
+- Fix support for --yes flag for fsadm.
+- Do not execute lvresize from fsadm --dry-run.
+- Fix fsadm return error code from user's break action.
+- Return const pointer from dm_basename() in libdevmapper.
+- Add dm_zalloc and use it and dm_pool_zalloc throughout.
+- Add dm_task_set_newuuid to set uuid of mapped device post-creation.
+- Fix missing variable initialization in cluster_send() function from cmirrord.
+- Fix pointer for VG name in _pv_resize_single error code path.
+- Fix vg_read memory leak with directory-based metadata.
+- Fix memory leak of config_tree in reinitialization code path.
+- Fix pool destruction order in dmeventd_lvm2_exit() to avoid leak debug mesg.
+- Remove dependency on libm by replacing floor() by an integer-based algorithm.
+- Refactor and add 'get' functions for pv, vg and lv properties/fields.
+- Add pv_get_property and create generic internal _get_property function.
+- Make generic GET_*_PROPERTY_FN macros with secondary macro for vg, pv & lv.
+
+* Fri Oct 15 2010 Alasdair Kergon <agk@redhat.com> - 2.02.73-3
+- Add --setuuid to dmsetup rename.
+- Add dm_task_set_newuuid to set uuid of mapped device post-creation.
+
+* Wed Sep 29 2010 jkeating - 2.02.74-2
+- Rebuilt for gcc bug 634757
+
+* Fri Sep 24 2010 Alasdair Kergon <agk@redhat.com> - 2.02.74-1
+- Fix the way regions are marked complete to avoid slow --nosync cmirror I/O.
+- Add DM_REPORT_FIELD_TYPE_ID_LEN to libdevmapper.h.
+- Allow : and @ to be escaped with \ in device names of PVs.
+- Avoid stack corruption when reading in large metadata.
+- Fix partial mode operations for lvm1 metadata format.
+- Track recursive filter iteration to avoid refreshing while in use. (2.02.56)
+- Allocate buffer for metadata tags dynamically to remove 4k limit.
+- Add random suffix to archive file names to prevent races when being created.
+- Reinitialize archive and backup handling on toolcontext refresh.
+- Make poll_mirror_progress report PROGRESS_CHECK_FAILED if LV is not a mirror.
+- Like mirrors, don't scan origins if ignore_suspended_devices() is set.
+- Automatically generate tailored LSB Requires-Start for clvmd init script.
+- Fix return code of pvmove --abort PV.
+- Fix pvmove --abort to remove even for empty pvmove LV.
+- Add implementation for simple numeric 'get' property functions.
+- Simplify MD/swap signature detection in pvcreate and allow aborting.
+- Allow --yes to be used without --force mode.
+- Fix file descriptor leak in swap signature detection error path.
+- Detect and allow abort in pvcreate if LUKS signature is detected.
+
+* Wed Aug 25 2010 Peter Rajnoha <prajnoha@redhat.com> - 2.02.73-2
+- Add configure --with-default-data-alignment.
+- Update heuristic used for default and detected data alignment.
+- Add "devices/default_data_alignment" to lvm.conf.
+
+* Wed Aug 18 2010 Alasdair Kergon <agk@redhat.com> - 2.02.73-1
+- Change default alignment of data extents to 1MB.
+- Add --norestorefile option to pvcreate.
+- Require --restorefile when using pvcreate --uuid.
+- Fix potential for corruption during cluster mirror device failure.
+- Ignore snapshots when performing mirror recovery beneath an origin.
+- Monitor origin -real device below snapshot instead of overlay device.
+- Don't really change monitoring status when in test mode.
+- Fix some exit statuses when starting/stopping monitoring fails.
+- Enable snapshot monitoring by default when dmeventd is enabled.
+- Fix 'lvconvert --splitmirrors' in cluster operation.
+- Fix clvmd init script exit code to return 4 when executed as non-root user.
+- Recognise and give preference to md device partitions (blkext major).
+- Never scan internal LVM devices.
+- Don't ignore user-specified PVs in split-mirror operations. (2.02.71)
+- Fix data corruption bug in cluster mirrors.
+- Require logical volume(s) to be explicitly named for lvconvert --merge.
+- Avoid changing aligned pe_start as a side-effect of a log message.
+- Use built-in rule for device aliases: block/ < dm- < disk/ < mapper/ < other.
+- Handle failure of all mirrored log devices and all but one mirror leg. 
+- Disallow 'mirrored' log type for cluster mirrors.
+- Fix configure to supply DEFAULT_RUN_DIR to Makefiles.
+- Fix allocation of wrong number of mirror logs with 'remove' fault policy.
+- Add dmeventd/executable to lvm.conf to test alternative dmeventd.
+- Fix udev rules to support udev database content generated by older rules.
+- Reinstate detection of inappropriate uevent with DISK_RO set and suppress it.
+- Fix regex ttree off-by-one error.
+- Fix segfault in regex matcher with characters of ordinal value > 127.
+- Wait for node creation before displaying debug info in dmsetup.
+- Fix return status 0 for "dmsetup info -c -o help".
+
+* Mon Aug 2 2010 Alasdair Kergon <agk@redhat.com> - 2.02.72-5
+- Make udev configurable and merge with f12.
+
+* Mon Aug 2 2010 Alasdair Kergon <agk@redhat.com> - 2.02.72-4
+- Merge f13, f14 and rawhide spec files.
+
+* Sat Jul 31 2010 Alasdair Kergon <agk@redhat.com> - 2.02.72-3
+- Address lvm2-cluster security flaw CVE-2010-2526.
+    https://bugzilla.redhat.com/CVE-2010-2526
+- Change clvmd to communicate with lvm2 via a socket in /var/run/lvm.
+- Return controlled error if clvmd is run by non-root user.
+- Never use clvmd singlenode unless explicitly requested with -Isinglenode.
+- Fix exported_symbols generation to use standard compiler arguments.
+- Use #include <> not "" in lvm2app.h which gets installed on the system.
+- Make liblvm.device-mapper wait for include file generation.
+- Fix configure to supply DEFAULT_RUN_DIR to Makefiles.
+- Fix wrong number of mirror log at allocate policy
+
+* Wed Jul 28 2010 Alasdair Kergon <agk@redhat.com> - 2.02.71-1
+- Make vgck warn about missing PVs.
+- Revert failed table load preparation after "create, load and resume".
+- Check if cluster log daemon is running before allowing cmirror create.
+- Add dm_create_lockfile to libdm and use for pidfiles for all daemons.
+- Correct LV list order used by lvconvert when splitting a mirror.
+- Check if LV with specified name already exists when splitting a mirror.
+- Fix suspend/resume logic for LVs resulting from splitting a mirror.
+- Fix possible hang when all mirror images of a mirrored log fail.
+- Adjust auto-metadata repair and caching logic to try to cope with empty mdas.
+- Update pvcreate, {pv|vg}change, and lvm.conf man pages about metadataignore.
+- Prompt if metadataignore with vgextend or pvchange would adjust vg_mda_copies.
+- Adjust vg_mda_copies if metadataignore given with vgextend or pvchange.
+- Speed up the regex matcher.
+- Use "nowatch" udev rule for inappropriate devices.
+- Document LVM fault handling in lvm_fault_handling.txt.
+- Clarify help text for vg_mda_count.
+- Add more verbose messages while checking volume_list and hosttags settings.
+- Add log_error when strdup fails in {vg|lv}_change_tag().
+- Do not log backtrace in valid _lv_resume() code path.
+
+* Wed Jul 7 2010 Alasdair Kergon <agk@redhat.com> - 2.02.70-1
+- Remove log directly if all mirror images of a mirrored log fail.
+- Randomly select which mdas to use or ignore.
+- Add printf format attributes to yes_no_prompt and fix a caller.
+- Always pass unsuspended dm devices through persistent filter to other filters.
+- Move test for suspended dm devices ahead of other filters.
+- Fix another segfault in clvmd -R if no response from daemon received. (2.02.68)
+- Remove superfluous suspended device counter from clvmd.
+- Fix lvm shell crash when input is entirely whitespace.
+- Update partial mode warning message.
+- Preserve memlock balance in clvmd when activation triggers a resume.
+- Restore the removemissing behaviour of lvconvert --repair --use-policies.
+
+* Wed Jun 30 2010 Alasdair Kergon <agk@redhat.com> - 2.02.69-1
+- Fix vgremove to allow removal of VG with missing PVs. (2.02.52)
+- Add metadata/vgmetadatacopies to lvm.conf.
+- Add --metadataignore to pvcreate and vgextend.
+- Add vg_mda_copies, pv_mda_used_count and vg_mda_used_count to reports.
+- Describe --vgmetadatacopies in lvm.conf and other man pages.
+- Add --[vg]metadatacopies to select number of mdas to use in a VG.
+- Make the metadata ignore bit control read/write metadata areas in a PV.
+- Add pvchange --metadataignore to set or clear a metadata ignore bit.
+- Refactor metadata code to prepare for --metadataignore / --vgmetadatacopies.
+- Ensure region_size of mirrored log does not exceed its full size.
+- Preload libc locale messages to prevent reading it in memory locked state.
+- Fix handling of simultaneous mirror image and mirrored log image failure.
+
+* Thu Jun 24 2010 Peter Rajnoha <prajnoha@redhat.com> - 2.02.68-2
+- Fix udev rules to handle spurious events properly.
+- Add Requires: udev >= 158-1 (needed for the change in udev rules).
+
+* Wed Jun 23 2010 Alasdair Kergon <agk@redhat.com> - 2.02.68-1
+- Have device-mapper-libs require device-mapper (circular) for udev rules.
+- Clear exec_prefix.
+- Use early udev synchronisation and update of dev nodes for clustered mirrors.
+- Add lv_path to reports to offer full /dev pathname.
+- Avoid abort when generating cmirror status.
+- Fix clvmd initscript status to print only active clustered LVs.
+- Fix segfault in clvmd -R if no response from daemon received.
+- Honour log argument when down-converting stacked mirror.
+- Sleep to workaround clvmd -S race: socket closed early and server drops cmd.
+- Exit successfully when using -o help (but not -o +help) with LVM reports.
+- Add man pages for lvmconf, dmeventd and non-existent lvmsadc and lvmsar tools.
+- Add --force, --nofsck and --resizefs to lvresize/extend/reduce man pages.
+- Fix lvm2cmd example in documentation.
+- Fix typo in warning message about missing device with allocated data areas.
+- Add device name and offset to raw_read_mda_header error messages.
+- Allow use of lvm2app and lvm2cmd headers in C++ code.
+
+* Fri Jun 4 2010 Alasdair Kergon <agk@redhat.com> - 2.02.67-1
+- Require partial option in lvchange --refresh for partial LVs.
+- Don't merge unchanged persistent cache file before dumping if tool scanned.
+- Avoid selecting names under /dev/block if there is an alternative.
+- Fix semctl parameter (union) to avoid misaligned parameter on some arches.
+- Fix clvmd initscript restart command to start clvmd if not yet running.
+- Handle failed restart of clvmd using -S switch properly.
+- Use built-in absolute paths in clvmd (clvmd restart and PV and LV queries).
+- Consistently return ECMD_FAILED if interrupted processing multiple LVs.
+- Add --type parameter description to the lvcreate man page.
+- Document 'clear' in dmsetup man page.
+- Replace strncmp kernel version number checks with proper ones.
+- Update clustered log kernel module name to log-userspace for 2.6.31 onwards.
+- Support autoloading of dm-mod module for kernels from 2.6.35.
+- Add dm_tree_node_set_presuspend_node() to presuspend child when deactivating.
+- Do not fail lvm_init() if init_logging() or _init_rand() generates an errno.
+- Fix incorrect memory pool deallocation while using vg_read for files.
+
+* Thu May 20 2010 Alasdair Kergon <agk@redhat.com> - 2.02.66-2
+- Simplify and fix Requires package headers.
+- If unable to obtain snapshot percentage leave value blank on reports.
+- Use new install_system_dirs and install_initscripts makefile targets.
+- Add lvm2app functions to lookup a vgname from a pvid and pvname.
+- Change internal processing of PVs in pvchange.
+- Validate internal lock ordering of orphan and VG_GLOBAL locks.
+
+* Mon May 17 2010 Alasdair Kergon <agk@redhat.com> - 2.02.65-1
+- Disallow vgchange --clustered if there are active mirrors or snapshots.
+- Fix truncated total size displayed by pvscan.
+- Skip internal lvm devices in scan if ignore_suspended_devices is set.
+- Do not merge old device cache after we run full scan. (2.02.56)
+- Add new --sysinit compound option to vgchange and lvchange.
+- Fix clvmd init script never to deactivate non-clustered volume groups.
+- Drop duplicate errors for read failures and missing devices to verbose level.
+- Do not print encryption key in message debug output (cryptsetup luksResume).
+- Use -d to control level of messages sent to syslog by dmeventd.
+- Change -d to -f to run dmeventd in foreground.
+- Fix udev flags on remove in create_and_load error path.
+- Add dm_list_splice() function to join two lists together.
+- Use /bin/bash for scripts with bashisms.
+- Switch Libs.private to Requires.private in devmapper.pc and lvm2app.pc.
+- Use pkgconfig Requires.private for devmapper-event.pc.
+
+* Fri Apr 30 2010 Alasdair Kergon <agk@redhat.com> - 2.02.64-1
+- Avoid pointless initialisation when the 'version' command is run directly.
+- Fix memory leak for invalid regex pattern input.
+- Display invalid regex pattern for filter configuration in case of error.
+- Fix -M and --type to use strings, not pointers that change on config refresh.
+- Fix lvconvert error message when existing mirrored LV is not found.
+- Set appropriate udev flags for reserved LVs.
+- Disallow the direct removal of a merging snapshot.
+- Don't preload the origin when removing a snapshot whose merge is pending.
+- Disallow the addition of mirror images while a conversion is happening.
+- Disallow primary mirror image removal when mirror is not in-sync.
+- Remove obsolete --name parameter from vgcfgrestore.
+- Add -S command to clvmd to restart the daemon preserving exclusive locks.
+- Increment lvm2app version from 1 to 2 (memory allocation changes).
+- Change lvm2app memory alloc/free for pv/vg/lv properties.
+- Change daemon lock filename from lvm2_monitor to lvm2-monitor for consistency.
+- Add support for new IMPORT{db} udev rule.
+- Add DM_UDEV_PRIMARY_SOURCE_FLAG udev flag to recognize proper DM events.
+- Also include udev libs in libdevmapper.pc.
+- Cache bitset locations to speed up _calc_states.
+- Add a regex optimisation pass for shared prefixes and suffixes.
+- Add dm_bit_and and dm_bitset_equal to libdevmapper.
+- Speed up dm_bit_get_next with ffs().
+
+* Thu Apr 15 2010 Alasdair Kergon <agk@redhat.com> - 2.02.63-2
+- Remove 'lvmconf --lockinglibdir' from cluster post: locking is now built-in.
+- Move libdevmapper-event-lvm2.so to devel package.
+- Explicitly specify libdevmapper-event.so* attributes.
+- Drop support for upgrades from very old versions that used lvm not lvm2.
+- Move libdevmapper-event plug-in libraries into new device-mapper subdirectory.
+- Don't verify lvm.conf contents when using rpm --verify.
+
+* Wed Apr 14 2010 Alasdair Kergon <agk@redhat.com> - 2.02.63-1
+- Move development links to shared objects to /usr (hard-coded temporarily).
+- Change libdevmapper deactivation to fail if device is open.
+- Wipe memory buffers for libdevmapper dm-ioctl parameters before releasing.
+- Strictly require libudev if udev_sync is used.
+- Add support for ioctl's DM_UEVENT_GENERATED_FLAG.
+- Allow incomplete mirror restore in lvconvert --repair upon insufficient space.
+- Do not reset position in metadata ring buffer on vgrename and vgcfgrestore.
+- Allow VGs with active LVs to be renamed.
+- Only pass visible LVs to tools in cmdline VG name/tag expansions without -a.
+- Use C locale and mlockall in clvmd and dmeventd.
+- Mask LCK_HOLD in cluster VG locks for upgrade compatibility with older clvmd.
+- Add activation/polling_interval to lvm.conf as --interval default.
+- Don't ignore error if resuming any LV fails when resuming groups of LVs.
+- Skip closing persistent filter cache file if open failed.
+- Permit mimage LVs to be striped in lvcreate, lvresize and lvconvert.
+- Fix pvmove allocation to take existing parallel stripes into account.
+- Fix incorrect removal of symlinks after LV deactivation fails.
+- Fix is_partitioned_dev not to attempt to reopen device.
+- Fix another thread race in clvmd.
+- Improve vg_validate to detect some loops in lists.
+- Change most remaining log_error WARNING messages to log_warn.
+- Always use blocking lock for VGs and orphan locks.
+- Allocate all memory for segments from private VG mempool.
+- Optimise searching PV segments for seeking the most recently-added.
+- Remove duplicated vg_validate checks when parsing cached metadata.
+- Use hash table of LVs to speed up parsing of text metadata with many LVs.
+- Fix two vg_validate messages, adding whitespace and parentheses.
+- When dmeventd is not forking because of -d flag, don't kill parent process.
+- Fix dso resource leak in error path of dmeventd.
+- Fix --alloc contiguous policy only to allocate one set of parallel areas.
+- Do not allow {vg|lv}change --ignoremonitoring if on clustered VG.
+- Add ability to create mirrored logs for mirror LVs.
+- Fix clvmd cluster propagation of dmeventd monitoring mode.
+- Allow ALLOC_ANYWHERE to split contiguous areas.
+- Add some assertions to allocation code.
+- Introduce pv_area_used into allocation algorithm and add debug messages.
+- Add activation/monitoring to lvm.conf.
+- Add --monitor and --ignoremonitoring to lvcreate.
+- Don't allow resizing of internal logical volumes.
+- Fix libdevmapper-event pkgconfig version string to match libdevmapper.
+- Avoid scanning all pvs in the system if operating on a device with mdas.
+- Disable long living process flag in lvm2app library.
+- Fix pvcreate device md filter check.
+- Suppress repeated errors about the same missing PV uuids.
+- Bypass full device scans when using internally-cached VG metadata.
+- Only do one full device scan during each read of text format metadata.
+- Look up missing PVs by uuid not dev_name in pvs to avoid invalid stat.
+
+* Tue Mar 09 2010 Alasdair Kergon <agk@redhat.com> - 2.02.62-1
+- Rewrite clvmd init script.
+- Add default alternative to mlockall using mlock to reduce pinned memory size.
+- Add use_mlockall and mlock_filter to activation section of lvm.conf.
+- Handle misaligned devices that report alignment_offset of -1.
+- Extend core allocation code in preparation for mirrored log areas.
+- No longer fall back to looking up active devices by name if uuid not found.
+- Don't touch /dev in vgmknodes if activation is disabled.
+- Add --showkeys parameter description to dmsetup man page.
+- Add --help option as synonym for help command.
+- Add lvm2app functions lvm_{vg|lv}_{get|add|remove}_tag() functions.
+- Refactor snapshot-merge deptree and device removal to support info-by-uuid.
+
+* Fri Mar 05 2010 Peter Rajnoha <prajnoha@redhat.com> - 2.02.61-2
+- Change spec file to support excluding cluster components from the build.
+
+* Tue Feb 16 2010 Alasdair Kergon <agk@redhat.com> - 2.02.61-1
+- Add %%ORIGIN support to lv{create,extend,reduce,resize} --extents.
+- Accept a list of LVs with 'lvconvert --merge @tag' using process_each_lv.
+- Remove false "failed to find tree node" error when activating merging origin.
+- Exit with success when lvconvert --repair --use-policies performs no action.
+- Avoid unnecessary second resync when adding mimage to core-logged mirror.
+- Make clvmd -V return status zero.
+- Fix cmirrord segfault in clog_cpg list processing when converting mirror log.
+- Deactivate temporary pvmove mirror cluster-wide when activating it fails.
+- Add missing metadata vg_reverts in pvmove error paths.
+- Unlock shared lock in clvmd if activation calls fail.
+- Add lvm_pv_get_size, lvm_pv_get_free and lvm_pv_get_dev_size to lvm2app.
+- Change lvm2app to return all sizes in bytes as documented (not sectors).
+- Exclude internal VG names and uuids from lists returned through lvm2app.
+- Add LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES environment variable.
+- Add DM_UDEV_DISABLE_LIBRARY_FALLBACK udev flag to rely on udev only.
+- Remove hard-coding that skipped _mimage devices from 11-dm-lvm.rules.
+- Export dm_udev_create_cookie function to create new cookies on demand.
+- Add --udevcookie, udevcreatecookie and udevreleasecookie to dmsetup.
+- Set udev state automatically instead of using DM_UDEV_DISABLE_CHECKING.
+- Set udev state automatically instead of using LVM_UDEV_DISABLE_CHECKING.
+- Remove pointless versioned symlinks to dmeventd plugin libraries.
+
+* Fri Jan 29 2010 Alasdair Kergon <agk@redhat.com> - 2.02.60-5
+- Replace spaces with tabs in a couple of places in spec file.
+
+* Sat Jan 23 2010 Alasdair Kergon <agk@redhat.com> - 2.02.60-4
+- Extend cmirrord man page.
+- Sleep before first progress check iff pvmove/lvconvert interval has prefix '+'.
+- Fix cmirror initscript syntax problems.
+- Fix first syslog message prefix for dmeventd plugins.
+- Make failed locking initialisation messages more descriptive.
+
+* Fri Jan 22 2010 Alasdair Kergon <agk@redhat.com> - 2.02.59-3
+- Fix dmeventd lvm2 wrapper (plug-ins unusable in last build).
+- Make failed locking initialisation messages more descriptive.
+
+* Fri Jan 22 2010 Fabio M. Di Nitto <fdinitto@redhat.com> - 2.02.59-2
+- Drop duplicated BuildRequires on openaislib-devel.
+- Drop Requires on clusterlib for cmirror subpackage.
+- clvmd subpackage should Requires cman (#506592).
+
+* Fri Jan 22 2010 Alasdair Kergon <agk@redhat.com> - 2.02.59-1
+- Add cmirror subpackage for clustered mirrors.
+- Set 'preferred_names' in default lvm.conf.
+- Add libdevmapper-event-lvm2.so to serialise dmeventd plugin liblvm2cmd use.
+- Stop dmeventd trying to access already-removed snapshots.
+- Fix clvmd to never scan suspended devices.
+- Fix detection of completed snapshot merge.
+- Improve snapshot merge metadata import validation.
+
+* Thu Jan 14 2010 Alasdair Kergon <agk@redhat.com> - 2.02.58-1
+- Fix clvmd automatic target module loading crash.
+- Fix allocation code not to stop at the first area of a PV that fits.
+- Add support for the "snapshot-merge" kernel target (2.6.33-rc1).
+- Add --merge to lvconvert to merge a snapshot into its origin.
+
+* Tue Jan 12 2010 Alasdair Kergon <agk@redhat.com> - 2.02.57-1
+- Add --splitmirrors to lvconvert to split off part of a mirror.
+- Allow vgremove to remove a VG with PVs missing after a prompt.
+- Add activation/udev_rules config option in lvm.conf.
+- Add --poll flag to vgchange and lvchange to control background daemon launch.
+- Impose limit of 8 mirror images to match the in-kernel kcopyd restriction.
+- Log failure type and recognise type 'F' (flush) in dmeventd mirror plugin.
+- Add --noudevrules option for dmsetup to disable /dev node management by udev.
+- Fix 'dmsetup info -c -o all' to show all fields.
+- Fix coredump and memory leak for 'dmsetup help -c'.
+- Rename mirror_device_fault_policy to mirror_image_fault policy.
+- Use extended status of new kernel snapshot target 1.8.0 to detect when empty.
+- Allow use of precommitted metadata when a PV is missing.
+- Add global/abort_on_internal_errors to lvm.conf to assist testing.
+- If aborting due to internal error, always send that message to stderr.
+- Keep log type consistent when changing mirror image count.
+- Exit with success in lvconvert --repair --use-policies on failed allocation.
+- Ensure any background daemon exits without duplicating parent's functionality.
+- Change background daemon process names to "(lvm2)".
+- Fix internal lock state after forking.
+- Remove empty PV devices if lvconvert --repair is using defined policies.
+- Use fixed buffer to prevent stack overflow in persistent filter dump.
+- Propagate metadata commit and revert notifications to other cluster nodes.
+- Fix metadata caching and lock state propagation to remote nodes in clvmd.
+- Properly decode all flags in clvmd messages including VG locks.
+- Drop cached metadata after device was auto-repaired and removed from VG.
+- Clear MISSING_PV flag if PV reappeared and is empty.
+- Fix removal of multiple devices from a mirror.
+- Also clean up PVs flagged as missing in vgreduce --removemissing --force.
+- Fix some pvresize and toollib error paths with missing VG releases/unlocks.
+- Explicitly call suspend for temporary mirror layer.
+- Add memlock information to do_lock_lv debug output.
+- Always bypass calls to remote cluster nodes for non-clustered VGs.
+- Permit implicit cluster lock conversion in pre/post callbacks on local node.
+- Permit implicit cluster lock conversion to the lock mode already held.
+- Fix lock flag masking in clvmd so intended code paths get invoked.
+- Remove newly-created mirror log from metadata if initial deactivation fails.
+- Improve pvmove error message when all source LVs are skipped.
+- Fix memlock imbalance in lv_suspend if already suspended.
+- Fix pvmove test mode not to poll (and fail).
+- Fix vgcreate error message if VG already exists.
+- Fix tools to use log_error when aborted due to user response to prompt.
+- Fix ignored readahead setting in lvcreate --readahead.
+- Fix clvmd memory leak in lv_info_by_lvid by calling release_vg.
+- If LVM_UDEV_DISABLE_CHECKING is set in environment, disable udev warnings.
+- If DM_UDEV_DISABLE_CHECKING is set in environment, disable udev warnings.
+- Always set environment variables for an LVM2 device in 11-dm-lvm.rules.
+- Disable udev rules for change events with DISK_RO set.
+- Add dm_tree_add_dev_with_udev_flags to provide wider support for udev flags.
+- Correct activated or deactivated text in vgchange summary message.
+- Fix fsadm man page typo (fsdam).
+
+* Tue Nov 24 2009 Alasdair Kergon <agk@redhat.com> - 2.02.56-2
+- Revert vg_read_internal change as clvmd was not ready for vg_read. (2.02.55)
+- Fix unbalanced memory locking when deactivating LVs.
+- Add missing vg_release to pvs and pvdisplay to fix memory leak.
+- Do not try to unlock VG which is not locked when processing a VG.
+- Update .cache file after every full device rescan in clvmd.
+- Refresh all device filters (including sysfs) before each full device rescan.
+- Return error status if vgchange fails to activate any volume.
+
+* Thu Nov 19 2009 Alasdair Kergon <agk@redhat.com> - 2.02.55-1
+- Fix deadlock when changing mirrors due to unpaired memlock refcount changes.
+- Fix pvmove region_size overflow for very large PVs.
+- Fix lvcreate and lvresize %%PVS argument always to use sensible total size.
+- Directly restrict vgchange to activating visible LVs.
+- Fix hash lookup segfault when keys compared are different lengths.
+- Flush stdout after yes/no prompt.
+- Recognise DRBD devices and handle them like md devices.
+- Add dmsetup --inactive support (requires kernel support targetted for 2.6.33).
+
+* Fri Nov 13 2009 Peter Rajnoha <prajnoha@redhat.com> - 2.02.54-3
+- Support udev flags even when udev_sync is disabled.
+- Remove last_rule from udev_rules.
+- Udev rules cleanup.
+
+* Tue Nov 3 2009 Peter Rajnoha <prajnoha@redhat.com> - 2.02.54-2
+- Enable udev synchronisation code.
+- Install default udev rules for device-mapper and LVM2.
+- Add BuildRequires: libudev-devel.
+- Add Requires: libudev (to check udev is running).
+- Add Requires: util-linux-ng (blkid used in udev rules).
+- Add Conflicts: dracut < 002-18 (for dracut to install required udev rules)
+
+* Tue Oct 27 2009 Alasdair Kergon <agk@redhat.com> - 2.02.54-1
+- Add implict pvcreate support to vgcreate and vgextend.
+- Add --pvmetadatacopies for pvcreate, vgcreate, vgextend, vgconvert.
+- Distinguish between powers of 1000 and powers of 1024 in unit suffixes.
+- Restart lvconverts in vgchange.
+- Don't attempt to deactivate an LV if any of its snapshots are in use.
+- Return error if lv_deactivate fails to remove device from kernel.
+- Treat input units of both 's' and 'S' as 512-byte sectors.  (2.02.49)
+- Use standard output units for 'PE Size' and 'Stripe size' in pv/lvdisplay.
+- Add global/si_unit_consistency to enable cleaned-up use of units in output.
+- Only do lock conversions in clvmd if we are explicitly asked for one.
+- Fix clvmd segfault when refresh_toolcontext fails.
+- Cleanup mimagetmp LV if allocation fails for new lvconvert mimage.
+- Handle metadata with unknown segment types more gracefully.
+- Make clvmd return 0 on success rather than 1.
+- Correct example.conf to indicate that lvm2 not lvm1 is the default format.
+- Delay announcing mirror monitoring to syslog until initialisation succeeded.
+- Update lvcreate/lvconvert man pages to explain PhysicalVolume parameter.
+- Document --all option in man pages and cleanup {pv|vg|lv}{s|display} pages.
+
+* Mon Oct 19 2009 Fabio M. Di Nitto <fdinitto@redhat.com> - 2.02.53-3
+- Enable openais support in clvmd.
+
+* Fri Sep 25 2009 Alasdair Kergon <agk@redhat.com> - 2.02.53-2
+- Reissued tarball to fix compilation warning from lvm2_log_fn prototype.
+
+* Fri Sep 25 2009 Alasdair Kergon <agk@redhat.com> - 2.02.53-1
+- Create any directories in /dev with umask 022. (#507397)
+- Handle paths supplied to dm_task_set_name by getting name from /dev/mapper.
+- Add splitname and --yes to dmsetup man page.
+
+* Thu Sep 24 2009 Peter Rajnoha <prajnoha@redhat.com> - 2.02.52-4
+- Disable udev synchronisation code (revert previous build).
+
+* Mon Sep 21 2009 Peter Rajnoha <prajnoha@redhat.com> - 2.02.52-3
+- Enable udev synchronisation code.
+- Install default udev rules for device-mapper and LVM2.
+- Add BuildRequires: libudev-devel.
+- Add Requires: libudev (to check udev is running).
+- Add Requires: util-linux-ng (blkid used in udev rules).
+
+* Wed Sep 16 2009 Alasdair Kergon <agk@redhat.com> - 2.02.52-2
+- Build dmeventd and place into a separate set of subpackages.
+- Remove no-longer-needed BuildRoot tag and buildroot emptying at install.
+
+* Tue Sep 15 2009 Alasdair Kergon <agk@redhat.com> - 2.02.52-1
+- Prioritise write locks over read locks by default for file locking.
+- Add local lock files with suffix ':aux' to serialise locking requests.
+- Fix readonly locking to permit writeable global locks (for vgscan). (2.02.49)
+- Make readonly locking available as locking type 4.
+- Fix global locking in PV reporting commands (2.02.49).
+- Make lvchange --refresh only take a read lock on volume group.
+- Fix race where non-blocking file locks could be granted in error.
+- Fix pvcreate string termination in duplicate uuid warning message.
+- Don't loop reading sysfs with pvcreate on a non-blkext partition (2.02.51).
+- Fix vgcfgrestore error paths when locking fails (2.02.49).
+- Make clvmd check corosync to see what cluster interface it should use.
+- Fix vgextend error path - if ORPHAN lock fails, unlock / release vg (2.02.49).
+- Clarify use of PE ranges in lv{convert|create|extend|resize} man pages.
+- Restore umask when device node creation fails.
+- Check kernel vsn to use 'block_on_error' or 'handle_errors' in mirror table.
+
+* Mon Aug 24 2009 Milan Broz <mbroz@redhat.com> - 2.02.51-3
+- Fix global locking in PV reporting commands (2.02.49).
+- Fix pvcreate on a partition (2.02.51).
+- Build clvmd with both cman and corosync support.
+
+* Thu Aug 6 2009 Alasdair Kergon <agk@redhat.com> - 2.02.51-2
+- Fix clvmd locking broken in 2.02.50-1.
+- Only change LV /dev symlinks on ACTIVATE not PRELOAD (so not done twice).
+- Make lvconvert honour log mirror options combined with downconversion.
+- Add devices/data_alignment_detection to lvm.conf.
+- Add devices/data_alignment_offset_detection to lvm.conf.
+- Add --dataalignmentoffset to pvcreate to shift start of aligned data area.
+- Update synopsis in lvconvert manpage to mention --repair.
+- Document -I option of clvmd in the man page.
+
+* Thu Jul 30 2009 Alasdair Kergon <agk@redhat.com> - 2.02.50-2
+- lvm2-devel requires device-mapper-devel.
+- Fix lvm2app.pc filename.
+
+* Tue Jul 28 2009 Alasdair Kergon <agk@redhat.com> - 2.02.50-1
+- Add libs and devel subpackages to include shared libraries for applications.
+  N.B. The liblvm2app API is not frozen yet and may still be changed
+  Send any feedback to the mailing list lvm-devel@redhat.com.
+- Remove obsolete --with-dmdir from configure.
+- Add global/wait_for_locks to lvm.conf so blocking for locks can be disabled.
+- Fix race condition with vgcreate and vgextend on same device since 2.02.49.
+- Add an API version number, LVM_LIBAPI, to the VERSION string.
+- Return EINVALID_CMD_LINE not success when invalid VG name format is used.
+- Remove unnecessary messages after vgcreate/vgsplit code change in 2.02.49.
+- Store any errno and error messages issued while processing each command.
+
+* Sat Jul 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.02.49-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Wed Jul 15 2009 Alasdair Kergon <agk@redhat.com> - 2.02.49-1
+- Exclude VG_GLOBAL from vg_write_lock_held so scans open devs read-only again.
+- Fix dev name mismatch in vgcreate man page example.
+- Check md devices for a partition table during device scan.
+- Add extended device (blkext) and md partition (mdp) types to filters.
+- Make text metadata read errors for segment areas more precise.
+- Fix text segment metadata read errors to mention correct segment name.
+- Include segment and LV names in text segment import error messages.
+- Fix memory leak in vgsplit when re-reading the vg.
+- Permit several segment types to be registered by a single shared object.
+- Update the man pages to document size units uniformly.
+- Allow commandline sizes to be specified in terms of bytes and sectors.
+- Update 'md_chunk_alignment' to use stripe-width to align PV data area.
+- Fix segfault in vg_release when vg->cmd is NULL.
+- Add dm_log_with_errno and dm_log_with_errno_init, deprecating the old fns.
+- Fix whitespace in linear target line to fix identical table line detection.
+- Add device number to more log messages during activation.
+
+* Fri Jul 10 2009 Fabio M. Di Nitto <fdinitto@redhat.com> 2.02.48-2
+- BuildRequires and Requires on stable versions of both corosync-lib (1.0.0-1)
+  and cluster-lib (3.0.0-20).
+
+* Tue Jun 30 2009 Alasdair Kergon <agk@redhat.com> - 2.02.48-1
+- Abort if automatic metadata correction fails when reading VG to update it.
+- Don't fallback to default major number in libdm: use dm_task_set_major_minor.
+- Explicitly request fallback to default major number in device mapper.
+- Ignore suspended devices during repair.
+- Suggest using lvchange --resync when adding leg to not-yet-synced mirror.
+- Destroy toolcontext on clvmd exit to avoid memory pool leaks.
+- Fix lvconvert not to poll mirror if no conversion in progress.
+- Fix memory leaks in toolcontext error path.
+- Reinstate partial activation support in clustered mode.
+- Allow metadata correction even when PVs are missing.
+- Use 'lvm lvresize' instead of 'lvresize' in fsadm.
+- Do not use '-n' realine option in fsadm for rescue disk compatiblity.
+- Round up requested readahead to at least one page and print warning.
+- Try to repair vg before actual vgremove when force flag provided.
+- Unify error messages when processing inconsistent volume group.
+- Introduce lvconvert --use_policies (repair policy according to lvm.conf).
+- Fix rename of active snapshot with virtual origin.
+- Fix convert polling to ignore LV with different UUID.
+- Cache underlying device readahead only before activation calls.
+- Fix segfault when calculating readahead on missing device in vgreduce.
+- Remove verbose 'visited' messages.
+- Handle multi-extent mirror log allocation when smallest PV has only 1 extent.
+- Add LSB standard headers and functions (incl. reload) to clvmd initscript.
+- When creating new LV, double-check that name is not already in use.
+- Remove /dev/vgname/lvname symlink automatically if LV is no longer visible.
+- Rename internal vorigin LV to match visible LV.
+- Suppress 'removed' messages displayed when internal LVs are removed.
+- Fix lvchange -a and -p for sparse LVs.
+- Fix lvcreate --virtualsize to activate the new device immediately.
+- Make --snapshot optional with lvcreate --virtualsize.
+- Generalise --virtualoriginsize to --virtualsize.
+- Skip virtual origins in process_each_lv_in_vg() without --all.
+- Fix counting of virtual origin LVs in vg_validate.
+- Attempt to load dm-zero module if zero target needed but not present.
+- Add crypt target handling to libdevmapper tree nodes.
+- Add splitname command to dmsetup.
+- Add subsystem, vg_name, lv_name, lv_layer fields to dmsetup reports.
+- Make mempool optional in dm_split_lvm_name() in libdevmapper.
+
+* Wed Jun 10 2009 Fabio M. Di Nitto <fdinitto@redhat.com> - 2.02.47-2
+- BuildRequire newer version of corosynclib (0.97-1) to link against
+  latest libraries version (soname 4.0.0).
+- Add lvm2-2_02_48-cluster-cpg-new-api.patch to port clvmd-corosync
+  to new corosync cpg API.
+
+* Fri May 22 2009 Alasdair Kergon <agk@redhat.com> - 2.02.47-1
+- Inherit readahead setting from underlying devices during activation.
+- Detect LVs active on remote nodes by querying locks if supported.
+- Enable online resizing of mirrors.
+- Use suspend with flush when device size was changed during table preload.
+- Implement query_resource_fn for cluster_locking.
+- Support query_resource_fn in locking modules.
+- Fix pvmove to revert operation if temporary mirror creation fails.
+- Fix metadata export for VG with missing PVs.
+- Add vgimportclone and install it and the man page by default.
+- Force max_lv restriction only for newly created LV.
+- Do not query nonexistent devices for readahead.
+- Reject missing PVs from allocation in toollib.
+- Fix PV datalignment for values starting prior to MDA area. (2.02.45)
+- Add sparse devices: lvcreate -s --virtualoriginsize (hidden zero origin).
+- Fix minimum width of devices column in reports.
+- Add lvs origin_size field.
+- Implement lvconvert --repair for repairing partially-failed mirrors.
+- Fix vgreduce --removemissing failure exit code.
+- Fix remote metadata backup for clvmd.
+- Fix metadata backup to run after vg_commit always.
+- Fix pvs report for orphan PVs when segment attributes are requested.
+- Fix pvs -a output to not read volume groups from non-PV devices.
+- Introduce memory pools per volume group (to reduce memory for large VGs).
+- Always return exit error status when locking of volume group fails.
+- Fix mirror log convert validation question.
+- Enable use of cached metadata for pvs and pvdisplay commands.
+- Fix memory leak in mirror allocation code.
+- Save and restore the previous logging level when log level is changed.
+- Fix error message when archive initialization fails.
+- Make sure clvmd-corosync releases the lockspace when it exits.
+- Fix segfault for vgcfgrestore on VG with missing PVs.
+- Block SIGTERM & SIGINT in clvmd subthreads.
+- Detect and conditionally wipe swapspace signatures in pvcreate.
+- Fix maximal volume count check for snapshots if max_lv set for volume group.
+- Fix lvcreate to remove unused cow volume if the snapshot creation fails.
+- Fix error messages when PV uuid or pe_start reading fails.
+- Flush memory pool and fix locking in clvmd refresh and backup command.
+- Fix unlocks in clvmd-corosync. (2.02.45)
+- Fix error message when adding metadata directory to internal list fails.
+- Fix size and error message of memory allocation at backup initialization.
+- Remove old metadata backup file after renaming VG.
+- Restore log_suppress state when metadata backup file is up-to-date.
+- Export dm_tree_node_size_changed() from libdevmapper.
+- Fix segfault when getopt processes dmsetup -U, -G and -M options.
+- Add _smp_mflags to compilation and remove DESTDIR.
+
+* Fri Apr 17 2009 Milan Broz <mbroz@redhat.com> - 2.02.45-4
+- Add MMC (mmcblk) device type to filters. (483686)
+
+* Mon Mar 30 2009 Jussi Lehtola <jussi.lehtola@iki.fi> 2.02.45-3
+- Add FTP server location to Source0.
+
+* Mon Mar 30 2009 Fabio M. Di Nitto <fdinitto@redhat.com> - 2.02.45-2
+- BuildRequires a newer version of corosync (0.95-2) to fix linking.
+
+* Tue Mar 3 2009 Alasdair Kergon <agk@redhat.com> - 2.02.45-1
+- Update clusterlib and corosync dependencies.
+- Attempt proper clean up in child before executing fsadm or modprobe.
+- Do not scan devices if reporting only attributes from PV label.
+- Use pkgconfig to obtain corosync library details during configuration.
+- Fix error returns in clvmd-corosync interface to DLM.
+- Add --refresh to vgchange and vgmknodes man pages.
+- Pass --test from lvresize to fsadm as --dry-run.
+- Prevent fsadm from checking mounted filesystems.
+- No longer treats any other key as 'no' when prompting in fsadm.
+- Add --dataalignment to pvcreate to specify alignment of data area.
+- Fix unblocking of interrupts after several commands.
+- Provide da and mda locations in debug message when writing text format label.
+- Mention the restriction on file descriptors at invocation on the lvm man page.
+- Index cached vgmetadata by vgid not vgname to cope with duplicate vgnames.
+- No longer require kernel and metadata major numbers to match.
+- If kernel supports only one dm major number, use in place of any supplied.
+- Add option to /etc/sysconfig/cluster to select cluster type for clvmd.
+- Allow clvmd to start up if its lockspace already exists.
+- Separate PV label attributes which do not need parse metadata when reporting.
+- Remove external dependency on the 'cut' command from fsadm.
+- Fix pvs segfault when pv mda attributes requested for unavailable PV.
+- Add fsadm support for reszing ext4 filesysystems.
+- Change lvm2-cluster to corosync instead of cman.
+- Fix some old changelog typos in email addresses.
+
+* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.02.44-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Tue Jan 27 2009 Alasdair Kergon <agk@redhat.com> - 2.02.44-1
+- Add --nameprefixes, --unquoted, --rows to pvs, vgs, lvs man pages.
+- Fix lvresize size conversion for fsadm when block size is not 1K.
+- Fix pvs segfault when run with orphan PV and some VG fields.
+- Display a 'dev_size' of zero for missing devices in reports.
+- Add pv_mda_size to pvs and vg_mda_size to vgs.
+- Fix lvmdump /sys listing to include virtual devices directory.
+- Add "--refresh" functionality to vgchange and vgmknodes.
+- Avoid exceeding LV size when wiping device.
+- Calculate mirror log size instead of using 1 extent.
+- Ensure requested device number is available before activating with it.
+- Fix incorrect exit status from 'help <command>'.
+- Fix vgrename using UUID if there are VGs with identical names.
+- Fix segfault when invalid field given in reporting commands.
+- Use better random seed value in temp file creation.
+- Add read_urandom to read /dev/urandom. Use in uuid calculation.
+- Fix race in vgcreate that would result in second caller overwriting first.
+- Fix uninitialised lv_count in vgdisplay -c.
+- Don't skip updating pvid hash when lvmcache_info struct got swapped.
+- Fix startup race in clvmd.
+- Cope with snapshot dependencies when removing a whole VG with lvremove.
+- Make man pages and tool help text consistent using | for alternative options.
+- Add "all" field to reports expanding to all fields of report type.
+- Enforce device name length and character limitations in libdm.
+
+* Mon Nov 10 2008 Alasdair Kergon <agk@redhat.com> - 2.02.43-1
+- Upstream merge of device-mapper and lvm2 source.
+- Correct prototype for --permission on lvchange and lvcreate man pages.
+- Exit with non-zero status from vgdisplay if couldn't show any requested VG.
+- libdevmapper.pc: Use simplified x.y.z version number.
+- Accept locking fallback_to_* options in the global section as documented.
+- Several fixes to lvconvert involving mirrors.
+- Avoid overwriting in-use on-disk text metadata when metadataarea fills up.
+- Generate man pages from templates and include version.
+- Fix misleading error message when there are no allocatable extents in VG.
+- Fix handling of PVs which reappeared with old metadata version.
+- Fix validation of --minor and --major in lvcreate to require -My always.
+- Allow lvremove to remove LVs from VGs with missing PVs.
+- In VG with PVs missing, by default allow activation of LVs that are complete.
+- Require --force with --removemissing in vgreduce to remove partial LVs.
+- No longer write out PARTIAL flag into metadata backups.
+- Treat new default activation/missing_stripe_filler "error" as an error target.
+- Add devices/md_chunk_alignment to lvm.conf.
+- Pass struct physical_volume to pe_align and adjust for md chunk size.
+- Avoid shuffling remaining mirror images when removing one, retaining primary.
+- Prevent resizing an LV while lvconvert is using it.
+- Avoid repeatedly wiping cache while VG_GLOBAL is held in vgscan & pvscan.
+- Fix pvresize to not allow resize if PV has two metadata areas.
+- Fix setting of volume limit count if converting to lvm1 format.
+- Fix vgconvert logical volume id metadata validation.
+- Fix lvmdump metadata gather option (-m) to work correctly.
+- Fix allocation bug in text metadata format write error path.
+- Fix vgcfgbackup to properly check filename if template is used.
+- vgremove tries to remove lv snapshot first.
+- Improve file descriptor leak detection to display likely culprit and filename.
+- Avoid looping forever in _pv_analyze_mda_raw used by pvck.
+- Change lvchange exit status to indicate if any part of the operation failed.
+- Fix pvchange and pvremove to handle PVs without mdas.
+- Fix pvchange -M1 -u to preserve existing extent locations when there's a VG.
+- Cease recognising snapshot-in-use percentages returned by early devt kernels.
+- Add backward-compatible flags field to on-disk format_text metadata.
+- libdevmapper: Only resume devices in dm_tree_preload_children if size changes.
+- libdevmapper: Extend deptree buffers so the largest possible device numbers fit.
+- libdevmapper: Underline longer report help text headings.
+
+* Tue Oct 7 2008 Alasdair Kergon <agk@redhat.com> - 2.02.39-6
+- Only set exec_prefix once and configure explicit directories to work with
+  new version of rpm.
+
+* Fri Sep 26 2008 Fabio M. Di Nitto <fdinitto@redhat.cm> - 2.02.39-5
+- Add BuildRequires on cmanlib-devel. This is required after libcman split
+  from cman and cman-devel into cmanlib and cmanlib-devel.
+- Make versioned BuildRequires on cman-devel and cmanlib-devel more strict
+  to guarantee to get the right version.
+
+* Thu Sep 25 2008 Fabio M. Di Nitto <fdinitto@redhat.cm> - 2.02.39-5
+- Add versioned BuildRequires on new cman-devel.
+
+* Sun Sep 21 2008 Ville Skyttä <ville.skytta at iki.fi> - 2.02.39-5
+- Change %%patch to %%patch0 to match Patch0 as required by RPM package update.
+
+* Thu Aug  7 2008 Tom "spot" Callaway <tcallawa@redhat.com> - 2.02.39-4
+- Fix license tag.
+
+* Fri Jun 27 2008 Alasdair Kergon <agk@redhat.com> - 2.02.39-3
+- Fix up cache for PVs without mdas after consistent VG metadata is processed.
+- Update validation of safe mirror log type conversions in lvconvert.
+- Fix lvconvert to disallow snapshot and mirror combinations.
+- Fix reporting of LV fields alongside unallocated PV segments.
+- Add --unquoted and --rows to reporting tools.
+- Avoid undefined status code after _memlock commands in lvm shell.
+- Fix and improve readahead 'auto' calculation for stripe_size.
+- Fix lvchange output for -r auto setting if auto is already set.
+- Fix add_mirror_images not to dereference uninitialized log_lv upon failure.
+- Add --force to lvextend and lvresize.
+- Fix vgchange to not activate component mirror volumes directly.
+
+* Wed Jun 25 2008 Alasdair Kergon <agk@redhat.com> - 2.02.38-2
+- dmsetup: Add --unquoted and --rows to 'info -c' command.
+- libdevmapper: Fix inverted no_flush debug message.
+
+* Fri Jun 13 2008 Alasdair Kergon <agk@redhat.com> - 2.02.38-1
+- libdevmapper: Make dm_hash_iter safe against deletion.
+- libdevmapper: Accept a NULL pointer to dm_free silently.
+- libdevmapper: Calculate string size within dm_pool_grow_object.
+- libdevmapper: Send reporting field help text to stderr not stdout.
+
+- dmsetup: Add tables_loaded, readonly and suspended columns to reports.
+- dmsetup: Add --nameprefixes for new report output format FIELD=VALUE.
+
+- Add --nameprefixes to reporting tools for field name prefix output format.
+- Fix return values for reporting commands when run with no PVs, LVs, or VGs.
+- Add omitted unlock_vg() call when sigint_caught() during vg processing.
+- Fix free_count when reading pool metadata.
+- Fix segfault when using pvcreate on a device containing pool metadata.
+- In script-processing mode, stop if any command fails.
+- Warn if command exits with non-zero status code without a prior log_error.
+- Correct config file line numbers in messages when parsing comments.
+- Add missing deactivation after activation failure in lvcreate -Zy.
+- When removing LV symlinks, skip any where the VG name is not determined.
+- Fix vgsplit internal counting of snapshot LVs.
+- Update vgsplit to only restrict split with active LVs involved in split.
+- Fix vgsplit to only move hidden 'snapshotN' LVs when necessary.
+- Update vgsplit man page to reflect lvnames on the cmdline.
+- Update vgsplit to take "-n LogicalVolumeName" on the cmdline.
+- Fix vgsplit error paths to release vg_to lock.
+- Avoid spurious duplicate VG messages referring to VGs that are gone.
+- Drop dev_name_confirmed error message to debug level.
+- Fix setpriority error message to signed int.
+- Add assertions to trap deprecated P_ and V_ lock usage.
+- Avoid using DLM locks with LCK_CACHE type P_ lock requests.
+- Don't touch /dev in vgrename if activation is disabled.
+- Exclude VG_GLOBAL from internal concurrent VG lock counter.
+- Fix vgmerge snapshot_count when source VG contains snapshots.
+- Fix internal LV counter when a snapshot is removed.
+- Fix metadata corruption writing lvm1-formatted metadata with snapshots.
+- Fix lvconvert -m0 allocatable space check.
+- Don't attempt remote metadata backups of non-clustered VGs.
+- Improve preferred_names lvm.conf example.
+- Fix vgdisplay 'Cur LV' field to match lvdisplay output.
+- Fix lv_count report field to exclude hidden LVs.
+- Fix some pvmove error status codes.
+- Indicate whether or not VG is clustered in vgcreate log message.
+- Mention default --clustered setting in vgcreate man page.
+- Fix vgreduce to use vg_split_mdas to check sufficient mdas remain.
+- Update lvmcache VG lock state for all locking types now.
+- Fix output if overriding command_names on cmdline.
+- Add check to vg_commit() ensuring VG lock held before writing new VG metadata.
+- Add validation of LV name to pvmove -n.
+- Add some basic internal VG lock validation.
+- Fix vgsplit internal counting of snapshot LVs.
+- Update vgsplit to only restrict split with active LVs involved in split.
+- Fix vgsplit to only move hidden 'snapshotN' LVs when necessary.
+- Update vgsplit man page to reflect lvnames on the cmdline.
+- Update vgsplit to take "-n LogicalVolumeName" on the cmdline.
+- Fix vgsplit error paths to release vg_to lock.
+- Fix vgsplit locking of new VG.
+- Avoid erroneous vgsplit error message for new VG.
+- Suppress duplicate message when lvresize fails because of invalid vgname.
+- Cache VG metadata internally while VG lock is held.
+- Fix redundant lvresize message if vg doesn't exist.
+- Make clvmd-cman use a hash rather than an array for node updown info.
+- Decode numbers in clvmd debugging output.
+- Fix uninitialised mutex in clvmd if all daemons are not running at startup.
+- Add config file overrides to clvmd when it reads the active LVs list.
+- Make clvmd refresh the context correctly when lvm.conf is updated.
+- Fix another allocation bug with clvmd and large node IDs.
+- Fix uninitialised variable in clvmd that could cause odd hangs.
+- Correct command name in lvmdiskscan man page.
+- clvmd no longer crashes if it sees nodeids over 50.
+- Fix potential deadlock in clvmd thread handling.
+- Update usage message for clvmd.
+- Fix clvmd man page not to print <br> and clarified debug options.
+- Escape double quotes and backslashes in external metadata and config data.
+- Correct a function name typo in _line_append error message.
+- Fix resetting of MIRROR_IMAGE and VISIBLE_LV after removal of LV.
+- Fix remove_layer_from_lv to empty the LV before removing it.
+- Add missing no-longer-used segs_using_this_lv test to check_lv_segments.
+- Fix lvconvert detection of mirror conversion in progress.
+- Avoid automatic lvconvert polldaemon invocation when -R specified.
+- Fix 'pvs -a' to detect VGs of PVs without metadata areas.
+- Divide up internal orphan volume group by format type.
+- Fix lvresize to support /dev/mapper prefix in the LV name.
+- Fix lvresize to pass new size to fsadm when extending device.
+- Fix unfilled parameter passed to fsadm from lvresize.
+- Update fsadm to call lvresize if the partition size differs (with option -l).
+- Fix fsadm to support VG/LV names.
+
+* Wed Apr  2 2008 Jeremy Katz <katzj@redhat.com> - 2.02.33-11
+- Adjust for new name for vio disks (from danpb)
+- And fix the build (also from danpb)
+
+* Wed Mar  5 2008 Jeremy Katz <katzj@redhat.com> - 2.02.33-10
+- recognize vio disks
+
+* Thu Jan 31 2008 Alasdair Kergon <agk@redhat.com> - 2.02.33-9
+- Improve internal label caching performance while locks are held.
+- Fix mirror log name construction during lvconvert.
+
+* Tue Jan 29 2008 Alasdair Kergon <agk@redhat.com> - 2.02.32-8
+- Fix pvs, vgs, lvs error exit status on some error paths.
+- Fix new parameter validation in vgsplit and test mode.
+- Fix internal metadata corruption in lvchange --resync.
+
+* Sat Jan 19 2008 Alasdair Kergon <agk@redhat.com> - 2.02.31-7
+- Avoid readahead error message when using default setting of lvcreate -M1.
+- Fix lvcreate --nosync not to wait for non-happening sync.
+- Add very_verbose lvconvert messages.
+
+* Thu Jan 17 2008 Alasdair Kergon <agk@redhat.com> - 2.02.30-6
+- Remove static libraries and binaries and move most binaries out of /usr.
+- Fix a segfault if using pvs with --all argument.
+- Fix vgreduce PV list processing not to process every PV in the VG.
+- Reinstate VG extent size and stripe size defaults (halved).
+- Set default readahead to twice maximium stripe size.
+- Detect non-orphans without MDAs correctly.
+- Prevent pvcreate from overwriting MDA-less PVs belonging to active VGs.
+- Don't use block_on_error with mirror targets version 1.12 and above.
+- Change vgsplit -l (for unimplemented --list) into --maxlogicalvolumes.
+- Update vgsplit to accept vgcreate options when new VG is destination.
+- Update vgsplit to accept existing VG as destination.
+- Major restructuring of pvmove and lvconvert code, adding stacking support.
+- Add new convert_lv field to lvs output.
+- Permit LV segment fields with PV segment reports.
+- Extend lvconvert to use polldaemon and wait for completion of initial sync.
+- Add seg_start_pe and seg_pe_ranges to reports.
+- Add fsadm interface to filesystem resizing tools.
+- Update --uuid argument description in man pages.
+- Print warning when lvm tools are running as non-root.
+
+* Thu Dec 20 2007 Alasdair Kergon <agk@redhat.com> - 2.02.29-5
+- Fix libdevmapper readahead processing with snapshots (for example).
+
+* Thu Dec 13 2007 Alasdair Kergon <agk@redhat.com> - 2.02.29-4
+- Add missing lvm2 build & runtime dependencies on module-init-tools (modprobe).
+
+* Thu Dec  6 2007 Jeremy Katz <katzj@redhat.com> - 2.02.29-3
+- fix requirements
+
+* Thu Dec 06 2007 Alasdair Kergon <agk@redhat.com> - 2.02.29-2
+- Fold device-mapper build into this lvm2 spec file.
+
+* Wed Dec 05 2007 Alasdair Kergon <agk@redhat.com> - 2.02.29-1
+- Make clvmd backup vg metadata on remote nodes.
+- Decode cluster locking state in log message.
+- Change file locking state messages from debug to very verbose.
+- Fix --addtag to drop @ prefix from name.
+- Stop clvmd going haywire if a pre_function fails.
+- Avoid nested vg_reads when processing PVs in VGs and fix associated locking.
+- Attempt to remove incomplete LVs with lvcreate zeroing/activation problems.
+- Add full read_ahead support.
+- Add lv_read_ahead and lv_kernel_read_ahead fields to reports and lvdisplay.
+- Prevent lvconvert -s from using same LV as origin and snapshot.
+- Fix human-readable output of odd numbers of sectors.
+- Add pv_mda_free and vg_mda_free fields to reports for raw text format.
+- Add LVM2 version to 'Generated by' comment in metadata.
+- Show 'not usable' space when PV is too large for device in pvdisplay.
+- Ignore and fix up any excessive device size found in metadata.
+- Fix error message when fixing up PV size in lvm2 metadata (2.02.11).
+- Fix orphan-related locking in pvdisplay and pvs.
+- Fix missing VG unlocks in some pvchange error paths.
+- Add some missing validation of VG names.
+- Detect md superblocks version 1.0, 1.1 and 1.2.
+- Add some pv-related error paths.
+- Handle future sysfs subsystem/block/devices directory structure.
+- Fix a bug in lvm_dump.sh checks for lvm/dmsetup binaries.
+- Fix underquotations in lvm_dump.sh.
+- Print --help output to stdout, not stderr.
+- After a cmdline processing error, don't print help text but suggest --help.
+- Add %%PVS extents option to lvresize, lvextend, and lvcreate.
+- Remove no-longer-correct restrictions on PV arg count with stripes/mirrors.
+- Fix strdup memory leak in str_list_dup().
+- Link with -lpthread when static SELinux libraries require that.
+- Detect command line PE values that exceed their 32-bit range.
+- Include strerror string in dev_open_flags' stat failure message.
+- Avoid error when --corelog is provided without --mirrorlog. (2.02.28)
+- Correct --mirrorlog argument name in man pages (not --log).
+- Clear MIRROR_NOTSYNCED LV flag when converting from mirror to linear.
+- Modify lvremove to prompt for removal if LV active on other cluster nodes.
+- Add '-f' to vgremove to force removal of VG even if LVs exist.
+
+* Fri Aug 24 2007 Alasdair Kergon <agk@redhat.com> - 2.02.28-1
+- vgscan and pvscan now trigger clvmd -R, which should now work.
+- Fix clvmd logging so you can get lvm-level debugging out of it.
+- Allow clvmd debug to be turned on in a running daemon using clvmd -d [-C].
+- Add more cluster info to lvmdump.
+- Fix lvdisplay man page to say LV size is reported in sectors, not KB.
+- Fix loading of persistent cache if cache_dir is used.
+- Only permit --force, --verbose and --debug arguments to be repeated.
+- Add support for renaming mirrored LVs.
+- Add --mirrorlog argument to specify log type for mirrors.
+- Don't leak a file descriptor if flock or fcntl fails.
+- Detect stream write failure reliably.
+- Reduce severity of lstat error messages to very_verbose.
+- Update to use autoconf 2.61, while still supporting 2.57.
+
+* Thu Aug 09 2007 Alasdair Kergon <agk@redhat.com> - 2.02.27-3
+- Clarify GPL licence as being version 2.
+
+* Wed Aug 01 2007 Milan Broz <mbroz@redhat.com> - 2.02.27-2
+- Add SUN's LDOM virtual block device (vdisk) and ps3disk to filters.
+
+* Wed Jul 18 2007 Alasdair Kergon <agk@redhat.com> - 2.02.27-1
+- Add -f to vgcfgrestore to list metadata backup files.
+- Add pvdisplay --maps implementation.
+- Add devices/preferred_names config regex list for displayed device names.
+- Add vg_mda_count and pv_mda_count columns to reports.
+- Change cling alloc policy attribute character from 'C' to l'.
+- Print warnings to stderr instead of stdout.
+- Fix snapshot cow area deactivation if origin is not active.
+- Reinitialise internal lvmdiskscan variables when called repeatedly.
+- Allow keyboard interrupt during user prompts when appropriate.
+- Fix deactivation code to follow dependencies and remove symlinks.
+- Fix a segfault in device_is_usable() if a device has no table.
+- Fix creation and conversion of mirrors with tags.
+- Add command stub for pvck.
+- Handle vgsplit of an entire VG as a vgrename.
+- Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata).
+- Split metadata areas in vgsplit properly.
+- Fix and clarify vgsplit error messages.
+- Update lists of attribute characters in man pages.
+- Remove unsupported LVM1 options from vgcfgrestore man page.
+- Update vgcfgrestore man page to show mandatory VG name.
+- Update vgrename man page to include UUID and be consistent with lvrename.
+- Add some more debug messages to clvmd startup.
+- Fix thread race in clvmd.
+- Make clvmd cope with quorum devices.
+- Add extra internal error checking to clvmd.
+- Fix missing lvm_shell symbol in lvm2cmd library.
+- Move regex functions into libdevmapper.
+- Add kernel and device-mapper targets versions to lvmdump.
+- Add /sys/block listings to lvmdump.
+- Make lvmdump list /dev recursively.
+- Mark /etc/lvm subdirectories as directories in spec file.
+
+* Mon Mar 19 2007 Alasdair Kergon <agk@redhat.com> - 2.02.24-1
+- Add BuildRequires readline-static until makefiles get fixed.
+- Fix processing of exit status in init scripts
+- Fix vgremove to require at least one vg argument.
+- Fix reading of striped LVs in LVM1 format.
+- Flag nolocking as clustered so clvmd startup sees clustered LVs.
+- Add a few missing pieces of vgname command line validation.
+- Support the /dev/mapper prefix on most command lines.
+
+* Thu Mar 08 2007 Alasdair Kergon <agk@redhat.com> - 2.02.23-1
+- Fix vgrename active LV check to ignore differing vgids.
+- Fix two more segfaults if an empty config file section encountered.
+- Fix a leak in a reporting error path.
+- Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
+
+* Tue Feb 27 2007 Alasdair Kergon <agk@redhat.com> - 2.02.22-3
+- Move .cache file to /etc/lvm/cache.
+
+* Wed Feb 14 2007 Alasdair Kergon <agk@redhat.com> - 2.02.22-2
+- Rebuild after device-mapper package split.
+
+* Wed Feb 14 2007 Alasdair Kergon <agk@redhat.com> - 2.02.22-1
+- Add ncurses-static BuildRequires after package split.
+- Fix loading of segment_libraries.
+- If a PV reappears after it was removed from its VG, make it an orphan.
+- Don't update metadata automatically if VGIDs don't match.
+- Fix some vgreduce --removemissing command line validation.
+- Trivial man page corrections (-b and -P).
+- Add global/units to example.conf.
+- Remove readline support from lvm.static.
+
+* Mon Feb 05 2007 Alasdair Kergon <agk@redhat.com> - 2.02.21-4
+- Remove file wildcards and unintentional lvmconf installation.
+
+* Mon Feb 05 2007 Alasdair Kergon <agk@redhat.com> - 2.02.21-3
+- Add build dependency on new device-mapper-devel package.
+
+* Wed Jan 31 2007 Alasdair Kergon <agk@redhat.com> - 2.02.21-2
+- Remove superfluous execute perm from .cache data file.
+
+* Tue Jan 30 2007 Alasdair Kergon <agk@redhat.com> - 2.02.21-1
+- Fix vgsplit to handle mirrors.
+- Reorder fields in reporting field definitions.
+- Fix vgs to treat args as VGs even when PV fields are displayed.
+- Fix md signature check to handle both endiannesses.
+
+* Fri Jan 26 2007 Alasdair Kergon <agk@redhat.com> - 2.02.20-1
+- Fix exit statuses of reporting tools.
+- Add some missing close() and fclose() return code checks.
+- Add devices/ignore_suspended_devices to ignore suspended dm devices.
+- Fix refresh_toolcontext() always to wipe persistent device filter cache.
+- Long-lived processes write out persistent dev cache in refresh_toolcontext().
+- Streamline dm_report_field_* interface.
+- Update reporting man pages.
+- Add --clustered to man pages.
+- Add field definitions to report help text.
+
+* Mon Jan 22 2007 Milan Broz <mbroz@redhat.com> - 2.02.19-2
+- Remove BuildRequires libtermcap-devel
+  Resolves: #223766
+
+* Wed Jan 17 2007 Alasdair Kergon <agk@redhat.com> - 2.02.19-1
+- Fix a segfault if an empty config file section encountered.
+- Fix partition table processing after sparc changes.
+- Fix cmdline PE range processing segfault.
+- Move basic reporting functions into libdevmapper.
+
+* Fri Jan 12 2007 Alasdair Kergon <agk@redhat.com> - 2.02.18-2
+- Rebuild.
+
+* Thu Jan 11 2007 Alasdair Kergon <agk@redhat.com> - 2.02.18-1
+- Use CFLAGS when linking so mixed sparc builds can supply -m64.
+- Prevent permission changes on active mirrors.
+- Print warning instead of error message if lvconvert cannot zero volume.
+- Add snapshot options to lvconvert man page.
+- dumpconfig accepts a list of configuration variables to display.
+- Change dumpconfig to use --file to redirect output to a file.
+- Avoid vgreduce error when mirror code removes the log LV.
+- Fix ambiguous vgsplit error message for split LV.
+- Fix lvextend man page typo.
+- Use no flush suspending for mirrors.
+- Fix create mirror with name longer than 22 chars.
+
+* Thu Dec 14 2006 Alasdair Kergon <agk@redhat.com> - 2.02.17-1
+- Add missing pvremove error message when device doesn't exist.
+- When lvconvert allocates a mirror log, respect parallel area constraints.
+- Check for failure to allocate just the mirror log.
+- Support mirror log allocation when there is only one PV: area_count now 0.
+- Fix detection of smallest area in _alloc_parallel_area() for cling policy.
+- Add manpage entry for clvmd -T
+- Fix hang in clvmd if a pre-command failed.
+
+* Fri Dec 01 2006 Alasdair Kergon <agk@redhat.com> - 2.02.16-1
+- Fix VG clustered read locks to use PR not CR.
+- Adjust some alignments for ia64/sparc.
+- Fix mirror segment removal to use temporary error segment.
+- Always compile debug logging into clvmd.
+- Add startup timeout to clvmd startup script.
+- Add -T (startup timeout) switch to clvmd.
+- Improve lvm_dump.sh robustness.
+
+* Tue Nov 21 2006 Alasdair Kergon <agk@redhat.com> - 2.02.15-3
+- Fix clvmd init script line truncation.
+
+* Tue Nov 21 2006 Alasdair Kergon <agk@redhat.com> - 2.02.15-2
+- Fix lvm.conf segfault.
+
+* Mon Nov 20 2006 Alasdair Kergon <agk@redhat.com> - 2.02.15-1
+- New upstream - see WHATS_NEW.
+
+* Sat Nov 11 2006 Alasdair Kergon <agk@redhat.com> - 2.02.14-1
+- New upstream - see WHATS_NEW.
+
+* Mon Oct 30 2006 Alasdair Kergon <agk@redhat.com> - 2.02.13-2
+- Fix high-level free-space check on partial allocation.
+  Resolves: #212774
+
+* Fri Oct 27 2006 Alasdair Kergon <agk@redhat.com> - 2.02.13-1
+- New upstream - see WHATS_NEW.
+  Resolves: #205818
+
+* Fri Oct 20 2006 Alasdair Kergon <agk@redhat.com> - 2.02.12-2
+- Remove no-longer-used ldconfig from lvm2-cluster and fix lvmconf
+  to cope without the shared library.
+
+* Mon Oct 16 2006 Alasdair Kergon <agk@redhat.com> - 2.02.12-1
+- New upstream.
+
+* Sat Oct 14 2006 Alasdair Kergon <agk@redhat.com> - 2.02.11-6
+- Incorporate lvm2-cluster as a subpackage.
+
+* Sat Oct 14 2006 Alasdair Kergon <agk@redhat.com> - 2.02.11-5
+- Install lvmdump script.
+
+* Sat Oct 14 2006 Alasdair Kergon <agk@redhat.com> - 2.02.11-4
+- Build in cluster locking with fallback if external locking fails to load.
+
+* Sat Oct 14 2006 Alasdair Kergon <agk@redhat.com> - 2.02.11-3
+- Drop .0 suffix from release.
+
+* Sat Oct 14 2006 Alasdair Kergon <agk@redhat.com> - 2.02.11-2.0
+- Append distribution to release.
+
+* Fri Oct 13 2006 Alasdair Kergon <agk@redhat.com> - 2.02.11-1.0
+- New upstream with numerous fixes and small enhancements.
+  (See the WHATS_NEW documentation file for complete upstream changelog.)
+
+* Thu Sep 28 2006 Peter Jones <pjones@redhat.com> - 2.02.06-4
+- Fix metadata and map alignment problems on ppc64 (#206202)
+
+* Tue Aug  1 2006 Jeremy Katz <katzj@redhat.com> - 2.02.06-3
+- require new libselinux to avoid segfaults on xen (#200783)
+
+* Thu Jul 27 2006 Jeremy Katz <katzj@redhat.com> - 2.02.06-2
+- free trip through the buildsystem
+
+* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 2.02.06-1.2.1
+- rebuild
+
+* Tue Jun  6 2006 Stephen C. Tweedie <sct@redhat.com> - 2.02.06-1.2
+- Rebuild to pick up new nosegneg libc.a for lvm.static
+
+* Mon May 22 2006 Alasdair Kergon <agk@redhat.com> - 2.02.06-1.1
+- Reinstate archs now build system is back.
+- BuildRequires libsepol-devel.
+
+* Fri May 12 2006 Alasdair Kergon <agk@redhat.com> - 2.02.06-1.0
+- New upstream release.
+
+* Sat Apr 22 2006 Alasdair Kergon <agk@redhat.com> - 2.02.05-1.1
+- Exclude archs that aren't building.
+
+* Fri Apr 21 2006 Alasdair Kergon <agk@redhat.com> - 2.02.05-1.0
+- Fix VG uuid comparisons.
+
+* Wed Apr 19 2006 Alasdair Kergon <agk@redhat.com> - 2.02.04-1.0
+- New release upstream, including better handling of duplicated VG names.
+
+* Fri Feb 10 2006 Jesse Keating <jkeating@redhat.com> - 2.02.01-1.2.1
+- bump again for double-long bug on ppc(64)
+
+* Tue Feb 07 2006 Jesse Keating <jkeating@redhat.com> - 2.02.01-1.2
+- rebuilt for new gcc4.1 snapshot and glibc changes
+
+* Fri Dec 09 2005 Jesse Keating <jkeating@redhat.com>
+- rebuilt
+
+* Fri Dec  2 2005 Peter Jones <pjones@redhat.com> - 2.02.01-1
+- update to 2.02.01
+
+* Tue Nov  8 2005 Jeremy Katz <katzj@redhat.com> - 2.01.14-4
+- add patch for xen block devices
+
+* Sat Oct 15 2005 Florian La Roche <laroche@redhat.com>
+- add -lselinux -lsepol to the static linking -ldevice-mapper requires it
+
+* Wed Sep 14 2005 Jeremy Katz <katzj@redhat.com> - 2.01.14-2
+- the distro doesn't really work without a 2.6 kernel, so no need to require it
+
+* Thu Aug 4 2005 Alasdair Kergon <agk@redhat.com> - 2.01.14-1.0
+- And a few more bugs fixes.
+
+* Wed Jul 13 2005 Alasdair Kergon <agk@redhat.com> - 2.01.13-1.0
+- Fix several bugs discovered in the last release.
+
+* Tue Jun 14 2005 Alasdair Kergon <agk@redhat.com> - 2.01.12-1.0
+- New version upstream with a lot of fixes and enhancements.
+
+* Wed Apr 27 2005 Alasdair Kergon <agk@redhat.com> - 2.01.08-2.1
+- Add /etc/lvm
+
+* Wed Apr 27 2005 Alasdair Kergon <agk@redhat.com> - 2.01.08-2.0
+- No longer abort read operations if archive/backup directories aren't there.
+- Add runtime directories and file to the package.
+
+* Tue Mar 22 2005 Alasdair Kergon <agk@redhat.com> - 2.01.08-1.0
+- Improve detection of external changes affecting internal cache.
+- Add clustered VG attribute.
+- Suppress rmdir opendir error message.
+
+* Tue Mar 08 2005 Alasdair Kergon <agk@redhat.com> - 2.01.07-1.3
+* Tue Mar 08 2005 Alasdair Kergon <agk@redhat.com> - 2.01.07-1.2
+* Tue Mar 08 2005 Alasdair Kergon <agk@redhat.com> - 2.01.07-1.1
+- Suppress some new compiler messages.
+
+* Tue Mar 08 2005 Alasdair Kergon <agk@redhat.com> - 2.01.07-1.0
+- Remove build directory from built-in path.
+- Extra /dev scanning required for clustered operation.
+
+* Thu Mar 03 2005 Alasdair Kergon <agk@redhat.com> - 2.01.06-1.0
+- Allow anaconda to suppress warning messages.
+
+* Fri Feb 18 2005 Alasdair Kergon <agk@redhat.com> - 2.01.05-1.0
+- Upstream changes not affecting Fedora.
+
+* Wed Feb 09 2005 Alasdair Kergon <agk@redhat.com> - 2.01.04-1.0
+- Offset pool minors; lvm2cmd.so skips open fd check; pvmove -f gone.
+
+* Tue Feb 01 2005 Alasdair Kergon <agk@redhat.com> - 2.01.03-1.0
+- Fix snapshot device size & 64-bit display output.
+
+* Fri Jan 21 2005 Alasdair Kergon <agk@redhat.com> - 2.01.02-1.0
+- Minor fixes.
+
+* Mon Jan 17 2005 Alasdair Kergon <agk@redhat.com> - 2.01.01-1.0
+- Update vgcreate man page.  Preparation for snapshot origin extension fix.
+
+* Mon Jan 17 2005 Alasdair Kergon <agk@redhat.com> - 2.01.00-1.0
+- Fix metadata auto-correction. Only request open_count when needed.
+
+* Wed Jan 12 2005 Tim Waugh <twaugh@redhat.com> - 2.00.33-2.0
+- Rebuilt for new readline.
+
+* Fri Jan 7 2005 Alasdair Kergon <agk@redhat.com> - 2.00.33-1.0
+- pvcreate wipes ext label
+- several clvm fixes
+
+* Thu Jan 6 2005 Alasdair Kergon <agk@redhat.com> - 2.00.32-2.0
+- Remove temporary /sbin symlinks no longer needed.
+- Include read-only pool support in the build.
+
+* Wed Dec 22 2004 Alasdair Kergon <agk@redhat.com> - 2.00.32-1.0
+- More fixes (143501).
+
+* Sun Dec 12 2004 Alasdair Kergon <agk@redhat.com> - 2.00.31-1.0
+- Fix pvcreate install issues.
+
+* Fri Dec 10 2004 Alasdair Kergon <agk@redhat.com> - 2.00.30-1.0
+- Additional debugging code.
+- Some trivial man page corrections.
+
+* Tue Nov 30 2004 Alasdair Kergon <agk@redhat.com> - 2.00.29-1.3
+- Reinstate all archs.
+
+* Sun Nov 28 2004 Alasdair Kergon <agk@redhat.com> - 2.00.29-1.2
+- Try excluding more archs.
+
+* Sat Nov 27 2004 Alasdair Kergon <agk@redhat.com> - 2.00.29-1.1
+- Exclude s390x which fails.
+
+* Sat Nov 27 2004 Alasdair Kergon <agk@redhat.com> - 2.00.29-1
+- Fix last fix.
+
+* Sat Nov 27 2004 Alasdair Kergon <agk@redhat.com> - 2.00.28-1
+- Endian fix to partition/md signature detection.
+
+* Wed Nov 24 2004 Alasdair Kergon <agk@redhat.com> - 2.00.27-1
+- Fix partition table detection & an out of memory segfault.
+
+* Tue Nov 23 2004 Alasdair Kergon <agk@redhat.com> - 2.00.26-1
+- Several installation-related fixes & man page updates.
+
+* Mon Oct 25 2004 Elliot Lee <sopwith@redhat.com> - 2.00.25-1.01
+- Fix 2.6 kernel requirement
+
+* Wed Sep 29 2004 Alasdair Kergon <agk@redhat.com> - 2.00.25-1
+- Fix vgmknodes return code & vgremove locking.
+
+* Fri Sep 17 2004 Alasdair Kergon <agk@redhat.com> - 2.00.24-2
+- Obsolete old lvm1 packages; refuse install if running kernel 2.4. [bz 128185]
+
+* Thu Sep 16 2004 Alasdair Kergon <agk@redhat.com> - 2.00.24-1
+- More upstream fixes.  (Always check WHATS_NEW file for details.)
+- Add requested BuildRequires. [bz 124916, 132408]
+
+* Wed Sep 15 2004 Alasdair Kergon <agk@redhat.com> - 2.00.23-1
+- Various minor upstream fixes.
+
+* Fri Sep  3 2004 Alasdair Kergon <agk@redhat.com> - 2.00.22-1
+- Permission fix included upstream; use different endian conversion macros.
+
+* Thu Sep  2 2004 Jeremy Katz <katzj@redhat.com> - 2.00.21-2
+- fix permissions on vg dirs
+
+* Thu Aug 19 2004 Alasdair Kergon <agk@redhat.com> - 2.00.21-1
+- New upstream release incorporating fixes plus minor enhancements.
+
+* Tue Aug 17 2004 Jeremy Katz <katzj@redhat.com> - 2.00.20-2
+- add patch for iSeries viodasd support
+- add patch to check file type using stat(2) if d_type == DT_UNKNOWN (#129674)
+
+* Sat Jul 3 2004 Alasdair Kergon <agk@redhat.com> - 2.00.20-1
+- New upstream release fixes 2.6 kernel device numbers.
+
+* Tue Jun 29 2004 Alasdair Kergon <agk@redhat.com> - 2.00.19-1
+- Latest upstream release.  Lots of changes (see WHATS_NEW).
+
+* Tue Jun 15 2004 Elliot Lee <sopwith@redhat.com> - 2.00.15-5
+- rebuilt
+
+* Wed May 26 2004 Alasdair Kergon <agk@redhat.com> - 2.00.15-4
+- clone %%description from LVM rpm
+
+* Wed May 26 2004 Alasdair Kergon <agk@redhat.com> - 2.00.15-3
+- vgscan shouldn't return error status when no VGs present
+
+* Thu May 06 2004 Warren Togami <wtogami@redhat.com> - 2.00.15-2
+- i2o patch from Markus Lidel
+
+* Tue Apr 20 2004 Bill Nottingham <notting@redhat.com> - 2.00.15-1.1
+- handle disabled SELinux correctly, so that LVMs can be detected in a
+  non-SELinux context
+  
+* Mon Apr 19 2004 Alasdair Kergon <agk@redhat.com> - 2.00.15-1
+- Fix non-root build with current version of 'install'.
+
+* Fri Apr 16 2004 Alasdair Kergon <agk@redhat.com> - 2.00.14-1
+- Use 64-bit file offsets.
+
+* Fri Apr 16 2004 Alasdair Kergon <agk@redhat.com> - 2.00.13-1
+- Avoid scanning devices containing md superblocks.
+- Integrate ENOTSUP patch.
+
+* Thu Apr 15 2004 Jeremy Katz <katzj@redhat.com> - 2.00.12-4
+- don't die if we get ENOTSUP setting selinux contexts
+
+* Thu Apr 15 2004 Alasdair Kergon <agk@redhat.com> 2.00.12-3
+- Add temporary pvscan symlink for LVM1 until mkinitrd gets updated.
+
+* Wed Apr 14 2004 Alasdair Kergon <agk@redhat.com> 2.00.12-2
+- Mark config file noreplace.
+
+* Wed Apr 14 2004 Alasdair Kergon <agk@redhat.com> 2.00.12-1
+- Install default /etc/lvm/lvm.conf.
+- Move non-static binaries to /usr/sbin.
+- Add temporary links in /sbin to lvm.static until rc.sysinit gets updated.
+
+* Thu Apr 08 2004 Alasdair Kergon <agk@redhat.com> 2.00.11-1
+- Fallback to using LVM1 tools when using a 2.4 kernel without device-mapper.
+
+* Wed Apr 07 2004 Alasdair Kergon <agk@redhat.com> 2.00.10-2
+- Install the full toolset, not just 'lvm'.
+
+* Wed Apr 07 2004 Alasdair Kergon <agk@redhat.com> 2.00.10-1
+- Update to version 2.00.10, which incorporates the RH-specific patches
+  and includes various fixes and enhancements detailed in WHATS_NEW.
+
+* Wed Mar 17 2004 Jeremy Katz <katzj@redhat.com> 2.00.08-5
+- Fix sysfs patch to find sysfs
+- Take patch from dwalsh and tweak a little for setting SELinux contexts on
+  device node creation and also do it on the symlink creation.  
+  Part of this should probably be pushed down to device-mapper instead
+
+* Thu Feb 19 2004 Stephen C. Tweedie <sct@redhat.com> 2.00.08-4
+- Add sysfs filter patch
+- Allow non-root users to build RPM
+
+* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Fri Dec  5 2003 Jeremy Katz <katzj@redhat.com> 2.00.08-2
+- add static lvm binary
+
+* Tue Dec  2 2003 Jeremy Katz <katzj@redhat.com> 
+- Initial build.
+
+