diff --git a/.gitignore b/.gitignore
index 7f87764..bd1506b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/LVM2.2.02.105.tgz
+SOURCES/LVM2.2.02.115.tgz
diff --git a/.lvm2.metadata b/.lvm2.metadata
index 2f3f5b8..0ed8558 100644
--- a/.lvm2.metadata
+++ b/.lvm2.metadata
@@ -1 +1 @@
-796163e766480cdc427cd443dc1336ae8e8e3bd7 SOURCES/LVM2.2.02.105.tgz
+bc229c7790b796051a8e45c58bd97ab57eadf360 SOURCES/LVM2.2.02.115.tgz
diff --git a/SOURCES/lvm2-2_02_106-additional-lvmetad-fixes.patch b/SOURCES/lvm2-2_02_106-additional-lvmetad-fixes.patch
deleted file mode 100644
index f828438..0000000
--- a/SOURCES/lvm2-2_02_106-additional-lvmetad-fixes.patch
+++ /dev/null
@@ -1,127 +0,0 @@
-commit 923b95504e189fb3b9353a66a3c3a9e147a46e39
-Author: Peter Rajnoha <prajnoha@redhat.com>
-Date:   Wed Mar 5 16:48:17 2014 +0100
-
-    lvmetad_fixes
----
- WHATS_NEW                       |  3 +++
- daemons/lvmetad/lvmetad-core.c  | 20 +++++++++++++++++---
- test/shell/lvmetad-ambiguous.sh | 34 ++++++++++++++++++++++++++++++++++
- 3 files changed, 54 insertions(+), 3 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 224e351..3ee9585 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,8 @@
- Version 2.02.106 - 
- ====================================
-+  Fix cache consistency in lvmetad when PV moves around.
-+  Fix memleak when lvmetad discovers PV to appear on another device.
-+  Fix invalid memory read in lvmetad that could cause a deadlock.
-   Fix calculation of maximum size of COW device for snapshot (2.02.99).
-   Do not allow stripe size to be bigger then extent size for lvresize.
-   Zero snapshot COW header when creating read-only snapshot.
-diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
-index e6e222f..f35db89 100644
---- a/daemons/lvmetad/lvmetad-core.c
-+++ b/daemons/lvmetad/lvmetad-core.c
-@@ -861,7 +861,7 @@ static response pv_found(lvmetad_state *s, request r)
- 	const char *vgid = daemon_request_str(r, "metadata/id", NULL);
- 	const char *vgid_old = NULL;
- 	struct dm_config_node *pvmeta = dm_config_find_node(r.cft->root, "pvmeta");
--	uint64_t device;
-+	uint64_t device, device_old_pvid = 0;
- 	struct dm_config_tree *cft, *pvmeta_old_dev = NULL, *pvmeta_old_pvid = NULL;
- 	char *old;
- 	char *pvid_dup;
-@@ -883,9 +883,12 @@ static response pv_found(lvmetad_state *s, request r)
- 		dm_hash_remove(s->pvid_to_pvmeta, old);
- 		vgid_old = dm_hash_lookup(s->pvid_to_vgid, old);
- 	}
--	pvmeta_old_pvid = dm_hash_lookup(s->pvid_to_pvmeta, pvid);
- 
--	DEBUGLOG(s, "pv_found %s, vgid = %s, device = %" PRIu64 ", old = %s", pvid, vgid, device, old);
-+	if ((pvmeta_old_pvid = dm_hash_lookup(s->pvid_to_pvmeta, pvid)))
-+		dm_config_get_uint64(pvmeta_old_pvid->root, "pvmeta/device", &device_old_pvid);
-+
-+	DEBUGLOG(s, "pv_found %s, vgid = %s, device = %" PRIu64 " (previously %" PRIu64 "), old = %s",
-+		 pvid, vgid, device, device_old_pvid, old);
- 
- 	dm_free(old);
- 
-@@ -903,6 +906,12 @@ static response pv_found(lvmetad_state *s, request r)
- 		return reply_fail("out of memory");
- 	}
- 
-+	if (pvmeta_old_pvid && device != device_old_pvid) {
-+		DEBUGLOG(s, "pv %s no longer on device %" PRIu64, pvid, device_old_pvid);
-+		dm_free(dm_hash_lookup_binary(s->device_to_pvid, &device_old_pvid, sizeof(device_old_pvid)));
-+		dm_hash_remove_binary(s->device_to_pvid, &device_old_pvid, sizeof(device_old_pvid));
-+	}
-+
- 	if (!dm_hash_insert(s->pvid_to_pvmeta, pvid, cft) ||
- 	    !dm_hash_insert_binary(s->device_to_pvid, &device, sizeof(device), (void*)pvid_dup)) {
- 		dm_hash_remove(s->pvid_to_pvmeta, pvid);
-@@ -911,6 +920,7 @@ static response pv_found(lvmetad_state *s, request r)
- 		dm_free(pvid_dup);
- 		return reply_fail("out of memory");
- 	}
-+
- 	if (pvmeta_old_pvid)
- 		dm_config_destroy(pvmeta_old_pvid);
- 	if (pvmeta_old_dev && pvmeta_old_dev != pvmeta_old_pvid)
-@@ -949,9 +959,13 @@ static response pv_found(lvmetad_state *s, request r)
- 	}
- 
- 	if (vgid_old && (!vgid || strcmp(vgid, vgid_old))) {
-+		/* make a copy, because vg_remove_if_missing will deallocate the
-+		 * storage behind vgid_old */
-+		vgid_old = dm_strdup(vgid_old);
- 		lock_vg(s, vgid_old);
- 		vg_remove_if_missing(s, vgid_old, 1);
- 		unlock_vg(s, vgid_old);
-+		dm_free((char*)vgid_old);
- 	}
- 
- 	return daemon_reply_simple("OK",
-diff --git a/test/shell/lvmetad-ambiguous.sh b/test/shell/lvmetad-ambiguous.sh
-new file mode 100644
-index 0000000..455aa5d
---- /dev/null
-+++ b/test/shell/lvmetad-ambiguous.sh
-@@ -0,0 +1,34 @@
-+#!/bin/sh
-+# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+. lib/test
-+
-+test -e LOCAL_LVMETAD || skip
-+
-+aux prepare_pvs 2
-+
-+# flip the devices around
-+aux init_udev_transaction
-+dmsetup remove -f "$dev1"
-+dmsetup remove -f "$dev2"
-+dmsetup create -u TEST-${PREFIX}pv2 ${PREFIX}pv2 ${PREFIX}pv2.table
-+dmsetup create -u TEST-${PREFIX}pv1 ${PREFIX}pv1 ${PREFIX}pv1.table
-+aux finish_udev_transaction
-+
-+# re-scan them
-+pvscan --cache $dev1
-+pvscan --cache $dev2
-+
-+# expect both to be there
-+pvs | tee pvs.txt
-+grep $dev1 pvs.txt
-+grep $dev2 pvs.txt
-+
diff --git a/SOURCES/lvm2-2_02_106-cleanup-stray-warning-messages-for-cmirror-addendum.patch b/SOURCES/lvm2-2_02_106-cleanup-stray-warning-messages-for-cmirror-addendum.patch
deleted file mode 100644
index 3b4924b..0000000
--- a/SOURCES/lvm2-2_02_106-cleanup-stray-warning-messages-for-cmirror-addendum.patch
+++ /dev/null
@@ -1,20 +0,0 @@
- daemons/cmirrord/cluster.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/daemons/cmirrord/cluster.c b/daemons/cmirrord/cluster.c
-index 67391f1..3fd5d23 100644
---- a/daemons/cmirrord/cluster.c
-+++ b/daemons/cmirrord/cluster.c
-@@ -985,9 +985,9 @@ static int do_cluster_work(void *data __attribute__((unused)))
- 	dm_list_iterate_items_safe(entry, tmp, &clog_cpg_list) {
- 		r = cpg_dispatch(entry->handle, CS_DISPATCH_ALL);
- 		if (r != CS_OK) {
--			if ((entry->cpg_state == INVALID) &&
--			    (entry->state == LEAVING) &&
--			    (r == CS_ERR_BAD_HANDLE))
-+			if ((r == CS_ERR_BAD_HANDLE) &&
-+			    ((entry->state == INVALID) ||
-+			     (entry->state == LEAVING)))
- 				/* It's ok if we've left the cluster */
- 				r = CS_OK;
- 			else
diff --git a/SOURCES/lvm2-2_02_106-cleanup-stray-warning-messages-for-cmirror.patch b/SOURCES/lvm2-2_02_106-cleanup-stray-warning-messages-for-cmirror.patch
deleted file mode 100644
index bff73f3..0000000
--- a/SOURCES/lvm2-2_02_106-cleanup-stray-warning-messages-for-cmirror.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-commit 52aa3dbcabe85b38b51c68c27fb2397eb0fb1efd
-Author: Jonathan Brassow <jbrassow@redhat.com>
-Date:   Wed Mar 5 10:44:20 2014 -0600
-
-    cmirrord:  Clean-up stray warning message
-    
-    cmirrord polls for messages on the kernel and cluster interfaces.
-    Sometimes it is possible for messages to be received on the cluster
-    interface and be waiting for processing while the node is in the
-    process of leaving the cluster group.  When this happens, the
-    messages received on the cluster interface are attempted to be
-    dispatched, but an error is returned because the connection is no
-    longer valid.  It is a harmless situation.  So, if we get the
-    specific error (CS_ERR_BAD_HANDLE) and we know that we have left
-    the group, then simply don't print the message.
----
- daemons/cmirrord/cluster.c | 13 ++++++++++---
- 1 file changed, 10 insertions(+), 3 deletions(-)
-
-diff --git a/daemons/cmirrord/cluster.c b/daemons/cmirrord/cluster.c
-index fea739a..67391f1 100644
---- a/daemons/cmirrord/cluster.c
-+++ b/daemons/cmirrord/cluster.c
-@@ -984,9 +984,16 @@ static int do_cluster_work(void *data __attribute__((unused)))
- 
- 	dm_list_iterate_items_safe(entry, tmp, &clog_cpg_list) {
- 		r = cpg_dispatch(entry->handle, CS_DISPATCH_ALL);
--		if (r != CS_OK)
--			LOG_ERROR("cpg_dispatch failed: %s",
--				  str_ais_error(r));
-+		if (r != CS_OK) {
-+			if ((entry->cpg_state == INVALID) &&
-+			    (entry->state == LEAVING) &&
-+			    (r == CS_ERR_BAD_HANDLE))
-+				/* It's ok if we've left the cluster */
-+				r = CS_OK;
-+			else
-+				LOG_ERROR("cpg_dispatch failed: %s",
-+					  str_ais_error(r));
-+		}
- 
- 		if (entry->free_me) {
- 			free(entry);
diff --git a/SOURCES/lvm2-2_02_106-enahnce-lvmetad-protocol-for-pvscan-to-lock-vg-properly-and-run-refresh-only-when-needed.patch b/SOURCES/lvm2-2_02_106-enahnce-lvmetad-protocol-for-pvscan-to-lock-vg-properly-and-run-refresh-only-when-needed.patch
deleted file mode 100644
index 336de06..0000000
--- a/SOURCES/lvm2-2_02_106-enahnce-lvmetad-protocol-for-pvscan-to-lock-vg-properly-and-run-refresh-only-when-needed.patch
+++ /dev/null
@@ -1,325 +0,0 @@
- WHATS_NEW                      |  5 +++
- daemons/lvmetad/lvmetad-core.c | 74 +++++++++++++++++++++++-------------------
- lib/cache/lvmetad.c            |  9 +++--
- lib/cache/lvmetad.h            |  3 +-
- lib/locking/file_locking.c     |  2 +-
- tools/pvscan.c                 | 32 ++++++++++--------
- 6 files changed, 74 insertions(+), 51 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index a3d48f3..b5afb19 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,10 @@
- Version 2.02.106 - 
- ====================================
-+  Use VG read lock during 'pvscan --cache -aay' autoactivation.
-+  Issue a VG refresh before autoactivation only if the PV has changed/is new.
-+  Add flag to lvmetad protocol to indicate the PV scanned has changed/is new.
-+  Also add vgname to lvmetad protocol when referencing VGs for PVs scanned.
-+  Use correct PATH_MAX for locking dir path.
-   Update API for internal function build_dm_uuid().
-   Do not try to check empty pool with scheduled messages.
-   Fix return value in pool_has_message() when quering for any message.
-diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
-index f35db89..1858ee2 100644
---- a/daemons/lvmetad/lvmetad-core.c
-+++ b/daemons/lvmetad/lvmetad-core.c
-@@ -344,8 +344,8 @@ static response pv_lookup(lvmetad_state *s, request r)
- 		pvid = dm_hash_lookup_binary(s->device_to_pvid, &devt, sizeof(devt));
- 
- 	if (!pvid) {
--		WARN(s, "pv_lookup: could not find device %" PRIu64, devt);
- 		unlock_pvid_to_pvmeta(s);
-+		WARN(s, "pv_lookup: could not find device %" PRIu64, devt);
- 		dm_config_destroy(res.cft);
- 		return reply_unknown("device not found");
- 	}
-@@ -809,30 +809,28 @@ static response pv_gone(lvmetad_state *s, request r)
- 	pvid_old = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device));
- 	vgid = dm_hash_lookup(s->pvid_to_vgid, pvid);
- 
--	if (vgid && !(vgid = dm_strdup(vgid))) {
--		unlock_pvid_to_pvmeta(s);
--		return reply_fail("out of memory");
--	}
--
- 	dm_hash_remove_binary(s->device_to_pvid, &device, sizeof(device));
- 	dm_hash_remove(s->pvid_to_pvmeta, pvid);
- 	unlock_pvid_to_pvmeta(s);
- 
-+	dm_free(pvid_old);
-+
- 	if (vgid) {
-+		if (!(vgid = dm_strdup(vgid)))
-+			return reply_fail("out of memory");
-+
- 		lock_vg(s, vgid);
- 		vg_remove_if_missing(s, vgid, 1);
- 		unlock_vg(s, vgid);
- 		dm_free(vgid);
- 	}
- 
--	if (pvid_old)
--		dm_free(pvid_old);
--
--	if (pvmeta) {
--		dm_config_destroy(pvmeta);
--		return daemon_reply_simple("OK", NULL);
--	} else
-+	if (!pvmeta)
- 		return reply_unknown("PVID does not exist");
-+
-+	dm_config_destroy(pvmeta);
-+
-+	return daemon_reply_simple("OK", NULL);
- }
- 
- static response pv_clear_all(lvmetad_state *s, request r)
-@@ -866,7 +864,7 @@ static response pv_found(lvmetad_state *s, request r)
- 	char *old;
- 	char *pvid_dup;
- 	int complete = 0, orphan = 0;
--	int64_t seqno = -1, seqno_old = -1;
-+	int64_t seqno = -1, seqno_old = -1, changed = 0;
- 
- 	if (!pvid)
- 		return reply_fail("need PV UUID");
-@@ -876,58 +874,60 @@ static response pv_found(lvmetad_state *s, request r)
- 	if (!dm_config_get_uint64(pvmeta, "pvmeta/device", &device))
- 		return reply_fail("need PV device number");
- 
-+	if (!(cft = dm_config_create()) ||
-+	    (!(pvid_dup = dm_strdup(pvid)))) {
-+		if (cft)
-+			dm_config_destroy(cft);
-+		return reply_fail("out of memory");
-+	}
-+
- 	lock_pvid_to_pvmeta(s);
- 
-+	if ((pvmeta_old_pvid = dm_hash_lookup(s->pvid_to_pvmeta, pvid)))
-+		dm_config_get_uint64(pvmeta_old_pvid->root, "pvmeta/device", &device_old_pvid);
-+
- 	if ((old = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device)))) {
- 		pvmeta_old_dev = dm_hash_lookup(s->pvid_to_pvmeta, old);
- 		dm_hash_remove(s->pvid_to_pvmeta, old);
- 		vgid_old = dm_hash_lookup(s->pvid_to_vgid, old);
- 	}
- 
--	if ((pvmeta_old_pvid = dm_hash_lookup(s->pvid_to_pvmeta, pvid)))
--		dm_config_get_uint64(pvmeta_old_pvid->root, "pvmeta/device", &device_old_pvid);
--
- 	DEBUGLOG(s, "pv_found %s, vgid = %s, device = %" PRIu64 " (previously %" PRIu64 "), old = %s",
- 		 pvid, vgid, device, device_old_pvid, old);
- 
--	dm_free(old);
--
--	if (!(cft = dm_config_create()) ||
--	    !(cft->root = dm_config_clone_node(cft, pvmeta, 0))) {
--		unlock_pvid_to_pvmeta(s);
--		if (cft)
--			dm_config_destroy(cft);
--		return reply_fail("out of memory");
--	}
-+	if (!(cft->root = dm_config_clone_node(cft, pvmeta, 0)))
-+                goto out_of_mem;
- 
--	if (!(pvid_dup = dm_strdup(pvid))) {
--		unlock_pvid_to_pvmeta(s);
--		dm_config_destroy(cft);
--		return reply_fail("out of memory");
--	}
-+	if (!pvmeta_old_pvid || compare_config(pvmeta_old_pvid->root, cft->root))
-+		changed |= 1;
- 
- 	if (pvmeta_old_pvid && device != device_old_pvid) {
- 		DEBUGLOG(s, "pv %s no longer on device %" PRIu64, pvid, device_old_pvid);
- 		dm_free(dm_hash_lookup_binary(s->device_to_pvid, &device_old_pvid, sizeof(device_old_pvid)));
- 		dm_hash_remove_binary(s->device_to_pvid, &device_old_pvid, sizeof(device_old_pvid));
-+		changed |= 1;
- 	}
- 
- 	if (!dm_hash_insert(s->pvid_to_pvmeta, pvid, cft) ||
- 	    !dm_hash_insert_binary(s->device_to_pvid, &device, sizeof(device), (void*)pvid_dup)) {
- 		dm_hash_remove(s->pvid_to_pvmeta, pvid);
-+out_of_mem:
- 		unlock_pvid_to_pvmeta(s);
- 		dm_config_destroy(cft);
- 		dm_free(pvid_dup);
-+		dm_free(old);
- 		return reply_fail("out of memory");
- 	}
- 
-+	unlock_pvid_to_pvmeta(s);
-+
-+	dm_free(old);
-+
- 	if (pvmeta_old_pvid)
- 		dm_config_destroy(pvmeta_old_pvid);
- 	if (pvmeta_old_dev && pvmeta_old_dev != pvmeta_old_pvid)
- 		dm_config_destroy(pvmeta_old_dev);
- 
--	unlock_pvid_to_pvmeta(s);
--
- 	if (metadata) {
- 		if (!vgid)
- 			return reply_fail("need VG UUID");
-@@ -939,6 +939,7 @@ static response pv_found(lvmetad_state *s, request r)
- 
- 		if (!update_metadata(s, vgname, vgid, metadata, &seqno_old))
- 			return reply_fail("metadata update failed");
-+		changed |= (seqno_old != dm_config_find_int(metadata, "metadata/seqno", -1));
- 	} else {
- 		lock_pvid_to_vgid(s);
- 		vgid = dm_hash_lookup(s->pvid_to_vgid, pvid);
-@@ -956,6 +957,11 @@ static response pv_found(lvmetad_state *s, request r)
- 			return reply_fail("non-orphan VG without metadata encountered");
- 		}
- 		unlock_vg(s, vgid);
-+
-+		// TODO: separate vgid->vgname lock
-+		lock_vgid_to_metadata(s);
-+		vgname = dm_hash_lookup(s->vgid_to_vgname, vgid);
-+		unlock_vgid_to_metadata(s);
- 	}
- 
- 	if (vgid_old && (!vgid || strcmp(vgid, vgid_old))) {
-@@ -971,7 +977,9 @@ static response pv_found(lvmetad_state *s, request r)
- 	return daemon_reply_simple("OK",
- 				   "status = %s", orphan ? "orphan" :
- 				                     (complete ? "complete" : "partial"),
-+				   "changed = %d", changed,
- 				   "vgid = %s", vgid ? vgid : "#orphan",
-+				   "vgname = %s", vgname ? vgname : "#orphan",
- 				   "seqno_before = %"PRId64, seqno_old,
- 				   "seqno_after = %"PRId64, seqno,
- 				   NULL);
-diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
-index c994874..38d9042 100644
---- a/lib/cache/lvmetad.c
-+++ b/lib/cache/lvmetad.c
-@@ -749,7 +749,8 @@ int lvmetad_pv_found(const struct id *pvid, struct device *dev, const struct for
- 	daemon_reply reply;
- 	struct lvmcache_info *info;
- 	struct dm_config_tree *pvmeta, *vgmeta;
--	const char *status, *vgid;
-+	const char *status, *vgname, *vgid;
-+	int64_t changed;
- 	int result;
- 
- 	if (!lvmetad_active() || test_mode())
-@@ -818,11 +819,13 @@ int lvmetad_pv_found(const struct id *pvid, struct device *dev, const struct for
- 
- 	if (result && handler) {
- 		status = daemon_reply_str(reply, "status", "<missing>");
-+		vgname = daemon_reply_str(reply, "vgname", "<missing>");
- 		vgid = daemon_reply_str(reply, "vgid", "<missing>");
-+		changed = daemon_reply_int(reply, "changed", 0);
- 		if (!strcmp(status, "partial"))
--			handler(_lvmetad_cmd, vgid, 1, CHANGE_AAY);
-+			handler(_lvmetad_cmd, vgname, vgid, 1, changed, CHANGE_AAY);
- 		else if (!strcmp(status, "complete"))
--			handler(_lvmetad_cmd, vgid, 0, CHANGE_AAY);
-+			handler(_lvmetad_cmd, vgname, vgid, 0, changed, CHANGE_AAY);
- 		else if (!strcmp(status, "orphan"))
- 			;
- 		else
-diff --git a/lib/cache/lvmetad.h b/lib/cache/lvmetad.h
-index 85b71c2..d9aa77f 100644
---- a/lib/cache/lvmetad.h
-+++ b/lib/cache/lvmetad.h
-@@ -23,7 +23,8 @@ struct dm_config_tree;
- enum activation_change;
- 
- typedef int (*activation_handler) (struct cmd_context *cmd,
--				   const char *vgid, int partial,
-+				   const char *vgname, const char *vgid,
-+				   int partial, int changed,
- 				   enum activation_change activate);
- 
- #ifdef LVMETAD_SUPPORT
-diff --git a/lib/locking/file_locking.c b/lib/locking/file_locking.c
-index fb84c5b..734e0b4 100644
---- a/lib/locking/file_locking.c
-+++ b/lib/locking/file_locking.c
-@@ -37,7 +37,7 @@ struct lock_list {
- };
- 
- static struct dm_list _lock_list;
--static char _lock_dir[NAME_LEN];
-+static char _lock_dir[PATH_MAX];
- static int _prioritise_write_locks;
- 
- static sig_t _oldhandler;
-diff --git a/tools/pvscan.c b/tools/pvscan.c
-index 4f99f45..5db627a 100644
---- a/tools/pvscan.c
-+++ b/tools/pvscan.c
-@@ -95,13 +95,13 @@ static void _pvscan_display_single(struct cmd_context *cmd,
- #define REFRESH_BEFORE_AUTOACTIVATION_RETRY_USLEEP_DELAY 100000
- 
- static int _auto_activation_handler(struct cmd_context *cmd,
--				    const char *vgid, int partial,
-+				    const char *vgname, const char *vgid,
-+				    int partial, int changed,
- 				    activation_change_t activate)
- {
- 	unsigned int refresh_retries = REFRESH_BEFORE_AUTOACTIVATION_RETRIES;
- 	int refresh_done = 0;
- 	struct volume_group *vg;
--	int consistent = 0;
- 	struct id vgid_raw;
- 	int r = 0;
- 
-@@ -113,8 +113,12 @@ static int _auto_activation_handler(struct cmd_context *cmd,
- 		return_0;
- 
- 	/* NB. This is safe because we know lvmetad is running and we won't hit disk. */
--	if (!(vg = vg_read_internal(cmd, NULL, (const char *) &vgid_raw, 0, &consistent)))
--	    return 1;
-+	vg = vg_read(cmd, vgname, (const char *)&vgid_raw, 0);
-+	if (vg_read_error(vg)) {
-+		log_error("Failed to read Volume Group \"%s\" (%s) during autoactivation.", vgname, vgid);
-+		release_vg(vg);
-+		return 0;
-+	}
- 
- 	if (vg_is_clustered(vg)) {
- 		r = 1; goto out;
-@@ -139,16 +143,18 @@ static int _auto_activation_handler(struct cmd_context *cmd,
- 	 *
- 	 * Remove this workaround with "refresh_retries" once we have proper locking in!
- 	 */
--	while (refresh_retries--) {
--		if (vg_refresh_visible(vg->cmd, vg)) {
--			refresh_done = 1;
--			break;
-+	if (changed) {
-+		while (refresh_retries--) {
-+			if (vg_refresh_visible(vg->cmd, vg)) {
-+				refresh_done = 1;
-+				break;
-+			}
-+			usleep(REFRESH_BEFORE_AUTOACTIVATION_RETRY_USLEEP_DELAY);
- 		}
--		usleep(REFRESH_BEFORE_AUTOACTIVATION_RETRY_USLEEP_DELAY);
--	}
- 
--	if (!refresh_done)
--		log_warn("%s: refresh before autoactivation failed.", vg->name);
-+		if (!refresh_done)
-+			log_warn("%s: refresh before autoactivation failed.", vg->name);
-+	}
- 
- 	if (!vgchange_activate(vg->cmd, vg, activate)) {
- 		log_error("%s: autoactivation failed.", vg->name);
-@@ -158,7 +164,7 @@ static int _auto_activation_handler(struct cmd_context *cmd,
- 	r = 1;
- 
- out:
--	release_vg(vg);
-+	unlock_and_release_vg(cmd, vg, vgname);
- 	return r;
- }
- 
diff --git a/SOURCES/lvm2-2_02_106-fix-dmeventd-logging-with-parallel-wait-processing.patch b/SOURCES/lvm2-2_02_106-fix-dmeventd-logging-with-parallel-wait-processing.patch
deleted file mode 100644
index 510cf5b..0000000
--- a/SOURCES/lvm2-2_02_106-fix-dmeventd-logging-with-parallel-wait-processing.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-commit 6281d212fa5e70e400c70677dfc20e99553e60d1
-Author: Peter Rajnoha <prajnoha@redhat.com>
-Date:   Wed Mar 12 14:36:55 2014 +0100
-
-    dmeventd parallel processing
----
- WHATS_NEW_DM                |  1 +
- daemons/dmeventd/dmeventd.c | 16 ++++++++++++++--
- 2 files changed, 15 insertions(+), 2 deletions(-)
-
-diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
-index 32c2265..e470cd2 100644
---- a/WHATS_NEW_DM
-+++ b/WHATS_NEW_DM
-@@ -1,5 +1,6 @@
- Version 1.02.85 - 
- ===================================
-+  Fix dmeventd logging with parallel wait event processing.
-   Reuse _node_send_messages() for validation of transaction_id in preload.
-   Transaction_id could be lower by one only when messages are prepared.
-   Do not call callback when preload fails.
-diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
-index 4a17fb2..f27444c 100644
---- a/daemons/dmeventd/dmeventd.c
-+++ b/daemons/dmeventd/dmeventd.c
-@@ -661,6 +661,7 @@ static sigset_t _unblock_sigalrm(void)
- /* Wait on a device until an event occurs. */
- static int _event_wait(struct thread_status *thread, struct dm_task **task)
- {
-+	static unsigned _in_event_counter = 0;
- 	sigset_t set;
- 	int ret = DM_WAIT_RETRY;
- 	struct dm_task *dmt;
-@@ -677,12 +678,20 @@ static int _event_wait(struct thread_status *thread, struct dm_task **task)
- 	    !dm_task_set_event_nr(dmt, thread->event_nr))
- 		goto out;
- 
-+	_lock_mutex();
-+	/*
-+	 * Check if there are already some waiting events,
-+	 * in this case the logging is unmodified.
-+	 * TODO: audit libdm thread usage
-+	 */
-+	if (!_in_event_counter++)
-+		dm_log_init(_no_intr_log);
-+	_unlock_mutex();
- 	/*
- 	 * This is so that you can break out of waiting on an event,
- 	 * either for a timeout event, or to cancel the thread.
- 	 */
- 	set = _unblock_sigalrm();
--	dm_log_init(_no_intr_log);
- 	errno = 0;
- 	if (dm_task_run(dmt)) {
- 		thread->current_events |= DM_EVENT_DEVICE_ERROR;
-@@ -706,7 +715,10 @@ static int _event_wait(struct thread_status *thread, struct dm_task **task)
- 	}
- 
- 	pthread_sigmask(SIG_SETMASK, &set, NULL);
--	dm_log_init(NULL);
-+	_lock_mutex();
-+	if (--_in_event_counter == 0)
-+		dm_log_init(NULL);
-+	_unlock_mutex();
- 
-       out:
- 	if (ret == DM_WAIT_FATAL || ret == DM_WAIT_RETRY) {
diff --git a/SOURCES/lvm2-2_02_106-fix-incorrect-snapshot-calculation-of-cow-size.patch b/SOURCES/lvm2-2_02_106-fix-incorrect-snapshot-calculation-of-cow-size.patch
deleted file mode 100644
index 3bff830..0000000
--- a/SOURCES/lvm2-2_02_106-fix-incorrect-snapshot-calculation-of-cow-size.patch
+++ /dev/null
@@ -1,122 +0,0 @@
-commit d00fc1de784cee27d6ddb1b045a67c930f743074
-Author: Zdenek Kabelac <zkabelac@redhat.com>
-Date:   Thu Feb 27 12:55:50 2014 +0100
-
-    snapshot: correct previous snapshot commit
-    
-    Condition was swapped - however since it's been based on 'random'
-    memory content it's been missed as attribute has not been set.
-    
-    So now we have quite a few possible results when testing.
-    
-    We have old status without separate metadata and
-    we have kernels with fixed snapshot leak bug.
-    
-    (in-release update)
----
- lib/metadata/snapshot_manip.c |  4 ++--
- lib/snapshot/snapshot.c       |  3 +++
- test/shell/snapshot-usage.sh  | 31 ++++++++++++++++++++++++-------
- 3 files changed, 29 insertions(+), 9 deletions(-)
-
-diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c
-index 25fee76..8fcab0c 100644
---- a/lib/metadata/snapshot_manip.c
-+++ b/lib/metadata/snapshot_manip.c
-@@ -46,9 +46,9 @@ static uint64_t _cow_extra_chunks(struct cmd_context *cmd, uint64_t n_chunks)
- 	    segtype->ops->target_present &&
- 	    segtype->ops->target_present(cmd, NULL, &attrs) &&
- 	    (attrs & SNAPSHOT_FEATURE_FIXED_LEAK))
--		return (n_chunks + 63) / 64;
-+		return 0;
- 
--	return 0;
-+	return (n_chunks + 63) / 64;
- }
- 
- static uint64_t _cow_max_size(struct cmd_context *cmd, uint64_t origin_size, uint32_t chunk_size)
-diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c
-index 0b7b845..64919b0 100644
---- a/lib/snapshot/snapshot.c
-+++ b/lib/snapshot/snapshot.c
-@@ -165,6 +165,9 @@ static int _snap_target_present(struct cmd_context *cmd,
- 			log_very_verbose("Target snapshot may leak metadata.");
- 	}
- 
-+	if (attributes)
-+		*attributes = _snap_attrs;
-+
- 	/* TODO: test everything at once */
- 	if (seg && (seg->status & MERGING)) {
- 		if (!_snap_merge_checked) {
-diff --git a/test/shell/snapshot-usage.sh b/test/shell/snapshot-usage.sh
-index cb60556..bd0723d 100644
---- a/test/shell/snapshot-usage.sh
-+++ b/test/shell/snapshot-usage.sh
-@@ -33,6 +33,25 @@ vgcreate -s 4M $vg $(cat DEVICES)
- TSIZE=15P
- aux can_use_16T || TSIZE=15T
- 
-+# With different snapshot target driver we may obtain different results.
-+# Older targets have metadata leak bug which needs extra compenstion.
-+# Ancient targets do not even provide separate info for metadata.
-+EXPECT1="16.00k"
-+EXPECT2="512.00k"
-+EXPECT3="32.00k"
-+EXPECT4="66.67"
-+if aux target_at_least dm-snapshot 1 10 0 ; then
-+	# Extra metadata size
-+	EXPECT4="0.00"
-+
-+	if aux target_at_least dm-snapshot 1 12 0 ; then
-+		# When fixed leak, expect smaller sizes
-+		EXPECT1="12.00k"
-+		EXPECT2="384.00k"
-+		EXPECT3="28.00k"
-+	fi
-+fi
-+
- lvcreate -s -l 100%FREE -n $lv $vg --virtualsize $TSIZE
- 
- aux extend_filter_LVMTEST
-@@ -86,12 +105,12 @@ lvcreate -an -Zn -l1 -n $lv1 $vg1
- not lvcreate -s -l1 $vg1/$lv1
- not lvcreate -s -l3 $vg1/$lv1
- lvcreate -s -l30 -n $lv2 $vg1/$lv1
--check lv_field $vg1/$lv2 size "12.00k"
-+check lv_field $vg1/$lv2 size "$EXPECT1"
- 
- not lvcreate -s -c512 -l512 $vg1/$lv1
- lvcreate -s -c128 -l1700 -n $lv3 $vg1/$lv1
- # 3 * 128
--check lv_field $vg1/$lv3 size "384.00k"
-+check lv_field $vg1/$lv3 size "$EXPECT2"
- lvremove -ff $vg1
- 
- lvcreate -aey -l20 $vg1
-@@ -110,7 +129,7 @@ lvextend --use-policies $vg1/lvol1
- check lv_field $vg1/lvol1 size "18.00k"
- 
- lvextend -l+33 $vg1/lvol1
--check lv_field $vg1/lvol1 size "32.00k"
-+check lv_field $vg1/lvol1 size "$EXPECT3"
- 
- fill 20K
- lvremove -f $vg1
-@@ -138,14 +157,12 @@ fsck -n "$DM_DEV_DIR/$vg1/snap"
- # This test would trigger read of weird percentage for undeleted header
- # And since older snapshot target counts with metadata sectors
- # we have 2 valid results  (unsure about correct version number)
--EXPECT="0.00"
--aux target_at_least dm-snapshot 1 10 0 || EXPECT="66.67"
--check lv_field $vg1/snap data_percent "$EXPECT"
-+check lv_field $vg1/snap data_percent "$EXPECT4"
- 
- vgremove -ff $vg1
- 
- # Can't test >= 16T devices on 32bit
--if test "$TSIZE" -eq 15P ; then
-+if test "$TSIZE" = 15P ; then
- 
- # Check usability with largest extent size
- pvcreate "$DM_DEV_DIR/$vg/$lv"
diff --git a/SOURCES/lvm2-2_02_106-fix-timeout-for-initial-lvmetad-scan-when-done-in-parallel.patch b/SOURCES/lvm2-2_02_106-fix-timeout-for-initial-lvmetad-scan-when-done-in-parallel.patch
deleted file mode 100644
index c4c73f4..0000000
--- a/SOURCES/lvm2-2_02_106-fix-timeout-for-initial-lvmetad-scan-when-done-in-parallel.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-commit a7864d8f81e29dd7228c16f35314843e2f0c7b86
-Author: Peter Rajnoha <prajnoha@redhat.com>
-Date:   Wed Mar 26 09:09:33 2014 +0100
-
-    0
----
- lib/cache/lvmetad.c              | 16 +++++++++++-----
- libdaemon/client/daemon-client.h |  2 +-
- 2 files changed, 12 insertions(+), 6 deletions(-)
-
-diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
-index 38d9042..c019250 100644
---- a/lib/cache/lvmetad.c
-+++ b/lib/cache/lvmetad.c
-@@ -143,6 +143,7 @@ static daemon_reply _lvmetad_send(const char *id, ...)
- 	daemon_reply repl;
- 	daemon_request req;
- 	int try = 0;
-+	int time = 0, wait, sleep = 1;
- 
- retry:
- 	req = daemon_request_make(id);
-@@ -159,7 +160,7 @@ retry:
- 	daemon_request_destroy(req);
- 
- 	if (!repl.error && !strcmp(daemon_reply_str(repl, "response", ""), "token_mismatch") &&
--	    try < 60 && !test_mode()) {
-+	    try < 10 && time < 80000000 && !test_mode()) {
- 		/*
- 		 * If another process is trying to scan, they might have the
- 		 * same future token id and it's better to wait and avoid doing
-@@ -172,12 +173,17 @@ retry:
- 		 * the update, we back off for a short while (0.2-2 seconds) and
- 		 * try again.
- 		 */
--		if (!strcmp(daemon_reply_str(repl, "expected", ""), "update in progress") || try % 5)
--			usleep( 50000 + random() % 450000 ); /* 0.05 - 0.5s */
--		else
-+		if (!strcmp(daemon_reply_str(repl, "expected", ""), "update in progress") || sleep) {
-+			wait = 50000 + random() % 450000; /* 0.05 - 0.5s */
-+			time += wait;
-+			usleep( wait );
-+			-- sleep;
-+		} else {
- 			/* If the re-scan fails here, we try again later. */
- 			lvmetad_pvscan_all_devs(_lvmetad_cmd, NULL);
--		++ try;
-+			++ try;
-+			sleep = 5;
-+		}
- 		daemon_reply_destroy(repl);
- 		goto retry;
- 	}
-diff --git a/libdaemon/client/daemon-client.h b/libdaemon/client/daemon-client.h
-index 6ba65e6..8a44f8b 100644
---- a/libdaemon/client/daemon-client.h
-+++ b/libdaemon/client/daemon-client.h
-@@ -102,7 +102,7 @@ static inline int64_t daemon_reply_int(daemon_reply r, const char *path, int64_t
- }
- 
- static inline const char *daemon_reply_str(daemon_reply r, const char *path, const char *def) {
--	return dm_config_find_str(r.cft->root, path, def);
-+	return dm_config_find_str_allow_empty(r.cft->root, path, def);
- }
- 
- 
diff --git a/SOURCES/lvm2-2_02_106-reinitialise-lvmcache-properly-on-fork-to-fix-premature-polldaemon-exit.patch b/SOURCES/lvm2-2_02_106-reinitialise-lvmcache-properly-on-fork-to-fix-premature-polldaemon-exit.patch
deleted file mode 100644
index 2563f9b..0000000
--- a/SOURCES/lvm2-2_02_106-reinitialise-lvmcache-properly-on-fork-to-fix-premature-polldaemon-exit.patch
+++ /dev/null
@@ -1,185 +0,0 @@
-commit 129b8f8e525126f660fa22f88ee58cd086c5f338
-Author: Peter Rajnoha <prajnoha@redhat.com>
-Date:   Tue Mar 25 11:01:23 2014 +0100
-
-    lvmcache init
----
- WHATS_NEW                       |  1 +
- lib/cache/lvmcache.c            |  9 ++++++---
- lib/cache/lvmcache.h            |  2 +-
- lib/commands/toolcontext.c      |  4 ++--
- test/shell/pvmove-background.sh | 24 ++++++++++++++++++++++++
- tools/lvmcmdline.c              |  2 +-
- tools/pvscan.c                  |  2 +-
- tools/toollib.c                 |  1 +
- tools/vgrename.c                |  2 +-
- tools/vgscan.c                  |  2 +-
- 10 files changed, 39 insertions(+), 10 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index b5afb19..cf6103d 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,6 @@
- Version 2.02.106 - 
- ====================================
-+  Reinitialise lvmcache properly on fork to fix polldaemon exiting prematurely.
-   Use VG read lock during 'pvscan --cache -aay' autoactivation.
-   Issue a VG refresh before autoactivation only if the PV has changed/is new.
-   Add flag to lvmetad protocol to indicate the PV scanned has changed/is new.
-diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
-index d40bdce..fe64c8a 100644
---- a/lib/cache/lvmcache.c
-+++ b/lib/cache/lvmcache.c
-@@ -1609,7 +1609,7 @@ static void _lvmcache_destroy_lockname(struct dm_hash_node *n)
- 			  dm_hash_get_key(_lock_hash, n));
- }
- 
--void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
-+void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
- {
- 	struct dm_hash_node *n;
- 	log_verbose("Wiping internal VG cache");
-@@ -1635,8 +1635,11 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
- 	}
- 
- 	if (_lock_hash) {
--		dm_hash_iterate(n, _lock_hash)
--			_lvmcache_destroy_lockname(n);
-+		if (reset)
-+			_vg_global_lock_held = 0;
-+		else
-+			dm_hash_iterate(n, _lock_hash)
-+				_lvmcache_destroy_lockname(n);
- 		dm_hash_destroy(_lock_hash);
- 		_lock_hash = NULL;
- 	}
-diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
-index bf26664..83d561b 100644
---- a/lib/cache/lvmcache.h
-+++ b/lib/cache/lvmcache.h
-@@ -42,7 +42,7 @@ struct lvmcache_vginfo;
- int lvmcache_init(void);
- void lvmcache_allow_reads_with_lvmetad(void);
- 
--void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
-+void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset);
- 
- /* Set full_scan to 1 to reread every filtered device label or
-  * 2 to rescan /dev for new devices */
-diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
-index a709284..d08ca61 100644
---- a/lib/commands/toolcontext.c
-+++ b/lib/commands/toolcontext.c
-@@ -1640,7 +1640,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
- 	 */
- 
- 	activation_release();
--	lvmcache_destroy(cmd, 0);
-+	lvmcache_destroy(cmd, 0, 0);
- 	label_exit();
- 	_destroy_segtypes(&cmd->segtypes);
- 	_destroy_formats(cmd, &cmd->formats);
-@@ -1732,7 +1732,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
- 
- 	archive_exit(cmd);
- 	backup_exit(cmd);
--	lvmcache_destroy(cmd, 0);
-+	lvmcache_destroy(cmd, 0, 0);
- 	label_exit();
- 	_destroy_segtypes(&cmd->segtypes);
- 	_destroy_formats(cmd, &cmd->formats);
-diff --git a/test/shell/pvmove-background.sh b/test/shell/pvmove-background.sh
-new file mode 100644
-index 0000000..0f657be
---- /dev/null
-+++ b/test/shell/pvmove-background.sh
-@@ -0,0 +1,24 @@
-+#!/bin/sh
-+# Copyright (C) 2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+# Check pvmove behavior when it's progress and machine is rebooted
-+
-+. lib/test
-+
-+aux prepare_vg 3
-+
-+lvcreate -l1 -n $lv1 $vg "$dev1"
-+
-+lvs -o +devices | grep $dev1
-+pvmove -i 1 -b "$dev1" "$dev2"
-+sleep 5 # arbitrary...
-+lvs -o +devices | not grep "pvmove"
-+lvs -o +devices | grep "$dev2"
-diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
-index 6fe4670..e70e64a 100644
---- a/tools/lvmcmdline.c
-+++ b/tools/lvmcmdline.c
-@@ -1183,7 +1183,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
-       out:
- 	if (test_mode()) {
- 		log_verbose("Test mode: Wiping internal cache");
--		lvmcache_destroy(cmd, 1);
-+		lvmcache_destroy(cmd, 1, 0);
- 	}
- 
- 	if ((old_cft = remove_config_tree_by_source(cmd, CONFIG_STRING))) {
-diff --git a/tools/pvscan.c b/tools/pvscan.c
-index 5db627a..af834fe 100644
---- a/tools/pvscan.c
-+++ b/tools/pvscan.c
-@@ -373,7 +373,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
- 
- 	if (cmd->filter->wipe)
- 		cmd->filter->wipe(cmd->filter);
--	lvmcache_destroy(cmd, 1);
-+	lvmcache_destroy(cmd, 1, 0);
- 
- 	/* populate lvmcache */
- 	if (!lvmetad_vg_list_to_lvmcache(cmd))
-diff --git a/tools/toollib.c b/tools/toollib.c
-index 91b0559..6b68f55 100644
---- a/tools/toollib.c
-+++ b/tools/toollib.c
-@@ -92,6 +92,7 @@ int become_daemon(struct cmd_context *cmd, int skip_lvm)
- 
- 	if (!skip_lvm) {
- 		reset_locking();
-+		lvmcache_destroy(cmd, 1, 1);
- 		if (!lvmcache_init())
- 			/* FIXME Clean up properly here */
- 			_exit(ECMD_FAILED);
-diff --git a/tools/vgrename.c b/tools/vgrename.c
-index b5e778f..d97b871 100644
---- a/tools/vgrename.c
-+++ b/tools/vgrename.c
-@@ -185,7 +185,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
- 	/* FIXME lvmcache corruption - vginfo duplicated instead of renamed */
- 	if (cmd->filter->wipe)
- 		cmd->filter->wipe(cmd->filter);
--	lvmcache_destroy(cmd, 1);
-+	lvmcache_destroy(cmd, 1, 0);
- 
- 	return 1;
- 
-diff --git a/tools/vgscan.c b/tools/vgscan.c
-index baf25b0..fff0e89 100644
---- a/tools/vgscan.c
-+++ b/tools/vgscan.c
-@@ -44,7 +44,7 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
- 
- 	if (cmd->filter->wipe)
- 		cmd->filter->wipe(cmd->filter);
--	lvmcache_destroy(cmd, 1);
-+	lvmcache_destroy(cmd, 1, 0);
- 
- 	if (arg_count(cmd, cache_ARG)) {
- 		if (lvmetad_active()) {
diff --git a/SOURCES/lvm2-2_02_106-upstream-with-cache-support.patch b/SOURCES/lvm2-2_02_106-upstream-with-cache-support.patch
deleted file mode 100644
index b9b3d8c..0000000
--- a/SOURCES/lvm2-2_02_106-upstream-with-cache-support.patch
+++ /dev/null
@@ -1,13782 +0,0 @@
-commit 8cb42e4d9a3f46998defef78bb5bc38971ef3870
-Author: Peter Rajnoha <prajnoha@redhat.com>
-Date:   Wed Feb 26 16:19:41 2014 +0100
-
-    v106+cache
----
- WHATS_NEW                                          |  42 +-
- WHATS_NEW_DM                                       |  12 +
- autoconf/config.guess                              | 415 +++++++++-------
- autoconf/config.sub                                | 288 +++++++----
- conf/example.conf.in                               |  28 +-
- configure                                          |  37 +-
- configure.in                                       |  26 +
- daemons/dmeventd/dmeventd.c                        | 145 +++++-
- daemons/dmeventd/dmeventd.h                        |   1 +
- daemons/dmeventd/libdevmapper-event.c              |   7 +
- daemons/dmeventd/libdevmapper-event.h              |   2 +-
- daemons/lvmetad/lvmetad-core.c                     |  20 +-
- lib/Makefile.in                                    |  13 +-
- lib/activate/activate.c                            | 168 +++++++
- lib/activate/activate.h                            |  17 +
- lib/activate/dev_manager.c                         |  68 ++-
- lib/activate/dev_manager.h                         |   3 +
- lib/cache/lvmcache.c                               |   4 +-
- lib/cache/lvmetad.c                                |  29 +-
- lib/cache_segtype/.exported_symbols                |   1 +
- lib/cache_segtype/Makefile.in                      |  24 +
- lib/cache_segtype/cache.c                          | 448 +++++++++++++++++
- lib/commands/toolcontext.c                         |   9 +-
- lib/config/config.c                                |  41 +-
- lib/config/config.h                                |  11 +-
- lib/config/config_settings.h                       |  47 +-
- lib/config/defaults.h                              |   7 +-
- lib/device/dev-io.c                                |   4 +-
- lib/device/dev-type.c                              |  71 ++-
- lib/device/dev-type.h                              |   6 +-
- lib/device/device-types.h                          |   9 +-
- lib/display/display.c                              |  16 +
- lib/display/display.h                              |   3 +
- lib/format_text/export.c                           |   6 +-
- lib/format_text/flags.c                            |   4 +
- lib/format_text/format-text.c                      |  16 +-
- lib/format_text/tags.c                             |  10 +-
- lib/label/label.c                                  |   1 -
- lib/locking/file_locking.c                         |  17 +-
- lib/metadata/cache_manip.c                         | 278 +++++++++++
- lib/metadata/lv.c                                  |  47 +-
- lib/metadata/lv_alloc.h                            |   2 +-
- lib/metadata/lv_manip.c                            | 543 +++++++++++++++-----
- lib/metadata/merge.c                               |  60 ++-
- lib/metadata/metadata-exported.h                   |  66 ++-
- lib/metadata/metadata.c                            |  65 ++-
- lib/metadata/metadata.h                            |   2 +-
- lib/metadata/mirror.c                              |  14 +-
- lib/metadata/pool_manip.c                          | 325 ++++++++++++
- lib/metadata/raid_manip.c                          |  10 +-
- lib/metadata/segtype.h                             |  10 +
- lib/metadata/snapshot_manip.c                      |  46 +-
- lib/metadata/thin_manip.c                          | 282 ++---------
- lib/metadata/vg.c                                  |   1 +
- lib/metadata/vg.h                                  |   1 +
- lib/mirror/mirrored.c                              |  51 +-
- lib/misc/configure.h.in                            |   3 +
- lib/misc/lvm-exec.c                                |   1 -
- lib/raid/raid.c                                    |  40 +-
- lib/report/report.c                                |  17 +-
- lib/snapshot/snapshot.c                            |  15 +-
- lib/thin/thin.c                                    |  35 +-
- libdm/libdevmapper.h                               | 134 +++--
- libdm/libdm-common.c                               |  19 +-
- libdm/libdm-deptree.c                              | 438 ++++++++++++++---
- liblvm/lvm_lv.c                                    |  21 +-
- make.tmpl.in                                       |   1 +
- man/lvchange.8.in                                  |   5 +-
- man/lvconvert.8.in                                 |  46 +-
- man/lvcreate.8.in                                  |  61 ++-
- man/lvextend.8.in                                  |   7 +
- man/lvm.8.in                                       | 199 ++++++++
- man/lvm.conf.5.in                                  |   2 +-
- man/lvreduce.8.in                                  |   6 +
- man/lvresize.8.in                                  |  11 +-
- man/lvs.8.in                                       |   4 +-
- man/vgchange.8.in                                  |   7 +-
- python/liblvm.c                                    |  25 +-
- scripts/Makefile.in                                |  13 +-
- scripts/dm_event_systemd_red_hat.service.in        |   5 +-
- .../lvm2_activation_generator_systemd_red_hat.c    |   2 +-
- scripts/lvm2_cluster_activation_red_hat.sh.in      |  70 +++
- ...2_cluster_activation_systemd_red_hat.service.in |  17 +
- scripts/lvm2_clvmd_systemd_red_hat.service.in      |  23 +
- scripts/lvm2_cmirrord_systemd_red_hat.service.in   |  17 +
- scripts/lvm2_lvmetad_systemd_red_hat.service.in    |   5 +-
- scripts/lvm2_monitoring_init_red_hat.in            |   8 +-
- scripts/lvm2_monitoring_systemd_red_hat.service.in |   4 +-
- test/api/pytest.sh                                 |  15 +-
- test/lib/aux.sh                                    |   7 +-
- test/lib/check.sh                                  |  17 +-
- test/lib/get.sh                                    |   7 +
- test/lib/test.sh                                   |   2 +-
- test/shell/activation-skip.sh                      |  32 ++
- test/shell/lock-parallel.sh                        |  40 ++
- test/shell/lvchange-partial.sh                     |   6 +-
- test/shell/lvchange-raid.sh                        | 146 +++---
- test/shell/lvconvert-mirror-updown.sh              |  36 ++
- test/shell/lvconvert-mirror.sh                     |   4 +
- test/shell/lvconvert-repair-dmeventd.sh            |   4 +-
- test/shell/lvconvert-repair-thin.sh                |  26 +-
- test/shell/lvconvert-repair-transient-dmeventd.sh  |   2 +-
- test/shell/lvconvert-repair-transient.sh           |   2 +-
- test/shell/lvconvert-thin-external.sh              |  20 +-
- test/shell/lvcreate-cache.sh                       | 137 ++++++
- test/shell/lvcreate-large-raid.sh                  |   4 +-
- test/shell/lvcreate-large-raid10.sh                |   4 +-
- test/shell/lvcreate-large.sh                       |   4 +-
- test/shell/lvcreate-pvtags.sh                      |   2 +-
- test/shell/lvcreate-raid.sh                        | 118 +++++
- test/shell/lvcreate-raid10.sh                      |  33 +-
- test/shell/lvcreate-thin-external.sh               |  18 +-
- test/shell/lvcreate-thin-snap.sh                   |   8 +-
- test/shell/lvcreate-thin.sh                        |   4 +-
- test/shell/lvextend-thin-metadata-dmeventd.sh      |  93 ++++
- test/shell/lvmetad-disabled.sh                     |  13 +-
- test/shell/lvresize-thin-external-origin.sh        |  42 ++
- test/shell/lvresize-thin-metadata.sh               |  26 +-
- test/shell/lvresize-usage.sh                       |   9 +-
- test/shell/name-mangling.sh                        |   4 +-
- test/shell/process-each-lv.sh                      | 545 +++++----------------
- test/shell/pvmove-all-segtypes.sh                  |  25 +-
- test/shell/pvmove-cache-segtypes.sh                | 178 +++++++
- test/shell/read-ahead.sh                           |   2 +-
- test/shell/snapshot-usage.sh                       |  49 +-
- test/shell/thin-merge.sh                           |  23 +-
- test/shell/thin-vglock.sh                          |  51 ++
- test/shell/vgsplit-stacked.sh                      |   4 +-
- tools/Makefile.in                                  |   3 +-
- tools/args.h                                       |   2 +
- tools/commands.h                                   |  38 +-
- tools/dumpconfig.c                                 |  10 +-
- tools/lvchange.c                                   |   5 +-
- tools/lvconvert.c                                  | 229 +++++++--
- tools/lvcreate.c                                   | 311 +++++++++---
- tools/pvmove.c                                     |  43 ++
- tools/tags.c                                       |  23 +
- tools/toollib.c                                    |  97 ++--
- tools/toollib.h                                    |   4 +-
- tools/vgchange.c                                   |  25 +-
- tools/vgsplit.c                                    |  79 +++
- udev/10-dm.rules.in                                |   6 -
- udev/69-dm-lvm-metad.rules.in                      |   3 +
- 143 files changed, 5891 insertions(+), 1889 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 26b63ae..224e351 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,3 +1,43 @@
-+Version 2.02.106 - 
-+====================================
-+  Fix calculation of maximum size of COW device for snapshot (2.02.99).
-+  Do not allow stripe size to be bigger then extent size for lvresize.
-+  Zero snapshot COW header when creating read-only snapshot.
-+  Comment out config lines in dumpconfig output without default values defined.
-+  Improve detection of clustered mirror support.
-+  Enhance raid code with feature flags, for now checks for raid10.
-+  Move parsing of VG metadata from vg_commit() back to vg_write() (2.02.99)
-+  Avoid a PV label scan while in a critical section.
-+  Remove (always 0) skip argument from lv_activation_skip().
-+  Create /dev/disk/by-id/lvm-pv-uuid-<PV_UUID> symlink for each PV via udev.
-+  lvcreate computes RAID4/5/6 stripes if not given from # of allocatable PVs.
-+  Fix merging of old snapshot into thin volume origin.
-+  Use --ignoreskippedcluster in lvm2-monitor initscript/systemd unit.
-+  Do not use VG read/write state for LV read/write state.
-+  Use --ignoreskippedcluster in activation systemd units if use_lvmetad=0.
-+  Allow approximate allocation when specifying size in percentage terms.
-+  Add basic LVM support for cache[pool] segment types.
-+  Use local exclusive activation for creation of raid in cluster.
-+  Use correctly signed 64b constant when selecting raid volumes.
-+  Add systemd native service for clvmd, cmirrord and clustered LV activation.
-+  Remove ExecReload from lvmetad systemd unit: lvmetad -R undefined. (2.02.98)
-+  Do not fork lvmetad if running under systemd.
-+  Wipe DM_snapshot_cow signature without prompt in new LVs with blkid wiping.
-+  Avoid exposing temporary devices when initializing raid metadata volumes.
-+  Add internal tags command to display any tags defined on the host.
-+  Prohibit use of external origin with size incompatible with thin pool.
-+  Avoid trying to convert single to thin pool and volume at the same time.
-+  Add support for partitions on ZFS zvol.
-+  Fix unwanted drop of hold flocks on forked children.
-+  Respect LVM_LVMETAD_PIDFILE env var for lvm command.
-+  Avoid exposing temporary devices when initializing thin pool volume.
-+  Fix test when checking target version for available thin features.
-+  Detect thin feature external_origin_extend and limit extend when missing.
-+  Rename internal pool_can_resize_metadata() to thin_pool_feature_supported().
-+  Issue error if libbblkid detects signature and fails to return offset/length.
-+  Update autoconf config.guess/sub to 2014-01-01.
-+  Online thin pool metadata resize requires 1.10 kernel thin pool target.
-+
- Version 2.02.105 - 20th January 2014
- ====================================
-   Fix thin LV flagging for udev to skip scanning only if the LV is wiped.
-@@ -31,7 +71,7 @@ Version 2.02.105 - 20th January 2014
-   Add --splitsnapshot to lvconvert to separate out cow LV.
-   Reinstate origin reload to complete lvconvert -s with active LVs. (2.02.98)
-   Select only active volume groups if vgdisplay -A is used.
--  Add -p and LVM_LVMETAD_PID env var to lvmetad to change pid file.
-+  Add -p and LVM_LVMETAD_PIDFILE env var to lvmetad to change pid file.
-   Allow lvmetad to reuse stale socket.
-   Only unlink lvmetad socket on error if created by the same process.
-   Append missing newline to lvmetad missing socket path error message.
-diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
-index ce302f3..32c2265 100644
---- a/WHATS_NEW_DM
-+++ b/WHATS_NEW_DM
-@@ -1,3 +1,15 @@
-+Version 1.02.85 - 
-+===================================
-+  Reuse _node_send_messages() for validation of transaction_id in preload.
-+  Transaction_id could be lower by one only when messages are prepared.
-+  Do not call callback when preload fails.
-+  Wrap is_selinux_enabled() to be called just once.
-+  Use correctly signed 64b constant when working with raid volumes.
-+  Exit dmeventd with pidfile cleanup instead of raising SIGKILL on DIE request.
-+  Add new DM_EVENT_GET_PARAMETERS request to dmeventd protocol.
-+  Do not use systemd's reload for dmeventd restart, use dmeventd -R instead.
-+  Drop cryptsetup rules from 10-dm.rules - cryptsetup >= 1.1.3 sets them.
-+
- Version 1.02.84 - 20th January 2014
- ===================================
-   Revert activation of activated nodes if a node preload callback fails.
-diff --git a/autoconf/config.guess b/autoconf/config.guess
-index dc84c68..4438cd7 100755
---- a/autoconf/config.guess
-+++ b/autoconf/config.guess
-@@ -1,14 +1,12 @@
- #! /bin/sh
- # Attempt to guess a canonical system name.
--#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
--#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
--#   Free Software Foundation, Inc.
-+#   Copyright 1992-2014 Free Software Foundation, Inc.
- 
--timestamp='2009-11-20'
-+timestamp='2014-01-01'
- 
- # This file is free software; you can redistribute it and/or modify it
- # under the terms of the GNU General Public License as published by
--# the Free Software Foundation; either version 2 of the License, or
-+# the Free Software Foundation; either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful, but
-@@ -17,26 +15,22 @@ timestamp='2009-11-20'
- # General Public License for more details.
- #
- # 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.
-+# along with this program; if not, see <http://www.gnu.org/licenses/>.
- #
- # As a special exception to the GNU General Public License, if you
- # distribute this file as part of a program that contains a
- # configuration script generated by Autoconf, you may include it under
--# the same distribution terms that you use for the rest of that program.
--
--
--# Originally written by Per Bothner.  Please send patches (context
--# diff format) to <config-patches@gnu.org> and include a ChangeLog
--# entry.
-+# the same distribution terms that you use for the rest of that
-+# program.  This Exception is an additional permission under section 7
-+# of the GNU General Public License, version 3 ("GPLv3").
- #
--# This script attempts to guess a canonical system name similar to
--# config.sub.  If it succeeds, it prints the system name on stdout, and
--# exits with 0.  Otherwise, it exits with 1.
-+# Originally written by Per Bothner.
- #
- # You can get the latest version of this script from:
- # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
-+#
-+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
-+
- 
- me=`echo "$0" | sed -e 's,.*/,,'`
- 
-@@ -56,8 +50,7 @@ version="\
- GNU config.guess ($timestamp)
- 
- Originally written by Per Bothner.
--Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
--2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-+Copyright 1992-2014 Free Software Foundation, Inc.
- 
- This is free software; see the source for copying conditions.  There is NO
- warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-@@ -139,12 +132,33 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
- UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
- UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
- 
-+case "${UNAME_SYSTEM}" in
-+Linux|GNU|GNU/*)
-+	# If the system lacks a compiler, then just pick glibc.
-+	# We could probably try harder.
-+	LIBC=gnu
-+
-+	eval $set_cc_for_build
-+	cat <<-EOF > $dummy.c
-+	#include <features.h>
-+	#if defined(__UCLIBC__)
-+	LIBC=uclibc
-+	#elif defined(__dietlibc__)
-+	LIBC=dietlibc
-+	#else
-+	LIBC=gnu
-+	#endif
-+	EOF
-+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
-+	;;
-+esac
-+
- # Note: order is significant - the case branches are not exclusive.
- 
- case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
-     *:NetBSD:*:*)
- 	# NetBSD (nbsd) targets should (where applicable) match one or
--	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
-+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
- 	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
- 	# switched to ELF, *-*-netbsd* would select the old
- 	# object file format.  This provides both forward
-@@ -180,7 +194,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- 		fi
- 		;;
- 	    *)
--	        os=netbsd
-+		os=netbsd
- 		;;
- 	esac
- 	# The OS release
-@@ -201,6 +215,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- 	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- 	echo "${machine}-${os}${release}"
- 	exit ;;
-+    *:Bitrig:*:*)
-+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
-+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
-+	exit ;;
-     *:OpenBSD:*:*)
- 	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- 	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
-@@ -223,7 +241,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- 		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
- 		;;
- 	*5.*)
--	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
-+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
- 		;;
- 	esac
- 	# According to Compaq, /usr/sbin/psrinfo has been available on
-@@ -269,7 +287,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- 	# A Xn.n version is an unreleased experimental baselevel.
- 	# 1.2 uses "1.2" for uname -r.
- 	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
--	exit ;;
-+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
-+	exitcode=$?
-+	trap '' 0
-+	exit $exitcode ;;
-     Alpha\ *:Windows_NT*:*)
- 	# How do we know it's Interix rather than the generic POSIX subsystem?
- 	# Should we change UNAME_MACHINE based on the output of uname instead
-@@ -295,12 +316,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- 	echo s390-ibm-zvmoe
- 	exit ;;
-     *:OS400:*:*)
--        echo powerpc-ibm-os400
-+	echo powerpc-ibm-os400
- 	exit ;;
-     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- 	echo arm-acorn-riscix${UNAME_RELEASE}
- 	exit ;;
--    arm:riscos:*:*|arm:RISCOS:*:*)
-+    arm*:riscos:*:*|arm*:RISCOS:*:*)
- 	echo arm-unknown-riscos
- 	exit ;;
-     SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
-@@ -394,23 +415,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
-     # MiNT.  But MiNT is downward compatible to TOS, so this should
-     # be no problem.
-     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
--        echo m68k-atari-mint${UNAME_RELEASE}
-+	echo m68k-atari-mint${UNAME_RELEASE}
- 	exit ;;
-     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- 	echo m68k-atari-mint${UNAME_RELEASE}
--        exit ;;
-+	exit ;;
-     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
--        echo m68k-atari-mint${UNAME_RELEASE}
-+	echo m68k-atari-mint${UNAME_RELEASE}
- 	exit ;;
-     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
--        echo m68k-milan-mint${UNAME_RELEASE}
--        exit ;;
-+	echo m68k-milan-mint${UNAME_RELEASE}
-+	exit ;;
-     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
--        echo m68k-hades-mint${UNAME_RELEASE}
--        exit ;;
-+	echo m68k-hades-mint${UNAME_RELEASE}
-+	exit ;;
-     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
--        echo m68k-unknown-mint${UNAME_RELEASE}
--        exit ;;
-+	echo m68k-unknown-mint${UNAME_RELEASE}
-+	exit ;;
-     m68k:machten:*:*)
- 	echo m68k-apple-machten${UNAME_RELEASE}
- 	exit ;;
-@@ -480,8 +501,8 @@ EOF
- 	echo m88k-motorola-sysv3
- 	exit ;;
-     AViiON:dgux:*:*)
--        # DG/UX returns AViiON for all architectures
--        UNAME_PROCESSOR=`/usr/bin/uname -p`
-+	# DG/UX returns AViiON for all architectures
-+	UNAME_PROCESSOR=`/usr/bin/uname -p`
- 	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
- 	then
- 	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
-@@ -494,7 +515,7 @@ EOF
- 	else
- 	    echo i586-dg-dgux${UNAME_RELEASE}
- 	fi
-- 	exit ;;
-+	exit ;;
-     M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
- 	echo m88k-dolphin-sysv3
- 	exit ;;
-@@ -551,7 +572,7 @@ EOF
- 		echo rs6000-ibm-aix3.2
- 	fi
- 	exit ;;
--    *:AIX:*:[456])
-+    *:AIX:*:[4567])
- 	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- 	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
- 		IBM_ARCH=rs6000
-@@ -594,52 +615,52 @@ EOF
- 	    9000/[678][0-9][0-9])
- 		if [ -x /usr/bin/getconf ]; then
- 		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
--                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
--                    case "${sc_cpu_version}" in
--                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
--                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
--                      532)                      # CPU_PA_RISC2_0
--                        case "${sc_kernel_bits}" in
--                          32) HP_ARCH="hppa2.0n" ;;
--                          64) HP_ARCH="hppa2.0w" ;;
-+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-+		    case "${sc_cpu_version}" in
-+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
-+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
-+		      532)                      # CPU_PA_RISC2_0
-+			case "${sc_kernel_bits}" in
-+			  32) HP_ARCH="hppa2.0n" ;;
-+			  64) HP_ARCH="hppa2.0w" ;;
- 			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
--                        esac ;;
--                    esac
-+			esac ;;
-+		    esac
- 		fi
- 		if [ "${HP_ARCH}" = "" ]; then
- 		    eval $set_cc_for_build
--		    sed 's/^              //' << EOF >$dummy.c
-+		    sed 's/^		//' << EOF >$dummy.c
- 
--              #define _HPUX_SOURCE
--              #include <stdlib.h>
--              #include <unistd.h>
-+		#define _HPUX_SOURCE
-+		#include <stdlib.h>
-+		#include <unistd.h>
- 
--              int main ()
--              {
--              #if defined(_SC_KERNEL_BITS)
--                  long bits = sysconf(_SC_KERNEL_BITS);
--              #endif
--                  long cpu  = sysconf (_SC_CPU_VERSION);
-+		int main ()
-+		{
-+		#if defined(_SC_KERNEL_BITS)
-+		    long bits = sysconf(_SC_KERNEL_BITS);
-+		#endif
-+		    long cpu  = sysconf (_SC_CPU_VERSION);
- 
--                  switch (cpu)
--              	{
--              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
--              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
--              	case CPU_PA_RISC2_0:
--              #if defined(_SC_KERNEL_BITS)
--              	    switch (bits)
--              		{
--              		case 64: puts ("hppa2.0w"); break;
--              		case 32: puts ("hppa2.0n"); break;
--              		default: puts ("hppa2.0"); break;
--              		} break;
--              #else  /* !defined(_SC_KERNEL_BITS) */
--              	    puts ("hppa2.0"); break;
--              #endif
--              	default: puts ("hppa1.0"); break;
--              	}
--                  exit (0);
--              }
-+		    switch (cpu)
-+			{
-+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-+			case CPU_PA_RISC2_0:
-+		#if defined(_SC_KERNEL_BITS)
-+			    switch (bits)
-+				{
-+				case 64: puts ("hppa2.0w"); break;
-+				case 32: puts ("hppa2.0n"); break;
-+				default: puts ("hppa2.0"); break;
-+				} break;
-+		#else  /* !defined(_SC_KERNEL_BITS) */
-+			    puts ("hppa2.0"); break;
-+		#endif
-+			default: puts ("hppa1.0"); break;
-+			}
-+		    exit (0);
-+		}
- EOF
- 		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
- 		    test -z "$HP_ARCH" && HP_ARCH=hppa
-@@ -730,22 +751,22 @@ EOF
- 	exit ;;
-     C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
- 	echo c1-convex-bsd
--        exit ;;
-+	exit ;;
-     C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
- 	if getsysinfo -f scalar_acc
- 	then echo c32-convex-bsd
- 	else echo c2-convex-bsd
- 	fi
--        exit ;;
-+	exit ;;
-     C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
- 	echo c34-convex-bsd
--        exit ;;
-+	exit ;;
-     C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
- 	echo c38-convex-bsd
--        exit ;;
-+	exit ;;
-     C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
- 	echo c4-convex-bsd
--        exit ;;
-+	exit ;;
-     CRAY*Y-MP:*:*:*)
- 	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- 	exit ;;
-@@ -769,14 +790,14 @@ EOF
- 	exit ;;
-     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- 	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
--        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
--        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
--        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
--        exit ;;
-+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-+	exit ;;
-     5000:UNIX_System_V:4.*:*)
--        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
--        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
--        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
-+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- 	exit ;;
-     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- 	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
-@@ -788,30 +809,35 @@ EOF
- 	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- 	exit ;;
-     *:FreeBSD:*:*)
--	case ${UNAME_MACHINE} in
--	    pc98)
--		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
-+	UNAME_PROCESSOR=`/usr/bin/uname -p`
-+	case ${UNAME_PROCESSOR} in
- 	    amd64)
- 		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- 	    *)
--		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
-+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- 	esac
- 	exit ;;
-     i*:CYGWIN*:*)
- 	echo ${UNAME_MACHINE}-pc-cygwin
- 	exit ;;
-+    *:MINGW64*:*)
-+	echo ${UNAME_MACHINE}-pc-mingw64
-+	exit ;;
-     *:MINGW*:*)
- 	echo ${UNAME_MACHINE}-pc-mingw32
- 	exit ;;
-+    i*:MSYS*:*)
-+	echo ${UNAME_MACHINE}-pc-msys
-+	exit ;;
-     i*:windows32*:*)
--    	# uname -m includes "-pc" on this system.
--    	echo ${UNAME_MACHINE}-mingw32
-+	# uname -m includes "-pc" on this system.
-+	echo ${UNAME_MACHINE}-mingw32
- 	exit ;;
-     i*:PW*:*)
- 	echo ${UNAME_MACHINE}-pc-pw32
- 	exit ;;
-     *:Interix*:*)
--    	case ${UNAME_MACHINE} in
-+	case ${UNAME_MACHINE} in
- 	    x86)
- 		echo i586-pc-interix${UNAME_RELEASE}
- 		exit ;;
-@@ -848,15 +874,22 @@ EOF
- 	exit ;;
-     *:GNU:*:*)
- 	# the GNU system
--	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
-+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- 	exit ;;
-     *:GNU/*:*:*)
- 	# other systems with GNU libc and userland
--	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
-+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
- 	exit ;;
-     i*86:Minix:*:*)
- 	echo ${UNAME_MACHINE}-pc-minix
- 	exit ;;
-+    aarch64:Linux:*:*)
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-+	exit ;;
-+    aarch64_be:Linux:*:*)
-+	UNAME_MACHINE=aarch64_be
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-+	exit ;;
-     alpha:Linux:*:*)
- 	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
- 	  EV5)   UNAME_MACHINE=alphaev5 ;;
-@@ -866,52 +899,56 @@ EOF
- 	  EV6)   UNAME_MACHINE=alphaev6 ;;
- 	  EV67)  UNAME_MACHINE=alphaev67 ;;
- 	  EV68*) UNAME_MACHINE=alphaev68 ;;
--        esac
-+	esac
- 	objdump --private-headers /bin/sh | grep -q ld.so.1
--	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
--	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
-+	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-+	exit ;;
-+    arc:Linux:*:* | arceb:Linux:*:*)
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     arm*:Linux:*:*)
- 	eval $set_cc_for_build
- 	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
- 	    | grep -q __ARM_EABI__
- 	then
--	    echo ${UNAME_MACHINE}-unknown-linux-gnu
-+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	else
--	    echo ${UNAME_MACHINE}-unknown-linux-gnueabi
-+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
-+		| grep -q __ARM_PCS_VFP
-+	    then
-+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
-+	    else
-+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
-+	    fi
- 	fi
- 	exit ;;
-     avr32*:Linux:*:*)
--	echo ${UNAME_MACHINE}-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     cris:Linux:*:*)
--	echo cris-axis-linux-gnu
-+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
- 	exit ;;
-     crisv32:Linux:*:*)
--	echo crisv32-axis-linux-gnu
-+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
- 	exit ;;
-     frv:Linux:*:*)
--    	echo frv-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-+	exit ;;
-+    hexagon:Linux:*:*)
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     i*86:Linux:*:*)
--	LIBC=gnu
--	eval $set_cc_for_build
--	sed 's/^	//' << EOF >$dummy.c
--	#ifdef __dietlibc__
--	LIBC=dietlibc
--	#endif
--EOF
--	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
--	echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
-+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
- 	exit ;;
-     ia64:Linux:*:*)
--	echo ${UNAME_MACHINE}-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     m32r*:Linux:*:*)
--	echo ${UNAME_MACHINE}-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     m68*:Linux:*:*)
--	echo ${UNAME_MACHINE}-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     mips:Linux:*:* | mips64:Linux:*:*)
- 	eval $set_cc_for_build
-@@ -930,51 +967,63 @@ EOF
- 	#endif
- EOF
- 	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
--	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
-+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
- 	;;
-+    or1k:Linux:*:*)
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-+	exit ;;
-     or32:Linux:*:*)
--	echo or32-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     padre:Linux:*:*)
--	echo sparc-unknown-linux-gnu
-+	echo sparc-unknown-linux-${LIBC}
- 	exit ;;
-     parisc64:Linux:*:* | hppa64:Linux:*:*)
--	echo hppa64-unknown-linux-gnu
-+	echo hppa64-unknown-linux-${LIBC}
- 	exit ;;
-     parisc:Linux:*:* | hppa:Linux:*:*)
- 	# Look for CPU level
- 	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
--	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
--	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
--	  *)    echo hppa-unknown-linux-gnu ;;
-+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
-+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
-+	  *)    echo hppa-unknown-linux-${LIBC} ;;
- 	esac
- 	exit ;;
-     ppc64:Linux:*:*)
--	echo powerpc64-unknown-linux-gnu
-+	echo powerpc64-unknown-linux-${LIBC}
- 	exit ;;
-     ppc:Linux:*:*)
--	echo powerpc-unknown-linux-gnu
-+	echo powerpc-unknown-linux-${LIBC}
-+	exit ;;
-+    ppc64le:Linux:*:*)
-+	echo powerpc64le-unknown-linux-${LIBC}
-+	exit ;;
-+    ppcle:Linux:*:*)
-+	echo powerpcle-unknown-linux-${LIBC}
- 	exit ;;
-     s390:Linux:*:* | s390x:Linux:*:*)
--	echo ${UNAME_MACHINE}-ibm-linux
-+	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
- 	exit ;;
-     sh64*:Linux:*:*)
--    	echo ${UNAME_MACHINE}-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     sh*:Linux:*:*)
--	echo ${UNAME_MACHINE}-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     sparc:Linux:*:* | sparc64:Linux:*:*)
--	echo ${UNAME_MACHINE}-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-+	exit ;;
-+    tile*:Linux:*:*)
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     vax:Linux:*:*)
--	echo ${UNAME_MACHINE}-dec-linux-gnu
-+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
- 	exit ;;
-     x86_64:Linux:*:*)
--	echo x86_64-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     xtensa*:Linux:*:*)
--    	echo ${UNAME_MACHINE}-unknown-linux-gnu
-+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- 	exit ;;
-     i*86:DYNIX/ptx:4*:*)
- 	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
-@@ -983,11 +1032,11 @@ EOF
- 	echo i386-sequent-sysv4
- 	exit ;;
-     i*86:UNIX_SV:4.2MP:2.*)
--        # Unixware is an offshoot of SVR4, but it has its own version
--        # number series starting with 2...
--        # I am not positive that other SVR4 systems won't match this,
-+	# Unixware is an offshoot of SVR4, but it has its own version
-+	# number series starting with 2...
-+	# I am not positive that other SVR4 systems won't match this,
- 	# I just have to hope.  -- rms.
--        # Use sysv4.2uw... so that sysv4* matches it.
-+	# Use sysv4.2uw... so that sysv4* matches it.
- 	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- 	exit ;;
-     i*86:OS/2:*:*)
-@@ -1019,7 +1068,7 @@ EOF
- 	fi
- 	exit ;;
-     i*86:*:5:[678]*)
--    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
-+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
- 	case `/bin/uname -X | grep "^Machine"` in
- 	    *486*)	     UNAME_MACHINE=i486 ;;
- 	    *Pentium)	     UNAME_MACHINE=i586 ;;
-@@ -1047,13 +1096,13 @@ EOF
- 	exit ;;
-     pc:*:*:*)
- 	# Left here for compatibility:
--        # uname -m prints for DJGPP always 'pc', but it prints nothing about
--        # the processor, so we play safe by assuming i586.
-+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
-+	# the processor, so we play safe by assuming i586.
- 	# Note: whatever this is, it MUST be the same as what config.sub
- 	# prints for the "djgpp" host, or else GDB configury will decide that
- 	# this is a cross-build.
- 	echo i586-pc-msdosdjgpp
--        exit ;;
-+	exit ;;
-     Intel:Mach:3*:*)
- 	echo i386-pc-mach3
- 	exit ;;
-@@ -1088,8 +1137,8 @@ EOF
- 	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- 	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
-     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
--        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
--          && { echo i486-ncr-sysv4; exit; } ;;
-+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-+	  && { echo i486-ncr-sysv4; exit; } ;;
-     NCR*:*:4.2:* | MPRAS*:*:4.2:*)
- 	OS_REL='.3'
- 	test -r /etc/.relid \
-@@ -1132,10 +1181,10 @@ EOF
- 		echo ns32k-sni-sysv
- 	fi
- 	exit ;;
--    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
--                      # says <Richard.M.Bartel@ccMail.Census.GOV>
--        echo i586-unisys-sysv4
--        exit ;;
-+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-+			# says <Richard.M.Bartel@ccMail.Census.GOV>
-+	echo i586-unisys-sysv4
-+	exit ;;
-     *:UNIX_System_V:4*:FTX*)
- 	# From Gerald Hewes <hewes@openmarket.com>.
- 	# How about differentiating between stratus architectures? -djm
-@@ -1161,11 +1210,11 @@ EOF
- 	exit ;;
-     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
- 	if [ -d /usr/nec ]; then
--	        echo mips-nec-sysv${UNAME_RELEASE}
-+		echo mips-nec-sysv${UNAME_RELEASE}
- 	else
--	        echo mips-unknown-sysv${UNAME_RELEASE}
-+		echo mips-unknown-sysv${UNAME_RELEASE}
- 	fi
--        exit ;;
-+	exit ;;
-     BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
- 	echo powerpc-be-beos
- 	exit ;;
-@@ -1178,6 +1227,9 @@ EOF
-     BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
- 	echo i586-pc-haiku
- 	exit ;;
-+    x86_64:Haiku:*:*)
-+	echo x86_64-unknown-haiku
-+	exit ;;
-     SX-4:SUPER-UX:*:*)
- 	echo sx4-nec-superux${UNAME_RELEASE}
- 	exit ;;
-@@ -1204,19 +1256,31 @@ EOF
- 	exit ;;
-     *:Darwin:*:*)
- 	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
--	case $UNAME_PROCESSOR in
--	    i386)
--		eval $set_cc_for_build
--		if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
--		  if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
--		      (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
--		      grep IS_64BIT_ARCH >/dev/null
--		  then
--		      UNAME_PROCESSOR="x86_64"
--		  fi
--		fi ;;
--	    unknown) UNAME_PROCESSOR=powerpc ;;
--	esac
-+	eval $set_cc_for_build
-+	if test "$UNAME_PROCESSOR" = unknown ; then
-+	    UNAME_PROCESSOR=powerpc
-+	fi
-+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
-+	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
-+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-+		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
-+		    grep IS_64BIT_ARCH >/dev/null
-+		then
-+		    case $UNAME_PROCESSOR in
-+			i386) UNAME_PROCESSOR=x86_64 ;;
-+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
-+		    esac
-+		fi
-+	    fi
-+	elif test "$UNAME_PROCESSOR" = i386 ; then
-+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
-+	    # that puts up a graphical alert prompting to install
-+	    # developer tools.  Any system running Mac OS X 10.7 or
-+	    # later (Darwin 11 and later) is required to have a 64-bit
-+	    # processor. This is not true of the ARM version of Darwin
-+	    # that Apple uses in portable devices.
-+	    UNAME_PROCESSOR=x86_64
-+	fi
- 	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- 	exit ;;
-     *:procnto*:*:* | *:QNX:[0123456789]*:*)
-@@ -1230,7 +1294,10 @@ EOF
-     *:QNX:*:4*)
- 	echo i386-pc-qnx
- 	exit ;;
--    NSE-?:NONSTOP_KERNEL:*:*)
-+    NEO-?:NONSTOP_KERNEL:*:*)
-+	echo neo-tandem-nsk${UNAME_RELEASE}
-+	exit ;;
-+    NSE-*:NONSTOP_KERNEL:*:*)
- 	echo nse-tandem-nsk${UNAME_RELEASE}
- 	exit ;;
-     NSR-?:NONSTOP_KERNEL:*:*)
-@@ -1275,13 +1342,13 @@ EOF
- 	echo pdp10-unknown-its
- 	exit ;;
-     SEI:*:*:SEIUX)
--        echo mips-sei-seiux${UNAME_RELEASE}
-+	echo mips-sei-seiux${UNAME_RELEASE}
- 	exit ;;
-     *:DragonFly:*:*)
- 	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- 	exit ;;
-     *:*VMS:*:*)
--    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
-+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
- 	case "${UNAME_MACHINE}" in
- 	    A*) echo alpha-dec-vms ; exit ;;
- 	    I*) echo ia64-dec-vms ; exit ;;
-@@ -1299,11 +1366,11 @@ EOF
-     i*86:AROS:*:*)
- 	echo ${UNAME_MACHINE}-pc-aros
- 	exit ;;
-+    x86_64:VMkernel:*:*)
-+	echo ${UNAME_MACHINE}-unknown-esx
-+	exit ;;
- esac
- 
--#echo '(No uname command or uname output not recognized.)' 1>&2
--#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
--
- eval $set_cc_for_build
- cat >$dummy.c <<EOF
- #ifdef _SEQUENT_
-@@ -1321,11 +1388,11 @@ main ()
- #include <sys/param.h>
-   printf ("m68k-sony-newsos%s\n",
- #ifdef NEWSOS4
--          "4"
-+	"4"
- #else
--	  ""
-+	""
- #endif
--         ); exit (0);
-+	); exit (0);
- #endif
- #endif
- 
-diff --git a/autoconf/config.sub b/autoconf/config.sub
-index 2a55a50..092cff0 100755
---- a/autoconf/config.sub
-+++ b/autoconf/config.sub
-@@ -1,38 +1,31 @@
- #! /bin/sh
- # Configuration validation subroutine script.
--#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
--#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
--#   Free Software Foundation, Inc.
-+#   Copyright 1992-2014 Free Software Foundation, Inc.
- 
--timestamp='2009-11-20'
-+timestamp='2014-01-01'
- 
--# This file is (in principle) common to ALL GNU software.
--# The presence of a machine in this file suggests that SOME GNU software
--# can handle that machine.  It does not imply ALL GNU software can.
--#
--# This file is free software; you can redistribute it and/or modify
--# it under the terms of the GNU General Public License as published by
--# the Free Software Foundation; either version 2 of the License, or
-+# This file is free software; you can redistribute it and/or modify it
-+# under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 3 of the License, or
- # (at your option) any later version.
- #
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY; without even the implied warranty of
--# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--# GNU General Public License for more details.
-+# This program is distributed in the hope that it will be useful, but
-+# WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+# General Public License for more details.
- #
- # 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.
-+# along with this program; if not, see <http://www.gnu.org/licenses/>.
- #
- # As a special exception to the GNU General Public License, if you
- # distribute this file as part of a program that contains a
- # configuration script generated by Autoconf, you may include it under
--# the same distribution terms that you use for the rest of that program.
-+# the same distribution terms that you use for the rest of that
-+# program.  This Exception is an additional permission under section 7
-+# of the GNU General Public License, version 3 ("GPLv3").
- 
- 
--# Please send patches to <config-patches@gnu.org>.  Submit a context
--# diff and a properly formatted GNU ChangeLog entry.
-+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
- #
- # Configuration subroutine to validate and canonicalize a configuration type.
- # Supply the specified configuration type as an argument.
-@@ -75,8 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
- version="\
- GNU config.sub ($timestamp)
- 
--Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
--2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-+Copyright 1992-2014 Free Software Foundation, Inc.
- 
- This is free software; see the source for copying conditions.  There is NO
- warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-@@ -123,13 +115,18 @@ esac
- # Here we must recognize all the valid KERNEL-OS combinations.
- maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
- case $maybe_os in
--  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
--  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
-+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
-+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
-+  knetbsd*-gnu* | netbsd*-gnu* | \
-   kopensolaris*-gnu* | \
-   storm-chaos* | os2-emx* | rtmk-nova*)
-     os=-$maybe_os
-     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
-     ;;
-+  android-linux)
-+    os=-linux-android
-+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
-+    ;;
-   *)
-     basic_machine=`echo $1 | sed 's/-[^-]*$//'`
-     if [ $basic_machine != $1 ]
-@@ -152,12 +149,12 @@ case $os in
- 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
--	-apple | -axis | -knuth | -cray | -microblaze)
-+	-apple | -axis | -knuth | -cray | -microblaze*)
- 		os=
- 		basic_machine=$1
- 		;;
--        -bluegene*)
--	        os=-cnk
-+	-bluegene*)
-+		os=-cnk
- 		;;
- 	-sim | -cisco | -oki | -wec | -winbond)
- 		os=
-@@ -173,10 +170,10 @@ case $os in
- 		os=-chorusos
- 		basic_machine=$1
- 		;;
-- 	-chorusrdb)
-- 		os=-chorusrdb
-+	-chorusrdb)
-+		os=-chorusrdb
- 		basic_machine=$1
-- 		;;
-+		;;
- 	-hiux*)
- 		os=-hiuxwe2
- 		;;
-@@ -221,6 +218,12 @@ case $os in
- 	-isc*)
- 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- 		;;
-+	-lynx*178)
-+		os=-lynxos178
-+		;;
-+	-lynx*5)
-+		os=-lynxos5
-+		;;
- 	-lynx*)
- 		os=-lynxos
- 		;;
-@@ -245,20 +248,28 @@ case $basic_machine in
- 	# Some are omitted here because they have special meanings below.
- 	1750a | 580 \
- 	| a29k \
-+	| aarch64 | aarch64_be \
- 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
- 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- 	| am33_2.0 \
--	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
-+	| arc | arceb \
-+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
-+	| avr | avr32 \
-+	| be32 | be64 \
- 	| bfin \
--	| c4x | clipper \
-+	| c4x | c8051 | clipper \
- 	| d10v | d30v | dlx | dsp16xx \
-+	| epiphany \
- 	| fido | fr30 | frv \
- 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
-+	| hexagon \
- 	| i370 | i860 | i960 | ia64 \
- 	| ip2k | iq2000 \
-+	| k1om \
-+	| le32 | le64 \
- 	| lm32 \
- 	| m32c | m32r | m32rle | m68000 | m68k | m88k \
--	| maxq | mb | microblaze | mcore | mep | metag \
-+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
- 	| mips | mipsbe | mipseb | mipsel | mipsle \
- 	| mips16 \
- 	| mips64 | mips64el \
-@@ -276,34 +287,45 @@ case $basic_machine in
- 	| mipsisa64r2 | mipsisa64r2el \
- 	| mipsisa64sb1 | mipsisa64sb1el \
- 	| mipsisa64sr71k | mipsisa64sr71kel \
-+	| mipsr5900 | mipsr5900el \
- 	| mipstx39 | mipstx39el \
- 	| mn10200 | mn10300 \
- 	| moxie \
- 	| mt \
- 	| msp430 \
--	| nios | nios2 \
-+	| nds32 | nds32le | nds32be \
-+	| nios | nios2 | nios2eb | nios2el \
- 	| ns16k | ns32k \
--	| or32 \
-+	| open8 \
-+	| or1k | or32 \
- 	| pdp10 | pdp11 | pj | pjl \
--	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
-+	| powerpc | powerpc64 | powerpc64le | powerpcle \
- 	| pyramid \
--	| rx \
-+	| rl78 | rx \
- 	| score \
- 	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
- 	| sh64 | sh64le \
- 	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
- 	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
--	| spu | strongarm \
--	| tahoe | thumb | tic4x | tic80 | tron \
-+	| spu \
-+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
- 	| ubicom32 \
--	| v850 | v850e \
-+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
- 	| we32k \
--	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
-+	| x86 | xc16x | xstormy16 | xtensa \
- 	| z8k | z80)
- 		basic_machine=$basic_machine-unknown
- 		;;
--	m6811 | m68hc11 | m6812 | m68hc12 | picochip)
--		# Motorola 68HC11/12.
-+	c54x)
-+		basic_machine=tic54x-unknown
-+		;;
-+	c55x)
-+		basic_machine=tic55x-unknown
-+		;;
-+	c6x)
-+		basic_machine=tic6x-unknown
-+		;;
-+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
- 		basic_machine=$basic_machine-unknown
- 		os=-none
- 		;;
-@@ -313,6 +335,21 @@ case $basic_machine in
- 		basic_machine=mt-unknown
- 		;;
- 
-+	strongarm | thumb | xscale)
-+		basic_machine=arm-unknown
-+		;;
-+	xgate)
-+		basic_machine=$basic_machine-unknown
-+		os=-none
-+		;;
-+	xscaleeb)
-+		basic_machine=armeb-unknown
-+		;;
-+
-+	xscaleel)
-+		basic_machine=armel-unknown
-+		;;
-+
- 	# We use `pc' rather than `unknown'
- 	# because (1) that's what they normally are, and
- 	# (2) the word "unknown" tends to confuse beginning users.
-@@ -327,25 +364,31 @@ case $basic_machine in
- 	# Recognize the basic CPU types with company name.
- 	580-* \
- 	| a29k-* \
-+	| aarch64-* | aarch64_be-* \
- 	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
--	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
-+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
- 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
- 	| avr-* | avr32-* \
-+	| be32-* | be64-* \
- 	| bfin-* | bs2000-* \
--	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
--	| clipper-* | craynv-* | cydra-* \
-+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
-+	| c8051-* | clipper-* | craynv-* | cydra-* \
- 	| d10v-* | d30v-* | dlx-* \
- 	| elxsi-* \
- 	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
- 	| h8300-* | h8500-* \
- 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
-+	| hexagon-* \
- 	| i*86-* | i860-* | i960-* | ia64-* \
- 	| ip2k-* | iq2000-* \
-+	| k1om-* \
-+	| le32-* | le64-* \
- 	| lm32-* \
- 	| m32c-* | m32r-* | m32rle-* \
- 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
--	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
-+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
-+	| microblaze-* | microblazeel-* \
- 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
- 	| mips16-* \
- 	| mips64-* | mips64el-* \
-@@ -363,29 +406,34 @@ case $basic_machine in
- 	| mipsisa64r2-* | mipsisa64r2el-* \
- 	| mipsisa64sb1-* | mipsisa64sb1el-* \
- 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
-+	| mipsr5900-* | mipsr5900el-* \
- 	| mipstx39-* | mipstx39el-* \
- 	| mmix-* \
- 	| mt-* \
- 	| msp430-* \
--	| nios-* | nios2-* \
-+	| nds32-* | nds32le-* | nds32be-* \
-+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
- 	| none-* | np1-* | ns16k-* | ns32k-* \
-+	| open8-* \
- 	| orion-* \
- 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
--	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
-+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
- 	| pyramid-* \
--	| romp-* | rs6000-* | rx-* \
-+	| rl78-* | romp-* | rs6000-* | rx-* \
- 	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
- 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- 	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
- 	| sparclite-* \
--	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
--	| tahoe-* | thumb-* \
--	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
-+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
-+	| tahoe-* \
-+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
-+	| tile*-* \
- 	| tron-* \
- 	| ubicom32-* \
--	| v850-* | v850e-* | vax-* \
-+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
-+	| vax-* \
- 	| we32k-* \
--	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
-+	| x86-* | x86_64-* | xc16x-* | xps100-* \
- 	| xstormy16-* | xtensa*-* \
- 	| ymp-* \
- 	| z8k-* | z80-*)
-@@ -410,7 +458,7 @@ case $basic_machine in
- 		basic_machine=a29k-amd
- 		os=-udi
- 		;;
--    	abacus)
-+	abacus)
- 		basic_machine=abacus-unknown
- 		;;
- 	adobe68k)
-@@ -480,11 +528,20 @@ case $basic_machine in
- 		basic_machine=powerpc-ibm
- 		os=-cnk
- 		;;
-+	c54x-*)
-+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
-+		;;
-+	c55x-*)
-+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
-+		;;
-+	c6x-*)
-+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
-+		;;
- 	c90)
- 		basic_machine=c90-cray
- 		os=-unicos
- 		;;
--        cegcc)
-+	cegcc)
- 		basic_machine=arm-unknown
- 		os=-cegcc
- 		;;
-@@ -516,7 +573,7 @@ case $basic_machine in
- 		basic_machine=craynv-cray
- 		os=-unicosmp
- 		;;
--	cr16)
-+	cr16 | cr16-*)
- 		basic_machine=cr16-unknown
- 		os=-elf
- 		;;
-@@ -674,7 +731,6 @@ case $basic_machine in
- 	i370-ibm* | ibm*)
- 		basic_machine=i370-ibm
- 		;;
--# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
- 	i*86v32)
- 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- 		os=-sysv32
-@@ -732,11 +788,15 @@ case $basic_machine in
- 		basic_machine=ns32k-utek
- 		os=-sysv
- 		;;
--        microblaze)
-+	microblaze*)
- 		basic_machine=microblaze-xilinx
- 		;;
-+	mingw64)
-+		basic_machine=x86_64-pc
-+		os=-mingw64
-+		;;
- 	mingw32)
--		basic_machine=i386-pc
-+		basic_machine=i686-pc
- 		os=-mingw32
- 		;;
- 	mingw32ce)
-@@ -771,10 +831,18 @@ case $basic_machine in
- 	ms1-*)
- 		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
- 		;;
-+	msys)
-+		basic_machine=i686-pc
-+		os=-msys
-+		;;
- 	mvs)
- 		basic_machine=i370-ibm
- 		os=-mvs
- 		;;
-+	nacl)
-+		basic_machine=le32-unknown
-+		os=-nacl
-+		;;
- 	ncr3000)
- 		basic_machine=i486-ncr
- 		os=-sysv4
-@@ -839,6 +907,12 @@ case $basic_machine in
- 	np1)
- 		basic_machine=np1-gould
- 		;;
-+	neo-tandem)
-+		basic_machine=neo-tandem
-+		;;
-+	nse-tandem)
-+		basic_machine=nse-tandem
-+		;;
- 	nsr-tandem)
- 		basic_machine=nsr-tandem
- 		;;
-@@ -921,9 +995,10 @@ case $basic_machine in
- 		;;
- 	power)	basic_machine=power-ibm
- 		;;
--	ppc)	basic_machine=powerpc-unknown
-+	ppc | ppcbe)	basic_machine=powerpc-unknown
- 		;;
--	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
-+	ppc-* | ppcbe-*)
-+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- 		;;
- 	ppcle | powerpclittle | ppc-le | powerpc-little)
- 		basic_machine=powerpcle-unknown
-@@ -948,7 +1023,11 @@ case $basic_machine in
- 		basic_machine=i586-unknown
- 		os=-pw32
- 		;;
--	rdos)
-+	rdos | rdos64)
-+		basic_machine=x86_64-pc
-+		os=-rdos
-+		;;
-+	rdos32)
- 		basic_machine=i386-pc
- 		os=-rdos
- 		;;
-@@ -1017,6 +1096,9 @@ case $basic_machine in
- 		basic_machine=i860-stratus
- 		os=-sysv4
- 		;;
-+	strongarm-* | thumb-*)
-+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
-+		;;
- 	sun2)
- 		basic_machine=m68000-sun
- 		;;
-@@ -1073,20 +1155,8 @@ case $basic_machine in
- 		basic_machine=t90-cray
- 		os=-unicos
- 		;;
--	tic54x | c54x*)
--		basic_machine=tic54x-unknown
--		os=-coff
--		;;
--	tic55x | c55x*)
--		basic_machine=tic55x-unknown
--		os=-coff
--		;;
--	tic6x | c6x*)
--		basic_machine=tic6x-unknown
--		os=-coff
--		;;
- 	tile*)
--		basic_machine=tile-unknown
-+		basic_machine=$basic_machine-unknown
- 		os=-linux-gnu
- 		;;
- 	tx39)
-@@ -1156,6 +1226,9 @@ case $basic_machine in
- 	xps | xps100)
- 		basic_machine=xps100-honeywell
- 		;;
-+	xscale-* | xscalee[bl]-*)
-+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
-+		;;
- 	ymp)
- 		basic_machine=ymp-cray
- 		os=-unicos
-@@ -1253,11 +1326,11 @@ esac
- if [ x"$os" != x"" ]
- then
- case $os in
--        # First match some system type aliases
--        # that might get confused with valid system types.
-+	# First match some system type aliases
-+	# that might get confused with valid system types.
- 	# -solaris* is a basic system type, with this one exception.
--        -auroraux)
--	        os=-auroraux
-+	-auroraux)
-+		os=-auroraux
- 		;;
- 	-solaris1 | -solaris1.*)
- 		os=`echo $os | sed -e 's|solaris1|sunos4|'`
-@@ -1281,20 +1354,21 @@ case $os in
- 	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- 	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
- 	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
--	      | -sym* | -kopensolaris* \
-+	      | -sym* | -kopensolaris* | -plan9* \
- 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- 	      | -aos* | -aros* \
- 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
- 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
--	      | -openbsd* | -solidbsd* \
-+	      | -bitrig* | -openbsd* | -solidbsd* \
- 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
- 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
- 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- 	      | -chorusos* | -chorusrdb* | -cegcc* \
--	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
--	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
-+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-+	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
-+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
- 	      | -uxpv* | -beos* | -mpeix* | -udk* \
- 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
- 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
-@@ -1341,7 +1415,7 @@ case $os in
- 	-opened*)
- 		os=-openedition
- 		;;
--        -os400*)
-+	-os400*)
- 		os=-os400
- 		;;
- 	-wince*)
-@@ -1390,7 +1464,7 @@ case $os in
- 	-sinix*)
- 		os=-sysv4
- 		;;
--        -tpf*)
-+	-tpf*)
- 		os=-tpf
- 		;;
- 	-triton*)
-@@ -1426,15 +1500,14 @@ case $os in
- 	-aros*)
- 		os=-aros
- 		;;
--	-kaos*)
--		os=-kaos
--		;;
- 	-zvmoe)
- 		os=-zvmoe
- 		;;
- 	-dicos*)
- 		os=-dicos
- 		;;
-+	-nacl*)
-+		;;
- 	-none)
- 		;;
- 	*)
-@@ -1457,10 +1530,10 @@ else
- # system, and we'll never get to this point.
- 
- case $basic_machine in
--        score-*)
-+	score-*)
- 		os=-elf
- 		;;
--        spu-*)
-+	spu-*)
- 		os=-elf
- 		;;
- 	*-acorn)
-@@ -1472,8 +1545,23 @@ case $basic_machine in
- 	arm*-semi)
- 		os=-aout
- 		;;
--        c4x-* | tic4x-*)
--        	os=-coff
-+	c4x-* | tic4x-*)
-+		os=-coff
-+		;;
-+	c8051-*)
-+		os=-elf
-+		;;
-+	hexagon-*)
-+		os=-elf
-+		;;
-+	tic54x-*)
-+		os=-coff
-+		;;
-+	tic55x-*)
-+		os=-coff
-+		;;
-+	tic6x-*)
-+		os=-coff
- 		;;
- 	# This must come before the *-dec entry.
- 	pdp10-*)
-@@ -1493,14 +1581,11 @@ case $basic_machine in
- 		;;
- 	m68000-sun)
- 		os=-sunos3
--		# This also exists in the configure program, but was not the
--		# default.
--		# os=-sunos4
- 		;;
- 	m68*-cisco)
- 		os=-aout
- 		;;
--        mep-*)
-+	mep-*)
- 		os=-elf
- 		;;
- 	mips*-cisco)
-@@ -1509,6 +1594,9 @@ case $basic_machine in
- 	mips*-*)
- 		os=-elf
- 		;;
-+	or1k-*)
-+		os=-elf
-+		;;
- 	or32-*)
- 		os=-coff
- 		;;
-@@ -1527,7 +1615,7 @@ case $basic_machine in
- 	*-ibm)
- 		os=-aix
- 		;;
--    	*-knuth)
-+	*-knuth)
- 		os=-mmixware
- 		;;
- 	*-wec)
-diff --git a/conf/example.conf.in b/conf/example.conf.in
-index 79b574e..5e23291 100644
---- a/conf/example.conf.in
-+++ b/conf/example.conf.in
-@@ -301,6 +301,21 @@ allocation {
-     # until version 2.02.85.
-     mirror_logs_require_separate_pvs = 0
- 
-+    # Set to 1 to guarantee that cache_pool metadata will always be
-+    # placed on  different PVs from the cache_pool data.
-+    cache_pool_metadata_require_separate_pvs = 0
-+
-+    # Specify the minimal chunk size (in kiB) for cache pool volumes.
-+    # Using a chunk_size that is too large can result in wasteful use of
-+    # the cache, where small reads and writes can cause large sections of
-+    # an LV to be mapped into the cache.  However, choosing a chunk_size
-+    # that is too small can result in more overhead trying to manage the
-+    # numerous chunks that become mapped into the cache.  The former is
-+    # more of a problem than the latter in most cases, so we default to
-+    # a value that is on the smaller end of the spectrum.  Supported values
-+    # range from 32(kiB) to 1048576 in multiples of 32.
-+    # cache_pool_chunk_size = 64
-+
-     # Set to 1 to guarantee that thin pool metadata will always
-     # be placed on different PVs from the pool data.
-     thin_pool_metadata_require_separate_pvs = 0
-@@ -321,14 +336,14 @@ allocation {
-     # thin_pool_chunk_size_policy = "generic"
- 
-     # Specify the minimal chunk size (in KB) for thin pool volumes.
--    # Use of the larger chunk size may improve perfomance for plain
-+    # Use of the larger chunk size may improve performance for plain
-     # thin volumes, however using them for snapshot volumes is less efficient,
-     # as it consumes more space and takes extra time for copying.
-     # When unset, lvm tries to estimate chunk size starting from 64KB
-     # Supported values are in range from 64 to 1048576.
-     # thin_pool_chunk_size = 64
- 
--    # Specify discards behavior of the thin pool volume.
-+    # Specify discards behaviour of the thin pool volume.
-     # Select one of  "ignore", "nopassdown", "passdown"
-     # thin_pool_discards = "passdown"
- 
-@@ -408,7 +423,7 @@ log {
- # Configuration of metadata backups and archiving.  In LVM2 when we
- # talk about a 'backup' we mean making a copy of the metadata for the
- # *current* system.  The 'archive' contains old metadata configurations.
--# Backups are stored in a human readeable text format.
-+# Backups are stored in a human readable text format.
- backup {
- 
-     # Should we maintain a backup of the current metadata configuration ?
-@@ -599,7 +614,7 @@ global {
-     # "mirror" - LVM will layer the 'mirror' and 'stripe' segment types.  It
-     #            will do this by creating a mirror on top of striped sub-LVs;
-     #            effectively creating a RAID 0+1 array.  This is suboptimal
--    #            in terms of providing redunancy and performance.  Changing to
-+    #            in terms of providing redundancy and performance. Changing to
-     #            this setting is not advised.
-     # Specify the '--type <raid10|mirror>' option to override this default
-     # setting.
-@@ -663,7 +678,7 @@ global {
-     # Array of string options passed with thin_check command. By default,
-     # option "-q" is for quiet output.
-     # With thin_check version 2.1 or newer you can add "--ignore-non-fatal-errors"
--    # to let it pass through ignoreable errors and fix them later.
-+    # to let it pass through ignorable errors and fix them later.
-     #
-     # thin_check_options = [ "-q" ]
- 
-@@ -691,6 +706,7 @@ global {
-     #   discards_non_power_2
-     #   external_origin
-     #   metadata_resize
-+    #   external_origin_extend
-     #
-     # thin_disabled_features = [ "discards", "block_size" ]
- }
-@@ -822,7 +838,7 @@ activation {
-     # auto_set_activation_skip = 1
- 
-     # For RAID or 'mirror' segment types, 'raid_region_size' is the
--    # size (in kiB) of each:
-+    # size (in KiB) of each:
-     # - synchronization operation when initializing
-     # - each copy operation when performing a 'pvmove' (using 'mirror' segtype)
-     # This setting has replaced 'mirror_region_size' since version 2.02.99
-diff --git a/configure b/configure
-index c96911c..6803010 100755
---- a/configure
-+++ b/configure
-@@ -688,6 +688,7 @@ CLUSTER
- CLDWHOLEARCHIVE
- CLDNOWHOLEARCHIVE
- CLDFLAGS
-+CACHE
- BUILD_LVMETAD
- BUILD_DMEVENTD
- BUILD_CMIRRORD
-@@ -839,6 +840,7 @@ with_thin
- with_thin_check
- with_thin_dump
- with_thin_repair
-+with_cache
- enable_readline
- enable_realtime
- enable_ocf
-@@ -1622,6 +1624,8 @@ Optional Packages:
-   --with-thin-check=PATH  thin_check tool: [[autodetect]]
-   --with-thin-dump=PATH   thin_dump tool: [[autodetect]]
-   --with-thin-repair=PATH thin_repair tool: [[autodetect]]
-+  --with-cache=TYPE       cache support: internal/shared/none
-+                          [[TYPE=none]]
-   --with-ocfdir=DIR       install OCF files in DIR
-                           [[PREFIX/lib/ocf/resource.d/lvm2]]
-   --with-default-pid-dir=PID_DIR
-@@ -7531,6 +7535,30 @@ cat >>confdefs.h <<_ACEOF
- _ACEOF
- 
- 
-+################################################################################
-+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include cache" >&5
-+$as_echo_n "checking whether to include cache... " >&6; }
-+
-+# Check whether --with-cache was given.
-+if test "${with_cache+set}" = set; then :
-+  withval=$with_cache; CACHE=$withval
-+else
-+  CACHE=none
-+fi
-+
-+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CACHE" >&5
-+$as_echo "$CACHE" >&6; }
-+
-+if [ "x$CACHE" != xnone -a "x$CACHE" != xinternal -a "x$CACHE" != xshared ];
-+ then  as_fn_error $? "--with-cache parameter invalid
-+" "$LINENO" 5
-+fi;
-+
-+if test x$CACHE = xinternal; then
-+
-+$as_echo "#define CACHE_INTERNAL 1" >>confdefs.h
-+
-+fi
- 
- ################################################################################
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable readline" >&5
-@@ -10150,6 +10178,7 @@ fi
- if [ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o "x$CLUSTER" = xshared \
-       -o "x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
-       -o "x$RAID" = xshared \
-+      -o "x$CACHE" = xshared \
-       \) -a "x$STATIC_LINK" = xyes ];
-  then  as_fn_error $? "Features cannot be 'shared' when building statically
- " "$LINENO" 5
-@@ -11423,8 +11452,9 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
- 
- 
- 
-+
- ################################################################################
--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/lvmetad/Makefile conf/Makefile conf/example.conf conf/default.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile 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/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.socket scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/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/lvmetad/Makefile conf/Makefile conf/example.conf conf/default.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile 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/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/lvm2_clvmd_systemd_red_hat.service scripts/cmirrord_init_red_hat scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.socket scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
- 
- cat >confcache <<\_ACEOF
- # This file is a shell script that caches the results of configure
-@@ -12142,6 +12172,7 @@ do
-     "lib/raid/Makefile") CONFIG_FILES="$CONFIG_FILES lib/raid/Makefile" ;;
-     "lib/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
-     "lib/thin/Makefile") CONFIG_FILES="$CONFIG_FILES lib/thin/Makefile" ;;
-+    "lib/cache_segtype/Makefile") CONFIG_FILES="$CONFIG_FILES lib/cache_segtype/Makefile" ;;
-     "libdaemon/Makefile") CONFIG_FILES="$CONFIG_FILES libdaemon/Makefile" ;;
-     "libdaemon/client/Makefile") CONFIG_FILES="$CONFIG_FILES libdaemon/client/Makefile" ;;
-     "libdaemon/server/Makefile") CONFIG_FILES="$CONFIG_FILES libdaemon/server/Makefile" ;;
-@@ -12156,8 +12187,12 @@ do
-     "scripts/blkdeactivate.sh") CONFIG_FILES="$CONFIG_FILES scripts/blkdeactivate.sh" ;;
-     "scripts/blk_availability_init_red_hat") CONFIG_FILES="$CONFIG_FILES scripts/blk_availability_init_red_hat" ;;
-     "scripts/blk_availability_systemd_red_hat.service") CONFIG_FILES="$CONFIG_FILES scripts/blk_availability_systemd_red_hat.service" ;;
-+    "scripts/lvm2_cluster_activation_red_hat.sh") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_cluster_activation_red_hat.sh" ;;
-+    "scripts/lvm2_cluster_activation_systemd_red_hat.service") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_cluster_activation_systemd_red_hat.service" ;;
-     "scripts/clvmd_init_red_hat") CONFIG_FILES="$CONFIG_FILES scripts/clvmd_init_red_hat" ;;
-+    "scripts/lvm2_clvmd_systemd_red_hat.service") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_clvmd_systemd_red_hat.service" ;;
-     "scripts/cmirrord_init_red_hat") CONFIG_FILES="$CONFIG_FILES scripts/cmirrord_init_red_hat" ;;
-+    "scripts/lvm2_cmirrord_systemd_red_hat.service") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_cmirrord_systemd_red_hat.service" ;;
-     "scripts/lvm2_lvmetad_init_red_hat") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_lvmetad_init_red_hat" ;;
-     "scripts/lvm2_lvmetad_systemd_red_hat.socket") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_lvmetad_systemd_red_hat.socket" ;;
-     "scripts/lvm2_lvmetad_systemd_red_hat.service") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_lvmetad_systemd_red_hat.service" ;;
-diff --git a/configure.in b/configure.in
-index cff7e45..f125209 100644
---- a/configure.in
-+++ b/configure.in
-@@ -476,6 +476,25 @@ AC_DEFINE_UNQUOTED([THIN_DUMP_CMD], ["$THIN_DUMP_CMD"],
- AC_DEFINE_UNQUOTED([THIN_REPAIR_CMD], ["$THIN_REPAIR_CMD"],
- 		   [The path to 'thin_repair', if available.])
- 
-+################################################################################
-+dnl -- cache inclusion type
-+AC_MSG_CHECKING(whether to include cache)
-+AC_ARG_WITH(cache,
-+	    AC_HELP_STRING([--with-cache=TYPE],
-+			   [cache support: internal/shared/none
-+			    [[TYPE=none]]]),
-+	    CACHE=$withval, CACHE=none)
-+AC_MSG_RESULT($CACHE)
-+
-+if [[ "x$CACHE" != xnone -a "x$CACHE" != xinternal -a "x$CACHE" != xshared ]];
-+ then  AC_MSG_ERROR(
-+--with-cache parameter invalid
-+)
-+fi;
-+
-+if test x$CACHE = xinternal; then
-+	AC_DEFINE([CACHE_INTERNAL], 1, [Define to 1 to include built-in support for cache.])
-+fi
- 
- ################################################################################
- dnl -- Disable readline
-@@ -1241,6 +1260,7 @@ dnl -- Check for shared/static conflicts
- if [[ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o "x$CLUSTER" = xshared \
-       -o "x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
-       -o "x$RAID" = xshared \
-+      -o "x$CACHE" = xshared \
-       \) -a "x$STATIC_LINK" = xyes ]];
-  then  AC_MSG_ERROR(
- Features cannot be 'shared' when building statically
-@@ -1596,6 +1616,7 @@ AC_SUBST(BLKID_WIPING)
- AC_SUBST(BUILD_CMIRRORD)
- AC_SUBST(BUILD_DMEVENTD)
- AC_SUBST(BUILD_LVMETAD)
-+AC_SUBST(CACHE)
- AC_SUBST(CFLAGS)
- AC_SUBST(CFLOW_CMD)
- AC_SUBST(CLDFLAGS)
-@@ -1752,6 +1773,7 @@ lib/misc/lvm-version.h
- lib/raid/Makefile
- lib/snapshot/Makefile
- lib/thin/Makefile
-+lib/cache_segtype/Makefile
- libdaemon/Makefile
- libdaemon/client/Makefile
- libdaemon/server/Makefile
-@@ -1766,8 +1788,12 @@ python/setup.py
- scripts/blkdeactivate.sh
- scripts/blk_availability_init_red_hat
- scripts/blk_availability_systemd_red_hat.service
-+scripts/lvm2_cluster_activation_red_hat.sh
-+scripts/lvm2_cluster_activation_systemd_red_hat.service
- scripts/clvmd_init_red_hat
-+scripts/lvm2_clvmd_systemd_red_hat.service
- scripts/cmirrord_init_red_hat
-+scripts/lvm2_cmirrord_systemd_red_hat.service
- scripts/lvm2_lvmetad_init_red_hat
- scripts/lvm2_lvmetad_systemd_red_hat.socket
- scripts/lvm2_lvmetad_systemd_red_hat.service
-diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
-index 179775a..4a17fb2 100644
---- a/daemons/dmeventd/dmeventd.c
-+++ b/daemons/dmeventd/dmeventd.c
-@@ -514,6 +514,30 @@ static int _get_status(struct message_data *message_data)
- 
- }
- 
-+static int _get_parameters(struct message_data *message_data) {
-+	struct dm_event_daemon_message *msg = message_data->msg;
-+	char buf[128];
-+	int r = -1;
-+
-+	dm_free(msg->data);
-+
-+	if (!(dm_snprintf(buf, sizeof(buf), "%s pid=%d daemon=%s exec_method=%s",
-+			  message_data->id,
-+			  getpid(),
-+			  _foreground ? "no" : "yes",
-+			  _systemd_activation ? "systemd" : "direct")))
-+		goto_out;
-+
-+	msg->size = strlen(buf) + 1;
-+	if (!(msg->data = dm_malloc(msg->size)))
-+		goto_out;
-+	if (!dm_strncpy(msg->data, buf, msg->size))
-+		goto_out;
-+	r = 0;
-+out:
-+	return r;
-+}
-+
- /* Cleanup at exit. */
- static void _exit_dm_lib(void)
- {
-@@ -1437,6 +1461,14 @@ static int _handle_request(struct dm_event_daemon_message *msg,
- 		{ DM_EVENT_CMD_GET_TIMEOUT, _get_timeout},
- 		{ DM_EVENT_CMD_ACTIVE, _active},
- 		{ DM_EVENT_CMD_GET_STATUS, _get_status},
-+		/* dmeventd parameters of running dmeventd,
-+		 * returns 'pid=<pid> daemon=<no/yes> exec_method=<direct/systemd>'
-+		 * 	pid - pidfile of running dmeventd
-+		 * 	daemon - running as a daemon or not (foreground)?
-+		 * 	exec_method - "direct" if executed directly or
-+		 * 		      "systemd" if executed via systemd
-+		 */
-+		{ DM_EVENT_CMD_GET_PARAMETERS, _get_parameters},
- 	}, *req;
- 
- 	for (req = requests; req < requests + sizeof(requests) / sizeof(struct request); req++)
-@@ -1504,7 +1536,11 @@ static void _process_request(struct dm_event_fifos *fifos)
- 
- 	dm_free(msg.data);
- 
--	if (die) raise(9);
-+	if (die) {
-+		if (unlink(DMEVENTD_PIDFILE))
-+			perror(DMEVENTD_PIDFILE ": unlink failed");
-+		_exit(0);
-+	}
- }
- 
- static void _process_initial_registrations(void)
-@@ -1732,6 +1768,7 @@ out:
- 	unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
- 	return r;
- }
-+
- #endif
- 
- static void _remove_files_on_exit(void)
-@@ -1823,6 +1860,59 @@ static void _daemonize(void)
- 	setsid();
- }
- 
-+static int _reinstate_registrations(struct dm_event_fifos *fifos)
-+{
-+	static const char _failed_parsing_msg[] = "Failed to parse existing event registration.\n";
-+	static const char *_delim = " ";
-+	struct dm_event_daemon_message msg = { 0 };
-+	char *endp, *dso_name, *dev_name, *mask, *timeout;
-+	unsigned long mask_value, timeout_value;
-+	int i, ret;
-+
-+	ret = daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
-+	dm_free(msg.data);
-+	msg.data = NULL;
-+
-+	if (ret) {
-+		fprintf(stderr, "Failed to communicate with new instance of dmeventd.\n");
-+		return 0;
-+	}
-+
-+	for (i = 0; _initial_registrations[i]; ++i) {
-+		if (!(strtok(_initial_registrations[i], _delim)) ||
-+		    !(dso_name = strtok(NULL, _delim)) ||
-+		    !(dev_name = strtok(NULL, _delim)) ||
-+		    !(mask = strtok(NULL, _delim)) ||
-+		    !(timeout = strtok(NULL, _delim))) {
-+			fprintf(stderr, _failed_parsing_msg);
-+			continue;
-+		}
-+
-+		errno = 0;
-+		mask_value = strtoul(mask, &endp, 10);
-+		if (errno || !endp || *endp) {
-+			fprintf(stderr, _failed_parsing_msg);
-+			continue;
-+		}
-+
-+		errno = 0;
-+		timeout_value = strtoul(timeout, &endp, 10);
-+		if (errno || !endp || *endp) {
-+			fprintf(stderr, _failed_parsing_msg);
-+			continue;
-+		}
-+
-+		if (daemon_talk(fifos, &msg, DM_EVENT_CMD_REGISTER_FOR_EVENT,
-+				dso_name,
-+				dev_name,
-+				(enum dm_event_mask) mask_value,
-+				timeout_value))
-+			fprintf(stderr, "Failed to reinstate monitoring for device %s.\n", dev_name);
-+	}
-+
-+	return 1;
-+}
-+
- static void restart(void)
- {
- 	struct dm_event_fifos fifos = {
-@@ -1837,9 +1927,9 @@ static void restart(void)
- 	char *message;
- 	int length;
- 	int version;
-+	const char *e;
- 
- 	/* Get the list of registrations from the running daemon. */
--
- 	if (!init_fifos(&fifos)) {
- 		fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n");
- 		exit(EXIT_FAILURE);
-@@ -1885,24 +1975,61 @@ static void restart(void)
- 	}
- 	_initial_registrations[count] = 0;
- 
-+	if (version >= 2) {
-+		if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
-+			fprintf(stderr, "Failed to acquire parameters from old dmeventd.\n");
-+			goto bad;
-+		}
-+		if (strstr(msg.data, "exec_method=systemd"))
-+			_systemd_activation = 1;
-+	}
-+#ifdef __linux__
-+	/*
-+	* If the protocol version is old, just assume that if systemd is running,
-+	* the dmeventd is also run as a systemd service via fifo activation.
-+	*/
-+	if (version < 2) {
-+		/* This check is copied from sd-daemon.c. */
-+		struct stat st;
-+		if (!lstat("/run/systemd/system/", &st) && !!S_ISDIR(st.st_mode))
-+			_systemd_activation = 1;
-+	}
-+#endif
-+
- 	if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) {
- 		fprintf(stderr, "Old dmeventd refused to die.\n");
- 		goto bad;
- 	}
- 
--	/*
--	 * Wait for daemon to die, detected by sending further DIE messages
--	 * until one fails.
--	 */
-+	if (!_systemd_activation &&
-+	    ((e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) && strcmp(e, "1")))
-+		_systemd_activation = 1;
-+
- 	for (i = 0; i < 10; ++i) {
--		if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0))
--			break; /* yep, it's dead probably */
-+		if ((access(DMEVENTD_PIDFILE, F_OK) == -1) && (errno == ENOENT))
-+			break;
- 		usleep(10);
- 	}
- 
-+	if (!_systemd_activation) {
-+		fini_fifos(&fifos);
-+		return;
-+	}
-+
-+	/* Reopen fifos. */
- 	fini_fifos(&fifos);
-+	if (!init_fifos(&fifos)) {
-+		fprintf(stderr, "Could not initiate communication with new instance of dmeventd.\n");
-+		exit(EXIT_FAILURE);
-+	}
- 
--	return;
-+	if (!_reinstate_registrations(&fifos)) {
-+		fprintf(stderr, "Failed to reinstate monitoring with new instance of dmeventd.\n");
-+		goto bad;
-+	}
-+
-+	fini_fifos(&fifos);
-+	exit(EXIT_SUCCESS);
- bad:
- 	fini_fifos(&fifos);
- 	exit(EXIT_FAILURE);
-diff --git a/daemons/dmeventd/dmeventd.h b/daemons/dmeventd/dmeventd.h
-index e21cf45..25a4bbb 100644
---- a/daemons/dmeventd/dmeventd.h
-+++ b/daemons/dmeventd/dmeventd.h
-@@ -34,6 +34,7 @@ enum dm_event_command {
- 	DM_EVENT_CMD_HELLO,
- 	DM_EVENT_CMD_DIE,
- 	DM_EVENT_CMD_GET_STATUS,
-+	DM_EVENT_CMD_GET_PARAMETERS,
- };
- 
- /* Message passed between client and daemon. */
-diff --git a/daemons/dmeventd/libdevmapper-event.c b/daemons/dmeventd/libdevmapper-event.c
-index 1b5273d..db9200f 100644
---- a/daemons/dmeventd/libdevmapper-event.c
-+++ b/daemons/dmeventd/libdevmapper-event.c
-@@ -619,6 +619,13 @@ 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-lvm2snapshot.so") &&
-+	    !strstr(dmevh->dso, "libdevmapper-event-lvm2mirror.so") &&
-+	    !strstr(dmevh->dso, "libdevmapper-event-lvm2raid.so"))
-+		log_warn("WARNING: %s: dmeventd plugins are deprecated", dmevh->dso);
-+
-+
- 	if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
- 			     dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
- 		log_error("%s: event registration failed: %s",
-diff --git a/daemons/dmeventd/libdevmapper-event.h b/daemons/dmeventd/libdevmapper-event.h
-index 9c1cc6f..532bebf 100644
---- a/daemons/dmeventd/libdevmapper-event.h
-+++ b/daemons/dmeventd/libdevmapper-event.h
-@@ -46,7 +46,7 @@ enum dm_event_mask {
- };
- 
- #define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
--#define DM_EVENT_PROTOCOL_VERSION 1
-+#define DM_EVENT_PROTOCOL_VERSION 2
- 
- struct dm_task;
- struct dm_event_handler;
-diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
-index eefbf1d..e6e222f 100644
---- a/daemons/lvmetad/lvmetad-core.c
-+++ b/daemons/lvmetad/lvmetad-core.c
-@@ -1095,7 +1095,8 @@ static response handler(daemon_state s, client_handle h, request r)
- 		return daemon_reply_simple("token_mismatch",
- 					   "expected = %s", state->token,
- 					   "received = %s", token,
--					   "reason = %s", "token mismatch", NULL);
-+					   "reason = %s",
-+					   "lvmetad cache is invalid due to a global_filter change or due to a running rescan", NULL);
- 	}
- 	pthread_mutex_unlock(&state->token_lock);
- 
-@@ -1189,7 +1190,7 @@ static int fini(daemon_state *s)
- 	return 1;
- }
- 
--static void usage(char *prog, FILE *file)
-+static void usage(const char *prog, FILE *file)
- {
- 	fprintf(file, "Usage:\n"
- 		"%s [-V] [-h] [-f] [-l {all|wire|debug}] [-s path]\n\n"
-@@ -1204,27 +1205,19 @@ static void usage(char *prog, FILE *file)
- int main(int argc, char *argv[])
- {
- 	signed char opt;
--	lvmetad_state ls;
-+	lvmetad_state ls = { .log_config = "" };
- 	daemon_state s = {
- 		.daemon_fini = fini,
- 		.daemon_init = init,
- 		.handler = handler,
- 		.name = "lvmetad",
--		.pidfile = getenv("LVM_LVMETAD_PIDFILE"),
-+		.pidfile = getenv("LVM_LVMETAD_PIDFILE") ? : LVMETAD_PIDFILE,
- 		.private = &ls,
- 		.protocol = "lvmetad",
- 		.protocol_version = 1,
--		.socket_path = getenv("LVM_LVMETAD_SOCKET"),
-+		.socket_path = getenv("LVM_LVMETAD_SOCKET") ? : LVMETAD_SOCKET,
- 	};
- 
--	if (!s.pidfile)
--		s.pidfile = LVMETAD_PIDFILE;
--
--	if (!s.socket_path)
--		s.socket_path = LVMETAD_SOCKET;
--
--	ls.log_config = "";
--
- 	// use getopt_long
- 	while ((opt = getopt(argc, argv, "?fhVl:p:s:")) != EOF) {
- 		switch (opt) {
-@@ -1253,5 +1246,6 @@ int main(int argc, char *argv[])
- 	}
- 
- 	daemon_start(s);
-+
- 	return 0;
- }
-diff --git a/lib/Makefile.in b/lib/Makefile.in
-index 8fdc194..968ad00 100644
---- a/lib/Makefile.in
-+++ b/lib/Makefile.in
-@@ -1,6 +1,6 @@
- #
- # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
--# Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
-+# Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
- #
- # This file is part of LVM2.
- #
-@@ -44,6 +44,10 @@ ifeq ("@THIN@", "shared")
-   SUBDIRS += thin
- endif
- 
-+ifeq ("@CACHE@", "shared")
-+  SUBDIRS += cache_segtype
-+endif
-+
- SOURCES =\
- 	activate/activate.c \
- 	cache/lvmcache.c \
-@@ -83,11 +87,13 @@ SOURCES =\
- 	locking/locking.c \
- 	locking/no_locking.c \
- 	log/log.c \
-+	metadata/cache_manip.c \
- 	metadata/lv.c \
- 	metadata/lv_manip.c \
- 	metadata/merge.c \
- 	metadata/metadata.c \
- 	metadata/mirror.c \
-+	metadata/pool_manip.c \
- 	metadata/pv.c \
- 	metadata/pv_manip.c \
- 	metadata/pv_map.c \
-@@ -164,6 +170,10 @@ ifeq ("@THIN@", "internal")
-   SOURCES += thin/thin.c
- endif
- 
-+ifeq ("@CACHE@", "internal")
-+  SOURCES += cache_segtype/cache.c
-+endif
-+
- ifeq ("@DEVMAPPER@", "yes")
-   SOURCES +=\
- 	activate/dev_manager.c \
-@@ -198,6 +208,7 @@ ifeq ($(MAKECMDGOALS),distclean)
- 	raid \
- 	replicator \
- 	thin \
-+	cache_segtype \
- 	locking
- endif
- 
-diff --git a/lib/activate/activate.c b/lib/activate/activate.c
-index 4c8c16d..26dc0e1 100644
---- a/lib/activate/activate.c
-+++ b/lib/activate/activate.c
-@@ -285,6 +285,18 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
- {
- 	return 0;
- }
-+int lv_cache_block_info(const struct logical_volume *lv,
-+			uint32_t *chunk_size, uint64_t *dirty_count,
-+			uint64_t *used_count, uint64_t *total_count)
-+{
-+	return 0;
-+}
-+int lv_cache_policy_info(const struct logical_volume *lv,
-+			 char **policy_name, int *policy_argc,
-+			 char ***policy_argv)
-+{
-+	return 0;
-+}
- int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
- 			 percent_t *percent)
- {
-@@ -969,6 +981,162 @@ out:
- 	return r;
- }
- 
-+int lv_cache_block_info(struct logical_volume *lv,
-+			uint32_t *chunk_size, uint64_t *dirty_count,
-+			uint64_t *used_count, uint64_t *total_count)
-+{
-+	struct lv_segment *cache_seg;
-+	struct logical_volume *cache_lv;
-+	struct dev_manager *dm;
-+	struct dm_status_cache *status;
-+
-+	/* The user is free to choose which args they are interested in */
-+	if (chunk_size)
-+		*chunk_size = 0;
-+	if (dirty_count)
-+		*dirty_count = 0;
-+	if (used_count)
-+		*used_count = 0;
-+	if (total_count)
-+		*total_count = 0;
-+
-+	if (lv_is_cache(lv))
-+		cache_lv = lv;
-+	else if (lv_is_cache_pool(lv)) {
-+		if (dm_list_empty(&lv->segs_using_this_lv)) {
-+			//FIXME: Ok to return value not sourced from kernel?
-+			//       This could be valuable - esp for 'lvs' output
-+			log_error(INTERNAL_ERROR "Unable to get block info"
-+				  " of unlinked cache_pool, %s", lv->name);
-+			//FIXME: ... because we could do this:
-+			if (chunk_size)
-+				*chunk_size = first_seg(lv)->chunk_size;
-+			/* Unlinked cache_pools have 0 dirty & used blocks */
-+			if (total_count) {
-+				*total_count = lv->size; /* in sectors */
-+				*total_count /= first_seg(lv)->chunk_size;
-+			}
-+
-+			return 1;
-+		}
-+		if (!(cache_seg = get_only_segment_using_this_lv(lv)))
-+			return_0;
-+		cache_lv = cache_seg->lv;
-+	} else {
-+		log_error(INTERNAL_ERROR
-+			  "Unable to get block info of non-cache LV, %s",
-+			  lv->name);
-+		return 0;
-+	}
-+
-+	if (!lv_info(cache_lv->vg->cmd, cache_lv, 0, NULL, 0, 0))
-+		return_0;
-+
-+	log_debug_activation("Checking cache block info for LV %s/%s",
-+			     cache_lv->vg->name, cache_lv->name);
-+
-+	if (!(dm = dev_manager_create(cache_lv->vg->cmd, cache_lv->vg->name, 1)))
-+		return_0;
-+
-+	if (!dev_manager_cache_status(dm, cache_lv, &status)) {
-+		dev_manager_destroy(dm);
-+		return_0;
-+	}
-+
-+	if (chunk_size)
-+		*chunk_size = status->block_size;
-+	if (dirty_count)
-+		*dirty_count = status->dirty_blocks;
-+	if (used_count)
-+		*used_count = status->used_blocks;
-+	if (total_count)
-+		*total_count = status->total_blocks;
-+
-+	dev_manager_destroy(dm);
-+
-+	return 1;
-+}
-+
-+int lv_cache_policy_info(struct logical_volume *lv,
-+			 char **policy_name, int *policy_argc,
-+			 char ***policy_argv)
-+{
-+	int i;
-+	struct lv_segment *cache_seg;
-+	struct logical_volume *cache_lv;
-+	struct dev_manager *dm;
-+	struct dm_status_cache *status;
-+	struct dm_pool *mem = lv->vg->cmd->mem;
-+
-+	/* The user is free to choose which args they are interested in */
-+	if (policy_name)
-+		*policy_name = NULL;
-+	if (policy_argc)
-+		*policy_argc = 0;
-+	if (policy_argv)
-+		*policy_argv = NULL;
-+
-+	if (lv_is_cache(lv))
-+		cache_lv = lv;
-+	else if (lv_is_cache_pool(lv)) {
-+		if (dm_list_empty(&lv->segs_using_this_lv)) {
-+			//FIXME: Ok to return value not sourced from kernel?
-+			log_error(INTERNAL_ERROR "Unable to get policy info"
-+				  " of unlinked cache_pool, %s", lv->name);
-+			//FIXME: ... because we could do this:
-+			if (policy_name)
-+				*policy_name = first_seg(lv)->policy_name;
-+			if (policy_argc)
-+				*policy_argc = first_seg(lv)->policy_argc;
-+			if (policy_argv)
-+				*policy_argv = first_seg(lv)->policy_argv;
-+
-+			return 1;
-+		}
-+		if (!(cache_seg = get_only_segment_using_this_lv(lv)))
-+			return_0;
-+		cache_lv = cache_seg->lv;
-+	} else {
-+		log_error(INTERNAL_ERROR
-+			  "Unable to get policy info of non-cache LV, %s",
-+			  lv->name);
-+		return 0;
-+	}
-+
-+	if (!lv_info(cache_lv->vg->cmd, cache_lv, 0, NULL, 0, 0))
-+		return_0;
-+
-+	log_debug_activation("Checking cache policy for LV %s/%s",
-+			     cache_lv->vg->name, cache_lv->name);
-+
-+	if (!(dm = dev_manager_create(cache_lv->vg->cmd, cache_lv->vg->name, 1)))
-+		return_0;
-+
-+	if (!dev_manager_cache_status(dm, cache_lv, &status)) {
-+		dev_manager_destroy(dm);
-+		return_0;
-+	}
-+
-+	if (policy_name &&
-+	    !(*policy_name = dm_pool_strdup(mem, status->policy_name)))
-+		return_0;
-+	if (policy_argc)
-+		*policy_argc = status->policy_argc;
-+	if (policy_argv) {
-+		if (!(*policy_argv =
-+		      dm_pool_zalloc(mem, sizeof(char *) * *policy_argc)))
-+			return_0;
-+		for (i = 0; i < *policy_argc; i++)
-+			if (!((*policy_argv)[i] =
-+			      dm_pool_strdup(mem, status->policy_argv[i])))
-+				return_0;
-+	}
-+
-+	dev_manager_destroy(dm);
-+
-+	return 1;
-+}
-+
- /*
-  * Returns data or metadata percent usage, depends on metadata 0/1.
-  * Returns 1 if percent set, else 0 on failure.
-diff --git a/lib/activate/activate.h b/lib/activate/activate.h
-index 1881f75..ad14a57 100644
---- a/lib/activate/activate.h
-+++ b/lib/activate/activate.h
-@@ -55,6 +55,11 @@ struct lv_activate_opts {
- /* target attribute flags */
- #define MIRROR_LOG_CLUSTERED	0x00000001U
- 
-+/* snapshot target attribute flags */
-+enum {
-+	SNAPSHOT_FEATURE_FIXED_LEAK		= (1 << 0), /* version 1.12 */
-+};
-+
- /* thin target attribute flags */
- enum {
- 	/* bitfields - new features from 1.1 version */
-@@ -64,6 +69,12 @@ enum {
- 	THIN_FEATURE_BLOCK_SIZE			= (1 << 3),
- 	THIN_FEATURE_DISCARDS_NON_POWER_2	= (1 << 4),
- 	THIN_FEATURE_METADATA_RESIZE		= (1 << 5),
-+	THIN_FEATURE_EXTERNAL_ORIGIN_EXTEND	= (1 << 6),
-+};
-+
-+/* raid target attribute flags */
-+enum {
-+	RAID_FEATURE_RAID10			= (1 << 0), /* version 1.3 */
- };
- 
- void set_activation(int activation);
-@@ -134,6 +145,12 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
- int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
- int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
- int lv_raid_message(const struct logical_volume *lv, const char *msg);
-+int lv_cache_block_info(struct logical_volume *lv,
-+			uint32_t *chunk_size, uint64_t *dirty_count,
-+			uint64_t *used_count, uint64_t *total_count);
-+int lv_cache_policy_info(struct logical_volume *lv,
-+			 char **policy_name, int *policy_argc,
-+			 char ***policy_argv);
- int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
- 			 percent_t *percent);
- int lv_thin_percent(const struct logical_volume *lv, int mapped,
-diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
-index 7b0b6e2..6b5f8c2 100644
---- a/lib/activate/dev_manager.c
-+++ b/lib/activate/dev_manager.c
-@@ -1,6 +1,6 @@
- /*
-  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
-- * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -63,7 +63,7 @@ struct lv_layer {
- 
- int read_only_lv(struct logical_volume *lv, struct lv_activate_opts *laopts)
- {
--	return (laopts->read_only || !(lv->vg->status & LVM_WRITE) || !(lv->status & LVM_WRITE));
-+	return (laopts->read_only || !(lv->status & LVM_WRITE));
- }
- 
- /*
-@@ -1160,6 +1160,55 @@ out:
- 	return r;
- }
- 
-+int dev_manager_cache_status(struct dev_manager *dm,
-+			     const struct logical_volume *lv,
-+			     struct dm_status_cache **status)
-+{
-+	int r = 0;
-+	const char *dlid;
-+	struct dm_task *dmt;
-+	struct dm_info info;
-+	uint64_t start, length;
-+	char *type = NULL;
-+	char *params = NULL;
-+	const char *layer = lv_layer(lv);
-+
-+	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer)))
-+		return_0;
-+
-+	log_debug_activation("Getting cache device status for %s.", lv->name);
-+
-+	if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0)))
-+		return_0;
-+
-+	if (!dm_task_no_open_count(dmt))
-+		log_error("Failed to disable open_count.");
-+
-+	if (!dm_task_run(dmt))
-+		goto_out;
-+
-+	if (!dm_task_get_info(dmt, &info) || !info.exists)
-+		goto_out;
-+
-+	dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
-+
-+	if (!type || strcmp(type, "cache")) {
-+		log_debug("Expected cache segment type but got %s instead",
-+			  type ? type : "NULL");
-+		goto out;
-+	}
-+
-+	if (!dm_get_status_cache(dm->mem, params, status))
-+		goto_out;
-+
-+	r = 1;
-+out:
-+	dm_task_destroy(dmt);
-+
-+	return r;
-+}
-+
-+//FIXME: Can we get rid of this crap below?
- #if 0
- 	log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
- 
-@@ -1863,6 +1912,10 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
- 		    !_add_lv_to_dtree(dm, dtree, seg->pool_lv, 1)) /* stack */
- 			return_0;
- 
-+		if (seg->pool_lv && lv_is_cache_pool(seg->pool_lv) &&
-+		    !_add_lv_to_dtree(dm, dtree, seg->pool_lv, 0))
-+			return_0;
-+
- 		for (s = 0; s < seg->area_count; s++) {
- 			if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s) &&
- 			    !_add_lv_to_dtree(dm, dtree, seg_lv(seg, s), 0))
-@@ -2327,15 +2380,18 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
- 	if (seg->external_lv &&
- 	    !_add_new_external_lv_to_dtree(dm, dtree, seg->external_lv, laopts))
- 		return_0;
-+
- 	/* Add mirror log */
- 	if (seg->log_lv &&
- 	    !_add_new_lv_to_dtree(dm, dtree, seg->log_lv, laopts, NULL))
- 		return_0;
--	/* Add thin pool metadata */
-+
-+	/* Add pool metadata */
- 	if (seg->metadata_lv &&
- 	    !_add_new_lv_to_dtree(dm, dtree, seg->metadata_lv, laopts, NULL))
- 		return_0;
--	/* Add thin pool layer */
-+
-+	/* Add pool layer */
- 	if (seg->pool_lv &&
- 	    !_add_new_lv_to_dtree(dm, dtree, seg->pool_lv, laopts,
- 				  lv_layer(seg->pool_lv)))
-@@ -2450,7 +2506,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
- 		     dinfo->open_count)) {
- 			if (seg_is_thin_volume(seg) ||
- 			    /* FIXME Is there anything simpler to check for instead? */
--                            !lv_has_target_type(dm->mem, lv, NULL, "snapshot-merge"))
-+			    !lv_has_target_type(dm->mem, lv, NULL, "snapshot-merge"))
- 				laopts->no_merging = 1;
- 		}
- 	}
-@@ -2506,7 +2562,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
- 			return_0;
- 		if (!laopts->no_merging && lv_is_merging_origin(lv)) {
- 			if (!_add_new_lv_to_dtree(dm, dtree,
--			     find_snapshot(lv)->cow, laopts, "cow"))
-+						  find_snapshot(lv)->cow, laopts, "cow"))
- 				return_0;
- 			/*
- 			 * Must also add "real" LV for use when
-diff --git a/lib/activate/dev_manager.h b/lib/activate/dev_manager.h
-index 032766e..446b349 100644
---- a/lib/activate/dev_manager.h
-+++ b/lib/activate/dev_manager.h
-@@ -60,6 +60,9 @@ int dev_manager_raid_status(struct dev_manager *dm,
- int dev_manager_raid_message(struct dev_manager *dm,
- 			     const struct logical_volume *lv,
- 			     const char *msg);
-+int dev_manager_cache_status(struct dev_manager *dm,
-+			     const struct logical_volume *lv,
-+			     struct dm_status_cache **status);
- int dev_manager_thin_pool_status(struct dev_manager *dm,
- 				 const struct logical_volume *lv,
- 				 struct dm_status_thin_pool **status,
-diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
-index ec8699b..d40bdce 100644
---- a/lib/cache/lvmcache.c
-+++ b/lib/cache/lvmcache.c
-@@ -264,9 +264,9 @@ static void _drop_metadata(const char *vgname, int drop_precommitted)
- }
- 
- /*
-- * Remote node uses this to upgrade precommited metadata to commited state
-+ * Remote node uses this to upgrade precommitted metadata to commited state
-  * when receives vg_commit notification.
-- * (Note that devices can be suspended here, if so, precommited metadata are already read.)
-+ * (Note that devices can be suspended here, if so, precommitted metadata are already read.)
-  */
- void lvmcache_commit_metadata(const char *vgname)
- {
-diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
-index aec6a71..c994874 100644
---- a/lib/cache/lvmetad.c
-+++ b/lib/cache/lvmetad.c
-@@ -40,7 +40,7 @@ void lvmetad_disconnect(void)
- 
- void lvmetad_init(struct cmd_context *cmd)
- {
--	if (!_lvmetad_use && !access(LVMETAD_PIDFILE, F_OK))
-+	if (!_lvmetad_use && !access(getenv("LVM_LVMETAD_PIDFILE") ? : LVMETAD_PIDFILE, F_OK))
- 		log_warn("WARNING: lvmetad is running but disabled."
- 			 " Restart lvmetad before enabling it!");
- 	_lvmetad_cmd = cmd;
-@@ -159,12 +159,27 @@ retry:
- 	daemon_request_destroy(req);
- 
- 	if (!repl.error && !strcmp(daemon_reply_str(repl, "response", ""), "token_mismatch") &&
--	    try < 2 && !test_mode()) {
--		if (lvmetad_pvscan_all_devs(_lvmetad_cmd, NULL)) {
--			++ try;
--			daemon_reply_destroy(repl);
--			goto retry;
--		}
-+	    try < 60 && !test_mode()) {
-+		/*
-+		 * If another process is trying to scan, they might have the
-+		 * same future token id and it's better to wait and avoid doing
-+		 * the work multiple times. For the case the future token is
-+		 * different, the wait is randomized so that multiple waiting
-+		 * processes do not start scanning all at once.
-+		 *
-+		 * If the token is mismatched because of global_filter changes,
-+		 * we re-scan immediately, but if we lose the potential race for
-+		 * the update, we back off for a short while (0.2-2 seconds) and
-+		 * try again.
-+		 */
-+		if (!strcmp(daemon_reply_str(repl, "expected", ""), "update in progress") || try % 5)
-+			usleep( 50000 + random() % 450000 ); /* 0.05 - 0.5s */
-+		else
-+			/* If the re-scan fails here, we try again later. */
-+			lvmetad_pvscan_all_devs(_lvmetad_cmd, NULL);
-+		++ try;
-+		daemon_reply_destroy(repl);
-+		goto retry;
- 	}
- 
- 	return repl;
-diff --git a/lib/cache_segtype/.exported_symbols b/lib/cache_segtype/.exported_symbols
-new file mode 100644
-index 0000000..95cb3ff
---- /dev/null
-+++ b/lib/cache_segtype/.exported_symbols
-@@ -0,0 +1 @@
-+init_cache_segtypes
-diff --git a/lib/cache_segtype/Makefile.in b/lib/cache_segtype/Makefile.in
-new file mode 100644
-index 0000000..32a1f2b
---- /dev/null
-+++ b/lib/cache_segtype/Makefile.in
-@@ -0,0 +1,24 @@
-+# Copyright (C) 2013-2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+srcdir = @srcdir@
-+top_srcdir = @top_srcdir@
-+top_builddir = @top_builddir@
-+
-+SOURCES = cache.c
-+
-+LIB_SHARED = liblvm2cache.$(LIB_SUFFIX)
-+LIB_VERSION = $(LIB_VERSION_LVM)
-+
-+include $(top_builddir)/make.tmpl
-+
-+install: install_lvm2_plugin
-diff --git a/lib/cache_segtype/cache.c b/lib/cache_segtype/cache.c
-new file mode 100644
-index 0000000..57c7a5c
---- /dev/null
-+++ b/lib/cache_segtype/cache.c
-@@ -0,0 +1,448 @@
-+/*
-+ * Copyright (C) 2013-2014 Red Hat, Inc. All rights reserved.
-+ *
-+ * This file is part of LVM2.
-+ *
-+ * This copyrighted material is made available to anyone wishing to use,
-+ * modify, copy, or redistribute it subject to the terms and conditions
-+ * of the GNU Lesser General Public License v.2.1.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public License
-+ * along with this program; if not, write to the Free Software Foundation,
-+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include "lib.h"
-+#include "toolcontext.h"
-+#include "segtype.h"
-+#include "display.h"
-+#include "text_export.h"
-+#include "config.h"
-+#include "str_list.h"
-+#include "targets.h"
-+#include "lvm-string.h"
-+#include "activate.h"
-+#include "metadata.h"
-+#include "lv_alloc.h"
-+#include "defaults.h"
-+
-+#define SEG_LOG_ERROR(t, p...) \
-+        log_error(t " segment %s of logical volume %s.", ## p,	\
-+                  dm_config_parent_name(sn), seg->lv->name), 0;
-+
-+
-+static const char *_name(const struct lv_segment *seg)
-+{
-+	return seg->segtype->name;
-+}
-+
-+static int _cache_pool_text_import(struct lv_segment *seg,
-+				   const struct dm_config_node *sn,
-+				   struct dm_hash_table *pv_hash __attribute__((unused)))
-+{
-+	uint32_t chunk_size;
-+	struct logical_volume *data_lv, *meta_lv;
-+	const char *str = NULL;
-+	char *argv_str;
-+	struct dm_pool *mem = seg->lv->vg->vgmem; //FIXME: what mempool should be used?
-+
-+	if (!dm_config_has_node(sn, "data"))
-+		return SEG_LOG_ERROR("Cache data not specified in");
-+	if (!(str = dm_config_find_str(sn, "data", NULL)))
-+		return SEG_LOG_ERROR("Cache data must be a string in");
-+	if (!(data_lv = find_lv(seg->lv->vg, str)))
-+		return SEG_LOG_ERROR("Unknown logical volume %s specified for "
-+			  "cache data in", str);
-+
-+	if (!dm_config_has_node(sn, "metadata"))
-+		return SEG_LOG_ERROR("Cache metadata not specified in");
-+	if (!(str = dm_config_find_str(sn, "metadata", NULL)))
-+		return SEG_LOG_ERROR("Cache metadata must be a string in");
-+	if (!(meta_lv = find_lv(seg->lv->vg, str)))
-+		return SEG_LOG_ERROR("Unknown logical volume %s specified for "
-+			  "cache metadata in", str);
-+
-+	if (!dm_config_get_uint32(sn, "chunk_size", &chunk_size))
-+		return SEG_LOG_ERROR("Couldn't read cache chunk_size in");
-+
-+	/*
-+	 * Read in features:
-+	 *   cache_mode = {writethrough|writeback}
-+	 *
-+	 *   'cache_mode' does not have to be present.
-+	 */
-+	if (dm_config_has_node(sn, "cache_mode")) {
-+		if (!(str = dm_config_find_str(sn, "cache_mode", NULL)))
-+			return SEG_LOG_ERROR("cache_mode must be a string in");
-+		if (!strcmp(str, "writethrough"))
-+			seg->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
-+		else if (!strcmp(str, "writeback"))
-+			seg->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
-+		else
-+			return SEG_LOG_ERROR("Unknown cache_mode in");
-+	}
-+
-+	/*
-+	 * Read in core arguments (these are key/value pairs)
-+	 *   core_argc = <# args>
-+	 *   core_argv = "[<key> <value>]..."
-+	 *
-+	 *   'core_argc' does not have to be present.  If it is not present,
-+	 *   any other core_* fields are ignored.  If it is present, then
-+	 *   'core_argv' must be present - even if they are
-+	 *   'core_argc = 0' and 'core_argv = ""'.
-+	 */
-+	if (dm_config_has_node(sn, "core_argc")) {
-+		if (!dm_config_has_node(sn, "core_argv"))
-+			return SEG_LOG_ERROR("not all core arguments defined in");
-+
-+		if (!dm_config_get_uint32(sn, "core_argc", &seg->core_argc))
-+			return SEG_LOG_ERROR("Unable to read core_argc in");
-+
-+		str = dm_config_find_str(sn, "core_argv", NULL);
-+		if ((str && !seg->core_argc) || (!str && seg->core_argc))
-+			return SEG_LOG_ERROR("core_argc and core_argv do"
-+					     " not match in");
-+
-+		if (!(seg->core_argv =
-+		      dm_pool_alloc(mem, sizeof(char *) * seg->core_argc)))
-+			return_0;
-+		if (str &&
-+		    (!(argv_str = dm_pool_strdup(mem, str)) ||
-+		     ((int)seg->core_argc != dm_split_words(argv_str, seg->core_argc,
-+							    0, seg->core_argv))))
-+			return SEG_LOG_ERROR("core_argc and core_argv do"
-+					     " not match in");
-+	}
-+
-+	/*
-+	 * Read in policy:
-+	 *   policy_name = "<policy_name>"
-+	 *   policy_argc = <# args>
-+	 *   policy_argv = "[<key> <value>]..."
-+	 *
-+	 *   'policy_name' does not have to be present.  If it is not present,
-+	 *   any other policy_* fields are ignored.  If it is present, then
-+	 *   the other policy_* fields must be present - even if they are
-+	 *   'policy_argc = 0' and 'policy_argv = ""'.
-+	 */
-+	if (dm_config_has_node(sn, "policy_name")) {
-+		if (!dm_config_has_node(sn, "policy_argc") ||
-+		    !dm_config_has_node(sn, "policy_argv"))
-+			return SEG_LOG_ERROR("not all policy arguments defined in");
-+		if (!(str = dm_config_find_str(sn, "policy_name", NULL)))
-+			return SEG_LOG_ERROR("policy_name must be a string in");
-+		seg->policy_name = dm_pool_strdup(mem, str);
-+
-+		if (!dm_config_get_uint32(sn, "policy_argc", &seg->policy_argc))
-+			return SEG_LOG_ERROR("Unable to read policy_argc in");
-+
-+		str = dm_config_find_str(sn, "policy_argv", NULL);
-+		if ((str && !seg->policy_argc) || (!str && seg->policy_argc))
-+			return SEG_LOG_ERROR("policy_argc and policy_argv do"
-+					     " not match in");
-+
-+		if (!(seg->policy_argv =
-+		      dm_pool_alloc(mem, sizeof(char *) * seg->policy_argc)))
-+			return_0;
-+		if (str &&
-+		    (!(argv_str = dm_pool_strdup(mem, str)) ||
-+		     ((int)seg->policy_argc != dm_split_words(argv_str,
-+							      seg->policy_argc,
-+							      0, seg->policy_argv))))
-+			return SEG_LOG_ERROR("policy_argc and policy_argv do"
-+					     " not match in");
-+	}
-+
-+	if (!attach_pool_data_lv(seg, data_lv))
-+		return_0;
-+	if (!attach_pool_metadata_lv(seg, meta_lv))
-+		return_0;
-+	seg->chunk_size = chunk_size;
-+
-+	return 1;
-+}
-+
-+static int _cache_pool_text_import_area_count(const struct dm_config_node *sn,
-+					      uint32_t *area_count)
-+{
-+	*area_count = 1;
-+
-+	return 1;
-+}
-+
-+static int _cache_pool_text_export(const struct lv_segment *seg,
-+				   struct formatter *f)
-+{
-+	unsigned i;
-+	char buf[256]; //FIXME: IS THERE AN 'outf' THAT DOESN'T DO NEWLINE?!?
-+	uint32_t feature_flags = seg->feature_flags;
-+
-+	outf(f, "data = \"%s\"", seg_lv(seg, 0)->name);
-+	outf(f, "metadata = \"%s\"", seg->metadata_lv->name);
-+	outf(f, "chunk_size = %" PRIu32, seg->chunk_size);
-+
-+	if (feature_flags) {
-+		if (feature_flags & DM_CACHE_FEATURE_WRITETHROUGH) {
-+			outf(f, "cache_mode = \"writethrough\"");
-+			feature_flags &= ~DM_CACHE_FEATURE_WRITETHROUGH;
-+		} else if (feature_flags & DM_CACHE_FEATURE_WRITEBACK) {
-+			outf(f, "cache_mode = \"writeback\"");
-+			feature_flags &= ~DM_CACHE_FEATURE_WRITEBACK;
-+		} else {
-+			log_error(INTERNAL_ERROR "Unknown feature flags "
-+				  "in cache_pool segment for %s", seg->lv->name);
-+			return 0;
-+		}
-+	}
-+
-+	if (seg->core_argc) {
-+		outf(f, "core_argc = %u", seg->core_argc);
-+		outf(f, "core_argv = \"");
-+		for (i = 0; i < seg->core_argc; i++)
-+			outf(f, "%s%s", i ? " " : "", seg->core_argv[i]);
-+		outf(f, "\"");
-+	}
-+
-+	if (seg->policy_name) {
-+		outf(f, "policy_name = \"%s\"", seg->policy_name);
-+		outf(f, "policy_argc = %u", seg->policy_argc);
-+		buf[0] = '\0';
-+		for (i = 0; i < seg->policy_argc; i++)
-+			sprintf(buf, "%s%s", i ? " " : "", seg->policy_argv[i]);
-+		outf(f, "policy_argv = \"%s\"", buf);
-+	}
-+
-+	return 1;
-+}
-+
-+static int _cache_pool_add_target_line(struct dev_manager *dm,
-+				       struct dm_pool *mem,
-+				       struct cmd_context *cmd __attribute__((unused)),
-+				       void **target_state __attribute__((unused)),
-+				       struct lv_segment *seg,
-+				       const struct lv_activate_opts *laopts __attribute__((unused)),
-+				       struct dm_tree_node *node, uint64_t len,
-+				       uint32_t *pvmove_mirror_count __attribute__((unused)))
-+{
-+	/*
-+	 * This /could/ be directed at _cdata, but I prefer
-+	 * not to give a user direct access to a sub-LV via
-+	 * this cache_pool.
-+	 */
-+	return dm_tree_node_add_error_target(node, len);
-+}
-+
-+static int _modules_needed(struct dm_pool *mem,
-+			   const struct lv_segment *seg __attribute__((unused)),
-+			   struct dm_list *modules)
-+{
-+	if (!str_list_add(mem, modules, "cache")) {
-+		log_error("cache module string list allocation failed");
-+		return 0;
-+	}
-+
-+	return 1;
-+}
-+
-+static void _destroy(struct segment_type *segtype)
-+{
-+	dm_free((void *) segtype);
-+}
-+
-+#ifdef DEVMAPPER_SUPPORT
-+static int _target_present(struct cmd_context *cmd,
-+				const struct lv_segment *seg __attribute__((unused)),
-+				unsigned *attributes __attribute__((unused)))
-+{
-+	uint32_t maj, min, patchlevel;
-+	static int _cache_checked = 0;
-+	static int _cache_present = 0;
-+
-+	if (!_cache_checked) {
-+		_cache_present = target_present(cmd, "cache", 1);
-+
-+		if (!target_version("cache", &maj, &min, &patchlevel)) {
-+			log_error("Failed to determine version of cache kernel module");
-+			return 0;
-+		}
-+
-+		_cache_checked = 1;
-+
-+		if ((maj < 1) ||
-+		    ((maj == 1) && (min < 3))) {
-+			log_error("The cache kernel module is version %u.%u.%u."
-+				  "  Version 1.3.0+ is required.",
-+				  maj, min, patchlevel);
-+			return 0;
-+		}
-+	}
-+
-+	return _cache_present;
-+}
-+
-+#endif /* DEVMAPPER_SUPPORT */
-+
-+static struct segtype_handler _cache_pool_ops = {
-+	.name = _name,
-+	.text_import = _cache_pool_text_import,
-+	.text_import_area_count = _cache_pool_text_import_area_count,
-+	.text_export = _cache_pool_text_export,
-+	.add_target_line = _cache_pool_add_target_line,
-+#ifdef DEVMAPPER_SUPPORT
-+	.target_present = _target_present,
-+#  ifdef DMEVENTD
-+#  endif        /* DMEVENTD */
-+#endif
-+	.modules_needed = _modules_needed,
-+	.destroy = _destroy,
-+};
-+
-+static int _cache_text_import(struct lv_segment *seg,
-+			      const struct dm_config_node *sn,
-+			      struct dm_hash_table *pv_hash __attribute__((unused)))
-+{
-+	struct logical_volume *pool_lv, *origin_lv;
-+	const char *name = NULL;
-+
-+	if (!dm_config_has_node(sn, "cache_pool"))
-+		return SEG_LOG_ERROR("cache_pool not specified in");
-+	if (!(name = dm_config_find_str(sn, "cache_pool", NULL)))
-+		return SEG_LOG_ERROR("cache_pool must be a string in");
-+	if (!(pool_lv = find_lv(seg->lv->vg, name)))
-+		return SEG_LOG_ERROR("Unknown logical volume %s specified for "
-+			  "cache_pool in", name);
-+
-+	if (!dm_config_has_node(sn, "origin"))
-+		return SEG_LOG_ERROR("Cache origin not specified in");
-+	if (!(name = dm_config_find_str(sn, "origin", NULL)))
-+		return SEG_LOG_ERROR("Cache origin must be a string in");
-+	if (!(origin_lv = find_lv(seg->lv->vg, name)))
-+		return SEG_LOG_ERROR("Unknown logical volume %s specified for "
-+			  "cache origin in", name);
-+
-+	if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0))
-+		return_0;
-+	if (!attach_pool_lv(seg, pool_lv, NULL, NULL))
-+		return_0;
-+
-+	return 1;
-+}
-+
-+static int _cache_text_import_area_count(const struct dm_config_node *sn,
-+					 uint32_t *area_count)
-+{
-+	*area_count = 1;
-+
-+	return 1;
-+}
-+
-+static int _cache_text_export(const struct lv_segment *seg, struct formatter *f)
-+{
-+	if (!seg_lv(seg, 0))
-+		return_0;
-+
-+	outf(f, "cache_pool = \"%s\"", seg->pool_lv->name);
-+	outf(f, "origin = \"%s\"", seg_lv(seg, 0)->name);
-+
-+	return 1;
-+}
-+
-+static int _cache_add_target_line(struct dev_manager *dm,
-+				 struct dm_pool *mem,
-+				 struct cmd_context *cmd __attribute__((unused)),
-+				 void **target_state __attribute__((unused)),
-+				 struct lv_segment *seg,
-+				 const struct lv_activate_opts *laopts __attribute__((unused)),
-+				 struct dm_tree_node *node, uint64_t len,
-+				 uint32_t *pvmove_mirror_count __attribute__((unused)))
-+{
-+	struct lv_segment *cache_pool_seg = first_seg(seg->pool_lv);
-+	char *metadata_uuid, *data_uuid, *origin_uuid;
-+
-+	if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv->lvid.s, NULL)))
-+		return_0;
-+
-+	if (!(data_uuid = build_dm_uuid(mem, seg_lv(cache_pool_seg, 0)->lvid.s, NULL)))
-+		return_0;
-+
-+	if (!(origin_uuid = build_dm_uuid(mem, seg_lv(seg, 0)->lvid.s, NULL)))
-+		return_0;
-+
-+	if (!dm_tree_node_add_cache_target(node, len,
-+					   metadata_uuid,
-+					   data_uuid,
-+					   origin_uuid,
-+					   cache_pool_seg->chunk_size,
-+					   cache_pool_seg->feature_flags,
-+					   cache_pool_seg->core_argc,
-+					   cache_pool_seg->core_argv,
-+					   cache_pool_seg->policy_name,
-+					   cache_pool_seg->policy_argc,
-+					   cache_pool_seg->policy_argv))
-+		return_0;
-+
-+	return add_areas_line(dm, seg, node, 0u, seg->area_count);
-+}
-+
-+static struct segtype_handler _cache_ops = {
-+	.name = _name,
-+	.text_import = _cache_text_import,
-+	.text_import_area_count = _cache_text_import_area_count,
-+	.text_export = _cache_text_export,
-+	.add_target_line = _cache_add_target_line,
-+#ifdef DEVMAPPER_SUPPORT
-+	.target_present = _target_present,
-+#  ifdef DMEVENTD
-+#  endif        /* DMEVENTD */
-+#endif
-+	.modules_needed = _modules_needed,
-+	.destroy = _destroy,
-+};
-+
-+#ifdef CACHE_INTERNAL /* Shared */
-+int init_cache_segtypes(struct cmd_context *cmd,
-+			struct segtype_library *seglib)
-+#else
-+int init_cache_segtypes(struct cmd_context *cmd,
-+			struct segtype_library *seglib);
-+int init_cache_segtypes(struct cmd_context *cmd,
-+			struct segtype_library *seglib)
-+#endif
-+{
-+	struct segment_type *segtype = dm_zalloc(sizeof(*segtype));
-+
-+	if (!segtype) {
-+		log_error("Failed to allocate memory for cache_pool segtype");
-+		return 0;
-+	}
-+	segtype->cmd = cmd;
-+
-+	segtype->name = "cache-pool";
-+	segtype->flags = SEG_CACHE_POOL;
-+	segtype->ops = &_cache_pool_ops;
-+	segtype->private = NULL;
-+
-+	if (!lvm_register_segtype(seglib, segtype))
-+		return_0;
-+	log_very_verbose("Initialised segtype: %s", segtype->name);
-+
-+	segtype = dm_zalloc(sizeof(*segtype));
-+	if (!segtype) {
-+		log_error("Failed to allocate memory for cache segtype");
-+		return 0;
-+	}
-+	segtype->cmd = cmd;
-+
-+	segtype->name = "cache";
-+	segtype->flags = SEG_CACHE;
-+	segtype->ops = &_cache_ops;
-+	segtype->private = NULL;
-+
-+	if (!lvm_register_segtype(seglib, segtype))
-+		return_0;
-+	log_very_verbose("Initialised segtype: %s", segtype->name);
-+
-+	return 1;
-+}
-+
-diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
-index 9d6ef5e..a709284 100644
---- a/lib/commands/toolcontext.c
-+++ b/lib/commands/toolcontext.c
-@@ -1,6 +1,6 @@
--		/*
-+/*
-  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
-- * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -1181,6 +1181,11 @@ static int _init_segtypes(struct cmd_context *cmd)
- 		return 0;
- #endif
- 
-+#ifdef CACHE_INTERNAL
-+	if (!init_cache_segtypes(cmd, &seglib))
-+		return 0;
-+#endif
-+
- #ifdef HAVE_LIBDL
- 	/* Load any formats in shared libs unless static */
- 	if (!is_static() &&
-diff --git a/lib/config/config.c b/lib/config/config.c
-index 6e93c40..e51c26f 100644
---- a/lib/config/config.c
-+++ b/lib/config/config.c
-@@ -477,20 +477,24 @@ time_t config_file_timestamp(struct dm_config_tree *cft)
- 
- #define cfg_def_get_item_p(id) (&_cfg_def_items[id])
- #define cfg_def_get_default_value(item,type) item->default_value.v_##type
--#define cfg_def_get_path(item) (_cfg_def_make_path(_cfg_path,CFG_PATH_MAX_LEN,item->id,item),_cfg_path)
-+#define cfg_def_get_path(item) (_cfg_def_make_path(_cfg_path,CFG_PATH_MAX_LEN,item->id,item, 0),_cfg_path)
-+#define cfg_def_get_path_xlated(item) (_cfg_def_make_path(_cfg_path,CFG_PATH_MAX_LEN,item->id,item, 1),_cfg_path)
- 
--static int _cfg_def_make_path(char *buf, size_t buf_size, int id, cfg_def_item_t *item)
-+static int _cfg_def_make_path(char *buf, size_t buf_size, int id, cfg_def_item_t *item, int xlate)
- {
-+	int variable = item->flags & CFG_NAME_VARIABLE;
- 	int parent_id = item->parent;
- 	int count, n;
- 
- 	if (id == parent_id)
- 		return 0;
- 
--	count = _cfg_def_make_path(buf, buf_size, parent_id, cfg_def_get_item_p(parent_id));
--	if ((n = dm_snprintf(buf + count, buf_size - count, "%s%s",
-+	count = _cfg_def_make_path(buf, buf_size, parent_id, cfg_def_get_item_p(parent_id), xlate);
-+	if ((n = dm_snprintf(buf + count, buf_size - count, "%s%s%s%s",
- 			     count ? "/" : "",
--			     item->flags & CFG_NAME_VARIABLE ? "#" : item->name)) < 0) {
-+			     xlate && variable ? "<" : "",
-+			     !xlate && variable ? "#" : item->name,
-+			     xlate && variable ? ">" : "")) < 0) {
- 		log_error(INTERNAL_ERROR "_cfg_def_make_path: supplied buffer too small for %s/%s",
- 					  cfg_def_get_item_p(parent_id)->name, item->name);
- 		buf[0] = '\0';
-@@ -502,7 +506,7 @@ static int _cfg_def_make_path(char *buf, size_t buf_size, int id, cfg_def_item_t
- 
- int config_def_get_path(char *buf, size_t buf_size, int id)
- {
--	return _cfg_def_make_path(buf, buf_size, id, cfg_def_get_item_p(id));
-+	return _cfg_def_make_path(buf, buf_size, id, cfg_def_get_item_p(id), 0);
- }
- 
- static void _get_type_name(char *buf, size_t buf_size, cfg_def_type_t type)
-@@ -1086,8 +1090,7 @@ int merge_config_tree(struct cmd_context *cmd, struct dm_config_tree *cft,
- 
- struct out_baton {
- 	FILE *fp;
--	int withcomment;
--	int withversion;
-+	struct config_def_tree_spec *tree_spec;
- };
- 
- static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, void *baton)
-@@ -1108,8 +1111,8 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
- 
- 	cfg_def = cfg_def_get_item_p(cn->id);
- 
--	if (out->withcomment) {
--		path = cfg_def_get_path(cfg_def);
-+	if (out->tree_spec->withcomments) {
-+		path = cfg_def_get_path_xlated(cfg_def);
- 		fprintf(out->fp, "%s# Configuration %s %s.\n", line, node_type_name, path);
- 
- 		if (cfg_def->comment)
-@@ -1120,9 +1123,15 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
- 
- 		if (cfg_def->flags & CFG_UNSUPPORTED)
- 			fprintf(out->fp, "%s# This configuration %s is not officially supported.\n", line, node_type_name);
-+
-+		if (cfg_def->flags & CFG_NAME_VARIABLE)
-+			fprintf(out->fp, "%s# This configuration %s has variable name.\n", line, node_type_name);
-+
-+		if (cfg_def->flags & CFG_DEFAULT_UNDEFINED)
-+			fprintf(out->fp, "%s# This configuration %s does not have a default value defined.\n", line, node_type_name);
- 	}
- 
--	if (out->withversion) {
-+	if (out->tree_spec->withversions) {
- 		if (dm_snprintf(version, 9, "%u.%u.%u",
- 				(cfg_def->since_version & 0xE000) >> 13,
- 				(cfg_def->since_version & 0x1E00) >> 9,
-@@ -1139,7 +1148,10 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
- static int _out_line_fn(const struct dm_config_node *cn, const char *line, void *baton)
- {
- 	struct out_baton *out = baton;
--	fprintf(out->fp, "%s\n", line);
-+	struct cfg_def_item *cfg_def = cfg_def_get_item_p(cn->id);
-+
-+	fprintf(out->fp, "%s%s\n", (out->tree_spec->type != CFG_DEF_TREE_CURRENT) &&
-+				   (cfg_def->flags & CFG_DEFAULT_UNDEFINED) ? "#" : "", line);
- 	return 1;
- }
- 
-@@ -1149,7 +1161,7 @@ static int _out_suffix_fn(const struct dm_config_node *cn, const char *line, voi
- }
- 
- int config_write(struct dm_config_tree *cft,
--		 int withcomment, int withversion,
-+		 struct config_def_tree_spec *tree_spec,
- 		 const char *file, int argc, char **argv)
- {
- 	static const struct dm_config_node_out_spec _out_spec = {
-@@ -1159,8 +1171,7 @@ int config_write(struct dm_config_tree *cft,
- 	};
- 	const struct dm_config_node *cn;
- 	struct out_baton baton = {
--		.withcomment = withcomment,
--		.withversion = withversion
-+		.tree_spec = tree_spec
- 	};
- 	int r = 1;
- 
-diff --git a/lib/config/config.h b/lib/config/config.h
-index 0769c40..f716efb 100644
---- a/lib/config/config.h
-+++ b/lib/config/config.h
-@@ -82,6 +82,8 @@ typedef union {
- #define CFG_UNSUPPORTED		0x08
- /* whether the configuration item is customizable by a profile */
- #define CFG_PROFILABLE		0x10
-+/* whether the default value is undefned */
-+#define CFG_DEFAULT_UNDEFINED	0x20
- 
- /* configuration definition item structure */
- typedef struct cfg_def_item {
-@@ -109,8 +111,10 @@ typedef enum {
- struct config_def_tree_spec {
- 	cfg_def_tree_t type;		/* tree type */
- 	uint16_t version;		/* tree at this LVM2 version */
--	int ignoreadvanced;		/* do not include advanced configs */
--	int ignoreunsupported;		/* do not include unsupported configs */
-+	int ignoreadvanced:1;		/* do not include advanced configs */
-+	int ignoreunsupported:1;	/* do not include unsupported configs */
-+	int withcomments:1;		/* include comments */
-+	int withversions:1;		/* include versions */
- 	uint8_t *check_status;		/* status of last tree check (currently needed for CFG_DEF_TREE_MISSING only) */
- };
- 
-@@ -163,8 +167,7 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
- 			checksum_fn_t checksum_fn, uint32_t checksum);
- int config_file_read(struct dm_config_tree *cft);
- struct dm_config_tree *config_file_open_and_read(const char *config_file, config_source_t source);
--int config_write(struct dm_config_tree *cft,
--		 int withcomment, int withversion,
-+int config_write(struct dm_config_tree *cft, struct config_def_tree_spec *tree_spec,
- 		 const char *file, int argc, char **argv);
- struct dm_config_tree *config_def_create_tree(struct config_def_tree_spec *spec);
- void config_destroy(struct dm_config_tree *cft);
-diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
-index 06cff7e..2c0dff2 100644
---- a/lib/config/config_settings.h
-+++ b/lib/config/config_settings.h
-@@ -32,6 +32,7 @@
-  * 				CFG_ADVANCED - this node belongs to advanced config set
-  * 				CFG_UNSUPPORTED - this node belongs to unsupported config set
-  * 				CFG_PROFILABLE - this node is customizable by a profile
-+ * 				CFG_DEFAULT_UNDEFINED - node's default value is undefined
-  * type:		allowed type for the value of simple configuation setting, one of:
-  * 				CFG_TYPE_BOOL
-  * 				CFG_TYPE_INT
-@@ -77,16 +78,16 @@ cfg(config_profile_dir_CFG, "profile_dir", config_CFG_SECTION, 0, CFG_TYPE_STRIN
- 
- cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DEV_DIR, vsn(1, 0, 0), NULL)
- cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, 0, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL)
--cfg_array(devices_loopfiles_CFG, "loopfiles", devices_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(1, 2, 0), NULL)
-+cfg_array(devices_loopfiles_CFG, "loopfiles", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 2, 0), NULL)
- cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV, vsn(2, 2, 85), NULL)
--cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL)
--cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
--cfg_array(devices_global_filter_CFG, "global_filter", devices_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(2, 2, 98), NULL)
-+cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL)
-+cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
-+cfg_array(devices_global_filter_CFG, "global_filter", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 98), NULL)
- cfg(devices_cache_CFG, "cache", devices_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
- cfg(devices_cache_dir_CFG, "cache_dir", devices_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL)
- cfg(devices_cache_file_prefix_CFG, "cache_file_prefix", devices_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL)
- cfg(devices_write_cache_state_CFG, "write_cache_state", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(1, 0, 0), NULL)
--cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, 0, CFG_TYPE_INT | CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
-+cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT | CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
- cfg(devices_sysfs_scan_CFG, "sysfs_scan", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SYSFS_SCAN, vsn(1, 0, 8), NULL)
- cfg(devices_multipath_component_detection_CFG, "multipath_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MULTIPATH_COMPONENT_DETECTION, vsn(2, 2, 89), NULL)
- cfg(devices_md_component_detection_CFG, "md_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_COMPONENT_DETECTION, vsn(1, 0, 18), NULL)
-@@ -102,11 +103,15 @@ cfg(devices_require_restorefile_with_uuid_CFG, "require_restorefile_with_uuid",
- cfg(devices_pv_min_size_CFG, "pv_min_size", devices_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_PV_MIN_SIZE_KB, vsn(2, 2, 85), NULL)
- cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ISSUE_DISCARDS, vsn(2, 2, 85), NULL)
- 
--cfg_array(allocation_cling_tag_list_CFG, "cling_tag_list", allocation_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(2, 2, 77), NULL)
-+cfg_array(allocation_cling_tag_list_CFG, "cling_tag_list", allocation_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 77), NULL)
- cfg(allocation_maximise_cling_CFG, "maximise_cling", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MAXIMISE_CLING, vsn(2, 2, 85), NULL)
- cfg(allocation_use_blkid_wiping_CFG, "use_blkid_wiping", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 105), NULL)
- cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_zeroing_new_lvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 105), NULL)
- cfg(allocation_mirror_logs_require_separate_pvs_CFG, "mirror_logs_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MIRROR_LOGS_REQUIRE_SEPARATE_PVS, vsn(2, 2, 85), NULL)
-+
-+cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL)
-+cfg(allocation_cache_pool_chunk_size_CFG, "cache_pool_chunk_size", allocation_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 106), NULL)
-+
- cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL)
- cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL)
- cfg(allocation_thin_pool_discards_CFG, "thin_pool_discards", allocation_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_STRING, DEFAULT_THIN_POOL_DISCARDS, vsn(2, 2, 99), NULL)
-@@ -144,8 +149,8 @@ cfg(global_activation_CFG, "activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, D
- cfg(global_suffix_CFG, "suffix", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SUFFIX, vsn(1, 0, 0), NULL)
- cfg(global_fallback_to_lvm1_CFG, "fallback_to_lvm1", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LVM1, vsn(1, 0, 18), NULL)
- cfg(global_format_CFG, "format", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_FORMAT, vsn(1, 0, 0), NULL)
--cfg_array(global_format_libraries_CFG, "format_libraries", global_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
--cfg_array(global_segment_libraries_CFG, "segment_libraries", global_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL)
-+cfg_array(global_format_libraries_CFG, "format_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
-+cfg_array(global_segment_libraries_CFG, "segment_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL)
- cfg(global_proc_CFG, "proc", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_PROC_DIR, vsn(1, 0, 0), NULL)
- cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, 0, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL)
- cfg(global_wait_for_locks_CFG, "wait_for_locks", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_WAIT_FOR_LOCKS, vsn(2, 2, 50), NULL)
-@@ -179,9 +184,9 @@ cfg(activation_use_linear_target_CFG, "use_linear_target", activation_CFG_SECTIO
- cfg(activation_reserved_stack_CFG, "reserved_stack", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RESERVED_STACK, vsn(1, 0, 0), NULL)
- cfg(activation_reserved_memory_CFG, "reserved_memory", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RESERVED_MEMORY, vsn(1, 0, 0), NULL)
- cfg(activation_process_priority_CFG, "process_priority", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_PROCESS_PRIORITY, vsn(1, 0, 0), NULL)
--cfg_array(activation_volume_list_CFG, "volume_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL)
--cfg_array(activation_auto_activation_volume_list_CFG, "auto_activation_volume_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, NULL, vsn(2, 2, 97), NULL)
--cfg_array(activation_read_only_volume_list_CFG, "read_only_volume_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, NULL, vsn(2, 2, 89), NULL)
-+cfg_array(activation_volume_list_CFG, "volume_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY|CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL)
-+cfg_array(activation_auto_activation_volume_list_CFG, "auto_activation_volume_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 97), NULL)
-+cfg_array(activation_read_only_volume_list_CFG, "read_only_volume_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 89), NULL)
- cfg(activation_mirror_region_size_CFG, "mirror_region_size", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(1, 0, 0), NULL)
- cfg(activation_raid_region_size_CFG, "raid_region_size", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(2, 2, 99), NULL)
- cfg(activation_readahead_CFG, "readahead", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_READ_AHEAD, vsn(1, 0, 23), NULL)
-@@ -193,7 +198,7 @@ cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold
- cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_PERCENT, vsn(2, 2, 75), NULL)
- cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD, vsn(2, 2, 89), NULL)
- cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent", activation_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT, vsn(2, 2, 89), NULL)
--cfg_array(activation_mlock_filter_CFG, "mlock_filter", activation_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(2, 2, 62), NULL)
-+cfg_array(activation_mlock_filter_CFG, "mlock_filter", activation_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 62), NULL)
- cfg(activation_use_mlockall_CFG, "use_mlockall", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_MLOCKALL, vsn(2, 2, 62), NULL)
- cfg(activation_monitoring_CFG, "monitoring", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DMEVENTD_MONITOR, vsn(2, 2, 63), NULL)
- cfg(activation_polling_interval_CFG, "polling_interval", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_INTERVAL, vsn(2, 2, 63), NULL)
-@@ -204,13 +209,13 @@ cfg(metadata_vgmetadatacopies_CFG, "vgmetadatacopies", metadata_CFG_SECTION, CFG
- cfg(metadata_pvmetadatasize_CFG, "pvmetadatasize", metadata_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_INT, DEFAULT_PVMETADATASIZE, vsn(1, 0, 0), NULL)
- cfg(metadata_pvmetadataignore_CFG, "pvmetadataignore", metadata_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_BOOL, DEFAULT_PVMETADATAIGNORE, vsn(2, 2, 69), NULL)
- cfg(metadata_stripesize_CFG, "stripesize", metadata_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_INT, DEFAULT_STRIPESIZE, vsn(1, 0, 0), NULL)
--cfg_array(metadata_dirs_CFG, "dirs", metadata_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
-+cfg_array(metadata_dirs_CFG, "dirs", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
- 
--cfg_section(metadata_disk_areas_CFG_SUBSECTION, "disk_areas", metadata_CFG_SECTION, CFG_ADVANCED | CFG_UNSUPPORTED, vsn(1, 0, 0), NULL)
--cfg_section(disk_area_CFG_SUBSECTION, "disk_area", metadata_disk_areas_CFG_SUBSECTION, CFG_NAME_VARIABLE | CFG_ADVANCED | CFG_UNSUPPORTED, vsn(1, 0, 0), NULL)
--cfg(disk_area_start_sector_CFG, "start_sector", disk_area_CFG_SUBSECTION, CFG_ADVANCED | CFG_UNSUPPORTED, CFG_TYPE_INT, 0, vsn(1, 0, 0), NULL)
--cfg(disk_area_size_CFG, "size", disk_area_CFG_SUBSECTION, CFG_ADVANCED | CFG_UNSUPPORTED, CFG_TYPE_INT, 0, vsn(1, 0, 0), NULL)
--cfg(disk_area_id_CFG, "id", disk_area_CFG_SUBSECTION, CFG_ADVANCED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
-+cfg_section(metadata_disk_areas_CFG_SUBSECTION, "disk_areas", metadata_CFG_SECTION, CFG_ADVANCED | CFG_UNSUPPORTED | CFG_DEFAULT_UNDEFINED, vsn(1, 0, 0), NULL)
-+cfg_section(disk_area_CFG_SUBSECTION, "disk_area", metadata_disk_areas_CFG_SUBSECTION, CFG_NAME_VARIABLE | CFG_ADVANCED | CFG_UNSUPPORTED | CFG_DEFAULT_UNDEFINED, vsn(1, 0, 0), NULL)
-+cfg(disk_area_start_sector_CFG, "start_sector", disk_area_CFG_SUBSECTION, CFG_ADVANCED | CFG_UNSUPPORTED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, 0, vsn(1, 0, 0), NULL)
-+cfg(disk_area_size_CFG, "size", disk_area_CFG_SUBSECTION, CFG_ADVANCED | CFG_UNSUPPORTED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, 0, vsn(1, 0, 0), NULL)
-+cfg(disk_area_id_CFG, "id", disk_area_CFG_SUBSECTION, CFG_ADVANCED | CFG_UNSUPPORTED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
- 
- cfg(report_aligned_CFG, "aligned", report_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_REP_ALIGNED, vsn(1, 0, 0), NULL)
- cfg(report_buffered_CFG, "buffered", report_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_REP_BUFFERED, vsn(1, 0, 0), NULL)
-@@ -242,11 +247,11 @@ cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, 0, CFG_
- cfg(dmeventd_raid_library_CFG, "raid_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_RAID_LIB, vsn(2, 2, 87), NULL)
- cfg(dmeventd_snapshot_library_CFG, "snapshot_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_SNAPSHOT_LIB, vsn(1, 2, 26), NULL)
- cfg(dmeventd_thin_library_CFG, "thin_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_THIN_LIB, vsn(2, 2, 89), NULL)
--cfg(dmeventd_executable_CFG, "executable", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, NULL, vsn(2, 2, 73), NULL)
-+cfg(dmeventd_executable_CFG, "executable", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DMEVENTD_PATH, vsn(2, 2, 73), NULL)
- 
- cfg(tags_hosttags_CFG, "hosttags", tags_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_HOSTTAGS, vsn(1, 0, 18), NULL)
- 
--cfg_section(tag_CFG_SUBSECTION, "tag", tags_CFG_SECTION, CFG_NAME_VARIABLE, vsn(1, 0, 18), NULL)
--cfg(tag_host_list_CFG, "host_list", tag_CFG_SUBSECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL)
-+cfg_section(tag_CFG_SUBSECTION, "tag", tags_CFG_SECTION, CFG_NAME_VARIABLE | CFG_DEFAULT_UNDEFINED, vsn(1, 0, 18), NULL)
-+cfg(tag_host_list_CFG, "host_list", tag_CFG_SUBSECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL)
- 
- cfg(CFG_COUNT, NULL, root_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL)
-diff --git a/lib/config/defaults.h b/lib/config/defaults.h
-index 141b7ae..6820def 100644
---- a/lib/config/defaults.h
-+++ b/lib/config/defaults.h
-@@ -77,7 +77,12 @@
- #define DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE 512 /* KB */
- #define DEFAULT_THIN_POOL_DISCARDS "passdown"
- #define DEFAULT_THIN_POOL_ZERO 1
--#define DEFAULT_POOL_METADATA_SPARE 1
-+#define DEFAULT_POOL_METADATA_SPARE 1 /* thin + cache */
-+
-+#define DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
-+#define DEFAULT_CACHE_POOL_CHUNK_SIZE 64 /* KB */
-+#define DEFAULT_CACHE_POOL_MIN_METADATA_SIZE 2048  /* KB */
-+#define DEFAULT_CACHE_POOL_MAX_METADATA_SIZE (16 * 1024 * 1024)  /* KB */
- 
- #define DEFAULT_UMASK 0077
- 
-diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c
-index 82cc2fc..6697456 100644
---- a/lib/device/dev-io.c
-+++ b/lib/device/dev-io.c
-@@ -178,8 +178,8 @@ int dev_get_block_size(struct device *dev, unsigned int *physical_block_size, un
- 	*physical_block_size = (unsigned int) dev->phys_block_size;
- 	*block_size = (unsigned int) dev->block_size;
- out:
--	if (needs_open)
--		dev_close(dev);
-+	if (needs_open && !dev_close(dev))
-+		stack;
- 
- 	return r;
- }
-diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
-index 02bc99f..1efc447 100644
---- a/lib/device/dev-type.c
-+++ b/lib/device/dev-type.c
-@@ -449,25 +449,45 @@ out:
- 
- #ifdef BLKID_WIPING_SUPPORT
- 
-+static inline int _type_in_flag_list(const char *type, uint32_t flag_list)
-+{
-+	return (((flag_list & TYPE_LVM2_MEMBER) && !strcmp(type, "LVM2_member")) ||
-+		((flag_list & TYPE_LVM1_MEMBER) && !strcmp(type, "LVM1_member")) ||
-+		((flag_list & TYPE_DM_SNAPSHOT_COW) && !strcmp(type, "DM_snapshot_cow")));
-+}
-+
- static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
--		       int exclude_lvm_member, int yes, force_t force)
-+		       uint32_t types_to_exclude, uint32_t types_no_prompt,
-+		       int yes, force_t force)
- {
-+	static const char _msg_failed_offset[] = "Failed to get offset of the %s signature on %s.";
-+	static const char _msg_failed_length[] = "Failed to get length of the %s signature on %s.";
-+	static const char _msg_wiping[] = "Wiping %s signature on %s.";
- 	const char *offset = NULL, *type = NULL, *magic = NULL,
- 		   *usage = NULL, *label = NULL, *uuid = NULL;
- 	loff_t offset_value;
- 	size_t len;
- 
- 	if (!blkid_probe_lookup_value(probe, "TYPE", &type, NULL)) {
--		if (exclude_lvm_member &&
--		    (!strcmp(type, "LVM1_member") || !strcmp(type, "LVM2_member")))
-+		if (_type_in_flag_list(type, types_to_exclude))
- 			return 1;
--		if (!blkid_probe_lookup_value(probe, "SBMAGIC_OFFSET", &offset, NULL) &&
--		     blkid_probe_lookup_value(probe, "SBMAGIC", &magic, &len))
--			return_0;
-+		if (blkid_probe_lookup_value(probe, "SBMAGIC_OFFSET", &offset, NULL)) {
-+			log_error(_msg_failed_offset, type, name);
-+			return 0;
-+		}
-+		if (blkid_probe_lookup_value(probe, "SBMAGIC", &magic, &len)) {
-+			log_error(_msg_failed_length, type, name);
-+			return 0;
-+		}
- 	} else if (!blkid_probe_lookup_value(probe, "PTTYPE", &type, NULL)) {
--		if (!blkid_probe_lookup_value(probe, "PTMAGIC_OFFSET", &offset, NULL) &&
--		     blkid_probe_lookup_value(probe, "PTMAGIC", &magic, &len))
--			return_0;
-+		if (blkid_probe_lookup_value(probe, "PTMAGIC_OFFSET", &offset, NULL)) {
-+			log_error(_msg_failed_offset, type, name);
-+			return 0;
-+		}
-+		if (blkid_probe_lookup_value(probe, "PTMAGIC", &magic, &len)) {
-+			log_error(_msg_failed_length, type, name);
-+			return 0;
-+		}
- 		usage = "partition table";
- 	} else
- 		return_0;
-@@ -483,12 +503,15 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
- 		    "UUID=\"%s\" TYPE=\"%s\" USAGE=\"%s\"",
- 		     name, offset, label, uuid, type, usage);
- 
--	if (!yes && (force == PROMPT) &&
--	    yes_no_prompt("WARNING: %s signature detected on %s at offset %s. "
--			  "Wipe it? [y/n] ", type, name, offset) != 'y')
--		return_0;
-+	if (!_type_in_flag_list(type, types_no_prompt)) {
-+		if (!yes && (force == PROMPT) &&
-+		    yes_no_prompt("WARNING: %s signature detected on %s at offset %s. "
-+				  "Wipe it? [y/n] ", type, name, offset) != 'y')
-+			return_0;
-+		log_print_unless_silent(_msg_wiping, type, name);
-+	} else
-+		log_verbose(_msg_wiping, type, name);
- 
--	log_print_unless_silent("Wiping %s signature on %s.", type, name);
- 	if (!dev_set(dev, offset_value, len, 0)) {
- 		log_error("Failed to wipe %s signature on %s.", type, name);
- 		return 0;
-@@ -498,7 +521,8 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
- }
- 
- static int _wipe_known_signatures_with_blkid(struct device *dev, const char *name,
--					     int exclude_lvm_member,
-+					     uint32_t types_to_exclude,
-+					     uint32_t types_no_prompt,
- 					     int yes, force_t force)
- {
- 	blkid_probe probe = NULL;
-@@ -525,7 +549,7 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
- 
- 	while (!blkid_do_probe(probe)) {
- 		found++;
--		if (_blkid_wipe(probe, dev, name, exclude_lvm_member, yes, force))
-+		if (_blkid_wipe(probe, dev, name, types_to_exclude, types_no_prompt, yes, force))
- 			wiped++;
- 	}
- 
-@@ -579,7 +603,8 @@ static int _wipe_signature(struct device *dev, const char *type, const char *nam
- }
- 
- static int _wipe_known_signatures_with_lvm(struct device *dev, const char *name,
--					   int exclude_lvm_member,
-+					   uint32_t types_to_exclude __attribute__((unused)),
-+					   uint32_t types_no_prompt __attribute__((unused)),
- 					   int yes, force_t force)
- {
- 	if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, dev_is_md) ||
-@@ -591,16 +616,20 @@ static int _wipe_known_signatures_with_lvm(struct device *dev, const char *name,
- }
- 
- int wipe_known_signatures(struct cmd_context *cmd, struct device *dev,
--			  const char *name, int exclude_lvm_member,
--			  int yes, force_t force)
-+			  const char *name, uint32_t types_to_exclude,
-+			  uint32_t types_no_prompt, int yes, force_t force)
- {
- #ifdef BLKID_WIPING_SUPPORT
- 	if (find_config_tree_bool(cmd, allocation_use_blkid_wiping_CFG, NULL))
- 		return _wipe_known_signatures_with_blkid(dev, name,
--				exclude_lvm_member, yes, force);
-+							 types_to_exclude,
-+							 types_no_prompt,
-+							 yes, force);
- #endif
- 	return _wipe_known_signatures_with_lvm(dev, name,
--			exclude_lvm_member, yes, force);
-+					       types_to_exclude,
-+					       types_no_prompt,
-+					       yes, force);
- }
- 
- #ifdef __linux__
-diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
-index 284280e..b1520ee 100644
---- a/lib/device/dev-type.h
-+++ b/lib/device/dev-type.h
-@@ -60,8 +60,12 @@ int dev_is_swap(struct device *dev, uint64_t *signature);
- int dev_is_luks(struct device *dev, uint64_t *signature);
- 
- /* Signature wiping. */
-+#define TYPE_LVM1_MEMBER	0x001
-+#define TYPE_LVM2_MEMBER	0x002
-+#define TYPE_DM_SNAPSHOT_COW	0x004
- int wipe_known_signatures(struct cmd_context *cmd, struct device *dev, const char *name,
--			  int exclude_lvm_member, int yes, force_t force);
-+			  uint32_t types_to_exclude, uint32_t types_no_prompt,
-+			  int yes, force_t force);
- 
- /* Type-specific device properties */
- unsigned long dev_md_stripe_width(struct dev_types *dt, struct device *dev);
-diff --git a/lib/device/device-types.h b/lib/device/device-types.h
-index d716878..463f847 100644
---- a/lib/device/device-types.h
-+++ b/lib/device/device-types.h
-@@ -28,11 +28,13 @@ typedef struct {
-  * The list can be supplemented with devices/types in the config file.
-  */
- static const dev_known_type_t _dev_known_types[] = {
--	{"ide", 64, "IDE disk"},
- 	{"sd", 16, "SCSI disk"},
-+	{"ide", 64, "IDE disk"},
- 	{"md", 1, "Multiple Disk (MD/SoftRAID)"},
--	{"mdp", 1, "Partitionable MD"},
- 	{"loop", 1, "Loop device"},
-+	{"ramdisk", 1, "RAM disk"},
-+	{"device-mapper", 1, "Mapped device"},
-+	{"mdp", 1, "Partitionable MD"},
- 	{"dasd", 4, "DASD disk (IBM S/390, zSeries)"},
- 	{"dac960", 8, "DAC960"},
- 	{"nbd", 16, "Network Block Device"},
-@@ -46,9 +48,7 @@ static const dev_known_type_t _dev_known_types[] = {
- 	{"i2o_block", 16, "i2o Block Disk"},
- 	{"iseries/vd", 8, "iSeries disks"},
- 	{"gnbd", 1, "Network block device"},
--	{"ramdisk", 1, "RAM disk"},
- 	{"aoe", 16, "ATA over Ethernet"},
--	{"device-mapper", 1, "Mapped device"},
- 	{"xvd", 16, "Xen virtual block device"},
- 	{"vdisk", 8, "SUN's LDOM virtual block device"},
- 	{"ps3disk", 16, "PlayStation 3 internal disk"},
-@@ -62,5 +62,6 @@ static const dev_known_type_t _dev_known_types[] = {
- 	{"scm", 8, "Storage Class Memory (IBM S/390)"},
- 	{"bcache", 1, "bcache block device cache"},
- 	{"nvme", 64, "NVM Express"},
-+	{"zvol", 16, "ZFS Zvols"},
- 	{"", 0, ""}
- };
-diff --git a/lib/display/display.c b/lib/display/display.c
-index 1babffc..66acb88 100644
---- a/lib/display/display.c
-+++ b/lib/display/display.c
-@@ -182,6 +182,13 @@ alloc_policy_t get_alloc_from_string(const char *str)
- 	return ALLOC_INVALID;
- }
- 
-+static const char *_percent_types[7] = { "NONE", "VGS", "FREE", "LVS", "PVS", "ORIGIN" };
-+
-+const char *get_percent_string(percent_type_t def)
-+{
-+	return _percent_types[def];
-+}
-+
- #define BASE_UNKNOWN 0
- #define BASE_SHARED 1
- #define BASE_1024 8
-@@ -921,6 +928,15 @@ void display_segtypes(const struct cmd_context *cmd)
- 	}
- }
- 
-+void display_tags(const struct cmd_context *cmd)
-+{
-+	const struct str_list *sl;
-+
-+	dm_list_iterate_items(sl, &cmd->tags) {
-+		log_print("%s", sl->str);
-+	}
-+}
-+
- void display_name_error(name_error_t name_error)
- {
- 	if (name_error != NAME_VALID) {
-diff --git a/lib/display/display.h b/lib/display/display.h
-index 077fff4..41fba03 100644
---- a/lib/display/display.h
-+++ b/lib/display/display.h
-@@ -53,6 +53,7 @@ void vgdisplay_short(const struct volume_group *vg);
- 
- void display_formats(const struct cmd_context *cmd);
- void display_segtypes(const struct cmd_context *cmd);
-+void display_tags(const struct cmd_context *cmd);
- 
- void display_name_error(name_error_t name_error);
- 
-@@ -63,6 +64,8 @@ const char *get_alloc_string(alloc_policy_t alloc);
- char alloc_policy_char(alloc_policy_t alloc);
- alloc_policy_t get_alloc_from_string(const char *str);
- 
-+const char *get_percent_string(percent_type_t def);
-+
- char yes_no_prompt(const char *prompt, ...) __attribute__ ((format(printf, 1, 2)));
- 
- #endif
-diff --git a/lib/format_text/export.c b/lib/format_text/export.c
-index 73030e4..883e076 100644
---- a/lib/format_text/export.c
-+++ b/lib/format_text/export.c
-@@ -367,12 +367,12 @@ static int _print_flag_config(struct formatter *f, uint64_t status, int type)
- }
- 
- 
--static int _out_tags(struct formatter *f, struct dm_list *tags)
-+static int _out_tags(struct formatter *f, struct dm_list *tagsl)
- {
- 	char *tag_buffer;
- 
--	if (!dm_list_empty(tags)) {
--		if (!(tag_buffer = alloc_printed_tags(tags)))
-+	if (!dm_list_empty(tagsl)) {
-+		if (!(tag_buffer = alloc_printed_tags(tagsl)))
- 			return_0;
- 		if (!out_text(f, "tags = %s", tag_buffer)) {
- 			dm_free(tag_buffer);
-diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
-index e31429e..bc48952 100644
---- a/lib/format_text/flags.c
-+++ b/lib/format_text/flags.c
-@@ -83,6 +83,10 @@ static const struct flag _lv_flags[] = {
- 	{THIN_POOL, NULL, 0},
- 	{THIN_POOL_DATA, NULL, 0},
- 	{THIN_POOL_METADATA, NULL, 0},
-+	{CACHE, NULL, 0},
-+	{CACHE_POOL, NULL, 0},
-+	{CACHE_POOL_DATA, NULL, 0},
-+	{CACHE_POOL_METADATA, NULL, 0},
- 	{0, NULL, 0}
- };
- 
-diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
-index 6e309a3..b4f96f8 100644
---- a/lib/format_text/format-text.c
-+++ b/lib/format_text/format-text.c
-@@ -29,6 +29,7 @@
- #include "label.h"
- #include "lvmcache.h"
- #include "lvmetad.h"
-+#include "memlock.h"
- 
- #include <unistd.h>
- #include <sys/param.h>
-@@ -1912,8 +1913,19 @@ static int _create_vg_text_instance(struct format_instance *fid,
- 		}
- 
- 		if (type & FMT_INSTANCE_MDAS) {
--			/* Scan PVs in VG for any further MDAs */
--			lvmcache_label_scan(fid->fmt->cmd, 0);
-+			/*
-+			 * TODO in theory, this function should be never reached
-+			 * while in critical_section(), because lvmcache's
-+			 * cached_vg should be valid. However, this assumption
-+			 * sometimes fails (possibly due to inconsistent
-+			 * (precommit) metadata and/or missing devices), and
-+			 * calling lvmcache_label_scan inside the critical
-+			 * section may be fatal (i.e. deadlock).
-+			 */
-+			if (!critical_section())
-+				/* Scan PVs in VG for any further MDAs */
-+				lvmcache_label_scan(fid->fmt->cmd, 0);
-+
- 			if (!(vginfo = lvmcache_vginfo_from_vgname(vg_name, vg_id)))
- 				goto_out;
- 			if (!lvmcache_fid_add_mdas_vg(vginfo, fid))
-diff --git a/lib/format_text/tags.c b/lib/format_text/tags.c
-index b0f0732..d0bf2b1 100644
---- a/lib/format_text/tags.c
-+++ b/lib/format_text/tags.c
-@@ -19,14 +19,14 @@
- #include "str_list.h"
- #include "lvm-string.h"
- 
--char *alloc_printed_tags(struct dm_list *tags)
-+char *alloc_printed_tags(struct dm_list *tagsl)
- {
- 	struct str_list *sl;
- 	int first = 1;
- 	size_t size = 0;
- 	char *buffer, *buf;
- 
--	dm_list_iterate_items(sl, tags)
-+	dm_list_iterate_items(sl, tagsl)
- 		/* '"' + tag + '"' + ',' + ' ' */
- 		size += strlen(sl->str) + 4;
- 	/* '[' + ']' + '\0' */
-@@ -40,7 +40,7 @@ char *alloc_printed_tags(struct dm_list *tags)
- 	if (!emit_to_buffer(&buf, &size, "["))
- 		goto_bad;
- 
--	dm_list_iterate_items(sl, tags) {
-+	dm_list_iterate_items(sl, tagsl) {
- 		if (!first) {
- 			if (!emit_to_buffer(&buf, &size, ", "))
- 				goto_bad;
-@@ -61,7 +61,7 @@ bad:
- 	return_NULL;
- }
- 
--int read_tags(struct dm_pool *mem, struct dm_list *tags, const struct dm_config_value *cv)
-+int read_tags(struct dm_pool *mem, struct dm_list *tagsl, const struct dm_config_value *cv)
- {
- 	if (cv->type == DM_CFG_EMPTY_ARRAY)
- 		return 1;
-@@ -72,7 +72,7 @@ int read_tags(struct dm_pool *mem, struct dm_list *tags, const struct dm_config_
- 			return 0;
- 		}
- 
--		if (!str_list_add(mem, tags, dm_pool_strdup(mem, cv->v.str)))
-+		if (!str_list_add(mem, tagsl, dm_pool_strdup(mem, cv->v.str)))
- 			return_0;
- 
- 		cv = cv->next;
-diff --git a/lib/label/label.c b/lib/label/label.c
-index 25e5f2c..703fef7 100644
---- a/lib/label/label.c
-+++ b/lib/label/label.c
-@@ -19,7 +19,6 @@
- #include "xlate.h"
- #include "lvmcache.h"
- #include "lvmetad.h"
--#include "metadata.h"
- 
- #include <sys/stat.h>
- #include <fcntl.h>
-diff --git a/lib/locking/file_locking.c b/lib/locking/file_locking.c
-index 1fa23b3..fb84c5b 100644
---- a/lib/locking/file_locking.c
-+++ b/lib/locking/file_locking.c
-@@ -1,6 +1,6 @@
- /*
-  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
-- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -44,6 +44,15 @@ static sig_t _oldhandler;
- static sigset_t _fullsigset, _intsigset;
- static volatile sig_atomic_t _handler_installed;
- 
-+/* Drop lock known to be shared with another file descriptor. */
-+static void _drop_shared_flock(const char *file, int fd)
-+{
-+	log_debug_locking("_drop_shared_flock %s.", file);
-+
-+	if (close(fd) < 0)
-+		log_sys_debug("close", file);
-+}
-+
- static void _undo_flock(const char *file, int fd)
- {
- 	struct stat buf1, buf2;
-@@ -74,9 +83,9 @@ static int _release_lock(const char *file, int unlock)
- 				log_very_verbose("Unlocking %s", ll->res);
- 				if (flock(ll->lf, LOCK_NB | LOCK_UN))
- 					log_sys_debug("flock", ll->res);
--			}
--
--			_undo_flock(ll->res, ll->lf);
-+				_undo_flock(ll->res, ll->lf);
-+			} else
-+				_drop_shared_flock(ll->res, ll->lf);
- 
- 			dm_free(ll->res);
- 			dm_free(llh);
-diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
-new file mode 100644
-index 0000000..673d90e
---- /dev/null
-+++ b/lib/metadata/cache_manip.c
-@@ -0,0 +1,278 @@
-+/*
-+ * Copyright (C) 2014 Red Hat, Inc. All rights reserved.
-+ *
-+ * This file is part of LVM2.
-+ *
-+ * This copyrighted material is made available to anyone wishing to use,
-+ * modify, copy, or redistribute it subject to the terms and conditions
-+ * of the GNU Lesser General Public License v.2.1.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public License
-+ * along with this program; if not, write to the Free Software Foundation,
-+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include "lib.h"
-+#include "metadata.h"
-+#include "locking.h"
-+#include "pv_map.h"
-+#include "lvm-string.h"
-+#include "toolcontext.h"
-+#include "lv_alloc.h"
-+#include "pv_alloc.h"
-+#include "display.h"
-+#include "segtype.h"
-+#include "archiver.h"
-+#include "activate.h"
-+#include "str_list.h"
-+#include "defaults.h"
-+#include "lvm-exec.h"
-+
-+int update_cache_pool_params(struct volume_group *vg, unsigned attr,
-+			     int passed_args,
-+			     uint32_t data_extents, uint32_t extent_size,
-+			     int *chunk_size_calc_method, uint32_t *chunk_size,
-+			     thin_discards_t *discards,
-+			     uint64_t *pool_metadata_size, int *zero)
-+{
-+	uint64_t min_meta_size;
-+
-+	if ((*chunk_size < DM_CACHE_MIN_DATA_BLOCK_SIZE) ||
-+	    (*chunk_size > DM_CACHE_MAX_DATA_BLOCK_SIZE)) {
-+		log_error("Chunk size must be in the range %s to %s.",
-+			  display_size(vg->cmd, DM_CACHE_MIN_DATA_BLOCK_SIZE),
-+			  display_size(vg->cmd, DM_CACHE_MAX_DATA_BLOCK_SIZE));
-+		return 0;
-+	}
-+
-+	if (*chunk_size & (DM_CACHE_MIN_DATA_BLOCK_SIZE - 1)) {
-+		log_error("Chunk size must be a multiple of %u sectors.",
-+			  DM_CACHE_MIN_DATA_BLOCK_SIZE);
-+		return 0;
-+	}
-+
-+	/*
-+	 * Default meta size is:
-+	 * (4MiB + (16 Bytes for each chunk-sized block))
-+	 * ... plus a good amount of padding (2x) to cover any
-+	 * policy hint data that may be added in the future.
-+	 */
-+	min_meta_size = 16 * (data_extents * vg->extent_size);
-+	min_meta_size /= *chunk_size; /* # of Bytes we need */
-+	min_meta_size *= 2;              /* plus some padding */
-+	min_meta_size /= 512;            /* in sectors */
-+	min_meta_size += 4*1024*2;       /* plus 4MiB */
-+
-+	if (!*pool_metadata_size)
-+		*pool_metadata_size = min_meta_size;
-+
-+	if (*pool_metadata_size < min_meta_size) {
-+		*pool_metadata_size = min_meta_size;
-+		log_print("Increasing metadata device size to %"
-+			  PRIu64 " sectors", *pool_metadata_size);
-+	}
-+	if (*pool_metadata_size > (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE)) {
-+		*pool_metadata_size = 2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE;
-+		log_print("Reducing metadata device size to %" PRIu64 " sectors",
-+			  *pool_metadata_size);
-+	}
-+
-+	return 1;
-+}
-+
-+/*
-+ * lv_cache_create
-+ * @pool
-+ * @origin
-+ *
-+ * Given a cache_pool and an origin, link the two and create a
-+ * cached LV.
-+ *
-+ * Returns: cache LV on success, NULL on failure
-+ */
-+struct logical_volume *lv_cache_create(struct logical_volume *pool,
-+				       struct logical_volume *origin)
-+{
-+	const struct segment_type *segtype;
-+	struct cmd_context *cmd = pool->vg->cmd;
-+	struct logical_volume *cache_lv;
-+	struct lv_segment *seg;
-+
-+	if (!lv_is_cache_pool(pool)) {
-+		log_error(INTERNAL_ERROR
-+			  "%s is not a cache_pool LV", pool->name);
-+		return NULL;
-+	}
-+
-+	if (!dm_list_empty(&pool->segs_using_this_lv)) {
-+		seg = get_only_segment_using_this_lv(pool);
-+		log_error("%s is already in use by %s",
-+			  pool->name, seg ? seg->lv->name : "another LV");
-+		return NULL;
-+	}
-+
-+	if (lv_is_cache_type(origin)) {
-+		/*
-+		 * FIXME: We can layer caches, insert_layer_for_lv() would
-+		 * have to do a better job renaming the LVs in the stack
-+		 * first so that there isn't a name collision with <name>_corig.
-+		 * The origin under the origin would become *_corig_corig
-+		 * before renaming the origin above to *_corig.
-+		 */
-+		log_error(INTERNAL_ERROR
-+			  "The origin, %s, cannot be of cache type",
-+			  origin->name);
-+		return NULL;
-+	}
-+
-+	if (!(segtype = get_segtype_from_string(cmd, "cache")))
-+		return_NULL;
-+
-+	cache_lv = origin;
-+	if (!(origin = insert_layer_for_lv(cmd, cache_lv, CACHE, "_corig")))
-+		return_NULL;
-+
-+	seg = first_seg(cache_lv);
-+	seg->segtype = segtype;
-+
-+	if (!attach_pool_lv(seg, pool, NULL, NULL))
-+		return_NULL;
-+
-+	return cache_lv;
-+}
-+
-+/*
-+ * lv_cache_remove
-+ * @cache_lv
-+ *
-+ * Given a cache LV, remove the cache layer.  This will unlink
-+ * the origin and cache_pool, remove the cache LV layer, and promote
-+ * the origin to a usable non-cached LV of the same name as the
-+ * given cache_lv.
-+ *
-+ * Returns: 1 on success, 0 on failure
-+ */
-+int lv_cache_remove(struct logical_volume *cache_lv)
-+{
-+	struct cmd_context *cmd = cache_lv->vg->cmd;
-+	char *policy_name;
-+	uint64_t dirty_blocks;
-+	struct segment_type *segtype;
-+	struct lv_segment *cache_seg = first_seg(cache_lv);
-+	struct logical_volume *origin_lv;
-+	struct logical_volume *cache_pool_lv;
-+
-+	if (!lv_is_cache(cache_lv))
-+		return_0;
-+
-+	/*
-+	 * FIXME:
-+	 * Before the link can be broken, we must ensure that the
-+	 * cache has been flushed.  This may already be the case
-+	 * if the cache mode is writethrough (or the cleaner
-+	 * policy is in place from a previous half-finished attempt
-+	 * to remove the cache_pool).  It could take a long time to
-+	 * flush the cache - it should probably be done in the background.
-+	 *
-+	 * Also, if we do perform the flush in the background and we
-+	 * happen to also be removing the cache/origin LV, then we
-+	 * could check if the cleaner policy is in place and simply
-+	 * remove the cache_pool then without waiting for the flush to
-+	 * complete.
-+	 */
-+	if (!lv_cache_policy_info(cache_lv, &policy_name, NULL, NULL))
-+		return_0;
-+
-+	if (strcmp(policy_name, "cleaner")) {
-+		/* We must swap in the cleaner to flush the cache */
-+		log_error("Flushing cache for %s", cache_lv->name);
-+
-+		/*
-+		 * Is there are clean way to free the memory for the name
-+		 * and argv when changing the policy?
-+		 */
-+		cache_seg->policy_name = (char *)"cleaner";
-+		cache_seg->policy_argc = 0;
-+		cache_seg->policy_argv = NULL;
-+
-+		/* update the kernel to put the cleaner policy in place */
-+		if (!vg_write(cache_lv->vg))
-+			return_0;
-+		if (!suspend_lv(cmd, cache_lv))
-+			return_0;
-+		if (!vg_commit(cache_lv->vg))
-+			return_0;
-+		if (!resume_lv(cmd, cache_lv))
-+			return_0;
-+	}
-+
-+	//FIXME: use polling to do this...
-+	do {
-+		if (!lv_cache_block_info(cache_lv, NULL,
-+					 &dirty_blocks, NULL, NULL))
-+			return_0;
-+		log_error("%" PRIu64 " blocks must still be flushed.",
-+			  dirty_blocks);
-+		if (dirty_blocks)
-+			sleep(5);
-+	} while (dirty_blocks);
-+
-+	cache_pool_lv = first_seg(cache_lv)->pool_lv;
-+	if (!detach_pool_lv(first_seg(cache_lv)))
-+		return_0;
-+
-+	origin_lv = seg_lv(first_seg(cache_lv), 0);
-+	lv_set_visible(origin_lv);
-+
-+//FIXME: We should be able to use 'remove_layer_from_lv', but
-+//       there is a call to 'lv_empty' in there that recursively
-+//       deletes everything down the tree - including the origin_lv
-+//       that we are trying to preserve!
-+//	if (!remove_layer_from_lv(cache_lv, origin_lv))
-+//		return_0;
-+
-+	if (!remove_seg_from_segs_using_this_lv(origin_lv, first_seg(cache_lv)))
-+		return_0;
-+	if (!move_lv_segments(cache_lv, origin_lv, 0, 0))
-+		return_0;
-+
-+	cache_lv->status &= ~CACHE;
-+
-+	segtype = get_segtype_from_string(cmd, "error");
-+	if (!lv_add_virtual_segment(origin_lv, 0,
-+				    cache_lv->le_count, segtype, NULL))
-+		return_0;
-+
-+	if (!vg_write(cache_lv->vg))
-+		return_0;
-+
-+	/*
-+	 * suspend_lv on this cache LV will suspend all of the components:
-+	 * - the top-level cache LV
-+	 * - the origin
-+	 * - the cache_pool and all of its sub-LVs
-+	 */
-+	if (!suspend_lv(cmd, cache_lv))
-+		return_0;
-+
-+	if (!vg_commit(cache_lv->vg))
-+		return_0;
-+
-+	/*
-+	 * resume_lv on this (former) cache LV will resume all
-+	 * but the cache_pool LV.  It must be resumed seperately.
-+	 */
-+	if (!resume_lv(cmd, cache_lv))
-+		return_0;
-+	if (!resume_lv(cmd, cache_pool_lv))
-+		return_0;
-+
-+	if (!activate_lv(cmd, origin_lv))
-+		return_0;
-+	if (!deactivate_lv(cmd, origin_lv))
-+		return_0;
-+	if (!lv_remove(origin_lv))
-+		return_0;
-+
-+	return 1;
-+}
-diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
-index 3e1458c..4549f03 100644
---- a/lib/metadata/lv.c
-+++ b/lib/metadata/lv.c
-@@ -170,7 +170,7 @@ uint64_t lvseg_chunksize(const struct lv_segment *seg)
- 
- 	if (lv_is_cow(seg->lv))
- 		size = (uint64_t) find_snapshot(seg->lv)->chunk_size;
--	else if (seg_is_thin_pool(seg))
-+	else if (seg_is_thin_pool(seg) || seg_is_cache_pool(seg))
- 		size = (uint64_t) seg->chunk_size;
- 	else
- 		size = UINT64_C(0);
-@@ -202,6 +202,9 @@ char *lv_origin_dup(struct dm_pool *mem, const struct logical_volume *lv)
- 	if (lv_is_cow(lv))
- 		return lv_name_dup(mem, origin_from_cow(lv));
- 
-+	if (lv_is_cache(lv) && first_seg(lv)->origin)
-+		return lv_name_dup(mem, first_seg(lv)->origin);
-+
- 	if (lv_is_thin_volume(lv) && first_seg(lv)->origin)
- 		return lv_name_dup(mem, first_seg(lv)->origin);
- 
-@@ -246,7 +249,8 @@ char *lv_pool_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
- 	struct lv_segment *seg;
- 
- 	dm_list_iterate_items(seg, &lv->segments)
--		if (seg_is_thin_volume(seg) && seg->pool_lv)
-+		if (seg->pool_lv &&
-+		    (seg_is_thin_volume(seg) || seg_is_cache(seg)))
- 			return dm_pool_strdup(mem, seg->pool_lv->name);
- 
- 	return NULL;
-@@ -254,14 +258,16 @@ char *lv_pool_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
- 
- char *lv_data_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
- {
--	struct lv_segment *seg = lv_is_thin_pool(lv) ? first_seg(lv) : NULL;
-+	struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ?
-+		first_seg(lv) : NULL;
- 
- 	return seg ? dm_pool_strdup(mem, seg_lv(seg, 0)->name) : NULL;
- }
- 
- char *lv_metadata_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
- {
--	struct lv_segment *seg = lv_is_thin_pool(lv) ? first_seg(lv) : NULL;
-+	struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ?
-+		first_seg(lv) : NULL;
- 
- 	return seg ? dm_pool_strdup(mem, seg->metadata_lv->name) : NULL;
- }
-@@ -338,7 +344,8 @@ uint64_t lv_origin_size(const struct logical_volume *lv)
- 
- uint64_t lv_metadata_size(const struct logical_volume *lv)
- {
--	struct lv_segment *seg = lv_is_thin_pool(lv) ? first_seg(lv) : NULL;
-+	struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ?
-+		first_seg(lv) : NULL;
- 
- 	return seg ? seg->metadata_lv->size : 0;
- }
-@@ -386,10 +393,14 @@ uint64_t lv_size(const struct logical_volume *lv)
- static int _lv_mimage_in_sync(const struct logical_volume *lv)
- {
- 	percent_t percent;
--	struct lv_segment *mirror_seg = find_mirror_seg(first_seg(lv));
-+	struct lv_segment *seg = first_seg(lv);
-+	struct lv_segment *mirror_seg;
- 
--	if (!(lv->status & MIRROR_IMAGE) || !mirror_seg)
--		return_0;
-+	if (!(lv->status & MIRROR_IMAGE) || !seg ||
-+	    !(mirror_seg = find_mirror_seg(seg))) {
-+		log_error(INTERNAL_ERROR "Cannot find mirror segment.");
-+		return 0;
-+	}
- 
- 	if (!lv_mirror_percent(lv->vg->cmd, mirror_seg->lv, 0, &percent,
- 			       NULL))
-@@ -403,7 +414,7 @@ static int _lv_raid_image_in_sync(const struct logical_volume *lv)
- 	unsigned s;
- 	percent_t percent;
- 	char *raid_health;
--	struct lv_segment *raid_seg;
-+	struct lv_segment *seg, *raid_seg = NULL;
- 
- 	/*
- 	 * If the LV is not active locally,
-@@ -417,7 +428,8 @@ static int _lv_raid_image_in_sync(const struct logical_volume *lv)
- 		return 0;
- 	}
- 
--	raid_seg = get_only_segment_using_this_lv(first_seg(lv)->lv);
-+	if ((seg = first_seg(lv)))
-+		raid_seg = get_only_segment_using_this_lv(seg->lv);
- 	if (!raid_seg) {
- 		log_error("Failed to find RAID segment for %s", lv->name);
- 		return 0;
-@@ -465,7 +477,7 @@ static int _lv_raid_healthy(const struct logical_volume *lv)
- {
- 	unsigned s;
- 	char *raid_health;
--	struct lv_segment *raid_seg;
-+	struct lv_segment *seg, *raid_seg = NULL;
- 
- 	/*
- 	 * If the LV is not active locally,
-@@ -481,8 +493,8 @@ static int _lv_raid_healthy(const struct logical_volume *lv)
- 
- 	if (lv->status & RAID)
- 		raid_seg = first_seg(lv);
--	else
--		raid_seg = get_only_segment_using_this_lv(first_seg(lv)->lv);
-+	else if ((seg = first_seg(lv)))
-+		raid_seg = get_only_segment_using_this_lv(seg->lv);
- 
- 	if (!raid_seg) {
- 		log_error("Failed to find RAID segment for %s", lv->name);
-@@ -546,6 +558,10 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
- 	/* Origin takes precedence over mirror and thin volume */
- 	else if (lv_is_origin(lv) || lv_is_external_origin(lv))
- 		repstr[0] = (lv_is_merging_origin(lv)) ? 'O' : 'o';
-+	else if (lv_is_cache_pool_metadata(lv))
-+		repstr[0] = 'e';
-+	else if (lv_is_cache_type(lv))
-+		repstr[0] = 'C';
- 	else if (lv_is_thin_pool_metadata(lv) ||
- 		 lv_is_pool_metadata_spare(lv) ||
- 		 (lv->status & RAID_META))
-@@ -638,6 +654,8 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
- 
- 	if (lv_is_thin_pool(lv) || lv_is_thin_volume(lv))
- 		repstr[6] = 't';
-+	else if (lv_is_cache_type(lv))
-+		repstr[6] = 'C';
- 	else if (lv_is_raid_type(lv))
- 		repstr[6] = 'r';
- 	else if (lv_is_mirror_type(lv))
-@@ -741,7 +759,8 @@ static int _lv_is_exclusive(struct logical_volume *lv)
- 	/* Some devices require exlusivness */
- 	return seg_is_raid(first_seg(lv)) ||
- 		lv_is_origin(lv) ||
--		lv_is_thin_type(lv);
-+		lv_is_thin_type(lv) ||
-+		lv_is_cache_type(lv);
- }
- 
- int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv,
-diff --git a/lib/metadata/lv_alloc.h b/lib/metadata/lv_alloc.h
-index acfebca..395420d 100644
---- a/lib/metadata/lv_alloc.h
-+++ b/lib/metadata/lv_alloc.h
-@@ -54,7 +54,7 @@ struct alloc_handle *allocate_extents(struct volume_group *vg,
-                                       uint32_t mirrors, uint32_t log_count,
- 				      uint32_t log_region_size, uint32_t extents,
-                                       struct dm_list *allocatable_pvs,
--				      alloc_policy_t alloc,
-+				      alloc_policy_t alloc, int approx_alloc,
- 				      struct dm_list *parallel_areas);
- 
- int lv_add_segment(struct alloc_handle *ah,
-diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
-index f45c89f..57ce2d9 100644
---- a/lib/metadata/lv_manip.c
-+++ b/lib/metadata/lv_manip.c
-@@ -1,6 +1,6 @@
- /*
-  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
-- * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -346,6 +346,11 @@ struct lv_segment *get_only_segment_using_this_lv(struct logical_volume *lv)
- {
- 	struct seg_list *sl;
- 
-+	if (!lv) {
-+		log_error(INTERNAL_ERROR "get_only_segment_using_this_lv() called with NULL LV.");
-+		return NULL;
-+	}
-+
- 	if (dm_list_size(&lv->segs_using_this_lv) != 1) {
- 		log_error("%s is expected to have only one segment using it, "
- 			  "while it has %d", lv->name,
-@@ -542,6 +547,8 @@ struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv,
- static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t s,
- 						uint32_t area_reduction, int with_discard)
- {
-+	struct lv_segment *cache_seg;
-+
- 	if (seg_type(seg, s) == AREA_UNASSIGNED)
- 		return 1;
- 
-@@ -558,13 +565,24 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
- 		return 1;
- 	}
- 
--	if ((seg_lv(seg, s)->status & MIRROR_IMAGE) ||
--	    (seg_lv(seg, s)->status & THIN_POOL_DATA)) {
-+	if (seg_is_cache(seg) ||
-+	    (seg_lv(seg, s)->status & MIRROR_IMAGE) ||
-+	    (seg_lv(seg, s)->status & THIN_POOL_DATA) ||
-+	    (seg_lv(seg, s)->status & CACHE_POOL_DATA)) {
- 		if (!lv_reduce(seg_lv(seg, s), area_reduction))
- 			return_0; /* FIXME: any upper level reporting */
- 		return 1;
- 	}
- 
-+	if (seg_is_cache_pool(seg) &&
-+	    !dm_list_empty(&seg->lv->segs_using_this_lv)) {
-+		if (!(cache_seg = get_only_segment_using_this_lv(seg->lv)))
-+			return_0;
-+
-+		if (!lv_cache_remove(cache_seg->lv))
-+			return_0;
-+	}
-+
- 	if (seg_lv(seg, s)->status & RAID_IMAGE) {
- 		/*
- 		 * FIXME: Use lv_reduce not lv_remove
-@@ -905,6 +923,7 @@ struct alloc_handle {
- 	struct dm_pool *mem;
- 
- 	alloc_policy_t alloc;		/* Overall policy */
-+	int approx_alloc;                /* get as much as possible up to new_extents */
- 	uint32_t new_extents;		/* Number of new extents required */
- 	uint32_t area_count;		/* Number of parallel areas */
- 	uint32_t parity_count;   /* Adds to area_count, but not area_multiple */
-@@ -924,8 +943,12 @@ struct alloc_handle {
- 	 * that is new_extents + log_len and then split that between two
- 	 * allocated areas when found.  'alloc_and_split_meta' indicates
- 	 * that this is the desired dynamic.
-+	 *
-+	 * This same idea is used by cache LVs to get the metadata device
-+	 * and data device allocated together.
- 	 */
- 	unsigned alloc_and_split_meta;
-+	unsigned split_metadata_is_allocated;	/* Metadata has been allocated */
- 
- 	const struct dm_config_node *cling_tag_list_cn;
- 
-@@ -1025,7 +1048,7 @@ static uint32_t mirror_log_extents(uint32_t region_size, uint32_t pe_size, uint3
- static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
- 					struct dm_pool *mem,
- 					const struct segment_type *segtype,
--					alloc_policy_t alloc,
-+					alloc_policy_t alloc, int approx_alloc,
- 					uint32_t new_extents,
- 					uint32_t mirrors,
- 					uint32_t stripes,
-@@ -1115,6 +1138,7 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
- 	 * a correct area_multiple.
- 	 */
- 	ah->area_multiple = _calc_area_multiple(segtype, area_count + parity_count, stripes);
-+	//FIXME: s/mirror_logs_separate/metadata_separate/ so it can be used by otehrs?
- 	ah->mirror_logs_separate = find_config_tree_bool(cmd, allocation_mirror_logs_require_separate_pvs_CFG, NULL);
- 
- 	if (segtype_is_raid(segtype)) {
-@@ -1131,23 +1155,53 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
- 			 * We need 'log_len' extents for each
- 			 * RAID device's metadata_area
- 			 */
--			ah->new_extents += (ah->log_len * ah->area_multiple);
-+			if (!approx_alloc)
-+				ah->new_extents += (ah->log_len * ah->area_multiple);
- 		} else {
- 			ah->log_area_count = 0;
- 			ah->log_len = 0;
- 		}
-+		if (approx_alloc) {
-+			ah->new_extents = ah->new_extents * ah->area_multiple / (ah->area_count + ah->parity_count);
-+			ah->new_extents = (ah->new_extents / ah->area_multiple) * ah->area_multiple;
-+			log_debug("Adjusted allocation request to %" PRIu32 " data extents.", ah->new_extents);
-+		}
- 	} else if (segtype_is_thin_pool(segtype)) {
--		ah->log_area_count = metadata_area_count;
--		/* thin_pool uses region_size to pass metadata size in extents */
-+		/*
-+		 * thin_pool uses ah->region_size to
-+		 * pass metadata size in extents
-+		 */
- 		ah->log_len = ah->region_size;
-+		ah->log_area_count = metadata_area_count;
- 		ah->region_size = 0;
- 		ah->mirror_logs_separate =
- 			find_config_tree_bool(cmd, allocation_thin_pool_metadata_require_separate_pvs_CFG, NULL);
-+	} else if (segtype_is_cache_pool(segtype)) {
-+		/*
-+		 * Like thin_pool, cache_pool uses ah->region_size to
-+		 * pass metadata size in extents
-+		 */
-+		ah->log_len = ah->region_size;
-+		/* use metadata_area_count, not log_area_count */
-+		ah->metadata_area_count = metadata_area_count;
-+		ah->region_size = 0;
-+		ah->mirror_logs_separate =
-+			find_config_tree_bool(cmd, allocation_cache_pool_metadata_require_separate_pvs_CFG, NULL);
-+		if (!ah->mirror_logs_separate) {
-+			ah->alloc_and_split_meta = 1;
-+			if (!approx_alloc)
-+				ah->new_extents += ah->log_len;
-+		}
- 	} else {
- 		ah->log_area_count = metadata_area_count;
- 		ah->log_len = !metadata_area_count ? 0 :
- 			mirror_log_extents(ah->region_size, extent_size,
- 					   new_extents / ah->area_multiple);
-+		if (approx_alloc) {
-+			ah->new_extents = ah->new_extents * ah->area_multiple / ah->area_count;
-+			ah->new_extents = (ah->new_extents / ah->area_multiple) * ah->area_multiple;
-+			log_debug("Adjusted allocation request to %" PRIu32 " data extents.", ah->new_extents);
-+		}
- 	}
- 
- 	for (s = 0; s < alloc_count; s++)
-@@ -1159,6 +1213,8 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
- 
- 	ah->maximise_cling = find_config_tree_bool(cmd, allocation_maximise_cling_CFG, NULL);
- 
-+	ah->approx_alloc = approx_alloc;
-+
- 	return ah;
- }
- 
-@@ -1384,7 +1440,7 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t max_to_allocat
- 		if (area_len > alloc_state->areas[s].used)
- 			area_len = alloc_state->areas[s].used;
- 
--	len = (ah->alloc_and_split_meta) ? total_area_count * 2 : total_area_count;
-+	len = (ah->alloc_and_split_meta && !ah->split_metadata_is_allocated) ? total_area_count * 2 : total_area_count;
- 	len *= sizeof(*aa);
- 	if (!(aa = dm_pool_alloc(ah->mem, len))) {
- 		log_error("alloced_area allocation failed");
-@@ -1404,7 +1460,7 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t max_to_allocat
- 		}
- 
- 		pva = alloc_state->areas[s + ix_log_skip].pva;
--		if (ah->alloc_and_split_meta) {
-+		if (ah->alloc_and_split_meta && !ah->split_metadata_is_allocated) {
- 			/*
- 			 * The metadata area goes at the front of the allocated
- 			 * space for now, but could easily go at the end (or
-@@ -1430,7 +1486,7 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t max_to_allocat
- 			dm_list_add(&ah->alloced_areas[s], &aa[s].list);
- 			s -= ah->area_count + ah->parity_count;
- 		}
--		aa[s].len = (ah->alloc_and_split_meta) ? len - ah->log_len : len;
-+		aa[s].len = (ah->alloc_and_split_meta && !ah->split_metadata_is_allocated) ? len - ah->log_len : len;
- 		/* Skip empty allocations */
- 		if (!aa[s].len)
- 			continue;
-@@ -1448,7 +1504,8 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t max_to_allocat
- 	}
- 
- 	/* Only need to alloc metadata from the first batch */
--	ah->alloc_and_split_meta = 0;
-+	if (ah->alloc_and_split_meta)
-+		ah->split_metadata_is_allocated = 1;
- 
- 	ah->total_area_len += area_len;
- 
-@@ -1950,33 +2007,40 @@ static void _reset_unreserved(struct dm_list *pvms)
- }
- 
- static void _report_needed_allocation_space(struct alloc_handle *ah,
--					    struct alloc_state *alloc_state)
-+					    struct alloc_state *alloc_state,
-+					    struct dm_list *pvms)
- {
- 	const char *metadata_type;
- 	uint32_t parallel_areas_count, parallel_area_size;
- 	uint32_t metadata_count, metadata_size;
- 
--	parallel_area_size = (ah->new_extents - alloc_state->allocated) / ah->area_multiple -
--		      ((ah->alloc_and_split_meta) ? ah->log_len : 0);
-+	parallel_area_size = ah->new_extents - alloc_state->allocated;
-+	parallel_area_size /= ah->area_multiple;
-+	parallel_area_size -= (ah->alloc_and_split_meta && !ah->split_metadata_is_allocated) ? ah->log_len : 0;
- 
- 	parallel_areas_count = ah->area_count + ah->parity_count;
- 
- 	metadata_size = ah->log_len;
- 	if (ah->alloc_and_split_meta) {
--		metadata_type = "RAID metadata area";
-+		metadata_type = "metadata area";
- 		metadata_count = parallel_areas_count;
-+		if (ah->split_metadata_is_allocated)
-+			metadata_size = 0;
- 	} else {
- 		metadata_type = "mirror log";
- 		metadata_count = alloc_state->log_area_count_still_needed;
- 	}
- 
--	log_debug_alloc("Still need %" PRIu32 " total extents:",
--			parallel_area_size * parallel_areas_count + metadata_size * metadata_count);
-+	log_debug_alloc("Still need %s%" PRIu32 " total extents from %" PRIu32 " remaining:",
-+			ah->approx_alloc ? "up to " : "",
-+			parallel_area_size * parallel_areas_count + metadata_size * metadata_count, pv_maps_size(pvms));
- 	log_debug_alloc("  %" PRIu32 " (%" PRIu32 " data/%" PRIu32
- 			" parity) parallel areas of %" PRIu32 " extents each",
- 			parallel_areas_count, ah->area_count, ah->parity_count, parallel_area_size);
--	log_debug_alloc("  %" PRIu32 " %ss of %" PRIu32 " extents each",
--			metadata_count, metadata_type, metadata_size);
-+	log_debug_alloc("  %" PRIu32 " %s%s of %" PRIu32 " extents each",
-+			metadata_count, metadata_type,
-+			(metadata_count == 1) ? "" : "s",
-+			metadata_size);
- }
- /*
-  * Returns 1 regardless of whether any space was found, except on error.
-@@ -2015,7 +2079,7 @@ static int _find_some_parallel_space(struct alloc_handle *ah, const struct alloc
- 	_clear_areas(alloc_state);
- 	_reset_unreserved(pvms);
- 
--	_report_needed_allocation_space(ah, alloc_state);
-+	_report_needed_allocation_space(ah, alloc_state, pvms);
- 
- 	/* ix holds the number of areas found on other PVs */
- 	do {
-@@ -2240,11 +2304,11 @@ static int _find_max_parallel_space_for_one_policy(struct alloc_handle *ah, stru
- 				 * data together will be split, we must adjust
- 				 * the comparison accordingly.
- 				 */
--				if (ah->alloc_and_split_meta)
-+				if (ah->alloc_and_split_meta && !ah->split_metadata_is_allocated)
- 					max_tmp -= ah->log_len;
- 				if (max_tmp > (spvs->le + spvs->len) * ah->area_multiple) {
- 					max_to_allocate = (spvs->le + spvs->len) * ah->area_multiple - alloc_state->allocated;
--					max_to_allocate += ah->alloc_and_split_meta ? ah->log_len : 0;
-+					max_to_allocate += (ah->alloc_and_split_meta && !ah->split_metadata_is_allocated) ? ah->log_len : 0;
- 				}
- 				parallel_pvs = &spvs->pvs;
- 				break;
-@@ -2272,7 +2336,7 @@ static int _find_max_parallel_space_for_one_policy(struct alloc_handle *ah, stru
- 		} else if (ah->maximise_cling && alloc_parms->alloc == ALLOC_NORMAL &&
- 			   !(alloc_parms->flags & A_CLING_TO_ALLOCED))
- 			alloc_parms->flags |= A_CLING_TO_ALLOCED;
--	} while ((alloc_parms->alloc != ALLOC_CONTIGUOUS) && alloc_state->allocated != alloc_parms->extents_still_needed && (alloc_parms->flags & A_CAN_SPLIT));
-+	} while ((alloc_parms->alloc != ALLOC_CONTIGUOUS) && alloc_state->allocated != alloc_parms->extents_still_needed && (alloc_parms->flags & A_CAN_SPLIT) && (!ah->approx_alloc || pv_maps_size(pvms)));
- 
- 	return 1;
- }
-@@ -2366,7 +2430,7 @@ static int _allocate(struct alloc_handle *ah,
- 		old_allocated = alloc_state.allocated;
- 		log_debug_alloc("Trying allocation using %s policy.", get_alloc_string(alloc));
- 
--		if (!_sufficient_pes_free(ah, pvms, alloc_state.allocated, ah->new_extents))
-+		if (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated, ah->new_extents))
- 			goto_out;
- 
- 		_init_alloc_parms(ah, &alloc_parms, alloc, prev_lvseg,
-@@ -2376,19 +2440,36 @@ static int _allocate(struct alloc_handle *ah,
- 		if (!_find_max_parallel_space_for_one_policy(ah, &alloc_parms, pvms, &alloc_state))
- 			goto_out;
- 
--		if ((alloc_state.allocated == ah->new_extents && !alloc_state.log_area_count_still_needed) ||
-+		if ((alloc_state.allocated == ah->new_extents &&
-+		     !alloc_state.log_area_count_still_needed) ||
- 		    (!can_split && (alloc_state.allocated != old_allocated)))
- 			break;
- 	}
- 
- 	if (alloc_state.allocated != ah->new_extents) {
--		log_error("Insufficient suitable %sallocatable extents "
--			  "for logical volume %s: %u more required",
--			  can_split ? "" : "contiguous ",
--			  lv ? lv->name : "",
--			  (ah->new_extents - alloc_state.allocated) * ah->area_count
--			  / ah->area_multiple);
--		goto out;
-+		if (!ah->approx_alloc) {
-+			log_error("Insufficient suitable %sallocatable extents "
-+				  "for logical volume %s: %u more required",
-+				  can_split ? "" : "contiguous ",
-+				  lv ? lv->name : "",
-+				  (ah->new_extents - alloc_state.allocated) *
-+				  ah->area_count / ah->area_multiple);
-+			goto out;
-+		}
-+		if (!alloc_state.allocated) {
-+			log_error("Insufficient suitable %sallocatable extents "
-+				  "found for logical volume %s.",
-+				  can_split ? "" : "contiguous ",
-+				  lv ? lv->name : "");
-+			goto out;
-+		}
-+		log_verbose("Found fewer %sallocatable extents "
-+			    "for logical volume %s than requested: using %" PRIu32 " extents (reduced by %u).",
-+			    can_split ? "" : "contiguous ",
-+			    lv ? lv->name : "",
-+			    alloc_state.allocated,
-+			    (ah->new_extents - alloc_state.allocated) * ah->area_count / ah->area_multiple);
-+		ah->new_extents = alloc_state.allocated;
- 	}
- 
- 	if (alloc_state.log_area_count_still_needed) {
-@@ -2465,7 +2546,7 @@ struct alloc_handle *allocate_extents(struct volume_group *vg,
- 				      uint32_t mirrors, uint32_t log_count,
- 				      uint32_t region_size, uint32_t extents,
- 				      struct dm_list *allocatable_pvs,
--				      alloc_policy_t alloc,
-+				      alloc_policy_t alloc, int approx_alloc,
- 				      struct dm_list *parallel_areas)
- {
- 	struct alloc_handle *ah;
-@@ -2495,7 +2576,7 @@ struct alloc_handle *allocate_extents(struct volume_group *vg,
- 		alloc = vg->alloc;
- 
- 	new_extents = (lv ? lv->le_count : 0) + extents;
--	if (!(ah = _alloc_init(vg->cmd, vg->cmd->mem, segtype, alloc,
-+	if (!(ah = _alloc_init(vg->cmd, vg->cmd->mem, segtype, alloc, approx_alloc,
- 			       new_extents, mirrors, stripes, log_count,
- 			       vg->extent_size, region_size,
- 			       parallel_areas)))
-@@ -2955,26 +3036,38 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
- 
- /*
-  * Entry point for single-step LV allocation + extension.
-+ * Extents is the number of logical extents to append to the LV unless
-+ * approx_alloc is set when it is an upper limit for the total number of
-+ * extents to use from the VG.
-+ *
-+ * FIXME The approx_alloc raid/stripe conversion should be performed
-+ * before calling this function.
-  */
- int lv_extend(struct logical_volume *lv,
- 	      const struct segment_type *segtype,
- 	      uint32_t stripes, uint32_t stripe_size,
- 	      uint32_t mirrors, uint32_t region_size,
- 	      uint32_t extents, const char *thin_pool_name,
--	      struct dm_list *allocatable_pvs, alloc_policy_t alloc)
-+	      struct dm_list *allocatable_pvs, alloc_policy_t alloc,
-+	      int approx_alloc)
- {
- 	int r = 1;
- 	int log_count = 0;
- 	struct alloc_handle *ah;
- 	uint32_t sub_lv_count;
- 
--	log_very_verbose("Extending segment type, %s", segtype->name);
-+	log_very_verbose("Adding segment of type %s to LV %s.", segtype->name, lv->name);
- 
- 	if (segtype_is_virtual(segtype))
- 		return lv_add_virtual_segment(lv, 0u, extents, segtype, thin_pool_name);
- 
--	if (!lv->le_count && segtype_is_thin_pool(segtype)) {
--		/* Thin pool allocation treats its metadata device like a mirror log. */
-+	if (!lv->le_count &&
-+	    (segtype_is_thin_pool(segtype) ||
-+	     segtype_is_cache_pool(segtype))) {
-+		/*
-+		 * Thinpool and cache_pool allocations treat the metadata
-+		 * device like a mirror log.
-+		 */
- 		/* FIXME Allow pool and data on same device with NORMAL */
- 		/* FIXME Support striped metadata pool */
- 		log_count = 1;
-@@ -2984,13 +3077,19 @@ int lv_extend(struct logical_volume *lv,
- 
- 	if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors,
- 				    log_count, region_size, extents,
--				    allocatable_pvs, alloc, NULL)))
-+				    allocatable_pvs, alloc, approx_alloc, NULL)))
- 		return_0;
- 
--	if (segtype_is_thin_pool(segtype)) {
-+	if (ah->approx_alloc) {
-+		extents = ah->new_extents;
-+		if (segtype_is_raid(segtype))
-+			extents -= ah->log_len * ah->area_multiple;
-+	}
-+
-+	if (segtype_is_thin_pool(segtype) || segtype_is_cache_pool(segtype)) {
- 		if (lv->le_count) {
- 			/* lv_resize abstracts properly _tdata */
--			log_error(INTERNAL_ERROR "Cannot lv_extend() the existing thin pool segment.");
-+			log_error(INTERNAL_ERROR "Cannot lv_extend() the existing %s segment.", segtype->name);
- 			return 0;
- 		}
- 		if (!(r = create_pool(lv, segtype, ah, stripes, stripe_size)))
-@@ -3307,6 +3406,7 @@ int lv_rename(struct cmd_context *cmd, struct logical_volume *lv,
- 
- #define SIZE_BUF 128
- 
-+/* TODO: unify stripe size validation across source code */
- static int _validate_stripesize(struct cmd_context *cmd,
- 				const struct volume_group *vg,
- 				struct lvresize_params *lp)
-@@ -3320,11 +3420,11 @@ static int _validate_stripesize(struct cmd_context *cmd,
- 
- 	if (!(vg->fid->fmt->features & FMT_SEGMENTS))
- 		log_warn("Varied stripesize not supported. Ignoring.");
--	else if (lp->ac_stripesize_value > (uint64_t) vg->extent_size * 2) {
--		log_error("Reducing stripe size %s to maximum, "
--			  "physical extent size %s",
--			  display_size(cmd,lp->ac_stripesize_value),
--			  display_size(cmd, (uint64_t) vg->extent_size));
-+	else if (lp->ac_stripesize_value > vg->extent_size) {
-+		log_print_unless_silent("Reducing stripe size %s to maximum, "
-+					"physical extent size %s",
-+					display_size(cmd, lp->ac_stripesize_value),
-+					display_size(cmd, vg->extent_size));
- 		lp->stripe_size = vg->extent_size;
- 	} else
- 		lp->stripe_size = lp->ac_stripesize_value;
-@@ -3469,7 +3569,7 @@ static int _adjust_policy_params(struct cmd_context *cmd,
- 			return_0;
- 		if ((PERCENT_0 < percent && percent <= PERCENT_100) &&
- 		    (percent > policy_threshold)) {
--			if (!pool_can_resize_metadata(lv)) {
-+			if (!thin_pool_feature_supported(lv, THIN_FEATURE_METADATA_RESIZE)) {
- 				log_error_once("Online metadata resize for %s/%s is not supported.",
- 					       lp->vg_name, lp->lv_name);
- 				return 0;
-@@ -3535,7 +3635,7 @@ static int _lvresize_poolmetadata_prepare(struct cmd_context *cmd,
- 
- 	lp->poolmetadataextents = 0;
- 
--	if (!pool_can_resize_metadata(pool_lv)) {
-+	if (!thin_pool_feature_supported(pool_lv, THIN_FEATURE_METADATA_RESIZE)) {
- 		log_error("Support for online metadata resize not detected.");
- 		return 0;
- 	}
-@@ -3603,7 +3703,7 @@ static int _lvresize_poolmetadata(struct cmd_context *cmd, struct volume_group *
- 		       seg_mirrors,
- 		       mseg->region_size,
- 		       lp->poolmetadataextents - lv->le_count, NULL,
--		       pvh, alloc))
-+		       pvh, alloc, 0))
- 		return_0;
- 
- 	return 1;
-@@ -3716,7 +3816,7 @@ static int _lvresize_adjust_extents(struct cmd_context *cmd, struct logical_volu
- {
- 	struct volume_group *vg = lv->vg;
- 	uint32_t pv_extent_count;
--	uint32_t extents_used;
-+	uint32_t extents_used, extents;
- 	uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size;
- 	uint32_t seg_mirrors = 0;
- 	struct lv_segment *seg, *uninitialized_var(mirr_seg);
-@@ -3728,24 +3828,24 @@ static int _lvresize_adjust_extents(struct cmd_context *cmd, struct logical_volu
- 	/* If percent options were used, convert them into actual numbers of extents */
- 	switch (lp->percent) {
- 		case PERCENT_VG:
--			lp->extents = percent_of_extents(lp->extents, vg->extent_count,
-+			extents = percent_of_extents(lp->extents, vg->extent_count,
- 							 (lp->sign != SIGN_MINUS));
- 			break;
- 		case PERCENT_FREE:
--			lp->extents = percent_of_extents(lp->extents, vg->free_count,
-+			extents = percent_of_extents(lp->extents, vg->free_count,
- 							 (lp->sign != SIGN_MINUS));
- 			break;
- 		case PERCENT_LV:
--			lp->extents = percent_of_extents(lp->extents, lv->le_count,
-+			extents = percent_of_extents(lp->extents, lv->le_count,
- 							 (lp->sign != SIGN_MINUS));
- 			break;
- 		case PERCENT_PVS:
- 			if (lp->argc) {
- 				pv_extent_count = pv_list_extents_free(pvh);
--				lp->extents = percent_of_extents(lp->extents, pv_extent_count,
-+				extents = percent_of_extents(lp->extents, pv_extent_count,
- 								 (lp->sign != SIGN_MINUS));
- 			} else
--				lp->extents = percent_of_extents(lp->extents, vg->extent_count,
-+				extents = percent_of_extents(lp->extents, vg->extent_count,
- 								 (lp->sign != SIGN_MINUS));
- 			break;
- 		case PERCENT_ORIGIN:
-@@ -3753,11 +3853,23 @@ static int _lvresize_adjust_extents(struct cmd_context *cmd, struct logical_volu
- 				log_error("Specified LV does not have an origin LV.");
- 				return 0;
- 			}
--			lp->extents = percent_of_extents(lp->extents, origin_from_cow(lv)->le_count,
-+			extents = percent_of_extents(lp->extents, origin_from_cow(lv)->le_count,
- 							 (lp->sign != SIGN_MINUS));
- 			break;
- 		case PERCENT_NONE:
-+			extents = lp->extents;
- 			break;
-+		default:
-+			log_error(INTERNAL_ERROR "Unsupported percent type %u.", lp->percent);
-+			return 0;
-+	}
-+
-+	if (lp->percent != PERCENT_NONE) {
-+		log_verbose("Converted %" PRIu32 "%%%s into %" PRIu32 " extents.", lp->extents, get_percent_string(lp->percent), extents);
-+		lp->extents = extents;
-+		if (lp->sign == SIGN_NONE && (lp->percent != PERCENT_LV && lp->percent != PERCENT_ORIGIN))
-+			lp->approx_alloc = 1;
-+		/* FIXME Adjust for parallel areas here before processing relative allocations */
- 	}
- 
- 	if (lp->sign == SIGN_PLUS) {
-@@ -4028,6 +4140,26 @@ static int _lvresize_check_type(struct cmd_context *cmd, const struct logical_vo
- 		}
- 	}
- 
-+	if (lv_is_thin_volume(lv) && first_seg(lv)->external_lv &&
-+	    (lp->resize == LV_EXTEND)) {
-+		/*
-+		 * TODO: currently we do not support extension of already reduced thin volume.
-+		 * But it might be possible to create combined mapping of some part of
-+		 * the external origin followed by zero target.
-+		 */
-+		if (first_seg(lv)->external_lv->size > lv->size) {
-+			log_error("Extension of reduced thin volume with external origin is unsupported.");
-+			return 0;
-+		}
-+
-+		/* Validate thin target supports bigger size of thin volume then external origin */
-+		if (first_seg(lv)->external_lv->size <= lv->size &&
-+		    !thin_pool_feature_supported(first_seg(lv)->pool_lv, THIN_FEATURE_EXTERNAL_ORIGIN_EXTEND)) {
-+			log_error("Thin target does not support external origin smaller then thin volume.");
-+			return 0;
-+		}
-+	}
-+
- 	return 1;
- }
- 
-@@ -4096,7 +4228,7 @@ static struct logical_volume *_lvresize_volume(struct cmd_context *cmd,
- 			      lp->stripes, lp->stripe_size,
- 			      lp->mirrors, first_seg(lv)->region_size,
- 			      lp->extents - lv->le_count, NULL,
--			      pvh, alloc))
-+			      pvh, alloc, lp->approx_alloc))
- 		return_NULL;
- 
- 	if (lock_lv) {
-@@ -4157,6 +4289,11 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
- 	struct logical_volume *lock_lv = NULL;
- 	int inactive = 0;
- 
-+	if (lv_is_cache_type(lv)) {
-+		log_error("Unable to resize logical volumes of cache type.");
-+		return 0;
-+	}
-+
- 	if (lp->sizeargs &&
- 	    !(lock_lv = _lvresize_volume(cmd, lv, lp, pvh)))
- 		return_0;
-@@ -4502,6 +4639,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
- 	int format1_reload_required = 0;
- 	int visible;
- 	struct logical_volume *pool_lv = NULL;
-+	struct lv_segment *cache_seg = NULL;
- 	int ask_discard;
- 
- 	vg = lv->vg;
-@@ -4546,6 +4684,27 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
- 	} else if (lv_is_thin_volume(lv))
- 		pool_lv = first_seg(lv)->pool_lv;
- 
-+	/*
-+	 * If we are removing a cache_pool, we must first unlink
-+	 * it from any origins (i.e. remove the cache layer).
-+	 *
-+	 * If the cache_pool is not linked, we can simply proceed
-+	 * to remove it.
-+	 */
-+	if (lv_is_cache_pool(lv) && !dm_list_empty(&lv->segs_using_this_lv)) {
-+		if (!(cache_seg = get_only_segment_using_this_lv(lv)))
-+			return_0;
-+
-+		if (!lv_cache_remove(cache_seg->lv))
-+			return_0;
-+	}
-+
-+	if (lv_is_cache_pool_data(lv) || lv_is_cache_pool_metadata(lv)) {
-+		log_error("Can't remove logical volume %s used by a cache_pool.",
-+			  lv->name);
-+		return 0;
-+	}
-+
- 	if (lv->status & LOCKED) {
- 		log_error("Can't remove locked LV %s", lv->name);
- 		return 0;
-@@ -4774,12 +4933,14 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
- 	if (lv_is_used_thin_pool(lv) &&
- 	    !_lv_remove_segs_using_this_lv(cmd, lv, force, level, "pool"))
- 		return_0;
--
--	if (lv_is_thin_pool(lv) && lv->vg->pool_metadata_spare_lv) {
--		/* When removing last thin pool, remove also spare */
-+	if ((lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) &&
-+	    lv->vg->pool_metadata_spare_lv) {
-+		/* When removing last pool, also remove the spare */
- 		is_last_pool = 1;
- 		dm_list_iterate_items(lvl, &lv->vg->lvs)
--			if (lv_is_thin_pool(lvl->lv) && lvl->lv != lv) {
-+			if ((lv_is_thin_pool(lvl->lv) ||
-+			     lv_is_cache_pool(lvl->lv)) &&
-+			    lvl->lv != lv) {
- 				is_last_pool = 0;
- 				break;
- 			}
-@@ -4792,9 +4953,10 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
- 
- 	if (lv_is_pool_metadata_spare(lv) &&
- 	    (force == PROMPT) &&
--	    (yes_no_prompt("Removal of pool metadata spare logical volume \"%s\" "
--			   "disables automatic recovery attempts after damage "
--			   "to a thin pool. Proceed? [y/n]: ", lv->name) == 'n'))
-+	    (yes_no_prompt("Removal of pool metadata spare logical volume"
-+			   " \"%s\" disables automatic recovery attempts"
-+			   " after damage to a thin or cache pool."
-+			   " Proceed? [y/n]: ", lv->name) == 'n'))
- 		goto no_remove;
- 
- 	return lv_remove_single(cmd, lv, force, 0);
-@@ -5061,6 +5223,8 @@ int remove_layer_from_lv(struct logical_volume *lv,
- 	    parent->le_count != layer_lv->le_count)
- 		return_0;
- 
-+	//FIXME: why do we empty the parent?  It removes everything below.
-+	//This makes the function unusable for 'lv_cache_remove'
- 	if (!lv_empty(parent))
- 		return_0;
- 
-@@ -5448,7 +5612,9 @@ int wipe_lv(struct logical_volume *lv, struct wipe_params wp)
- 	if (wp.do_wipe_signatures) {
- 		log_verbose("Wiping known signatures on logical volume \"%s/%s\"",
- 			     lv->vg->name, lv->name);
--		if (!wipe_known_signatures(lv->vg->cmd, dev, name, 0, wp.yes, wp.force))
-+		if (!wipe_known_signatures(lv->vg->cmd, dev, name, 0,
-+					   TYPE_DM_SNAPSHOT_COW,
-+					   wp.yes, wp.force))
- 			stack;
- 	}
- 
-@@ -5458,8 +5624,9 @@ int wipe_lv(struct logical_volume *lv, struct wipe_params wp)
- 		if (zero_sectors > lv->size)
- 			zero_sectors = lv->size;
- 
--		log_verbose("Clearing start of logical volume \"%s/%s\"",
--			     lv->vg->name, lv->name);
-+		log_verbose("Initializing %s of logical volume \"%s/%s\" with value %d.",
-+			    display_size(lv->vg->cmd, zero_sectors),
-+			    lv->vg->name, lv->name, wp.zero_value);
- 
- 		if (!dev_set(dev, UINT64_C(0), (size_t) zero_sectors << SECTOR_SHIFT, wp.zero_value))
- 			stack;
-@@ -5503,7 +5670,7 @@ static struct logical_volume *_create_virtual_origin(struct cmd_context *cmd,
- 		return_NULL;
- 
- 	if (!lv_extend(lv, segtype, 1, 0, 1, 0, voriginextents,
--		       NULL, NULL, ALLOC_INHERIT))
-+		       NULL, NULL, ALLOC_INHERIT, 0))
- 		return_NULL;
- 
- 	/* store vg on disk(s) */
-@@ -5549,16 +5716,16 @@ void lv_set_activation_skip(struct logical_volume *lv, int override_default,
-  * of the 'skip' arg supplied instead.
-  */
- int lv_activation_skip(struct logical_volume *lv, activation_change_t activate,
--		      int override_lv_skip_flag, int skip)
-+		       int override_lv_skip_flag)
- {
--	/* Do not skip deactivation! */
--	if ((activate == CHANGE_AN) || (activate == CHANGE_ALN))
-+	if (!(lv->status & LV_ACTIVATION_SKIP) ||
-+	    !is_change_activating(activate) || /* Do not skip deactivation */
-+	    override_lv_skip_flag)
- 		return 0;
- 
--	if (override_lv_skip_flag)
--		return skip;
--
--	return (lv->status & LV_ACTIVATION_SKIP) ? 1 : 0;
-+	log_verbose("ACTIVATON_SKIP flag set for LV %s/%s, skipping activation.",
-+		    lv->vg->name, lv->name);
-+	return 1;
- }
- 
- /* Greatest common divisor */
-@@ -5583,8 +5750,8 @@ static unsigned long _lcm(unsigned long n1, unsigned long n2)
- 	return (n1 * n2) / _gcd(n1, n2);
- }
- 
--static int _recalculate_thin_pool_chunk_size_with_dev_hints(struct lvcreate_params *lp,
--							    struct logical_volume *pool_lv)
-+static int _recalculate_pool_chunk_size_with_dev_hints(struct lvcreate_params *lp,
-+						       struct logical_volume *pool_lv)
- {
- 	struct logical_volume *pool_data_lv;
- 	struct lv_segment *seg;
-@@ -5592,13 +5759,34 @@ static int _recalculate_thin_pool_chunk_size_with_dev_hints(struct lvcreate_para
- 	struct cmd_context *cmd = pool_lv->vg->cmd;
- 	unsigned long previous_hint = 0, hint = 0;
- 	uint32_t chunk_size = lp->chunk_size;
--	uint32_t default_chunk_size = lp->thin_chunk_size_calc_policy == THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE ?
--					DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE*2 : DEFAULT_THIN_POOL_CHUNK_SIZE*2;
-+	uint32_t default_chunk_size;
-+	uint32_t min_chunk_size, max_chunk_size;
- 
--	if (lp->passed_args & PASS_ARG_CHUNK_SIZE ||
--	    find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, NULL))
-+	if (lp->passed_args & PASS_ARG_CHUNK_SIZE)
- 		goto out;
- 
-+	if (seg_is_thin_pool(lp)) {
-+		if (find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, NULL))
-+			goto out;
-+
-+		min_chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
-+		max_chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
-+		if (lp->thin_chunk_size_calc_policy == THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE)
-+			default_chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE*2;
-+		else
-+			default_chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE*2;
-+	} else if (seg_is_cache_pool(lp)) {
-+		if (find_config_tree_int(cmd, allocation_cache_pool_chunk_size_CFG, NULL))
-+			goto out;
-+		min_chunk_size = DM_CACHE_MIN_DATA_BLOCK_SIZE;
-+		max_chunk_size = DM_CACHE_MAX_DATA_BLOCK_SIZE;
-+		default_chunk_size = DEFAULT_CACHE_POOL_CHUNK_SIZE*2;
-+	} else {
-+		log_error(INTERNAL_ERROR "%s is not a thin pool or cache pool",
-+			  pool_lv->name);
-+		return 0;
-+	}
-+
- 	pool_data_lv = seg_lv(first_seg(pool_lv), 0);
- 
- 	dm_list_iterate_items(seg, &pool_data_lv->segments) {
-@@ -5616,19 +5804,19 @@ static int _recalculate_thin_pool_chunk_size_with_dev_hints(struct lvcreate_para
- 	}
- 
- 	if (!hint) {
--		log_debug_alloc("No usable device hint found while recalculating "
--				"thin pool chunk size for %s.", pool_lv->name);
-+		log_debug_alloc("No usable device hint found while recalculating"
-+				" thin pool chunk size for %s.", pool_lv->name);
- 		goto out;
- 	}
- 
--	if (hint < DM_THIN_MIN_DATA_BLOCK_SIZE ||
--	    hint > DM_THIN_MAX_DATA_BLOCK_SIZE) {
--		log_debug_alloc("Calculated chunk size value of %ld sectors "
--				"for thin pool %s is out of allowed range (%d-%d).",
--				hint, pool_lv->name, DM_THIN_MIN_DATA_BLOCK_SIZE,
--				DM_THIN_MAX_DATA_BLOCK_SIZE);
-+	if ((hint < min_chunk_size) || (hint > max_chunk_size)) {
-+		log_debug_alloc("Calculated chunk size value of %ld sectors for"
-+				" thin pool %s is out of allowed range (%d-%d).",
-+				hint, pool_lv->name,
-+				min_chunk_size, max_chunk_size);
- 	} else
--		chunk_size = hint >= default_chunk_size ? hint : default_chunk_size;
-+		chunk_size = (hint >= default_chunk_size) ?
-+			hint : default_chunk_size;
- out:
- 	first_seg(pool_lv)->chunk_size = chunk_size;
- 	return 1;
-@@ -5637,7 +5825,7 @@ out:
- static int _should_wipe_lv(struct lvcreate_params *lp, struct logical_volume *lv) {
- 	int r = lp->zero | lp->wipe_signatures;
- 
--	if (!seg_is_thin(lp))
-+	if (!seg_is_thin(lp) && !seg_is_cache_pool(lp))
- 		return r;
- 
- 	if (lv_is_thin_volume(lv))
-@@ -5676,9 +5864,11 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 		return NULL;
- 	}
- 
--	if ((segtype_is_mirrored(lp->segtype) ||
--	     segtype_is_raid(lp->segtype) || segtype_is_thin(lp->segtype)) &&
--	    !(vg->fid->fmt->features & FMT_SEGMENTS)) {
-+	if (!(vg->fid->fmt->features & FMT_SEGMENTS) &&
-+	    (segtype_is_mirrored(lp->segtype) ||
-+	     segtype_is_raid(lp->segtype) ||
-+	     segtype_is_thin(lp->segtype) ||
-+	     segtype_is_cache(lp->segtype))) {
- 		log_error("Metadata does not support %s segments.",
- 			  lp->segtype->name);
- 		return NULL;
-@@ -5725,7 +5915,59 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 
- 	status |= lp->permission | VISIBLE_LV;
- 
--	if (seg_is_thin(lp) && lp->snapshot) {
-+	if (segtype_is_cache(lp->segtype) && lp->pool) {
-+		/* We have the cache_pool, create the origin with cache */
-+		if (!(pool_lv = find_lv(vg, lp->pool))) {
-+			log_error("Couldn't find origin volume '%s'.",
-+				  lp->pool);
-+			return NULL;
-+		}
-+
-+		if (pool_lv->status & LOCKED) {
-+			log_error("Caching locked devices is not supported.");
-+			return NULL;
-+		}
-+
-+		if (!lp->extents) {
-+			log_error("No size given for new cache origin LV");
-+			return NULL;
-+		}
-+
-+		if (lp->extents < pool_lv->le_count) {
-+			log_error("Origin size cannot be smaller than"
-+				  " the cache_pool");
-+			return NULL;
-+		}
-+
-+		if (!(lp->segtype = get_segtype_from_string(vg->cmd, "striped")))
-+			return_0;
-+	} else if (segtype_is_cache(lp->segtype) && lp->origin) {
-+		/* We have the origin, create the cache_pool and cache */
-+		if (!(org = find_lv(vg, lp->origin))) {
-+			log_error("Couldn't find origin volume '%s'.",
-+				  lp->origin);
-+			return NULL;
-+		}
-+
-+		if (org->status & LOCKED) {
-+			log_error("Caching locked devices is not supported.");
-+			return NULL;
-+		}
-+
-+		if (!lp->extents) {
-+			log_error("No size given for new cache_pool LV");
-+			return NULL;
-+		}
-+
-+		if (lp->extents > org->le_count) {
-+			log_error("cache-pool size cannot be larger than"
-+				  " the origin");
-+			return NULL;
-+		}
-+		if (!(lp->segtype = get_segtype_from_string(vg->cmd,
-+							    "cache-pool")))
-+			return_0;
-+	} else if (seg_is_thin(lp) && lp->snapshot) {
- 		if (!(org = find_lv(vg, lp->origin))) {
- 			log_error("Couldn't find origin volume '%s'.",
- 				  lp->origin);
-@@ -5806,10 +6048,12 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 		return NULL;
- 	}
- 
--	if (seg_is_thin_pool(lp) &&
--	    ((uint64_t)lp->extents * vg->extent_size < lp->chunk_size)) {
--		log_error("Unable to create thin pool smaller than 1 chunk.");
--		return NULL;
-+	if (seg_is_thin_pool(lp) || seg_is_cache_pool(lp)) {
-+		if (((uint64_t)lp->extents * vg->extent_size < lp->chunk_size)) {
-+			log_error("Unable to create %s smaller than 1 chunk.",
-+				  lp->segtype->name);
-+			return NULL;
-+		}
- 	}
- 
- 	if (lp->snapshot && !seg_is_thin(lp) &&
-@@ -5824,7 +6068,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 	}
- 
- 	if (!seg_is_virtual(lp) &&
--	    vg->free_count < lp->extents) {
-+	    vg->free_count < lp->extents && !lp->approx_alloc) {
- 		log_error("Volume group \"%s\" has insufficient free space "
- 			  "(%u extents): %u required.",
- 			  vg->name, vg->free_count, lp->extents);
-@@ -5841,7 +6085,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 	if (!activation() &&
- 	    (seg_is_mirrored(lp) ||
- 	     seg_is_raid(lp) ||
--	     seg_is_thin_pool(lp))) {
-+	     seg_is_thin_pool(lp) ||
-+	     seg_is_cache_pool(lp))) {
- 		/*
- 		 * FIXME: For thin pool add some code to allow delayed
- 		 * initialization of empty thin pool volume.
-@@ -5850,9 +6095,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 		 */
- 		log_error("Can't create %s without using "
- 			  "device-mapper kernel driver.",
--			  segtype_is_raid(lp->segtype) ? lp->segtype->name :
--			  segtype_is_mirrored(lp->segtype) ?  "mirror" :
--			  "thin pool volume");
-+			  seg_is_thin_pool(lp) ? "thin pool volume" :
-+			  lp->segtype->name);
- 		return NULL;
- 	}
- 
-@@ -5888,10 +6132,9 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 			return NULL;
- 		}
- 
--		if (lv_is_active(lvl->lv) ||
--		    ((lp->activate != CHANGE_AN) && (lp->activate != CHANGE_ALN)))
--			if (!update_pool_lv(lvl->lv, 1))
--				return_NULL;
-+		if ((lv_is_active(lvl->lv) || is_change_activating(lp->activate)) &&
-+		    !update_pool_lv(lvl->lv, 1))
-+			return_NULL;
- 
- 		/* For thin snapshot we must have matching pool */
- 		if (org && lv_is_thin_volume(org) && (!lp->pool ||
-@@ -5938,13 +6181,18 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 	if (!lv_extend(lv, lp->segtype,
- 		       lp->stripes, lp->stripe_size,
- 		       lp->mirrors,
--		       seg_is_thin_pool(lp) ? lp->poolmetadataextents : lp->region_size,
-+		       (seg_is_thin_pool(lp) || seg_is_cache_pool(lp)) ?
-+		       lp->poolmetadataextents : lp->region_size,
- 		       seg_is_thin_volume(lp) ? lp->voriginextents : lp->extents,
--		       thin_name, lp->pvh, lp->alloc))
-+		       thin_name, lp->pvh, lp->alloc, lp->approx_alloc))
- 		return_NULL;
- 
--	if (seg_is_thin_pool(lp)) {
--		if (!_recalculate_thin_pool_chunk_size_with_dev_hints(lp, lv))
-+	if (seg_is_cache_pool(lp)) {
-+		if (!_recalculate_pool_chunk_size_with_dev_hints(lp, lv))
-+			return_NULL;
-+		first_seg(lv)->feature_flags = lp->feature_flags;
-+	} else if (seg_is_thin_pool(lp)) {
-+		if (!_recalculate_pool_chunk_size_with_dev_hints(lp, lv))
- 			return_NULL;
- 		first_seg(lv)->zero_new_blocks = lp->zero ? 1 : 0;
- 		first_seg(lv)->discards = lp->discards;
-@@ -5960,6 +6208,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 		 * within the same thin pool
- 		 */
- 		if (lp->snapshot && (first_seg(org)->pool_lv != pool_lv)) {
-+			if (!pool_supports_external_origin(first_seg(pool_lv), org))
-+				return_0;
- 			if (org->status & LVM_WRITE) {
- 				log_error("Cannot use writable LV as the external origin.");
- 				return 0; // TODO conversion for inactive
-@@ -5978,14 +6228,42 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 	} else if (seg_is_raid(lp)) {
- 		first_seg(lv)->min_recovery_rate = lp->min_recovery_rate;
- 		first_seg(lv)->max_recovery_rate = lp->max_recovery_rate;
--		if (vg_is_clustered(lv->vg) &&
--		    is_change_activating(lp->activate) &&
--		    (lp->activate != CHANGE_AE)) {
--			log_debug_activation("Creating RAID logical volume in a"
--					     " cluster: setting activation"
--					     " mode to EX");
--			lp->activate = CHANGE_AE;
-+	}
-+
-+	if (lp->cache) {
-+		struct logical_volume *tmp_lv;
-+
-+		if (lp->origin) {
-+			/*
-+			 * FIXME:  At this point, create_pool has created
-+			 * the pool and added the data and metadata sub-LVs,
-+			 * but only the metadata sub-LV is in the kernel -
-+			 * a suspend/resume cycle is still necessary on the
-+			 * cache_pool to actualize it in the kernel.
-+			 *
-+			 * Should the suspend/resume be added to create_pool?
-+			 *    I say that would be cleaner, but I'm not sure
-+			 *    about the effects on thinpool yet...
-+			 */
-+			if (!vg_write(vg) || !suspend_lv(cmd, lv) ||
-+			    !vg_commit(vg) || !resume_lv(cmd, lv))
-+				goto deactivate_and_revert_new_lv;
-+
-+			if (!(lvl = find_lv_in_vg(vg, lp->origin)))
-+				goto deactivate_and_revert_new_lv;
-+			org = lvl->lv;
-+			pool_lv = lv;
-+		} else {
-+			if (!(lvl = find_lv_in_vg(vg, lp->pool)))
-+				goto deactivate_and_revert_new_lv;
-+			pool_lv = lvl->lv;
-+			org = lv;
- 		}
-+
-+		if (!(tmp_lv = lv_cache_create(pool_lv, org)))
-+			goto deactivate_and_revert_new_lv;
-+
-+		lv = tmp_lv;
- 	}
- 
- 	/* FIXME Log allocation and attachment should have happened inside lv_extend. */
-@@ -6010,11 +6288,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 		lp->activate = lv_passes_auto_activation_filter(cmd, lv) ?
- 				CHANGE_ALY : CHANGE_ALN;
- 
--	if (lv_activation_skip(lv, lp->activate, lp->activation_skip & ACTIVATION_SKIP_IGNORE, 0)) {
--		log_verbose("ACTIVATION_SKIP flag set for LV %s/%s, skipping activation.",
--			    lv->vg->name, lv->name);
-+	if (lv_activation_skip(lv, lp->activate, lp->activation_skip & ACTIVATION_SKIP_IGNORE))
- 		lp->activate = CHANGE_AN;
--	}
- 
- 	/*
- 	 * For thin pools - deactivate when inactive pool is requested or
-@@ -6047,7 +6322,25 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 	if (lp->temporary)
- 		lv->status |= LV_TEMPORARY;
- 
--	if (lv_is_thin_pool(lv)) {
-+	if (lv_is_cache_type(lv)) {
-+		if (!lv_is_active(lv)) {
-+			if (!activate_lv_excl(cmd, lv)) {
-+				log_error("Failed to activate pool %s.",
-+					  lv->name);
-+				goto deactivate_and_revert_new_lv;
-+			}
-+		} else {
-+			if (!suspend_lv(cmd, lv)) {
-+				log_error("Failed to suspend pool %s.",
-+					  lv->name);
-+				goto deactivate_and_revert_new_lv;
-+			}
-+			if (!resume_lv(cmd, lv)) {
-+				log_error("Failed to resume pool %s.", lv->name);
-+				goto deactivate_and_revert_new_lv;
-+			}
-+		}
-+	} else if (lv_is_thin_pool(lv)) {
- 		if (is_change_activating(lp->activate)) {
- 			if (vg_is_clustered(lv->vg)) {
- 				if (!activate_lv_excl(cmd, lv)) {
-@@ -6227,7 +6520,7 @@ struct logical_volume *lv_create_single(struct volume_group *vg,
- 	struct logical_volume *lv;
- 
- 	/* Create thin pool first if necessary */
--	if (lp->create_thin_pool) {
-+	if (lp->create_pool && !seg_is_cache_pool(lp) && !seg_is_cache(lp)) {
- 		if (!seg_is_thin_pool(lp) &&
- 		    !(lp->segtype = get_segtype_from_string(vg->cmd, "thin-pool")))
- 			return_0;
-diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
-index 93e4bfa..f6a14a8 100644
---- a/lib/metadata/merge.c
-+++ b/lib/metadata/merge.c
-@@ -190,31 +190,54 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
- 					inc_error_count;
- 				}
- 
--				if (seg->area_count != 1 || seg_type(seg, 0) != AREA_LV) {
--					log_error("LV %s: thin pool segment %u is missing a pool data LV",
--						  lv->name, seg_count);
-+			}
-+			if (seg_is_thin_pool(seg) || seg_is_cache_pool(seg)) {
-+				if (seg->area_count != 1 ||
-+				    seg_type(seg, 0) != AREA_LV) {
-+					log_error("LV %s: %spool segment %u is missing a pool data LV",
-+						  lv->name,
-+						  seg_is_thin_pool(seg) ?
-+						  "thin " : "cache",
-+						  seg_count);
- 					inc_error_count;
- 				} else if (!(seg2 = first_seg(seg_lv(seg, 0))) || find_pool_seg(seg2) != seg) {
--					log_error("LV %s: thin pool segment %u data LV does not refer back to pool LV",
--						  lv->name, seg_count);
-+					log_error("LV %s: %spool segment %u data LV does not refer back to pool LV",
-+						  lv->name,
-+						  seg_is_thin_pool(seg) ?
-+						  "thin " : "cache",
-+						  seg_count);
- 					inc_error_count;
- 				}
- 
- 				if (!seg->metadata_lv) {
--					log_error("LV %s: thin pool segment %u is missing a pool metadata LV",
--						  lv->name, seg_count);
-+					log_error("LV %s: %spool segment %u is missing a pool metadata LV",
-+						  lv->name,
-+						  seg_is_thin_pool(seg) ?
-+						  "thin " : "cache",
-+						  seg_count);
- 					inc_error_count;
- 				} else if (!(seg2 = first_seg(seg->metadata_lv)) ||
- 					   find_pool_seg(seg2) != seg) {
--					log_error("LV %s: thin pool segment %u metadata LV does not refer back to pool LV",
--						  lv->name, seg_count);
-+					log_error("LV %s: %spool segment %u metadata LV does not refer back to pool LV",
-+						  lv->name,
-+						  seg_is_thin_pool(seg) ?
-+						  "thin " : "cache",
-+						  seg_count);
- 					inc_error_count;
- 				}
- 
--				if (seg->chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE ||
--				    seg->chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE) {
--					log_error("LV %s: thin pool segment %u has chunk size %u out of range.",
--						  lv->name, seg_count, seg->chunk_size);
-+				if ((seg_is_thin_pool(seg) &&
-+				     ((seg->chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE) ||
-+				     (seg->chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE))) ||
-+				    (seg_is_cache_pool(seg) &&
-+				     ((seg->chunk_size < DM_CACHE_MIN_DATA_BLOCK_SIZE) ||
-+				     (seg->chunk_size > DM_CACHE_MAX_DATA_BLOCK_SIZE))))
-+{
-+					log_error("LV %s: %spool segment %u has chunk size %u out of range.",
-+						  lv->name,
-+						  seg_is_thin_pool(seg) ?
-+						  "thin " : "cache",
-+						  seg_count, seg->chunk_size);
- 					inc_error_count;
- 				}
- 			} else {
-@@ -271,6 +294,17 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
- 						inc_error_count;
- 					}
- 				}
-+			} else if (seg_is_cache(seg)) {
-+				if (!lv_is_cache(lv)) {
-+					log_error("LV %s is missing cache flag for segment %u",
-+						  lv->name, seg_count);
-+					inc_error_count;
-+				}
-+				if (!seg->pool_lv) {
-+					log_error("LV %s: segment %u is missing cache_pool LV",
-+						  lv->name, seg_count);
-+					inc_error_count;
-+				}
- 			} else {
- 				if (seg->pool_lv) {
- 					log_error("LV %s: segment %u must not have thin pool LV set",
-diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
-index 8e36891..87e6046 100644
---- a/lib/metadata/metadata-exported.h
-+++ b/lib/metadata/metadata-exported.h
-@@ -1,6 +1,6 @@
- /*
-  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
-- * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -105,9 +105,15 @@
- #define LV_NOSCAN		UINT64_C(0x0000080000000000)	/* LV - internal use only - the LV
- 									should not be scanned */
- #define LV_TEMPORARY		UINT64_C(0x0000100000000000)	/* LV - internal use only - the LV
--								        is supposed to be created and
--									removed during single LVM
--									command execution. */
-+									is supposed to be created and
-+									removed or reactivated with
-+									this flag dropped during single
-+									LVM command execution. */
-+
-+#define CACHE_POOL		UINT64_C(0x0000200000000000)    /* LV */
-+#define CACHE_POOL_DATA		UINT64_C(0x0000400000000000)    /* LV */
-+#define CACHE_POOL_METADATA	UINT64_C(0x0000800000000000)    /* LV */
-+#define CACHE			UINT64_C(0x0001000000000000)    /* LV */
- 
- /* Format features flags */
- #define FMT_SEGMENTS		0x00000001U	/* Arbitrary segment params? */
-@@ -168,6 +174,12 @@
- #define lv_is_raid(lv)		(((lv)->status & (RAID)) ? 1 : 0)
- #define lv_is_raid_type(lv)	(((lv)->status & (RAID | RAID_IMAGE | RAID_META)) ? 1 : 0)
- 
-+#define lv_is_cache(lv)		(((lv)->status & (CACHE)) ? 1 : 0)
-+#define lv_is_cache_pool(lv)	(((lv)->status & (CACHE_POOL)) ? 1 : 0)
-+#define lv_is_cache_pool_data(lv)	(((lv)->status & (CACHE_POOL_DATA)) ? 1 : 0)
-+#define lv_is_cache_pool_metadata(lv)	(((lv)->status & (CACHE_POOL_METADATA)) ? 1 : 0)
-+#define lv_is_cache_type(lv)	(((lv)->status & (CACHE | CACHE_POOL | CACHE_POOL_DATA | CACHE_POOL_METADATA)) ? 1 : 0)
-+
- #define lv_is_virtual(lv)	(((lv)->status & VIRTUAL) ? 1 : 0)
- #define lv_is_pool_metadata_spare(lv)	(((lv)->status & POOL_METADATA_SPARE) ? 1 : 0)
- 
-@@ -384,6 +396,13 @@ struct lv_segment {
- 	struct logical_volume *pool_lv;		/* For thin */
- 	uint32_t device_id;			/* For thin, 24bit */
- 
-+	uint32_t feature_flags;			/* For cache */
-+	unsigned core_argc;			/* For cache */
-+	char **core_argv;			/* For cache */
-+	char *policy_name;			/* For cache */
-+	unsigned policy_argc;			/* For cache */
-+	char **policy_argv;			/* For cache */
-+
- 	struct logical_volume *replicator;/* For replicator-devs - link to replicator LV */
- 	struct logical_volume *rlog_lv;	/* For replicators */
- 	const char *rlog_type;		/* For replicators */
-@@ -465,6 +484,7 @@ struct lvresize_params {
- 	uint64_t poolmetadatasize;
- 	sign_t poolmetadatasign;
- 	uint32_t poolmetadataextents;
-+	int approx_alloc;
- 	percent_type_t percent;
- 
- 	enum {
-@@ -653,7 +673,8 @@ int lv_extend(struct logical_volume *lv,
- 	      uint32_t stripes, uint32_t stripe_size,
- 	      uint32_t mirrors, uint32_t region_size,
- 	      uint32_t extents, const char *thin_pool_name,
--	      struct dm_list *allocatable_pvs, alloc_policy_t alloc);
-+	      struct dm_list *allocatable_pvs, alloc_policy_t alloc,
-+	      int approx_alloc);
- 
- /* lv must be part of lv->vg->lvs */
- int lv_remove(struct logical_volume *lv);
-@@ -674,17 +695,19 @@ uint64_t extents_from_size(struct cmd_context *cmd, uint64_t size,
- 
- struct logical_volume *find_pool_lv(const struct logical_volume *lv);
- int pool_is_active(const struct logical_volume *pool_lv);
--int pool_can_resize_metadata(const struct logical_volume *pool_lv);
-+int pool_supports_external_origin(const struct lv_segment *pool_seg, const struct logical_volume *external_lv);
-+int thin_pool_feature_supported(const struct logical_volume *pool_lv, int feature);
- int update_pool_lv(struct logical_volume *lv, int activate);
- int update_profilable_pool_params(struct cmd_context *cmd, struct profile *profile,
- 				  int passed_args, int *chunk_size_calc_method,
- 				  uint32_t *chunk_size, thin_discards_t *discards,
- 				  int *zero);
--int update_pool_params(struct volume_group *vg, unsigned attr, int passed_args,
--		       uint32_t data_extents, uint32_t extent_size,
--		       int *chunk_size_calc_method, uint32_t *chunk_size,
--		       thin_discards_t *discards,
--		       uint64_t *pool_metadata_size, int *zero);
-+int update_thin_pool_params(struct volume_group *vg, unsigned attr,
-+			    int passed_args,
-+			    uint32_t data_extents, uint32_t extent_size,
-+			    int *chunk_size_calc_method, uint32_t *chunk_size,
-+			    thin_discards_t *discards,
-+			    uint64_t *pool_metadata_size, int *zero);
- int get_pool_discards(const char *str, thin_discards_t *discards);
- const char *get_pool_discards_name(thin_discards_t discards);
- struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
-@@ -729,9 +752,10 @@ static inline int is_change_activating(activation_change_t change)
- /* FIXME: refactor and reduce the size of this struct! */
- struct lvcreate_params {
- 	/* flags */
-+	int cache;
- 	int snapshot; /* snap */
- 	int thin; /* thin */
--	int create_thin_pool; /* thin */
-+	int create_pool; /* thin */
- 	int zero; /* all */
- 	int wipe_signatures; /* all */
- 	int major; /* all */
-@@ -773,6 +797,8 @@ struct lvcreate_params {
- 	uint32_t min_recovery_rate; /* RAID */
- 	uint32_t max_recovery_rate; /* RAID */
- 
-+	uint32_t feature_flags; /* cache */
-+
- 	const struct segment_type *segtype; /* all */
- 	unsigned target_attr; /* all */
- 
-@@ -786,6 +812,7 @@ struct lvcreate_params {
- 
- 	uint32_t permission; /* all */
- 	uint32_t read_ahead; /* all */
-+	int approx_alloc;     /* all */
- 	alloc_policy_t alloc; /* all */
- 
- 	struct dm_list tags;	/* all */
-@@ -806,7 +833,7 @@ struct logical_volume *lv_create_single(struct volume_group *vg,
-  */
- void lv_set_activation_skip(struct logical_volume *lv, int override_default, int add_skip_flag);
- int lv_activation_skip(struct logical_volume *lv, activation_change_t activate,
--		       int override_lv_skip_flag, int skip);
-+		       int override_lv_skip_flag);
- 
- /*
-  * Functions for layer manipulation
-@@ -996,9 +1023,20 @@ int lv_raid_reshape(struct logical_volume *lv,
- int lv_raid_replace(struct logical_volume *lv, struct dm_list *remove_pvs,
- 		    struct dm_list *allocate_pvs);
- int lv_raid_remove_missing(struct logical_volume *lv);
--
- /* --  metadata/raid_manip.c */
- 
-+/* ++  metadata/cache_manip.c */
-+int update_cache_pool_params(struct volume_group *vg, unsigned attr,
-+			     int passed_args,
-+			     uint32_t data_extents, uint32_t extent_size,
-+			     int *chunk_size_calc_method, uint32_t *chunk_size,
-+			     thin_discards_t *discards,
-+			     uint64_t *pool_metadata_size, int *zero);
-+struct logical_volume *lv_cache_create(struct logical_volume *pool,
-+				       struct logical_volume *origin);
-+int lv_cache_remove(struct logical_volume *cache_lv);
-+/* --  metadata/cache_manip.c */
-+
- struct cmd_vg *cmd_vg_add(struct dm_pool *mem, struct dm_list *cmd_vgs,
- 			  const char *vg_name, const char *vgid,
- 			  uint32_t flags);
-diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
-index 4d4778b..8643b75 100644
---- a/lib/metadata/metadata.c
-+++ b/lib/metadata/metadata.c
-@@ -856,30 +856,45 @@ int vgcreate_params_validate(struct cmd_context *cmd,
- 	return 1;
- }
- 
--static int _vg_update_vg_ondisk(struct volume_group *vg)
-+/*
-+ * Update content of precommitted VG
-+ *
-+ * TODO: Optimize in the future, since lvmetad needs similar
-+ *       config tree processing in lvmetad_vg_update().
-+ */
-+static int _vg_update_vg_precommitted(struct volume_group *vg)
- {
- 	struct dm_config_tree *cft;
--	int pool_locked;
- 
--	if (vg->vg_ondisk || is_orphan_vg(vg->name)) /* we already have it */
--		return 1;
-+	release_vg(vg->vg_precommitted);
-+	vg->vg_precommitted = NULL;
- 
--	pool_locked = dm_pool_locked(vg->vgmem);
--	if (pool_locked && !dm_pool_unlock(vg->vgmem, 0))
-+	if (!(cft = export_vg_to_config_tree(vg)))
- 		return_0;
- 
--	cft = export_vg_to_config_tree(vg);
--	if (!cft)
--		return 0;
-+	if (!(vg->vg_precommitted = import_vg_from_config_tree(cft, vg->fid)))
-+		stack;
- 
--	vg->vg_ondisk = import_vg_from_config_tree(cft, vg->fid);
- 	dm_config_destroy(cft);
- 
--	/* recompute the pool crc */
--	if (pool_locked && !dm_pool_lock(vg->vgmem, 1))
-+	return vg->vg_precommitted ? 1 : 0;
-+}
-+
-+static int _vg_update_vg_ondisk(struct volume_group *vg)
-+{
-+	if (dm_pool_locked(vg->vgmem))
-+		return 1;
-+
-+	if (vg->vg_ondisk || is_orphan_vg(vg->name)) /* we already have it */
-+		return 1;
-+
-+	if (!_vg_update_vg_precommitted(vg))
- 		return_0;
- 
--	return vg->vg_ondisk ? 1 : 0;
-+	vg->vg_ondisk = vg->vg_precommitted;
-+	vg->vg_precommitted = NULL;
-+
-+	return 1;
- }
- 
- /*
-@@ -1322,8 +1337,7 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name,
- 	/* FIXME Check partition type is LVM unless --force is given */
- 
- 	/* Is there a pv here already? */
--	if (!(pv = find_pv_by_name(cmd, name, 1, 1)))
--		stack;
-+	pv = find_pv_by_name(cmd, name, 1, 1);
- 
- 	/* Allow partial & exported VGs to be destroyed. */
- 	/* We must have -ff to overwrite a non orphan */
-@@ -1372,7 +1386,9 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name,
- 		goto bad;
- 	}
- 
--	if (!wipe_known_signatures(cmd, dev, name, 1, pp->yes, pp->force)) {
-+	if (!wipe_known_signatures(cmd, dev, name,
-+				   TYPE_LVM1_MEMBER | TYPE_LVM2_MEMBER,
-+				   0, pp->yes, pp->force)) {
- 		log_error("Aborting pvcreate on %s.", name);
- 		goto bad;
- 	}
-@@ -2686,6 +2702,9 @@ int vg_write(struct volume_group *vg)
- 	if (!(vg->fid->fmt->features & FMT_PRECOMMIT) && !lvmetad_vg_update(vg))
- 		return_0;
- 
-+	if (!_vg_update_vg_precommitted(vg)) /* prepare precommited */
-+		return_0;
-+
- 	return 1;
- }
- 
-@@ -2752,9 +2771,8 @@ int vg_commit(struct volume_group *vg)
- 
- 		/* This *is* the original now that it's commited. */
- 		release_vg(vg->vg_ondisk);
--		vg->vg_ondisk = NULL;
--		if (!_vg_update_vg_ondisk(vg)) /* make a new one for future edits */
--			return_0;
-+		vg->vg_ondisk = vg->vg_precommitted;
-+		vg->vg_precommitted = NULL;
- 	}
- 
- 	/* If update failed, remove any cached precommitted metadata. */
-@@ -2771,6 +2789,9 @@ void vg_revert(struct volume_group *vg)
- {
- 	struct metadata_area *mda;
- 
-+	release_vg(vg->vg_precommitted);  /* VG is no longer needed */
-+	vg->vg_precommitted = NULL;
-+
- 	dm_list_iterate_items(mda, &vg->fid->metadata_areas_in_use) {
- 		if (mda->ops->vg_revert &&
- 		    !mda->ops->vg_revert(vg->fid, vg, mda)) {
-@@ -4653,7 +4674,7 @@ int pv_change_metadataignore(struct physical_volume *pv, uint32_t mda_ignored)
- 	return 1;
- }
- 
--char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tags)
-+char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tagsl)
- {
- 	struct str_list *sl;
- 
-@@ -4662,9 +4683,9 @@ char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tags)
- 		return NULL;
- 	}
- 
--	dm_list_iterate_items(sl, tags) {
-+	dm_list_iterate_items(sl, tagsl) {
- 		if (!dm_pool_grow_object(mem, sl->str, strlen(sl->str)) ||
--		    (sl->list.n != tags && !dm_pool_grow_object(mem, ",", 1))) {
-+		    (sl->list.n != tagsl && !dm_pool_grow_object(mem, ",", 1))) {
- 			log_error("dm_pool_grow_object failed");
- 			return NULL;
- 		}
-diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
-index fef4b3f..83959bb 100644
---- a/lib/metadata/metadata.h
-+++ b/lib/metadata/metadata.h
-@@ -488,6 +488,6 @@ int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
- 		 struct physical_volume *pv, struct pvcreate_params *pp);
- 
- uint64_t find_min_mda_size(struct dm_list *mdas);
--char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tags);
-+char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tagsl);
- 
- #endif
-diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
-index 18917d3..86ec4ca 100644
---- a/lib/metadata/mirror.c
-+++ b/lib/metadata/mirror.c
-@@ -279,7 +279,7 @@ static int _write_log_header(struct cmd_context *cmd, struct logical_volume *lv)
-  */
- static int _init_mirror_log(struct cmd_context *cmd,
- 			    struct logical_volume *log_lv, int in_sync,
--			    struct dm_list *tags, int remove_on_failure)
-+			    struct dm_list *tagsl, int remove_on_failure)
- {
- 	struct str_list *sl;
- 	uint64_t orig_status = log_lv->status;
-@@ -315,7 +315,7 @@ static int _init_mirror_log(struct cmd_context *cmd,
- 	lv_set_visible(log_lv);
- 
- 	/* Temporary tag mirror log for activation */
--	dm_list_iterate_items(sl, tags)
-+	dm_list_iterate_items(sl, tagsl)
- 		if (!str_list_add(cmd->mem, &log_lv->tags, sl->str)) {
- 			log_error("Aborting. Unable to tag mirror log.");
- 			goto activate_lv;
-@@ -336,7 +336,7 @@ static int _init_mirror_log(struct cmd_context *cmd,
- 	}
- 
- 	/* Remove the temporary tags */
--	dm_list_iterate_items(sl, tags)
-+	dm_list_iterate_items(sl, tagsl)
- 		str_list_del(&log_lv->tags, sl->str);
- 
- 	if (activation()) {
-@@ -376,7 +376,7 @@ deactivate_and_revert_new_lv:
- revert_new_lv:
- 	log_lv->status = orig_status;
- 
--	dm_list_iterate_items(sl, tags)
-+	dm_list_iterate_items(sl, tagsl)
- 		str_list_del(&log_lv->tags, sl->str);
- 
- 	if (remove_on_failure && !lv_remove(log_lv)) {
-@@ -1676,7 +1676,7 @@ int add_mirrors_to_segments(struct cmd_context *cmd, struct logical_volume *lv,
- 							   region_size);
- 
- 	if (!(ah = allocate_extents(lv->vg, NULL, segtype, 1, mirrors, 0, 0,
--				    lv->le_count, allocatable_pvs, alloc,
-+				    lv->le_count, allocatable_pvs, alloc, 0,
- 				    parallel_areas))) {
- 		log_error("Unable to allocate mirror extents for %s.", lv->name);
- 		return 0;
-@@ -1944,7 +1944,7 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
- 	ah = allocate_extents(lv->vg, NULL, segtype,
- 			      0, 0, log_count - old_log_count, region_size,
- 			      lv->le_count, allocatable_pvs,
--			      alloc, parallel_areas);
-+			      alloc, 0, parallel_areas);
- 	if (!ah) {
- 		log_error("Unable to allocate extents for mirror log.");
- 		return 0;
-@@ -2008,7 +2008,7 @@ int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
- 
- 	ah = allocate_extents(lv->vg, NULL, segtype,
- 			      stripes, mirrors, log_count, region_size, lv->le_count,
--			      allocatable_pvs, alloc, parallel_areas);
-+			      allocatable_pvs, alloc, 0, parallel_areas);
- 	if (!ah) {
- 		log_error("Unable to allocate extents for mirror(s).");
- 		return 0;
-diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
-new file mode 100644
-index 0000000..0c7bf96
---- /dev/null
-+++ b/lib/metadata/pool_manip.c
-@@ -0,0 +1,325 @@
-+/*
-+ * Copyright (C) 2013-2014 Red Hat, Inc. All rights reserved.
-+ *
-+ * This file is part of LVM2.
-+ *
-+ * This copyrighted material is made available to anyone wishing to use,
-+ * modify, copy, or redistribute it subject to the terms and conditions
-+ * of the GNU Lesser General Public License v.2.1.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public License
-+ * along with this program; if not, write to the Free Software Foundation,
-+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+/*
-+ * This file holds common pool functions.
-+ */
-+
-+#include "lib.h"
-+#include "activate.h"
-+#include "locking.h"
-+#include "metadata.h"
-+#include "segtype.h"
-+#include "lv_alloc.h"
-+#include "defaults.h"
-+
-+int attach_pool_metadata_lv(struct lv_segment *pool_seg,
-+			    struct logical_volume *metadata_lv)
-+{
-+	if (!seg_is_thin_pool(pool_seg) && !seg_is_cache_pool(pool_seg)) {
-+		log_error(INTERNAL_ERROR
-+			  "Unable to attach pool metadata LV to %s segtype.",
-+			  pool_seg->segtype->ops->name(pool_seg));
-+		return 0;
-+	}
-+	pool_seg->metadata_lv = metadata_lv;
-+	metadata_lv->status |= seg_is_thin_pool(pool_seg) ?
-+		THIN_POOL_METADATA : CACHE_POOL_METADATA;
-+	lv_set_hidden(metadata_lv);
-+
-+	return add_seg_to_segs_using_this_lv(metadata_lv, pool_seg);
-+}
-+
-+int attach_pool_data_lv(struct lv_segment *pool_seg,
-+			struct logical_volume *pool_data_lv)
-+{
-+	if (!seg_is_thin_pool(pool_seg) && !seg_is_cache_pool(pool_seg)) {
-+		log_error(INTERNAL_ERROR
-+			  "Unable to attach pool data LV to %s segtype.",
-+			  pool_seg->segtype->ops->name(pool_seg));
-+		return 0;
-+	}
-+
-+	if (!set_lv_segment_area_lv(pool_seg, 0, pool_data_lv,
-+				    0, seg_is_thin_pool(pool_seg) ?
-+				    THIN_POOL_DATA : CACHE_POOL_DATA))
-+		return_0;
-+
-+	pool_seg->lv->status |= seg_is_thin_pool(pool_seg) ?
-+		THIN_POOL : CACHE_POOL;
-+	lv_set_hidden(pool_data_lv);
-+
-+	return 1;
-+}
-+
-+int attach_pool_lv(struct lv_segment *seg,
-+		   struct logical_volume *pool_lv,
-+		   struct logical_volume *origin,
-+		   struct logical_volume *merge_lv)
-+{
-+	if (!seg_is_thin_volume(seg) && !seg_is_cache(seg)) {
-+		log_error(INTERNAL_ERROR "Unable to attach pool to %s/%s"
-+			  " that is not cache or thin volume.",
-+			  pool_lv->vg->name, seg->lv->name);
-+		return 0;
-+	}
-+
-+	seg->pool_lv = pool_lv;
-+	seg->origin = origin;
-+	seg->lv->status |= seg_is_cache(seg) ? CACHE : THIN_VOLUME;
-+
-+	if (origin && !add_seg_to_segs_using_this_lv(origin, seg))
-+		return_0;
-+
-+	if (!add_seg_to_segs_using_this_lv(pool_lv, seg))
-+		return_0;
-+
-+	if (merge_lv) {
-+		if (origin != merge_lv) {
-+			if (!add_seg_to_segs_using_this_lv(merge_lv, seg))
-+				return_0;
-+		}
-+
-+		init_snapshot_merge(seg, merge_lv);
-+	}
-+
-+	return 1;
-+}
-+
-+int detach_pool_lv(struct lv_segment *seg)
-+{
-+	struct lv_thin_message *tmsg, *tmp;
-+	struct seg_list *sl, *tsl;
-+	int no_update = 0;
-+
-+	if (!seg->pool_lv) {
-+		log_error(INTERNAL_ERROR
-+			  "No pool associated with %s LV, %s.",
-+			  seg->segtype->ops->name(seg), seg->lv->name);
-+		return 0;
-+	}
-+
-+	if (seg_is_cache(seg)) {
-+		if (!remove_seg_from_segs_using_this_lv(seg->pool_lv, seg))
-+			return_0;
-+		seg->pool_lv = NULL;
-+		return 1;
-+	}
-+
-+	if (!lv_is_thin_pool(seg->pool_lv)) {
-+		log_error(INTERNAL_ERROR
-+			  "Cannot detach pool from LV %s.",
-+			  seg->lv->name);
-+		return 0;
-+	}
-+
-+	/* Drop any message referencing removed segment */
-+	dm_list_iterate_items_safe(tmsg, tmp, &(first_seg(seg->pool_lv)->thin_messages)) {
-+		switch (tmsg->type) {
-+		case DM_THIN_MESSAGE_CREATE_SNAP:
-+		case DM_THIN_MESSAGE_CREATE_THIN:
-+			if (tmsg->u.lv == seg->lv) {
-+				log_debug_metadata("Discarding message for LV %s.",
-+						   tmsg->u.lv->name);
-+				dm_list_del(&tmsg->list);
-+				no_update = 1; /* Replacing existing */
-+			}
-+			break;
-+		case DM_THIN_MESSAGE_DELETE:
-+			if (tmsg->u.delete_id == seg->device_id) {
-+				log_error(INTERNAL_ERROR "Trying to delete %u again.",
-+					  tmsg->u.delete_id);
-+				return 0;
-+			}
-+			break;
-+		default:
-+			log_error(INTERNAL_ERROR "Unsupported message type %u.", tmsg->type);
-+			break;
-+		}
-+	}
-+
-+	if (!detach_thin_external_origin(seg))
-+		return_0;
-+
-+	if (!attach_pool_message(first_seg(seg->pool_lv),
-+				 DM_THIN_MESSAGE_DELETE,
-+				 NULL, seg->device_id, no_update))
-+		return_0;
-+
-+	if (!remove_seg_from_segs_using_this_lv(seg->pool_lv, seg))
-+		return_0;
-+
-+	if (seg->origin &&
-+	    !remove_seg_from_segs_using_this_lv(seg->origin, seg))
-+		return_0;
-+
-+	/* If thin origin, remove it from related thin snapshots */
-+	/*
-+	 * TODO: map removal of origin as snapshot lvconvert --merge?
-+	 * i.e. rename thin snapshot to origin thin origin
-+	 */
-+	dm_list_iterate_items_safe(sl, tsl, &seg->lv->segs_using_this_lv) {
-+		if (!seg_is_thin_volume(sl->seg) ||
-+		    (seg->lv != sl->seg->origin))
-+			continue;
-+
-+		if (!remove_seg_from_segs_using_this_lv(seg->lv, sl->seg))
-+			return_0;
-+		/* Thin snapshot is now regular thin volume */
-+		sl->seg->origin = NULL;
-+	}
-+
-+	seg->lv->status &= ~THIN_VOLUME;
-+	seg->pool_lv = NULL;
-+	seg->origin = NULL;
-+
-+	return 1;
-+}
-+
-+struct lv_segment *find_pool_seg(const struct lv_segment *seg)
-+{
-+	struct lv_segment *pool_seg;
-+
-+	pool_seg = get_only_segment_using_this_lv(seg->lv);
-+
-+	if (!pool_seg) {
-+		log_error("Failed to find pool_seg for %s", seg->lv->name);
-+		return NULL;
-+	}
-+
-+	if ((lv_is_thin_type(seg->lv) && !seg_is_thin_pool(pool_seg)) &&
-+	    !seg_is_cache_pool(pool_seg)) {
-+		log_error("%s on %s is not a %s pool segment",
-+			  pool_seg->lv->name, seg->lv->name,
-+			  lv_is_thin_type(seg->lv) ? "thin" : "cache");
-+		return NULL;
-+	}
-+
-+	return pool_seg;
-+}
-+
-+int create_pool(struct logical_volume *pool_lv,
-+		const struct segment_type *segtype,
-+		struct alloc_handle *ah, uint32_t stripes, uint32_t stripe_size)
-+{
-+	const struct segment_type *striped;
-+	struct logical_volume *meta_lv, *data_lv;
-+	struct lv_segment *seg;
-+	char name[NAME_LEN];
-+
-+	if (pool_lv->le_count) {
-+		log_error(INTERNAL_ERROR "Pool %s already has extents.",
-+			  pool_lv->name);
-+		return 0;
-+	}
-+
-+	/* LV is not yet a pool, so it's extension from lvcreate */
-+	if (!(striped = get_segtype_from_string(pool_lv->vg->cmd, "striped")))
-+		return_0;
-+
-+	if (activation() && segtype->ops->target_present &&
-+	    !segtype->ops->target_present(pool_lv->vg->cmd, NULL, NULL)) {
-+		log_error("%s: Required device-mapper target(s) not "
-+			  "detected in your kernel.", segtype->name);
-+		return 0;
-+	}
-+
-+	/* Metadata segment */
-+	if (!lv_add_segment(ah, stripes, 1, pool_lv, striped, 1, 0, 0))
-+		return_0;
-+
-+	if (!activation())
-+		log_warn("WARNING: Pool %s is created without initialization.",
-+			 pool_lv->name);
-+	else {
-+		if (!vg_write(pool_lv->vg) || !vg_commit(pool_lv->vg))
-+			return_0;
-+
-+		/*
-+		 * If killed here, only the VISIBLE striped pool LV is left
-+		 * and user could easily remove it.
-+		 *
-+		 * FIXME: implement lazy clearing when activation is disabled
-+		 */
-+		/*
-+		 * pool_lv is a new LV so the VG lock protects us
-+		 * Pass in LV_TEMPORARY flag, since device is activated purely for wipe
-+		 * and later it is either deactivated (in cluster)
-+		 * or directly converted to invisible device via suspend/resume
-+		 */
-+		pool_lv->status |= LV_TEMPORARY;
-+		if (!activate_lv_local(pool_lv->vg->cmd, pool_lv) ||
-+		    /* Clear 4KB of metadata device for new thin-pool. */
-+		    !wipe_lv(pool_lv, (struct wipe_params) { .do_zero = 1 })) {
-+			log_error("Aborting. Failed to wipe pool metadata %s.",
-+				  pool_lv->name);
-+			goto bad;
-+		}
-+		pool_lv->status &= ~LV_TEMPORARY;
-+	}
-+
-+	if (dm_snprintf(name, sizeof(name), "%s_%s", pool_lv->name,
-+			(segtype_is_cache_pool(segtype)) ?
-+			"cmeta" : "tmeta") < 0) {
-+		log_error("Name is too long to be a pool name.");
-+		goto bad;
-+	}
-+
-+	if (!(meta_lv = lv_create_empty(name, NULL, LVM_READ | LVM_WRITE,
-+					ALLOC_INHERIT, pool_lv->vg)))
-+		goto_bad;
-+
-+	if (!move_lv_segments(meta_lv, pool_lv, 0, 0))
-+		goto_bad;
-+
-+	/* Pool data segment */
-+	if (!lv_add_segment(ah, 0, stripes, pool_lv, striped, stripe_size, 0, 0))
-+		goto_bad;
-+
-+	if (!(data_lv = insert_layer_for_lv(pool_lv->vg->cmd, pool_lv,
-+					    pool_lv->status,
-+					    (segtype_is_cache_pool(segtype)) ?
-+					    "_cdata" : "_tdata")))
-+		goto_bad;
-+
-+	seg = first_seg(pool_lv);
-+	/* Drop reference as attach_pool_data_lv() takes it again */
-+	if (!remove_seg_from_segs_using_this_lv(data_lv, seg))
-+		goto_bad;
-+
-+	seg->segtype = segtype; /* Set as thin_pool or cache_pool segment */
-+
-+	if (!attach_pool_data_lv(seg, data_lv))
-+		goto_bad;
-+
-+	if (!attach_pool_metadata_lv(seg, meta_lv))
-+		goto_bad;
-+
-+	return 1;
-+
-+bad:
-+	if (activation()) {
-+		if (deactivate_lv_local(pool_lv->vg->cmd, pool_lv)) {
-+			log_error("Aborting. Could not deactivate pool %s.",
-+				  pool_lv->name);
-+			return 0;
-+		}
-+		if (!lv_remove(pool_lv) ||
-+		    !vg_write(pool_lv->vg) || !vg_commit(pool_lv->vg))
-+			log_error("Manual intervention may be required to "
-+				  "remove abandoned LV(s) before retrying.");
-+	}
-+
-+	return 0;
-+}
-diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
-index a29ea85..d1759ae 100644
---- a/lib/metadata/raid_manip.c
-+++ b/lib/metadata/raid_manip.c
-@@ -174,11 +174,13 @@ static int _clear_lv(struct logical_volume *lv)
- 	if (test_mode())
- 		return 1;
- 
--	if (!was_active && !activate_lv_excl_local(lv->vg->cmd, lv)) {
--		log_error("Failed to activate %s for clearing",
-+	lv->status |= LV_TEMPORARY;
-+	if (!was_active && !activate_lv_local(lv->vg->cmd, lv)) {
-+		log_error("Failed to activate localy %s for clearing",
- 			  lv->name);
- 		return 0;
- 	}
-+	lv->status &= ~LV_TEMPORARY;
- 
- 	log_verbose("Clearing metadata area of %s/%s",
- 		    lv->vg->name, lv->name);
-@@ -417,7 +419,7 @@ static int _alloc_image_components(struct logical_volume *lv,
- 
- 	if (!(ah = allocate_extents(lv->vg, NULL, segtype, 0, count, count,
- 				    region_size, extents, pvs,
--				    lv->alloc, parallel_areas)))
-+				    lv->alloc, 0, parallel_areas)))
- 		return_0;
- 
- 	for (s = 0; s < count; s++) {
-@@ -481,7 +483,7 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
- 	if (!(ah = allocate_extents(data_lv->vg, NULL, seg->segtype, 0, 1, 0,
- 				    seg->region_size,
- 				    1 /*RAID_METADATA_AREA_LEN*/,
--				    &allocatable_pvs, data_lv->alloc, NULL)))
-+				    &allocatable_pvs, data_lv->alloc, 0, NULL)))
- 		return_0;
- 
- 	if (!_alloc_image_component(data_lv, base_name, ah, 0,
-diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
-index 2c02d1b..75429b4 100644
---- a/lib/metadata/segtype.h
-+++ b/lib/metadata/segtype.h
-@@ -41,8 +41,12 @@ struct dev_manager;
- #define SEG_RAID		0x00000400U
- #define SEG_THIN_POOL		0x00000800U
- #define SEG_THIN_VOLUME		0x00001000U
-+#define SEG_CACHE		0x00002000U
-+#define SEG_CACHE_POOL		0x00004000U
- #define SEG_UNKNOWN		0x80000000U
- 
-+#define segtype_is_cache(segtype)	((segtype)->flags & SEG_CACHE ? 1 : 0)
-+#define segtype_is_cache_pool(segtype)	((segtype)->flags & SEG_CACHE_POOL ? 1 : 0)
- #define segtype_is_mirrored(segtype)	((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
- #define segtype_is_raid(segtype)	((segtype)->flags & SEG_RAID ? 1 : 0)
- #define segtype_is_striped(segtype)	((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
-@@ -51,6 +55,8 @@ struct dev_manager;
- #define segtype_is_thin_volume(segtype)	((segtype)->flags & SEG_THIN_VOLUME ? 1 : 0)
- #define segtype_is_virtual(segtype)	((segtype)->flags & SEG_VIRTUAL ? 1 : 0)
- 
-+#define seg_is_cache(seg)	segtype_is_cache((seg)->segtype)
-+#define seg_is_cache_pool(seg)	segtype_is_cache_pool((seg)->segtype)
- #define seg_is_linear(seg)	(seg_is_striped(seg) && ((seg)->area_count == 1))
- #define seg_is_mirrored(seg)	segtype_is_mirrored((seg)->segtype)
- #define seg_is_raid(seg)	segtype_is_raid((seg)->segtype)
-@@ -147,6 +153,10 @@ int init_replicator_segtype(struct cmd_context *cmd, struct segtype_library *seg
- int init_thin_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
- #endif
- 
-+#ifdef CACHE_INTERNAL
-+int init_cache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
-+#endif
-+
- #ifdef SNAPSHOT_INTERNAL
- struct segment_type *init_snapshot_segtype(struct cmd_context *cmd);
- #endif
-diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c
-index e563a78..25fee76 100644
---- a/lib/metadata/snapshot_manip.c
-+++ b/lib/metadata/snapshot_manip.c
-@@ -15,6 +15,7 @@
- 
- #include "lib.h"
- #include "metadata.h"
-+#include "segtype.h"
- #include "locking.h"
- #include "toolcontext.h"
- #include "lv_alloc.h"
-@@ -31,7 +32,26 @@ int lv_is_cow(const struct logical_volume *lv)
- 	return (!lv_is_thin_volume(lv) && !lv_is_origin(lv) && lv->snapshot) ? 1 : 0;
- }
- 
--static uint64_t _cow_max_size(uint64_t origin_size, uint32_t chunk_size)
-+/*
-+ * Some kernels have a bug that they may leak space in the snapshot on crash.
-+ * If the kernel is buggy, we add some extra space.
-+ */
-+static uint64_t _cow_extra_chunks(struct cmd_context *cmd, uint64_t n_chunks)
-+{
-+	const struct segment_type *segtype;
-+	unsigned attrs;
-+
-+	if (activation() &&
-+	    (segtype = get_segtype_from_string(cmd, "snapshot")) &&
-+	    segtype->ops->target_present &&
-+	    segtype->ops->target_present(cmd, NULL, &attrs) &&
-+	    (attrs & SNAPSHOT_FEATURE_FIXED_LEAK))
-+		return (n_chunks + 63) / 64;
-+
-+	return 0;
-+}
-+
-+static uint64_t _cow_max_size(struct cmd_context *cmd, uint64_t origin_size, uint32_t chunk_size)
- {
- 	/* Snapshot disk layout:
- 	 *    COW is divided into chunks
-@@ -40,21 +60,22 @@ static uint64_t _cow_max_size(uint64_t origin_size, uint32_t chunk_size)
- 	 *        3rd. chunk is the 1st. data chunk
- 	 */
- 
--	/* Size of metadata for snapshot in sectors */
--	uint64_t mdata_size = ((origin_size + chunk_size - 1) / chunk_size * 16 + 511) >> SECTOR_SHIFT;
-+	uint64_t origin_chunks = (origin_size + chunk_size - 1) / chunk_size;
-+	uint64_t chunks_per_metadata_area = (uint64_t)chunk_size << (SECTOR_SHIFT - 4);
- 
--	/* Sum all chunks - header + metadata size + origin size (aligned on chunk boundary) */
--	uint64_t size = chunk_size +
--		((mdata_size + chunk_size - 1) & ~(uint64_t)(chunk_size - 1)) +
--		((origin_size + chunk_size - 1) & ~(uint64_t)(chunk_size - 1));
-+	/*
-+	 * Note: if origin_chunks is divisible by chunks_per_metadata_area, we
-+	 * need one extra metadata chunk as a terminator.
-+	 */
-+	uint64_t metadata_chunks = (origin_chunks + chunks_per_metadata_area) / chunks_per_metadata_area;
-+	uint64_t n_chunks = 1 + origin_chunks + metadata_chunks;
- 
--	/* Does not overflow since size is in sectors (9 bits) */
--	return size;
-+	return (n_chunks + _cow_extra_chunks(cmd, n_chunks)) * chunk_size;
- }
- 
- uint32_t cow_max_extents(const struct logical_volume *origin, uint32_t chunk_size)
- {
--	uint64_t size = _cow_max_size(origin->size, chunk_size);
-+	uint64_t size = _cow_max_size(origin->vg->cmd, origin->size, chunk_size);
- 	uint32_t extent_size = origin->vg->extent_size;
- 	uint64_t max_size = (uint64_t) MAX_EXTENT_COUNT * extent_size;
- 
-@@ -70,7 +91,8 @@ uint32_t cow_max_extents(const struct logical_volume *origin, uint32_t chunk_siz
- int lv_is_cow_covering_origin(const struct logical_volume *lv)
- {
- 	return lv_is_cow(lv) &&
--		(lv->size >= _cow_max_size(origin_from_cow(lv)->size, find_snapshot(lv)->chunk_size));
-+		(lv->size >= _cow_max_size(lv->vg->cmd, origin_from_cow(lv)->size,
-+					   find_snapshot(lv)->chunk_size));
- }
- 
- int lv_is_visible(const struct logical_volume *lv)
-@@ -151,7 +173,7 @@ void init_snapshot_merge(struct lv_segment *snap_seg,
- 	origin->snapshot = snap_seg;
- 	origin->status |= MERGING;
- 
--	if (lv_is_thin_volume(origin)) {
-+	if (seg_is_thin_volume(snap_seg)) {
- 		snap_seg->merge_lv = origin;
- 		/* Making thin LV inivisible with regular log */
- 		lv_set_hidden(snap_seg->lv);
-diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
-index e12a8ad..b28f5a0 100644
---- a/lib/metadata/thin_manip.c
-+++ b/lib/metadata/thin_manip.c
-@@ -17,19 +17,9 @@
- #include "locking.h"
- #include "metadata.h"
- #include "segtype.h"
--#include "lv_alloc.h"
- #include "defaults.h"
- #include "display.h"
- 
--int attach_pool_metadata_lv(struct lv_segment *pool_seg, struct logical_volume *metadata_lv)
--{
--	pool_seg->metadata_lv = metadata_lv;
--	metadata_lv->status |= THIN_POOL_METADATA;
--	lv_set_hidden(metadata_lv);
--
--	return add_seg_to_segs_using_this_lv(metadata_lv, pool_seg);
--}
--
- int detach_pool_metadata_lv(struct lv_segment *pool_seg, struct logical_volume **metadata_lv)
- {
- 	struct logical_volume *lv = pool_seg->metadata_lv;
-@@ -48,117 +38,6 @@ int detach_pool_metadata_lv(struct lv_segment *pool_seg, struct logical_volume *
- 	return 1;
- }
- 
--int attach_pool_data_lv(struct lv_segment *pool_seg, struct logical_volume *pool_data_lv)
--{
--	if (!set_lv_segment_area_lv(pool_seg, 0, pool_data_lv, 0, THIN_POOL_DATA))
--		return_0;
--
--	pool_seg->lv->status |= THIN_POOL;
--	lv_set_hidden(pool_data_lv);
--
--	return 1;
--}
--
--int attach_pool_lv(struct lv_segment *seg, struct logical_volume *pool_lv,
--		   struct logical_volume *origin, struct logical_volume *merge_lv)
--{
--	seg->pool_lv = pool_lv;
--	seg->lv->status |= THIN_VOLUME;
--	seg->origin = origin;
--
--	if (origin && !add_seg_to_segs_using_this_lv(origin, seg))
--		return_0;
--
--	if (!add_seg_to_segs_using_this_lv(pool_lv, seg))
--		return_0;
--
--	if (merge_lv) {
--		if (origin != merge_lv) {
--			if (!add_seg_to_segs_using_this_lv(merge_lv, seg))
--				return_0;
--		}
--
--		init_snapshot_merge(seg, merge_lv);
--	}
--
--	return 1;
--}
--
--int detach_pool_lv(struct lv_segment *seg)
--{
--	struct lv_thin_message *tmsg, *tmp;
--	struct seg_list *sl, *tsl;
--	int no_update = 0;
--
--	if (!seg->pool_lv || !lv_is_thin_pool(seg->pool_lv)) {
--		log_error(INTERNAL_ERROR "Cannot detach pool from non-thin LV %s",
--			  seg->lv->name);
--		return 0;
--	}
--
--	/* Drop any message referencing removed segment */
--	dm_list_iterate_items_safe(tmsg, tmp, &(first_seg(seg->pool_lv)->thin_messages)) {
--		switch (tmsg->type) {
--		case DM_THIN_MESSAGE_CREATE_SNAP:
--		case DM_THIN_MESSAGE_CREATE_THIN:
--			if (tmsg->u.lv == seg->lv) {
--				log_debug_metadata("Discarding message for LV %s.",
--						   tmsg->u.lv->name);
--				dm_list_del(&tmsg->list);
--				no_update = 1; /* Replacing existing */
--			}
--			break;
--		case DM_THIN_MESSAGE_DELETE:
--			if (tmsg->u.delete_id == seg->device_id) {
--				log_error(INTERNAL_ERROR "Trying to delete %u again.",
--					  tmsg->u.delete_id);
--				return 0;
--			}
--			break;
--		default:
--			log_error(INTERNAL_ERROR "Unsupported message type %u.", tmsg->type);
--			break;
--		}
--	}
--
--	if (!detach_thin_external_origin(seg))
--		return_0;
--
--	if (!attach_pool_message(first_seg(seg->pool_lv),
--				 DM_THIN_MESSAGE_DELETE,
--				 NULL, seg->device_id, no_update))
--		return_0;
--
--	if (!remove_seg_from_segs_using_this_lv(seg->pool_lv, seg))
--		return_0;
--
--	if (seg->origin &&
--	    !remove_seg_from_segs_using_this_lv(seg->origin, seg))
--		return_0;
--
--	/* If thin origin, remove it from related thin snapshots */
--	/*
--	 * TODO: map removal of origin as snapshot lvconvert --merge?
--	 * i.e. rename thin snapshot to origin thin origin
--	 */
--	dm_list_iterate_items_safe(sl, tsl, &seg->lv->segs_using_this_lv) {
--		if (!seg_is_thin_volume(sl->seg) ||
--		    (seg->lv != sl->seg->origin))
--			continue;
--
--		if (!remove_seg_from_segs_using_this_lv(seg->lv, sl->seg))
--			return_0;
--		/* Thin snapshot is now regular thin volume */
--		sl->seg->origin = NULL;
--	}
--
--	seg->lv->status &= ~THIN_VOLUME;
--	seg->pool_lv = NULL;
--	seg->origin = NULL;
--
--	return 1;
--}
--
- int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type,
- 			struct logical_volume *lv, uint32_t delete_id,
- 			int no_update)
-@@ -206,9 +85,9 @@ int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type,
- 
- 	dm_list_add(&pool_seg->thin_messages, &tmsg->list);
- 
--	log_debug_metadata("Added %s message",
-+	log_debug_metadata("Added %s message.",
- 			   (type == DM_THIN_MESSAGE_CREATE_SNAP ||
--			   type == DM_THIN_MESSAGE_CREATE_THIN) ? "create" :
-+			    type == DM_THIN_MESSAGE_CREATE_THIN) ? "create" :
- 			   (type == DM_THIN_MESSAGE_DELETE) ? "delete" : "unknown");
- 
- 	return 1;
-@@ -261,7 +140,9 @@ int detach_thin_external_origin(struct lv_segment *seg)
- 
- int lv_is_merging_thin_snapshot(const struct logical_volume *lv)
- {
--	return (first_seg(lv)->status & MERGING) ? 1 : 0;
-+	struct lv_segment *seg = first_seg(lv);
-+
-+	return (seg && seg->status & MERGING) ? 1 : 0;
- }
- 
- /*
-@@ -326,7 +207,7 @@ int pool_is_active(const struct logical_volume *lv)
- 	return 0;
- }
- 
--int pool_can_resize_metadata(const struct logical_volume *lv)
-+int thin_pool_feature_supported(const struct logical_volume *lv, int feature)
- {
- 	static unsigned attr = 0U;
- 	struct lv_segment *seg;
-@@ -345,7 +226,7 @@ int pool_can_resize_metadata(const struct logical_volume *lv)
- 		return 0;
- 	}
- 
--	return (attr & THIN_FEATURE_METADATA_RESIZE) ? 1 : 0;
-+	return (attr & feature) ? 1 : 0;
- }
- 
- int pool_below_threshold(const struct lv_segment *pool_seg)
-@@ -360,36 +241,37 @@ int pool_below_threshold(const struct lv_segment *pool_seg)
- 		return_0;
- 
- 	if (percent >= threshold)
--		return_0;
-+		return 0;
- 
- 	/* Metadata */
- 	if (!lv_thin_pool_percent(pool_seg->lv, 1, &percent))
- 		return_0;
- 
- 	if (percent >= threshold)
--		return_0;
-+		return 0;
- 
- 	return 1;
- }
- 
--struct lv_segment *find_pool_seg(const struct lv_segment *seg)
-+/*
-+ * Validate given external origin could be used with thin pool
-+ */
-+int pool_supports_external_origin(const struct lv_segment *pool_seg, const struct logical_volume *external_lv)
- {
--	struct lv_segment *pool_seg;
--
--	pool_seg = get_only_segment_using_this_lv(seg->lv);
--
--	if (!pool_seg) {
--		log_error("Failed to find pool_seg for %s", seg->lv->name);
--		return NULL;
--	}
--
--	if (!seg_is_thin_pool(pool_seg)) {
--		log_error("%s on %s is not a pool segment",
--			  pool_seg->lv->name, seg->lv->name);
--		return NULL;
-+	uint32_t csize = pool_seg->chunk_size;
-+
-+	if ((external_lv->size < csize) || (external_lv->size % csize)) {
-+		/* TODO: Validate with thin feature flag once, it will be supported */
-+		log_error("Can't use \"%s/%s\" as external origin with \"%s/%s\" pool. "
-+			  "Size %s is not a multiple of pool's chunk size %s.",
-+			  external_lv->vg->name, external_lv->name,
-+			  pool_seg->lv->vg->name, pool_seg->lv->name,
-+			  display_size(external_lv->vg->cmd, external_lv->size),
-+			  display_size(external_lv->vg->cmd, csize));
-+		return 0;
- 	}
- 
--	return pool_seg;
-+	return 1;
- }
- 
- struct logical_volume *find_pool_lv(const struct logical_volume *lv)
-@@ -443,107 +325,6 @@ uint32_t get_free_pool_device_id(struct lv_segment *thin_pool_seg)
- 	return max_id;
- }
- 
--int create_pool(struct logical_volume *pool_lv, const struct segment_type *segtype,
--		struct alloc_handle *ah, uint32_t stripes, uint32_t stripe_size)
--{
--	const struct segment_type *striped;
--	struct logical_volume *meta_lv, *data_lv;
--	struct lv_segment *seg;
--	char name[NAME_LEN];
--
--	if (pool_lv->le_count) {
--		/* FIXME move code for manipulation from lv_manip.c */
--		log_error(INTERNAL_ERROR "Pool %s has already extents.", pool_lv->name);
--		return 0;
--	}
--
--	/* LV is not yet a pool, so it's extension from lvcreate */
--	if (!(striped = get_segtype_from_string(pool_lv->vg->cmd, "striped")))
--		return_0;
--
--	if (activation() && segtype->ops->target_present &&
--	    !segtype->ops->target_present(pool_lv->vg->cmd, NULL, NULL)) {
--		log_error("%s: Required device-mapper target(s) not "
--			  "detected in your kernel.", segtype->name);
--		return 0;
--	}
--
--	/* Metadata segment */
--	if (!lv_add_segment(ah, stripes, 1, pool_lv, striped, 1, 0, 0))
--		return_0;
--
--	if (!activation())
--		log_warn("WARNING: Pool %s is created without initialization.", pool_lv->name);
--	else {
--		if (!vg_write(pool_lv->vg) || !vg_commit(pool_lv->vg))
--			return_0;
--
--		/*
--		 * If killed here, only the VISIBLE striped pool LV is left
--		 * and user could easily remove it.
--		 *
--		 * FIXME: implement lazy clearing when activation is disabled
--		 */
--		/* pool_lv is a new LV so the VG lock protects us */
--		if (!activate_lv_local(pool_lv->vg->cmd, pool_lv) ||
--		    /* Clear 4KB of metadata device for new thin-pool. */
--		    !wipe_lv(pool_lv, (struct wipe_params) { .do_zero = 1 })) {
--			log_error("Aborting. Failed to wipe pool metadata %s.",
--				  pool_lv->name);
--			goto bad;
--		}
--	}
--
--	if (dm_snprintf(name, sizeof(name), "%s_tmeta", pool_lv->name) < 0) {
--		log_error("Name is too long to be a pool name.");
--		goto bad;
--	}
--
--	if (!(meta_lv = lv_create_empty(name, NULL, LVM_READ | LVM_WRITE,
--					ALLOC_INHERIT, pool_lv->vg)))
--		goto_bad;
--
--	if (!move_lv_segments(meta_lv, pool_lv, 0, 0))
--		goto_bad;
--
--	/* Pool data segment */
--	if (!lv_add_segment(ah, 0, stripes, pool_lv, striped, stripe_size, 0, 0))
--		goto_bad;
--
--	if (!(data_lv = insert_layer_for_lv(pool_lv->vg->cmd, pool_lv,
--					    pool_lv->status, "_tdata")))
--		goto_bad;
--
--	seg = first_seg(pool_lv);
--	/* Drop reference as attach_pool_data_lv() takes it again */
--	if (!remove_seg_from_segs_using_this_lv(data_lv, seg))
--		goto_bad;
--
--	if (!attach_pool_data_lv(seg, data_lv))
--		goto_bad;
--
--	if (!attach_pool_metadata_lv(seg, meta_lv))
--		goto_bad;
--
--	seg->segtype = segtype; /* Set as thin_pool segment */
--
--	return 1;
--
--bad:
--	if (activation()) {
--		if (deactivate_lv_local(pool_lv->vg->cmd, pool_lv)) {
--			log_error("Aborting. Could not deactivate pool %s.",
--				  pool_lv->name);
--			return 0;
--		}
--		if (!lv_remove(pool_lv) || !vg_write(pool_lv->vg) || !vg_commit(pool_lv->vg))
--			log_error("Manual intervention may be required to remove "
--				  "abandoned LV(s) before retrying.");
--	}
--
--	return 0;
--}
--
- int update_pool_lv(struct logical_volume *lv, int activate)
- {
- 	int monitored;
-@@ -640,11 +421,12 @@ int update_profilable_pool_params(struct cmd_context *cmd, struct profile *profi
- 	return 1;
- }
- 
--int update_pool_params(struct volume_group *vg, unsigned attr, int passed_args,
--		       uint32_t data_extents, uint32_t extent_size,
--		       int *chunk_size_calc_method, uint32_t *chunk_size,
--		       thin_discards_t *discards, uint64_t *pool_metadata_size,
--		       int *zero)
-+int update_thin_pool_params(struct volume_group *vg, unsigned attr,
-+			    int passed_args,
-+			    uint32_t data_extents, uint32_t extent_size,
-+			    int *chunk_size_calc_method, uint32_t *chunk_size,
-+			    thin_discards_t *discards,
-+			    uint64_t *pool_metadata_size, int *zero)
- {
- 	size_t estimate_chunk_size;
- 	struct cmd_context *cmd = vg->cmd;
-@@ -897,7 +679,7 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
- 		       seg_mirrors,
- 		       seg->region_size,
- 		       extents - lv->le_count, NULL,
--		       pvh, lv->alloc))
-+		       pvh, lv->alloc, 0))
- 		return_0;
- 
- 	return 1;
-diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c
-index 877371e..8f23d56 100644
---- a/lib/metadata/vg.c
-+++ b/lib/metadata/vg.c
-@@ -89,6 +89,7 @@ void release_vg(struct volume_group *vg)
- 		return;
- 
- 	release_vg(vg->vg_ondisk);
-+	release_vg(vg->vg_precommitted);
- 	_free_vg(vg);
- }
- 
-diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h
-index 43d27bf..028471b 100644
---- a/lib/metadata/vg.h
-+++ b/lib/metadata/vg.h
-@@ -57,6 +57,7 @@ struct volume_group {
- 	 * _vg_update_vg_ondisk.
- 	 */
- 	struct volume_group *vg_ondisk;
-+	struct volume_group *vg_precommitted; /* Parsed from precommitted */
- 
- 	alloc_policy_t alloc;
- 	struct profile *profile;
-diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c
-index c3eb27b..5088173 100644
---- a/lib/mirror/mirrored.c
-+++ b/lib/mirror/mirrored.c
-@@ -150,7 +150,6 @@ static int _mirrored_text_export(const struct lv_segment *seg, struct formatter
- 
- #ifdef DEVMAPPER_SUPPORT
- static int _block_on_error_available = 0;
--static unsigned _mirror_attributes = 0;
- 
- static struct mirror_state *_mirrored_init_target(struct dm_pool *mem,
- 					 struct cmd_context *cmd)
-@@ -462,13 +461,13 @@ static int _mirrored_target_present(struct cmd_context *cmd,
- {
- 	static int _mirrored_checked = 0;
- 	static int _mirrored_present = 0;
-+	static unsigned _mirror_attributes = 0;
- 	uint32_t maj, min, patchlevel;
- 	unsigned maj2, min2, patchlevel2;
- 	char vsn[80];
--	struct utsname uts;
--	unsigned kmaj, kmin, krel;
- 
- 	if (!_mirrored_checked) {
-+		_mirrored_checked = 1;
- 		_mirrored_present = target_present(cmd, "mirror", 1);
- 
- 		/*
-@@ -492,14 +491,16 @@ static int _mirrored_target_present(struct cmd_context *cmd,
- 		      sscanf(vsn, "%u.%u.%u", &maj2, &min2, &patchlevel2) == 3 &&
- 		      maj2 == 4 && min2 == 5 && patchlevel2 == 0)))	/* RHEL4U3 */
- 			_block_on_error_available = 1;
--	}
- 
--	/*
--	 * Check only for modules if atttributes requested and no previous check.
--	 * FIXME: Fails incorrectly if cmirror was built into kernel.
--	 */
--	if (attributes) {
--		if (!_mirror_attributes) {
-+#ifdef CMIRRORD_PIDFILE
-+		/*
-+		 * The cluster mirror log daemon must be running,
-+		 * otherwise, the kernel module will fail to make
-+		 * contact.
-+		 */
-+		if (dm_daemon_is_running(CMIRRORD_PIDFILE)) {
-+			struct utsname uts;
-+			unsigned kmaj, kmin, krel;
- 			/*
- 			 * The dm-log-userspace module was added to the
- 			 * 2.6.31 kernel.
-@@ -508,31 +509,25 @@ static int _mirrored_target_present(struct cmd_context *cmd,
- 			    (sscanf(uts.release, "%u.%u.%u", &kmaj, &kmin, &krel) == 3) &&
- 			    KERNEL_VERSION(kmaj, kmin, krel) < KERNEL_VERSION(2, 6, 31)) {
- 				if (module_present(cmd, "log-clustered"))
--					_mirror_attributes |= MIRROR_LOG_CLUSTERED;
-+				_mirror_attributes |= MIRROR_LOG_CLUSTERED;
- 			} else if (module_present(cmd, "log-userspace"))
- 				_mirror_attributes |= MIRROR_LOG_CLUSTERED;
- 
- 			if (!(_mirror_attributes & MIRROR_LOG_CLUSTERED))
--				log_verbose("Cluster mirror log module is not available");
--
--			/*
--			 * The cluster mirror log daemon must be running,
--			 * otherwise, the kernel module will fail to make
--			 * contact.
--			 */
--#ifdef CMIRRORD_PIDFILE
--			if (!dm_daemon_is_running(CMIRRORD_PIDFILE)) {
--				log_verbose("Cluster mirror log daemon is not running");
--				_mirror_attributes &= ~MIRROR_LOG_CLUSTERED;
--			}
-+				log_verbose("Cluster mirror log module is not available.");
-+		} else
-+			log_verbose("Cluster mirror log daemon is not running.");
- #else
--			log_verbose("Cluster mirror log daemon not included in build");
--			_mirror_attributes &= ~MIRROR_LOG_CLUSTERED;
-+		log_verbose("Cluster mirror log daemon not included in build.");
- #endif
--		}
--		*attributes = _mirror_attributes;
- 	}
--	_mirrored_checked = 1;
-+
-+	/*
-+	 * Check only for modules if atttributes requested and no previous check.
-+	 * FIXME: Fails incorrectly if cmirror was built into kernel.
-+	 */
-+	if (attributes)
-+		*attributes = _mirror_attributes;
- 
- 	return _mirrored_present;
- }
-diff --git a/lib/misc/configure.h.in b/lib/misc/configure.h.in
-index 4e9ffd1..c1f088e 100644
---- a/lib/misc/configure.h.in
-+++ b/lib/misc/configure.h.in
-@@ -3,6 +3,9 @@
- /* Define to 1 to use libblkid detection of signatures when wiping. */
- #undef BLKID_WIPING_SUPPORT
- 
-+/* Define to 1 to include built-in support for cache. */
-+#undef CACHE_INTERNAL
-+
- /* Define to 1 if the `closedir' function returns void instead of `int'. */
- #undef CLOSEDIR_VOID
- 
-diff --git a/lib/misc/lvm-exec.c b/lib/misc/lvm-exec.c
-index 01704ad..e862bad 100644
---- a/lib/misc/lvm-exec.c
-+++ b/lib/misc/lvm-exec.c
-@@ -18,7 +18,6 @@
- #include "locking.h"
- #include "lvm-exec.h"
- #include "toolcontext.h"
--#include "activate.h"
- 
- #include <unistd.h>
- #include <sys/wait.h>
-diff --git a/lib/raid/raid.c b/lib/raid/raid.c
-index 956472e..e592573 100644
---- a/lib/raid/raid.c
-+++ b/lib/raid/raid.c
-@@ -221,11 +221,11 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
- 
- 	for (s = 0; s < seg->area_count; s++)
- 		if (seg_lv(seg, s)->status & LV_REBUILD)
--			rebuilds |= 1 << s;
-+			rebuilds |= 1ULL << s;
- 
- 	for (s = 0; s < seg->area_count; s++)
- 		if (seg_lv(seg, s)->status & LV_WRITEMOSTLY)
--			writemostly |= 1 << s;
-+			writemostly |= 1ULL << s;
- 
- 	if (mirror_in_sync())
- 		flags = DM_NOSYNC;
-@@ -326,15 +326,45 @@ static int _raid_target_percent(void **target_state,
- 
- static int _raid_target_present(struct cmd_context *cmd,
- 				const struct lv_segment *seg __attribute__((unused)),
--				unsigned *attributes __attribute__((unused)))
-+				unsigned *attributes)
- {
-+	/* List of features with their kernel target version */
-+	static const struct feature {
-+		uint32_t maj;
-+		uint32_t min;
-+		unsigned raid_feature;
-+		const char *feature;
-+	} const _features[] = {
-+		{ 1, 3, RAID_FEATURE_RAID10, "raid10" },
-+	};
-+
- 	static int _raid_checked = 0;
- 	static int _raid_present = 0;
-+	static int _raid_attrs = 0;
-+	uint32_t maj, min, patchlevel;
-+	unsigned i;
- 
--	if (!_raid_checked)
-+	if (!_raid_checked) {
- 		_raid_present = target_present(cmd, "raid", 1);
- 
--	_raid_checked = 1;
-+		if (!target_version("raid", &maj, &min, &patchlevel)) {
-+			log_error("Cannot read target version of RAID kernel module.");
-+			return 0;
-+		}
-+
-+		for (i = 0; i < sizeof(_features)/sizeof(*_features); i++)
-+			if ((maj > _features[i].maj) ||
-+			    (maj == _features[i].maj && min >= _features[i].min))
-+				_raid_attrs |= _features[i].raid_feature;
-+			else
-+				log_very_verbose("Target raid does not support %s.",
-+						 _features[i].feature);
-+
-+		_raid_checked = 1;
-+	}
-+
-+	if (attributes)
-+		*attributes = _raid_attrs;
- 
- 	return _raid_present;
- }
-diff --git a/lib/report/report.c b/lib/report/report.c
-index 3a5119d..681e80c 100644
---- a/lib/report/report.c
-+++ b/lib/report/report.c
-@@ -130,10 +130,10 @@ static int _tags_disp(struct dm_report *rh __attribute__((unused)), struct dm_po
- 		      struct dm_report_field *field,
- 		      const void *data, void *private __attribute__((unused)))
- {
--	const struct dm_list *tags = (const struct dm_list *) data;
-+	const struct dm_list *tagsl = (const struct dm_list *) data;
- 	char *tags_str;
- 
--	if (!(tags_str = tags_format_and_copy(mem, tags)))
-+	if (!(tags_str = tags_format_and_copy(mem, tagsl)))
- 		return_0;
- 
- 	return _field_set_value(field, tags_str, NULL);
-@@ -321,7 +321,7 @@ static int _datalv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__(
- 			const void *data, void *private __attribute__((unused)))
- {
- 	const struct logical_volume *lv = (const struct logical_volume *) data;
--	const struct lv_segment *seg = lv_is_thin_pool(lv) ? first_seg(lv) : NULL;
-+	const struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ? first_seg(lv) : NULL;
- 
- 	if (seg)
- 		return _lvname_disp(rh, mem, field, seg_lv(seg, 0), private);
-@@ -334,7 +334,7 @@ static int _metadatalv_disp(struct dm_report *rh, struct dm_pool *mem __attribut
- 			    const void *data, void *private __attribute__((unused)))
- {
- 	const struct logical_volume *lv = (const struct logical_volume *) data;
--	const struct lv_segment *seg = lv_is_thin_pool(lv) ? first_seg(lv) : NULL;
-+	const struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ? first_seg(lv) : NULL;
- 
- 	if (seg)
- 		return _lvname_disp(rh, mem, field, seg->metadata_lv, private);
-@@ -347,7 +347,8 @@ static int _poollv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__(
- 			const void *data, void *private __attribute__((unused)))
- {
- 	const struct logical_volume *lv = (const struct logical_volume *) data;
--	struct lv_segment *seg = lv_is_thin_volume(lv) ? first_seg(lv) : NULL;
-+	struct lv_segment *seg = (lv_is_thin_volume(lv) || lv_is_cache(lv)) ?
-+				  first_seg(lv) : NULL;
- 
- 	if (seg)
- 		return _lvname_disp(rh, mem, field, seg->pool_lv, private);
-@@ -373,10 +374,14 @@ static int _origin_disp(struct dm_report *rh, struct dm_pool *mem,
- 			const void *data, void *private)
- {
- 	const struct logical_volume *lv = (const struct logical_volume *) data;
-+	const struct lv_segment *seg = first_seg(lv);
- 
- 	if (lv_is_cow(lv))
- 		return _lvname_disp(rh, mem, field, origin_from_cow(lv), private);
- 
-+	if (lv_is_cache(lv))
-+		return _lvname_disp(rh, mem, field, seg_lv(seg, 0), private);
-+
- 	if (lv_is_thin_volume(lv) && first_seg(lv)->origin)
- 		return _lvname_disp(rh, mem, field, first_seg(lv)->origin, private);
- 
-@@ -1051,7 +1056,7 @@ static int _lvmetadatasize_disp(struct dm_report *rh, struct dm_pool *mem,
- 	const struct logical_volume *lv = (const struct logical_volume *) data;
- 	uint64_t size;
- 
--	if (lv_is_thin_pool(lv)) {
-+	if (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) {
- 		size = lv_metadata_size(lv);
- 		return _size64_disp(rh, mem, field, &size, private);
- 	}
-diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c
-index 91e778f..0b7b845 100644
---- a/lib/snapshot/snapshot.c
-+++ b/lib/snapshot/snapshot.c
-@@ -142,19 +142,30 @@ static int _snap_target_percent(void **target_state __attribute__((unused)),
- 
- static int _snap_target_present(struct cmd_context *cmd,
- 				const struct lv_segment *seg,
--				unsigned *attributes __attribute__((unused)))
-+				unsigned *attributes)
- {
- 	static int _snap_checked = 0;
- 	static int _snap_merge_checked = 0;
- 	static int _snap_present = 0;
- 	static int _snap_merge_present = 0;
-+	static unsigned _snap_attrs = 0;
-+	uint32_t maj, min, patchlevel;
- 
- 	if (!_snap_checked) {
-+		_snap_checked = 1;
- 		_snap_present = target_present(cmd, "snapshot", 1) &&
- 		    target_present(cmd, "snapshot-origin", 0);
--		_snap_checked = 1;
-+
-+		if (_snap_present &&
-+		    target_version("snapshot", &maj, &min, &patchlevel) &&
-+		    (maj > 1 ||
-+		     (maj == 1 && (min >= 12 || (min == 10 && patchlevel >= 2)))))
-+			_snap_attrs |= SNAPSHOT_FEATURE_FIXED_LEAK;
-+		else
-+			log_very_verbose("Target snapshot may leak metadata.");
- 	}
- 
-+	/* TODO: test everything at once */
- 	if (seg && (seg->status & MERGING)) {
- 		if (!_snap_merge_checked) {
- 			_snap_merge_present = target_present(cmd, "snapshot-merge", 0);
-diff --git a/lib/thin/thin.c b/lib/thin/thin.c
-index ff263d9..7c989f8 100644
---- a/lib/thin/thin.c
-+++ b/lib/thin/thin.c
-@@ -215,7 +215,7 @@ static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter
- 
- #ifdef DEVMAPPER_SUPPORT
- static int _thin_target_present(struct cmd_context *cmd,
--				const struct lv_segment *seg,
-+				const struct lv_segment *seg __attribute__((unused)),
- 				unsigned *attributes);
- 
- static int _thin_pool_modules_needed(struct dm_pool *mem,
-@@ -262,7 +262,7 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
- 	uint64_t transaction_id = 0;
- 	unsigned attr;
- 
--	if (!_thin_target_present(cmd, seg, &attr))
-+	if (!_thin_target_present(cmd, NULL, &attr))
- 		return_0;
- 
- 	if (!seg->metadata_lv) {
-@@ -528,6 +528,7 @@ static int _thin_add_target_line(struct dev_manager *dm,
- {
- 	char *pool_dlid, *external_dlid;
- 	uint32_t device_id = seg->device_id;
-+	unsigned attr;
- 
- 	if (!seg->pool_lv) {
- 		log_error(INTERNAL_ERROR "Segment %s has no pool.",
-@@ -541,18 +542,19 @@ static int _thin_add_target_line(struct dev_manager *dm,
- 	}
- 
- 	if (!laopts->no_merging) {
-+		if (seg->merge_lv) {
-+			log_error(INTERNAL_ERROR "Failed to add merged segment of %s.",
-+				  seg->lv->name);
-+			return 0;
-+		}
- 		/*
- 		 * merge support for thinp snapshots is implemented by
- 		 * simply swapping the thinp device_id of the snapshot
- 		 * and origin.
- 		 */
--		if (seg->merge_lv) {
--			/* snapshot, use merging lv's device_id */
--			device_id = first_seg(seg->merge_lv)->device_id;
--		} else if (lv_is_merging_origin(seg->lv)) {
-+		if (lv_is_merging_origin(seg->lv) && seg_is_thin_volume(find_snapshot(seg->lv)))
- 			/* origin, use merging snapshot's device_id */
- 			device_id = find_snapshot(seg->lv)->device_id;
--		}
- 	}
- 
- 	if (!dm_tree_node_add_thin_target(node, len, pool_dlid, device_id))
-@@ -560,6 +562,17 @@ static int _thin_add_target_line(struct dev_manager *dm,
- 
- 	/* Add external origin LV */
- 	if (seg->external_lv) {
-+		if (!pool_supports_external_origin(first_seg(seg->pool_lv), seg->external_lv))
-+			return_0;
-+		if (seg->external_lv->size < seg->lv->size) {
-+			/* Validate target supports smaller external origin */
-+			if (!_thin_target_present(cmd, NULL, &attr) ||
-+			    !(attr & THIN_FEATURE_EXTERNAL_ORIGIN_EXTEND)) {
-+				log_error("Thin target does not support smaller size of external origin LV %s.",
-+					  seg->external_lv->name);
-+				return 0;
-+			}
-+		}
- 		if (!(external_dlid = build_dm_uuid(mem, seg->external_lv->lvid.s,
- 						    lv_layer(seg->external_lv)))) {
- 			log_error("Failed to build uuid for external origin LV %s.",
-@@ -604,7 +617,7 @@ static int _thin_target_percent(void **target_state __attribute__((unused)),
- }
- 
- static int _thin_target_present(struct cmd_context *cmd,
--				const struct lv_segment *seg,
-+				const struct lv_segment *seg __attribute__((unused)),
- 				unsigned *attributes)
- {
- 	/* List of features with their kernel target version */
-@@ -618,7 +631,8 @@ static int _thin_target_present(struct cmd_context *cmd,
- 		{ 1, 1, THIN_FEATURE_EXTERNAL_ORIGIN, "external_origin" },
- 		{ 1, 4, THIN_FEATURE_BLOCK_SIZE, "block_size" },
- 		{ 1, 5, THIN_FEATURE_DISCARDS_NON_POWER_2, "discards_non_power_2" },
--		{ 9, 9, THIN_FEATURE_METADATA_RESIZE, "metadata_resize" },
-+		{ 1, 10, THIN_FEATURE_METADATA_RESIZE, "metadata_resize" },
-+		{ 9, 11, THIN_FEATURE_EXTERNAL_ORIGIN_EXTEND, "external_origin_extend" },
- 	};
- 
- 	static const char _lvmconf[] = "global/thin_disabled_features";
-@@ -640,7 +654,8 @@ static int _thin_target_present(struct cmd_context *cmd,
- 		}
- 
- 		for (i = 0; i < sizeof(_features)/sizeof(*_features); i++)
--			if (maj >= _features[i].maj && min >= _features[i].min)
-+			if ((maj > _features[i].maj) ||
-+			    (maj == _features[i].maj && min >= _features[i].min))
- 				_attrs |= _features[i].thin_feature;
- 			else
- 				log_very_verbose("Target %s does not support %s.",
-diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
-index adfbb76..dd57457 100644
---- a/libdm/libdevmapper.h
-+++ b/libdm/libdevmapper.h
-@@ -1,6 +1,6 @@
- /*
-  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
-- * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of the device-mapper userspace tools.
-  *
-@@ -294,6 +294,39 @@ struct dm_status_raid {
- int dm_get_status_raid(struct dm_pool *mem, const char *params,
- 		       struct dm_status_raid **status);
- 
-+struct dm_status_cache {
-+	uint64_t version;  /* zero for now */
-+
-+	uint32_t metadata_block_size;   /* in 512B sectors */
-+	uint32_t block_size;            /* AKA 'chunk_size' */
-+
-+	uint64_t metadata_used_blocks;
-+	uint64_t metadata_total_blocks;
-+
-+	uint64_t used_blocks;
-+	uint64_t dirty_blocks;
-+	uint64_t total_blocks;
-+
-+	uint64_t read_hits;
-+	uint64_t read_misses;
-+	uint64_t write_hits;
-+	uint64_t write_misses;
-+
-+	uint64_t demotions;
-+	uint64_t promotions;
-+
-+	uint32_t feature_flags;
-+
-+	int core_argc;
-+	char **core_argv;
-+
-+	char *policy_name;
-+	int   policy_argc;
-+	char **policy_argv;
-+};
-+
-+int dm_get_status_cache(struct dm_pool *mem, const char *params,
-+			struct dm_status_cache **status);
- 
- /*
-  * Snapshot target's format:
-@@ -524,10 +557,10 @@ struct dm_tree_node *dm_tree_add_new_dev_with_udev_flags(struct dm_tree *tree,
-  * Set major and minor to 0 or uuid to NULL to get the root node.
-  */
- struct dm_tree_node *dm_tree_find_node(struct dm_tree *tree,
--					  uint32_t major,
--					  uint32_t minor);
-+				       uint32_t major,
-+				       uint32_t minor);
- struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *tree,
--						  const char *uuid);
-+					       const char *uuid);
- 
- /*
-  * Use this to walk through all children of a given node.
-@@ -559,8 +592,8 @@ int dm_tree_node_num_children(const struct dm_tree_node *node, uint32_t inverted
-  * Ignores devices that don't have a uuid starting with uuid_prefix.
-  */
- int dm_tree_deactivate_children(struct dm_tree_node *dnode,
--				   const char *uuid_prefix,
--				   size_t uuid_prefix_len);
-+				const char *uuid_prefix,
-+				size_t uuid_prefix_len);
- /*
-  * Preload/create a device plus all dependencies.
-  * Ignores devices that don't have a uuid starting with uuid_prefix.
-@@ -582,8 +615,8 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
-  * Ignores devices that don't have a uuid starting with uuid_prefix.
-  */
- int dm_tree_suspend_children(struct dm_tree_node *dnode,
--				   const char *uuid_prefix,
--				   size_t uuid_prefix_len);
-+			     const char *uuid_prefix,
-+			     size_t uuid_prefix_len);
- 
- /*
-  * Skip the filesystem sync when suspending.
-@@ -613,36 +646,36 @@ void dm_tree_retry_remove(struct dm_tree_node *dnode);
-  * Returns 1 if the tree walk has to be aborted.
-  */
- int dm_tree_children_use_uuid(struct dm_tree_node *dnode,
--				 const char *uuid_prefix,
--				 size_t uuid_prefix_len);
-+			      const char *uuid_prefix,
-+			      size_t uuid_prefix_len);
- 
- /*
-  * Construct tables for new nodes before activating them.
-  */
- int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
--					       uint64_t size,
--					       const char *origin_uuid);
-+					    uint64_t size,
-+					    const char *origin_uuid);
- int dm_tree_node_add_snapshot_target(struct dm_tree_node *node,
--					uint64_t size,
--					const char *origin_uuid,
--					const char *cow_uuid,
--					int persistent,
--					uint32_t chunk_size);
-+				     uint64_t size,
-+				     const char *origin_uuid,
-+				     const char *cow_uuid,
-+				     int persistent,
-+				     uint32_t chunk_size);
- int dm_tree_node_add_snapshot_merge_target(struct dm_tree_node *node,
--					     uint64_t size,
--					     const char *origin_uuid,
--					     const char *cow_uuid,
--					     const char *merge_uuid,
--					     uint32_t chunk_size);
-+					   uint64_t size,
-+					   const char *origin_uuid,
-+					   const char *cow_uuid,
-+					   const char *merge_uuid,
-+					   uint32_t chunk_size);
- int dm_tree_node_add_error_target(struct dm_tree_node *node,
--				     uint64_t size);
-+				  uint64_t size);
- int dm_tree_node_add_zero_target(struct dm_tree_node *node,
--				    uint64_t size);
-+				 uint64_t size);
- int dm_tree_node_add_linear_target(struct dm_tree_node *node,
--				      uint64_t size);
-+				   uint64_t size);
- int dm_tree_node_add_striped_target(struct dm_tree_node *node,
--				       uint64_t size,
--				       uint32_t stripe_size);
-+				    uint64_t size,
-+				    uint32_t stripe_size);
- 
- #define DM_CRYPT_IV_DEFAULT	UINT64_C(-1)	/* iv_offset == seg offset */
- /*
-@@ -659,7 +692,7 @@ int dm_tree_node_add_crypt_target(struct dm_tree_node *node,
- 				  uint64_t iv_offset,
- 				  const char *key);
- int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
--				      uint64_t size);
-+				   uint64_t size);
-  
- /* Mirror log flags */
- #define DM_NOSYNC		0x00000001	/* Known already in sync */
-@@ -668,11 +701,11 @@ int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
- #define DM_CORELOG		0x00000008	/* In-memory log */
- 
- int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
--					  uint32_t region_size,
--					  unsigned clustered,
--					  const char *log_uuid,
--					  unsigned area_count,
--					  uint32_t flags);
-+				       uint32_t region_size,
-+				       unsigned clustered,
-+				       const char *log_uuid,
-+				       unsigned area_count,
-+				       uint32_t flags);
- 
- int dm_tree_node_add_raid_target(struct dm_tree_node *node,
- 				 uint64_t size,
-@@ -682,6 +715,22 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
- 				 uint64_t rebuilds,
- 				 uint64_t flags);
- 
-+/*
-+ * Defines bellow are based on kernel's dm-cache.c defines
-+ * DM_CACHE_MIN_DATA_BLOCK_SIZE (32 * 1024 >> SECTOR_SHIFT)
-+ * DM_CACHE_MAX_DATA_BLOCK_SIZE (1024 * 1024 * 1024 >> SECTOR_SHIFT)
-+ */
-+#define DM_CACHE_MIN_DATA_BLOCK_SIZE (UINT32_C(64))
-+#define DM_CACHE_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152))
-+/*
-+ * Max supported size for cache pool metadata device.
-+ * Limitation is hardcoded into the kernel and bigger device sizes
-+ * are not accepted.
-+ *
-+ * Limit defined in drivers/md/dm-cache-metadata.h
-+ */
-+#define DM_CACHE_METADATA_MAX_SECTORS DM_THIN_METADATA_MAX_SECTORS
-+
- struct dm_tree_node_raid_params {
- 	const char *raid_type;
- 
-@@ -712,6 +761,23 @@ int dm_tree_node_add_raid_target_with_params(struct dm_tree_node *node,
- 					     uint64_t size,
- 					     struct dm_tree_node_raid_params *p);
- 
-+/* Cache feature_flags */
-+#define DM_CACHE_FEATURE_WRITEBACK    0x00000001
-+#define DM_CACHE_FEATURE_WRITETHROUGH 0x00000002
-+
-+int dm_tree_node_add_cache_target(struct dm_tree_node *node,
-+				  uint64_t size,
-+				  const char *metadata_uuid,
-+				  const char *data_uuid,
-+				  const char *origin_uuid,
-+				  uint32_t chunk_size,
-+				  uint32_t feature_flags, /* DM_CACHE_FEATURE_* */
-+				  unsigned core_argc,
-+				  char **core_argv,
-+				  char *policy_name,
-+				  unsigned policy_argc,
-+				  char **policy_argv);
-+
- /*
-  * Replicator operation mode
-  * Note: API for Replicator is not yet stable
-@@ -1083,7 +1149,7 @@ void dm_hash_remove(struct dm_hash_table *t, const char *key);
- 
- void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key, uint32_t len);
- int dm_hash_insert_binary(struct dm_hash_table *t, const void *key, uint32_t len,
--		       void *data);
-+			  void *data);
- void dm_hash_remove_binary(struct dm_hash_table *t, const void *key, uint32_t len);
- 
- unsigned dm_hash_get_num_entries(struct dm_hash_table *t);
-diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
-index 5ec5769..2ec66e7 100644
---- a/libdm/libdm-common.c
-+++ b/libdm/libdm-common.c
-@@ -868,12 +868,27 @@ static int _selabel_lookup(const char *path, mode_t mode,
- }
- #endif
- 
-+#ifdef HAVE_SELINUX
-+static int _is_selinux_enabled(void)
-+{
-+	static int _tested = 0;
-+	static int _enabled;
-+
-+	if (!_tested) {
-+		_tested = 1;
-+		_enabled = is_selinux_enabled();
-+	}
-+
-+	return _enabled;
-+}
-+#endif
-+
- int dm_prepare_selinux_context(const char *path, mode_t mode)
- {
- #ifdef HAVE_SELINUX
- 	security_context_t scontext = NULL;
- 
--	if (is_selinux_enabled() <= 0)
-+	if (_is_selinux_enabled() <= 0)
- 		return 1;
- 
- 	if (path) {
-@@ -901,7 +916,7 @@ int dm_set_selinux_context(const char *path, mode_t mode)
- #ifdef HAVE_SELINUX
- 	security_context_t scontext = NULL;
- 
--	if (is_selinux_enabled() <= 0)
-+	if (_is_selinux_enabled() <= 0)
- 		return 1;
- 
- 	if (!_selabel_lookup(path, mode, &scontext))
-diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
-index 42bb9e7..e513885 100644
---- a/libdm/libdm-deptree.c
-+++ b/libdm/libdm-deptree.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (C) 2005-2013 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2005-2014 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of the device-mapper userspace tools.
-  *
-@@ -27,6 +27,7 @@
- 
- /* Supported segment types */
- enum {
-+	SEG_CACHE,
- 	SEG_CRYPT,
- 	SEG_ERROR,
- 	SEG_LINEAR,
-@@ -59,6 +60,7 @@ struct {
- 	unsigned type;
- 	const char *target;
- } dm_segtypes[] = {
-+	{ SEG_CACHE, "cache" },
- 	{ SEG_CRYPT, "crypt" },
- 	{ SEG_ERROR, "error" },
- 	{ SEG_LINEAR, "linear" },
-@@ -158,18 +160,24 @@ struct load_segment {
- 	uint32_t stripe_size;		/* Striped + raid */
- 
- 	int persistent;			/* Snapshot */
--	uint32_t chunk_size;		/* Snapshot */
-+	uint32_t chunk_size;		/* Snapshot + cache */
- 	struct dm_tree_node *cow;	/* Snapshot */
--	struct dm_tree_node *origin;	/* Snapshot + Snapshot origin */
-+	struct dm_tree_node *origin;	/* Snapshot + Snapshot origin + Cache */
- 	struct dm_tree_node *merge;	/* Snapshot */
- 
- 	struct dm_tree_node *log;	/* Mirror + Replicator */
- 	uint32_t region_size;		/* Mirror + raid */
- 	unsigned clustered;		/* Mirror */
- 	unsigned mirror_area_count;	/* Mirror */
--	uint32_t flags;			/* Mirror log */
-+	uint32_t flags;			/* Mirror + raid + Cache */
- 	char *uuid;			/* Clustered mirror log */
- 
-+	unsigned core_argc;		/* Cache */
-+	char **core_argv;		/* Cache */
-+	char *policy_name;		/* Cache */
-+	unsigned policy_argc;		/* Cache */
-+	char **policy_argv;		/* Cache */
-+
- 	const char *cipher;		/* Crypt */
- 	const char *chainmode;		/* Crypt */
- 	const char *iv;			/* Crypt */
-@@ -189,7 +197,7 @@ struct load_segment {
- 	uint32_t max_recovery_rate;	/* raid kB/sec/disk */
- 	uint32_t min_recovery_rate;	/* raid kB/sec/disk */
- 
--	struct dm_tree_node *metadata;	/* Thin_pool */
-+	struct dm_tree_node *metadata;	/* Thin_pool + Cache */
- 	struct dm_tree_node *pool;	/* Thin_pool, Thin */
- 	struct dm_tree_node *external;	/* Thin */
- 	struct dm_list thin_messages;	/* Thin_pool */
-@@ -530,7 +538,7 @@ static struct dm_tree_node *_find_dm_tree_node(struct dm_tree *dtree,
- 	dev_t dev = MKDEV((dev_t)major, minor);
- 
- 	return dm_hash_lookup_binary(dtree->devs, (const char *) &dev,
--				  sizeof(dev));
-+				     sizeof(dev));
- }
- 
- static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
-@@ -699,8 +707,8 @@ static int _children_suspended(struct dm_tree_node *node,
-  * Set major and minor to zero for root of tree.
-  */
- struct dm_tree_node *dm_tree_find_node(struct dm_tree *dtree,
--					  uint32_t major,
--					  uint32_t minor)
-+				       uint32_t major,
-+				       uint32_t minor)
- {
- 	if (!major && !minor)
- 		return &dtree->root;
-@@ -712,7 +720,7 @@ struct dm_tree_node *dm_tree_find_node(struct dm_tree *dtree,
-  * Set uuid to NULL for root of tree.
-  */
- struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *dtree,
--						  const char *uuid)
-+					       const char *uuid)
- {
- 	if (!uuid || !*uuid)
- 		return &dtree->root;
-@@ -1470,14 +1478,17 @@ out:
- 	return r;
- }
- 
-+/* For preload pass only validate pool's transaction_id */
- static int _node_send_messages(struct dm_tree_node *dnode,
- 			       const char *uuid_prefix,
--			       size_t uuid_prefix_len)
-+			       size_t uuid_prefix_len,
-+			       int send)
- {
- 	struct load_segment *seg;
- 	struct thin_message *tmsg;
- 	uint64_t trans_id;
- 	const char *uuid;
-+	int have_messages;
- 
- 	if (!dnode->info.exists || (dm_list_size(&dnode->props.segs) != 1))
- 		return 1;
-@@ -1495,32 +1506,34 @@ static int _node_send_messages(struct dm_tree_node *dnode,
- 	}
- 
- 	if (!_thin_pool_status_transaction_id(dnode, &trans_id))
--		goto_bad;
-+		return_0;
- 
-+	have_messages = !dm_list_empty(&seg->thin_messages) ? 1 : 0;
- 	if (trans_id == seg->transaction_id) {
--		if (!dm_list_empty(&seg->thin_messages))
-+		dnode->props.send_messages = 0; /* messages already committed */
-+		if (have_messages)
- 			log_debug_activation("Thin pool transaction_id matches %" PRIu64
- 					     ", skipping messages.", trans_id);
--		return 1; /* In sync - skip messages */
-+		return 1;
- 	}
- 
--	if (trans_id != (seg->transaction_id - 1)) {
-+	/* Error if there are no stacked messages or id mismatches */
-+	if (trans_id != (seg->transaction_id - have_messages)) {
- 		log_error("Thin pool transaction_id=%" PRIu64 ", while expected: %" PRIu64 ".",
--			  trans_id, seg->transaction_id - 1);
--		goto bad; /* Nothing to send */
-+			  trans_id, seg->transaction_id - have_messages);
-+		return 0;
- 	}
- 
-+	if (!send)
-+		return 1; /* transaction_id is matching */
-+
- 	dm_list_iterate_items(tmsg, &seg->thin_messages)
- 		if (!(_thin_pool_node_message(dnode, tmsg)))
--			goto_bad;
-+			return_0;
- 
--	return 1;
--bad:
--	/* Try to deactivate */
--	if (!(dm_tree_deactivate_children(dnode, uuid_prefix, uuid_prefix_len)))
--		log_error("Failed to deactivate %s", dnode->name);
-+	dnode->props.send_messages = 0; /* messages posted */
- 
--	return 0;
-+	return 1;
- }
- 
- /*
-@@ -1613,7 +1626,9 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
- 				  info.minor);
- 			r = 0;
- 			continue;
--		} else if (info.suspended && info.live_table)
-+		}
-+
-+		if (info.suspended && info.live_table)
- 			dec_suspended();
- 
- 		if (child->callback &&
-@@ -1856,14 +1871,9 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
- 	 * resume should continue further, just whole command
- 	 * has to report failure.
- 	 */
--	if (r && dnode->props.send_messages) {
--		if (!(r = _node_send_messages(dnode, uuid_prefix, uuid_prefix_len)))
--			stack;
--		else
--			dnode->props.send_messages = 0; /* messages posted */
--	}
--
--	handle = NULL;
-+	if (r && dnode->props.send_messages &&
-+	    !(r = _node_send_messages(dnode, uuid_prefix, uuid_prefix_len, 1)))
-+		stack;
- 
- 	return r;
- }
-@@ -2235,11 +2245,11 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
- 		EMIT_PARAMS(pos, " region_size %u", seg->region_size);
- 
- 	for (i = 0; i < (seg->area_count / 2); i++)
--		if (seg->rebuilds & (1 << i))
-+		if (seg->rebuilds & (1ULL << i))
- 			EMIT_PARAMS(pos, " rebuild %u", i);
- 
- 	for (i = 0; i < (seg->area_count / 2); i++)
--		if (seg->writemostly & (1 << i))
-+		if (seg->writemostly & (1ULL << i))
- 			EMIT_PARAMS(pos, " write_mostly %u", i);
- 
- 	if (seg->writebehind)
-@@ -2262,6 +2272,70 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
- 	return 1;
- }
- 
-+static int _cache_emit_segment_line(struct dm_task *dmt,
-+				    struct load_segment *seg,
-+				    char *params, size_t paramsize)
-+{
-+	int pos = 0;
-+	unsigned i = 0;
-+	unsigned feature_count;
-+	struct seg_area *area;
-+	char data[DM_FORMAT_DEV_BUFSIZE];
-+	char metadata[DM_FORMAT_DEV_BUFSIZE];
-+	char origin[DM_FORMAT_DEV_BUFSIZE];
-+
-+	/* Metadata Dev */
-+	if (!_build_dev_string(metadata, sizeof(metadata), seg->metadata))
-+		return_0;
-+
-+	/* Cache Dev */
-+	if (!_build_dev_string(data, sizeof(origin), seg->pool))
-+		return_0;
-+
-+	/* Origin Dev */
-+	dm_list_iterate_items(area, &seg->areas)
-+		break; /* There is only ever 1 area */
-+	if (!_build_dev_string(origin, sizeof(data), area->dev_node))
-+		return_0;
-+
-+	EMIT_PARAMS(pos, " %s %s %s", metadata, data, origin);
-+
-+	/* Chunk size */
-+	EMIT_PARAMS(pos, " %u", seg->chunk_size);
-+
-+	/* Features */
-+	feature_count = hweight32(seg->flags);
-+	EMIT_PARAMS(pos, " %u", feature_count);
-+	if (seg->flags & DM_CACHE_FEATURE_WRITETHROUGH)
-+		EMIT_PARAMS(pos, " writethrough");
-+	else if (seg->flags & DM_CACHE_FEATURE_WRITEBACK)
-+		EMIT_PARAMS(pos, " writeback");
-+
-+	/* Core Arguments (like 'migration_threshold') */
-+	if (seg->core_argc) {
-+		EMIT_PARAMS(pos, " %u", seg->core_argc);
-+		for (i = 0; i < seg->core_argc; i++)
-+			EMIT_PARAMS(pos, " %s", seg->core_argv[i]);
-+	}
-+
-+	/* Cache Policy */
-+	if (!seg->policy_name)
-+		EMIT_PARAMS(pos, " default 0");
-+	else {
-+		EMIT_PARAMS(pos, " %s %u", seg->policy_name, seg->policy_argc);
-+		if (seg->policy_argc % 2) {
-+			log_error(INTERNAL_ERROR
-+				  "Cache policy arguments must be in "
-+				  "<key> <value> pairs");
-+			return 0;
-+		}
-+		for (i = 0; i < seg->policy_argc; i++)
-+			EMIT_PARAMS(pos, " %s", seg->policy_argv[i]);
-+	}
-+
-+	return 1;
-+}
-+
- static int _thin_pool_emit_segment_line(struct dm_task *dmt,
- 					struct load_segment *seg,
- 					char *params, size_t paramsize)
-@@ -2398,6 +2472,10 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
- 		if (!_thin_emit_segment_line(dmt, seg, params, paramsize))
- 			return_0;
- 		break;
-+	case SEG_CACHE:
-+		if (!_cache_emit_segment_line(dmt, seg, params, paramsize))
-+			return_0;
-+		break;
- 	}
- 
- 	switch(seg->type) {
-@@ -2409,6 +2487,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
- 	case SEG_ZERO:
- 	case SEG_THIN_POOL:
- 	case SEG_THIN:
-+	case SEG_CACHE:
- 		break;
- 	case SEG_CRYPT:
- 	case SEG_LINEAR:
-@@ -2550,13 +2629,16 @@ out:
- 	return r;
- }
- 
-+/*
-+ * Currently try to deactivate only nodes created during preload.
-+ * New node is always attached to the front of activated_list
-+ */
- static int _dm_tree_revert_activated(struct dm_tree_node *parent)
- {
- 	struct dm_tree_node *child;
- 
--	dm_list_iterate_back_items_gen(child, &parent->activated, activated_list) {
--		_dm_tree_revert_activated(child);
--		log_debug("Reverting preloaded %s.", child->name);
-+	dm_list_iterate_items_gen(child, &parent->activated, activated_list) {
-+		log_debug_activation("Reverting %s.", child->name);
- 		if (!_deactivate_node(child->name, child->info.major, child->info.minor,
- 				      &child->dtree->cookie, child->udev_flags, 0)) {
- 			log_error("Unable to deactivate %s (%" PRIu32
-@@ -2564,6 +2646,8 @@ static int _dm_tree_revert_activated(struct dm_tree_node *parent)
- 				  child->info.minor);
- 			return 0;
- 		}
-+		if (!_dm_tree_revert_activated(child))
-+			return_0;
- 	}
- 
- 	return 1;
-@@ -2623,7 +2707,7 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
- 				  child->info.minor);
- 			/* If the device was not previously active, we might as well remove this node. */
- 			if (!child->info.live_table &&
--			    !_deactivate_node(child->name, child->info.major,child->info.minor,
-+			    !_deactivate_node(child->name, child->info.major, child->info.minor,
- 					      &child->dtree->cookie, child->udev_flags, 0))
- 				log_error("Unable to deactivate %s (%" PRIu32
- 					  ":%" PRIu32 ")", child->name, child->info.major,
-@@ -2633,9 +2717,22 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
- 			continue;
- 		}
- 
--		if (!child->info.live_table)
-+		if (!child->info.live_table) {
- 			/* Collect newly introduced devices for revert */
--			dm_list_add(&dnode->activated, &child->activated_list);
-+			dm_list_add_h(&dnode->activated, &child->activated_list);
-+
-+			/* When creating new node also check transaction_id. */
-+			if (child->props.send_messages &&
-+			    !_node_send_messages(child, uuid_prefix, uuid_prefix_len, 0)) {
-+				stack;
-+				if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
-+					stack;
-+				dm_tree_set_cookie(dnode, 0);
-+				(void) _dm_tree_revert_activated(dnode);
-+				r = 0;
-+				continue;
-+			}
-+		}
- 
- 		/* Update cached info */
- 		child->info = newinfo;
-@@ -2649,12 +2746,12 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
- 	}
- 
- 	if (update_devs_flag ||
--	    (!dnode->info.exists && dnode->callback)) {
-+	    (r && !dnode->info.exists && dnode->callback)) {
- 		if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
- 			stack;
- 		dm_tree_set_cookie(dnode, 0);
- 
--		if (!dnode->info.exists && dnode->callback &&
-+		if (r && !dnode->info.exists && dnode->callback &&
- 		    !dnode->callback(dnode, DM_NODE_CALLBACK_PRELOADED,
- 				     dnode->callback_data))
- 		{
-@@ -2724,8 +2821,8 @@ static struct load_segment *_add_segment(struct dm_tree_node *dnode, unsigned ty
- }
- 
- int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
--					       uint64_t size,
--					       const char *origin_uuid)
-+					    uint64_t size,
-+					    const char *origin_uuid)
- {
- 	struct load_segment *seg;
- 	struct dm_tree_node *origin_node;
-@@ -2755,12 +2852,12 @@ int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
- }
- 
- static int _add_snapshot_target(struct dm_tree_node *node,
--				   uint64_t size,
--				   const char *origin_uuid,
--				   const char *cow_uuid,
--				   const char *merge_uuid,
--				   int persistent,
--				   uint32_t chunk_size)
-+				uint64_t size,
-+				const char *origin_uuid,
-+				const char *cow_uuid,
-+				const char *merge_uuid,
-+				int persistent,
-+				uint32_t chunk_size)
- {
- 	struct load_segment *seg;
- 	struct dm_tree_node *origin_node, *cow_node, *merge_node;
-@@ -2873,7 +2970,7 @@ int dm_get_status_snapshot(struct dm_pool *mem, const char *params,
- }
- 
- int dm_tree_node_add_error_target(struct dm_tree_node *node,
--				     uint64_t size)
-+				  uint64_t size)
- {
- 	if (!_add_segment(node, SEG_ERROR, size))
- 		return_0;
-@@ -2882,7 +2979,7 @@ int dm_tree_node_add_error_target(struct dm_tree_node *node,
- }
- 
- int dm_tree_node_add_zero_target(struct dm_tree_node *node,
--				    uint64_t size)
-+				 uint64_t size)
- {
- 	if (!_add_segment(node, SEG_ZERO, size))
- 		return_0;
-@@ -2891,7 +2988,7 @@ int dm_tree_node_add_zero_target(struct dm_tree_node *node,
- }
- 
- int dm_tree_node_add_linear_target(struct dm_tree_node *node,
--				      uint64_t size)
-+				   uint64_t size)
- {
- 	if (!_add_segment(node, SEG_LINEAR, size))
- 		return_0;
-@@ -2900,8 +2997,8 @@ int dm_tree_node_add_linear_target(struct dm_tree_node *node,
- }
- 
- int dm_tree_node_add_striped_target(struct dm_tree_node *node,
--				       uint64_t size,
--				       uint32_t stripe_size)
-+				    uint64_t size,
-+				    uint32_t stripe_size)
- {
- 	struct load_segment *seg;
- 
-@@ -2936,11 +3033,11 @@ int dm_tree_node_add_crypt_target(struct dm_tree_node *node,
- }
- 
- int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
--					  uint32_t region_size,
--					  unsigned clustered,
--					  const char *log_uuid,
--					  unsigned area_count,
--					  uint32_t flags)
-+				       uint32_t region_size,
-+				       unsigned clustered,
-+				       const char *log_uuid,
-+				       unsigned area_count,
-+				       uint32_t flags)
- {
- 	struct dm_tree_node *log_node = NULL;
- 	struct load_segment *seg;
-@@ -2988,7 +3085,7 @@ int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
- }
- 
- int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
--				      uint64_t size)
-+				   uint64_t size)
- {
- 	if (!_add_segment(node, SEG_MIRRORED, size))
- 		return_0;
-@@ -3033,19 +3130,17 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
- 				 uint64_t rebuilds,
- 				 uint64_t flags)
- {
--	struct dm_tree_node_raid_params params;
--
--	memset(&params, 0, sizeof(params));
--	params.raid_type = raid_type;
--	params.region_size = region_size;
--	params.stripe_size = stripe_size;
--	params.rebuilds = rebuilds;
--	params.flags = flags;
-+	struct dm_tree_node_raid_params params = {
-+		.raid_type = raid_type,
-+		.region_size = region_size,
-+		.stripe_size = stripe_size,
-+		.rebuilds = rebuilds,
-+		.flags = flags
-+	};
- 
- 	return dm_tree_node_add_raid_target_with_params(node, size, &params);
- }
- 
--
- /*
-  * Various RAID status versions include:
-  * Versions < 1.5.0 (4 fields):
-@@ -3124,6 +3219,203 @@ bad:
- 	return 0;
- }
- 
-+int dm_tree_node_add_cache_target(struct dm_tree_node *node,
-+				  uint64_t size,
-+				  const char *metadata_uuid,
-+				  const char *data_uuid,
-+				  const char *origin_uuid,
-+				  uint32_t chunk_size,
-+				  uint32_t feature_flags, /* DM_CACHE_FEATURE_* */
-+				  unsigned core_argc,
-+				  char **core_argv,
-+				  char *policy_name,
-+				  unsigned policy_argc,
-+				  char **policy_argv)
-+{
-+	int i;
-+	struct load_segment *seg = NULL;
-+
-+	for (i = 0; dm_segtypes[i].target && !seg; i++) {
-+		if (strcmp("cache", dm_segtypes[i].target))
-+			continue;
-+		if (!(seg = _add_segment(node, dm_segtypes[i].type, size)))
-+			return_0;
-+	}
-+
-+	if (!seg)
-+		return_0;
-+
-+	if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree,
-+						    data_uuid))) {
-+		log_error("Missing cache's data uuid %s.",
-+			  data_uuid);
-+		return 0;
-+	}
-+	if (!_link_tree_nodes(node, seg->pool))
-+		return_0;
-+
-+	if (!(seg->metadata = dm_tree_find_node_by_uuid(node->dtree,
-+							metadata_uuid))) {
-+		log_error("Missing cache's metadata uuid %s.",
-+			  metadata_uuid);
-+		return 0;
-+	}
-+	if (!_link_tree_nodes(node, seg->metadata))
-+		return_0;
-+
-+	seg->chunk_size = chunk_size;
-+
-+	seg->flags = feature_flags;
-+
-+	/* FIXME: validation missing */
-+
-+	seg->core_argc = core_argc;
-+	seg->core_argv = core_argv;
-+
-+	seg->policy_name = policy_name;
-+	seg->policy_argc = policy_argc;
-+	seg->policy_argv = policy_argv;
-+
-+	return 1;
-+}
-+
-+static const char *advance_to_next_word(const char *str, int count)
-+{
-+	int i;
-+	const char *p;
-+
-+	for (p = str, i = 0; i < count; i++, p++)
-+		if (!(p = strchr(p, ' ')))
-+			return NULL;
-+
-+	return p;
-+}
-+
-+/*
-+ * <metadata block size> <#used metadata blocks>/<#total metadata blocks>
-+ * <cache block size> <#used cache blocks>/<#total cache blocks>
-+ * <#read hits> <#read misses> <#write hits> <#write misses>
-+ * <#demotions> <#promotions> <#dirty> <#features> <features>*
-+ * <#core args> <core args>* <policy name> <#policy args> <policy args>*
-+ *
-+ * metadata block size      : Fixed block size for each metadata block in
-+ *                            sectors
-+ * #used metadata blocks    : Number of metadata blocks used
-+ * #total metadata blocks   : Total number of metadata blocks
-+ * cache block size         : Configurable block size for the cache device
-+ *                            in sectors
-+ * #used cache blocks       : Number of blocks resident in the cache
-+ * #total cache blocks      : Total number of cache blocks
-+ * #read hits               : Number of times a READ bio has been mapped
-+ *                            to the cache
-+ * #read misses             : Number of times a READ bio has been mapped
-+ *                            to the origin
-+ * #write hits              : Number of times a WRITE bio has been mapped
-+ *                            to the cache
-+ * #write misses            : Number of times a WRITE bio has been
-+ *                            mapped to the origin
-+ * #demotions               : Number of times a block has been removed
-+ *                            from the cache
-+ * #promotions              : Number of times a block has been moved to
-+ *                            the cache
-+ * #dirty                   : Number of blocks in the cache that differ
-+ *                            from the origin
-+ * #feature args            : Number of feature args to follow
-+ * feature args             : 'writethrough' (optional)
-+ * #core args               : Number of core arguments (must be even)
-+ * core args                : Key/value pairs for tuning the core
-+ *                            e.g. migration_threshold
-+ *			     *policy name              : Name of the policy
-+ * #policy args             : Number of policy arguments to follow (must be even)
-+ * policy args              : Key/value pairs
-+ *                            e.g. sequential_threshold
-+ */
-+int dm_get_status_cache(struct dm_pool *mem, const char *params,
-+			struct dm_status_cache **status)
-+{
-+	int i, feature_argc;
-+	char *str;
-+	const char *p, *pp;
-+	struct dm_status_cache *s;
-+
-+	if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_cache))))
-+		return_0;
-+
-+	/* Read in args that have definitive placement */
-+	if (sscanf(params,
-+		   " %" PRIu32
-+		   " %" PRIu64 "/%" PRIu64
-+		   " %" PRIu32
-+		   " %" PRIu64 "/%" PRIu64
-+		   " %" PRIu64 " %" PRIu64
-+		   " %" PRIu64 " %" PRIu64
-+		   " %" PRIu64 " %" PRIu64
-+		   " %" PRIu64
-+		   " %d",
-+		   &s->metadata_block_size,
-+		   &s->metadata_used_blocks, &s->metadata_total_blocks,
-+		   &s->block_size, /* AKA, chunk_size */
-+		   &s->used_blocks, &s->total_blocks,
-+		   &s->read_hits, &s->read_misses,
-+		   &s->write_hits, &s->write_misses,
-+		   &s->demotions, &s->promotions,
-+		   &s->dirty_blocks,
-+		   &feature_argc) != 14)
-+		goto bad;
-+
-+	/* Now jump to "features" section */
-+	if (!(p = advance_to_next_word(params, 12)))
-+		goto bad;
-+
-+	/* Read in features */
-+	for (i = 0; i < feature_argc; i++) {
-+		if (!strncmp(p, "writethrough ", 13))
-+			s->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
-+		else if (!strncmp(p, "writeback ", 10))
-+			s->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
-+		else
-+			log_error("Unknown feature in status: %s", params);
-+
-+		if (!(p = advance_to_next_word(p, 1)))
-+			goto bad;
-+	}
-+
-+	/* Read in core_args. */
-+	if (sscanf(p, "%d ", &s->core_argc) != 1)
-+		goto bad;
-+	if (s->core_argc &&
-+	    (!(s->core_argv = dm_pool_zalloc(mem, sizeof(char *) * s->core_argc)) ||
-+	     !(p = advance_to_next_word(p, 1)) ||
-+	     !(str = dm_pool_strdup(mem, p)) ||
-+	     !(p = advance_to_next_word(p, s->core_argc)) ||
-+	     (dm_split_words(str, s->core_argc, 0, s->core_argv) != s->core_argc)))
-+		goto bad;
-+
-+	/* Read in policy args */
-+	pp = p;
-+	if (!(p = advance_to_next_word(p, 1)) ||
-+	    !(s->policy_name = dm_pool_zalloc(mem, (p - pp))))
-+		goto bad;
-+	if (sscanf(pp, "%s %d", s->policy_name, &s->policy_argc) != 2)
-+		goto bad;
-+	if (s->policy_argc &&
-+	    (!(s->policy_argv = dm_pool_zalloc(mem, sizeof(char *) * s->policy_argc)) ||
-+	     !(p = advance_to_next_word(p, 1)) ||
-+	     !(str = dm_pool_strdup(mem, p)) ||
-+	     (dm_split_words(str, s->policy_argc, 0, s->policy_argv) != s->policy_argc)))
-+		goto bad;
-+
-+	*status = s;
-+	return 1;
-+
-+bad:
-+	log_error("Failed to parse cache params: %s", params);
-+	dm_pool_free(mem, s);
-+	*status = NULL;
-+
-+	return 0;
-+}
-+
- int dm_tree_node_add_replicator_target(struct dm_tree_node *node,
- 				       uint64_t size,
- 				       const char *rlog_uuid,
-@@ -3614,9 +3906,9 @@ static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct
- }
- 
- int dm_tree_node_add_target_area(struct dm_tree_node *node,
--				    const char *dev_name,
--				    const char *uuid,
--				    uint64_t offset)
-+				 const char *dev_name,
-+				 const char *uuid,
-+				 uint64_t offset)
- {
- 	struct load_segment *seg;
- 	struct stat info;
-diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
-index 3b0e18d..d89e8ae 100644
---- a/liblvm/lvm_lv.c
-+++ b/liblvm/lvm_lv.c
-@@ -507,7 +507,7 @@ static int _lv_set_pool_params(struct lvcreate_params *lp,
- 
- 	lp->pool = pool;
- 
--	lp->create_thin_pool = 1;
-+	lp->create_pool = 1;
- 	lp->segtype = get_segtype_from_string(vg->cmd, "thin-pool");
- 	lp->stripes = 1;
- 
-@@ -757,17 +757,15 @@ struct lvm_property_value lvm_lv_params_get_property(
- 						const lv_create_params_t params,
- 						const char *name)
- {
--	struct lvm_property_value rc = {
--		.is_valid = 0
--	};
--	struct saved_env e = store_user_env(params->vg->cmd);
-+	struct lvm_property_value rc = { .is_valid = 0 };
- 
- 	if (params && params->magic == LV_CREATE_PARAMS_MAGIC) {
-+		struct saved_env e = store_user_env(params->vg->cmd);
- 		rc = get_property(NULL, NULL, NULL, NULL, NULL, &params->lvp, NULL, name);
--	} else {
-+		restore_user_env(&e);
-+	} else
- 		log_error("Invalid lv_create_params parameter");
--	}
--	restore_user_env(&e);
-+
- 	return rc;
- }
- 
-@@ -775,15 +773,14 @@ int lvm_lv_params_set_property(lv_create_params_t params, const char *name,
- 								struct lvm_property_value *prop)
- {
- 	int rc = -1;
--	struct saved_env e = store_user_env(params->vg->cmd);
- 
- 	if (params && params->magic == LV_CREATE_PARAMS_MAGIC) {
-+		struct saved_env e = store_user_env(params->vg->cmd);
- 		rc = set_property(NULL, NULL, NULL, &params->lvp, NULL, name, prop);
--	} else {
-+		restore_user_env(&e);
-+	} else
- 		log_error("Invalid lv_create_params parameter");
--	}
- 
--	restore_user_env(&e);
- 	return rc;
- }
- 
-diff --git a/make.tmpl.in b/make.tmpl.in
-index 65b1da0..7d7d701 100644
---- a/make.tmpl.in
-+++ b/make.tmpl.in
-@@ -84,6 +84,7 @@ pkgconfigdir = $(usrlibdir)/pkgconfig
- initdir = $(DESTDIR)$(sysconfdir)/rc.d/init.d
- systemd_unit_dir = $(DESTDIR)@systemdsystemunitdir@
- systemd_generator_dir = $(DESTDIR)@systemdutildir@/system-generators
-+systemd_dir = $(DESTDIR)@systemdutildir@
- tmpfiles_dir = $(DESTDIR)@tmpfilesdir@
- ocf_scriptdir = $(DESTDIR)@OCFDIR@
- pyexecdir = $(DESTDIR)$(prefix)
-diff --git a/man/lvchange.8.in b/man/lvchange.8.in
-index 49337e4..64231c8 100644
---- a/man/lvchange.8.in
-+++ b/man/lvchange.8.in
-@@ -74,8 +74,9 @@ logical volumes. If autoactivation option is used (\-aay),
- the logical volume is activated only if it matches an item in
- the activation/auto_activation_volume_list set in lvm.conf.
- If this list is not set, then all volumes are considered for
--autoactivation. The autoactivation is not yet supported for
--logical volumes that are part of partial or clustered volume groups.
-+activation. The \-aay option should be also used during system
-+boot so it's possible to select which volumes to activate using
-+the activation/auto_activation_volume_list setting.
- .IP
- If clustered locking is enabled, -aey will activate exclusively
- on one node and -aly will activate only on the local node.
-diff --git a/man/lvconvert.8.in b/man/lvconvert.8.in
-index c8cb2dc..190e221 100644
---- a/man/lvconvert.8.in
-+++ b/man/lvconvert.8.in
-@@ -113,6 +113,30 @@ lvconvert \- convert a logical volume from linear to mirror or snapshot
- .RB [ \-v | \-\-verbose ]
- .RB [ \-\-version ]
- .sp
-+.B lvconvert \-\-type cache-pool
-+.RB [ \-c | \-\-chunksize
-+.IR ChunkSize [ bBsSkKmMgG ]]
-+.RB [ \-\-cachemode
-+.RI { writeback | writethrough }]
-+.RB [[ \-\-poolmetadata
-+.IR CachePoolMetadataLogicalVolume { Name | Path }]
-+|
-+.RB [ \-\-poolmetadatasize
-+.IR CachePoolMetadataSize [ bBsSkKmMgG ]]
-+.IR LogicalVolume [ Path ]
-+.RI [ PhysicalVolume [ Path ][ :PE [ -PE ]]...]
-+.RB [ \-h | \-? | \-\-help ]
-+.RB [ \-v | \-\-verbose ]
-+.RB [ \-\-version ]
-+.sp
-+.B lvconvert \-\-type cache
-+.RB \-\-cachepool
-+.IR CachePoolLV { Name | Path }
-+.IR LogicalVolume [ Path ]
-+.RB [ \-h | \-? | \-\-help ]
-+.RB [ \-v | \-\-verbose ]
-+.RB [ \-\-version ]
-+.sp
- 
- .SH DESCRIPTION
- lvconvert is used to change the segment type (i.e. linear, mirror, etc) or
-@@ -146,6 +170,10 @@ arguments is required.
- .BR \-b ", " \-\-background
- Run the daemon in the background.
- .TP
-+.BR \-\-cachepool " " \fCachePoolLV
-+This argument is necessary when converting a logical volume to a cache LV.
-+For more information on cache pool LVs and cache LVs, see \fBlvm\fP(8).
-+.TP
- .BR \-m ", " \-\-mirrors " " \fIMirrors
- Specifies the degree of the mirror you wish to create.
- For example, "\fB-m 1\fP" would convert the original logical
-@@ -176,9 +204,9 @@ A mirror is divided into regions of this size (in MB), and the mirror log
- uses this granularity to track which regions are in sync.
- .TP
- .B \-\-type \fISegmentType
--Used to convert a logical volume to another segment type or to explicitly state
--the desired RAID1 segment type (\fImirror\fP or \fIraid1\fP) when converting
--a linear logical volume to a mirror with the \fB-m\fP argument.
-+Used to convert a logical volume to another segment type, like cache-pool,
-+cache, raid1, or thin-pool.  When converting a logical volume to a cache LV,
-+the \-\-cachepool argument is required.
- .TP
- .BR \-i ", " \-\-interval " " \fISeconds
- Report progress as a percentage at regular intervals.
-@@ -447,6 +475,18 @@ For the read-only external origin use the new name "vg00/external".
- .sp
- .B lvconvert \-\-thinpool vg00/lvpool \-\-originname external -T vg00/origin
- 
-+Convert an existing logical volume to a cache pool LV using the
-+given cache metadata LV.
-+.sp
-+.B lvconvert --type cache-pool --poolmetadata vg00/lvx_meta vg00/lvx_data
-+.br
-+.B lvrename vg00/lvx_data vg00/lvx_cachepool
-+
-+Convert an existing logical volume to a cache LV using the given
-+cache pool LV.
-+.sp
-+.B lvconvert \-\-type cache  \-\-cachepool vg00/lvx_cachepool vg00/lvx
-+
- .SH SEE ALSO
- .BR lvm (8),
- .BR lvm.conf (5),
-diff --git a/man/lvcreate.8.in b/man/lvcreate.8.in
-index 4a769cb..325baad 100644
---- a/man/lvcreate.8.in
-+++ b/man/lvcreate.8.in
-@@ -59,6 +59,8 @@ lvcreate \- create a logical volume in an existing volume group
- .RI { ReadAheadSectors | auto | none }]
- .RB [ \-t | \-\-test ]
- .RB [ \-T | \-\-thin
-+.RB [ \-\-cachemode
-+.IR { writeback | writethrough }
- .RB [ \-c | \-\-chunksize
- .IR ChunkSize [ bBsSkKmMgG ]]
- .RB [ \-\-discards
-@@ -155,14 +157,29 @@ use \fBlvs\fP command where the state of the flag is reported within
- .TP
- .IR \fB\-K ", " \fB\-\-ignoreactivationskip
- Ignore the flag to skip Logical Volumes during activation.
-+
-+.TP
-+.BR \-\-cachemode " " { writeback | writethrough }
-+Specifying a cache mode determines when the writes to a cache LV
-+are considered complete.  When \fIwriteback\fP is specified, a write is
-+considered complete as soon as it is stored in the cache pool LV.
-+If \fIwritethough\fP is specified, a write is considered complete only
-+when it has been stored in the cache pool LV and on the origin LV.
-+While \fIwritethrough\fP may be slower for writes, it is more
-+resilient if something should happen to a device associated with the
-+cache pool LV.
-+
- .TP
- .BR \-c ", " \-\-chunksize " " \fIChunkSize [ \fIbBsSkKmMgG ]
--Gives the size of chunk for snapshot and thin pool logical volumes.
-+Gives the size of chunk for snapshot, cache pool and thin pool logical volumes.
- Default unit is in kilobytes.
- .br
- For snapshots the value must be power of 2 between 4KiB and 512KiB
- and the default value is 4.
- .br
-+For cache pool LVs the value must be between 32KiB and 1GiB.  The default
-+is 64KiB.  Values must be a multiple of 32KiB.
-+.br
- For thin pools the value must be between 64KiB and
- 1GiB and the default value starts with 64 and scales
- up to fit the pool metadata size within 128MiB,
-@@ -188,7 +205,11 @@ the extra devices which are necessary for parity are
- internally accounted for.  Specifying
- .BI \-i 3
- would use 3 devices for striped logical volumes,
--4 devices for RAID 4/5, and 5 devices for RAID 6.
-+4 devices for RAID 4/5, and 5 devices for RAID 6.  Alternatively,
-+RAID 4/5/6 will stripe across all PVs in the volume group or
-+all of the PVs specified if the
-+.B \-i
-+argument is omitted.
- .TP
- .BR \-I ", " \-\-stripesize " " \fIStripeSize
- Gives the number of kilobytes for the granularity of the stripes.
-@@ -203,14 +224,17 @@ is specified.
- .TP
- .IR \fB\-l ", " \fB\-\-extents " " LogicalExtentsNumber [ % { VG | PVS | FREE | ORIGIN }]
- Gives the number of logical extents to allocate for the new
--logical volume.
-+logical volume.  The total number of physical extents allocated will be
-+greater than this, for example, if the volume is mirrored.
- The number can also be expressed as a percentage of the total space
- in the Volume Group with the suffix \fI%VG\fR, as a percentage of the
- remaining free space in the Volume Group with the suffix \fI%FREE\fR, as a
- percentage of the remaining free space for the specified
- PhysicalVolume(s) with the suffix \fI%PVS\fR, or (for a snapshot) as a
- percentage of the total space in the Origin Logical Volume with the
--suffix \fI%ORIGIN\fR.
-+suffix \fI%ORIGIN\fR.  When expressed as a percentage, the number is treated
-+as an approximate upper limit for the total number of physical extents
-+to be allocated (including extents used by any mirrors, for example).
- .TP
- .IR \fB\-L ", " \fB\-\-size " " LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]
- Gives the size to allocate for the new logical volume.
-@@ -382,6 +406,7 @@ commandline switch alias that will enable their use
- However, this argument must be used when no existing
- commandline switch alias is available for the desired type,
- as is the case with
-+.IR cache ,
- .IR error ,
- .IR raid1 ,
- .IR raid4 ,
-@@ -390,6 +415,9 @@ as is the case with
- .IR raid10
- or
- .IR zero .
-+Note that the cache segment type requires a dm-cache kernel module version
-+1.3.0 or greater.
-+
- .TP
- .BR \-V ", " \-\-virtualsize " " \fIVirtualSize [ \fIbBsSkKmMgGtTpPeE ]
- Creates a sparse device of the given size (in MiB by default) using a snapshot
-@@ -471,8 +499,14 @@ a parity drive for a total of 4 devices) and a stripesize of 64KiB:
- .sp
- .B lvcreate \-\-type raid5 \-L 5G \-i 3 \-I 64 \-n my_lv vg00
- 
-+Creates a RAID5 logical volume "vg00/my_lv", using all of the free
-+space in the VG and spanning all the PVs in the VG:
-+.sp
-+.B lvcreate \-\-type raid5 \-l 100%FREE \-n my_lv vg00
-+
- Creates a 5GiB RAID10 logical volume "vg00/my_lv", with 2 stripes on
--2 2-way mirrors.  Note that the \fB-i\fP and \fB-m\fP arguments behave differently.
-+2 2-way mirrors.  Note that the \fB-i\fP and \fB-m\fP arguments behave
-+differently.
- The \fB-i\fP specifies the number of stripes.
- The \fB-m\fP specifies the number of
- .B additional
-@@ -499,6 +533,23 @@ in vg00 that will use an existing thin pool "vg00/pool":
- .sp
- .B lvcreate -s --thinpool vg00/pool  origin
- 
-+Create a cache pool LV that can later be used to cache one
-+logical volume.
-+.sp
-+.B lvcreate --type cache-pool -L 1G -n my_lv_cachepool vg /dev/fast1
-+
-+If there is an existing cache pool LV, create the large slow
-+device (i.e. the origin LV) and link it to the supplied cache pool LV,
-+creating a cache LV.
-+.sp
-+.B lvcreate --type cache -L 100G -n my_lv vg/my_lv_cachepool /dev/slow1
-+
-+If there is an existing logical volume, create the small and fast
-+cache pool LV and link it to the supplied existing logical
-+volume (i.e. the origin LV), creating a cache LV.
-+.sp
-+.B lvcreate --type cache -L 1G -n my_lv_cachepool vg/my_lv /dev/fast1
-+
- .SH SEE ALSO
- .BR lvm (8),
- .BR lvm.conf (5),
-diff --git a/man/lvextend.8.in b/man/lvextend.8.in
-index c51a9dc..d9bc0c8 100644
---- a/man/lvextend.8.in
-+++ b/man/lvextend.8.in
-@@ -45,6 +45,8 @@ Proceed with size extension without prompting.
- Extend or set the logical volume size in units of logical extents.
- With the '\fI+\fP' sign the value is added to the actual size
- of the logical volume and without it, the value is taken as an absolute one.
-+The total number of physical extents allocated will be
-+greater than this, for example, if the volume is mirrored.
- The number can also be expressed as a percentage of the total space
- in the Volume Group with the suffix \fI%VG\fP, relative to the existing
- size of the Logical Volume with the suffix \fI%LV\fP, of the remaining
-@@ -53,6 +55,11 @@ as a percentage of the remaining free space in the Volume Group
- with the suffix \fI%FREE\fP, or (for a snapshot) as a percentage of the total
- space in the Origin Logical Volume with the suffix \fI%ORIGIN\fP.
- The resulting value is rounded upward.
-+N.B. In a future release, when expressed as a percentage with PVS, VG or FREE,
-+the number will be treated as an approximate upper limit for the total number
-+of physical extents to be allocated (including extents used by any mirrors, for
-+example).  The code may currently allocate more space than you might otherwise
-+expect.
- .TP
- .IR \fB\-L ", " \fB\-\-size " [" + ] LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]
- Extend or set the logical volume size in units of megabytes.
-diff --git a/man/lvm.8.in b/man/lvm.8.in
-index d78281a..39e47d3 100644
---- a/man/lvm.8.in
-+++ b/man/lvm.8.in
-@@ -56,6 +56,8 @@ loading \fBlvm.conf\fP(5) and any other configuration files.
- .TP
- \fBsegtypes\fP \(em Display recognised Logical Volume segment types.
- .TP
-+\fBtags\fP \(em Display any tags defined on this host.
-+.TP
- \fBversion\fP \(em Display version information.
- .LP
- .SH COMMANDS
-@@ -301,6 +303,12 @@ is executed.
- The Volume Group name that is assumed for
- any reference to a Logical Volume that doesn't specify a path.
- Not set by default.
-+.TP
-+.B LVM_LVMETAD_PIDFILE
-+Path for the lvmetad pid file.
-+.TP
-+.B LVM_LVMETAD_SOCKET
-+Path for the lvmetad socket file.
- .SH VALID NAMES
- The following characters are valid for VG and LV names:
- .B a-z A-Z 0-9 + _ . -
-@@ -381,6 +389,197 @@ discretion over the layout.
- To view the way the allocation process currently works in any specific
- case, read the debug logging output, for example by adding \fB\-vvvv\fP to
- a command.
-+
-+.SH LOGICAL VOLUME TYPES
-+Some logical volume types are simple to create and can be done with a
-+single \fBlvcreate\fP(8) command.  The linear and striped logical
-+volume types are an example of this.  Other logical volume types may
-+require more than one command to create.  The cache and thin provisioning
-+types are examples of this.
-+
-+.br
-+.SS Cache
-+The \fIcache\fP logical volume type uses a small and fast LV to improve
-+the performance of a large and slow LV.  It does this by storing the
-+frequently used blocks on the faster LV.
-+LVM refers to the small fast LV as a \fBcache pool LV\fP.  The large
-+slow LV is called the \fBorigin LV\fP.  Due to requirements from dm-cache
-+(the kernel driver), LVM further splits the cache pool LV into two
-+devices - the \fBcache data LV\fP and \fBcache metadata LV\fP.  The cache
-+data LV is where copies of data blocks are kept from the
-+origin LV to increase speed.  The cache metadata LV holds the
-+accounting information that specifies where data blocks are stored (e.g.
-+on the origin LV or on the cache data LV).  Users should be familiar with
-+these LVs if they wish to create the best and most robust cached
-+logical volumes.
-+
-+.SS Cache Terms
-+.nf
-+origin LV           OriginLV      large slow LV
-+cache data LV       CacheDataLV   small fast LV for cache pool data
-+cache metadata LV   CacheMetaLV   small fast LV for cache pool metadata
-+cache pool LV       CachePoolLV   CacheDataLV + CacheMetaLV
-+cache LV            CacheLV       OriginLV + CachePoolLV
-+.fi
-+
-+.SS Cache Steps
-+The steps to create a logical volume of \fIcache\fP type are as follows:
-+.TP
-+0.
-+Create an LV or identify an existing LV to be the origin LV.
-+.TP
-+1.
-+Create the cache data LV.  The size of this LV is the size of the cache
-+and will be reported as the size of the cache pool LV.
-+.TP
-+2.
-+Create the cache metadata LV.
-+The size of this LV should be 1000 times smaller than the cache data LV
-+with a minimum size of 8MiB.
-+.TP
-+3.
-+Create the cache pool LV by combining the cache data LV (from step 1)
-+and cache metadata LV (from step 2).  When performing this step,
-+behavioral characteristics of the cache pool LV can be set.
-+The name of the cache pool LV takes the name of the cache data LV and
-+the cache data LV and cache metadata LV are renamed
-+to CachePoolLV_cdata and CachePoolLV_cmeta.
-+.TP
-+4.
-+Create a cache LV by linking the cache pool LV to the origin LV.
-+The user accessible cache LV takes the name of the origin LV,
-+while the origin LV becomes a hidden LV with the name
-+OriginLV_corig.  Users can perform this step while the origin LV
-+is in use.
-+
-+.P
-+The steps above represent the best way to create a cache LV.
-+They provide the most options and have the ability to create the
-+most robust logical volumes.  The examples below illustrate how these
-+steps might be used in practice.
-+
-+.SS Cache Commands
-+.nf
-+0. create OriginLV
-+lvcreate -L LargeSize -n OriginLV VG SlowPVs
-+
-+1. create CacheDataLV
-+lvcreate -L CacheSize -n CacheDataLV VG FastPVs
-+
-+2. create CacheMetaLV
-+lvcreate -L MetaSize -n CacheMetaLV VG FastPVs
-+
-+3. create CachePoolLV
-+lvconvert --type cache-pool --poolmetadata VG/CacheMetaLV VG/CacheDataLV
-+CachePoolLV takes the name of CacheDataLV.
-+CacheDataLV is renamed CachePoolLV_cdata and becomes hidden.
-+CacheMetaLV is renamed CachePoolLV_cmeta and becomes hidden.
-+
-+4. create CacheLV
-+lvconvert --type cache --cachepool VG/CachePoolLV VG/OriginLV
-+CacheLV takes the name of OriginLV.
-+OriginLV is renamed OriginLV_corig and becomes hidden.
-+.fi
-+
-+.SS Cache Examples
-+
-+.B Example 1:
-+Creating a simple cache LV.
-+.br
-+
-+.nf
-+0. Create the origin LV
-+# lvcreate -L 10G -n lvx vg /dev/slow_dev
-+
-+1. Create a cache data LV
-+# lvcreate -L 1G -n lvx_cache vg /dev/fast_dev
-+
-+2. Create a cache metadata LV (~1/1000th size of CacheDataLV or 8MiB)
-+# lvcreate -L 8M -n lvx_cache_meta vg /dev/fast_dev
-+
-+3. Create a cache pool LV, combining cache data LV and cache metadata LV
-+# lvconvert --type cache-pool --poolmetadata vg/lvx_cache_meta \\
-+	vg/lvx_cache
-+
-+4. Create a cached LV by combining the cache pool LV and origin LV
-+# lvconvert --type cache --cachepool vg/lvx_cache vg/lvx
-+.fi
-+
-+.B Example 2:
-+Creating a cache LV with a fault tolerant cache pool LV.
-+
-+Users who are concerned about the possibility of failures in their fast devices
-+that could lead to data loss might consider making their cache pool sub-LVs
-+redundant.  Example 2 illustrates how to do that.  Note that only steps
-+1 & 2 change.
-+
-+.nf
-+0. Create an origin LV we wish to cache
-+# lvcreate -L 10G -n lvx vg /dev/slow_devs
-+
-+1. Create a 2-way RAID1 cache data LV
-+# lvcreate --type raid1 -m 1 -L 1G -n lvx_cache vg \\
-+	/dev/fast1 /dev/fast2
-+
-+2. Create a 2-way RAID1 cache metadata LV
-+# lvcreate --type raid1 -m 1 -L 8M -n lvx_cache_meta vg \\
-+	/dev/fast1 /dev/fast2
-+
-+3. Create a cache pool LV combining cache data LV and cache metadata LV
-+# lvconvert --type cache-pool --poolmetadata vg/lvx_cache_meta \\
-+	vg/lvx_cache
-+
-+4. Create a cached LV by combining the cache pool LV and origin LV
-+# lvconvert --type cache --cachepool vg/lvx_cache vg/lvx
-+.fi
-+
-+.B Example 3:
-+Creating a simple cache LV with \fIwritethough\fP caching.
-+
-+Some users wish to ensure that any data written will be stored both in the
-+cache pool LV and on the origin LV.  The loss of a device associated with
-+the cache pool LV in this case would not mean the loss of any data.  When
-+combining the cache data LV and the cache metadata LV to form the cache pool
-+LV, properties of the cache can be specified - in this case,
-+\fIwritethrough\fP vs. \fIwriteback\fP.  Note that only step 3 is affected
-+in this case.
-+
-+.nf
-+0. Create an origin LV we wish to cache (yours may already exist)
-+# lvcreate -L 10G -n lvx vg /dev/slow
-+
-+1. Create a cache data LV
-+# lvcreate -L 1G -n lvx_cache vg /dev/fast
-+
-+2. Create a cache metadata LV
-+# lvcreate -L 8M -n lvx_cache_meta vg /dev/fast
-+
-+3. Create a cache pool LV specifying cache mode "writethrough"
-+# lvconvert --type cache-pool --poolmetadata vg/lvx_cache_meta \\
-+	--cachemode writethrough vg/lvx_cache
-+
-+4. Create a cache LV by combining the cache pool LV and origin LV
-+# lvconvert --type cache --cachepool vg/lvx_cache vg/lvx
-+.fi
-+
-+.SS Removing Cache Logical Volumes
-+If you wish to remove all logical volumes associated with a cache
-+LV, you must remove both top-level, user-visible devices.
-+The cache metadata LV and cache data LV cannot be removed
-+directly.  If only the cache pool LV is specfied for removal, any cached
-+blocks not yet on the origin LV will be flush, the cache pool LV will be
-+removed, and the now un-cached origin LV will remain.  If the user
-+specifies a cache LV for removal, then the origin LV is
-+removed and only the cache pool LV will remain.  The cache pool LV can then
-+be used to create another cache LV with a different origin LV if desired.
-+
-+When users intend to remove all logical volumes associated with a
-+cache LV, it is generally better to start with the origin LV and then
-+remove the cache pool LV.  If the operations are performed in the
-+reverse order, the user will have to wait for the contents of the
-+cache pool LV to be flushed before the origin LV is removed.  This
-+could take some time.
-+
- .SH DIAGNOSTICS
- All tools return a status code of zero on success or non-zero on failure.
- .SH FILES
-diff --git a/man/lvm.conf.5.in b/man/lvm.conf.5.in
-index 2786df2..73fcf47 100644
---- a/man/lvm.conf.5.in
-+++ b/man/lvm.conf.5.in
-@@ -102,7 +102,7 @@ e.g.	backup {
- .br
- An assignment associates a type with an identifier.
- .br
--e.g.	max_archives = 42
-+e.g.	level = 7
- .br
- .TP
- .BR array " =  '" [ "' ( " type " '" , "')* " type " '" ] "' | '" [ "' '" ] '
-diff --git a/man/lvreduce.8.in b/man/lvreduce.8.in
-index 2c38f5b..2b0f3f8 100644
---- a/man/lvreduce.8.in
-+++ b/man/lvreduce.8.in
-@@ -51,6 +51,8 @@ Reduce or set the logical volume size in units of logical extents.
- With the \fI-\fP sign the value will be subtracted from
- the logical volume's actual size and without it the value will be taken
- as an absolute size.
-+The total number of physical extents freed will be greater than this logical
-+value if, for example, the volume is mirrored.
- The number can also be expressed as a percentage of the total space
- in the Volume Group with the suffix \fI%VG\fP, relative to the existing
- size of the Logical Volume with the suffix \fI%LV\fP, as a percentage of the
-@@ -59,6 +61,10 @@ a snapshot) as a percentage of the total space in the Origin Logical
- Volume with the suffix \fI%ORIGIN\fP.
- The resulting value for the subtraction is rounded downward, for the absolute
- size it is rounded upward.
-+N.B. In a future release, when expressed as a percentage with VG or FREE, the
-+number will be treated as an approximate total number of physical extents to be
-+freed (including extents used by any mirrors, for example).  The code may
-+currently release more space than you might otherwise expect.
- .TP
- .IR \fB\-L ", " \fB\-\-size " [" \- ] LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]
- Reduce or set the logical volume size in units of megabytes.
-diff --git a/man/lvresize.8.in b/man/lvresize.8.in
-index 3606762..75d20a0 100644
---- a/man/lvresize.8.in
-+++ b/man/lvresize.8.in
-@@ -49,6 +49,8 @@ Resize underlying filesystem together with the logical volume using
- Change or set the logical volume size in units of logical extents.
- With the \fI+\fP or \fI-\fP sign the value is added to or subtracted from the actual size
- of the logical volume and without it, the value is taken as an absolute one.
-+The total number of physical extents affected will be
-+greater than this if, for example, the volume is mirrored.
- The number can also be expressed as a percentage of the total space
- in the Volume Group with the suffix \fI%VG\fP, relative to the existing
- size of the Logical Volume with the suffix \fI%LV\fP, as a percentage of
-@@ -58,6 +60,11 @@ Volume Group with the suffix \fI%FREE\fP, or (for a snapshot) as a percentage
- of the total space in the Origin Logical Volume with the suffix \fI%ORIGIN\fP.
- The resulting value is rounded downward for the subtraction otherwise
- it is rounded upward.
-+N.B. In a future release, when expressed as a percentage with PVS, VG or FREE,
-+the number will be treated as an approximate total number of physical extents
-+to be allocated or freed (including extents used by any mirrors, for example).
-+The code may currently allocate or remove more space than you might otherwise
-+expect.
- .TP
- .IR \fB\-L ", " \fB\-\-size " [" + | - ] LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]
- Change or set the logical volume size in units of megabytes.
-@@ -88,7 +95,9 @@ Defaults to whatever the last segment of the Logical Volume uses.
- Not applicable to LVs using the original metadata LVM format, which
- must use a single value throughout.
- .br
--StripeSize must be 2^n (n = 2 to 9).
-+StripeSize must be 2^n (n = 2 to 9) for metadata in LVM1 format.
-+For metadata in LVM2 format, the stripe size may be a larger
-+power of 2 but must not exceed the physical extent size.
- .TP
- .B \-\-noudevsync
- Disable udev synchronisation. The
-diff --git a/man/lvs.8.in b/man/lvs.8.in
-index 8427aca..95eb25a 100644
---- a/man/lvs.8.in
-+++ b/man/lvs.8.in
-@@ -135,12 +135,12 @@ can also be chosen.
- The lv_attr bits are:
- .RS
- .IP 1 3
--Volume type: (m)irrored, (M)irrored without initial sync, (o)rigin,
-+Volume type: (C)ache, (m)irrored, (M)irrored without initial sync, (o)rigin,
- (O)rigin with merging snapshot, (r)aid, (R)aid without initial sync,
- (s)napshot, merging (S)napshot, (p)vmove, (v)irtual,
- mirror or raid (i)mage, mirror or raid (I)mage out-of-sync, mirror (l)og device,
- under (c)onversion, thin (V)olume, (t)hin pool, (T)hin pool data, raid or
--thin pool m(e)tadata or pool metadata spare.
-+pool m(e)tadata or pool metadata spare.
- .IP 2 3
- Permissions: (w)riteable, (r)ead-only, (R)ead-only activation of non-read-only
- volume
-diff --git a/man/vgchange.8.in b/man/vgchange.8.in
-index 823d134..16adf4df 100644
---- a/man/vgchange.8.in
-+++ b/man/vgchange.8.in
-@@ -76,9 +76,10 @@ In other words, makes the logical volumes known/unknown to the kernel.
- If autoactivation option is used (\-aay), each logical volume in
- the volume group is activated only if it matches an item in the
- activation/auto_activation_volume_list set in lvm.conf. If this
--list is not set, then all volumes are considered for autoactivation.
--The autoactivation is not yet supported for partial or clustered
--volume groups.
-+list is not set, then all volumes are considered for activation.
-+The \-aay option should be also used during system boot so it's
-+possible to select which volumes to activate using the
-+activation/auto_activation_volume_list settting.
- .IP
- If clustered locking is enabled, add 'e' to activate/deactivate
- exclusively on one node or 'l' to activate/deactivate only
-diff --git a/python/liblvm.c b/python/liblvm.c
-index 6abd5ff..094aec2 100644
---- a/python/liblvm.c
-+++ b/python/liblvm.c
-@@ -1043,22 +1043,22 @@ static PyObject *_liblvm_lvm_vg_list_lvs(vgobject *self)
- 
- static PyObject *_liblvm_lvm_vg_get_tags(vgobject *self)
- {
--	struct dm_list *tags;
-+	struct dm_list *tagsl;
- 	struct lvm_str_list *strl;
- 	PyObject * pytuple;
- 	int i = 0;
- 
- 	VG_VALID(self);
- 
--	if (!(tags = lvm_vg_get_tags(self->vg))) {
-+	if (!(tagsl = lvm_vg_get_tags(self->vg))) {
- 		PyErr_SetObject(_LibLVMError, _liblvm_get_last_error());
- 		return NULL;
- 	}
- 
--	if (!(pytuple = PyTuple_New(dm_list_size(tags))))
-+	if (!(pytuple = PyTuple_New(dm_list_size(tagsl))))
- 		return NULL;
- 
--	dm_list_iterate_items(strl, tags) {
-+	dm_list_iterate_items(strl, tagsl) {
- 		PyTuple_SET_ITEM(pytuple, i, PyString_FromString(strl->str));
- 		i++;
- 	}
-@@ -1163,8 +1163,9 @@ static PyObject *_liblvm_lvm_vg_create_lv_thin(vgobject *self, PyObject *args)
- static void liblvm_lv_dealloc(lvobject *self)
- {
- 	/* We can dealloc an object that didn't get fully created */
--	if (self->parent_vgobj)
-+	if (self->parent_vgobj) {
- 		Py_DECREF(self->parent_vgobj);
-+	}
- 
- 	PyObject_Del(self);
- }
-@@ -1291,11 +1292,13 @@ static PyObject *_liblvm_lvm_pv_from_uuid(vgobject *self, PyObject *arg)
- 
- static void _liblvm_pv_dealloc(pvobject *self)
- {
--	if (self->parent_vgobj)
-+	if (self->parent_vgobj) {
- 		Py_DECREF(self->parent_vgobj);
-+	}
- 
--	if (self->parent_pvslistobj)
-+	if (self->parent_pvslistobj) {
- 		Py_DECREF(self->parent_pvslistobj);
-+	}
- 
- 	self->parent_vgobj = NULL;
- 	self->parent_pvslistobj = NULL;
-@@ -1474,22 +1477,22 @@ static PyObject *_liblvm_lvm_lv_remove_tag(lvobject *self, PyObject *args)
- 
- static PyObject *_liblvm_lvm_lv_get_tags(lvobject *self)
- {
--	struct dm_list *tags;
-+	struct dm_list *tagsl;
- 	struct lvm_str_list *strl;
- 	PyObject * pytuple;
- 	int i = 0;
- 
- 	LV_VALID(self);
- 
--	if (!(tags = lvm_lv_get_tags(self->lv))) {
-+	if (!(tagsl = lvm_lv_get_tags(self->lv))) {
- 		PyErr_SetObject(_LibLVMError, _liblvm_get_last_error());
- 		return NULL;
- 	}
- 
--	if (!(pytuple = PyTuple_New(dm_list_size(tags))))
-+	if (!(pytuple = PyTuple_New(dm_list_size(tagsl))))
- 		return NULL;
- 
--	dm_list_iterate_items(strl, tags) {
-+	dm_list_iterate_items(strl, tagsl) {
- 		PyTuple_SET_ITEM(pytuple, i, PyString_FromString(strl->str));
- 		i++;
- 	}
-diff --git a/scripts/Makefile.in b/scripts/Makefile.in
-index ed587ca..8fdb5f7 100644
---- a/scripts/Makefile.in
-+++ b/scripts/Makefile.in
-@@ -111,6 +111,14 @@ ifeq ("@BUILD_LVMETAD@", "yes")
- 	$(INSTALL_DATA) lvm2_lvmetad_systemd_red_hat.service $(systemd_unit_dir)/lvm2-lvmetad.service
- 	$(INSTALL_DATA) lvm2_pvscan_systemd_red_hat@.service $(systemd_unit_dir)/lvm2-pvscan@.service
- endif
-+ifneq ("@CLVMD@", "none")
-+	$(INSTALL_DATA) lvm2_clvmd_systemd_red_hat.service $(systemd_unit_dir)/lvm2-clvmd.service
-+	$(INSTALL_DATA) lvm2_cluster_activation_systemd_red_hat.service $(systemd_unit_dir)/lvm2-cluster-activation.service
-+	$(INSTALL_DATA) lvm2_cluster_activation_red_hat.sh $(systemd_dir)/lvm2-cluster-activation
-+endif
-+ifeq ("@BUILD_CMIRRORD@", "yes")
-+	$(INSTALL_DATA) lvm2_cmirrord_systemd_red_hat.service $(systemd_unit_dir)/lvm2-cmirrord.service
-+endif
- 
- install_tmpfiles_configuration:
- 	$(INSTALL_DIR) $(tmpfiles_dir)
-@@ -124,4 +132,7 @@ DISTCLEAN_TARGETS += clvmd_init_red_hat cmirrord_init_red_hat \
- 		     lvm2_pvscan_systemd_red_hat@.service \
- 		     lvm2_tmpfiles_red_hat.conf blk_availability_init_red_hat \
- 		     blk_availability_systemd_red_hat.service \
--		     blkdeactivate.sh
-+		     blkdeactivate.sh lvm2_clvmd_systemd_red_hat.service \
-+		     lvm2_cmirrord_systemd_red_hat.service \
-+		     lvm2_cluster_activation_systemd_red_hat.service \
-+		     lvm2_cluster_activation_red_hat.sh
-diff --git a/scripts/dm_event_systemd_red_hat.service.in b/scripts/dm_event_systemd_red_hat.service.in
-index 96c5225..3791618 100644
---- a/scripts/dm_event_systemd_red_hat.service.in
-+++ b/scripts/dm_event_systemd_red_hat.service.in
-@@ -7,9 +7,8 @@ Before=local-fs.target
- DefaultDependencies=no
- 
- [Service]
--Type=forking
--ExecStart=@sbindir@/dmeventd
--ExecReload=@sbindir@/dmeventd -R
-+Type=simple
-+ExecStart=@sbindir@/dmeventd -f
- Environment=SD_ACTIVATION=1
- PIDFile=@DMEVENTD_PIDFILE@
- OOMScoreAdjust=-1000
-diff --git a/scripts/lvm2_activation_generator_systemd_red_hat.c b/scripts/lvm2_activation_generator_systemd_red_hat.c
-index f2e2e49..07a2563 100644
---- a/scripts/lvm2_activation_generator_systemd_red_hat.c
-+++ b/scripts/lvm2_activation_generator_systemd_red_hat.c
-@@ -150,7 +150,7 @@ static int generate_unit(const char *dir, int unit)
- 		      "[Service]\n", f);
- 	}
- 
--	fputs("ExecStart=" LVM_PATH " vgchange -aay --sysinit\n"
-+	fputs("ExecStart=" LVM_PATH " vgchange -aay --sysinit --ignoreskippedcluster\n"
- 	      "Type=oneshot\n", f);
- 
- 	if (fclose(f) < 0) {
-diff --git a/scripts/lvm2_cluster_activation_red_hat.sh.in b/scripts/lvm2_cluster_activation_red_hat.sh.in
-new file mode 100644
-index 0000000..0d4676c
---- /dev/null
-+++ b/scripts/lvm2_cluster_activation_red_hat.sh.in
-@@ -0,0 +1,70 @@
-+#!/bin/bash
-+
-+sbindir=@sbindir@
-+
-+lvm_vgchange=${sbindir}/vgchange
-+lvm_vgscan=${sbindir}/vgscan
-+lvm_vgs=${sbindir}/vgs
-+lvm_lvm=${sbindir}/lvm
-+
-+parse_clustered_vgs() {
-+	while read -r name attrs;
-+	do
-+		test "${attrs:5:1}" == 'c' && echo -n "$name "
-+	done
-+}
-+
-+# NOTE: replace this with vgs, once display filter per attr is implemented.
-+clustered_vgs() {
-+	${lvm_vgs} -o vg_name,vg_attr --noheadings | parse_clustered_vgs
-+}
-+
-+activate() {
-+	eval local $(${lvm_lvm} dumpconfig devices/obtain_device_list_from_udev 2>/dev/null) 2>/dev/null
-+	if [ $? -ne 0 ]; then
-+		echo "Warning: expected single couple of key=value in output of dumpconfig"
-+	fi
-+
-+	if [ -z $obtain_device_list_from_udev -o $obtain_device_list_from_udev -ne 1 ]; then
-+		echo -n "lvm.conf option obtain_device_list_from_udev!=1: Executing vgscan"
-+		${lvm_vgscan} > /dev/null 2>&1
-+	fi
-+
-+	echo -n "Activating ${LVM_VGS:-"all VG(s)"}: "
-+	# Respect activation/auto_activation_volume_list!
-+	# Call "-aay" which is equal to "-aly" but respects this list.
-+        ${lvm_vgchange} -aay $LVM_VGS || return 1
-+
-+	return 0
-+}
-+
-+deactivate()
-+{
-+	# NOTE: following section will be replaced by blkdeactivate script
-+	# with option supporting request to deactivate all clustered volume
-+	# groups in the system
-+	[ -z $LVM_VGS ] && LVM_VGS="$(clustered_vgs)"
-+	if [ -n "$LVM_VGS" ]; then
-+		echo -n "Deactivating clustered VG(s): "
-+		${lvm_vgchange} -anl $LVM_VGS || return 1
-+	fi
-+
-+	return 0
-+}
-+
-+case "$1" in
-+  deactivate)
-+	deactivate
-+	rtrn=$?
-+	;;
-+  activate)
-+	activate
-+	rtrn=$?
-+	;;
-+  *)
-+	echo $"Usage: $0 {activate|deactivate}"
-+	rtrn=3
-+	;;
-+esac
-+
-+exit $rtrn
-diff --git a/scripts/lvm2_cluster_activation_systemd_red_hat.service.in b/scripts/lvm2_cluster_activation_systemd_red_hat.service.in
-new file mode 100644
-index 0000000..970e93a
---- /dev/null
-+++ b/scripts/lvm2_cluster_activation_systemd_red_hat.service.in
-@@ -0,0 +1,17 @@
-+[Unit]
-+Description=Clustered LVM volumes activation service
-+Requires=lvm2-clvmd.service
-+After=lvm2-clvmd.service lvm2-cmirrord.service
-+OnFailure=lvm2-clvmd.service
-+DefaultDependencies=no
-+Conflicts=shutdown.target
-+
-+[Service]
-+Type=simple
-+RemainAfterExit=yes
-+EnvironmentFile=-@sysconfdir@/sysconfig/clvmd
-+ExecStart=@systemdutildir@/lvm2-cluster-activation activate
-+ExecStop=@systemdutildir@/lvm2-cluster-activation deactivate
-+
-+[Install]
-+WantedBy=multi-user.target
-diff --git a/scripts/lvm2_clvmd_systemd_red_hat.service.in b/scripts/lvm2_clvmd_systemd_red_hat.service.in
-new file mode 100644
-index 0000000..2978d21
---- /dev/null
-+++ b/scripts/lvm2_clvmd_systemd_red_hat.service.in
-@@ -0,0 +1,23 @@
-+[Unit]
-+Description=Clustered LVM daemon
-+Documentation=man:clvmd(8)
-+After=dlm.service corosync.service
-+Before=remote-fs.target
-+Requires=network.target dlm.service corosync.service
-+RefuseManualStart=true
-+RefuseManualStop=true
-+StopWhenUnneeded=true
-+DefaultDependencies=no
-+Conflicts=shutdown.target
-+
-+[Service]
-+Type=forking
-+Environment=CLVMD_OPTS=-T30
-+EnvironmentFile=-@sysconfdir@/sysconfig/clvmd
-+ExecStart=@sbindir@/clvmd $CLVMD_OPTS
-+SuccessExitStatus=5
-+TimeoutStartSec=30
-+TimeoutStopSec=10
-+OOMScoreAdjust=-1000
-+Restart=on-abort
-+PIDFile=@CLVMD_PIDFILE@
-diff --git a/scripts/lvm2_cmirrord_systemd_red_hat.service.in b/scripts/lvm2_cmirrord_systemd_red_hat.service.in
-new file mode 100644
-index 0000000..16d38ce
---- /dev/null
-+++ b/scripts/lvm2_cmirrord_systemd_red_hat.service.in
-@@ -0,0 +1,17 @@
-+[Unit]
-+Description=Clustered LVM mirror log daemon
-+Documentation=man:cmirrord(8)
-+Requires=corosync.service
-+After=corosync.service
-+Before=remote-fs.target
-+DefaultDependencies=no
-+Conflicts=shutdown.target
-+
-+[Service]
-+Type=forking
-+ExecStart=@sbindir@/cmirrord
-+PIDFile=@CMIRRORD_PIDFILE@
-+Restart=on-abort
-+
-+[Install]
-+WantedBy=multi-user.target
-diff --git a/scripts/lvm2_lvmetad_systemd_red_hat.service.in b/scripts/lvm2_lvmetad_systemd_red_hat.service.in
-index 0150726..8f4c60d 100644
---- a/scripts/lvm2_lvmetad_systemd_red_hat.service.in
-+++ b/scripts/lvm2_lvmetad_systemd_red_hat.service.in
-@@ -7,10 +7,9 @@ DefaultDependencies=no
- Conflicts=shutdown.target
- 
- [Service]
--Type=forking
-+Type=simple
- NonBlocking=true
--ExecStart=@sbindir@/lvmetad
--ExecReload=@sbindir@/lvmetad -R
-+ExecStart=@sbindir@/lvmetad -f
- Environment=SD_ACTIVATION=1
- Restart=on-abort
- PIDFile=@LVMETAD_PIDFILE@
-diff --git a/scripts/lvm2_monitoring_init_red_hat.in b/scripts/lvm2_monitoring_init_red_hat.in
-index cae652c..44de07f 100644
---- a/scripts/lvm2_monitoring_init_red_hat.in
-+++ b/scripts/lvm2_monitoring_init_red_hat.in
-@@ -48,10 +48,10 @@ start()
- {
- 	ret=0
- 	# TODO do we want to separate out already active groups only?
--	VGSLIST=`$VGS --noheadings -o name --config 'log{command_names=0 prefix="  "}' 2> /dev/null`
-+	VGSLIST=`$VGS --noheadings -o name --ignoreskippedcluster --config 'log{command_names=0 prefix="  "}' 2> /dev/null`
- 	for vg in $VGSLIST
- 	do
--	    action "Starting monitoring for VG $vg:" $VGCHANGE --monitor y --poll y --config 'log{command_names=0 prefix="  "}' $vg || ret=$?
-+	    action "Starting monitoring for VG $vg:" $VGCHANGE --monitor y --poll y --ignoreskippedcluster --config 'log{command_names=0 prefix="  "}' $vg || ret=$?
- 	done
- 
- 	return $ret
-@@ -66,10 +66,10 @@ stop()
- 	   echo "Not stopping monitoring, this is a dangerous operation. Please use force-stop to override."
- 	   return 1
- 	fi
--	VGSLIST=`$VGS --noheadings -o name --config 'log{command_names=0 prefix="  "}' 2> /dev/null`
-+	VGSLIST=`$VGS --noheadings -o name --ignoreskippedcluster --config 'log{command_names=0 prefix="  "}' 2> /dev/null`
- 	for vg in $VGSLIST
- 	do
--	    action "Stopping monitoring for VG $vg:" $VGCHANGE --monitor n --config 'log{command_names=0 prefix="  "}' $vg || ret=$?
-+	    action "Stopping monitoring for VG $vg:" $VGCHANGE --monitor n --ignoreskippedcluster --config 'log{command_names=0 prefix="  "}' $vg || ret=$?
- 	done
- 	return $ret
- }
-diff --git a/scripts/lvm2_monitoring_systemd_red_hat.service.in b/scripts/lvm2_monitoring_systemd_red_hat.service.in
-index 670d0c4..05f911b 100644
---- a/scripts/lvm2_monitoring_systemd_red_hat.service.in
-+++ b/scripts/lvm2_monitoring_systemd_red_hat.service.in
-@@ -10,9 +10,9 @@ Conflicts=shutdown.target
- [Service]
- Type=oneshot
- Environment=LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES=1
--ExecStart=@sbindir@/lvm vgchange --monitor y
-+ExecStart=@sbindir@/lvm vgchange --monitor y --ignoreskippedcluster
- # The lvmetad must be disabled here, it needs https://bugzilla.redhat.com/show_bug.cgi?id=843587 to be resolved first.
--ExecStop=@sbindir@/lvm vgchange --monitor n --config 'global{use_lvmetad=0}'
-+ExecStop=@sbindir@/lvm vgchange --monitor n --config 'global{use_lvmetad=0}' --ignoreskippedcluster
- RemainAfterExit=yes
- 
- [Install]
-diff --git a/test/api/pytest.sh b/test/api/pytest.sh
-index a0f9a2f..8359c01 100644
---- a/test/api/pytest.sh
-+++ b/test/api/pytest.sh
-@@ -20,19 +20,20 @@
- # Until fixed - testing always runs with enabled monitoring
- # thus it needs dmeventd
- #
--aux prepare_dmeventd
--test ! -e LOCAL_CLVMD || skip
--test ! -e LOCAL_LVMETAD || skip
--
--#If you change this change the unit test case too.
--aux prepare_pvs 6
- 
- #Locate the python binding library to use.
- python_lib=$(find $abs_top_builddir -name lvm.so)
--
- # Unable to test python bindings if library not available
- test -n "$python_lib" || skip
- 
-+test -e LOCAL_CLVMD && skip
-+test -e LOCAL_LVMETAD && skip
-+
-+aux prepare_dmeventd
-+
-+#If you change this change the unit test case too.
-+aux prepare_pvs 6
-+
- export PYTHONPATH=$(dirname $python_lib):$PYTHONPATH
- 
- #Setup which devices the unit test can use.
-diff --git a/test/lib/aux.sh b/test/lib/aux.sh
-index 2a882a2..66ed910 100644
---- a/test/lib/aux.sh
-+++ b/test/lib/aux.sh
-@@ -52,6 +52,7 @@ prepare_clvmd() {
- 
- prepare_dmeventd() {
- 	if pgrep dmeventd ; then
-+		rm -f debug.log
- 		echo "Cannot test dmeventd with real dmeventd ($(pgrep dmeventd)) running."
- 		skip
- 	fi
-@@ -392,6 +393,7 @@ disable_dev() {
- enable_dev() {
- 	local dev
- 
-+	rm -f debug.log
- 	init_udev_transaction
- 	for dev in "$@"; do
- 		local name=$(echo "$dev" | sed -e 's,.*/,,')
-@@ -536,7 +538,7 @@ generate_config() {
- devices/dir = "$DM_DEV_DIR"
- devices/scan = "$DM_DEV_DIR"
- devices/filter = "a|.*|"
--devices/global_filter = [ "a|$DM_DEV_DIR/mirror|", "a|$DM_DEV_DIR/mapper/.*pv[0-9_]*$|", "r|.*|" ]
-+devices/global_filter = [ "a|$DM_DEV_DIR/mapper/.*pv[0-9_]*$|", "r|.*|" ]
- devices/cache_dir = "$TESTDIR/etc"
- devices/sysfs_scan = 0
- devices/default_data_alignment = 1
-@@ -654,7 +656,7 @@ skip_if_raid456_replace_broken() {
- 
- udev_wait() {
- 	pgrep udev >/dev/null || return 0
--	which udevadm >/dev/null || return 0
-+	which udevadm &>/dev/null || return 0
- 	if test -n "$1" ; then
- 		udevadm settle --exit-if-exists="$1" || true
- 	else
-@@ -689,6 +691,7 @@ can_use_16T()
- # i.e.   dm_target_at_least  dm-thin-pool  1 0
- target_at_least()
- {
-+	rm -f debug.log
- 	case "$1" in
- 	  dm-*) modprobe "$1" || true ;;
- 	esac
-diff --git a/test/lib/check.sh b/test/lib/check.sh
-index 84604e3..9c55338 100644
---- a/test/lib/check.sh
-+++ b/test/lib/check.sh
-@@ -240,7 +240,7 @@ inactive() {
- 		die "$lv expected inactive, but lvs says it's not:" \
- 			$(lvl $lv -o+devices)
- 	not dmsetup info $1-$2 2>/dev/null || \
--		die "$lv expected inactive, lvs thinks it is but there are mappings!" 
-+		die "$lv expected inactive, lvs thinks it is but there are mappings!"
- }
- 
- # Check for list of LVs from given VG
-@@ -251,10 +251,25 @@ lv_exists() {
- 		shift
- 		lv="$lv $vg/$1"
- 	done
-+	test -n "$lv" || lv=$vg
- 	lvl $lv &>/dev/null || \
- 		die "$lv expected to exist but does not"
- }
- 
-+lv_not_exists() {
-+	local vg=$1
-+	if test $# -le 1 ; then
-+		lvl $vg &>/dev/null || return
-+		die "$vg expected to not exist but it does!"
-+	else
-+		while [ $# -gt 1 ]; do
-+			shift
-+			lvl $vg/$1 &>/dev/null || continue
-+			die "$vg/$1 expected to not exist but it does!"
-+		done
-+	fi
-+}
-+
- pv_field() {
- 	local actual=$(get pv_field "$1" "$2" "${@:4}")
- 	test "$actual" = "$3" || \
-diff --git a/test/lib/get.sh b/test/lib/get.sh
-index 5dd5451..babc4c9 100644
---- a/test/lib/get.sh
-+++ b/test/lib/get.sh
-@@ -70,6 +70,13 @@ lv_tree_devices_() {
- 		lv_tree_devices_ "$1" "$(lv_field_lv_ $lv data_lv)"
- 		lv_tree_devices_ "$1" "$(lv_field_lv_ $lv metadata_lv)"
- 		;;
-+	cache)
-+		lv_tree_devices_ "$1" "$(lv_devices $lv)"
-+		;;
-+	cache-pool)
-+		lv_tree_devices_ "$1" "$(lv_field_lv_ $lv data_lv)"
-+		lv_tree_devices_ "$1" "$(lv_field_lv_ $lv metadata_lv)"
-+		;;
- 	esac
- }
- 
-diff --git a/test/lib/test.sh b/test/lib/test.sh
-index 265d61d..71ad55d 100644
---- a/test/lib/test.sh
-+++ b/test/lib/test.sh
-@@ -81,9 +81,9 @@ test -n "$BASH" && set -eE -o pipefail
- aux lvmconf
- aux prepare_clvmd
- test -n "$LVM_TEST_LVMETAD" && {
--	aux prepare_lvmetad
- 	export LVM_LVMETAD_SOCKET="$TESTDIR/lvmetad.socket"
- 	export LVM_LVMETAD_PIDFILE="$TESTDIR/lvmetad.pid"
-+	aux prepare_lvmetad
- }
- echo "@TESTDIR=$TESTDIR"
- echo "@PREFIX=$PREFIX"
-diff --git a/test/shell/activation-skip.sh b/test/shell/activation-skip.sh
-new file mode 100644
-index 0000000..7c80283
---- /dev/null
-+++ b/test/shell/activation-skip.sh
-@@ -0,0 +1,32 @@
-+#!/bin/bash
-+# Copyright (C) 2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+. lib/test
-+
-+# Test skip activation flag  -k|--setactivationskip
-+
-+aux prepare_vg
-+
-+lvcreate -an --zero n -l 1 -n $lv1 $vg
-+lvcreate -ky -K -l1 -n $lv2 $vg
-+get lv_field $vg/$lv2 lv_attr | grep -- "-wi-a----k"
-+
-+lvchange -ay -K $vg
-+check active $vg $lv1
-+lvchange -an $vg
-+
-+lvchange -ay --setactivationskip y $vg/$lv1
-+check inactive $vg $lv1
-+
-+get lv_field $vg/$lv1 lv_attr | grep -- "-wi------k"
-+
-+lvchange -ay -K $vg
-+check active $vg $lv1
-diff --git a/test/shell/lock-parallel.sh b/test/shell/lock-parallel.sh
-new file mode 100644
-index 0000000..4820129
---- /dev/null
-+++ b/test/shell/lock-parallel.sh
-@@ -0,0 +1,40 @@
-+#!/bin/sh
-+# Copyright (C) 2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+# Test parallel use of lvm commands and check locks aren't dropped
-+# RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1049296
-+
-+. lib/test
-+
-+which mkfs.ext3 || skip
-+
-+aux prepare_vg
-+
-+lvcreate -L10 -n $lv1 $vg
-+lvcreate -l1 -n $lv2 $vg
-+mkfs.ext3 "$DM_DEV_DIR/$vg/$lv1"
-+
-+# Slowdown PV for resized LV
-+aux delay_dev "$dev1" 20 20
-+
-+lvresize -L-5 -r $vg/$lv1 &
-+
-+# Let's wait till resize starts
-+sleep 2
-+
-+lvremove -f $vg/$lv2
-+
-+wait
-+
-+aux enable_dev "$dev1"
-+
-+# Check removed $lv2 does not reappear
-+not check lv_exists $vg $lv2
-diff --git a/test/shell/lvchange-partial.sh b/test/shell/lvchange-partial.sh
-index 891dd0a..b79004d 100644
---- a/test/shell/lvchange-partial.sh
-+++ b/test/shell/lvchange-partial.sh
-@@ -11,11 +11,13 @@
- 
- . lib/test
- 
--aux target_at_least dm-raid 1 1 0 || skip
- 
- aux prepare_vg 4
- 
--lvcreate --type raid1 -m 1 -l 2 -n $lv1 $vg
-+TYPE=raid1
-+aux target_at_least dm-raid 1 1 0 || TYPE=mirror
-+
-+lvcreate -aey --type $TYPE -m 1 -l 2 -n $lv1 $vg
- lvchange -an $vg/$lv1
- aux disable_dev "$dev1"
- 
-diff --git a/test/shell/lvchange-raid.sh b/test/shell/lvchange-raid.sh
-index 91c8e8d..0ee5290 100644
---- a/test/shell/lvchange-raid.sh
-+++ b/test/shell/lvchange-raid.sh
-@@ -19,7 +19,7 @@ THIN_POSTFIX=""
- # Proper mismatch count 1.5.2 upstream,1.3.5 < x < 1.4.0 in RHEL6
- #
- # We will simplify and simple test for 1.5.2 and 1.3.5 < x < 1.4.0
--aux target_at_least dm-raid 1 3 5 && 
-+aux target_at_least dm-raid 1 3 5 &&
-   ! aux target_at_least dm-raid 1 4 0 ||
-   aux target_at_least dm-raid 1 5 2 || skip
- 
-@@ -29,108 +29,103 @@ aux prepare_vg 6
- 
- # run_writemostly_check <VG> <LV>
- run_writemostly_check() {
--	local d0
--	local d1
- 	local vg=$1
- 	local lv=${2}${THIN_POSTFIX}
-+	local segtype=$(get lv_field $vg/$lv segtype -a)
-+	local d0=$(get lv_devices $vg/${lv}_rimage_0)
-+	local d1=$(get lv_devices $vg/${lv}_rimage_1)
- 
- 	printf "#\n#\n#\n# %s/%s (%s): run_writemostly_check\n#\n#\n#\n" \
--		$vg $lv `lvs -a --noheadings -o segtype $vg/$lv`
--	d0=`lvs -a --noheadings -o devices $vg/${lv}_rimage_0 | sed s/\(.\)//`
--	d0=$(sed s/^[[:space:]]*// <<< "$d0")
--	d1=`lvs -a --noheadings -o devices $vg/${lv}_rimage_1 | sed s/\(.\)//`
--	d1=$(sed s/^[[:space:]]*// <<< "$d1")
-+		$vg $lv $segtype
- 
- 	# No writemostly flag should be there yet.
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*-.$'
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_1 | grep '.*-.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*-.$'
-+	get lv_field $vg/${lv}_rimage_1 lv_attr -a | grep '.*-.$'
- 
--	if [ `lvs -a --noheadings -o segtype $vg/$lv` != "raid1" ]; then
-+	if [ "$segtype" != "raid1" ]; then
- 		not lvchange --writemostly $d0 $vg/$lv
- 		return
- 	fi
- 
- 	# Set the flag
- 	lvchange --writemostly $d0 $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*w.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*w.$'
- 
- 	# Running again should leave it set (not toggle)
- 	lvchange --writemostly $d0 $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*w.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*w.$'
- 
- 	# Running again with ':y' should leave it set
- 	lvchange --writemostly $d0:y $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*w.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*w.$'
- 
- 	# ':n' should unset it
- 	lvchange --writemostly $d0:n $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*-.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*-.$'
- 
- 	# ':n' again should leave it unset
- 	lvchange --writemostly $d0:n $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*-.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*-.$'
- 
- 	# ':t' toggle to set
- 	lvchange --writemostly $d0:t $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*w.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*w.$'
- 
- 	# ':t' toggle to unset
- 	lvchange --writemostly $d0:t $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*-.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*-.$'
- 
- 	# ':y' to set
- 	lvchange --writemostly $d0:y $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*w.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*w.$'
- 
- 	# Toggle both at once
- 	lvchange --writemostly $d0:t --writemostly $d1:t $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*-.$'
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_1 | grep '.*w.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*-.$'
-+	get lv_field $vg/${lv}_rimage_1 lv_attr -a | grep '.*w.$'
- 
- 	# Toggle both at once again
- 	lvchange --writemostly $d0:t --writemostly $d1:t $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*w.$'
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_1 | grep '.*-.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*w.$'
-+	get lv_field $vg/${lv}_rimage_1 lv_attr -a | grep '.*-.$'
- 
- 	# Toggle one, unset the other
- 	lvchange --writemostly $d0:n --writemostly $d1:t $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*-.$'
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_1 | grep '.*w.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*-.$'
-+	get lv_field $vg/${lv}_rimage_1 lv_attr -a | grep '.*w.$'
- 
- 	# Toggle one, set the other
- 	lvchange --writemostly $d0:y --writemostly $d1:t $vg/$lv
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*w.$'
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_1 | grep '.*-.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*w.$'
-+	get lv_field $vg/${lv}_rimage_1 lv_attr -a | grep '.*-.$'
- 
- 	# Partial flag supercedes writemostly flag
- 	aux disable_dev $d0
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*p.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*p.$'
- 
- 	# It is possible for the kernel to detect the failed device before
- 	# we re-enable it.  If so, the field will be set to 'r'efresh since
- 	# that also takes precedence over 'w'ritemostly.  If this has happened,
- 	# we refresh the LV and then check for 'w'.
- 	aux enable_dev $d0
--	if lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*r.$'; then
--		lvchange --refresh $vg/$lv
--	fi
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*w.$'
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*r.$' && lvchange --refresh $vg/$lv
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a | grep '.*w.$'
- 
- 	# Catch Bad writebehind values
- 	not lvchange --writebehind "invalid" $vg/$lv
- 	not lvchange --writebehind -256 $vg/$lv
- 
- 	# Set writebehind
--	[ ! `lvs --noheadings -o raid_write_behind $vg/$lv` ]
-+	check lv_field $vg/$lv raid_write_behind ""
- 	lvchange --writebehind 512 $vg/$lv
--	[ `lvs --noheadings -o raid_write_behind $vg/$lv` -eq 512 ]
-+	check lv_field $vg/$lv raid_write_behind "512"
- 
- 	# Converting to linear should clear flags and writebehind
- 	lvconvert -m 0 $vg/$lv $d1
- 	lvconvert --type raid1 -m 1 $vg/$lv $d1
--	[ ! `lvs --noheadings -o raid_write_behind $vg/$lv` ]
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_0 | grep '.*-.$'
--	lvs -a --noheadings -o lv_attr $vg/${lv}_rimage_1 | grep '.*-.$'
-+	check lv_field $vg/$lv raid_write_behind ""
-+	get lv_field $vg/${lv}_rimage_0 lv_attr -a  | grep '.*-.$'
-+	get lv_field $vg/${lv}_rimage_1 lv_attr -a  | grep '.*-.$'
- }
- 
- # run_syncaction_check <VG> <LV>
-@@ -143,33 +138,29 @@ run_syncaction_check() {
- 	local lv=${2}${THIN_POSTFIX}
- 
- 	printf "#\n#\n#\n# %s/%s (%s): run_syncaction_check\n#\n#\n#\n" \
--		$vg $lv `lvs -a --noheadings -o segtype $vg/$lv`
-+		$vg $lv $(get lv_field $vg/$lv segtype -a)
- 	aux wait_for_sync $vg $lv
- 
--	device=`lvs -a --noheadings -o devices $vg/${lv}_rimage_1 | sed s/\(.\)//`
--	device=$(sed s/^[[:space:]]*// <<< "$device")
-+	device=$(get lv_devices $vg/${lv}_rimage_1)
- 
--	size=`lvs -a --noheadings -o size --units 1k $vg/${lv}_rimage_1 | sed s/\.00k//`
--	size=$(sed s/^[[:space:]]*// <<< "$size")
--	size=$(($size / 2))
-+	size=$(get lv_field $vg/${lv}_rimage_1 size -a --units 1k)
-+	size=$((${size%\.00k} / 2))
- 
--	tmp=`pvs --noheadings -o mda_size --units 1k $device | sed s/\.00k//`
--	tmp=$(sed s/^[[:space:]]*// <<< "$tmp")
--	seek=$tmp  # Jump over MDA
-+	tmp=$(get pv_field $device mda_size --units 1k)
-+	seek=${tmp%\.00k} # Jump over MDA
- 
--	tmp=`lvs -a --noheadings -o size --units 1k $vg/${lv}_rmeta_1 | sed s/\.00k//`
--	tmp=$(sed s/^[[:space:]]*// <<< "$tmp")
--	seek=$(($seek + $tmp))  # Jump over RAID metadata image
-+	tmp=$(get lv_field $vg/${lv}_rmeta_1 size -a --units 1k)
-+	seek=$(($seek + ${tmp%\.00k}))  # Jump over RAID metadata image
- 
- 	seek=$(($seek + $size)) # Jump halfway through the RAID image
- 
--	lvs --noheadings -o lv_attr $vg/$lv | grep '.*-.$'
--	[ `lvs --noheadings -o raid_mismatch_count $vg/$lv` == 0 ]
-+	get lv_field $vg/$lv lv_attr | grep '.*-.$'
-+	check lv_field $vg/$lv raid_mismatch_count "0"
- 
- 	# Overwrite the last half of one of the PVs with crap
- 	dd if=/dev/urandom of=$device bs=1k count=$size seek=$seek
- 
--	if [ ! -z $THIN_POSTFIX ]; then
-+	if [ -n "$THIN_POSTFIX" ]; then
- 		#
- 		# Seems to work fine on real devices,
- 		# but can't make the system notice the bad blocks
-@@ -189,12 +180,11 @@ run_syncaction_check() {
- 	# 'lvs' should show results
- 	lvchange --syncaction check $vg/$lv
- 	aux wait_for_sync $vg $lv
--	if ! lvs --noheadings -o lv_attr $vg/$lv | grep '.*m.$'; then
--		lvs --noheadings -o lv_attr $vg/$lv
-+	if ! get lv_field $vg/$lv lv_attr -a | grep '.*m.$'; then
- 		dmsetup status | grep $vg
- 		false
- 	fi
--	[ `lvs --noheadings -o raid_mismatch_count $vg/$lv` != 0 ]
-+	not check lv_field $vg/$lv raid_mismatch_count "0"
- 
- 	# "repair" will fix discrepancies
- 	lvchange --syncaction repair $vg/$lv
-@@ -204,40 +194,35 @@ run_syncaction_check() {
- 	# 'lvs' should show results
- 	lvchange --syncaction check $vg/$lv
- 	aux wait_for_sync $vg $lv
--	lvs --noheadings -o lv_attr $vg/$lv | grep '.*-.$'
--	[ `lvs --noheadings -o raid_mismatch_count $vg/$lv` == 0 ]
-+	get lv_field $vg/$lv lv_attr | grep '.*-.$'
-+	check lv_field $vg/$lv raid_mismatch_count "0"
- }
- 
- # run_refresh_check <VG> <LV>
- #   Assumes "$dev2" is in the array
- run_refresh_check() {
- 	local size
-+	local sizelv
- 	local vg=$1
- 	local lv=${2}${THIN_POSTFIX}
- 
- 	printf "#\n#\n#\n# %s/%s (%s): run_refresh_check\n#\n#\n#\n" \
--		$vg $lv `lvs -a --noheadings -o segtype $vg/$lv`
-+		$vg $lv $(get lv_field $vg/$lv segtype -a)
- 
- 	aux wait_for_sync $vg $lv
- 
--	if [ -z $THIN_POSTFIX ]; then
--		size=`lvs -a --noheadings -o size --units 1k $vg/$lv | sed s/\.00k//`
--	else
--		size=`lvs -a --noheadings -o size --units 1k $vg/thinlv | sed s/\.00k//`
--	fi
--	size=$(sed s/^[[:space:]]*// <<< "$size")
-+	sizelv=$vg/$lv
-+	test -z "$THIN_POSTFIX" || sizelv=$vg/thinlv
-+	size=$(get lv_field $sizelv size --units 1k)
-+	size=${size%\.00k}
- 
- 	# Disable dev2 and do some I/O to make the kernel notice
- 	aux disable_dev "$dev2"
--	if [ -z $THIN_POSTFIX ]; then
--		dd if=/dev/urandom of=/dev/$vg/$lv bs=1k count=$size
--	else
--		dd if=/dev/urandom of=/dev/$vg/thinlv bs=1k count=$size
--		sync; sync; sync
--	fi
-+	dd if=/dev/urandom of=/dev/$sizelv bs=1k count=$size
-+	sync
- 
- 	# Check for 'p'artial flag
--	lvs --noheadings -o lv_attr $vg/$lv | grep '.*p.$'
-+	get lv_field $vg/$lv lv_attr | grep '.*p.$'
- 	dmsetup status
- 	lvs -a -o name,attr,devices $vg
- 
-@@ -247,18 +232,18 @@ run_refresh_check() {
- 	lvs -a -o name,attr,devices $vg
- 
- 	# Check for 'r'efresh flag
--	lvs --noheadings -o lv_attr $vg/$lv | grep '.*r.$'
-+	get lv_field $vg/$lv lv_attr | grep '.*r.$'
- 
- 	lvchange --refresh $vg/$lv
- 	aux wait_for_sync $vg $lv
--	lvs --noheadings -o lv_attr $vg/$lv | grep '.*-.$'
-+	get lv_field $vg/$lv lv_attr | grep '.*-.$'
- 
- 	# Writing random data above should mean that the devices
- 	# were out-of-sync.  The refresh should have taken care
- 	# of properly reintegrating the device.
- 	lvchange --syncaction repair $vg/$lv
- 	aux wait_for_sync $vg $lv
--	lvs --noheadings -o lv_attr $vg/$lv | grep '.*-.$'
-+	get lv_field $vg/$lv lv_attr | grep '.*-.$'
- }
- 
- # run_recovery_rate_check <VG> <LV>
-@@ -267,14 +252,13 @@ run_recovery_rate_check() {
- 	local vg=$1
- 	local lv=${2}${THIN_POSTFIX}
- 
--	printf "#\n#\n#\n# %s/%s (%s): run_recovery_rate_check\n#\n#\n#\n" \
--		$vg $lv `lvs -a --noheadings -o segtype $vg/$lv`
--
-+	printf "#\n#\n#\n# %s/%s $(%s): run_recovery_rate_check\n#\n#\n#\n" \
-+		 $vg $lv $(get lv_field $vg/$lv segtype -a)
- 	lvchange --minrecoveryrate 50 $vg/$lv
- 	lvchange --maxrecoveryrate 100 $vg/$lv
- 
--	[ `lvs --noheadings -o raid_min_recovery_rate $vg/$lv` == "50" ]
--	[ `lvs --noheadings -o raid_max_recovery_rate $vg/$lv` == "100" ]
-+	check lv_field $vg/$lv raid_min_recovery_rate "50"
-+	check lv_field $vg/$lv raid_max_recovery_rate "100"
- }
- 
- # run_checks <VG> <LV> <"-"|snapshot_dev|"thinpool_data"|"thinpool_meta">
-@@ -292,7 +276,7 @@ run_checks() {
- 		run_refresh_check $1 $2
- 		run_recovery_rate_check $1 $2
- 	elif [ 'thinpool_data' == $3 ]; then
--		aux target_at_least dm-thin-pool 1 8 0 || return 0
-+		aux have_thin 1 8 0 || return 0
- 
- 		# RAID works EX in cluster
- 		# thinpool works EX in cluster
-@@ -313,7 +297,7 @@ run_checks() {
- 		run_refresh_check $1 $2
- 		run_recovery_rate_check $1 $2
- 	elif [ 'thinpool_meta' == $3 ]; then
--		aux target_at_least dm-thin-pool 1 8 0 || return 0
-+		aux have_thin 1 8 0 || return 0
- 		test -e LOCAL_CLVMD && return 0
- 		printf "#\n#\n# run_checks: RAID as thinpool metadata\n#\n#\n"
- 
-diff --git a/test/shell/lvconvert-mirror-updown.sh b/test/shell/lvconvert-mirror-updown.sh
-new file mode 100644
-index 0000000..3b30738
---- /dev/null
-+++ b/test/shell/lvconvert-mirror-updown.sh
-@@ -0,0 +1,36 @@
-+#!/bin/sh
-+# Copyright (C) 2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+# Demonstrate problem when upconverting and cutting leg in clvmd
-+
-+. lib/test
-+
-+aux prepare_pvs 3
-+
-+vgcreate -s 64k $vg $(cat DEVICES)
-+
-+lvcreate -aey -l10 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2"
-+
-+# Slow down device so we are able to start next conversion in parallel
-+aux delay_dev "$dev3" 0 200
-+
-+lvconvert -m+1 -b $vg/$lv1 "$dev3"
-+
-+# To fix - wait helps here....
-+#lvconvert $vg/$lv1
-+
-+lvs -a $vg
-+#
-+# It fails so use 'should' and -vvvv for now
-+#
-+should lvconvert -vvvv -m-1 $vg/$lv1 "$dev2"
-+
-+vgremove -f $vg
-diff --git a/test/shell/lvconvert-mirror.sh b/test/shell/lvconvert-mirror.sh
-index 911e022..097e0d4 100644
---- a/test/shell/lvconvert-mirror.sh
-+++ b/test/shell/lvconvert-mirror.sh
-@@ -176,6 +176,10 @@ lvremove -ff $vg
- # "remove from original mirror (the original is still mirror)"
- lvcreate -aey -l2 --type mirror -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev5" "$dev3:$DEVRANGE"
- lvconvert -m+1 -b $vg/$lv1 "$dev4"
-+# FIXME: Extra wait here for mirror upconvert synchronization
-+# otherwise we may fail her on parallel upconvert and downconvert
-+# lvconvert-mirror-updown.sh tests this errornous case separately
-+lvconvert $vg/$lv1
- lvconvert -m-1 $vg/$lv1 "$dev2"
- lvconvert $vg/$lv1
- 
-diff --git a/test/shell/lvconvert-repair-dmeventd.sh b/test/shell/lvconvert-repair-dmeventd.sh
-index 55eee37..a2d3ef8 100644
---- a/test/shell/lvconvert-repair-dmeventd.sh
-+++ b/test/shell/lvconvert-repair-dmeventd.sh
-@@ -14,13 +14,13 @@
- which mkfs.ext2 || skip
- aux skip_if_mirror_recovery_broken
- 
--aux prepare_vg 5
- aux prepare_dmeventd
-+aux prepare_vg 5
- 
- lvcreate -aey --type mirror -m 3 --ignoremonitoring -L 1 -n 4way $vg
- lvchange --monitor y $vg/4way
- aux disable_dev "$dev2" "$dev4"
--mkfs.ext2 $DM_DEV_DIR/$vg/4way
-+mkfs.ext2 "$DM_DEV_DIR/$vg/4way"
- sleep 10 # FIXME: need a "poll" utility, akin to "check"
- aux enable_dev "$dev2" "$dev4"
- check mirror $vg 4way
-diff --git a/test/shell/lvconvert-repair-thin.sh b/test/shell/lvconvert-repair-thin.sh
-index aa301d6..b80b855 100644
---- a/test/shell/lvconvert-repair-thin.sh
-+++ b/test/shell/lvconvert-repair-thin.sh
-@@ -10,7 +10,7 @@
- # along with this program; if not, write to the Free Software Foundation,
- # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- 
--# Test repairing of broken thin pool metadata 
-+# Test repairing of broken thin pool metadata
- 
- . lib/test
- 
-@@ -34,8 +34,8 @@ aux prepare_vg 4
- lvcreate -T -L20 -V10 -n $lv1 $vg/pool  "$dev1" "$dev2"
- lvcreate -T -V10 -n $lv2 $vg/pool
- 
--mkfs.ext2 $DM_DEV_DIR/$vg/$lv1
--mkfs.ext2 $DM_DEV_DIR/$vg/$lv2
-+mkfs.ext2 "$DM_DEV_DIR/$vg/$lv1"
-+mkfs.ext2 "$DM_DEV_DIR/$vg/$lv2"
- 
- lvcreate -L20 -n repair $vg
- lvcreate -L2 -n fixed $vg
-@@ -55,26 +55,26 @@ lvconvert -y -f --poolmetadata $vg/repair --thinpool $vg/pool
- 
- lvchange -aey $vg/repair $vg/fixed
- 
--#dd if=$DM_DEV_DIR/$vg/repair of=back bs=1M
-+#dd if="$DM_DEV_DIR/$vg/repair" of=back bs=1M
- 
- # Make some 'repairable' damage??
--dd if=/dev/zero of=$DM_DEV_DIR/$vg/repair bs=1 seek=40960 count=1
-+dd if=/dev/zero of="$DM_DEV_DIR/$vg/repair" bs=1 seek=40960 count=1
- 
--#dd if=$DM_DEV_DIR/$vg/repair of=back_trashed bs=1M
-+#dd if="$DM_DEV_DIR/$vg/repair" of=back_trashed bs=1M
- #not vgchange -ay $vg
- 
- #lvconvert --repair $vg/pool
- 
- # Using now SHOULD - since thin tools currently do not seem to work
--should not $THIN_CHECK $DM_DEV_DIR/$vg/repair
-+should not "$THIN_CHECK" "$DM_DEV_DIR/$vg/repair"
- 
--should not $LVM_TEST_THIN_DUMP_CMD $DM_DEV_DIR/$vg/repair | tee dump
-+should not "$LVM_TEST_THIN_DUMP_CMD" "$DM_DEV_DIR/$vg/repair" | tee dump
- 
--should $LVM_TEST_THIN_REPAIR_CMD -i $DM_DEV_DIR/$vg/repair -o $DM_DEV_DIR/$vg/fixed
-+should "$LVM_TEST_THIN_REPAIR_CMD" -i "$DM_DEV_DIR/$vg/repair" -o "$DM_DEV_DIR/$vg/fixed"
- 
--should $LVM_TEST_THIN_DUMP_CMD --repair $DM_DEV_DIR/$vg/repair | tee repaired_xml
-+should "$LVM_TEST_THIN_DUMP_CMD" --repair "$DM_DEV_DIR/$vg/repair" | tee repaired_xml
- 
--should $LVM_TEST_THIN_CHECK_CMD $DM_DEV_DIR/$vg/fixed
-+should "$LVM_TEST_THIN_CHECK_CMD" "$DM_DEV_DIR/$vg/fixed"
- 
- # Swap repaired metadata back
- lvconvert -y -f --poolmetadata $vg/fixed --thinpool $vg/pool
-@@ -83,7 +83,7 @@ lvs -a $vg
- # Activate pool - this should now work
- should vgchange -ay $vg
- 
--lvs -a -o+devices $vg 
-+lvs -a -o+devices $vg
- dmsetup table
- dmsetup info -c
- dmsetup ls --tree
-@@ -99,7 +99,7 @@ dmsetup remove $vg-pool_tmeta || true
- 
- dmsetup table
- 
--# FIXME: needs  also --yes with double force 
-+# FIXME: needs  also --yes with double force
- pvremove --yes -ff "$dev1"
- pvremove --yes -ff "$dev2"
- 
-diff --git a/test/shell/lvconvert-repair-transient-dmeventd.sh b/test/shell/lvconvert-repair-transient-dmeventd.sh
-index 699195a..6bd1442 100644
---- a/test/shell/lvconvert-repair-transient-dmeventd.sh
-+++ b/test/shell/lvconvert-repair-transient-dmeventd.sh
-@@ -18,7 +18,7 @@ aux prepare_dmeventd
- lvcreate -aey --type mirror -m 3 --ignoremonitoring -L 1 -n 4way $vg
- lvchange --monitor y $vg/4way
- aux disable_dev "$dev2" "$dev4"
--mkfs.ext3 $DM_DEV_DIR/$vg/4way
-+mkfs.ext3 "$DM_DEV_DIR/$vg/4way"
- aux enable_dev "$dev2" "$dev4"
- sleep 3
- lvs -a -o +devices $vg | tee out
-diff --git a/test/shell/lvconvert-repair-transient.sh b/test/shell/lvconvert-repair-transient.sh
-index 28b06c6..3baa293 100644
---- a/test/shell/lvconvert-repair-transient.sh
-+++ b/test/shell/lvconvert-repair-transient.sh
-@@ -16,7 +16,7 @@ aux prepare_vg 5
- 
- lvcreate -aey --type mirror -m 3 --ignoremonitoring -L 1 -n 4way $vg
- aux disable_dev "$dev2" "$dev4"
--mkfs.ext3 $DM_DEV_DIR/$vg/4way &
-+mkfs.ext3 "$DM_DEV_DIR/$vg/4way" &
- sleep 1
- aux enable_dev "$dev2" "$dev4"
- echo n | lvconvert --repair $vg/4way 2>&1 | tee 4way.out
-diff --git a/test/shell/lvconvert-thin-external.sh b/test/shell/lvconvert-thin-external.sh
-index d9d4d19..00712bd 100644
---- a/test/shell/lvconvert-thin-external.sh
-+++ b/test/shell/lvconvert-thin-external.sh
-@@ -49,16 +49,24 @@ fi
- 
- lvcreate -l10 -T $vg/pool
- # Can't convert pool to external origin
--lvcreate -l10 -T $vg/pool1
-+lvcreate -l10 -T $vg/pool1 -c 192k
- not lvconvert -T --thinpool $vg/pool1 $vg/pool --originname origin
--lvremove -f $vg/pool1
-+# Create pool1 chunk_size unaligned LV and check failing conversion
-+lvcreate -l2 -n $lv1 $vg
-+not lvconvert -T --thinpool $vg/pool1 $vg/$lv1
-+
-+lvremove -f $vg/pool1 $vg/$lv1
- 
- # create plain LV (will be used for external origin)
- lvcreate -L8M -n $lv1 $vg
- 
--mkfs.ext2 $DM_DEV_DIR/$vg/$lv1
-+# Can't convert same LV to the thin pool and thin volume
-+not lvconvert --thinpool $vg/$lv1 -T $vg/$lv1
-+check lv_field $vg/$lv1 segtype linear
-+
-+mkfs.ext2 "$DM_DEV_DIR/$vg/$lv1"
- mkdir mnt
--mount $DM_DEV_DIR/$vg/$lv1 mnt
-+mount "$DM_DEV_DIR/$vg/$lv1" mnt
- 
- dd if=/dev/zero of=mnt/test1 bs=1M count=1
- 
-@@ -76,7 +84,7 @@ touch mnt/test
- umount mnt
- 
- # check fs is without errors
--fsck -n $DM_DEV_DIR/$vg/$lv1
-+fsck -n "$DM_DEV_DIR/$vg/$lv1"
- 
- lvchange -aey $vg/extorg
- lvchange -an $vg/$lv1
-@@ -85,7 +93,7 @@ check active $vg extorg
- check inactive $vg $lv1
- 
- # fsck in read-only mode
--fsck -n $DM_DEV_DIR/$vg/extorg
-+fsck -n "$DM_DEV_DIR/$vg/extorg"
- 
- not lvresize -l+8 $vg/extorg
- not lvresize -l-4 $vg/extorg
-diff --git a/test/shell/lvcreate-cache.sh b/test/shell/lvcreate-cache.sh
-new file mode 100644
-index 0000000..ccfb4ad
---- /dev/null
-+++ b/test/shell/lvcreate-cache.sh
-@@ -0,0 +1,137 @@
-+#!/bin/sh
-+# Copyright (C) 2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+. lib/test
-+
-+aux target_at_least dm-cache 1 3 0 || skip
-+
-+# Skip in cluster for now, but should test EX mode...
-+test -e LOCAL_CLVMD && skip
-+
-+aux prepare_vg 5 80
-+
-+####################
-+# Cache_Pool creation
-+####################
-+
-+# Full CLI (the advertised form)
-+lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg
-+lvremove -ff $vg/${lv}_cache_pool
-+
-+# Shorthand CLI (not advertised) -- not yet implemented
-+# lvcreate --cache -l 1 vg
-+# lvremove -ff $vg
-+
-+# Shorthand CLI (not advertised) -- not yet implemented
-+# lvcreate -H -l 1 vg
-+# lvremove -ff $vg
-+
-+################
-+# Cache creation
-+# Creating a cache is a two phase process
-+# - first, cache_pool (or origin)
-+# - then, the cache LV (lvcreate distinguishes supplied origin vs cache_pool)
-+################
-+
-+# Create/remove cache_pool
-+lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg
-+lvremove -ff $vg
-+
-+# Create cache_pool, then origin with cache, then remove all
-+lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg
-+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1
-+dmsetup table ${vg}-$lv1 | grep cache  # ensure it is loaded in kernel
-+lvremove -ff $vg
-+
-+# Create cache_pool, then origin with cache, then remove cache_pool/cache
-+lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg
-+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1
-+lvremove -ff $vg/${lv}_cache_pool
-+lvremove -ff $vg/$lv1
-+
-+# Create cache_pool, then origin with cache, then remove origin
-+lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg
-+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1
-+lvremove -ff $vg/$lv1
-+lvremove -ff $vg/${lv}_cache_pool
-+
-+# Shorthand CLI (cache_pool exists, create origin w/ cache)
-+#lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg
-+#lvcreate --cache -l 2 $vg/${lv}_cache_pool -n $lv1
-+#lvremove -ff $vg
-+
-+# Shorthand CLI (cache_pool exists, create origin w/ cache)
-+#lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg
-+#lvcreate -H -l 2 $vg/${lv}_cache_pool -n $lv1
-+#lvremove -ff $vg
-+
-+# Create origin, then cache_pool and cache
-+lvcreate -l 2 -n $lv1 $vg
-+lvcreate --type cache -l 1 $vg/$lv1
-+dmsetup table ${vg}-$lv1 | grep cache  # ensure it is loaded in kernel
-+lvremove -ff $vg
-+
-+# Shorthand CLI (origin exists, create cache_pool and cache)
-+#lvcreate -l 1 -n $lv1 $vg
-+#lvcreate --cache -l 2 $vg/$lv1
-+#lvremove -ff $vg
-+
-+# Shorthand CLI (origin exists, create cache_pool and cache)
-+#lvcreate -l 1 -n $lv1 $vg
-+#lvcreate -H -l 2 $vg/$lv1
-+#lvremove -ff $vg
-+
-+
-+################################################
-+# Repeat key tests with 'writethrough' cachemode
-+################################################
-+# Create/remove cache_pool
-+lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg --cachemode writethrough
-+lvremove -ff $vg
-+
-+# Create cache_pool, then origin with cache, then remove all
-+lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg
-+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1 --cachemode writethrough
-+lvremove -ff $vg
-+
-+# Create cache_pool, then origin with cache, then remove cache_pool/cache
-+lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg
-+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1 --cachemode writethrough
-+lvremove -ff $vg/${lv}_cache_pool
-+lvremove -ff $vg/$lv1
-+
-+# Create cache_pool, then origin with cache, then remove origin
-+lvcreate --type cache-pool -l 1 -n ${lv}_cache_pool $vg
-+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1 --cachemode writethrough
-+lvremove -ff $vg/$lv1
-+lvremove -ff $vg/${lv}_cache_pool
-+
-+# Create origin, then cache_pool and cache
-+lvcreate -l 2 -n $lv1 $vg
-+lvcreate --type cache -l 1 $vg/$lv1 --cachemode writethrough
-+lvremove -ff $vg
-+
-+
-+##############################
-+# Test things that should fail
-+##############################
-+
-+# Attempt to create smaller cache than origin should fail
-+lvcreate -l 1 -n $lv1 $vg
-+not lvcreate --type cache -l 2 $vg/$lv1
-+lvremove -ff $vg
-+
-+
-+# Option testing
-+# --chunksize
-+# --cachepolicy
-+# --poolmetadatasize
-+# --poolmetadataspare
-diff --git a/test/shell/lvcreate-large-raid.sh b/test/shell/lvcreate-large-raid.sh
-index 395cf2b..e5d883c 100644
---- a/test/shell/lvcreate-large-raid.sh
-+++ b/test/shell/lvcreate-large-raid.sh
-@@ -31,8 +31,8 @@ lvcreate -s -l 20%FREE -n $lv5 $vg --virtualsize 256T
- 
- aux extend_filter_LVMTEST
- 
--pvcreate $DM_DEV_DIR/$vg/$lv[12345]
--vgcreate $vg1 $DM_DEV_DIR/$vg/$lv[12345]
-+pvcreate "$DM_DEV_DIR"/$vg/$lv[12345]
-+vgcreate $vg1 "$DM_DEV_DIR"/$vg/$lv[12345]
- 
- # bz837927 START
- 
-diff --git a/test/shell/lvcreate-large-raid10.sh b/test/shell/lvcreate-large-raid10.sh
-index 4f97997..3d02e81 100644
---- a/test/shell/lvcreate-large-raid10.sh
-+++ b/test/shell/lvcreate-large-raid10.sh
-@@ -28,8 +28,8 @@ lvcreate -s -l 20%FREE -n $lv5 $vg --virtualsize 256T
- 
- aux extend_filter_LVMTEST
- 
--pvcreate $DM_DEV_DIR/$vg/$lv[12345]
--vgcreate $vg1 $DM_DEV_DIR/$vg/$lv[12345]
-+pvcreate "$DM_DEV_DIR"/$vg/$lv[12345]
-+vgcreate $vg1 "$DM_DEV_DIR"/$vg/$lv[12345]
- 
- #
- # Create large RAID LVs
-diff --git a/test/shell/lvcreate-large.sh b/test/shell/lvcreate-large.sh
-index c8790f1..f3d3f30 100644
---- a/test/shell/lvcreate-large.sh
-+++ b/test/shell/lvcreate-large.sh
-@@ -25,8 +25,8 @@ lvcreate -s -l 100%FREE -n $lv $vg --virtualsize 1024T
- 
- aux extend_filter_LVMTEST
- 
--pvcreate $DM_DEV_DIR/$vg/$lv
--vgcreate $vg1 $DM_DEV_DIR/$vg/$lv
-+pvcreate "$DM_DEV_DIR/$vg/$lv"
-+vgcreate $vg1 "$DM_DEV_DIR/$vg/$lv"
- 
- lvcreate -l 100%FREE -n $lv1 $vg1
- check lv_field $vg1/$lv1 size "1024.00t"
-diff --git a/test/shell/lvcreate-pvtags.sh b/test/shell/lvcreate-pvtags.sh
-index 20a241c..340a4f4 100644
---- a/test/shell/lvcreate-pvtags.sh
-+++ b/test/shell/lvcreate-pvtags.sh
-@@ -28,7 +28,7 @@ lvcreate -l3 -i3 $vg @fast
- not lvcreate -l4 -i4 $vg @fast
- 
- # 2 stripes is too many with just one PV
--not lvcreate -l2 -i2 $vg $DM_DEV_DIR/mapper/pv1
-+not lvcreate -l2 -i2 $vg "$DM_DEV_DIR/mapper/pv1"
- 
- # lvcreate mirror
- lvcreate -aey -l1 --type mirror -m1 $vg @fast
-diff --git a/test/shell/lvcreate-raid.sh b/test/shell/lvcreate-raid.sh
-index 214b162..2053d04 100644
---- a/test/shell/lvcreate-raid.sh
-+++ b/test/shell/lvcreate-raid.sh
-@@ -11,6 +11,14 @@
- 
- . lib/test
- 
-+lv_devices() {
-+	local local_vg=$1
-+	local local_lv=$2
-+	local count=$3
-+
-+	[ $count == `lvs --noheadings -o devices $local_vg/$local_lv | sed s/,/' '/g | wc -w` ]
-+}
-+
- ########################################################
- # MAIN
- ########################################################
-@@ -70,3 +78,113 @@ for i in raid4 \
- 	aux wait_for_sync $vg $lv1
- 	lvremove -ff $vg
- done
-+
-+# Create RAID using 100%FREE
-+############################
-+# 6 PVs with 18.5m in each PV.
-+# 1 metadata LV = 1 extent   = .5m
-+# 1 image = 36+37+37 extents = 55.00m = lv_size
-+lvcreate --type raid1 -m 1 -l 100%FREE -n raid1 $vg
-+check lv_field $vg/raid1 size "55.00m"
-+lvremove -ff $vg
-+
-+# 1 metadata LV = 1 extent
-+# 1 image = 36 extents
-+# 5 images = 180 extents = 90.00m = lv_size
-+lvcreate --type raid5 -i 5 -l 100%FREE -n raid5 $vg
-+check lv_field $vg/raid5 size "90.00m"
-+lvremove -ff $vg
-+
-+# 1 image = 36+37 extents
-+# 2 images = 146 extents = 73.00m = lv_size
-+lvcreate --type raid5 -i 2 -l 100%FREE -n raid5 $vg
-+check lv_field $vg/raid5 size "73.00m"
-+lvremove -ff $vg
-+
-+# 1 image = 36 extents
-+# 4 images = 144 extents = 72.00m = lv_size
-+lvcreate --type raid6 -i 4 -l 100%FREE -n raid6 $vg
-+check lv_field $vg/raid6 size "72.00m"
-+lvremove -ff $vg
-+
-+# Eat 18 of 37 extents from dev1, leaving 19
-+lvcreate -l 18 -n lv $vg $dev1
-+# Using 100% free should take the rest of dev1 and equal from dev2
-+# 1 meta takes 1 extent
-+# 1 image = 18 extents = 9.00m = lv_size
-+lvcreate --type raid1 -m 1 -l 100%FREE -n raid1 $vg $dev1 $dev2
-+check lv_field $vg/raid1 size "9.00m"
-+# Ensure image size is the same as the RAID1 size
-+check lv_field $vg/raid1 size `lvs --noheadings -o size $vg/raid1_rimage_0`
-+# Amount remaining in dev2 should equal the amount taken by 'lv' in dev1
-+check pv_field "$dev2" pv_free `lvs --noheadings -o size $vg/lv`
-+lvremove -ff $vg
-+
-+# Eat 18 of 37 extents from dev1, leaving 19
-+lvcreate -l 18 -n lv $vg $dev1
-+# Using 100% free should take the rest of dev1 and equal amount from the rest
-+# 1 meta takes 1 extent
-+# 1 image = 18 extents = 9.00m
-+# 5 images = 90 extents = 45.00m = lv_size
-+lvcreate --type raid5 -i 5 -l 100%FREE -n raid5 $vg
-+check lv_field $vg/raid5 size "45.00m"
-+# Amount remaining in dev6 should equal the amount taken by 'lv' in dev1
-+check pv_field "$dev6" pv_free `lvs --noheadings -o size $vg/lv`
-+lvremove -ff $vg
-+
-+# Eat 18 of 37 extents from dev1, leaving 19
-+lvcreate -l 18 -n lv $vg $dev1
-+# Using 100% free should take the rest of dev1, an equal amount
-+# from 2 more devs, and all extents from 3 additional devs
-+# 1 meta takes 1 extent
-+# 1 image = 18+37 extents
-+# 2 images = 110 extents = 55.00m = lv_size
-+lvcreate --type raid5 -i 2 -l 100%FREE -n raid5 $vg
-+check lv_field $vg/raid5 size "55.00m"
-+lvremove -ff $vg
-+
-+# Let's do some stripe tests too
-+# Eat 18 of 37 extents from dev1, leaving 19
-+lvcreate -l 18 -n lv $vg $dev1
-+# Using 100% free should take the rest of dev1 and an equal amount from rest
-+# 1 image = 19 extents
-+# 6 images = 114 extents = 57.00m = lv_size
-+lvcreate -i 6 -l 100%FREE -n stripe $vg
-+check lv_field $vg/stripe size "57.00m"
-+lvremove -ff $vg
-+
-+# Eat 18 of 37 extents from dev1, leaving 19
-+lvcreate -l 18 -n lv $vg $dev1
-+# Using 100% free should take the rest of dev1, an equal amount from
-+#  one more dev, and all of the remaining 4
-+# 1 image = 19+37+37 extents
-+# 2 images = 186 extents = 93.00m = lv_size
-+lvcreate -i 2 -l 100%FREE -n stripe $vg
-+check lv_field $vg/stripe size "93.00m"
-+lvremove -ff $vg
-+
-+# Create RAID (implicit stripe count based on PV count)
-+#######################################################
-+
-+# Not enough drives
-+not lvcreate --type raid1 -l1 $vg $dev1
-+not lvcreate --type raid5 -l2 $vg $dev1 $dev2
-+not lvcreate --type raid6 -l3 $vg $dev1 $dev2 $dev3 $dev4
-+
-+# Implicit count comes from #PVs given (always 2 for mirror though)
-+lvcreate --type raid1 -l1 -n raid1 $vg $dev1 $dev2
-+lv_devices $vg raid1 2
-+lvcreate --type raid5 -l2 -n raid5 $vg $dev1 $dev2 $dev3
-+lv_devices $vg raid5 3
-+lvcreate --type raid6 -l3 -n raid6 $vg $dev1 $dev2 $dev3 $dev4 $dev5
-+lv_devices $vg raid6 5
-+lvremove -ff $vg
-+
-+# Implicit count comes from total #PVs in VG (always 2 for mirror though)
-+lvcreate --type raid1 -l1 -n raid1 $vg
-+lv_devices $vg raid1 2
-+lvcreate --type raid5 -l2 -n raid5 $vg
-+lv_devices $vg raid5 6
-+lvcreate --type raid6 -l3 -n raid6 $vg
-+lv_devices $vg raid6 6
-+lvremove -ff $vg
-diff --git a/test/shell/lvcreate-raid10.sh b/test/shell/lvcreate-raid10.sh
-index 143e869..ba35fdf 100644
---- a/test/shell/lvcreate-raid10.sh
-+++ b/test/shell/lvcreate-raid10.sh
-@@ -11,6 +11,14 @@
- 
- . lib/test
- 
-+lv_devices() {
-+	local local_vg=$1
-+	local local_lv=$2
-+	local count=$3
-+
-+	[ $count == `lvs --noheadings -o devices $local_vg/$local_lv | sed s/,/' '/g | wc -w` ]
-+}
-+
- ########################################################
- # MAIN
- ########################################################
-@@ -23,7 +31,6 @@ vgcreate -s 512k $vg $(cat DEVICES)
- # Create RAID10:
- #
- 
--
- # Should not allow more than 2-way mirror
- not lvcreate --type raid10 -m 2 -i 2 -l 2 -n $lv1 $vg
- 
-@@ -46,6 +53,30 @@ aux wait_for_sync $vg $lv2
- 
- lvremove -ff $vg
- 
-+# Test 100%FREE option
-+# 37 extents / device
-+# 1 image = 36 extents (1 for meta)
-+# 3 images = 108 extents = 54.00m
-+lvcreate --type raid10 -i 3 -l 100%FREE -n raid10 $vg
-+check lv_field $vg/raid10 size "54.00m"
-+lvremove -ff $vg
-+
-+# Create RAID (implicit stripe count based on PV count)
-+#######################################################
-+
-+# Not enough drives
-+not lvcreate --type raid10 -l2 $vg $dev1 $dev2 $dev3
-+
-+# Implicit count comes from #PVs given (always 2-way mirror)
-+lvcreate --type raid10 -l2 -n raid10 $vg $dev1 $dev2 $dev3 $dev4
-+lv_devices $vg raid10 4
-+lvremove -ff $vg
-+
-+# Implicit count comes from total #PVs in VG (always 2 for mirror though)
-+lvcreate --type raid10 -l2 -n raid10 $vg
-+lv_devices $vg raid10 6
-+lvremove -ff $vg
-+
- #
- # FIXME: Add tests that specify particular PVs to use for creation
- #
-diff --git a/test/shell/lvcreate-thin-external.sh b/test/shell/lvcreate-thin-external.sh
-index c9aba6f..1e5b333 100644
---- a/test/shell/lvcreate-thin-external.sh
-+++ b/test/shell/lvcreate-thin-external.sh
-@@ -26,11 +26,21 @@ aux prepare_pvs 2 64
- 
- vgcreate $vg -s 64K $(cat DEVICES)
- 
-+# Test validation for external origin being multiple of thin pool chunk size
-+lvcreate -L10M -T $vg/pool192 -c 192k
-+lvcreate -an -pr -Zn -l1 -n $lv1 $vg
-+not lvcreate -s $vg/$lv1 --thinpool $vg/pool192
-+
-+lvcreate -an -pr -Zn -l5 -n $lv2 $vg
-+not lvcreate -s $vg/$lv2 --thinpool $vg/pool192
-+lvremove -f $vg
-+
-+# Prepare pool and external origin with filesystem
- lvcreate -L10M -V10M -T $vg/pool --name $lv1
--mkfs.ext2 $DM_DEV_DIR/$vg/$lv1
-+mkfs.ext2 "$DM_DEV_DIR/$vg/$lv1"
- 
- lvcreate -L4M -n $lv2 $vg
--mkfs.ext2 $DM_DEV_DIR/$vg/$lv2
-+mkfs.ext2 "$DM_DEV_DIR/$vg/$lv2"
- 
- # Fail to create external origin snapshot of rw LV
- not lvcreate -s $vg/$lv2 --thinpool $vg/pool
-@@ -80,7 +90,7 @@ check active $vg $lv5
- check active $vg $lv6
- check active $vg $lv7
- 
--fsck -n $DM_DEV_DIR/$vg/$lv1
--fsck -n $DM_DEV_DIR/$vg/$lv7
-+fsck -n "$DM_DEV_DIR/$vg/$lv1"
-+fsck -n "$DM_DEV_DIR/$vg/$lv7"
- 
- vgremove -ff $vg
-diff --git a/test/shell/lvcreate-thin-snap.sh b/test/shell/lvcreate-thin-snap.sh
-index b7511e7..cfc801a 100644
---- a/test/shell/lvcreate-thin-snap.sh
-+++ b/test/shell/lvcreate-thin-snap.sh
-@@ -33,11 +33,11 @@ aux prepare_pvs 2 64
- vgcreate $vg -s 64K $(cat DEVICES)
- 
- lvcreate -L10M -V10M -T $vg/pool --name $lv1
--mkfs.ext4 $DM_DEV_DIR/$vg/$lv1
-+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1"
- # create thin snapshot of thin LV
- lvcreate -K -s $vg/$lv1 --name snap
- # check snapshot filesystem was properly frozen before snapping
--fsck -n $DM_DEV_DIR/$vg/snap
-+fsck -n "$DM_DEV_DIR/$vg/snap"
- lvcreate -K -s $vg/$lv1 --name $lv2
- lvcreate -K -s $vg/$lv1 --name $vg/$lv3
- lvcreate --type snapshot $vg/$lv1
-@@ -57,8 +57,8 @@ lvcreate -K -s --name sn4 $vg/sn3
- lvremove -ff $vg
- 
- lvcreate -L10M --zero n -T $vg/pool -V10M --name $lv1
--mkfs.ext4 $DM_DEV_DIR/$vg/$lv1
-+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1"
- lvcreate -K -s $vg/$lv1 --name snap
--fsck -n $DM_DEV_DIR/$vg/snap
-+fsck -n "$DM_DEV_DIR/$vg/snap"
- 
- vgremove -ff $vg
-diff --git a/test/shell/lvcreate-thin.sh b/test/shell/lvcreate-thin.sh
-index 98ab7eb..a2811d2 100644
---- a/test/shell/lvcreate-thin.sh
-+++ b/test/shell/lvcreate-thin.sh
-@@ -136,9 +136,9 @@ check vg_field $vg lv_count 0
- 
- # Create thin snapshot of thinLV
- lvcreate -L10M -V10M -T $vg/pool --name lv1
--mkfs.ext4 $DM_DEV_DIR/$vg/lv1
-+mkfs.ext4 "$DM_DEV_DIR/$vg/lv1"
- lvcreate -K -s $vg/lv1 --name snap_lv1
--fsck -n $DM_DEV_DIR/$vg/snap_lv1
-+fsck -n "$DM_DEV_DIR/$vg/snap_lv1"
- lvcreate -s $vg/lv1 --name lv2
- lvcreate -s $vg/lv1 --name $vg/lv3
- lvcreate --type snapshot $vg/lv1 --name lv6
-diff --git a/test/shell/lvextend-thin-metadata-dmeventd.sh b/test/shell/lvextend-thin-metadata-dmeventd.sh
-new file mode 100644
-index 0000000..cb5261c
---- /dev/null
-+++ b/test/shell/lvextend-thin-metadata-dmeventd.sh
-@@ -0,0 +1,93 @@
-+#!/bin/sh
-+# Copyright (C) 2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+# Test autoextension of thin metadata volume
-+. lib/test
-+
-+meta_percent_() {
-+	get lv_field $vg/pool metadata_percent | cut -d. -f1
-+}
-+
-+wait_for_change_() {
-+	# dmeventd only checks every 10 seconds :(
-+	for i in $(seq 1 15) ; do
-+		test "$(meta_percent_)" != "$1" && return
-+		sleep 1
-+	done
-+
-+	return 1  # timeout
-+}
-+
-+#
-+# Temporary solution to create some occupied thin metadata
-+# This heavily depends on thin metadata output format to stay as is.
-+# Currently it expects 2MB thin metadata and 200MB data volume size
-+# Argument specifies how many devices should be created.
-+fake_metadata_() {
-+	echo '<superblock uuid="" time="1" transaction="'$2'" data_block_size="128" nr_data_blocks="3200">'
-+	for i in $(seq 1 $1)
-+	do
-+		echo ' <device dev_id="'$i'" mapped_blocks="785" transaction="0" creation_time="0" snap_time="1">'
-+		echo '  <range_mapping origin_begin="0" data_begin="0" length="37" time="0"/>'
-+		echo ' </device>'
-+	done
-+	echo "</superblock>"
-+}
-+
-+aux have_thin 1 10 0 || skip
-+
-+aux prepare_dmeventd
-+
-+aux lvmconf "activation/thin_pool_autoextend_percent = 10" \
-+	    "activation/thin_pool_autoextend_threshold = 70"
-+
-+aux prepare_pvs 3 256
-+
-+vgcreate -s 1M $vg $(cat DEVICES)
-+
-+# Testing dmeventd autoresize
-+lvcreate -L200M -V1G -n thin -T $vg/pool
-+lvcreate -L2M -n $lv1 $vg
-+lvchange -an $vg/thin $vg/pool
-+
-+# Prepare some fake metadata with unmatching id
-+# Transaction_id is lower by 1 and there are no message -> ERROR
-+fake_metadata_ 10 0 >data
-+thin_restore -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
-+lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1
-+not vgchange -ay $vg 2>&1 | tee out
-+grep expected out
-+
-+check inactive $vg pool_tmeta
-+
-+# Transaction_id is higher by 1
-+fake_metadata_ 10 2 >data
-+thin_restore -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
-+lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1
-+not vgchange -ay $vg 2>&1 | tee out
-+grep expected out
-+
-+check inactive $vg pool_tmeta
-+
-+# Prepare some fake metadata prefilled to ~81% (>70%)
-+fake_metadata_ 400 1 >data
-+thin_restore -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
-+
-+# Swap volume with restored fake metadata
-+lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1
-+
-+vgchange -ay $vg
-+
-+# Check dmeventd resizes metadata
-+pre=$(meta_percent_)
-+wait_for_change_ $pre
-+
-+vgremove -f $vg
-diff --git a/test/shell/lvmetad-disabled.sh b/test/shell/lvmetad-disabled.sh
-index 41a3a19..c344d7f 100644
---- a/test/shell/lvmetad-disabled.sh
-+++ b/test/shell/lvmetad-disabled.sh
-@@ -13,14 +13,17 @@
- 
- test -e LOCAL_LVMETAD || skip
- kill $(cat LOCAL_LVMETAD)
-+while test -e "$TESTDIR/lvmetad.socket"; do echo -n .; sleep .1; done # wait for the socket close
-+test ! -e "$LVM_LVMETAD_PIDFILE"
- 
--test -e $LVMETAD_PIDFILE && skip
- lvmetad
--test -e $LVMETAD_PIDFILE
--cp $LVMETAD_PIDFILE LOCAL_LVMETAD
-+while ! test -e "$TESTDIR/lvmetad.socket"; do echo -n .; sleep .1; done # wait for the socket
-+test -e "$LVM_LVMETAD_PIDFILE"
-+cp "$LVM_LVMETAD_PIDFILE" LOCAL_LVMETAD
-+
- pvs 2>&1 | not grep "lvmetad is running"
- aux lvmconf "global/use_lvmetad = 0"
- pvs 2>&1 | grep "lvmetad is running"
- 
--kill $(cat $LVMETAD_PIDFILE)
--not ls $LVMETAD_PIDFILE
-+kill $(cat "$LVM_LVMETAD_PIDFILE")
-+not ls "$LVM_LVMETAD_PIDFILE"
-diff --git a/test/shell/lvresize-thin-external-origin.sh b/test/shell/lvresize-thin-external-origin.sh
-new file mode 100644
-index 0000000..3499196
---- /dev/null
-+++ b/test/shell/lvresize-thin-external-origin.sh
-@@ -0,0 +1,42 @@
-+#!/bin/sh
-+# Copyright (C) 2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+# Test resize of thin volume with external origin
-+. lib/test
-+
-+aux have_thin 1 2 0 || skip
-+
-+# Pretend we miss the external_origin_extend feature
-+aux lvmconf "global/thin_disabled_features = [ \"external_origin_extend\" ]"
-+
-+aux prepare_pvs 2
-+
-+vgcreate -s 1M $vg $(cat DEVICES)
-+
-+lvcreate -L10 -n $lv1 $vg
-+
-+# Prepare thin pool
-+lvcreate -L20 -T $vg/pool
-+
-+# Convert $lv1 into thin LV with external origin
-+lvconvert -T $vg/$lv1 --thinpool $vg/pool --originname ext
-+
-+lvs -a $vg
-+
-+# Bigger size is not supported without feature external_origin_extend
-+not lvresize -L+10 $vg/$lv1
-+
-+# But reduction works
-+lvresize -L-5 -f $vg/$lv1
-+not lvresize -L+15 -y $vg/$lv1
-+# Try to resize again back up to the size of external origin
-+# But for now we do not support zeroing for rexetended areas.
-+not lvresize -L+5 -f $vg/$lv1
-diff --git a/test/shell/lvresize-thin-metadata.sh b/test/shell/lvresize-thin-metadata.sh
-index 16a7500..e62d8b6 100644
---- a/test/shell/lvresize-thin-metadata.sh
-+++ b/test/shell/lvresize-thin-metadata.sh
-@@ -1,5 +1,5 @@
- #!/bin/sh
--# Copyright (C) 2013 Red Hat, Inc. All rights reserved.
-+# Copyright (C) 2013-2014 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
-@@ -11,31 +11,35 @@
- 
- . lib/test
- 
--aux have_thin 9 9 0 || skip
-+aux have_thin 1 10 0 || skip
- 
--aux prepare_pvs 3 256
-+aux prepare_pvs 3 1256
- 
- vgcreate -s 1M $vg $(cat DEVICES)
- 
- for deactivate in true false; do
--	lvcreate -l1 -T $vg/pool
--
--	test $deactivate && lvchange -an $vg
--
-+# Create some thin volumes
-+	lvcreate -L20 -V30 -n $lv1 -T $vg/pool
-+	lvcreate -s $vg/$lv1
- # Confirm we have basic 2M metadata
- 	check lv_field $vg/pool_tmeta size "2.00m"
- 
--	lvresize --poolmetadata +2 $vg/pool
-+	test $deactivate && lvchange -an $vg
- 
-+	lvresize --poolmetadata +2M $vg/pool
- # Test it's been resized to 4M
- 	check lv_field $vg/pool_tmeta size "4.00m"
- 
--# TODO: Add more tests when kernel is fixed
--	lvresize --alloc anywhere --poolmetadata +256 $vg/pool
-+	lvresize --poolmetadata +256M $vg/pool
-+	check lv_field $vg/pool_tmeta size "260.00m"
-+
-+	lvresize --poolmetadata +3G $vg/pool
-+	check lv_field $vg/pool_tmeta size "3.25g"
- 
- 	vgchange -an $vg
- 	vgchange -ay $vg
- 
--# TODO: Make a full metadata device and test dmeventd support
-+# TODO: Add more tests
-+
- 	lvremove -ff $vg
- done
-diff --git a/test/shell/lvresize-usage.sh b/test/shell/lvresize-usage.sh
-index 51ef221..84431ed 100644
---- a/test/shell/lvresize-usage.sh
-+++ b/test/shell/lvresize-usage.sh
-@@ -1,5 +1,5 @@
- #!/bin/sh
--# Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
-+# Copyright (C) 2007-2014 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
-@@ -11,7 +11,7 @@
- 
- . lib/test
- 
--aux prepare_vg 2
-+aux prepare_vg 2 80
- 
- lvcreate -L 10M -n lv -i2 $vg
- lvresize -l +4 $vg/lv
-@@ -19,3 +19,8 @@ lvremove -ff $vg
- 
- lvcreate -L 64M -n $lv -i2 $vg
- not lvresize -v -l +4 xxx/$lv
-+
-+# Check stripe size is reduced to extent size when it's bigger
-+ESIZE=$(get vg_field $vg vg_extent_size --units b)
-+lvextend -L+64m -i 2 -I$(( ${ESIZE%%B} * 2 ))B $vg/$lv 2>&1 | tee err
-+grep "Reducing stripe size" err
-diff --git a/test/shell/name-mangling.sh b/test/shell/name-mangling.sh
-index 5b92e60..76d90fa 100644
---- a/test/shell/name-mangling.sh
-+++ b/test/shell/name-mangling.sh
-@@ -164,8 +164,8 @@ function check_mangle_cmd()
- # check dmsetup can process path where the last component is not equal dm name (rhbz #797322)
- r=0
- create_dm_dev auto "abc"
--ln -s ${DM_DEV_DIR}/mapper/${name_prefix}abc ${DM_DEV_DIR}/${name_prefix}xyz
--dmsetup status ${DM_DEV_DIR}/${name_prefix}xyz || r=1
-+ln -s "$DM_DEV_DIR/mapper/${name_prefix}abc" "$DM_DEV_DIR/${name_prefix}xyz"
-+dmsetup status "$DM_DEV_DIR/${name_prefix}xyz" || r=1
- remove_dm_dev auto "abc"
- if [ r = 1 ]; then
- 	exit 1
-diff --git a/test/shell/process-each-lv.sh b/test/shell/process-each-lv.sh
-index 0140c26..207f1ba 100644
---- a/test/shell/process-each-lv.sh
-+++ b/test/shell/process-each-lv.sh
-@@ -36,139 +36,88 @@ aux prepare_devs 10
- # test lvremove vg|lv names
- #
- 
--# set up vgs/lvs that we will remove
--vgcreate $vg1 "$dev1" "$dev2"
--vgcreate $vg2 "$dev3" "$dev4"
--vgcreate $vg3 "$dev5" "$dev6"
--vgcreate $vg4 "$dev7" "$dev8"
--vgcreate $vg5 "$dev9" "$dev10"
--lvcreate -l 2 -n $lv1 $vg1
--lvcreate -l 2 -n $lv1 $vg2
--lvcreate -l 2 -n $lv2 $vg2
--lvcreate -l 2 -n $lv1 $vg3
--lvcreate -l 2 -n $lv2 $vg3
--lvcreate -l 2 -n $lv3 $vg3
--lvcreate -l 2 -n $lv1 $vg5
--lvcreate -l 2 -n $lv2 $vg5
--lvcreate -l 2 -n $lv3 $vg5
--lvcreate -l 2 -n $lv4 $vg5
--lvcreate -l 2 -n $lv5 $vg5
--vgchange -an $vg1
--vgchange -an $vg2
--vgchange -an $vg3
--vgchange -an $vg4
--vgchange -an $vg5
-+prepare_vgs_() {
-+	# set up vgs/lvs that we will remove
-+	vgcreate $vg1 "$dev1" "$dev2"
-+	vgcreate $vg2 "$dev3" "$dev4"
-+	vgcreate $vg3 "$dev5" "$dev6"
-+	vgcreate $vg4 "$dev7" "$dev8"
-+	vgcreate $vg5 "$dev9" "$dev10"
-+	lvcreate -Zn -an -l 2 -n $lv1 $vg1
-+	lvcreate -Zn -an -l 2 -n $lv1 $vg2
-+	lvcreate -Zn -an -l 2 -n $lv2 $vg2
-+	lvcreate -Zn -an -l 2 -n $lv1 $vg3
-+	lvcreate -Zn -an -l 2 -n $lv2 $vg3
-+	lvcreate -Zn -an -l 2 -n $lv3 $vg3
-+	lvcreate -Zn -an -l 2 -n $lv1 $vg5
-+	lvcreate -Zn -an -l 2 -n $lv2 $vg5
-+	lvcreate -Zn -an -l 2 -n $lv3 $vg5
-+	lvcreate -Zn -an -l 2 -n $lv4 $vg5
-+	lvcreate -Zn -an -l 2 -n $lv5 $vg5
-+}
-+
-+#
-+#
-+#
-+prepare_vgs_
- 
- not lvremove
- not lvremove garbage
- not lvremove $vg1/garbage
- 
- lvremove $vg1
--lvs $vg1
--not lvs $vg1/$lv1
-+check lv_exists $vg1
-+check lv_not_exists $vg1 $lv1
- vgremove $vg1
- 
- lvremove $vg2
--lvs $vg2
--not lvs $vg2/$lv1
--not lvs $vg2/$lv2
-+check lv_exists $vg2
-+check lv_not_exists $vg2 $lv1 $lv2
- vgremove $vg2
- 
- lvremove $vg3/$lv1
- lvremove $vg3/$lv2 $vg3/$lv3
--lvs $vg3
--not lvs $vg3/$lv1
--not lvs $vg3/$lv2
--not lvs $vg3/$lv3
-+check lv_exists $vg3
-+check lv_not_exists $vg3 $lv1 $lv2 $lv3
- vgremove $vg3
- 
- lvremove $vg4
--lvs $vg4
-+check lv_exists $vg4
- vgremove $vg4
- 
- lvremove $vg5/$lv1 $vg5 $vg5/$lv3
--not lvs $vg5/$lv1
--not lvs $vg5/$lv2
--not lvs $vg5/$lv3
--not lvs $vg5/$lv4
--not lvs $vg5/$lv5
-+check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5
- vgremove $vg5
- 
- 
- #
- # test lvremove vg|lv names from multiple vgs
- #
--
--# set up vgs/lvs that we will remove
--vgcreate $vg1 "$dev1" "$dev2"
--vgcreate $vg2 "$dev3" "$dev4"
--vgcreate $vg3 "$dev5" "$dev6"
--vgcreate $vg4 "$dev7" "$dev8"
--vgcreate $vg5 "$dev9" "$dev10"
--lvcreate -l 2 -n $lv1 $vg1
--lvcreate -l 2 -n $lv1 $vg2
--lvcreate -l 2 -n $lv2 $vg2
--lvcreate -l 2 -n $lv1 $vg3
--lvcreate -l 2 -n $lv2 $vg3
--lvcreate -l 2 -n $lv3 $vg3
--lvcreate -l 2 -n $lv1 $vg5
--lvcreate -l 2 -n $lv2 $vg5
--lvcreate -l 2 -n $lv3 $vg5
--lvcreate -l 2 -n $lv4 $vg5
--lvcreate -l 2 -n $lv5 $vg5
--vgchange -an $vg1
--vgchange -an $vg2
--vgchange -an $vg3
--vgchange -an $vg4
--vgchange -an $vg5
-+prepare_vgs_
- 
- lvremove $vg2 $vg3/$lv3 $vg5/$lv1
--not lvs $vg2/$lv1
--not lvs $vg2/$lv2
--not lvs $vg3/$lv3
--not lvs $vg5/$lv1
-+check lv_not_exists $vg2 $lv1 $lv2
-+check lv_not_exists $vg3 $lv3
-+check lv_not_exists $vg5 $lv1
- 
- lvremove $vg2 $vg1
--not lvs $vg1/$lv1
-+check lv_not_exists $vg1 $lv1
- 
- lvremove $vg3/$lv1 $vg3 $vg4 $vg5/$lv2
--not lvs $vg3/$lv1
--not lvs $vg3/$lv2
--not lvs $vg5/$lv2
-+check lv_not_exists $vg3 $lv1 $lv2
-+check lv_not_exists $vg5 $lv2
- 
- lvremove $vg5 $vg1 $vg5/$lv3
--not lvs $vg5/$lv3
--not lvs $vg5/$lv4
--not lvs $vg5/$lv5
-+check lv_not_exists $vg5 $lv3 $lv4 $lv5
- 
--vgremove $vg1
--vgremove $vg2
--vgremove $vg3
--vgremove $vg4
--vgremove $vg5
-+vgremove $vg1 $vg2 $vg3 $vg4 $vg5
- 
- 
- #
- # test lvremove @lvtags
- #
-+prepare_vgs_
- 
--# set up vgs/lvs that we will remove
--vgcreate $vg1 "$dev1" "$dev2"
--vgcreate $vg2 "$dev3" "$dev4"
--vgcreate $vg3 "$dev5" "$dev6"
--vgcreate $vg4 "$dev7" "$dev8"
--vgcreate $vg5 "$dev9" "$dev10"
--lvcreate -l 2 -n $lv1 $vg1
--lvcreate -l 2 -n $lv1 $vg2
--lvcreate -l 2 -n $lv2 $vg2
--lvcreate -l 2 -n $lv1 $vg3
--lvcreate -l 2 -n $lv2 $vg3
--lvcreate -l 2 -n $lv3 $vg3
--lvcreate -l 2 -n $lv1 $vg5
--lvcreate -l 2 -n $lv2 $vg5
--lvcreate -l 2 -n $lv3 $vg5
--lvcreate -l 2 -n $lv4 $vg5
--lvcreate -l 2 -n $lv5 $vg5
- lvchange --addtag V1L1 $vg1/$lv1
- lvchange --addtag V2L1 $vg2/$lv1
- lvchange --addtag V2L2 $vg2/$lv2
-@@ -185,99 +134,52 @@ lvchange --addtag V5L234 $vg5/$lv2
- lvchange --addtag V5L234 $vg5/$lv3
- lvchange --addtag V5L234 $vg5/$lv4
- lvchange --addtag V5L5   $vg5/$lv5
--vgchange -an $vg1
--vgchange -an $vg2
--vgchange -an $vg3
--vgchange -an $vg4
--vgchange -an $vg5
-+vgchange -an $vg1 $vg2 $vg3 $vg4 $vg5
- 
- # verify all exist
--lvs $vg1/$lv1
--lvs $vg2/$lv1
--lvs $vg2/$lv2
--lvs $vg3/$lv1
--lvs $vg3/$lv2
--lvs $vg3/$lv3
--lvs $vg5/$lv1
--lvs $vg5/$lv2
--lvs $vg5/$lv3
--lvs $vg5/$lv4
--lvs $vg5/$lv5
-+check lv_exists $vg1 $lv1
-+check lv_exists $vg2 $lv1 $lv2
-+check lv_exists $vg3 $lv1 $lv2 $lv3
-+check lv_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5
- 
- lvremove @garbage
- 
- lvremove @V3L3A
--not lvs $vg3/$lv3
-+check lv_not_exists $vg3 $lv3
- # verify unremoved still exist
--lvs $vg1/$lv1
--lvs $vg2/$lv1
--lvs $vg2/$lv2
--lvs $vg3/$lv1
--lvs $vg3/$lv2
--lvs $vg5/$lv1
--lvs $vg5/$lv2
--lvs $vg5/$lv3
--lvs $vg5/$lv4
--lvs $vg5/$lv5
-+check lv_exists $vg1 $lv1
-+check lv_exists $vg2 $lv1 $lv2
-+check lv_exists $vg3 $lv1 $lv2
-+check lv_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5
- 
- lvremove @V5L234
--not lvs $vg5/$lv2
--not lvs $vg5/$lv3
--not lvs $vg5/$lv4
-+check lv_not_exists $vg5 $lv2 $lv3 $lv4
- # verify unremoved still exist
--lvs $vg1/$lv1
--lvs $vg2/$lv1
--lvs $vg2/$lv2
--lvs $vg3/$lv1
--lvs $vg3/$lv2
--lvs $vg5/$lv1
--lvs $vg5/$lv5
-+check lv_exists $vg1 $lv1
-+check lv_exists $vg2 $lv1 $lv2
-+check lv_exists $vg3 $lv1 $lv2
-+check lv_exists $vg5 $lv1 $lv5
- 
- lvremove @V5L1 @V5L5
--not lvs $vg5/$lv1
--not lvs $vg5/$lv5
-+check lv_not_exists $vg5 $lv1 $lv5
- # verify unremoved still exist
--lvs $vg1/$lv1
--lvs $vg2/$lv1
--lvs $vg2/$lv2
--lvs $vg3/$lv1
--lvs $vg3/$lv2
-+check lv_exists $vg1 $lv1
-+check lv_exists $vg2 $lv1 $lv2
-+check lv_exists $vg3 $lv1 $lv2
- 
- lvremove @V23 @V1L1 @V3L2
--not lvs $vg1/$lv1
--not lvs $vg2/$lv1
--not lvs $vg2/$lv2
--not lvs $vg3/$lv1
--not lvs $vg3/$lv2
-+check lv_not_exists $vg1 $lv1
-+check lv_not_exists $vg2 $lv1 $lv2
-+check lv_not_exists $vg3 $lv1 $lv2
- 
--vgremove $vg1
--vgremove $vg2
--vgremove $vg3
--vgremove $vg4
--vgremove $vg5
-+vgremove $vg1 $vg2 $vg3 $vg4 $vg5
- 
- 
- #
- # test lvremove @vgtags
- #
-+prepare_vgs_
- 
--# set up vgs/lvs that we will remove
--vgcreate $vg1 "$dev1" "$dev2"
--vgcreate $vg2 "$dev3" "$dev4"
--vgcreate $vg3 "$dev5" "$dev6"
--vgcreate $vg4 "$dev7" "$dev8"
--vgcreate $vg5 "$dev9" "$dev10"
--lvcreate -l 2 -n $lv1 $vg1
--lvcreate -l 2 -n $lv1 $vg2
--lvcreate -l 2 -n $lv2 $vg2
--lvcreate -l 2 -n $lv1 $vg3
--lvcreate -l 2 -n $lv2 $vg3
--lvcreate -l 2 -n $lv3 $vg3
--lvcreate -l 2 -n $lv1 $vg5
--lvcreate -l 2 -n $lv2 $vg5
--lvcreate -l 2 -n $lv3 $vg5
--lvcreate -l 2 -n $lv4 $vg5
--lvcreate -l 2 -n $lv5 $vg5
- vgchange --addtag V1  $vg1
- vgchange --addtag V23 $vg2
- vgchange --addtag V23 $vg3
-@@ -285,71 +187,34 @@ vgchange --addtag V35 $vg3
- vgchange --addtag V4  $vg4
- vgchange --addtag V35 $vg5
- vgchange --addtag V5  $vg5
--vgchange -an $vg1
--vgchange -an $vg2
--vgchange -an $vg3
--vgchange -an $vg4
--vgchange -an $vg5
-+vgchange -an $vg1 $vg2 $vg3 $vg4 $vg5
- 
- lvremove @V4
- # verify unremoved exist
--lvs $vg1/$lv1
--lvs $vg2/$lv1
--lvs $vg2/$lv2
--lvs $vg3/$lv1
--lvs $vg3/$lv2
--lvs $vg3/$lv3
--lvs $vg5/$lv1
--lvs $vg5/$lv2
--lvs $vg5/$lv3
--lvs $vg5/$lv4
--lvs $vg5/$lv5
-+check lv_exists $vg1 $lv1
-+check lv_exists $vg2 $lv1 $lv2
-+check lv_exists $vg3 $lv1 $lv2 $lv3
-+check lv_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5
- 
- lvremove @V5
--not lvs $vg5/$lv1
--not lvs $vg5/$lv2
--not lvs $vg5/$lv3
--not lvs $vg5/$lv4
--not lvs $vg5/$lv5
-+check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5
- # verify unremoved exist
--lvs $vg1/$lv1
--lvs $vg2/$lv1
--lvs $vg2/$lv2
--lvs $vg3/$lv1
--lvs $vg3/$lv2
--lvs $vg3/$lv3
-+check lv_exists $vg1 $lv1
-+check lv_exists $vg2 $lv1 $lv2
-+check lv_exists $vg3 $lv1 $lv2 $lv3
- 
- lvremove @V1 @V23
--not lvs $vg1/$lv1
--not lvs $vg2/$lv1
--not lvs $vg2/$lv2
--not lvs $vg3/$lv1
--not lvs $vg3/$lv2
--not lvs $vg3/$lv3
-+check lv_not_exists $vg1 $lv1
-+check lv_not_exists $vg2 $lv1 $lv2
-+check lv_not_exists $vg3 $lv1 $lv2 $lv3
- 
--vgremove $vg1
--vgremove $vg2
--vgremove $vg3
--vgremove $vg4
--vgremove $vg5
-+vgremove $vg1 $vg2 $vg3 $vg4 $vg5
-+
-+#
-+#
-+#
-+prepare_vgs_
- 
--# set up vgs/lvs that we will remove
--vgcreate $vg1 "$dev1" "$dev2"
--vgcreate $vg2 "$dev3" "$dev4"
--vgcreate $vg3 "$dev5" "$dev6"
--vgcreate $vg4 "$dev7" "$dev8"
--vgcreate $vg5 "$dev9" "$dev10"
--lvcreate -l 2 -n $lv1 $vg1
--lvcreate -l 2 -n $lv1 $vg2
--lvcreate -l 2 -n $lv2 $vg2
--lvcreate -l 2 -n $lv1 $vg3
--lvcreate -l 2 -n $lv2 $vg3
--lvcreate -l 2 -n $lv3 $vg3
--lvcreate -l 2 -n $lv1 $vg5
--lvcreate -l 2 -n $lv2 $vg5
--lvcreate -l 2 -n $lv3 $vg5
--lvcreate -l 2 -n $lv4 $vg5
--lvcreate -l 2 -n $lv5 $vg5
- vgchange --addtag V1  $vg1
- vgchange --addtag V23 $vg2
- vgchange --addtag V23 $vg3
-@@ -357,59 +222,26 @@ vgchange --addtag V35 $vg3
- vgchange --addtag V4  $vg4
- vgchange --addtag V35 $vg5
- vgchange --addtag V5  $vg5
--vgchange -an $vg1
--vgchange -an $vg2
--vgchange -an $vg3
--vgchange -an $vg4
--vgchange -an $vg5
- 
- lvremove @V35 @V5
--not lvs $vg3/$lv1
--not lvs $vg3/$lv2
--not lvs $vg3/$lv3
--not lvs $vg5/$lv1
--not lvs $vg5/$lv2
--not lvs $vg5/$lv3
--not lvs $vg5/$lv4
--not lvs $vg5/$lv5
-+check lv_not_exists $vg3 $lv1 $lv2 /$lv3
-+check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5
- # verify unremoved exist
--lvs $vg1/$lv1
--lvs $vg2/$lv1
--lvs $vg2/$lv2
-+check lv_exists $vg1 $lv1
-+check lv_exists $vg2 $lv1 $lv2
- 
- lvremove @V1 @V23
--not lvs $vg1/$lv1
--not lvs $vg2/$lv1
--not lvs $vg2/$lv2
-+check lv_not_exists $vg1 $lv1
-+check lv_not_exists $vg2 $lv1 $lv2
- 
--vgremove $vg1
--vgremove $vg2
--vgremove $vg3
--vgremove $vg4
--vgremove $vg5
-+vgremove $vg1 $vg2 $vg3 $vg4 $vg5
- 
- 
- #
- # test lvremove vg|lv names and @lvtags
- #
-+prepare_vgs_
- 
--# set up vgs/lvs that we will remove
--vgcreate $vg1 "$dev1" "$dev2"
--vgcreate $vg2 "$dev3" "$dev4"
--vgcreate $vg3 "$dev5" "$dev6"
--vgcreate $vg4 "$dev7" "$dev8"
--vgcreate $vg5 "$dev9" "$dev10"
--lvcreate -l 2 -n $lv1 $vg1
--lvcreate -l 2 -n $lv1 $vg2
--lvcreate -l 2 -n $lv2 $vg2
--lvcreate -l 2 -n $lv1 $vg3
--lvcreate -l 2 -n $lv2 $vg3
--lvcreate -l 2 -n $lv3 $vg3
--lvcreate -l 2 -n $lv1 $vg5
--lvcreate -l 2 -n $lv2 $vg5
--lvcreate -l 2 -n $lv3 $vg5
--lvcreate -l 2 -n $lv4 $vg5
--lvcreate -l 2 -n $lv5 $vg5
- lvchange --addtag V1L1 $vg1/$lv1
- lvchange --addtag V2L1 $vg2/$lv1
- lvchange --addtag V2L2 $vg2/$lv2
-@@ -426,56 +258,27 @@ lvchange --addtag V5L234 $vg5/$lv2
- lvchange --addtag V5L234 $vg5/$lv3
- lvchange --addtag V5L234 $vg5/$lv4
- lvchange --addtag V5L5   $vg5/$lv5
--vgchange -an $vg1
--vgchange -an $vg2
--vgchange -an $vg3
--vgchange -an $vg4
--vgchange -an $vg5
-+vgchange -an $vg1 $vg2 $vg3 $vg4 $vg5
- 
- lvremove $vg1/$lv1 @V3L2 @V5L234
--not lvs $vg1/$lv1
--not lvs $vg3/$lv2
--not lvs $vg5/$lv2
--not lvs $vg5/$lv3
--not lvs $vg5/$lv4
-+check lv_not_exists $vg1 $lv1
-+check lv_not_exists $vg3 $lv2
-+check lv_not_exists $vg5 $lv2 $lv3 $lv4
- # verify unremoved exist
--lvs $vg2/$lv1
--lvs $vg2/$lv2
--lvs $vg3/$lv1
--lvs $vg3/$lv3
--lvs $vg5/$lv1
--lvs $vg5/$lv5
-+check lv_exists $vg2 $lv1 $lv2
-+check lv_exists $vg3 $lv1 $lv3
-+check lv_exists $vg5 $lv1 $lv5
- 
- lvremove $vg2/$lv1 @V23 $vg5/$lv1 @V5L5
- 
--vgremove $vg1
--vgremove $vg2
--vgremove $vg3
--vgremove $vg4
--vgremove $vg5
-+vgremove $vg1 $vg2 $vg3 $vg4 $vg5
- 
- 
- #
- # test lvremove vg|lv names and @vgtags
- #
-+prepare_vgs_
- 
--# set up vgs/lvs that we will remove
--vgcreate $vg1 "$dev1" "$dev2"
--vgcreate $vg2 "$dev3" "$dev4"
--vgcreate $vg3 "$dev5" "$dev6"
--vgcreate $vg4 "$dev7" "$dev8"
--vgcreate $vg5 "$dev9" "$dev10"
--lvcreate -l 2 -n $lv1 $vg1
--lvcreate -l 2 -n $lv1 $vg2
--lvcreate -l 2 -n $lv2 $vg2
--lvcreate -l 2 -n $lv1 $vg3
--lvcreate -l 2 -n $lv2 $vg3
--lvcreate -l 2 -n $lv3 $vg3
--lvcreate -l 2 -n $lv1 $vg5
--lvcreate -l 2 -n $lv2 $vg5
--lvcreate -l 2 -n $lv3 $vg5
--lvcreate -l 2 -n $lv4 $vg5
--lvcreate -l 2 -n $lv5 $vg5
- vgchange --addtag V1  $vg1
- vgchange --addtag V23 $vg2
- vgchange --addtag V23 $vg3
-@@ -483,56 +286,24 @@ vgchange --addtag V35 $vg3
- vgchange --addtag V4  $vg4
- vgchange --addtag V35 $vg5
- vgchange --addtag V5  $vg5
--vgchange -an $vg1
--vgchange -an $vg2
--vgchange -an $vg3
--vgchange -an $vg4
--vgchange -an $vg5
- 
- lvremove $vg1/$lv1 @V35
--not lvs $vg1/$lv1
--not lvs $vg3/$lv1
--not lvs $vg3/$lv2
--not lvs $vg3/$lv3
--not lvs $vg5/$lv1
--not lvs $vg5/$lv2
--not lvs $vg5/$lv3
--not lvs $vg5/$lv4
--not lvs $vg5/$lv5
-+check lv_not_exists $vg1 $lv1
-+check lv_not_exists $vg3 $lv1 $lv2 $lv3
-+check lv_not_exists $vg5 $lv1 $lv2 $lv3not $lv4 $lv5
- # verify unremoved exist
--lvs $vg2/$lv1
--lvs $vg2/$lv2
-+check lv_exists $vg2 $lv1 $lv2
- 
- lvremove $vg2/$lv1 @V23 $vg2/$lv2
- 
--vgremove $vg1
--vgremove $vg2
--vgremove $vg3
--vgremove $vg4
--vgremove $vg5
-+vgremove $vg1 $vg2 $vg3 $vg4 $vg5
- 
- 
- #
- # test lvremove @lvtags and @vgtags
- #
-+prepare_vgs_
- 
--# set up vgs/lvs that we will remove
--vgcreate $vg1 "$dev1" "$dev2"
--vgcreate $vg2 "$dev3" "$dev4"
--vgcreate $vg3 "$dev5" "$dev6"
--vgcreate $vg4 "$dev7" "$dev8"
--vgcreate $vg5 "$dev9" "$dev10"
--lvcreate -l 2 -n $lv1 $vg1
--lvcreate -l 2 -n $lv1 $vg2
--lvcreate -l 2 -n $lv2 $vg2
--lvcreate -l 2 -n $lv1 $vg3
--lvcreate -l 2 -n $lv2 $vg3
--lvcreate -l 2 -n $lv3 $vg3
--lvcreate -l 2 -n $lv1 $vg5
--lvcreate -l 2 -n $lv2 $vg5
--lvcreate -l 2 -n $lv3 $vg5
--lvcreate -l 2 -n $lv4 $vg5
--lvcreate -l 2 -n $lv5 $vg5
- lvchange --addtag V1L1 $vg1/$lv1
- lvchange --addtag V2L1 $vg2/$lv1
- lvchange --addtag V2L2 $vg2/$lv2
-@@ -557,57 +328,25 @@ vgchange --addtag V35 $vg3
- vgchange --addtag V4  $vg4
- vgchange --addtag V35 $vg5
- vgchange --addtag V5  $vg5
--vgchange -an $vg1
--vgchange -an $vg2
--vgchange -an $vg3
--vgchange -an $vg4
--vgchange -an $vg5
- 
- lvremove @V23 @V35
--not lvs $vg2/$lv1
--not lvs $vg2/$lv2
--not lvs $vg3/$lv1
--not lvs $vg3/$lv2
--not lvs $vg3/$lv3
--not lvs $vg5/$lv1
--not lvs $vg5/$lv2
--not lvs $vg5/$lv3
--not lvs $vg5/$lv4
--not lvs $vg5/$lv5
-+check lv_not_exists $vg2 $lv1 $lv2
-+check lv_not_exists $vg3 $lv1 $lv2 $lv3
-+check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5
- # verify unremoved exist
--lvs $vg1/$lv1
-+check lv_exists $vg1 $lv1
- 
- lvremove @V1 @V1L1
--not lvs $vg1/$lv1
-+check lv_not_exists $vg1 $lv1
- 
--vgremove $vg1
--vgremove $vg2
--vgremove $vg3
--vgremove $vg4
--vgremove $vg5
-+vgremove $vg1 $vg2 $vg3 $vg4 $vg5
- 
- 
- #
- # test lvremove vg|lv names and @lvtags and @vgtags
- #
-+prepare_vgs_
- 
--# set up vgs/lvs that we will remove
--vgcreate $vg1 "$dev1" "$dev2"
--vgcreate $vg2 "$dev3" "$dev4"
--vgcreate $vg3 "$dev5" "$dev6"
--vgcreate $vg4 "$dev7" "$dev8"
--vgcreate $vg5 "$dev9" "$dev10"
--lvcreate -l 2 -n $lv1 $vg1
--lvcreate -l 2 -n $lv1 $vg2
--lvcreate -l 2 -n $lv2 $vg2
--lvcreate -l 2 -n $lv1 $vg3
--lvcreate -l 2 -n $lv2 $vg3
--lvcreate -l 2 -n $lv3 $vg3
--lvcreate -l 2 -n $lv1 $vg5
--lvcreate -l 2 -n $lv2 $vg5
--lvcreate -l 2 -n $lv3 $vg5
--lvcreate -l 2 -n $lv4 $vg5
--lvcreate -l 2 -n $lv5 $vg5
- lvchange --addtag V1L1 $vg1/$lv1
- lvchange --addtag V2L1 $vg2/$lv1
- lvchange --addtag V2L2 $vg2/$lv2
-@@ -632,60 +371,26 @@ vgchange --addtag V35 $vg3
- vgchange --addtag V4  $vg4
- vgchange --addtag V35 $vg5
- vgchange --addtag V5  $vg5
--vgchange -an $vg1
--vgchange -an $vg2
--vgchange -an $vg3
--vgchange -an $vg4
--vgchange -an $vg5
- 
- lvremove $vg1/$lv1 @V23 @V5L5
--not lvs $vg1/$lv1
--not lvs $vg2/$lv1
--not lvs $vg2/$lv2
--not lvs $vg3/$lv1
--not lvs $vg3/$lv2
--not lvs $vg3/$lv3
--not lvs $vg5/$lv5
-+check lv_not_exists $vg1 $lv1
-+check lv_not_exists $vg2 $lv1 $lv2
-+check lv_not_exists $vg3 $lv1 $lv2 $lv3
-+check lv_not_exists $vg5 $lv5
- # verify unremoved exist
--lvs $vg5/$lv1
--lvs $vg5/$lv2
--lvs $vg5/$lv3
--lvs $vg5/$lv4
-+check lv_exists $vg5 $lv1 $lv2 $lv3 $lv4
- 
- lvremove $vg5/$lv2 @V5L234 @V5
--not lvs $vg5/$lv1
--not lvs $vg5/$lv2
--not lvs $vg5/$lv3
--not lvs $vg5/$lv4
-+check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4
- 
--vgremove $vg1
--vgremove $vg2
--vgremove $vg3
--vgremove $vg4
--vgremove $vg5
-+vgremove $vg1 $vg2 $vg3 $vg4 $vg5
- 
- 
- #
- # test lvs: empty, vg(s), lv(s), vgtag(s), lvtag(s), garbage, combinations
- #
-+prepare_vgs_
- 
--# set up vgs/lvs that we will remove
--vgcreate $vg1 "$dev1" "$dev2"
--vgcreate $vg2 "$dev3" "$dev4"
--vgcreate $vg3 "$dev5" "$dev6"
--vgcreate $vg4 "$dev7" "$dev8"
--vgcreate $vg5 "$dev9" "$dev10"
--lvcreate -l 2 -n $lv1 $vg1
--lvcreate -l 2 -n $lv1 $vg2
--lvcreate -l 2 -n $lv2 $vg2
--lvcreate -l 2 -n $lv1 $vg3
--lvcreate -l 2 -n $lv2 $vg3
--lvcreate -l 2 -n $lv3 $vg3
--lvcreate -l 2 -n $lv1 $vg5
--lvcreate -l 2 -n $lv2 $vg5
--lvcreate -l 2 -n $lv3 $vg5
--lvcreate -l 2 -n $lv4 $vg5
--lvcreate -l 2 -n $lv5 $vg5
- lvchange --addtag V1L1 $vg1/$lv1
- lvchange --addtag V2L1 $vg2/$lv1
- lvchange --addtag V2L2 $vg2/$lv2
-@@ -709,11 +414,6 @@ vgchange --addtag V35 $vg3
- vgchange --addtag V4  $vg4
- vgchange --addtag V35 $vg5
- vgchange --addtag V5  $vg5
--vgchange -an $vg1
--vgchange -an $vg2
--vgchange -an $vg3
--vgchange -an $vg4
--vgchange -an $vg5
- 
- # empty
- lvs -o vg_name,lv_name --separator '-' >err
-@@ -951,4 +651,3 @@ not grep $vg5-$lv2 err
- not grep $vg5-$lv3 err
- not grep $vg5-$lv4 err
- not grep $vg5-$lv5 err
--
-diff --git a/test/shell/pvmove-all-segtypes.sh b/test/shell/pvmove-all-segtypes.sh
-index fcd8913..5e1c71c 100644
---- a/test/shell/pvmove-all-segtypes.sh
-+++ b/test/shell/pvmove-all-segtypes.sh
-@@ -13,12 +13,11 @@ test_description="ensure pvmove works with all common segment types"
- 
- . lib/test
- 
--test -e LOCAL_CLVMD && skip
- which mkfs.ext2 || skip
- which md5sum || skip
- 
- aux prepare_pvs 5 20
--vgcreate -c n -s 256k $vg $(cat DEVICES)
-+vgcreate -s 256k $vg $(cat DEVICES)
- 
- # Each of the following tests does:
- # 1) Create two LVs - one linear and one other segment type
-@@ -27,8 +26,8 @@ vgcreate -c n -s 256k $vg $(cat DEVICES)
- # 3) Move only the second LV by name
- 
- # Testing pvmove of linear LV
--lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
--lvcreate -l 2 -n $lv1 $vg "$dev1"
-+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"
- aux mkdev_md5sum $vg $lv1
-@@ -43,8 +42,8 @@ check dev_md5sum $vg $lv1
- lvremove -ff $vg
- 
- # Testing pvmove of stripe LV
--lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
--lvcreate -l 4 -i 2 -n $lv1 $vg "$dev1" "$dev2"
-+lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate -aey -l 4 -i 2 -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
-@@ -58,9 +57,14 @@ check lv_tree_on $vg ${lv1}_foo "$dev5"
- check dev_md5sum $vg $lv1
- lvremove -ff $vg
- 
-+if test -e LOCAL_CLVMD ; then
-+#FIXME these tests currently fail end require cmirrord
-+echo "TEST WARNING, FIXME!!! pvmove in clustered VG not fully supported!"
-+else
-+
- # Testing pvmove of mirror LV
--lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
--lvcreate -l 2 --type mirror -m 1 -n $lv1 $vg "$dev1" "$dev2"
-+lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate -aey -l 2 --type mirror -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
-@@ -76,8 +80,8 @@ lvremove -ff $vg
- 
- # Dummy LV and snap share dev1, while origin is on dev2
- # Testing pvmove of snapshot LV
--lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
--lvcreate -l 2 -n $lv1 $vg "$dev2"
-+lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate -aey -l 2 -n $lv1 $vg "$dev2"
- lvcreate -s $vg/$lv1 -l 2 -n snap "$dev1"
- check lv_tree_on $vg ${lv1}_foo "$dev1"
- check lv_tree_on $vg snap "$dev1"
-@@ -91,3 +95,4 @@ check lv_tree_on $vg snap "$dev4"
- check lv_tree_on $vg ${lv1}_foo "$dev5"
- check dev_md5sum $vg snap
- lvremove -ff $vg
-+fi
-diff --git a/test/shell/pvmove-cache-segtypes.sh b/test/shell/pvmove-cache-segtypes.sh
-new file mode 100644
-index 0000000..1c2423e
---- /dev/null
-+++ b/test/shell/pvmove-cache-segtypes.sh
-@@ -0,0 +1,178 @@
-+#!/bin/sh
-+# Copyright (C) 2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+test_description="ensure pvmove works with the cache segment types"
-+
-+. lib/test
-+
-+# pvmove fails when a RAID LV is the origin of a cache LV
-+# pvmoving cache types is currently disabled in tools/pvmove.c
-+# So, for now we set everything up and make sure pvmove /isn't/ allowed.
-+# This allows us to ensure that it is disallowed even when there are
-+# stacking complications to consider.
-+
-+test -e LOCAL_CLVMD && skip
-+which mkfs.ext2 || skip
-+which md5sum || skip
-+
-+aux target_at_least dm-cache 1 3 0 || skip
-+# for stacking
-+aux target_at_least dm-thin-pool 1 8 0 || skip
-+aux target_at_least dm-raid 1 4 2 || skip
-+
-+aux prepare_vg 5 80
-+
-+# Each of the following tests does:
-+# 1) Create two LVs - one linear and one other segment type
-+#    The two LVs will share a PV.
-+# 2) Move both LVs together
-+# 3) Move only the second LV by name
-+
-+# Testing pvmove of cache-pool LV (can't check contents though)
-+###############################################################
-+lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate --type cache-pool -n ${lv1}_pool -l 4 $vg "$dev1"
-+check lv_tree_on $vg ${lv1}_foo "$dev1"
-+check lv_tree_on $vg ${lv1}_pool "$dev1"
-+
-+pvmove "$dev1" "$dev5" 2>&1 | tee out
-+grep "Skipping cache-pool LV, ${lv1}_pool" out
-+grep "Skipping cache-related LV, ${lv1}_pool_cmeta" out
-+grep "Skipping cache-related LV, ${lv1}_pool_cdata" out
-+check lv_tree_on $vg ${lv1}_foo "$dev5"
-+not check lv_tree_on $vg ${lv1}_pool "$dev5"
-+
-+#pvmove -n ${lv1}_pool "$dev5" "$dev4"
-+#check lv_tree_on $vg ${lv1}_pool "$dev4"
-+#check lv_tree_on $vg ${lv1}_foo "$dev5"
-+
-+lvremove -ff $vg
-+
-+# Testing pvmove of origin LV
-+#############################
-+lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate --type cache-pool -n ${lv1}_pool -l 4 $vg "$dev5"
-+lvcreate --type cache -n $lv1 -l 8 $vg/${lv1}_pool "$dev1"
-+
-+check lv_tree_on $vg ${lv1}_foo "$dev1"
-+check lv_tree_on $vg ${lv1}_pool "$dev5"
-+check lv_tree_on $vg ${lv1} "$dev1"
-+
-+aux mkdev_md5sum $vg $lv1
-+pvmove "$dev1" "$dev3" 2>&1 | tee out
-+grep "Skipping cache LV, ${lv1}" out
-+check lv_tree_on $vg ${lv1}_foo "$dev3"
-+#check lv_tree_on $vg ${lv1}_pool "$dev5"
-+lvs -a -o name,attr,devices $vg
-+not check lv_tree_on $vg ${lv1} "$dev3"
-+#check dev_md5sum $vg $lv1
-+
-+#pvmove -n $lv1 "$dev3" "$dev1"
-+#check lv_tree_on $vg ${lv1}_foo "$dev3"
-+#check lv_tree_on $vg ${lv1}_pool "$dev5"
-+#check lv_tree_on $vg ${lv1} "$dev1"
-+#check dev_md5sum $vg $lv1
-+lvremove -ff $vg
-+
-+# Testing pvmove of a RAID origin LV
-+####################################
-+lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate --type raid1 -m 1 -l 8 -n $lv1 $vg "$dev1" "$dev2"
-+lvcreate --type cache -l 4 -n ${lv1}_pool $vg/$lv1 "$dev5"
-+check lv_tree_on $vg ${lv1}_foo "$dev1"
-+check lv_tree_on $vg ${lv1} "$dev1" "$dev2"
-+check lv_tree_on $vg ${lv1}_pool "$dev5"
-+
-+aux mkdev_md5sum $vg $lv1
-+pvmove "$dev1" "$dev3" 2>&1 | tee out
-+grep "Skipping cache LV, ${lv1}" out
-+check lv_tree_on $vg ${lv1}_foo "$dev3"
-+not check lv_tree_on $vg ${lv1} "$dev2" "$dev3"
-+#check lv_tree_on $vg ${lv1}_pool "$dev5"
-+#check dev_md5sum $vg $lv1 -- THIS IS WHERE THINGS FAIL IF PVMOVE NOT DISALLOWED
-+
-+#pvmove -n $lv1 "$dev3" "$dev1"
-+#check lv_tree_on $vg ${lv1}_foo "$dev3"
-+#check lv_tree_on $vg ${lv1} "$dev1" "$dev2"
-+#check lv_tree_on $vg ${lv1}_pool "$dev5"
-+#check dev_md5sum $vg $lv1
-+lvremove -ff $vg
-+
-+# Testing pvmove of a RAID cachepool (metadata and data)
-+########################################################
-+lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
-+lvcreate --type raid1 -L 2M -n meta $vg "$dev1" "$dev2"
-+lvcreate --type raid1 -L 4M -n ${lv1}_pool $vg "$dev1" "$dev2"
-+lvconvert --type cache-pool $vg/${lv1}_pool --poolmetadata $vg/meta
-+lvcreate --type cache -n $lv1 -L 8M $vg/${lv1}_pool "$dev5"
-+
-+check lv_tree_on $vg ${lv1}_foo "$dev1"
-+check lv_tree_on $vg ${lv1}_pool "$dev1" "$dev2"
-+check lv_tree_on $vg ${lv1} "$dev5"
-+
-+aux mkdev_md5sum $vg $lv1
-+# This will move ${lv1}_foo and the cache-pool data & meta
-+#  LVs, both of which contain a RAID1 _rimage & _rmeta LV - 5 total LVs
-+pvmove "$dev1" "$dev3" 2>&1 | tee out
-+grep "Skipping cache-pool LV, ${lv1}_pool" out
-+grep "Skipping cache-related LV, ${lv1}_pool_cmeta" out
-+grep "Skipping cache-related LV, ${lv1}_pool_cdata" out
-+check lv_tree_on $vg ${lv1}_foo "$dev3"
-+not check lv_tree_on $vg ${lv1}_pool "$dev2" "$dev3"
-+#check lv_tree_on $vg ${lv1} "$dev5"
-+#check dev_md5sum $vg $lv1
-+
-+#pvmove -n ${lv1}_pool "$dev3" "$dev1"
-+#check lv_tree_on $vg ${lv1}_foo "$dev3"
-+#check lv_tree_on $vg ${lv1}_pool "$dev1" "$dev2"
-+#check lv_tree_on $vg ${lv1} "$dev5"
-+#check dev_md5sum $vg $lv1
-+lvremove -ff $vg
-+
-+# Testing pvmove of Thin-pool on cache LV on RAID
-+#################################################
-+lvcreate -l 2 -n ${lv1}_foo $vg "$dev1"
-+# RAID for cachepool
-+lvcreate --type raid1 -m 1 -L 2M -n meta $vg "$dev1" "$dev2"
-+lvcreate --type raid1 -m 1 -L 4M -n cachepool $vg "$dev1" "$dev2"
-+lvconvert --type cache-pool $vg/cachepool --poolmetadata $vg/meta
-+# RAID for thin pool data LV
-+lvcreate --type raid1 -m 1 -L 8 -n thinpool $vg "$dev3" "$dev4"
-+# Convert thin pool data to a cached LV
-+lvconvert --type cache $vg/thinpool --cachepool $vg/cachepool
-+# Create simple thin pool meta
-+lvcreate -L 2M -n meta $vg "$dev1"
-+# Use thin pool data LV to build a thin pool
-+lvconvert --thinpool $vg/thinpool --poolmetadata $vg/meta
-+# Create a thin lv for fun
-+lvcreate -T $vg/thinpool -V 20 -n thin_lv
-+
-+check lv_tree_on $vg ${lv1}_foo "$dev1"
-+check lv_tree_on $vg cachepool "$dev1" "$dev2"
-+check lv_tree_on $vg thinpool "$dev1" "$dev3" "$dev4"
-+
-+aux mkdev_md5sum $vg thin_lv
-+lvs -a -o name,attr,devices $vg
-+# Should move ${lv1}_foo and thinpool_tmeta from dev1 to dev5
-+pvmove "$dev1" "$dev5" 2>&1 | tee out
-+lvs -a -o name,attr,devices $vg
-+check lv_tree_on $vg ${lv1}_foo "$dev5"
-+not check lv_tree_on $vg cachepool "$dev5" "$dev2"
-+check lv_tree_on $vg thinpool "$dev3" "$dev4" "$dev5" # Move non-cache tmeta
-+#check dev_md5sum $vg/thin_lv
-+
-+#pvmove -n $vg/cachepool "$dev5" "$dev1"
-+#check lv_tree_on $vg ${lv1}_foo "$dev5"
-+#check lv_tree_on $vg $vg/cachepool "$dev1" "$dev2"
-+#check lv_tree_on $vg $vg/thinpool "$dev3" "$dev4"
-+#check dev_md5sum $vg/thin_lv
-+
-+lvremove -ff $vg
-\ No newline at end of file
-diff --git a/test/shell/read-ahead.sh b/test/shell/read-ahead.sh
-index 8c8f42c..264910c 100644
---- a/test/shell/read-ahead.sh
-+++ b/test/shell/read-ahead.sh
-@@ -34,7 +34,7 @@ lvremove -ff $vg
- blockdev --setra 768 "$dev1"
- vgscan
- lvcreate -n $lv -L4m $vg "$dev1"
--test $(blockdev --getra $DM_DEV_DIR/$vg/$lv) -eq 768
-+test $(blockdev --getra "$DM_DEV_DIR/$vg/$lv") -eq 768
- lvremove -ff $vg
- 
- # Check default, active/inactive values for read_ahead / kernel_read_ahead
-diff --git a/test/shell/snapshot-usage.sh b/test/shell/snapshot-usage.sh
-index 9e6a14f..cb60556 100644
---- a/test/shell/snapshot-usage.sh
-+++ b/test/shell/snapshot-usage.sh
-@@ -13,8 +13,11 @@
- 
- . lib/test
- 
-+MKFS=mkfs.ext2
-+which $MKFS || skip
-+
- fill() {
--	dd if=/dev/zero of=$DM_DEV_DIR/$vg1/lvol0 bs=$1 count=1
-+	dd if=/dev/zero of="$DM_DEV_DIR/$vg1/lvol0" bs=$1 count=1
- }
- 
- cleanup_tail()
-@@ -37,8 +40,8 @@ aux lvmconf "activation/snapshot_autoextend_percent = 20" \
-             "activation/snapshot_autoextend_threshold = 50"
- 
- # Check usability with smallest extent size
--pvcreate --setphysicalvolumesize 4T $DM_DEV_DIR/$vg/$lv
--vgcreate -s 1K $vg1 $DM_DEV_DIR/$vg/$lv
-+pvcreate --setphysicalvolumesize 4T "$DM_DEV_DIR/$vg/$lv"
-+vgcreate -s 1K $vg1 "$DM_DEV_DIR/$vg/$lv"
- 
- # Test removal of opened snapshot
- lvcreate -V50 -L10 -n $lv1 -s $vg1
-@@ -52,9 +55,12 @@ lvs -a -o+lv_active $vg1
- 
- trap 'cleanup_tail' EXIT
- # Keep device busy (but not mounted) for a while
--sleep 30 < $DM_DEV_DIR/$vg1/$lv1 &
-+sleep 30 < "$DM_DEV_DIR/$vg1/$lv1" &
- SLEEP_PID=$!
- 
-+# give some short time to lock file above
-+sleep 0.1
-+
- # Opened virtual snapshot device is not removable
- # it should retry device removal for a few seconds
- not lvremove -f $vg1/$lv1
-@@ -104,17 +110,46 @@ lvextend --use-policies $vg1/lvol1
- check lv_field $vg1/lvol1 size "18.00k"
- 
- lvextend -l+33 $vg1/lvol1
--check lv_field $vg1/lvol1 size "28.00k"
-+check lv_field $vg1/lvol1 size "32.00k"
- 
- fill 20K
-+lvremove -f $vg1
-+
-+# Check snapshot really deletes COW header for read-only snapshot
-+# Test needs special relation between chunk size and extent size
-+# This test expects extent size 1K
-+aux lvmconf "allocation/wipe_signatures_when_zeroing_new_lvs = 1"
-+lvcreate -aey -L4 -n $lv $vg1
-+lvcreate -c 8 -s -L1 -n snap $vg1/$lv
-+# Populate snapshot
-+#dd if=/dev/urandom of="$DM_DEV_DIR/$vg1/$lv" bs=4096 count=10
-+$MKFS "$DM_DEV_DIR/$vg1/$lv"
-+lvremove -f $vg1/snap
-+
-+# Undeleted header would trigger attempt to access
-+# beyond end of COW device
-+# Fails to create when chunk size is different
-+lvcreate -s -pr -l12 -n snap $vg1/$lv
-+
-+# When header is undelete, fails to read snapshot without read errors
-+#dd if="$DM_DEV_DIR/$vg1/snap" of=/dev/null bs=1M count=2
-+fsck -n "$DM_DEV_DIR/$vg1/snap"
-+
-+# This test would trigger read of weird percentage for undeleted header
-+# And since older snapshot target counts with metadata sectors
-+# we have 2 valid results  (unsure about correct version number)
-+EXPECT="0.00"
-+aux target_at_least dm-snapshot 1 10 0 || EXPECT="66.67"
-+check lv_field $vg1/snap data_percent "$EXPECT"
-+
- vgremove -ff $vg1
- 
- # Can't test >= 16T devices on 32bit
- if test "$TSIZE" -eq 15P ; then
- 
- # Check usability with largest extent size
--pvcreate $DM_DEV_DIR/$vg/$lv
--vgcreate -s 4G $vg1 $DM_DEV_DIR/$vg/$lv
-+pvcreate "$DM_DEV_DIR/$vg/$lv"
-+vgcreate -s 4G $vg1 "$DM_DEV_DIR/$vg/$lv"
- 
- lvcreate -an -Zn -l50%FREE -n $lv1 $vg1
- lvcreate -s -l100%FREE -n $lv2 $vg1/$lv1
-diff --git a/test/shell/thin-merge.sh b/test/shell/thin-merge.sh
-index 10a81f0..7eb137e 100644
---- a/test/shell/thin-merge.sh
-+++ b/test/shell/thin-merge.sh
-@@ -13,7 +13,8 @@
- 
- . lib/test
- 
--which mkfs.ext2 || skip
-+MKFS=mkfs.ext2
-+which $MKFS  || skip
- which fsck || skip
- 
- #
-@@ -27,14 +28,14 @@ lvcreate -T -L8M $vg/pool -V10M -n $lv1
- lvchange --addtag tagL $vg/$lv1
- 
- mkdir mnt
--mkfs.ext2 $DM_DEV_DIR/$vg/$lv1
--mount $DM_DEV_DIR/$vg/$lv1 mnt
-+$MKFS "$DM_DEV_DIR/$vg/$lv1"
-+mount "$DM_DEV_DIR/$vg/$lv1" mnt
- touch mnt/test
- 
- lvcreate -K -s -n snap --addtag tagS $vg/$lv1
- mkdir mntsnap
--mkfs.ext2 $DM_DEV_DIR/$vg/snap
--mount $DM_DEV_DIR/$vg/snap mntsnap
-+$MKFS "$DM_DEV_DIR/$vg/snap"
-+mount "$DM_DEV_DIR/$vg/snap" mntsnap
- touch mntsnap/test_snap
- 
- lvs -o+tags,thin_id $vg
-@@ -82,10 +83,10 @@ lvchange -ay $vg/$lv1
- check lv_exists $vg $lv1
- check lv_field  $vg/$lv1 thin_id "2"
- check lv_field $vg/$lv1 tags "tagL"
--not check lv_exists $vg snap
-+check lv_not_exists $vg snap
- 
--fsck -n $DM_DEV_DIR/$vg/$lv1
--mount $DM_DEV_DIR/$vg/$lv1 mnt
-+fsck -n "$DM_DEV_DIR/$vg/$lv1"
-+mount "$DM_DEV_DIR/$vg/$lv1" mnt
- test -e mnt/test_snap
- umount mnt
- 
-@@ -97,8 +98,10 @@ lvcreate -s -n snap $vg/$lv1
- # Also add old snapshot to thin origin
- lvcreate -s -L10 -n oldsnapof_${lv1} $vg/$lv1
- not lvconvert --merge $vg/snap
--lvremove -f $vg/oldsnapof_${lv1}
--
-+$MKFS "$DM_DEV_DIR/$vg/oldsnapof_${lv1}"
-+lvconvert --merge $vg/oldsnapof_${lv1}
-+fsck -n "$DM_DEV_DIR/$vg/$lv1"
-+check lv_not_exists $vg oldsnapof_${lv1}
- # Add old snapshot to thin snapshot
- lvcreate -s -L10 -n oldsnapof_snap $vg/snap
- lvconvert --merge $vg/snap
-diff --git a/test/shell/thin-vglock.sh b/test/shell/thin-vglock.sh
-new file mode 100644
-index 0000000..083fcd8
---- /dev/null
-+++ b/test/shell/thin-vglock.sh
-@@ -0,0 +1,51 @@
-+#!/bin/sh
-+# Copyright (C) 2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+# Test locking works and doesn't update metadata
-+# RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1063542
-+
-+. lib/test
-+
-+MKFS=mkfs.ext2
-+which $MKFS || skip
-+
-+aux have_thin 1 0 0 || skip
-+aux prepare_vg
-+
-+lvcreate -L10 -T -V5 -n $lv1 $vg/pool
-+lvcreate -an -V10 -T $vg/pool
-+
-+$MKFS "$DM_DEV_DIR/$vg/$lv1"
-+mkdir mnt
-+mount "$DM_DEV_DIR/$vg/$lv1" mnt
-+
-+lvcreate -s -n snap $vg/$lv1
-+check lv_field $vg/snap thin_id "3"
-+
-+lvconvert --merge $vg/snap
-+
-+umount mnt
-+vgchange -an $vg
-+
-+# Check reboot case
-+vgchange -ay --sysinit $vg
-+# Metadata are still not updated (--poll n)
-+check lv_field $vg/$lv1 thin_id "1"
-+check lv_field $vg/pool transaction_id "3"
-+
-+# Check the metadata are updated after refresh
-+vgchange --refresh $vg
-+check lv_field $vg/$lv1 thin_id "3"
-+check lv_field $vg/pool transaction_id "4"
-+
-+#lvs -a -o+transaction_id,thin_id $vg
-+
-+vgremove -f $vg
-diff --git a/test/shell/vgsplit-stacked.sh b/test/shell/vgsplit-stacked.sh
-index 3256191..c8b89b5 100644
---- a/test/shell/vgsplit-stacked.sh
-+++ b/test/shell/vgsplit-stacked.sh
-@@ -18,8 +18,8 @@ vgcreate $vg1 "$dev1" "$dev2"
- lvcreate -n $lv1 -l 100%FREE $vg1
- 
- #top VG
--pvcreate $DM_DEV_DIR/$vg1/$lv1
--vgcreate $vg $DM_DEV_DIR/$vg1/$lv1 "$dev3"
-+pvcreate "$DM_DEV_DIR/$vg1/$lv1"
-+vgcreate $vg "$DM_DEV_DIR/$vg1/$lv1" "$dev3"
- 
- vgchange -a n $vg $vg1
- 
-diff --git a/tools/Makefile.in b/tools/Makefile.in
-index f18d3ea..253c404 100644
---- a/tools/Makefile.in
-+++ b/tools/Makefile.in
-@@ -43,6 +43,7 @@ SOURCES =\
- 	pvscan.c \
- 	reporter.c \
- 	segtypes.c \
-+	tags.c \
- 	toollib.c \
- 	vgcfgbackup.c \
- 	vgcfgrestore.c \
-@@ -166,7 +167,7 @@ liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION): liblvm2cmd.$(LIB_SUFFIX)
- 
- .commands: $(srcdir)/commands.h $(srcdir)/cmdnames.h Makefile
- 	$(CC) -E -P $(srcdir)/cmdnames.h 2> /dev/null | \
--		egrep -v '^ *(|#.*|devtypes|dumpconfig|formats|help|pvdata|segtypes|version) *$$' > .commands
-+		egrep -v '^ *(|#.*|devtypes|dumpconfig|formats|help|pvdata|segtypes|tags|version) *$$' > .commands
- 
- ifneq ("$(CFLOW_CMD)", "")
- CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
-diff --git a/tools/args.h b/tools/args.h
-index 1207189..f1a4ef4 100644
---- a/tools/args.h
-+++ b/tools/args.h
-@@ -62,6 +62,8 @@ arg(monitor_ARG, '\0', "monitor", yes_no_arg, 0)
- arg(config_ARG, '\0', "config", string_arg, 0)
- arg(trustcache_ARG, '\0', "trustcache", NULL, 0)
- arg(cache_ARG, '\0', "cache", NULL, 0)
-+arg(cachemode_ARG, '\0', "cachemode", string_arg, 0)
-+arg(cachepool_ARG, '\0', "cachepool", string_arg, 0)
- arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", NULL, 0)
- arg(nameprefixes_ARG, '\0', "nameprefixes", NULL, 0)
- arg(unquoted_ARG, '\0', "unquoted", NULL, 0)
-diff --git a/tools/commands.h b/tools/commands.h
-index 938898b..b0d608b 100644
---- a/tools/commands.h
-+++ b/tools/commands.h
-@@ -212,13 +212,27 @@ xx(lvconvert,
-    "\t[-T|--thin ExternalLogicalVolume[Path]\n"
-    "\t [--originname NewExternalOriginVolumeName]]\n"
-    "\t[-Z|--zero {y|n}]\n"
--   "\t[-d|--debug] [-h|-?|--help] [-v|--verbose]\n",
-+   "\t[-d|--debug] [-h|-?|--help] [-v|--verbose]\n\n"
- 
--   alloc_ARG, background_ARG, chunksize_ARG, corelog_ARG, discards_ARG,
--   force_ARG, interval_ARG, merge_ARG, mirrorlog_ARG, mirrors_ARG, name_ARG,
--   noudevsync_ARG, originname_ARG, poolmetadata_ARG, poolmetadatasize_ARG,
--   poolmetadataspare_ARG, readahead_ARG, regionsize_ARG, repair_ARG,
--   replace_ARG, snapshot_ARG, splitmirrors_ARG, splitsnapshot_ARG,
-+   "lvconvert "
-+   "--type cache_pool\n"
-+   "\t[--cachemode CacheMode]\n"
-+   "\t[--chunksize size]\n"
-+   "\t[--poolmetadata CacheMetadataLogicalVolume[Path] |\n"
-+   "\t [--poolmetadatasize size]\n"
-+   "\t [--poolmetadataspare {y|n}]]\n"
-+   "\tCacheDataLogicalVolume[Path]\n\n"
-+
-+   "lvconvert "
-+   "--type cache\n"
-+   "\t--cachepool CachePoolLogicalVolume[Path]\n"
-+   "\tLogicalVolume[Path]\n\n",
-+
-+   alloc_ARG, background_ARG, cachemode_ARG, cachepool_ARG, chunksize_ARG,
-+   corelog_ARG, discards_ARG, force_ARG, interval_ARG, merge_ARG, mirrorlog_ARG,
-+   mirrors_ARG, name_ARG, noudevsync_ARG, originname_ARG, poolmetadata_ARG,
-+   poolmetadatasize_ARG, poolmetadataspare_ARG, readahead_ARG, regionsize_ARG,
-+   repair_ARG, replace_ARG, snapshot_ARG, splitmirrors_ARG, splitsnapshot_ARG,
-    stripes_long_ARG, stripesize_ARG, test_ARG, thin_ARG, thinpool_ARG,
-    trackchanges_ARG, type_ARG, use_policies_ARG, zero_ARG)
- 
-@@ -230,6 +244,7 @@ xx(lvcreate,
-    "\t[-a|--activate [a|e|l]{y|n}]\n"
-    "\t[--addtag Tag]\n"
-    "\t[--alloc AllocationPolicy]\n"
-+   "\t[--cachemode CacheMode]\n"
-    "\t[-C|--contiguous {y|n}]\n"
-    "\t[-d|--debug]\n"
-    "\t[-h|-?|--help]\n"
-@@ -296,9 +311,9 @@ xx(lvcreate,
-    "\t[PhysicalVolumePath...]\n\n",
- 
-    addtag_ARG, alloc_ARG, autobackup_ARG, activate_ARG, available_ARG,
--   chunksize_ARG, contiguous_ARG, corelog_ARG, discards_ARG, extents_ARG,
--   ignoreactivationskip_ARG, ignoremonitoring_ARG, major_ARG, minor_ARG,
--   mirrorlog_ARG, mirrors_ARG, monitor_ARG, minrecoveryrate_ARG,
-+   cachemode_ARG, chunksize_ARG, contiguous_ARG, corelog_ARG, discards_ARG,
-+   extents_ARG, ignoreactivationskip_ARG, ignoremonitoring_ARG, major_ARG,
-+   minor_ARG, mirrorlog_ARG, mirrors_ARG, monitor_ARG, minrecoveryrate_ARG,
-    maxrecoveryrate_ARG, name_ARG, nosync_ARG, noudevsync_ARG,
-    permission_ARG, persistent_ARG, poolmetadatasize_ARG, poolmetadataspare_ARG,
-    raidminrecoveryrate_ARG, raidmaxrecoveryrate_ARG, readahead_ARG,
-@@ -789,6 +804,11 @@ xx(segtypes,
-    PERMITTED_READ_ONLY,
-    "segtypes\n")
- 
-+xx(tags,
-+   "List tags defined on this host",
-+   PERMITTED_READ_ONLY,
-+   "tags\n")
-+
- xx(vgcfgbackup,
-    "Backup volume group configuration(s)",
-    PERMITTED_READ_ONLY,
-diff --git a/tools/dumpconfig.c b/tools/dumpconfig.c
-index 18fba34..cb88bc6 100644
---- a/tools/dumpconfig.c
-+++ b/tools/dumpconfig.c
-@@ -193,6 +193,12 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
- 		goto out;
- 	}
- 
-+	if (arg_count(cmd, withcomments_ARG))
-+		tree_spec.withcomments = 1;
-+
-+	if (arg_count(cmd, withversions_ARG))
-+		tree_spec.withversions = 1;
-+
- 	if (cft_check_handle)
- 		tree_spec.check_status = cft_check_handle->status;
- 
-@@ -202,9 +208,7 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
- 		goto_out;
- 	}
- 
--	if (!config_write(cft, arg_count(cmd, withcomments_ARG),
--			  arg_count(cmd, withversions_ARG),
--			  file, argc, argv)) {
-+	if (!config_write(cft, &tree_spec, file, argc, argv)) {
- 		stack;
- 		r = ECMD_FAILED;
- 	}
-diff --git a/tools/lvchange.c b/tools/lvchange.c
-index a0e350f..8ceacc5 100644
---- a/tools/lvchange.c
-+++ b/tools/lvchange.c
-@@ -215,11 +215,8 @@ static int _lvchange_activate(struct cmd_context *cmd, struct logical_volume *lv
- 
- 	activate = (activation_change_t) arg_uint_value(cmd, activate_ARG, CHANGE_AY);
- 
--	if (lv_activation_skip(lv, activate, arg_count(cmd, ignoreactivationskip_ARG), 0)) {
--		log_verbose("ACTIVATON_SKIP flag set for LV %s/%s, skipping activation.",
--			    lv->vg->name, lv->name);
-+	if (lv_activation_skip(lv, activate, arg_count(cmd, ignoreactivationskip_ARG)))
- 		return 1;
--	}
- 
- 	if (lv_is_cow(lv) && !lv_is_virtual_origin(origin_from_cow(lv)))
- 		lv = origin_from_cow(lv);
-diff --git a/tools/lvconvert.c b/tools/lvconvert.c
-index 87eb643..09a64c7 100644
---- a/tools/lvconvert.c
-+++ b/tools/lvconvert.c
-@@ -28,6 +28,7 @@ struct lvconvert_params {
- 	int zero;
- 
- 	const char *origin;
-+	const char *cachepool;
- 	const char *lv_name;
- 	const char *lv_split_name;
- 	const char *lv_name_full;
-@@ -45,6 +46,7 @@ struct lvconvert_params {
- 	uint32_t stripes;
- 	uint32_t stripe_size;
- 	uint32_t read_ahead;
-+	uint32_t feature_flags; /* cache_pool */
- 
- 	const struct segment_type *segtype;
- 	unsigned target_attr;
-@@ -198,7 +200,9 @@ static int _check_conversion_type(struct cmd_context *cmd, const char *type_str)
- 	}
- 
- 	/* FIXME: Check thin-pool and thin more thoroughly! */
--	if (!strcmp(type_str, "snapshot") || !strncmp(type_str, "raid", 4) ||
-+	if (!strcmp(type_str, "snapshot") ||
-+	    !strncmp(type_str, "raid", 4) ||
-+	    !strcmp(type_str, "cache-pool") || !strcmp(type_str, "cache") ||
- 	    !strcmp(type_str, "thin-pool") || !strcmp(type_str, "thin"))
- 		return 1;
- 
-@@ -217,6 +221,7 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
- 			int argc, char **argv)
- {
- 	int i;
-+	int cache_pool = 0;
- 	const char *tmp_str;
- 	struct arg_value_group_list *group;
- 	int region_size;
-@@ -250,6 +255,20 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
- 		return 0;
- 	}
- 
-+	if (!strcmp(type_str, "cache-pool")) {
-+		cache_pool = 1;
-+		if ((tmp_str = arg_str_value(cmd, cachemode_ARG, NULL))) {
-+			if (!strcmp(tmp_str, "writeback"))
-+				lp->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
-+			else if (!strcmp(tmp_str, "writethrough"))
-+				lp->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
-+			else {
-+				log_error("Unknown cachemode argument");
-+				return 0;
-+			}
-+		}
-+	}
-+
- 	if (!arg_count(cmd, background_ARG))
- 		lp->wait_completion = 1;
- 
-@@ -270,28 +289,38 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
- 	if (arg_count(cmd, thin_ARG))
- 		lp->thin = 1;
- 
--	if (arg_count(cmd, thinpool_ARG)) {
-+	if (arg_count(cmd, cachepool_ARG)) {
-+		if (strcmp(type_str, "cache")) {
-+			log_error("--cachepool argument is only valid with "
-+				  " the \"cache\" segment type");
-+			return 0;
-+		}
-+		lp->cachepool = arg_str_value(cmd, cachepool_ARG, NULL);
-+	} else if (arg_count(cmd, thinpool_ARG) || cache_pool) {
- 		if (arg_count(cmd, merge_ARG)) {
--			log_error("--thinpool and --merge are mutually exlusive.");
-+			log_error("--%spool and --merge are mutually exlusive.",
-+				  cache_pool ? "type cache_" : "thin");
- 			return 0;
- 		}
- 		if (mirror_or_raid_type_requested(cmd, type_str)) {
--			log_error("--thinpool and --mirrors/--type mirror/--type raid* are mutually exlusive.");
-+			log_error("--%spool and --mirrors/--type mirror/--type raid* are mutually exlusive.", cache_pool ? "type cache_" : "thin");
- 			return 0;
- 		}
- 		if (arg_count(cmd, repair_ARG)) {
--			log_error("--thinpool and --repair are mutually exlusive.");
-+			log_error("--%spool and --repair are mutually exlusive.",
-+				  cache_pool ? "type cache_" : "thin");
- 			return 0;
- 		}
- 		if (snapshot_type_requested(cmd, type_str)) {
--			log_error("--thinpool and --snapshot/--type snapshot are mutually exlusive.");
-+			log_error("--%spool and --snapshot/--type snapshot are mutually exlusive.", cache_pool ? "type cache_" : "thin");
- 			return 0;
- 		}
- 		if (arg_count(cmd, splitmirrors_ARG)) {
--			log_error("--thinpool and --splitmirrors are mutually exlusive.");
-+			log_error("--%spool and --splitmirrors are mutually exlusive.", cache_pool ? "type cache_" : "thin");
- 			return 0;
- 		}
--		lp->discards = (thin_discards_t) arg_uint_value(cmd, discards_ARG, THIN_DISCARDS_PASSDOWN);
-+		if (!cache_pool)
-+			lp->discards = (thin_discards_t) arg_uint_value(cmd, discards_ARG, THIN_DISCARDS_PASSDOWN);
- 	} else if (lp->thin) {
- 		log_error("--thin is only valid with --thinpool.");
- 		return 0;
-@@ -442,8 +471,15 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
- 								    tmp_str)))
- 				return_0;
- 		}
--	} else if (arg_count(cmd, thinpool_ARG)) {
--		if (!(lp->pool_data_lv_name = arg_str_value(cmd, thinpool_ARG, NULL))) {
-+	} else if (arg_count(cmd, thinpool_ARG) || cache_pool) {
-+		if (cache_pool) {
-+			if (!argc) {
-+				log_error("Please specify the pool data LV.");
-+				return 0;
-+			}
-+			lp->pool_data_lv_name = argv[0];
-+			argv++, argc--;
-+		} else if (!(lp->pool_data_lv_name = arg_str_value(cmd, thinpool_ARG, NULL))) {
- 			log_error("Missing pool logical volume name.");
- 			return 0;
- 		}
-@@ -469,7 +505,7 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
- 		lp->read_ahead = arg_uint_value(cmd, readahead_ARG,
- 						cmd->default_settings.read_ahead);
- 
--		/* If --thinpool contains VG name, extract it. */
-+		/* If pool_data_lv_name contains VG name, extract it. */
- 		if ((tmp_str = strchr(lp->pool_data_lv_name, (int) '/'))) {
- 			if (!(lp->vg_name = extract_vgname(cmd, lp->pool_data_lv_name)))
- 				return 0;
-@@ -484,7 +520,7 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
- 			}
- 		}
- 
--		lp->segtype = get_segtype_from_string(cmd, arg_str_value(cmd, type_ARG, "thin-pool"));
-+		lp->segtype = get_segtype_from_string(cmd, arg_str_value(cmd, type_ARG, cache_pool ? "cache-pool" : "thin-pool"));
- 		if (!lp->segtype)
- 			return_0;
- 	} else { /* Mirrors (and some RAID functions) */
-@@ -861,7 +897,7 @@ int lvconvert_poll(struct cmd_context *cmd, struct logical_volume *lv,
- 
- 	if (lv_is_merging_origin(lv))
- 		return poll_daemon(cmd, lv_full_name, uuid, background, 0,
--				   lv_is_thin_volume(lv) ?
-+				   seg_is_thin_volume(find_snapshot(lv)) ?
- 				   &_lvconvert_thin_merge_fns : &_lvconvert_merge_fns,
- 				   "Merged");
- 
-@@ -2483,6 +2519,9 @@ static int _lvconvert_thinpool_external(struct cmd_context *cmd,
- 
- 	dm_list_init(&lvc.tags);
- 
-+	if (!pool_supports_external_origin(first_seg(pool_lv), external_lv))
-+		return_0;
-+
- 	if (!(lvc.segtype = get_segtype_from_string(cmd, "thin")))
- 		return_0;
- 
-@@ -2549,17 +2588,46 @@ revert_new_lv:
- 	return 0;
- }
- 
-+static int _lvconvert_update_pool_params(struct logical_volume *pool_lv,
-+					 struct lvconvert_params *lp)
-+{
-+	if (seg_is_cache_pool(lp))
-+		return update_cache_pool_params(pool_lv->vg, lp->target_attr,
-+						lp->passed_args,
-+						pool_lv->le_count,
-+						pool_lv->vg->extent_size,
-+						&lp->thin_chunk_size_calc_policy,
-+						&lp->chunk_size,
-+						&lp->discards,
-+						&lp->poolmetadata_size,
-+						&lp->zero);
-+
-+	return update_thin_pool_params(pool_lv->vg, lp->target_attr,
-+				       lp->passed_args,
-+				       pool_lv->le_count,
-+				       pool_lv->vg->extent_size,
-+				       &lp->thin_chunk_size_calc_policy,
-+				       &lp->chunk_size,
-+				       &lp->discards,
-+				       &lp->poolmetadata_size,
-+				       &lp->zero);
-+}
-+
-+
-+
- /*
-  * Thin lvconvert version which
-  *  rename metadata
-  *  convert/layers thinpool over data
-  *  attach metadata
-  */
--static int _lvconvert_thinpool(struct cmd_context *cmd,
--			       struct logical_volume *pool_lv,
--			       struct lvconvert_params *lp)
-+static int _lvconvert_to_pool(struct cmd_context *cmd,
-+			      struct logical_volume *pool_lv,
-+			      struct lvconvert_params *lp)
- {
- 	int r = 0;
-+	uint64_t min_metadata_size;
-+	uint64_t max_metadata_size;
- 	const char *old_name;
- 	struct lv_segment *seg;
- 	struct logical_volume *data_lv;
-@@ -2582,6 +2650,12 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
- 	}
- 
- 	if (lp->thin) {
-+		if (strcmp(pool_lv->name, lp->pool_data_lv_name) == 0) {
-+			log_error("Can't use same LV %s/%s for thin pool and thin volume.",
-+				  pool_lv->vg->name, pool_lv->name);
-+			return 0;
-+		}
-+
- 		external_lv = pool_lv;
- 		if (!(pool_lv = find_lv(external_lv->vg, lp->pool_data_lv_name))) {
- 			log_error("Can't find pool LV %s/%s.",
-@@ -2626,20 +2700,21 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
- 		return 0;
- 	}
- 
--	if ((dm_snprintf(metadata_name, sizeof(metadata_name), "%s_tmeta",
--			 pool_lv->name) < 0) ||
--	    (dm_snprintf(data_name, sizeof(data_name), "%s_tdata",
--			 pool_lv->name) < 0)) {
-+	if ((dm_snprintf(metadata_name, sizeof(metadata_name), "%s%s",
-+			 pool_lv->name,
-+			 (segtype_is_cache_pool(lp->segtype)) ?
-+			  "_cmeta" : "_tmeta") < 0) ||
-+	    (dm_snprintf(data_name, sizeof(data_name), "%s%s",
-+			 pool_lv->name,
-+			 (segtype_is_cache_pool(lp->segtype)) ?
-+			 "_cdata" : "_tdata") < 0)) {
- 		log_error("Failed to create internal lv names, "
--			  "thin pool name is too long.");
-+			  "pool name is too long.");
- 		return 0;
- 	}
- 
- 	if (!lp->pool_metadata_lv_name) {
--		if (!update_pool_params(pool_lv->vg, lp->target_attr, lp->passed_args,
--					pool_lv->le_count, pool_lv->vg->extent_size,
--					&lp->thin_chunk_size_calc_policy, &lp->chunk_size,
--					&lp->discards, &lp->poolmetadata_size, &lp->zero))
-+		if (!_lvconvert_update_pool_params(pool_lv, lp))
- 			return_0;
- 
- 		if (!get_stripe_params(cmd, &lp->stripes, &lp->stripe_size))
-@@ -2733,37 +2808,40 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
- 		}
- 
- 		lp->poolmetadata_size = metadata_lv->size;
--		if (lp->poolmetadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
-+		max_metadata_size = (segtype_is_cache_pool(lp->segtype)) ?
-+			DEFAULT_CACHE_POOL_MAX_METADATA_SIZE * 2 :
-+			DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2;
-+		min_metadata_size = (segtype_is_cache_pool(lp->segtype)) ?
-+			DEFAULT_CACHE_POOL_MIN_METADATA_SIZE * 2 :
-+			DEFAULT_THIN_POOL_MIN_METADATA_SIZE * 2;
-+
-+		if (lp->poolmetadata_size > max_metadata_size) {
- 			log_warn("WARNING: Maximum size used by metadata is %s, rest is unused.",
--				 display_size(cmd, 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE));
--			lp->poolmetadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
--		} else if (lp->poolmetadata_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
-+				 display_size(cmd, max_metadata_size));
-+			lp->poolmetadata_size = max_metadata_size;
-+		} else if (lp->poolmetadata_size < min_metadata_size) {
- 			log_error("Logical volume %s/%s is too small (<%s) for metadata.",
- 				  metadata_lv->vg->name, metadata_lv->name,
--				  display_size(cmd, 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE));
-+				  display_size(cmd, min_metadata_size));
- 			return 0;
- 		}
--		if (!update_pool_params(pool_lv->vg, lp->target_attr, lp->passed_args,
--					pool_lv->le_count, pool_lv->vg->extent_size,
--					&lp->thin_chunk_size_calc_policy, &lp->chunk_size,
--					&lp->discards, &lp->poolmetadata_size, &lp->zero))
-+		if (!_lvconvert_update_pool_params(pool_lv, lp))
- 			return_0;
- 
- 		metadata_lv->status |= LV_TEMPORARY;
- 		if (!activate_lv_local(cmd, metadata_lv)) {
--			log_error("Aborting. Failed to activate thin metadata lv.");
-+			log_error("Aborting. Failed to activate metadata lv.");
- 			return 0;
- 		}
- 
--
- 		if (!wipe_lv(metadata_lv, (struct wipe_params) { .do_zero = 1 })) {
--			log_error("Aborting. Failed to wipe thin metadata lv.");
-+			log_error("Aborting. Failed to wipe metadata lv.");
- 			return 0;
- 		}
- 	}
- 
- 	if (!deactivate_lv(cmd, metadata_lv)) {
--		log_error("Aborting. Failed to deactivate thin metadata lv. "
-+		log_error("Aborting. Failed to deactivate metadata lv. "
- 			  "Manual intervention required.");
- 		return 0;
- 	}
-@@ -2774,7 +2852,7 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
- 
- 	old_name = data_lv->name; /* Use for pool name */
- 	/*
--	 * Since we wish to have underlaying devs to match _tdata
-+	 * Since we wish to have underlaying devs to match _[ct]data
- 	 * rename data LV to match pool LV subtree first,
- 	 * also checks for visible LV.
- 	 */
-@@ -2783,7 +2861,9 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
- 		return_0;
- 
- 	if (!(pool_lv = lv_create_empty(old_name, NULL,
--					THIN_POOL | VISIBLE_LV | LVM_READ | LVM_WRITE,
-+					((segtype_is_cache_pool(lp->segtype)) ?
-+					 CACHE_POOL : THIN_POOL) |
-+					VISIBLE_LV | LVM_READ | LVM_WRITE,
- 					ALLOC_INHERIT, data_lv->vg))) {
- 		log_error("Creation of pool LV failed.");
- 		return 0;
-@@ -2791,8 +2871,8 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
- 
- 	/* Allocate a new linear segment */
- 	if (!(seg = alloc_lv_segment(lp->segtype, pool_lv, 0, data_lv->le_count,
--				     pool_lv->status, 0, NULL, NULL, 1, data_lv->le_count,
--				     0, 0, 0, NULL)))
-+				     pool_lv->status, 0, NULL, NULL, 1,
-+				     data_lv->le_count, 0, 0, 0, NULL)))
- 		return_0;
- 
- 	/* Add the new segment to the layer LV */
-@@ -2838,8 +2918,10 @@ mda_write:
- 		goto out;
- 	}
- 
--	log_print_unless_silent("Converted %s/%s to thin pool.",
--				pool_lv->vg->name, pool_lv->name);
-+	log_print_unless_silent("Converted %s/%s to %s pool.",
-+				pool_lv->vg->name, pool_lv->name,
-+				(segtype_is_cache_pool(lp->segtype)) ?
-+				"cache" : "thin");
- 
- 	r = 1;
- out:
-@@ -2852,6 +2934,41 @@ out:
- 	return r;
- }
- 
-+static int _lvconvert_cache(struct logical_volume *origin,
-+			    struct lvconvert_params *lp)
-+{
-+	struct cmd_context *cmd = origin->vg->cmd;
-+	struct logical_volume *cache_lv;
-+	struct logical_volume *cachepool;
-+
-+	if (!lp->cachepool) {
-+		log_error("--cachepool argument is required.");
-+		return 0;
-+	}
-+
-+	if (!(cachepool = find_lv(origin->vg, lp->cachepool))) {
-+		log_error("Unable to find cache pool LV, %s", lp->cachepool);
-+		return 0;
-+	}
-+
-+	if (!(cache_lv = lv_cache_create(cachepool, origin)))
-+		return_0;
-+
-+	if (!vg_write(cache_lv->vg))
-+		return_0;
-+	if (!suspend_lv(cmd, cache_lv))
-+		return_0;
-+	if (!vg_commit(cache_lv->vg))
-+		return_0;
-+	if (!resume_lv(cmd, cache_lv))
-+		return_0;
-+
-+	log_print_unless_silent("%s/%s is now cached.",
-+				cache_lv->vg->name, cache_lv->name);
-+
-+	return 1;
-+}
-+
- static int _lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
- 			     void *handle)
- {
-@@ -2884,7 +3001,9 @@ static int _lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
- 	    !(lv->status & MIRRORED) && !(lv->status & RAID)) {
- 		if (arg_count(cmd, use_policies_ARG))
- 			return ECMD_PROCESSED; /* nothing to be done here */
--		log_error("Can't repair non-mirrored LV \"%s\".", lv->name);
-+		log_error("Can't repair LV \"%s\" of segtype %s.",
-+			  lv->name,
-+			  first_seg(lv)->segtype->ops->name(first_seg(lv)));
- 		return ECMD_FAILED;
- 	}
- 
-@@ -2920,11 +3039,25 @@ static int _lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
- 		if (!_lvconvert_snapshot(cmd, lv, lp))
- 			return_ECMD_FAILED;
- 
-+	} else if (segtype_is_cache(lp->segtype)) {
-+		if (!archive(lv->vg))
-+			return_ECMD_FAILED;
-+
-+		if (!_lvconvert_cache(lv, lp))
-+			return_ECMD_FAILED;
-+
-+	} else if (segtype_is_cache_pool(lp->segtype)) {
-+		if (!archive(lv->vg))
-+			return_ECMD_FAILED;
-+
-+		if (!_lvconvert_to_pool(cmd, lv, lp))
-+			return_ECMD_FAILED;
-+
- 	} else if (arg_count(cmd, thinpool_ARG)) {
- 		if (!archive(lv->vg))
- 			return_ECMD_FAILED;
- 
--		if (!_lvconvert_thinpool(cmd, lv, lp))
-+		if (!_lvconvert_to_pool(cmd, lv, lp))
- 			return_ECMD_FAILED;
- 
- 	} else if (segtype_is_raid(lp->segtype) ||
-@@ -3001,6 +3134,7 @@ static int _poll_logical_volume(struct cmd_context *cmd, struct logical_volume *
- 		log_print_unless_silent("Conversion starts after activation.");
- 		return ECMD_PROCESSED;
- 	}
-+
- 	return lvconvert_poll(cmd, lv, wait_completion ? 0 : 1U);
- }
- 
-@@ -3019,8 +3153,7 @@ static int lvconvert_single(struct cmd_context *cmd, struct lvconvert_params *lp
- 	if (!lv)
- 		goto_out;
- 
--	if (arg_count(cmd, thinpool_ARG) &&
--	    !get_pool_params(cmd, lv_config_profile(lv),
-+	if (!get_pool_params(cmd, lv_config_profile(lv),
- 			     &lp->passed_args, &lp->thin_chunk_size_calc_policy,
- 			     &lp->chunk_size, &lp->discards,
- 			     &lp->poolmetadata_size, &lp->zero))
-diff --git a/tools/lvcreate.c b/tools/lvcreate.c
-index d0ca7bc..ad00327 100644
---- a/tools/lvcreate.c
-+++ b/tools/lvcreate.c
-@@ -1,6 +1,6 @@
- /*
-  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
-- * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -21,7 +21,7 @@ struct lvcreate_cmdline_params {
- 	percent_type_t percent;
- 	uint64_t size;
- 	char **pvs;
--	int pv_count;
-+	uint32_t pv_count;
- };
- 
- static int _set_vg_name(struct lvcreate_params *lp, const char *vg_name)
-@@ -73,8 +73,45 @@ static int _lvcreate_name_params(struct lvcreate_params *lp,
- 			lp->lv_name = ptr + 1;
- 	}
- 
--	/* Need an origin? */
--	if (lp->snapshot && !arg_count(cmd, virtualsize_ARG)) {
-+	if (seg_is_cache(lp)) {
-+		/*
-+		 * We are looking for the origin or cache_pool LV.
-+		 * Could be in the form 'lv' or 'vg/lv'
-+		 *
-+		 * We store the lv name in 'lp->origin' for now, but
-+		 * it must be accessed later (when we can look-up the
-+		 * LV in the VG) whether it is truly the origin that
-+		 * was specified, or whether it is the cache_pool.
-+		 */
-+		if (!argc) {
-+			log_error("Please specify a logical volume to act as "
-+				  "the origin or cache_pool.");
-+			return 0;
-+		}
-+
-+		lp->origin = skip_dev_dir(cmd, argv[0], NULL);
-+		if (strrchr(lp->origin, '/')) {
-+			if (!_set_vg_name(lp, extract_vgname(cmd, lp->origin)))
-+				return_0;
-+
-+			/* Strip the volume group from the origin */
-+			if ((ptr = strrchr(lp->origin, (int) '/')))
-+				lp->origin = ptr + 1;
-+		}
-+
-+		if (!lp->vg_name &&
-+		    !_set_vg_name(lp, extract_vgname(cmd, NULL)))
-+			return_0;
-+
-+		if (!lp->vg_name) {
-+			log_error("The origin or cache_pool name should include"
-+				  " the volume group.");
-+			return 0;
-+		}
-+
-+		lp->cache = 1;
-+		(*pargv)++, (*pargc)--;
-+	} else if (lp->snapshot && !arg_count(cmd, virtualsize_ARG)) {
- 		/* argv[0] might be origin or vg/origin */
- 		if (!argc) {
- 			log_error("Please specify a logical volume to act as "
-@@ -227,6 +264,68 @@ static int _determine_snapshot_type(struct volume_group *vg,
- 	return 1;
- }
- 
-+static int _lvcreate_update_pool_params(struct volume_group *vg,
-+					struct lvcreate_params *lp)
-+{
-+	if (seg_is_cache_pool(lp))
-+		return update_cache_pool_params(vg, lp->target_attr,
-+						lp->passed_args,
-+						lp->extents, vg->extent_size,
-+						&lp->thin_chunk_size_calc_policy,
-+						&lp->chunk_size, &lp->discards,
-+						&lp->poolmetadatasize,
-+						&lp->zero);
-+
-+	return update_thin_pool_params(vg, lp->target_attr, lp->passed_args,
-+				       lp->extents, vg->extent_size,
-+				       &lp->thin_chunk_size_calc_policy,
-+				       &lp->chunk_size, &lp->discards,
-+				       &lp->poolmetadatasize, &lp->zero);
-+}
-+
-+/*
-+ * _determine_cache_argument
-+ * @vg
-+ * @lp
-+ *
-+ * 'lp->origin' is set with an LV that could be either the origin
-+ * or the cache_pool of the cached LV which is being created.  This
-+ * function determines which it is and sets 'lp->origin' or
-+ * 'lp->pool' appropriately.
-+ */
-+static int _determine_cache_argument(struct volume_group *vg,
-+				     struct lvcreate_params *lp)
-+{
-+	struct lv_list *lvl;
-+
-+	if (!seg_is_cache(lp)) {
-+		log_error(INTERNAL_ERROR
-+			  "Unable to determine cache argument on %s segtype",
-+			  lp->segtype->name);
-+		return 0;
-+	}
-+
-+	if (!(lvl = find_lv_in_vg(vg, lp->origin))) {
-+		log_error("LV %s not found in Volume group %s.",
-+			  lp->origin, vg->name);
-+		return 0;
-+	}
-+
-+	if (lv_is_cache_pool(lvl->lv)) {
-+		lp->pool = lp->origin;
-+		lp->origin = NULL;
-+	} else {
-+		lp->pool = NULL;
-+		lp->create_pool = 1;
-+		lp->poolmetadataspare = arg_int_value(vg->cmd,
-+						      poolmetadataspare_ARG,
-+						      DEFAULT_POOL_METADATA_SPARE);
-+		lp->origin = lp->origin;
-+	}
-+
-+	return 1;
-+}
-+
- /*
-  * Update extents parameters based on other parameters which affect the size
-  * calculation.
-@@ -264,19 +363,19 @@ static int _update_extents_params(struct volume_group *vg,
- 	} else
- 		lp->pvh = &vg->pvs;
- 
--	switch(lcp->percent) {
-+	switch (lcp->percent) {
- 		case PERCENT_VG:
--			lp->extents = percent_of_extents(lp->extents, vg->extent_count, 0);
-+			extents = percent_of_extents(lp->extents, vg->extent_count, 0);
- 			break;
- 		case PERCENT_FREE:
--			lp->extents = percent_of_extents(lp->extents, vg->free_count, 0);
-+			extents = percent_of_extents(lp->extents, vg->free_count, 0);
- 			break;
- 		case PERCENT_PVS:
- 			if (lcp->pv_count) {
- 				pv_extent_count = pv_list_extents_free(lp->pvh);
--				lp->extents = percent_of_extents(lp->extents, pv_extent_count, 0);
-+				extents = percent_of_extents(lp->extents, pv_extent_count, 0);
- 			} else
--				lp->extents = percent_of_extents(lp->extents, vg->extent_count, 0);
-+				extents = percent_of_extents(lp->extents, vg->extent_count, 0);
- 			break;
- 		case PERCENT_LV:
- 			log_error("Please express size as %%VG, %%PVS, or "
-@@ -293,10 +392,21 @@ static int _update_extents_params(struct volume_group *vg,
- 				log_error(INTERNAL_ERROR "Couldn't find origin volume.");
- 				return 0;
- 			}
--			lp->extents = percent_of_extents(lp->extents, origin->le_count, 0);
-+			extents = percent_of_extents(lp->extents, origin->le_count, 0);
- 			break;
- 		case PERCENT_NONE:
-+			extents = lp->extents;
- 			break;
-+		default:
-+			log_error(INTERNAL_ERROR "Unsupported percent type %u.", lcp->percent);
-+			return 0;
-+	}
-+
-+	if (lcp->percent) {
-+		/* FIXME Don't do the adjustment for parallel allocation with PERCENT_ORIGIN! */
-+		lp->approx_alloc = 1;
-+		log_verbose("Converted %" PRIu32 "%%%s into %" PRIu32 " extents.", lp->extents, get_percent_string(lcp->percent), extents);
-+		lp->extents = extents;
- 	}
- 
- 	if (lp->snapshot && lp->origin && lp->extents) {
-@@ -333,12 +443,8 @@ static int _update_extents_params(struct volume_group *vg,
- 		lp->extents = lp->extents - size_rest;
- 	}
- 
--	if (lp->create_thin_pool) {
--		if (!update_pool_params(vg, lp->target_attr, lp->passed_args,
--					lp->extents, vg->extent_size,
--					&lp->thin_chunk_size_calc_policy,
--					&lp->chunk_size, &lp->discards,
--					&lp->poolmetadatasize, &lp->zero))
-+	if (lp->create_pool) {
-+		if (!_lvcreate_update_pool_params(vg, lp))
- 			return_0;
- 
- 		if (!(lp->poolmetadataextents =
-@@ -392,9 +498,9 @@ static int _read_size_params(struct lvcreate_params *lp,
- 
- 	/* If size/extents given with thin, then we are creating a thin pool */
- 	if (seg_is_thin(lp) && (arg_count(cmd, size_ARG) || arg_count(cmd, extents_ARG)))
--		lp->create_thin_pool = 1;
-+		lp->create_pool = 1;
- 
--	if (!lp->create_thin_pool && arg_count(cmd, poolmetadatasize_ARG)) {
-+	if (!lp->create_pool && arg_count(cmd, poolmetadatasize_ARG)) {
- 		log_error("--poolmetadatasize may only be specified when allocating the thin pool.");
- 		return 0;
- 	}
-@@ -522,20 +628,7 @@ static int _read_raid_params(struct lvcreate_params *lp,
- 		return 0;
- 	}
- 
--	/*
--	 * get_stripe_params is called before _read_raid_params
--	 * and already sets:
--	 *   lp->stripes
--	 *   lp->stripe_size
--	 *
--	 * For RAID 4/5/6/10, these values must be set.
--	 */
--	if (!segtype_is_mirrored(lp->segtype) &&
--	    (lp->stripes <= lp->segtype->parity_devs)) {
--		log_error("Number of stripes must be at least %d for %s",
--			  lp->segtype->parity_devs + 1, lp->segtype->name);
--		return 0;
--	} else if (!strcmp(lp->segtype->name, "raid10") && (lp->stripes < 2)) {
-+	if (!strcmp(lp->segtype->name, "raid10") && (lp->stripes < 2)) {
- 		if (arg_count(cmd, stripes_ARG)) {
- 			/* User supplied the bad argument */
- 			log_error("Segment type 'raid10' requires 2 or more stripes.");
-@@ -594,13 +687,45 @@ static int _read_raid_params(struct lvcreate_params *lp,
- 
- 	if (lp->max_recovery_rate &&
- 	    (lp->max_recovery_rate < lp->min_recovery_rate)) {
--		log_error("Minumum recovery rate cannot be higher than maximum.");
-+		log_error("Minimum recovery rate cannot be higher than maximum.");
- 		return 0;
- 	}
- 	return 1;
- }
- 
--static int _read_activation_params(struct lvcreate_params *lp, struct cmd_context *cmd,
-+static int _read_cache_pool_params(struct lvcreate_params *lp,
-+				  struct cmd_context *cmd)
-+{
-+	const char *str_arg;
-+
-+	if (!segtype_is_cache_pool(lp->segtype))
-+		return 1;
-+
-+	if (arg_sign_value(cmd, chunksize_ARG, SIGN_NONE) == SIGN_MINUS) {
-+		log_error("Negative chunk size is invalid.");
-+		return 0;
-+	}
-+
-+	lp->chunk_size = arg_uint_value(cmd, chunksize_ARG,
-+					DEFAULT_CACHE_POOL_CHUNK_SIZE * 2);
-+
-+	str_arg = arg_str_value(cmd, cachemode_ARG, NULL);
-+	if (str_arg) {
-+		if (!strcmp(str_arg, "writeback"))
-+			lp->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
-+		else if (!strcmp(str_arg, "writethrough"))
-+			lp->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
-+		else {
-+			log_error("Unknown cachemode argument");
-+			return 0;
-+		}
-+	}
-+
-+	return 1;
-+}
-+
-+static int _read_activation_params(struct lvcreate_params *lp,
-+				   struct cmd_context *cmd,
- 				   struct volume_group *vg)
- {
- 	unsigned pagesize;
-@@ -608,7 +733,7 @@ static int _read_activation_params(struct lvcreate_params *lp, struct cmd_contex
- 	lp->activate = (activation_change_t)
- 		arg_uint_value(cmd, activate_ARG, CHANGE_AY);
- 
--	if (lp->activate == CHANGE_AN || lp->activate == CHANGE_ALN) {
-+	if (!is_change_activating(lp->activate)) {
- 		if (lp->zero && !seg_is_thin(lp)) {
- 			log_error("--activate n requires --zero n");
- 			return 0;
-@@ -644,8 +769,12 @@ static int _read_activation_params(struct lvcreate_params *lp, struct cmd_contex
- 	lp->permission = arg_uint_value(cmd, permission_ARG,
- 					LVM_READ | LVM_WRITE);
- 
--	/* Must not zero/wipe read only volume */
--	if (!(lp->permission & LVM_WRITE)) {
-+	if (lp->snapshot) {
-+		/* Snapshot has to zero COW header */
-+		lp->zero = 1;
-+		lp->wipe_signatures = 0;
-+	} else if (!(lp->permission & LVM_WRITE)) {
-+		/* Must not zero/wipe read only volume */
- 		lp->zero = 0;
- 		lp->wipe_signatures = 0;
- 	}
-@@ -665,7 +794,7 @@ static int _read_activation_params(struct lvcreate_params *lp, struct cmd_contex
- 
- 	/* Persistent minor */
- 	if (arg_count(cmd, persistent_ARG)) {
--		if (lp->create_thin_pool && !lp->thin) {
-+		if (lp->create_pool && !lp->thin) {
- 			log_error("--persistent is not permitted when creating a thin pool device.");
- 			return 0;
- 		}
-@@ -774,12 +903,15 @@ static int _lvcreate_params(struct lvcreate_params *lp,
- 	    (!seg_is_thin(lp) && arg_count(cmd, virtualsize_ARG)))
- 		lp->snapshot = 1;
- 
-+	if (seg_is_cache_pool(lp))
-+		lp->create_pool = 1;
-+
- 	if (seg_is_thin_pool(lp)) {
- 		if (lp->snapshot) {
- 			log_error("Snapshots are incompatible with thin_pool segment_type.");
- 			return 0;
- 		}
--		lp->create_thin_pool = 1;
-+		lp->create_pool = 1;
- 	}
- 
- 	if (seg_is_thin_volume(lp))
-@@ -853,19 +985,16 @@ static int _lvcreate_params(struct lvcreate_params *lp,
- 		}
- 	}
- 
--	if (activation() && lp->segtype->ops->target_present &&
--	    !lp->segtype->ops->target_present(cmd, NULL, &lp->target_attr)) {
--		log_error("%s: Required device-mapper target(s) not "
--			  "detected in your kernel", lp->segtype->name);
--		return 0;
--	} else if (!strcmp(lp->segtype->name, "raid10")) {
--		uint32_t maj, min, patchlevel;
--		if (!target_version("raid", &maj, &min, &patchlevel)) {
--			log_error("Failed to determine version of RAID kernel module");
-+	if (activation() && lp->segtype->ops->target_present) {
-+		if (!lp->segtype->ops->target_present(cmd, NULL, &lp->target_attr)) {
-+			log_error("%s: Required device-mapper target(s) not detected in your kernel.",
-+				  lp->segtype->name);
- 			return 0;
- 		}
--		if ((maj != 1) || (min < 3)) {
--			log_error("RAID module does not support RAID10");
-+
-+		if ((strcmp(lp->segtype->name, "raid10") == 0) &&
-+		    !(lp->target_attr & RAID_FEATURE_RAID10)) {
-+			log_error("RAID module does not support RAID10.");
- 			return 0;
- 		}
- 	}
-@@ -873,13 +1002,13 @@ static int _lvcreate_params(struct lvcreate_params *lp,
- 	/*
- 	 * Should we zero/wipe signatures on the lv.
- 	 */
--	lp->zero = strcmp(arg_str_value(cmd, zero_ARG,
--		(lp->segtype->flags & SEG_CANNOT_BE_ZEROED) ? "n" : "y"), "n");
-+	lp->zero = (!(lp->segtype->flags & SEG_CANNOT_BE_ZEROED) &&
-+		    (strcmp(arg_str_value(cmd, zero_ARG, "y"), "y") == 0)) ? 1 : 0;
- 
- 	if (arg_count(cmd, wipesignatures_ARG)) {
- 		/* If -W/--wipesignatures is given on command line directly, respect it. */
--		lp->wipe_signatures = strcmp(arg_str_value(cmd, wipesignatures_ARG,
--			(lp->segtype->flags & SEG_CANNOT_BE_ZEROED) ? "n" : "y"), "n");
-+		lp->wipe_signatures =(!(lp->segtype->flags & SEG_CANNOT_BE_ZEROED) &&
-+				      (strcmp(arg_str_value(cmd, wipesignatures_ARG, "y"), "y") == 0)) ? 1 : 0;
- 	} else {
- 		/*
- 		 * If -W/--wipesignatures is not given on command line,
-@@ -895,13 +1024,14 @@ static int _lvcreate_params(struct lvcreate_params *lp,
- 	if (!_lvcreate_name_params(lp, cmd, &argc, &argv) ||
- 	    !_read_size_params(lp, lcp, cmd) ||
- 	    !get_stripe_params(cmd, &lp->stripes, &lp->stripe_size) ||
--	    (lp->create_thin_pool &&
-+	    (lp->create_pool &&
- 	     !get_pool_params(cmd, NULL, &lp->passed_args,
- 			      &lp->thin_chunk_size_calc_policy,
- 			      &lp->chunk_size, &lp->discards,
- 			      &lp->poolmetadatasize, &lp->zero)) ||
- 	    !_read_mirror_params(lp, cmd) ||
--	    !_read_raid_params(lp, cmd))
-+	    !_read_raid_params(lp, cmd) ||
-+	    !_read_cache_pool_params(lp, cmd))
- 		return_0;
- 
- 	if (lp->snapshot && (lp->extents || lcp->size)) {
-@@ -920,12 +1050,12 @@ static int _lvcreate_params(struct lvcreate_params *lp,
- 
- 		if (!(lp->segtype = get_segtype_from_string(cmd, "snapshot")))
- 			return_0;
--	} else if (!lp->create_thin_pool && arg_count(cmd, chunksize_ARG)) {
-+	} else if (!lp->create_pool && arg_count(cmd, chunksize_ARG)) {
- 		log_error("--chunksize is only available with snapshots and thin pools.");
- 		return 0;
- 	}
- 
--	if (lp->create_thin_pool) {
-+	if (lp->create_pool) {
- 		/* TODO: add lvm.conf default y|n */
- 		lp->poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG,
- 						      DEFAULT_POOL_METADATA_SPARE);
-@@ -974,7 +1104,7 @@ static int _check_thin_parameters(struct volume_group *vg, struct lvcreate_param
- 	struct lv_list *lvl;
- 	unsigned i;
- 
--	if (!lp->thin && !lp->create_thin_pool && !lp->snapshot) {
-+	if (!lp->thin && !lp->create_pool && !lp->snapshot) {
- 		log_error("Please specify device size(s).");
- 		return 0;
- 	}
-@@ -984,7 +1114,7 @@ static int _check_thin_parameters(struct volume_group *vg, struct lvcreate_param
- 		return 0;
- 	}
- 
--	if (!lp->create_thin_pool) {
-+	if (!lp->create_pool) {
- 		static const int _argname[] = {
- 			alloc_ARG,
- 			chunksize_ARG,
-@@ -1051,6 +1181,45 @@ static int _check_thin_parameters(struct volume_group *vg, struct lvcreate_param
- 	return 1;
- }
- 
-+static int _check_raid_parameters(struct volume_group *vg,
-+				  struct lvcreate_params *lp,
-+				  struct lvcreate_cmdline_params *lcp)
-+{
-+	unsigned devs = lcp->pv_count ? : dm_list_size(&vg->pvs);
-+	struct cmd_context *cmd = vg->cmd;
-+
-+	/*
-+	 * If number of devices was not supplied, we can infer from
-+	 * the PVs given.
-+	 */
-+	if (!seg_is_mirrored(lp)) {
-+		if (!arg_count(cmd, stripes_ARG) &&
-+		    (devs > 2 * lp->segtype->parity_devs))
-+			lp->stripes = devs - lp->segtype->parity_devs;
-+
-+		if (!lp->stripe_size)
-+			lp->stripe_size = find_config_tree_int(cmd, metadata_stripesize_CFG, NULL) * 2;
-+
-+		if (lp->stripes <= lp->segtype->parity_devs) {
-+			log_error("Number of stripes must be at least %d for %s",
-+				  lp->segtype->parity_devs + 1,
-+				  lp->segtype->name);
-+			return 0;
-+		}
-+	} else if (!strcmp(lp->segtype->name, "raid10")) {
-+		if (!arg_count(cmd, stripes_ARG))
-+			lp->stripes = devs / lp->mirrors;
-+		if (lp->stripes < 2) {
-+			log_error("Unable to create RAID10 LV,"
-+				  " insufficient number of devices.");
-+			return 0;
-+		}
-+	}
-+	/* 'mirrors' defaults to 2 - not the number of PVs supplied */
-+
-+	return 1;
-+}
-+
- /*
-  * Ensure the set of thin parameters extracted from the command line is consistent.
-  */
-@@ -1060,14 +1229,14 @@ static int _validate_internal_thin_processing(const struct lvcreate_params *lp)
- 
- 	/*
- 	   The final state should be one of:
--	   thin  create_thin_pool  snapshot   origin   pool  
--	     1          1             0          0      y/n    - create new pool and a thin LV in it
--	     1          0             0          0      y      - create new thin LV in existing pool
--	     0          1             0          0      y/n    - create new pool only
--	     1          0             1          1      y      - create thin snapshot of existing thin LV
-+	   thin  create_pool  snapshot   origin   pool
-+	     1        1           0         0      y/n    - create new pool and a thin LV in it
-+	     1        0           0         0      y      - create new thin LV in existing pool
-+	     0        1           0         0      y/n    - create new pool only
-+	     1        0           1         1      y      - create thin snapshot of existing thin LV
- 	*/
- 
--	if (!lp->create_thin_pool && !lp->pool) {
-+	if (!lp->create_pool && !lp->pool) {
- 		log_error(INTERNAL_ERROR "--thinpool not identified.");
- 		r = 0;
- 	}
-@@ -1077,7 +1246,7 @@ static int _validate_internal_thin_processing(const struct lvcreate_params *lp)
- 		r = 0;
- 	}
- 
--	if (!lp->thin && !lp->create_thin_pool && !lp->snapshot) {
-+	if (!lp->thin && !lp->create_pool && !lp->snapshot) {
- 		log_error(INTERNAL_ERROR "Failed to identify what type of thin target to use.");
- 		r = 0;
- 	}
-@@ -1113,6 +1282,12 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
- 	if (seg_is_thin(&lp) && !_check_thin_parameters(vg, &lp, &lcp))
- 		goto_out;
- 
-+	if (seg_is_cache(&lp) && !_determine_cache_argument(vg, &lp))
-+		goto_out;
-+
-+	if (seg_is_raid(&lp) && !_check_raid_parameters(vg, &lp, &lcp))
-+		goto_out;
-+
- 	/*
- 	 * Check activation parameters to support inactive thin snapshot creation
- 	 * FIXME: anything else needs to be moved past _determine_snapshot_type()?
-@@ -1126,7 +1301,7 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
- 	if (seg_is_thin(&lp) && !_validate_internal_thin_processing(&lp))
- 		goto_out;
- 
--	if (lp.create_thin_pool) {
-+	if (lp.create_pool) {
- 		if (!handle_pool_metadata_spare(vg, lp.poolmetadataextents,
- 						lp.pvh, lp.poolmetadataspare))
- 			goto_out;
-diff --git a/tools/pvmove.c b/tools/pvmove.c
-index 19e1482..a7788ba 100644
---- a/tools/pvmove.c
-+++ b/tools/pvmove.c
-@@ -233,6 +233,32 @@ static int sub_lv_of(struct logical_volume *lv, const char *lv_name)
- 	return sub_lv_of(seg->lv, lv_name);
- }
- 
-+/*
-+ * parent_lv_is_cache_type
-+ *
-+ * FIXME: This function can be removed when 'pvmove' is supported for
-+ *        cache types.
-+ *
-+ * If this LV is below a cache LV (at any depth), return 1.
-+ */
-+static int parent_lv_is_cache_type(struct logical_volume *lv)
-+{
-+	struct lv_segment *seg;
-+
-+	/* Sub-LVs only ever have one segment using them */
-+	if (dm_list_size(&lv->segs_using_this_lv) != 1)
-+		return 0;
-+
-+	if (!(seg = get_only_segment_using_this_lv(lv)))
-+		return_0;
-+
-+	if (lv_is_cache_type(seg->lv))
-+		return 1;
-+
-+	/* Continue up the tree */
-+	return parent_lv_is_cache_type(seg->lv);
-+}
-+
- /* Create new LV with mirror segments for the required copies */
- static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 						struct volume_group *vg,
-@@ -342,6 +368,23 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
- 		if (!lv_is_on_pvs(lv, source_pvl))
- 			continue;
- 
-+		if (lv_is_cache_type(lv)) {
-+			log_print_unless_silent("Skipping %s LV, %s",
-+						lv_is_cache(lv) ? "cache" :
-+						lv_is_cache_pool(lv) ?
-+						"cache-pool" : "cache-related",
-+						lv->name);
-+			lv_skipped = 1;
-+			continue;
-+		}
-+
-+		if (parent_lv_is_cache_type(lv)) {
-+			log_print_unless_silent("Skipping %s because a parent"
-+						" is of cache type", lv->name);
-+			lv_skipped = 1;
-+			continue;
-+		}
-+
- 		/*
- 		 * If the VG is clustered, we are unable to handle
- 		 * snapshots, origins, thin types, RAID or mirror
-diff --git a/tools/tags.c b/tools/tags.c
-new file mode 100644
-index 0000000..bbb446a
---- /dev/null
-+++ b/tools/tags.c
-@@ -0,0 +1,23 @@
-+/*
-+ * Copyright (C) 2014 Red Hat, Inc. All rights reserved.
-+ *
-+ * This file is part of LVM2.
-+ *
-+ * This copyrighted material is made available to anyone wishing to use,
-+ * modify, copy, or redistribute it subject to the terms and conditions
-+ * of the GNU Lesser General Public License v.2.1.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public License
-+ * along with this program; if not, write to the Free Software Foundation,
-+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include "tools.h"
-+
-+int tags(struct cmd_context *cmd, int argc __attribute__((unused)),
-+	     char **argv __attribute__((unused)))
-+{
-+	display_tags(cmd);
-+
-+	return ECMD_PROCESSED;
-+}
-diff --git a/tools/toollib.c b/tools/toollib.c
-index 61c14f1..91b0559 100644
---- a/tools/toollib.c
-+++ b/tools/toollib.c
-@@ -184,7 +184,7 @@ int ignore_vg(struct volume_group *vg, const char *vg_name, int allow_inconsiste
- int process_each_lv_in_vg(struct cmd_context *cmd,
- 			  struct volume_group *vg,
- 			  const struct dm_list *arg_lvnames,
--			  const struct dm_list *tags,
-+			  const struct dm_list *tagsl,
- 			  struct dm_list *failed_lvnames,
- 			  void *handle,
- 			  process_single_lv_fn_t process_single_lv)
-@@ -201,7 +201,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
- 	if (!vg_check_status(vg, EXPORTED_VG))
- 		return ECMD_FAILED;
- 
--	if (tags && !dm_list_empty(tags))
-+	if (tagsl && !dm_list_empty(tagsl))
- 		tags_supplied = 1;
- 
- 	if (arg_lvnames && !dm_list_empty(arg_lvnames))
-@@ -212,7 +212,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
- 		process_all = 1;
- 	/* Or if VG tags match */
- 	else if (tags_supplied &&
--		 str_list_match_list(tags, &vg->tags, NULL))
-+		 str_list_match_list(tagsl, &vg->tags, NULL))
- 		process_all = 1;
- 
- 	/*
-@@ -247,7 +247,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
- 		/* LV tag match?   skip test, when process_all */
- 		else if (!process_all &&
- 			 (!tags_supplied ||
--			  !str_list_match_list(tags, &lvl->lv->tags, NULL)))
-+			  !str_list_match_list(tagsl, &lvl->lv->tags, NULL)))
- 			continue;
- 
- 		if (sigint_caught())
-@@ -296,7 +296,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
- 	struct cmd_vg *cvl_vg;
- 	struct dm_list cmd_vgs;
- 	struct dm_list failed_lvnames;
--	struct dm_list tags, lvnames;
-+	struct dm_list tagsl, lvnames;
- 	struct dm_list arg_lvnames;	/* Cmdline vgname or vgname/lvname */
- 	struct dm_list arg_vgnames;
- 	char *vglv;
-@@ -304,7 +304,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
- 
- 	const char *vgname;
- 
--	dm_list_init(&tags);
-+	dm_list_init(&tagsl);
- 	dm_list_init(&arg_lvnames);
- 	dm_list_init(&failed_lvnames);
- 
-@@ -327,7 +327,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
- 						  vgname);
- 					continue;
- 				}
--				if (!str_list_add(cmd->mem, &tags,
-+				if (!str_list_add(cmd->mem, &tagsl,
- 						  dm_pool_strdup(cmd->mem,
- 							      vgname + 1))) {
- 					log_error("strlist allocation failed");
-@@ -395,7 +395,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
- 		vgnames = &arg_vgnames;
- 	}
- 
--	if (!argc || !dm_list_empty(&tags)) {
-+	if (!argc || !dm_list_empty(&tagsl)) {
- 		log_verbose("Finding all logical volumes");
- 		if (!lvmetad_vg_list_to_lvmcache(cmd))
- 			stack;
-@@ -420,7 +420,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
- 			continue;
- 		}
- 
--		tags_arg = &tags;
-+		tags_arg = &tagsl;
- 		dm_list_init(&lvnames);	/* LVs to be processed in this VG */
- 		dm_list_iterate_items(sll, &arg_lvnames) {
- 			const char *vg_name = sll->str;
-@@ -562,7 +562,7 @@ int process_each_segment_in_lv(struct cmd_context *cmd,
- 
- static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
- 			   const char *vgid,
--			   struct dm_list *tags, struct dm_list *arg_vgnames,
-+			   struct dm_list *tagsl, struct dm_list *arg_vgnames,
- 			   uint32_t flags, void *handle, int ret_max,
- 			   process_single_vg_fn_t process_single_vg)
- {
-@@ -591,10 +591,10 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
- 			}
- 		}
- 
--		if (!dm_list_empty(tags) &&
-+		if (!dm_list_empty(tagsl) &&
- 		    /* Only process if a tag matches or it's on arg_vgnames */
- 		    !str_list_match_item(arg_vgnames, vg_name) &&
--		    !str_list_match_list(tags, &cvl_vg->vg->tags, NULL))
-+		    !str_list_match_list(tagsl, &cvl_vg->vg->tags, NULL))
- 			break;
- 
- 		ret = process_single_vg(cmd, vg_name, cvl_vg->vg, handle);
-@@ -622,11 +622,11 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- 
- 	struct str_list *sl;
- 	struct dm_list *vgnames, *vgids;
--	struct dm_list arg_vgnames, tags;
-+	struct dm_list arg_vgnames, tagsl;
- 
- 	const char *vg_name, *vgid;
- 
--	dm_list_init(&tags);
-+	dm_list_init(&tagsl);
- 	dm_list_init(&arg_vgnames);
- 
- 	if (argc) {
-@@ -642,7 +642,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- 						ret_max = EINVALID_CMD_LINE;
- 					continue;
- 				}
--				if (!str_list_add(cmd->mem, &tags,
-+				if (!str_list_add(cmd->mem, &tagsl,
- 						  dm_pool_strdup(cmd->mem,
- 							      vg_name + 1))) {
- 					log_error("strlist allocation failed");
-@@ -669,7 +669,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- 		vgnames = &arg_vgnames;
- 	}
- 
--	if (!argc || !dm_list_empty(&tags)) {
-+	if (!argc || !dm_list_empty(&tagsl)) {
- 		log_verbose("Finding all volume groups");
- 		if (!lvmetad_vg_list_to_lvmcache(cmd))
- 			stack;
-@@ -681,9 +681,9 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- 			if (sigint_caught())
- 				return_ECMD_FAILED;
- 			vgid = sl->str;
--			if (!(vgid) || !(vg_name = lvmcache_vgname_from_vgid(cmd->mem, vgid)))
-+			if (!vgid || !(vg_name = lvmcache_vgname_from_vgid(cmd->mem, vgid)))
- 				continue;
--			ret_max = _process_one_vg(cmd, vg_name, vgid, &tags,
-+			ret_max = _process_one_vg(cmd, vg_name, vgid, &tagsl,
- 						  &arg_vgnames,
- 						  flags, handle,
- 					  	  ret_max, process_single_vg);
-@@ -695,7 +695,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- 			vg_name = sl->str;
- 			if (is_orphan_vg(vg_name))
- 				continue;	/* FIXME Unnecessary? */
--			ret_max = _process_one_vg(cmd, vg_name, NULL, &tags,
-+			ret_max = _process_one_vg(cmd, vg_name, NULL, &tagsl,
- 						  &arg_vgnames,
- 						  flags, handle,
- 					  	  ret_max, process_single_vg);
-@@ -706,7 +706,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- }
- 
- int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
--			  const struct dm_list *tags, void *handle,
-+			  const struct dm_list *tagsl, void *handle,
- 			  process_single_pv_fn_t process_single_pv)
- {
- 	int ret_max = ECMD_PROCESSED;
-@@ -716,8 +716,8 @@ int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
- 	dm_list_iterate_items(pvl, &vg->pvs) {
- 		if (sigint_caught())
- 			return_ECMD_FAILED;
--		if (tags && !dm_list_empty(tags) &&
--		    !str_list_match_list(tags, &pvl->pv->tags, NULL)) {
-+		if (tagsl && !dm_list_empty(tagsl) &&
-+		    !str_list_match_list(tagsl, &pvl->pv->tags, NULL)) {
- 			continue;
- 		}
- 		if ((ret = process_single_pv(cmd, vg, pvl->pv, handle)) > ret_max)
-@@ -801,12 +801,12 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
- 	struct pv_list *pvl;
- 	struct physical_volume *pv;
- 	struct dm_list *pvslist = NULL, *vgnames;
--	struct dm_list tags;
-+	struct dm_list tagsl;
- 	struct str_list *sll;
- 	char *at_sign, *tagname;
- 	struct device *dev;
- 
--	dm_list_init(&tags);
-+	dm_list_init(&tagsl);
- 
- 	if (lock_global && !lock_vol(cmd, VG_GLOBAL, LCK_VG_READ, NULL)) {
- 		log_error("Unable to obtain global lock.");
-@@ -831,7 +831,7 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
- 						ret_max = EINVALID_CMD_LINE;
- 					continue;
- 				}
--				if (!str_list_add(cmd->mem, &tags,
-+				if (!str_list_add(cmd->mem, &tagsl,
- 						  dm_pool_strdup(cmd->mem,
- 							      tagname))) {
- 					log_error("strlist allocation failed");
-@@ -881,7 +881,7 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
- 			if (ret > ret_max)
- 				ret_max = ret;
- 		}
--		if (!dm_list_empty(&tags) && (vgnames = get_vgnames(cmd, 1)) &&
-+		if (!dm_list_empty(&tagsl) && (vgnames = get_vgnames(cmd, 1)) &&
- 			   !dm_list_empty(vgnames)) {
- 			dm_list_iterate_items(sll, vgnames) {
- 				if (sigint_caught()) {
-@@ -895,7 +895,7 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
- 					continue;
- 				}
- 
--				ret = process_each_pv_in_vg(cmd, vg, &tags,
-+				ret = process_each_pv_in_vg(cmd, vg, &tagsl,
- 							    handle,
- 							    process_single_pv);
- 				if (ret > ret_max)
-@@ -1215,7 +1215,7 @@ struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int
- {
- 	struct dm_list *r;
- 	struct pv_list *pvl;
--	struct dm_list tags, arg_pvnames;
-+	struct dm_list tagsl, arg_pvnames;
- 	char *pvname = NULL;
- 	char *colon, *at_sign, *tagname;
- 	int i;
-@@ -1227,7 +1227,7 @@ struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int
- 	}
- 	dm_list_init(r);
- 
--	dm_list_init(&tags);
-+	dm_list_init(&tagsl);
- 	dm_list_init(&arg_pvnames);
- 
- 	for (i = 0; i < argc; i++) {
-@@ -1404,7 +1404,7 @@ int lv_change_activate(struct cmd_context *cmd, struct logical_volume *lv,
- 		 * deactivation of origin, which is the only visible LV
- 		 */
- 		if (!deactivate_lv(cmd, find_snapshot(lv)->lv)) {
--			if ((activate != CHANGE_AN) && (activate != CHANGE_ALN)) {
-+			if (is_change_activating(activate)) {
- 				log_error("Refusing to activate merging \"%s\" while snapshot \"%s\" is still active.",
- 					  lv->name, find_snapshot(lv)->lv->name);
- 				return 0;
-@@ -1420,8 +1420,7 @@ int lv_change_activate(struct cmd_context *cmd, struct logical_volume *lv,
- 		return_0;
- 
- 	if (background_polling() &&
--	    (activate != CHANGE_AN) &&
--	    (activate != CHANGE_ALN) &&
-+	    is_change_activating(activate) &&
- 	    (lv->status & (PVMOVE|CONVERTING|MERGING)))
- 		lv_spawn_background_polling(cmd, lv);
- 
-@@ -1661,14 +1660,28 @@ int get_pool_params(struct cmd_context *cmd,
- 		    uint64_t *pool_metadata_size,
- 		    int *zero)
- {
-+	int cache_pool = 0;
-+
-+	if (!strcmp("cache-pool", arg_str_value(cmd, type_ARG, "none")))
-+		cache_pool = 1;
-+
-+	if (!cache_pool && !arg_count(cmd, thinpool_ARG)) {
-+		/* Check for arguments that should only go with pools */
-+		if (arg_count(cmd, poolmetadata_ARG)) {
-+			log_error("'--poolmetadata' argument is only valid when"
-+				  " converting to pool LVs.");
-+			return_0;
-+		}
-+	}
-+
- 	*passed_args = 0;
--	if (arg_count(cmd, zero_ARG)) {
-+	if (!cache_pool && arg_count(cmd, zero_ARG)) {
- 		*passed_args |= PASS_ARG_ZERO;
- 		*zero = strcmp(arg_str_value(cmd, zero_ARG, "y"), "n");
- 		log_very_verbose("Setting pool zeroing: %u", *zero);
- 	}
- 
--	if (arg_count(cmd, discards_ARG)) {
-+	if (!cache_pool && arg_count(cmd, discards_ARG)) {
- 		*passed_args |= PASS_ARG_DISCARDS;
- 		*discards = (thin_discards_t) arg_uint_value(cmd, discards_ARG, 0);
- 		log_very_verbose("Setting pool discards: %s",
-@@ -1681,15 +1694,20 @@ int get_pool_params(struct cmd_context *cmd,
- 			return 0;
- 		}
- 		*passed_args |= PASS_ARG_CHUNK_SIZE;
--		*chunk_size = arg_uint_value(cmd, chunksize_ARG,
-+		*chunk_size = arg_uint_value(cmd, chunksize_ARG, cache_pool ?
-+					     DM_CACHE_MIN_DATA_BLOCK_SIZE :
- 					     DM_THIN_MIN_DATA_BLOCK_SIZE);
- 		log_very_verbose("Setting pool chunk size: %s",
- 				 display_size(cmd, *chunk_size));
- 	}
- 
--	if (!update_profilable_pool_params(cmd, profile, *passed_args,
--					   chunk_size_calc_method, chunk_size,
--					   discards, zero))
-+	if (cache_pool) {
-+		//FIXME: add cache_pool support to update_profilable_pool_params
-+		if (!(*passed_args & PASS_ARG_CHUNK_SIZE))
-+			*chunk_size = DEFAULT_CACHE_POOL_CHUNK_SIZE * 2;
-+	} else if (!update_profilable_pool_params(cmd, profile, *passed_args,
-+						  chunk_size_calc_method,
-+						  chunk_size, discards, zero))
- 		return_0;
- 
- 	if (arg_count(cmd, poolmetadatasize_ARG)) {
-@@ -1699,7 +1717,8 @@ int get_pool_params(struct cmd_context *cmd,
- 		}
- 		*passed_args |= PASS_ARG_POOL_METADATA_SIZE;
- 	}
--	*pool_metadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, UINT64_C(0));
-+	*pool_metadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG,
-+					       UINT64_C(0));
- 
- 	return 1;
- }
-diff --git a/tools/toollib.h b/tools/toollib.h
-index d809123..54636ab 100644
---- a/tools/toollib.h
-+++ b/tools/toollib.h
-@@ -80,14 +80,14 @@ int process_each_segment_in_lv(struct cmd_context *cmd,
- 			       process_single_seg_fn_t process_single_seg);
- 
- int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
--			  const struct dm_list *tags, void *handle,
-+			  const struct dm_list *tagsl, void *handle,
- 			  process_single_pv_fn_t process_single_pv);
- 
- 
- int process_each_lv_in_vg(struct cmd_context *cmd,
- 			  struct volume_group *vg,
- 			  const struct dm_list *arg_lvnames,
--			  const struct dm_list *tags,
-+			  const struct dm_list *tagsl,
- 			  struct dm_list *failed_lvnames,
- 			  void *handle,
- 			  process_single_lv_fn_t process_single_lv);
-diff --git a/tools/vgchange.c b/tools/vgchange.c
-index af4b002..e7b5e59 100644
---- a/tools/vgchange.c
-+++ b/tools/vgchange.c
-@@ -117,15 +117,11 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd, struct volume_group *vg,
- 
- 		/* Can't deactivate a pvmove LV */
- 		/* FIXME There needs to be a controlled way of doing this */
--		if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) &&
--		    ((lv->status & PVMOVE) ))
-+		if ((lv->status & PVMOVE) && !is_change_activating(activate))
- 			continue;
- 
--		if (lv_activation_skip(lv, activate, arg_count(cmd, ignoreactivationskip_ARG), 0)) {
--			log_verbose("ACTIVATION_SKIP flag set for LV %s/%s, skipping activation.",
--				    lv->vg->name, lv->name);
-+		if (lv_activation_skip(lv, activate, arg_count(cmd, ignoreactivationskip_ARG)))
- 			continue;
--		}
- 
- 		if ((activate == CHANGE_AAY) &&
- 		    !lv_passes_auto_activation_filter(cmd, lv))
-@@ -155,8 +151,8 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd, struct volume_group *vg,
- 
- 	if (expected_count)
- 		log_verbose("%s %d logical volumes in volume group %s",
--			    (activate == CHANGE_AN || activate == CHANGE_ALN)?
--			    "Deactivated" : "Activated", count, vg->name);
-+			    is_change_activating(activate) ?
-+			    "Activated" : "Deactivated", count, vg->name);
- 
- 	return (expected_count != count) ? 0 : 1;
- }
-@@ -196,12 +192,10 @@ static int _vgchange_background_polling(struct cmd_context *cmd, struct volume_g
- int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
- 		      activation_change_t activate)
- {
--	int lv_open, active, monitored = 0, r = 1, do_activate = 1;
-+	int lv_open, active, monitored = 0, r = 1;
- 	const struct lv_list *lvl;
- 	struct lvinfo info;
--
--	if ((activate == CHANGE_AN) || (activate == CHANGE_ALN))
--		do_activate = 0;
-+	int do_activate = is_change_activating(activate);
- 
- 	/*
- 	 * Safe, since we never write out new metadata here. Required for
-@@ -592,8 +586,7 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
- 
- 	if (arg_count(cmd, activate_ARG) &&
- 	    (arg_count(cmd, monitor_ARG) || arg_count(cmd, poll_ARG))) {
--		int activate = arg_uint_value(cmd, activate_ARG, 0);
--		if (activate == CHANGE_AN || activate == CHANGE_ALN) {
-+		if (!is_change_activating(arg_uint_value(cmd, activate_ARG, 0))) {
- 			log_error("Only -ay* allowed with --monitor or --poll.");
- 			return EINVALID_CMD_LINE;
- 		}
-@@ -604,8 +597,8 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
- 		return EINVALID_CMD_LINE;
- 	}
- 
--	if (arg_count(cmd, activate_ARG) == 1
--	    && arg_count(cmd, autobackup_ARG)) {
-+	if ((arg_count(cmd, activate_ARG) == 1) &&
-+	    arg_count(cmd, autobackup_ARG)) {
- 		log_error("-A option not necessary with -a option");
- 		return EINVALID_CMD_LINE;
- 	}
-diff --git a/tools/vgsplit.c b/tools/vgsplit.c
-index dfcb120..150be1d 100644
---- a/tools/vgsplit.c
-+++ b/tools/vgsplit.c
-@@ -14,6 +14,7 @@
-  */
- 
- #include "tools.h"
-+#include "metadata.h"  /* for 'get_only_segment_using_this_lv' */
- 
- /* FIXME Why not (lv->vg == vg) ? */
- static int _lv_is_in_vg(struct volume_group *vg, struct logical_volume *lv)
-@@ -72,6 +73,10 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
- 		    lv_is_thin_volume(lv))
- 			continue;
- 
-+		if (lv_is_cache(lv) || lv_is_cache_pool(lv))
-+			/* further checks by _move_cache() */
-+			continue;
-+
- 		/* Ensure all the PVs used by this LV remain in the same */
- 		/* VG as each other */
- 		vg_with = NULL;
-@@ -268,6 +273,77 @@ static int _move_thins(struct volume_group *vg_from,
- 	return 1;
- }
- 
-+static int _move_cache(struct volume_group *vg_from,
-+		       struct volume_group *vg_to)
-+{
-+	int is_moving;
-+	struct dm_list *lvh, *lvht;
-+	struct logical_volume *lv, *data, *meta, *orig;
-+	struct lv_segment *seg, *cache_seg;
-+
-+	dm_list_iterate_safe(lvh, lvht, &vg_from->lvs) {
-+		lv = dm_list_item(lvh, struct lv_list)->lv;
-+		data = meta = orig = NULL;
-+		seg = first_seg(lv);
-+
-+		if (!lv_is_cache(lv) && !lv_is_cache_pool(lv))
-+			continue;
-+
-+		/*
-+		 * FIXME: The code seems to move cache LVs fine, but it
-+		 *        hasn't been well tested and it causes problems
-+		 *        when just splitting PVs that don't contain
-+		 *        cache LVs.
-+		 * Waiting for next release before fixing and enabling.
-+		 */
-+		log_error("Unable to split VG while it contains cache LVs");
-+		return 0;
-+
-+		if (lv_is_cache(lv)) {
-+			orig = seg_lv(seg, 0);
-+			data = seg_lv(first_seg(seg->pool_lv), 0);
-+			meta = first_seg(seg->pool_lv)->metadata_lv;
-+			/* Ensure all components are coming along */
-+			is_moving = !!_lv_is_in_vg(vg_to, orig);
-+		} else {
-+			if (!dm_list_empty(&seg->lv->segs_using_this_lv) &&
-+			    !(cache_seg = get_only_segment_using_this_lv(seg->lv)))
-+				return_0;
-+			orig = seg_lv(cache_seg, 0);
-+			data = seg_lv(seg, 0);
-+			meta = seg->metadata_lv;
-+
-+			if (_lv_is_in_vg(vg_to, data) ||
-+			    _lv_is_in_vg(vg_to, meta))
-+				is_moving = 1;
-+		}
-+
-+		if (orig && (!!_lv_is_in_vg(vg_to, orig) != is_moving)) {
-+			log_error("Can't split %s and its origin (%s)"
-+				  " into separate VGs", lv->name, orig->name);
-+			return 0;
-+		}
-+
-+		if (data && (!!_lv_is_in_vg(vg_to, data) != is_moving)) {
-+			log_error("Can't split %s and its cache pool"
-+				  " data LV (%s) into separate VGs",
-+				  lv->name, data->name);
-+			return 0;
-+		}
-+
-+		if (meta && (!!_lv_is_in_vg(vg_to, meta) != is_moving)) {
-+			log_error("Can't split %s and its cache pool"
-+				  " metadata LV (%s) into separate VGs",
-+				  lv->name, meta->name);
-+			return 0;
-+		}
-+		if (!_move_one_lv(vg_from, vg_to, lvh))
-+			return_0;
-+	}
-+
-+	return 1;
-+}
-+
- /*
-  * Create or open the destination of the vgsplit operation.
-  * Returns
-@@ -481,6 +557,9 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
- 	if (!(_move_thins(vg_from, vg_to)))
- 		goto_bad;
- 
-+	if (!(_move_cache(vg_from, vg_to)))
-+		goto_bad;
-+
- 	/* Split metadata areas and check if both vgs have at least one area */
- 	if (!(vg_split_mdas(cmd, vg_from, vg_to)) && vg_from->pv_count) {
- 		log_error("Cannot split: Nowhere to store metadata for new Volume Group");
-diff --git a/udev/10-dm.rules.in b/udev/10-dm.rules.in
-index f7088f1..8d7a8ca 100644
---- a/udev/10-dm.rules.in
-+++ b/udev/10-dm.rules.in
-@@ -120,12 +120,6 @@ ENV{DM_UDEV_RULES_VSN}="2"
- 
- ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="(DM_DIR)/$env{DM_NAME}"
- 
--# We have to ignore further rule application for inappropriate events
--# and devices. But still send the notification if cookie exists.
--ENV{DM_UUID}=="mpath-?*", ENV{DM_ACTION}=="PATH_FAILED", GOTO="dm_disable"
--ENV{DM_UUID}=="CRYPT-TEMP-?*", GOTO="dm_disable"
--ENV{DM_UUID}!="?*", ENV{DM_NAME}=="temporary-cryptsetup-?*", GOTO="dm_disable"
--
- # Avoid processing and scanning a DM device in the other (foreign)
- # rules if it is in suspended state. However, we still keep 'disk'
- # and 'DM subsystem' related rules enabled in this case.
-diff --git a/udev/69-dm-lvm-metad.rules.in b/udev/69-dm-lvm-metad.rules.in
-index e8304b5..bd75fc8 100644
---- a/udev/69-dm-lvm-metad.rules.in
-+++ b/udev/69-dm-lvm-metad.rules.in
-@@ -34,6 +34,9 @@ ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="lvm_end"
- # Inform lvmetad about any PV that is gone.
- ACTION=="remove", GOTO="lvm_scan"
- 
-+# Create /dev/disk/by-id/lvm-pv-uuid-<PV_UUID> symlink for each PV
-+ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-id/lvm-pv-uuid-$env{ID_FS_UUID_ENC}"
-+
- # If the PV is a special device listed below, scan only if the device is
- # properly activated. These devices are not usable after an ADD event,
- # but they require an extra setup and they are ready after a CHANGE event.
diff --git a/SOURCES/lvm2-2_02_106-various-man-page-cleanups.patch b/SOURCES/lvm2-2_02_106-various-man-page-cleanups.patch
deleted file mode 100644
index 7ef5269..0000000
--- a/SOURCES/lvm2-2_02_106-various-man-page-cleanups.patch
+++ /dev/null
@@ -1,188 +0,0 @@
- man/lvchange.8.in  |  6 +++---
- man/lvconvert.8.in | 36 +++++++++++++++++++++++-------------
- man/lvcreate.8.in  |  8 ++++----
- man/lvmetad.8.in   | 11 ++++-------
- 4 files changed, 34 insertions(+), 27 deletions(-)
-
-diff --git a/man/lvchange.8.in b/man/lvchange.8.in
-index 64231c8..5de75e0 100644
---- a/man/lvchange.8.in
-+++ b/man/lvchange.8.in
-@@ -41,7 +41,7 @@ lvchange \- change attributes of a logical volume
- .RB [ \-\-[raid]writebehind
- .IR IOCount ]
- .RB [ \-\-[raid]writemostly
--.IR PhysicalVolume[:{t|n|y}] ]
-+.IR PhysicalVolume [ : { t | n | y }]]
- .RB [ \-\-sysinit ]
- .RB [ \-\-noudevsync ]
- .RB [ \-M | \-\-persistent
-@@ -166,7 +166,7 @@ If \fIrepair\fP is used, the discrepancies will be corrected as they are
- encountered.  The 'lvs' command can be used to show the number of
- discrepancies found or repaired.
- .TP
--.BR \-\-[raid]writebehind " IOCount"
-+.BR \-\-[raid]writebehind " " \fIIOCount
- Specify the maximum number of outstanding writes that are allowed to
- devices in a RAID1 logical volume that are marked as \fIwrite-mostly\fP.
- Once this value is exceeded, writes become synchronous (i.e. all writes
-@@ -174,7 +174,7 @@ to the constituent devices must complete before the array signals the
- write has completed).  Setting the value to zero clears the preference
- and allows the system to choose the value arbitrarily.
- .TP
--.BR \-\-[raid]writemostly " PhysicalVolume[:{t|y|n}]"
-+.IR \fB\-\-[raid]writemostly " " PhysicalVolume [ : { t | y | n }]
- Mark a device in a RAID1 logical volume as \fIwrite-mostly\fP.  All reads
- to these drives will be avoided unless absolutely necessary.  This keeps
- the number of I/Os to the drive to a minimum.  The default behavior is to
-diff --git a/man/lvconvert.8.in b/man/lvconvert.8.in
-index 190e221..fe6525b 100644
---- a/man/lvconvert.8.in
-+++ b/man/lvconvert.8.in
-@@ -91,11 +91,11 @@ lvconvert \- convert a logical volume from linear to mirror or snapshot
- .IR ChunkSize [ bBsSkKmMgG ]]
- .RB [ \-\-discards
- .RI { ignore | nopassdown | passdown }]
--.RB [[ \-\-poolmetadata
--.IR ThinPoolMetadataLogicalVolume { Name | Path }]
-+.RB [{ \-\-poolmetadata
-+.IR ThinPoolMetadataLogicalVolume { Name | Path }
- |
--.RB [ \-\-poolmetadatasize
--.IR ThinPoolMetadataSize [ bBsSkKmMgG ]]
-+.B \-\-poolmetadatasize
-+.IR ThinPoolMetadataSize [ bBsSkKmMgG ]}]
- .RB [ \-r | \-\-readahead
- .RI { ReadAheadSectors | auto | none }]
- .RB [ \-\-stripes
-@@ -113,24 +113,24 @@ lvconvert \- convert a logical volume from linear to mirror or snapshot
- .RB [ \-v | \-\-verbose ]
- .RB [ \-\-version ]
- .sp
--.B lvconvert \-\-type cache-pool
-+.B lvconvert \-\-type \fIcache-pool
- .RB [ \-c | \-\-chunksize
- .IR ChunkSize [ bBsSkKmMgG ]]
- .RB [ \-\-cachemode
- .RI { writeback | writethrough }]
--.RB [[ \-\-poolmetadata
--.IR CachePoolMetadataLogicalVolume { Name | Path }]
-+.RB [{ \-\-poolmetadata
-+.IR CachePoolMetadataLogicalVolume { Name | Path }
- |
--.RB [ \-\-poolmetadatasize
--.IR CachePoolMetadataSize [ bBsSkKmMgG ]]
-+.B \-\-poolmetadatasize
-+.IR CachePoolMetadataSize [ bBsSkKmMgG ]}]
- .IR LogicalVolume [ Path ]
- .RI [ PhysicalVolume [ Path ][ :PE [ -PE ]]...]
- .RB [ \-h | \-? | \-\-help ]
- .RB [ \-v | \-\-verbose ]
- .RB [ \-\-version ]
- .sp
--.B lvconvert \-\-type cache
--.RB \-\-cachepool
-+.B lvconvert \-\-type \fIcache
-+.B \-\-cachepool
- .IR CachePoolLV { Name | Path }
- .IR LogicalVolume [ Path ]
- .RB [ \-h | \-? | \-\-help ]
-@@ -333,14 +333,23 @@ a suitable value automatically.
- "None" is equivalent to specifying zero.
- .TP
- .B \-\-repair
--Repair a mirror after suffering a disk failure. The mirror will be brought back
--into a consistent state.  By default, the original number of mirrors will be
-+Repair a mirror after suffering a disk failure or try to fix thin pool metadata.
-+
-+The mirror will be brought back into a consistent state.
-+By default, the original number of mirrors will be
- restored if possible.  Specify \fB\-y\fP on the command line to skip
- the prompts. Use \fB\-f\fP if you do not want any replacement.
- Additionally, you may use \fB\-\-use\-policies\fP to use the device
- replacement policy specified in \fBlvm.conf\fP(5),
- viz. activation/mirror_log_fault_policy or
- activation/mirror_device_fault_policy.
-+
-+Thin pool repair automates the use of \fBthin_repair\fP(8) tool.
-+Only inactive thin pool volumes can be repaired.
-+There is no validation of metadata between kernel and lvm2.
-+This requires further manual work.
-+After successfull repair the old unmodified metadata are still
-+available in \fB<pool>_tmeta<n>\fP LV.
- .TP
- .B \-\-replace \fIPhysicalVolume
- Remove the specified device (\fIPhysicalVolume\fP) and replace it with one
-@@ -498,4 +507,5 @@ cache pool LV.
- .BR lvscan (8),
- .BR vgcreate (8),
- .BR thin_dump (8),
-+.BR thin_repair (8)
- .BR thin_restore (8)
-diff --git a/man/lvcreate.8.in b/man/lvcreate.8.in
-index 325baad..445af80 100644
---- a/man/lvcreate.8.in
-+++ b/man/lvcreate.8.in
-@@ -60,7 +60,7 @@ lvcreate \- create a logical volume in an existing volume group
- .RB [ \-t | \-\-test ]
- .RB [ \-T | \-\-thin
- .RB [ \-\-cachemode
--.IR { writeback | writethrough }
-+.RI { writeback | writethrough }
- .RB [ \-c | \-\-chunksize
- .IR ChunkSize [ bBsSkKmMgG ]]
- .RB [ \-\-discards
-@@ -145,7 +145,7 @@ be overridden. If the clustered locking is enabled,
- .IR \fB\-a { a | l } y
- will activate only on the local node.
- .TP
--.IR \fB\-k ", " \fB\-\-setactivationskip " " { y | n }
-+.IR \fB\-k ", " \fB\-\-setactivationskip "  {" y | n }
- Controls whether Logical Volumes are persistently flagged to be skipped during
- activation. By default, thin snapshot volumes are flagged for activation skip.
- To activate such volumes, an extra \fB\-K/\-\-ignoreactivationskip\fP option must
-@@ -155,11 +155,11 @@ detach the flag for existing volumes. To see whether the flag is attached,
- use \fBlvs\fP command where the state of the flag is reported within
- \fBlv_attr\fP bits.
- .TP
--.IR \fB\-K ", " \fB\-\-ignoreactivationskip
-+.BR \-K ", " \-\-ignoreactivationskip
- Ignore the flag to skip Logical Volumes during activation.
- 
- .TP
--.BR \-\-cachemode " " { writeback | writethrough }
-+.IR \fB\-\-cachemode " " { writeback | writethrough }
- Specifying a cache mode determines when the writes to a cache LV
- are considered complete.  When \fIwriteback\fP is specified, a write is
- considered complete as soon as it is stored in the cache pool LV.
-diff --git a/man/lvmetad.8.in b/man/lvmetad.8.in
-index 4956a3f..444c7c0 100644
---- a/man/lvmetad.8.in
-+++ b/man/lvmetad.8.in
-@@ -4,14 +4,11 @@ lvmetad \- LVM metadata cache daemon
- .SH SYNOPSIS
- .B lvmetad
- .RB [ \-l
--.RI {all|wire|debug}
--.RB ]
-+.RI { all | wire | debug }]
- .RB [ \-p
--.RI pidfile_path
--.RB ]
-+.IR pidfile_path ]
- .RB [ \-s
--.RI socket_path
--.RB ]
-+.IR socket_path ]
- .RB [ \-f ]
- .RB [ \-h ]
- .RB [ \-V ]
-@@ -34,7 +31,7 @@ Don't fork, but run in the foreground.
- .BR \-h ", " \-?
- Show help information.
- .TP
--.BR \-l " {" \fIall | \fIwire | \fIdebug }
-+.IR \fB\-l " {" all | wire | debug }
- Select the type of log messages to generate.
- Messages are logged by syslog.  
- Additionally, when -f is given they are also sent to standard error.
diff --git a/SOURCES/lvm2-2_02_106-various-thin-fixes.patch b/SOURCES/lvm2-2_02_106-various-thin-fixes.patch
deleted file mode 100644
index c4e7ef5..0000000
--- a/SOURCES/lvm2-2_02_106-various-thin-fixes.patch
+++ /dev/null
@@ -1,633 +0,0 @@
-commit 85fc38d398d1bc8acb4027da7acc376af2be0cc1
-Author: Peter Rajnoha <prajnoha@redhat.com>
-Date:   Wed Mar 12 14:37:59 2014 +0100
-
-    thin fixes
----
- WHATS_NEW                   |  3 ++
- lib/activate/activate.c     |  2 +-
- lib/activate/dev_manager.c  | 72 +++++++++++++++++++++++++--------------------
- lib/cache_segtype/cache.c   |  6 ++--
- lib/metadata/lv_manip.c     | 63 +++------------------------------------
- lib/metadata/pool_manip.c   |  3 ++
- lib/metadata/thin_manip.c   |  2 +-
- lib/mirror/mirrored.c       |  4 +--
- lib/misc/lvm-string.c       |  8 ++++-
- lib/misc/lvm-string.h       |  3 +-
- lib/thin/thin.c             |  8 ++---
- test/shell/lvcreate-thin.sh |  4 ++-
- test/shell/pvremove-thin.sh | 28 ++++++++++++++++++
- 13 files changed, 101 insertions(+), 105 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 3ee9585..a3d48f3 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,8 @@
- Version 2.02.106 - 
- ====================================
-+  Update API for internal function build_dm_uuid().
-+  Do not try to check empty pool with scheduled messages.
-+  Fix return value in pool_has_message() when quering for any message.
-   Fix cache consistency in lvmetad when PV moves around.
-   Fix memleak when lvmetad discovers PV to appear on another device.
-   Fix invalid memory read in lvmetad that could cause a deadlock.
-diff --git a/lib/activate/activate.c b/lib/activate/activate.c
-index 26dc0e1..565634f 100644
---- a/lib/activate/activate.c
-+++ b/lib/activate/activate.c
-@@ -1546,7 +1546,7 @@ static char *_build_target_uuid(struct cmd_context *cmd, struct logical_volume *
- 	else
- 		layer = NULL;
- 
--	return build_dm_uuid(cmd->mem, lv->lvid.s, layer);
-+	return build_dm_uuid(cmd->mem, lv, layer);
- }
- 
- int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso,
-diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
-index 6b5f8c2..c723a61 100644
---- a/lib/activate/dev_manager.c
-+++ b/lib/activate/dev_manager.c
-@@ -446,6 +446,12 @@ static int _device_is_usable(struct device *dev, int check_lv_names)
- 		    !dm_split_lvm_name(NULL, NULL, &vgname, &lvname, &layer))
- 			goto_out;
- 
-+		if (strlen(uuid) > 68) {
-+			log_debug_activation("%s: Reserved uuid %s on internal LV device %s/%s%s%s not usable.",
-+					     dev_name(dev), uuid, vgname, lvname, *layer ? "-" : "", layer);
-+			goto out;
-+		}
-+
- 		if (lvname && (is_reserved_lvname(lvname) || *layer)) {
- 			log_debug_activation("%s: Reserved internal LV device %s/%s%s%s not usable.",
- 					     dev_name(dev), vgname, lvname, *layer ? "-" : "", layer);
-@@ -505,7 +511,7 @@ int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv,
- 		return 0;
- 	}
- 
--	if (!(dlid = build_dm_uuid(mem, lv->lvid.s, layer))) {
-+	if (!(dlid = build_dm_uuid(mem, lv, layer))) {
- 		log_error("dlid build failed for %s", name);
- 		r = 0;
- 		goto out;
-@@ -528,7 +534,7 @@ static const struct dm_info *_cached_info(struct dm_pool *mem,
- 	const struct dm_tree_node *dnode;
- 	const struct dm_info *dinfo = NULL;
- 
--	if (!(dlid = build_dm_uuid(mem, lv->lvid.s, layer))) {
-+	if (!(dlid = build_dm_uuid(mem, lv, layer))) {
- 		log_error("Failed to build dlid for %s.", lv->name);
- 		return NULL;
- 	}
-@@ -641,7 +647,7 @@ int lv_has_target_type(struct dm_pool *mem, struct logical_volume *lv,
- 	char *type = NULL;
- 	char *params = NULL;
- 
--	if (!(dlid = build_dm_uuid(mem, lv->lvid.s, layer)))
-+	if (!(dlid = build_dm_uuid(mem, lv, layer)))
- 		return_0;
- 
- 	if (!(dmt = _setup_task(NULL, dlid, 0,
-@@ -872,7 +878,7 @@ int dev_manager_transient(struct dev_manager *dm, struct logical_volume *lv)
- 	const struct dm_list *segh = &lv->segments;
- 	struct lv_segment *seg = NULL;
- 
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer)))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
- 		return_0;
- 
- 	if (!(dmt = _setup_task(0, dlid, NULL, DM_DEVICE_STATUS, 0, 0)))
-@@ -1015,7 +1021,7 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
- 	if (!(name = dm_build_dm_name(dm->mem, snap_lv->vg->name, snap_lv->name, NULL)))
- 		return_0;
- 
--	if (!(dlid = build_dm_uuid(dm->mem, snap_lv->lvid.s, NULL)))
-+	if (!(dlid = build_dm_uuid(dm->mem, snap_lv, NULL)))
- 		return_0;
- 
- 	/*
-@@ -1047,7 +1053,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
- 	if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
- 		return_0;
- 
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer))) {
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, layer))) {
- 		log_error("dlid build failed for %s", lv->name);
- 		return 0;
- 	}
-@@ -1074,7 +1080,7 @@ int dev_manager_raid_status(struct dev_manager *dm,
- 	char *params = NULL;
- 	const char *layer = lv_layer(lv);
- 
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer)))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
- 		return_0;
- 
- 	log_debug_activation("Getting raid device status for %s.", lv->name);
-@@ -1138,7 +1144,7 @@ int dev_manager_raid_message(struct dev_manager *dm,
- 		return 0;
- 	}
- 
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer)))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
- 		return_0;
- 
- 	if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_TARGET_MSG, 0, 0)))
-@@ -1173,7 +1179,7 @@ int dev_manager_cache_status(struct dev_manager *dm,
- 	char *params = NULL;
- 	const char *layer = lv_layer(lv);
- 
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer)))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
- 		return_0;
- 
- 	log_debug_activation("Getting cache device status for %s.", lv->name);
-@@ -1282,7 +1288,7 @@ int dev_manager_thin_pool_status(struct dev_manager *dm,
- 	int r = 0;
- 
- 	/* Build dlid for the thin pool layer */
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, lv_layer(lv))))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
- 		return_0;
- 
- 	log_debug_activation("Getting thin pool device status for %s.", lv->name);
-@@ -1328,7 +1334,7 @@ int dev_manager_thin_pool_percent(struct dev_manager *dm,
- 				      lv_layer(lv))))
- 		return_0;
- 
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, lv_layer(lv))))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
- 		return_0;
- 
- 	log_debug_activation("Getting device status percentage for %s", name);
-@@ -1351,7 +1357,7 @@ int dev_manager_thin_percent(struct dev_manager *dm,
- 	if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
- 		return_0;
- 
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer)))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
- 		return_0;
- 
- 	log_debug_activation("Getting device status percentage for %s", name);
-@@ -1374,7 +1380,7 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
- 	int r = 0;
- 
- 	/* Build dlid for the thin layer */
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, lv_layer(lv))))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
- 		return_0;
- 
- 	log_debug_activation("Getting device id for %s.", dlid);
-@@ -1575,7 +1581,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
- 	if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
- 		return_0;
- 
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer)))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
- 		return_0;
- 
- 	log_debug_activation("Getting device info for %s [%s]", name, dlid);
-@@ -1648,7 +1654,7 @@ static int _add_partial_replicator_to_dtree(struct dev_manager *dm,
- 	if (!_add_dev_to_dtree(dm, dtree, rlv, NULL))
- 		return_0;
- 
--	if (!(uuid = build_dm_uuid(dm->mem, rlv->lvid.s, NULL)))
-+	if (!(uuid = build_dm_uuid(dm->mem, rlv, NULL)))
- 		return_0;
- 
- 	rep_node = dm_tree_find_node_by_uuid(dtree, uuid);
-@@ -1670,7 +1676,7 @@ static int _add_partial_replicator_to_dtree(struct dev_manager *dm,
- 				/* If replicator exists - try connect existing heads */
- 				if (rep_node) {
- 					uuid = build_dm_uuid(dm->mem,
--							     rdev->replicator_dev->lv->lvid.s,
-+							     rdev->replicator_dev->lv,
- 							     NULL);
- 					if (!uuid)
- 						return_0;
-@@ -1790,7 +1796,9 @@ static int _thin_pool_register_callback(struct dev_manager *dm,
- 	struct thin_cb_data *data;
- 
- 	/* Skip metadata testing for unused pool. */
--	if (!first_seg(lv)->transaction_id)
-+	if (!first_seg(lv)->transaction_id ||
-+	    ((first_seg(lv)->transaction_id == 1) &&
-+	     pool_has_message(first_seg(lv), NULL, 0)))
- 		return 1;
- 
- 	if (!(data = dm_pool_alloc(dm->mem, sizeof(*data)))) {
-@@ -1836,7 +1844,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
- #if 0
- 		/* ? Use origin_only to avoid 'deep' thin pool suspend ? */
- 		/* FIXME Implement dm_tree_node_skip_childrens optimisation */
--		if (!(uuid = build_dm_uuid(dm->mem, lv->lvid.s, lv_layer(lv))))
-+		if (!(uuid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
- 			return_0;
- 		if ((thin_node = dm_tree_find_node_by_uuid(dtree, uuid)))
- 			dm_tree_node_skip_childrens(thin_node, 1);
-@@ -1866,7 +1874,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
- 			/* Setup callback for non-activation partial tree */
- 			/* Activation gets own callback when needed */
- 			/* TODO: extend _cached_info() to return dnode */
--			if (!(uuid = build_dm_uuid(dm->mem, lv->lvid.s, lv_layer(lv))))
-+			if (!(uuid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
- 				return_0;
- 			if ((thin_node = dm_tree_find_node_by_uuid(dtree, uuid)) &&
- 			    !_thin_pool_register_callback(dm, thin_node, lv))
-@@ -1977,7 +1985,7 @@ static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
- 
- 	sprintf(errid, "missing_%d_%d", segno, s);
- 
--	if (!(dlid = build_dm_uuid(dm->mem, seg->lv->lvid.s, errid)))
-+	if (!(dlid = build_dm_uuid(dm->mem, seg->lv, errid)))
- 		return_NULL;
- 
- 	if (!(name = dm_build_dm_name(dm->mem, seg->lv->vg->name,
-@@ -2085,18 +2093,18 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
- 					return_0;
- 				continue;
- 			}
--			if (!(dlid = build_dm_uuid(dm->mem, seg_metalv(seg, s)->lvid.s, NULL)))
-+			if (!(dlid = build_dm_uuid(dm->mem, seg_metalv(seg, s), NULL)))
- 				return_0;
- 			if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_metale(seg, s)))
- 				return_0;
- 
--			if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, s)->lvid.s, NULL)))
-+			if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, s), NULL)))
- 				return_0;
- 			if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_le(seg, s)))
- 				return_0;
- 		} else if (seg_type(seg, s) == AREA_LV) {
- 
--			if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, s)->lvid.s, NULL)))
-+			if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, s), NULL)))
- 				return_0;
- 			if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_le(seg, s)))
- 				return_0;
-@@ -2125,7 +2133,7 @@ static int _add_layer_target_to_dtree(struct dev_manager *dm,
- {
- 	const char *layer_dlid;
- 
--	if (!(layer_dlid = build_dm_uuid(dm->mem, lv->lvid.s, lv_layer(lv))))
-+	if (!(layer_dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
- 		return_0;
- 
- 	/* Add linear mapping over layered LV */
-@@ -2144,7 +2152,7 @@ static int _add_origin_target_to_dtree(struct dev_manager *dm,
- {
- 	const char *real_dlid;
- 
--	if (!(real_dlid = build_dm_uuid(dm->mem, lv->lvid.s, "real")))
-+	if (!(real_dlid = build_dm_uuid(dm->mem, lv, "real")))
- 		return_0;
- 
- 	if (!dm_tree_node_add_snapshot_origin_target(dnode, lv->size, real_dlid))
-@@ -2165,13 +2173,13 @@ static int _add_snapshot_merge_target_to_dtree(struct dev_manager *dm,
- 		return 0;
- 	}
- 
--	if (!(origin_dlid = build_dm_uuid(dm->mem, lv->lvid.s, "real")))
-+	if (!(origin_dlid = build_dm_uuid(dm->mem, lv, "real")))
- 		return_0;
- 
--	if (!(cow_dlid = build_dm_uuid(dm->mem, merging_snap_seg->cow->lvid.s, "cow")))
-+	if (!(cow_dlid = build_dm_uuid(dm->mem, merging_snap_seg->cow, "cow")))
- 		return_0;
- 
--	if (!(merge_dlid = build_dm_uuid(dm->mem, merging_snap_seg->cow->lvid.s, NULL)))
-+	if (!(merge_dlid = build_dm_uuid(dm->mem, merging_snap_seg->cow, NULL)))
- 		return_0;
- 
- 	if (!dm_tree_node_add_snapshot_merge_target(dnode, lv->size, origin_dlid,
-@@ -2197,10 +2205,10 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
- 		return 0;
- 	}
- 
--	if (!(origin_dlid = build_dm_uuid(dm->mem, snap_seg->origin->lvid.s, "real")))
-+	if (!(origin_dlid = build_dm_uuid(dm->mem, snap_seg->origin, "real")))
- 		return_0;
- 
--	if (!(cow_dlid = build_dm_uuid(dm->mem, snap_seg->cow->lvid.s, "cow")))
-+	if (!(cow_dlid = build_dm_uuid(dm->mem, snap_seg->cow, "cow")))
- 		return_0;
- 
- 	size = (uint64_t) snap_seg->len * snap_seg->origin->vg->extent_size;
-@@ -2514,7 +2522,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
- 	if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
- 		return_0;
- 
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer)))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
- 		return_0;
- 
- 	/* We've already processed this node if it already has a context ptr */
-@@ -2774,7 +2782,7 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv,
- 	/* Restore fs cookie */
- 	dm_tree_set_cookie(root, fs_get_cookie());
- 
--	if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, laopts->origin_only ? lv_layer(lv) : NULL)))
-+	if (!(dlid = build_dm_uuid(dm->mem, lv, laopts->origin_only ? lv_layer(lv) : NULL)))
- 		goto_out;
- 
- 	/* Only process nodes with uuid of "LVM-" plus VG id. */
-diff --git a/lib/cache_segtype/cache.c b/lib/cache_segtype/cache.c
-index 57c7a5c..df521c4 100644
---- a/lib/cache_segtype/cache.c
-+++ b/lib/cache_segtype/cache.c
-@@ -360,13 +360,13 @@ static int _cache_add_target_line(struct dev_manager *dm,
- 	struct lv_segment *cache_pool_seg = first_seg(seg->pool_lv);
- 	char *metadata_uuid, *data_uuid, *origin_uuid;
- 
--	if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv->lvid.s, NULL)))
-+	if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv, NULL)))
- 		return_0;
- 
--	if (!(data_uuid = build_dm_uuid(mem, seg_lv(cache_pool_seg, 0)->lvid.s, NULL)))
-+	if (!(data_uuid = build_dm_uuid(mem, seg_lv(cache_pool_seg, 0), NULL)))
- 		return_0;
- 
--	if (!(origin_uuid = build_dm_uuid(mem, seg_lv(seg, 0)->lvid.s, NULL)))
-+	if (!(origin_uuid = build_dm_uuid(mem, seg_lv(seg, 0), NULL)))
- 		return_0;
- 
- 	if (!dm_tree_node_add_cache_target(node, len,
-diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
-index 57ce2d9..abbcbf8 100644
---- a/lib/metadata/lv_manip.c
-+++ b/lib/metadata/lv_manip.c
-@@ -6291,19 +6291,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 	if (lv_activation_skip(lv, lp->activate, lp->activation_skip & ACTIVATION_SKIP_IGNORE))
- 		lp->activate = CHANGE_AN;
- 
--	/*
--	 * For thin pools - deactivate when inactive pool is requested or
--	 * for cluster give-up local lock and take proper exlusive lock
--	 */
--	if (lv_is_thin_pool(lv) &&
--	    (!is_change_activating(lp->activate) ||
--	     vg_is_clustered(lv->vg)) &&
--	    /* Deactivates cleared metadata LV */
--	    !deactivate_lv(lv->vg->cmd, lv)) {
--		stack;
--		goto deactivate_failed;
--	}
--
- 	/* store vg on disk(s) */
- 	if (!vg_write(vg) || !vg_commit(vg))
- 		return_NULL;
-@@ -6322,50 +6309,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 	if (lp->temporary)
- 		lv->status |= LV_TEMPORARY;
- 
--	if (lv_is_cache_type(lv)) {
--		if (!lv_is_active(lv)) {
--			if (!activate_lv_excl(cmd, lv)) {
--				log_error("Failed to activate pool %s.",
--					  lv->name);
--				goto deactivate_and_revert_new_lv;
--			}
--		} else {
--			if (!suspend_lv(cmd, lv)) {
--				log_error("Failed to suspend pool %s.",
--					  lv->name);
--				goto deactivate_and_revert_new_lv;
--			}
--			if (!resume_lv(cmd, lv)) {
--				log_error("Failed to resume pool %s.", lv->name);
--				goto deactivate_and_revert_new_lv;
--			}
--		}
--	} else if (lv_is_thin_pool(lv)) {
--		if (is_change_activating(lp->activate)) {
--			if (vg_is_clustered(lv->vg)) {
--				if (!activate_lv_excl(cmd, lv)) {
--					log_error("Failed to activate pool %s.", lv->name);
--					goto deactivate_and_revert_new_lv;
--				}
--			} else {
--				/*
--				 * Suspend cleared plain metadata LV
--				 * but now already commited as pool LV
--				 * and resume it as a pool LV.
--				 *
--				 * This trick avoids collision with udev watch rule.
--				 */
--				if (!suspend_lv(cmd, lv)) {
--					log_error("Failed to suspend pool %s.", lv->name);
--					goto deactivate_and_revert_new_lv;
--				}
--				if (!resume_lv(cmd, lv)) {
--					log_error("Failed to resume pool %s.", lv->name);
--					goto deactivate_and_revert_new_lv;
--				}
--			}
--		}
--	} else if (lv_is_thin_volume(lv)) {
-+	if (lv_is_thin_volume(lv)) {
- 		/* For snapshot, suspend active thin origin first */
- 		if (org && lv_is_active(org) && lv_is_thin_volume(org)) {
- 			if (!suspend_lv_origin(cmd, org)) {
-@@ -6403,7 +6347,9 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 		}
- 	} else if (!lv_active_change(cmd, lv, lp->activate)) {
- 		log_error("Failed to activate new LV.");
--		if (lp->zero || lp->wipe_signatures)
-+		if (lp->zero || lp->wipe_signatures ||
-+		    lv_is_thin_pool(lv) ||
-+		    lv_is_cache_type(lv))
- 			goto deactivate_and_revert_new_lv;
- 		return NULL;
- 	}
-@@ -6497,7 +6443,6 @@ out:
- 
- deactivate_and_revert_new_lv:
- 	if (!deactivate_lv(cmd, lv)) {
--deactivate_failed:
- 		log_error("Unable to deactivate failed new LV \"%s/%s\". "
- 			  "Manual intervention required.", lv->vg->name, lv->name);
- 		return NULL;
-diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
-index 0c7bf96..f414f3f 100644
---- a/lib/metadata/pool_manip.c
-+++ b/lib/metadata/pool_manip.c
-@@ -267,6 +267,9 @@ int create_pool(struct logical_volume *pool_lv,
- 			goto bad;
- 		}
- 		pool_lv->status &= ~LV_TEMPORARY;
-+		/* Deactivates cleared metadata LV */
-+		if (!deactivate_lv_local(pool_lv->vg->cmd, pool_lv))
-+			goto_bad;
- 	}
- 
- 	if (dm_snprintf(name, sizeof(name), "%s_%s", pool_lv->name,
-diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
-index b28f5a0..b94a4a8 100644
---- a/lib/metadata/thin_manip.c
-+++ b/lib/metadata/thin_manip.c
-@@ -160,7 +160,7 @@ int pool_has_message(const struct lv_segment *seg,
- 	}
- 
- 	if (!lv && !device_id)
--		return dm_list_empty(&seg->thin_messages);
-+		return !dm_list_empty(&seg->thin_messages);
- 
- 	dm_list_iterate_items(tmsg, &seg->thin_messages) {
- 		switch (tmsg->type) {
-diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c
-index 5088173..e35a372 100644
---- a/lib/mirror/mirrored.c
-+++ b/lib/mirror/mirrored.c
-@@ -356,14 +356,14 @@ static int _add_log(struct dm_pool *mem, struct lv_segment *seg,
- 
- 	if (seg->log_lv) {
- 		/* If disk log, use its UUID */
--		if (!(log_dlid = build_dm_uuid(mem, seg->log_lv->lvid.s, NULL))) {
-+		if (!(log_dlid = build_dm_uuid(mem, seg->log_lv, NULL))) {
- 			log_error("Failed to build uuid for log LV %s.",
- 				  seg->log_lv->name);
- 			return 0;
- 		}
- 	} else {
- 		/* If core log, use mirror's UUID and set DM_CORELOG flag */
--		if (!(log_dlid = build_dm_uuid(mem, seg->lv->lvid.s, NULL))) {
-+		if (!(log_dlid = build_dm_uuid(mem, seg->lv, NULL))) {
- 			log_error("Failed to build uuid for mirror LV %s.",
- 				  seg->lv->name);
- 			return 0;
-diff --git a/lib/misc/lvm-string.c b/lib/misc/lvm-string.c
-index 380fe81..b96b5cc 100644
---- a/lib/misc/lvm-string.c
-+++ b/lib/misc/lvm-string.c
-@@ -15,6 +15,7 @@
- 
- #include "lib.h"
- #include "lvm-string.h"
-+#include "metadata-exported.h"
- 
- #include <ctype.h>
- 
-@@ -160,8 +161,13 @@ int is_reserved_lvname(const char *name)
- 	return rc;
- }
- 
--char *build_dm_uuid(struct dm_pool *mem, const char *lvid,
-+char *build_dm_uuid(struct dm_pool *mem, const struct logical_volume *lv,
- 		    const char *layer)
- {
-+	const char *lvid = lv->lvid.s;
-+
-+	if (!layer && lv_is_thin_pool(lv))
-+		layer = "pool";
-+
- 	return dm_build_dm_uuid(mem, UUID_PREFIX, lvid, layer);
- }
-diff --git a/lib/misc/lvm-string.h b/lib/misc/lvm-string.h
-index 13aacf8..82ebb12 100644
---- a/lib/misc/lvm-string.h
-+++ b/lib/misc/lvm-string.h
-@@ -23,6 +23,7 @@
- #define UUID_PREFIX "LVM-"
- 
- struct pool;
-+struct logical_volume;
- 
- typedef enum name_error { NAME_VALID = 0, NAME_INVALID_EMPTY = -1,
- 					NAME_INVALID_HYPEN = -2, NAME_INVALID_DOTS = -3,
-@@ -32,7 +33,7 @@ typedef enum name_error { NAME_VALID = 0, NAME_INVALID_EMPTY = -1,
- int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
-   __attribute__ ((format(printf, 3, 4)));
- 
--char *build_dm_uuid(struct dm_pool *mem, const char *lvid,
-+char *build_dm_uuid(struct dm_pool *mem, const struct logical_volume *lvid,
- 		    const char *layer);
- 
- int validate_name(const char *n);
-diff --git a/lib/thin/thin.c b/lib/thin/thin.c
-index 7c989f8..494fa92 100644
---- a/lib/thin/thin.c
-+++ b/lib/thin/thin.c
-@@ -277,13 +277,13 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
- 		return 0;
- 	}
- 
--	if (!(metadata_dlid = build_dm_uuid(mem, seg->metadata_lv->lvid.s, NULL))) {
-+	if (!(metadata_dlid = build_dm_uuid(mem, seg->metadata_lv, NULL))) {
- 		log_error("Failed to build uuid for metadata LV %s.",
- 			  seg->metadata_lv->name);
- 		return 0;
- 	}
- 
--	if (!(pool_dlid = build_dm_uuid(mem, seg_lv(seg, 0)->lvid.s, NULL))) {
-+	if (!(pool_dlid = build_dm_uuid(mem, seg_lv(seg, 0), NULL))) {
- 		log_error("Failed to build uuid for pool LV %s.",
- 			  seg_lv(seg, 0)->name);
- 		return 0;
-@@ -535,7 +535,7 @@ static int _thin_add_target_line(struct dev_manager *dm,
- 			  seg->lv->name);
- 		return 0;
- 	}
--	if (!(pool_dlid = build_dm_uuid(mem, seg->pool_lv->lvid.s, lv_layer(seg->pool_lv)))) {
-+	if (!(pool_dlid = build_dm_uuid(mem, seg->pool_lv, lv_layer(seg->pool_lv)))) {
- 		log_error("Failed to build uuid for pool LV %s.",
- 			  seg->pool_lv->name);
- 		return 0;
-@@ -573,7 +573,7 @@ static int _thin_add_target_line(struct dev_manager *dm,
- 				return 0;
- 			}
- 		}
--		if (!(external_dlid = build_dm_uuid(mem, seg->external_lv->lvid.s,
-+		if (!(external_dlid = build_dm_uuid(mem, seg->external_lv,
- 						    lv_layer(seg->external_lv)))) {
- 			log_error("Failed to build uuid for external origin LV %s.",
- 				  seg->external_lv->name);
-diff --git a/test/shell/lvcreate-thin.sh b/test/shell/lvcreate-thin.sh
-index a2811d2..ab27dfb 100644
---- a/test/shell/lvcreate-thin.sh
-+++ b/test/shell/lvcreate-thin.sh
-@@ -173,7 +173,9 @@ not lvcreate --chunksize 32 -l1 -T $vg/pool1
- # Too large chunk size (max is 1GB)
- not lvcreate -L4M --chunksize 2G -T $vg/pool1
- 
--lvcreate -L4M -V2G --name lv1 -T $vg/pool1
-+# Test creation of inactive pool
-+lvcreate -an -L4M -T $vg/pool1
-+lvcreate -V2G --name lv1 -T $vg/pool1
- # Origin name is not accepted
- not lvcreate -s $vg/lv1 -L4M -V2G --name $vg/lv4
- 
-diff --git a/test/shell/pvremove-thin.sh b/test/shell/pvremove-thin.sh
-new file mode 100644
-index 0000000..03e6ca3
---- /dev/null
-+++ b/test/shell/pvremove-thin.sh
-@@ -0,0 +1,28 @@
-+#!/bin/sh
-+# Copyright (C) 2014 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+# Checks we are not reading our own devices
-+# https://bugzilla.redhat.com/show_bug.cgi?id=1064374
-+
-+. lib/test
-+
-+aux prepare_vg
-+
-+aux target_at_least dm-thin-pool 1 8 0 || skip
-+
-+aux extend_filter_LVMTEST
-+
-+lvcreate -L10 -V10 -n $lv1 -T $vg/pool1
-+
-+pvcreate "$DM_DEV_DIR/$vg/$lv1"
-+pvremove "$DM_DEV_DIR/$vg/$lv1"
-+
-+vgremove -ff $vg
diff --git a/SOURCES/lvm2-2_02_116-fix-raid-image-splitting.patch b/SOURCES/lvm2-2_02_116-fix-raid-image-splitting.patch
new file mode 100644
index 0000000..e94b45d
--- /dev/null
+++ b/SOURCES/lvm2-2_02_116-fix-raid-image-splitting.patch
@@ -0,0 +1,201 @@
+ WHATS_NEW                           |  6 ++++++
+ lib/activate/activate.c             | 21 +++++++++++++++++++++
+ lib/activate/dev_manager.c          |  2 +-
+ lib/metadata/lv.c                   |  4 ++++
+ lib/metadata/raid_manip.c           | 30 ++++++++++--------------------
+ test/shell/lvconvert-raid.sh        |  6 ++++++
+ test/shell/lvconvert-repair-thin.sh |  9 ++++++++-
+ tools/lvconvert.c                   |  1 +
+ 8 files changed, 57 insertions(+), 22 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 75c4569..ef5cc83 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,3 +1,9 @@
++Version 2.02.116 - 
++====================================
++  Preserve chunk size with repair and metadata swap of a thin pool.
++  Fix raid --splitmirror 1 functionality (2.02.112).
++  Fix tree preload to handle splitting raid images.
++
+ Version 2.02.115 - 21st January 2015
+ ====================================
+   Report segment types without monitoring support as undefined.
+diff --git a/lib/activate/activate.c b/lib/activate/activate.c
+index 424786c..00d3a10 100644
+--- a/lib/activate/activate.c
++++ b/lib/activate/activate.c
+@@ -1760,6 +1760,22 @@ static int _preload_detached_lv(struct logical_volume *lv, void *data)
+ 	struct detached_lv_data *detached = data;
+ 	struct lv_list *lvl_pre;
+ 
++        /* Check and preload removed raid image leg */
++	if (lv_is_raid_image(lv)) {
++		if ((lvl_pre = find_lv_in_vg_by_lvid(detached->lv_pre->vg, &lv->lvid)) &&
++		    !lv_is_raid_image(lvl_pre->lv) &&
++		    !_lv_preload(lvl_pre->lv, detached->laopts, detached->flush_required))
++			return_0;
++	}
++
++        /* Check and preload removed of raid metadata */
++	if (lv_is_raid_metadata(lv)) {
++		if ((lvl_pre = find_lv_in_vg_by_lvid(detached->lv_pre->vg, &lv->lvid)) &&
++		    !lv_is_raid_metadata(lvl_pre->lv) &&
++		    !_lv_preload(lvl_pre->lv, detached->laopts, detached->flush_required))
++			return_0;
++	}
++
+ 	if ((lvl_pre = find_lv_in_vg(detached->lv_pre->vg, lv->name))) {
+ 		if (lv_is_visible(lvl_pre->lv) && lv_is_active(lv) &&
+ 		    (!lv_is_cow(lv) || !lv_is_cow(lvl_pre->lv)) &&
+@@ -1863,6 +1879,11 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
+ 		if (!for_each_sub_lv((struct logical_volume *)ondisk_lv, &_preload_detached_lv, &detached))
+ 			goto_out;
+ 
++		/* ATM cache/thin pool is not scanned in  'for_each_sub_lv()', TODO explore better way */
++		if (lv_is_cache(ondisk_lv) &&
++		    !for_each_sub_lv(first_seg(ondisk_lv)->pool_lv, &_preload_detached_lv, &detached))
++			goto_out;
++
+ 		/*
+ 		 * Preload any snapshots that are being removed.
+ 		 */
+diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
+index 015af5b..dcb2c5d 100644
+--- a/lib/activate/dev_manager.c
++++ b/lib/activate/dev_manager.c
+@@ -2295,7 +2295,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
+ 			 * is used in the CTR table.
+ 			 */
+ 			if ((seg_type(seg, s) == AREA_UNASSIGNED) ||
+-			    ((seg_lv(seg, s)->status & VISIBLE_LV) &&
++			    (lv_is_visible(seg_lv(seg, s)) &&
+ 			     !(seg_lv(seg, s)->status & LVM_WRITE))) {
+ 				/* One each for metadata area and data area */
+ 				if (!dm_tree_node_add_null_area(node, 0) ||
+diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
+index 683ec47..9052e63 100644
+--- a/lib/metadata/lv.c
++++ b/lib/metadata/lv.c
+@@ -1018,6 +1018,10 @@ const struct logical_volume *lv_lock_holder(const struct logical_volume *lv)
+ 				return sl->seg->lv;
+ 			}
+ 
++	/* RAID changes visibility of splitted LVs but references them still as leg/meta */
++	if ((lv_is_raid_image(lv) || lv_is_raid_metadata(lv)) && lv_is_visible(lv))
++		return lv;
++
+ 	/* For other types, by default look for the first user */
+ 	dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
+ 		/* FIXME: complete this exception list */
+diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
+index d502379..22f71c7 100644
+--- a/lib/metadata/raid_manip.c
++++ b/lib/metadata/raid_manip.c
+@@ -1149,12 +1149,6 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
+ 		return 0;
+ 	}
+ 
+-	if (!resume_lv(lv->vg->cmd, lv_lock_holder(lv))) {
+-		log_error("Failed to resume %s/%s after committing changes",
+-			  lv->vg->name, lv->name);
+-		return 0;
+-	}
+-
+ 	/*
+ 	 * First activate the newly split LV and LVs on the removal list.
+ 	 * This is necessary so that there are no name collisions due to
+@@ -1164,26 +1158,22 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
+ 	if (!activate_lv_excl_local(cmd, lvl->lv))
+ 		return_0;
+ 
++	dm_list_iterate_items(lvl, &removal_list)
++		if (!activate_lv_excl_local(cmd, lvl->lv))
++			return_0;
++
++	if (!resume_lv(cmd, lv_lock_holder(lv))) {
++		log_error("Failed to resume %s/%s after committing changes",
++			  lv->vg->name, lv->name);
++		return 0;
++	}
++
+ 	/*
+ 	 * Since newly split LV is typically already active - we need to call
+ 	 * suspend() and resume() to also rename it.
+ 	 *
+ 	 * TODO: activate should recognize it and avoid these 2 calls
+ 	 */
+-	if (!suspend_lv(cmd, lvl->lv)) {
+-		log_error("Failed to suspend %s.", lvl->lv->name);
+-		return 0;
+-	}
+-
+-	if (!resume_lv(cmd, lvl->lv)) {
+-		log_error("Failed to reactivate %s.", lvl->lv->name);
+-		return 0;
+-	}
+-
+-	dm_list_iterate_items(lvl, &removal_list)
+-		if (!activate_lv_excl_local(cmd, lvl->lv))
+-			return_0;
+-
+ 
+ 	/*
+ 	 * Eliminate the residual LVs
+diff --git a/test/shell/lvconvert-raid.sh b/test/shell/lvconvert-raid.sh
+index 8621311..12e0420 100644
+--- a/test/shell/lvconvert-raid.sh
++++ b/test/shell/lvconvert-raid.sh
+@@ -121,6 +121,12 @@ check active $vg $lv2
+ # FIXME: ensure no residual devices
+ lvremove -ff $vg
+ 
++# 4-way
++lvcreate --type raid1 -m 4 -l 2 -n $lv1 $vg
++aux wait_for_sync $vg $lv1
++lvconvert --yes --splitmirrors 1 --name $lv2 $vg/$lv1 "$dev2"
++lvremove -ff $vg
++
+ ###########################################
+ # RAID1 split + trackchanges / merge
+ ###########################################
+diff --git a/test/shell/lvconvert-repair-thin.sh b/test/shell/lvconvert-repair-thin.sh
+index 0e9534b..73f061c 100644
+--- a/test/shell/lvconvert-repair-thin.sh
++++ b/test/shell/lvconvert-repair-thin.sh
+@@ -24,7 +24,9 @@ aux have_thin 1 0 0 || skip
+ aux prepare_vg 4
+ 
+ # Create LV
+-lvcreate -T -L20 -V10 -n $lv1 $vg/pool  "$dev1" "$dev2"
++# TODO: investigate problem with --zero n and my repairable damage trick
++#lvcreate -T -L20 -V10 -n $lv1 $vg/pool --discards ignore --zero n --chunksize 128 "$dev1" "$dev2"
++lvcreate -T -L20 -V10 -n $lv1 $vg/pool --chunksize 128 --discards ignore "$dev1" "$dev2"
+ lvcreate -T -V10 -n $lv2 $vg/pool
+ 
+ mkfs.ext2 "$DM_DEV_DIR/$vg/$lv1"
+@@ -71,6 +73,11 @@ lvchange -an $vg
+ # Swap repaired metadata back
+ lvconvert -y -f --poolmetadata $vg/fixed --thinpool $vg/pool
+ 
++# Check pool still preserves its original settings
++check lv_field $vg/pool chunksize "128.00k"
++check lv_field $vg/pool discards "ignore"
++check lv_field $vg/pool zero "zero"
++
+ # Activate pool - this should now work
+ vgchange -ay $vg
+ 
+diff --git a/tools/lvconvert.c b/tools/lvconvert.c
+index c7acd5d..20f017a 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -2956,6 +2956,7 @@ static int _lvconvert_pool(struct cmd_context *cmd,
+ 			return 0;
+ 		}
+ 
++		lp->passed_args |= PASS_ARG_CHUNK_SIZE | PASS_ARG_DISCARDS | PASS_ARG_ZERO;
+ 		seg = first_seg(pool_lv);
+ 
+ 		/* Normally do NOT change chunk size when swapping */
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 b1cb821..67b7081 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 ++--
- lib/device/dev-type.c |    3 +--
+ configure             | 20 ++++++++++----------
+ configure.in          |  4 ++--
+ lib/device/dev-type.c |  3 +--
  3 files changed, 13 insertions(+), 14 deletions(-)
 
 diff --git a/configure b/configure
-index a156460..c96911c 100755
+index df902c3..d8319e0 100755
 --- a/configure
 +++ b/configure
-@@ -9484,12 +9484,12 @@ if test -n "$BLKID_CFLAGS"; then
+@@ -10524,12 +10524,12 @@ if test -n "$BLKID_CFLAGS"; then
      pkg_cv_BLKID_CFLAGS="$BLKID_CFLAGS"
   elif test -n "$PKG_CONFIG"; then
      if test -n "$PKG_CONFIG" && \
@@ -20,10 +20,10 @@ index a156460..c96911c 100755
    test $ac_status = 0; }; then
 -  pkg_cv_BLKID_CFLAGS=`$PKG_CONFIG --cflags "blkid >= 2.24" 2>/dev/null`
 +  pkg_cv_BLKID_CFLAGS=`$PKG_CONFIG --cflags "blkid >= 2.23" 2>/dev/null`
+ 		      test "x$?" != "x0" && pkg_failed=yes
  else
    pkg_failed=yes
- fi
-@@ -9500,12 +9500,12 @@ if test -n "$BLKID_LIBS"; then
+@@ -10541,12 +10541,12 @@ if test -n "$BLKID_LIBS"; then
      pkg_cv_BLKID_LIBS="$BLKID_LIBS"
   elif test -n "$PKG_CONFIG"; then
      if test -n "$PKG_CONFIG" && \
@@ -36,65 +36,63 @@ index a156460..c96911c 100755
    test $ac_status = 0; }; then
 -  pkg_cv_BLKID_LIBS=`$PKG_CONFIG --libs "blkid >= 2.24" 2>/dev/null`
 +  pkg_cv_BLKID_LIBS=`$PKG_CONFIG --libs "blkid >= 2.23" 2>/dev/null`
+ 		      test "x$?" != "x0" && pkg_failed=yes
  else
    pkg_failed=yes
- fi
-@@ -9525,9 +9525,9 @@ else
+@@ -10567,9 +10567,9 @@ else
          _pkg_short_errors_supported=no
  fi
          if test $_pkg_short_errors_supported = yes; then
--	        BLKID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "blkid >= 2.24" 2>&1`
-+	        BLKID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "blkid >= 2.23" 2>&1`
+-	        BLKID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "blkid >= 2.24" 2>&1`
++	        BLKID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "blkid >= 2.23" 2>&1`
          else
--	        BLKID_PKG_ERRORS=`$PKG_CONFIG --print-errors "blkid >= 2.24" 2>&1`
-+	        BLKID_PKG_ERRORS=`$PKG_CONFIG --print-errors "blkid >= 2.23" 2>&1`
+-	        BLKID_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "blkid >= 2.24" 2>&1`
++	        BLKID_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "blkid >= 2.23" 2>&1`
          fi
  	# Put the nasty error message in config.log where it belongs
  	echo "$BLKID_PKG_ERRORS" >&5
-@@ -9535,7 +9535,7 @@ fi
- 	if test x$BLKID_WIPING = xmaybe; then
- 					BLKID_WIPING=no
- 				 else
--					as_fn_error $? "bailing out... blkid library >= 2.24 is required" "$LINENO" 5
-+					as_fn_error $? "bailing out... blkid library >= 2.23 is required" "$LINENO" 5
- 				 fi
- 
+@@ -10577,7 +10577,7 @@ fi
+ 	if test "$BLKID_WIPING" = maybe; then
+ 				BLKID_WIPING=no
+ 			   else
+-			        as_fn_error $? "bailing out... blkid library >= 2.24 is required" "$LINENO" 5
++			        as_fn_error $? "bailing out... blkid library >= 2.23 is required" "$LINENO" 5
+ 			   fi
  elif test $pkg_failed = untried; then
-@@ -9544,7 +9544,7 @@ $as_echo "no" >&6; }
- 	if test x$BLKID_WIPING = xmaybe; then
- 					BLKID_WIPING=no
- 				 else
--					as_fn_error $? "bailing out... blkid library >= 2.24 is required" "$LINENO" 5
-+					as_fn_error $? "bailing out... blkid library >= 2.23 is required" "$LINENO" 5
- 				 fi
- 
+      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+@@ -10585,7 +10585,7 @@ $as_echo "no" >&6; }
+ 	if test "$BLKID_WIPING" = maybe; then
+ 				BLKID_WIPING=no
+ 			   else
+-			        as_fn_error $? "bailing out... blkid library >= 2.24 is required" "$LINENO" 5
++			        as_fn_error $? "bailing out... blkid library >= 2.23 is required" "$LINENO" 5
+ 			   fi
  else
+ 	BLKID_CFLAGS=$pkg_cv_BLKID_CFLAGS
 diff --git a/configure.in b/configure.in
-index 3e0e508..cff7e45 100644
+index 5b22b93..2c3fcba 100644
 --- a/configure.in
 +++ b/configure.in
-@@ -981,14 +981,14 @@ if test x$BLKID_WIPING != xno; then
- 	if test x$PKGCONFIG_INIT != x1; then
- 		pkg_config_init
- 	fi
+@@ -1077,12 +1077,12 @@ AC_MSG_RESULT($BLKID_WIPING)
+ 
+ if test "$BLKID_WIPING" != no; then
+ 	pkg_config_init
 -	PKG_CHECK_MODULES(BLKID, blkid >= 2.24,
 +	PKG_CHECK_MODULES(BLKID, blkid >= 2.23,
- 				[if test x$BLKID_WIPING = xmaybe; then
- 					BLKID_WIPING=yes
- 				 fi],
- 				[if test x$BLKID_WIPING = xmaybe; then
- 					BLKID_WIPING=no
- 				 else
--					AC_MSG_ERROR([bailing out... blkid library >= 2.24 is required])
-+					AC_MSG_ERROR([bailing out... blkid library >= 2.23 is required])
- 				 fi
- 				])
- 	if test x$BLKID_WIPING = xyes; then
+ 			  [test "$BLKID_WIPING" = maybe && BLKID_WIPING=yes],
+ 			  [if test "$BLKID_WIPING" = maybe; then
+ 				BLKID_WIPING=no
+ 			   else
+-			        AC_MSG_ERROR([bailing out... blkid library >= 2.24 is required])
++			        AC_MSG_ERROR([bailing out... blkid library >= 2.23 is required])
+ 			   fi])
+ 	if test "$BLKID_WIPING" = yes; then
+ 		BLKID_PC="blkid"
 diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
-index 78b093c..02bc99f 100644
+index 001248d..03752a5 100644
 --- a/lib/device/dev-type.c
 +++ b/lib/device/dev-type.c
-@@ -521,8 +521,7 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
+@@ -548,8 +548,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-enable-lvmetad-by-default.patch b/SOURCES/lvm2-enable-lvmetad-by-default.patch
index 26b8224..7f16b92 100644
--- a/SOURCES/lvm2-enable-lvmetad-by-default.patch
+++ b/SOURCES/lvm2-enable-lvmetad-by-default.patch
@@ -3,28 +3,28 @@
  2 files changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/conf/example.conf.in b/conf/example.conf.in
-index 10f12bd..03bee13 100644
+index d1a1397..812b747 100644
 --- a/conf/example.conf.in
 +++ b/conf/example.conf.in
-@@ -594,7 +594,7 @@ global {
-     # supported in clustered environment. If use_lvmetad=1 and locking_type=3
+@@ -730,7 +730,7 @@ global {
      # is set at the same time, LVM always issues a warning message about this
-     # and then it automatically disables lvmetad use.
+     # and then it automatically disables use_lvmetad.
+ 
 -    use_lvmetad = 0
 +    use_lvmetad = 1
  
      # Full path of the utility called to check that a thin metadata device
      # is in a state that allows it to be used.
 diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
-index c935920..a9f35e6 100644
+index e944b81..7b5beff 100644
 --- a/lib/config/config_settings.h
 +++ b/lib/config/config_settings.h
-@@ -158,7 +158,7 @@ cfg(global_metadata_read_only_CFG, "metadata_read_only", global_CFG_SECTION, 0,
- cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_MIRROR_SEGTYPE, vsn(2, 2, 87), NULL)
+@@ -177,7 +177,7 @@ cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECT
  cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_RAID10_SEGTYPE, vsn(2, 2, 99), NULL)
- cfg(global_lvdisplay_shows_full_device_path_CFG, "lvdisplay_shows_full_device_path", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_LVDISPLAY_SHOWS_FULL_DEVICE_PATH, vsn(2, 2, 89), NULL)
+ cfg(global_sparse_segtype_default_CFG, "sparse_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_SPARSE_SEGTYPE, vsn(2, 2, 112), NULL)
+ cfg(global_lvdisplay_shows_full_device_path_CFG, "lvdisplay_shows_full_device_path", global_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_LVDISPLAY_SHOWS_FULL_DEVICE_PATH, vsn(2, 2, 89), NULL)
 -cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), NULL)
 +cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 93), NULL)
  cfg(global_thin_check_executable_CFG, "thin_check_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, THIN_CHECK_CMD, vsn(2, 2, 94), NULL)
  cfg_array(global_thin_check_options_CFG, "thin_check_options", global_CFG_SECTION, 0, CFG_TYPE_STRING, "#S" DEFAULT_THIN_CHECK_OPTIONS, vsn(2, 2, 96), NULL)
- cfg_array(global_thin_disabled_features_CFG, "thin_disabled_features", global_CFG_SECTION, 0, CFG_TYPE_STRING, "#S", vsn(2, 2, 99), NULL)
+ cfg_array(global_thin_disabled_features_CFG, "thin_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, NULL, vsn(2, 2, 99), NULL)
diff --git a/SOURCES/lvm2-remove-mpath-device-handling-from-udev-rules.patch b/SOURCES/lvm2-remove-mpath-device-handling-from-udev-rules.patch
new file mode 100644
index 0000000..168603b
--- /dev/null
+++ b/SOURCES/lvm2-remove-mpath-device-handling-from-udev-rules.patch
@@ -0,0 +1,18 @@
+ udev/10-dm.rules.in | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/udev/10-dm.rules.in b/udev/10-dm.rules.in
+index 2755530..8d7a8ca 100644
+--- a/udev/10-dm.rules.in
++++ b/udev/10-dm.rules.in
+@@ -120,10 +120,6 @@ ENV{DM_UDEV_RULES_VSN}="2"
+ 
+ ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="(DM_DIR)/$env{DM_NAME}"
+ 
+-# We have to ignore further rule application for inappropriate events
+-# and devices. But still send the notification if cookie exists.
+-ENV{DM_UUID}=="mpath-?*", ENV{DM_ACTION}=="PATH_FAILED", GOTO="dm_disable"
+-
+ # Avoid processing and scanning a DM device in the other (foreign)
+ # rules if it is in suspended state. However, we still keep 'disk'
+ # and 'DM subsystem' related rules enabled in this case.
diff --git a/SOURCES/lvm2-rhel7.patch b/SOURCES/lvm2-rhel7.patch
index 862e4aa..80ed52d 100644
--- a/SOURCES/lvm2-rhel7.patch
+++ b/SOURCES/lvm2-rhel7.patch
@@ -7,12 +7,12 @@ index dd4e60e..39d6c15 100644
 --- a/VERSION
 +++ b/VERSION
 @@ -1 +1 @@
--2.02.105(2) (2014-01-20)
-+2.02.105(2)-RHEL7 (2014-03-26)
+-2.02.115(2) (2015-01-21)
++2.02.115(2)-RHEL7 (2015-01-28)
 diff --git a/VERSION_DM b/VERSION_DM
 index d53f47a..005fbd4 100644
 --- a/VERSION_DM
 +++ b/VERSION_DM
 @@ -1 +1 @@
--1.02.84 (2014-01-20)
-+1.02.84-RHEL7 (2014-03-26)
+-1.02.93 (2015-01-21)
++1.02.93-RHEL7 (2015-01-28)
diff --git a/SOURCES/lvm2-set-default-preferred_names.patch b/SOURCES/lvm2-set-default-preferred_names.patch
index 3fe0e5b..801177f 100644
--- a/SOURCES/lvm2-set-default-preferred_names.patch
+++ b/SOURCES/lvm2-set-default-preferred_names.patch
@@ -1,20 +1,11 @@
- conf/example.conf.in | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/conf/example.conf.in b/conf/example.conf.in
-index 2032a81..0bd72f1 100644
---- a/conf/example.conf.in
-+++ b/conf/example.conf.in
-@@ -53,10 +53,10 @@ devices {
-     # same block device and the tools need to display a name for device,
-     # all the pathnames are matched against each item in the following
-     # list of regular expressions in turn and the first match is used.
--    preferred_names = [ ]
-+    # preferred_names = [ ]
+--- LVM2.2.02.108/conf/example.conf.in	2014-07-23 16:21:02.000000000 +0100
++++ LVM2.2.02.108-new/conf/example.conf.in	2014-07-23 23:05:06.000000000 +0100
+@@ -58,7 +58,7 @@
+     # preferred_names = [ ]
  
      # Try to avoid using undescriptive /dev/dm-N names, if present.
 -    # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
 +    preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
  
-     # A filter that tells LVM2 to only use a restricted set of devices.
-     # The filter consists of an array of regular expressions.  These
+     # In case no prefererred name matches or if preferred_names are not
+     # defined at all, builtin rules are used to determine the preference.
diff --git a/SPECS/lvm2.spec b/SPECS/lvm2.spec
index 1d5e3c6..a13d84c 100644
--- a/SPECS/lvm2.spec
+++ b/SPECS/lvm2.spec
@@ -1,4 +1,4 @@
-%define device_mapper_version 1.02.84
+%define device_mapper_version 1.02.93
 
 %define enable_cache 1
 %define enable_cluster 1
@@ -15,10 +15,10 @@
 %define resource_agents_version 3.9.5-25
 %define dlm_version 3.99.1-1
 %define libselinux_version 1.30.19-4
-%define persistent_data_version 0.2.7-1
+%define persistent_data_version 0.3.2-1
 
 %if 0%{?rhel}
-  %ifnarch i686 x86_64
+  %ifnarch i686 x86_64 s390x
     %define enable_cluster 0
     %define enable_cmirror 0
   %endif
@@ -40,8 +40,8 @@
 Summary: Userland logical volume management tools 
 Name: lvm2
 Epoch: 7
-Version: 2.02.105
-Release: 14%{?dist}
+Version: 2.02.115
+Release: 3%{?dist}
 License: GPLv2
 Group: System Environment/Base
 URL: http://sources.redhat.com/lvm2
@@ -50,17 +50,8 @@ Patch0: lvm2-rhel7.patch
 Patch1: lvm2-set-default-preferred_names.patch
 Patch2: lvm2-enable-lvmetad-by-default.patch
 Patch3: lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection.patch
-Patch4: lvm2-2_02_106-upstream-with-cache-support.patch
-Patch5: lvm2-2_02_106-fix-incorrect-snapshot-calculation-of-cow-size.patch
-Patch6: lvm2-2_02_106-additional-lvmetad-fixes.patch
-Patch7: lvm2-2_02_106-cleanup-stray-warning-messages-for-cmirror.patch
-Patch8: lvm2-2_02_106-fix-dmeventd-logging-with-parallel-wait-processing.patch
-Patch9: lvm2-2_02_106-various-thin-fixes.patch
-Patch10: lvm2-2_02_106-enahnce-lvmetad-protocol-for-pvscan-to-lock-vg-properly-and-run-refresh-only-when-needed.patch
-Patch11: lvm2-2_02_106-cleanup-stray-warning-messages-for-cmirror-addendum.patch
-Patch12: lvm2-2_02_106-reinitialise-lvmcache-properly-on-fork-to-fix-premature-polldaemon-exit.patch
-Patch13: lvm2-2_02_106-fix-timeout-for-initial-lvmetad-scan-when-done-in-parallel.patch
-Patch14: lvm2-2_02_106-various-man-page-cleanups.patch
+Patch4: lvm2-remove-mpath-device-handling-from-udev-rules.patch
+Patch5: lvm2-2_02_116-fix-raid-image-splitting.patch
 
 BuildRequires: libselinux-devel >= %{libselinux_version}, libsepol-devel
 BuildRequires: libblkid-devel >= %{util_linux_version}
@@ -78,6 +69,9 @@ BuildRequires: systemd-units
 BuildRequires: python2-devel
 BuildRequires: python-setuptools
 %endif
+%if %{enable_thin}
+BuildRequires: device-mapper-persistent-data >= %{persistent_data_version}
+%endif
 Requires: %{name}-libs = %{epoch}:%{version}-%{release}
 Requires: bash >= %{bash_version}
 Requires(post): systemd-units >= %{systemd_version}
@@ -102,17 +96,8 @@ or more physical volumes and creating one or more logical volumes
 %patch1 -p1 -b .preferred_names
 %patch2 -p1 -b .enable_lvmetad
 %patch3 -p1 -b .blkid_sublks_badcsum
-%patch4 -p1 -b .v106_upstream_cache
-%patch5 -p1 -b .snap_cow_size_calc
-%patch6 -p1 -b .lvmetad_fixes
-%patch7 -p1 -b .cmirror_messages
-%patch8 -p1 -b .dmeventd_parallel_wait
-%patch9 -p1 -b .thin_fixes
-%patch10 -p1 -b .pvscan_lvmetad
-%patch11 -p1 -b .cmirror_messages_addendum
-%patch12 -p1 -b .lvmcache_reinitialise
-%patch13 -p1 -b .initial_lvmetad_scan_timeout
-%patch14 -p1 -b .man_page_cleanups
+%patch4 -p1 -b .multipath
+%patch5 -p1 -b .raid_split
 
 %build
 %define _default_pid_dir /run
@@ -134,7 +119,7 @@ or more physical volumes and creating one or more logical volumes
 %endif
 
 %if %{enable_lvmetad}
-%define configure_lvmetad --enable-lvmetad --enable-udev-systemd-background-jobs
+%define configure_lvmetad --enable-lvmetad
 %endif
 
 %if %{enable_python}
@@ -237,6 +222,8 @@ rm -rf $RPM_BUILD_ROOT
 %{_sbindir}/vgscan
 %{_sbindir}/vgsplit
 %{_mandir}/man5/lvm.conf.5.gz
+%{_mandir}/man7/lvmcache.7.gz
+%{_mandir}/man7/lvmthin.7.gz
 %{_mandir}/man8/blkdeactivate.8.gz
 %{_mandir}/man8/fsadm.8.gz
 %{_mandir}/man8/lvchange.8.gz
@@ -245,6 +232,8 @@ rm -rf $RPM_BUILD_ROOT
 %{_mandir}/man8/lvdisplay.8.gz
 %{_mandir}/man8/lvextend.8.gz
 %{_mandir}/man8/lvm.8.gz
+%{_mandir}/man8/lvm2-activation-generator.8.gz
+%{_mandir}/man8/lvm-dumpconfig.8.gz
 %{_mandir}/man8/lvmchange.8.gz
 %{_mandir}/man8/lvmconf.8.gz
 %{_mandir}/man8/lvmdiskscan.8.gz
@@ -294,13 +283,15 @@ rm -rf $RPM_BUILD_ROOT
 %ghost %{_sysconfdir}/lvm/cache/.cache
 %attr(644, -, -) %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/lvm.conf
 %dir %{_sysconfdir}/lvm/profile
-%{_sysconfdir}/lvm/profile/default.profile
+%{_sysconfdir}/lvm/profile/command_profile_template.profile
+%{_sysconfdir}/lvm/profile/metadata_profile_template.profile
+%{_sysconfdir}/lvm/profile/thin-generic.profile
 %{_sysconfdir}/lvm/profile/thin-performance.profile
 %dir %{_sysconfdir}/lvm/backup
 %dir %{_sysconfdir}/lvm/cache
 %dir %{_sysconfdir}/lvm/archive
-%dir %{_default_locking_dir}
-%dir %{_default_run_dir}
+%ghost %dir %{_default_locking_dir}
+%ghost %dir %{_default_run_dir}
 %{_tmpfilesdir}/%{name}.conf
 %{_unitdir}/blk-availability.service
 %{_unitdir}/lvm2-monitor.service
@@ -319,8 +310,8 @@ Summary: Development libraries and headers
 Group: Development/Libraries
 License: LGPLv2
 Requires: %{name} = %{epoch}:%{version}-%{release}
-Requires: device-mapper-devel >= %{epoch}:%{device_mapper_version}-%{release}
-Requires: device-mapper-event-devel >= %{epoch}:%{device_mapper_version}-%{release}
+Requires: device-mapper-devel = %{epoch}:%{device_mapper_version}-%{release}
+Requires: device-mapper-event-devel = %{epoch}:%{device_mapper_version}-%{release}
 Requires: pkgconfig
 
 %description devel
@@ -340,7 +331,7 @@ the lvm2 libraries.
 Summary: Shared libraries for lvm2
 License: LGPLv2
 Group: System Environment/Libraries
-Requires: device-mapper-event >= %{epoch}:%{device_mapper_version}-%{release}
+Requires: device-mapper-event = %{epoch}:%{device_mapper_version}-%{release}
 
 %description libs
 This package contains shared lvm2 libraries for applications.
@@ -388,7 +379,7 @@ logical volumes, physical volumes, and volume groups.
 
 ##############################################################################
 # Cluster subpackage
-# The OCF script to manage clvmd instance is part of resource-agents package.
+# The 'clvm' OCF script to manage clvmd instance is part of resource-agents.
 ##############################################################################
 %if %{enable_cluster}
 
@@ -396,8 +387,8 @@ logical volumes, physical volumes, and volume groups.
 Summary: Cluster extensions for userland logical volume management tools
 License: GPLv2
 Group: System Environment/Base
-Requires: lvm2 >= %{epoch}:%{version}-%{release}
-Requires(preun): device-mapper >= %{epoch}:%{device_mapper_version}
+Requires: lvm2 = %{epoch}:%{version}-%{release}
+Requires(preun): device-mapper = %{epoch}:%{device_mapper_version}
 Requires(preun): lvm2 >= 2.02
 Requires: corosync >= %{corosync_version}
 Requires: dlm >= %{dlm_version}
@@ -429,7 +420,7 @@ fi
 Summary: Additional files to support clustered LVM2 in standalone mode
 License: GPLv2
 Group: System Environment/Base
-Requires: lvm2-cluster >= %{epoch}:%{version}-%{release}
+Requires: lvm2-cluster = %{epoch}:%{version}-%{release}
 
 %description cluster-standalone
 
@@ -455,10 +446,10 @@ involvement (e.g. pacemaker).
 
 %endif
 
-#################################################################################
+###############################################################################
 # Cluster mirror subpackage
-# The OCF script to manage cmirrord instance is part of resource-agents package.
-#################################################################################
+# The 'clvm' OCF script to manage cmirrord instance is part of resource-agents.
+###############################################################################
 %if %{enable_cluster}
 %if %{enable_cmirror}
 
@@ -466,7 +457,7 @@ involvement (e.g. pacemaker).
 Summary: Daemon for device-mapper-based clustered mirrors
 Group: System Environment/Base
 Requires: corosync >= %{corosync_version}
-Requires: device-mapper >= %{epoch}:%{device_mapper_version}-%{release}
+Requires: device-mapper = %{epoch}:%{device_mapper_version}-%{release}
 Requires: resource-agents >= %{resource_agents_version}
 
 %description -n cmirror
@@ -675,6 +666,88 @@ the device-mapper event library.
 %{_libdir}/pkgconfig/devmapper-event.pc
 
 %changelog
+* Wed Jan 28 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.115-3
+- Preserve chunk size with repair and metadata swap of a thin pool.
+- Fix raid --splitmirror 1 functionality (2.02.112).
+- Fix tree preload to handle splitting raid images.
+
+* Thu Jan 22 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.115-2
+- Remove rules from 10-dm.rules which handle multipath, rules for handling
+  multipath devices are directly part of device-mapper-multipath package.
+
+* Wed Jan 21 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.115-1
+- Report segment types without monitoring support as undefined.
+- Support lvchange --errorwhenfull for thin pools.
+- Improve the processing and reporting of duplicate PVs.
+- Add support for lvcreate --errorwhenfull y|n for thin pools
+- Fix lvconvert --repair to honour resilience requirement for segmented RAID LV.
+- Also call lvscan --cache in dmeventd for mirror device update in lvmetad.
+- Filter out partitioned device-mapper devices as unsuitable for use as PVs.
+- Also notify lvmetad about filtered device if using pvscan --cache DevicePath.
+- Add report/compact_output to lvm.conf to enable/disable compact report output.
+- Rename lv_error_when_full reporting field to lv_when_full.
+- Reduce severity of ioctl error message when dmeventd waitevent is interrupted.
+- Report 'unknown version' when incompatible version numbers were not obtained.
+- Add dm_report_compact_fields to remove empty fields from report output.
+- Add BuildRequires: device-mapper-persistent-data for proper thin_check configuration.
+
+* Wed Jan 14 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.114-5
+- Report lv_health_status and health attribute also for thin pool.
+- Add lv_error_when_full reporting field.
+- Add support for lvcreate --errorwhenfull y|n for thin pools.
+- Report more info from thin pool status (out of data, metadata-ro, fail).
+- Support error_if_no_space for thin pool target.
+- Do not filter out snapshot origin LVs as unusable devices for an LVM stack.
+- Fix process_each_pv to match item by device not by its PV device name only.
+
+* Wed Jan 07 2015 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.114-4
+- Fix incorrect rimage names when converting from mirror to raid1 LV (2.02.112).
+- Avoid excessive re-reading of metadata and related error messages in pvremove.
+- Check for cmirror availability during cluster mirror creation and activation.
+- Fix possible segfault when using cache_policy and cache_settings fields.
+- Fix reserved values recognition for cache_policy and cache_settings fields.
+
+* Wed Dec 17 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.114-3
+- Add cache_policy and cache_settings reporting fields.
+- Add missing recognition for --binary option with {pv,vg,lv}display -C.
+- Fix vgimportclone to notify lvmetad about changes done if lvmetad is used.
+- Fix vgimportclone to properly override config if it is missing in lvm.conf.
+- Fix automatic use of configure --enable-udev-systemd-background-jobs.
+- Correctly rename active split LV with -splitmirrors for raid1.
+- Still restrict mirror region size to power of 2 when VG extent size is not.
+- Fix segfault while using selection with regex and unbuffered reporting.
+- Remove unimplemented dm_report_set_output_selection from libdevmapper.h.
+
+* Mon Dec 01 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.114-2
+- Release socket in daemon_close and protocol string in daemon_open error path.
+- Add --cachepolicy and --cachesettings to lvcreate.
+- Fix regression when parsing /dev/mapper dir (2.02.112).
+- Fix typo in clvmd initscript causing CLVMD_STOP_TIMEOUT var to be ignored.
+
+* Wed Nov 26 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.113-1
+- Fix missing rounding to 64KB when estimating optimal thin pool chunk size.
+- Fix size in pvresize "Resizing to ..." verbose msg to show proper result size.
+- Add --cachepolicy and --cachesettings options to lvchange.
+- Validate that converted volume and specified pool volume differ in lvconvert.
+- Fix regression in vgscan --mknodes usage (2.02.112).
+- Respect --prefix when setting CLMVD_PATH configure (2.02.89).
+- Default to configure --enable-udev-systemd-background-jobs for systemd>=205.
+- Fix ignore_vg() to properly react on various vg_read errors (2.02.112).
+- Failed recovery returns FAILED_RECOVERY status flag for vg_read().
+- Exit with non-zero status code when pvck encounters a problem.
+- Fix clean_tree after activation/resume for cache target (2.02.112).
+- Fix memory corruption with sorting empty string lists (1.02.86).
+- Fix man dmsetup.8 syntax warning of Groff
+- Accept unquoted strings and / in place of {} when parsing configs.
+
+* Tue Nov 11 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.112-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
+* Mon Sep 29 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.111-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
+
 * Wed Mar 26 2014 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.105-14
 - Increase wait time for finishing initial lvmetad scan that's run in parallel.
 - Reinitialise lvmcache properly on fork to fix polldaemon exiting prematurely.