diff --git a/.gitignore b/.gitignore
index 5bf5c35..325731b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/LVM2.2.03.11.tgz
+SOURCES/LVM2.2.03.12.tgz
diff --git a/.lvm2.metadata b/.lvm2.metadata
index c85bb4b..dc25d8a 100644
--- a/.lvm2.metadata
+++ b/.lvm2.metadata
@@ -1 +1 @@
-9484fd277914a85f330b4067aa222ee13f061189 SOURCES/LVM2.2.03.11.tgz
+6d74d987b474dd0b45f239eb6dcc050622ad6962 SOURCES/LVM2.2.03.12.tgz
diff --git a/SOURCES/lvm2-2_03_12-WHATS_NEW-update.patch b/SOURCES/lvm2-2_03_12-WHATS_NEW-update.patch
deleted file mode 100644
index ed16b64..0000000
--- a/SOURCES/lvm2-2_03_12-WHATS_NEW-update.patch
+++ /dev/null
@@ -1,15 +0,0 @@
- WHATS_NEW | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index ffefc9d..3953c7e 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,7 @@
- Version 2.03.12 - 
- ===================================
-+  Fix problem with wiping of converted LVs.
-+  Fix memleak in scanning  (2.03.11).
-   Fix corner case allocation for thin-pools.
- 
- Version 2.03.11 - 08th January 2021
diff --git a/SOURCES/lvm2-2_03_12-alloc-enhance-estimation-of-sufficient_pes_free.patch b/SOURCES/lvm2-2_03_12-alloc-enhance-estimation-of-sufficient_pes_free.patch
deleted file mode 100644
index a60a2b8..0000000
--- a/SOURCES/lvm2-2_03_12-alloc-enhance-estimation-of-sufficient_pes_free.patch
+++ /dev/null
@@ -1,47 +0,0 @@
- WHATS_NEW               | 10 ++++++++--
- lib/metadata/lv_manip.c | 10 +++++++---
- 2 files changed, 11 insertions(+), 3 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 452a631..fe347f7 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,3 +1,7 @@
-+Version 2.03.12 - 
-+===================================
-+  Fix corner case allocation for thin-pools.
-+
- Version 2.03.11 - 08th January 2021
- ===================================
-   Fix pvck handling MDA at offset different from 4096.
-diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
-index 7046436..443d32c 100644
---- a/lib/metadata/lv_manip.c
-+++ b/lib/metadata/lv_manip.c
-@@ -1850,11 +1850,13 @@ static uint32_t _mirror_log_extents(uint32_t region_size, uint32_t pe_size, uint
- 
- /* Is there enough total space or should we give up immediately? */
- static int _sufficient_pes_free(struct alloc_handle *ah, struct dm_list *pvms,
--				uint32_t allocated, uint32_t extents_still_needed)
-+				uint32_t allocated, uint32_t log_still_needed,
-+				uint32_t extents_still_needed)
- {
- 	uint32_t area_extents_needed = (extents_still_needed - allocated) * ah->area_count / ah->area_multiple;
- 	uint32_t parity_extents_needed = (extents_still_needed - allocated) * ah->parity_count / ah->area_multiple;
--	uint32_t metadata_extents_needed = ah->alloc_and_split_meta ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN + ah->log_len; /* One each */
-+	uint32_t metadata_extents_needed = (ah->alloc_and_split_meta ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN) +
-+	    (log_still_needed ? ah->log_len : 0); /* One each */
- 	uint64_t total_extents_needed = (uint64_t)area_extents_needed + parity_extents_needed + metadata_extents_needed;
- 	uint32_t free_pes = pv_maps_size(pvms);
- 
-@@ -3359,7 +3361,9 @@ 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 (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated, ah->new_extents))
-+		if (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated,
-+							       alloc_state.log_area_count_still_needed,
-+							       ah->new_extents))
- 			goto_out;
- 
- 		_init_alloc_parms(ah, &alloc_parms, alloc, prev_lvseg,
diff --git a/SOURCES/lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch b/SOURCES/lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch
deleted file mode 100644
index ce35731..0000000
--- a/SOURCES/lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch
+++ /dev/null
@@ -1,107 +0,0 @@
- lib/metadata/cache_manip.c       | 40 ++++++++++++++--------------------------
- lib/metadata/metadata-exported.h |  1 +
- tools/lvconvert.c                |  1 +
- tools/lvcreate.c                 |  1 +
- 4 files changed, 17 insertions(+), 26 deletions(-)
-
-diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
-index 2c4cc92..90ebd94 100644
---- a/lib/metadata/cache_manip.c
-+++ b/lib/metadata/cache_manip.c
-@@ -204,6 +204,7 @@ int update_cache_pool_params(struct cmd_context *cmd,
- 			     unsigned attr,
- 			     uint32_t pool_data_extents,
- 			     uint32_t *pool_metadata_extents,
-+			     struct logical_volume *metadata_lv,
- 			     int *chunk_size_calc_method, uint32_t *chunk_size)
- {
- 	uint64_t min_meta_size;
-@@ -252,39 +253,26 @@ int update_cache_pool_params(struct cmd_context *cmd,
- 	if (!validate_cache_chunk_size(cmd, *chunk_size))
- 		return_0;
- 
--	min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
-+	if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
-+		log_error("Size of %s data volume cannot be smaller than chunk size %s.",
-+			  segtype->name, display_size(cmd, *chunk_size));
-+		return 0;
-+	}
- 
--	/* Round up to extent size */
--	if (min_meta_size % extent_size)
--		min_meta_size += extent_size - min_meta_size % extent_size;
-+	min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
-+	min_meta_size = dm_round_up(min_meta_size, extent_size);
- 
- 	if (!pool_metadata_size)
- 		pool_metadata_size = min_meta_size;
- 
--	if (pool_metadata_size > (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE)) {
--		pool_metadata_size = 2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE;
--		if (*pool_metadata_extents)
--			log_warn("WARNING: Maximum supported pool metadata size is %s.",
--				 display_size(cmd, pool_metadata_size));
--	} else if (pool_metadata_size < min_meta_size) {
--		if (*pool_metadata_extents)
--			log_warn("WARNING: Minimum required pool metadata size is %s "
--				 "(needs extra %s).",
--				 display_size(cmd, min_meta_size),
--				 display_size(cmd, min_meta_size - pool_metadata_size));
--		pool_metadata_size = min_meta_size;
--	}
--
--	if (!(*pool_metadata_extents =
--	      extents_from_size(cmd, pool_metadata_size, extent_size)))
-+	if (!update_pool_metadata_min_max(cmd, extent_size,
-+					  min_meta_size,
-+					  (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE),
-+					  &pool_metadata_size,
-+					  metadata_lv,
-+					  pool_metadata_extents))
- 		return_0;
- 
--	if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
--		log_error("Size of %s data volume cannot be smaller than chunk size %s.",
--			  segtype->name, display_size(cmd, *chunk_size));
--		return 0;
--	}
--
- 	log_verbose("Preferred pool metadata size %s.",
- 		    display_size(cmd, (uint64_t)*pool_metadata_extents * extent_size));
- 
-diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
-index 0e57722..c0fa564 100644
---- a/lib/metadata/metadata-exported.h
-+++ b/lib/metadata/metadata-exported.h
-@@ -1319,6 +1319,7 @@ int update_cache_pool_params(struct cmd_context *cmd,
- 			     unsigned attr,
- 			     uint32_t pool_data_extents,
- 			     uint32_t *pool_metadata_extents,
-+			     struct logical_volume *metadata_lv,
- 			     int *chunk_size_calc_method, uint32_t *chunk_size);
- int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size);
- int validate_lv_cache_create_pool(const struct logical_volume *pool_lv);
-diff --git a/tools/lvconvert.c b/tools/lvconvert.c
-index ce90279..416e8a7 100644
---- a/tools/lvconvert.c
-+++ b/tools/lvconvert.c
-@@ -3189,6 +3189,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
- 					      pool_segtype, target_attr,
- 					      lv->le_count,
- 					      &meta_extents,
-+					      metadata_lv,
- 					      &chunk_calc,
- 					      &chunk_size))
- 			goto_bad;
-diff --git a/tools/lvcreate.c b/tools/lvcreate.c
-index 1ee9e14..1ce561f 100644
---- a/tools/lvcreate.c
-+++ b/tools/lvcreate.c
-@@ -403,6 +403,7 @@ static int _update_extents_params(struct volume_group *vg,
- 						      lp->segtype, lp->target_attr,
- 						      lp->extents,
- 						      &lp->pool_metadata_extents,
-+						      NULL,
- 						      &lp->thin_chunk_size_calc_policy,
- 						      &lp->chunk_size))
- 				return_0;
diff --git a/SOURCES/lvm2-2_03_12-dev_get_primary_dev-fix-invalid-path-check.patch b/SOURCES/lvm2-2_03_12-dev_get_primary_dev-fix-invalid-path-check.patch
deleted file mode 100644
index add3525..0000000
--- a/SOURCES/lvm2-2_03_12-dev_get_primary_dev-fix-invalid-path-check.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From b3719266bd5e3a9e6737d6bda60e543121ddf343 Mon Sep 17 00:00:00 2001
-From: David Teigland <teigland@redhat.com>
-Date: Tue, 9 Feb 2021 09:47:08 -0600
-Subject: [PATCH] dev_get_primary_dev: fix invalid path check
-
-Fix commit bee9f4efdd81 "filter-mpath: work with nvme devices"
-which removed setting the path for readlink.
-
-(cherry picked from commit f74f94c2ddb1d33d75d325c959344a566a621fd5)
-
-Conflicts:
-	lib/device/dev-type.c
----
- lib/device/dev-type.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
-diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
-index 379afa8..1342e97 100644
---- a/lib/device/dev-type.c
-+++ b/lib/device/dev-type.c
-@@ -434,7 +434,7 @@ static int _has_sys_partition(struct device *dev)
- 	int minor = (int) MINOR(dev->dev);
- 
- 	/* check if dev is a partition */
--	if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
-+	if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/partition",
- 			dm_sysfs_dir(), major, minor) < 0) {
- 		log_error("dm_snprintf partition failed");
- 		return 0;
-@@ -660,8 +660,13 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
- 	 * - basename ../../block/md0/md0  = md0
- 	 * Parent's 'dev' sysfs attribute  = /sys/block/md0/dev
- 	 */
--	if ((size = readlink(dirname(path), temp_path, sizeof(temp_path) - 1)) < 0) {
--		log_sys_error("readlink", path);
-+	if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d",
-+			dm_sysfs_dir(), major, minor) < 0) {
-+		log_warn("WARNING: %s: major:minor sysfs path is too long.", dev_name(dev));
-+		return 0;
-+	}
-+	if ((size = readlink(path, temp_path, sizeof(temp_path) - 1)) < 0) {
-+		log_warn("WARNING: Readlink of %s failed.", path);
- 		goto out;
- 	}
- 
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch b/SOURCES/lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch
deleted file mode 100644
index 0f00653..0000000
--- a/SOURCES/lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch
+++ /dev/null
@@ -1,255 +0,0 @@
- lib/device/dev-cache.c    | 161 ++++++++++++++++++++++++++++++++++++----------
- test/shell/dev-aliases.sh |  53 +++++++++++++++
- 2 files changed, 179 insertions(+), 35 deletions(-)
- create mode 100644 test/shell/dev-aliases.sh
-
-diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
-index d5f18ff..8082efa 100644
---- a/lib/device/dev-cache.c
-+++ b/lib/device/dev-cache.c
-@@ -1428,60 +1428,151 @@ struct device *dev_hash_get(const char *name)
- 	return (struct device *) dm_hash_lookup(_cache.names, name);
- }
- 
-+static void _remove_alias(struct device *dev, const char *name)
-+{
-+	struct dm_str_list *strl;
-+
-+	dm_list_iterate_items(strl, &dev->aliases) {
-+		if (!strcmp(strl->str, name)) {
-+			dm_list_del(&strl->list);
-+			return;
-+		}
-+	}
-+}
-+
-+/*
-+ * Check that paths for this dev still refer to the same dev_t.  This is known
-+ * to drop invalid paths in the case where lvm deactivates an LV, which causes
-+ * that LV path to go away, but that LV path is not removed from dev-cache (it
-+ * probably should be).  Later a new path to a different LV is added to
-+ * dev-cache, where the new LV has the same major:minor as the previously
-+ * deactivated LV.  The new LV will find the existing struct dev, and that
-+ * struct dev will have dev->aliases entries that refer to the name of the old
-+ * deactivated LV.  Those old paths are all invalid and are dropped here.
-+ */
-+
-+static void _verify_aliases(struct device *dev, const char *newname)
-+{
-+	struct dm_str_list *strl, *strl2;
-+	struct stat st;
-+
-+	dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
-+		/* newname was just stat'd and added by caller */
-+		if (newname && !strcmp(strl->str, newname))
-+			continue;
-+
-+		if (stat(strl->str, &st) || (st.st_rdev != dev->dev)) {
-+			log_debug("Drop invalid path %s for %d:%d (new path %s).",
-+				  strl->str, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), newname ?: "");
-+			dm_hash_remove(_cache.names, strl->str);
-+			dm_list_del(&strl->list);
-+		}
-+	}
-+}
-+
- struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f)
- {
--	struct stat buf;
--	struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
--	int info_available = 0;
--	int ret = 1;
-+	struct device *dev = (struct device *) dm_hash_lookup(_cache.names, name);
-+	struct stat st;
-+	int ret;
- 
--	if (d && (d->flags & DEV_REGULAR))
--		return d;
-+	/*
-+	 * DEV_REGULAR means that is "dev" is actually a file, not a device.
-+	 * FIXME: I don't think dev-cache is used for files any more and this
-+	 * can be dropped?
-+	 */
-+	if (dev && (dev->flags & DEV_REGULAR))
-+		return dev;
-+
-+	/*
-+	 * The requested path is invalid, remove any dev-cache
-+	 * info for it.
-+	 */
-+	if (stat(name, &st)) {
-+		if (dev) {
-+			log_print("Device path %s is invalid for %d:%d %s.",
-+				  name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
- 
--	/* If the entry's wrong, remove it */
--	if (stat(name, &buf) < 0) {
--		if (d)
- 			dm_hash_remove(_cache.names, name);
--		log_sys_very_verbose("stat", name);
--		d = NULL;
--	} else
--		info_available = 1;
- 
--	if (d && (buf.st_rdev != d->dev)) {
--		dm_hash_remove(_cache.names, name);
--		d = NULL;
--	}
-+			_remove_alias(dev, name);
- 
--	if (!d) {
--		_insert(name, info_available ? &buf : NULL, 0, obtain_device_list_from_udev());
--		d = (struct device *) dm_hash_lookup(_cache.names, name);
--		if (!d) {
--			log_debug_devs("Device name not found in dev_cache repeat dev_cache_scan for %s", name);
--			dev_cache_scan();
--			d = (struct device *) dm_hash_lookup(_cache.names, name);
-+			/* Remove any other names in dev->aliases that are incorrect. */
-+			_verify_aliases(dev, NULL);
- 		}
-+		return NULL;
- 	}
- 
--	if (!d)
-+	if (!S_ISBLK(st.st_mode)) {
-+		log_debug("Not a block device %s.", name);
- 		return NULL;
-+	}
- 
--	if (d && (d->flags & DEV_REGULAR))
--		return d;
-+	/*
-+	 * dev-cache has incorrect info for the requested path.
-+	 * Remove incorrect info and then add new dev-cache entry.
-+	 */
-+	if (dev && (st.st_rdev != dev->dev)) {
-+		log_print("Device path %s does not match %d:%d %s.",
-+			  name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
-+
-+		dm_hash_remove(_cache.names, name);
-+
-+		_remove_alias(dev, name);
-+
-+		/* Remove any other names in dev->aliases that are incorrect. */
-+		_verify_aliases(dev, NULL);
-+
-+		/* Add new dev-cache entry next. */
-+		dev = NULL;
-+	}
-+
-+	/*
-+	 * Either add a new struct dev for st_rdev and name,
-+	 * or add name as a new alias for an existing struct dev
-+	 * for st_rdev.
-+	 */
-+	if (!dev) {
-+		_insert_dev(name, st.st_rdev);
- 
--	if (f && !(d->flags & DEV_REGULAR)) {
--		ret = f->passes_filter(cmd, f, d, NULL);
-+		/* Get the struct dev that was just added. */
-+		dev = (struct device *) dm_hash_lookup(_cache.names, name);
- 
--		if (ret == -EAGAIN) {
--			log_debug_devs("get device by name defer filter %s", dev_name(d));
--			d->flags |= DEV_FILTER_AFTER_SCAN;
--			ret = 1;
-+		if (!dev) {
-+			log_error("Failed to get device %s", name);
-+			return NULL;
- 		}
-+
-+		_verify_aliases(dev, name);
- 	}
- 
--	if (f && !(d->flags & DEV_REGULAR) && !ret)
-+	/*
-+	 * The caller passed a filter if they only want the dev if it
-+	 * passes filters.
-+	 */
-+
-+	if (!f)
-+		return dev;
-+
-+	ret = f->passes_filter(cmd, f, dev, NULL);
-+
-+	/*
-+	 * This might happen if this function is called before
-+	 * filters can do i/o.  I don't think this will happen
-+	 * any longer and this EAGAIN case can be removed.
-+	 */
-+	if (ret == -EAGAIN) {
-+		log_debug_devs("dev_cache_get filter deferred %s", dev_name(dev));
-+		dev->flags |= DEV_FILTER_AFTER_SCAN;
-+		ret = 1;
-+	}
-+
-+	if (!ret) {
-+		log_debug_devs("dev_cache_get filter excludes %s", dev_name(dev));
- 		return NULL;
-+	}
- 
--	return d;
-+	return dev;
- }
- 
- static struct device *_dev_cache_seek_devt(dev_t dev)
-diff --git a/test/shell/dev-aliases.sh b/test/shell/dev-aliases.sh
-new file mode 100644
-index 0000000..c97cd5d
---- /dev/null
-+++ b/test/shell/dev-aliases.sh
-@@ -0,0 +1,53 @@
-+#!/usr/bin/env bash
-+
-+# Copyright (C) 2012 Red Hat, Inc. All rights reserved.
-+#
-+# This copyrighted material is made available to anyone wishing to use,
-+# modify, copy, or redistribute it subject to the terms and conditions
-+# of the GNU General Public License v.2.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, write to the Free Software Foundation,
-+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+
-+SKIP_WITH_LVMPOLLD=1
-+
-+. lib/inittest
-+
-+aux prepare_devs 3
-+
-+vgcreate $vg $dev1 $dev2 $dev3
-+
-+#
-+# This lvconvert command will deactivate LV1, then internally create a new
-+# lv, lvol0, as a poolmetadataspare, then activate lvol0 to zero it.
-+# lvol0 will get the same major:minor that LV1 had.  When the code gets
-+# the struct dev for lvol0, the new path to lvol0 is added to the
-+# dev-cache with it's major:minor.  That major:minor already exists in
-+# dev-cache and has the stale LV1 as an alias.  So the path to lvol0 is
-+# added as an alias to the existing struct dev (with the correct
-+# major:minor), but that struct dev has the stale LV1 path on its aliases
-+# list.  The code will now validate all the aliases before returning the
-+# dev for lvol0, and will find that the LV1 path is stale and remove it
-+# from the aliases.  That will prevent the stale path from being used for
-+# the dev in place of the new path.
-+#
-+# The preferred_name is set to /dev/mapper so that if the stale path still
-+# exists, that stale path would be used as the name for the dev, and the
-+# wiping code would fail to open that stale name.
-+#
-+
-+lvcreate -n $lv1 -L32M $vg $dev1
-+lvcreate -n $lv2 -L16M $vg $dev2
-+lvconvert -y --type cache-pool --poolmetadata $lv2 --cachemode writeback $vg/$lv1 --config='devices { preferred_names=["/dev/mapper/"] }' 
-+lvremove -y $vg/$lv1
-+
-+lvcreate -n $lv1 -L32M $vg $dev1
-+lvcreate -n $lv2 -L16M $vg $dev2
-+lvconvert -y --type cache-pool --poolmetadata $lv2 $vg/$lv1
-+lvremove -y $vg/$lv1
-+
-+# TODO: add more validation of dev aliases being specified as command
-+# args in combination with various preferred_names settings.
-+
-+vgremove -ff  $vg
diff --git a/SOURCES/lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch b/SOURCES/lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch
deleted file mode 100644
index 3778134..0000000
--- a/SOURCES/lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch
+++ /dev/null
@@ -1,494 +0,0 @@
- lib/device/dev-type.c      |  81 +++++++++++++++++++----
- lib/device/dev-type.h      |   2 +
- lib/device/device.h        |   1 +
- lib/filters/filter-mpath.c | 156 ++++++++++++++++++++++++++++++---------------
- 4 files changed, 177 insertions(+), 63 deletions(-)
-
-diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
-index 896821d..379afa8 100644
---- a/lib/device/dev-type.c
-+++ b/lib/device/dev-type.c
-@@ -21,6 +21,7 @@
- #include "lib/metadata/metadata.h"
- #include "lib/device/bcache.h"
- #include "lib/label/label.h"
-+#include "lib/commands/toolcontext.h"
- 
- #ifdef BLKID_WIPING_SUPPORT
- #include <blkid.h>
-@@ -67,6 +68,31 @@ int dev_is_pmem(struct device *dev)
- 	return is_pmem ? 1 : 0;
- }
- 
-+/*
-+ * An nvme device has major number 259 (BLKEXT), minor number <minor>,
-+ * and reading /sys/dev/block/259:<minor>/device/dev shows a character
-+ * device cmajor:cminor where cmajor matches the major number of the
-+ * nvme character device entry in /proc/devices.  Checking all of that
-+ * is excessive and unnecessary compared to just comparing /dev/name*.
-+ */
-+
-+int dev_is_nvme(struct dev_types *dt, struct device *dev)
-+{
-+	struct dm_str_list *strl;
-+
-+	if (dev->flags & DEV_IS_NVME)
-+		return 1;
-+
-+	dm_list_iterate_items(strl, &dev->aliases) {
-+		if (!strncmp(strl->str, "/dev/nvme", 9)) {
-+			log_debug("Found nvme device %s", dev_name(dev));
-+			dev->flags |= DEV_IS_NVME;
-+			return 1;
-+		}
-+	}
-+	return 0;
-+}
-+
- int dev_is_lv(struct device *dev)
- {
- 	FILE *fp;
-@@ -302,6 +328,9 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
- 
- const char *dev_subsystem_name(struct dev_types *dt, struct device *dev)
- {
-+	if (dev->flags & DEV_IS_NVME)
-+		return "NVME";
-+
- 	if (MAJOR(dev->dev) == dt->device_mapper_major)
- 		return "DM";
- 
-@@ -348,7 +377,6 @@ int major_is_scsi_device(struct dev_types *dt, int major)
- 	return (dt->dev_type_array[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0;
- }
- 
--
- static int _loop_is_with_partscan(struct device *dev)
- {
- 	FILE *fp;
-@@ -398,6 +426,28 @@ struct partition {
- 	uint32_t nr_sects;
- } __attribute__((packed));
- 
-+static int _has_sys_partition(struct device *dev)
-+{
-+	char path[PATH_MAX];
-+	struct stat info;
-+	int major = (int) MAJOR(dev->dev);
-+	int minor = (int) MINOR(dev->dev);
-+
-+	/* check if dev is a partition */
-+	if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
-+			dm_sysfs_dir(), major, minor) < 0) {
-+		log_error("dm_snprintf partition failed");
-+		return 0;
-+	}
-+
-+	if (stat(path, &info) == -1) {
-+		if (errno != ENOENT)
-+			log_sys_error("stat", path);
-+		return 0;
-+	}
-+	return 1;
-+}
-+
- static int _is_partitionable(struct dev_types *dt, struct device *dev)
- {
- 	int parts = major_max_partitions(dt, MAJOR(dev->dev));
-@@ -414,6 +464,13 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
- 	    _loop_is_with_partscan(dev))
- 		return 1;
- 
-+	if (dev_is_nvme(dt, dev)) {
-+		/* If this dev is already a partition then it's not partitionable. */
-+		if (_has_sys_partition(dev))
-+			return 0;
-+		return 1;
-+	}
-+
- 	if ((parts <= 1) || (MINOR(dev->dev) % parts))
- 		return 0;
- 
-@@ -557,11 +614,18 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
- 	char path[PATH_MAX];
- 	char temp_path[PATH_MAX];
- 	char buffer[64];
--	struct stat info;
- 	FILE *fp = NULL;
- 	int parts, residue, size, ret = 0;
- 
- 	/*
-+	 * /dev/nvme devs don't use the major:minor numbering like
-+	 * block dev types that have their own major number, so
-+	 * the calculation based on minor number doesn't work.
-+	 */
-+	if (dev_is_nvme(dt, dev))
-+		goto sys_partition;
-+
-+	/*
- 	 * Try to get the primary dev out of the
- 	 * list of known device types first.
- 	 */
-@@ -576,23 +640,14 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
- 		goto out;
- 	}
- 
-+ sys_partition:
- 	/*
- 	 * If we can't get the primary dev out of the list of known device
- 	 * types, try to look at sysfs directly then. This is more complex
- 	 * way and it also requires certain sysfs layout to be present
- 	 * which might not be there in old kernels!
- 	 */
--
--	/* check if dev is a partition */
--	if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
--			sysfs_dir, major, minor) < 0) {
--		log_error("dm_snprintf partition failed");
--		goto out;
--	}
--
--	if (stat(path, &info) == -1) {
--		if (errno != ENOENT)
--			log_sys_error("stat", path);
-+	if (!_has_sys_partition(dev)) {
- 		*result = dev->dev;
- 		ret = 1;
- 		goto out; /* dev is not a partition! */
-diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
-index fdf7791..8b94b79 100644
---- a/lib/device/dev-type.h
-+++ b/lib/device/dev-type.h
-@@ -95,6 +95,8 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev);
- 
- int dev_is_pmem(struct device *dev);
- 
-+int dev_is_nvme(struct dev_types *dt, struct device *dev);
-+
- int dev_is_lv(struct device *dev);
- 
- int get_fs_block_size(struct device *dev, uint32_t *fs_block_size);
-diff --git a/lib/device/device.h b/lib/device/device.h
-index a58bff8..816db31 100644
---- a/lib/device/device.h
-+++ b/lib/device/device.h
-@@ -38,6 +38,7 @@
- #define DEV_SCAN_FOUND_LABEL	0x00010000      /* label scan read dev and found label */
- #define DEV_IS_MD_COMPONENT	0x00020000	/* device is an md component */
- #define DEV_UDEV_INFO_MISSING   0x00040000	/* we have no udev info for this device */
-+#define DEV_IS_NVME		0x00080000	/* set if dev is nvme */
- 
- /*
-  * Support for external device info.
-diff --git a/lib/filters/filter-mpath.c b/lib/filters/filter-mpath.c
-index 85d1625..40e7df6 100644
---- a/lib/filters/filter-mpath.c
-+++ b/lib/filters/filter-mpath.c
-@@ -16,6 +16,7 @@
- #include "lib/misc/lib.h"
- #include "lib/filters/filter.h"
- #include "lib/activate/activate.h"
-+#include "lib/commands/toolcontext.h"
- #ifdef UDEV_SYNC_SUPPORT
- #include <libudev.h>
- #include "lib/device/dev-ext-udev-constants.h"
-@@ -27,7 +28,6 @@
- 
- #define MPATH_PREFIX "mpath-"
- 
--
- struct mpath_priv {
- 	struct dm_pool *mem;
- 	struct dev_filter f;
-@@ -35,6 +35,9 @@ struct mpath_priv {
- 	struct dm_hash_table *hash;
- };
- 
-+/*
-+ * given "/dev/foo" return "foo"
-+ */
- static const char *_get_sysfs_name(struct device *dev)
- {
- 	const char *name;
-@@ -53,6 +56,11 @@ static const char *_get_sysfs_name(struct device *dev)
- 	return name;
- }
- 
-+/*
-+ * given major:minor
-+ * readlink translates /sys/dev/block/major:minor to /sys/.../foo
-+ * from /sys/.../foo return "foo"
-+ */
- static const char *_get_sysfs_name_by_devt(const char *sysfs_dir, dev_t devno,
- 					  char *buf, size_t buf_size)
- {
-@@ -102,27 +110,28 @@ static int _get_sysfs_string(const char *path, char *buffer, int max_size)
- 	return r;
- }
- 
--static int _get_sysfs_get_major_minor(const char *sysfs_dir, const char *kname, int *major, int *minor)
-+static int _get_sysfs_dm_mpath(struct dev_types *dt, const char *sysfs_dir, const char *holder_name)
- {
--	char path[PATH_MAX], buffer[64];
-+	char path[PATH_MAX];
-+	char buffer[128];
- 
--	if (dm_snprintf(path, sizeof(path), "%s/block/%s/dev", sysfs_dir, kname) < 0) {
-+	if (dm_snprintf(path, sizeof(path), "%sblock/%s/dm/uuid", sysfs_dir, holder_name) < 0) {
- 		log_error("Sysfs path string is too long.");
- 		return 0;
- 	}
- 
-+	buffer[0] = '\0';
-+
- 	if (!_get_sysfs_string(path, buffer, sizeof(buffer)))
- 		return_0;
- 
--	if (sscanf(buffer, "%d:%d", major, minor) != 2) {
--		log_error("Failed to parse major minor from %s", buffer);
--		return 0;
--	}
-+	if (!strncmp(buffer, MPATH_PREFIX, 6))
-+		return 1;
- 
--	return 1;
-+	return 0;
- }
- 
--static int _get_parent_mpath(const char *dir, char *name, int max_size)
-+static int _get_holder_name(const char *dir, char *name, int max_size)
- {
- 	struct dirent *d;
- 	DIR *dr;
-@@ -155,7 +164,7 @@ static int _get_parent_mpath(const char *dir, char *name, int max_size)
- }
- 
- #ifdef UDEV_SYNC_SUPPORT
--static int _udev_dev_is_mpath(struct device *dev)
-+static int _udev_dev_is_mpath_component(struct device *dev)
- {
- 	const char *value;
- 	struct dev_ext *ext;
-@@ -174,95 +183,148 @@ static int _udev_dev_is_mpath(struct device *dev)
- 	return 0;
- }
- #else
--static int _udev_dev_is_mpath(struct device *dev)
-+static int _udev_dev_is_mpath_component(struct device *dev)
- {
- 	return 0;
- }
- #endif
- 
--static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
-+static int _native_dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
- {
- 	struct mpath_priv *mp = (struct mpath_priv *) f->private;
- 	struct dev_types *dt = mp->dt;
--	const char *part_name, *name;
--	struct stat info;
--	char path[PATH_MAX], parent_name[PATH_MAX];
-+	const char *part_name;
-+	const char *name;               /* e.g. "sda" for "/dev/sda" */
-+	char link_path[PATH_MAX];       /* some obscure, unpredictable sysfs path */
-+	char holders_path[PATH_MAX];    /* e.g. "/sys/block/sda/holders/" */
-+	char dm_dev_path[PATH_MAX];    /* e.g. "/dev/dm-1" */
-+	char holder_name[128] = { 0 };  /* e.g. "dm-1" */
- 	const char *sysfs_dir = dm_sysfs_dir();
--	int major = MAJOR(dev->dev);
--	int minor = MINOR(dev->dev);
-+	int dev_major = MAJOR(dev->dev);
-+	int dev_minor = MINOR(dev->dev);
-+	int dm_dev_major;
-+	int dm_dev_minor;
-+	struct stat info;
- 	dev_t primary_dev;
- 	long look;
- 
--	/* Limit this filter only to SCSI devices */
--	if (!major_is_scsi_device(dt, MAJOR(dev->dev)))
-+	/* Limit this filter to SCSI or NVME devices */
-+	if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
- 		return 0;
- 
- 	switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
-+
- 	case 2: /* The dev is partition. */
- 		part_name = dev_name(dev); /* name of original dev for log_debug msg */
--		if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, parent_name, sizeof(parent_name))))
-+
-+		/* gets "foo" for "/dev/foo" where "/dev/foo" comes from major:minor */
-+		if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
- 			return_0;
-+
- 		log_debug_devs("%s: Device is a partition, using primary "
- 			       "device %s for mpath component detection",
- 			       part_name, name);
- 		break;
-+
- 	case 1: /* The dev is already a primary dev. Just continue with the dev. */
-+
-+		/* gets "foo" for "/dev/foo" */
- 		if (!(name = _get_sysfs_name(dev)))
- 			return_0;
- 		break;
-+
- 	default: /* 0, error. */
--		log_warn("Failed to get primary device for %d:%d.", major, minor);
-+		log_warn("Failed to get primary device for %d:%d.", dev_major, dev_minor);
- 		return 0;
- 	}
- 
--	if (dm_snprintf(path, sizeof(path), "%s/block/%s/holders", sysfs_dir, name) < 0) {
-+	if (dm_snprintf(holders_path, sizeof(holders_path), "%sblock/%s/holders", sysfs_dir, name) < 0) {
- 		log_warn("Sysfs path to check mpath is too long.");
- 		return 0;
- 	}
- 
- 	/* also will filter out partitions */
--	if (stat(path, &info))
-+	if (stat(holders_path, &info))
- 		return 0;
- 
- 	if (!S_ISDIR(info.st_mode)) {
--		log_warn("Path %s is not a directory.", path);
-+		log_warn("Path %s is not a directory.", holders_path);
- 		return 0;
- 	}
- 
--	if (!_get_parent_mpath(path, parent_name, sizeof(parent_name)))
-+	/*
-+	 * If holders dir contains an entry such as "dm-1", then this sets
-+	 * holder_name to "dm-1".
-+	 *
-+	 * If holders dir is empty, return 0 (this is generally where
-+	 * devs that are not mpath components return.)
-+	 */
-+	if (!_get_holder_name(holders_path, holder_name, sizeof(holder_name)))
- 		return 0;
- 
--	if (!_get_sysfs_get_major_minor(sysfs_dir, parent_name, &major, &minor))
--		return_0;
-+	if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0) {
-+		log_warn("dm device path to check mpath is too long.");
-+		return 0;
-+	}
- 
--	if (major != dt->device_mapper_major)
-+	/*
-+	 * stat "/dev/dm-1" which is the holder of the dev we're checking
-+	 * dm_dev_major:dm_dev_minor come from stat("/dev/dm-1")
-+	 */
-+	if (stat(dm_dev_path, &info)) {
-+		log_debug("filter-mpath %s holder %s stat result %d",
-+			  dev_name(dev), dm_dev_path, errno);
- 		return 0;
-+	}
-+	dm_dev_major = (int)MAJOR(info.st_rdev);
-+	dm_dev_minor = (int)MINOR(info.st_rdev);
-+	
-+	if (dm_dev_major != dt->device_mapper_major) {
-+		log_debug_devs("filter-mpath %s holder %s %d:%d does not have dm major",
-+			       dev_name(dev), dm_dev_path, dm_dev_major, dm_dev_minor);
-+		return 0;
-+	}
- 
--	/* Avoid repeated detection of multipath device and use first checked result */
--	look = (long) dm_hash_lookup_binary(mp->hash, &minor, sizeof(minor));
-+	/*
-+	 * Save the result of checking that "/dev/dm-1" is an mpath device
-+	 * to avoid repeating it for each path component.
-+	 * The minor number of "/dev/dm-1" is added to the hash table with
-+	 * const value 2 meaning that dm minor 1 (for /dev/dm-1) is a multipath dev
-+	 * and const value 1 meaning that dm minor 1 is not a multipath dev.
-+	 */
-+	look = (long) dm_hash_lookup_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor));
- 	if (look > 0) {
--		log_debug_devs("%s(%u:%u): already checked as %sbeing mpath.",
--			       parent_name, major, minor, (look > 1) ? "" : "not ");
-+		log_debug_devs("filter-mpath %s holder %s %u:%u already checked as %sbeing mpath.",
-+			       dev_name(dev), holder_name, dm_dev_major, dm_dev_minor, (look > 1) ? "" : "not ");
- 		return (look > 1) ? 1 : 0;
- 	}
- 
--	if (lvm_dm_prefix_check(major, minor, MPATH_PREFIX)) {
--		(void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)2);
-+	/*
-+	 * Returns 1 if /sys/block/<holder_name>/dm/uuid indicates that
-+	 * <holder_name> is a dm device with dm uuid prefix mpath-.
-+	 * When true, <holder_name> will be something like "dm-1".
-+	 *
-+	 * (Is a hash table worth it to avoid reading one sysfs file?)
-+	 */
-+	if (_get_sysfs_dm_mpath(dt, sysfs_dir, holder_name)) {
-+		log_debug_devs("filter-mpath %s holder %s %u:%u ignore mpath component",
-+			       dev_name(dev), holder_name, dm_dev_major, dm_dev_minor);
-+		(void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)2);
- 		return 1;
- 	}
- 
--	(void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)1);
-+	(void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)1);
- 
- 	return 0;
- }
- 
--static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
-+static int _dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
- {
- 	if (dev->ext.src == DEV_EXT_NONE)
--		return _native_dev_is_mpath(f, dev);
-+		return _native_dev_is_mpath_component(cmd, f, dev);
- 
- 	if (dev->ext.src == DEV_EXT_UDEV)
--		return _udev_dev_is_mpath(dev);
-+		return _udev_dev_is_mpath_component(dev);
- 
- 	log_error(INTERNAL_ERROR "Missing hook for mpath recognition "
- 		  "using external device info source %s", dev_ext_name(dev));
-@@ -272,11 +334,11 @@ static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
- 
- #define MSG_SKIPPING "%s: Skipping mpath component device"
- 
--static int _ignore_mpath(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
-+static int _ignore_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
- {
- 	dev->filtered_flags &= ~DEV_FILTERED_MPATH_COMPONENT;
- 
--	if (_dev_is_mpath(f, dev) == 1) {
-+	if (_dev_is_mpath_component(cmd, f, dev) == 1) {
- 		if (dev->ext.src == DEV_EXT_NONE)
- 			log_debug_devs(MSG_SKIPPING, dev_name(dev));
- 		else
-@@ -303,8 +365,8 @@ static void _destroy(struct dev_filter *f)
- struct dev_filter *mpath_filter_create(struct dev_types *dt)
- {
- 	const char *sysfs_dir = dm_sysfs_dir();
--	struct dm_pool *mem;
- 	struct mpath_priv *mp;
-+	struct dm_pool *mem;
- 	struct dm_hash_table *hash;
- 
- 	if (!*sysfs_dir) {
-@@ -328,19 +390,13 @@ struct dev_filter *mpath_filter_create(struct dev_types *dt)
- 		goto bad;
- 	}
- 
--	if (!(mp = dm_pool_zalloc(mem, sizeof(*mp)))) {
--		log_error("mpath filter allocation failed.");
--		goto bad;
--	}
--
--	mp->f.passes_filter = _ignore_mpath;
-+	mp->f.passes_filter = _ignore_mpath_component;
- 	mp->f.destroy = _destroy;
- 	mp->f.use_count = 0;
- 	mp->f.private = mp;
- 	mp->f.name = "mpath";
--
--	mp->mem = mem;
- 	mp->dt = dt;
-+	mp->mem = mem;
- 	mp->hash = hash;
- 
- 	log_debug_devs("mpath filter initialised.");
diff --git a/SOURCES/lvm2-2_03_12-fsadm-avoid-access-to-unbound-variable.patch b/SOURCES/lvm2-2_03_12-fsadm-avoid-access-to-unbound-variable.patch
deleted file mode 100644
index 6beff68..0000000
--- a/SOURCES/lvm2-2_03_12-fsadm-avoid-access-to-unbound-variable.patch
+++ /dev/null
@@ -1,16 +0,0 @@
- scripts/fsadm.sh | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/scripts/fsadm.sh b/scripts/fsadm.sh
-index 2cb1fc7..4f59cee 100755
---- a/scripts/fsadm.sh
-+++ b/scripts/fsadm.sh
-@@ -163,7 +163,7 @@ cleanup() {
- 		_FSADM_EXTOFF=$EXTOFF
- 		export _FSADM_YES _FSADM_EXTOFF
- 		unset FSADM_RUNNING
--		test -n "$LVM_BINARY" && PATH=$_SAVEPATH
-+		test -n "${LVM_BINARY-}" && PATH=$_SAVEPATH
- 		dry exec "$LVM" lvresize $VERB $FORCE -r -L"${NEWSIZE_ORIG}b" "$VOLUME_ORIG"
- 	fi
- 
diff --git a/SOURCES/lvm2-2_03_12-integrity-fix-segfault-on-error-path-when-replacing-.patch b/SOURCES/lvm2-2_03_12-integrity-fix-segfault-on-error-path-when-replacing-.patch
deleted file mode 100644
index d4ece0d..0000000
--- a/SOURCES/lvm2-2_03_12-integrity-fix-segfault-on-error-path-when-replacing-.patch
+++ /dev/null
@@ -1,24 +0,0 @@
- lib/metadata/integrity_manip.c | 10 +++++++---
- 1 file changed, 7 insertions(+), 3 deletions(-)
-
-diff --git a/lib/metadata/integrity_manip.c b/lib/metadata/integrity_manip.c
-index 53ab1b3..abf90d8 100644
---- a/lib/metadata/integrity_manip.c
-+++ b/lib/metadata/integrity_manip.c
-@@ -773,9 +773,13 @@ int lv_add_integrity_to_raid(struct logical_volume *lv, struct integrity_setting
- bad:
- 	log_error("Failed to add integrity.");
- 
--	for (s = 0; s < revert_meta_lvs; s++) {
--		if (!lv_remove(imeta_lvs[s]))
--			log_error("New integrity metadata LV may require manual removal.");
-+	if (revert_meta_lvs) {
-+		for (s = 0; s < DEFAULT_RAID_MAX_IMAGES; s++) {
-+			if (!imeta_lvs[s])
-+				continue;
-+			if (!lv_remove(imeta_lvs[s]))
-+				log_error("New integrity metadata LV may require manual removal.");
-+		}
- 	}
- 			       
- 	if (!vg_write(vg) || !vg_commit(vg))
diff --git a/SOURCES/lvm2-2_03_12-label_scan-fix-missing-free-of-filtered_devs.patch b/SOURCES/lvm2-2_03_12-label_scan-fix-missing-free-of-filtered_devs.patch
deleted file mode 100644
index b5bccfb..0000000
--- a/SOURCES/lvm2-2_03_12-label_scan-fix-missing-free-of-filtered_devs.patch
+++ /dev/null
@@ -1,19 +0,0 @@
- lib/label/label.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/lib/label/label.c b/lib/label/label.c
-index e067a6b..e6dd4a1 100644
---- a/lib/label/label.c
-+++ b/lib/label/label.c
-@@ -1243,6 +1243,11 @@ int label_scan(struct cmd_context *cmd)
- 		free(devl);
- 	}
- 
-+	dm_list_iterate_items_safe(devl, devl2, &filtered_devs) {
-+		dm_list_del(&devl->list);
-+		free(devl);
-+	}
-+
- 	/*
- 	 * If hints were not available/usable, then we scanned all devs,
- 	 * and we now know which are PVs.  Save this list of PVs we've
diff --git a/SOURCES/lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch b/SOURCES/lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch
deleted file mode 100644
index bb28cd7..0000000
--- a/SOURCES/lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch
+++ /dev/null
@@ -1,66 +0,0 @@
- WHATS_NEW               | 4 ++++
- lib/activate/activate.c | 5 +++++
- lib/activate/activate.h | 2 ++
- lib/metadata/lv_manip.c | 6 ++++++
- 4 files changed, 17 insertions(+)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 3953c7e..c8f869c 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,9 @@
- Version 2.03.12 - 
- ===================================
-+  Check if lvcreate passes read_only_volume_list with tags and skips zeroing.
-+  Limit pool metadata spare to 16GiB.
-+  Improves conversion and allocation of pool metadata.
-+  Support thin pool metadata 15.88GiB, adds 64MiB, thin_pool_crop_metadata=0.
-   Fix problem with wiping of converted LVs.
-   Fix memleak in scanning  (2.03.11).
-   Fix corner case allocation for thin-pools.
-diff --git a/lib/activate/activate.c b/lib/activate/activate.c
-index 7ed6441..de866fb 100644
---- a/lib/activate/activate.c
-+++ b/lib/activate/activate.c
-@@ -466,6 +466,11 @@ static int _passes_readonly_filter(struct cmd_context *cmd,
- 	return _lv_passes_volumes_filter(cmd, lv, cn, activation_read_only_volume_list_CFG);
- }
- 
-+int lv_passes_readonly_filter(const struct logical_volume *lv)
-+{
-+	return _passes_readonly_filter(lv->vg->cmd, lv);
-+}
-+
- int library_version(char *version, size_t size)
- {
- 	if (!activation())
-diff --git a/lib/activate/activate.h b/lib/activate/activate.h
-index 3f4d128..53c8631 100644
---- a/lib/activate/activate.h
-+++ b/lib/activate/activate.h
-@@ -208,6 +208,8 @@ int lvs_in_vg_opened(const struct volume_group *vg);
- 
- int lv_is_active(const struct logical_volume *lv);
- 
-+int lv_passes_readonly_filter(const struct logical_volume *lv);
-+
- /* Check is any component LV is active */
- const struct logical_volume *lv_component_is_active(const struct logical_volume *lv);
- const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv);
-diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
-index 445c4ad..5ff64a3 100644
---- a/lib/metadata/lv_manip.c
-+++ b/lib/metadata/lv_manip.c
-@@ -7976,6 +7976,12 @@ static int _should_wipe_lv(struct lvcreate_params *lp,
- 	     first_seg(first_seg(lv)->pool_lv)->zero_new_blocks))
- 		return 0;
- 
-+	if (warn && (lv_passes_readonly_filter(lv))) {
-+		log_warn("WARNING: Read-only activated logical volume %s not zeroed.",
-+			 display_lvname(lv));
-+		return 0;
-+	}
-+
- 	/* Cannot zero read-only volume */
- 	if ((lv->status & LVM_WRITE) &&
- 	    (lp->zero || lp->wipe_signatures))
diff --git a/SOURCES/lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch b/SOURCES/lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch
deleted file mode 100644
index 9bc2f48..0000000
--- a/SOURCES/lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch
+++ /dev/null
@@ -1,29 +0,0 @@
- daemons/lvmlockd/lvmlockd-core.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
-index fea8ee6..c4abf66 100644
---- a/daemons/lvmlockd/lvmlockd-core.c
-+++ b/daemons/lvmlockd/lvmlockd-core.c
-@@ -896,8 +896,9 @@ static int read_adopt_file(struct list_head *vg_lockd)
- 				goto fail;
- 
- 			memset(vg_uuid, 0, sizeof(vg_uuid));
-+			memset(lm_type_str, 0, sizeof(lm_type_str));
- 
--			if (sscanf(adopt_line, "VG: %63s %64s %16s %64s",
-+			if (sscanf(adopt_line, "VG: %63s %64s %15s %64s",
- 				   vg_uuid, ls->vg_name, lm_type_str, ls->vg_args) != 4) {
- 				goto fail;
- 			}
-@@ -916,8 +917,9 @@ static int read_adopt_file(struct list_head *vg_lockd)
- 			r->type = LD_RT_LV;
- 
- 			memset(vg_uuid, 0, sizeof(vg_uuid));
-+			memset(mode, 0, sizeof(mode));
- 
--			if (sscanf(adopt_line, "LV: %64s %64s %s %8s %u",
-+			if (sscanf(adopt_line, "LV: %64s %64s %s %7s %u",
- 				   vg_uuid, r->name, r->lv_args, mode, &r->version) != 5) {
- 				goto fail;
- 			}
diff --git a/SOURCES/lvm2-2_03_12-make-generate.patch b/SOURCES/lvm2-2_03_12-make-generate.patch
deleted file mode 100644
index 2f4f682..0000000
--- a/SOURCES/lvm2-2_03_12-make-generate.patch
+++ /dev/null
@@ -1,18 +0,0 @@
- man/lvconvert.8_pregen | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen
-index a47ccac..170eec8 100644
---- a/man/lvconvert.8_pregen
-+++ b/man/lvconvert.8_pregen
-@@ -772,6 +772,10 @@ Add a cache to an LV, using a specified cache device.
- .br
- .RS 4
- .ad l
-+[ \fB-c\fP|\fB--chunksize\fP \fISize\fP[k|UNIT] ]
-+.ad b
-+.br
-+.ad l
- [    \fB--cachesize\fP \fISize\fP[m|UNIT] ]
- .ad b
- .br
diff --git a/SOURCES/lvm2-2_03_12-man-Fix-wording-in-lvmthin-7.patch b/SOURCES/lvm2-2_03_12-man-Fix-wording-in-lvmthin-7.patch
deleted file mode 100644
index 09088d5..0000000
--- a/SOURCES/lvm2-2_03_12-man-Fix-wording-in-lvmthin-7.patch
+++ /dev/null
@@ -1,22 +0,0 @@
- man/lvmthin.7_main | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main
-index 3ce34a5..9568eca 100644
---- a/man/lvmthin.7_main
-+++ b/man/lvmthin.7_main
-@@ -443,12 +443,12 @@ If the repair works, the thin pool LV and its thin LVs can be activated.
- User should manually check if repaired thin pool kernel metadata
- has all data for all lvm2 known LVs by individual activation of
- every thin LV. When all works, user should continue with fsck of
--all filesystems present these such volumes.
-+all filesystems present on these volumes.
- Once the thin pool is considered fully functional user may remove ThinPoolLV_metaN
- (the LV containing the damaged thin pool metadata) for possible
- space reuse.
- For a better performance it may be useful to pvmove the new repaired metadata LV
--(written to previous pmspare volume) to a better PV (i.e. SSD)
-+(written to previous pmspare volume) to a faster PV, e.g. SSD.
- 
- If the repair operation fails, the thin pool LV and its thin LVs
- are not accessible and it may be necessary to restore their content
diff --git a/SOURCES/lvm2-2_03_12-man-update-lvmthin.patch b/SOURCES/lvm2-2_03_12-man-update-lvmthin.patch
deleted file mode 100644
index f61660f..0000000
--- a/SOURCES/lvm2-2_03_12-man-update-lvmthin.patch
+++ /dev/null
@@ -1,86 +0,0 @@
- man/lvmthin.7_main | 37 +++++++++++++++++++++++++------------
- 1 file changed, 25 insertions(+), 12 deletions(-)
-
-diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main
-index ce23431..e6f1d63 100644
---- a/man/lvmthin.7_main
-+++ b/man/lvmthin.7_main
-@@ -394,7 +394,7 @@ the pmspare LV.
- \&
- 
- If thin pool metadata is damaged, it may be repairable.
--Checking and repairing thin pool metadata is analagous to
-+Checking and repairing thin pool metadata is analogous to
- running fsck/repair on a file system.
- 
- When a thin pool LV is activated, lvm runs the thin_check command
-@@ -437,14 +437,24 @@ copy to the VG's pmspare LV.
- If step 1 is successful, the thin pool metadata LV is replaced
- with the pmspare LV containing the corrected metadata.
- The previous thin pool metadata LV, containing the damaged metadata,
--becomes visible with the new name ThinPoolLV_tmetaN (where N is 0,1,...).
--
--If the repair works, the thin pool LV and its thin LVs can be activated,
--and the LV containing the damaged thin pool metadata can be removed.
--It may be useful to move the new metadata LV (previously pmspare) to a
--better PV.
--
--If the repair does not work, the thin pool LV and its thin LVs are lost.
-+becomes visible with the new name ThinPoolLV_metaN (where N is 0,1,...).
-+
-+If the repair works, the thin pool LV and its thin LVs can be activated.
-+User should manually check if repaired thin pool kernel metadata
-+has all data for all lvm2 known LVs by individual activation of
-+every thin LV. When all works, user should continue with fsck of
-+all filesystems present these such volumes.
-+Once the thin pool is considered fully functional user may remove ThinPoolLV_metaN
-+(the LV containing the damaged thin pool metadata) for possible
-+space reuse.
-+For a better performance it may be useful to pvmove the new repaired metadata LV
-+(written to previous pmspare volume) to a better PV (i.e. SSD)
-+
-+If the repair operation fails, the thin pool LV and its thin LVs
-+are not accessible and it may be necessary to restore their content
-+from a backup.  In such case the content of unmodified original damaged
-+ThinPoolLV_metaN volume can be used by your support for more
-+advanced recovery methods.
- 
- If metadata is manually restored with thin_repair directly,
- the pool metadata LV can be manually swapped with another LV
-@@ -452,6 +462,9 @@ containing new metadata:
- 
- .B lvconvert --thinpool VG/ThinPoolLV --poolmetadata VG/NewThinMetaLV
- 
-+Note: Thin pool metadata is compact so even small corruptions
-+in them may result in significant portions of mappings to be lost.
-+It is recommended to use fast resilient storage for them.
- 
- .SS Activation of thin snapshots
- 
-@@ -549,7 +562,7 @@ Command to extend thin pool data space:
- .fi
- 
- Other methods of increasing free data space in a thin pool LV
--include removing a thin LV and its related snapsots, or running
-+include removing a thin LV and its related snapshots, or running
- fstrim on the file system using a thin LV.
- 
- 
-@@ -689,7 +702,7 @@ with two configuration settings:
- .B thin_pool_autoextend_threshold
- .br
- is a percentage full value that defines when the thin pool LV should be
--extended.  Setting this to 100 disables automatic extention.  The minimum
-+extended.  Setting this to 100 disables automatic extension.  The minimum
- value is 50.
- 
- .BR lvm.conf (5)
-@@ -716,7 +729,7 @@ the --ignoremonitoring option can be used.  With this option, the command
- will not ask dmeventd to monitor the thin pool LV.
- 
- .IP \[bu]
--Setting thin_pool_autoextend_threshould to 100 disables automatic
-+Setting thin_pool_autoextend_threshold to 100 disables automatic
- extension of thin pool LVs, even if they are being monitored by dmeventd.
- 
- .P
diff --git a/SOURCES/lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch b/SOURCES/lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch
deleted file mode 100644
index b41b370..0000000
--- a/SOURCES/lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch
+++ /dev/null
@@ -1,39 +0,0 @@
- lib/metadata/pool_manip.c | 10 +++++++++-
- 1 file changed, 9 insertions(+), 1 deletion(-)
-
-diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
-index b67882e..1975cb4 100644
---- a/lib/metadata/pool_manip.c
-+++ b/lib/metadata/pool_manip.c
-@@ -697,6 +697,8 @@ static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg
- int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
- 			       struct dm_list *pvh, int poolmetadataspare)
- {
-+	/* Max usable size of any spare volume is currently 16GiB rouned to extent size */
-+	const uint64_t MAX_SIZE = (UINT64_C(2 * 16) * 1024 * 1024 + vg->extent_size - 1) / vg->extent_size;
- 	struct logical_volume *lv = vg->pool_metadata_spare_lv;
- 	uint32_t seg_mirrors;
- 	struct lv_segment *seg;
-@@ -706,8 +708,11 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
- 		/* Find maximal size of metadata LV */
- 		dm_list_iterate_items(lvl, &vg->lvs)
- 			if (lv_is_pool_metadata(lvl->lv) &&
--			    (lvl->lv->le_count > extents))
-+			    (lvl->lv->le_count > extents)) {
- 				extents = lvl->lv->le_count;
-+				if (extents >= MAX_SIZE)
-+					break;
-+			}
- 
- 	if (!poolmetadataspare) {
- 		/* TODO: Not showing when lvm.conf would define 'n' ? */
-@@ -718,6 +723,9 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
- 		return 1;
- 	}
- 
-+	if (extents > MAX_SIZE)
-+		extents = MAX_SIZE;
-+
- 	if (!lv) {
- 		if (!_alloc_pool_metadata_spare(vg, extents, pvh))
- 			return_0;
diff --git a/SOURCES/lvm2-2_03_12-pvck-fix-warning-and-exit-code-for-non-4k-mda1-offse.patch b/SOURCES/lvm2-2_03_12-pvck-fix-warning-and-exit-code-for-non-4k-mda1-offse.patch
deleted file mode 100644
index 63020bd..0000000
--- a/SOURCES/lvm2-2_03_12-pvck-fix-warning-and-exit-code-for-non-4k-mda1-offse.patch
+++ /dev/null
@@ -1,24 +0,0 @@
- tools/pvck.c | 10 +++++++---
- 1 file changed, 7 insertions(+), 3 deletions(-)
-
-diff --git a/tools/pvck.c b/tools/pvck.c
-index c36e182..88350de 100644
---- a/tools/pvck.c
-+++ b/tools/pvck.c
-@@ -1140,9 +1140,13 @@ static int _dump_label_and_pv_header(struct cmd_context *cmd, uint64_t labelsect
- 			*mda1_offset = xlate64(dlocn->offset);
- 			*mda1_size = xlate64(dlocn->size);
- 
--			if (*mda1_offset != 4096) {
--				log_print("CHECK: pv_header.disk_locn[%d].offset expected 4096 # for first mda", di);
--				bad++;
-+			/*
-+			 * mda1 offset is page size from machine that created it,
-+			 * warn if it's not one of the expected page sizes.
-+			 */
-+			if ((*mda1_offset != 4096) && (*mda1_offset != 8192) && (*mda1_offset != 65536)) {
-+				log_print("WARNING: pv_header.disk_locn[%d].offset %llu is unexpected # for first mda",
-+					  di, (unsigned long long)*mda1_offset);
- 			}
- 		} else {
- 			*mda2_offset = xlate64(dlocn->offset);
diff --git a/SOURCES/lvm2-2_03_12-test-check-read_only_volume_list-tagging-works.patch b/SOURCES/lvm2-2_03_12-test-check-read_only_volume_list-tagging-works.patch
deleted file mode 100644
index bdcc15b..0000000
--- a/SOURCES/lvm2-2_03_12-test-check-read_only_volume_list-tagging-works.patch
+++ /dev/null
@@ -1,19 +0,0 @@
- test/shell/tags.sh | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/test/shell/tags.sh b/test/shell/tags.sh
-index fd1b332..5b636a8 100644
---- a/test/shell/tags.sh
-+++ b/test/shell/tags.sh
-@@ -52,6 +52,11 @@ check lv_field @firstlvtag1 tags "firstlvtag1"
- not check lv_field @secondlvtag1 tags "firstlvtag1"
- check lv_field $vg1/$lv2 tags "secondlvtag1"
- not check lv_field $vg1/$lv1 tags "secondlvtag1"
-+
-+# LV is not zeroed when tag matches read only volume list
-+lvcreate -l1 $vg1 --addtag "RO" --config "activation/read_only_volume_list = [ \"@RO\" ]" 2>&1 | tee out
-+grep "not zeroed" out
-+
- vgremove -f $vg1
- 
- # lvchange with --addtag and --deltag
diff --git a/SOURCES/lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch b/SOURCES/lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch
deleted file mode 100644
index ae05b76..0000000
--- a/SOURCES/lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch
+++ /dev/null
@@ -1,98 +0,0 @@
- test/shell/thin-16g.sh | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 88 insertions(+)
- create mode 100644 test/shell/thin-16g.sh
-
-diff --git a/test/shell/thin-16g.sh b/test/shell/thin-16g.sh
-new file mode 100644
-index 0000000..ee7e22e
---- /dev/null
-+++ b/test/shell/thin-16g.sh
-@@ -0,0 +1,88 @@
-+#!/usr/bin/env bash
-+
-+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
-+#
-+# This copyrighted material is made available to anyone wishing to use,
-+# modify, copy, or redistribute it subject to the terms and conditions
-+# of the GNU General Public License v.2.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, write to the Free Software Foundation,
-+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+
-+# Test usability of 16g thin pool metadata  LV
-+
-+
-+SKIP_WITH_LVMPOLLD=1
-+
-+. lib/inittest
-+
-+aux have_thin 1 0 0 || skip
-+
-+aux prepare_vg 1 50000
-+
-+lvcreate -T -L10 --poolmetadatasize 16g $vg/pool
-+check lv_field $vg/pool_tmeta size "<15.88g"
-+lvremove -f $vg
-+
-+# Cropped way
-+lvcreate -T -L10 --poolmetadatasize 16g --config 'allocation/thin_pool_crop_metadata=1' $vg/pool
-+check lv_field $vg/pool_tmeta size "15.81g"
-+lvremove -f $vg
-+
-+lvcreate -L16G -n meta $vg
-+lvcreate -L10  -n pool $vg
-+lvconvert --yes --thinpool $vg/pool --poolmetadata meta
-+# Uncropped size 33554432 sectors - 16GiB
-+dmsetup table ${vg}-pool_tmeta | grep 33554432
-+lvremove -f $vg
-+
-+# Uses 20G metadata volume, but crops the size in DM table
-+lvcreate -L20G -n meta $vg
-+lvcreate -L10  -n pool $vg
-+lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1'
-+check lv_field $vg/lvol0_pmspare size "16.00g"
-+# Size should be cropped to 33161216 sectors  ~15.81GiB
-+dmsetup table ${vg}-pool_tmeta | grep 33161216
-+
-+# Also size remains unchanged with activation has no cropping,
-+# but metadata have no CROP_METADATA flag set
-+lvchange -an $vg
-+lvchange -ay $vg
-+# Size still stays cropped to 33161216 sectors  ~15.81GiB
-+dmsetup table ${vg}-pool_tmeta | grep 33161216
-+lvremove -f $vg
-+
-+# Minimal size is 2M
-+lvcreate -L1M -n meta $vg
-+lvcreate -L10 -n pool $vg
-+not lvconvert --yes --thinpool $vg/pool --poolmetadata meta
-+lvremove -f $vg
-+
-+# Uses 20G metadata volume, but crops the size in DM table
-+lvcreate -L1 --poolmetadatasize 10G -T $vg/pool
-+lvresize -L+10G $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1'
-+check lv_field $vg/lvol0_pmspare size "15.81g"
-+# Size should be cropped to 33161216 sectors  ~15.81GiB
-+dmsetup table ${vg}-pool_tmeta | grep 33161216
-+
-+# Without cropping we can grop to ~15.88GiB
-+lvresize -L+10G $vg/pool_tmeta
-+check lv_field $vg/lvol0_pmspare size "<15.88g"
-+lvremove -f $vg
-+
-+# User has already 'bigger' metadata and wants them uncropped
-+lvcreate -L16G -n meta $vg
-+lvcreate -L10  -n pool $vg
-+lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1'
-+
-+# No change with cropping
-+lvresize -l+1 $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1'
-+dmsetup table ${vg}-pool_tmeta | grep 33161216
-+
-+# Resizes to 'uncropped' size 16GiB with ANY size
-+lvresize -l+1 $vg/pool_tmeta
-+dmsetup table ${vg}-pool_tmeta | grep 33554432
-+check lv_field $vg/pool_tmeta size "16.00g"
-+
-+vgremove -ff $vg
diff --git a/SOURCES/lvm2-2_03_12-tests-check-full-zeroing-of-thin-pool-metadata.patch b/SOURCES/lvm2-2_03_12-tests-check-full-zeroing-of-thin-pool-metadata.patch
deleted file mode 100644
index d7edcc7..0000000
--- a/SOURCES/lvm2-2_03_12-tests-check-full-zeroing-of-thin-pool-metadata.patch
+++ /dev/null
@@ -1,78 +0,0 @@
- test/shell/thin-zero-meta.sh | 68 ++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 68 insertions(+)
- create mode 100644 test/shell/thin-zero-meta.sh
-
-diff --git a/test/shell/thin-zero-meta.sh b/test/shell/thin-zero-meta.sh
-new file mode 100644
-index 0000000..6a15a73
---- /dev/null
-+++ b/test/shell/thin-zero-meta.sh
-@@ -0,0 +1,68 @@
-+#!/usr/bin/env bash
-+
-+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
-+#
-+# This copyrighted material is made available to anyone wishing to use,
-+# modify, copy, or redistribute it subject to the terms and conditions
-+# of the GNU General Public License v.2.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, write to the Free Software Foundation,
-+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+
-+# Test how zeroing of thin-pool metadata works
-+
-+SKIP_WITH_LVMLOCKD=1
-+SKIP_WITH_LVMPOLLD=1
-+
-+export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false}
-+
-+. lib/inittest
-+
-+#
-+# Main
-+#
-+aux have_thin 1 3 0 || skip
-+aux have_cache 1 3 0 || skip
-+
-+aux prepare_vg 3 40000
-+
-+# Create mostly-zero devs only front of it has some 'real' back-end
-+aux zero_dev "$dev1" "$(( $(get first_extent_sector "$dev1") + 8192 )):"
-+aux zero_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 8192 )):"
-+aux zero_dev "$dev3" "$(( $(get first_extent_sector "$dev3") + 8192 )):"
-+
-+# Prepare randomly filled 4M LV on dev2
-+lvcreate -L16G -n $lv1 $vg "$dev2"
-+dd if=/dev/urandom of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=4 oflag=direct  || true
-+lvremove -f $vg
-+
-+for i in 0 1
-+do
-+	aux lvmconf "allocation/zero_metadata = $i"
-+
-+	# Lvm2 should allocate metadata on dev2
-+	lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2"
-+	lvchange -an $vg
-+
-+	lvs -ao+seg_pe_ranges $vg
-+	lvchange -ay $vg/pool_tmeta --yes
-+
-+	# Skip past 1.2M which is 'created' by  thin-pool initialization
-+	hexdump -C -n 200 -s 2000000 "$DM_DEV_DIR/$vg/pool_tmeta" | tee out
-+
-+	# When fully zeroed, it should be zero - so almost no output from hexdump
-+	case "$i" in
-+	0) test $(wc -l < out) -ge 10 ;; # should not be zeroed
-+	1) test $(wc -l < out) -le 10 ;; # should be zeroed
-+	esac
-+
-+	lvremove -f $vg/pool
-+done
-+
-+# Check lvm2 spots error during full zeroing of metadata device
-+aux error_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 32 )):"
-+not lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2" |& tee err
-+grep "Failed to initialize logical volume" err
-+
-+vgremove -ff $vg
diff --git a/SOURCES/lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch b/SOURCES/lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch
deleted file mode 100644
index 04962b8..0000000
--- a/SOURCES/lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch
+++ /dev/null
@@ -1,47 +0,0 @@
- test/shell/lvcreate-thin-limits.sh | 30 ++++++++++++++++++++++++++----
- 1 file changed, 26 insertions(+), 4 deletions(-)
-
-diff --git a/test/shell/lvcreate-thin-limits.sh b/test/shell/lvcreate-thin-limits.sh
-index 6a9c33d..5dcc160 100644
---- a/test/shell/lvcreate-thin-limits.sh
-+++ b/test/shell/lvcreate-thin-limits.sh
-@@ -27,13 +27,35 @@ aux can_use_16T || skip
- aux have_thin 1 0 0 || skip
- which mkfs.ext4 || skip
- 
--aux prepare_pvs 1 16777216
-+# 16T device
-+aux prepare_pvs 2 8388608
- get_devs
- 
--vgcreate $SHARED -s 4K "$vg" "${DEVICES[@]}"
-+# gives 16777215M device
-+vgcreate $SHARED -s 4M "$vg" "${DEVICES[@]}"
- 
--not lvcreate -T -L15.995T --poolmetadatasize 5G $vg/pool
-+# For 1st. pass only single PV
-+lvcreate -l100%PV --name $lv1 $vg "$dev2"
- 
--lvs -ao+seg_pe_ranges $vg
-+for i in 1 0
-+do
-+	SIZE=$(get vg_field "$vg" vg_free --units m)
-+	SIZE=${SIZE%%\.*}
-+
-+	# ~16T - 2 * 5G + something  -> should not fit
-+	not lvcreate -Zn -T -L$(( SIZE - 2 * 5 * 1024 + 1 )) --poolmetadatasize 5G $vg/pool
-+
-+	check vg_field "$vg" lv_count "$i"
-+
-+	# Should fit  data + metadata + pmspare
-+	lvcreate -Zn -T -L$(( SIZE - 2 * 5 * 1024 )) --poolmetadatasize 5G $vg/pool
-+
-+	check vg_field "$vg" vg_free "0"
-+
-+	lvs -ao+seg_pe_ranges $vg
-+
-+        # Remove everything for 2nd. pass
-+	lvremove -ff $vg
-+done
- 
- vgremove -ff $vg
diff --git a/SOURCES/lvm2-2_03_12-tests-remove-local-setting-of-LVM_BINARY.patch b/SOURCES/lvm2-2_03_12-tests-remove-local-setting-of-LVM_BINARY.patch
deleted file mode 100644
index 71f6272..0000000
--- a/SOURCES/lvm2-2_03_12-tests-remove-local-setting-of-LVM_BINARY.patch
+++ /dev/null
@@ -1,61 +0,0 @@
- test/shell/fsadm-crypt.sh   | 3 ---
- test/shell/fsadm-renamed.sh | 3 ---
- test/shell/fsadm.sh         | 3 ---
- test/shell/lvresize-full.sh | 2 --
- 4 files changed, 11 deletions(-)
-
-diff --git a/test/shell/fsadm-crypt.sh b/test/shell/fsadm-crypt.sh
-index 4b8fc4e..2004db9 100644
---- a/test/shell/fsadm-crypt.sh
-+++ b/test/shell/fsadm-crypt.sh
-@@ -76,9 +76,6 @@ dev_vg_lv="$DM_DEV_DIR/$vg_lv"
- dev_vg_lv2="$DM_DEV_DIR/$vg_lv2"
- dev_vg_lv3="$DM_DEV_DIR/$vg_lv3"
- mount_dir="mnt"
--# for recursive call
--LVM_BINARY=$(which lvm)
--export LVM_BINARY
- 
- test ! -d "$mount_dir" && mkdir "$mount_dir"
- 
-diff --git a/test/shell/fsadm-renamed.sh b/test/shell/fsadm-renamed.sh
-index 3218939..50c6d3e 100644
---- a/test/shell/fsadm-renamed.sh
-+++ b/test/shell/fsadm-renamed.sh
-@@ -27,9 +27,6 @@ dev_vg_lv_ren="$DM_DEV_DIR/$vg_lv_ren"
- mount_dir="mnt"
- mount_space_dir="mnt space dir"
- mount_dolar_dir="mnt \$SPACE dir"
--# for recursive call
--LVM_BINARY=$(which lvm)
--export LVM_BINARY
- 
- test ! -d "$mount_dir" && mkdir "$mount_dir"
- test ! -d "$mount_space_dir" && mkdir "$mount_space_dir"
-diff --git a/test/shell/fsadm.sh b/test/shell/fsadm.sh
-index 67f9660..987b1a1 100644
---- a/test/shell/fsadm.sh
-+++ b/test/shell/fsadm.sh
-@@ -45,9 +45,6 @@ dev_vg_lv="$DM_DEV_DIR/$vg_lv"
- dev_vg_lv2="$DM_DEV_DIR/$vg_lv2"
- mount_dir="mnt"
- mount_space_dir="mnt space dir"
--# for recursive call
--LVM_BINARY=$(which lvm)
--export LVM_BINARY
- 
- test ! -d "$mount_dir" && mkdir "$mount_dir"
- test ! -d "$mount_space_dir" && mkdir "$mount_space_dir"
-diff --git a/test/shell/lvresize-full.sh b/test/shell/lvresize-full.sh
-index 3cab522..dcf93a7 100644
---- a/test/shell/lvresize-full.sh
-+++ b/test/shell/lvresize-full.sh
-@@ -21,8 +21,6 @@ SKIP_WITH_LVMPOLLD=1
- FSCK=${FSCK-fsck}
- MKFS=${MKFS-mkfs.ext3}
- RESIZEFS=${RESIZEFS-resize2fs}
--LVM_BINARY=$(which lvm)
--export LVM_BINARY
- 
- which $FSCK || skip
- which $MKFS || skip
diff --git a/SOURCES/lvm2-2_03_12-tests-update-thin-and-cache-checked-messages.patch b/SOURCES/lvm2-2_03_12-tests-update-thin-and-cache-checked-messages.patch
deleted file mode 100644
index f4ccd37..0000000
--- a/SOURCES/lvm2-2_03_12-tests-update-thin-and-cache-checked-messages.patch
+++ /dev/null
@@ -1,77 +0,0 @@
- test/shell/lvconvert-thin.sh    |  2 +-
- test/shell/lvcreate-cache.sh    | 12 +++++-------
- test/shell/lvcreate-thin-big.sh | 10 +++++-----
- 3 files changed, 11 insertions(+), 13 deletions(-)
-
-diff --git a/test/shell/lvconvert-thin.sh b/test/shell/lvconvert-thin.sh
-index 1319655..ee85691 100644
---- a/test/shell/lvconvert-thin.sh
-+++ b/test/shell/lvconvert-thin.sh
-@@ -128,7 +128,7 @@ lvcreate -L1T -n $lv1 $vg
- lvcreate -L32G -n $lv2 $vg
- # Warning about bigger then needed
- lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 2>&1 | tee err
--grep "WARNING: Maximum" err
-+grep -i "maximum" err
- lvremove -f $vg
- 
- 
-diff --git a/test/shell/lvcreate-cache.sh b/test/shell/lvcreate-cache.sh
-index 2c46e21..4d9d75e 100644
---- a/test/shell/lvcreate-cache.sh
-+++ b/test/shell/lvcreate-cache.sh
-@@ -27,7 +27,6 @@ aux prepare_vg 5 80000
- 
- aux lvmconf 'global/cache_disabled_features = [ "policy_smq" ]'
- 
--
- #######################
- # Cache_Pool creation #
- #######################
-@@ -173,17 +172,16 @@ dmsetup table ${vg}-$lv1 | grep cache  # ensure it is loaded in kernel
- 
- lvremove -f $vg
- 
--
- # Check minimum cache pool metadata size
--lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>out
--grep "WARNING: Minimum" out
-+lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>&1 | tee out
-+grep -i "minimal" out
-+
- 
- # FIXME: This test is failing in allocator with smaller VG sizes
--lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>out
--grep "WARNING: Maximum" out
-+lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>&1 | tee out
-+grep -i "maximum" out
- 
- lvremove -f $vg
--
- ########################################
- # Cache conversion and r/w permissions #
- ########################################
-diff --git a/test/shell/lvcreate-thin-big.sh b/test/shell/lvcreate-thin-big.sh
-index 0b622b7..2549035 100644
---- a/test/shell/lvcreate-thin-big.sh
-+++ b/test/shell/lvcreate-thin-big.sh
-@@ -31,14 +31,14 @@ vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}"
- 
- # Size 0 is not valid
- invalid lvcreate -L4M --chunksize 128 --poolmetadatasize 0 -T $vg/pool1 2>out
--lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 2>out
--grep "WARNING: Minimum" out
-+lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 2>&1 >out
-+grep -i "minimal" out
- # FIXME: metadata allocation fails, if PV doesn't have at least 16GB
- # i.e. pool metadata device cannot be multisegment
--lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>out
--grep "WARNING: Maximum" out
-+lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>&1 >out
-+grep "maximum" out
- check lv_field $vg/pool1_tmeta size "2.00m"
--check lv_field $vg/pool2_tmeta size "15.81g"
-+check lv_field $vg/pool2_tmeta size "<15.88g"
- 
- # Check we do report correct percent values.
- lvcreate --type zero -L3G $vg -n pool3
diff --git a/SOURCES/lvm2-2_03_12-thin-improve-16g-support-for-thin-pool-metadata.patch b/SOURCES/lvm2-2_03_12-thin-improve-16g-support-for-thin-pool-metadata.patch
deleted file mode 100644
index 8347ad4..0000000
--- a/SOURCES/lvm2-2_03_12-thin-improve-16g-support-for-thin-pool-metadata.patch
+++ /dev/null
@@ -1,694 +0,0 @@
- conf/example.conf.in             |  7 +++
- device_mapper/all.h              | 16 +++++--
- device_mapper/libdm-deptree.c    | 39 ++++++++++++-----
- lib/activate/dev_manager.c       |  8 ++--
- lib/config/config_settings.h     |  5 +++
- lib/config/defaults.h            |  2 +
- lib/format_text/flags.c          |  1 +
- lib/metadata/lv_manip.c          | 31 ++++++++++++++
- lib/metadata/merge.c             |  2 +
- lib/metadata/metadata-exported.h | 11 +++++
- lib/metadata/metadata.h          | 13 ++++++
- lib/metadata/pool_manip.c        | 46 ++++++++++++++++++++
- lib/metadata/thin_manip.c        | 92 ++++++++++++++++++++++++++--------------
- lib/thin/thin.c                  | 22 +++++++---
- man/lvmthin.7_main               | 10 ++++-
- tools/lvconvert.c                |  4 ++
- tools/lvcreate.c                 |  2 +
- 17 files changed, 256 insertions(+), 55 deletions(-)
-
-diff --git a/conf/example.conf.in b/conf/example.conf.in
-index d149ed9..107a071 100644
---- a/conf/example.conf.in
-+++ b/conf/example.conf.in
-@@ -494,6 +494,13 @@ allocation {
- 	# This configuration option has an automatic default value.
- 	# thin_pool_metadata_require_separate_pvs = 0
- 
-+	# Configuration option allocation/thin_pool_crop_metadata.
-+	# Older version of lvm2 cropped pool's metadata size to 15.81 GiB.
-+	# This is slightly less then the actual maximum 15.88 GiB.
-+	# For compatibility with older version and use of cropped size set to 1.
-+	# This configuration option has an automatic default value.
-+	# thin_pool_crop_metadata = 0
-+
- 	# Configuration option allocation/thin_pool_zero.
- 	# Thin pool data chunks are zeroed before they are first used.
- 	# Zeroing with a larger thin pool chunk size reduces performance.
-diff --git a/device_mapper/all.h b/device_mapper/all.h
-index 1080d25..489ca1c 100644
---- a/device_mapper/all.h
-+++ b/device_mapper/all.h
-@@ -1072,10 +1072,10 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
- #define DM_THIN_MIN_DATA_BLOCK_SIZE (UINT32_C(128))
- #define DM_THIN_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152))
- /*
-- * Max supported size for thin pool  metadata device (17112760320 bytes)
-- * Limitation is hardcoded into the kernel and bigger device size
-- * is not accepted.
-+ * Max supported size for thin pool metadata device (17045913600 bytes)
-  * drivers/md/dm-thin-metadata.h THIN_METADATA_MAX_SECTORS
-+ * But here DM_THIN_MAX_METADATA_SIZE got defined incorrectly
-+ * Correct size is (UINT64_C(255) * ((1 << 14) - 64) * (4096 / (1 << 9)))
-  */
- #define DM_THIN_MAX_METADATA_SIZE   (UINT64_C(255) * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024)
- 
-@@ -1088,6 +1088,16 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
- 				      uint64_t low_water_mark,
- 				      unsigned skip_block_zeroing);
- 
-+int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
-+					 uint64_t size,
-+					 uint64_t transaction_id,
-+					 const char *metadata_uuid,
-+					 const char *pool_uuid,
-+					 uint32_t data_block_size,
-+					 uint64_t low_water_mark,
-+					 unsigned skip_block_zeroing,
-+					 unsigned crop_metadata);
-+
- /* Supported messages for thin provision target */
- typedef enum {
- 	DM_THIN_MESSAGE_CREATE_SNAP,		/* device_id, origin_id */
-diff --git a/device_mapper/libdm-deptree.c b/device_mapper/libdm-deptree.c
-index 6ce956f..5b60dc9 100644
---- a/device_mapper/libdm-deptree.c
-+++ b/device_mapper/libdm-deptree.c
-@@ -3979,6 +3979,24 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
- 				      uint64_t low_water_mark,
- 				      unsigned skip_block_zeroing)
- {
-+	return dm_tree_node_add_thin_pool_target_v1(node, size, transaction_id,
-+						    metadata_uuid, pool_uuid,
-+						    data_block_size,
-+						    low_water_mark,
-+						    skip_block_zeroing,
-+						    1);
-+}
-+
-+int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
-+					 uint64_t size,
-+					 uint64_t transaction_id,
-+					 const char *metadata_uuid,
-+					 const char *pool_uuid,
-+					 uint32_t data_block_size,
-+					 uint64_t low_water_mark,
-+					 unsigned skip_block_zeroing,
-+					 unsigned crop_metadata)
-+{
- 	struct load_segment *seg, *mseg;
- 	uint64_t devsize = 0;
- 
-@@ -4005,17 +4023,18 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
- 	if (!_link_tree_nodes(node, seg->metadata))
- 		return_0;
- 
--	/* FIXME: more complex target may need more tweaks */
--	dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
--		devsize += mseg->size;
--		if (devsize > DM_THIN_MAX_METADATA_SIZE) {
--			log_debug_activation("Ignoring %" PRIu64 " of device.",
--					     devsize - DM_THIN_MAX_METADATA_SIZE);
--			mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
--			devsize = DM_THIN_MAX_METADATA_SIZE;
--			/* FIXME: drop remaining segs */
-+	if (crop_metadata)
-+		/* FIXME: more complex target may need more tweaks */
-+		dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
-+			devsize += mseg->size;
-+			if (devsize > DM_THIN_MAX_METADATA_SIZE) {
-+				log_debug_activation("Ignoring %" PRIu64 " of device.",
-+						     devsize - DM_THIN_MAX_METADATA_SIZE);
-+				mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
-+				devsize = DM_THIN_MAX_METADATA_SIZE;
-+				/* FIXME: drop remaining segs */
-+			}
- 		}
--	}
- 
- 	if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, pool_uuid))) {
- 		log_error("Missing pool uuid %s.", pool_uuid);
-diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
-index 8d27bd3..9a25482 100644
---- a/lib/activate/dev_manager.c
-+++ b/lib/activate/dev_manager.c
-@@ -261,7 +261,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
- 	int dmtask;
- 	int with_flush; /* TODO: arg for _info_run */
- 	void *target = NULL;
--	uint64_t target_start, target_length, start, length;
-+	uint64_t target_start, target_length, start, length, length_crop = 0;
- 	char *target_name, *target_params;
- 	const char *devname;
- 
-@@ -297,7 +297,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
- 		/* Uses max DM_THIN_MAX_METADATA_SIZE sectors for metadata device */
- 		if (lv_is_thin_pool_metadata(seg_status->seg->lv) &&
- 		    (length > DM_THIN_MAX_METADATA_SIZE))
--			length = DM_THIN_MAX_METADATA_SIZE;
-+			length_crop = DM_THIN_MAX_METADATA_SIZE;
- 
- 		/* Uses virtual size with headers for VDO pool device */
- 		if (lv_is_vdo_pool(seg_status->seg->lv))
-@@ -310,7 +310,9 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
- 			target = dm_get_next_target(dmt, target, &target_start,
- 						    &target_length, &target_name, &target_params);
- 
--			if ((start == target_start) && (length == target_length))
-+			if ((start == target_start) &&
-+			    ((length == target_length) ||
-+			     (length_crop && (length_crop == target_length))))
- 				break; /* Keep target_params when matching segment is found */
- 
- 			target_params = NULL; /* Marking this target_params unusable */
-diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
-index 3c4032e..cb4e23a 100644
---- a/lib/config/config_settings.h
-+++ b/lib/config/config_settings.h
-@@ -628,6 +628,11 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF
- cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
- 	"Thin pool metadata and data will always use different PVs.\n")
- 
-+cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 3, 12), NULL, 0, NULL,
-+	"Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
-+	"This is slightly less then the actual maximum 15.88 GiB.\n"
-+	"For compatibility with older version and use of cropped size set to 1.\n")
-+
- cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL,
- 	"Thin pool data chunks are zeroed before they are first used.\n"
- 	"Zeroing with a larger thin pool chunk size reduces performance.\n")
-diff --git a/lib/config/defaults.h b/lib/config/defaults.h
-index 708a575..bcc20cc 100644
---- a/lib/config/defaults.h
-+++ b/lib/config/defaults.h
-@@ -118,6 +118,8 @@
- #define DEFAULT_THIN_REPAIR_OPTION1 ""
- #define DEFAULT_THIN_REPAIR_OPTIONS_CONFIG "#S" DEFAULT_THIN_REPAIR_OPTION1
- #define DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
-+#define DEFAULT_THIN_POOL_CROP_METADATA 0
-+#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB (UINT64_C(255) * ((1 << 14) - 64) * 4)  /* KB */ /* 0x3f8040 blocks */
- #define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (DM_THIN_MAX_METADATA_SIZE / 2)  /* KB */
- #define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048  /* KB */
- #define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */
-diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
-index bc93a5d..4cee14a 100644
---- a/lib/format_text/flags.c
-+++ b/lib/format_text/flags.c
-@@ -72,6 +72,7 @@ static const struct flag _lv_flags[] = {
- 	{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
- 	{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
- 	{LV_METADATA_FORMAT, "METADATA_FORMAT", SEGTYPE_FLAG},
-+	{LV_CROP_METADATA, "CROP_METADATA", SEGTYPE_FLAG},
- 	{LV_CACHE_VOL, "CACHE_VOL", COMPATIBLE_FLAG},
- 	{LV_CACHE_USES_CACHEVOL, "CACHE_USES_CACHEVOL", SEGTYPE_FLAG},
- 	{LV_NOSCAN, NULL, 0},
-diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
-index 443d32c..445c4ad 100644
---- a/lib/metadata/lv_manip.c
-+++ b/lib/metadata/lv_manip.c
-@@ -5384,6 +5384,8 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
- 	uint32_t existing_extents;
- 	uint32_t seg_size = 0;
- 	uint32_t new_extents;
-+	uint64_t max_metadata_size;
-+	thin_crop_metadata_t crop;
- 	int reducing = 0;
- 
- 	seg_last = last_seg(lv);
-@@ -5544,6 +5546,33 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
- 					return 1;
- 				}
- 			}
-+		} else if (lv_is_thin_pool_metadata(lv)) {
-+			if (!(seg = get_only_segment_using_this_lv(lv)))
-+				return_0;
-+
-+			max_metadata_size = get_thin_pool_max_metadata_size(cmd, vg->profile, &crop);
-+
-+			if (((uint64_t)lp->extents * vg->extent_size) > max_metadata_size) {
-+				lp->extents = (max_metadata_size + vg->extent_size - 1) / vg->extent_size;
-+				log_print_unless_silent("Reached maximum pool metadata size %s (%" PRIu32 " extents).",
-+							display_size(vg->cmd, max_metadata_size), lp->extents);
-+			}
-+
-+			if (existing_logical_extents >= lp->extents)
-+				lp->extents = existing_logical_extents;
-+
-+			crop = get_thin_pool_crop_metadata(cmd, crop, (uint64_t)lp->extents * vg->extent_size);
-+
-+			if (seg->crop_metadata != crop) {
-+				seg->crop_metadata = crop;
-+				seg->lv->status |= LV_CROP_METADATA;
-+				/* Crop change require reload even if there no size change */
-+				lp->size_changed = 1;
-+				log_print_unless_silent("Thin pool will use metadata without cropping.");
-+			}
-+
-+			if (!(seg_size = lp->extents - existing_logical_extents))
-+				return 1;  /* No change in metadata size */
- 		}
- 	} else {  /* If reducing, find stripes, stripesize & size of last segment */
- 		if (lp->stripes || lp->stripe_size || lp->mirrors)
-@@ -8388,6 +8417,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
- 		first_seg(lv)->chunk_size = lp->chunk_size;
- 		first_seg(lv)->zero_new_blocks = lp->zero_new_blocks;
- 		first_seg(lv)->discards = lp->discards;
-+		if ((first_seg(lv)->crop_metadata = lp->crop_metadata) == THIN_CROP_METADATA_NO)
-+			lv->status |= LV_CROP_METADATA;
- 		if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->thin_chunk_size_calc_policy)) {
- 			stack;
- 			goto revert_new_lv;
-diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
-index 0aa2293..eff59ae 100644
---- a/lib/metadata/merge.c
-+++ b/lib/metadata/merge.c
-@@ -495,6 +495,8 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
- 			seg_error("sets discards");
- 		if (!dm_list_empty(&seg->thin_messages))
- 			seg_error("sets thin_messages list");
-+		if (seg->lv->status & LV_CROP_METADATA)
-+			seg_error("sets CROP_METADATA flag");
- 	}
- 
- 	if (seg_is_thin_volume(seg)) {
-diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
-index 54dc29f..0e57722 100644
---- a/lib/metadata/metadata-exported.h
-+++ b/lib/metadata/metadata-exported.h
-@@ -143,6 +143,7 @@
- 
- #define LV_REMOVE_AFTER_RESHAPE	UINT64_C(0x0400000000000000)	/* LV needs to be removed after a shrinking reshape */
- #define LV_METADATA_FORMAT	UINT64_C(0x0800000000000000)    /* LV has segments with metadata format */
-+#define LV_CROP_METADATA	UINT64_C(0x0000000000000400)	/* LV - also VG CLUSTERED */
- 
- #define LV_RESHAPE		UINT64_C(0x1000000000000000)    /* Ongoing reshape (number of stripes, stripesize or raid algorithm change):
- 								   used as SEGTYPE_FLAG to prevent activation on old runtime */
-@@ -326,6 +327,12 @@ typedef enum {
- } thin_discards_t;
- 
- typedef enum {
-+	THIN_CROP_METADATA_UNSELECTED = 0,  /* 'auto' selects */
-+	THIN_CROP_METADATA_NO,
-+	THIN_CROP_METADATA_YES,
-+} thin_crop_metadata_t;
-+
-+typedef enum {
- 	CACHE_MODE_UNSELECTED = 0,
- 	CACHE_MODE_WRITETHROUGH,
- 	CACHE_MODE_WRITEBACK,
-@@ -502,6 +509,7 @@ struct lv_segment {
- 	uint64_t transaction_id;		/* For thin_pool, thin */
- 	thin_zero_t zero_new_blocks;		/* For thin_pool */
- 	thin_discards_t discards;		/* For thin_pool */
-+	thin_crop_metadata_t crop_metadata;	/* For thin_pool */
- 	struct dm_list thin_messages;		/* For thin_pool */
- 	struct logical_volume *external_lv;	/* For thin */
- 	struct logical_volume *pool_lv;		/* For thin, cache */
-@@ -885,6 +893,8 @@ int update_thin_pool_params(struct cmd_context *cmd,
- 			    unsigned attr,
- 			    uint32_t pool_data_extents,
- 			    uint32_t *pool_metadata_extents,
-+			    struct logical_volume *metadata_lv,
-+			    unsigned *crop_metadata,
- 			    int *chunk_size_calc_method, uint32_t *chunk_size,
- 			    thin_discards_t *discards, thin_zero_t *zero_new_blocks);
- 
-@@ -1011,6 +1021,7 @@ struct lvcreate_params {
- 
- 	uint64_t permission; /* all */
- 	unsigned error_when_full; /* when segment supports it */
-+	thin_crop_metadata_t crop_metadata;
- 	uint32_t read_ahead; /* all */
- 	int approx_alloc;     /* all */
- 	alloc_policy_t alloc; /* all */
-diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
-index 2c22450..0f230e4 100644
---- a/lib/metadata/metadata.h
-+++ b/lib/metadata/metadata.h
-@@ -512,8 +512,21 @@ int pool_below_threshold(const struct lv_segment *pool_seg);
- int pool_check_overprovisioning(const struct logical_volume *lv);
- int create_pool(struct logical_volume *pool_lv, const struct segment_type *segtype,
- 		struct alloc_handle *ah, uint32_t stripes, uint32_t stripe_size);
-+uint64_t get_thin_pool_max_metadata_size(struct cmd_context *cmd, struct profile *profile,
-+					 thin_crop_metadata_t *crop);
-+thin_crop_metadata_t get_thin_pool_crop_metadata(struct cmd_context *cmd,
-+						  thin_crop_metadata_t crop,
-+						  uint64_t metadata_size);
- uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size);
- 
-+int update_pool_metadata_min_max(struct cmd_context *cmd,
-+				 uint32_t extent_size,
-+				 uint64_t min_metadata_size,		/* required min */
-+				 uint64_t max_metadata_size,		/* writable max */
-+				 uint64_t *metadata_size,		/* current calculated */
-+				 struct logical_volume *metadata_lv,	/* name of converted LV or NULL */
-+				 uint32_t *metadata_extents);		/* resulting extent count */
-+
- /*
-  * Begin skeleton for external LVM library
-  */
-diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
-index a9dc611..b67882e 100644
---- a/lib/metadata/pool_manip.c
-+++ b/lib/metadata/pool_manip.c
-@@ -742,6 +742,52 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
- 	return 1;
- }
- 
-+int update_pool_metadata_min_max(struct cmd_context *cmd,
-+				 uint32_t extent_size,
-+				 uint64_t min_metadata_size,		/* required min */
-+				 uint64_t max_metadata_size,		/* writable max */
-+				 uint64_t *metadata_size,		/* current calculated */
-+				 struct logical_volume *metadata_lv,	/* name of converted LV or NULL */
-+				 uint32_t *metadata_extents)		/* resulting extent count */
-+{
-+	max_metadata_size = dm_round_up(max_metadata_size, extent_size);
-+	min_metadata_size = dm_round_up(min_metadata_size, extent_size);
-+
-+	if (*metadata_size > max_metadata_size) {
-+		if (metadata_lv) {
-+			log_print_unless_silent("Size %s of pool metadata volume %s is bigger then maximum usable size %s.",
-+						display_size(cmd, *metadata_size),
-+						display_lvname(metadata_lv),
-+						display_size(cmd, max_metadata_size));
-+		} else {
-+			if (*metadata_extents)
-+				log_print_unless_silent("Reducing pool metadata size %s to maximum usable size %s.",
-+							display_size(cmd, *metadata_size),
-+							display_size(cmd, max_metadata_size));
-+			*metadata_size = max_metadata_size;
-+		}
-+	} else if (*metadata_size < min_metadata_size) {
-+		if (metadata_lv) {
-+			log_error("Can't use volume %s with size %s as pool metadata. Minimal required size is %s.",
-+				  display_lvname(metadata_lv),
-+				  display_size(cmd, *metadata_size),
-+				  display_size(cmd, min_metadata_size));
-+			return 0;
-+		} else {
-+			if (*metadata_extents)
-+				log_print_unless_silent("Extending pool metadata size %s to required minimal size %s.",
-+							display_size(cmd, *metadata_size),
-+							display_size(cmd, min_metadata_size));
-+			*metadata_size = min_metadata_size;
-+		}
-+	}
-+
-+	if (!(*metadata_extents = extents_from_size(cmd, *metadata_size, extent_size)))
-+		return_0;
-+
-+	return 1;
-+}
-+
- int vg_set_pool_metadata_spare(struct logical_volume *lv)
- {
- 	char new_name[NAME_LEN];
-diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
-index 4591dd7..451c382 100644
---- a/lib/metadata/thin_manip.c
-+++ b/lib/metadata/thin_manip.c
-@@ -610,9 +610,9 @@ static uint64_t _estimate_metadata_size(uint32_t data_extents, uint32_t extent_s
- }
- 
- /* Estimate maximal supportable thin pool data size for given chunk_size */
--static uint64_t _estimate_max_data_size(uint32_t chunk_size)
-+static uint64_t _estimate_max_data_size(uint64_t max_metadata_size, uint32_t chunk_size)
- {
--	return  chunk_size * (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2) * SECTOR_SIZE / UINT64_C(64);
-+	return  max_metadata_size * chunk_size * SECTOR_SIZE / UINT64_C(64);
- }
- 
- /* Estimate thin pool chunk size from data and metadata size (in sector units) */
-@@ -662,6 +662,38 @@ int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct
- 	return 1;
- }
- 
-+/* Return max supported metadata size with selected cropping */
-+uint64_t get_thin_pool_max_metadata_size(struct cmd_context *cmd, struct profile *profile,
-+					 thin_crop_metadata_t *crop)
-+{
-+	*crop = find_config_tree_bool(cmd, allocation_thin_pool_crop_metadata_CFG, profile) ?
-+		THIN_CROP_METADATA_YES : THIN_CROP_METADATA_NO;
-+
-+	return (*crop == THIN_CROP_METADATA_NO) ?
-+		(2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB) : (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE);
-+}
-+
-+/*
-+ * With existing crop method, check if the metadata_size would need cropping.
-+ * If not, set UNSELECTED, otherwise print some verbose info about selected cropping
-+ */
-+thin_crop_metadata_t get_thin_pool_crop_metadata(struct cmd_context *cmd,
-+						  thin_crop_metadata_t crop,
-+						  uint64_t metadata_size)
-+{
-+	const uint64_t crop_size = (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE);
-+
-+	if (metadata_size > crop_size) {
-+		if (crop == THIN_CROP_METADATA_NO)
-+			log_verbose("Using metadata size without cropping.");
-+		else
-+			log_verbose("Cropping metadata size to %s.", display_size(cmd, crop_size));
-+	} else
-+		crop = THIN_CROP_METADATA_UNSELECTED;
-+
-+	return crop;
-+}
-+
- int update_thin_pool_params(struct cmd_context *cmd,
- 			    struct profile *profile,
- 			    uint32_t extent_size,
-@@ -669,10 +701,13 @@ int update_thin_pool_params(struct cmd_context *cmd,
- 			    unsigned attr,
- 			    uint32_t pool_data_extents,
- 			    uint32_t *pool_metadata_extents,
-+			    struct logical_volume *metadata_lv,
-+			    thin_crop_metadata_t *crop_metadata,
- 			    int *chunk_size_calc_method, uint32_t *chunk_size,
- 			    thin_discards_t *discards, thin_zero_t *zero_new_blocks)
- {
--	uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
-+	uint64_t pool_metadata_size;
-+	uint64_t max_metadata_size;
- 	uint32_t estimate_chunk_size;
- 	uint64_t max_pool_data_size;
- 	const char *str;
-@@ -702,7 +737,9 @@ int update_thin_pool_params(struct cmd_context *cmd,
- 		*zero_new_blocks = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile)
- 			? THIN_ZERO_YES : THIN_ZERO_NO;
- 
--	if (!pool_metadata_size) {
-+	max_metadata_size = get_thin_pool_max_metadata_size(cmd, profile, crop_metadata);
-+
-+	if (!*pool_metadata_extents) {
- 		if (!*chunk_size) {
- 			if (!get_default_allocation_thin_pool_chunk_size(cmd, profile,
- 									 chunk_size,
-@@ -723,20 +760,20 @@ int update_thin_pool_params(struct cmd_context *cmd,
- 		} else {
- 			pool_metadata_size = _estimate_metadata_size(pool_data_extents, extent_size, *chunk_size);
- 
--			if (pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) {
-+			if (pool_metadata_size > max_metadata_size) {
- 				/* Suggest bigger chunk size */
- 				estimate_chunk_size =
- 					_estimate_chunk_size(pool_data_extents, extent_size,
--							     (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2), attr);
-+							     max_metadata_size, attr);
- 				log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.",
- 					 display_size(cmd, estimate_chunk_size));
- 			}
- 		}
- 
- 		/* Round up to extent size silently */
--		if (pool_metadata_size % extent_size)
--			pool_metadata_size += extent_size - pool_metadata_size % extent_size;
-+		pool_metadata_size = dm_round_up(pool_metadata_size, extent_size);
- 	} else {
-+		pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
- 		estimate_chunk_size = _estimate_chunk_size(pool_data_extents, extent_size,
- 							   pool_metadata_size, attr);
- 
-@@ -751,7 +788,19 @@ int update_thin_pool_params(struct cmd_context *cmd,
- 		}
- 	}
- 
--	max_pool_data_size = _estimate_max_data_size(*chunk_size);
-+	/* Use not rounded max for data size */
-+	max_pool_data_size = _estimate_max_data_size(max_metadata_size, *chunk_size);
-+
-+	if (!update_pool_metadata_min_max(cmd, extent_size,
-+					  2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE,
-+					  max_metadata_size,
-+					  &pool_metadata_size,
-+					  metadata_lv,
-+					  pool_metadata_extents))
-+		return_0;
-+
-+	*crop_metadata = get_thin_pool_crop_metadata(cmd, *crop_metadata, pool_metadata_size);
-+
- 	if ((max_pool_data_size / extent_size) < pool_data_extents) {
- 		log_error("Selected chunk size %s cannot address more then %s of thin pool data space.",
- 			  display_size(cmd, *chunk_size), display_size(cmd, max_pool_data_size));
-@@ -764,22 +813,6 @@ int update_thin_pool_params(struct cmd_context *cmd,
- 	if (!validate_thin_pool_chunk_size(cmd, *chunk_size))
- 		return_0;
- 
--	if (pool_metadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
--		pool_metadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
--		if (*pool_metadata_extents)
--			log_warn("WARNING: Maximum supported pool metadata size is %s.",
--				 display_size(cmd, pool_metadata_size));
--	} else if (pool_metadata_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
--		pool_metadata_size = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
--		if (*pool_metadata_extents)
--			log_warn("WARNING: Minimum supported pool metadata size is %s.",
--				 display_size(cmd, pool_metadata_size));
--	}
--
--	if (!(*pool_metadata_extents =
--	      extents_from_size(cmd, pool_metadata_size, extent_size)))
--		return_0;
--
- 	if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
- 		log_error("Size of %s data volume cannot be smaller than chunk size %s.",
- 			  segtype->name, display_size(cmd, *chunk_size));
-@@ -958,12 +991,5 @@ int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size)
- 
- uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size)
- {
--	uint64_t sz = _estimate_metadata_size(data_extents, extent_size, chunk_size);
--
--	if (sz > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE))
--		sz = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
--	else if (sz < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE))
--		sz = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
--
--	return sz;
-+	return _estimate_metadata_size(data_extents, extent_size, chunk_size);
- }
-diff --git a/lib/thin/thin.c b/lib/thin/thin.c
-index ba0da71..51bc269 100644
---- a/lib/thin/thin.c
-+++ b/lib/thin/thin.c
-@@ -86,6 +86,7 @@ static int _thin_pool_text_import(struct lv_segment *seg,
- 	struct logical_volume *pool_data_lv, *pool_metadata_lv;
- 	const char *discards_str = NULL;
- 	uint32_t zero = 0;
-+	uint32_t crop = 0;
- 
- 	if (!dm_config_get_str(sn, "metadata", &lv_name))
- 		return SEG_LOG_ERROR("Metadata must be a string in");
-@@ -131,6 +132,13 @@ static int _thin_pool_text_import(struct lv_segment *seg,
- 
- 	seg->zero_new_blocks = (zero) ? THIN_ZERO_YES : THIN_ZERO_NO;
- 
-+	if (dm_config_has_node(sn, "crop_metadata")) {
-+		if (!dm_config_get_uint32(sn, "crop_metadata", &crop))
-+			return SEG_LOG_ERROR("Could not read crop_metadata for");
-+		seg->crop_metadata = (crop) ? THIN_CROP_METADATA_YES : THIN_CROP_METADATA_NO;
-+		seg->lv->status |= LV_CROP_METADATA;
-+	}
-+
- 	/* Read messages */
- 	for (; sn; sn = sn->sib)
- 		if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child))
-@@ -177,6 +185,9 @@ static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter
- 		return 0;
- 	}
- 
-+	if (seg->crop_metadata != THIN_CROP_METADATA_UNSELECTED)
-+		outf(f, "crop_metadata = %u", (seg->crop_metadata == THIN_CROP_METADATA_YES) ? 1 : 0);
-+
- 	dm_list_iterate_items(tmsg, &seg->thin_messages) {
- 		/* Extra validation */
- 		switch (tmsg->type) {
-@@ -307,11 +318,12 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
- 	else
- 		low_water_mark = 0;
- 
--	if (!dm_tree_node_add_thin_pool_target(node, len,
--					       seg->transaction_id,
--					       metadata_dlid, pool_dlid,
--					       seg->chunk_size, low_water_mark,
--					       (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1))
-+	if (!dm_tree_node_add_thin_pool_target_v1(node, len,
-+						  seg->transaction_id,
-+						  metadata_dlid, pool_dlid,
-+						  seg->chunk_size, low_water_mark,
-+						  (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1,
-+						  (seg->crop_metadata == THIN_CROP_METADATA_YES) ? 1 : 0))
- 		return_0;
- 
- 	if (attr & THIN_FEATURE_DISCARDS) {
-diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main
-index e6f1d63..3ce34a5 100644
---- a/man/lvmthin.7_main
-+++ b/man/lvmthin.7_main
-@@ -1104,7 +1104,7 @@ The default value is shown by:
- The amount of thin metadata depends on how many blocks are shared between
- thin LVs (i.e. through snapshots).  A thin pool with many snapshots may
- need a larger metadata LV.  Thin pool metadata LV sizes can be from 2MiB
--to 16GiB.
-+to approximately 16GiB.
- 
- When using lvcreate to create what will become a thin metadata LV, the
- size is specified with the -L|--size option.
-@@ -1119,6 +1119,14 @@ needed, so it is recommended to start with a size of 1GiB which should be
- enough for all practical purposes.  A thin pool metadata LV can later be
- manually or automatically extended if needed.
- 
-+Configurable setting
-+.BR lvm.conf (5)
-+.BR allocation / thin_pool_crop_metadata
-+gives control over cropping to 15.81GiB to stay backward compatible with older
-+versions of lvm2. With enabled cropping there can be observed some problems when
-+using volumes above this size with thin tools (i.e. thin_repair).
-+Cropping should be enabled only when compatibility is required.
-+
- 
- .SS Create a thin snapshot of an external, read only LV
- 
-diff --git a/tools/lvconvert.c b/tools/lvconvert.c
-index 7b74afb..ce90279 100644
---- a/tools/lvconvert.c
-+++ b/tools/lvconvert.c
-@@ -3032,6 +3032,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
- 	const char *policy_name;
- 	struct dm_config_tree *policy_settings = NULL;
- 	int pool_metadata_spare;
-+	thin_crop_metadata_t crop_metadata;
- 	thin_discards_t discards;
- 	thin_zero_t zero_new_blocks;
- 	int r = 0;
-@@ -3196,6 +3197,8 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
- 					     pool_segtype, target_attr,
- 					     lv->le_count,
- 					     &meta_extents,
-+					     metadata_lv,
-+					     &crop_metadata,
- 					     &chunk_calc,
- 					     &chunk_size,
- 					     &discards, &zero_new_blocks))
-@@ -3401,6 +3404,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
- 			goto_bad;
- 	} else {
- 		seg->transaction_id = 0;
-+		seg->crop_metadata = crop_metadata;
- 		seg->chunk_size = chunk_size;
- 		seg->discards = discards;
- 		seg->zero_new_blocks = zero_new_blocks;
-diff --git a/tools/lvcreate.c b/tools/lvcreate.c
-index e384291..1ee9e14 100644
---- a/tools/lvcreate.c
-+++ b/tools/lvcreate.c
-@@ -391,6 +391,8 @@ static int _update_extents_params(struct volume_group *vg,
- 						     lp->segtype, lp->target_attr,
- 						     lp->extents,
- 						     &lp->pool_metadata_extents,
-+						     NULL,
-+						     &lp->crop_metadata,
- 						     &lp->thin_chunk_size_calc_policy,
- 						     &lp->chunk_size,
- 						     &lp->discards,
diff --git a/SOURCES/lvm2-2_03_12-writecache-use-cleaner-message-instead-of-table-relo.patch b/SOURCES/lvm2-2_03_12-writecache-use-cleaner-message-instead-of-table-relo.patch
deleted file mode 100644
index 9f08576..0000000
--- a/SOURCES/lvm2-2_03_12-writecache-use-cleaner-message-instead-of-table-relo.patch
+++ /dev/null
@@ -1,45 +0,0 @@
- lib/metadata/writecache_manip.c | 10 +++++++---
- tools/lvconvert.c               |  2 ++
- 2 files changed, 9 insertions(+), 3 deletions(-)
-
-diff --git a/lib/metadata/writecache_manip.c b/lib/metadata/writecache_manip.c
-index 5004aa9..8150d07 100644
---- a/lib/metadata/writecache_manip.c
-+++ b/lib/metadata/writecache_manip.c
-@@ -75,7 +75,7 @@ static int _get_writecache_kernel_status(struct cmd_context *cmd,
- 		return 0;
- 	}
- 
--	if (!lv_info_with_seg_status(cmd, first_seg(lv), &status, 1, 1)) {
-+	if (!lv_info_with_seg_status(cmd, first_seg(lv), &status, 0, 0)) {
- 		log_error("Failed to get device mapper status for %s", display_lvname(lv));
- 		goto fail;
- 	}
-@@ -434,8 +434,12 @@ int lv_writecache_set_cleaner(struct logical_volume *lv)
- 	seg->writecache_settings.cleaner_set = 1;
- 
- 	if (lv_is_active(lv)) {
--		if (!lv_update_and_reload(lv)) {
--			log_error("Failed to update VG and reload LV.");
-+		if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
-+			log_error("Failed to update VG.");
-+			return 0;
-+		}
-+		if (!lv_writecache_message(lv, "cleaner")) {
-+			log_error("Failed to set writecache cleaner for %s.", display_lvname(lv));
- 			return 0;
- 		}
- 	} else {
-diff --git a/tools/lvconvert.c b/tools/lvconvert.c
-index 4323965..7b74afb 100644
---- a/tools/lvconvert.c
-+++ b/tools/lvconvert.c
-@@ -5720,6 +5720,8 @@ static int _lvconvert_detach_writecache_when_clean(struct cmd_context *cmd,
- 		return 0;
- 	}
- 
-+	log_debug("detach writecache check clean reading vg %s", id->vg_name);
-+
- 	vg = vg_read(cmd, id->vg_name, NULL, READ_FOR_UPDATE, lockd_state, &error_flags, NULL);
- 
- 	if (!vg) {
diff --git a/SOURCES/lvm2-2_03_13-device_id-handle-scsi_debug-wwid.patch b/SOURCES/lvm2-2_03_13-device_id-handle-scsi_debug-wwid.patch
new file mode 100644
index 0000000..84cc940
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-device_id-handle-scsi_debug-wwid.patch
@@ -0,0 +1,18 @@
+ lib/device/device_id.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/lib/device/device_id.c b/lib/device/device_id.c
+index f158e4f..9cc82f1 100644
+--- a/lib/device/device_id.c
++++ b/lib/device/device_id.c
+@@ -308,6 +308,10 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
+ 
+ 		if (!sysbuf[0])
+ 			_read_sys_block(cmd, dev, "wwid", sysbuf, sizeof(sysbuf));
++
++		/* scsi_debug wwid begins "t10.Linux   scsi_debug ..." */
++		if (strstr(sysbuf, "scsi_debug"))
++			sysbuf[0] = '\0';
+ 	}
+ 
+ 	else if (idtype == DEV_ID_TYPE_SYS_SERIAL)
diff --git a/SOURCES/lvm2-2_03_13-devices-don-t-use-deleted-loop-backing-file-for-devi.patch b/SOURCES/lvm2-2_03_13-devices-don-t-use-deleted-loop-backing-file-for-devi.patch
new file mode 100644
index 0000000..6de11be
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-devices-don-t-use-deleted-loop-backing-file-for-devi.patch
@@ -0,0 +1,21 @@
+ lib/device/device_id.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/lib/device/device_id.c b/lib/device/device_id.c
+index 67f72e5..1b98487 100644
+--- a/lib/device/device_id.c
++++ b/lib/device/device_id.c
+@@ -325,8 +325,12 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
+ 	else if (idtype == DEV_ID_TYPE_MD_UUID)
+ 		_read_sys_block(cmd, dev, "md/uuid", sysbuf, sizeof(sysbuf));
+ 
+-	else if (idtype == DEV_ID_TYPE_LOOP_FILE)
++	else if (idtype == DEV_ID_TYPE_LOOP_FILE) {
+ 		_read_sys_block(cmd, dev, "loop/backing_file", sysbuf, sizeof(sysbuf));
++		/* if backing file is deleted, fall back to devname */
++		if (strstr(sysbuf, "(deleted)"))
++			sysbuf[0] = '\0';
++	}
+ 
+ 	else if (idtype == DEV_ID_TYPE_DEVNAME) {
+ 		if (!(idname = strdup(dev_name(dev))))
diff --git a/SOURCES/lvm2-2_03_13-enable-command-syntax-for-thin-and-writecache.patch b/SOURCES/lvm2-2_03_13-enable-command-syntax-for-thin-and-writecache.patch
new file mode 100644
index 0000000..652b0b7
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-enable-command-syntax-for-thin-and-writecache.patch
@@ -0,0 +1,25 @@
+ tools/command-lines.in | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/command-lines.in b/tools/command-lines.in
+index 1107c1e..67c37ff 100644
+--- a/tools/command-lines.in
++++ b/tools/command-lines.in
+@@ -534,7 +534,7 @@ RULE: all and lv_is_visible
+ 
+ ---
+ 
+-lvconvert --type thin-pool LV_linear_striped_raid_cache_error_zero
++lvconvert --type thin-pool LV_linear_striped_raid_cache_writecache_error_zero
+ OO: --stripes_long Number, --stripesize SizeKB,
+ OO_LVCONVERT_THINPOOL, OO_LVCONVERT_POOL, OO_LVCONVERT
+ OP: PV ...
+@@ -566,7 +566,7 @@ RULE: --poolmetadata not --readahead --stripesize --stripes_long
+ # This command syntax is deprecated, and the primary forms
+ # of creating a pool or swapping metadata should be used.
+ 
+-lvconvert --thinpool LV_linear_striped_raid_cache_thinpool
++lvconvert --thinpool LV_linear_striped_raid_cache_writecache_thinpool
+ OO: --stripes_long Number, --stripesize SizeKB,
+ OO_LVCONVERT_THINPOOL, OO_LVCONVERT_POOL, OO_LVCONVERT
+ OP: PV ...
diff --git a/SOURCES/lvm2-2_03_13-lvconvert-allow-writecache-with-other-thinpool-comma.patch b/SOURCES/lvm2-2_03_13-lvconvert-allow-writecache-with-other-thinpool-comma.patch
new file mode 100644
index 0000000..2875b22
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-lvconvert-allow-writecache-with-other-thinpool-comma.patch
@@ -0,0 +1,16 @@
+ tools/lvconvert.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/lvconvert.c b/tools/lvconvert.c
+index 8dd8a15..6066d1f 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -4803,7 +4803,7 @@ static int _lvconvert_to_pool_or_swap_metadata_single(struct cmd_context *cmd,
+ 
+ 	switch (cmd->command->command_enum) {
+ 	case lvconvert_to_thinpool_or_swap_metadata_CMD:
+-		if (lv_is_cache(lv))
++		if (lv_is_cache(lv) || lv_is_writecache(lv))
+ 			/* For cached LV check the cache origin LV type */
+ 			lvt_enum = get_lvt_enum(seg_lv(first_seg(lv), 0));
+ 		to_thinpool = 1;
diff --git a/SOURCES/lvm2-2_03_13-lvconvert-fix-vdo-virtual-size-when-specified.patch b/SOURCES/lvm2-2_03_13-lvconvert-fix-vdo-virtual-size-when-specified.patch
new file mode 100644
index 0000000..7758cca
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-lvconvert-fix-vdo-virtual-size-when-specified.patch
@@ -0,0 +1,17 @@
+ lib/metadata/vdo_manip.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/lib/metadata/vdo_manip.c b/lib/metadata/vdo_manip.c
+index 7d5a2cb..afc513a 100644
+--- a/lib/metadata/vdo_manip.c
++++ b/lib/metadata/vdo_manip.c
+@@ -393,7 +393,8 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
+ 	} else {
+ 		log_verbose("Skiping VDO formating %s.", display_lvname(data_lv));
+ 		/* TODO: parse existing VDO data and retrieve vdo_logical_size */
+-		vdo_logical_size = data_lv->size;
++		if (!*virtual_extents)
++			vdo_logical_size = data_lv->size;
+ 	}
+ 
+ 	if (!deactivate_lv(data_lv->vg->cmd, data_lv)) {
diff --git a/SOURCES/lvm2-2_03_13-lvmdevices-add-deviceidtype-option.patch b/SOURCES/lvm2-2_03_13-lvmdevices-add-deviceidtype-option.patch
new file mode 100644
index 0000000..6d4e6bf
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-lvmdevices-add-deviceidtype-option.patch
@@ -0,0 +1,211 @@
+ lib/device/device_id.c | 32 ++++++++++++++----------
+ man/lvmdevices.8_des   | 68 +++++++++++++++++++++++++++++++++++++++-----------
+ tools/args.h           |  5 ++++
+ tools/command-lines.in |  1 +
+ tools/lvmdevices.c     |  7 ++++--
+ 5 files changed, 84 insertions(+), 29 deletions(-)
+
+diff --git a/lib/device/device_id.c b/lib/device/device_id.c
+index 1b98487..f158e4f 100644
+--- a/lib/device/device_id.c
++++ b/lib/device/device_id.c
+@@ -931,6 +931,7 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
+ 	/*
+ 	 * Choose the device_id type for the device being added.
+ 	 *
++	 * 0. use an idtype specified by the user
+ 	 * 1. use an idtype specific to a special/virtual device type
+ 	 *    e.g. loop, mpath, crypt, lvmlv, md, etc.
+ 	 * 2. use an idtype specified by user option.
+@@ -939,6 +940,24 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
+ 	 * 5. use devname as the last resort.
+ 	 */
+ 
++	if (idtype_arg) {
++		if (!(idtype = idtype_from_str(idtype_arg)))
++			log_warn("WARNING: ignoring unknown device_id type %s.", idtype_arg);
++		else {
++			if (id_arg) {
++				if ((idname = strdup(id_arg)))
++					goto id_done;
++				log_warn("WARNING: ignoring device_id name %s.", id_arg);
++			}
++
++			if ((idname = device_id_system_read(cmd, dev, idtype)))
++				goto id_done;
++
++			log_warn("WARNING: ignoring deviceidtype %s which is not available for device.", idtype_arg);
++			idtype = 0;
++		}
++	}
++
+ 	if (MAJOR(dev->dev) == cmd->dev_types->device_mapper_major) {
+ 		if (_dev_has_mpath_uuid(cmd, dev, &idname)) {
+ 			idtype = DEV_ID_TYPE_MPATH_UUID;
+@@ -972,19 +991,6 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
+ 		log_warn("Missing support for DRBD idtype");
+ 	}
+ 
+-	if (idtype_arg) {
+-		if (!(idtype = idtype_from_str(idtype_arg)))
+-			log_warn("WARNING: ignoring unknown device_id type %s.", idtype_arg);
+-		else {
+-			if (id_arg) {
+-				if (!(idname = strdup(id_arg)))
+-					stack;
+-				goto id_done;
+-			}
+-			goto id_name;
+-		}
+-	}
+-
+ 	/*
+ 	 * No device-specific, existing, or user-specified idtypes,
+ 	 * so use first available of sys_wwid / sys_serial / devname.
+diff --git a/man/lvmdevices.8_des b/man/lvmdevices.8_des
+index 015aa11..2335456 100644
+--- a/man/lvmdevices.8_des
++++ b/man/lvmdevices.8_des
+@@ -9,18 +9,18 @@ remove it from the devices file with lvmdevices --deldev.  The
+ vgimportdevices(8) command adds all PVs from a VG to the devices file,
+ and updates the VG metadata to include device IDs of the PVs.
+ .P
+-Commands adding new devices to the devices file necessarily look outside
+-the existing devices file to find the devices to add.  pvcreate, vgcreate,
+-and vgextend also look outside the devices file to create new PVs and add
+-them to the devices file.
++Commands that add new devices to the devices file necessarily look outside
++the existing devices file to find the devices being added.  pvcreate,
++vgcreate, and vgextend also look outside the devices file to create new
++PVs and add those PVs to the devices file.
+ .P
+ LVM records devices in the devices file using hardware-specific IDs, such
+ as the WWID, and attempts to use subsystem-specific IDs for virtual device
+-types (which also aim to be as unique and stable as possible.)
+-These device IDs are also written in the VG metadata.  When no hardware or
++types (which also aim to be as unique and stable as possible.) These
++device IDs are also written in the VG metadata.  When no hardware or
+ virtual ID is available, lvm falls back using the unstable device name as
+-the device ID.  When devnames are used, lvm performs extra scanning to
+-find devices if their devname changes, e.g. after reboot.
++the device ID.  When devnames are used as IDs, lvm performs extra scanning
++to find devices if their devname changes, e.g. after reboot.
+ .P
+ When proper device IDs are used, an lvm command will not look at devices
+ outside the devices file, but when devnames are used as a fallback, lvm
+@@ -34,12 +34,13 @@ overriding the devices file.  The listed devices act as a sort of devices
+ file in terms of limiting which devices lvm will see and use.  Devices
+ that are not listed will appear to be missing to the lvm command.
+ .P
+-Multiple devices files can be kept in \fI#DEFAULT_SYS_DIR#/devices\fP, which allows lvm
+-to be used with different sets of devices, e.g. system devices do not need
+-to be exposed to a specific application, and the application can use lvm on
+-its own devices that are not exposed to the system.  The option
+---devicesfile <filename> is used to select the devices file to use with the
+-command.  Without the option set, the default system devices file is used.
++Multiple devices files can be kept \fI#DEFAULT_SYS_DIR#/devices\fP, which
++allows lvm to be used with different sets of devices.  For example, system
++devices do not need to be exposed to a specific application, and the
++application can use lvm on its own devices that are not exposed to the
++system.  The option --devicesfile <filename> is used to select the devices
++file to use with the command.  Without the option set, the default system
++devices file is used.
+ .P
+ Setting --devicesfile "" causes lvm to not use a devices file.
+ .P
+@@ -59,3 +60,42 @@ if it does not yet exist.
+ .P
+ It is recommended to use lvm commands to make changes to the devices file to
+ ensure proper updates.
++.P
++The device ID and device ID type are included in the VG metadata and can
++be reported with pvs -o deviceid,deviceidtype.  (Note that the lvmdevices
++command does not update VG metadata, but subsequent lvm commands modifying
++the metadata will include the device ID.)
++.P
++Possible device ID types are:
++.br
++.IP \[bu] 2
++.B sys_wwid
++uses the wwid reported by sysfs.  This is the first choice for non-virtual
++devices.
++.IP \[bu] 2
++.B sys_serial
++uses the serial number reported by sysfs.  This is the second choice for
++non-virtual devices.
++.IP \[bu] 2
++.B mpath_uuid
++is used for dm multipath devices, reported by sysfs.
++.IP \[bu] 2
++.B crypt_uuid
++is used for dm crypt devices, reported by sysfs.
++.IP \[bu] 2
++.B md_uuid
++is used for md devices, reported by sysfs.
++.B lvmlv_uuid
++is used if a PV is placed on top of an lvm LV, reported by sysfs.
++.IP \[bu] 2
++.B loop_file
++is used for loop devices, the backing file name repored by sysfs.
++.IP \[bu] 2
++.B devname
++the device name is used if no other type applies.
++.P
++
++The default choice for device ID type can be overriden using lvmdevices
++--addev --deviceidtype <type>.  If the specified type is available for the
++device it will be used, otherwise the device will be added using the type
++that would otherwise be chosen.
+diff --git a/tools/args.h b/tools/args.h
+index 741c82b..d4f23f8 100644
+--- a/tools/args.h
++++ b/tools/args.h
+@@ -228,6 +228,11 @@ arg(detachprofile_ARG, '\0', "detachprofile", 0, 0, 0,
+     "Detaches a metadata profile from a VG or LV.\n"
+     "See \\fBlvm.conf\\fP(5) for more information about profiles.\n")
+ 
++arg(deviceidtype_ARG, '\0', "deviceidtype", string_VAL, 0, 0,
++    "The type of device ID to use for the device.\n"
++    "If the specified type is available for the device,\n"
++    "then it will override the default type that lvm would use.\n")
++
+ arg(devices_ARG, '\0', "devices", pv_VAL, ARG_GROUPABLE, 0,
+     "Devices that the command can use. This option can be repeated\n"
+     "or accepts a comma separated list of devices. This overrides\n"
+diff --git a/tools/command-lines.in b/tools/command-lines.in
+index 67c37ff..8607305 100644
+--- a/tools/command-lines.in
++++ b/tools/command-lines.in
+@@ -1430,6 +1430,7 @@ ID: lvmdevices_update
+ DESC: Update the devices file to fix incorrect values.
+ 
+ lvmdevices --adddev PV
++OO: --deviceidtype String
+ ID: lvmdevices_edit
+ DESC: Add a device to the devices file.
+ 
+diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c
+index 6b3e056..3448bdd 100644
+--- a/tools/lvmdevices.c
++++ b/tools/lvmdevices.c
+@@ -265,6 +265,7 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
+ 
+ 	if (arg_is_set(cmd, adddev_ARG)) {
+ 		const char *devname;
++		const char *deviceidtype;
+ 
+ 		if (!(devname = arg_str_value(cmd, adddev_ARG, NULL)))
+ 			goto_bad;
+@@ -311,8 +312,10 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
+ 				 dev_name(dev), dev_filtered_reason(dev));
+ 		}
+ 
+-		/* allow deviceidtype_ARG/deviceid_ARG ? */
+-		if (!device_id_add(cmd, dev, dev->pvid, NULL, NULL))
++		/* also allow deviceid_ARG ? */
++		deviceidtype = arg_str_value(cmd, deviceidtype_ARG, NULL);
++
++		if (!device_id_add(cmd, dev, dev->pvid, deviceidtype, NULL))
+ 			goto_bad;
+ 		if (!device_ids_write(cmd))
+ 			goto_bad;
diff --git a/SOURCES/lvm2-2_03_13-lvremove-fix-removing-thin-pool-with-writecache-on-d.patch b/SOURCES/lvm2-2_03_13-lvremove-fix-removing-thin-pool-with-writecache-on-d.patch
new file mode 100644
index 0000000..45a878d
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-lvremove-fix-removing-thin-pool-with-writecache-on-d.patch
@@ -0,0 +1,150 @@
+ lib/metadata/lv_manip.c                | 19 +++++++++
+ lib/metadata/metadata-exported.h       |  2 +
+ lib/metadata/thin_manip.c              | 12 ++++++
+ test/shell/lvremove-thindata-caches.sh | 71 ++++++++++++++++++++++++++++++++++
+ 4 files changed, 104 insertions(+)
+ create mode 100644 test/shell/lvremove-thindata-caches.sh
+
+diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
+index 508f78c..37dd361 100644
+--- a/lib/metadata/lv_manip.c
++++ b/lib/metadata/lv_manip.c
+@@ -6692,6 +6692,25 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
+ 			return_0;
+ 	}
+ 
++	/* if thin pool data lv is writecache, then detach and remove the writecache */
++	if (lv_is_thin_pool(lv)) {
++		struct logical_volume *data_lv = data_lv_from_thin_pool(lv);
++
++		if (data_lv && lv_is_writecache(data_lv)) {
++			struct logical_volume *cachevol_lv = first_seg(data_lv)->writecache;
++
++			if (!lv_detach_writecache_cachevol(data_lv, 1)) {
++				log_error("Failed to detach writecache from %s", display_lvname(data_lv));
++				return 0;
++			}
++
++			if (!lv_remove_single(cmd, cachevol_lv, force, 1)) {
++				log_error("Failed to remove cachevol %s.", display_lvname(cachevol_lv));
++				return 0;
++			}
++		}
++	}
++
+ 	if (lv_is_writecache(lv)) {
+ 		struct logical_volume *cachevol_lv = first_seg(lv)->writecache;
+ 
+diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
+index c611635..54bc0d0 100644
+--- a/lib/metadata/metadata-exported.h
++++ b/lib/metadata/metadata-exported.h
+@@ -927,6 +927,8 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
+ int vg_set_pool_metadata_spare(struct logical_volume *lv);
+ int vg_remove_pool_metadata_spare(struct volume_group *vg);
+ 
++struct logical_volume *data_lv_from_thin_pool(struct logical_volume *pool_lv);
++
+ int attach_thin_external_origin(struct lv_segment *seg,
+ 				struct logical_volume *external_lv);
+ int detach_thin_external_origin(struct lv_segment *seg);
+diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
+index 451c382..6ce88bd 100644
+--- a/lib/metadata/thin_manip.c
++++ b/lib/metadata/thin_manip.c
+@@ -21,6 +21,18 @@
+ #include "lib/config/defaults.h"
+ #include "lib/display/display.h"
+ 
++struct logical_volume *data_lv_from_thin_pool(struct logical_volume *pool_lv)
++{
++	struct lv_segment *seg_thinpool = first_seg(pool_lv);
++
++	if (!seg_thinpool || !seg_is_thin_pool(seg_thinpool)) {
++		log_error(INTERNAL_ERROR "data_lv_from_thin_pool arg not thin pool %s", pool_lv->name);
++		return NULL;
++	}
++
++	return seg_thinpool->areas[0].u.lv.lv;
++}
++
+ /* TODO: drop unused no_update */
+ int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type,
+ 			struct logical_volume *lv, uint32_t delete_id,
+diff --git a/test/shell/lvremove-thindata-caches.sh b/test/shell/lvremove-thindata-caches.sh
+new file mode 100644
+index 0000000..ba099c3
+--- /dev/null
++++ b/test/shell/lvremove-thindata-caches.sh
+@@ -0,0 +1,71 @@
++#!/usr/bin/env bash
++
++# Copyright (C) 2017-2020 Red Hat, Inc. All rights reserved.
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions
++# of the GNU General Public License v.2.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software Foundation,
++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++
++SKIP_WITH_LVMPOLLD=1
++
++. lib/inittest
++
++aux have_cache 1 10 0 || skip
++aux have_writecache 1 0 0 || skip
++which mkfs.xfs || skip
++
++aux prepare_devs 6 70 # want 64M of usable space from each dev
++
++vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6"
++
++# lv1 is thinpool LV: 128M
++# lv2 is fast LV:      64M
++# lv3 is thin LV:       1G
++
++#
++# Test lvremove of a thinpool that uses cache|writecache on data
++#
++
++# attach writecache to thinpool data
++lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2"
++lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg
++lvcreate -n $lv2 -L64M -an $vg "$dev3"
++lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1
++lvchange -ay $vg/$lv1
++lvs -a $vg
++mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3"
++lvremove -y $vg/$lv1
++
++# attach cache/writeback (cachevol) to thinpool data
++lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2"
++lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg
++lvcreate -n $lv2 -L64M -an $vg "$dev3"
++lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1
++lvchange -ay $vg/$lv1
++mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3"
++lvremove -y $vg/$lv1
++
++# attach cache/writethrough (cachevol) to thinpool data
++lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2"
++lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg
++lvcreate -n $lv2 -L64M -an $vg "$dev3"
++lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1
++lvchange -ay $vg/$lv1
++mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3"
++lvremove -y $vg/$lv1
++
++# attach cache (cachepool) to thinpool data
++lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2"
++lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg
++lvcreate -y --type cache-pool -n $lv2 -L64M --poolmetadataspare n $vg "$dev3" "$dev6"
++lvconvert -y --type cache --cachepool $lv2 --poolmetadataspare n $vg/$lv1
++lvchange -ay $vg/$lv1
++mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3"
++lvremove -y $vg/$lv1
++
++vgremove -f $vg
++
diff --git a/SOURCES/lvm2-2_03_13-man-vdoimport-page.patch b/SOURCES/lvm2-2_03_13-man-vdoimport-page.patch
new file mode 100644
index 0000000..fe6032c
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-man-vdoimport-page.patch
@@ -0,0 +1,102 @@
+ man/vdoimport.8_main | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 92 insertions(+)
+ create mode 100644 man/vdoimport.8_main
+
+diff --git a/man/vdoimport.8_main b/man/vdoimport.8_main
+new file mode 100644
+index 0000000..1f32909
+--- /dev/null
++++ b/man/vdoimport.8_main
+@@ -0,0 +1,92 @@
++.TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
++.
++.SH "NAME"
++.
++vdoimport \(em utility to import VDO volumes into a new volume group.
++.
++.SH SYNOPSIS
++.
++.PD 0
++.ad l
++.TP 10
++.B vdoimport
++.RI [ options ]
++.IR device
++.
++.PD
++.
++.SH DESCRIPTION
++.
++vdoimport utility imports VDO volumes created and managed by
++.BR vdo (8)
++manager into
++.BR lvm2 (8)
++managed VDO LV. This is realized by moving VDO superblock by 2MiB
++and creating lvm2 metadata at the front of this device. The operation is not reversible,
++thus after conversion to lvm2 the access to VDO data is only possible with
++.BR lvm2 (8)
++commands,
++.BR vdo (8)
++manager no longer control such volume.
++.
++.SH OPTIONS
++.
++.TP
++.BR -f | --force
++Bypass some sanity checks.
++.
++.TP
++.BR -h | --help
++Display the help text.
++.
++.TP
++.BR -n | --name
++Specifies the name of converted VDO LV. When the name is not specified,
++some automatic name is selected. In case the converted VDO volume is
++already using LV a backend device, the name of this LV is used for VDO LV.
++In this case also the of volume group must stay same.
++.
++.TP
++.BR -v | --verbose
++Be more verbose.
++.
++.TP
++.BR -y | --yes
++Answer "yes" at any prompts.
++.
++.TP
++.BR --dry-run
++Print commands without running them.
++.
++.
++.SH DIAGNOSTICS
++.
++On successful completion, the status code is 0.
++A status code of 1 is used for failure.
++.
++.SH EXAMPLES
++.
++Convert VDO volume created by vdo manager into logical volume LV1 with within volume group VG1.
++.P
++#
++.B vdoimport --name VG1/LV1 /dev/mapper/vdo-volume
++.
++.SH ENVIRONMENT VARIABLES
++.
++.TP
++.B TMPDIR
++The temporary directory name for mount points. Defaults to "\fI/tmp\fP".
++.TP
++.B DM_DEV_DIR
++The device directory name.
++Defaults to "\fI/dev\fP" and must be an absolute path.
++.
++.SH SEE ALSO
++.
++.nh
++.ad l
++.BR lvm (8),
++.BR lvm.conf (5),
++.P
++.BR vdo (8),
++.BR vdo2lvm (8),
diff --git a/SOURCES/lvm2-2_03_13-test.patch b/SOURCES/lvm2-2_03_13-test.patch
new file mode 100644
index 0000000..f6672b7
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-test.patch
@@ -0,0 +1,61 @@
+ test/shell/vgsplit-cache.sh | 47 +++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 47 insertions(+)
+
+diff --git a/test/shell/vgsplit-cache.sh b/test/shell/vgsplit-cache.sh
+index eba85be..202e4b5 100644
+--- a/test/shell/vgsplit-cache.sh
++++ b/test/shell/vgsplit-cache.sh
+@@ -75,6 +75,53 @@ lvremove -y $vg
+ vgremove -ff $vg
+ vgremove -ff $vg1
+ 
++#
++# Check we handle pmspare for splitted VGs
++#
++aux prepare_vg 7
++
++# Create cache-pool and pmspare on single PV1
++lvcreate -L10 --type cache-pool $vg/cpool "$dev1"
++# Move spare to separate PV3
++pvmove -n $vg/lvol0_pmspare "$dev1" "$dev3"
++# Create origin on PV2
++lvcreate -L10 -n orig $vg  "$dev2"
++lvconvert -H -y --cachepool $vg/cpool $vg/orig
++
++vgchange -an $vg
++
++# Check we do not create new _pmspare
++vgsplit --poolmetadataspare n  $vg $vg1 "$dev2" "$dev1"
++
++check lv_exists $vg/lvol0_pmspare
++check lv_not_exists $vg1/lvol0_pmspare
++
++vgremove $vg
++vgremove -f $vg1
++
++
++aux prepare_vg 7
++
++# Again - now with handling _pmspare by vgsplit
++lvcreate -L10 --type cache-pool $vg/cpool "$dev1"
++# Move spare to separate PV3
++pvmove -n $vg/lvol0_pmspare "$dev1" "$dev3"
++# Create origin on PV2
++lvcreate -L10 -n orig $vg  "$dev2"
++lvconvert -H -y --cachepool $vg/cpool $vg/orig
++
++vgchange -an $vg
++
++# Handle _pmspare  (default)
++vgsplit --poolmetadataspare y  $vg $vg1 "$dev2" "$dev1"
++
++check lv_not_exists $vg/lvol0_pmspare
++check lv_exists $vg1/lvol0_pmspare
++
++vgremove $vg
++vgremove -f $vg1
++
++
+ vgcreate $vg "$dev1" "$dev2" "$dev3" "$dev4"
+ 
+ lvcreate -L6 -n $lv1 -an $vg "$dev2"
diff --git a/SOURCES/lvm2-2_03_13-tests-extend-vgmerge-testing.patch b/SOURCES/lvm2-2_03_13-tests-extend-vgmerge-testing.patch
new file mode 100644
index 0000000..22dca89
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-tests-extend-vgmerge-testing.patch
@@ -0,0 +1,53 @@
+ test/shell/vgmerge-operation.sh | 42 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+
+diff --git a/test/shell/vgmerge-operation.sh b/test/shell/vgmerge-operation.sh
+index 21889e9..0bf517d 100644
+--- a/test/shell/vgmerge-operation.sh
++++ b/test/shell/vgmerge-operation.sh
+@@ -80,3 +80,45 @@ grep "Duplicate logical volume name \"$lv1\" in \"$vg2\" and \"$vg1" err
+ check pvlv_counts $vg1 2 1 0
+ check pvlv_counts $vg2 2 1 0
+ vgremove -f $vg1 $vg2
++
++
++# 'vgmerge' handle pmspare for merged VG
++if aux have_thin 1 5 0; then
++
++# With disabled pmspare nothing is created
++vgcreate $vg1 "$dev1" "$dev2"
++vgcreate $vg2 "$dev3" "$dev4"
++lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M --poolmetadataspare n
++lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M --poolmetadataspare n
++vgchange -an $vg1 $vg2
++
++vgmerge --poolmetadataspare n $vg1 $vg2
++check lv_not_exists $vg/lvol0_pmspare
++vgremove -ff $vg1
++
++
++# With pmspare handling there are one created
++vgcreate $vg1 "$dev1" "$dev2"
++vgcreate $vg2 "$dev3" "$dev4"
++lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M --poolmetadataspare n
++lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M --poolmetadataspare n
++vgchange -an $vg1 $vg2
++
++vgmerge $vg1 $vg2
++check lv_field $vg1/lvol0_pmspare size "8.00m"
++vgremove -ff $vg1
++
++
++# When merged, bigger pmspare is preserved
++vgcreate $vg1 "$dev1" "$dev2"
++vgcreate $vg2 "$dev3" "$dev4"
++lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M
++lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M
++vgchange -an $vg1 $vg2
++
++vgmerge $vg1 $vg2
++
++check lv_field $vg1/lvol0_pmspare size "8.00m"
++vgremove -ff $vg1
++
++fi
diff --git a/SOURCES/lvm2-2_03_13-thin-fix-component-detection-of-external-origin.patch b/SOURCES/lvm2-2_03_13-thin-fix-component-detection-of-external-origin.patch
new file mode 100644
index 0000000..5b97d90
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-thin-fix-component-detection-of-external-origin.patch
@@ -0,0 +1,63 @@
+ WHATS_NEW                          |  1 +
+ lib/activate/activate.c            |  5 ++++-
+ test/shell/lvconvert-cache-thin.sh | 22 ++++++++++++++++++++++
+ 3 files changed, 27 insertions(+), 1 deletion(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 5806ecb..097160e 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,6 @@
+ Version 2.03.13 - 
+ ===============================
++  Fix detection of active components of external origin volume.
+   Add vdoimport tool to support conversion of VDO volumes.
+   Support configurable allocation/vdo_pool_header_size.
+   Fix handling of lvconvert --type vdo-pool --virtualsize.
+diff --git a/lib/activate/activate.c b/lib/activate/activate.c
+index 6bda738..94fc944 100644
+--- a/lib/activate/activate.c
++++ b/lib/activate/activate.c
+@@ -2740,7 +2740,10 @@ static int _component_cb(struct logical_volume *lv, void *data)
+ 	    (lv_is_thin_pool(lv) && pool_is_active(lv)))
+ 		return -1;
+ 
+-	if (lv_is_active(lv)) {
++	/* External origin is activated through thinLV and uses -real suffix.
++	 * Note: for old clustered logic we would need to check for all thins */
++	if ((lv_is_external_origin(lv) && lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0)) ||
++	    lv_is_active(lv)) {
+ 		if (!lv_is_component(lv) || lv_is_visible(lv))
+ 			return -1;	/* skip whole subtree */
+ 
+diff --git a/test/shell/lvconvert-cache-thin.sh b/test/shell/lvconvert-cache-thin.sh
+index 7dda6e6..9254239 100644
+--- a/test/shell/lvconvert-cache-thin.sh
++++ b/test/shell/lvconvert-cache-thin.sh
+@@ -67,4 +67,26 @@ fail lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv
+ # Thin-pool CAN use cached data LV
+ lvconvert --yes --thinpool $vg/$lv
+ 
++lvremove -f $vg
++
++# Check we can active snapshot of cached external origin (BZ: 1967744)
++lvcreate -T -L10M $vg/pool "$dev1"
++
++lvcreate -L10M -n origin $vg "$dev1"
++lvcreate -H -L4M -n CPOOL $vg/origin "$dev2"
++
++# Use cached origin as external origin
++lvconvert -y -T --thinpool $vg/pool --originname extorig origin
++
++# Check we can easily create snapshot of such LV
++lvcreate -y -kn -n snap -s $vg/origin
++
++# Deactivate everything and do a component activation of _cmeta volume
++lvchange -an $vg
++lvchange -ay -y $vg/CPOOL_cpool_cmeta
++
++# Now this must fail since component volume is active
++not lvcreate -y -kn -n snap2 -s $vg/origin |& tee err
++grep "cmeta is active" err
++
+ vgremove -f $vg
diff --git a/SOURCES/lvm2-2_03_13-vdo-add-vdoimport-support.patch b/SOURCES/lvm2-2_03_13-vdo-add-vdoimport-support.patch
new file mode 100644
index 0000000..aed2254
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-vdo-add-vdoimport-support.patch
@@ -0,0 +1,729 @@
+ WHATS_NEW                 |   3 +
+ configure                 |  25 +++
+ configure.ac              |  15 ++
+ include/configure.h.in    |   3 +
+ man/Makefile.in           |   7 +-
+ scripts/Makefile.in       |   4 +
+ scripts/vdoimport.sh      | 376 ++++++++++++++++++++++++++++++++++++++++++++++
+ test/Makefile.in          |   1 +
+ test/shell/vdo-convert.sh | 110 ++++++++++++++
+ 9 files changed, 543 insertions(+), 1 deletion(-)
+ create mode 100755 scripts/vdoimport.sh
+ create mode 100644 test/shell/vdo-convert.sh
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 04c6dcd..5806ecb 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,8 @@
+ Version 2.03.13 - 
+ ===============================
++  Add vdoimport tool to support conversion of VDO volumes.
++  Support configurable allocation/vdo_pool_header_size.
++  Fix handling of lvconvert --type vdo-pool --virtualsize.
+   Fix load of kvdo target when it is not present in memory (2.03.12).
+ 
+ Version 2.03.12 - 07th May 2021
+diff --git a/configure b/configure
+index 7c6bd48..661702d 100755
+--- a/configure
++++ b/configure
+@@ -643,6 +643,8 @@ WRITE_INSTALL
+ WRITECACHE
+ VDO_LIB
+ VDO_INCLUDE
++VDOIMPORT_PATH
++VDOIMPORT
+ VDO
+ VALGRIND_POOL
+ USRSBINDIR
+@@ -966,6 +968,7 @@ enable_dbus_service
+ enable_pkgconfig
+ enable_write_install
+ enable_fsadm
++enable_vdoimport
+ enable_blkdeactivate
+ enable_dmeventd
+ enable_selinux
+@@ -1701,6 +1704,7 @@ Optional Features:
+   --enable-pkgconfig      install pkgconfig support
+   --enable-write_install  install user writable files
+   --disable-fsadm         disable fsadm
++  --disable-vdoimport     disable vdoimport
+   --disable-blkdeactivate disable blkdeactivate
+   --enable-dmeventd       enable the device-mapper event daemon
+   --disable-selinux       disable selinux support
+@@ -3128,6 +3132,7 @@ case "$host_os" in
+ 		DM_IOCTLS=yes
+ 		SELINUX=yes
+ 		FSADM=yes
++		VDOIMPORT=yes
+ 		BLKDEACTIVATE=yes
+ 		;;
+ 	darwin*)
+@@ -3141,6 +3146,7 @@ case "$host_os" in
+ 		DM_IOCTLS=no
+ 		SELINUX=no
+ 		FSADM=no
++		VDOIMPORT=no
+ 		BLKDEACTIVATE=no
+ 		;;
+ 	*)
+@@ -12371,6 +12377,18 @@ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FSADM" >&5
+ $as_echo "$FSADM" >&6; }
+ 
++
++################################################################################
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install vdoimport" >&5
++$as_echo_n "checking whether to install vdoimport... " >&6; }
++# Check whether --enable-vdoimport was given.
++if test "${enable_vdoimport+set}" = set; then :
++  enableval=$enable_vdoimport; VDOIMPORT=$enableval
++fi
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $VDOIMPORT" >&5
++$as_echo "$VDOIMPORT" >&6; }
++
+ ################################################################################
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install blkdeactivate" >&5
+ $as_echo_n "checking whether to install blkdeactivate... " >&6; }
+@@ -13857,6 +13875,13 @@ cat >>confdefs.h <<_ACEOF
+ _ACEOF
+ 
+ 
++VDOIMPORT_PATH="$SBINDIR/vdoimport"
++
++cat >>confdefs.h <<_ACEOF
++#define VDOIMPORT_PATH "$VDOIMPORT_PATH"
++_ACEOF
++
++
+ ################################################################################
+ if test "$BUILD_DMEVENTD" = yes; then
+ 
+diff --git a/configure.ac b/configure.ac
+index 1a49e7f..5a8b486 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -45,6 +45,7 @@ case "$host_os" in
+ 		DM_IOCTLS=yes
+ 		SELINUX=yes
+ 		FSADM=yes
++		VDOIMPORT=yes
+ 		BLKDEACTIVATE=yes
+ 		;;
+ 	darwin*)
+@@ -58,6 +59,7 @@ case "$host_os" in
+ 		DM_IOCTLS=no
+ 		SELINUX=no
+ 		FSADM=no
++		VDOIMPORT=no
+ 		BLKDEACTIVATE=no
+ 		;;
+ 	*)
+@@ -1291,6 +1293,14 @@ AC_ARG_ENABLE(fsadm, AC_HELP_STRING([--disable-fsadm], [disable fsadm]),
+ 	      FSADM=$enableval)
+ AC_MSG_RESULT($FSADM)
+ 
++
++################################################################################
++dnl -- Enable vdoimport
++AC_MSG_CHECKING(whether to install vdoimport)
++AC_ARG_ENABLE(vdoimport, AC_HELP_STRING([--disable-vdoimport], [disable vdoimport]),
++	      VDOIMPORT=$enableval)
++AC_MSG_RESULT($VDOIMPORT)
++
+ ################################################################################
+ dnl -- Enable blkdeactivate
+ AC_MSG_CHECKING(whether to install blkdeactivate)
+@@ -1646,6 +1656,9 @@ USRSBINDIR="$(eval echo $(eval echo $usrsbindir))"
+ FSADM_PATH="$SBINDIR/fsadm"
+ AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
+ 
++VDOIMPORT_PATH="$SBINDIR/vdoimport"
++AC_DEFINE_UNQUOTED(VDOIMPORT_PATH, ["$VDOIMPORT_PATH"], [Path to vdoimport binary.])
++
+ ################################################################################
+ dnl -- dmeventd pidfile and executable path
+ if test "$BUILD_DMEVENTD" = yes; then
+@@ -1882,6 +1895,8 @@ AC_SUBST(SILENT_RULES)
+ AC_SUBST(USRSBINDIR)
+ AC_SUBST(VALGRIND_POOL)
+ AC_SUBST(VDO)
++AC_SUBST(VDOIMPORT)
++AC_SUBST(VDOIMPORT_PATH)
+ AC_SUBST(VDO_FORMAT_CMD)
+ AC_SUBST(VDO_INCLUDE)
+ AC_SUBST(VDO_LIB)
+diff --git a/include/configure.h.in b/include/configure.h.in
+index 671d201..6df8d89 100644
+--- a/include/configure.h.in
++++ b/include/configure.h.in
+@@ -684,6 +684,9 @@
+ /* Enable a valgrind aware build of pool */
+ #undef VALGRIND_POOL
+ 
++/* Path to vdoimport binary. */
++#undef VDOIMPORT_PATH
++
+ /* The path to 'vdoformat', if available. */
+ #undef VDO_FORMAT_CMD
+ 
+diff --git a/man/Makefile.in b/man/Makefile.in
+index 29afc77..d60a92c 100644
+--- a/man/Makefile.in
++++ b/man/Makefile.in
+@@ -23,6 +23,7 @@ else
+ endif
+ 
+ FSADMMAN = fsadm.8
++VDOIMPORTMAN = vdoimport.8
+ BLKDEACTIVATEMAN = blkdeactivate.8
+ DMEVENTDMAN = dmeventd.8
+ DMFILEMAPDMAN = dmfilemapd.8
+@@ -50,7 +51,7 @@ MAN8SYSTEMD_GENERATORS=lvm2-activation-generator.8
+ 
+ ifeq (,$(findstring $(MAKECMDGOALS), distclean all_man install_all_man))
+   MAN7 += lvmcache.7 lvmthin.7 lvmvdo.7
+-  MAN8+=$(FSADMMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN)
++  MAN8+=$(FSADMMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN) $(VDOIMPORTMAN)
+   MAN8DM+=$(BLKDEACTIVATEMAN) $(DMEVENTDMAN) $(DMFILEMAPDMAN)
+   MAN8CLUSTER+=$(CMIRRORDMAN)
+ else
+@@ -58,6 +59,10 @@ else
+     MAN8+=$(FSADMMAN)
+   endif
+ 
++  ifeq ("@VDOIMPORT@", "yes")
++    MAN8+=$(VDOIMPORTMAN)
++  endif
++
+   ifeq ("@BUILD_LVMDBUSD@", "yes")
+     MAN8+=$(LVMDBUSDMAN)
+   endif
+diff --git a/scripts/Makefile.in b/scripts/Makefile.in
+index e8f6742..1fe88ca 100644
+--- a/scripts/Makefile.in
++++ b/scripts/Makefile.in
+@@ -31,6 +31,10 @@ ifeq ("@FSADM@", "yes")
+ 	LVM_SCRIPTS += fsadm.sh
+ endif
+ 
++ifeq ("@VDOIMPORT@", "yes")
++	LVM_SCRIPTS += vdoimport.sh
++endif
++
+ ifeq ("@BLKDEACTIVATE@", "yes")
+ 	DM_SCRIPTS += blkdeactivate.sh
+ endif
+diff --git a/scripts/vdoimport.sh b/scripts/vdoimport.sh
+new file mode 100755
+index 0000000..ef96591
+--- /dev/null
++++ b/scripts/vdoimport.sh
+@@ -0,0 +1,376 @@
++#!/bin/bash
++#
++# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
++#
++# This file is part of LVM2.
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions
++# of the GNU General Public License v.2.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software Foundation,
++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++#
++# Author: Zdenek Kabelac <zkabelac at redhat.com>
++#
++# Script for converting VDO volumes to lvm2 VDO LVs
++#
++# Needed utilities:
++#  lvm, dmsetup,
++#  vdo, vdo2lvm,
++#  grep, awk, sed, blockdev, readlink, mkdir
++#
++# Conversion is using  'vdo convert' support from VDO manager to move
++# existing VDO header by 2M which makes space to place in PV header
++# and VG metadata area, and then create VDOPOOL LV and VDO LV in such VG.
++#
++
++set -euE -o pipefail
++
++TOOL=vdoimport
++
++_SAVEPATH=$PATH
++PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH"
++
++# user may override lvm location by setting LVM_BINARY
++LVM=${LVM_BINARY:-lvm}
++VDO=${VDO_BINARY:-vdo}
++VDOCONF=${VDOCONF:-}
++BLOCKDEV="blockdev"
++READLINK="readlink"
++READLINK_E="-e"
++MKDIR="mkdir"
++
++TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$"
++DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
++
++DRY=0
++VERB=""
++FORCE=""
++YES=""
++
++# default name for converted VG and its VDO LV
++NAME="vdovg/vdolvol"
++
++# help message
++tool_usage() {
++	echo "${TOOL}: Utility to convert VDO volume to VDO LV."
++	echo
++	echo "	${TOOL} [options] <vdo_device_path>"
++	echo
++	echo "	Options:"
++	echo "	  -f | --force	      Bypass sanity checks"
++	echo "	  -h | --help	      Show this help message"
++	echo "	  -n | --name	      Specifies VG/LV name for converted VDO volume"
++	echo "	  -v | --verbose      Be verbose"
++	echo "	  -y | --yes	      Answer \"yes\" at any prompts"
++	echo "	       --dry-run      Print commands without running them"
++
++	exit
++}
++
++verbose() {
++	test -z "$VERB" || echo "$TOOL:" "$@"
++}
++
++# Support multi-line error messages
++error() {
++	for i in "$@" ;  do
++		echo "$TOOL: $i" >&2
++	done
++	cleanup 1
++}
++
++dry() {
++	if [ "$DRY" -ne 0 ]; then
++		verbose "Dry execution" "$@"
++		return 0
++	fi
++	verbose "Executing" "$@"
++	"$@"
++}
++
++cleanup() {
++	trap '' 2
++
++	rm -rf "$TEMPDIR"
++	# error exit status for break
++	exit "${1:-1}"
++}
++
++get_enabled_value_() {
++	case "$1" in
++	enabled) echo "1" ;;
++	*) echo "0" ;;
++	esac
++}
++
++get_kb_size_with_unit_() {
++	case "$1" in
++	*[kK]) echo $(( ${1%[kK]} )) ;;
++	*[mM]) echo $(( ${1%[mM]} * 1024 )) ;;
++	*[gG]) echo $(( ${1%[gG]} * 1024 * 1024 )) ;;
++	*[tT]) echo $(( ${1%[tT]} * 1024 * 1024 * 1024 )) ;;
++	*[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 * 1024 )) ;;
++	esac
++}
++
++get_mb_size_with_unit_() {
++	case "$1" in
++	*[mM]) echo $(( ${1%[mM]} )) ;;
++	*[gG]) echo $(( ${1%[gG]} * 1024 )) ;;
++	*[tT]) echo $(( ${1%[tT]} * 1024 * 1024 )) ;;
++	*[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 )) ;;
++	esac
++}
++
++# Figure out largest possible extent size usable for VG
++# $1   physical size
++# $2   logical size
++get_largest_extent_size_() {
++	local max=4
++	local i
++	local d
++
++	for i in 8 16 32 64 128 256 512 1024 2048 4096 ; do
++		d=$(( $1 / i ))
++		test $(( d * i )) -eq "$1" || break
++		d=$(( $2 / i ))
++		test $(( d * i )) -eq "$2" || break
++		max=$i
++	done
++	echo "$max"
++}
++
++# detect LV on the given device
++# dereference device name if it is symbolic link
++detect_lv_() {
++	local DEVICE=$1
++	local MAJOR
++	local MINOR
++	local SYSVOLUME
++	local MAJORMINOR
++
++	DEVICE=${1/#"${DM_DEV_DIR}/"/}
++	DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE")
++	test -n "$DEVICE" || error "Cannot get readlink \"$1\"."
++	RDEVICE=$DEVICE
++	case "$RDEVICE" in
++	  # hardcoded /dev  since udev does not create these entries elsewhere
++	  /dev/dm-[0-9]*)
++		read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME"
++		read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"."
++		MAJOR=${MAJORMINOR%%:*}
++		MINOR=${MAJORMINOR##*:}
++		;;
++	  *)
++		STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE")
++		test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"."
++		eval "$STAT"
++		;;
++	esac
++
++	eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
++}
++
++# parse yaml config files into 'prefix_yaml_part_names=("value")' strings
++parse_yaml_() {
++	local yaml_file=$1
++	local prefix=$2
++	local s
++	local w
++	local fs
++
++	s='[[:space:]]*'
++	w='[a-zA-Z0-9_.-]*'
++	fs="$(echo @|tr @ '\034')"
++
++	(
++	    sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/[[:space:]]*$//g;' \
++		-e 's/\$/\\\$/g' \
++		-e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \
++		-e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
++		-e "s|^\($s\)\($w\)${s}[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" |
++
++	    awk -F"$fs" '{
++		indent = length($1)/2;
++		if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";}
++		vname[indent] = $2;
++		for (i in vname) {if (i > indent) {delete vname[i]}}
++		    if (length($3) > 0) {
++			vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
++			printf("%s%s%s%s=(\"%s\")\n", "'"$prefix"'",vn, $2, conj[indent-1], $3);
++		    }
++		}' |
++
++	    sed -e 's/_=/+=/g' |
++
++	    awk 'BEGIN {
++		    FS="=";
++		    OFS="="
++		}
++		/(-|\.).*=/ {
++		    gsub("-|\\.", "_", $1)
++		}
++		{ print }'
++	) < "$yaml_file"
++}
++
++# convert existing VDO volume into lvm2 volume
++convert2lvm_() {
++	local DEVICE=$1
++	local VGNAME=${NAME%/*}
++	local LVNAME=${NAME#*/}
++	local VDONAME
++	local TRVDONAME
++	local EXTENTSZ
++	local IS_LV=1
++
++	DM_UUID=""
++	detect_lv_ "$DEVICE"
++	case "$DM_UUID" in
++		LVM-*)	eval "$(dmsetup splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
++			if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ]  ; then
++				VGNAME=$DM_VG_NAME
++			elif test "$VGNAME" != "$DM_VG_NAME" ; then
++				error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"."
++			fi
++			;;
++		*) IS_LV=0
++			# Check $VGNANE does not already exists
++			"$LVM" vgs "$VGNAME" && error "Cannot use already existing volume group name \"$VGNAME\"."
++			;;
++	esac
++
++	verbose "Checked whether device $1 is already LV ($IS_LV)."
++
++	"$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR."
++
++	verbose "Getting YAML VDO configuration."
++	"$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml"
++
++	VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
++	TRVDONAME=$(echo "$VDONAME" | tr '-' '_')
++
++	# When VDO volume is 'active', check it's not mounted/being used
++	eval "$(dmsetup info -c -o open  "$VDONAME" --noheadings --nameprefixes || true)"
++	test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
++
++	#parse_yaml_ "$TEMPDIR/vdoconf.yml" _
++	eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")"
++
++	vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize")
++	vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize")
++
++	verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB."
++	verbose "With logical volume of size $vdo_logicalSize KiB."
++
++	PARAMS=$(cat <<EOF
++allocation {
++	vdo_use_compression = $(get_enabled_value_ "$vdo_compression")
++	vdo_use_deduplication = $(get_enabled_value_ "$vdo_deduplication")
++	vdo_use_metadata_hints=1
++	vdo_minimum_io_size = $vdo_logicalBlockSize
++	vdo_block_map_cache_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize")
++	vdo_block_map_period = $vdo_blockMapPeriod
++	vdo_check_point_frequency = $vdo_indexCfreq
++	vdo_use_sparse_index = $(get_enabled_value_ "$vdo_indexSparse")
++	vdo_index_memory_size_mb = $(awk "BEGIN {print $vdo_indexMemory * 1024}")
++	vdo_slab_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize")
++	vdo_ack_threads = $vdo_ackThreads
++	vdo_bio_threads = $vdo_bioThreads
++	vdo_bio_rotation = $vdo_bioRotationInterval
++	vdo_cpu_threads = $vdo_cpuThreads
++	vdo_hash_zone_threads = $vdo_hashZoneThreads
++	vdo_logical_threads = $vdo_logicalThreads
++	vdo_physical_threads = $vdo_physicalThreads
++	vdo_write_policy = $vdo_writePolicy
++	vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") * 1024 ))
++	vdo_pool_header_size = 0
++}
++EOF
++)
++	verbose "VDO conversion paramaters: $PARAMS"
++
++	verbose "Stopping VDO volume."
++	dry "$VDO" stop $VDOCONF --name "$VDONAME"
++
++	if [ "$IS_LV" = "0" ]; then
++		verbose "Moving VDO header by 2MiB."
++		dry "$VDO" convert $VDOCONF --force --name "$VDONAME"
++
++		dry "$LVM" pvcreate $YES --dataalignment 2M "$DEVICE" || {
++			error "Creation of PV on \"$DEVICE\" failed, while VDO header has been already moved!"
++		}
++
++		# Obtain free space in this new PV
++		# after 'vdo convert/vdo2lvm' call there is +2M free space at the front of the device
++		case "$DRY" in
++		0) pvfree=$("$LVM" pvs -o devsize --units b --nosuffix --noheadings "$DEVICE") ;;
++		*) pvfree=$("$BLOCKDEV" --getsize64 "$DEVICE") ;;
++		esac
++
++		pvfree=$(( pvfree / 1024 - 2048 ))	# to KiB
++	else
++		pvfree=$("$LVM" lvs -o size --units b --nosuffix --noheadings "$VGNAME/$LVNAME")
++		pvfree=$(( pvfree / 1024 ))		# to KiB
++	fi
++
++	# select largest possible extent size that can exactly express both sizes
++	EXTENTSZ=$(get_largest_extent_size_ "$pvfree" "$vdo_logicalSize")
++
++	if [ "$IS_LV" = "0" ]; then
++		verbose "Creating VG \"${NAME%/*}\" with extent size $EXTENTSZ KiB."
++		dry "$LVM" vgcreate $YES $VERB -s "${EXTENTSZ}k" "$VGNAME" "$DEVICE" || {
++			error "Creation of VG \"$VGNAME\" failed, while VDO header has been already moved!"
++		}
++
++		verbose "Creating VDO pool data LV from all extents in volume group $VGNAME."
++		dry "$LVM" lvcreate -Zn -Wn $YES $VERB -l100%VG -n "${LVNAME}_vpool" "$VGNAME"
++	else
++		# validate existing  VG extent_size can express virtual VDO size
++		vg_extent_size=$("$LVM" vgs -o vg_extent_size --units b --nosuffix --noheadings "$VGNAME" || true)
++		vg_extent_size=$(( vg_extent_size / 1024 ))
++
++		test "$vg_extent_size" -le "$EXTENTSZ" || {
++			error "Please vgchange extent_size to at most $EXTENTSZ KiB or extend and align virtual size on $vg_extent_size KiB."
++		}
++		verbose "Renaming existing LV to be used as _vdata volume for VDO pool LV."
++		dry "$LVM" lvrename $YES $VERB "$VGNAME/$LVNAME" "$VGNAME/${LVNAME}_vpool" || {
++			error "Rename of LV \"$VGNAME/$LVNAME\" failed, while VDO header has been already moved!"
++		}
++	fi
++
++	verbose "Converting to VDO pool."
++	dry "$LVM" lvconvert $YES $VERB $FORCE --config "$PARAMS" -Zn -V "${vdo_logicalSize}k" -n "$LVNAME" --type vdo-pool "$VGNAME/${LVNAME}_vpool"
++
++	rm -fr "$TEMPDIR"
++}
++
++#############################
++# start point of this script
++# - parsing parameters
++#############################
++trap "cleanup 2" 2
++
++test "$#" -eq 0 && tool_usage
++
++while [ "$#" -ne 0 ]
++do
++	 case "$1" in
++	  "") ;;
++	  "-f"|"--force"  ) FORCE="-f" ;;
++	  "-h"|"--help"   ) tool_usage ;;
++	  "-n"|"--name"   ) shift; NAME=$1 ;;
++	  "-v"|"--verbose") VERB="-v" ;;
++	  "-y"|"--yes"    ) YES="-y" ;;
++	  "--dry-run"     ) DRY="1" ;;
++	  "-*") error "Wrong argument \"$1\". (see: $TOOL --help)" ;;
++	  *) DEVICENAME=$1 ;;  # device name does not start with '-'
++	esac
++	shift
++done
++
++# do conversion
++convert2lvm_ "$DEVICENAME"
+diff --git a/test/Makefile.in b/test/Makefile.in
+index e4cd3aa..6be03aa 100644
+--- a/test/Makefile.in
++++ b/test/Makefile.in
+@@ -353,6 +353,7 @@ LIB = $(addprefix lib/, $(LIB_SECURETEST) $(LIB_DMSECURETEST) $(LIB_SHARED) $(LI
+ 	$(Q) $(LN_S) -f $(abs_top_srcdir)/conf/lvmdbusd.profile lib/
+ 	$(Q) $(LN_S) -f $(abs_top_srcdir)/conf/thin-performance.profile lib/
+ 	$(Q) $(LN_S) -f $(abs_top_srcdir)/scripts/fsadm.sh lib/fsadm
++	$(Q) $(LN_S) -f $(abs_top_srcdir)/scripts/vdoimport.sh lib/vdoimport
+ 	@test "$(srcdir)" = . || \
+ 		for i in $(LIB_LVMLOCKD_CONF) $(LIB_MKE2FS_CONF); do \
+ 			test -n "$(Q)" || echo "$(LN_S) -f $(abs_top_srcdir)/test/lib/$$i lib/"; \
+diff --git a/test/shell/vdo-convert.sh b/test/shell/vdo-convert.sh
+new file mode 100644
+index 0000000..538147b
+--- /dev/null
++++ b/test/shell/vdo-convert.sh
+@@ -0,0 +1,110 @@
++#!/usr/bin/env bash
++
++# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions
++# of the GNU General Public License v.2.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software Foundation,
++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++
++# Test conversion of VDO volumes made by vdo manager into VDO LV.
++
++
++SKIP_WITH_LVMPOLLD=1
++
++. lib/inittest
++
++# Use local for this test vdo configuratoin
++VDOCONF="-f vdotestconf.yml"
++#VDOCONF=""
++export VDOCONF
++VDONAME="${PREFIX}-TESTVDO"
++
++# VDO automatically starts dmeventd
++aux prepare_dmeventd
++
++#
++# Main
++#
++which vdo || skip
++which mkfs.ext4 || skip
++export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf"
++
++aux have_vdo 6 2 0 || skip
++
++aux prepare_devs 2 10000
++
++aux extend_filter_LVMTEST
++
++
++#
++#  Check conversion of VDO volume made on some LV
++#
++#  In this case we do not need to move any VDO headers.
++#
++vgcreate $vg "$dev1"
++
++lvcreate -L5G -n $lv1 $vg
++
++vdo create $VDOCONF --name "$VDONAME" --device="$DM_DEV_DIR/$vg/$lv1" --vdoLogicalSize=10G
++
++mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
++
++# Different VG name fails
++not vdoimport -y -v --name $vg1/$lv1 "$DM_DEV_DIR/$vg/$lv1"
++
++# Try just dry run and observe logging
++vdoimport --dry-run -y -v --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
++
++vdoimport -y --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
++
++# ATM needed - since we do not call 'vdo convert' in this case
++vdo remove $VDOCONF --force --name "$VDONAME" || true
++
++vgremove -f $vg
++
++aux wipefs_a "$dev1"
++
++# prepare 'unused' $vg2
++vgcreate $vg2 "$dev2"
++
++#
++# Check conversion of VDO volume on  non-LV device
++#
++vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=31G
++
++mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
++
++# Fail with an already existing volume group $vg2
++not vdoimport --dry-run -y -v --name $vg2/$lv1 "$dev1" |& tee err
++grep "already existing volume group" err
++
++# User can also convert already stopped VDO volume
++vdo stop $VDOCONF --name "$VDONAME"
++
++vdoimport -y -v --name $vg/$lv1 "$dev1"
++
++fsck -n "$DM_DEV_DIR/$vg/$lv1"
++
++vgremove -f $vg
++
++
++#
++# Try once again with different vgname/lvname and sizes
++#
++aux teardown_devs
++aux prepare_devs 1 23456
++
++vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=23G
++
++mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
++
++vdoimport -y -v --name $vg1/$lv2 "$dev1"
++
++fsck -n "$DM_DEV_DIR/$vg1/$lv2"
++
++vgremove -f $vg1
++
diff --git a/SOURCES/lvm2-2_03_13-vdo-fix-preload-of-kvdo.patch b/SOURCES/lvm2-2_03_13-vdo-fix-preload-of-kvdo.patch
new file mode 100644
index 0000000..042ef0e
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-vdo-fix-preload-of-kvdo.patch
@@ -0,0 +1,37 @@
+ WHATS_NEW               |  4 ++++
+ lib/activate/activate.c | 10 +++-------
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 6f339a5..04c6dcd 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,3 +1,7 @@
++Version 2.03.13 - 
++===============================
++  Fix load of kvdo target when it is not present in memory (2.03.12).
++
+ Version 2.03.12 - 07th May 2021
+ ===============================
+   Allow attaching cache to thin data volume.
+diff --git a/lib/activate/activate.c b/lib/activate/activate.c
+index 71db981..6bda738 100644
+--- a/lib/activate/activate.c
++++ b/lib/activate/activate.c
+@@ -574,13 +574,9 @@ int module_present(struct cmd_context *cmd, const char *target_name)
+ 	}
+ 
+ #ifdef MODPROBE_CMD
+-	if (strcmp(target_name, MODULE_NAME_VDO) == 0) {
+-		argv[1] = target_name;		/* ATM kvdo is without dm- prefix */
+-		if ((ret = exec_cmd(cmd, argv, NULL, 0)))
+-			return ret;
+-	}
+-
+-	if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
++	if (strcmp(target_name, TARGET_NAME_VDO) == 0)
++		argv[1] = MODULE_NAME_VDO; /* ATM kvdo is without dm- prefix */
++	else if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
+ 		log_error("module_present module name too long: %s",
+ 			  target_name);
+ 		return 0;
diff --git a/SOURCES/lvm2-2_03_13-vdo-rename-variable-vdo_pool_zero.patch b/SOURCES/lvm2-2_03_13-vdo-rename-variable-vdo_pool_zero.patch
new file mode 100644
index 0000000..74b141c
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-vdo-rename-variable-vdo_pool_zero.patch
@@ -0,0 +1,50 @@
+ tools/lvconvert.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/tools/lvconvert.c b/tools/lvconvert.c
+index 6066d1f..8488596 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -5438,7 +5438,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
+ 					struct processing_handle *handle)
+ {
+ 	const char *vg_name = NULL;
+-	unsigned int zero_vdopool;
++	unsigned int vdo_pool_zero;
+ 	struct volume_group *vg = lv->vg;
+ 	struct logical_volume *vdo_lv;
+ 	struct dm_vdo_target_params vdo_params; /* vdo */
+@@ -5497,12 +5497,12 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
+ 		goto out;
+ 	}
+ 
+-	zero_vdopool = arg_int_value(cmd, zero_ARG, 1);
++	vdo_pool_zero = arg_int_value(cmd, zero_ARG, 1);
+ 
+ 	log_warn("WARNING: Converting logical volume %s to VDO pool volume %s formating.",
+-		 display_lvname(lv), zero_vdopool ? "with" : "WITHOUT");
++		 display_lvname(lv), vdo_pool_zero ? "with" : "WITHOUT");
+ 
+-	if (zero_vdopool)
++	if (vdo_pool_zero)
+ 		log_warn("THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.)");
+ 	else
+ 		log_warn("WARNING: Using invalid VDO pool data MAY DESTROY YOUR DATA!");
+@@ -5514,7 +5514,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
+ 		goto out;
+ 	}
+ 
+-	if (zero_vdopool) {
++	if (vdo_pool_zero) {
+ 		if (!wipe_lv(lv, (struct wipe_params) { .do_zero = 1, .do_wipe_signatures = 1,
+ 			     .yes = arg_count(cmd, yes_ARG),
+ 			     .force = arg_count(cmd, force_ARG)})) {
+@@ -5526,7 +5526,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
+ 	if (!archive(vg))
+ 		goto_out;
+ 
+-	if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents, zero_vdopool))
++	if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents, vdo_pool_zero))
+ 		goto_out;
+ 
+ 	dm_list_init(&lvc.tags);
diff --git a/SOURCES/lvm2-2_03_13-vdo-support-vdo_pool_header_size.patch b/SOURCES/lvm2-2_03_13-vdo-support-vdo_pool_header_size.patch
new file mode 100644
index 0000000..63235b0
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-vdo-support-vdo_pool_header_size.patch
@@ -0,0 +1,197 @@
+ conf/example.conf.in             |  5 +++++
+ lib/config/config_settings.h     |  3 +++
+ lib/config/defaults.h            |  3 +--
+ lib/metadata/lv_manip.c          |  3 ++-
+ lib/metadata/metadata-exported.h |  5 ++++-
+ lib/metadata/vdo_manip.c         | 13 ++++++++-----
+ tools/lvconvert.c                |  6 ++++--
+ tools/lvcreate.c                 |  2 +-
+ 8 files changed, 28 insertions(+), 12 deletions(-)
+
+diff --git a/conf/example.conf.in b/conf/example.conf.in
+index aaf73a4..78547a6 100644
+--- a/conf/example.conf.in
++++ b/conf/example.conf.in
+@@ -734,6 +734,11 @@ allocation {
+ 	# The default and minimum is 1. The maximum is UINT_MAX / 4096.
+ 	# This configuration option has an automatic default value.
+ 	# vdo_max_discard = 1
++
++	# Configuration option allocation/vdo_pool_header_size.
++	# Specified the emptry header size in KiB at the front and end of vdo pool device.
++	# This configuration option has an automatic default value.
++	# vdo_pool_header_size = 512
+ }
+ 
+ # Configuration section log.
+diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
+index f5dac4d..5217da8 100644
+--- a/lib/config/config_settings.h
++++ b/lib/config/config_settings.h
+@@ -816,6 +816,9 @@ cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, C
+ 	"increased latency for the individual discard requests.\n"
+ 	"The default and minimum is 1. The maximum is UINT_MAX / 4096.\n")
+ 
++cfg(allocation_vdo_pool_header_size_CFG, "vdo_pool_header_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_HEADER_SIZE_KB, vsn(2, 3, 12), NULL, 0, NULL,
++	"Specified the emptry header size in KiB at the front and end of vdo pool device.\n")
++
+ cfg(log_report_command_log_CFG, "report_command_log", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_BOOL, DEFAULT_COMMAND_LOG_REPORT, vsn(2, 2, 158), NULL, 0, NULL,
+ 	"Enable or disable LVM log reporting.\n"
+ 	"If enabled, LVM will collect a log of operations, messages,\n"
+diff --git a/lib/config/defaults.h b/lib/config/defaults.h
+index 2870dee..d5e5b3b 100644
+--- a/lib/config/defaults.h
++++ b/lib/config/defaults.h
+@@ -181,8 +181,7 @@
+  * VDO pool will reverve some sectors in the front and the back of pool device to avoid
+  * seeing same device twice in the system.
+  */
+-#define DEFAULT_VDO_POOL_HEADER_SIZE  (1024)   // 512KiB
+-
++#define DEFAULT_VDO_POOL_HEADER_SIZE_KB  (512)
+ 
+ 
+ #define DEFAULT_FSADM_PATH FSADM_PATH
+diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
+index 37dd361..43af474 100644
+--- a/lib/metadata/lv_manip.c
++++ b/lib/metadata/lv_manip.c
+@@ -8766,7 +8766,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
+ 	}
+ 
+ 	if (seg_is_vdo_pool(lp)) {
+-		if (!convert_vdo_pool_lv(lv, &lp->vdo_params, &lp->virtual_extents, 1)) {
++		if (!convert_vdo_pool_lv(lv, &lp->vdo_params, &lp->virtual_extents,
++					 1, lp->vdo_pool_header_size)) {
+ 			stack;
+ 			goto deactivate_and_revert_new_lv;
+ 		}
+diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
+index 54bc0d0..adbbe76 100644
+--- a/lib/metadata/metadata-exported.h
++++ b/lib/metadata/metadata-exported.h
+@@ -1033,6 +1033,7 @@ struct lvcreate_params {
+ 	int approx_alloc;     /* all */
+ 	alloc_policy_t alloc; /* all */
+ 	struct dm_vdo_target_params vdo_params; /* vdo */
++	uint64_t vdo_pool_header_size; /* VDO */
+ 
+ 	int raidintegrity;
+ 	const char *raidintegritymode;
+@@ -1367,10 +1368,12 @@ int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_
+ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
+ 					   const struct dm_vdo_target_params *vtp,
+ 					   uint32_t *virtual_extents,
+-					   int format);
++					   int format,
++					   uint64_t vdo_pool_header_size);
+ int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy);
+ int fill_vdo_target_params(struct cmd_context *cmd,
+ 			   struct dm_vdo_target_params *vtp,
++			   uint64_t *vdo_pool_header_size,
+ 			   struct profile *profile);
+ /* --  metadata/vdo_manip.c */
+ 
+diff --git a/lib/metadata/vdo_manip.c b/lib/metadata/vdo_manip.c
+index afc513a..3f2de1a 100644
+--- a/lib/metadata/vdo_manip.c
++++ b/lib/metadata/vdo_manip.c
+@@ -356,9 +356,9 @@ static int _format_vdo_pool_data_lv(struct logical_volume *data_lv,
+ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
+ 					   const struct dm_vdo_target_params *vtp,
+ 					   uint32_t *virtual_extents,
+-					   int format)
++					   int format,
++					   uint64_t vdo_pool_header_size)
+ {
+-	const uint64_t header_size = DEFAULT_VDO_POOL_HEADER_SIZE;
+ 	const uint32_t extent_size = data_lv->vg->extent_size;
+ 	struct cmd_context *cmd = data_lv->vg->cmd;
+ 	struct logical_volume *vdo_pool_lv = data_lv;
+@@ -379,7 +379,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
+ 
+ 	if (*virtual_extents)
+ 		vdo_logical_size =
+-			_get_virtual_size(*virtual_extents, extent_size, header_size);
++			_get_virtual_size(*virtual_extents, extent_size, vdo_pool_header_size);
+ 
+ 	if (!dm_vdo_validate_target_params(vtp, vdo_logical_size))
+ 		return_0;
+@@ -403,7 +403,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
+ 		return NULL;
+ 	}
+ 
+-	vdo_logical_size -= 2 * header_size;
++	vdo_logical_size -= 2 * vdo_pool_header_size;
+ 
+ 	if (vdo_logical_size < extent_size) {
+ 		if (!*virtual_extents)
+@@ -426,7 +426,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
+ 	vdo_pool_seg = first_seg(vdo_pool_lv);
+ 	vdo_pool_seg->segtype = vdo_pool_segtype;
+ 	vdo_pool_seg->vdo_params = *vtp;
+-	vdo_pool_seg->vdo_pool_header_size = DEFAULT_VDO_POOL_HEADER_SIZE;
++	vdo_pool_seg->vdo_pool_header_size = vdo_pool_header_size;
+ 	vdo_pool_seg->vdo_pool_virtual_extents = *virtual_extents;
+ 
+ 	vdo_pool_lv->status |= LV_VDO_POOL;
+@@ -453,6 +453,7 @@ int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy)
+ 
+ int fill_vdo_target_params(struct cmd_context *cmd,
+ 			   struct dm_vdo_target_params *vtp,
++			   uint64_t *vdo_pool_header_size,
+ 			   struct profile *profile)
+ {
+ 	const char *policy;
+@@ -501,5 +502,7 @@ int fill_vdo_target_params(struct cmd_context *cmd,
+ 	if (!set_vdo_write_policy(&vtp->write_policy, policy))
+ 		return_0;
+ 
++	*vdo_pool_header_size = 2 * find_config_tree_int64(cmd, allocation_vdo_pool_header_size_CFG, profile);
++
+ 	return 1;
+ }
+diff --git a/tools/lvconvert.c b/tools/lvconvert.c
+index 8488596..f87ee78 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -5439,6 +5439,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
+ {
+ 	const char *vg_name = NULL;
+ 	unsigned int vdo_pool_zero;
++	uint64_t vdo_pool_header_size;
+ 	struct volume_group *vg = lv->vg;
+ 	struct logical_volume *vdo_lv;
+ 	struct dm_vdo_target_params vdo_params; /* vdo */
+@@ -5481,7 +5482,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
+ 		goto out;
+ 	}
+ 
+-	if (!fill_vdo_target_params(cmd, &vdo_params, vg->profile))
++	if (!fill_vdo_target_params(cmd, &vdo_params, &vdo_pool_header_size, vg->profile))
+ 		goto_out;
+ 
+ 	if (arg_is_set(cmd, compression_ARG))
+@@ -5526,7 +5527,8 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
+ 	if (!archive(vg))
+ 		goto_out;
+ 
+-	if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents, vdo_pool_zero))
++	if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents,
++				 vdo_pool_zero, vdo_pool_header_size))
+ 		goto_out;
+ 
+ 	dm_list_init(&lvc.tags);
+diff --git a/tools/lvcreate.c b/tools/lvcreate.c
+index a28f093..0def236 100644
+--- a/tools/lvcreate.c
++++ b/tools/lvcreate.c
+@@ -1097,7 +1097,7 @@ static int _lvcreate_params(struct cmd_context *cmd,
+ 
+ 		// FIXME: prefiling here - this is wrong place
+ 		// but will work for this moment
+-		if (!fill_vdo_target_params(cmd, &lp->vdo_params, NULL))
++		if (!fill_vdo_target_params(cmd, &lp->vdo_params, &lp->vdo_pool_header_size, NULL))
+ 			return_0;
+ 
+ 		if (arg_is_set(cmd, compression_ARG))
diff --git a/SOURCES/lvm2-2_03_13-vgmerge-remove-one-of-merge-pmspare-LVs.patch b/SOURCES/lvm2-2_03_13-vgmerge-remove-one-of-merge-pmspare-LVs.patch
new file mode 100644
index 0000000..62d6686
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-vgmerge-remove-one-of-merge-pmspare-LVs.patch
@@ -0,0 +1,28 @@
+ tools/vgmerge.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/tools/vgmerge.c b/tools/vgmerge.c
+index 895018a..884ad4b 100644
+--- a/tools/vgmerge.c
++++ b/tools/vgmerge.c
+@@ -92,6 +92,20 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
+ 		}
+ 	}
+ 
++	if (vg_from->pool_metadata_spare_lv &&
++	    vg_to->pool_metadata_spare_lv) {
++		if (vg_from->pool_metadata_spare_lv->le_count >
++		    vg_to->pool_metadata_spare_lv->le_count)
++			/* Preserve bigger pmspare from  VG_FROM */
++			lv = vg_to->pool_metadata_spare_lv;
++		else
++			lv = vg_from->pool_metadata_spare_lv;
++
++		log_debug_metadata("Removing pool metadata spare %s.", display_lvname(lv));
++		if (!lv_remove_single(cmd, lv, DONT_PROMPT, 0))
++				return_ECMD_FAILED;
++	}
++
+ 	if (!vgs_are_compatible(cmd, vg_from, vg_to))
+ 		goto_bad;
+ 
diff --git a/SOURCES/lvm2-2_03_13-vgmerge-support-option-poolmetadataspare.patch b/SOURCES/lvm2-2_03_13-vgmerge-support-option-poolmetadataspare.patch
new file mode 100644
index 0000000..002c060
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-vgmerge-support-option-poolmetadataspare.patch
@@ -0,0 +1,82 @@
+ WHATS_NEW              | 2 +-
+ man/vgmerge.8_pregen   | 9 +++++++++
+ tools/command-lines.in | 2 +-
+ tools/vgmerge.c        | 6 ++++++
+ 4 files changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 0b8e3f2..5556789 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,6 +1,6 @@
+ Version 2.03.13 - 
+ ===============================
+-  Support --poolmetadataspare with vgsplit.
++  Support --poolmetadataspare with vgsplit and vgmerge.
+   Fix detection of active components of external origin volume.
+   Add vdoimport tool to support conversion of VDO volumes.
+   Support configurable allocation/vdo_pool_header_size.
+diff --git a/man/vgmerge.8_pregen b/man/vgmerge.8_pregen
+index 1264bb5..e229218 100644
+--- a/man/vgmerge.8_pregen
++++ b/man/vgmerge.8_pregen
+@@ -27,6 +27,8 @@ of both VGs fit into the destination VG's limits.
+ .br
+ [ \fB-l\fP|\fB--list\fP ]
+ .br
++[    \fB--poolmetadataspare\fP \fBy\fP|\fBn\fP ]
++.br
+ [ COMMON_OPTIONS ]
+ .ad b
+ .RE
+@@ -147,6 +149,13 @@ Display long help text.
+ Disable locking.
+ .
+ .HP
++\fB--poolmetadataspare\fP \fBy\fP|\fBn\fP
++.br
++Enable or disable the automatic creation and management of a
++spare pool metadata LV in the VG. A spare metadata LV is reserved
++space that can be used when repairing a pool.
++.
++.HP
+ \fB--profile\fP \fIString\fP
+ .br
+ An alias for --commandprofile or --metadataprofile, depending
+diff --git a/tools/command-lines.in b/tools/command-lines.in
+index a4785b3..0bc5a49 100644
+--- a/tools/command-lines.in
++++ b/tools/command-lines.in
+@@ -1847,7 +1847,7 @@ DESC: Add devices from all accessible VGs to the devices file.
+ ---
+ 
+ vgmerge VG VG
+-OO: --autobackup Bool, --list
++OO: --autobackup Bool, --list, --poolmetadataspare Bool
+ ID: vgmerge_general
+ 
+ ---
+diff --git a/tools/vgmerge.c b/tools/vgmerge.c
+index 884ad4b..08615cd 100644
+--- a/tools/vgmerge.c
++++ b/tools/vgmerge.c
+@@ -64,6 +64,8 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
+ 	struct lv_list *lvl1, *lvl2;
+ 	int r = ECMD_FAILED;
+ 	int lock_vg_from_first = 0;
++	struct logical_volume *lv;
++	int poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG, DEFAULT_POOL_METADATA_SPARE);
+ 
+ 	if (!strcmp(vg_name_to, vg_name_from)) {
+ 		log_error("Duplicate volume group name \"%s\"", vg_name_from);
+@@ -185,6 +187,10 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
+ 	/* Flag up that some PVs have moved from another VG */
+ 	vg_to->old_name = vg_from->name;
+ 
++        /* Check whether size of pmspare is big enough now for merged VG */
++	if (!handle_pool_metadata_spare(vg_to, 0, &vg_to->pvs, poolmetadataspare))
++		goto_bad;
++
+ 	/* store it on disks */
+ 	log_verbose("Writing out updated volume group");
+ 	if (!vg_write(vg_to) || !vg_commit(vg_to))
diff --git a/SOURCES/lvm2-2_03_13-vgremove-remove-forgotten-pmspare.patch b/SOURCES/lvm2-2_03_13-vgremove-remove-forgotten-pmspare.patch
new file mode 100644
index 0000000..53fa667
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-vgremove-remove-forgotten-pmspare.patch
@@ -0,0 +1,18 @@
+ tools/vgremove.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/tools/vgremove.c b/tools/vgremove.c
+index 8f73297..b6685ae 100644
+--- a/tools/vgremove.c
++++ b/tools/vgremove.c
+@@ -65,6 +65,10 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
+ 		}
+ 	}
+ 
++	if (vg->pool_metadata_spare_lv &&
++	    !lvremove_single(cmd, vg->pool_metadata_spare_lv, &void_handle))
++		return_ECMD_FAILED;
++
+ 	if (!lockd_free_vg_before(cmd, vg, 0))
+ 		return_ECMD_FAILED;
+ 
diff --git a/SOURCES/lvm2-2_03_13-vgsplit-add-support-for-option-poolmetadataspare.patch b/SOURCES/lvm2-2_03_13-vgsplit-add-support-for-option-poolmetadataspare.patch
new file mode 100644
index 0000000..1a9d26b
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-vgsplit-add-support-for-option-poolmetadataspare.patch
@@ -0,0 +1,106 @@
+ WHATS_NEW                 |  1 +
+ lib/metadata/pool_manip.c | 11 +++++++++++
+ man/vgsplit.8_pregen      |  9 +++++++++
+ tools/command-lines.in    |  2 +-
+ tools/vgsplit.c           |  8 ++++++++
+ 5 files changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 097160e..0b8e3f2 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,6 @@
+ Version 2.03.13 - 
+ ===============================
++  Support --poolmetadataspare with vgsplit.
+   Fix detection of active components of external origin volume.
+   Add vdoimport tool to support conversion of VDO volumes.
+   Support configurable allocation/vdo_pool_header_size.
+diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
+index 9ceec3a..e451e92 100644
+--- a/lib/metadata/pool_manip.c
++++ b/lib/metadata/pool_manip.c
+@@ -722,6 +722,17 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
+ 		return 1;
+ 	}
+ 
++	if (!extents) {
++		/* pmspare is not needed */
++		if (lv) {
++			log_debug_metadata("Dropping unused pool metadata spare LV %s.",
++					   display_lvname(lv));
++			if (!lv_remove_single(vg->cmd, lv, DONT_PROMPT, 0))
++				return_0;
++		}
++		return 1;
++	}
++
+ 	if (extents > MAX_SIZE)
+ 		extents = MAX_SIZE;
+ 
+diff --git a/man/vgsplit.8_pregen b/man/vgsplit.8_pregen
+index 331c6e4..8a0ae59 100644
+--- a/man/vgsplit.8_pregen
++++ b/man/vgsplit.8_pregen
+@@ -70,6 +70,8 @@ Common options for command:
+ .hy
+ ]
+ .br
++[    \fB--poolmetadataspare\fP \fBy\fP|\fBn\fP ]
++.br
+ [    \fB--\fP[\fBvg\fP]\fBmetadatacopies\fP \fBall\fP|\fBunmanaged\fP|\fINumber\fP ]
+ .ad b
+ .RE
+@@ -235,6 +237,13 @@ Move only PVs used by the named LV.
+ Disable locking.
+ .
+ .HP
++\fB--poolmetadataspare\fP \fBy\fP|\fBn\fP
++.br
++Enable or disable the automatic creation and management of a
++spare pool metadata LV in the VG. A spare metadata LV is reserved
++space that can be used when repairing a pool.
++.
++.HP
+ \fB--profile\fP \fIString\fP
+ .br
+ An alias for --commandprofile or --metadataprofile, depending
+diff --git a/tools/command-lines.in b/tools/command-lines.in
+index 8607305..a4785b3 100644
+--- a/tools/command-lines.in
++++ b/tools/command-lines.in
+@@ -1912,7 +1912,7 @@ ID: vgscan_general
+ 
+ ---
+ 
+-OO_VGSPLIT: --autobackup Bool
++OO_VGSPLIT: --autobackup Bool, --poolmetadataspare Bool
+ 
+ # used only when the destination VG is new
+ OO_VGSPLIT_NEW: --alloc Alloc,
+diff --git a/tools/vgsplit.c b/tools/vgsplit.c
+index 296248e..a085ac2 100644
+--- a/tools/vgsplit.c
++++ b/tools/vgsplit.c
+@@ -525,6 +525,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
+ 	int existing_vg = 0;
+ 	int r = ECMD_FAILED;
+ 	const char *lv_name;
++	int poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG, DEFAULT_POOL_METADATA_SPARE);
+ 
+ 	if ((arg_is_set(cmd, name_ARG) + argc) < 3) {
+ 		log_error("Existing VG, new VG and either physical volumes "
+@@ -699,6 +700,13 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
+ 	 */
+ 	vg_to->status |= EXPORTED_VG;
+ 
++
++	if (!handle_pool_metadata_spare(vg_to, 0, &vg_to->pvs, poolmetadataspare))
++		goto_bad;
++
++	if (!handle_pool_metadata_spare(vg_from, 0, &vg_from->pvs, poolmetadataspare))
++		goto_bad;
++
+ 	if (!archive(vg_to))
+ 		goto_bad;
+ 
diff --git a/SOURCES/lvm2-2_03_13-writecache-don-t-pvmove-device-used-by-writecache.patch b/SOURCES/lvm2-2_03_13-writecache-don-t-pvmove-device-used-by-writecache.patch
new file mode 100644
index 0000000..1457f7f
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-writecache-don-t-pvmove-device-used-by-writecache.patch
@@ -0,0 +1,23 @@
+ tools/pvmove.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/tools/pvmove.c b/tools/pvmove.c
+index da635a6..bb372f7 100644
+--- a/tools/pvmove.c
++++ b/tools/pvmove.c
+@@ -387,6 +387,15 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
+ 			return NULL;
+ 		}
+ 
++		if (lv_is_writecache(lv)) {
++			struct logical_volume *lv_cachevol = first_seg(lv)->writecache;
++			if (lv_is_on_pvs(lv_cachevol, source_pvl)) {
++				log_error("Unable to move device used for writecache cachevol %s.", display_lvname(lv_cachevol));
++				return NULL;
++			}
++
++		}
++
+ 		if (lv_is_raid(lv) && lv_raid_has_integrity(lv)) {
+ 			log_error("Unable to pvmove device used for raid with integrity.");
+ 			return NULL;
diff --git a/SOURCES/lvm2-2_03_13-writecache-fix-lv_on_pmem.patch b/SOURCES/lvm2-2_03_13-writecache-fix-lv_on_pmem.patch
new file mode 100644
index 0000000..b926cac
--- /dev/null
+++ b/SOURCES/lvm2-2_03_13-writecache-fix-lv_on_pmem.patch
@@ -0,0 +1,17 @@
+ lib/metadata/metadata.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
+index 002d80c..1f65045 100644
+--- a/lib/metadata/metadata.c
++++ b/lib/metadata/metadata.c
+@@ -4402,6 +4402,9 @@ int lv_on_pmem(struct logical_volume *lv)
+ 
+ 	dm_list_iterate_items(seg, &lv->segments) {
+ 		for (s = 0; s < seg->area_count; s++) {
++			if (seg_type(seg, s) != AREA_PV)
++				continue;
++
+ 			pv = seg_pv(seg, s);
+ 
+ 			if (dev_is_pmem(lv->vg->cmd->dev_types, pv->dev)) {
diff --git a/SOURCES/lvm2-2_03_14-tests-check-lvm2-parses-vdo-statistics.patch b/SOURCES/lvm2-2_03_14-tests-check-lvm2-parses-vdo-statistics.patch
new file mode 100644
index 0000000..1adbfdd
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-tests-check-lvm2-parses-vdo-statistics.patch
@@ -0,0 +1,25 @@
+From 155d8c55086b09528de799425e77f7aeafd9b165 Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Thu, 9 Sep 2021 15:22:20 +0200
+Subject: [PATCH 2/5] tests: check lvm2 parses vdo statistics
+
+(cherry picked from commit bd2dae464386033241afa35934cdeddfe47f6a77)
+---
+ test/shell/lvcreate-vdo.sh | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/test/shell/lvcreate-vdo.sh b/test/shell/lvcreate-vdo.sh
+index d66e353..5b370fb 100644
+--- a/test/shell/lvcreate-vdo.sh
++++ b/test/shell/lvcreate-vdo.sh
+@@ -47,6 +47,7 @@ fi
+ check lv_field $vg/$lv1 size "<1.24g"
+ check lv_field $vg/${lv2} size "4.00g"
+ check lv_field $vg/${lv2}_vdata size "4.00g"
++check lv_field $vg/${lv1} data_percent "0.00"
+ lvremove -ff $vg
+ 
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_03_14-vdo-Rename-vdoimport-to-lvm_import_vdo.patch b/SOURCES/lvm2-2_03_14-vdo-Rename-vdoimport-to-lvm_import_vdo.patch
new file mode 100644
index 0000000..2250e1c
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-vdo-Rename-vdoimport-to-lvm_import_vdo.patch
@@ -0,0 +1,1137 @@
+ WHATS_NEW                 |   4 +
+ configure                 |   6 +-
+ configure.ac              |   8 +-
+ include/configure.h.in    |   2 +-
+ man/Makefile.in           |   2 +-
+ man/lvm_import_vdo.8_main |  92 ++++++++++++
+ man/vdoimport.8_main      |  92 ------------
+ scripts/Makefile.in       |   2 +-
+ scripts/lvm_import_vdo.sh | 376 ++++++++++++++++++++++++++++++++++++++++++++++
+ scripts/vdoimport.sh      | 376 ----------------------------------------------
+ test/Makefile.in          |   2 +-
+ test/shell/vdo-convert.sh |  12 +-
+ 12 files changed, 489 insertions(+), 485 deletions(-)
+ create mode 100644 man/lvm_import_vdo.8_main
+ delete mode 100644 man/vdoimport.8_main
+ create mode 100755 scripts/lvm_import_vdo.sh
+ delete mode 100755 scripts/vdoimport.sh
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 5556789..3637e31 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,3 +1,7 @@
++Version 2.03.14 - 
++==================================
++  Rename vdoimport to lvm_import_vdo.
++
+ Version 2.03.13 - 
+ ===============================
+   Support --poolmetadataspare with vgsplit and vgmerge.
+diff --git a/configure b/configure
+index 661702d..897a810 100755
+--- a/configure
++++ b/configure
+@@ -12379,8 +12379,8 @@ $as_echo "$FSADM" >&6; }
+ 
+ 
+ ################################################################################
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install vdoimport" >&5
+-$as_echo_n "checking whether to install vdoimport... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install lvm_import_vdo" >&5
++$as_echo_n "checking whether to install lvm_import_vdo... " >&6; }
+ # Check whether --enable-vdoimport was given.
+ if test "${enable_vdoimport+set}" = set; then :
+   enableval=$enable_vdoimport; VDOIMPORT=$enableval
+@@ -13875,7 +13875,7 @@ cat >>confdefs.h <<_ACEOF
+ _ACEOF
+ 
+ 
+-VDOIMPORT_PATH="$SBINDIR/vdoimport"
++VDOIMPORT_PATH="$SBINDIR/lvm_import_vdo"
+ 
+ cat >>confdefs.h <<_ACEOF
+ #define VDOIMPORT_PATH "$VDOIMPORT_PATH"
+diff --git a/configure.ac b/configure.ac
+index 5a8b486..f769a63 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1295,8 +1295,8 @@ AC_MSG_RESULT($FSADM)
+ 
+ 
+ ################################################################################
+-dnl -- Enable vdoimport
+-AC_MSG_CHECKING(whether to install vdoimport)
++dnl -- Enable lvm_import_vdo
++AC_MSG_CHECKING(whether to install lvm_import_vdo)
+ AC_ARG_ENABLE(vdoimport, AC_HELP_STRING([--disable-vdoimport], [disable vdoimport]),
+ 	      VDOIMPORT=$enableval)
+ AC_MSG_RESULT($VDOIMPORT)
+@@ -1656,8 +1656,8 @@ USRSBINDIR="$(eval echo $(eval echo $usrsbindir))"
+ FSADM_PATH="$SBINDIR/fsadm"
+ AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
+ 
+-VDOIMPORT_PATH="$SBINDIR/vdoimport"
+-AC_DEFINE_UNQUOTED(VDOIMPORT_PATH, ["$VDOIMPORT_PATH"], [Path to vdoimport binary.])
++VDOIMPORT_PATH="$SBINDIR/lvm_import_vdo"
++AC_DEFINE_UNQUOTED(VDOIMPORT_PATH, ["$VDOIMPORT_PATH"], [Path to lvm_import_vdo binary.])
+ 
+ ################################################################################
+ dnl -- dmeventd pidfile and executable path
+diff --git a/include/configure.h.in b/include/configure.h.in
+index 6df8d89..028ae48 100644
+--- a/include/configure.h.in
++++ b/include/configure.h.in
+@@ -684,7 +684,7 @@
+ /* Enable a valgrind aware build of pool */
+ #undef VALGRIND_POOL
+ 
+-/* Path to vdoimport binary. */
++/* Path to lvm_import_vdo binary. */
+ #undef VDOIMPORT_PATH
+ 
+ /* The path to 'vdoformat', if available. */
+diff --git a/man/Makefile.in b/man/Makefile.in
+index d60a92c..45ebf54 100644
+--- a/man/Makefile.in
++++ b/man/Makefile.in
+@@ -23,7 +23,7 @@ else
+ endif
+ 
+ FSADMMAN = fsadm.8
+-VDOIMPORTMAN = vdoimport.8
++VDOIMPORTMAN = lvm_import_vdo.8
+ BLKDEACTIVATEMAN = blkdeactivate.8
+ DMEVENTDMAN = dmeventd.8
+ DMFILEMAPDMAN = dmfilemapd.8
+diff --git a/man/lvm_import_vdo.8_main b/man/lvm_import_vdo.8_main
+new file mode 100644
+index 0000000..ee817a0
+--- /dev/null
++++ b/man/lvm_import_vdo.8_main
+@@ -0,0 +1,92 @@
++.TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
++.
++.SH "NAME"
++.
++lvm_import_vdo \(em utility to import VDO volumes into a new volume group.
++.
++.SH SYNOPSIS
++.
++.PD 0
++.ad l
++.TP 10
++.B lvm_import_vdo
++.RI [ options ]
++.IR device
++.
++.PD
++.
++.SH DESCRIPTION
++.
++lvm_import_vdo utility imports VDO volumes created and managed by
++.BR vdo (8)
++manager into
++.BR lvm2 (8)
++managed VDO LV. This is realized by moving VDO superblock by 2MiB
++and creating lvm2 metadata at the front of this device. The operation is not reversible,
++thus after conversion to lvm2 the access to VDO data is only possible with
++.BR lvm2 (8)
++commands,
++.BR vdo (8)
++manager no longer control such volume.
++.
++.SH OPTIONS
++.
++.TP
++.BR -f | --force
++Bypass some sanity checks.
++.
++.TP
++.BR -h | --help
++Display the help text.
++.
++.TP
++.BR -n | --name
++Specifies the name of converted VDO LV. When the name is not specified,
++some automatic name is selected. In case the converted VDO volume is
++already using LV a backend device, the name of this LV is used for VDO LV.
++In this case also the of volume group must stay same.
++.
++.TP
++.BR -v | --verbose
++Be more verbose.
++.
++.TP
++.BR -y | --yes
++Answer "yes" at any prompts.
++.
++.TP
++.BR --dry-run
++Print commands without running them.
++.
++.
++.SH DIAGNOSTICS
++.
++On successful completion, the status code is 0.
++A status code of 1 is used for failure.
++.
++.SH EXAMPLES
++.
++Convert VDO volume created by vdo manager into logical volume LV1 with within volume group VG1.
++.P
++#
++.B lvm_import_vdo --name VG1/LV1 /dev/mapper/vdo-volume
++.
++.SH ENVIRONMENT VARIABLES
++.
++.TP
++.B TMPDIR
++The temporary directory name for mount points. Defaults to "\fI/tmp\fP".
++.TP
++.B DM_DEV_DIR
++The device directory name.
++Defaults to "\fI/dev\fP" and must be an absolute path.
++.
++.SH SEE ALSO
++.
++.nh
++.ad l
++.BR lvm (8),
++.BR lvm.conf (5),
++.P
++.BR vdo (8),
++.BR vdo2lvm (8),
+diff --git a/man/vdoimport.8_main b/man/vdoimport.8_main
+deleted file mode 100644
+index 1f32909..0000000
+--- a/man/vdoimport.8_main
++++ /dev/null
+@@ -1,92 +0,0 @@
+-.TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
+-.
+-.SH "NAME"
+-.
+-vdoimport \(em utility to import VDO volumes into a new volume group.
+-.
+-.SH SYNOPSIS
+-.
+-.PD 0
+-.ad l
+-.TP 10
+-.B vdoimport
+-.RI [ options ]
+-.IR device
+-.
+-.PD
+-.
+-.SH DESCRIPTION
+-.
+-vdoimport utility imports VDO volumes created and managed by
+-.BR vdo (8)
+-manager into
+-.BR lvm2 (8)
+-managed VDO LV. This is realized by moving VDO superblock by 2MiB
+-and creating lvm2 metadata at the front of this device. The operation is not reversible,
+-thus after conversion to lvm2 the access to VDO data is only possible with
+-.BR lvm2 (8)
+-commands,
+-.BR vdo (8)
+-manager no longer control such volume.
+-.
+-.SH OPTIONS
+-.
+-.TP
+-.BR -f | --force
+-Bypass some sanity checks.
+-.
+-.TP
+-.BR -h | --help
+-Display the help text.
+-.
+-.TP
+-.BR -n | --name
+-Specifies the name of converted VDO LV. When the name is not specified,
+-some automatic name is selected. In case the converted VDO volume is
+-already using LV a backend device, the name of this LV is used for VDO LV.
+-In this case also the of volume group must stay same.
+-.
+-.TP
+-.BR -v | --verbose
+-Be more verbose.
+-.
+-.TP
+-.BR -y | --yes
+-Answer "yes" at any prompts.
+-.
+-.TP
+-.BR --dry-run
+-Print commands without running them.
+-.
+-.
+-.SH DIAGNOSTICS
+-.
+-On successful completion, the status code is 0.
+-A status code of 1 is used for failure.
+-.
+-.SH EXAMPLES
+-.
+-Convert VDO volume created by vdo manager into logical volume LV1 with within volume group VG1.
+-.P
+-#
+-.B vdoimport --name VG1/LV1 /dev/mapper/vdo-volume
+-.
+-.SH ENVIRONMENT VARIABLES
+-.
+-.TP
+-.B TMPDIR
+-The temporary directory name for mount points. Defaults to "\fI/tmp\fP".
+-.TP
+-.B DM_DEV_DIR
+-The device directory name.
+-Defaults to "\fI/dev\fP" and must be an absolute path.
+-.
+-.SH SEE ALSO
+-.
+-.nh
+-.ad l
+-.BR lvm (8),
+-.BR lvm.conf (5),
+-.P
+-.BR vdo (8),
+-.BR vdo2lvm (8),
+diff --git a/scripts/Makefile.in b/scripts/Makefile.in
+index 1fe88ca..f16c37d 100644
+--- a/scripts/Makefile.in
++++ b/scripts/Makefile.in
+@@ -32,7 +32,7 @@ ifeq ("@FSADM@", "yes")
+ endif
+ 
+ ifeq ("@VDOIMPORT@", "yes")
+-	LVM_SCRIPTS += vdoimport.sh
++	LVM_SCRIPTS += lvm_import_vdo.sh
+ endif
+ 
+ ifeq ("@BLKDEACTIVATE@", "yes")
+diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
+new file mode 100755
+index 0000000..35140a0
+--- /dev/null
++++ b/scripts/lvm_import_vdo.sh
+@@ -0,0 +1,376 @@
++#!/bin/bash
++#
++# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
++#
++# This file is part of LVM2.
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions
++# of the GNU General Public License v.2.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software Foundation,
++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++#
++# Author: Zdenek Kabelac <zkabelac at redhat.com>
++#
++# Script for converting VDO volumes to lvm2 VDO LVs
++#
++# Needed utilities:
++#  lvm, dmsetup,
++#  vdo, vdo2lvm,
++#  grep, awk, sed, blockdev, readlink, mkdir
++#
++# Conversion is using  'vdo convert' support from VDO manager to move
++# existing VDO header by 2M which makes space to place in PV header
++# and VG metadata area, and then create VDOPOOL LV and VDO LV in such VG.
++#
++
++set -euE -o pipefail
++
++TOOL=lvm_import_vdo
++
++_SAVEPATH=$PATH
++PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH"
++
++# user may override lvm location by setting LVM_BINARY
++LVM=${LVM_BINARY:-lvm}
++VDO=${VDO_BINARY:-vdo}
++VDOCONF=${VDOCONF:-}
++BLOCKDEV="blockdev"
++READLINK="readlink"
++READLINK_E="-e"
++MKDIR="mkdir"
++
++TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$"
++DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
++
++DRY=0
++VERB=""
++FORCE=""
++YES=""
++
++# default name for converted VG and its VDO LV
++NAME="vdovg/vdolvol"
++
++# help message
++tool_usage() {
++	echo "${TOOL}: Utility to convert VDO volume to VDO LV."
++	echo
++	echo "	${TOOL} [options] <vdo_device_path>"
++	echo
++	echo "	Options:"
++	echo "	  -f | --force	      Bypass sanity checks"
++	echo "	  -h | --help	      Show this help message"
++	echo "	  -n | --name	      Specifies VG/LV name for converted VDO volume"
++	echo "	  -v | --verbose      Be verbose"
++	echo "	  -y | --yes	      Answer \"yes\" at any prompts"
++	echo "	       --dry-run      Print commands without running them"
++
++	exit
++}
++
++verbose() {
++	test -z "$VERB" || echo "$TOOL:" "$@"
++}
++
++# Support multi-line error messages
++error() {
++	for i in "$@" ;  do
++		echo "$TOOL: $i" >&2
++	done
++	cleanup 1
++}
++
++dry() {
++	if [ "$DRY" -ne 0 ]; then
++		verbose "Dry execution" "$@"
++		return 0
++	fi
++	verbose "Executing" "$@"
++	"$@"
++}
++
++cleanup() {
++	trap '' 2
++
++	rm -rf "$TEMPDIR"
++	# error exit status for break
++	exit "${1:-1}"
++}
++
++get_enabled_value_() {
++	case "$1" in
++	enabled) echo "1" ;;
++	*) echo "0" ;;
++	esac
++}
++
++get_kb_size_with_unit_() {
++	case "$1" in
++	*[kK]) echo $(( ${1%[kK]} )) ;;
++	*[mM]) echo $(( ${1%[mM]} * 1024 )) ;;
++	*[gG]) echo $(( ${1%[gG]} * 1024 * 1024 )) ;;
++	*[tT]) echo $(( ${1%[tT]} * 1024 * 1024 * 1024 )) ;;
++	*[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 * 1024 )) ;;
++	esac
++}
++
++get_mb_size_with_unit_() {
++	case "$1" in
++	*[mM]) echo $(( ${1%[mM]} )) ;;
++	*[gG]) echo $(( ${1%[gG]} * 1024 )) ;;
++	*[tT]) echo $(( ${1%[tT]} * 1024 * 1024 )) ;;
++	*[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 )) ;;
++	esac
++}
++
++# Figure out largest possible extent size usable for VG
++# $1   physical size
++# $2   logical size
++get_largest_extent_size_() {
++	local max=4
++	local i
++	local d
++
++	for i in 8 16 32 64 128 256 512 1024 2048 4096 ; do
++		d=$(( $1 / i ))
++		test $(( d * i )) -eq "$1" || break
++		d=$(( $2 / i ))
++		test $(( d * i )) -eq "$2" || break
++		max=$i
++	done
++	echo "$max"
++}
++
++# detect LV on the given device
++# dereference device name if it is symbolic link
++detect_lv_() {
++	local DEVICE=$1
++	local MAJOR
++	local MINOR
++	local SYSVOLUME
++	local MAJORMINOR
++
++	DEVICE=${1/#"${DM_DEV_DIR}/"/}
++	DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE")
++	test -n "$DEVICE" || error "Cannot get readlink \"$1\"."
++	RDEVICE=$DEVICE
++	case "$RDEVICE" in
++	  # hardcoded /dev  since udev does not create these entries elsewhere
++	  /dev/dm-[0-9]*)
++		read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME"
++		read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"."
++		MAJOR=${MAJORMINOR%%:*}
++		MINOR=${MAJORMINOR##*:}
++		;;
++	  *)
++		STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE")
++		test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"."
++		eval "$STAT"
++		;;
++	esac
++
++	eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
++}
++
++# parse yaml config files into 'prefix_yaml_part_names=("value")' strings
++parse_yaml_() {
++	local yaml_file=$1
++	local prefix=$2
++	local s
++	local w
++	local fs
++
++	s='[[:space:]]*'
++	w='[a-zA-Z0-9_.-]*'
++	fs="$(echo @|tr @ '\034')"
++
++	(
++	    sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/[[:space:]]*$//g;' \
++		-e 's/\$/\\\$/g' \
++		-e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \
++		-e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
++		-e "s|^\($s\)\($w\)${s}[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" |
++
++	    awk -F"$fs" '{
++		indent = length($1)/2;
++		if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";}
++		vname[indent] = $2;
++		for (i in vname) {if (i > indent) {delete vname[i]}}
++		    if (length($3) > 0) {
++			vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
++			printf("%s%s%s%s=(\"%s\")\n", "'"$prefix"'",vn, $2, conj[indent-1], $3);
++		    }
++		}' |
++
++	    sed -e 's/_=/+=/g' |
++
++	    awk 'BEGIN {
++		    FS="=";
++		    OFS="="
++		}
++		/(-|\.).*=/ {
++		    gsub("-|\\.", "_", $1)
++		}
++		{ print }'
++	) < "$yaml_file"
++}
++
++# convert existing VDO volume into lvm2 volume
++convert2lvm_() {
++	local DEVICE=$1
++	local VGNAME=${NAME%/*}
++	local LVNAME=${NAME#*/}
++	local VDONAME
++	local TRVDONAME
++	local EXTENTSZ
++	local IS_LV=1
++
++	DM_UUID=""
++	detect_lv_ "$DEVICE"
++	case "$DM_UUID" in
++		LVM-*)	eval "$(dmsetup splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
++			if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ]  ; then
++				VGNAME=$DM_VG_NAME
++			elif test "$VGNAME" != "$DM_VG_NAME" ; then
++				error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"."
++			fi
++			;;
++		*) IS_LV=0
++			# Check $VGNANE does not already exists
++			"$LVM" vgs "$VGNAME" && error "Cannot use already existing volume group name \"$VGNAME\"."
++			;;
++	esac
++
++	verbose "Checked whether device $1 is already LV ($IS_LV)."
++
++	"$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR."
++
++	verbose "Getting YAML VDO configuration."
++	"$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml"
++
++	VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
++	TRVDONAME=$(echo "$VDONAME" | tr '-' '_')
++
++	# When VDO volume is 'active', check it's not mounted/being used
++	eval "$(dmsetup info -c -o open  "$VDONAME" --noheadings --nameprefixes || true)"
++	test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
++
++	#parse_yaml_ "$TEMPDIR/vdoconf.yml" _
++	eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")"
++
++	vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize")
++	vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize")
++
++	verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB."
++	verbose "With logical volume of size $vdo_logicalSize KiB."
++
++	PARAMS=$(cat <<EOF
++allocation {
++	vdo_use_compression = $(get_enabled_value_ "$vdo_compression")
++	vdo_use_deduplication = $(get_enabled_value_ "$vdo_deduplication")
++	vdo_use_metadata_hints=1
++	vdo_minimum_io_size = $vdo_logicalBlockSize
++	vdo_block_map_cache_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize")
++	vdo_block_map_period = $vdo_blockMapPeriod
++	vdo_check_point_frequency = $vdo_indexCfreq
++	vdo_use_sparse_index = $(get_enabled_value_ "$vdo_indexSparse")
++	vdo_index_memory_size_mb = $(awk "BEGIN {print $vdo_indexMemory * 1024}")
++	vdo_slab_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize")
++	vdo_ack_threads = $vdo_ackThreads
++	vdo_bio_threads = $vdo_bioThreads
++	vdo_bio_rotation = $vdo_bioRotationInterval
++	vdo_cpu_threads = $vdo_cpuThreads
++	vdo_hash_zone_threads = $vdo_hashZoneThreads
++	vdo_logical_threads = $vdo_logicalThreads
++	vdo_physical_threads = $vdo_physicalThreads
++	vdo_write_policy = $vdo_writePolicy
++	vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") * 1024 ))
++	vdo_pool_header_size = 0
++}
++EOF
++)
++	verbose "VDO conversion paramaters: $PARAMS"
++
++	verbose "Stopping VDO volume."
++	dry "$VDO" stop $VDOCONF --name "$VDONAME"
++
++	if [ "$IS_LV" = "0" ]; then
++		verbose "Moving VDO header by 2MiB."
++		dry "$VDO" convert $VDOCONF --force --name "$VDONAME"
++
++		dry "$LVM" pvcreate $YES --dataalignment 2M "$DEVICE" || {
++			error "Creation of PV on \"$DEVICE\" failed, while VDO header has been already moved!"
++		}
++
++		# Obtain free space in this new PV
++		# after 'vdo convert/vdo2lvm' call there is +2M free space at the front of the device
++		case "$DRY" in
++		0) pvfree=$("$LVM" pvs -o devsize --units b --nosuffix --noheadings "$DEVICE") ;;
++		*) pvfree=$("$BLOCKDEV" --getsize64 "$DEVICE") ;;
++		esac
++
++		pvfree=$(( pvfree / 1024 - 2048 ))	# to KiB
++	else
++		pvfree=$("$LVM" lvs -o size --units b --nosuffix --noheadings "$VGNAME/$LVNAME")
++		pvfree=$(( pvfree / 1024 ))		# to KiB
++	fi
++
++	# select largest possible extent size that can exactly express both sizes
++	EXTENTSZ=$(get_largest_extent_size_ "$pvfree" "$vdo_logicalSize")
++
++	if [ "$IS_LV" = "0" ]; then
++		verbose "Creating VG \"${NAME%/*}\" with extent size $EXTENTSZ KiB."
++		dry "$LVM" vgcreate $YES $VERB -s "${EXTENTSZ}k" "$VGNAME" "$DEVICE" || {
++			error "Creation of VG \"$VGNAME\" failed, while VDO header has been already moved!"
++		}
++
++		verbose "Creating VDO pool data LV from all extents in volume group $VGNAME."
++		dry "$LVM" lvcreate -Zn -Wn $YES $VERB -l100%VG -n "${LVNAME}_vpool" "$VGNAME"
++	else
++		# validate existing  VG extent_size can express virtual VDO size
++		vg_extent_size=$("$LVM" vgs -o vg_extent_size --units b --nosuffix --noheadings "$VGNAME" || true)
++		vg_extent_size=$(( vg_extent_size / 1024 ))
++
++		test "$vg_extent_size" -le "$EXTENTSZ" || {
++			error "Please vgchange extent_size to at most $EXTENTSZ KiB or extend and align virtual size on $vg_extent_size KiB."
++		}
++		verbose "Renaming existing LV to be used as _vdata volume for VDO pool LV."
++		dry "$LVM" lvrename $YES $VERB "$VGNAME/$LVNAME" "$VGNAME/${LVNAME}_vpool" || {
++			error "Rename of LV \"$VGNAME/$LVNAME\" failed, while VDO header has been already moved!"
++		}
++	fi
++
++	verbose "Converting to VDO pool."
++	dry "$LVM" lvconvert $YES $VERB $FORCE --config "$PARAMS" -Zn -V "${vdo_logicalSize}k" -n "$LVNAME" --type vdo-pool "$VGNAME/${LVNAME}_vpool"
++
++	rm -fr "$TEMPDIR"
++}
++
++#############################
++# start point of this script
++# - parsing parameters
++#############################
++trap "cleanup 2" 2
++
++test "$#" -eq 0 && tool_usage
++
++while [ "$#" -ne 0 ]
++do
++	 case "$1" in
++	  "") ;;
++	  "-f"|"--force"  ) FORCE="-f" ;;
++	  "-h"|"--help"   ) tool_usage ;;
++	  "-n"|"--name"   ) shift; NAME=$1 ;;
++	  "-v"|"--verbose") VERB="-v" ;;
++	  "-y"|"--yes"    ) YES="-y" ;;
++	  "--dry-run"     ) DRY="1" ;;
++	  "-*") error "Wrong argument \"$1\". (see: $TOOL --help)" ;;
++	  *) DEVICENAME=$1 ;;  # device name does not start with '-'
++	esac
++	shift
++done
++
++# do conversion
++convert2lvm_ "$DEVICENAME"
+diff --git a/scripts/vdoimport.sh b/scripts/vdoimport.sh
+deleted file mode 100755
+index ef96591..0000000
+--- a/scripts/vdoimport.sh
++++ /dev/null
+@@ -1,376 +0,0 @@
+-#!/bin/bash
+-#
+-# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+-#
+-# This file is part of LVM2.
+-#
+-# This copyrighted material is made available to anyone wishing to use,
+-# modify, copy, or redistribute it subject to the terms and conditions
+-# of the GNU General Public License v.2.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software Foundation,
+-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+-#
+-# Author: Zdenek Kabelac <zkabelac at redhat.com>
+-#
+-# Script for converting VDO volumes to lvm2 VDO LVs
+-#
+-# Needed utilities:
+-#  lvm, dmsetup,
+-#  vdo, vdo2lvm,
+-#  grep, awk, sed, blockdev, readlink, mkdir
+-#
+-# Conversion is using  'vdo convert' support from VDO manager to move
+-# existing VDO header by 2M which makes space to place in PV header
+-# and VG metadata area, and then create VDOPOOL LV and VDO LV in such VG.
+-#
+-
+-set -euE -o pipefail
+-
+-TOOL=vdoimport
+-
+-_SAVEPATH=$PATH
+-PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH"
+-
+-# user may override lvm location by setting LVM_BINARY
+-LVM=${LVM_BINARY:-lvm}
+-VDO=${VDO_BINARY:-vdo}
+-VDOCONF=${VDOCONF:-}
+-BLOCKDEV="blockdev"
+-READLINK="readlink"
+-READLINK_E="-e"
+-MKDIR="mkdir"
+-
+-TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$"
+-DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
+-
+-DRY=0
+-VERB=""
+-FORCE=""
+-YES=""
+-
+-# default name for converted VG and its VDO LV
+-NAME="vdovg/vdolvol"
+-
+-# help message
+-tool_usage() {
+-	echo "${TOOL}: Utility to convert VDO volume to VDO LV."
+-	echo
+-	echo "	${TOOL} [options] <vdo_device_path>"
+-	echo
+-	echo "	Options:"
+-	echo "	  -f | --force	      Bypass sanity checks"
+-	echo "	  -h | --help	      Show this help message"
+-	echo "	  -n | --name	      Specifies VG/LV name for converted VDO volume"
+-	echo "	  -v | --verbose      Be verbose"
+-	echo "	  -y | --yes	      Answer \"yes\" at any prompts"
+-	echo "	       --dry-run      Print commands without running them"
+-
+-	exit
+-}
+-
+-verbose() {
+-	test -z "$VERB" || echo "$TOOL:" "$@"
+-}
+-
+-# Support multi-line error messages
+-error() {
+-	for i in "$@" ;  do
+-		echo "$TOOL: $i" >&2
+-	done
+-	cleanup 1
+-}
+-
+-dry() {
+-	if [ "$DRY" -ne 0 ]; then
+-		verbose "Dry execution" "$@"
+-		return 0
+-	fi
+-	verbose "Executing" "$@"
+-	"$@"
+-}
+-
+-cleanup() {
+-	trap '' 2
+-
+-	rm -rf "$TEMPDIR"
+-	# error exit status for break
+-	exit "${1:-1}"
+-}
+-
+-get_enabled_value_() {
+-	case "$1" in
+-	enabled) echo "1" ;;
+-	*) echo "0" ;;
+-	esac
+-}
+-
+-get_kb_size_with_unit_() {
+-	case "$1" in
+-	*[kK]) echo $(( ${1%[kK]} )) ;;
+-	*[mM]) echo $(( ${1%[mM]} * 1024 )) ;;
+-	*[gG]) echo $(( ${1%[gG]} * 1024 * 1024 )) ;;
+-	*[tT]) echo $(( ${1%[tT]} * 1024 * 1024 * 1024 )) ;;
+-	*[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 * 1024 )) ;;
+-	esac
+-}
+-
+-get_mb_size_with_unit_() {
+-	case "$1" in
+-	*[mM]) echo $(( ${1%[mM]} )) ;;
+-	*[gG]) echo $(( ${1%[gG]} * 1024 )) ;;
+-	*[tT]) echo $(( ${1%[tT]} * 1024 * 1024 )) ;;
+-	*[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 )) ;;
+-	esac
+-}
+-
+-# Figure out largest possible extent size usable for VG
+-# $1   physical size
+-# $2   logical size
+-get_largest_extent_size_() {
+-	local max=4
+-	local i
+-	local d
+-
+-	for i in 8 16 32 64 128 256 512 1024 2048 4096 ; do
+-		d=$(( $1 / i ))
+-		test $(( d * i )) -eq "$1" || break
+-		d=$(( $2 / i ))
+-		test $(( d * i )) -eq "$2" || break
+-		max=$i
+-	done
+-	echo "$max"
+-}
+-
+-# detect LV on the given device
+-# dereference device name if it is symbolic link
+-detect_lv_() {
+-	local DEVICE=$1
+-	local MAJOR
+-	local MINOR
+-	local SYSVOLUME
+-	local MAJORMINOR
+-
+-	DEVICE=${1/#"${DM_DEV_DIR}/"/}
+-	DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE")
+-	test -n "$DEVICE" || error "Cannot get readlink \"$1\"."
+-	RDEVICE=$DEVICE
+-	case "$RDEVICE" in
+-	  # hardcoded /dev  since udev does not create these entries elsewhere
+-	  /dev/dm-[0-9]*)
+-		read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME"
+-		read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"."
+-		MAJOR=${MAJORMINOR%%:*}
+-		MINOR=${MAJORMINOR##*:}
+-		;;
+-	  *)
+-		STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE")
+-		test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"."
+-		eval "$STAT"
+-		;;
+-	esac
+-
+-	eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
+-}
+-
+-# parse yaml config files into 'prefix_yaml_part_names=("value")' strings
+-parse_yaml_() {
+-	local yaml_file=$1
+-	local prefix=$2
+-	local s
+-	local w
+-	local fs
+-
+-	s='[[:space:]]*'
+-	w='[a-zA-Z0-9_.-]*'
+-	fs="$(echo @|tr @ '\034')"
+-
+-	(
+-	    sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/[[:space:]]*$//g;' \
+-		-e 's/\$/\\\$/g' \
+-		-e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \
+-		-e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
+-		-e "s|^\($s\)\($w\)${s}[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" |
+-
+-	    awk -F"$fs" '{
+-		indent = length($1)/2;
+-		if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";}
+-		vname[indent] = $2;
+-		for (i in vname) {if (i > indent) {delete vname[i]}}
+-		    if (length($3) > 0) {
+-			vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
+-			printf("%s%s%s%s=(\"%s\")\n", "'"$prefix"'",vn, $2, conj[indent-1], $3);
+-		    }
+-		}' |
+-
+-	    sed -e 's/_=/+=/g' |
+-
+-	    awk 'BEGIN {
+-		    FS="=";
+-		    OFS="="
+-		}
+-		/(-|\.).*=/ {
+-		    gsub("-|\\.", "_", $1)
+-		}
+-		{ print }'
+-	) < "$yaml_file"
+-}
+-
+-# convert existing VDO volume into lvm2 volume
+-convert2lvm_() {
+-	local DEVICE=$1
+-	local VGNAME=${NAME%/*}
+-	local LVNAME=${NAME#*/}
+-	local VDONAME
+-	local TRVDONAME
+-	local EXTENTSZ
+-	local IS_LV=1
+-
+-	DM_UUID=""
+-	detect_lv_ "$DEVICE"
+-	case "$DM_UUID" in
+-		LVM-*)	eval "$(dmsetup splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
+-			if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ]  ; then
+-				VGNAME=$DM_VG_NAME
+-			elif test "$VGNAME" != "$DM_VG_NAME" ; then
+-				error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"."
+-			fi
+-			;;
+-		*) IS_LV=0
+-			# Check $VGNANE does not already exists
+-			"$LVM" vgs "$VGNAME" && error "Cannot use already existing volume group name \"$VGNAME\"."
+-			;;
+-	esac
+-
+-	verbose "Checked whether device $1 is already LV ($IS_LV)."
+-
+-	"$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR."
+-
+-	verbose "Getting YAML VDO configuration."
+-	"$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml"
+-
+-	VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
+-	TRVDONAME=$(echo "$VDONAME" | tr '-' '_')
+-
+-	# When VDO volume is 'active', check it's not mounted/being used
+-	eval "$(dmsetup info -c -o open  "$VDONAME" --noheadings --nameprefixes || true)"
+-	test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
+-
+-	#parse_yaml_ "$TEMPDIR/vdoconf.yml" _
+-	eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")"
+-
+-	vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize")
+-	vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize")
+-
+-	verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB."
+-	verbose "With logical volume of size $vdo_logicalSize KiB."
+-
+-	PARAMS=$(cat <<EOF
+-allocation {
+-	vdo_use_compression = $(get_enabled_value_ "$vdo_compression")
+-	vdo_use_deduplication = $(get_enabled_value_ "$vdo_deduplication")
+-	vdo_use_metadata_hints=1
+-	vdo_minimum_io_size = $vdo_logicalBlockSize
+-	vdo_block_map_cache_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize")
+-	vdo_block_map_period = $vdo_blockMapPeriod
+-	vdo_check_point_frequency = $vdo_indexCfreq
+-	vdo_use_sparse_index = $(get_enabled_value_ "$vdo_indexSparse")
+-	vdo_index_memory_size_mb = $(awk "BEGIN {print $vdo_indexMemory * 1024}")
+-	vdo_slab_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize")
+-	vdo_ack_threads = $vdo_ackThreads
+-	vdo_bio_threads = $vdo_bioThreads
+-	vdo_bio_rotation = $vdo_bioRotationInterval
+-	vdo_cpu_threads = $vdo_cpuThreads
+-	vdo_hash_zone_threads = $vdo_hashZoneThreads
+-	vdo_logical_threads = $vdo_logicalThreads
+-	vdo_physical_threads = $vdo_physicalThreads
+-	vdo_write_policy = $vdo_writePolicy
+-	vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") * 1024 ))
+-	vdo_pool_header_size = 0
+-}
+-EOF
+-)
+-	verbose "VDO conversion paramaters: $PARAMS"
+-
+-	verbose "Stopping VDO volume."
+-	dry "$VDO" stop $VDOCONF --name "$VDONAME"
+-
+-	if [ "$IS_LV" = "0" ]; then
+-		verbose "Moving VDO header by 2MiB."
+-		dry "$VDO" convert $VDOCONF --force --name "$VDONAME"
+-
+-		dry "$LVM" pvcreate $YES --dataalignment 2M "$DEVICE" || {
+-			error "Creation of PV on \"$DEVICE\" failed, while VDO header has been already moved!"
+-		}
+-
+-		# Obtain free space in this new PV
+-		# after 'vdo convert/vdo2lvm' call there is +2M free space at the front of the device
+-		case "$DRY" in
+-		0) pvfree=$("$LVM" pvs -o devsize --units b --nosuffix --noheadings "$DEVICE") ;;
+-		*) pvfree=$("$BLOCKDEV" --getsize64 "$DEVICE") ;;
+-		esac
+-
+-		pvfree=$(( pvfree / 1024 - 2048 ))	# to KiB
+-	else
+-		pvfree=$("$LVM" lvs -o size --units b --nosuffix --noheadings "$VGNAME/$LVNAME")
+-		pvfree=$(( pvfree / 1024 ))		# to KiB
+-	fi
+-
+-	# select largest possible extent size that can exactly express both sizes
+-	EXTENTSZ=$(get_largest_extent_size_ "$pvfree" "$vdo_logicalSize")
+-
+-	if [ "$IS_LV" = "0" ]; then
+-		verbose "Creating VG \"${NAME%/*}\" with extent size $EXTENTSZ KiB."
+-		dry "$LVM" vgcreate $YES $VERB -s "${EXTENTSZ}k" "$VGNAME" "$DEVICE" || {
+-			error "Creation of VG \"$VGNAME\" failed, while VDO header has been already moved!"
+-		}
+-
+-		verbose "Creating VDO pool data LV from all extents in volume group $VGNAME."
+-		dry "$LVM" lvcreate -Zn -Wn $YES $VERB -l100%VG -n "${LVNAME}_vpool" "$VGNAME"
+-	else
+-		# validate existing  VG extent_size can express virtual VDO size
+-		vg_extent_size=$("$LVM" vgs -o vg_extent_size --units b --nosuffix --noheadings "$VGNAME" || true)
+-		vg_extent_size=$(( vg_extent_size / 1024 ))
+-
+-		test "$vg_extent_size" -le "$EXTENTSZ" || {
+-			error "Please vgchange extent_size to at most $EXTENTSZ KiB or extend and align virtual size on $vg_extent_size KiB."
+-		}
+-		verbose "Renaming existing LV to be used as _vdata volume for VDO pool LV."
+-		dry "$LVM" lvrename $YES $VERB "$VGNAME/$LVNAME" "$VGNAME/${LVNAME}_vpool" || {
+-			error "Rename of LV \"$VGNAME/$LVNAME\" failed, while VDO header has been already moved!"
+-		}
+-	fi
+-
+-	verbose "Converting to VDO pool."
+-	dry "$LVM" lvconvert $YES $VERB $FORCE --config "$PARAMS" -Zn -V "${vdo_logicalSize}k" -n "$LVNAME" --type vdo-pool "$VGNAME/${LVNAME}_vpool"
+-
+-	rm -fr "$TEMPDIR"
+-}
+-
+-#############################
+-# start point of this script
+-# - parsing parameters
+-#############################
+-trap "cleanup 2" 2
+-
+-test "$#" -eq 0 && tool_usage
+-
+-while [ "$#" -ne 0 ]
+-do
+-	 case "$1" in
+-	  "") ;;
+-	  "-f"|"--force"  ) FORCE="-f" ;;
+-	  "-h"|"--help"   ) tool_usage ;;
+-	  "-n"|"--name"   ) shift; NAME=$1 ;;
+-	  "-v"|"--verbose") VERB="-v" ;;
+-	  "-y"|"--yes"    ) YES="-y" ;;
+-	  "--dry-run"     ) DRY="1" ;;
+-	  "-*") error "Wrong argument \"$1\". (see: $TOOL --help)" ;;
+-	  *) DEVICENAME=$1 ;;  # device name does not start with '-'
+-	esac
+-	shift
+-done
+-
+-# do conversion
+-convert2lvm_ "$DEVICENAME"
+diff --git a/test/Makefile.in b/test/Makefile.in
+index 6be03aa..0f2cc25 100644
+--- a/test/Makefile.in
++++ b/test/Makefile.in
+@@ -353,7 +353,7 @@ LIB = $(addprefix lib/, $(LIB_SECURETEST) $(LIB_DMSECURETEST) $(LIB_SHARED) $(LI
+ 	$(Q) $(LN_S) -f $(abs_top_srcdir)/conf/lvmdbusd.profile lib/
+ 	$(Q) $(LN_S) -f $(abs_top_srcdir)/conf/thin-performance.profile lib/
+ 	$(Q) $(LN_S) -f $(abs_top_srcdir)/scripts/fsadm.sh lib/fsadm
+-	$(Q) $(LN_S) -f $(abs_top_srcdir)/scripts/vdoimport.sh lib/vdoimport
++	$(Q) $(LN_S) -f $(abs_top_srcdir)/scripts/lvm_import_vdo.sh lib/lvm_import_vdo
+ 	@test "$(srcdir)" = . || \
+ 		for i in $(LIB_LVMLOCKD_CONF) $(LIB_MKE2FS_CONF); do \
+ 			test -n "$(Q)" || echo "$(LN_S) -f $(abs_top_srcdir)/test/lib/$$i lib/"; \
+diff --git a/test/shell/vdo-convert.sh b/test/shell/vdo-convert.sh
+index 538147b..2d16c97 100644
+--- a/test/shell/vdo-convert.sh
++++ b/test/shell/vdo-convert.sh
+@@ -54,12 +54,12 @@ vdo create $VDOCONF --name "$VDONAME" --device="$DM_DEV_DIR/$vg/$lv1" --vdoLogic
+ mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
+ 
+ # Different VG name fails
+-not vdoimport -y -v --name $vg1/$lv1 "$DM_DEV_DIR/$vg/$lv1"
++not lvm_import_vdo -y -v --name $vg1/$lv1 "$DM_DEV_DIR/$vg/$lv1"
+ 
+ # Try just dry run and observe logging
+-vdoimport --dry-run -y -v --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
++lvm_import_vdo --dry-run -y -v --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
+ 
+-vdoimport -y --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
++lvm_import_vdo -y --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
+ 
+ # ATM needed - since we do not call 'vdo convert' in this case
+ vdo remove $VDOCONF --force --name "$VDONAME" || true
+@@ -79,13 +79,13 @@ vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=31G
+ mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
+ 
+ # Fail with an already existing volume group $vg2
+-not vdoimport --dry-run -y -v --name $vg2/$lv1 "$dev1" |& tee err
++not lvm_import_vdo --dry-run -y -v --name $vg2/$lv1 "$dev1" |& tee err
+ grep "already existing volume group" err
+ 
+ # User can also convert already stopped VDO volume
+ vdo stop $VDOCONF --name "$VDONAME"
+ 
+-vdoimport -y -v --name $vg/$lv1 "$dev1"
++lvm_import_vdo -y -v --name $vg/$lv1 "$dev1"
+ 
+ fsck -n "$DM_DEV_DIR/$vg/$lv1"
+ 
+@@ -102,7 +102,7 @@ vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=23G
+ 
+ mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
+ 
+-vdoimport -y -v --name $vg1/$lv2 "$dev1"
++lvm_import_vdo -y -v --name $vg1/$lv2 "$dev1"
+ 
+ fsck -n "$DM_DEV_DIR/$vg1/$lv2"
+ 
diff --git a/SOURCES/lvm2-2_03_14-vdo-better-message-for-missing-device.patch b/SOURCES/lvm2-2_03_14-vdo-better-message-for-missing-device.patch
new file mode 100644
index 0000000..b973cc1
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-vdo-better-message-for-missing-device.patch
@@ -0,0 +1,86 @@
+From deb36d236e2dd86ddc16b33d5ca8c648cc8ed369 Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Wed, 1 Sep 2021 15:46:04 +0200
+Subject: [PATCH 3/5] vdo: better message for missing device
+
+Show readable message when passed device cannot be accessed.
+And use STAT shell var wrapper to call 'stat' command.
+
+(cherry picked from commit 3287d37f440ca272b52f900fc60ee5effcf73697)
+
+Conflicts:
+	scripts/lvm_import_vdo.sh
+---
+ scripts/lvm_import_vdo.sh | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
+index f8dd71f..dec32bc 100755
+--- a/scripts/lvm_import_vdo.sh
++++ b/scripts/lvm_import_vdo.sh
+@@ -18,8 +18,8 @@
+ #
+ # Needed utilities:
+ #  lvm, dmsetup,
+-#  vdo, vdo2lvm,
+-#  grep, awk, sed, blockdev, readlink, mkdir
++#  vdo,
++#  grep, awk, sed, blockdev, readlink, stat, mkdir
+ #
+ # Conversion is using  'vdo convert' support from VDO manager to move
+ # existing VDO header by 2M which makes space to place in PV header
+@@ -40,6 +40,7 @@ VDOCONF=${VDOCONF:-}
+ BLOCKDEV="blockdev"
+ READLINK="readlink"
+ READLINK_E="-e"
++STAT="stat"
+ MKDIR="mkdir"
+ DMSETUP="dmsetup"
+ 
+@@ -156,8 +157,8 @@ detect_lv_() {
+ 	local MAJORMINOR
+ 
+ 	DEVICE=${1/#"${DM_DEV_DIR}/"/}
+-	DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE")
+-	test -n "$DEVICE" || error "Cannot get readlink \"$1\"."
++	DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE" || true)
++	test -n "$DEVICE" || error "Readlink cannot access device \"$1\"."
+ 	RDEVICE=$DEVICE
+ 	case "$RDEVICE" in
+ 	  # hardcoded /dev  since udev does not create these entries elsewhere
+@@ -168,9 +169,9 @@ detect_lv_() {
+ 		DEVMINOR=${MAJORMINOR##*:}
+ 		;;
+ 	  *)
+-		STAT=$(stat --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE")
+-		test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"."
+-		eval "$STAT"
++		RSTAT=$("$STAT" --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE" || true)
++		test -n "$RSTAT" || error "Cannot get major:minor for \"$DEVICE\"."
++		eval "$RSTAT"
+ 		;;
+ 	esac
+ 
+@@ -269,8 +270,8 @@ convert2lvm_() {
+ 	for i in $(awk '/.*device:/ {print $2}' "$TEMPDIR/vdoconf.yml") ; do
+ 		local DEV
+ 		DEV=$("$READLINK" $READLINK_E "$i") || continue
+-		STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue
+-		eval "$STAT"
++		RSTAT=$("$STAT" --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue
++		eval "$RSTAT"
+ 		test "$MAJOR" = "$DEVMAJOR" && test "$MINOR" = "$DEVMINOR" && {
+ 			test -z "$FOUND" || error "VDO configuration contains duplicate entries $FOUND and $i"
+ 			FOUND=$i
+@@ -287,7 +288,7 @@ convert2lvm_() {
+ 	DM_OPEN="$("$DMSETUP" info -c -o open  "$VDONAME" --noheadings --nameprefixes 2>/dev/null || true)"
+ 	case "$DM_OPEN" in
+ 	Device*) ;; # no devices
+-	*) 	eval "$DM_OPEN"
++	*)	eval "$DM_OPEN"
+ 		test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
+ 		;;
+ 	esac
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_03_14-vdo-fix-conversion-of-large-virtual-sizes.patch b/SOURCES/lvm2-2_03_14-vdo-fix-conversion-of-large-virtual-sizes.patch
new file mode 100644
index 0000000..9899966
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-vdo-fix-conversion-of-large-virtual-sizes.patch
@@ -0,0 +1,28 @@
+From 70467e905cea0811c269faf7e84f24d4e1c758cc Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Mon, 30 Aug 2021 18:12:59 +0200
+Subject: [PATCH 5/5] vdo: fix conversion of large virtual sizes
+
+Properly accept virtual sizes above 2TiB.
+
+(cherry picked from commit 4afe872fd6c43fcfcd519c862574d010cdbda653)
+---
+ tools/lvconvert.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/lvconvert.c b/tools/lvconvert.c
+index f87ee78..518b48f 100644
+--- a/tools/lvconvert.c
++++ b/tools/lvconvert.c
+@@ -5462,7 +5462,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
+ 		return_0;
+ 
+ 	lvc.virtual_extents = extents_from_size(cmd,
+-						arg_uint_value(cmd, virtualsize_ARG, 0),
++						arg_uint64_value(cmd, virtualsize_ARG, UINT64_C(0)),
+ 						vg->extent_size);
+ 
+ 	if (!(lvc.segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_VDO)))
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_03_14-vdo-fixes.patch b/SOURCES/lvm2-2_03_14-vdo-fixes.patch
new file mode 100644
index 0000000..ac6acb5
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-vdo-fixes.patch
@@ -0,0 +1,256 @@
+From 5d0756fc33bced8453fb5cf5807c5a3fa2b59dbb Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Tue, 31 Aug 2021 20:52:26 +0200
+Subject: [PATCH 1/5] vdo: fixes
+
+Better identify VDO device with major:minor.
+Handle different LV name from originally converted origin LV.
+Improve --dry-run handling.
+
+(cherry picked from commit 1ae157a0f67e984ef3037d19d62b84a3b0201c84)
+---
+ WHATS_NEW                 |  4 +++
+ scripts/lvm_import_vdo.sh | 70 +++++++++++++++++++++++++++++++++++------------
+ test/shell/vdo-convert.sh | 28 ++++++++++++++-----
+ 3 files changed, 78 insertions(+), 24 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 3637e31..b751009 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,9 @@
+ Version 2.03.14 - 
+ ==================================
++  Improve lvm_import_vdo script.
++  Support VDO LV with lvcreate -ky.
++  Fix lvconvert for VDO LV bigger then 2T.
++  Create VDO LVs automatically without zeroing.
+   Rename vdoimport to lvm_import_vdo.
+ 
+ Version 2.03.13 - 
+diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
+index 35140a0..bc73306 100755
+--- a/scripts/lvm_import_vdo.sh
++++ b/scripts/lvm_import_vdo.sh
+@@ -41,10 +41,15 @@ BLOCKDEV="blockdev"
+ READLINK="readlink"
+ READLINK_E="-e"
+ MKDIR="mkdir"
++DMSETUP="dmsetup"
+ 
+ TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$"
+ DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
+ 
++DEVICENAME=""
++DEVMAJOR=0
++DEVMINOR=0
++
+ DRY=0
+ VERB=""
+ FORCE=""
+@@ -147,8 +152,6 @@ get_largest_extent_size_() {
+ # dereference device name if it is symbolic link
+ detect_lv_() {
+ 	local DEVICE=$1
+-	local MAJOR
+-	local MINOR
+ 	local SYSVOLUME
+ 	local MAJORMINOR
+ 
+@@ -161,17 +164,21 @@ detect_lv_() {
+ 	  /dev/dm-[0-9]*)
+ 		read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME"
+ 		read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"."
+-		MAJOR=${MAJORMINOR%%:*}
+-		MINOR=${MAJORMINOR##*:}
++		DEVMAJOR=${MAJORMINOR%%:*}
++		DEVMINOR=${MAJORMINOR##*:}
+ 		;;
+ 	  *)
+-		STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE")
++		STAT=$(stat --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE")
+ 		test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"."
+ 		eval "$STAT"
+ 		;;
+ 	esac
+ 
+-	eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
++	DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ' 2>/dev/null)"
++	case "$DEV" in
++	Device*)  ;; # no devices
++	*)	eval "$DEV" ;;
++	esac
+ }
+ 
+ # parse yaml config files into 'prefix_yaml_part_names=("value")' strings
+@@ -226,20 +233,26 @@ convert2lvm_() {
+ 	local TRVDONAME
+ 	local EXTENTSZ
+ 	local IS_LV=1
++	local FOUND=""
++	local MAJOR=0
++	local MINOR=0
++	local DM_VG_NAME
++	local DM_LV_NAME
+ 
+ 	DM_UUID=""
+ 	detect_lv_ "$DEVICE"
+ 	case "$DM_UUID" in
+-		LVM-*)	eval "$(dmsetup splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
++		LVM-*)	eval "$("$DMSETUP" splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
+ 			if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ]  ; then
+ 				VGNAME=$DM_VG_NAME
++				LVNAME=$DM_LV_NAME
+ 			elif test "$VGNAME" != "$DM_VG_NAME" ; then
+ 				error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"."
+ 			fi
+ 			;;
+ 		*) IS_LV=0
+ 			# Check $VGNANE does not already exists
+-			"$LVM" vgs "$VGNAME" && error "Cannot use already existing volume group name \"$VGNAME\"."
++			"$LVM" vgs "$VGNAME" >/dev/null 2>&1 && error "Cannot use already existing volume group name \"$VGNAME\"."
+ 			;;
+ 	esac
+ 
+@@ -247,15 +260,37 @@ convert2lvm_() {
+ 
+ 	"$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR."
+ 
++	# TODO: might use directly  /etc/vdoconf.yml (avoding need of 'vdo' manager)
+ 	verbose "Getting YAML VDO configuration."
+ 	"$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml"
+ 
+-	VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
++	# Check list of devices in VDO configure file for their major:minor
++	# and match with given $DEVICE devmajor:devminor
++	for i in $(awk '/.*device:/ {print $2}' "$TEMPDIR/vdoconf.yml") ; do
++		local DEV
++		DEV=$("$READLINK" $READLINK_E "$i") || continue
++		STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue
++		eval "$STAT"
++		test "$MAJOR" = "$DEVMAJOR" && test "$MINOR" = "$DEVMINOR" && {
++			test -z "$FOUND" || error "VDO configuration contains duplicate entries $FOUND and $i"
++			FOUND=$i
++		}
++	done
++
++	test -n "$FOUND" || error "Can't find matching device in vdo configuration file."
++	verbose "Found matching device $FOUND  $MAJOR:$MINOR"
++
++	VDONAME=$(awk -v DNAME="$FOUND" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
+ 	TRVDONAME=$(echo "$VDONAME" | tr '-' '_')
+ 
+ 	# When VDO volume is 'active', check it's not mounted/being used
+-	eval "$(dmsetup info -c -o open  "$VDONAME" --noheadings --nameprefixes || true)"
+-	test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
++	DM_OPEN="$("$DMSETUP" info -c -o open  "$VDONAME" --noheadings --nameprefixes 2>/dev/null || true)"
++	case "$DM_OPEN" in
++	Device*) ;; # no devices
++	*) 	eval "$DM_OPEN"
++		test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
++		;;
++	esac
+ 
+ 	#parse_yaml_ "$TEMPDIR/vdoconf.yml" _
+ 	eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")"
+@@ -263,8 +298,7 @@ convert2lvm_() {
+ 	vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize")
+ 	vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize")
+ 
+-	verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB."
+-	verbose "With logical volume of size $vdo_logicalSize KiB."
++	verbose "Converted VDO device has logical/physical size $vdo_logicalSize/$vdo_physicalSize KiB."
+ 
+ 	PARAMS=$(cat <<EOF
+ allocation {
+@@ -313,7 +347,7 @@ EOF
+ 
+ 		pvfree=$(( pvfree / 1024 - 2048 ))	# to KiB
+ 	else
+-		pvfree=$("$LVM" lvs -o size --units b --nosuffix --noheadings "$VGNAME/$LVNAME")
++		pvfree=$("$LVM" lvs -o size --units b --nosuffix --noheadings "$DM_VG_NAME/$DM_LV_NAME")
+ 		pvfree=$(( pvfree / 1024 ))		# to KiB
+ 	fi
+ 
+@@ -334,11 +368,11 @@ EOF
+ 		vg_extent_size=$(( vg_extent_size / 1024 ))
+ 
+ 		test "$vg_extent_size" -le "$EXTENTSZ" || {
+-			error "Please vgchange extent_size to at most $EXTENTSZ KiB or extend and align virtual size on $vg_extent_size KiB."
++			error "Please vgchange extent_size to at most $EXTENTSZ KiB or extend and align virtual size of VDO device on $vg_extent_size KiB."
+ 		}
+ 		verbose "Renaming existing LV to be used as _vdata volume for VDO pool LV."
+-		dry "$LVM" lvrename $YES $VERB "$VGNAME/$LVNAME" "$VGNAME/${LVNAME}_vpool" || {
+-			error "Rename of LV \"$VGNAME/$LVNAME\" failed, while VDO header has been already moved!"
++		dry "$LVM" lvrename $YES $VERB "$VGNAME/$DM_LV_NAME" "$VGNAME/${LVNAME}_vpool" || {
++			error "Rename of LV \"$VGNAME/$DM_LV_NAME\" failed, while VDO header has been already moved!"
+ 		}
+ 	fi
+ 
+@@ -372,5 +406,7 @@ do
+ 	shift
+ done
+ 
++test -n "$DEVICENAME" || error "Device name is not specified. (see: $TOOL --help)"
++
+ # do conversion
+ convert2lvm_ "$DEVICENAME"
+diff --git a/test/shell/vdo-convert.sh b/test/shell/vdo-convert.sh
+index 2d16c97..493f415 100644
+--- a/test/shell/vdo-convert.sh
++++ b/test/shell/vdo-convert.sh
+@@ -61,22 +61,36 @@ lvm_import_vdo --dry-run -y -v --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
+ 
+ lvm_import_vdo -y --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
+ 
+-# ATM needed - since we do not call 'vdo convert' in this case
+-vdo remove $VDOCONF --force --name "$VDONAME" || true
++# ensure VDO device is not left in config file
++vdo remove $VDOCONF --force --name "$VDONAME" 2>/dev/null || true
++
++lvremove -f $vg
++
++
++# Test user can specify different VDO LV name (so the original LV is renamed)
++lvcreate -y -L5G -n $lv1 $vg
++
++vdo create $VDOCONF --name "$VDONAME" --device="$DM_DEV_DIR/$vg/$lv1" --vdoLogicalSize=10G
++
++lvm_import_vdo -y --name $vg/$lv2 "$DM_DEV_DIR/$vg/$lv1"
++
++check lv_exists $vg $lv2
++check lv_not_exists $vg $lv1
+ 
+ vgremove -f $vg
+ 
++# ensure VDO device is not left in config file
++vdo remove $VDOCONF --force --name "$VDONAME" 2>/dev/null || true
++
+ aux wipefs_a "$dev1"
+ 
+ # prepare 'unused' $vg2
+ vgcreate $vg2 "$dev2"
+ 
+ #
+-# Check conversion of VDO volume on  non-LV device
++# Check conversion of VDO volume on non-LV device and with >2T size
+ #
+-vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=31G
+-
+-mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
++vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=3T
+ 
+ # Fail with an already existing volume group $vg2
+ not lvm_import_vdo --dry-run -y -v --name $vg2/$lv1 "$dev1" |& tee err
+@@ -87,7 +101,7 @@ vdo stop $VDOCONF --name "$VDONAME"
+ 
+ lvm_import_vdo -y -v --name $vg/$lv1 "$dev1"
+ 
+-fsck -n "$DM_DEV_DIR/$vg/$lv1"
++check lv_field $vg/$lv1 size "3.00t"
+ 
+ vgremove -f $vg
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-fix-max_discard-size.patch b/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-fix-max_discard-size.patch
new file mode 100644
index 0000000..0265448
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-fix-max_discard-size.patch
@@ -0,0 +1,28 @@
+From 60eb37394b536e3b969496611ff4b59b71123476 Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Mon, 6 Sep 2021 14:57:43 +0200
+Subject: [PATCH 2/5] vdo: lvm_import_vdo fix max_discard size
+
+Use correct 4K units in lvm2 for max_discard VDO option.
+
+(cherry picked from commit 8d5b7de54f21ce5e34d533599f9d5a42f2977cd5)
+---
+ scripts/lvm_import_vdo.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
+index bc73306..f8dd71f 100755
+--- a/scripts/lvm_import_vdo.sh
++++ b/scripts/lvm_import_vdo.sh
+@@ -320,7 +320,7 @@ allocation {
+ 	vdo_logical_threads = $vdo_logicalThreads
+ 	vdo_physical_threads = $vdo_physicalThreads
+ 	vdo_write_policy = $vdo_writePolicy
+-	vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") * 1024 ))
++	vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") / 4 ))
+ 	vdo_pool_header_size = 0
+ }
+ EOF
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-script-needs-to-continue-when-vgn.patch b/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-script-needs-to-continue-when-vgn.patch
new file mode 100644
index 0000000..02bd359
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-script-needs-to-continue-when-vgn.patch
@@ -0,0 +1,29 @@
+From 4cf3e8bd846a171b4b945f289bf0c6f9c7b5864c Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Thu, 9 Sep 2021 18:10:13 +0200
+Subject: [PATCH 3/5] vdo: lvm_import_vdo script needs to continue when vgname
+ does not exist
+
+When the script cannot find vgname - it needs to continue to run.
+
+(cherry picked from commit 9db4ddabc1cf912dee30e0e6293767f01c976a4a)
+---
+ scripts/lvm_import_vdo.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
+index 70904f7..e5b30d8 100755
+--- a/scripts/lvm_import_vdo.sh
++++ b/scripts/lvm_import_vdo.sh
+@@ -262,7 +262,7 @@ convert2lvm_() {
+ 			if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then
+ 				VGNAME=${DEFAULT_NAME%/*}
+ 				# Find largest matching VG name to our 'default' vgname
+-				LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~${VGNAME} | grep -E "$VGNAME[0-9]? ?" | head -1)
++				LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~${VGNAME} | grep -E "$VGNAME[0-9]? ?" | head -1 || true)
+ 				if test -n "$LASTVGNAME" ; then
+ 					LASTVGNAME=${LASTVGNAME#*${VGNAME}}
+ 					# If the number is becoming too high, try some random number
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_03_14-vdo-man-page-updates.patch b/SOURCES/lvm2-2_03_14-vdo-man-page-updates.patch
new file mode 100644
index 0000000..03ca40a
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-vdo-man-page-updates.patch
@@ -0,0 +1,27 @@
+From 073cdd0ba8c39a0330e73773c92d78546d06e687 Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Fri, 10 Sep 2021 01:15:01 +0200
+Subject: [PATCH 4/5] vdo: man page updates
+
+(cherry picked from commit 812653d59806439379d80bb8124f6962ae42d46a)
+---
+ man/lvm_import_vdo.8_main | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/man/lvm_import_vdo.8_main b/man/lvm_import_vdo.8_main
+index ee817a0..c6cb5c3 100644
+--- a/man/lvm_import_vdo.8_main
++++ b/man/lvm_import_vdo.8_main
+@@ -45,6 +45,9 @@ Specifies the name of converted VDO LV. When the name is not specified,
+ some automatic name is selected. In case the converted VDO volume is
+ already using LV a backend device, the name of this LV is used for VDO LV.
+ In this case also the of volume group must stay same.
++Automatic name may change between releases and currently selects
++"vdolv" as LV name and VG name is selected from sequence
++"vdovg", "vdovg1", ...
+ .
+ .TP
+ .BR -v | --verbose
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_03_14-vdo-more-lvm_import_vdo-fixes.patch b/SOURCES/lvm2-2_03_14-vdo-more-lvm_import_vdo-fixes.patch
new file mode 100644
index 0000000..fb70af2
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-vdo-more-lvm_import_vdo-fixes.patch
@@ -0,0 +1,185 @@
+From 6621116b61f4c9ee53166a994be2ef7d80a3c346 Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Mon, 6 Sep 2021 15:06:32 +0200
+Subject: [PATCH 4/5] vdo: more lvm_import_vdo fixes
+
+Do not call 'dmsetup info' for non-dm devices.
+
+Better handling for VGNAME and LVNAME - so when convering LV as
+backend device automatically recognize it and reuse LV name for VDOLV.
+
+Add prompt for final confirmation before actual conversion is started
+(once confirmed, lvm2 commands no longer prompts to avoid leaving
+conversion in the middle of its process.)
+
+(cherry picked from commit 89595a366554191c3df1a18e1f82b79c450a21ad)
+---
+ scripts/lvm_import_vdo.sh | 48 ++++++++++++++++++++++++++++++++++------
+ test/shell/vdo-convert.sh | 56 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 97 insertions(+), 7 deletions(-)
+
+diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
+index dec32bc..70904f7 100755
+--- a/scripts/lvm_import_vdo.sh
++++ b/scripts/lvm_import_vdo.sh
+@@ -50,6 +50,7 @@ DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
+ DEVICENAME=""
+ DEVMAJOR=0
+ DEVMINOR=0
++PROMPTING=""
+ 
+ DRY=0
+ VERB=""
+@@ -57,7 +58,8 @@ FORCE=""
+ YES=""
+ 
+ # default name for converted VG and its VDO LV
+-NAME="vdovg/vdolvol"
++DEFAULT_NAME="vdovg/vdolvol"
++NAME=""
+ 
+ # help message
+ tool_usage() {
+@@ -100,6 +102,7 @@ dry() {
+ cleanup() {
+ 	trap '' 2
+ 
++	test -z "$PROMPTING" || echo "No"
+ 	rm -rf "$TEMPDIR"
+ 	# error exit status for break
+ 	exit "${1:-1}"
+@@ -175,7 +178,9 @@ detect_lv_() {
+ 		;;
+ 	esac
+ 
+-	DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ' 2>/dev/null)"
++	test "$DEVMAJOR" != "$(grep device-mapper /proc/devices | cut -f1 -d' ')" && return
++
++	DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
+ 	case "$DEV" in
+ 	Device*)  ;; # no devices
+ 	*)	eval "$DEV" ;;
+@@ -244,15 +249,31 @@ convert2lvm_() {
+ 	detect_lv_ "$DEVICE"
+ 	case "$DM_UUID" in
+ 		LVM-*)	eval "$("$DMSETUP" splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
+-			if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ]  ; then
++			if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then
+ 				VGNAME=$DM_VG_NAME
+-				LVNAME=$DM_LV_NAME
++				verbose "Using existing volume group name $VGNAME."
++				test -n "$LVNAME" || LVNAME=$DM_LV_NAME
+ 			elif test "$VGNAME" != "$DM_VG_NAME" ; then
+-				error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"."
++				error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for VDO device \"$DEVICE\"."
+ 			fi
+ 			;;
+-		*) IS_LV=0
+-			# Check $VGNANE does not already exists
++		*)	IS_LV=0
++			# Check if we need to generate unused $VGNANE
++			if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then
++				VGNAME=${DEFAULT_NAME%/*}
++				# Find largest matching VG name to our 'default' vgname
++				LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~${VGNAME} | grep -E "$VGNAME[0-9]? ?" | head -1)
++				if test -n "$LASTVGNAME" ; then
++					LASTVGNAME=${LASTVGNAME#*${VGNAME}}
++					# If the number is becoming too high, try some random number
++					test "$LASTVGNAME" -gt 99999999 2>/dev/null && LASTVGNAME=$RANDOM
++					# Generate new unused VG name
++					VGNAME="${VGNAME}$(( ${LASTVGNAME} + 1 ))"
++					verbose "Selected unused volume group name $VGNAME."
++				fi
++			fi
++			# New VG is created, LV name should be always unused.
++			test -n "$LVNAME" || LVNAME=${DEFAULT_NAME#*/}
+ 			"$LVM" vgs "$VGNAME" >/dev/null 2>&1 && error "Cannot use already existing volume group name \"$VGNAME\"."
+ 			;;
+ 	esac
+@@ -328,6 +349,19 @@ EOF
+ )
+ 	verbose "VDO conversion paramaters: $PARAMS"
+ 
++	# If user has not provided '--yes', prompt before conversion
++	if test -z "$YES" ; then
++		PROMPTING=yes
++		echo -n "Convert VDO device \"$DEVICE\" to VDO LV \"$VGNAME/$LVNAME\"? [y|N]: "
++		read -n 1 -s ANSWER
++		case "${ANSWER:0:1}" in
++			y|Y )  echo "Yes" ;;
++			* )    echo "No" ; PROMPTING=""; exit ;;
++		esac
++		PROMPTING=""
++		YES="-y" # From now, now prompting
++	fi
++
+ 	verbose "Stopping VDO volume."
+ 	dry "$VDO" stop $VDOCONF --name "$VDONAME"
+ 
+diff --git a/test/shell/vdo-convert.sh b/test/shell/vdo-convert.sh
+index 493f415..632f86a 100644
+--- a/test/shell/vdo-convert.sh
++++ b/test/shell/vdo-convert.sh
+@@ -122,3 +122,59 @@ fsck -n "$DM_DEV_DIR/$vg1/$lv2"
+ 
+ vgremove -f $vg1
+ 
++aux teardown_devs
++
++
++# Check with some real non-DM device from system
++# this needs to dropping DM_DEV_DIR
++
++aux prepare_loop 60000 || skip
++
++test -f LOOP
++LOOP=$(< LOOP)
++
++aux extend_filter "a|$LOOP|"
++aux extend_devices "$LOOP"
++
++#
++# Unfortunatelly generates this in syslog:
++#
++# vdo-start-by-dev@loop0.service: Main process exited, code=exited, status=1/FAILURE
++# vdo-start-by-dev@loop0.service: Failed with result 'exit-code'.
++# Failed to start Start VDO volume backed by loop0.
++#
++# TODO:  Could be handled by:
++#
++# systemctl mask vdo-start-by-dev@
++# systemctl unmask vdo-start-by-dev@
++#
++# automate...
++#
++vdo create $VDOCONF --name "$VDONAME" --device="$LOOP" --vdoLogicalSize=23G \
++	--blockMapCacheSize 192 \
++	--blockMapPeriod 2048 \
++	--emulate512 disabled \
++	--indexMem 0.5 \
++	--maxDiscardSize 10 \
++	--sparseIndex disabled \
++	--vdoAckThreads 2 \
++	--vdoBioRotationInterval 8 \
++	--vdoBioThreads 2 \
++	--vdoCpuThreads 5 \
++	--vdoHashZoneThreads 3 \
++	--vdoLogicalThreads 3 \
++	--writePolicy async-unsafe
++
++# Get VDO table line
++dmsetup table "$VDONAME" | tr " " "\n" | sed -e '5,6d' -e '12d' | tee vdo-orig
++
++DM_DEV_DIR= lvm_import_vdo -y --name $vg/$lv "$LOOP"
++lvs -a $vg
++
++dmsetup table "$vg-${lv}_vpool-vpool" | tr " " "\n" | sed -e '5,6d' -e '12d' | tee new-vdo-lv
++
++# Check there is a match between VDO and LV managed volume
++# (when differentiating parameters are deleted first)
++diff -u vdo-orig new-vdo-lv || die "Found mismatching VDO table lines!"
++
++check lv_field $vg/$lv size "23.00g"
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_03_14-vdo-prompt-with-no-return-failure.patch b/SOURCES/lvm2-2_03_14-vdo-prompt-with-no-return-failure.patch
new file mode 100644
index 0000000..4642667
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-vdo-prompt-with-no-return-failure.patch
@@ -0,0 +1,28 @@
+From f3f99d45b89d415528e21a66f94ab4576f95ba56 Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Fri, 10 Sep 2021 22:39:23 +0200
+Subject: [PATCH 5/5] vdo: prompt with no return failure
+
+Exit 1  (failure) when prompt for conversion is answered as 'No'.
+
+(cherry picked from commit 3b24c0fe4e197383101eae53b14f19586cf2eda1)
+---
+ scripts/lvm_import_vdo.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
+index e5b30d8..06a043c 100755
+--- a/scripts/lvm_import_vdo.sh
++++ b/scripts/lvm_import_vdo.sh
+@@ -356,7 +356,7 @@ EOF
+ 		read -n 1 -s ANSWER
+ 		case "${ANSWER:0:1}" in
+ 			y|Y )  echo "Yes" ;;
+-			* )    echo "No" ; PROMPTING=""; exit ;;
++			* )    echo "No" ; PROMPTING=""; exit 1 ;;
+ 		esac
+ 		PROMPTING=""
+ 		YES="-y" # From now, now prompting
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_03_14-vdo-read-new-sysfs-path.patch b/SOURCES/lvm2-2_03_14-vdo-read-new-sysfs-path.patch
new file mode 100644
index 0000000..c2d5f72
--- /dev/null
+++ b/SOURCES/lvm2-2_03_14-vdo-read-new-sysfs-path.patch
@@ -0,0 +1,184 @@
+From 1c6992d37eff5af7134a11b662eacc1bab538ac2 Mon Sep 17 00:00:00 2001
+From: Zdenek Kabelac <zkabelac@redhat.com>
+Date: Thu, 9 Sep 2021 14:59:38 +0200
+Subject: [PATCH 1/5] vdo: read new sysfs path
+
+New versions of kvdo module exposes statistics at new location:
+/sys/block/dm-XXX/vdo/statistics/...
+
+Enhance lvm2 to access this location first.
+Also if the statistic info is missing - make it 'debug' level info,
+so it is not failing 'lvs' command.
+
+(cherry picked from commit e6f735d411e5911de186a610932c9bb9638275eb)
+
+Conflicts:
+	WHATS_NEW
+---
+ WHATS_NEW                        |  1 +
+ lib/activate/dev_manager.c       |  7 +++---
+ lib/metadata/metadata-exported.h |  3 ++-
+ lib/metadata/vdo_manip.c         | 46 ++++++++++++++++++++++------------------
+ 4 files changed, 32 insertions(+), 25 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index b751009..c5a5ca5 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,6 @@
+ Version 2.03.14 - 
+ ==================================
++  Support newer location for VDO statistics.
+   Improve lvm_import_vdo script.
+   Support VDO LV with lvcreate -ky.
+   Fix lvconvert for VDO LV bigger then 2T.
+diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
+index c4a6739..0d954d1 100644
+--- a/lib/activate/dev_manager.c
++++ b/lib/activate/dev_manager.c
+@@ -157,6 +157,7 @@ out:
+ 
+ static int _get_segment_status_from_target_params(const char *target_name,
+ 						  const char *params,
++						  const struct dm_info *dminfo,
+ 						  struct lv_seg_status *seg_status)
+ {
+ 	const struct lv_segment *seg = seg_status->seg;
+@@ -216,7 +217,7 @@ static int _get_segment_status_from_target_params(const char *target_name,
+ 			return_0;
+ 		seg_status->type = SEG_STATUS_SNAPSHOT;
+ 	} else if (segtype_is_vdo_pool(segtype)) {
+-		if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, &seg_status->vdo_pool))
++		if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, dminfo, &seg_status->vdo_pool))
+ 			return_0;
+ 		seg_status->type = SEG_STATUS_VDO_POOL;
+ 	} else if (segtype_is_writecache(segtype)) {
+@@ -320,7 +321,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
+ 		} while (target);
+ 
+ 		if (!target_name ||
+-		    !_get_segment_status_from_target_params(target_name, target_params, seg_status))
++		    !_get_segment_status_from_target_params(target_name, target_params, dminfo, seg_status))
+ 			stack;
+ 	}
+ 
+@@ -1886,7 +1887,7 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
+ 		goto out;
+ 	}
+ 
+-	if (!parse_vdo_pool_status(dm->mem, lv, params, *status))
++	if (!parse_vdo_pool_status(dm->mem, lv, params, &info, *status))
+ 		goto_out;
+ 
+ 	(*status)->mem = dm->mem;
+diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
+index adbbe76..7c21b4d 100644
+--- a/lib/metadata/metadata-exported.h
++++ b/lib/metadata/metadata-exported.h
+@@ -1364,7 +1364,8 @@ const char *get_vdo_write_policy_name(enum dm_vdo_write_policy policy);
+ uint64_t get_vdo_pool_virtual_size(const struct lv_segment *vdo_pool_seg);
+ int update_vdo_pool_virtual_size(struct lv_segment *vdo_pool_seg);
+ int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_pool_lv,
+-			  const char *params, struct lv_status_vdo *status);
++			  const char *params, const struct dm_info *dminfo,
++			  struct lv_status_vdo *status);
+ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
+ 					   const struct dm_vdo_target_params *vtp,
+ 					   uint32_t *virtual_extents,
+diff --git a/lib/metadata/vdo_manip.c b/lib/metadata/vdo_manip.c
+index 3f2de1a..2917f29 100644
+--- a/lib/metadata/vdo_manip.c
++++ b/lib/metadata/vdo_manip.c
+@@ -123,48 +123,56 @@ int update_vdo_pool_virtual_size(struct lv_segment *vdo_pool_seg)
+ 	return 1;
+ }
+ 
+-static int _sysfs_get_kvdo_value(const char *dm_name, const char *vdo_param, uint64_t *value)
++static int _sysfs_get_kvdo_value(const char *dm_name, const struct dm_info *dminfo,
++				 const char *vdo_param, uint64_t *value)
+ {
+ 	char path[PATH_MAX];
+ 	char temp[64];
+ 	int fd, size, r = 0;
+ 
+-	if (dm_snprintf(path, sizeof(path), "%skvdo/%s/%s",
+-			dm_sysfs_dir(), dm_name, vdo_param) < 0) {
+-		log_error("Failed to build kmod path.");
++	if (dm_snprintf(path, sizeof(path), "%s/block/dm-%d/vdo/%s",
++			dm_sysfs_dir(), dminfo->minor, vdo_param) < 0) {
++		log_debug("Failed to build kvdo path.");
+ 		return 0;
+ 	}
+ 
+ 	if ((fd = open(path, O_RDONLY)) < 0) {
+-		if (errno != ENOENT)
+-			log_sys_error("open", path);
+-		else
++		/* try with older location */
++		if (dm_snprintf(path, sizeof(path), "%skvdo/%s/%s",
++				dm_sysfs_dir(), dm_name, vdo_param) < 0) {
++			log_debug("Failed to build kvdo path.");
++			return 0;
++		}
++
++		if ((fd = open(path, O_RDONLY)) < 0) {
+ 			log_sys_debug("open", path);
+-		goto bad;
++			goto bad;
++		}
+ 	}
+ 
+ 	if ((size = read(fd, temp, sizeof(temp) - 1)) < 0) {
+-		log_sys_error("read", path);
++		log_sys_debug("read", path);
+ 		goto bad;
+ 	}
+ 	temp[size] = 0;
+ 	errno = 0;
+ 	*value = strtoll(temp, NULL, 0);
+ 	if (errno) {
+-		log_sys_error("strtool", path);
++		log_sys_debug("strtool", path);
+ 		goto bad;
+ 	}
+ 
+ 	r = 1;
+ bad:
+ 	if (fd >= 0 && close(fd))
+-		log_sys_error("close", path);
++		log_sys_debug("close", path);
+ 
+ 	return r;
+ }
+ 
+ int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_pool_lv,
+-			  const char *params, struct lv_status_vdo *status)
++			  const char *params, const struct dm_info *dminfo,
++			  struct lv_status_vdo *status)
+ {
+ 	struct dm_vdo_status_parse_result result;
+ 	char *dm_name;
+@@ -188,15 +196,11 @@ int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_
+ 
+ 	status->vdo = result.status;
+ 
+-	if (result.status->operating_mode == DM_VDO_MODE_NORMAL) {
+-		if (!_sysfs_get_kvdo_value(dm_name, "statistics/data_blocks_used",
+-					   &status->data_blocks_used))
+-			return_0;
+-
+-		if (!_sysfs_get_kvdo_value(dm_name, "statistics/logical_blocks_used",
+-					   &status->logical_blocks_used))
+-			return_0;
+-
++	if ((result.status->operating_mode == DM_VDO_MODE_NORMAL) &&
++	    _sysfs_get_kvdo_value(dm_name, dminfo, "statistics/data_blocks_used",
++				  &status->data_blocks_used) &&
++	    _sysfs_get_kvdo_value(dm_name, dminfo, "statistics/logical_blocks_used",
++				  &status->logical_blocks_used)) {
+ 		status->usage = dm_make_percent(result.status->used_blocks,
+ 						result.status->total_blocks);
+ 		status->saving = dm_make_percent(status->logical_blocks_used - status->data_blocks_used,
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-make-generate.patch b/SOURCES/lvm2-make-generate.patch
new file mode 100644
index 0000000..0b37216
--- /dev/null
+++ b/SOURCES/lvm2-make-generate.patch
@@ -0,0 +1,146 @@
+ man/lvconvert.8_pregen  |  2 +-
+ man/lvmdevices.8_pregen | 79 ++++++++++++++++++++++++++++++++++++++++---------
+ 2 files changed, 66 insertions(+), 15 deletions(-)
+
+diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen
+index d733ab6..4fafe5d 100644
+--- a/man/lvconvert.8_pregen
++++ b/man/lvconvert.8_pregen
+@@ -670,7 +670,7 @@ Convert LV to type thin-pool.
+ .RE
+ .P
+ .RS 4
+-LV1 types: linear striped cache raid error zero
++LV1 types: linear striped cache raid error zero writecache
+ .RE
+ .P
+ \(em
+diff --git a/man/lvmdevices.8_pregen b/man/lvmdevices.8_pregen
+index 267ce96..fa85362 100644
+--- a/man/lvmdevices.8_pregen
++++ b/man/lvmdevices.8_pregen
+@@ -28,6 +28,8 @@ lvmdevices \(em Manage the devices file
+ .br
+     \fB--delpvid\fP \fIString\fP
+ .br
++    \fB--deviceidtype\fP \fIString\fP
++.br
+     \fB--devices\fP \fIPV\fP
+ .br
+     \fB--devicesfile\fP \fIString\fP
+@@ -70,18 +72,18 @@ remove it from the devices file with lvmdevices --deldev.  The
+ vgimportdevices(8) command adds all PVs from a VG to the devices file,
+ and updates the VG metadata to include device IDs of the PVs.
+ .P
+-Commands adding new devices to the devices file necessarily look outside
+-the existing devices file to find the devices to add.  pvcreate, vgcreate,
+-and vgextend also look outside the devices file to create new PVs and add
+-them to the devices file.
++Commands that add new devices to the devices file necessarily look outside
++the existing devices file to find the devices being added.  pvcreate,
++vgcreate, and vgextend also look outside the devices file to create new
++PVs and add those PVs to the devices file.
+ .P
+ LVM records devices in the devices file using hardware-specific IDs, such
+ as the WWID, and attempts to use subsystem-specific IDs for virtual device
+-types (which also aim to be as unique and stable as possible.)
+-These device IDs are also written in the VG metadata.  When no hardware or
++types (which also aim to be as unique and stable as possible.) These
++device IDs are also written in the VG metadata.  When no hardware or
+ virtual ID is available, lvm falls back using the unstable device name as
+-the device ID.  When devnames are used, lvm performs extra scanning to
+-find devices if their devname changes, e.g. after reboot.
++the device ID.  When devnames are used as IDs, lvm performs extra scanning
++to find devices if their devname changes, e.g. after reboot.
+ .P
+ When proper device IDs are used, an lvm command will not look at devices
+ outside the devices file, but when devnames are used as a fallback, lvm
+@@ -95,12 +97,13 @@ overriding the devices file.  The listed devices act as a sort of devices
+ file in terms of limiting which devices lvm will see and use.  Devices
+ that are not listed will appear to be missing to the lvm command.
+ .P
+-Multiple devices files can be kept in \fI#DEFAULT_SYS_DIR#/devices\fP, which allows lvm
+-to be used with different sets of devices, e.g. system devices do not need
+-to be exposed to a specific application, and the application can use lvm on
+-its own devices that are not exposed to the system.  The option
+---devicesfile <filename> is used to select the devices file to use with the
+-command.  Without the option set, the default system devices file is used.
++Multiple devices files can be kept \fI#DEFAULT_SYS_DIR#/devices\fP, which
++allows lvm to be used with different sets of devices.  For example, system
++devices do not need to be exposed to a specific application, and the
++application can use lvm on its own devices that are not exposed to the
++system.  The option --devicesfile <filename> is used to select the devices
++file to use with the command.  Without the option set, the default system
++devices file is used.
+ .P
+ Setting --devicesfile "" causes lvm to not use a devices file.
+ .P
+@@ -120,6 +123,45 @@ if it does not yet exist.
+ .P
+ It is recommended to use lvm commands to make changes to the devices file to
+ ensure proper updates.
++.P
++The device ID and device ID type are included in the VG metadata and can
++be reported with pvs -o deviceid,deviceidtype.  (Note that the lvmdevices
++command does not update VG metadata, but subsequent lvm commands modifying
++the metadata will include the device ID.)
++.P
++Possible device ID types are:
++.br
++.IP \[bu] 2
++.B sys_wwid
++uses the wwid reported by sysfs.  This is the first choice for non-virtual
++devices.
++.IP \[bu] 2
++.B sys_serial
++uses the serial number reported by sysfs.  This is the second choice for
++non-virtual devices.
++.IP \[bu] 2
++.B mpath_uuid
++is used for dm multipath devices, reported by sysfs.
++.IP \[bu] 2
++.B crypt_uuid
++is used for dm crypt devices, reported by sysfs.
++.IP \[bu] 2
++.B md_uuid
++is used for md devices, reported by sysfs.
++.B lvmlv_uuid
++is used if a PV is placed on top of an lvm LV, reported by sysfs.
++.IP \[bu] 2
++.B loop_file
++is used for loop devices, the backing file name repored by sysfs.
++.IP \[bu] 2
++.B devname
++the device name is used if no other type applies.
++.P
++
++The default choice for device ID type can be overriden using lvmdevices
++--addev --deviceidtype <type>.  If the specified type is available for the
++device it will be used, otherwise the device will be added using the type
++that would otherwise be chosen.
+ .
+ .SH USAGE
+ .
+@@ -169,6 +211,8 @@ Add a device to the devices file.
+ .br
+ .RS 4
+ .ad l
++[    \fB--deviceidtype\fP \fIString\fP ]
++.br
+ [ COMMON_OPTIONS ]
+ .ad b
+ .RE
+@@ -308,6 +352,13 @@ Remove a device from the devices file.
+ Remove a device with the PVID from the devices file.
+ .
+ .HP
++\fB--deviceidtype\fP \fIString\fP
++.br
++The type of device ID to use for the device.
++If the specified type is available for the device,
++then it will override the default type that lvm would use.
++.
++.HP
+ \fB--devices\fP \fIPV\fP
+ .br
+ Devices that the command can use. This option can be repeated
diff --git a/SOURCES/lvm2-rhel8.patch b/SOURCES/lvm2-rhel8.patch
index 874c350..8af2792 100644
--- a/SOURCES/lvm2-rhel8.patch
+++ b/SOURCES/lvm2-rhel8.patch
@@ -3,16 +3,16 @@
  2 files changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/VERSION b/VERSION
-index a6ba8f6..2a15962 100644
+index d9c3e23..2610861 100644
 --- a/VERSION
 +++ b/VERSION
 @@ -1 +1 @@
--2.03.11(2) (2021-01-08)
-+2.03.11(2)-RHEL8 (2021-01-28)
+-2.03.12(2) (2021-05-07)
++2.03.12(2)-RHEL8 (2021-05-19)
 diff --git a/VERSION_DM b/VERSION_DM
-index f44bc5f..2475a11 100644
+index 6105a0f..0991c69 100644
 --- a/VERSION_DM
 +++ b/VERSION_DM
 @@ -1 +1 @@
--1.02.175 (2021-01-08)
-+1.02.175-RHEL8 (2021-01-28)
+-1.02.177 (2021-05-07)
++1.02.177-RHEL8 (2021-05-19)
diff --git a/SOURCES/lvm2-set-default-preferred_names.patch b/SOURCES/lvm2-set-default-preferred_names.patch
index 26bef54..88912bb 100644
--- a/SOURCES/lvm2-set-default-preferred_names.patch
+++ b/SOURCES/lvm2-set-default-preferred_names.patch
@@ -1,23 +1,25 @@
- conf/example.conf.in         | 3 ++-
+ conf/example.conf.in         | 5 +++--
  lib/config/config_settings.h | 2 +-
- 2 files changed, 3 insertions(+), 2 deletions(-)
+ 2 files changed, 4 insertions(+), 3 deletions(-)
 
 diff --git a/conf/example.conf.in b/conf/example.conf.in
-index fe17942..d149ed9 100644
+index b4a55ae..aaf73a4 100644
 --- a/conf/example.conf.in
 +++ b/conf/example.conf.in
-@@ -122,7 +122,8 @@ devices {
+@@ -121,8 +121,9 @@ devices {
+ 	#
  	# Example
  	# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
- 	# 
+-	#
 -	# This configuration option does not have a default value defined.
++	# 
 +	# This configuration option has an automatic default value.
 +	# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
  
- 	# Configuration option devices/filter.
- 	# Limit the block devices that are used by LVM commands.
+ 	# Configuration option devices/use_devicesfile.
+ 	# Enable or disable the use of a devices file.
 diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
-index 163e014..3c4032e 100644
+index d3a42a1..f5dac4d 100644
 --- a/lib/config/config_settings.h
 +++ b/lib/config/config_settings.h
 @@ -269,7 +269,7 @@ cfg(devices_hints_CFG, "hints", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_
diff --git a/SOURCES/lvm2-test-skip-problematic-tests.patch b/SOURCES/lvm2-test-skip-problematic-tests.patch
index b8c65d9..0f107ad 100644
--- a/SOURCES/lvm2-test-skip-problematic-tests.patch
+++ b/SOURCES/lvm2-test-skip-problematic-tests.patch
@@ -3,10 +3,10 @@
  2 files changed, 4 insertions(+), 3 deletions(-)
 
 diff --git a/test/dbus/lvmdbustest.py b/test/dbus/lvmdbustest.py
-index efa1afb..473bb94 100755
+index 6d69222..64faf84 100755
 --- a/test/dbus/lvmdbustest.py
 +++ b/test/dbus/lvmdbustest.py
-@@ -1851,6 +1851,7 @@ class TestDbusService(unittest.TestCase):
+@@ -1856,6 +1856,7 @@ class TestDbusService(unittest.TestCase):
  		# path to it.  Additionally, we will take the symlink and do a lookup
  		# (Manager.LookUpByLvmId) using it and the original device path to
  		# ensure that we can find the PV.
diff --git a/SPECS/lvm2.spec b/SPECS/lvm2.spec
index 3262fe8..7da9aa8 100644
--- a/SPECS/lvm2.spec
+++ b/SPECS/lvm2.spec
@@ -1,4 +1,4 @@
-%global device_mapper_version 1.02.175
+%global device_mapper_version 1.02.177
 
 %global enable_cache 1
 %global enable_cluster 1
@@ -20,6 +20,7 @@
 %global bash_version 4.0
 %global corosync_version 1.99.9-1
 %global resource_agents_version 3.9.5-12
+# TODO: This needs newer dlm - do I need a side tag??? :-/
 %global dlm_version 4.0.9-1
 %global libselinux_version 1.30.19-4
 %global persistent_data_version 0.7.0-0.1.rc6
@@ -40,14 +41,12 @@
   %endif
 %endif
 
-%if %{enable_cluster}
-  %global configure_cluster --with-cluster=internal
-  %if %{enable_cmirror}
-    %global configure_cmirror --enable-cmirrord
-  %endif
-%else
-    %global configure_cluster --with-cluster=internal
+%global from_snapshot 0
+%if 0%{?from_snapshot}
+%global commit 4dc5d4ac7e7a9457ccc46ff04796b347e58bf4da
+%global shortcommit %(c=%{commit}; echo ${c:0:7})
 %endif
+#%%global rel_suffix .test
 
 # Do not reset Release to 1 unless both lvm2 and device-mapper
 # versions are increased together.
@@ -56,48 +55,67 @@ Name: lvm2
 %if 0%{?rhel}
 Epoch: %{rhel}
 %endif
-Version: 2.03.11
-Release: 5%{?dist}
+Version: 2.03.12
+%if 0%{?from_snapshot}
+Release: 0.1.20210426git%{shortcommit}%{?dist}%{?rel_suffix}
+%else
+Release: 10%{?dist}%{?rel_suffix}
+%endif
 License: GPLv2
 URL: http://sourceware.org/lvm2
+%if 0%{?from_snapshot}
+Source0: lvm2-%{shortcommit}.tgz
+%else
 Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz
 Patch0: lvm2-rhel8.patch
+%endif
 Patch1: lvm2-set-default-preferred_names.patch
 Patch2: lvm2-test-skip-problematic-tests.patch
-Patch3: lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch
-# BZ 1915497:
-Patch4: lvm2-2_03_12-alloc-enhance-estimation-of-sufficient_pes_free.patch
-Patch5: lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch
-Patch6: lvm2-2_03_12-tests-check-full-zeroing-of-thin-pool-metadata.patch
-# BZ 1915580:
-Patch7: lvm2-2_03_12-integrity-fix-segfault-on-error-path-when-replacing-.patch
-# BZ 1872695:
-Patch8: lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch
-Patch9: lvm2-2_03_12-make-generate.patch
-Patch10: lvm2-2_03_12-label_scan-fix-missing-free-of-filtered_devs.patch
-# BZ 1917920:
-Patch11: lvm2-2_03_12-pvck-fix-warning-and-exit-code-for-non-4k-mda1-offse.patch
-Patch12: lvm2-2_03_12-WHATS_NEW-update.patch
-# BZ 1921214:
-Patch13: lvm2-2_03_12-writecache-use-cleaner-message-instead-of-table-relo.patch
-# BZ 1909699:
-Patch14: lvm2-2_03_12-man-update-lvmthin.patch
-Patch15: lvm2-2_03_12-thin-improve-16g-support-for-thin-pool-metadata.patch
-Patch16: lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch
-Patch17: lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch
-Patch18: lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch
-Patch19: lvm2-2_03_12-tests-update-thin-and-cache-checked-messages.patch
-# BZ 1914389:
-Patch20: lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch
-Patch21: lvm2-2_03_12-test-check-read_only_volume_list-tagging-works.patch
-# BZ 1859659:
-Patch22: lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch
-# BZ 1925871:
-Patch23: lvm2-2_03_12-dev_get_primary_dev-fix-invalid-path-check.patch
-# BZ 1931893:
-Patch24: lvm2-2_03_12-fsadm-avoid-access-to-unbound-variable.patch
-Patch25: lvm2-2_03_12-tests-remove-local-setting-of-LVM_BINARY.patch
-Patch26: lvm2-2_03_12-man-Fix-wording-in-lvmthin-7.patch
+# BZ 1961890
+Patch3: lvm2-2_03_13-vdo-fix-preload-of-kvdo.patch
+# BZ 1964622:
+Patch4: lvm2-2_03_13-lvremove-fix-removing-thin-pool-with-writecache-on-d.patch
+# BZ 1957898:
+Patch5: lvm2-2_03_13-enable-command-syntax-for-thin-and-writecache.patch
+# BZ 1872903:
+Patch6: lvm2-2_03_13-writecache-fix-lv_on_pmem.patch
+Patch7: lvm2-2_03_13-writecache-don-t-pvmove-device-used-by-writecache.patch
+# BZ 1957898:
+Patch8: lvm2-2_03_13-lvconvert-allow-writecache-with-other-thinpool-comma.patch
+# BZ 1922312:
+Patch9: lvm2-2_03_13-devices-don-t-use-deleted-loop-backing-file-for-devi.patch
+Patch10: lvm2-2_03_13-lvmdevices-add-deviceidtype-option.patch
+# BZ 1974901:
+Patch11: lvm2-2_03_13-device_id-handle-scsi_debug-wwid.patch
+# BZ 1930261:
+Patch12: lvm2-2_03_13-lvconvert-fix-vdo-virtual-size-when-specified.patch
+Patch13: lvm2-2_03_13-vdo-rename-variable-vdo_pool_zero.patch
+Patch14: lvm2-2_03_13-vdo-support-vdo_pool_header_size.patch
+Patch15: lvm2-2_03_13-vdo-add-vdoimport-support.patch
+Patch16: lvm2-2_03_13-man-vdoimport-page.patch
+Patch17: lvm2-make-generate.patch
+# BZ 1967744: 
+Patch18: lvm2-2_03_13-thin-fix-component-detection-of-external-origin.patch
+# BZ 1899263:
+Patch19: lvm2-2_03_13-vgremove-remove-forgotten-pmspare.patch
+Patch20: lvm2-2_03_13-vgsplit-add-support-for-option-poolmetadataspare.patch
+Patch21: lvm2-2_03_13-test.patch
+Patch22: lvm2-2_03_13-vgmerge-remove-one-of-merge-pmspare-LVs.patch
+Patch23: lvm2-2_03_13-vgmerge-support-option-poolmetadataspare.patch
+Patch24: lvm2-2_03_13-tests-extend-vgmerge-testing.patch
+# BZ 1986930:
+Patch25: lvm2-2_03_14-vdo-Rename-vdoimport-to-lvm_import_vdo.patch
+# BZs #1930261 #1986885 #1986915 #1988504 #1989650 #1996227:
+Patch26: lvm2-2_03_14-vdo-fixes.patch
+Patch27: lvm2-2_03_14-vdo-lvm_import_vdo-fix-max_discard-size.patch
+Patch28: lvm2-2_03_14-vdo-better-message-for-missing-device.patch
+Patch29: lvm2-2_03_14-vdo-more-lvm_import_vdo-fixes.patch
+Patch30: lvm2-2_03_14-vdo-fix-conversion-of-large-virtual-sizes.patch
+Patch31: lvm2-2_03_14-vdo-read-new-sysfs-path.patch
+Patch32: lvm2-2_03_14-tests-check-lvm2-parses-vdo-statistics.patch
+Patch33: lvm2-2_03_14-vdo-lvm_import_vdo-script-needs-to-continue-when-vgn.patch
+Patch34: lvm2-2_03_14-vdo-man-page-updates.patch
+Patch35: lvm2-2_03_14-vdo-prompt-with-no-return-failure.patch
 
 BuildRequires: gcc
 %if %{enable_testsuite}
@@ -152,8 +170,12 @@ or more physical volumes and creating one or more logical volumes
 (kind of logical partitions) in volume groups.
 
 %prep
+%if 0%{?from_snapshot}
+%setup -q -n lvm2-%{commit}
+%else
 %setup -q -n LVM2.%{version}
 %patch0 -p1 -b .backup0
+%endif
 %patch1 -p1 -b .backup1
 %patch2 -p1 -b .backup2
 %patch3 -p1 -b .backup3
@@ -180,6 +202,15 @@ or more physical volumes and creating one or more logical volumes
 %patch24 -p1 -b .backup24
 %patch25 -p1 -b .backup25
 %patch26 -p1 -b .backup26
+%patch27 -p1 -b .backup27
+%patch28 -p1 -b .backup28
+%patch29 -p1 -b .backup29
+%patch30 -p1 -b .backup30
+%patch31 -p1 -b .backup31
+%patch32 -p1 -b .backup32
+%patch33 -p1 -b .backup33
+%patch34 -p1 -b .backup34
+%patch35 -p1 -b .backup35
 
 %build
 %global _default_pid_dir /run
@@ -189,48 +220,68 @@ or more physical volumes and creating one or more logical volumes
 
 %global _udevdir %{_prefix}/lib/udev/rules.d
 
-%global configure_udev --with-udevdir=%{_udevdir} --enable-udev_sync
-
-%if %{enable_cache}
-%global configure_cache --with-cache=internal
+# FIXME: Dropped in rhel9, do we need to keep this for "compatibility"?
+%if %{enable_cluster}
+  %global configure_cluster --with-cluster=internal
+  %if %{enable_cmirror}
+    %global configure_cmirror --enable-cmirrord
+  %endif
+%else
+    %global configure_cluster --with-cluster=internal
 %endif
 
+%configure\
+  --with-default-dm-run-dir=%{_default_dm_run_dir} \
+  --with-default-run-dir=%{_default_run_dir} \
+  --with-default-pid-dir=%{_default_pid_dir} \
+  --with-default-locking-dir=%{_default_locking_dir} \
+  --with-usrlibdir=%{_libdir} \
+  --enable-fsadm \
+  --enable-write_install \
+  --with-user= \
+  --with-group= \
+  --with-device-uid=0 \
+  --with-device-gid=6 \
+  --with-device-mode=0660 \
+  --enable-pkgconfig \
+  --enable-cmdlib \
+  --enable-dmeventd \
+  --enable-blkid_wiping \
+  %{?configure_cluster} \
+  %{?configure_cmirror} \
+  --with-udevdir=%{_udevdir} --enable-udev_sync \
 %if %{enable_thin}
-%global configure_thin --with-thin=internal
+  --with-thin=internal \
+%endif
+%if %{enable_cache}
+  --with-cache=internal \
+%endif
+%if %{enable_lvmpolld}
+  --enable-lvmpolld \
 %endif
-
 %if %{enable_lockd_dlm}
-%global configure_lockd_dlm --enable-lvmlockd-dlm --enable-lvmlockd-dlmcontrol
+  --enable-lvmlockd-dlm --enable-lvmlockd-dlmcontrol \
 %endif
 %if %{enable_lockd_sanlock}
-%global configure_lockd_sanlock --enable-lvmlockd-sanlock
-%endif
-
-%if %{enable_lvmpolld}
-%global configure_lvmpolld --enable-lvmpolld
+  --enable-lvmlockd-sanlock \
 %endif
-
 %if %{enable_lvmdbusd}
-%global configure_lvmdbusd --enable-dbus-service --enable-notify-dbus
+  --enable-dbus-service --enable-notify-dbus \
 %endif
-
 %if %{enable_dmfilemapd}
-%global configure_dmfilemapd --enable-dmfilemapd
+  --enable-dmfilemapd \
 %endif
-
-%if %{enable_vdo}
-%global configure_vdo --with-vdo=internal --with-vdo-format=%{_bindir}/vdoformat
-%endif
-
 %if %{enable_writecache}
-%global configure_writecache --with-writecache=internal
+  --with-writecache=internal \
 %endif
-
+%if %{enable_vdo}
+  --with-vdo=internal --with-vdo-format=%{_bindir}/vdoformat \
+%endif
+  %{?configure_integrity} \
 %if %{enable_integrity}
-%global configure_integrity --with-integrity=internal
+  --with-integrity=internal \
 %endif
-
-%configure --with-default-dm-run-dir=%{_default_dm_run_dir} --with-default-run-dir=%{_default_run_dir} --with-default-pid-dir=%{_default_pid_dir} --with-default-locking-dir=%{_default_locking_dir} --with-usrlibdir=%{_libdir} --enable-fsadm --enable-write_install --with-user= --with-group= --with-device-uid=0 --with-device-gid=6 --with-device-mode=0660 --enable-pkgconfig --enable-cmdlib --enable-dmeventd --enable-blkid_wiping %{?configure_cluster} %{?configure_cmirror} %{?configure_udev} %{?configure_thin} %{?configure_cache} %{?configure_lvmpolld} %{?configure_lockd_dlm} %{?configure_lockd_sanlock} %{?configure_lvmdbusd} %{?configure_dmfilemapd} %{?configure_writecache} %{?configure_vdo} %{?configure_integrity} --disable-silent-rules
+  --disable-silent-rules
 
 make %{?_smp_mflags}
 
@@ -293,10 +344,12 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
 %{_sbindir}/fsadm
 %{_sbindir}/lvm
 %{_sbindir}/lvmconfig
+%{_sbindir}/lvmdevices
 %{_sbindir}/lvmdump
 %if %{enable_lvmpolld}
 %{_sbindir}/lvmpolld
 %endif
+%{_sbindir}/lvm_import_vdo
 
 # Other files
 %defattr(444,root,root,-)
@@ -334,6 +387,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
 %{_sbindir}/vgextend
 %{_sbindir}/vgimport
 %{_sbindir}/vgimportclone
+%{_sbindir}/vgimportdevices
 %{_sbindir}/vgmerge
 %{_sbindir}/vgmknodes
 %{_sbindir}/vgreduce
@@ -359,6 +413,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
 %{_mandir}/man8/lvm2-activation-generator.8.gz
 %{_mandir}/man8/lvm-config.8.gz
 %{_mandir}/man8/lvmconfig.8.gz
+%{_mandir}/man8/lvmdevices.8.gz
 %{_mandir}/man8/lvm-dumpconfig.8.gz
 %{_mandir}/man8/lvmdiskscan.8.gz
 %{_mandir}/man8/lvmdump.8.gz
@@ -389,8 +444,10 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
 %{_mandir}/man8/vgdisplay.8.gz
 %{_mandir}/man8/vgexport.8.gz
 %{_mandir}/man8/vgextend.8.gz
+%{_mandir}/man8/lvm_import_vdo.8.gz
 %{_mandir}/man8/vgimport.8.gz
 %{_mandir}/man8/vgimportclone.8.gz
+%{_mandir}/man8/vgimportdevices.8.gz
 %{_mandir}/man8/vgmerge.8.gz
 %{_mandir}/man8/vgmknodes.8.gz
 %{_mandir}/man8/vgreduce.8.gz
@@ -417,9 +474,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
 %{_sysconfdir}/lvm/profile/cache-mq.profile
 %{_sysconfdir}/lvm/profile/cache-smq.profile
 %{_sysconfdir}/lvm/profile/lvmdbusd.profile
-%if %{enable_vdo}
 %{_sysconfdir}/lvm/profile/vdo-small.profile
-%endif
 %dir %{_sysconfdir}/lvm/backup
 %dir %{_sysconfdir}/lvm/cache
 %dir %{_sysconfdir}/lvm/archive
@@ -784,8 +839,41 @@ An extensive functional testsuite for LVM2.
 %endif
 
 %changelog
-* Thu Feb 11 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.11-5
-- Fix fsadm failure due to accessing unbound variable.
+* Mon Sep 20 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-10
+- Fix incorrect memory free.
+
+* Fri Sep 17 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-9
+- Fix various lvm_import_vdo issues.
+- Fix conversion to vdo when virtual size is above 2TiB.
+
+* Thu Aug 26 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-8
+- Rename vdoimport to lvm_import_vdo.
+
+* Wed Aug 11 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-7
+- Fix missing executable flag on vdoimport.
+
+* Tue Aug 03 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-6
+- Fix handling of pmspare by vgsplit, vgmerge and vgremove.
+- Fix detection of active components of external origin volume.
+
+* Tue Jul 13 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-5
+- Fix device_id handling of scsi_debug WWID.
+- Add vdoimport support.
+
+* Tue Jun 22 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-4
+- Fix conversion of writecache LVs to thin pool data volume.
+- Add deviceidtype option for lvmdevices.
+
+* Tue Jun 15 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-3
+- Allow extending thin-pool data with writecache on top.
+- Fix removing thin-pool data converted to writeache.
+
+* Tue Jun 01 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-2
+- Fix loading of VDO kernel module.
+
+* Wed May 19 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-1
+- Update to upstream version 2.03.12.
+- See WHATS_NEW for list of changes.
 
 * Thu Feb 11 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.11-4
 - Fix "Failed to get primary device" for NVMe devices.