diff --git a/.gitignore b/.gitignore
index d9acf11..bf3cd56 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-SOURCES/LVM2.2.02.177.tgz
-SOURCES/boom-0.8.5.tar.gz
+SOURCES/LVM2.2.02.180.tgz
+SOURCES/boom-0.9.tar.gz
diff --git a/.lvm2.metadata b/.lvm2.metadata
index b1e86fd..498c1a7 100644
--- a/.lvm2.metadata
+++ b/.lvm2.metadata
@@ -1,2 +1,2 @@
-b114b2ef40fca63c6df290a5f1aac54ff3e764aa SOURCES/LVM2.2.02.177.tgz
-56a275b49755264565ed595098ea2bb8b0cfe75e SOURCES/boom-0.8.5.tar.gz
+d85f7a9bdfd2de48f0bd7ce4d7698685eff6b68e SOURCES/LVM2.2.02.180.tgz
+dd96613e238f342641b5be8977ee8598662e8ab9 SOURCES/boom-0.9.tar.gz
diff --git a/SOURCES/lvm2-2_02_178-activation-guard-exclusive-activation.patch b/SOURCES/lvm2-2_02_178-activation-guard-exclusive-activation.patch
deleted file mode 100644
index 4221e16..0000000
--- a/SOURCES/lvm2-2_02_178-activation-guard-exclusive-activation.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From da05bd7f7207eeab5fbd70b7a7c5166a9885e3b4 Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Mon, 15 Jan 2018 16:26:00 +0100
-Subject: [PATCH 18/25] activation: guard exclusive activation
-
-Add protectional internall error whenever we spot activation
-of 'exclusive' only segments in 'non-exclusive' mode.
-
-TODO: possibly the activation locking could be enhanced to handle
-this fully behind the scene - as for now this works purely for
-lvchange/vgchange activation.
-
-(cherry picked from commit a8bcdef4fd172b705572e3c0b277e6941be642f4)
----
- WHATS_NEW               |  1 +
- lib/activate/activate.c | 10 ++++++++++
- 2 files changed, 11 insertions(+)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 4368543..c3117de 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,6 @@
- Version 2.02.178 - 
- =====================================
-+  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.
-   Avoid exceeding array bounds in allocation tag processing.
-diff --git a/lib/activate/activate.c b/lib/activate/activate.c
-index 4c69af7..b23400a 100644
---- a/lib/activate/activate.c
-+++ b/lib/activate/activate.c
-@@ -2568,6 +2568,16 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
- 	struct lvinfo info;
- 	int r = 0;
- 
-+	if (!laopts->exclusive &&
-+	    (lv_is_origin(lv) ||
-+	     lv_is_pvmove(lv) ||
-+	     seg_only_exclusive(first_seg(lv))))  {
-+		log_error(INTERNAL_ERROR "Trying non-exlusive activation of %s with "
-+			  "a volume type %s requiring exclusive activation.",
-+			  display_lvname(lv), lvseg_name(first_seg(lv)));
-+		return 0;
-+	}
-+
- 	if (!activation())
- 		return 1;
- 
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-activation-move-check-later.patch b/SOURCES/lvm2-2_02_178-activation-move-check-later.patch
deleted file mode 100644
index 0b17a2e..0000000
--- a/SOURCES/lvm2-2_02_178-activation-move-check-later.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From e3e7ea0c384da84ccd38406482ec1877c6b19d8a Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Wed, 17 Jan 2018 15:15:43 +0100
-Subject: [PATCH 25/25] activation: move check later
-
-Check for lv when it's known in all cases.
-
-(cherry picked from commit f3c75bb2014e9ae7d212e0c016a94c529ac8a912)
----
- lib/activate/activate.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
-diff --git a/lib/activate/activate.c b/lib/activate/activate.c
-index b23400a..18cc7cf 100644
---- a/lib/activate/activate.c
-+++ b/lib/activate/activate.c
-@@ -2568,6 +2568,12 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
- 	struct lvinfo info;
- 	int r = 0;
- 
-+	if (!activation())
-+		return 1;
-+
-+	if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0)))
-+		goto out;
-+
- 	if (!laopts->exclusive &&
- 	    (lv_is_origin(lv) ||
- 	     lv_is_pvmove(lv) ||
-@@ -2578,12 +2584,6 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
- 		return 0;
- 	}
- 
--	if (!activation())
--		return 1;
--
--	if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0)))
--		goto out;
--
- 	if (filter && !_passes_activation_filter(cmd, lv)) {
- 		log_verbose("Not activating %s since it does not pass "
- 			    "activation filter.", display_lvname(lv));
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-allocation-Avoid-exceeding-array-bounds-in-allocatio.patch b/SOURCES/lvm2-2_02_178-allocation-Avoid-exceeding-array-bounds-in-allocatio.patch
deleted file mode 100644
index c514685..0000000
--- a/SOURCES/lvm2-2_02_178-allocation-Avoid-exceeding-array-bounds-in-allocatio.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From ce8663ee13e68b8f21dce6e2cf612d3809519787 Mon Sep 17 00:00:00 2001
-From: Alasdair G Kergon <agk@redhat.com>
-Date: Wed, 10 Jan 2018 02:03:32 +0000
-Subject: [PATCH 12/25] allocation: Avoid exceeding array bounds in allocation
- tag code
-
-If _limit_to_one_area_per_tag() changes nothing it writes beyond
-the array.
-
-(cherry picked from commit bacc94233368cf136b55e2574e969e7f53b31c6c)
-
-Conflicts:
-	WHATS_NEW
----
- WHATS_NEW               | 4 ++++
- lib/metadata/lv_manip.c | 3 ++-
- 2 files changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 2163a5e..9375a86 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,3 +1,7 @@
-+Version 2.02.178 - 
-+=====================================
-+  Avoid exceeding array bounds in allocation tag processing.
-+
- Version 2.02.177 - 18th December 2017
- =====================================
-   When writing text metadata content, use complete 4096 byte blocks.
-diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
-index 70dc2d9..ac30dad 100644
---- a/lib/metadata/lv_manip.c
-+++ b/lib/metadata/lv_manip.c
-@@ -2737,7 +2737,8 @@ static int _limit_to_one_area_per_tag(struct alloc_handle *ah, struct alloc_stat
- 		s++;
- 	}
- 
--	alloc_state->areas[u].pva = NULL;
-+	if (u < alloc_state->areas_size)
-+		alloc_state->areas[u].pva = NULL;
- 
- 	return 1;
- }
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-cleanup-drop-unused-code.patch b/SOURCES/lvm2-2_02_178-cleanup-drop-unused-code.patch
deleted file mode 100644
index f738e92..0000000
--- a/SOURCES/lvm2-2_02_178-cleanup-drop-unused-code.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From be970a7e85cd3659119ca349303f3dd2ef40592b Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Thu, 11 Jan 2018 16:11:21 +0100
-Subject: [PATCH 20/25] cleanup: drop unused code
-
-(cherry picked from commit 3aedaa7f2aa3c8622538e2758bf905ceb156db4a)
----
- tools/pvmove.c | 9 ---------
- 1 file changed, 9 deletions(-)
-
-diff --git a/tools/pvmove.c b/tools/pvmove.c
-index af3fec4..b3d1d89 100644
---- a/tools/pvmove.c
-+++ b/tools/pvmove.c
-@@ -329,8 +329,6 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 	uint32_t log_count = 0;
- 	int lv_found = 0;
- 	int lv_skipped = 0;
--	int lv_active_count = 0;
--	int lv_exclusive_count = 0;
- 
- 	/* FIXME Cope with non-contiguous => splitting existing segments */
- 	if (!(lv_mirr = lv_create_empty("pvmove%d", NULL,
-@@ -451,13 +449,6 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 			continue;
- 		}
- 
--		if (vg_is_clustered(vg)) {
--			if (lv_is_active_exclusive_locally(lv))
--				lv_exclusive_count++;
--			else if (lv_is_active(lv))
--				lv_active_count++;
--		}
--
- 		if (!_insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
- 					    *lvs_changed))
- 			return_NULL;
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-cleanup-enhance-messages.patch b/SOURCES/lvm2-2_02_178-cleanup-enhance-messages.patch
deleted file mode 100644
index fe914e6..0000000
--- a/SOURCES/lvm2-2_02_178-cleanup-enhance-messages.patch
+++ /dev/null
@@ -1,90 +0,0 @@
-From f2365e3e82309056c2921016584a56210da6888b Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Thu, 11 Jan 2018 10:46:04 +0100
-Subject: [PATCH 19/25] cleanup: enhance messages
-
-Add extra info about failing local exlusive activation
-(as in cluster the LV can be active on some other nodes).
-
-(cherry picked from commit 38b81e6537a8dc497a4bc616a1f51632b43137ca)
----
- lib/locking/locking.c |  3 ++-
- tools/pvmove.c        | 27 ++++++++++++++-------------
- 2 files changed, 16 insertions(+), 14 deletions(-)
-
-diff --git a/lib/locking/locking.c b/lib/locking/locking.c
-index c68d4c7..8daa61e 100644
---- a/lib/locking/locking.c
-+++ b/lib/locking/locking.c
-@@ -406,7 +406,8 @@ int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs)
- 
- 	dm_list_iterate_items(lvl, lvs) {
- 		if (!activate_lv_excl_local(cmd, lvl->lv)) {
--			log_error("Failed to activate %s", display_lvname(lvl->lv));
-+			log_error("Failed to locally exclusively activate %s.",
-+				  display_lvname(lvl->lv));
- 			dm_list_uniterate(lvh, lvs, &lvl->list) {
- 				lvl = dm_list_item(lvh, struct lv_list);
- 				if (!deactivate_lv(cmd, lvl->lv))
-diff --git a/tools/pvmove.c b/tools/pvmove.c
-index c5d7e52..af3fec4 100644
---- a/tools/pvmove.c
-+++ b/tools/pvmove.c
-@@ -375,9 +375,9 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 			continue;
- 
- 		if (lv_is_converting(lv) || lv_is_merging(lv)) {
--			log_error("Unable to pvmove when %s volumes are present.",
--				  lv_is_converting(lv) ?
--				  "converting" : "merging");
-+			log_error("Unable to pvmove when %s volume %s is present.",
-+				  lv_is_converting(lv) ? "converting" : "merging",
-+				  display_lvname(lv));
- 			return NULL;
- 		}
- 
-@@ -389,13 +389,13 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 				return_NULL;
- 
- 			/*
-- 			 * Remove any PVs holding SubLV siblings to allow
-- 			 * for collocation (e.g. *rmeta_0 -> *rimage_0).
-- 			 *
-- 			 * Callee checks for lv_name and valid raid segment type.
-- 			 *
-- 			 * FIXME: don't rely on namespace
-- 			 */
-+			 * Remove any PVs holding SubLV siblings to allow
-+			 * for collocation (e.g. *rmeta_0 -> *rimage_0).
-+			 *
-+			 * Callee checks for lv_name and valid raid segment type.
-+			 *
-+			 * FIXME: don't rely on namespace
-+			 */
- 			if (!_remove_sibling_pvs_from_trim_list(lv, lv_name, &trim_list))
- 				return_NULL;
- 
-@@ -436,7 +436,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 
- 		if (lv_is_locked(lv)) {
- 			lv_skipped = 1;
--			log_print_unless_silent("Skipping locked LV %s.", lv->name);
-+			log_print_unless_silent("Skipping locked LV %s.", display_lvname(lv));
- 			continue;
- 		}
- 
-@@ -445,8 +445,9 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 		    lv_is_active(lv) &&
- 		    !lv_is_active_exclusive_locally(lv)) {
- 			lv_skipped = 1;
--			log_print_unless_silent("Skipping LV %s which is activated "
--						"exclusively on remote node.", lv->name);
-+			log_print_unless_silent("Skipping LV %s which is active, "
-+						"but not locally exclusively.",
-+						display_lvname(lv));
- 			continue;
- 		}
- 
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-dmeventd-add-check-for-result-code.patch b/SOURCES/lvm2-2_02_178-dmeventd-add-check-for-result-code.patch
deleted file mode 100644
index 41060a6..0000000
--- a/SOURCES/lvm2-2_02_178-dmeventd-add-check-for-result-code.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 94a631461d2d17e1847d2e215bce297bb1a2b70d Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Fri, 5 Jan 2018 21:08:24 +0100
-Subject: [PATCH 17/25] dmeventd: add check for result code
-
-Check result from pthread_kill.
-
-(cherry picked from commit f41935909fec9eb8d64bc04530be2f38866f0b8e)
----
- daemons/dmeventd/dmeventd.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
-index 7ad7f81..8917422 100644
---- a/daemons/dmeventd/dmeventd.c
-+++ b/daemons/dmeventd/dmeventd.c
-@@ -754,6 +754,7 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
- 	struct thread_status *thread;
- 	struct timespec timeout;
- 	time_t curr_time;
-+	int ret;
- 
- 	DEBUGLOG("Timeout thread starting.");
- 	pthread_cleanup_push(_exit_timeout, NULL);
-@@ -775,7 +776,10 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
- 				} else {
- 					DEBUGLOG("Sending SIGALRM to Thr %x for timeout.",
- 						 (int) thread->thread);
--					pthread_kill(thread->thread, SIGALRM);
-+					ret = pthread_kill(thread->thread, SIGALRM);
-+					if (ret && (ret != ESRCH))
-+						log_error("Unable to wakeup Thr %x for timeout: %s.",
-+							  (int) thread->thread, strerror(ret));
- 				}
- 				_unlock_mutex();
- 			}
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-libdm-accept-mirror-status-with-userspace-word-in-th.patch b/SOURCES/lvm2-2_02_178-libdm-accept-mirror-status-with-userspace-word-in-th.patch
deleted file mode 100644
index 6801604..0000000
--- a/SOURCES/lvm2-2_02_178-libdm-accept-mirror-status-with-userspace-word-in-th.patch
+++ /dev/null
@@ -1,32 +0,0 @@
- WHATS_NEW_DM          | 4 ++++
- libdm/libdm-targets.c | 5 +++++
- 2 files changed, 9 insertions(+)
-
-diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
-index 8b304e6..fb92416 100644
---- a/WHATS_NEW_DM
-+++ b/WHATS_NEW_DM
-@@ -1,3 +1,7 @@
-+Version 1.02.147 - 
-+=====================================
-+  Parsing mirror status accepts 'userspace' keyword in status.
-+
- Version 1.02.146 - 18th December 2017
- =====================================
-   Activation tree of thin pool skips duplicated check of pool status.
-diff --git a/libdm/libdm-targets.c b/libdm/libdm-targets.c
-index 990d275..8766789 100644
---- a/libdm/libdm-targets.c
-+++ b/libdm/libdm-targets.c
-@@ -508,6 +508,11 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
- 	if (!(pos = _skip_fields(pos, argc)))
- 		goto_out;
- 
-+	if (strncmp(pos, "userspace", 9) == 0) {
-+		pos += 9;
-+		/* FIXME: support status of userspace mirror implementation */
-+	}
-+
- 	if (sscanf(pos, "%u %n", &argc, &used) != 1)
- 		goto_out;
- 	pos += used;
diff --git a/SOURCES/lvm2-2_02_178-locking-exclusive-can-be-either-remote-or-local.patch b/SOURCES/lvm2-2_02_178-locking-exclusive-can-be-either-remote-or-local.patch
deleted file mode 100644
index f0e1cc5..0000000
--- a/SOURCES/lvm2-2_02_178-locking-exclusive-can-be-either-remote-or-local.patch
+++ /dev/null
@@ -1,32 +0,0 @@
- WHATS_NEW               | 1 +
- lib/activate/activate.c | 5 ++++-
- 2 files changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 762553f..776c739 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,6 @@
- Version 2.02.178 - 
- =====================================
-+  Do not report LV as remotely active when it's locally exclusive in cluster.
-   Add deprecate messages for usage of mirrors with mirrorlog.
-   Restore pvmove support for wide-clustered active volumes (2.02.177).
-   Avoid non-exclusive activation of exclusive segment types.
-diff --git a/lib/activate/activate.c b/lib/activate/activate.c
-index 7a37130..b67e7b1 100644
---- a/lib/activate/activate.c
-+++ b/lib/activate/activate.c
-@@ -1543,8 +1543,11 @@ static int _lv_is_active(const struct logical_volume *lv,
- 	if (skip_cluster_query)
- 		goto out;
- 
--	if ((r = cluster_lock_held(lv->lvid.s, "", &e)) >= 0)
-+	if ((r = cluster_lock_held(lv->lvid.s, "", &e)) >= 0) {
-+		if (l && e)
-+			r = 0; /* exclusive locally */
- 		goto out;
-+	}
- 
- 	/*
- 	 * If lock query is not supported (due to interfacing with old
diff --git a/SOURCES/lvm2-2_02_178-lvconvert-use-excl-activation-for-conversion.patch b/SOURCES/lvm2-2_02_178-lvconvert-use-excl-activation-for-conversion.patch
deleted file mode 100644
index 0ec0b2f..0000000
--- a/SOURCES/lvm2-2_02_178-lvconvert-use-excl-activation-for-conversion.patch
+++ /dev/null
@@ -1,156 +0,0 @@
-From 8c34a9b06eab6c40a221730a1b72dcd5e43aabcc Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Fri, 12 Jan 2018 13:34:13 +0100
-Subject: [PATCH 13/25] lvconvert: use excl activation for conversion
-
-Use properly exclusive activation when reactivating origin after
-snapshot merge (since origin must have been previously also exlusively
-activated).
-
-Same applies when converting volumes to thin-pool or cache.
-
-Previously used 'only' local activation incorrectly allowed local
-activation of some targets (i.e. raid) - thus 'leaking' chance to
-activate same device on another node - which can be a problem
-for device types like raid.
-
-(cherry picked from commit e86910b052ef50dfdaad104d17bda679f698e31f)
-
-Conflicts:
-	WHATS_NEW
----
- WHATS_NEW                  |  1 +
- lib/metadata/cache_manip.c |  2 +-
- lib/metadata/pool_manip.c  |  6 +++---
- tools/lvconvert.c          | 16 ++++++++--------
- 4 files changed, 13 insertions(+), 12 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 9375a86..c997206 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,6 @@
- Version 2.02.178 - 
- =====================================
-+  Preserve exclusive activation during thin snaphost merge.
-   Avoid exceeding array bounds in allocation tag processing.
- 
- Version 2.02.177 - 18th December 2017
-diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
-index 55ed724..97a3339 100644
---- a/lib/metadata/cache_manip.c
-+++ b/lib/metadata/cache_manip.c
-@@ -960,7 +960,7 @@ int wipe_cache_pool(struct logical_volume *cache_pool_lv)
- 	}
- 
- 	cache_pool_lv->status |= LV_TEMPORARY;
--	if (!activate_lv_local(cache_pool_lv->vg->cmd, cache_pool_lv)) {
-+	if (!activate_lv_excl_local(cache_pool_lv->vg->cmd, cache_pool_lv)) {
- 		log_error("Aborting. Failed to activate cache pool %s.",
- 			  display_lvname(cache_pool_lv));
- 		return 0;
-diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
-index 18e4e65..b832db7 100644
---- a/lib/metadata/pool_manip.c
-+++ b/lib/metadata/pool_manip.c
-@@ -526,7 +526,7 @@ int create_pool(struct logical_volume *pool_lv,
- 		 * or directly converted to invisible device via suspend/resume
- 		 */
- 		pool_lv->status |= LV_TEMPORARY;
--		if (!activate_lv_local(pool_lv->vg->cmd, pool_lv)) {
-+		if (!activate_lv_excl_local(pool_lv->vg->cmd, pool_lv)) {
- 			log_error("Aborting. Failed to activate pool metadata %s.",
- 				  display_lvname(pool_lv));
- 			goto bad;
-@@ -538,7 +538,7 @@ int create_pool(struct logical_volume *pool_lv,
- 		}
- 		pool_lv->status &= ~LV_TEMPORARY;
- 		/* Deactivates cleared metadata LV */
--		if (!deactivate_lv_local(pool_lv->vg->cmd, pool_lv)) {
-+		if (!deactivate_lv(pool_lv->vg->cmd, pool_lv)) {
- 			log_error("Aborting. Could not deactivate pool metadata %s.",
- 				  display_lvname(pool_lv));
- 			return 0;
-@@ -660,7 +660,7 @@ static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg
- 		return_0;
- 
- 	/* Spare LV should not be active */
--	if (!deactivate_lv_local(vg->cmd, lv)) {
-+	if (!deactivate_lv(vg->cmd, lv)) {
- 		log_error("Unable to deactivate pool metadata spare LV. "
- 			  "Manual intervention required.");
- 		return 0;
-diff --git a/tools/lvconvert.c b/tools/lvconvert.c
-index deb7cc9..fee0a4e 100644
---- a/tools/lvconvert.c
-+++ b/tools/lvconvert.c
-@@ -1970,14 +1970,14 @@ static int _lvconvert_snapshot(struct cmd_context *cmd,
- 		log_warn("WARNING: %s not zeroed.", snap_name);
- 	else {
- 		lv->status |= LV_TEMPORARY;
--		if (!activate_lv_local(cmd, lv) ||
-+		if (!activate_lv_excl_local(cmd, lv) ||
- 		    !wipe_lv(lv, (struct wipe_params) { .do_zero = 1 })) {
- 			log_error("Aborting. Failed to wipe snapshot exception store.");
- 			return 0;
- 		}
- 		lv->status &= ~LV_TEMPORARY;
- 		/* Deactivates cleared metadata LV */
--		if (!deactivate_lv_local(lv->vg->cmd, lv)) {
-+		if (!deactivate_lv(lv->vg->cmd, lv)) {
- 			log_error("Failed to deactivate zeroed snapshot exception store.");
- 			return 0;
- 		}
-@@ -2170,7 +2170,7 @@ static int _lvconvert_merge_thin_snapshot(struct cmd_context *cmd,
- 		log_print_unless_silent("Volume %s replaced origin %s.",
- 					display_lvname(origin), display_lvname(lv));
- 
--		if (origin_is_active && !activate_lv(cmd, lv)) {
-+		if (origin_is_active && !activate_lv_excl_local(cmd, lv)) {
- 			log_error("Failed to reactivate origin %s.",
- 				  display_lvname(lv));
- 			return 0;
-@@ -2278,13 +2278,13 @@ static int _lvconvert_thin_pool_repair(struct cmd_context *cmd,
- 		return 0;
- 	}
- 
--	if (!activate_lv_local(cmd, pmslv)) {
-+	if (!activate_lv_excl_local(cmd, pmslv)) {
- 		log_error("Cannot activate pool metadata spare volume %s.",
- 			  pmslv->name);
- 		return 0;
- 	}
- 
--	if (!activate_lv_local(cmd, mlv)) {
-+	if (!activate_lv_excl_local(cmd, mlv)) {
- 		log_error("Cannot activate thin pool metadata volume %s.",
- 			  mlv->name);
- 		goto deactivate_pmslv;
-@@ -2476,13 +2476,13 @@ static int _lvconvert_cache_repair(struct cmd_context *cmd,
- 		return 0;
- 	}
- 
--	if (!activate_lv_local(cmd, pmslv)) {
-+	if (!activate_lv_excl_local(cmd, pmslv)) {
- 		log_error("Cannot activate pool metadata spare volume %s.",
- 			  pmslv->name);
- 		return 0;
- 	}
- 
--	if (!activate_lv_local(cmd, mlv)) {
-+	if (!activate_lv_excl_local(cmd, mlv)) {
- 		log_error("Cannot activate cache pool metadata volume %s.",
- 			  mlv->name);
- 		goto deactivate_pmslv;
-@@ -3130,7 +3130,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
- 
- 		if (zero_metadata) {
- 			metadata_lv->status |= LV_TEMPORARY;
--			if (!activate_lv_local(cmd, metadata_lv)) {
-+			if (!activate_lv_excl_local(cmd, metadata_lv)) {
- 				log_error("Aborting. Failed to activate metadata lv.");
- 				goto bad;
- 			}
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-lvmlockd-add-lockopt-values-for-skipping-selected-lo.patch b/SOURCES/lvm2-2_02_178-lvmlockd-add-lockopt-values-for-skipping-selected-lo.patch
deleted file mode 100644
index 81d98a0..0000000
--- a/SOURCES/lvm2-2_02_178-lvmlockd-add-lockopt-values-for-skipping-selected-lo.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From 8a5e0083200db4b8d1ee2d4e95079372e75fd750 Mon Sep 17 00:00:00 2001
-From: David Teigland <teigland@redhat.com>
-Date: Tue, 9 Jan 2018 11:18:57 -0600
-Subject: [PATCH 09/25] lvmlockd: add lockopt values for skipping selected
- locks
-
-and add lockopt to common options.
-
-(cherry picked from commit 46cedb105bb7fdba0107794ca5801c2a0e8fd524)
----
- tools/command-lines.in |  9 ++++-----
- tools/lvmcmdline.c     | 10 ++++++++++
- 2 files changed, 14 insertions(+), 5 deletions(-)
-
-diff --git a/tools/command-lines.in b/tools/command-lines.in
-index d0e5e06..a1776ce 100644
---- a/tools/command-lines.in
-+++ b/tools/command-lines.in
-@@ -187,7 +187,7 @@
- # OO_ALL is included in every command automatically.
- #
- OO_ALL: --commandprofile String, --config String, --debug,
----driverloaded Bool, --help, --longhelp, --profile String, --quiet,
-+--driverloaded Bool, --help, --lockopt String, --longhelp, --profile String, --quiet,
- --verbose, --version, --yes, --test
- 
- #
-@@ -1524,19 +1524,18 @@ ID: vgchange_systemid
- DESC: Change the system ID of a VG.
- 
- vgchange --lockstart
--OO: --lockopt String, --select String
-+OO: --select String
- OP: VG|Tag|Select ...
- ID: vgchange_lockstart
- DESC: Start the lockspace of a shared VG in lvmlockd.
- 
- vgchange --lockstop
--OO: --lockopt String, --select String
-+OO: --select String
- OP: VG|Tag|Select ...
- ID: vgchange_lockstop
- DESC: Stop the lockspace of a shared VG in lvmlockd.
- 
- vgchange --locktype LockType VG
--OO: --lockopt String
- ID: vgchange_locktype
- DESC: Change the lock type for a shared VG.
- 
-@@ -1563,7 +1562,7 @@ OO: --addtag Tag, --alloc Alloc, --autobackup Bool, --clustered Bool, --maxlogic
- --physicalextentsize SizeMB, --force, --zero Bool, --labelsector Number,
- --metadatasize SizeMB, --pvmetadatacopies MetadataCopiesPV, --vgmetadatacopies MetadataCopiesVG,
- --reportformat ReportFmt, --dataalignment SizeKB, --dataalignmentoffset SizeKB,
----shared, --systemid String, --locktype LockType, --lockopt String
-+--shared, --systemid String, --locktype LockType
- ID: vgcreate_general
- 
- ---
-diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
-index b693722..791e272 100644
---- a/tools/lvmcmdline.c
-+++ b/tools/lvmcmdline.c
-@@ -2682,6 +2682,16 @@ static int _init_lvmlockd(struct cmd_context *cmd)
- 		return 1;
- 	}
- 
-+	if (use_lvmlockd && arg_is_set(cmd, lockopt_ARG)) {
-+		const char *opts = arg_str_value(cmd, lockopt_ARG, "");
-+		if (strstr(opts, "skiplv"))
-+			cmd->lockd_lv_disable = 1;
-+		if (strstr(opts, "skipvg"))
-+			cmd->lockd_vg_disable = 1;
-+		if (strstr(opts, "skipgl"))
-+			cmd->lockd_gl_disable = 1;
-+	}
-+
- 	if (use_lvmlockd && locking_is_clustered()) {
- 		log_error("ERROR: configuration setting use_lvmlockd cannot be used with clustered locking_type 3.");
- 		return 0;
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-lvmlockd-clear-coverity-complaint.patch b/SOURCES/lvm2-2_02_178-lvmlockd-clear-coverity-complaint.patch
deleted file mode 100644
index 31fd92c..0000000
--- a/SOURCES/lvm2-2_02_178-lvmlockd-clear-coverity-complaint.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From d70ba36fbb7851979265d7635740111a6aee5937 Mon Sep 17 00:00:00 2001
-From: David Teigland <teigland@redhat.com>
-Date: Mon, 18 Dec 2017 15:19:17 -0600
-Subject: [PATCH 07/25] lvmlockd: clear coverity complaint
-
-from previous coverity fix, it's never happy.
-
-(cherry picked from commit 3f9ae846b89a2963a4ca72cfa0281aab0bedcc02)
----
- lib/locking/lvmlockd.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
-index 0365797..a4684b4 100644
---- a/lib/locking/lvmlockd.c
-+++ b/lib/locking/lvmlockd.c
-@@ -2148,7 +2148,7 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
- static int _lockd_lv_thin(struct cmd_context *cmd, struct logical_volume *lv,
- 			  const char *def_mode, uint32_t flags)
- {
--	struct logical_volume *pool_lv;
-+	struct logical_volume *pool_lv = NULL;
- 
- 	if (lv_is_thin_volume(lv)) {
- 		struct lv_segment *pool_seg = first_seg(lv);
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-lvmlockd-print-warning-when-skipping-locking.patch b/SOURCES/lvm2-2_02_178-lvmlockd-print-warning-when-skipping-locking.patch
deleted file mode 100644
index aa2e689..0000000
--- a/SOURCES/lvm2-2_02_178-lvmlockd-print-warning-when-skipping-locking.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 599ec3dafea034dfafe0d897a8d591f0d07bd016 Mon Sep 17 00:00:00 2001
-From: David Teigland <teigland@redhat.com>
-Date: Tue, 9 Jan 2018 11:46:00 -0600
-Subject: [PATCH 10/25] lvmlockd: print warning when skipping locking
-
-(cherry picked from commit 51340888aab5e1b8630c7d8083e621ca0f4e4264)
----
- tools/lvmcmdline.c | 12 +++++++++---
- 1 file changed, 9 insertions(+), 3 deletions(-)
-
-diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
-index 791e272..6be4bcd 100644
---- a/tools/lvmcmdline.c
-+++ b/tools/lvmcmdline.c
-@@ -2684,12 +2684,18 @@ static int _init_lvmlockd(struct cmd_context *cmd)
- 
- 	if (use_lvmlockd && arg_is_set(cmd, lockopt_ARG)) {
- 		const char *opts = arg_str_value(cmd, lockopt_ARG, "");
--		if (strstr(opts, "skiplv"))
-+		if (strstr(opts, "skiplv")) {
-+			log_warn("WARNING: skipping LV lock in lvmlockd.");
- 			cmd->lockd_lv_disable = 1;
--		if (strstr(opts, "skipvg"))
-+		}
-+		if (strstr(opts, "skipvg")) {
-+			log_warn("WARNING: skipping VG lock in lvmlockd.");
- 			cmd->lockd_vg_disable = 1;
--		if (strstr(opts, "skipgl"))
-+		}
-+		if (strstr(opts, "skipgl")) {
-+			log_warn("WARNING: skipping global lock in lvmlockd.");
- 			cmd->lockd_gl_disable = 1;
-+		}
- 	}
- 
- 	if (use_lvmlockd && locking_is_clustered()) {
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-man-lvmlockd-remove-lv-resizing-comment.patch b/SOURCES/lvm2-2_02_178-man-lvmlockd-remove-lv-resizing-comment.patch
deleted file mode 100644
index e6b161c..0000000
--- a/SOURCES/lvm2-2_02_178-man-lvmlockd-remove-lv-resizing-comment.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 356e4eeb33d8f75cabb8f0c416cf9f09766d70b9 Mon Sep 17 00:00:00 2001
-From: David Teigland <teigland@redhat.com>
-Date: Wed, 10 Jan 2018 09:15:52 -0600
-Subject: [PATCH 11/25] man lvmlockd: remove lv resizing comment
-
-(cherry picked from commit 943b21779770f1cd93e73925e62f108e2efbd6cc)
----
- man/lvmlockd.8_main | 3 ---
- 1 file changed, 3 deletions(-)
-
-diff --git a/man/lvmlockd.8_main b/man/lvmlockd.8_main
-index bb45871..6f982bd 100644
---- a/man/lvmlockd.8_main
-+++ b/man/lvmlockd.8_main
-@@ -862,9 +862,6 @@ vgsplit
- .br
- \[bu]
- vgmerge
--.br
--\[bu]
--resizing an LV that is active in the shared mode on multiple hosts
- 
- 
- .SS lvmlockd changes from clvmd
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-man-lvmlockd-update-wording.patch b/SOURCES/lvm2-2_02_178-man-lvmlockd-update-wording.patch
deleted file mode 100644
index 90e78f3..0000000
--- a/SOURCES/lvm2-2_02_178-man-lvmlockd-update-wording.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 52fd5414cb31c4c92344e8fe9a4f137cdaabea7a Mon Sep 17 00:00:00 2001
-From: David Teigland <teigland@redhat.com>
-Date: Tue, 2 Jan 2018 13:10:34 -0600
-Subject: [PATCH 08/25] man lvmlockd: update wording
-
-(cherry picked from commit 96801ac0859798c4e478d05e91aaa68b4ce10c91)
----
- man/lvmlockd.8_main | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/man/lvmlockd.8_main b/man/lvmlockd.8_main
-index fbcdc87..bb45871 100644
---- a/man/lvmlockd.8_main
-+++ b/man/lvmlockd.8_main
-@@ -15,7 +15,7 @@ coordinate reading and writing of LVM metadata
- validate caching of LVM metadata
- .br
- \[bu]
--prevent concurrent activation of logical volumes
-+prevent conflicting activation of logical volumes
- .br
- 
- lvmlockd uses an external lock manager to perform basic locking.
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-mirror-Add-deprecation-warning-for-mirrored-log.patch b/SOURCES/lvm2-2_02_178-mirror-Add-deprecation-warning-for-mirrored-log.patch
deleted file mode 100644
index f1a0b7f..0000000
--- a/SOURCES/lvm2-2_02_178-mirror-Add-deprecation-warning-for-mirrored-log.patch
+++ /dev/null
@@ -1,74 +0,0 @@
- WHATS_NEW             |  1 +
- lib/metadata/mirror.c |  4 ++++
- tools/lvconvert.c     | 11 ++++++++---
- 3 files changed, 13 insertions(+), 3 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index da10eed..762553f 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,6 @@
- Version 2.02.178 - 
- =====================================
-+  Add deprecate messages for usage of mirrors with mirrorlog.
-   Restore pvmove support for wide-clustered active volumes (2.02.177).
-   Avoid non-exclusive activation of exclusive segment types.
-   Fix trimming sibling PVs when doing a pvmove of raid subLVs.
-diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
-index 38c3df6..4a0e99f 100644
---- a/lib/metadata/mirror.c
-+++ b/lib/metadata/mirror.c
-@@ -1945,6 +1945,10 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
- 		return 1;
- 	}
- 
-+	if (log_count > 1) {
-+		log_warn("WARNING: Log type \"mirrored\" is DEPRECATED and will be removed in the future. Use RAID1 LV or disk log instead.");
-+	}
-+
- 	if (!(parallel_areas = build_parallel_areas_from_lv(lv, 0, 0)))
- 		return_0;
- 
-diff --git a/tools/lvconvert.c b/tools/lvconvert.c
-index fee0a4e..8006699 100644
---- a/tools/lvconvert.c
-+++ b/tools/lvconvert.c
-@@ -686,7 +686,7 @@ static void _remove_missing_empty_pv(struct volume_group *vg, struct dm_list *re
- 			stack;
- 			return;
- 		}
--		log_warn("%d missing and now unallocated Physical Volumes removed from VG.", removed);
-+		log_warn("WARNING: %d missing and now unallocated Physical Volumes removed from VG.", removed);
- 	}
- }
- 
-@@ -828,7 +828,7 @@ static int _lvconvert_mirrors_aux(struct cmd_context *cmd,
- 	uint32_t old_log_count = _get_log_count(lv);
- 
- 	if ((lp->mirrors == 1) && !lv_is_mirrored(lv)) {
--		log_warn("Logical volume %s is already not mirrored.",
-+		log_warn("WARNING: Logical volume %s is already not mirrored.",
- 			 display_lvname(lv));
- 		return 1;
- 	}
-@@ -1100,7 +1100,7 @@ static int _lvconvert_mirrors_repair(struct cmd_context *cmd,
- 	log_count = replace_logs ? original_logs : (original_logs - failed_logs);
- 
- 	while (replace_mimages || replace_logs) {
--		log_warn("Trying to up-convert to %d images, %d logs.", lp->mirrors, log_count);
-+		log_warn("WARNING: Trying to up-convert to %d images, %d logs.", lp->mirrors, log_count);
- 		if (_lvconvert_mirrors_aux(cmd, lv, lp, NULL,
- 					   lp->mirrors, log_count, pvh))
- 			break;
-@@ -1216,6 +1216,11 @@ static int _lvconvert_mirrors(struct cmd_context *cmd,
- 	    (old_log_count == new_log_count))
- 		return 1;
- 
-+	if ((old_log_count != new_log_count) &&
-+	    (new_log_count == MIRROR_LOG_MIRRORED)) {
-+		log_warn("WARNING: Log type \"mirrored\" is DEPRECATED and will be removed in the future. Use RAID1 LV or disk log instead.");
-+	}
-+
- 	if (!_lvconvert_mirrors_aux(cmd, lv, lp, NULL,
- 				    new_mimage_count, new_log_count, lp->pvh))
- 		return_0;
diff --git a/SOURCES/lvm2-2_02_178-pvmove-better-check-for-exclusive-LV.patch b/SOURCES/lvm2-2_02_178-pvmove-better-check-for-exclusive-LV.patch
deleted file mode 100644
index 9f1ae45..0000000
--- a/SOURCES/lvm2-2_02_178-pvmove-better-check-for-exclusive-LV.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From d21e2b6005f656c1600bb49942f585d001e94839 Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Fri, 12 Jan 2018 15:59:07 +0100
-Subject: [PATCH 15/25] pvmove: better check for exclusive LV
-
-(cherry picked from commit 5a961d3411c8c11312d2998378277efc8988fc7f)
----
- tools/pvmove.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/tools/pvmove.c b/tools/pvmove.c
-index 39cf25f..9bbe12b 100644
---- a/tools/pvmove.c
-+++ b/tools/pvmove.c
-@@ -451,7 +451,9 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 		}
- 
- 		if (vg_is_clustered(vg) &&
--		    lv_is_active_exclusive_remotely(lv)) {
-+		    lv_is_visible(lv) &&
-+		    lv_is_active(lv) &&
-+		    !lv_is_active_exclusive_locally(lv)) {
- 			lv_skipped = 1;
- 			log_print_unless_silent("Skipping LV %s which is activated "
- 						"exclusively on remote node.", lv->name);
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-pvmove-drop-misleading-pvmove-restriction-for-cluste.patch b/SOURCES/lvm2-2_02_178-pvmove-drop-misleading-pvmove-restriction-for-cluste.patch
deleted file mode 100644
index f6a6d6a..0000000
--- a/SOURCES/lvm2-2_02_178-pvmove-drop-misleading-pvmove-restriction-for-cluste.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 00277d60e98409e493f6208f7f541f7b85ace91f Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Thu, 11 Jan 2018 16:15:16 +0100
-Subject: [PATCH 16/25] pvmove: drop misleading pvmove restriction for cluster
-
-pvmove handles properly locked LVs in cluster and this extra check
-actually cause misbehavior as some LVs were silently skipped from
-operation scope.
-
-(cherry picked from commit 02621cffb0d5ff72adb8770e26c1b4adb95bd0d9)
----
- tools/pvmove.c | 10 ----------
- 1 file changed, 10 deletions(-)
-
-diff --git a/tools/pvmove.c b/tools/pvmove.c
-index 9bbe12b..c5d7e52 100644
---- a/tools/pvmove.c
-+++ b/tools/pvmove.c
-@@ -371,16 +371,6 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 		if (lv_name && strcmp(lv->name, top_level_lv_name(vg, lv_name)))
- 			continue;
- 
--		/*
--		 * RAID, thin and snapshot-related LVs are not
--		 * processed in a cluster, so we don't have to
--		 * worry about avoiding certain PVs in that context.
--		 *
--		 * Allow clustered mirror, but not raid mirror.
--		 */
--		if (vg_is_clustered(vg) && !lv_is_mirror_type(lv))
--			continue;
--
- 		if (!lv_is_on_pvs(lv, source_pvl))
- 			continue;
- 
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-pvmove-enhance-accepted-states-of-active-LVs.patch b/SOURCES/lvm2-2_02_178-pvmove-enhance-accepted-states-of-active-LVs.patch
deleted file mode 100644
index 8970948..0000000
--- a/SOURCES/lvm2-2_02_178-pvmove-enhance-accepted-states-of-active-LVs.patch
+++ /dev/null
@@ -1,156 +0,0 @@
- tools/pvmove.c | 97 ++++++++++++++++++++++++++++++++--------------------------
- 1 file changed, 54 insertions(+), 43 deletions(-)
-
-diff --git a/tools/pvmove.c b/tools/pvmove.c
-index cbd5cb8..2a26a10 100644
---- a/tools/pvmove.c
-+++ b/tools/pvmove.c
-@@ -340,8 +340,8 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 	uint32_t log_count = 0;
- 	int lv_found = 0;
- 	int lv_skipped = 0;
--	int lv_active_count = 0;
--	int lv_exclusive_count = 0;
-+	int needs_exclusive = *exclusive;
-+	const struct logical_volume *holder;
- 
- 	/* FIXME Cope with non-contiguous => splitting existing segments */
- 	if (!(lv_mirr = lv_create_empty("pvmove%d", NULL,
-@@ -392,8 +392,13 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 			return NULL;
- 		}
- 
--		if (seg_is_raid(first_seg(lv)) ||
--		    seg_is_mirrored(first_seg(lv))) {
-+		seg = first_seg(lv);
-+
-+		/* Presence of exclusive LV decides whether pvmove must be also exclusive */
-+		if ((seg_only_exclusive(seg) || lv_is_origin(lv) || lv_is_cow(lv)))
-+			needs_exclusive = 1;
-+
-+		if (seg_is_raid(seg) || seg_is_mirrored(seg)) {
- 			dm_list_init(&trim_list);
- 
- 			if (!get_pv_list_for_lv(vg->cmd->mem, lv, &trim_list))
-@@ -432,6 +437,14 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 			lv_found = 1;
- 		}
- 
-+		seg = first_seg(lv);
-+
-+		if (seg_is_cache(seg) || seg_is_cache_pool(seg) ||
-+		    seg_is_mirrored(seg) || seg_is_raid(seg) ||
-+		    seg_is_snapshot(seg) ||
-+		    seg_is_thin(seg) || seg_is_thin_pool(seg))
-+			continue; /* bottom-level LVs only... */
-+
- 		if (!lv_is_on_pvs(lv, source_pvl))
- 			continue;
- 
-@@ -441,47 +454,36 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 			continue;
- 		}
- 
--		if (vg_is_clustered(vg) && lv_is_visible(lv)) {
--			if (lv_is_active_exclusive_locally(lv)) {
--				if (lv_active_count) {
--					log_error("Cannot move in clustered VG %s "
--						  "if some LVs are activated "
--						  "exclusively while others don't.",
--						  vg->name);
--					return NULL;
--				}
--
--				lv_exclusive_count++;
--			} else if (lv_is_active(lv)) {
--				if (seg_only_exclusive(first_seg(lv))) {
--					lv_skipped = 1;
--					log_print_unless_silent("Skipping LV %s which is active, "
--								"but not locally exclusively.",
--							display_lvname(lv));
--					continue;
--				}
--
--				if (*exclusive) {
--					log_error("Cannot move in clustered VG %s, "
--						  "clustered mirror (cmirror) not detected "
--						  "and LVs are activated non-exclusively.",
--						  vg->name);
--					return NULL;
--				}
--
--				lv_active_count++;
--			}
--		}
-+		holder = lv_lock_holder(lv);
- 
--		seg = first_seg(lv);
--		if (seg_is_raid(seg) || seg_is_mirrored(seg) ||
--		    seg_is_cache(seg) || seg_is_cache_pool(seg) ||
--		    seg_is_thin(seg) || seg_is_thin_pool(seg))
--			/*
--			 * Pass over top-level LVs - they were handled.
--			 * Allow sub-LVs to proceed.
-+		if (needs_exclusive) {
-+			/* With exclusive pvmove skip LV when:
-+			 *  - is active remotely
-+			 *  - is not active locally and cannot be activated exclusively locally
-+                         *
-+			 * Note: lvm2 can proceed with exclusive pvmove for 'just' locally active LVs
-+			 * in the case it's NOT active anywhere else, since LOCKED LVs cannot be
-+			 * later activated by user.
- 			 */
-+			if (lv_is_active_remotely(holder) ||
-+			    (!lv_is_active_locally(holder) && !activate_lv_excl_local(cmd, holder))) {
-+				lv_skipped = 1;
-+				log_print_unless_silent("Skipping LV %s which is not locally exclusive%s.",
-+							display_lvname(lv),
-+							/* Report missing cmirrord cases that matterd.
-+							 * With exclusive LV types cmirrord would not help. */
-+							(*exclusive &&
-+							 !lv_is_origin(holder) &&
-+							 !seg_only_exclusive(first_seg(holder))) ?
-+							" and clustered mirror (cmirror) not detected" : "");
-+				continue;
-+			}
-+		} else if (!activate_lv(cmd, holder)) {
-+			lv_skipped = 1;
-+			log_print_unless_silent("Skipping LV %s which cannot be activated.",
-+						display_lvname(lv));
- 			continue;
-+		}
- 
- 		if (!_insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
- 					    *lvs_changed))
-@@ -517,7 +519,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 		return NULL;
- 	}
- 
--	if (lv_exclusive_count)
-+	if (needs_exclusive)
- 		*exclusive = 1;
- 
- 	return lv_mirr;
-@@ -600,6 +602,8 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
- 	struct dm_list *lvs_changed;
- 	struct logical_volume *lv_mirr;
- 	struct logical_volume *lv = NULL;
-+	struct lv_list *lvl;
-+	const struct logical_volume *lvh;
- 	const char *pv_name = pv_dev_name(pv);
- 	unsigned flags = PVMOVE_FIRST_TIME;
- 	unsigned exclusive;
-@@ -661,6 +665,13 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
- 			goto out;
- 		}
- 
-+		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)))
-+				exclusive = 1;
-+		}
-+
- 		/* Ensure mirror LV is active */
- 		if (!_activate_lv(cmd, lv_mirr, exclusive)) {
- 			log_error("ABORTING: Temporary mirror activation failed.");
diff --git a/SOURCES/lvm2-2_02_178-pvmove-fix-_remove_sibling_pvs_from_trim_list.patch b/SOURCES/lvm2-2_02_178-pvmove-fix-_remove_sibling_pvs_from_trim_list.patch
deleted file mode 100644
index 411465a..0000000
--- a/SOURCES/lvm2-2_02_178-pvmove-fix-_remove_sibling_pvs_from_trim_list.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From 9c3e21e2483fa1818ff4ff4792aaec1d4ea437f8 Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Thu, 11 Jan 2018 13:21:08 +0100
-Subject: [PATCH 14/25] pvmove: fix _remove_sibling_pvs_from_trim_list
-
-Fix the function to really check it sibling raid image LV.
-For LV_rmeta_0  check for   LV_rimage_0   instead of
-LV_rmeta_0rimage_0.
-
-(cherry picked from commit 7c6fb63041cd5c1fb899cc468d0a5cf23a01abbe)
----
- WHATS_NEW      |  1 +
- tools/pvmove.c | 16 +++++++++++++---
- 2 files changed, 14 insertions(+), 3 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index c997206..4368543 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,6 @@
- Version 2.02.178 - 
- =====================================
-+  Fix trimming sibling PVs when doing a pvmove of raid subLVs.
-   Preserve exclusive activation during thin snaphost merge.
-   Avoid exceeding array bounds in allocation tag processing.
- 
-diff --git a/tools/pvmove.c b/tools/pvmove.c
-index 7bf1713..39cf25f 100644
---- a/tools/pvmove.c
-+++ b/tools/pvmove.c
-@@ -145,6 +145,7 @@ static int _remove_sibling_pvs_from_trim_list(struct logical_volume *lv,
- 					      struct dm_list *trim_list)
- {
- 	char *idx, *suffix;
-+	const char *sibling;
- 	char sublv_name[NAME_LEN];
- 	struct logical_volume *sublv;
- 	struct dm_list untrim_list, *pvh1, *pvh2;
-@@ -159,7 +160,16 @@ static int _remove_sibling_pvs_from_trim_list(struct logical_volume *lv,
- 
- 	dm_list_init(&untrim_list);
- 
--	if (!(suffix = first_substring(lv_name, "_rimage_", "_rmeta_", NULL))) {
-+	if (!dm_strncpy(sublv_name, lv_name, sizeof(sublv_name))) {
-+		log_error(INTERNAL_ERROR "LV name %s is too long.", lv_name);
-+		return 0;
-+	}
-+
-+	if ((suffix = strstr(sublv_name, "_rimage_")))
-+		sibling = "meta";
-+	else if ((suffix = strstr(sublv_name, "_rmeta_")))
-+		sibling = "image";
-+	else {
- 		log_error("Can't find rimage or rmeta suffix.");
- 		return 0;
- 	}
-@@ -171,8 +181,8 @@ static int _remove_sibling_pvs_from_trim_list(struct logical_volume *lv,
- 	idx++;
- 
- 	/* Create the siblings name (e.g. "raidlv_rmeta_N" -> "raidlv_rimage_N" */
--	if (dm_snprintf(sublv_name, sizeof(sublv_name), "%s_r%s_%s", lv_name,
--			strstr(suffix, "_rimage_") ? "meta" : "image", idx) < 0) {
-+	if (dm_snprintf(suffix + 2, sizeof(sublv_name) - 2 - (suffix - sublv_name),
-+			"%s_%s", sibling, idx) < 0) {
- 		log_error("Raid sublv for name %s too long.", lv_name);
- 		return 0;
- 	}
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-pvmove-reinstantiate-clustered-pvmove.patch b/SOURCES/lvm2-2_02_178-pvmove-reinstantiate-clustered-pvmove.patch
deleted file mode 100644
index 1c48301..0000000
--- a/SOURCES/lvm2-2_02_178-pvmove-reinstantiate-clustered-pvmove.patch
+++ /dev/null
@@ -1,280 +0,0 @@
- WHATS_NEW               |   1 +
- lib/activate/activate.c |   1 -
- lib/locking/locking.c   |  12 ++++--
- lib/locking/locking.h   |   2 +-
- tools/pvmove.c          | 109 ++++++++++++++++++++++++++++++++++++------------
- 5 files changed, 93 insertions(+), 32 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index c3117de..da10eed 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,6 @@
- Version 2.02.178 - 
- =====================================
-+  Restore pvmove support for wide-clustered active volumes (2.02.177).
-   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.
-diff --git a/lib/activate/activate.c b/lib/activate/activate.c
-index 18cc7cf..7a37130 100644
---- a/lib/activate/activate.c
-+++ b/lib/activate/activate.c
-@@ -2576,7 +2576,6 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
- 
- 	if (!laopts->exclusive &&
- 	    (lv_is_origin(lv) ||
--	     lv_is_pvmove(lv) ||
- 	     seg_only_exclusive(first_seg(lv))))  {
- 		log_error(INTERNAL_ERROR "Trying non-exlusive activation of %s with "
- 			  "a volume type %s requiring exclusive activation.",
-diff --git a/lib/locking/locking.c b/lib/locking/locking.c
-index 8daa61e..1a3ce9d 100644
---- a/lib/locking/locking.c
-+++ b/lib/locking/locking.c
-@@ -399,15 +399,19 @@ int activate_lv_excl(struct cmd_context *cmd, const struct logical_volume *lv)
- }
- 
- /* Lock a list of LVs */
--int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs)
-+int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive)
- {
- 	struct dm_list *lvh;
- 	struct lv_list *lvl;
- 
- 	dm_list_iterate_items(lvl, lvs) {
--		if (!activate_lv_excl_local(cmd, lvl->lv)) {
--			log_error("Failed to locally exclusively activate %s.",
--				  display_lvname(lvl->lv));
-+		if (!exclusive && !lv_is_active_exclusive(lvl->lv)) {
-+			if (!activate_lv(cmd, lvl->lv)) {
-+				log_error("Failed to activate %s", display_lvname(lvl->lv));
-+				return 0;
-+			}
-+		} else if (!activate_lv_excl(cmd, lvl->lv)) {
-+			log_error("Failed to activate %s", display_lvname(lvl->lv));
- 			dm_list_uniterate(lvh, lvs, &lvl->list) {
- 				lvl = dm_list_item(lvh, struct lv_list);
- 				if (!deactivate_lv(cmd, lvl->lv))
-diff --git a/lib/locking/locking.h b/lib/locking/locking.h
-index 47841ed..f2fbb00 100644
---- a/lib/locking/locking.h
-+++ b/lib/locking/locking.h
-@@ -262,6 +262,6 @@ int sync_dev_names(struct cmd_context* cmd);
- 
- /* Process list of LVs */
- struct volume_group;
--int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs);
-+int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive);
- 
- #endif
-diff --git a/tools/pvmove.c b/tools/pvmove.c
-index b3d1d89..cbd5cb8 100644
---- a/tools/pvmove.c
-+++ b/tools/pvmove.c
-@@ -64,6 +64,16 @@ static int _pvmove_target_present(struct cmd_context *cmd, int clustered)
- 	return found;
- }
- 
-+static unsigned _pvmove_is_exclusive(struct cmd_context *cmd,
-+				     struct volume_group *vg)
-+{
-+	if (vg_is_clustered(vg))
-+		if (!_pvmove_target_present(cmd, 1))
-+			return 1;
-+
-+	return 0;
-+}
-+
- /* Allow /dev/vgname/lvname, vgname/lvname or lvname */
- static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
- 				   const char *arg)
-@@ -320,7 +330,8 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 						const char *lv_name,
- 						struct dm_list *allocatable_pvs,
- 						alloc_policy_t alloc,
--						struct dm_list **lvs_changed)
-+						struct dm_list **lvs_changed,
-+						unsigned *exclusive)
- {
- 	struct logical_volume *lv_mirr, *lv;
- 	struct lv_segment *seg;
-@@ -329,6 +340,8 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 	uint32_t log_count = 0;
- 	int lv_found = 0;
- 	int lv_skipped = 0;
-+	int lv_active_count = 0;
-+	int lv_exclusive_count = 0;
- 
- 	/* FIXME Cope with non-contiguous => splitting existing segments */
- 	if (!(lv_mirr = lv_create_empty("pvmove%d", NULL,
-@@ -422,33 +435,54 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 		if (!lv_is_on_pvs(lv, source_pvl))
- 			continue;
- 
--		seg = first_seg(lv);
--		if (seg_is_raid(seg) || seg_is_mirrored(seg) ||
--		    lv_is_thin_volume(lv) || lv_is_thin_pool(lv)) {
--			/*
--			 * Pass over top-level LVs - they were handled.
--			 * Allow sub-LVs to proceed.
--			 */
--			continue;
--		}
--
- 		if (lv_is_locked(lv)) {
- 			lv_skipped = 1;
- 			log_print_unless_silent("Skipping locked LV %s.", display_lvname(lv));
- 			continue;
- 		}
- 
--		if (vg_is_clustered(vg) &&
--		    lv_is_visible(lv) &&
--		    lv_is_active(lv) &&
--		    !lv_is_active_exclusive_locally(lv)) {
--			lv_skipped = 1;
--			log_print_unless_silent("Skipping LV %s which is active, "
--						"but not locally exclusively.",
--						display_lvname(lv));
--			continue;
-+		if (vg_is_clustered(vg) && lv_is_visible(lv)) {
-+			if (lv_is_active_exclusive_locally(lv)) {
-+				if (lv_active_count) {
-+					log_error("Cannot move in clustered VG %s "
-+						  "if some LVs are activated "
-+						  "exclusively while others don't.",
-+						  vg->name);
-+					return NULL;
-+				}
-+
-+				lv_exclusive_count++;
-+			} else if (lv_is_active(lv)) {
-+				if (seg_only_exclusive(first_seg(lv))) {
-+					lv_skipped = 1;
-+					log_print_unless_silent("Skipping LV %s which is active, "
-+								"but not locally exclusively.",
-+							display_lvname(lv));
-+					continue;
-+				}
-+
-+				if (*exclusive) {
-+					log_error("Cannot move in clustered VG %s, "
-+						  "clustered mirror (cmirror) not detected "
-+						  "and LVs are activated non-exclusively.",
-+						  vg->name);
-+					return NULL;
-+				}
-+
-+				lv_active_count++;
-+			}
- 		}
- 
-+		seg = first_seg(lv);
-+		if (seg_is_raid(seg) || seg_is_mirrored(seg) ||
-+		    seg_is_cache(seg) || seg_is_cache_pool(seg) ||
-+		    seg_is_thin(seg) || seg_is_thin_pool(seg))
-+			/*
-+			 * Pass over top-level LVs - they were handled.
-+			 * Allow sub-LVs to proceed.
-+			 */
-+			continue;
-+
- 		if (!_insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
- 					    *lvs_changed))
- 			return_NULL;
-@@ -483,15 +517,35 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 		return NULL;
- 	}
- 
-+	if (lv_exclusive_count)
-+		*exclusive = 1;
-+
- 	return lv_mirr;
- }
- 
-+static int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
-+			unsigned exclusive)
-+{
-+	int r = 0;
-+
-+	if (exclusive || lv_is_active_exclusive(lv_mirr))
-+		r = activate_lv_excl(cmd, lv_mirr);
-+	else
-+		r = activate_lv(cmd, lv_mirr);
-+
-+	if (!r)
-+		stack;
-+
-+	return r;
-+}
-+
- /*
-  * Called to set up initial pvmove LV only.
-  * (Not called after first or any other section completes.)
-  */
- static int _update_metadata(struct logical_volume *lv_mirr,
--			    struct dm_list *lvs_changed)
-+			    struct dm_list *lvs_changed,
-+			    unsigned exclusive)
- {
- 	struct lv_list *lvl;
- 	struct logical_volume *lv = lv_mirr;
-@@ -505,7 +559,7 @@ static int _update_metadata(struct logical_volume *lv_mirr,
-                 return_0;
- 
- 	/* Ensure mirror LV is active */
--	if (!activate_lv_excl_local(lv_mirr->vg->cmd, lv_mirr)) {
-+	if (!_activate_lv(lv_mirr->vg->cmd, lv_mirr, exclusive)) {
- 		if (test_mode())
- 			return 1;
- 
-@@ -548,6 +602,7 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
- 	struct logical_volume *lv = NULL;
- 	const char *pv_name = pv_dev_name(pv);
- 	unsigned flags = PVMOVE_FIRST_TIME;
-+	unsigned exclusive;
- 	int r = ECMD_FAILED;
- 
- 	pp->found_pv = 1;
-@@ -594,6 +649,8 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
- 		}
- 	}
- 
-+	exclusive = _pvmove_is_exclusive(cmd, vg);
-+
- 	if ((lv_mirr = find_pvmove_lv(vg, pv_dev(pv), PVMOVE))) {
- 		log_print_unless_silent("Detected pvmove in progress for %s.", pv_name);
- 		if (pp->pv_count || lv_name)
-@@ -605,7 +662,7 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
- 		}
- 
- 		/* Ensure mirror LV is active */
--		if (!activate_lv_excl_local(cmd, lv_mirr)) {
-+		if (!_activate_lv(cmd, lv_mirr, exclusive)) {
- 			log_error("ABORTING: Temporary mirror activation failed.");
- 			goto out;
- 		}
-@@ -630,12 +687,12 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
- 
- 		if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, source_pvl, lv_name,
- 						  allocatable_pvs, pp->alloc,
--						  &lvs_changed)))
-+						  &lvs_changed, &exclusive)))
- 			goto_out;
- 	}
- 
- 	/* Lock lvs_changed and activate (with old metadata) */
--	if (!activate_lvs(cmd, lvs_changed))
-+	if (!activate_lvs(cmd, lvs_changed, exclusive))
- 		goto_out;
- 
- 	/* FIXME Presence of a mirror once set PVMOVE - now remove associated logic */
-@@ -646,7 +703,7 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
- 		goto out;
- 
- 	if (flags & PVMOVE_FIRST_TIME)
--		if (!_update_metadata(lv_mirr, lvs_changed))
-+		if (!_update_metadata(lv_mirr, lvs_changed, exclusive))
- 			goto_out;
- 
- 	/* LVs are all in status LOCKED */
diff --git a/SOURCES/lvm2-2_02_178-tests-check-preserved-exclusivness-of-snapshot-merge.patch b/SOURCES/lvm2-2_02_178-tests-check-preserved-exclusivness-of-snapshot-merge.patch
deleted file mode 100644
index ac295c6..0000000
--- a/SOURCES/lvm2-2_02_178-tests-check-preserved-exclusivness-of-snapshot-merge.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From 509497ae21a4c84f4714835c6f8017a66b666308 Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Mon, 15 Jan 2018 13:29:14 +0100
-Subject: [PATCH 22/25] tests: check preserved exclusivness of snapshot merge
-
-Detect if origin remains exclusively activated after merging.
-
-(cherry picked from commit 8ebd45fde759c438e854d6b4f02f0e9803094fea)
----
- test/shell/snapshot-merge.sh | 4 ++++
- test/shell/thin-merge.sh     | 9 +++++++++
- 2 files changed, 13 insertions(+)
-
-diff --git a/test/shell/snapshot-merge.sh b/test/shell/snapshot-merge.sh
-index 9d0a264..41e7b00 100644
---- a/test/shell/snapshot-merge.sh
-+++ b/test/shell/snapshot-merge.sh
-@@ -54,7 +54,11 @@ setup_merge_ $vg $lv1
- 
- # make sure lvconvert --merge requires explicit LV listing
- not lvconvert --merge
-+
-+# check exclusive lock is preserved after merge
-+check lv_field "$vg/$lv1" lv_active_exclusively "active exclusively"
- lvconvert --merge "$vg/$(snap_lv_name_ "$lv1")"
-+check lv_field "$vg/$lv1" lv_active_exclusively "active exclusively"
- lvremove -f $vg/$lv1
- 
- setup_merge_ $vg $lv1
-diff --git a/test/shell/thin-merge.sh b/test/shell/thin-merge.sh
-index 3abda40..24dec96 100644
---- a/test/shell/thin-merge.sh
-+++ b/test/shell/thin-merge.sh
-@@ -30,6 +30,15 @@ aux have_thin 1 0 0 || skip
- aux prepare_vg 2
- 
- lvcreate -T -L8M $vg/pool -V10M -n $lv1
-+lvcreate -s -K -n snap $vg/$lv1
-+# check exclusive lock is preserved after merge
-+check lv_field "$vg/$lv1" lv_active_exclusively "active exclusively"
-+lvconvert --merge $vg/snap
-+check lv_field "$vg/$lv1" lv_active_exclusively "active exclusively"
-+lvremove -ff $vg
-+
-+
-+lvcreate -T -L8M $vg/pool -V10M -n $lv1
- lvchange --addtag tagL $vg/$lv1
- 
- mkdir mnt
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-tests-check-pvmove-is-merging-segments.patch b/SOURCES/lvm2-2_02_178-tests-check-pvmove-is-merging-segments.patch
deleted file mode 100644
index a1885f6..0000000
--- a/SOURCES/lvm2-2_02_178-tests-check-pvmove-is-merging-segments.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From c3a9e28b2dad569fc39f36e90408a8a8f6357d5a Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Fri, 1 Dec 2017 11:58:38 +0100
-Subject: [PATCH 24/25] tests: check pvmove is merging segments
-
-pvmove was imporoved to properly merge consqutive segments after pvmove
-so check it's working.
-
-(cherry picked from commit e16d309d5651d1697f5246855ae816302cd8516f)
----
- test/shell/pvmove-all-segtypes.sh | 20 +++++++++++++++-----
- 1 file changed, 15 insertions(+), 5 deletions(-)
-
-diff --git a/test/shell/pvmove-all-segtypes.sh b/test/shell/pvmove-all-segtypes.sh
-index e10586e..f672290 100644
---- a/test/shell/pvmove-all-segtypes.sh
-+++ b/test/shell/pvmove-all-segtypes.sh
-@@ -29,12 +29,22 @@ aux prepare_vg 5 20
- # Testing pvmove of linear LV
- lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1"
- lvcreate -aey -l 2 -n $lv1 $vg "$dev1"
--check lv_tree_on $vg ${lv1}_foo "$dev1"
--check lv_tree_on $vg $lv1 "$dev1"
-+lvextend -l+2 $vg/${lv1}_foo "$dev1"
-+lvextend -l+2 $vg/${lv1} "$dev1"
-+lvextend -l+2 $vg/${lv1}_foo "$dev2"
-+lvextend -l+2 $vg/${lv1} "$dev3"
-+check lv_tree_on $vg ${lv1}_foo "$dev1" "$dev2"
-+check lv_tree_on $vg $lv1 "$dev1" "$dev3"
-+check lv_field $vg/${lv1}_foo seg_count 3
-+check lv_field $vg/$lv1 seg_count 3
- aux mkdev_md5sum $vg $lv1
--pvmove "$dev1" "$dev5"
--check lv_tree_on $vg ${lv1}_foo "$dev5"
--check lv_tree_on $vg $lv1 "$dev5"
-+dmsetup table
-+pvmove --atomic "$dev1" "$dev5"
-+check lv_tree_on $vg ${lv1}_foo "$dev2" "$dev5"
-+check lv_tree_on $vg $lv1 "$dev3" "$dev5"
-+# Also check 2 segments from $dev1 were merged on $dev5
-+check lv_field $vg/${lv1}_foo seg_count 2
-+check lv_field $vg/$lv1 seg_count 2
- check dev_md5sum $vg $lv1
- pvmove -n $lv1 "$dev5" "$dev4"
- check lv_tree_on $vg $lv1 "$dev4"
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-tests-longer-startup-timeout-for-daemons-with-valgri.patch b/SOURCES/lvm2-2_02_178-tests-longer-startup-timeout-for-daemons-with-valgri.patch
deleted file mode 100644
index d9235e5..0000000
--- a/SOURCES/lvm2-2_02_178-tests-longer-startup-timeout-for-daemons-with-valgri.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From b32a169b079a67629304c146aad65c2d79acfe01 Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Mon, 15 Jan 2018 16:26:34 +0100
-Subject: [PATCH 23/25] tests: longer startup timeout for daemons with valgrind
-
-It's getting noticable somewhat slower...
-
-(cherry picked from commit 5baf2de8986ceeb353c39ccf0503f9fefcb6eb92)
----
- test/lib/aux.sh | 16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/test/lib/aux.sh b/test/lib/aux.sh
-index 6bc7bd4..f30dfdd 100644
---- a/test/lib/aux.sh
-+++ b/test/lib/aux.sh
-@@ -180,8 +180,8 @@ prepare_clvmd() {
- 	LVM_LOG_FILE_EPOCH=CLVMD LVM_LOG_FILE_MAX_LINES=1000000 LVM_BINARY=$(which lvm) $run_valgrind clvmd -Isinglenode -d 1 -f &
- 	echo $! > LOCAL_CLVMD
- 
--	for i in {1..100} ; do
--		test "$i" -eq 100 && die "Startup of clvmd is too slow."
-+	for i in {200..0} ; do
-+		test "$i" -eq 0 && die "Startup of clvmd is too slow."
- 		test -e "$CLVMD_PIDFILE" && test -e "${CLVMD_PIDFILE%/*}/lvm/clvmd.sock" && break
- 		echo -n .
- 		sleep .1
-@@ -205,8 +205,8 @@ prepare_dmeventd() {
- 	echo $! > LOCAL_DMEVENTD
- 
- 	# FIXME wait for pipe in /var/run instead
--	for i in {1..100} ; do
--		test "$i" -eq 100 && die "Startup of dmeventd is too slow."
-+	for i in {200..0} ; do
-+		test "$i" -eq 0 && die "Startup of dmeventd is too slow."
- 		test -e "${DMEVENTD_PIDFILE}" && break
- 		echo -n .
- 		sleep .1
-@@ -230,8 +230,8 @@ prepare_lvmetad() {
- 	$run_valgrind lvmetad -f "$@" -s "$TESTDIR/lvmetad.socket" \
- 		${LVM_TEST_LVMETAD_DEBUG_OPTS--l all} &
- 	echo $! > LOCAL_LVMETAD
--	for i in {1..100} ; do
--		test "$i" -eq 100 && die "Startup of lvmetad is too slow."
-+	for i in {200..0} ; do
-+		test "$i" -eq 0 && die "Startup of lvmetad is too slow."
- 		test -e "$TESTDIR/lvmetad.socket" && break
- 		echo -n .
- 		sleep .1;
-@@ -280,8 +280,8 @@ prepare_lvmpolld() {
- 	echo -n "## preparing lvmpolld..."
- 	$run_valgrind lvmpolld -f "$@" -s "$TESTDIR/lvmpolld.socket" -B "$TESTDIR/lib/lvm" -l all &
- 	echo $! > LOCAL_LVMPOLLD
--	for i in {1..100} ; do
--		test "$i" -eq 100 && die "Startup of lvmpolld is too slow."
-+	for i in {200..0} ; do
-+		test "$i" -eq 0 && die "Startup of lvmpolld is too slow."
- 		test -e "$TESTDIR/lvmpolld.socket" && break
- 		echo -n .;
- 		sleep .1;
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_178-tests-properly-test-with-clustered-VG.patch b/SOURCES/lvm2-2_02_178-tests-properly-test-with-clustered-VG.patch
deleted file mode 100644
index 1029b8e..0000000
--- a/SOURCES/lvm2-2_02_178-tests-properly-test-with-clustered-VG.patch
+++ /dev/null
@@ -1,145 +0,0 @@
-From 42dd15665401075992d390ed034793c5c036e11f Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Thu, 11 Jan 2018 16:05:44 +0100
-Subject: [PATCH 21/25] tests: properly test with clustered VG
-
-Testing in cluster makes sense only with clustered VG.
-
-(cherry picked from commit 8c7ec44bf0fb23e2c5e426c5d07b02e3d25f5b59)
----
- test/shell/pvmove-basic.sh         | 10 +++++-----
- test/shell/pvmove-raid-segtypes.sh | 14 +++++++-------
- test/shell/pvmove-thin-segtypes.sh | 14 +++++++-------
- 3 files changed, 19 insertions(+), 19 deletions(-)
-
-diff --git a/test/shell/pvmove-basic.sh b/test/shell/pvmove-basic.sh
-index 056274d..42f165b 100644
---- a/test/shell/pvmove-basic.sh
-+++ b/test/shell/pvmove-basic.sh
-@@ -26,15 +26,15 @@ which md5sum || skip
- # Utilities
- 
- create_vg_() {
--	vgcreate -c n -s 128k "$vg" "${DEVICES[@]}"
-+	vgcreate -s 128k "$vg" "${DEVICES[@]}"
- }
- 
- # ---------------------------------------------------------------------
- # Common environment setup/cleanup for each sub testcases
- prepare_lvs_() {
--	lvcreate -l2 -n $lv1 $vg "$dev1"
-+	lvcreate -aey -l2 -n $lv1 $vg "$dev1"
- 	check lv_on $vg $lv1 "$dev1"
--	lvcreate -l9 -i3 -n $lv2 $vg "$dev2" "$dev3" "$dev4"
-+	lvcreate -aey -l9 -i3 -n $lv2 $vg "$dev2" "$dev3" "$dev4"
- 	check lv_on $vg $lv2 "$dev2" "$dev3" "$dev4"
- 	lvextend -l+2 $vg/$lv1 "$dev2"
- 	check lv_on $vg $lv1 "$dev1" "$dev2"
-@@ -57,7 +57,7 @@ prepare_lvs_() {
- # original content should be preserved
- restore_lvs_() {
- 	vgcfgrestore -f bak-$$ $vg
--	vgchange -ay $vg
-+	vgchange -aey $vg
- }
- 
- lvs_not_changed_() {
-@@ -348,7 +348,7 @@ vgremove -ff $vg
- pvcreate "${DEVICES[@]}"
- pvcreate --metadatacopies 0 "$dev1" "$dev2"
- create_vg_
--lvcreate -l4 -n $lv1 $vg "$dev1"
-+lvcreate -aey -l4 -n $lv1 $vg "$dev1"
- pvmove $mode "$dev1"
- 
- #COMM "pvmove fails activating mirror, properly restores state before pvmove"
-diff --git a/test/shell/pvmove-raid-segtypes.sh b/test/shell/pvmove-raid-segtypes.sh
-index be41547..6584b74 100644
---- a/test/shell/pvmove-raid-segtypes.sh
-+++ b/test/shell/pvmove-raid-segtypes.sh
-@@ -22,7 +22,7 @@ aux have_raid 1 3 5 || skip
- aux prepare_pvs 5 20
- get_devs
- 
--vgcreate -c n -s 128k "$vg" "${DEVICES[@]}"
-+vgcreate -s 128k "$vg" "${DEVICES[@]}"
- 
- for mode in "--atomic" ""
- do
-@@ -33,8 +33,8 @@ do
- # 3) Move only the second LV by name
- 
- # Testing pvmove of RAID1 LV
--lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
--lvcreate --regionsize 16K -l 2 --type raid1 -m 1 -n $lv1 $vg "$dev1" "$dev2"
-+lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate -aey --regionsize 16K -l 2 --type raid1 -m 1 -n $lv1 $vg "$dev1" "$dev2"
- check lv_tree_on $vg ${lv1}_foo "$dev1"
- check lv_tree_on $vg $lv1 "$dev1" "$dev2"
- aux mkdev_md5sum $vg $lv1
-@@ -49,8 +49,8 @@ check dev_md5sum $vg $lv1
- lvremove -ff $vg
- 
- # Testing pvmove of RAID10 LV
--lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
--lvcreate -l 4 --type raid10 -i 2 -m 1 -n $lv1 $vg \
-+lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate -aey -l 4 --type raid10 -i 2 -m 1 -n $lv1 $vg \
-                 "$dev1" "$dev2" "$dev3" "$dev4"
- check lv_tree_on $vg ${lv1}_foo "$dev1"
- check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4"
-@@ -75,8 +75,8 @@ check dev_md5sum $vg $lv1
- lvremove -ff $vg
- 
- # Testing pvmove of RAID5 LV
--lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
--lvcreate -l 4 --type raid5 -i 2 -n $lv1 $vg \
-+lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate -aey -l 4 --type raid5 -i 2 -n $lv1 $vg \
-                 "$dev1" "$dev2" "$dev3"
- check lv_tree_on $vg ${lv1}_foo "$dev1"
- check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3"
-diff --git a/test/shell/pvmove-thin-segtypes.sh b/test/shell/pvmove-thin-segtypes.sh
-index 01d98b4..08685c8 100644
---- a/test/shell/pvmove-thin-segtypes.sh
-+++ b/test/shell/pvmove-thin-segtypes.sh
-@@ -24,7 +24,7 @@ aux have_raid 1 3 5 || skip
- aux prepare_pvs 5 20
- get_devs
- 
--vgcreate -c n -s 128k "$vg" "${DEVICES[@]}" 
-+vgcreate -s 128k "$vg" "${DEVICES[@]}"
- 
- for mode in "--atomic" ""
- do
-@@ -37,8 +37,8 @@ do
- 
- 
- # Testing pvmove of thin LV
--lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
--lvcreate -T $vg/${lv1}_pool -l 4 -V 8 -n $lv1 "$dev1"
-+lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate -aey -T $vg/${lv1}_pool -l 4 -V 8 -n $lv1 "$dev1"
- check lv_tree_on $vg ${lv1}_foo "$dev1"
- check lv_tree_on $vg $lv1 "$dev1"
- aux mkdev_md5sum $vg $lv1
-@@ -53,12 +53,12 @@ check dev_md5sum $vg $lv1
- lvremove -ff $vg
- 
- # Testing pvmove of thin LV on RAID
--lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
--lvcreate --type raid1 -m 1 -l 4 -n ${lv1}_raid1_pool $vg "$dev1" "$dev2"
--lvcreate --type raid1 -m 1 -L 2 -n ${lv1}_raid1_meta $vg "$dev1" "$dev2"
-+lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate -aey --type raid1 -m 1 -l 4 -n ${lv1}_raid1_pool $vg "$dev1" "$dev2"
-+lvcreate -aey --type raid1 -m 1 -L 2 -n ${lv1}_raid1_meta $vg "$dev1" "$dev2"
- lvconvert --yes --thinpool $vg/${lv1}_raid1_pool \
-         --poolmetadata ${lv1}_raid1_meta
--lvcreate -T $vg/${lv1}_raid1_pool -V 8 -n $lv1
-+lvcreate -aey -T $vg/${lv1}_raid1_pool -V 8 -n $lv1
- check lv_tree_on $vg ${lv1}_foo "$dev1"
- check lv_tree_on $vg $lv1 "$dev1" "$dev2"
- aux mkdev_md5sum $vg $lv1
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_180-make-generate.patch b/SOURCES/lvm2-2_02_180-make-generate.patch
new file mode 100644
index 0000000..314425c
--- /dev/null
+++ b/SOURCES/lvm2-2_02_180-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 cd58615..742812c 100644
+--- a/conf/example.conf.in
++++ b/conf/example.conf.in
+@@ -702,17 +702,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-2_02_181-WHATS_NEW.patch b/SOURCES/lvm2-2_02_181-WHATS_NEW.patch
new file mode 100644
index 0000000..ad5b2a0
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-WHATS_NEW.patch
@@ -0,0 +1,29 @@
+From b6608e0f8426ad334a9eb2f6e1c9a1cfced0536e Mon Sep 17 00:00:00 2001
+From: Marian Csontos <mcsontos@redhat.com>
+Date: Tue, 31 Jul 2018 17:02:47 +0200
+Subject: [PATCH 1/2] Update WHATS_NEW
+
+---
+ WHATS_NEW | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 3b15325..546d3e6 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,7 +1,10 @@
+ Version 2.02.181 - 
+ =================================
+-  lvconvert: reject conversions on raid1 LVs with split tracked SubLVs
+-  lvconvert: reject conversions on raid1 split tracked SubLVs
++  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.
+ 
+ Version 2.02.180 - 19th July 2018
+ =================================
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_181-build-make-generate.patch b/SOURCES/lvm2-2_02_181-build-make-generate.patch
new file mode 100644
index 0000000..ea9232e
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-build-make-generate.patch
@@ -0,0 +1,52 @@
+From fc32d2b1b62eb9b75c246efd9c8e514b39f7bd3e Mon Sep 17 00:00:00 2001
+From: Marian Csontos <mcsontos@redhat.com>
+Date: Tue, 31 Jul 2018 17:36:04 +0200
+Subject: [PATCH] build: make generate
+
+(cherry picked from commit 12dfd0ed02e003e21072798d17dcec4a80fc466d)
+---
+ man/lvconvert.8_pregen | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen
+index 91691a3..a47127b 100644
+--- a/man/lvconvert.8_pregen
++++ b/man/lvconvert.8_pregen
+@@ -475,7 +475,7 @@ Split images from a raid1 or mirror LV and use them to create a new LV.
+ .RE
+ -
+ 
+-Split images from a raid1 LV and track changes to origin.
++Split images from a raid1 LV and track changes to origin for later merge.
+ .br
+ .P
+ \fBlvconvert\fP \fB--splitmirrors\fP \fINumber\fP \fB--trackchanges\fP \fILV\fP\fI_cache_raid1\fP
+@@ -1281,6 +1281,8 @@ Before the separation, the cache is flushed. Also see --uncache.
+ Splits the specified number of images from a raid1 or mirror LV
+ and uses them to create a new LV. If --trackchanges is also specified,
+ changes to the raid1 LV are tracked while the split LV remains detached.
++If --name is specified, then the images are permanently split from the
++original LV and changes are not tracked.
+ .ad b
+ .HP
+ .ad l
+@@ -1354,10 +1356,12 @@ The name of a thin pool LV.
+ .br
+ Can be used with --splitmirrors on a raid1 LV. This causes
+ changes to the original raid1 LV to be tracked while the split images
+-remain detached. This allows the read-only detached image(s) to be
+-merged efficiently back into the raid1 LV later. Only the regions with
+-changed data are resynchronized during merge. (This option only applies
+-when using the raid1 LV type.)
++remain detached. This is a temporary state that allows the read-only
++detached image to be merged efficiently back into the raid1 LV later.
++Only the regions with changed data are resynchronized during merge.
++While a raid1 LV is tracking changes, operations on it are limited to
++merging the split image (see --mergemirrors) or permanently splitting
++the image (see --splitmirrors with --name.
+ .ad b
+ .HP
+ .ad l
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_181-dmeventd-base-vdo-plugin.patch b/SOURCES/lvm2-2_02_181-dmeventd-base-vdo-plugin.patch
new file mode 100644
index 0000000..938c669
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-dmeventd-base-vdo-plugin.patch
@@ -0,0 +1,562 @@
+ WHATS_NEW_DM                                   |   1 +
+ configure                                      |   3 +-
+ configure.ac                                   |   1 +
+ daemons/dmeventd/libdevmapper-event.c          |   1 +
+ daemons/dmeventd/plugins/Makefile.in           |   9 +-
+ daemons/dmeventd/plugins/vdo/.exported_symbols |   3 +
+ daemons/dmeventd/plugins/vdo/Makefile.in       |  36 +++
+ daemons/dmeventd/plugins/vdo/dmeventd_vdo.c    | 406 +++++++++++++++++++++++++
+ 8 files changed, 453 insertions(+), 7 deletions(-)
+ create mode 100644 daemons/dmeventd/plugins/vdo/.exported_symbols
+ create mode 100644 daemons/dmeventd/plugins/vdo/Makefile.in
+ create mode 100644 daemons/dmeventd/plugins/vdo/dmeventd_vdo.c
+
+diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
+index e77352a..c42ee17 100644
+--- a/WHATS_NEW_DM
++++ b/WHATS_NEW_DM
+@@ -1,5 +1,6 @@
+ Version 1.02.150 - 
+ =================================
++  Add vdo plugin for monitoring VDO devices.
+ 
+ Version 1.02.149 - 19th July 2018
+ =================================
+diff --git a/configure b/configure
+index 10b49c6..eb7d70b 100755
+--- a/configure
++++ b/configure
+@@ -15648,7 +15648,7 @@ _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/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"
++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
+@@ -16356,6 +16356,7 @@ do
+     "daemons/dmeventd/plugins/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/mirror/Makefile" ;;
+     "daemons/dmeventd/plugins/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/snapshot/Makefile" ;;
+     "daemons/dmeventd/plugins/thin/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/thin/Makefile" ;;
++    "daemons/dmeventd/plugins/vdo/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/vdo/Makefile" ;;
+     "daemons/dmfilemapd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmfilemapd/Makefile" ;;
+     "daemons/lvmdbusd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/Makefile" ;;
+     "daemons/lvmdbusd/lvmdbusd") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/lvmdbusd" ;;
+diff --git a/configure.ac b/configure.ac
+index 9fa0c76..24bae39 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -2155,6 +2155,7 @@ 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
+diff --git a/daemons/dmeventd/libdevmapper-event.c b/daemons/dmeventd/libdevmapper-event.c
+index 9aeb4c5..f9a8a2b 100644
+--- a/daemons/dmeventd/libdevmapper-event.c
++++ b/daemons/dmeventd/libdevmapper-event.c
+@@ -645,6 +645,7 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh)
+ 	uuid = dm_task_get_uuid(dmt);
+ 
+ 	if (!strstr(dmevh->dso, "libdevmapper-event-lvm2thin.so") &&
++	    !strstr(dmevh->dso, "libdevmapper-event-lvm2vdo.so") &&
+ 	    !strstr(dmevh->dso, "libdevmapper-event-lvm2snapshot.so") &&
+ 	    !strstr(dmevh->dso, "libdevmapper-event-lvm2mirror.so") &&
+ 	    !strstr(dmevh->dso, "libdevmapper-event-lvm2raid.so"))
+diff --git a/daemons/dmeventd/plugins/Makefile.in b/daemons/dmeventd/plugins/Makefile.in
+index 27edf55..951dd2b 100644
+--- a/daemons/dmeventd/plugins/Makefile.in
++++ b/daemons/dmeventd/plugins/Makefile.in
+@@ -1,6 +1,6 @@
+ #
+ # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+-# Copyright (C) 2004-2005, 2011 Red Hat, Inc. All rights reserved.
++# Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved.
+ #
+ # This file is part of LVM2.
+ #
+@@ -16,11 +16,7 @@ srcdir = @srcdir@
+ top_srcdir = @top_srcdir@
+ top_builddir = @top_builddir@
+ 
+-SUBDIRS += lvm2 snapshot raid thin mirror
+-
+-ifeq ($(MAKECMDGOALS),distclean)
+-  SUBDIRS = lvm2 mirror snapshot raid thin
+-endif
++SUBDIRS += lvm2 snapshot raid thin mirror vdo
+ 
+ include $(top_builddir)/make.tmpl
+ 
+@@ -28,3 +24,4 @@ snapshot: lvm2
+ mirror: lvm2
+ raid: lvm2
+ thin: lvm2
++vdo: lvm2
+diff --git a/daemons/dmeventd/plugins/vdo/.exported_symbols b/daemons/dmeventd/plugins/vdo/.exported_symbols
+new file mode 100644
+index 0000000..b88c705
+--- /dev/null
++++ b/daemons/dmeventd/plugins/vdo/.exported_symbols
+@@ -0,0 +1,3 @@
++process_event
++register_device
++unregister_device
+diff --git a/daemons/dmeventd/plugins/vdo/Makefile.in b/daemons/dmeventd/plugins/vdo/Makefile.in
+new file mode 100644
+index 0000000..bda738a
+--- /dev/null
++++ b/daemons/dmeventd/plugins/vdo/Makefile.in
+@@ -0,0 +1,36 @@
++#
++# Copyright (C) 2018 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@
++
++INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
++CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
++
++SOURCES = dmeventd_vdo.c
++
++LIB_NAME = libdevmapper-event-lvm2vdo
++LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
++LIB_VERSION = $(LIB_VERSION_LVM)
++
++CFLOW_LIST = $(SOURCES)
++CFLOW_LIST_TARGET = $(LIB_NAME).cflow
++
++include $(top_builddir)/make.tmpl
++
++LIBS += -ldevmapper-event-lvm2 $(INTERNAL_LIBS)
++
++install_lvm2: install_dm_plugin
++
++install: install_lvm2
+diff --git a/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c b/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c
+new file mode 100644
+index 0000000..d77ca79
+--- /dev/null
++++ b/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c
+@@ -0,0 +1,406 @@
++/*
++ * Copyright (C) 2018 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/misc/lib.h"
++#include "dmeventd_lvm.h"
++#include "daemons/dmeventd/libdevmapper-event.h"
++#include "device_mapper/vdo/target.h"
++
++#include <sys/wait.h>
++#include <stdarg.h>
++
++/* First warning when VDO pool is 80% full. */
++#define WARNING_THRESH	(DM_PERCENT_1 * 80)
++/* Run a check every 5%. */
++#define CHECK_STEP	(DM_PERCENT_1 *  5)
++/* Do not bother checking VDO pool is less than 50% full. */
++#define CHECK_MINIMUM	(DM_PERCENT_1 * 50)
++
++#define MAX_FAILS	(256)  /* ~42 mins between cmd call retry with 10s delay */
++
++#define VDO_DEBUG 0
++
++struct dso_state {
++	struct dm_pool *mem;
++	int percent_check;
++	int percent;
++	uint64_t known_data_size;
++	unsigned fails;
++	unsigned max_fails;
++	int restore_sigset;
++	sigset_t old_sigset;
++	pid_t pid;
++	char *argv[3];
++	const char *cmd_str;
++	const char *name;
++};
++
++DM_EVENT_LOG_FN("vdo")
++
++static int _run_command(struct dso_state *state)
++{
++	char val[16];
++	int i;
++
++	/* Mark for possible lvm2 command we are running from dmeventd
++	 * lvm2 will not try to talk back to dmeventd while processing it */
++	(void) setenv("LVM_RUN_BY_DMEVENTD", "1", 1);
++
++	if (state->percent) {
++		/* Prepare some known data to env vars for easy use */
++		if (dm_snprintf(val, sizeof(val), "%d",
++				state->percent / DM_PERCENT_1) != -1)
++			(void) setenv("DMEVENTD_VDO_POOL", val, 1);
++	} else {
++		/* For an error event it's for a user to check status and decide */
++		log_debug("Error event processing.");
++	}
++
++	log_verbose("Executing command: %s", state->cmd_str);
++
++	/* TODO:
++	 *   Support parallel run of 'task' and it's waitpid maintainence
++	 *   ATM we can't handle signaling of  SIGALRM
++	 *   as signalling is not allowed while 'process_event()' is running
++	 */
++	if (!(state->pid = fork())) {
++		/* child */
++		(void) close(0);
++		for (i = 3; i < 255; ++i) (void) close(i);
++		execvp(state->argv[0], state->argv);
++		_exit(errno);
++	} else if (state->pid == -1) {
++		log_error("Can't fork command %s.", state->cmd_str);
++		state->fails = 1;
++		return 0;
++	}
++
++	return 1;
++}
++
++static int _use_policy(struct dm_task *dmt, struct dso_state *state)
++{
++#if VDO_DEBUG
++	log_debug("dmeventd executes: %s.", state->cmd_str);
++#endif
++	if (state->argv[0])
++		return _run_command(state);
++
++	if (!dmeventd_lvm2_run_with_lock(state->cmd_str)) {
++		log_error("Failed command for %s.", dm_task_get_name(dmt));
++		state->fails = 1;
++		return 0;
++	}
++
++	state->fails = 0;
++
++	return 1;
++}
++
++/* Check if executed command has finished
++ * Only 1 command may run */
++static int _wait_for_pid(struct dso_state *state)
++{
++	int status = 0;
++
++	if (state->pid == -1)
++		return 1;
++
++	if (!waitpid(state->pid, &status, WNOHANG))
++		return 0;
++
++	/* Wait for finish */
++	if (WIFEXITED(status)) {
++		log_verbose("Child %d exited with status %d.",
++			    state->pid, WEXITSTATUS(status));
++		state->fails = WEXITSTATUS(status) ? 1 : 0;
++	} else {
++		if (WIFSIGNALED(status))
++			log_verbose("Child %d was terminated with status %d.",
++				    state->pid, WTERMSIG(status));
++		state->fails = 1;
++	}
++
++	state->pid = -1;
++
++	return 1;
++}
++
++void process_event(struct dm_task *dmt,
++		   enum dm_event_mask event __attribute__((unused)),
++		   void **user)
++{
++	const char *device = dm_task_get_name(dmt);
++	struct dso_state *state = *user;
++	void *next = NULL;
++	uint64_t start, length;
++	char *target_type = NULL;
++	char *params;
++	int needs_policy = 0;
++	struct dm_task *new_dmt = NULL;
++	struct dm_vdo_status_parse_result vdop = { .status = NULL };
++
++#if VDO_DEBUG
++	log_debug("Watch for VDO %s:%.2f%%.", state->name,
++		  dm_percent_to_round_float(state->percent_check, 2));
++#endif
++	if (!_wait_for_pid(state)) {
++		log_warn("WARNING: Skipping event, child %d is still running (%s).",
++			 state->pid, state->cmd_str);
++		return;
++	}
++
++	if (event & DM_EVENT_DEVICE_ERROR) {
++#if VDO_DEBUG
++		log_debug("VDO event error.");
++#endif
++		/* Error -> no need to check and do instant resize */
++		state->percent = 0;
++		if (_use_policy(dmt, state))
++			goto out;
++
++		stack;
++
++		if (!(new_dmt = dm_task_create(DM_DEVICE_STATUS)))
++			goto_out;
++
++		if (!dm_task_set_uuid(new_dmt, dm_task_get_uuid(dmt)))
++			goto_out;
++
++		/* Non-blocking status read */
++		if (!dm_task_no_flush(new_dmt))
++			log_warn("WARNING: Can't set no_flush for dm status.");
++
++		if (!dm_task_run(new_dmt))
++			goto_out;
++
++		dmt = new_dmt;
++	}
++
++	dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
++
++	if (!target_type || (strcmp(target_type, "vdo") != 0)) {
++		log_error("Invalid target type.");
++		goto out;
++	}
++
++	if (!dm_vdo_status_parse(state->mem, params, &vdop)) {
++		log_error("Failed to parse status.");
++		goto out;
++	}
++
++	state->percent = dm_make_percent(vdop.status->used_blocks,
++					 vdop.status->total_blocks);
++
++#if VDO_DEBUG
++	log_debug("VDO %s status  %.2f%% " FMTu64 "/" FMTu64 ".",
++		  state->name, dm_percent_to_round_float(state->percent, 2),
++		  vdop.status->used_blocks, vdop.status->total_blocks);
++#endif
++
++	/* VDO pool size had changed. Clear the threshold. */
++	if (state->known_data_size != vdop.status->total_blocks) {
++		state->percent_check = CHECK_MINIMUM;
++		state->known_data_size = vdop.status->total_blocks;
++		state->fails = 0;
++	}
++
++	/*
++	 * Trigger action when threshold boundary is exceeded.
++	 * Report 80% threshold warning when it's used above 80%.
++	 * Only 100% is exception as it cannot be surpased so policy
++	 * action is called for:  >50%, >55% ... >95%, 100%
++	 */
++	if ((state->percent > WARNING_THRESH) &&
++	    (state->percent > state->percent_check))
++		log_warn("WARNING: VDO %s %s is now %.2f%% full.",
++			 state->name, device,
++			 dm_percent_to_round_float(state->percent, 2));
++	if (state->percent > CHECK_MINIMUM) {
++		/* Run action when usage raised more than CHECK_STEP since the last time */
++		if (state->percent > state->percent_check)
++			needs_policy = 1;
++		state->percent_check = (state->percent / CHECK_STEP + 1) * CHECK_STEP;
++		if (state->percent_check == DM_PERCENT_100)
++			state->percent_check--; /* Can't get bigger then 100% */
++	} else
++		state->percent_check = CHECK_MINIMUM;
++
++	/* Reduce number of _use_policy() calls by power-of-2 factor till frequency of MAX_FAILS is reached.
++	 * Avoids too high number of error retries, yet shows some status messages in log regularly.
++	 * i.e. PV could have been pvmoved and VG/LV was locked for a while...
++	 */
++	if (state->fails) {
++		if (state->fails++ <= state->max_fails) {
++			log_debug("Postponing frequently failing policy (%u <= %u).",
++				  state->fails - 1, state->max_fails);
++			return;
++		}
++		if (state->max_fails < MAX_FAILS)
++			state->max_fails <<= 1;
++		state->fails = needs_policy = 1; /* Retry failing command */
++	} else
++		state->max_fails = 1; /* Reset on success */
++
++	/* FIXME: ATM nothing can be done, drop 0, once it becomes useful */
++	if (0 && needs_policy)
++		_use_policy(dmt, state);
++out:
++	if (vdop.status)
++		dm_pool_free(state->mem, vdop.status);
++
++	if (new_dmt)
++		dm_task_destroy(new_dmt);
++}
++
++/* Handle SIGCHLD for a thread */
++static void _sig_child(int signum __attribute__((unused)))
++{
++	/* empty SIG_IGN */;
++}
++
++/* Setup handler for SIGCHLD when executing external command
++ * to get quick 'waitpid()' reaction
++ * It will interrupt syscall just like SIGALRM and
++ * invoke process_event().
++ */
++static void _init_thread_signals(struct dso_state *state)
++{
++	struct sigaction act = { .sa_handler = _sig_child };
++	sigset_t my_sigset;
++
++	sigemptyset(&my_sigset);
++
++	if (sigaction(SIGCHLD, &act, NULL))
++		log_warn("WARNING: Failed to set SIGCHLD action.");
++	else if (sigaddset(&my_sigset, SIGCHLD))
++		log_warn("WARNING: Failed to add SIGCHLD to set.");
++	else if (pthread_sigmask(SIG_UNBLOCK, &my_sigset, &state->old_sigset))
++		log_warn("WARNING: Failed to unblock SIGCHLD.");
++	else
++		state->restore_sigset = 1;
++}
++
++static void _restore_thread_signals(struct dso_state *state)
++{
++	if (state->restore_sigset &&
++	    pthread_sigmask(SIG_SETMASK, &state->old_sigset, NULL))
++		log_warn("WARNING: Failed to block SIGCHLD.");
++}
++
++int register_device(const char *device,
++		    const char *uuid,
++		    int major __attribute__((unused)),
++		    int minor __attribute__((unused)),
++		    void **user)
++{
++	struct dso_state *state;
++	const char *cmd;
++	char *str;
++	char cmd_str[PATH_MAX + 128 + 2]; /* cmd ' ' vg/lv \0 */
++        const char *name = "pool";
++
++	if (!dmeventd_lvm2_init_with_pool("vdo_pool_state", state))
++		goto_bad;
++
++	state->cmd_str = "";
++
++	/* Search for command for LVM- prefixed devices only */
++	cmd = (strncmp(uuid, "LVM-", 4) == 0) ? "_dmeventd_vdo_command" : "";
++
++	if (!dmeventd_lvm2_command(state->mem, cmd_str, sizeof(cmd_str), cmd, device))
++		goto_bad;
++
++	if (strncmp(cmd_str, "lvm ", 4) == 0) {
++		if (!(state->cmd_str = dm_pool_strdup(state->mem, cmd_str + 4))) {
++			log_error("Failed to copy lvm VDO command.");
++				goto bad;
++		}
++	} else if (cmd_str[0] == '/') {
++		if (!(state->cmd_str = dm_pool_strdup(state->mem, cmd_str))) {
++			log_error("Failed to copy VDO command.");
++			goto bad;
++		}
++
++		/* Find last space before 'vg/lv' */
++		if (!(str = strrchr(state->cmd_str, ' ')))
++			goto inval;
++
++		if (!(state->argv[0] = dm_pool_strndup(state->mem, state->cmd_str,
++						       str - state->cmd_str))) {
++			log_error("Failed to copy command.");
++			goto bad;
++		}
++
++		state->argv[1] = str + 1;  /* 1 argument - vg/lv */
++		_init_thread_signals(state);
++	} else if (cmd[0] == 0) {
++		state->name = "volume"; /* What to use with 'others?' */
++	} else/* Unuspported command format */
++		goto inval;
++
++	state->pid = -1;
++	state->name = name;
++	*user = state;
++
++	log_info("Monitoring VDO %s %s.", name, device);
++
++	return 1;
++inval:
++	log_error("Invalid command for monitoring: %s.", cmd_str);
++bad:
++	log_error("Failed to monitor VDO %s %s.", name, device);
++
++	if (state)
++		dmeventd_lvm2_exit_with_pool(state);
++
++	return 0;
++}
++
++int unregister_device(const char *device,
++		      const char *uuid __attribute__((unused)),
++		      int major __attribute__((unused)),
++		      int minor __attribute__((unused)),
++		      void **user)
++{
++	struct dso_state *state = *user;
++	const char *name = state->name;
++	int i;
++
++	for (i = 0; !_wait_for_pid(state) && (i < 6); ++i) {
++		if (i == 0)
++			/* Give it 2 seconds, then try to terminate & kill it */
++			log_verbose("Child %d still not finished (%s) waiting.",
++				    state->pid, state->cmd_str);
++		else if (i == 3) {
++			log_warn("WARNING: Terminating child %d.", state->pid);
++			kill(state->pid, SIGINT);
++			kill(state->pid, SIGTERM);
++		} else if (i == 5) {
++			log_warn("WARNING: Killing child %d.", state->pid);
++			kill(state->pid, SIGKILL);
++		}
++		sleep(1);
++	}
++
++	if (state->pid != -1)
++		log_warn("WARNING: Cannot kill child %d!", state->pid);
++
++	_restore_thread_signals(state);
++
++	dmeventd_lvm2_exit_with_pool(state);
++	log_info("No longer monitoring VDO %s %s.", name, device);
++
++	return 1;
++}
diff --git a/SOURCES/lvm2-2_02_181-dmeventd-rebase-to-stable-branch.patch b/SOURCES/lvm2-2_02_181-dmeventd-rebase-to-stable-branch.patch
new file mode 100644
index 0000000..05cdc33
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-dmeventd-rebase-to-stable-branch.patch
@@ -0,0 +1,94 @@
+ daemons/dmeventd/plugins/vdo/dmeventd_vdo.c | 39 +++++++++++++++++++----------
+ 1 file changed, 26 insertions(+), 13 deletions(-)
+
+diff --git a/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c b/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c
+index d77ca79..389632c 100644
+--- a/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c
++++ b/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c
+@@ -12,10 +12,9 @@
+  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ 
+-#include "lib/misc/lib.h"
++#include "lib.h"
+ #include "dmeventd_lvm.h"
+-#include "daemons/dmeventd/libdevmapper-event.h"
+-#include "device_mapper/vdo/target.h"
++#include "libdevmapper-event.h"
+ 
+ #include <sys/wait.h>
+ #include <stdarg.h>
+@@ -46,6 +45,23 @@ struct dso_state {
+ 	const char *name;
+ };
+ 
++struct vdo_status {
++	uint64_t used_blocks;
++	uint64_t total_blocks;
++};
++
++static int _vdo_status_parse(const char *params, struct vdo_status *status)
++{
++	if (sscanf(params, "%*s %*s %*s %*s %*s %" PRIu64 " %" PRIu64,
++		   &status->used_blocks,
++		   &status->total_blocks) < 2) {
++		log_error("Failed to parse vdo params: %s.", params);
++		return 0;
++	}
++
++	return 1;
++}
++
+ DM_EVENT_LOG_FN("vdo")
+ 
+ static int _run_command(struct dso_state *state)
+@@ -149,7 +165,7 @@ void process_event(struct dm_task *dmt,
+ 	char *params;
+ 	int needs_policy = 0;
+ 	struct dm_task *new_dmt = NULL;
+-	struct dm_vdo_status_parse_result vdop = { .status = NULL };
++	struct vdo_status status;
+ 
+ #if VDO_DEBUG
+ 	log_debug("Watch for VDO %s:%.2f%%.", state->name,
+@@ -195,24 +211,24 @@ void process_event(struct dm_task *dmt,
+ 		goto out;
+ 	}
+ 
+-	if (!dm_vdo_status_parse(state->mem, params, &vdop)) {
++	if (!_vdo_status_parse(params, &status)) {
+ 		log_error("Failed to parse status.");
+ 		goto out;
+ 	}
+ 
+-	state->percent = dm_make_percent(vdop.status->used_blocks,
+-					 vdop.status->total_blocks);
++	state->percent = dm_make_percent(status.used_blocks,
++					 status.total_blocks);
+ 
+ #if VDO_DEBUG
+ 	log_debug("VDO %s status  %.2f%% " FMTu64 "/" FMTu64 ".",
+ 		  state->name, dm_percent_to_round_float(state->percent, 2),
+-		  vdop.status->used_blocks, vdop.status->total_blocks);
++		  status.used_blocks, status.total_blocks);
+ #endif
+ 
+ 	/* VDO pool size had changed. Clear the threshold. */
+-	if (state->known_data_size != vdop.status->total_blocks) {
++	if (state->known_data_size != status.total_blocks) {
+ 		state->percent_check = CHECK_MINIMUM;
+-		state->known_data_size = vdop.status->total_blocks;
++		state->known_data_size = status.total_blocks;
+ 		state->fails = 0;
+ 	}
+ 
+@@ -257,9 +273,6 @@ void process_event(struct dm_task *dmt,
+ 	if (0 && needs_policy)
+ 		_use_policy(dmt, state);
+ out:
+-	if (vdop.status)
+-		dm_pool_free(state->mem, vdop.status);
+-
+ 	if (new_dmt)
+ 		dm_task_destroy(new_dmt);
+ }
diff --git a/SOURCES/lvm2-2_02_181-dmsetup-fix-error-propagation-in-_display_info_cols.patch b/SOURCES/lvm2-2_02_181-dmsetup-fix-error-propagation-in-_display_info_cols.patch
new file mode 100644
index 0000000..8a1a079
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-dmsetup-fix-error-propagation-in-_display_info_cols.patch
@@ -0,0 +1,19 @@
+ tools/dmsetup.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/tools/dmsetup.c b/tools/dmsetup.c
+index 95a15dd..3cdf862 100644
+--- a/tools/dmsetup.c
++++ b/tools/dmsetup.c
+@@ -939,8 +939,10 @@ static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
+ 			goto_out;
+ 
+ 		/* No regions to report is not an error */
+-		if (!dm_stats_get_nr_regions(obj.stats))
++		if (!dm_stats_get_nr_regions(obj.stats)) {
++			r = 1;
+ 			goto out;
++		}
+ 	}
+ 
+ 	/* group report with no groups? */
diff --git a/SOURCES/lvm2-2_02_181-lvconvert-improve-text-about-splitmirrors.patch b/SOURCES/lvm2-2_02_181-lvconvert-improve-text-about-splitmirrors.patch
new file mode 100644
index 0000000..32fd96d
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-lvconvert-improve-text-about-splitmirrors.patch
@@ -0,0 +1,72 @@
+ lib/metadata/raid_manip.c |  4 ++--
+ tools/args.h              | 14 +++++++++-----
+ tools/command-lines.in    |  2 +-
+ 3 files changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
+index 8f78e1a..705a7f9 100644
+--- a/lib/metadata/raid_manip.c
++++ b/lib/metadata/raid_manip.c
+@@ -3563,7 +3563,7 @@ int lv_raid_merge(struct logical_volume *image_lv)
+ 	struct volume_group *vg = image_lv->vg;
+ 
+ 	if (image_lv->status & LVM_WRITE) {
+-		log_error("%s is not read-only - refusing to merge.",
++		log_error("%s cannot be merged because --trackchanges was not used.",
+ 			  display_lvname(image_lv));
+ 		return 0;
+ 	}
+@@ -3572,7 +3572,7 @@ int lv_raid_merge(struct logical_volume *image_lv)
+ 		return_0;
+ 
+ 	if (!(p = strstr(lv_name, "_rimage_"))) {
+-		log_error("Unable to merge non-mirror image %s.",
++		log_error("Unable to merge non-raid image %s.",
+ 			  display_lvname(image_lv));
+ 		return 0;
+ 	}
+diff --git a/tools/args.h b/tools/args.h
+index b80b8da..abe193c 100644
+--- a/tools/args.h
++++ b/tools/args.h
+@@ -611,7 +611,9 @@ arg(splitcache_ARG, '\0', "splitcache", 0, 0, 0,
+ arg(splitmirrors_ARG, '\0', "splitmirrors", number_VAL, 0, 0,
+     "Splits the specified number of images from a raid1 or mirror LV\n"
+     "and uses them to create a new LV. If --trackchanges is also specified,\n"
+-    "changes to the raid1 LV are tracked while the split LV remains detached.\n")
++    "changes to the raid1 LV are tracked while the split LV remains detached.\n"
++    "If --name is specified, then the images are permanently split from the\n"
++    "original LV and changes are not tracked.\n")
+ 
+ arg(splitsnapshot_ARG, '\0', "splitsnapshot", 0, 0, 0,
+     "Separates a COW snapshot from its origin LV. The LV that is split off\n"
+@@ -691,10 +693,12 @@ arg(thinpool_ARG, '\0', "thinpool", lv_VAL, 0, 0,
+ arg(trackchanges_ARG, '\0', "trackchanges", 0, 0, 0,
+     "Can be used with --splitmirrors on a raid1 LV. This causes\n"
+     "changes to the original raid1 LV to be tracked while the split images\n"
+-    "remain detached. This allows the read-only detached image(s) to be\n"
+-    "merged efficiently back into the raid1 LV later. Only the regions with\n"
+-    "changed data are resynchronized during merge. (This option only applies\n"
+-    "when using the raid1 LV type.)\n")
++    "remain detached. This is a temporary state that allows the read-only\n"
++    "detached image to be merged efficiently back into the raid1 LV later.\n"
++    "Only the regions with changed data are resynchronized during merge.\n"
++    "While a raid1 LV is tracking changes, operations on it are limited to\n"
++    "merging the split image (see --mergemirrors) or permanently splitting\n"
++    "the image (see --splitmirrors with --name.\n")
+ 
+ /* TODO: hide this? */
+ arg(trustcache_ARG, '\0', "trustcache", 0, 0, 0,
+diff --git a/tools/command-lines.in b/tools/command-lines.in
+index b7aefa3..a8c06ba 100644
+--- a/tools/command-lines.in
++++ b/tools/command-lines.in
+@@ -399,7 +399,7 @@ lvconvert --splitmirrors Number --trackchanges LV_raid1_cache
+ OO: OO_LVCONVERT
+ OP: PV ...
+ ID: lvconvert_split_mirror_images
+-DESC: Split images from a raid1 LV and track changes to origin.
++DESC: Split images from a raid1 LV and track changes to origin for later merge.
+ RULE: all not lv_is_locked lv_is_pvmove
+ 
+ lvconvert --mergemirrors LV_linear_raid|VG|Tag ...
diff --git a/SOURCES/lvm2-2_02_181-lvconvert-reject-conversions-of-LVs-under-snapshot.patch b/SOURCES/lvm2-2_02_181-lvconvert-reject-conversions-of-LVs-under-snapshot.patch
new file mode 100644
index 0000000..78dfd4e
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-lvconvert-reject-conversions-of-LVs-under-snapshot.patch
@@ -0,0 +1,20 @@
+ tools/lvconvert.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/tools/lvconvert.c b/tools/lvconvert.c
+index 3ce228f..3fad02c 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -4256,6 +4256,12 @@ static int _lvconvert_to_pool_or_swap_metadata_single(struct cmd_context *cmd,
+ 		return 0;
+ 	};
+ 
++	if (lv_is_origin(lv)) {
++		log_error("Cannot convert logical volume %s under snapshot.",
++			  display_lvname(lv));
++		return 0;
++	};
++
+ 	if (cmd->position_argc > 1) {
+ 		/* First pos arg is required LV, remaining are optional PVs. */
+ 		if (!(use_pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0)))
diff --git a/SOURCES/lvm2-2_02_181-lvconvert-restrict-command-matching-for-no-option-va.patch b/SOURCES/lvm2-2_02_181-lvconvert-restrict-command-matching-for-no-option-va.patch
new file mode 100644
index 0000000..61608ed
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-lvconvert-restrict-command-matching-for-no-option-va.patch
@@ -0,0 +1,69 @@
+ lib/commands/toolcontext.h |  1 +
+ tools/command-lines.in     |  2 +-
+ tools/lvmcmdline.c         | 14 ++++++++++++++
+ 3 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
+index bc05736..da5d582 100644
+--- a/lib/commands/toolcontext.h
++++ b/lib/commands/toolcontext.h
+@@ -95,6 +95,7 @@ struct cmd_context {
+ 	char **argv;
+ 	struct arg_values *opt_arg_values;
+ 	struct dm_list arg_value_groups;
++	int opt_count; /* total number of options (beginning with - or --) */
+ 
+ 	/*
+ 	 * Position args remaining after command name
+diff --git a/tools/command-lines.in b/tools/command-lines.in
+index 9d407d0..b7aefa3 100644
+--- a/tools/command-lines.in
++++ b/tools/command-lines.in
+@@ -700,7 +700,7 @@ RULE: all and lv_is_converting
+ # for compat since this was how it used to be done.
+ lvconvert LV_mirror_raid
+ OO: OO_LVCONVERT
+-ID: lvconvert_start_poll
++ID: lvconvert_plain
+ DESC: Poll LV to continue conversion (also see --startpoll)
+ DESC: or waits till conversion/mirror syncing is finished
+ FLAGS: SECONDARY_SYNTAX
+diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
+index 0600b1c..c62a66e 100644
+--- a/tools/lvmcmdline.c
++++ b/tools/lvmcmdline.c
+@@ -119,6 +119,7 @@ static const struct command_function _command_functions[CMD_COUNT] = {
+ 
+ 	/* lvconvert utility to trigger polling on an LV. */
+ 	{ lvconvert_start_poll_CMD, lvconvert_start_poll_cmd },
++	{ lvconvert_plain_CMD, lvconvert_start_poll_cmd },
+ 
+ 	/* lvconvert utilities for creating/maintaining thin and cache objects. */
+ 	{ lvconvert_to_thinpool_CMD,			lvconvert_to_pool_cmd },
+@@ -1579,6 +1580,17 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
+ 		if (arg_is_set(cmd, help_ARG) || arg_is_set(cmd, help2_ARG) || arg_is_set(cmd, longhelp_ARG) || arg_is_set(cmd, version_ARG))
+ 			return &commands[i];
+ 
++		/*
++		 * The 'lvconvert LV' cmd def matches any lvconvert cmd which throws off
++		 * nearest-command partial-match suggestions.  Make it a special case so
++		 * that it won't be used as a close match.  If the command has any option
++		 * set (other than -v), don't attempt to match it to 'lvconvert LV'.
++		 */
++		if (commands[i].command_enum == lvconvert_plain_CMD) {
++			if (cmd->opt_count - cmd->opt_arg_values[verbose_ARG].count)
++				continue;
++		}
++
+ 		match_required = 0;	/* required parameters that match */
+ 		match_ro = 0;		/* required opt_args that match */
+ 		match_rp = 0;		/* required pos_args that match */
+@@ -2097,6 +2109,8 @@ static int _process_command_line(struct cmd_context *cmd, int *argc, char ***arg
+ 		if (goval == '?')
+ 			return 0;
+ 
++		cmd->opt_count++;
++
+ 		/*
+ 		 * translate the option value used by getopt into the enum
+ 		 * value (e.g. foo_ARG) from the args array.
diff --git a/SOURCES/lvm2-2_02_181-post-release.patch b/SOURCES/lvm2-2_02_181-post-release.patch
new file mode 100644
index 0000000..126d1bd
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-post-release.patch
@@ -0,0 +1,26 @@
+ WHATS_NEW    | 3 +++
+ WHATS_NEW_DM | 3 +++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 62a5045..bdd2fa6 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,3 +1,6 @@
++Version 2.02.181 - 
++=================================
++
+ Version 2.02.180 - 19th July 2018
+ =================================
+   Never send any discard ioctl with test mode.
+diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
+index 93e4b14..e77352a 100644
+--- a/WHATS_NEW_DM
++++ b/WHATS_NEW_DM
+@@ -1,3 +1,6 @@
++Version 1.02.150 - 
++=================================
++
+ Version 1.02.149 - 19th July 2018
+ =================================
+ 
diff --git a/SOURCES/lvm2-2_02_181-reject-conversions-trackchanges-LVs.patch b/SOURCES/lvm2-2_02_181-reject-conversions-trackchanges-LVs.patch
new file mode 100644
index 0000000..68c7b5d
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-reject-conversions-trackchanges-LVs.patch
@@ -0,0 +1,51 @@
+ WHATS_NEW                                        | 1 +
+ test/shell/lvconvert-raid1-split-trackchanges.sh | 7 +++++++
+ tools/lvconvert.c                                | 6 ++++++
+ 3 files changed, 14 insertions(+)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 7c74c50..3b15325 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,6 @@
+ Version 2.02.181 - 
+ =================================
++  lvconvert: reject conversions on raid1 LVs with split tracked SubLVs
+   lvconvert: reject conversions on raid1 split tracked SubLVs
+ 
+ Version 2.02.180 - 19th July 2018
+diff --git a/test/shell/lvconvert-raid1-split-trackchanges.sh b/test/shell/lvconvert-raid1-split-trackchanges.sh
+index e25a632..718c254 100644
+--- a/test/shell/lvconvert-raid1-split-trackchanges.sh
++++ b/test/shell/lvconvert-raid1-split-trackchanges.sh
+@@ -27,6 +27,13 @@ vgcreate $SHARED -s 512k "$vg" "${DEVICES[@]}"
+ lvcreate -y --ty raid1 -m 2 -n $lv1 -l 1 $vg
+ lvconvert -y --splitmirrors 1 --trackchanges $vg/$lv1
+ 
++not lvconvert -y --ty linear $vg/$lv1
++not lvconvert -y --ty striped -i 3 $vg/$lv1
++not lvconvert -y --ty mirror $vg/$lv1
++not lvconvert -y --ty raid4 $vg/$lv1
++not lvconvert -y --ty raid5 $vg/$lv1
++not lvconvert -y --ty raid6 $vg/$lv1
++not lvconvert -y --ty raid10 $vg/$lv1
+ not lvconvert -y --ty striped -m 1 $vg/${lv1}_rimage_2
+ not lvconvert -y --ty raid1 -m 1 $vg/${lv1}_rimage_2
+ not lvconvert -y --ty mirror -m 1 $vg/${lv1}_rimage_2
+diff --git a/tools/lvconvert.c b/tools/lvconvert.c
+index 079c3cd..731a210 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -1170,6 +1170,12 @@ static int _raid_split_image_conversion(struct logical_volume *lv)
+ {
+ 	const char *s;
+ 
++	if (lv_is_raid_with_tracking(lv)) {
++		log_error("Conversion of tracking raid1 LV %s is not supported.",
++			  display_lvname(lv));
++		return 1;
++	}
++
+ 	if (lv_is_raid_image(lv) &&
+ 	    (s = strstr(lv->name, "_rimage_"))) {
+ 		size_t len = s - lv->name;
diff --git a/SOURCES/lvm2-2_02_181-reject-conversions-trackchanges-SubLVs.patch b/SOURCES/lvm2-2_02_181-reject-conversions-trackchanges-SubLVs.patch
new file mode 100644
index 0000000..f822a79
--- /dev/null
+++ b/SOURCES/lvm2-2_02_181-reject-conversions-trackchanges-SubLVs.patch
@@ -0,0 +1,150 @@
+ WHATS_NEW                                        |  1 +
+ test/shell/lvconvert-raid1-split-trackchanges.sh | 36 +++++++++++++++++++
+ tools/lvconvert.c                                | 45 ++++++++++++++++++++++++
+ 3 files changed, 82 insertions(+)
+ create mode 100644 test/shell/lvconvert-raid1-split-trackchanges.sh
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index bdd2fa6..7c74c50 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,6 @@
+ Version 2.02.181 - 
+ =================================
++  lvconvert: reject conversions on raid1 split tracked SubLVs
+ 
+ Version 2.02.180 - 19th July 2018
+ =================================
+diff --git a/test/shell/lvconvert-raid1-split-trackchanges.sh b/test/shell/lvconvert-raid1-split-trackchanges.sh
+new file mode 100644
+index 0000000..e25a632
+--- /dev/null
++++ b/test/shell/lvconvert-raid1-split-trackchanges.sh
+@@ -0,0 +1,36 @@
++#!/usr/bin/env bash
++
++# Copyright (C) 2018 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_LVMPOLLD=1
++
++. lib/inittest
++
++# rhbz1579072/rhbz1579438
++
++aux have_raid 1 3 0 || skip
++
++# 8 PVs needed for RAID10 testing (4-stripes/2-mirror)
++aux prepare_pvs 4 2
++get_devs
++vgcreate $SHARED -s 512k "$vg" "${DEVICES[@]}"
++
++lvcreate -y --ty raid1 -m 2 -n $lv1 -l 1 $vg
++lvconvert -y --splitmirrors 1 --trackchanges $vg/$lv1
++
++not lvconvert -y --ty striped -m 1 $vg/${lv1}_rimage_2
++not lvconvert -y --ty raid1 -m 1 $vg/${lv1}_rimage_2
++not lvconvert -y --ty mirror -m 1 $vg/${lv1}_rimage_2
++not lvconvert -y --ty cache-pool $vg/${lv1}_rimage_2
++not lvconvert -y --ty thin-pool $vg/${lv1}_rimage_2
++
++vgremove -ff $vg
+diff --git a/tools/lvconvert.c b/tools/lvconvert.c
+index 3fad02c..079c3cd 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -1165,6 +1165,36 @@ static int _lvconvert_validate_thin(struct logical_volume *lv,
+ 	return 0;
+ }
+ 
++/* Check for raid1 split trackchanges image to reject conversions on it. */
++static int _raid_split_image_conversion(struct logical_volume *lv)
++{
++	const char *s;
++
++	if (lv_is_raid_image(lv) &&
++	    (s = strstr(lv->name, "_rimage_"))) {
++		size_t len = s - lv->name;
++		char raidlv_name[len + 1];
++		const struct logical_volume *tmp_lv;
++
++		strncpy(raidlv_name, lv->name, len);
++		raidlv_name[len] = '\0';
++
++		if (!(tmp_lv = find_lv(lv->vg, raidlv_name))) {
++			log_error(INTERNAL_ERROR "Failed to find RaidLV of RAID subvolume %s.",
++				  display_lvname(lv));
++			return 1;
++		}
++
++		if (lv_is_raid_with_tracking(tmp_lv)) {
++			log_error("Conversion of tracked raid1 subvolume %s is not supported.",
++				  display_lvname(lv));
++			return 1;
++		}
++	}
++
++	return 0;
++}
++
+ /*
+  * _lvconvert_mirrors
+  *
+@@ -1180,6 +1210,9 @@ static int _lvconvert_mirrors(struct cmd_context *cmd,
+ 	uint32_t new_mimage_count = 0;
+ 	uint32_t new_log_count = 0;
+ 
++	if (_raid_split_image_conversion(lv))
++		return 0;
++
+ 	if ((lp->corelog || lp->mirrorlog) && *lp->type_str && strcmp(lp->type_str, SEG_TYPE_NAME_MIRROR)) {
+ 		log_error("--corelog and --mirrorlog are only compatible with mirror devices.");
+ 		return 0;
+@@ -1296,6 +1329,9 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
+ 	struct cmd_context *cmd = lv->vg->cmd;
+ 	struct lv_segment *seg = first_seg(lv);
+ 
++	if (_raid_split_image_conversion(lv))
++		return 0;
++
+ 	if (_linear_type_requested(lp->type_str)) {
+ 		if (arg_is_set(cmd, mirrors_ARG) && (arg_uint_value(cmd, mirrors_ARG, 0) != 0)) {
+ 			log_error("Cannot specify mirrors with linear type.");
+@@ -2579,6 +2615,9 @@ static int _lvconvert_to_thin_with_external(struct cmd_context *cmd,
+ 		.virtual_extents = lv->le_count,
+ 	};
+ 
++	if (_raid_split_image_conversion(lv))
++		return 0;
++
+ 	if (lv == thinpool_lv) {
+ 		log_error("Can't use same LV %s for thin pool and thin volume.",
+ 			  display_lvname(thinpool_lv));
+@@ -2888,6 +2927,9 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
+ 	struct id lockd_meta_id;
+ 	const char *str_seg_type = to_cachepool ? SEG_TYPE_NAME_CACHE_POOL : SEG_TYPE_NAME_THIN_POOL;
+ 
++	if (_raid_split_image_conversion(lv))
++		return 0;
++
+ 	if (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) {
+ 		log_error(INTERNAL_ERROR "LV %s is already a pool.", display_lvname(lv));
+ 		return 0;
+@@ -3339,6 +3381,9 @@ static int _lvconvert_to_cache_vol(struct cmd_context *cmd,
+ 	struct dm_config_tree *policy_settings = NULL;
+ 	int r = 0;
+ 
++	if (_raid_split_image_conversion(lv))
++		return 0;
++
+ 	/* If LV is inactive here, ensure it's not active elsewhere. */
+ 	if (!lockd_lv(cmd, lv, "ex", 0))
+ 		return_0;
diff --git a/SOURCES/lvm2-2_02_182-cache-drop-metadata_format-validation.patch b/SOURCES/lvm2-2_02_182-cache-drop-metadata_format-validation.patch
new file mode 100644
index 0000000..6c92fad
--- /dev/null
+++ b/SOURCES/lvm2-2_02_182-cache-drop-metadata_format-validation.patch
@@ -0,0 +1,36 @@
+ WHATS_NEW                  | 4 ++++
+ lib/metadata/cache_manip.c | 5 -----
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 546d3e6..17aff08 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,3 +1,7 @@
++Version 2.02.182 - 
++==============================
++  Do not pair cache policy and cache metadata format.
++
+ Version 2.02.181 - 
+ =================================
+   Reject conversions on raid1 LVs with split tracked SubLVs.
+diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
+index c15f117..8376bfb 100644
+--- a/lib/metadata/cache_manip.c
++++ b/lib/metadata/cache_manip.c
+@@ -843,15 +843,10 @@ int cache_set_metadata_format(struct lv_segment *seg, cache_metadata_format_t fo
+ 
+ 	/*
+ 	 * If policy is unselected, but format 2 is selected, policy smq is enforced.
+-	 * ATM no other then smq & cleaner policy is allowed to select format 2.
+ 	 */
+ 	if (!seg->policy_name) {
+ 		if (format == CACHE_METADATA_FORMAT_2)
+ 			seg->policy_name = "smq";
+-	} else if (strcmp(seg->policy_name, "smq") &&
+-		   strcmp(seg->policy_name, "cleaner")) {
+-		seg->cache_metadata_format = CACHE_METADATA_FORMAT_1;
+-		return 1;
+ 	}
+ 
+ 	/* Check if we need to search for configured cache metadata format */
diff --git a/SOURCES/lvm2-2_02_182-dmeventd-lvm2-plugin-uses-envvar-registry.patch b/SOURCES/lvm2-2_02_182-dmeventd-lvm2-plugin-uses-envvar-registry.patch
new file mode 100644
index 0000000..3d79e13
--- /dev/null
+++ b/SOURCES/lvm2-2_02_182-dmeventd-lvm2-plugin-uses-envvar-registry.patch
@@ -0,0 +1,131 @@
+From 41d8039e12ebad0727f8c7455ad9392bc61e6414 Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Mon, 27 Aug 2018 10:18:26 +0200
+Subject: [PATCH 1/2] dmeventd: lvm2 plugin uses envvar registry
+
+Thin plugin started to use configuble setting to allow to configure
+usage of external scripts - however to read this value it needed to
+execute internal command as dmeventd itself has no access to lvm.conf
+and the API for dmeventd plugin has been kept stable.
+
+The call of command itself was not normally 'a big issue' until users
+started to use higher number of monitored LVs and execution of command
+got stuck because other monitored resource already started to execute
+some other lvm2 command and become blocked waiting on VG lock.
+
+This scenario revealed necesity to somehow avoid calling lvm2 command
+during resource registration - but this requires bigger changes - so
+meanwhile this patch tries to minimize the possibility to hit this race
+by obtaining any configurable setting just once - such patch is small
+and covers majority of problem - yet better solution needs to be
+introduced likely with bigger rework of dmeventd.
+
+TODO: Avoid blocking registration of resource with execution of lvm2
+commands since those can get stuck waiting on mutexes.
+
+(cherry picked from commit a8d59404f7713ae4f9a3b172dd560ed1364d8bee)
+
+Conflicts:
+	WHATS_NEW_DM
+---
+ WHATS_NEW_DM                                 |  4 +++
+ daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c | 49 +++++++++++++++++++++-------
+ 2 files changed, 42 insertions(+), 11 deletions(-)
+
+diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
+index c42ee17..42cf2a8 100644
+--- a/WHATS_NEW_DM
++++ b/WHATS_NEW_DM
+@@ -1,3 +1,7 @@
++Version 1.02.151 - 
++==============================
++  Add hot fix to avoiding locking collision when monitoring thin-pools.
++
+ Version 1.02.150 - 
+ =================================
+   Add vdo plugin for monitoring VDO devices.
+diff --git a/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c b/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
+index 930f9fc..5be11f1 100644
+--- a/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
++++ b/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
+@@ -31,6 +31,13 @@ static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static int _register_count = 0;
+ static struct dm_pool *_mem_pool = NULL;
+ static void *_lvm_handle = NULL;
++static DM_LIST_INIT(_env_registry);
++
++struct env_data {
++	struct dm_list list;
++	const char *cmd;
++	const char *data;
++};
+ 
+ DM_EVENT_LOG_FN("#lvm")
+ 
+@@ -100,6 +107,7 @@ void dmeventd_lvm2_exit(void)
+ 		lvm2_run(_lvm_handle, "_memlock_dec");
+ 		dm_pool_destroy(_mem_pool);
+ 		_mem_pool = NULL;
++		dm_list_init(&_env_registry);
+ 		lvm2_exit(_lvm_handle);
+ 		_lvm_handle = NULL;
+ 		log_debug("lvm plugin exited.");
+@@ -124,6 +132,8 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
+ 	static char _internal_prefix[] =  "_dmeventd_";
+ 	char *vg = NULL, *lv = NULL, *layer;
+ 	int r;
++	struct env_data *env_data;
++	const char *env = NULL;
+ 
+ 	if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) {
+ 		log_error("Unable to determine VG name from %s.",
+@@ -137,18 +147,35 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
+ 		*layer = '\0';
+ 
+ 	if (!strncmp(cmd, _internal_prefix, sizeof(_internal_prefix) - 1)) {
+-		dmeventd_lvm2_lock();
+-		/* output of internal command passed via env var */
+-		if (!dmeventd_lvm2_run(cmd))
+-			cmd = NULL;
+-		else if ((cmd = getenv(cmd)))
+-			cmd = dm_pool_strdup(mem, cmd); /* copy with lock */
+-		dmeventd_lvm2_unlock();
+-
+-		if (!cmd) {
+-			log_error("Unable to find configured command.");
+-			return 0;
++		/* check if ENVVAR wasn't already resolved */
++		dm_list_iterate_items(env_data, &_env_registry)
++			if (!strcmp(cmd, env_data->cmd)) {
++				env = env_data->data;
++				break;
++			}
++
++		if (!env) {
++			/* run lvm2 command to find out setting value */
++			dmeventd_lvm2_lock();
++			if (!dmeventd_lvm2_run(cmd) ||
++			    !(env = getenv(cmd))) {
++				log_error("Unable to find configured command.");
++				return 0;
++			}
++			/* output of internal command passed via env var */
++			env = dm_pool_strdup(_mem_pool, env); /* copy with lock */
++			dmeventd_lvm2_unlock();
++			if (!env ||
++			    !(env_data = dm_pool_zalloc(_mem_pool, sizeof(*env_data))) ||
++			    !(env_data->cmd = dm_pool_strdup(_mem_pool, cmd))) {
++				log_error("Unable to allocate env memory.");
++				return 0;
++			}
++			env_data->data = env;
++			/* add to ENVVAR registry */
++			dm_list_add(&_env_registry, &env_data->list);
+ 		}
++		cmd = env;
+ 	}
+ 
+ 	r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_182-lvconvert-avoid-superfluous-interim-raid-type.patch b/SOURCES/lvm2-2_02_182-lvconvert-avoid-superfluous-interim-raid-type.patch
new file mode 100644
index 0000000..7da9388
--- /dev/null
+++ b/SOURCES/lvm2-2_02_182-lvconvert-avoid-superfluous-interim-raid-type.patch
@@ -0,0 +1,45 @@
+From c43515c7ba1d13d54c92d43b76ca0a661c097292 Mon Sep 17 00:00:00 2001
+From: Heinz Mauelshagen <heinzm@redhat.com>
+Date: Fri, 31 Aug 2018 19:03:52 +0200
+Subject: [PATCH] lvconvert: avoid superfluous interim raid type
+
+When converting striped/raid0*/raid6_n_6 <-> raid4,
+avoid superfluous interim raid5_n layout.
+
+Related: rhbz1447809
+(cherry picked from commit 22a13043683a5647e8cc4e3aead911e5269ffd2f)
+(cherry picked from commit 0e03c686191b036a7cd6e570888793ddbdd5f958)
+---
+ lib/metadata/raid_manip.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
+index d3e3a20..3eee77a 100644
+--- a/lib/metadata/raid_manip.c
++++ b/lib/metadata/raid_manip.c
+@@ -6140,7 +6140,7 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 			seg_flag = SEG_RAID6_N_6;
+ 
+ 		if (segtype_is_linear(*segtype) ||
+-		    (!segtype_is_raid10(*segtype) && !segtype_is_striped(*segtype)))
++		    (!segtype_is_raid4(*segtype) && !segtype_is_raid10(*segtype) && !segtype_is_striped(*segtype)))
+ 			seg_flag = SEG_RAID5_N;
+ 
+ 	/* raid1 -> */
+@@ -6209,10 +6209,9 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 					  lvseg_name(seg_from), display_lvname(seg_from->lv), *new_image_count);
+ 		}
+ 
+-	/* raid4 -> !raid4/raid5* */
+-	} else if (seg_is_raid4(seg_from) &&
+-		   !segtype_is_raid4(*segtype) && !segtype_is_any_raid5(*segtype)) {
+-		seg_flag = SEG_RAID5_N;
++	/* raid4 -> * */
++	} else if (seg_is_raid4(seg_from) && !segtype_is_raid4(*segtype) && !segtype_is_striped(*segtype)) {
++		seg_flag = segtype_is_any_raid6(*segtype) ? SEG_RAID6_N_6 : SEG_RAID5_N;
+ 
+ 	/* raid6 -> striped/raid0/raid5/raid10 */
+ 	} else if (seg_is_any_raid6(seg_from)) {
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_182-lvconvert-fix-conversion-attempts-to-linear.patch b/SOURCES/lvm2-2_02_182-lvconvert-fix-conversion-attempts-to-linear.patch
new file mode 100644
index 0000000..9c1b7d1
--- /dev/null
+++ b/SOURCES/lvm2-2_02_182-lvconvert-fix-conversion-attempts-to-linear.patch
@@ -0,0 +1,268 @@
+From 83b93f9f5a72ac67f63e6be2c25ce4b3919c4c84 Mon Sep 17 00:00:00 2001
+From: Heinz Mauelshagen <heinzm@redhat.com>
+Date: Wed, 22 Aug 2018 16:39:36 +0200
+Subject: [PATCH] lvconvert: fix conversion attempts to linear
+
+"lvconvert --type linear RaidLV" on striped and raid4/5/6/10
+have to provide the convenient interim layouts.  Fix involves
+a cleanup to the convenience type function.
+
+As a result of testing, add missing sync waits to
+lvconvert-raid-reshape-linear_to_raid6-single-type.sh.
+
+Resolves: rhbz1447809
+(cherry picked from commit e83c4f07ca4a84808178d5d22cba655e5e370cd8)
+
+Conflicts:
+	WHATS_NEW
+
+(cherry picked from commit d910f75d89e02e46cd16f9ddbc8e8358c3c2efd3)
+---
+ WHATS_NEW                                          |   1 +
+ lib/metadata/raid_manip.c                          | 145 +++++++++------------
+ ...ert-raid-reshape-linear_to_raid6-single-type.sh |   2 +
+ 3 files changed, 68 insertions(+), 80 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index e3eee56..92e5c04 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,6 @@
+ Version 2.02.182 - 
+ ==============================
++  Fix lvconvert conversion attempts to linear.
+   Fix lvconvert raid0/raid0_meta -> striped regression.
+   Fix lvconvert --splitmirror for mirror type (2.02.178).
+   Do not pair cache policy and cache metadata format.
+diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
+index 804f78b..d3e3a20 100644
+--- a/lib/metadata/raid_manip.c
++++ b/lib/metadata/raid_manip.c
+@@ -6120,8 +6120,7 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 	const struct segment_type *segtype_sav = *segtype;
+ 
+ 	/* Linear -> striped request */
+-	if (seg_is_striped(seg_from) &&
+-	    seg_from->area_count == 1 &&
++	if (seg_is_linear(seg_from) &&
+ 	    segtype_is_striped(*segtype))
+ 		;
+ 	/* Bail out if same RAID level is requested. */
+@@ -6130,24 +6129,20 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 
+ 	log_debug("Checking LV %s requested %s segment type for convenience",
+ 		  display_lvname(seg_from->lv), (*segtype)->name);
+-	/* striped/raid0 -> raid5/6 */
+-	if (seg_is_striped(seg_from) || seg_is_any_raid0(seg_from)) {
+-		/* linear -> raid*, interim/first conversion is to raid1 */
+-		if (seg_from->area_count == 1)
+-			seg_flag = SEG_RAID1;
+-
+-		else if (seg_is_any_raid0(seg_from) && segtype_is_striped(*segtype))
+-			;
+-
+-		/* If this is any raid5 conversion request -> enforce raid5_n, because we convert from striped */
+-		else if (((segtype_is_striped(*segtype) && !segtype_is_any_raid0(*segtype)) || segtype_is_any_raid5(*segtype)) &&
+-			 !segtype_is_raid5_n(*segtype))
+-			seg_flag = SEG_RAID5_N;
+ 
+-		/* If this is any raid6 conversion request -> enforce raid6_n_6, because we convert from striped */
+-		else if (segtype_is_any_raid6(*segtype) && !segtype_is_raid6_n_6(*segtype))
++	/* linear -> */
++	if (seg_is_linear(seg_from)) {
++		seg_flag = SEG_RAID1;
++
++	/* striped/raid0 -> */
++	} else if (seg_is_striped(seg_from) || seg_is_any_raid0(seg_from)) {
++		if (segtype_is_any_raid6(*segtype))
+ 			seg_flag = SEG_RAID6_N_6;
+ 
++		if (segtype_is_linear(*segtype) ||
++		    (!segtype_is_raid10(*segtype) && !segtype_is_striped(*segtype)))
++			seg_flag = SEG_RAID5_N;
++
+ 	/* raid1 -> */
+ 	} else if (seg_is_raid1(seg_from) && !segtype_is_mirror(*segtype)) {
+ 		if (seg_from->area_count != 2) {
+@@ -6157,85 +6152,68 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 		}
+ 
+ 		if (segtype_is_striped(*segtype) ||
+-			   segtype_is_any_raid0(*segtype) ||
+-			   segtype_is_raid10(*segtype))
++		    segtype_is_any_raid0(*segtype) ||
++		    segtype_is_raid10(*segtype))
+ 			seg_flag = SEG_RAID5_N;
+ 
+ 		else if (!segtype_is_raid4(*segtype) && !segtype_is_any_raid5(*segtype))
+ 			seg_flag = SEG_RAID5_LS;
+ 
+-	/* raid4/raid5 -> striped/raid0/raid1/raid6/raid10 */
+-	} else if (seg_is_raid4(seg_from) || seg_is_any_raid5(seg_from)) {
+-		if ((segtype_is_raid1(*segtype) || segtype_is_linear(*segtype)) && seg_is_raid5_n(seg_from)) {
++	/* raid5* -> */
++	} else if (seg_is_any_raid5(seg_from)) {
++		if (segtype_is_raid1(*segtype) || segtype_is_linear(*segtype)) {
+ 			if (seg_from->area_count != 2) {
+ 				log_error("Converting %s LV %s to 2 stripes first.",
+ 					  lvseg_name(seg_from), display_lvname(seg_from->lv));
+ 				*new_image_count = 2;
+-				seg_flag = SEG_RAID5_N;
++				*segtype = seg_from->segtype;
++				seg_flag = 0;
+ 			} else
+ 				seg_flag = SEG_RAID1;
+ 
+-		} else if (segtype_is_raid1(*segtype) && seg_from->area_count != 2) {
+-			log_error("Convert %s LV %s to 2 stripes first (i.e. --stripes 1).",
+-				  lvseg_name(seg_from), display_lvname(seg_from->lv));
+-			return 0;
+-
+-		} else if (seg_is_raid4(seg_from) &&
+-		         (segtype_is_linear(*segtype) || segtype_is_any_raid5(*segtype)) &&
+-			 !segtype_is_raid5_n(*segtype))
+-			seg_flag = SEG_RAID5_N;
++		} else if (segtype_is_any_raid6(*segtype)) {
++			if (seg_from->area_count < 4) {
++				if (*stripes > 3)
++					*new_image_count = *stripes + seg_from->segtype->parity_devs;
++				else
++					*new_image_count = 4;
+ 
+-		else if (seg_is_raid5_n(seg_from) && seg_from->area_count == 2) {
+-			if (*stripes >= 2) {
++				*segtype = seg_from->segtype;
+ 				log_error("Converting %s LV %s to %u stripes first.",
+-					  lvseg_name(seg_from), display_lvname(seg_from->lv), *stripes);
++					  lvseg_name(seg_from), display_lvname(seg_from->lv), *new_image_count);
++
++			} else
++				seg_flag = _raid_seg_flag_5_to_6(seg_from);
++
++		} else if (segtype_is_striped(*segtype) || segtype_is_raid10(*segtype)) {
++			int change = 0;
++
++			if (!seg_is_raid5_n(seg_from)) {
++				seg_flag = SEG_RAID5_N;
++
++			} else if (*stripes > 2 && *stripes != seg_from->area_count - seg_from->segtype->parity_devs) {
++				change = 1;
+ 				*new_image_count = *stripes + seg_from->segtype->parity_devs;
+ 				seg_flag = SEG_RAID5_N;
+-			} else {
+-				log_error("Convert %s LV %s to minimum 3 stripes first (i.e. --stripes 2).",
+-					  lvseg_name(seg_from), display_lvname(seg_from->lv));
+-				return 0;
+-			}
+-		} else if (seg_is_any_raid5(seg_from) &&
+-		         (segtype_is_linear(*segtype) || segtype_is_raid4(*segtype)) &&
+-			 !segtype_is_raid5_n(*segtype))
+-			seg_flag = SEG_RAID5_N;
+ 
+-		else if (segtype_is_raid10(*segtype)) {
+-			if (seg_from->area_count < 3) {
+-				if (*stripes >= 2) {
+-					log_error("Converting %s LV %s to %u stripes first.",
+-						  lvseg_name(seg_from), display_lvname(seg_from->lv), *stripes);
+-					*new_image_count = *stripes + seg_from->segtype->parity_devs;
+-					seg_flag = SEG_RAID5_N;
+-				} else {
+-					log_error("Convert %s LV %s to minimum 3 stripes first (i.e. --stripes 2).",
+-						  lvseg_name(seg_from), display_lvname(seg_from->lv));
+-					return 0;
+-				}
+-			} else
+-				seg_flag = seg_is_raid5_n(seg_from) ? SEG_RAID0_META : SEG_RAID5_N;
++			} else if (seg_from->area_count < 3) {
++				change = 1;
++				*new_image_count = 3;
++				seg_flag = SEG_RAID5_N;
+ 
+-		} else if (segtype_is_any_raid6(*segtype)) {
+-			if (seg_from->area_count < 4 &&
+-			    seg_is_any_raid5(seg_from)) {
+-				if (*stripes >= 3) {
+-					log_error("Converting %s LV %s to %u stripes first.",
+-						  lvseg_name(seg_from), display_lvname(seg_from->lv), *stripes);
+-					*new_image_count = *stripes + seg_from->segtype->parity_devs;
+-					seg_flag = SEG_RAID5_LS;
+-				} else {
+-					log_error("Convert %s LV %s to minimum 4 stripes first (i.e. --stripes 3).",
+-						  lvseg_name(seg_from), display_lvname(seg_from->lv));
+-					return 0;
+-				}
++			} else if (!segtype_is_striped(*segtype))
++				seg_flag = SEG_RAID0_META;
+ 
+-			} else if (seg_is_raid4(seg_from) && !segtype_is_raid6_n_6(*segtype))
+-				seg_flag = SEG_RAID6_N_6;
+-			else
+-				seg_flag = _raid_seg_flag_5_to_6(seg_from);
++			if (change)
++				log_error("Converting %s LV %s to %u stripes first.",
++					  lvseg_name(seg_from), display_lvname(seg_from->lv), *new_image_count);
+ 		}
+ 
++	/* raid4 -> !raid4/raid5* */
++	} else if (seg_is_raid4(seg_from) &&
++		   !segtype_is_raid4(*segtype) && !segtype_is_any_raid5(*segtype)) {
++		seg_flag = SEG_RAID5_N;
++
+ 	/* raid6 -> striped/raid0/raid5/raid10 */
+ 	} else if (seg_is_any_raid6(seg_from)) {
+ 		if (segtype_is_raid1(*segtype)) {
+@@ -6247,6 +6225,9 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 		} else if (segtype_is_any_raid10(*segtype)) {
+ 			seg_flag = seg_is_raid6_n_6(seg_from) ? SEG_RAID0_META : SEG_RAID6_N_6;
+ 
++		} else if (segtype_is_linear(*segtype)) {
++			seg_flag = seg_is_raid6_n_6(seg_from) ? SEG_RAID5_N : SEG_RAID6_N_6;
++
+ 		} else if (segtype_is_striped(*segtype) || segtype_is_any_raid0(*segtype)) {
+ 			if (!seg_is_raid6_n_6(seg_from))
+ 				seg_flag = SEG_RAID6_N_6;
+@@ -6277,12 +6258,16 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 			return 0;
+ 		}
+ 
+-	/* raid10 -> ... */
+-	} else if (seg_is_raid10(seg_from) &&
+-		   !segtype_is_striped(*segtype) &&
+-		   !segtype_is_any_raid0(*segtype))
+-		seg_flag = SEG_RAID0_META;
++	} else if (seg_is_raid10(seg_from)) {
++		if (segtype_is_linear(*segtype) ||
++		    (!segtype_is_striped(*segtype) &&
++		    !segtype_is_any_raid0(*segtype))) {
++			seg_flag = SEG_RAID0_META;
++		}
++	}
+ 
++
++	/* raid10 -> ... */
+ 	if (seg_flag) {
+ 		if (!(*segtype = get_segtype_from_flag(cmd, seg_flag)))
+ 			return_0;
+diff --git a/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh b/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh
+index f01e7ef..05cb616 100644
+--- a/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh
++++ b/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh
+@@ -78,6 +78,7 @@ check lv_first_seg_field $vg/$lv data_stripes 3
+ check lv_first_seg_field $vg/$lv stripesize "64.00k"
+ check lv_first_seg_field $vg/$lv regionsize "128.00k"
+ check lv_first_seg_field $vg/$lv reshape_len_le 0
++aux wait_for_sync $vg $lv
+ 
+ # Convert raid6_ls_6 -> raid6(_zr) (reshape)
+ lvconvert -y --type raid6 --stripes 3 --stripesize 64K --regionsize 128K $vg/$lv
+@@ -88,6 +89,7 @@ check lv_first_seg_field $vg/$lv data_stripes 3
+ check lv_first_seg_field $vg/$lv stripesize "64.00k"
+ check lv_first_seg_field $vg/$lv regionsize "128.00k"
+ check lv_first_seg_field $vg/$lv reshape_len_le 10
++aux wait_for_sync $vg $lv
+ 
+ # Remove reshape space
+ lvconvert -y --type raid6 --stripes 3 --stripesize 64K --regionsize 128K $vg/$lv
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_182-lvconvert-fix-direct-raid0-to-striped-conversion.patch b/SOURCES/lvm2-2_02_182-lvconvert-fix-direct-raid0-to-striped-conversion.patch
new file mode 100644
index 0000000..c07dcaa
--- /dev/null
+++ b/SOURCES/lvm2-2_02_182-lvconvert-fix-direct-raid0-to-striped-conversion.patch
@@ -0,0 +1,62 @@
+ WHATS_NEW                             |  1 +
+ lib/metadata/raid_manip.c             |  3 +++
+ test/shell/lvconvert-raid0-striped.sh | 25 +++++++++++++++++++++++++
+ 3 files changed, 29 insertions(+)
+ create mode 100644 test/shell/lvconvert-raid0-striped.sh
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 6560357..e3eee56 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,6 @@
+ Version 2.02.182 - 
+ ==============================
++  Fix lvconvert raid0/raid0_meta -> striped regression.
+   Fix lvconvert --splitmirror for mirror type (2.02.178).
+   Do not pair cache policy and cache metadata format.
+ 
+diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
+index 705a7f9..804f78b 100644
+--- a/lib/metadata/raid_manip.c
++++ b/lib/metadata/raid_manip.c
+@@ -6136,6 +6136,9 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 		if (seg_from->area_count == 1)
+ 			seg_flag = SEG_RAID1;
+ 
++		else if (seg_is_any_raid0(seg_from) && segtype_is_striped(*segtype))
++			;
++
+ 		/* If this is any raid5 conversion request -> enforce raid5_n, because we convert from striped */
+ 		else if (((segtype_is_striped(*segtype) && !segtype_is_any_raid0(*segtype)) || segtype_is_any_raid5(*segtype)) &&
+ 			 !segtype_is_raid5_n(*segtype))
+diff --git a/test/shell/lvconvert-raid0-striped.sh b/test/shell/lvconvert-raid0-striped.sh
+new file mode 100644
+index 0000000..4521b34
+--- /dev/null
++++ b/test/shell/lvconvert-raid0-striped.sh
+@@ -0,0 +1,25 @@
++#!/usr/bin/env bash
++
++# Copyright (C) 2018 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_LVMPOLLD=1
++
++. lib/inittest
++
++aux have_raid 1 7 0 || skip
++
++aux prepare_vg 3 16
++
++lvcreate -aey --type raid0 -i 3 -l3 -n $lv $vg
++lvconvert -y --type striped $vg/$lv
++check lv_field $vg/$lv segtype "striped"
++vgremove -ff $vg
diff --git a/SOURCES/lvm2-2_02_182-lvconvert-fix-interim-segtype-regression-on-raid6-co.patch b/SOURCES/lvm2-2_02_182-lvconvert-fix-interim-segtype-regression-on-raid6-co.patch
new file mode 100644
index 0000000..32ad471
--- /dev/null
+++ b/SOURCES/lvm2-2_02_182-lvconvert-fix-interim-segtype-regression-on-raid6-co.patch
@@ -0,0 +1,93 @@
+From 2ee0f6d4ddd6c602def295e3b1dfccbd8a50a4c8 Mon Sep 17 00:00:00 2001
+From: Heinz Mauelshagen <heinzm@redhat.com>
+Date: Fri, 7 Sep 2018 13:48:13 +0200
+Subject: [PATCH] lvconvert: fix interim segtype regression on raid6
+ conversions
+
+When converting from striped/raid0/raid0_meta
+to raid6 with > 2 stripes, allow possible
+direct conversion (to raid6_n_6).
+
+In case of 2 stripes, first convert to raid5_n to restripe
+to at least 3 data stripes (the raid6 minimum in lvm2) in
+a second conversion before finally converting to raid6_n_6.
+
+As before, raid6_n_6 then can be converted
+to any other raid6 layout.
+
+Enhance lvconvert-raid-takeover.sh to test the
+2 stripes conversions to raid6.
+
+Resolves: rhbz1624038
+(cherry picked from commit e2e30a64ab10602951443dfbd3481bd6b32f5459)
+
+Conflicts:
+	WHATS_NEW
+
+(cherry picked from commit c26bde42af0930bef2cee95c76951285d801ba70)
+---
+ WHATS_NEW                             |  1 +
+ lib/metadata/raid_manip.c             |  6 +++---
+ test/shell/lvconvert-raid-takeover.sh | 16 ++++++++++++----
+ 3 files changed, 16 insertions(+), 7 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 9da40b6..d8a24b0 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,6 @@
+ Version 2.02.182 - 
+ ==============================
++  Fix lvconvert striped/raid0/raid0_meta -> raid6 regression.
+   Add After=rbdmap.service to {lvm2-activation-net,blk-availability}.service.
+   Fix lvconvert conversion attempts to linear.
+   Fix lvconvert raid0/raid0_meta -> striped regression.
+diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
+index 3eee77a..cb7202a 100644
+--- a/lib/metadata/raid_manip.c
++++ b/lib/metadata/raid_manip.c
+@@ -6137,10 +6137,10 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 	/* striped/raid0 -> */
+ 	} else if (seg_is_striped(seg_from) || seg_is_any_raid0(seg_from)) {
+ 		if (segtype_is_any_raid6(*segtype))
+-			seg_flag = SEG_RAID6_N_6;
++			seg_flag = seg_from->area_count < 3 ? SEG_RAID5_N : SEG_RAID6_N_6;
+ 
+-		if (segtype_is_linear(*segtype) ||
+-		    (!segtype_is_raid4(*segtype) && !segtype_is_raid10(*segtype) && !segtype_is_striped(*segtype)))
++		else if (segtype_is_linear(*segtype) ||
++			 (!segtype_is_raid4(*segtype) && !segtype_is_raid10(*segtype) && !segtype_is_striped(*segtype)))
+ 			seg_flag = SEG_RAID5_N;
+ 
+ 	/* raid1 -> */
+diff --git a/test/shell/lvconvert-raid-takeover.sh b/test/shell/lvconvert-raid-takeover.sh
+index d1c5d30..d22c11b 100644
+--- a/test/shell/lvconvert-raid-takeover.sh
++++ b/test/shell/lvconvert-raid-takeover.sh
+@@ -108,11 +108,19 @@ function _invalid_raid5_conversions
+ 	not _lvconvert raid6 raid6_n_6 4 6 $vg $lv1
+ }
+ 
+-# Check raid6 conversion constrainst of minimum 3 stripes
+-_lvcreate striped 2 2 4m $vg $lv1
+-not _lvconvert raid6 raid6_n_6 2 4 $vg $lv1
+-lvremove -y $vg
++# Check raid6 conversion constrainst for 2 stripes
++for type in striped raid0 raid0_meta
++do
++   _lvcreate $type 2 2 4m $vg $lv1
++   not _lvconvert raid6 raid6_n_6 2 4 $vg $lv1
++   _lvconvert raid6 raid5_n 2 3 $vg $lv1
++   _lvconvert raid6 raid5_n 3 4 $vg $lv1
++   _lvconvert raid6 raid6_n_6 3 5 $vg $lv1
++   lvremove -y $vg
++done
+ 
++
++# Check raid6 conversion constrainst of minimum 3 stripes
+ _lvcreate raid0 3 3 4m $vg $lv1
+ _lvconvert raid6 raid6_n_6 3 5 $vg $lv1
+ lvremove -y $vg
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_182-mirror-fix-splitmirrors-for-mirror-type.patch b/SOURCES/lvm2-2_02_182-mirror-fix-splitmirrors-for-mirror-type.patch
new file mode 100644
index 0000000..9c2e3ea
--- /dev/null
+++ b/SOURCES/lvm2-2_02_182-mirror-fix-splitmirrors-for-mirror-type.patch
@@ -0,0 +1,45 @@
+ WHATS_NEW               | 1 +
+ lib/activate/activate.c | 5 +++++
+ lib/metadata/mirror.c   | 2 +-
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 17aff08..6560357 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,6 @@
+ Version 2.02.182 - 
+ ==============================
++  Fix lvconvert --splitmirror for mirror type (2.02.178).
+   Do not pair cache policy and cache metadata format.
+ 
+ Version 2.02.181 - 
+diff --git a/lib/activate/activate.c b/lib/activate/activate.c
+index e38ab03..16704f6 100644
+--- a/lib/activate/activate.c
++++ b/lib/activate/activate.c
+@@ -2125,6 +2125,11 @@ static int _preload_detached_lv(struct logical_volume *lv, void *data)
+ 		    !lv_is_raid_metadata(lv_pre) && lv_is_active(lv) &&
+ 		    !_lv_preload(lv_pre, detached->laopts, detached->flush_required))
+ 			return_0;
++	} else if (lv_is_mirror_image(lv)) {
++		if ((lv_pre = find_lv_in_vg_by_lvid(detached->lv_pre->vg, &lv->lvid)) &&
++		    !lv_is_mirror_image(lv_pre) && lv_is_active(lv) &&
++		    !_lv_preload(lv_pre, detached->laopts, detached->flush_required))
++			return_0;
+ 	}
+ 
+ 	if (!lv_is_visible(lv) && (lv_pre = find_lv(detached->lv_pre->vg, lv->name)) &&
+diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
+index 7f38d4f..c7d8a9e 100644
+--- a/lib/metadata/mirror.c
++++ b/lib/metadata/mirror.c
+@@ -786,7 +786,7 @@ static int _split_mirror_images(struct logical_volume *lv,
+ 
+ 	act = lv_is_active(lv_lock_holder(lv));
+ 
+-	if (act && !_activate_lv_like_model(lv, new_lv)) {
++	if (act && (!deactivate_lv(cmd, new_lv) || !_activate_lv_like_model(lv, new_lv))) {
+ 		log_error("Failed to rename newly split LV in the kernel");
+ 		return 0;
+ 	}
diff --git a/SOURCES/lvm2-2_02_182-mirrors-fix-read_only_volume_list.patch b/SOURCES/lvm2-2_02_182-mirrors-fix-read_only_volume_list.patch
new file mode 100644
index 0000000..885d995
--- /dev/null
+++ b/SOURCES/lvm2-2_02_182-mirrors-fix-read_only_volume_list.patch
@@ -0,0 +1,16 @@
+ lib/activate/activate.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/lib/activate/activate.c b/lib/activate/activate.c
+index 18f4b84..e38ab03 100644
+--- a/lib/activate/activate.c
++++ b/lib/activate/activate.c
+@@ -1864,6 +1864,8 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
+ 
+ 	if (!laopts)
+ 		laopts = &zlaopts;
++	else
++		mirr_laopts.read_only = laopts->read_only;
+ 
+ 	/* skip dmeventd code altogether */
+ 	if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
diff --git a/SOURCES/lvm2-2_02_182-scripts-add-After-rbdmap.service-to-lvm2-activation.patch b/SOURCES/lvm2-2_02_182-scripts-add-After-rbdmap.service-to-lvm2-activation.patch
new file mode 100644
index 0000000..cc2f209
--- /dev/null
+++ b/SOURCES/lvm2-2_02_182-scripts-add-After-rbdmap.service-to-lvm2-activation.patch
@@ -0,0 +1,73 @@
+From 4484518f67dd41151571e0841ef13134abe39408 Mon Sep 17 00:00:00 2001
+From: Peter Rajnoha <prajnoha@redhat.com>
+Date: Thu, 30 Aug 2018 12:35:58 +0200
+Subject: [PATCH 2/2] scripts: add After=rbdmap.service to
+ {lvm2-activation-net,blk-availability}.service
+
+We need to have Ceph RBD devices mapped first before use in a stack
+where LVM is on top so make sure rbdmap.service is called before
+generated lvm2-activation-net.service.
+
+On shutdown, we need to stop blk-availability first before we stop the
+rbdmap.service.
+
+Resolves: rhbz1623479
+(cherry picked from commit cb17ef221bdefea3625a22c19c6d8f5504441771)
+
+Conflicts:
+	WHATS_NEW
+
+(cherry picked from commit 3374a592502ef099d38491b0c2020a6945d825b1)
+
+Conflicts:
+	WHATS_NEW
+---
+ WHATS_NEW                                           | 2 ++
+ scripts/blk_availability_systemd_red_hat.service.in | 2 +-
+ scripts/lvm2_activation_generator_systemd_red_hat.c | 2 +-
+ 3 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 92e5c04..9da40b6 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,9 +1,11 @@
+ Version 2.02.182 - 
+ ==============================
++  Add After=rbdmap.service to {lvm2-activation-net,blk-availability}.service.
+   Fix lvconvert conversion attempts to linear.
+   Fix lvconvert raid0/raid0_meta -> striped regression.
+   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.
+ 
+ Version 2.02.181 - 
+ =================================
+diff --git a/scripts/blk_availability_systemd_red_hat.service.in b/scripts/blk_availability_systemd_red_hat.service.in
+index 1198baa..9462072 100644
+--- a/scripts/blk_availability_systemd_red_hat.service.in
++++ b/scripts/blk_availability_systemd_red_hat.service.in
+@@ -1,6 +1,6 @@
+ [Unit]
+ Description=Availability of block devices
+-After=lvm2-activation.service lvm2-lvmetad.service iscsi-shutdown.service iscsi.service iscsid.service fcoe.service
++After=lvm2-activation.service lvm2-lvmetad.service iscsi-shutdown.service iscsi.service iscsid.service fcoe.service rbdmap.service
+ DefaultDependencies=no
+ Conflicts=shutdown.target
+ 
+diff --git a/scripts/lvm2_activation_generator_systemd_red_hat.c b/scripts/lvm2_activation_generator_systemd_red_hat.c
+index 0f7f89c..487582f 100644
+--- a/scripts/lvm2_activation_generator_systemd_red_hat.c
++++ b/scripts/lvm2_activation_generator_systemd_red_hat.c
+@@ -128,7 +128,7 @@ static int generate_unit(const char *dir, int unit, int sysinit_needed)
+ 	      "DefaultDependencies=no\n", f);
+ 
+ 	if (unit == UNIT_NET) {
+-		fprintf(f, "After=%s iscsi.service fcoe.service\n"
++		fprintf(f, "After=%s iscsi.service fcoe.service rbdmap.service\n"
+ 			"Before=remote-fs-pre.target shutdown.target\n\n"
+ 			"[Service]\n"
+ 			"ExecStartPre=/usr/bin/udevadm settle\n", unit_names[UNIT_MAIN]);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_182-vgcreate-close-exclusive-fd-after-pvcreate.patch b/SOURCES/lvm2-2_02_182-vgcreate-close-exclusive-fd-after-pvcreate.patch
new file mode 100644
index 0000000..7a7e060
--- /dev/null
+++ b/SOURCES/lvm2-2_02_182-vgcreate-close-exclusive-fd-after-pvcreate.patch
@@ -0,0 +1,53 @@
+ lib/label/label.c | 6 +++---
+ tools/toollib.c   | 7 +++++++
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/lib/label/label.c b/lib/label/label.c
+index ac37713..bafa543 100644
+--- a/lib/label/label.c
++++ b/lib/label/label.c
+@@ -1190,7 +1190,7 @@ bool dev_write_bytes(struct device *dev, uint64_t start, size_t len, void *data)
+ 		return false;
+ 	}
+ 
+-	if (!(dev->flags & DEV_BCACHE_WRITE)) {
++	if (_in_bcache(dev) && !(dev->flags & DEV_BCACHE_WRITE)) {
+ 		/* FIXME: avoid tossing out bcache blocks just to replace fd. */
+ 		log_debug("Close and reopen to write %s", dev_name(dev));
+ 		bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+@@ -1236,7 +1236,7 @@ bool dev_write_zeros(struct device *dev, uint64_t start, size_t len)
+ 		return false;
+ 	}
+ 
+-	if (!(dev->flags & DEV_BCACHE_WRITE)) {
++	if (_in_bcache(dev) && !(dev->flags & DEV_BCACHE_WRITE)) {
+ 		/* FIXME: avoid tossing out bcache blocks just to replace fd. */
+ 		log_debug("Close and reopen to write %s", dev_name(dev));
+ 		bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+@@ -1282,7 +1282,7 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val)
+ 		return false;
+ 	}
+ 
+-	if (!(dev->flags & DEV_BCACHE_WRITE)) {
++	if (_in_bcache(dev) && !(dev->flags & DEV_BCACHE_WRITE)) {
+ 		/* FIXME: avoid tossing out bcache blocks just to replace fd. */
+ 		log_debug("Close and reopen to write %s", dev_name(dev));
+ 		bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+diff --git a/tools/toollib.c b/tools/toollib.c
+index b60ff06..e1c86f9 100644
+--- a/tools/toollib.c
++++ b/tools/toollib.c
+@@ -5897,6 +5897,13 @@ do_command:
+ 					pd->name);
+ 	}
+ 
++	/*
++	 * Don't keep devs open excl in bcache because the excl will prevent
++	 * using that dev elsewhere.
++	 */
++	dm_list_iterate_items(devl, &rescan_devs)
++		label_scan_invalidate(devl->dev);
++
+ 	dm_list_iterate_items(pd, &pp->arg_fail)
+ 		log_debug("%s: command failed for %s.",
+ 			  cmd->command->name, pd->name);
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
index 29677e4..0c7a0b0 100644
--- 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
@@ -1,13 +1,13 @@
  configure             | 20 ++++++++++----------
- configure.in          |  4 ++--
+ configure.ac          |  4 ++--
  lib/device/dev-type.c |  3 +--
  3 files changed, 13 insertions(+), 14 deletions(-)
 
 diff --git a/configure b/configure
-index d04b9d3..4f6e7d7 100755
+index 7d945df..ef24b31 100755
 --- a/configure
 +++ b/configure
-@@ -12322,12 +12322,12 @@ if test -n "$BLKID_CFLAGS"; then
+@@ -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" && \
@@ -23,7 +23,7 @@ index d04b9d3..4f6e7d7 100755
  		      test "x$?" != "x0" && pkg_failed=yes
  else
    pkg_failed=yes
-@@ -12339,12 +12339,12 @@ if test -n "$BLKID_LIBS"; then
+@@ -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" && \
@@ -39,7 +39,7 @@ index d04b9d3..4f6e7d7 100755
  		      test "x$?" != "x0" && pkg_failed=yes
  else
    pkg_failed=yes
-@@ -12365,9 +12365,9 @@ else
+@@ -12154,9 +12154,9 @@ else
          _pkg_short_errors_supported=no
  fi
          if test $_pkg_short_errors_supported = yes; then
@@ -51,7 +51,7 @@ index d04b9d3..4f6e7d7 100755
          fi
  	# Put the nasty error message in config.log where it belongs
  	echo "$BLKID_PKG_ERRORS" >&5
-@@ -12375,7 +12375,7 @@ fi
+@@ -12164,7 +12164,7 @@ fi
  	if test "$BLKID_WIPING" = maybe; then
  				BLKID_WIPING=no
  			   else
@@ -60,7 +60,7 @@ index d04b9d3..4f6e7d7 100755
  			   fi
  elif test $pkg_failed = untried; then
       	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-@@ -12383,7 +12383,7 @@ $as_echo "no" >&6; }
+@@ -12172,7 +12172,7 @@ $as_echo "no" >&6; }
  	if test "$BLKID_WIPING" = maybe; then
  				BLKID_WIPING=no
  			   else
@@ -69,11 +69,11 @@ index d04b9d3..4f6e7d7 100755
  			   fi
  else
  	BLKID_CFLAGS=$pkg_cv_BLKID_CFLAGS
-diff --git a/configure.in b/configure.in
-index d879408..ab8b585 100644
---- a/configure.in
-+++ b/configure.in
-@@ -1312,7 +1312,7 @@ AC_ARG_ENABLE(blkid_wiping,
+diff --git a/configure.ac b/configure.ac
+index e427708..935ea08 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
@@ -82,7 +82,7 @@ index d879408..ab8b585 100644
  			  [ BLKID_WIPING=yes
  			    BLKID_PC="blkid"
  			    DEFAULT_USE_BLKID_WIPING=1
-@@ -1320,7 +1320,7 @@ if test "$BLKID_WIPING" != no; then
+@@ -1243,7 +1243,7 @@ if test "$BLKID_WIPING" != no; then
  			  ], [if test "$BLKID_WIPING" = maybe; then
  				BLKID_WIPING=no
  			   else
@@ -92,10 +92,10 @@ index d879408..ab8b585 100644
  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 9608146..1e45f9d 100644
+index af4b407..eda7982 100644
 --- a/lib/device/dev-type.c
 +++ b/lib/device/dev-type.c
-@@ -713,8 +713,7 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
+@@ -712,8 +712,7 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
  						 BLKID_SUBLKS_TYPE |
  						 BLKID_SUBLKS_USAGE |
  						 BLKID_SUBLKS_VERSION |
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..675ed3d
--- /dev/null
+++ b/SOURCES/lvm2-rhel7-add-lvm1-and-pool-back.patch
@@ -0,0 +1,6364 @@
+ 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                |  58 ++-
+ 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, 5254 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 ef24b31..10b49c6 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/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/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
+@@ -16285,6 +16374,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 935ea08..9fa0c76 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)
+@@ -2117,6 +2173,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 72473d7..f4f5f42 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 15fd150..605f1e1 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
+ 
+@@ -616,6 +620,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
+ 
+@@ -678,6 +689,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 56ec732..18f4b84 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 d2c6db7..2fc74ce 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 3e681a2..2fba3ff 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"
+@@ -543,6 +545,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 a1ab41a..2a2d7ea 100644
+--- a/lib/cache/lvmetad.c
++++ b/lib/cache/lvmetad.c
+@@ -37,6 +37,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)
+@@ -2277,6 +2279,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)
+@@ -2440,9 +2454,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);
+ 	}
+@@ -3058,6 +3074,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 c9596e2..2b72645 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>
+@@ -1134,12 +1142,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)) {
+@@ -1340,6 +1350,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 e98ca6d..6d79087 100644
+--- a/lib/config/config_settings.h
++++ b/lib/config/config_settings.h
+@@ -767,14 +767,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 5c7b72f..792d75a 100644
+--- a/lib/format_text/format-text.c
++++ b/lib/format_text/format-text.c
+@@ -2545,9 +2545,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 e4293cc..1c6dc62 100644
+--- a/lib/metadata/lv_manip.c
++++ b/lib/metadata/lv_manip.c
+@@ -5981,6 +5981,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;
+@@ -6133,6 +6135,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))
+@@ -6188,10 +6194,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 f4fb112..377644b 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 2292568..e33a779 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;
+@@ -2971,7 +2973,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)) {
+@@ -5375,6 +5377,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)
+@@ -5426,6 +5437,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 76d78f3..8357ea0 100644
+--- a/lib/metadata/snapshot_manip.c
++++ b/lib/metadata/snapshot_manip.c
+@@ -332,6 +332,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 b8b1501..1020a67 100644
+--- a/lib/metadata/vg.c
++++ b/lib/metadata/vg.c
+@@ -42,6 +42,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;
+@@ -172,7 +178,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)
+@@ -671,11 +677,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 603a0cf..b80b8da 100644
+--- a/tools/args.h
++++ b/tools/args.h
+@@ -1207,7 +1207,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 b149201..3ce228f 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -1770,6 +1770,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 0dd24ec..0600b1c 100644
+--- a/tools/lvmcmdline.c
++++ b/tools/lvmcmdline.c
+@@ -23,6 +23,7 @@
+ 
+ #include "stub.h"
+ #include "last-path-component.h"
++#include "format1.h"
+ 
+ #include <signal.h>
+ #include <sys/stat.h>
+@@ -2899,6 +2900,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: Disabling lvmetad cache for repair command.");
+ 		lvmetad_set_disabled(cmd, LVMETAD_DISABLE_REASON_REPAIR);
+@@ -2963,7 +2971,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.
+ 	 */
+@@ -3388,6 +3396,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())
+@@ -3477,6 +3520,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 2915db5..d9ad097 100644
+--- a/tools/pvscan.c
++++ b/tools/pvscan.c
+@@ -631,7 +631,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
+@@ -644,7 +644,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 413937f..b60ff06 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>
+@@ -4110,6 +4111,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),
+@@ -4747,6 +4749,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);
+@@ -5106,7 +5125,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. */
+@@ -5335,7 +5357,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 623517b..67be3ec 100644
+--- a/tools/vgchange.c
++++ b/tools/vgchange.c
+@@ -534,6 +534,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;
+@@ -583,6 +590,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-fix-StartLimitInterval.patch b/SOURCES/lvm2-rhel7-fix-StartLimitInterval.patch
index 6245bdb..5e6616b 100644
--- a/SOURCES/lvm2-rhel7-fix-StartLimitInterval.patch
+++ b/SOURCES/lvm2-rhel7-fix-StartLimitInterval.patch
@@ -18,6 +18,3 @@ index 839bfd1..f0bbd46 100644
  ExecStart=@SBINDIR@/lvm pvscan --cache --activate ay %i
  ExecStop=@SBINDIR@/lvm pvscan --cache %i
 +StartLimitInterval=0
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-rhel7.patch b/SOURCES/lvm2-rhel7.patch
index 5efa755..e14a8e9 100644
--- a/SOURCES/lvm2-rhel7.patch
+++ b/SOURCES/lvm2-rhel7.patch
@@ -3,17 +3,16 @@
  2 files changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/VERSION b/VERSION
-index 849efb0..996ced9 100644
+index 9e5739e..98731d0 100644
 --- a/VERSION
 +++ b/VERSION
 @@ -1 +1 @@
--2.02.177(2) (2017-12-18)
-+2.02.177(2)-RHEL7 (2018-01-22)
+-2.02.180(2) (2018-07-19)
++2.02.180(2)-RHEL7 (2018-07-20)
 diff --git a/VERSION_DM b/VERSION_DM
-index a37f632..1853e94 100644
+index 88fc33b..1da204c 100644
 --- a/VERSION_DM
 +++ b/VERSION_DM
 @@ -1 +1 @@
--1.02.146 (2017-12-18)
-+1.02.146-RHEL7 (2018-01-22)
-
+-1.02.149 (2018-07-19)
++1.02.149-RHEL7 (2018-07-20)
diff --git a/SPECS/lvm2.spec b/SPECS/lvm2.spec
index f68e8e7..4b87fd3 100644
--- a/SPECS/lvm2.spec
+++ b/SPECS/lvm2.spec
@@ -1,4 +1,4 @@
-%global device_mapper_version 1.02.146
+%global device_mapper_version 1.02.149
 
 %global enable_cache 1
 %global enable_cluster 1
@@ -20,16 +20,19 @@
 %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.8.5
+%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.8.5
+%global boom_version 0.9
+%global boom_release 11
 %global boom_summary A set of libraries and tools for managing boot loader entries
 %global boom_dir boom-%{boom_version}
 
+#%%global scratch .bz1610455
+
 %if 0%{?rhel}
   %ifnarch i686 x86_64 ppc64le s390x
     %global enable_cluster 0
@@ -63,8 +66,8 @@
 Summary: Userland logical volume management tools 
 Name: lvm2
 Epoch: 7
-Version: 2.02.177
-Release: 4%{?dist}
+Version: 2.02.180
+Release: 8%{?dist}%{?scratch}
 License: GPLv2
 Group: System Environment/Base
 URL: http://sources.redhat.com/lvm2
@@ -76,35 +79,35 @@ 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-2_02_178-lvmlockd-clear-coverity-complaint.patch
-Patch7: lvm2-2_02_178-man-lvmlockd-update-wording.patch
-Patch8: lvm2-2_02_178-lvmlockd-add-lockopt-values-for-skipping-selected-lo.patch
-Patch9: lvm2-2_02_178-lvmlockd-print-warning-when-skipping-locking.patch
-Patch10: lvm2-2_02_178-man-lvmlockd-remove-lv-resizing-comment.patch
-Patch11: lvm2-2_02_178-allocation-Avoid-exceeding-array-bounds-in-allocatio.patch
-Patch12: lvm2-2_02_178-lvconvert-use-excl-activation-for-conversion.patch
-Patch13: lvm2-2_02_178-pvmove-fix-_remove_sibling_pvs_from_trim_list.patch
-Patch14: lvm2-2_02_178-pvmove-better-check-for-exclusive-LV.patch
-Patch15: lvm2-2_02_178-pvmove-drop-misleading-pvmove-restriction-for-cluste.patch
-Patch16: lvm2-2_02_178-dmeventd-add-check-for-result-code.patch
-Patch17: lvm2-2_02_178-activation-guard-exclusive-activation.patch
-Patch18: lvm2-2_02_178-cleanup-enhance-messages.patch
-Patch19: lvm2-2_02_178-cleanup-drop-unused-code.patch
-Patch20: lvm2-2_02_178-tests-properly-test-with-clustered-VG.patch
-Patch21: lvm2-2_02_178-tests-check-preserved-exclusivness-of-snapshot-merge.patch
-Patch22: lvm2-2_02_178-tests-longer-startup-timeout-for-daemons-with-valgri.patch
-Patch23: lvm2-2_02_178-tests-check-pvmove-is-merging-segments.patch
-Patch24: lvm2-2_02_178-activation-move-check-later.patch
-Patch25: lvm2-2_02_178-libdm-accept-mirror-status-with-userspace-word-in-th.patch
-Patch26: lvm2-2_02_178-pvmove-reinstantiate-clustered-pvmove.patch
-Patch27: lvm2-2_02_178-mirror-Add-deprecation-warning-for-mirrored-log.patch
-Patch28: lvm2-2_02_178-locking-exclusive-can-be-either-remote-or-local.patch
-Patch29: lvm2-2_02_178-pvmove-enhance-accepted-states-of-active-LVs.patch
+Patch6: lvm2-rhel7-add-lvm1-and-pool-back.patch
+Patch7: lvm2-2_02_180-make-generate.patch
+Patch8: lvm2-2_02_181-post-release.patch
+Patch9: lvm2-2_02_181-lvconvert-restrict-command-matching-for-no-option-va.patch
+Patch10: lvm2-2_02_181-lvconvert-improve-text-about-splitmirrors.patch
+Patch11: lvm2-2_02_181-lvconvert-reject-conversions-of-LVs-under-snapshot.patch
+Patch12: lvm2-2_02_181-dmsetup-fix-error-propagation-in-_display_info_cols.patch
+Patch13: lvm2-2_02_181-reject-conversions-trackchanges-SubLVs.patch
+Patch14: lvm2-2_02_181-reject-conversions-trackchanges-LVs.patch
+Patch15: lvm2-2_02_181-dmeventd-base-vdo-plugin.patch
+Patch16: lvm2-2_02_181-dmeventd-rebase-to-stable-branch.patch
+Patch17: lvm2-2_02_181-WHATS_NEW.patch
+Patch18: lvm2-2_02_181-build-make-generate.patch
+Patch19: lvm2-2_02_182-vgcreate-close-exclusive-fd-after-pvcreate.patch
+Patch20: lvm2-2_02_182-mirrors-fix-read_only_volume_list.patch
+Patch21: lvm2-2_02_182-cache-drop-metadata_format-validation.patch
+Patch22: lvm2-2_02_182-mirror-fix-splitmirrors-for-mirror-type.patch
+Patch23: lvm2-2_02_182-lvconvert-fix-direct-raid0-to-striped-conversion.patch
+Patch24: lvm2-2_02_182-lvconvert-fix-conversion-attempts-to-linear.patch
+Patch25: lvm2-2_02_182-dmeventd-lvm2-plugin-uses-envvar-registry.patch
+Patch26: lvm2-2_02_182-scripts-add-After-rbdmap.service-to-lvm2-activation.patch
+Patch27: lvm2-2_02_182-lvconvert-avoid-superfluous-interim-raid-type.patch
+Patch28: lvm2-2_02_182-lvconvert-fix-interim-segtype-regression-on-raid6-co.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
@@ -157,30 +160,29 @@ or more physical volumes and creating one or more logical volumes
 %patch3 -p1 -b .blkid_sublks_badcsum
 %patch4 -p1 -b .default_allow_dup
 %patch5 -p1 -b .startlimitinterval
-%patch6 -p1 -b .6lvmlockd_clear_coverity_complaint
-%patch7 -p1 -b .7man_lvmlockd_update_wording
-%patch8 -p1 -b .8lvmlockd_add_lockopt_values_for_skipping_selected_lo
-%patch9 -p1 -b .9lvmlockd_print_warning_when_skipping_locking
-%patch10 -p1 -b .10man_lvmlockd_remove_lv_resizing_comment
-%patch11 -p1 -b .11allocation_Avoid_exceeding_array_bounds_in_allocatio
-%patch12 -p1 -b .12lvconvert_use_excl_activation_for_conversion
-%patch13 -p1 -b .13pvmove_fix__remove_sibling_pvs_from_trim_list
-%patch14 -p1 -b .14pvmove_better_check_for_exclusive_LV
-%patch15 -p1 -b .15pvmove_drop_misleading_pvmove_restriction_for_cluste
-%patch16 -p1 -b .16dmeventd_add_check_for_result_code
-%patch17 -p1 -b .17activation_guard_exclusive_activation
-%patch18 -p1 -b .18cleanup_enhance_messages
-%patch19 -p1 -b .19cleanup_drop_unused_code
-%patch20 -p1 -b .20tests_properly_test_with_clustered_VG
-%patch21 -p1 -b .21tests_check_preserved_exclusivness_of_snapshot_merge
-%patch22 -p1 -b .22tests_longer_startup_timeout_for_daemons_with_valgri
-%patch23 -p1 -b .23tests_check_pvmove_is_merging_segments
-%patch24 -p1 -b .24activation_move_check_later
-%patch25 -p1 -b .25libdm_mirror_status_userspace
-%patch26 -p1 -b .26clustered_pvmove
-%patch27 -p1 -b .27deprecation_warning_for_mirrored_log
-%patch28 -p1 -b .28locking_ex_either_remote_or_local
-%patch29 -p1 -b .29pvmove_enhance_accepted_states_of_active_LVs
+%patch6 -p1 -b .add_lvm1_and_pool
+%patch7 -p1 -b .make_generate
+%patch8 -p1 -b .post_release
+%patch9 -p1 -b .lvconvert_matching_no_option
+%patch10 -p1 -b .lvconvert_text_splitmirrors
+%patch11 -p1 -b .reject_conversions_under_snapshot
+%patch12 -p1 -b .dmsetup_fix_error_display_info_cols
+%patch13 -p1 -b .reject_conversions_trackchage_LVs
+%patch14 -p1 -b .reject_conversions_trackchang_subLVs
+%patch15 -p1 -b .dmeventd_base_vdo_plugin
+%patch16 -p1 -b .dmeventd_rebase_to_stable_branch
+%patch17 -p1 -b .WHATS_NEW
+%patch18 -p1 -b .build_make_generate
+%patch19 -p1 -b .close_excl_fd_after_pvcreate
+%patch20 -p1 -b .mirrors_fix_RO_volume_list
+%patch21 -p1 -b .cache_drop_metadata_format_validation
+%patch22 -p1 -b .mirror_fix_splitmirrors
+%patch23 -p1 -b .direct_raid0_to_striped_conversion
+%patch24 -p1 -b .fix_conversion_to_linear
+%patch25 -p1 -b .dmeventd_lvm2_plugin_uses_envvar_registry
+%patch26 -p1 -b .lvm2_activation_after_rdbmap
+%patch27 -p1 -b .avoid_superfluous_raid_conversion
+%patch28 -p1 -b .fix_interim_segtype_on_raid6
 
 %build
 %global _default_pid_dir /run
@@ -539,6 +541,10 @@ This package contains shared lvm2 libraries for applications.
 %{_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
@@ -924,10 +930,12 @@ the device-mapper event library.
 %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
@@ -953,6 +961,70 @@ This package provides the python2 version of boom.
 %endif
 
 %changelog
+* 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.