diff --git a/.gitignore b/.gitignore
index 345c6b9..6de202c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/LVM2.2.02.166.tgz
+SOURCES/LVM2.2.02.171.tgz
diff --git a/.lvm2.metadata b/.lvm2.metadata
index 59744c7..7d21c07 100644
--- a/.lvm2.metadata
+++ b/.lvm2.metadata
@@ -1 +1 @@
-5e2dd5bcae8a55c1721bf5c24e8c263895818b44 SOURCES/LVM2.2.02.166.tgz
+134498350084fe1371e48e1bdcf558913a112a78 SOURCES/LVM2.2.02.171.tgz
diff --git a/SOURCES/lvm2-2_02_167-disable-lvconvert-of-thin-pool-to-raid-while-active.patch b/SOURCES/lvm2-2_02_167-disable-lvconvert-of-thin-pool-to-raid-while-active.patch
deleted file mode 100644
index 3301d1b..0000000
--- a/SOURCES/lvm2-2_02_167-disable-lvconvert-of-thin-pool-to-raid-while-active.patch
+++ /dev/null
@@ -1,32 +0,0 @@
- WHATS_NEW                 | 4 ++++
- lib/metadata/raid_manip.c | 5 +++++
- 2 files changed, 9 insertions(+)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 977e578..5cbf4ec 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,3 +1,7 @@
-+Version 2.02.167 - 
-+======================================
-+  Disable lvconvert of thin pool to raid while active.
-+
- Version 2.02.166 - 26th September 2016
- ======================================
-   Fix lvm2-activation-generator to read all LVM2 config sources. (2.02.155)
-diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
-index e5fdf4f..5fc520e 100644
---- a/lib/metadata/raid_manip.c
-+++ b/lib/metadata/raid_manip.c
-@@ -776,6 +776,11 @@ static int _raid_add_images_without_commit(struct logical_volume *lv,
- 		return 0;
- 	}
- 
-+	if (lv_is_active(lv_lock_holder(lv)) && (old_count == 1) && (lv_is_thin_pool_data(lv) || lv_is_thin_pool_metadata(lv))) {
-+		log_error("Can't add image to active thin pool LV %s yet. Deactivate first.", display_lvname(lv));
-+		return 0;
-+	}
-+
- 	if (!archive(lv->vg))
- 		return_0;
- 
diff --git a/SOURCES/lvm2-2_02_167-fix-inability-of-lvconvert-repair-for-cache-raid-volumes.patch b/SOURCES/lvm2-2_02_167-fix-inability-of-lvconvert-repair-for-cache-raid-volumes.patch
deleted file mode 100644
index 8dc2754..0000000
--- a/SOURCES/lvm2-2_02_167-fix-inability-of-lvconvert-repair-for-cache-raid-volumes.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-@@ -, +, @@ 
- convert internal LV"
----
- tools/lvconvert.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
---- a/tools/lvconvert.c	
-+++ a/tools/lvconvert.c	
-@@ -243,6 +243,7 @@ static int _lvconvert_name_params(struct lvconvert_params *lp,
- 	    !strstr(lp->lv_name, "_tmeta") &&
- 	    !strstr(lp->lv_name, "_cdata") &&
- 	    !strstr(lp->lv_name, "_cmeta") &&
-+	    !strstr(lp->lv_name, "_corig") &&
- 	    !apply_lvname_restrictions(lp->lv_name))
- 		return_0;
- 
-@@ -4440,7 +4441,8 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
- 		    !lv_is_thin_pool_metadata(lv) &&
- 		    !lv_is_thin_pool_data(lv) &&
- 		    !lv_is_used_cache_pool(lv) &&
--		    !lv_is_raid_image(lv)) {
-+		    !lv_is_raid_image(lv) &&
-+		    !(lv_is_raid(lv) && strstr(lv->name, "_corig"))) {
- 			log_error("Cannot convert internal LV %s.", display_lvname(lv));
- 			ret = 0;
- 			goto out;
--- 
-
diff --git a/SOURCES/lvm2-2_02_167-fix-raid4-coversion-from-striped.patch b/SOURCES/lvm2-2_02_167-fix-raid4-coversion-from-striped.patch
deleted file mode 100644
index 11dd7db..0000000
--- a/SOURCES/lvm2-2_02_167-fix-raid4-coversion-from-striped.patch
+++ /dev/null
@@ -1,532 +0,0 @@
- WHATS_NEW                             |   2 +
- lib/metadata/raid_manip.c             | 277 +++++++++++++++++++++++++++++++---
- test/shell/lvconvert-raid-takeover.sh |  53 ++++++-
- tools/lvconvert.c                     |  24 +--
- 4 files changed, 314 insertions(+), 42 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 5cbf4ec..6a0c311 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,7 @@
- Version 2.02.167 - 
- ======================================
-+  Add direct striped -> raid4 conversion
-+  Fix raid4 parity image pair position on conversions from striped/raid0*
-   Disable lvconvert of thin pool to raid while active.
- 
- Version 2.02.166 - 26th September 2016
-diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
-index 5fc520e..e5fd195 100644
---- a/lib/metadata/raid_manip.c
-+++ b/lib/metadata/raid_manip.c
-@@ -2459,7 +2459,7 @@ static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
- 					   0 /* chunk_size */,
- 					   0 /* seg->region_size */, 0u /* extents_copied */ ,
- 					   NULL /* pvmove_source_seg */))) {
--		log_error("Failed to allocate new raid0 segement for LV %s.", display_lvname(lv));
-+		log_error("Failed to allocate new raid0 segment for LV %s.", display_lvname(lv));
- 		return NULL;
- 	}
- 
-@@ -2519,42 +2519,51 @@ static struct possible_takeover_reshape_type _possible_takeover_reshape_types[]
- 	{ .current_types  = SEG_STRIPED_TARGET, /* linear, i.e. seg->area_count = 1 */
- 	  .possible_types = SEG_RAID1,
- 	  .current_areas = 1,
--	  .options = ALLOW_NONE },
-+	  .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
- 	{ .current_types  = SEG_STRIPED_TARGET, /* linear, i.e. seg->area_count = 1 */
- 	  .possible_types = SEG_RAID0|SEG_RAID0_META,
- 	  .current_areas = 1,
- 	  .options = ALLOW_STRIPE_SIZE },
--	{ .current_types  = SEG_STRIPED_TARGET, /* striped, i.e. seg->area_count > 1 */
-+	{ .current_types  = SEG_STRIPED_TARGET, /* striped -> raid0*, i.e. seg->area_count > 1 */
- 	  .possible_types = SEG_RAID0|SEG_RAID0_META,
- 	  .current_areas = ~0U,
- 	  .options = ALLOW_NONE },
-+	{ .current_types  = SEG_STRIPED_TARGET, /* striped -> raid4 , i.e. seg->area_count > 1 */
-+	  .possible_types = SEG_RAID4,
-+	  .current_areas = ~0U,
-+	  .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
- 	/* raid0* -> */
- 	{ .current_types  = SEG_RAID0|SEG_RAID0_META, /* seg->area_count = 1 */
- 	  .possible_types = SEG_RAID1,
- 	  .current_areas = 1,
-+	  .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
-+	{ .current_types  = SEG_RAID0|SEG_RAID0_META, /* raid0* -> striped, i.e. seg->area_count > 1 */
-+	  .possible_types = SEG_STRIPED_TARGET,
-+	  .current_areas = ~0U,
- 	  .options = ALLOW_NONE },
--	{ .current_types  = SEG_RAID0|SEG_RAID0_META, /* seg->area_count > 1 */
--	  .possible_types = SEG_RAID4,
-+	{ .current_types  = SEG_RAID0|SEG_RAID0_META, /* raid0* -> raid0*, i.e. seg->area_count > 1 */
-+	  .possible_types = SEG_RAID0_META|SEG_RAID0,
- 	  .current_areas = ~0U,
- 	  .options = ALLOW_NONE },
--	{ .current_types  = SEG_RAID0|SEG_RAID0_META, /* raid0 striped, i.e. seg->area_count > 0 */
-+	{ .current_types  = SEG_RAID0|SEG_RAID0_META, /* raid0* -> raid4, i.e. seg->area_count > 1 */
-+	  .possible_types = SEG_RAID4,
-+	  .current_areas = ~0U,
-+	  .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
-+	/* raid4 -> -> */
-+	{ .current_types  = SEG_RAID4, /* raid4 ->striped/raid0*, i.e. seg->area_count > 1 */
- 	  .possible_types = SEG_STRIPED_TARGET|SEG_RAID0|SEG_RAID0_META,
- 	  .current_areas = ~0U,
- 	  .options = ALLOW_NONE },
--	/* raid1 -> */
-+	/* raid1 -> mirror */
- 	{ .current_types  = SEG_RAID1,
--	  .possible_types = SEG_RAID1|SEG_MIRROR,
-+	  .possible_types = SEG_MIRROR,
- 	  .current_areas = ~0U,
--	  .options = ALLOW_NONE },
-+	  .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
- 	/* mirror -> raid1 with arbitrary number of legs */
- 	{ .current_types  = SEG_MIRROR,
--	  .possible_types = SEG_MIRROR|SEG_RAID1,
--	  .current_areas = ~0U,
--	  .options = ALLOW_NONE },
--	{ .current_types  = SEG_RAID4,
--	  .possible_types = SEG_STRIPED_TARGET|SEG_RAID0|SEG_RAID0_META,
-+	  .possible_types = SEG_RAID1,
- 	  .current_areas = ~0U,
--	  .options = ALLOW_NONE },
-+	  .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
- 
- 	/* END */
- 	{ .current_types  = 0 }
-@@ -2861,9 +2870,176 @@ static int _raid1_to_mirrored_wrapper(TAKEOVER_FN_ARGS)
- 					allocate_pvs, 1, &removal_lvs);
- }
- 
-+/*
-+ * HM Helper: (raid0_meta -> raid4)
-+ *
-+ * To convert raid0_meta to raid4, which involves shifting the
-+ * parity device to lv segment area 0 and thus changing MD
-+ * array roles, detach the MetaLVs and reload as raid0 in
-+ * order to wipe them then reattach and set back to raid0_meta.
-+ */
-+static int _clear_meta_lvs(struct logical_volume *lv)
-+{
-+	uint32_t s;
-+	struct lv_segment *seg = first_seg(lv);
-+	struct lv_segment_area *tmp_areas;
-+	const struct segment_type *tmp_segtype;
-+	struct dm_list meta_lvs;
-+	struct lv_list *lvl_array, *lvl;
-+
-+	/* Reject non-raid0_meta segment types cautiously */
-+	if (!seg_is_raid0_meta(seg) ||
-+	    !seg->meta_areas)
-+		return_0;
-+
-+	if (!(lvl_array = dm_pool_alloc(lv->vg->vgmem, seg->area_count * sizeof(*lvl_array))))
-+		return_0;
-+
-+	dm_list_init(&meta_lvs);
-+	tmp_areas = seg->meta_areas;
-+
-+	/* Extract all MetaLVs listing them on @meta_lvs */
-+	log_debug_metadata("Extracting all MetaLVs of %s to activate as raid0",
-+			   display_lvname(lv));
-+	if (!_extract_image_component_sublist(seg, RAID_META, 0, seg->area_count, &meta_lvs, 0))
-+		return_0;
-+
-+	/* Memorize meta areas and segtype to set again after initializing. */
-+	seg->meta_areas = NULL;
-+	tmp_segtype = seg->segtype;
-+
-+	if (!(seg->segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID0)) ||
-+	    !lv_update_and_reload(lv))
-+		return_0;
-+
-+	/*
-+	 * Now deactivate the MetaLVs before clearing, so
-+	 * that _clear_lvs() will activate them visible.
-+	 */
-+	log_debug_metadata("Deactivating pulled out MetaLVs of %s before initializing.",
-+			   display_lvname(lv));
-+	dm_list_iterate_items(lvl, &meta_lvs)
-+		if (!deactivate_lv(lv->vg->cmd, lvl->lv))
-+			return_0;
-+
-+	log_debug_metadata("Clearing allocated raid0_meta metadata LVs for conversion to raid4");
-+	if (!_clear_lvs(&meta_lvs)) {
-+		log_error("Failed to initialize metadata LVs");
-+		return 0;
-+	}
-+
-+	/* Set memorized meta areas and raid0_meta segtype */
-+	seg->meta_areas = tmp_areas;
-+	seg->segtype = tmp_segtype;
-+
-+	log_debug_metadata("Adding metadata LVs back into %s", display_lvname(lv));
-+	s = 0;
-+	dm_list_iterate_items(lvl, &meta_lvs) {
-+		lv_set_hidden(lvl->lv);
-+		if (!set_lv_segment_area_lv(seg, s++, lvl->lv, 0, RAID_META))
-+			return 0;
-+	}
-+
-+	return 1;
-+}
-+
-+/*
-+ * HM Helper: (raid0* <-> raid4)
-+ *
-+ * Rename SubLVs (pairs) allowing to shift names w/o collisions with active ones.
-+ */
-+#define	SLV_COUNT	2
-+static int _rename_area_lvs(struct logical_volume *lv, const char *suffix)
-+{
-+	uint32_t s;
-+	size_t sz = strlen("rimage") + (suffix ? strlen(suffix) : 0) + 1;
-+	char *sfx[SLV_COUNT] = { NULL, NULL };
-+	struct lv_segment *seg = first_seg(lv);
-+
-+	/* Create _generate_raid_name() suffixes w/ or w/o passed in @suffix */
-+	for (s = 0; s < SLV_COUNT; s++)
-+		if (!(sfx[s] = dm_pool_alloc(lv->vg->cmd->mem, sz)) ||
-+		    dm_snprintf(sfx[s], sz, suffix ? "%s%s" : "%s", s ? "rmeta" : "rimage", suffix) < 0)
-+			return_0;
-+
-+	/* Change names (temporarily) to be able to shift numerical name suffixes */
-+	for (s = 0; s < seg->area_count; s++) {
-+		if (!(seg_lv(seg, s)->name = _generate_raid_name(lv, sfx[0], s)))
-+			return_0;
-+		if (seg->meta_areas &&
-+		    !(seg_metalv(seg, s)->name = _generate_raid_name(lv, sfx[1], s)))
-+			return_0;
-+	}
-+
-+	for (s = 0; s < SLV_COUNT; s++)
-+		dm_pool_free(lv->vg->cmd->mem, sfx[s]);
-+
-+	return 1;
-+}
-+
-+/*
-+ * HM Helper: (raid0* <-> raid4)
-+ *
-+ * Switch area LVs in lv segment @seg indexed by @s1 and @s2
-+ */
-+static void _switch_area_lvs(struct lv_segment *seg, uint32_t s1, uint32_t s2)
-+{
-+	struct logical_volume *lvt;
-+
-+	lvt = seg_lv(seg, s1);
-+	seg_lv(seg, s1) = seg_lv(seg, s2);
-+	seg_lv(seg, s2) = lvt;
-+
-+	/* Be cautious */
-+	if (seg->meta_areas) {
-+		lvt = seg_metalv(seg, s1);
-+		seg_metalv(seg, s1) = seg_metalv(seg, s2);
-+		seg_metalv(seg, s2) = lvt;
-+	}
-+}
-+
-+/*
-+ * HM Helper:
-+ *
-+ * shift range of area LVs in @seg in range [ @s1, @s2 ] up if @s1 < @s2,
-+ * else down  bubbling the parity SubLVs up/down whilst shifting.
-+ */
-+static void _shift_area_lvs(struct lv_segment *seg, uint32_t s1, uint32_t s2)
-+{
-+	uint32_t s;
-+
-+	if (s1 < s2)
-+		/* Forward shift n+1 -> n */
-+		for (s = s1; s < s2; s++)
-+			_switch_area_lvs(seg, s, s + 1);
-+	else
-+		/* Reverse shift n-1 -> n */
-+		for (s = s1; s > s2; s--)
-+			_switch_area_lvs(seg, s, s - 1);
-+}
-+
-+/*
-+ * Switch position of first and last area lv within
-+ * @lv to move parity SubLVs from end to end.
-+ *
-+ * Direction depends on segment type raid4 / raid0_meta.
-+ */
-+static int _shift_parity_dev(struct lv_segment *seg)
-+{
-+	if (seg_is_raid0_meta(seg))
-+		_shift_area_lvs(seg, seg->area_count - 1, 0);
-+	else if (seg_is_raid4(seg))
-+		_shift_area_lvs(seg, 0, seg->area_count - 1);
-+	else
-+		return 0;
-+
-+	return 1;
-+}
-+
- /* raid45 -> raid0* / striped */
- static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
- {
-+	int rename_sublvs = 0;
- 	struct lv_segment *seg = first_seg(lv);
- 	struct dm_list removal_lvs;
- 
-@@ -2879,10 +3055,39 @@ static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
- 	if (!_raid_in_sync(lv))
- 		return 0;
- 
-+	if (!yes && yes_no_prompt("Are you sure you want to convert \"%s\" LV %s to \"%s\" "
-+				  "type using all resilience? [y/n]: ",
-+				  lvseg_name(seg), display_lvname(lv), new_segtype->name) == 'n') {
-+		log_error("Logical volume %s NOT converted to \"%s\"",
-+			  display_lvname(lv), new_segtype->name);
-+		return 0;
-+	}
-+	if (sigint_caught())
-+		return_0;
-+
- 	/* Archive metadata */
- 	if (!archive(lv->vg))
- 		return_0;
- 
-+	/*
-+	 * raid4 (which actually gets mapped to raid5/dedicated first parity disk)
-+	 * needs shifting of SubLVs to move the parity SubLV pair in the first area
-+	 * to the last one before conversion to raid0[_meta]/striped to allow for
-+	 * SubLV removal from the end of the areas arrays.
-+	 */
-+	if (seg_is_raid4(seg)) {
-+		/* Shift parity SubLV pair "PDD..." -> "DD...P" to be able to remove it off the end */
-+		if (!_shift_parity_dev(seg))
-+			return 0;
-+
-+		if (segtype_is_any_raid0(new_segtype) &&
-+		    !(rename_sublvs = _rename_area_lvs(lv, "_"))) {
-+			log_error("Failed to rename %s LV %s MetaLVs", lvseg_name(seg), display_lvname(lv));
-+			return 0;
-+		}
-+
-+	}
-+
- 	/* Remove meta and data LVs requested */
- 	if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, &removal_lvs, 0, 0))
- 		return 0;
-@@ -2902,7 +3107,19 @@ static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
- 
- 	seg->region_size = 0;
- 
--	return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs);
-+	if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs))
-+		return_0;
-+
-+	if (rename_sublvs) {
-+		if (!_rename_area_lvs(lv, NULL)) {
-+			log_error("Failed to rename %s LV %s MetaLVs", lvseg_name(seg), display_lvname(lv));
-+			return 0;
-+		}
-+		if (!lv_update_and_reload(lv))
-+			return_0;
-+	}
-+
-+	return 1;
- }
- 
- static int _striped_to_raid0_wrapper(struct logical_volume *lv,
-@@ -2930,6 +3147,9 @@ static int _striped_to_raid0_wrapper(struct logical_volume *lv,
- static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
- {
- 	struct lv_segment *seg = first_seg(lv);
-+	struct dm_list removal_lvs;
-+
-+	dm_list_init(&removal_lvs);
- 
- 	if (seg_is_raid10(seg))
- 		return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
-@@ -2944,6 +3164,13 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
- 		return 0;
- 	}
- 
-+	/* FIXME: restricted to raid4 for the time being... */
-+	if (!segtype_is_raid4(new_segtype)) {
-+		/* Can't convert striped/raid0* to e.g. raid10_offset */
-+		log_error("Can't convert %s to %s", display_lvname(lv), new_segtype->name);
-+		return 0;
-+	}
-+
- 	/* Archive metadata */
- 	if (!archive(lv->vg))
- 		return_0;
-@@ -2961,7 +3188,10 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
- 		log_debug_metadata("Adding metadata LVs to %s", display_lvname(lv));
- 		if (!_raid0_add_or_remove_metadata_lvs(lv, 1 /* update_and_reload */, allocate_pvs, NULL))
- 			return 0;
--	}
-+	/* raid0_meta -> raid4 needs clearing of MetaLVs in order to avoid raid disk role cahnge issues in the kernel */
-+	} else if (segtype_is_raid4(new_segtype) &&
-+		   !_clear_meta_lvs(lv))
-+		return 0;
- 
- 	/* Add the additional component LV pairs */
- 	log_debug_metadata("Adding %" PRIu32 " component LV pair(s) to %s", new_image_count - lv_raid_image_count(lv),
-@@ -2969,8 +3199,9 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
- 	if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, NULL, 0, 1))
- 		return 0;
- 
--	if (!segtype_is_raid4(new_segtype)) {
--		/* Can't convert striped/raid0* to e.g. raid10_offset */
-+	if (segtype_is_raid4(new_segtype) &&
-+	    (!_shift_parity_dev(seg) ||
-+	     !_rename_area_lvs(lv, "_"))) {
- 		log_error("Can't convert %s to %s", display_lvname(lv), new_segtype->name);
- 		return 0;
- 	}
-@@ -2987,6 +3218,14 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
- 	if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, NULL))
- 		return_0;
- 
-+	if (segtype_is_raid4(new_segtype)) {
-+		/* We had to rename SubLVs because of collision free sgifting, rename back... */
-+		if (!_rename_area_lvs(lv, NULL))
-+			return 0;
-+		if (!lv_update_and_reload(lv))
-+			return_0;
-+	}
-+
- 	return 1;
- }
- 
-diff --git a/test/shell/lvconvert-raid-takeover.sh b/test/shell/lvconvert-raid-takeover.sh
-index 19a65d3..0140e22 100644
---- a/test/shell/lvconvert-raid-takeover.sh
-+++ b/test/shell/lvconvert-raid-takeover.sh
-@@ -78,22 +78,58 @@ aux wait_for_sync $vg $lv1
- # Clean up
- lvremove --yes $vg/$lv1
- 
--# Create 3-way raid0
--lvcreate -y -aey --type raid0 -i 3 -L 64M -n $lv1 $vg
--check lv_field $vg/$lv1 segtype "raid0"
-+# Create 3-way striped
-+lvcreate -y -aey --type striped -i 3 -L 64M -n $lv1 $vg
-+check lv_field $vg/$lv1 segtype "striped"
- check lv_field $vg/$lv1 stripes 3
- echo y | mkfs -t ext4 /dev/mapper/$vg-$lv1
- fsck -fn  /dev/mapper/$vg-$lv1
- 
--# Convert raid0 -> raid4
-+# Create 3-way raid0
-+lvcreate -y -aey --type raid0 -i 3 -L 64M -n $lv2 $vg
-+check lv_field $vg/$lv2 segtype "raid0"
-+check lv_field $vg/$lv2 stripes 3
-+echo y | mkfs -t ext4 /dev/mapper/$vg-$lv2
-+fsck -fn  /dev/mapper/$vg-$lv2
-+
-+# Create 3-way raid0_meta
-+lvcreate -y -aey --type raid0_meta -i 3 -L 64M -n $lv3 $vg
-+check lv_field $vg/$lv3 segtype "raid0_meta"
-+check lv_field $vg/$lv3 stripes 3
-+echo y | mkfs -t ext4 /dev/mapper/$vg-$lv3
-+fsck -fn  /dev/mapper/$vg-$lv3
-+
-+# Create 3-way raid4
-+lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg
-+check lv_field $vg/$lv4 segtype "raid4"
-+check lv_field $vg/$lv4 stripes 4
-+echo y | mkfs -t ext4 /dev/mapper/$vg-$lv4
-+fsck -fn  /dev/mapper/$vg-$lv4
-+aux wait_for_sync $vg $lv4
-+fsck -fn  /dev/mapper/$vg-$lv4
-+
-+# Convert raid4 -> striped (correct raid4 mapping test!)
-+lvconvert -y --ty striped $vg/$lv4
-+check lv_field $vg/$lv4 segtype "striped"
-+check lv_field $vg/$lv4 stripes 3
-+fsck -fn  /dev/mapper/$vg-$lv4
-+
-+# Convert striped -> raid4
- lvconvert -y --ty raid4 $vg/$lv1
--lvchange --refresh $vg/$lv1
- check lv_field $vg/$lv1 segtype "raid4"
- check lv_field $vg/$lv1 stripes 4
- fsck -fn  /dev/mapper/$vg-$lv1
- aux wait_for_sync $vg $lv1
- fsck -fn  /dev/mapper/$vg-$lv1
- 
-+# Convert raid0 -> raid4
-+lvconvert -y --ty raid4 $vg/$lv2
-+check lv_field $vg/$lv2 segtype "raid4"
-+check lv_field $vg/$lv2 stripes 4
-+fsck -fn  /dev/mapper/$vg-$lv2
-+aux wait_for_sync $vg $lv2
-+fsck -fn  /dev/mapper/$vg-$lv2
-+
- # Convert raid4 -> raid0_meta
- lvconvert -y --ty raid0_meta $vg/$lv1
- check lv_field $vg/$lv1 segtype "raid0_meta"
-@@ -116,11 +152,16 @@ fsck -fn  /dev/mapper/$vg-$lv1
- 
- # Convert raid0 -> raid4
- lvconvert -y --ty raid4 $vg/$lv1
--lvchange --refresh $vg/$lv1
- check lv_field $vg/$lv1 segtype "raid4"
- check lv_field $vg/$lv1 stripes 4
- fsck -fn  /dev/mapper/$vg-$lv1
- aux wait_for_sync $vg $lv1
- fsck -fn  /dev/mapper/$vg-$lv1
- 
-+# Convert raid4 -> striped
-+lvconvert -y --ty striped $vg/$lv1
-+check lv_field $vg/$lv1 segtype "striped"
-+check lv_field $vg/$lv1 stripes 3
-+fsck -fn  /dev/mapper/$vg-$lv1
-+
- vgremove -ff $vg
-diff --git a/tools/lvconvert.c b/tools/lvconvert.c
-index 0d2a4d1..541df72 100644
---- a/tools/lvconvert.c
-+++ b/tools/lvconvert.c
-@@ -1931,7 +1931,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
- 			return 1;
- 		}
- 		goto try_new_takeover_or_reshape;
--	} else if (!lp->repair && !lp->replace && (!*lp->type_str || seg->segtype == lp->segtype)) {
-+	} else if (!lp->repair && !lp->replace && !*lp->type_str) {
- 		log_error("Conversion operation not yet supported.");
- 		return 0;
- 	}
-@@ -2017,28 +2017,18 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
- 		return 1;
- 	}
- 
--
- try_new_takeover_or_reshape:
--
- 	/* FIXME This needs changing globally. */
- 	if (!arg_is_set(cmd, stripes_long_ARG))
- 		lp->stripes = 0;
- 
--	/* Only let raid4 through for now. */
--	if (lp->type_str && lp->type_str[0] && lp->segtype != seg->segtype &&
--	    ((seg_is_raid4(seg) && seg_is_striped(lp) && lp->stripes > 1) ||
--	     (seg_is_striped(seg) && seg->area_count > 1 && seg_is_raid4(lp)))) {
--		if (!lv_raid_convert(lv, lp->segtype, lp->yes, lp->force, lp->stripes, lp->stripe_size_supplied, lp->stripe_size,
--				     lp->region_size, lp->pvh))
--			return_0;
--
--		log_print_unless_silent("Logical volume %s successfully converted.",
--					display_lvname(lv));
--		return 1;
--	}
-+	if (!lv_raid_convert(lv, lp->segtype, lp->yes, lp->force, lp->stripes, lp->stripe_size_supplied, lp->stripe_size,
-+			     lp->region_size, lp->pvh))
-+		return_0;
- 
--	log_error("Conversion operation not yet supported.");
--	return 0;
-+	log_print_unless_silent("Logical volume %s successfully converted.",
-+				display_lvname(lv));
-+	return 1;
- }
- 
- static int _lvconvert_splitsnapshot(struct cmd_context *cmd, struct logical_volume *cow,
diff --git a/SOURCES/lvm2-2_02_167-prevent-raid4-creation-and-conversion-on-non-supporting-kernels.patch b/SOURCES/lvm2-2_02_167-prevent-raid4-creation-and-conversion-on-non-supporting-kernels.patch
deleted file mode 100644
index 93eb82e..0000000
--- a/SOURCES/lvm2-2_02_167-prevent-raid4-creation-and-conversion-on-non-supporting-kernels.patch
+++ /dev/null
@@ -1,303 +0,0 @@
- WHATS_NEW                             |  1 +
- lib/activate/activate.c               | 25 +++++++++++++++++++++++++
- lib/activate/activate.h               |  3 ++-
- lib/metadata/lv.c                     | 16 +++++++++++++++-
- lib/metadata/segtype.h                |  3 ++-
- lib/raid/raid.c                       | 10 ++++++++--
- test/shell/lvconvert-raid-takeover.sh | 13 +++++++++++++
- tools/lvconvert.c                     | 26 ++++++++++++++++++++++++++
- tools/lvcreate.c                      |  6 ++++++
- 9 files changed, 98 insertions(+), 5 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 6a0c311..519bbc9 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,6 @@
- Version 2.02.167 - 
- ======================================
-+  Prevent raid4 creation/conversion on non-supporting kernels
-   Add direct striped -> raid4 conversion
-   Fix raid4 parity image pair position on conversions from striped/raid0*
-   Disable lvconvert of thin pool to raid while active.
-diff --git a/lib/activate/activate.c b/lib/activate/activate.c
-index 5550955..571f2b2 100644
---- a/lib/activate/activate.c
-+++ b/lib/activate/activate.c
-@@ -370,6 +370,11 @@ void activation_exit(void)
- {
- }
- 
-+int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype)
-+{
-+	return 1;
-+}
-+
- int lv_is_active(const struct logical_volume *lv)
- {
- 	return 0;
-@@ -1489,6 +1494,26 @@ out:
- 	return r || l;
- }
- 
-+/*
-+ * Check if "raid4" @segtype is supported by kernel.
-+ *
-+ * if segment type is not raid4, return 1.
-+ */
-+int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype)
-+{
-+	unsigned attrs;
-+
-+	if (segtype_is_raid4(segtype) &&
-+	    (!segtype->ops->target_present ||
-+             !segtype->ops->target_present(cmd, NULL, &attrs) ||
-+             !(attrs & RAID_FEATURE_RAID4))) {
-+		log_error("RAID module does not support RAID4.");
-+		return 0;
-+	}
-+
-+	return 1;
-+}
-+
- int lv_is_active(const struct logical_volume *lv)
- {
- 	return _lv_is_active(lv, NULL, NULL, NULL);
-diff --git a/lib/activate/activate.h b/lib/activate/activate.h
-index 1e8d7a8..3922d78 100644
---- a/lib/activate/activate.h
-+++ b/lib/activate/activate.h
-@@ -1,6 +1,6 @@
- /*
-  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
-- * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -99,6 +99,7 @@ int target_present(struct cmd_context *cmd, const char *target_name,
- 		   int use_modprobe);
- int target_version(const char *target_name, uint32_t *maj,
- 		   uint32_t *min, uint32_t *patchlevel);
-+int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype);
- int lvm_dm_prefix_check(int major, int minor, const char *prefix);
- int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
- 			 struct dm_list *modules);
-diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
-index 53a1044..0f1b6e7 100644
---- a/lib/metadata/lv.c
-+++ b/lib/metadata/lv.c
-@@ -1,6 +1,6 @@
- /*
-  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
-- * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -1425,6 +1425,7 @@ int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv,
- 		     enum activation_change activate, int needs_exclusive)
- {
- 	const char *ay_with_mode = NULL;
-+	struct lv_segment *seg = first_seg(lv);
- 
- 	if (activate == CHANGE_ASY)
- 		ay_with_mode = "sh";
-@@ -1461,6 +1462,9 @@ deactivate:
- 		break;
- 	case CHANGE_ALY:
- 	case CHANGE_AAY:
-+		if (!raid4_is_supported(cmd, seg->segtype))
-+			goto no_raid4;
-+
- 		if (needs_exclusive || _lv_is_exclusive(lv)) {
- 			log_verbose("Activating logical volume %s exclusively locally.",
- 				    display_lvname(lv));
-@@ -1475,6 +1479,9 @@ deactivate:
- 		break;
- 	case CHANGE_AEY:
- exclusive:
-+		if (!raid4_is_supported(cmd, seg->segtype))
-+			goto no_raid4;
-+
- 		log_verbose("Activating logical volume %s exclusively.",
- 			    display_lvname(lv));
- 		if (!activate_lv_excl(cmd, lv))
-@@ -1483,6 +1490,9 @@ exclusive:
- 	case CHANGE_ASY:
- 	case CHANGE_AY:
- 	default:
-+		if (!raid4_is_supported(cmd, seg->segtype))
-+			goto no_raid4;
-+
- 		if (needs_exclusive || _lv_is_exclusive(lv))
- 			goto exclusive;
- 		log_verbose("Activating logical volume %s.", display_lvname(lv));
-@@ -1495,6 +1505,10 @@ exclusive:
- 		log_error("Failed to unlock logical volume %s.", display_lvname(lv));
- 
- 	return 1;
-+
-+no_raid4:
-+	log_error("Failed to activate %s LV %s", lvseg_name(seg), display_lvname(lv));
-+	return 0;
- }
- 
- char *lv_active_dup(struct dm_pool *mem, const struct logical_volume *lv)
-diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
-index 9ca740d..292b8b6 100644
---- a/lib/metadata/segtype.h
-+++ b/lib/metadata/segtype.h
-@@ -1,6 +1,6 @@
- /*
-  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
-- * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -268,6 +268,7 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
- #define RAID_FEATURE_RAID10			(1U << 0) /* version 1.3 */
- #define RAID_FEATURE_RAID0			(1U << 1) /* version 1.7 */
- #define RAID_FEATURE_RESHAPING			(1U << 2) /* version 1.8 */
-+#define RAID_FEATURE_RAID4			(1U << 3) /* ! version 1.8 or 1.9.0 */
- 
- #ifdef RAID_INTERNAL
- int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
-diff --git a/lib/raid/raid.c b/lib/raid/raid.c
-index 3bc3c75..92a96a3 100644
---- a/lib/raid/raid.c
-+++ b/lib/raid/raid.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2011-2016 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -366,7 +366,7 @@ static int _raid_target_present(struct cmd_context *cmd,
- 
- 	static int _raid_checked = 0;
- 	static int _raid_present = 0;
--	static int _raid_attrs = 0;
-+	static unsigned _raid_attrs = 0;
- 	uint32_t maj, min, patchlevel;
- 	unsigned i;
- 
-@@ -389,6 +389,12 @@ static int _raid_target_present(struct cmd_context *cmd,
- 			else
- 				log_very_verbose("Target raid does not support %s.",
- 						 _features[i].feature);
-+
-+		if (!(maj == 1 && (min == 8 || (min == 9 && patchlevel == 0))))
-+			_raid_attrs |= RAID_FEATURE_RAID4;
-+		else
-+			log_very_verbose("Target raid does not support %s.",
-+					 SEG_TYPE_NAME_RAID4);
- 	}
- 
- 	if (attributes)
-diff --git a/test/shell/lvconvert-raid-takeover.sh b/test/shell/lvconvert-raid-takeover.sh
-index 0140e22..332786d 100644
---- a/test/shell/lvconvert-raid-takeover.sh
-+++ b/test/shell/lvconvert-raid-takeover.sh
-@@ -16,6 +16,8 @@ SKIP_WITH_LVMPOLLD=1
- 
- aux have_raid 1 9 0 || skip
- 
-+[ `aux have_raid 1.9.1` ] && correct_raid4_layout=1
-+
- aux prepare_vg 9 288
- 
- # Delay 1st leg so that rebuilding status characters
-@@ -99,6 +101,9 @@ check lv_field $vg/$lv3 stripes 3
- echo y | mkfs -t ext4 /dev/mapper/$vg-$lv3
- fsck -fn  /dev/mapper/$vg-$lv3
- 
-+if [ $correct_raid4_layout -eq 1 ]
-+then
-+
- # Create 3-way raid4
- lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg
- check lv_field $vg/$lv4 segtype "raid4"
-@@ -164,4 +169,12 @@ check lv_field $vg/$lv1 segtype "striped"
- check lv_field $vg/$lv1 stripes 3
- fsck -fn  /dev/mapper/$vg-$lv1
- 
-+else
-+
-+not lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg
-+not lvconvert -y --ty raid4 $vg/$lv1
-+not lvconvert -y --ty raid4 $vg/$lv2
-+
-+fi
-+
- vgremove -ff $vg
-diff --git a/tools/lvconvert.c b/tools/lvconvert.c
-index 541df72..7a4215a 100644
---- a/tools/lvconvert.c
-+++ b/tools/lvconvert.c
-@@ -1821,6 +1821,25 @@ static void _lvconvert_raid_repair_ask(struct cmd_context *cmd,
- 	}
- }
- 
-+/* Check for dm-raid target supporting raid4 conversion properly. */
-+static int _raid4_conversion_supported(struct logical_volume *lv, struct lvconvert_params *lp)
-+{
-+	int ret = 1;
-+	struct lv_segment *seg = first_seg(lv);
-+
-+	if (seg_is_raid4(seg))
-+		ret = raid4_is_supported(lv->vg->cmd, seg->segtype);
-+	else if (segtype_is_raid4(lp->segtype))
-+		ret = raid4_is_supported(lv->vg->cmd, lp->segtype);
-+
-+	if (ret)
-+		return 1;
-+
-+	log_error("Cannot convert %s LV %s to %s.",
-+		  lvseg_name(seg), display_lvname(lv), lp->segtype->name);
-+	return 0;
-+}
-+
- static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *lp)
- {
- 	int replace = 0, image_count = 0;
-@@ -1945,6 +1964,9 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
- 			return 0;
- 		}
- 
-+		if (!_raid4_conversion_supported(lv, lp))
-+			return 0;
-+
- 		if (!arg_is_set(cmd, stripes_long_ARG))
- 			lp->stripes = 0;
- 
-@@ -2018,6 +2040,10 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
- 	}
- 
- try_new_takeover_or_reshape:
-+
-+	if (!_raid4_conversion_supported(lv, lp))
-+		return 0;
-+
- 	/* FIXME This needs changing globally. */
- 	if (!arg_is_set(cmd, stripes_long_ARG))
- 		lp->stripes = 0;
-diff --git a/tools/lvcreate.c b/tools/lvcreate.c
-index 387c8d4..dbc0708 100644
---- a/tools/lvcreate.c
-+++ b/tools/lvcreate.c
-@@ -1054,6 +1054,12 @@ static int _lvcreate_params(struct cmd_context *cmd,
- 			return 0;
- 		}
- 
-+		if (segtype_is_raid4(lp->segtype) &&
-+		    !(lp->target_attr & RAID_FEATURE_RAID4)) {
-+			log_error("RAID module does not support RAID4.");
-+			return 0;
-+		}
-+
- 		if (segtype_is_raid10(lp->segtype) && !(lp->target_attr & RAID_FEATURE_RAID10)) {
- 			log_error("RAID module does not support RAID10.");
- 			return 0;
diff --git a/SOURCES/lvm2-2_02_169-clvmd-add-mutex-protection-for-cpg_-call.patch b/SOURCES/lvm2-2_02_169-clvmd-add-mutex-protection-for-cpg_-call.patch
deleted file mode 100644
index c724772..0000000
--- a/SOURCES/lvm2-2_02_169-clvmd-add-mutex-protection-for-cpg_-call.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From dae4f53acb269219e876c229c8f034fcdaf3ff5a Mon Sep 17 00:00:00 2001
-From: Zdenek Kabelac <zkabelac@redhat.com>
-Date: Sat, 4 Feb 2017 14:47:27 +0100
-Subject: [PATCH] clvmd: add mutex protection for cpg_ call
-
-The library for corosync multicasting is not supporting multithread
-usage - add local mutex to avoid parallel call of cpg_mcast_joined().
----
- WHATS_NEW                      | 1 +
- daemons/clvmd/clvmd-corosync.c | 4 ++++
- 2 files changed, 5 insertions(+)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 8ae2df8..0b571ae 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,6 @@
- Version 2.02.169 - 
- =====================================
-+  Avoid parallel usage of cpg_mcast_joined() in clvmd with corosync.
-   Fix segfault in lvmetad from missing NULL in daemon_reply_simple.
- 
- Version 2.02.167 - 
-diff --git a/daemons/clvmd/clvmd-corosync.c b/daemons/clvmd/clvmd-corosync.c
-index 05c9882..2227cbf 100644
---- a/daemons/clvmd/clvmd-corosync.c
-+++ b/daemons/clvmd/clvmd-corosync.c
-@@ -532,6 +532,7 @@ static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
- static int _cluster_send_message(const void *buf, int msglen, const char *csid,
- 				 const char *errtext)
- {
-+	static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
- 	struct iovec iov[2];
- 	cs_error_t err;
- 	int target_node;
-@@ -546,7 +547,10 @@ static int _cluster_send_message(const void *buf, int msglen, const char *csid,
- 	iov[1].iov_base = (char *)buf;
- 	iov[1].iov_len = msglen;
- 
-+	pthread_mutex_lock(&_mutex);
- 	err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
-+	pthread_mutex_unlock(&_mutex);
-+
- 	return cs_to_errno(err);
- }
- 
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_169-fix-segfault-in-lvmetad-from-missing-null-in-daemon_reply_simple.patch b/SOURCES/lvm2-2_02_169-fix-segfault-in-lvmetad-from-missing-null-in-daemon_reply_simple.patch
deleted file mode 100644
index 21b85a4..0000000
--- a/SOURCES/lvm2-2_02_169-fix-segfault-in-lvmetad-from-missing-null-in-daemon_reply_simple.patch
+++ /dev/null
@@ -1,50 +0,0 @@
- WHATS_NEW                      | 4 ++++
- daemons/lvmetad/lvmetad-core.c | 9 ++++++---
- 2 files changed, 10 insertions(+), 3 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 519bbc9..8ae2df8 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,3 +1,7 @@
-+Version 2.02.169 - 
-+=====================================
-+  Fix segfault in lvmetad from missing NULL in daemon_reply_simple.
-+
- Version 2.02.167 - 
- ======================================
-   Prevent raid4 creation/conversion on non-supporting kernels
-diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
-index 36a5cec..c46c7ac 100644
---- a/daemons/lvmetad/lvmetad-core.c
-+++ b/daemons/lvmetad/lvmetad-core.c
-@@ -2745,7 +2745,8 @@ static response handler(daemon_state s, client_handle h, request r)
- 							   "expected = %s", state->token,
- 							   "received = %s", token,
- 							   "update_pid = " FMTd64, (int64_t)state->update_pid,
--							   "reason = %s", "another command has populated the cache");
-+							   "reason = %s", "another command has populated the cache",
-+							   NULL);
- 			}
- 
- 			DEBUGLOG(state, "token_update end len %d pid %d new token %s",
-@@ -2778,7 +2779,8 @@ static response handler(daemon_state s, client_handle h, request r)
- 					   "expected = %s", state->token,
- 					   "received = %s", token,
- 					   "update_pid = " FMTd64, (int64_t)state->update_pid,
--					   "reason = %s", "another command has populated the cache");
-+					   "reason = %s", "another command has populated the cache",
-+					   NULL);
- 	}
- 
- 	/* If a pid doing update was cancelled, ignore its update messages. */
-@@ -2793,7 +2795,8 @@ static response handler(daemon_state s, client_handle h, request r)
- 					   "expected = %s", state->token,
- 					   "received = %s", token,
- 					   "update_pid = " FMTd64, (int64_t)state->update_pid,
--					   "reason = %s", "another command has populated the lvmetad cache");
-+					   "reason = %s", "another command has populated the lvmetad cache",
-+					   NULL);
- 	}
- 
- 	pthread_mutex_unlock(&state->token_lock);
diff --git a/SOURCES/lvm2-2_02_169-lvcreate-fix-striped-limit.patch b/SOURCES/lvm2-2_02_169-lvcreate-fix-striped-limit.patch
deleted file mode 100644
index 9e224dd..0000000
--- a/SOURCES/lvm2-2_02_169-lvcreate-fix-striped-limit.patch
+++ /dev/null
@@ -1,34 +0,0 @@
- WHATS_NEW        | 1 +
- tools/lvcreate.c | 4 +++-
- 2 files changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 0b571ae..26aa5b0 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -1,5 +1,6 @@
- Version 2.02.169 - 
- =====================================
-+  Fix limit of stripes in lvcreate.
-   Avoid parallel usage of cpg_mcast_joined() in clvmd with corosync.
-   Fix segfault in lvmetad from missing NULL in daemon_reply_simple.
- 
-diff --git a/tools/lvcreate.c b/tools/lvcreate.c
-index dbc0708..dae9da6 100644
---- a/tools/lvcreate.c
-+++ b/tools/lvcreate.c
-@@ -559,8 +559,10 @@ static int _read_mirror_and_raid_params(struct cmd_context *cmd,
- 			else if (seg_is_any_raid6(lp))
- 				max_images -= 2;
- 		}
--	} else
-+	} else if (seg_is_mirrored(lp))
- 		max_images = DEFAULT_MIRROR_MAX_IMAGES;
-+	else
-+		max_images = MAX_STRIPES;
- 
- 	/* Common mirror and raid params */
- 	if (arg_is_set(cmd, mirrors_ARG)) {
--- 
-1.8.3.1
-
diff --git a/SOURCES/lvm2-2_02_172-fix-raid-segfault.patch b/SOURCES/lvm2-2_02_172-fix-raid-segfault.patch
new file mode 100644
index 0000000..0a40151
--- /dev/null
+++ b/SOURCES/lvm2-2_02_172-fix-raid-segfault.patch
@@ -0,0 +1,16 @@
+ lib/metadata/raid_manip.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
+index 9e4f3a3..66fc2bd 100644
+--- a/lib/metadata/raid_manip.c
++++ b/lib/metadata/raid_manip.c
+@@ -2373,7 +2373,7 @@ static int _raid_reshape(struct logical_volume *lv,
+ 	if (seg->area_count != 2 || old_image_count != seg->area_count) {
+ 		if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, 0, &removal_lvs, NULL))
+ 			return_0;
+-	} if (!_vg_write_commit_backup(lv->vg))
++	} else if (!_vg_write_commit_backup(lv->vg))
+ 		return_0;
+ 
+ 	return 1; 
diff --git a/SOURCES/lvm2-2_02_172-libdm-initialization-of-reused-struct.patch b/SOURCES/lvm2-2_02_172-libdm-initialization-of-reused-struct.patch
new file mode 100644
index 0000000..05f5a61
--- /dev/null
+++ b/SOURCES/lvm2-2_02_172-libdm-initialization-of-reused-struct.patch
@@ -0,0 +1,53 @@
+ WHATS_NEW_DM              |  1 +
+ libdm/ioctl/libdm-iface.c | 10 +++++++++-
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
+index 581cd42..bf08130 100644
+--- a/WHATS_NEW_DM
++++ b/WHATS_NEW_DM
+@@ -1,5 +1,6 @@
+ Version 1.02.141 - 
+ ===============================
++  Fix reusing of dm_task structure for status reading (used by dmeventd).
+   dm_get_status_raid() handle better some incosistent md statuses.
+   Accept truncated files in calls to dm_stats_update_regions_from_fd().
+   Restore Warning by 5% increment when thin-pool is over 80% (1.02.138).
+diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c
+index cb3e8dc..65e75f6 100644
+--- a/libdm/ioctl/libdm-iface.c
++++ b/libdm/ioctl/libdm-iface.c
+@@ -467,7 +467,7 @@ static void _dm_zfree_dmi(struct dm_ioctl *dmi)
+ 	}
+ }
+ 
+-void dm_task_destroy(struct dm_task *dmt)
++static void _dm_task_free_targets(struct dm_task *dmt)
+ {
+ 	struct target *t, *n;
+ 
+@@ -478,6 +478,12 @@ void dm_task_destroy(struct dm_task *dmt)
+ 		dm_free(t);
+ 	}
+ 
++	dmt->head = dmt->tail = NULL;
++}
++
++void dm_task_destroy(struct dm_task *dmt)
++{
++	_dm_task_free_targets(dmt);
+ 	_dm_zfree_dmi(dmt->dmi.v4);
+ 	dm_free(dmt->dev_name);
+ 	dm_free(dmt->mangled_dev_name);
+@@ -652,6 +658,8 @@ static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi)
+ 	uint32_t i;
+ 	struct dm_target_spec *spec;
+ 
++	_dm_task_free_targets(dmt);
++
+ 	for (i = 0; i < dmi->target_count; i++) {
+ 		spec = (struct dm_target_spec *) outptr;
+ 		if (!dm_task_add_target(dmt, spec->sector_start,
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-2_02_172-upstream-6.patch b/SOURCES/lvm2-2_02_172-upstream-6.patch
new file mode 100644
index 0000000..36ae424
--- /dev/null
+++ b/SOURCES/lvm2-2_02_172-upstream-6.patch
@@ -0,0 +1,1466 @@
+ WHATS_NEW                                          |   2 +
+ WHATS_NEW_DM                                       |   1 +
+ lib/metadata/lv.c                                  |  11 +-
+ lib/metadata/lv_manip.c                            |  18 +-
+ lib/metadata/metadata-exported.h                   |   1 +
+ lib/metadata/raid_manip.c                          | 354 +++++++++++----------
+ lib/raid/raid.c                                    |  39 +--
+ lib/report/report.c                                |  10 +-
+ libdm/libdm-targets.c                              |  18 ++
+ scripts/fsadm.sh                                   |   1 +
+ test/lib/check.sh                                  |   2 +-
+ test/shell/fsadm.sh                                |   1 +
+ test/shell/lvconvert-raid-status-validation.sh     | 127 ++++++++
+ .../shell/lvconvert-raid-takeover-alloc-failure.sh |   9 +-
+ test/shell/lvconvert-raid-takeover-thin.sh         |  72 +++++
+ tools/lvresize.c                                   |   1 +
+ 16 files changed, 465 insertions(+), 202 deletions(-)
+diff --git a/WHATS_NEW b/WHATS_NEW
+index b2796f6..e60380a 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,5 +1,7 @@
+ Version 2.02.172 - 
+ ===============================
++  Reenable conversion of data and metadata thin-pool volumes to raid.
++  Improve raid status reporting with lvs.
+   No longer necessary to '--force' a repair for RAID1
+   Linear to RAID1 upconverts now use "recover" sync action, not "resync".
+   Improve lvcreate --cachepool arg validation.
+diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
+index 5718ab7..581cd42 100644
+--- a/WHATS_NEW_DM
++++ b/WHATS_NEW_DM
+@@ -1,5 +1,6 @@
+ Version 1.02.141 - 
+ ===============================
++  dm_get_status_raid() handle better some incosistent md statuses.
+   Accept truncated files in calls to dm_stats_update_regions_from_fd().
+   Restore Warning by 5% increment when thin-pool is over 80% (1.02.138).
+ 
+diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
+index b24c4aa..c87bb6b 100644
+--- a/lib/metadata/lv.c
++++ b/lib/metadata/lv.c
+@@ -395,6 +395,15 @@ dm_percent_t lvseg_percent_with_info_and_seg_status(const struct lv_with_info_an
+ 			}
+ 		}
+ 		break;
++	case SEG_STATUS_RAID:
++		switch (type) {
++		case PERCENT_GET_DIRTY:
++			p = dm_make_percent(s->raid->insync_regions, s->raid->total_regions);
++			break;
++		default:
++			p = DM_PERCENT_INVALID;
++		}
++		break;
+ 	case SEG_STATUS_SNAPSHOT:
+ 		if (s->snapshot->merge_failed)
+ 			p = DM_PERCENT_INVALID;
+@@ -1087,7 +1096,7 @@ int lv_raid_healthy(const struct logical_volume *lv)
+ 	}
+ 
+ 	if (!seg_is_raid(raid_seg)) {
+-		log_error("%s on %s is not a RAID segment",
++		log_error(INTERNAL_ERROR "%s on %s is not a RAID segment.",
+ 			  raid_seg->lv->name, lv->name);
+ 		return 0;
+ 	}
+diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
+index 8f38839..c431868 100644
+--- a/lib/metadata/lv_manip.c
++++ b/lib/metadata/lv_manip.c
+@@ -4578,6 +4578,7 @@ enum fsadm_cmd_e { FSADM_CMD_CHECK, FSADM_CMD_RESIZE };
+ static int _fsadm_cmd(enum fsadm_cmd_e fcmd,
+ 		      struct logical_volume *lv,
+ 		      uint32_t extents,
++		      int yes,
+ 		      int force,
+ 		      int *status)
+ {
+@@ -4585,7 +4586,7 @@ static int _fsadm_cmd(enum fsadm_cmd_e fcmd,
+ 	struct cmd_context *cmd = vg->cmd;
+ 	char lv_path[PATH_MAX];
+ 	char size_buf[SIZE_BUF];
+-	const char *argv[FSADM_CMD_MAX_ARGS + 2];
++	const char *argv[FSADM_CMD_MAX_ARGS + 4];
+ 	unsigned i = 0;
+ 
+ 	argv[i++] = find_config_tree_str(cmd, global_fsadm_executable_CFG, NULL);
+@@ -4596,6 +4597,9 @@ static int _fsadm_cmd(enum fsadm_cmd_e fcmd,
+ 	if (verbose_level() >= _LOG_NOTICE)
+ 		argv[i++] = "--verbose";
+ 
++	if (yes)
++		argv[i++] = "--yes";
++
+ 	if (force)
+ 		argv[i++] = "--force";
+ 
+@@ -5498,7 +5502,7 @@ int lv_resize(struct logical_volume *lv,
+ 
+ 	if (lp->resizefs) {
+ 		if (!lp->nofsck &&
+-		    !_fsadm_cmd(FSADM_CMD_CHECK, lv, 0, lp->force, &status)) {
++		    !_fsadm_cmd(FSADM_CMD_CHECK, lv, 0, lp->yes, lp->force, &status)) {
+ 			if (status != FSADM_CHECK_FAILS_FOR_MOUNTED) {
+ 				log_error("Filesystem check failed.");
+ 				return 0;
+@@ -5508,7 +5512,7 @@ int lv_resize(struct logical_volume *lv,
+ 
+ 		/* FIXME forks here */
+ 		if ((lp->resize == LV_REDUCE) &&
+-		    !_fsadm_cmd(FSADM_CMD_RESIZE, lv, lp->extents, lp->force, NULL)) {
++		    !_fsadm_cmd(FSADM_CMD_RESIZE, lv, lp->extents, lp->yes, lp->force, NULL)) {
+ 			log_error("Filesystem resize failed.");
+ 			return 0;
+ 		}
+@@ -5589,7 +5593,7 @@ out:
+ 				display_lvname(lv));
+ 
+ 	if (lp->resizefs && (lp->resize == LV_EXTEND) &&
+-	    !_fsadm_cmd(FSADM_CMD_RESIZE, lv, lp->extents, lp->force, NULL))
++	    !_fsadm_cmd(FSADM_CMD_RESIZE, lv, lp->extents, lp->yes, lp->force, NULL))
+ 		return_0;
+ 
+ 	ret = 1;
+@@ -6368,6 +6372,12 @@ static int _lv_update_and_reload(struct logical_volume *lv, int origin_only)
+ 	if (!vg_write(vg))
+ 		return_0;
+ 
++	if (lock_lv != lv) {
++		log_debug_activation("Dropping origin_only for %s as lock holds %s",
++				     display_lvname(lv), display_lvname(lock_lv));
++		origin_only = 0;
++	}
++
+ 	if (!(origin_only ? suspend_lv_origin(vg->cmd, lock_lv) : suspend_lv(vg->cmd, lock_lv))) {
+ 		log_error("Failed to lock logical volume %s.",
+ 			  display_lvname(lock_lv));
+diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
+index c4bebd0..6c3d8d7 100644
+--- a/lib/metadata/metadata-exported.h
++++ b/lib/metadata/metadata-exported.h
+@@ -649,6 +649,7 @@ struct lvresize_params {
+ 	int use_policies;
+ 
+ 	alloc_policy_t alloc;
++	int yes;
+ 	int force;
+ 	int nosync;
+ 	int nofsck;
+diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
+index ade27e6..9e4f3a3 100644
+--- a/lib/metadata/raid_manip.c
++++ b/lib/metadata/raid_manip.c
+@@ -75,6 +75,24 @@ static int _rebuild_with_emptymeta_is_supported(struct cmd_context *cmd,
+ 	return 1;
+ }
+ 
++/* https://bugzilla.redhat.com/1447812 check open count of @lv vs. @open_count */
++static int _check_lv_open_count(struct logical_volume *lv, int open_count) {
++	struct lvinfo info = { 0 };
++
++	if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0)) {
++		log_error("lv_info failed: aborting.");
++		return 0;
++	}
++	if (info.open_count != open_count) {
++		log_error("Reshape is only supported when %s is not in use (e.g. unmount filesystem).",
++			  display_lvname(lv));
++		return 0;
++	}
++
++	return 1;
++}
++
++
+ /*
+  * Ensure region size exceeds the minimum for @lv because
+  * MD's bitmap is limited to tracking 2^21 regions.
+@@ -442,7 +460,7 @@ static int _raid_remove_top_layer(struct logical_volume *lv,
+ 
+ 	if (!(lvl_array = dm_pool_alloc(lv->vg->vgmem, 2 * sizeof(*lvl)))) {
+ 		log_error("Memory allocation failed.");
+-		return_0;
++		return 0;
+ 	}
+ 
+ 	/* Add last metadata area to removal_lvs */
+@@ -534,10 +552,20 @@ static int _lv_update_reload_fns_reset_eliminate_lvs(struct logical_volume *lv,
+ 	fn_on_lv_t fn_pre_on_lv = NULL, fn_post_on_lv;
+ 	void *fn_pre_data, *fn_post_data = NULL;
+ 	struct dm_list *removal_lvs;
++	const struct logical_volume *lock_lv = lv_lock_holder(lv);
+ 
+ 	va_start(ap, origin_only);
+ 	removal_lvs = va_arg(ap, struct dm_list *);
+ 
++	if (lock_lv != lv) {
++		log_debug_activation("Dropping origin_only for %s as lock holds %s",
++				     display_lvname(lv), display_lvname(lock_lv));
++		origin_only = 0;
++	}
++
++	/* TODO/FIXME:  this function should be simplified to just call
++	 * lv_update_and_reload() and cleanup of remained LVs */
++
+ 	/* Retrieve post/pre functions and post/pre data reference from variable arguments, if any */
+ 	if ((fn_post_on_lv = va_arg(ap, fn_on_lv_t))) {
+ 		fn_post_data = va_arg(ap, void *);
+@@ -545,11 +573,13 @@ static int _lv_update_reload_fns_reset_eliminate_lvs(struct logical_volume *lv,
+ 			fn_pre_data = va_arg(ap, void *);
+ 	}
+ 
++	va_end(ap);
++
+ 	/* Call any fn_pre_on_lv before the first update and reload call (e.g. to rename LVs) */
+ 	/* returns 1: ok+ask caller to update, 2: metadata commited+ask caller to resume */
+ 	if (fn_pre_on_lv && !(r = fn_pre_on_lv(lv, fn_pre_data))) {
+ 		log_error(INTERNAL_ERROR "Pre callout function failed.");
+-		goto err;
++		return 0;
+ 	}
+ 
+ 	if (r == 2) {
+@@ -557,19 +587,19 @@ static int _lv_update_reload_fns_reset_eliminate_lvs(struct logical_volume *lv,
+ 		 * Returning 2 from pre function -> lv is suspended and
+ 		 * metadata got updated, don't need to do it again
+ 		 */
+-		if (!(r = (origin_only ? resume_lv_origin(lv->vg->cmd, lv_lock_holder(lv)) :
+-					 resume_lv(lv->vg->cmd, lv_lock_holder(lv))))) {
++		if (!(r = (origin_only ? resume_lv_origin(lv->vg->cmd, lock_lv) :
++					 resume_lv(lv->vg->cmd, lock_lv)))) {
+ 			log_error("Failed to resume %s.", display_lvname(lv));
+-			goto err;
++			return 0;
+ 		}
+ 
+ 	/* Update metadata and reload mappings including flags (e.g. LV_REBUILD, LV_RESHAPE_DELTA_DISKS_PLUS) */
+ 	} else if (!(r = (origin_only ? lv_update_and_reload_origin(lv) : lv_update_and_reload(lv))))
+-		goto err;
++		return_0;
+ 
+ 	/* Eliminate any residual LV and don't commit the metadata */
+ 	if (!(r = _eliminate_extracted_lvs_optional_write_vg(lv->vg, removal_lvs, 0)))
+-		goto err;
++		return_0;
+ 
+ 	/*
+ 	 * Now that any 'REBUILD' or 'RESHAPE_DELTA_DISKS' etc.
+@@ -582,25 +612,22 @@ static int _lv_update_reload_fns_reset_eliminate_lvs(struct logical_volume *lv,
+ 	 */
+ 	log_debug_metadata("Clearing any flags for %s passed to the kernel.", display_lvname(lv));
+ 	if (!(r = _reset_flags_passed_to_kernel(lv, &flags_reset)))
+-		goto err;
++		return_0;
+ 
+ 	/* Call any @fn_post_on_lv before the second update call (e.g. to rename LVs back) */
+ 	if (fn_post_on_lv && !(r = fn_post_on_lv(lv, fn_post_data))) {
+ 		log_error("Post callout function failed.");
+-		goto err;
++		return 0;
+ 	}
+ 
+ 	/* Update and reload to clear out reset flags in the metadata and in the kernel */
+ 	log_debug_metadata("Updating metadata mappings for %s.", display_lvname(lv));
+ 	if ((r != 2 || flags_reset) && !(r = (origin_only ? lv_update_and_reload_origin(lv) : lv_update_and_reload(lv)))) {
+ 		log_error(INTERNAL_ERROR "Update of LV %s failed.", display_lvname(lv));
+-		goto err;
++		return 0;
+ 	}
+ 
+-	r = 1;
+-err:
+-	va_end(ap);
+-	return r;
++	return 1;
+ }
+ 
+ /*
+@@ -622,6 +649,12 @@ static int _lv_update_and_reload_list(struct logical_volume *lv, int origin_only
+ 	struct lv_list *lvl;
+ 	int r;
+ 
++	if (lock_lv != lv) {
++		log_debug_activation("Dropping origin_only for %s as lock holds %s",
++				     display_lvname(lv), display_lvname(lock_lv));
++		origin_only = 0;
++	}
++
+ 	log_very_verbose("Updating logical volume %s on disk(s)%s.",
+ 			 display_lvname(lock_lv), origin_only ? " (origin only)": "");
+ 
+@@ -879,7 +912,7 @@ static int _reorder_raid10_near_seg_areas(struct lv_segment *seg, enum raid0_rai
+ 		break;
+ 
+ 	default:
+-		return 0;
++		return_0;
+ 	}
+ 
+ 	/* Sort areas */
+@@ -1558,7 +1591,7 @@ static int _lv_alloc_reshape_space(struct logical_volume *lv,
+ 		lv->size = lv_size_cur;
+ 		/* pay attention to lv_extend maybe having allocated more because of layout specific rounding */
+ 		if (!_lv_set_reshape_len(lv, _lv_total_rimage_len(lv) - prev_rimage_len))
+-			return 0;
++			return_0;
+ 	}
+ 
+ 	/* Preset data offset in case we fail relocating reshape space below */
+@@ -1635,7 +1668,7 @@ static int _lv_free_reshape_space_with_status(struct logical_volume *lv, enum al
+ 		seg->extents_copied = first_seg(lv)->area_len;
+ 
+ 		if (!_lv_set_reshape_len(lv, 0))
+-			return 0;
++			return_0;
+ 
+ 		/*
+ 		 * Only in case reshape space was freed at the beginning,
+@@ -1689,7 +1722,7 @@ static int _reshaped_state(struct logical_volume *lv, const unsigned dev_count,
+ 		return_0;
+ 
+ 	if (!_get_dev_health(lv, &kernel_devs, devs_health, devs_in_sync, NULL))
+-		return 0;
++		return_0;
+ 
+ 	if (kernel_devs == dev_count)
+ 		return 1;
+@@ -1740,7 +1773,7 @@ static int _reshape_adjust_to_size(struct logical_volume *lv,
+ 	uint32_t new_le_count;
+ 
+ 	if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &new_le_count))
+-		return 0;
++		return_0;
+ 
+ 	/* Externally visible LV size w/o reshape space */
+ 	lv->le_count = seg->len = new_le_count;
+@@ -1803,7 +1836,7 @@ static int _raid_reshape_add_images(struct logical_volume *lv,
+ 	}
+ 
+ 	if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &grown_le_count))
+-		return 0;
++		return_0;
+ 
+ 	current_le_count = lv->le_count - _reshape_len_per_lv(lv);
+ 	grown_le_count -= _reshape_len_per_dev(seg) * _data_rimages_count(seg, new_image_count);
+@@ -1828,7 +1861,7 @@ static int _raid_reshape_add_images(struct logical_volume *lv,
+ 			   new_image_count - old_image_count, new_image_count - old_image_count > 1 ? "s" : "",
+ 			   display_lvname(lv));
+ 	if (!_lv_raid_change_image_count(lv, 1, new_image_count, allocate_pvs, NULL, 0, 0))
+-		return 0;
++		return_0;
+ 
+ 	/* Reshape adding image component pairs -> change sizes/counters accordingly */
+ 	if (!_reshape_adjust_to_size(lv, old_image_count, new_image_count)) {
+@@ -1839,7 +1872,7 @@ static int _raid_reshape_add_images(struct logical_volume *lv,
+ 	/* Allocate forward out of place reshape space at the beginning of all data image LVs */
+ 	log_debug_metadata("(Re)allocating reshape space for %s.", display_lvname(lv));
+ 	if (!_lv_alloc_reshape_space(lv, alloc_begin, NULL, allocate_pvs))
+-		return 0;
++		return_0;
+ 
+ 	/*
+ 	 * Reshape adding image component pairs:
+@@ -1914,7 +1947,7 @@ static int _raid_reshape_remove_images(struct logical_volume *lv,
+ 		}
+ 
+ 		if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &reduced_le_count))
+-			return 0;
++			return_0;
+ 
+ 		reduced_le_count -= seg->reshape_len * _data_rimages_count(seg, new_image_count);
+ 		current_le_count = lv->le_count - seg->reshape_len * _data_rimages_count(seg, old_image_count);
+@@ -1936,7 +1969,7 @@ static int _raid_reshape_remove_images(struct logical_volume *lv,
+ 			 new_stripes, display_lvname(lv));
+ 
+ 		if (!force) {
+-			log_warn("WARNING: Can't remove stripes without --force option.");
++			log_error("Can't remove stripes without --force option.");
+ 			return 0;
+ 		}
+ 
+@@ -1952,7 +1985,7 @@ static int _raid_reshape_remove_images(struct logical_volume *lv,
+ 		 * to remove disks from a raid set
+ 		 */
+ 		if (!_lv_alloc_reshape_space(lv, alloc_end, NULL, allocate_pvs))
+-			return 0;
++			return_0;
+ 
+ 		/* Flag all disks past new images as delta disks minus to kernel */
+ 		for (s = new_image_count; s < old_image_count; s++)
+@@ -1998,7 +2031,7 @@ static int _raid_reshape_remove_images(struct logical_volume *lv,
+ 				   old_image_count - new_image_count, old_image_count - new_image_count > 1 ? "s" : "",
+ 				   display_lvname(lv));
+ 		if (!_lv_raid_change_image_count(lv, 1, new_image_count, allocate_pvs, removal_lvs, 0, 0))
+-			return 0;
++			return_0;
+ 
+ 		seg->area_count = new_image_count;
+ 		break;
+@@ -2069,7 +2102,7 @@ static int _raid_reshape_keep_images(struct logical_volume *lv,
+ 
+ 	if (alloc_reshape_space &&
+ 	    !_lv_alloc_reshape_space(lv, where, NULL, allocate_pvs))
+-		return 0;
++		return_0;
+ 
+ 	seg->segtype = new_segtype;
+ 
+@@ -2084,15 +2117,22 @@ static int _vg_write_lv_suspend_commit_backup(struct volume_group *vg,
+ 					      struct logical_volume *lv,
+ 					      int origin_only, int do_backup)
+ {
++	const struct logical_volume *lock_lv = lv_lock_holder(lv);
+ 	int r = 1;
+ 
++	if (lock_lv != lv) {
++		log_debug_activation("Dropping origin_only for %s as lock holds %s",
++				     display_lvname(lv), display_lvname(lock_lv));
++		origin_only = 0;
++	}
++
+ 	if (!vg_write(vg)) {
+ 		log_error("Write of VG %s failed.", vg->name);
+ 		return_0;
+ 	}
+ 
+-	if (lv && !(r = (origin_only ? suspend_lv_origin(vg->cmd, lv_lock_holder(lv)) :
+-				       suspend_lv(vg->cmd, lv_lock_holder(lv))))) {
++	if (lv && !(r = (origin_only ? suspend_lv_origin(vg->cmd, lock_lv) :
++				       suspend_lv(vg->cmd, lock_lv)))) {
+ 		log_error("Failed to suspend %s before committing changes.",
+ 			  display_lvname(lv));
+ 		vg_revert(lv->vg);
+@@ -2133,24 +2173,6 @@ static int _activate_sub_lv_excl_local(struct logical_volume *lv)
+ 	return 1;
+ }
+ 
+-/* Helper: function to activate any sub LVs of @lv exclusively local starting with area indexed by @start_idx */
+-static int _activate_sub_lvs_excl_local(struct logical_volume *lv, uint32_t start_idx)
+-{
+-	uint32_t s;
+-	struct lv_segment *seg = first_seg(lv);
+-
+-	/* seg->area_count may be 0 here! */
+-	log_debug_metadata("Activating %u image component%s of LV %s.",
+-			   seg->area_count - start_idx, seg->meta_areas ? " pairs" : "s",
+-			   display_lvname(lv));
+-	for (s = start_idx; s < seg->area_count; s++)
+-		if (!_activate_sub_lv_excl_local(seg_lv(seg, s)) ||
+-		    (seg->meta_areas && !_activate_sub_lv_excl_local(seg_metalv(seg, s))))
+-			return_0;
+-
+-	return 1;
+-}
+-
+ /* Helper: function to activate any LVs on @lv_list */
+ static int _activate_sub_lvs_excl_local_list(struct logical_volume *lv, struct dm_list *lv_list)
+ {
+@@ -2169,20 +2191,6 @@ static int _activate_sub_lvs_excl_local_list(struct logical_volume *lv, struct d
+ 	return r;
+ }
+ 
+-/* Helper: callback function to activate image component pairs of @lv to update size after reshape space allocation */
+-static int _pre_raid_reactivate_legs(struct logical_volume *lv, void *data)
+-{
+-	if (!_vg_write_lv_suspend_vg_commit(lv, 1))
+-		return 0;
+-
+-	/* Reload any changed image component pairs for out-of-place reshape space */
+-	if (!_activate_sub_lvs_excl_local(lv, 0))
+-		return 0;
+-
+-	/* 1: ok+ask caller to update, 2: metadata commited+ask caller to resume */
+-	return 2;
+-}
+-
+ /* Helper: callback function to activate any rmetas on @data list */
+ __attribute__ ((__unused__))
+ static int _pre_raid0_remove_rmeta(struct logical_volume *lv, void *data)
+@@ -2190,26 +2198,12 @@ static int _pre_raid0_remove_rmeta(struct logical_volume *lv, void *data)
+ 	struct dm_list *lv_list = data;
+ 
+ 	if (!_vg_write_lv_suspend_vg_commit(lv, 1))
+-		return 0;
++		return_0;
+ 
+ 	/* 1: ok+ask caller to update, 2: metadata commited+ask caller to resume */
+ 	return _activate_sub_lvs_excl_local_list(lv, lv_list) ? 2 : 0;
+ }
+ 
+-/* Helper: callback dummy needed for takeover+reshape */
+-static int _post_raid_reshape(struct logical_volume *lv, void *data)
+-{
+-	/* 1: ask caller to update, 2: don't ask caller to update */
+-	return 1;
+-}
+-
+-/* Helper: callback dummy needed for takeover+reshape */
+-static int _post_raid_takeover(struct logical_volume *lv, void *data)
+-{
+-	/* 1: ask caller to update, 2: don't ask caller to update */
+-	return 2;
+-}
+-
+ /*
+  * Reshape logical volume @lv by adding/removing stripes
+  * (absolute new stripes given in @new_stripes), changing
+@@ -2251,7 +2245,7 @@ static int _raid_reshape(struct logical_volume *lv,
+ 		return_0;
+ 
+ 	if (!_check_region_size_constraints(lv, new_segtype, new_region_size, new_stripe_size))
+-		return 0;
++		return_0;
+ 
+ 	if (!_raid_in_sync(lv)) {
+ 		log_error("Unable to convert %s while it is not in-sync.",
+@@ -2346,30 +2340,18 @@ static int _raid_reshape(struct logical_volume *lv,
+ 
+ 	/* Handle disk addition reshaping */
+ 	if (old_image_count < new_image_count) {
+-		/* FIXME: remove once MD kernel rhbz1443999 got fixed. */
+-		if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
+-			log_error("Can't add stripes to LV %s on single core.", display_lvname(lv));
+-			return 0;
+-		}
+-
+ 		if (!_raid_reshape_add_images(lv, new_segtype, yes,
+ 					      old_image_count, new_image_count,
+ 					      new_stripes, new_stripe_size, allocate_pvs))
+-			return 0;
++			return_0;
+ 
+ 	/* Handle disk removal reshaping */
+ 	} else if (old_image_count > new_image_count) {
+-		/* FIXME: remove once MD kernel rhbz1443999 got fixed. */
+-		if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
+-			log_error("Can't remove stripes from LV %s on single core.", display_lvname(lv));
+-			return 0;
+-		}
+-
+ 		if (!_raid_reshape_remove_images(lv, new_segtype, yes, force,
+ 						 old_image_count, new_image_count,
+ 						 new_stripes, new_stripe_size,
+ 						 allocate_pvs, &removal_lvs))
+-			return 0;
++			return_0;
+ 
+ 	/*
+ 	 * Handle raid set layout reshaping w/o changing # of legs (allocation algorithm or stripe size change)
+@@ -2377,20 +2359,22 @@ static int _raid_reshape(struct logical_volume *lv,
+ 	 */
+ 	} else if (!_raid_reshape_keep_images(lv, new_segtype, yes, force, &force_repair,
+ 					      new_data_copies, new_stripe_size, allocate_pvs))
+-		return 0;
++		return_0;
+ 
+ 	/* HM FIXME: workaround for not resetting "nosync" flag */
+ 	init_mirror_in_sync(0);
+ 
+ 	seg->region_size = new_region_size;
+ 
++	/* https://bugzilla.redhat.com/1447812 also check open count */
++	if (!_check_lv_open_count(lv, 1))
++		return_0;
++
+ 	if (seg->area_count != 2 || old_image_count != seg->area_count) {
+-		if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, 0, &removal_lvs,
+-							       _post_raid_reshape, NULL,
+-							       _pre_raid_reactivate_legs, NULL))
+-			return 0;
++		if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, 0, &removal_lvs, NULL))
++			return_0;
+ 	} if (!_vg_write_commit_backup(lv->vg))
+-		return 0;
++		return_0;
+ 
+ 	return 1; 
+ 	/* FIXME force_repair ? _lv_cond_repair(lv) : 1; */
+@@ -2565,14 +2549,6 @@ static int _raid_add_images_without_commit(struct logical_volume *lv,
+ 		return 0;
+ 	}
+ 
+-	if (lv_is_active(lv_lock_holder(lv)) &&
+-	    (old_count == 1) &&
+-	    (lv_is_thin_pool_data(lv) || lv_is_thin_pool_metadata(lv))) {
+-		log_error("Can't add image to active thin pool LV %s yet. Deactivate first.",
+-			  display_lvname(lv));
+-		return 0;
+-	}
+-
+ 	if (!archive(lv->vg))
+ 		return_0;
+ 
+@@ -3233,11 +3209,13 @@ int lv_raid_split(struct logical_volume *lv, int yes, const char *split_name,
+ 	}
+ 
+ 	/* Split on a 2-legged raid1 LV causes losing all resilience */
+-	if (new_count == 1 &&
+-	    !yes && yes_no_prompt("Are you sure you want to split %s LV %s losing all resilience? [y/n]: ",
+-				  lvseg_name(first_seg(lv)), display_lvname(lv)) == 'n') {
+-		log_error("Logical volume %s NOT split.", display_lvname(lv));
+-		return 0;
++	if (new_count == 1) {
++		if (!yes && yes_no_prompt("Are you sure you want to split %s LV %s losing all resilience? [y/n]: ",
++					  lvseg_name(first_seg(lv)), display_lvname(lv)) == 'n') {
++			log_error("Logical volume %s NOT split.", display_lvname(lv));
++			return 0;
++		}
++		log_verbose("Losing all resilience for logical volume %s.", display_lvname(lv));
+ 	}
+ 
+ 	/*
+@@ -3375,11 +3353,14 @@ int lv_raid_split_and_track(struct logical_volume *lv,
+ 	}
+ 
+ 	/* Split and track changes on a 2-legged raid1 LV causes losing resilience for newly written data. */
+-	if (seg->area_count == 2 &&
+-	    !yes && yes_no_prompt("Are you sure you want to split and track %s LV %s losing resilience for any newly written data? [y/n]: ",
+-				  lvseg_name(seg), display_lvname(lv)) == 'n') {
+-		log_error("Logical volume %s NOT split.", display_lvname(lv));
+-		return 0;
++	if (seg->area_count == 2) {
++		if (!yes && yes_no_prompt("Are you sure you want to split and track %s LV %s losing resilience for any newly written data? [y/n]: ",
++					  lvseg_name(seg), display_lvname(lv)) == 'n') {
++			log_error("Logical volume %s NOT split.", display_lvname(lv));
++			return 0;
++		}
++		log_verbose("Losing resilience for newly written data on logical volume %s.",
++			    display_lvname(lv));
+ 	}
+ 
+ 	for (s = seg->area_count - 1; s >= 0; --s) {
+@@ -3408,7 +3389,7 @@ int lv_raid_split_and_track(struct logical_volume *lv,
+ 		return_0;
+ 
+ 	if (seg->area_count == 2)
+-		log_warn("Any newly written data will be non-resilient on LV %s during the split!",
++		log_warn("WARNING: Any newly written data will be non-resilient on LV %s during the split!",
+ 			 display_lvname(lv));
+ 
+ 	log_print_unless_silent("Use 'lvconvert --merge %s' to merge back into %s.",
+@@ -3568,7 +3549,7 @@ static int _add_image_component_list(struct lv_segment *seg, int delete_from_lis
+ 		if (delete_from_list)
+ 			dm_list_del(&lvl->list);
+ 		if (!_add_component_lv(seg, lvl->lv, lv_flags, s++))
+-			return 0;
++			return_0;
+ 	}
+ 
+ 	return 1;
+@@ -3674,7 +3655,7 @@ static int _extract_image_component_sublist(struct lv_segment *seg,
+ 
+ 	for (s = idx; s < end; s++) {
+ 		if (!_extract_image_component_error_seg(seg, type, s, &lvl->lv, error_seg))
+-			return 0;
++			return_0;
+ 
+ 		dm_list_add(removal_lvs, &lvl->list);
+ 		lvl++;
+@@ -3831,7 +3812,7 @@ static int _raid0_add_or_remove_metadata_lvs(struct logical_volume *lv,
+ 		new_raid_type_flag = SEG_RAID0;
+ 	} else {
+ 		if (!_alloc_and_add_rmeta_devs_for_lv(lv, allocate_pvs))
+-			return 0;
++			return_0;
+ 
+ 		new_raid_type_flag = SEG_RAID0_META;
+ 	}
+@@ -4002,7 +3983,6 @@ static int _convert_raid1_to_mirror(struct logical_volume *lv,
+ 				    uint32_t new_image_count,
+ 				    uint32_t new_region_size,
+ 				    struct dm_list *allocate_pvs,
+-				    int update_and_reload,
+ 				    struct dm_list *removal_lvs)
+ {
+ 	struct logical_volume *log_lv;
+@@ -4042,14 +4022,14 @@ static int _convert_raid1_to_mirror(struct logical_volume *lv,
+ 	/* Remove rmeta LVs */
+ 	log_debug_metadata("Extracting and renaming metadata LVs.");
+ 	if (!_extract_image_component_list(seg, RAID_META, 0, removal_lvs))
+-		return 0;
++		return_0;
+ 
+ 	seg->meta_areas = NULL;
+ 
+ 	/* Rename all data sub LVs from "*_rimage_*" to "*_mimage_*" and set their status */
+ 	log_debug_metadata("Adjust data LVs of %s.", display_lvname(lv));
+ 	if (!_adjust_data_lvs(lv, RAID1_TO_MIRROR))
+-		return 0;
++		return_0;
+ 
+ 	seg->segtype = new_segtype;
+ 	seg->region_size = new_region_size;
+@@ -4059,7 +4039,10 @@ static int _convert_raid1_to_mirror(struct logical_volume *lv,
+ 	if (!attach_mirror_log(first_seg(lv), log_lv))
+ 		return_0;
+ 
+-	return update_and_reload ? _lv_update_reload_fns_reset_eliminate_lvs(lv, 0, removal_lvs, NULL) : 1;
++	if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, 0, removal_lvs, NULL))
++		return_0;
++
++	return 1;
+ }
+ 
+ /*
+@@ -4543,7 +4526,7 @@ static int _process_type_flags(const struct logical_volume *lv, struct possible_
+ 		    !(t & seg->segtype->flags) &&
+ 		     ((segtype = get_segtype_from_flag(lv->vg->cmd, t))))
+ 			if (!tfn(processed_segtypes, data ? : (void *) segtype))
+-				return 0;
++				return_0;
+ 	}
+ 
+ 	return 1;
+@@ -4794,7 +4777,7 @@ static int _raid1_to_mirrored_wrapper(TAKEOVER_FN_ARGS)
+ 		return_0;
+ 
+ 	return _convert_raid1_to_mirror(lv, new_segtype, new_image_count, new_region_size,
+-					allocate_pvs, 1, &removal_lvs);
++					allocate_pvs, &removal_lvs);
+ }
+ 
+ /*
+@@ -4874,7 +4857,7 @@ static int _clear_meta_lvs(struct logical_volume *lv)
+ 	dm_list_iterate_items(lvl, &meta_lvs) {
+ 		lv_set_hidden(lvl->lv);
+ 		if (!set_lv_segment_area_lv(seg, s++, lvl->lv, 0, RAID_META))
+-			return 0;
++			return_0;
+ 	}
+ 
+ 	return 1;
+@@ -5028,7 +5011,7 @@ static int _raid45_to_raid54_wrapper(TAKEOVER_FN_ARGS)
+ 
+ 	/* Shift parity SubLV pair "PDD..." <-> "DD...P" on raid4 <-> raid5_n conversion */
+ 	if( !_shift_parity_dev(seg))
+-		return 0;
++		return_0;
+ 
+ 	/* Don't resync */
+ 	init_mirror_in_sync(1);
+@@ -5068,7 +5051,7 @@ static int _takeover_downconvert_wrapper(TAKEOVER_FN_ARGS)
+ 	}
+ 
+ 	if (!_check_region_size_constraints(lv, new_segtype, new_region_size, new_stripe_size))
+-		return 0;
++		return_0;
+ 
+ 	if (seg_is_any_raid10(seg) && (seg->area_count % seg->data_copies)) {
+ 		log_error("Can't convert %s LV %s to %s with odd number of stripes.",
+@@ -5113,12 +5096,12 @@ static int _takeover_downconvert_wrapper(TAKEOVER_FN_ARGS)
+ 	if (seg_is_raid4(seg)) {
+ 		/* Shift parity SubLV pair "PDD..." -> "DD...P" to be able to remove it off the end */
+ 		if (!_shift_parity_dev(seg))
+-			return 0;
++			return_0;
+ 
+ 	} else if (seg_is_raid10_near(seg)) {
+ 		log_debug_metadata("Reordering areas for raid10 -> raid0 takeover.");
+ 		if (!_reorder_raid10_near_seg_areas(seg, reorder_from_raid10_near))
+-			return 0;
++			return_0;
+ 	}
+ 
+ 	if (segtype_is_any_raid0(new_segtype) &&
+@@ -5133,7 +5116,7 @@ static int _takeover_downconvert_wrapper(TAKEOVER_FN_ARGS)
+ 				   lv_raid_image_count(lv) - new_image_count,
+ 				   display_lvname(lv));
+ 		if (!_lv_raid_change_image_count(lv, 1, new_image_count, allocate_pvs, &removal_lvs, 0, 0))
+-			return 0;
++			return_0;
+ 
+ 		seg->area_count = new_image_count;
+ 	}
+@@ -5283,7 +5266,7 @@ static int _takeover_upconvert_wrapper(TAKEOVER_FN_ARGS)
+ 	}
+ 
+ 	if (!_check_region_size_constraints(lv, new_segtype, new_region_size, new_stripe_size))
+-		return 0;
++		return_0;
+ 
+ 	/* Archive metadata */
+ 	if (!archive(lv->vg))
+@@ -5304,7 +5287,7 @@ static int _takeover_upconvert_wrapper(TAKEOVER_FN_ARGS)
+ 	if (seg_is_raid0(seg)) {
+ 		log_debug_metadata("Adding metadata LVs to %s.", display_lvname(lv));
+ 		if (!_raid0_add_or_remove_metadata_lvs(lv, 0 /* update_and_reload */, allocate_pvs, NULL))
+-			return 0;
++			return_0;
+ 	}
+ 
+ 	/* Have to be cleared in conversion from raid0_meta -> raid4 or kernel will reject due to reordering disks */
+@@ -5354,7 +5337,7 @@ static int _takeover_upconvert_wrapper(TAKEOVER_FN_ARGS)
+ 			if (!_eliminate_extracted_lvs(lv->vg, &removal_lvs)) /* Updates vg */
+ 				return_0;
+ 
+-			return 0;
++			return_0;
+ 		}
+ 
+ 		seg = first_seg(lv);
+@@ -5384,11 +5367,11 @@ static int _takeover_upconvert_wrapper(TAKEOVER_FN_ARGS)
+ 
+ 			if (!_raid45_to_raid54_wrapper(lv, raid5_n_segtype, 1 /* yes */, force, seg->area_count,
+ 						       1 /* data_copies */, 0, 0, 0, allocate_pvs))
+-				return 0;
++				return_0;
+ 
+ 			if (!_drop_suffix(meta_lv->name, "_extracted") ||
+ 			    !_drop_suffix(data_lv->name, "_extracted"))
+-				return 0;
++				return_0;
+ 
+ 			data_lv->status |= RAID_IMAGE;
+ 			meta_lv->status |= RAID_META;
+@@ -5403,7 +5386,7 @@ static int _takeover_upconvert_wrapper(TAKEOVER_FN_ARGS)
+ 		} else if (segtype_is_raid5_n(new_segtype) &&
+ 			   !_raid45_to_raid54_wrapper(lv, raid5_n_segtype, yes, force, seg->area_count,
+ 						      1 /* data_copies */, 0, 0, 0, allocate_pvs))
+-			return 0;
++			return_0;
+ 	}
+ 
+ 	seg->data_copies = new_data_copies;
+@@ -5419,7 +5402,7 @@ static int _takeover_upconvert_wrapper(TAKEOVER_FN_ARGS)
+ 
+ 		log_debug_metadata("Reordering areas for raid0 -> raid10_near takeover.");
+ 		if (!_reorder_raid10_near_seg_areas(seg, reorder_to_raid10_near))
+-			return 0;
++			return_0;
+ 		/* Set rebuild flags accordingly */
+ 		for (s = 0; s < seg->area_count; s++) {
+ 			seg_lv(seg, s)->status &= ~LV_REBUILD;
+@@ -5436,10 +5419,8 @@ static int _takeover_upconvert_wrapper(TAKEOVER_FN_ARGS)
+ 
+ 	log_debug_metadata("Updating VG metadata and reloading %s LV %s.",
+ 			   lvseg_name(seg), display_lvname(lv));
+-	if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, 0, &removal_lvs,
+-						       _post_raid_takeover, NULL,
+-						       _pre_raid_reactivate_legs, NULL))
+-		return 0;
++	if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, 0, &removal_lvs, NULL))
++		return_0;
+ 
+ 	if (segtype_is_raid4(new_segtype) &&
+ 	    seg->area_count != 2) {
+@@ -5975,7 +5956,7 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 	/* raid1 -> */
+ 	} else if (seg_is_raid1(seg_from) && !segtype_is_mirror(*segtype)) {
+ 		if (seg_from->area_count != 2) {
+-			log_warn("Convert %s LV %s to 2 images first.",
++			log_error("Convert %s LV %s to 2 images first.",
+ 				 lvseg_name(seg_from), display_lvname(seg_from->lv));
+ 			return 0;
+ 
+@@ -5991,8 +5972,8 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 	} else if (seg_is_raid4(seg_from) || seg_is_any_raid5(seg_from)) {
+ 		if (segtype_is_raid1(*segtype) &&
+ 		    seg_from->area_count != 2) {
+-			log_warn("Convert %s LV %s to 2 stripes first (i.e. --stripes 1).",
+-				 lvseg_name(seg_from), display_lvname(seg_from->lv));
++			log_error("Convert %s LV %s to 2 stripes first (i.e. --stripes 1).",
++				  lvseg_name(seg_from), display_lvname(seg_from->lv));
+ 			return 0;
+ 
+ 		} else if (seg_is_raid4(seg_from) &&
+@@ -6007,8 +5988,8 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 
+ 		else if (segtype_is_raid10(*segtype)) {
+ 			if (seg_from->area_count < 3) {
+-				log_warn("Convert %s LV %s to minimum 3 stripes first (i.e. --stripes 2).",
+-					 lvseg_name(seg_from), display_lvname(seg_from->lv));
++				log_error("Convert %s LV %s to minimum 3 stripes first (i.e. --stripes 2).",
++					  lvseg_name(seg_from), display_lvname(seg_from->lv));
+ 				return 0;
+ 			}
+ 
+@@ -6016,8 +5997,8 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 
+ 		} else if (segtype_is_any_raid6(*segtype)) {
+ 			if (seg_from->area_count < 4) {
+-				log_warn("Convert %s LV %s to minimum 4 stripes first (i.e. --stripes 3).",
+-					 lvseg_name(seg_from), display_lvname(seg_from->lv));
++				log_error("Convert %s LV %s to minimum 4 stripes first (i.e. --stripes 3).",
++					  lvseg_name(seg_from), display_lvname(seg_from->lv));
+ 				return 0;
+ 
+ 			} else if (seg_is_raid4(seg_from) && !segtype_is_raid6_n_6(*segtype))
+@@ -6053,12 +6034,12 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr
+ 	/* -> raid1 */
+ 	} else if (!seg_is_mirror(seg_from) && segtype_is_raid1(*segtype)) {
+ 		if (!seg_is_raid4(seg_from) && !seg_is_any_raid5(seg_from)) {
+-			log_warn("Convert %s LV %s to raid4/raid5 first.",
+-				 lvseg_name(seg_from), display_lvname(seg_from->lv));
++			log_error("Convert %s LV %s to raid4/raid5 first.",
++				  lvseg_name(seg_from), display_lvname(seg_from->lv));
+ 			return 0;
+ 
+ 		} else if (seg_from->area_count != 2) {
+-			log_warn("Convert %s LV %s to 2 stripes first (i.e. --stripes 1).",
++			log_error("Convert %s LV %s to 2 stripes first (i.e. --stripes 1).",
+ 				 lvseg_name(seg_from), display_lvname(seg_from->lv));
+ 			return 0;
+ 
+@@ -6113,7 +6094,7 @@ static int _region_size_change_requested(struct logical_volume *lv, int yes, con
+ 	}
+ 
+ 	if (!_check_region_size_constraints(lv, seg->segtype, region_size, seg->stripe_size))
+-		return 0;
++		return_0;
+ 
+ 	if (!_raid_in_sync(lv)) {
+ 		log_error("Unable to change region size on %s LV %s while it is not in-sync.",
+@@ -6224,6 +6205,27 @@ static int _conversion_options_allowed(const struct lv_segment *seg_from,
+ 	return r;
+ }
+ 
++/* https://bugzilla.redhat.com/1447812 try opening LV exclusively */
++static int _lv_open_excl(struct logical_volume *lv, struct device **dev) {
++	char *dev_path;
++	size_t sz = strlen(lv->vg->cmd->dev_dir) + strlen(lv->vg->name) + strlen(lv->name) + 2;
++
++	*dev = NULL;
++	if (!(dev_path = dm_pool_alloc(lv->vg->cmd->mem, sz)))
++		return_0;
++	if (dm_snprintf(dev_path, sz, "%s%s/%s", lv->vg->cmd->dev_dir, lv->vg->name, lv->name) < 0)
++		return_0;
++	if (!(*dev = dev_create_file(dev_path, NULL, NULL, 0)))
++		return_0;
++	if (!dev_open_flags(*dev, O_EXCL, 1, 1)) {
++		log_error("Reshape is only supported when %s is not in use (e.g. unmount filesystem).",
++			  display_lvname(lv));
++		return 0;
++	}
++
++	return 1;
++}
++
+ /*
+  * lv_raid_convert
+  *
+@@ -6273,6 +6275,7 @@ int lv_raid_convert(struct logical_volume *lv,
+ 	uint32_t region_size;
+ 	uint32_t data_copies = seg->data_copies;
+ 	uint32_t available_slvs, removed_slvs;
++	struct device *dev;
+ 	takeover_fn_t takeover_fn;
+ 
+ 	/* FIXME If not active, prompt and activate */
+@@ -6282,6 +6285,12 @@ int lv_raid_convert(struct logical_volume *lv,
+ 		log_error("%s must be active to perform this operation.",
+ 			  display_lvname(lv));
+ 		return 0;
++	} else if (vg_is_clustered(lv->vg) &&
++		   !lv_is_active_exclusive_locally(lv_lock_holder(lv))) {
++		/* In clustered VGs, the LV must be active on this node exclusively. */
++		log_error("%s must be active exclusive locally to "
++			  "perform this operation.", display_lvname(lv));
++		return 0;
+ 	}
+ 
+ 	new_segtype = new_segtype ? : seg->segtype;
+@@ -6318,6 +6327,12 @@ int lv_raid_convert(struct logical_volume *lv,
+ 					 new_stripes, new_stripe_size_supplied))
+ 		return _log_possible_conversion_types(lv, new_segtype);
+ 
++	/* https://bugzilla.redhat.com/1439399 */
++	if (lv_is_origin(lv)) {
++		log_error("Can't convert snapshot origin %s.", display_lvname(lv));
++		return 0;
++	}
++
+ 	/*
+ 	 * reshape of capable raid type requested
+ 	 */
+@@ -6325,13 +6340,31 @@ int lv_raid_convert(struct logical_volume *lv,
+ 	case 0:
+ 		break;
+ 	case 1:
++		/* Conversion of reshapable raids is the cluster is not supported yet. */
++		if (locking_is_clustered()) {
++			log_error("Conversion of %s not supported in the cluster.", display_lvname(lv));
++			return 0;
++		}
++
++		/* https://bugzilla.redhat.com/1447812 reject reshape on open LV */
++		if (!_check_lv_open_count(lv, 0))
++			return_0;
++		if (!_lv_open_excl(lv, &dev))
++			return_0;
++		if (!_check_lv_open_count(lv, 1)) {
++			dev_close(dev);
++			return_0;
++		}
++
+ 		if (!_raid_reshape(lv, new_segtype, yes, force,
+ 				   data_copies, region_size,
+ 				   stripes, stripe_size, allocate_pvs)) {
++			dev_close(dev);
+ 			log_error("Reshape request failed on LV %s.", display_lvname(lv));
+ 			return 0;
+ 		}
+ 
++		dev_close(dev);
+ 		return 1;
+ 	case 2:
+ 		log_error("Invalid conversion request on %s.", display_lvname(lv));
+@@ -6344,7 +6377,8 @@ int lv_raid_convert(struct logical_volume *lv,
+ 
+ 	/* Prohibit any takeover in case sub LVs to be removed still exist after a previous reshape */
+ 	if (!_get_available_removed_sublvs(lv, &available_slvs, &removed_slvs))
+-		return 0;
++		return_0;
++
+ 	if (removed_slvs) {
+ 		log_error("Can't convert %s LV %s to %s containing sub LVs to remove after a reshape.",
+ 			  lvseg_name(seg), display_lvname(lv), new_segtype->name);
+@@ -6387,13 +6421,6 @@ int lv_raid_convert(struct logical_volume *lv,
+ 		    (segtype_is_striped_target(new_segtype) &&
+ 		    (new_stripes == 1)) ? SEG_TYPE_NAME_LINEAR : new_segtype->name);
+ 
+-	/* In clustered VGs, the LV must be active on this node exclusively. */
+-	if (vg_is_clustered(lv->vg) && !lv_is_active_exclusive_locally(lv)) {
+-		log_error("%s must be active exclusive locally to "
+-			  "perform this operation.", display_lvname(lv));
+-		return 0;
+-	}
+-
+ 	/* LV must be in sync. */
+ 	if (!_raid_in_sync(lv)) {
+ 		log_error("Unable to convert %s while it is not in-sync.",
+@@ -6634,6 +6661,11 @@ static int _lv_raid_rebuild_or_replace(struct logical_volume *lv,
+ 	}
+ 
+ 	if (!match_count) {
++		if (remove_pvs && !dm_list_empty(remove_pvs)) {
++			log_error("Logical volume %s does not contain devices specified to %s.",
++				  display_lvname(lv), action_str);
++			return 0;
++		}
+ 		log_print_unless_silent("%s does not contain devices specified to %s.",
+ 					display_lvname(lv), action_str);
+ 		return 1;
+diff --git a/lib/raid/raid.c b/lib/raid/raid.c
+index 8a53d7e..c5cfb0f 100644
+--- a/lib/raid/raid.c
++++ b/lib/raid/raid.c
+@@ -358,36 +358,21 @@ static int _raid_target_percent(void **target_state,
+ 				uint64_t *total_numerator,
+ 				uint64_t *total_denominator)
+ {
+-	int i;
+-	uint64_t numerator, denominator;
+-	char *pos = params;
+-	/*
+-	 * Status line:
+-	 *    <raid_type> <#devs> <status_chars> <synced>/<total>
+-	 * Example:
+-	 *    raid1 2 AA 1024000/1024000
+-	 */
+-	for (i = 0; i < 3; i++) {
+-		pos = strstr(pos, " ");
+-		if (pos)
+-			pos++;
+-		else
+-			break;
+-	}
+-	if (!pos || (sscanf(pos, FMTu64 "/" FMTu64 "%n", &numerator, &denominator, &i) != 2) ||
+-	    !denominator) {
+-		log_error("Failed to parse %s status fraction: %s",
+-			  (seg) ? seg->segtype->name : "segment", params);
+-		return 0;
+-	}
++	struct dm_status_raid *sr;
++
++	if (!dm_get_status_raid(mem, params, &sr))
++		return_0;
+ 
+-	*total_numerator += numerator;
+-	*total_denominator += denominator;
++	*total_numerator += sr->insync_regions;
++	*total_denominator += sr->total_regions;
+ 
+ 	if (seg)
+-		seg->extents_copied = (uint64_t) seg->area_len * dm_make_percent(numerator, denominator) / DM_PERCENT_100;
++		seg->extents_copied = (uint64_t) seg->area_len
++			* dm_make_percent(sr->insync_regions , sr->total_regions) / DM_PERCENT_100;
++
++	*percent = dm_make_percent(sr->insync_regions, sr->total_regions);
+ 
+-	*percent = dm_make_percent(numerator, denominator);
++	dm_pool_free(mem, sr);
+ 
+ 	return 1;
+ }
+@@ -475,7 +460,7 @@ static int _raid_target_present(struct cmd_context *cmd,
+ 		{ 1, 7, 0, RAID_FEATURE_RAID0, SEG_TYPE_NAME_RAID0 },
+ 		{ 1, 9, 0, RAID_FEATURE_SHRINK, "shrinking" },
+ 		{ 1, 9, 0, RAID_FEATURE_NEW_DEVICES_ACCEPT_REBUILD, "rebuild+emptymeta" },
+-		{ 1, 10, 1, RAID_FEATURE_RESHAPE, "reshaping" },
++		{ 1, 12, 0, RAID_FEATURE_RESHAPE, "reshaping" },
+ 	};
+ 
+ 	static int _raid_checked = 0;
+diff --git a/lib/report/report.c b/lib/report/report.c
+index d9880b2..f61776e 100644
+--- a/lib/report/report.c
++++ b/lib/report/report.c
+@@ -3079,11 +3079,13 @@ static int _copypercent_disp(struct dm_report *rh,
+ 	dm_percent_t percent = DM_PERCENT_INVALID;
+ 
+ 	/* TODO: just cache passes through lvseg_percent... */
+-	if (lv_is_cache(lv) || lv_is_used_cache_pool(lv))
++	if (lv_is_cache(lv) || lv_is_used_cache_pool(lv) ||
++	    (!lv_is_merging_origin(lv) && lv_is_raid(lv) && !seg_is_any_raid0(first_seg(lv))))
+ 		percent = lvseg_percent_with_info_and_seg_status(lvdm, PERCENT_GET_DIRTY);
+-	else if (((lv_is_raid(lv) && !seg_is_any_raid0(first_seg(lv)) &&
+-		   lv_raid_percent(lv, &percent)) ||
+-		  (lv_is_mirror(lv) &&
++	else if (lv_is_raid(lv) && !seg_is_any_raid0(first_seg(lv)))
++		/* old way for percentage when merging snapshot into raid origin */
++		(void) lv_raid_percent(lv, &percent);
++	else if (((lv_is_mirror(lv) &&
+ 		   lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, NULL))) &&
+ 		 (percent != DM_PERCENT_INVALID))
+ 		percent = copy_percent(lv);
+diff --git a/libdm/libdm-targets.c b/libdm/libdm-targets.c
+index 1709c2b..6577f07 100644
+--- a/libdm/libdm-targets.c
++++ b/libdm/libdm-targets.c
+@@ -99,6 +99,7 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
+ 	unsigned num_fields;
+ 	const char *p, *pp, *msg_fields = "";
+ 	struct dm_status_raid *s = NULL;
++	unsigned a = 0;
+ 
+ 	if ((num_fields = _count_fields(params)) < 4)
+ 		goto_bad;
+@@ -168,6 +169,23 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
+ out:
+ 	*status = s;
+ 
++	if (s->insync_regions == s->total_regions) {
++		/* FIXME: kernel gives misleading info here
++		 * Trying to recognize a true state */
++		while (i-- > 0)
++			if (s->dev_health[i] == 'a')
++				a++; /* Count number of 'a' */
++
++		if (a && a < s->dev_count) {
++			/* SOME legs are in 'a' */
++			if (!strcasecmp(s->sync_action, "recover")
++			    || !strcasecmp(s->sync_action, "idle"))
++				/* Kernel may possibly start some action
++				 * in near-by future, do not report 100% */
++				s->insync_regions--;
++		}
++	}
++
+ 	return 1;
+ 
+ bad:
+diff --git a/scripts/fsadm.sh b/scripts/fsadm.sh
+index ea14efe..adf9b55 100755
+--- a/scripts/fsadm.sh
++++ b/scripts/fsadm.sh
+@@ -402,6 +402,7 @@ yes_no() {
+ 	while read -r -s -n 1 ANS ; do
+ 		case "$ANS" in
+ 		 "y" | "Y" ) echo y ; return 0 ;;
++		 "n" | "N") break ;;
+ 		 "" ) if [ -t 1 ] ; then
+ 			echo y ; return 0
+ 		      fi ;;
+diff --git a/test/lib/check.sh b/test/lib/check.sh
+index 64812fb..5eec936 100644
+--- a/test/lib/check.sh
++++ b/test/lib/check.sh
+@@ -411,7 +411,7 @@ raid_leg_status() {
+ 
+ grep_dmsetup() {
+ 	dmsetup $1 $2 | tee out
+-	grep "${@:3}" out || die "Expected output from dmsetup $1 not found!"
++	grep -q "${@:3}" out || die "Expected output \"${@:3}\" from dmsetup $1 not found!"
+ }
+ 
+ #set -x
+diff --git a/test/shell/fsadm.sh b/test/shell/fsadm.sh
+index ac43900..6eff24a 100644
+--- a/test/shell/fsadm.sh
++++ b/test/shell/fsadm.sh
+@@ -131,6 +131,7 @@ if check_missing ext3; then
+ 	not fsadm -y --lvresize resize $vg_lv 4M
+ 	echo n | not lvresize -L4M -r -n $vg_lv
+ 	lvresize -L+20M -r -n $vg_lv
++	lvresize -L-10M -r -y $vg_lv
+ 	umount "$mount_dir"
+ 	umount "$mount_space_dir"
+ 	fscheck_ext3
+diff --git a/test/shell/lvconvert-raid-status-validation.sh b/test/shell/lvconvert-raid-status-validation.sh
+new file mode 100644
+index 0000000..d705cc2
+--- /dev/null
++++ b/test/shell/lvconvert-raid-status-validation.sh
+@@ -0,0 +1,127 @@
++#######################################################################
++# This series of tests is meant to validate the correctness of
++# 'dmsetup status' for RAID LVs - especially during various sync action
++# transitions, like: recover, resync, check, repair, idle, reshape, etc
++#######################################################################
++SKIP_WITH_LVMLOCKD=1
++SKIP_WITH_LVMPOLLD=1
++
++export LVM_TEST_LVMETAD_DEBUG_OPTS=${LVM_TEST_LVMETAD_DEBUG_OPTS-}
++
++. lib/inittest
++
++# check for version 1.9.0
++# - it is the point at which linear->raid1 uses "recover"
++aux have_raid 1 9 0 || skip
++
++aux prepare_pvs 9
++vgcreate -s 2m $vg $(cat DEVICES)
++
++###########################################
++# Upconverted RAID1 should never have all 'a's in status output
++###########################################
++aux delay_dev $dev2 0 50
++lvcreate -aey -l 2 -n $lv1 $vg $dev1
++lvconvert --type raid1 -y -m 1 $vg/$lv1 $dev2
++while ! check in_sync $vg $lv1; do
++        a=( $(dmsetup status $vg-$lv1) ) || die "Unable to get status of $vg/$lv1"
++	[ ${a[5]} != "aa" ]
++        sleep .1
++done
++aux enable_dev $dev2
++lvremove -ff $vg
++
++###########################################
++# Upconverted RAID1 should not be at 100% right after upconvert
++###########################################
++aux delay_dev $dev2 0 50
++lvcreate -aey -l 2 -n $lv1 $vg $dev1
++lvconvert --type raid1 -y -m 1 $vg/$lv1 $dev2
++a=( $(dmsetup status $vg-$lv1) ) || die "Unable to get status of $vg/$lv1"
++b=( $(echo ${a[6]} | sed s:/:' ':) )
++[ ${b[0]} -ne ${b[1]} ]
++aux enable_dev $dev2
++lvremove -ff $vg
++
++###########################################
++# Catch anything suspicious with linear -> RAID1 upconvert
++###########################################
++aux delay_dev $dev2 0 50
++lvcreate -aey -l 2 -n $lv1 $vg $dev1
++lvconvert --type raid1 -y -m 1 $vg/$lv1 $dev2
++while true; do
++        a=( $(dmsetup status $vg-$lv1) ) || die "Unable to get status of $vg/$lv1"
++	b=( $(echo ${a[6]} | sed s:/:' ':) )
++	if [ ${b[0]} -ne ${b[1]} ]; then
++		# If the sync operation ("recover" in this case) is not
++		# finished, then it better be as follows:
++		[ ${a[5]} == "Aa" ]
++		[ ${a[7]} == "recover" ]
++	else
++		# Tough to tell the INVALID case,
++		#   Before starting sync thread: "Aa X/X recover"
++		# from the valid case,
++		#   Just finished sync thread: "Aa X/X recover"
++		# We'll just put "should" for now
++		should [ ${a[5]} == "AA" ]
++		should [ ${a[7]} == "idle" ]
++		break
++	fi
++        sleep .1
++done
++aux enable_dev $dev2
++lvremove -ff $vg
++
++###########################################
++# Catch anything suspicious with RAID1 2-way -> 3-way upconvert
++###########################################
++aux delay_dev $dev3 0 50
++lvcreate --type raid1 -m 1 -aey -l 2 -n $lv1 $vg $dev1 $dev2
++lvconvert -y -m +1 $vg/$lv1 $dev3
++while true; do
++        a=( $(dmsetup status $vg-$lv1) ) || die "Unable to get status of $vg/$lv1"
++	b=( $(echo ${a[6]} | sed s:/:' ':) )
++	if [ ${b[0]} -ne ${b[1]} ]; then
++		# If the sync operation ("recover" in this case) is not
++		# finished, then it better be as follows:
++		[ ${a[5]} == "AAa" ]
++		[ ${a[7]} == "recover" ]
++	else
++		# Tough to tell the INVALID case,
++		#   Before starting sync thread: "Aa X/X recover"
++		# from the valid case,
++		#   Just finished sync thread: "Aa X/X recover"
++		# We'll just put "should" for now
++		should [ ${a[5]} == "AAA" ]
++		should [ ${a[7]} == "idle" ]
++		break
++	fi
++        sleep .1
++done
++aux enable_dev $dev3
++lvremove -ff $vg
++
++###########################################
++# Catch anything suspicious with RAID1 initial resync
++###########################################
++aux delay_dev $dev2 0 50
++lvcreate --type raid1 -m 1 -aey -l 2 -n $lv1 $vg $dev1 $dev2
++while true; do
++        a=( $(dmsetup status $vg-$lv1) ) || die "Unable to get status of $vg/$lv1"
++	b=( $(echo ${a[6]} | sed s:/:' ':) )
++	if [ ${b[0]} -ne ${b[1]} ]; then
++		# If the sync operation ("resync" in this case) is not
++		# finished, then it better be as follows:
++		[ ${a[5]} == "aa" ]
++		[ ${a[7]} == "resync" ]
++	else
++		should [ ${a[5]} == "AA" ]
++		should [ ${a[7]} == "idle" ]
++		break
++	fi
++        sleep .1
++done
++aux enable_dev $dev2
++lvremove -ff $vg
++
++vgremove -ff $vg
+diff --git a/test/shell/lvconvert-raid-takeover-alloc-failure.sh b/test/shell/lvconvert-raid-takeover-alloc-failure.sh
+index 3870c35..cf926a1 100644
+--- a/test/shell/lvconvert-raid-takeover-alloc-failure.sh
++++ b/test/shell/lvconvert-raid-takeover-alloc-failure.sh
+@@ -48,7 +48,7 @@ function check_no_sub_lvs
+ # Check takover upconversion fails allocation errors nicely without leaving image pair remnants behind
+ 
+ # 6-way striped: neither conversion to raid5 nor raid6 possible
+-lvcreate --yes --stripes 6 --size 4M --name $lv1 $vg
++lvcreate -aey --yes --stripes 6 --size 4M --name $lv1 $vg
+ not lvconvert --yes --type raid4 $vg/$lv1
+ check lv_field $vg/$lv1 segtype "striped"
+ check_no_sub_lvs $vg $lv1 0 5
+@@ -69,7 +69,7 @@ check_sub_lvs $vg $lv1 0 5
+ lvremove -y $vg
+ 
+ # 5-way striped: conversion to raid5 possible but not to raid6
+-lvcreate --yes --stripes 5 --size 4M --name $lv1 $vg
++lvcreate -aey --stripes 5 --size 4M --name $lv1 $vg
+ not lvconvert --yes --type raid6 $vg/$lv1
+ check lv_field $vg/$lv1 segtype "striped"
+ check_no_sub_lvs $vg $lv1 0 5
+@@ -83,7 +83,7 @@ check_sub_lvs $vg $lv1 0 5
+ lvremove -y $vg
+ 
+ # 4-way striped: conversion to raid5 and raid6 possible
+-lvcreate --yes --stripes 4 --size 4M --name $lv1 $vg
++lvcreate -aey --stripes 4 --size 4M --name $lv1 $vg
+ lvconvert --yes --type raid5 $vg/$lv1
+ check lv_field $vg/$lv1 segtype "raid5_n"
+ check lv_field $vg/$lv1 stripes 5
+@@ -92,7 +92,8 @@ check_sub_lvs $vg $lv1 0 4
+ check_no_sub_lvs $vg $lv1 5 5
+ 
+ lvremove -y $vg
+-lvcreate --yes --stripes 4 --size 4M --name $lv1 $vg
++
++lvcreate -aey --stripes 4 --size 4M --name $lv1 $vg
+ lvconvert --yes --type raid6 $vg/$lv1
+ check lv_field $vg/$lv1 segtype "raid6_n_6"
+ check lv_field $vg/$lv1 stripes 6
+diff --git a/test/shell/lvconvert-raid-takeover-thin.sh b/test/shell/lvconvert-raid-takeover-thin.sh
+new file mode 100644
+index 0000000..647b133
+--- /dev/null
++++ b/test/shell/lvconvert-raid-takeover-thin.sh
+@@ -0,0 +1,72 @@
++#!/bin/sh
++# Copyright (C) 2017 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, MA2110-1301 USA
++
++# check we may convert thin-pool to raid1/raid10 and back
++# RHBZ#1365286
++
++SKIP_WITH_LVMLOCKD=1
++SKIP_WITH_LVMPOLLD=1
++
++. lib/inittest
++
++aux have_thin 1 0 0 || skip
++aux have_raid 1 9 0 || skip
++
++aux prepare_vg 6
++
++lvcreate -L4 -i3 -T $vg/pool -V10
++
++for i in 1 2 ; do
++lvconvert --type raid10 -y $vg/pool_tdata
++check grep_dmsetup table $vg-pool_tdata "raid10"
++aux wait_for_sync $vg pool_tdata
++
++lvconvert --type striped -y $vg/pool_tdata
++check grep_dmsetup table $vg-pool_tdata "striped"
++done
++
++lvremove -f $vg
++
++lvcreate -L4  -T $vg/pool -V10 -n $lv1
++
++for j in data meta ; do
++  LV=pool_t${j}
++  for i in 1 2 ; do
++    lvconvert --type raid1 -m1 -y  $vg/$LV
++    check grep_dmsetup table $vg-${LV} "raid1"
++    aux wait_for_sync $vg $LV
++
++    lvconvert --type raid1 -m0 -y  $vg/$LV
++    check grep_dmsetup table ${vg}-${LV} "linear"
++  done
++done
++
++
++#
++# Now same test again, when lock holding LV is not a thin-poll
++# but thinLV $lv1
++#
++lvchange -an $vg
++lvchange -ay $vg/$lv1
++
++for j in data meta ; do
++  LV=pool_t${j}
++  for i in 1 2 ; do
++    lvconvert --type raid1 -m1 -y  $vg/$LV
++    check grep_dmsetup table $vg-${LV} "raid1"
++    aux wait_for_sync $vg $LV
++
++    lvconvert --type raid1 -m0 -y  $vg/$LV
++    check grep_dmsetup table ${vg}-${LV} "linear"
++  done
++done
++
++vgremove -ff $vg
+diff --git a/tools/lvresize.c b/tools/lvresize.c
+index 1d59239..9b061ac 100644
+--- a/tools/lvresize.c
++++ b/tools/lvresize.c
+@@ -147,6 +147,7 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
+ 	lp->argv = ++argv;
+ 
+ 	lp->alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, 0);
++	lp->yes = arg_is_set(cmd, yes_ARG);
+ 	lp->force = arg_is_set(cmd, force_ARG);
+ 	lp->nofsck = arg_is_set(cmd, nofsck_ARG);
+ 	lp->nosync = arg_is_set(cmd, nosync_ARG);
diff --git a/SOURCES/lvm2-2_02_172-upstream.patch b/SOURCES/lvm2-2_02_172-upstream.patch
new file mode 100644
index 0000000..ea903d7
--- /dev/null
+++ b/SOURCES/lvm2-2_02_172-upstream.patch
@@ -0,0 +1,4536 @@
+ WHATS_NEW                                          |  19 +
+ WHATS_NEW_DM                                       |   5 +
+ daemons/dmeventd/plugins/raid/dmeventd_raid.c      |  16 +
+ daemons/dmeventd/plugins/thin/dmeventd_thin.c      |  12 +-
+ daemons/dmfilemapd/dmfilemapd.c                    |  49 +-
+ daemons/lvmdbusd/automatedproperties.py            |   2 +-
+ daemons/lvmdbusd/background.py                     |  13 +-
+ daemons/lvmdbusd/cmdhandler.py                     |  18 +-
+ daemons/lvmdbusd/fetch.py                          |  10 +-
+ daemons/lvmdbusd/objectmanager.py                  |  10 +-
+ daemons/lvmdbusd/utils.py                          |   4 +-
+ lib/activate/activate.c                            |   1 -
+ lib/config/config_settings.h                       |   7 +-
+ lib/config/defaults.h                              |   4 +-
+ lib/format_text/export.c                           |  32 +-
+ lib/format_text/flags.c                            | 107 +++-
+ lib/format_text/import-export.h                    |  17 +-
+ lib/format_text/import_vsn1.c                      |  23 +-
+ lib/metadata/merge.c                               |   2 +-
+ lib/metadata/metadata-exported.h                   |   5 +-
+ lib/metadata/metadata.c                            | 129 ++++-
+ lib/metadata/raid_manip.c                          | 598 ++++++++++++++++-----
+ lib/metadata/segtype.h                             |  18 +
+ lib/metadata/thin_manip.c                          |  19 +-
+ lib/raid/raid.c                                    |   1 +
+ libdm/libdm-stats.c                                |  24 +-
+ liblvm/lvm_lv.c                                    |   2 +-
+ man/clvmd.8_main                                   |   7 +-
+ man/lvm-fullreport.8_des                           |   1 -
+ man/lvm.8_main                                     |   2 +
+ man/lvm.conf.5_main                                |   4 +
+ man/lvmcache.7_main                                |  18 +
+ man/lvmetad.8_main                                 |  11 +-
+ man/lvmlockd.8_main                                |  97 ++--
+ man/lvmraid.7_main                                 | 132 +++--
+ man/lvmreport.7_main                               |   2 +-
+ man/lvmsystemid.7_main                             |  19 +-
+ man/pvchange.8_des                                 |   3 +
+ man/see_also.end                                   |   2 +
+ man/vgexport.8_des                                 |   2 +-
+ scripts/fsadm.sh                                   | 203 +++++--
+ test/dbus/lvmdbustest.py                           |  56 +-
+ test/shell/fsadm-renamed.sh                        | 116 ++++
+ test/shell/lvchange-raid.sh                        |   1 +
+ test/shell/lvconvert-raid-regionsize.sh            |   8 +
+ .../lvconvert-raid-reshape-striped_to_linear.sh    |   2 +-
+ test/shell/lvconvert-raid.sh                       |  61 +++
+ test/shell/lvconvert-thin.sh                       |   2 +-
+ test/shell/lvcreate-cache.sh                       |   6 +
+ test/shell/lvcreate-large-raid.sh                  |  10 +-
+ test/shell/lvcreate-raid-nosync.sh                 |   6 +-
+ test/shell/lvcreate-thin-big.sh                    |   2 +-
+ test/shell/lvresize-full.sh                        |   1 +
+ test/shell/thin-dmeventd-warns.sh                  |  85 +++
+ test/shell/thin-large.sh                           |  54 ++
+ test/shell/thin-resize-match.sh                    |   3 +-
+ test/shell/unknown-segment.sh                      |   9 +-
+ test/unit/Makefile.in                              |  14 +-
+ tools/args.h                                       |  99 +++-
+ tools/command-lines.in                             |   2 +-
+ tools/command.c                                    |  27 +-
+ tools/lvchange.c                                   |  10 +
+ tools/lvcreate.c                                   |  44 +-
+ tools/reporter.c                                   |   6 +-
+ tools/toollib.c                                    |  18 +-
+ 65 files changed, 1829 insertions(+), 453 deletions(-)
+
+diff --git a/WHATS_NEW b/WHATS_NEW
+index 33a27e8..b2796f6 100644
+--- a/WHATS_NEW
++++ b/WHATS_NEW
+@@ -1,3 +1,22 @@
++Version 2.02.172 - 
++===============================
++  No longer necessary to '--force' a repair for RAID1
++  Linear to RAID1 upconverts now use "recover" sync action, not "resync".
++  Improve lvcreate --cachepool arg validation.
++  Limit maximal size of thin-pool for specific chunk size.
++  Print a warning about in-use PVs with no VG using them.
++  Disable automatic clearing of PVs that look like in-use orphans.
++  Cache format2 flag is now using segment name type field.
++  Support storing status flags via segtype name field.
++  Stop using '--yes' mode when fsadm runs without terminal.
++  Extend validation of filesystems resized by fsadm.
++  Enhance lvconvert automatic settings of possible (raid) LV types.
++  Allow lvchange to change properties on a thin pool data sub LV.
++  Fix lvcreate extent percentage calculation for mirrors.
++  Don't reinstate still-missing devices when correcting inconsistent metadata.
++  Properly handle subshell return codes in fsadm.
++  Disallow cachepool creation with policy cleaner and mode writeback.
++
+ Version 2.02.171 - 3rd May 2017
+ ===============================
+   Fix memory warnings by using mempools for command definition processing.
+diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
+index 20d6220..5718ab7 100644
+--- a/WHATS_NEW_DM
++++ b/WHATS_NEW_DM
+@@ -1,3 +1,8 @@
++Version 1.02.141 - 
++===============================
++  Accept truncated files in calls to dm_stats_update_regions_from_fd().
++  Restore Warning by 5% increment when thin-pool is over 80% (1.02.138).
++
+ Version 1.02.140 - 3rd May 2017
+ ===============================
+   Add missing configure --enable-dmfilemapd status message and fix --disable.
+diff --git a/daemons/dmeventd/plugins/raid/dmeventd_raid.c b/daemons/dmeventd/plugins/raid/dmeventd_raid.c
+index 4f204bf..afeac28 100644
+--- a/daemons/dmeventd/plugins/raid/dmeventd_raid.c
++++ b/daemons/dmeventd/plugins/raid/dmeventd_raid.c
+@@ -58,6 +58,22 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
+ 		dead = 1;
+ 	}
+ 
++	/*
++	 * if we are converting from non-RAID to RAID (e.g. linear -> raid1)
++	 * and too many original devices die, such that we cannot continue
++	 * the "recover" operation, the sync action will go to "idle", the
++	 * unsynced devs will remain at 'a', and the original devices will
++	 * NOT SWITCH TO 'D', but will remain at 'A' - hoping to be revived.
++	 *
++	 * This is simply the way the kernel works...
++	 */
++	if (!strcmp(status->sync_action, "idle") &&
++	    strchr(status->dev_health, 'a')) {
++		log_error("Primary sources for new RAID, %s, have failed.",
++			  device);
++		dead = 1; /* run it through LVM repair */
++	}
++
+ 	if (dead) {
+ 		if (status->insync_regions < status->total_regions) {
+ 			if (!state->warned) {
+diff --git a/daemons/dmeventd/plugins/thin/dmeventd_thin.c b/daemons/dmeventd/plugins/thin/dmeventd_thin.c
+index e7d24c5..7fd7b0e 100644
+--- a/daemons/dmeventd/plugins/thin/dmeventd_thin.c
++++ b/daemons/dmeventd/plugins/thin/dmeventd_thin.c
+@@ -47,10 +47,8 @@ struct dso_state {
+ 	struct dm_pool *mem;
+ 	int metadata_percent_check;
+ 	int metadata_percent;
+-	int metadata_warn_once;
+ 	int data_percent_check;
+ 	int data_percent;
+-	int data_warn_once;
+ 	uint64_t known_metadata_size;
+ 	uint64_t known_data_size;
+ 	unsigned fails;
+@@ -253,9 +251,8 @@ void process_event(struct dm_task *dmt,
+ 	 * action is called for:  >50%, >55% ... >95%, 100%
+ 	 */
+ 	state->metadata_percent = dm_make_percent(tps->used_metadata_blocks, tps->total_metadata_blocks);
+-	if (state->metadata_percent <= WARNING_THRESH)
+-		state->metadata_warn_once = 0; /* Dropped bellow threshold, reset warn once */
+-	else if (!state->metadata_warn_once++) /* Warn once when raised above threshold */
++	if ((state->metadata_percent > WARNING_THRESH) &&
++	    (state->metadata_percent > state->metadata_percent_check))
+ 		log_warn("WARNING: Thin pool %s metadata is now %.2f%% full.",
+ 			 device, dm_percent_to_float(state->metadata_percent));
+ 	if (state->metadata_percent > CHECK_MINIMUM) {
+@@ -269,9 +266,8 @@ void process_event(struct dm_task *dmt,
+ 		state->metadata_percent_check = CHECK_MINIMUM;
+ 
+ 	state->data_percent = dm_make_percent(tps->used_data_blocks, tps->total_data_blocks);
+-	if (state->data_percent <= WARNING_THRESH)
+-		state->data_warn_once = 0;
+-	else if (!state->data_warn_once++)
++	if ((state->data_percent > WARNING_THRESH) &&
++	    (state->data_percent > state->data_percent_check))
+ 		log_warn("WARNING: Thin pool %s data is now %.2f%% full.",
+ 			 device, dm_percent_to_float(state->data_percent));
+ 	if (state->data_percent > CHECK_MINIMUM) {
+diff --git a/daemons/dmfilemapd/dmfilemapd.c b/daemons/dmfilemapd/dmfilemapd.c
+index 2dd069a..43ae970 100644
+--- a/daemons/dmfilemapd/dmfilemapd.c
++++ b/daemons/dmfilemapd/dmfilemapd.c
+@@ -266,8 +266,6 @@ static int _parse_args(int argc, char **argv, struct filemap_monitor *fm)
+ 		return 0;
+ 	}
+ 
+-	memset(fm, 0, sizeof(*fm));
+-
+ 	/*
+ 	 * We don't know the true nr_regions at daemon start time,
+ 	 * and it is not worth a dm_stats_list()/group walk to count:
+@@ -359,30 +357,33 @@ static int _parse_args(int argc, char **argv, struct filemap_monitor *fm)
+ 	return 1;
+ }
+ 
+-static int _filemap_fd_check_changed(struct filemap_monitor *fm)
++static int _filemap_fd_update_blocks(struct filemap_monitor *fm)
+ {
+-	int64_t blocks, old_blocks;
+ 	struct stat buf;
+ 
+ 	if (fm->fd < 0) {
+ 		log_error("Filemap fd is not open.");
+-		return -1;
++		return 0;
+ 	}
+ 
+ 	if (fstat(fm->fd, &buf)) {
+ 		log_error("Failed to fstat filemap file descriptor.");
+-		return -1;
++		return 0;
+ 	}
+ 
+-	blocks = buf.st_blocks;
++	fm->blocks = buf.st_blocks;
+ 
+-	/* first check? */
+-	if (fm->blocks < 0)
+-		old_blocks = buf.st_blocks;
+-	else
+-		old_blocks = fm->blocks;
++	return 1;
++}
++
++static int _filemap_fd_check_changed(struct filemap_monitor *fm)
++{
++	int64_t old_blocks;
++
++	old_blocks = fm->blocks;
+ 
+-	fm->blocks = blocks;
++	if (!_filemap_fd_update_blocks(fm))
++		return -1;
+ 
+ 	return (fm->blocks != old_blocks);
+ }
+@@ -564,6 +565,7 @@ static int _filemap_monitor_check_file_unlinked(struct filemap_monitor *fm)
+ 	ssize_t len;
+ 
+ 	fm->deleted = 0;
++	same = 0;
+ 
+ 	if ((fd = open(fm->path, O_RDONLY)) < 0)
+ 		goto check_unlinked;
+@@ -684,7 +686,10 @@ static int _update_regions(struct dm_stats *dms, struct filemap_monitor *fm)
+ 	for (region = regions; *region != DM_STATS_REGIONS_ALL; region++)
+ 		nr_regions++;
+ 
+-	if (regions[0] != fm->group_id) {
++	if (!nr_regions)
++		log_warn("File contains no extents: exiting.");
++
++	if (nr_regions && (regions[0] != fm->group_id)) {
+ 		log_warn("group_id changed from " FMTu64 " to " FMTu64,
+ 			 fm->group_id, regions[0]);
+ 		fm->group_id = regions[0];
+@@ -715,6 +720,9 @@ static int _dmfilemapd(struct filemap_monitor *fm)
+ 	if (!_filemap_monitor_set_notify(fm))
+ 		goto bad;
+ 
++	if (!_filemap_fd_update_blocks(fm))
++		goto bad;
++
+ 	if (!dm_stats_list(dms, DM_STATS_ALL_PROGRAMS)) {
+ 		log_error("Failed to list stats handle.");
+ 		goto bad;
+@@ -748,17 +756,16 @@ static int _dmfilemapd(struct filemap_monitor *fm)
+ 		if ((check = _filemap_fd_check_changed(fm)) < 0)
+ 			goto bad;
+ 
+-		if (!check)
+-			goto wait;
+-
+-		if (!_update_regions(dms, fm))
++		if (check && !_update_regions(dms, fm))
+ 			goto bad;
+ 
++		running = !!fm->nr_regions;
++		if (!running)
++			continue;
++
+ wait:
+ 		_filemap_monitor_wait(FILEMAPD_WAIT_USECS);
+ 
+-		running = !!fm->nr_regions;
+-
+ 		/* mode=inode termination condions */
+ 		if (fm->mode == DM_FILEMAPD_FOLLOW_INODE) {
+ 			if (!_filemap_monitor_check_file_unlinked(fm))
+@@ -801,6 +808,8 @@ int main(int argc, char **argv)
+ {
+ 	struct filemap_monitor fm;
+ 
++	memset(&fm, 0, sizeof(fm));
++
+ 	if (!_parse_args(argc, argv, &fm)) {
+ 		dm_free(fm.path);
+ 		return 1;
+diff --git a/daemons/lvmdbusd/automatedproperties.py b/daemons/lvmdbusd/automatedproperties.py
+index 68cea6e..e188fa4 100644
+--- a/daemons/lvmdbusd/automatedproperties.py
++++ b/daemons/lvmdbusd/automatedproperties.py
+@@ -100,7 +100,7 @@ class AutomatedProperties(dbus.service.Object):
+ 		raise dbus.exceptions.DBusException(
+ 			obj._ap_interface,
+ 			'The object %s does not implement the %s interface'
+-			% (self.__class__, interface_name))
++			% (obj.__class__, interface_name))
+ 
+ 	@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
+ 							in_signature='s', out_signature='a{sv}',
+diff --git a/daemons/lvmdbusd/background.py b/daemons/lvmdbusd/background.py
+index f7f77d5..90e8b68 100644
+--- a/daemons/lvmdbusd/background.py
++++ b/daemons/lvmdbusd/background.py
+@@ -9,12 +9,13 @@
+ 
+ import subprocess
+ from . import cfg
+-from .cmdhandler import options_to_cli_args
++from .cmdhandler import options_to_cli_args, LvmExecutionMeta
+ import dbus
+ from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug,\
+ 	add_no_notify
+ import os
+ import threading
++import time
+ 
+ 
+ def pv_move_lv_cmd(move_options, lv_full_name,
+@@ -47,6 +48,11 @@ def _move_merge(interface_name, command, job_state):
+ 	# Instruct lvm to not register an event with us
+ 	command = add_no_notify(command)
+ 
++	#(self, start, ended, cmd, ec, stdout_txt, stderr_txt)
++	meta = LvmExecutionMeta(time.time(), 0, command, -1000, None, None)
++
++	cfg.blackbox.add(meta)
++
+ 	process = subprocess.Popen(command, stdout=subprocess.PIPE,
+ 								env=os.environ,
+ 								stderr=subprocess.PIPE, close_fds=True)
+@@ -74,6 +80,11 @@ def _move_merge(interface_name, command, job_state):
+ 
+ 	out = process.communicate()
+ 
++	with meta.lock:
++		meta.ended = time.time()
++		meta.ec = process.returncode
++		meta.stderr_txt = out[1]
++
+ 	if process.returncode == 0:
+ 		job_state.Percent = 100
+ 	else:
+diff --git a/daemons/lvmdbusd/cmdhandler.py b/daemons/lvmdbusd/cmdhandler.py
+index 8ed38cb..4fb1670 100644
+--- a/daemons/lvmdbusd/cmdhandler.py
++++ b/daemons/lvmdbusd/cmdhandler.py
+@@ -37,6 +37,7 @@ cmd_lock = threading.RLock()
+ class LvmExecutionMeta(object):
+ 
+ 	def __init__(self, start, ended, cmd, ec, stdout_txt, stderr_txt):
++		self.lock = threading.RLock()
+ 		self.start = start
+ 		self.ended = ended
+ 		self.cmd = cmd
+@@ -45,12 +46,13 @@ class LvmExecutionMeta(object):
+ 		self.stderr_txt = stderr_txt
+ 
+ 	def __str__(self):
+-		return "EC= %d for %s\n" \
+-			"STARTED: %f, ENDED: %f\n" \
+-			"STDOUT=%s\n" \
+-			"STDERR=%s\n" % \
+-			(self.ec, str(self.cmd), self.start, self.ended, self.stdout_txt,
+-			self.stderr_txt)
++		with self.lock:
++			return "EC= %d for %s\n" \
++				"STARTED: %f, ENDED: %f\n" \
++				"STDOUT=%s\n" \
++				"STDERR=%s\n" % \
++				(self.ec, str(self.cmd), self.start, self.ended, self.stdout_txt,
++				self.stderr_txt)
+ 
+ 
+ class LvmFlightRecorder(object):
+@@ -618,10 +620,10 @@ def vg_reduce(vg_name, missing, pv_devices, reduce_options):
+ 	cmd = ['vgreduce']
+ 	cmd.extend(options_to_cli_args(reduce_options))
+ 
+-	if len(pv_devices) == 0:
+-		cmd.append('--all')
+ 	if missing:
+ 		cmd.append('--removemissing')
++	elif len(pv_devices) == 0:
++		cmd.append('--all')
+ 
+ 	cmd.append(vg_name)
+ 	cmd.extend(pv_devices)
+diff --git a/daemons/lvmdbusd/fetch.py b/daemons/lvmdbusd/fetch.py
+index 78c3a4b..c053685 100644
+--- a/daemons/lvmdbusd/fetch.py
++++ b/daemons/lvmdbusd/fetch.py
+@@ -82,10 +82,10 @@ class StateUpdate(object):
+ 
+ 	@staticmethod
+ 	def update_thread(obj):
++		queued_requests = []
+ 		while cfg.run.value != 0:
+ 			# noinspection PyBroadException
+ 			try:
+-				queued_requests = []
+ 				refresh = True
+ 				emit_signal = True
+ 				cache_refresh = True
+@@ -96,7 +96,7 @@ class StateUpdate(object):
+ 					wait = not obj.deferred
+ 					obj.deferred = False
+ 
+-				if wait:
++				if len(queued_requests) == 0 and wait:
+ 					queued_requests.append(obj.queue.get(True, 2))
+ 
+ 				# Ok we have one or the deferred queue has some,
+@@ -131,11 +131,17 @@ class StateUpdate(object):
+ 				for i in queued_requests:
+ 					i.set_result(num_changes)
+ 
++				# Only clear out the requests after we have given them a result
++				# otherwise we can orphan the waiting threads and they never
++				# wake up if we get an exception
++				queued_requests = []
++
+ 			except queue.Empty:
+ 				pass
+ 			except Exception:
+ 				st = traceback.format_exc()
+ 				log_error("update_thread exception: \n%s" % st)
++				cfg.blackbox.dump()
+ 
+ 	def __init__(self):
+ 		self.lock = threading.RLock()
+diff --git a/daemons/lvmdbusd/objectmanager.py b/daemons/lvmdbusd/objectmanager.py
+index a9d13a7..563b9ec 100644
+--- a/daemons/lvmdbusd/objectmanager.py
++++ b/daemons/lvmdbusd/objectmanager.py
+@@ -223,8 +223,9 @@ class ObjectManager(AutomatedProperties):
+ 		:param lvm_id: The lvm identifier
+ 		"""
+ 		with self.rlock:
+-			if lvm_id in self._id_to_object_path:
+-				return self.get_object_by_path(self._id_to_object_path[lvm_id])
++			lookup_rc = self._id_lookup(lvm_id)
++			if lookup_rc:
++				return self.get_object_by_path(lookup_rc)
+ 			return None
+ 
+ 	def get_object_path_by_lvm_id(self, lvm_id):
+@@ -234,8 +235,9 @@ class ObjectManager(AutomatedProperties):
+ 		:return: Object path or '/' if not found
+ 		"""
+ 		with self.rlock:
+-			if lvm_id in self._id_to_object_path:
+-				return self._id_to_object_path[lvm_id]
++			lookup_rc = self._id_lookup(lvm_id)
++			if lookup_rc:
++				return lookup_rc
+ 			return '/'
+ 
+ 	def _uuid_verify(self, path, uuid, lvm_id):
+diff --git a/daemons/lvmdbusd/utils.py b/daemons/lvmdbusd/utils.py
+index af9e10a..170824d 100644
+--- a/daemons/lvmdbusd/utils.py
++++ b/daemons/lvmdbusd/utils.py
+@@ -519,7 +519,9 @@ def add_no_notify(cmdline):
+ 		if '--config' in cmdline:
+ 			for i, arg in enumerate(cmdline):
+ 				if arg == '--config':
+-					cmdline[i] += "global/notify_dbus=0"
++					if len(cmdline) <= i+1:
++						raise dbus.exceptions.DBusException("Missing value for --config option.")
++					cmdline[i+1] += " global/notify_dbus=0"
+ 					break
+ 		else:
+ 			cmdline.extend(['--config', 'global/notify_dbus=0'])
+diff --git a/lib/activate/activate.c b/lib/activate/activate.c
+index a3978ad..282dd4f 100644
+--- a/lib/activate/activate.c
++++ b/lib/activate/activate.c
+@@ -835,7 +835,6 @@ int lv_info_with_seg_status(struct cmd_context *cmd,
+ 				 * When merge is in progress, query merging origin LV instead.
+ 				 * COW volume is already mapped as error target in this case.
+ 				 */
+-				status->lv = olv;
+ 				return 1;
+ 			}
+ 
+diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
+index 3b0eebb..40b64ab 100644
+--- a/lib/config/config_settings.h
++++ b/lib/config/config_settings.h
+@@ -469,8 +469,9 @@ cfg(allocation_mirror_logs_require_separate_pvs_CFG, "mirror_logs_require_separa
+ 
+ cfg(allocation_raid_stripe_all_devices_CFG, "raid_stripe_all_devices", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ALLOCATION_STRIPE_ALL_DEVICES, vsn(2, 2, 162), NULL, 0, NULL,
+ 	"Stripe across all PVs when RAID stripes are not specified.\n"
+-	"If enabled, all PVs in the VG or on the command line are used for raid0/4/5/6/10\n"
+-	"when the command does not specify the number of stripes to use.\n"
++	"If enabled, all PVs in the VG or on the command line are used for\n"
++	"raid0/4/5/6/10 when the command does not specify the number of\n"
++	"stripes to use.\n"
+ 	"This was the default behaviour until release 2.02.162.\n")
+ 
+ cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL,
+@@ -934,7 +935,7 @@ cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL,
+ 	"devices/global_filter.\n")
+ 
+ cfg(global_lvmetad_update_wait_time_CFG, "lvmetad_update_wait_time", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_LVMETAD_UPDATE_WAIT_TIME, vsn(2, 2, 151), NULL, 0, NULL,
+-	"The number of seconds a command will wait for lvmetad update to finish.\n"
++	"Number of seconds a command will wait for lvmetad update to finish.\n"
+ 	"After waiting for this period, a command will not use lvmetad, and\n"
+ 	"will revert to disk scanning.\n")
+ 
+diff --git a/lib/config/defaults.h b/lib/config/defaults.h
+index 65b81f1..d9e19d9 100644
+--- a/lib/config/defaults.h
++++ b/lib/config/defaults.h
+@@ -104,9 +104,9 @@
+ #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_MAX_METADATA_SIZE (16 * 1024 * 1024)  /* KB */
++#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_SIZE     (128 * 1024 * 1024)	/* KB */
++#define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */
+ #define DEFAULT_THIN_POOL_CHUNK_SIZE_POLICY "generic"
+ #define DEFAULT_THIN_POOL_CHUNK_SIZE	    64	  /* KB */
+ #define DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE 512 /* KB */
+diff --git a/lib/format_text/export.c b/lib/format_text/export.c
+index 473275d..f369089 100644
+--- a/lib/format_text/export.c
++++ b/lib/format_text/export.c
+@@ -358,11 +358,12 @@ static int _print_header(struct cmd_context *cmd, struct formatter *f,
+ static int _print_flag_config(struct formatter *f, uint64_t status, int type)
+ {
+ 	char buffer[4096];
+-	if (!print_flags(status, type | STATUS_FLAG, buffer, sizeof(buffer)))
++
++	if (!print_flags(buffer, sizeof(buffer), type, STATUS_FLAG, status))
+ 		return_0;
+ 	outf(f, "status = %s", buffer);
+ 
+-	if (!print_flags(status, type, buffer, sizeof(buffer)))
++	if (!print_flags(buffer, sizeof(buffer), type, COMPATIBLE_FLAG, status))
+ 		return_0;
+ 	outf(f, "flags = %s", buffer);
+ 
+@@ -501,7 +502,13 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
+  */
+ static const char *_get_pv_name_from_uuid(struct formatter *f, char *uuid)
+ {
+-	return dm_hash_lookup(f->pv_names, uuid);
++	const char *pv_name = dm_hash_lookup(f->pv_names, uuid);
++
++	if (!pv_name)
++		log_error(INTERNAL_ERROR "PV name for uuid %s missing from text metadata export hash table.",
++			  uuid);
++
++	return pv_name;
+ }
+ 
+ static const char *_get_pv_name(struct formatter *f, struct physical_volume *pv)
+@@ -577,6 +584,11 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
+ static int _print_segment(struct formatter *f, struct volume_group *vg,
+ 			  int count, struct lv_segment *seg)
+ {
++	char buffer[2048];
++
++	if (!print_segtype_lvflags(buffer, sizeof(buffer), seg->lv->status))
++		return_0;
++
+ 	outf(f, "segment%u {", count);
+ 	_inc_indent(f);
+ 
+@@ -587,7 +599,8 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
+ 	if (seg->reshape_len)
+ 		outsize(f, (uint64_t) seg->reshape_len * vg->extent_size,
+ 			"reshape_count = %u", seg->reshape_len);
+-	outf(f, "type = \"%s\"", seg->segtype->name);
++
++	outf(f, "type = \"%s%s\"", seg->segtype->name, buffer);
+ 
+ 	if (!_out_list(f, &seg->tags, "tags"))
+ 		return_0;
+@@ -607,6 +620,7 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
+ {
+ 	const char *name;
+ 	unsigned int s;
++	struct physical_volume *pv;
+ 
+ 	outnl(f);
+ 
+@@ -616,7 +630,13 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
+ 	for (s = 0; s < seg->area_count; s++) {
+ 		switch (seg_type(seg, s)) {
+ 		case AREA_PV:
+-			if (!(name = _get_pv_name(f, seg_pv(seg, s))))
++			if (!(pv = seg_pv(seg, s))) {
++				log_error(INTERNAL_ERROR "Missing PV for area %" PRIu32 " of %s segment of LV %s.",
++					  s, type, display_lvname(seg->lv));
++				return 0;
++			}
++				
++			if (!(name = _get_pv_name(f, pv)))
+ 				return_0;
+ 
+ 			outf(f, "\"%s\", %u%s", name,
+@@ -650,6 +670,8 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
+ 
+ 			break;
+ 		case AREA_UNASSIGNED:
++			log_error(INTERNAL_ERROR "Invalid type for area %" PRIu32 " of %s segment of LV %s.",
++				  s, type, display_lvname(seg->lv));
+ 			return 0;
+ 		}
+ 	}
+diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
+index a9f81f5..88fb091 100644
+--- a/lib/format_text/flags.c
++++ b/lib/format_text/flags.c
+@@ -47,6 +47,7 @@ static const struct flag _pv_flags[] = {
+ 	{ALLOCATABLE_PV, "ALLOCATABLE", STATUS_FLAG},
+ 	{EXPORTED_VG, "EXPORTED", STATUS_FLAG},
+ 	{MISSING_PV, "MISSING", COMPATIBLE_FLAG},
++	{MISSING_PV, "MISSING", STATUS_FLAG},
+ 	{UNLABELLED_PV, NULL, 0},
+ 	{0, NULL, 0}
+ };
+@@ -61,13 +62,14 @@ static const struct flag _lv_flags[] = {
+ 	{LOCKED, "LOCKED", STATUS_FLAG},
+ 	{LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
+ 	{LV_REBUILD, "REBUILD", STATUS_FLAG},
+-	{LV_RESHAPE_DELTA_DISKS_PLUS, "RESHAPE_DELTA_DISKS_PLUS", STATUS_FLAG},
+-	{LV_RESHAPE_DELTA_DISKS_MINUS, "RESHAPE_DELTA_DISKS_MINUS", STATUS_FLAG},
+-	{LV_REMOVE_AFTER_RESHAPE, "REMOVE_AFTER_RESHAPE", STATUS_FLAG},
++	{LV_RESHAPE, "RESHAPE", SEGTYPE_FLAG},
++	{LV_RESHAPE_DELTA_DISKS_PLUS, "RESHAPE_DELTA_DISKS_PLUS", SEGTYPE_FLAG},
++	{LV_RESHAPE_DELTA_DISKS_MINUS, "RESHAPE_DELTA_DISKS_MINUS", SEGTYPE_FLAG},
++	{LV_REMOVE_AFTER_RESHAPE, "REMOVE_AFTER_RESHAPE", SEGTYPE_FLAG},
+ 	{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
+ 	{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
+ 	{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
+-	{LV_METADATA_FORMAT, "METADATA_FORMAT", STATUS_FLAG},
++	{LV_METADATA_FORMAT, "METADATA_FORMAT", SEGTYPE_FLAG},
+ 	{LV_NOSCAN, NULL, 0},
+ 	{LV_TEMPORARY, NULL, 0},
+ 	{POOL_METADATA_SPARE, NULL, 0},
+@@ -101,9 +103,9 @@ static const struct flag _lv_flags[] = {
+ 	{0, NULL, 0}
+ };
+ 
+-static const struct flag *_get_flags(int type)
++static const struct flag *_get_flags(enum pv_vg_lv_e type)
+ {
+-	switch (type & ~STATUS_FLAG) {
++	switch (type) {
+ 	case VG_FLAGS:
+ 		return _vg_flags;
+ 
+@@ -114,7 +116,7 @@ static const struct flag *_get_flags(int type)
+ 		return _lv_flags;
+ 	}
+ 
+-	log_error("Unknown flag set requested.");
++	log_error(INTERNAL_ERROR "Unknown flag set requested.");
+ 	return NULL;
+ }
+ 
+@@ -123,7 +125,7 @@ static const struct flag *_get_flags(int type)
+  * using one of the tables defined at the top of
+  * the file.
+  */
+-int print_flags(uint64_t status, int type, char *buffer, size_t size)
++int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint64_t status)
+ {
+ 	int f, first = 1;
+ 	const struct flag *flags;
+@@ -132,13 +134,13 @@ int print_flags(uint64_t status, int type, char *buffer, size_t size)
+ 		return_0;
+ 
+ 	if (!emit_to_buffer(&buffer, &size, "["))
+-		return 0;
++		return_0;
+ 
+ 	for (f = 0; flags[f].mask; f++) {
+ 		if (status & flags[f].mask) {
+ 			status &= ~flags[f].mask;
+ 
+-			if ((type & STATUS_FLAG) != flags[f].kind)
++			if (mask != flags[f].kind)
+ 				continue;
+ 
+ 			/* Internal-only flag? */
+@@ -147,18 +149,18 @@ int print_flags(uint64_t status, int type, char *buffer, size_t size)
+ 
+ 			if (!first) {
+ 				if (!emit_to_buffer(&buffer, &size, ", "))
+-					return 0;
++					return_0;
+ 			} else
+ 				first = 0;
+ 	
+ 			if (!emit_to_buffer(&buffer, &size, "\"%s\"",
+-			    flags[f].description))
+-				return 0;
++					    flags[f].description))
++				return_0;
+ 		}
+ 	}
+ 
+ 	if (!emit_to_buffer(&buffer, &size, "]"))
+-		return 0;
++		return_0;
+ 
+ 	if (status)
+ 		log_warn(INTERNAL_ERROR "Metadata inconsistency: "
+@@ -167,9 +169,9 @@ int print_flags(uint64_t status, int type, char *buffer, size_t size)
+ 	return 1;
+ }
+ 
+-int read_flags(uint64_t *status, int type, const struct dm_config_value *cv)
++int read_flags(uint64_t *status, enum pv_vg_lv_e type, int mask, const struct dm_config_value *cv)
+ {
+-	int f;
++	unsigned f;
+ 	uint64_t s = UINT64_C(0);
+ 	const struct flag *flags;
+ 
+@@ -186,7 +188,8 @@ int read_flags(uint64_t *status, int type, const struct dm_config_value *cv)
+ 		}
+ 
+ 		for (f = 0; flags[f].description; f++)
+-			if (!strcmp(flags[f].description, cv->v.str)) {
++			if ((flags[f].kind & mask) &&
++			    !strcmp(flags[f].description, cv->v.str)) {
+ 				s |= flags[f].mask;
+ 				break;
+ 			}
+@@ -200,7 +203,7 @@ int read_flags(uint64_t *status, int type, const struct dm_config_value *cv)
+ 			 * by this case.
+ 			 */
+ 			s |= PARTIAL_VG;
+-		} else if (!flags[f].description && (type & STATUS_FLAG)) {
++		} else if (!flags[f].description && (mask & STATUS_FLAG)) {
+ 			log_error("Unknown status flag '%s'.", cv->v.str);
+ 			return 0;
+ 		}
+@@ -212,3 +215,71 @@ int read_flags(uint64_t *status, int type, const struct dm_config_value *cv)
+ 	*status |= s;
+ 	return 1;
+ }
++
++/*
++ * Parse extra status flags from segment "type" string.
++ * These flags are seen as INCOMPATIBLE by any older lvm2 code.
++ * All flags separated by '+' are trimmed from passed string.
++ * All UNKNOWN flags will again cause the "UNKNOWN" segtype.
++ *
++ * Note: using these segtype status flags instead of actual
++ * status flags ensures wanted incompatiblity.
++ */
++int read_segtype_lvflags(uint64_t *status, char *segtype_str)
++{
++	unsigned i;
++	const struct flag *flags = _lv_flags;
++	char *delim;
++	char *flag, *buffer, *str;
++
++	if (!(str = strchr(segtype_str, '+')))
++		return 1; /* No flags */
++
++	if (!(buffer = dm_strdup(str + 1))) {
++		log_error("Cannot duplicate segment string.");
++		return 0;
++	}
++
++	delim = buffer;
++
++	do {
++		flag = delim;
++		if ((delim = strchr(delim, '+')))
++			*delim++ = '\0';
++
++		for (i = 0; flags[i].description; i++)
++			if ((flags[i].kind & SEGTYPE_FLAG) &&
++			    !strcmp(flags[i].description, flag)) {
++				*status |= flags[i].mask;
++				break;
++			}
++
++	} while (delim && flags[i].description); /* Till no more flags in type appear */
++
++	if (!flags[i].description)
++		/* Unknown flag is incompatible - returns unmodified segtype_str */
++		log_warn("WARNING: Unrecognised flag %s in segment type %s.",
++			 flag, segtype_str);
++	else
++		*str = '\0'; /* Cut away 1st. '+' */
++
++	dm_free(buffer);
++
++	return 1;
++}
++
++int print_segtype_lvflags(char *buffer, size_t size, uint64_t status)
++{
++	unsigned i;
++	const struct flag *flags = _lv_flags;
++
++	buffer[0] = 0;
++	for (i = 0; flags[i].mask; i++)
++		if ((flags[i].kind & SEGTYPE_FLAG) &&
++		    (status & flags[i].mask) &&
++		    !emit_to_buffer(&buffer, &size, "+%s",
++				    flags[i].description))
++			return 0;
++
++	return 1;
++}
+diff --git a/lib/format_text/import-export.h b/lib/format_text/import-export.h
+index c081c51..4b47636 100644
+--- a/lib/format_text/import-export.h
++++ b/lib/format_text/import-export.h
+@@ -35,14 +35,16 @@
+  * VGs, PVs and LVs all have status bitsets, we gather together
+  * common code for reading and writing them.
+  */
+-enum {
+-	COMPATIBLE_FLAG = 0x0,
++enum pv_vg_lv_e {
++	PV_FLAGS = 1,
+ 	VG_FLAGS,
+-	PV_FLAGS,
+ 	LV_FLAGS,
+-	STATUS_FLAG = 0x8,
+ };
+ 
++#define COMPATIBLE_FLAG	0x01
++#define STATUS_FLAG	0x02
++#define SEGTYPE_FLAG	0x04
++
+ struct text_vg_version_ops {
+ 	int (*check_version) (const struct dm_config_tree * cf);
+ 	struct volume_group *(*read_vg) (struct format_instance * fid,
+@@ -58,8 +60,11 @@ struct text_vg_version_ops {
+ 
+ struct text_vg_version_ops *text_vg_vsn1_init(void);
+ 
+-int print_flags(uint64_t status, int type, char *buffer, size_t size);
+-int read_flags(uint64_t *status, int type, const struct dm_config_value *cv);
++int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint64_t status);
++int read_flags(uint64_t *status, enum pv_vg_lv_e type, int mask, const struct dm_config_value *cv);
++
++int print_segtype_lvflags(char *buffer, size_t size, uint64_t status);
++int read_segtype_lvflags(uint64_t *status, char *segtype_scr);
+ 
+ int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp);
+ size_t text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf);
+diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
+index e545008..7d9257e 100644
+--- a/lib/format_text/import_vsn1.c
++++ b/lib/format_text/import_vsn1.c
+@@ -140,13 +140,14 @@ static int _read_flag_config(const struct dm_config_node *n, uint64_t *status, i
+ 		return 0;
+ 	}
+ 
+-	if (!(read_flags(status, type | STATUS_FLAG, cv))) {
++	/* For backward compatible metadata accept both type of flags */
++	if (!(read_flags(status, type, STATUS_FLAG | SEGTYPE_FLAG, cv))) {
+ 		log_error("Could not read status flags.");
+ 		return 0;
+ 	}
+ 
+ 	if (dm_config_get_list(n, "flags", &cv)) {
+-		if (!(read_flags(status, type, cv))) {
++		if (!(read_flags(status, type, COMPATIBLE_FLAG, cv))) {
+ 			log_error("Could not read flags.");
+ 			return 0;
+ 		}
+@@ -357,6 +358,7 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
+ 	uint32_t area_extents, start_extent, extent_count, reshape_count, data_copies;
+ 	struct segment_type *segtype;
+ 	const char *segtype_str;
++	char *segtype_with_flags;
+ 
+ 	if (!sn_child) {
+ 		log_error("Empty segment section.");
+@@ -388,9 +390,24 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
+ 		return 0;
+ 	}
+ 
+-	if (!(segtype = get_segtype_from_string(lv->vg->cmd, segtype_str)))
++        /* Locally duplicate to parse out status flag bits */
++	if (!(segtype_with_flags = dm_pool_strdup(mem, segtype_str))) {
++		log_error("Cannot duplicate segtype string.");
++		return 0;
++	}
++
++	if (!read_segtype_lvflags(&lv->status, segtype_with_flags)) {
++		log_error("Couldn't read segtype for logical volume %s.",
++			  display_lvname(lv));
++	       return 0;
++	}
++
++	if (!(segtype = get_segtype_from_string(lv->vg->cmd, segtype_with_flags)))
+ 		return_0;
+ 
++	/* Can drop temporary string here as nothing has allocated from VGMEM meanwhile */
++	dm_pool_free(mem, segtype_with_flags);
++
+ 	if (segtype->ops->text_import_area_count &&
+ 	    !segtype->ops->text_import_area_count(sn_child, &area_count))
+ 		return_0;
+diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
+index 3d82a05..e642459 100644
+--- a/lib/metadata/merge.c
++++ b/lib/metadata/merge.c
+@@ -222,7 +222,7 @@ static void _check_non_raid_seg_members(struct lv_segment *seg, int *error_count
+ }
+ 
+ /*
+- * Check RAID segment sruct members of @seg for acceptable
++ * Check RAID segment struct members of @seg for acceptable
+  * properties and increment @error_count for any bogus ones.
+  */
+ static void _check_raid_seg(struct lv_segment *seg, int *error_count)
+diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
+index 8b4310b..c4bebd0 100644
+--- a/lib/metadata/metadata-exported.h
++++ b/lib/metadata/metadata-exported.h
+@@ -142,7 +142,10 @@
+ 
+ #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 */
+-/* Next unused flag:		UINT64_C(0x1000000000000000)    */
++
++#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 */
++/* Next unused flag:		UINT64_C(0x2000000000000000)    */
+ 
+ /* Format features flags */
+ #define FMT_SEGMENTS		0x00000001U	/* Arbitrary segment params? */
+diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
+index 1b500ed..4ba81c7 100644
+--- a/lib/metadata/metadata.c
++++ b/lib/metadata/metadata.c
+@@ -1089,8 +1089,7 @@ static struct volume_group *_vg_make_handle(struct cmd_context *cmd,
+ 	if (!vg && !(vg = alloc_vg("vg_make_handle", cmd, NULL)))
+ 		return_NULL;
+ 
+-	if (vg->read_status != failure)
+-		vg->read_status = failure;
++	vg->read_status = failure;
+ 
+ 	if (vg->fid && !_vg_update_vg_committed(vg))
+ 		vg->read_status |= FAILED_ALLOCATION;
+@@ -1122,6 +1121,7 @@ int vg_has_unknown_segments(const struct volume_group *vg)
+ struct volume_group *vg_lock_and_create(struct cmd_context *cmd, const char *vg_name)
+ {
+ 	uint32_t rc;
++	struct volume_group *vg;
+ 
+ 	if (!validate_name(vg_name)) {
+ 		log_error("Invalid vg name %s", vg_name);
+@@ -1134,7 +1134,11 @@ struct volume_group *vg_lock_and_create(struct cmd_context *cmd, const char *vg_
+ 		/* NOTE: let caller decide - this may be check for existence */
+ 		return _vg_make_handle(cmd, NULL, rc);
+ 
+-	return vg_create(cmd, vg_name);
++	vg = vg_create(cmd, vg_name);
++	if (!vg || vg_read_error(vg))
++		unlock_vg(cmd, NULL, vg_name);
++
++	return vg;
+ }
+ 
+ /*
+@@ -3707,6 +3711,37 @@ struct _vg_read_orphan_baton {
+ 	int repair;
+ };
+ 
++/*
++ * If we know that the PV is orphan, meaning there's at least one MDA on
++ * that PV which does not reference any VG and at the same time there's
++ * PV_EXT_USED flag set, we're certainly in an inconsistent state and we
++ * need to fix this.
++ *
++ * For example, such situation can happen during vgremove/vgreduce if we
++ * removed/reduced the VG, but we haven't written PV headers yet because
++ * vgremove stopped abruptly for whatever reason just before writing new
++ * PV headers with updated state, including PV extension flags (and so the
++ * PV_EXT_USED flag).
++ *
++ * However, in case the PV has no MDAs at all, we can't double-check
++ * whether the PV_EXT_USED is correct or not - if that PV is marked
++ * as used, it's either:
++ *  - really used (but other disks with MDAs are missing)
++ *  - or the error state as described above is hit
++ *
++ * User needs to overwrite the PV header directly if it's really clear
++ * the PV having no MDAs does not belong to any VG and at the same time
++ * it's still marked as being in use (pvcreate -ff <dev_name> will fix this).
++ *
++ * Note that the above doesn't account for the case where the PV has
++ * VG metadata that fails to be parsed.  In that case, the PV looks
++ * like an in-use orphan, and is auto-repaired here.  A PV with
++ * unparsable metadata should be kept on a special list of devices
++ * (like duplicate PVs) that are not auto-repaired, cannot be used
++ * by pvcreate, and are displayed with a special flag by 'pvs'.
++ */
++
++#if 0
+ static int _check_or_repair_orphan_pv_ext(struct physical_volume *pv,
+ 					  struct lvmcache_info *info,
+ 					  struct _vg_read_orphan_baton *b)
+@@ -3760,12 +3795,15 @@ static int _check_or_repair_orphan_pv_ext(struct physical_volume *pv,
+ 
+ 	return 1;
+ }
++#endif
+ 
+ static int _vg_read_orphan_pv(struct lvmcache_info *info, void *baton)
+ {
+ 	struct _vg_read_orphan_baton *b = baton;
+ 	struct physical_volume *pv = NULL;
+ 	struct pv_list *pvl;
++	uint32_t ext_version;
++	uint32_t ext_flags;
+ 
+ 	if (!(pv = _pv_read(b->vg->cmd, b->vg->vgmem, dev_name(lvmcache_device(info)),
+ 			    b->vg->fid, b->warn_flags, 0))) {
+@@ -3781,10 +3819,59 @@ static int _vg_read_orphan_pv(struct lvmcache_info *info, void *baton)
+ 	pvl->pv = pv;
+ 	add_pvl_to_vgs(b->vg, pvl);
+ 
++	/*
++	 * FIXME: this bit of code that does the auto repair is disabled
++	 * until we can distinguish cases where the repair should not
++	 * happen, i.e. the VG metadata could not be read/parsed.
++	 *
++	 * A PV holding VG metadata that lvm can't understand
++	 * (e.g. damaged, checksum error, unrecognized flag)
++	 * will appear as an in-use orphan, and would be cleared
++	 * by this repair code.  Disable this repair until the
++	 * code can keep track of these problematic PVs, and
++	 * distinguish them from actual in-use orphans.
++	 */
++
++	/*
+ 	if (!_check_or_repair_orphan_pv_ext(pv, info, baton)) {
+ 		stack;
+ 		return 0;
+ 	}
++	*/
++
++	/*
++	 * Nothing to do if PV header extension < 2:
++	 *  - version 0 is PV header without any extensions,
++	 *  - version 1 has bootloader area support only and
++	 *    we're not checking anything for that one here.
++	 */
++	ext_version = lvmcache_ext_version(info);
++	ext_flags = lvmcache_ext_flags(info);
++
++	/*
++	 * Warn about a PV that has the in-use flag set, but appears in
++	 * the orphan VG (no VG was found referencing it.)
++	 * There are a number of conditions that could lead to this:
++	 *
++	 * . The PV was created with no mdas and is used in a VG with
++	 * other PVs (with metadata) that have not yet appeared on
++	 * the system.  So, no VG metadata is found by lvm which
++	 * references the in-use PV with no mdas.
++	 *
++	 * . vgremove could have failed after clearing mdas but
++	 * before clearing the in-use flag.  In this case, the
++	 * in-use flag needs to be manually cleared on the PV.
++	 *
++	 * . The PV may have damanged/unrecognized VG metadata
++	 * that lvm could not read.
++	 *
++	 * . The PV may have no mdas, and the PVs with the metadata
++	 * may have damaged/unrecognized metadata.
++	 */
++	if ((ext_version >= 2) && (ext_flags & PV_EXT_USED)) {
++		log_warn("WARNING: PV %s is marked in use but no VG was found using it.", pv_dev_name(pv));
++		log_warn("WARNING: PV %s might need repairing.", pv_dev_name(pv));
++	}
+ 
+ 	return 1;
+ }
+@@ -3910,7 +3997,13 @@ static int _check_reappeared_pv(struct volume_group *correct_vg,
+          * confusing.
+          */
+         if (correct_vg->cmd->handles_missing_pvs)
+-            return rv;
++		return rv;
++
++	/*
++	 * Skip this if there is no underlying device present for this PV.
++	 */
++	if (!pv->dev)
++		return rv;
+ 
+ 	dm_list_iterate_items(pvl, &correct_vg->pvs)
+ 		if (pv->dev == pvl->pv->dev && is_missing_pv(pvl->pv)) {
+@@ -4039,6 +4132,7 @@ static int _check_or_repair_pv_ext(struct cmd_context *cmd,
+ 				   struct volume_group *vg,
+ 				   int repair, int *inconsistent_pvs)
+ {
++	char uuid[64] __attribute__((aligned(8)));
+ 	struct lvmcache_info *info;
+ 	uint32_t ext_version, ext_flags;
+ 	struct pv_list *pvl;
+@@ -4052,6 +4146,14 @@ static int _check_or_repair_pv_ext(struct cmd_context *cmd,
+ 		if (is_missing_pv(pvl->pv))
+ 			continue;
+ 
++		if (!pvl->pv->dev) {
++			/* is_missing_pv doesn't catch NULL dev */
++			memset(&uuid, 0, sizeof(uuid));
++			id_write_format(&pvl->pv->id, uuid, sizeof(uuid));
++			log_warn("WARNING: Not repairing PV %s with missing device.", uuid);
++			continue;
++		}
++
+ 		if (!(info = lvmcache_info_from_pvid(pvl->pv->dev->pvid, pvl->pv->dev, 0))) {
+ 			log_error("Failed to find cached info for PV %s.", pv_dev_name(pvl->pv));
+ 			goto out;
+@@ -4165,8 +4267,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
+ 	if (lvmetad_used() && !use_precommitted) {
+ 		if ((correct_vg = lvmcache_get_vg(cmd, vgname, vgid, precommitted))) {
+ 			dm_list_iterate_items(pvl, &correct_vg->pvs)
+-				if (pvl->pv->dev)
+-					reappeared += _check_reappeared_pv(correct_vg, pvl->pv, *consistent);
++				reappeared += _check_reappeared_pv(correct_vg, pvl->pv, *consistent);
+ 			if (reappeared && *consistent)
+ 				*consistent = _repair_inconsistent_vg(correct_vg);
+ 			else
+@@ -5863,7 +5964,11 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
+ 	if (failure)
+ 		goto_bad;
+ 
+-	return _vg_make_handle(cmd, vg, failure);
++	if (!(vg = _vg_make_handle(cmd, vg, failure)) || vg_read_error(vg))
++		if (!already_locked)
++			unlock_vg(cmd, vg, vg_name);
++
++	return vg;
+ 
+ bad:
+ 	if (!already_locked)
+@@ -5924,7 +6029,12 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg_read_for_update(struct cmd_context *cmd, const char *vg_name,
+ 			 const char *vgid, uint32_t read_flags, uint32_t lockd_state)
+ {
+-	return vg_read(cmd, vg_name, vgid, read_flags | READ_FOR_UPDATE, lockd_state);
++	struct volume_group *vg = vg_read(cmd, vg_name, vgid, read_flags | READ_FOR_UPDATE, lockd_state);
++
++	if (!vg || vg_read_error(vg))
++		stack;
++
++	return vg;
+ }
+ 
+ /*
+@@ -5953,9 +6063,8 @@ uint32_t vg_read_error(struct volume_group *vg_handle)
+  */
+ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)
+ {
+-	if (!lock_vol(cmd, vgname, LCK_VG_WRITE, NULL)) {
++	if (!lock_vol(cmd, vgname, LCK_VG_WRITE, NULL))
+ 		return FAILED_LOCKING;
+-	}
+ 
+ 	/* Find the vgname in the cache */
+ 	/* If it's not there we must do full scan to be completely sure */
+diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
+index b708442..52def78 100644
+--- a/lib/metadata/raid_manip.c
++++ b/lib/metadata/raid_manip.c
+@@ -57,6 +57,25 @@ static int _reshape_is_supported(struct cmd_context *cmd, const struct segment_t
+ }
+ 
+ /*
++ * Check if rebuild CTR args are allowed when other images exist in the array
++ * with empty metadata areas for this kernel.
++ */
++static int _rebuild_with_emptymeta_is_supported(struct cmd_context *cmd,
++						const struct segment_type *segtype)
++{
++	unsigned attrs;
++
++	if (!segtype->ops->target_present ||
++            !segtype->ops->target_present(cmd, NULL, &attrs) ||
++            !(attrs & RAID_FEATURE_NEW_DEVICES_ACCEPT_REBUILD)) {
++		log_verbose("RAID module does not support rebuild+emptymeta.");
++		return 0;
++	}
++
++	return 1;
++}
++
++/*
+  * Ensure region size exceeds the minimum for @lv because
+  * MD's bitmap is limited to tracking 2^21 regions.
+  *
+@@ -285,6 +304,17 @@ static int _deactivate_and_remove_lvs(struct volume_group *vg, struct dm_list *r
+ 	struct lv_list *lvl;
+ 
+ 	dm_list_iterate_items(lvl, removal_lvs) {
++		if (!lv_is_visible(lvl->lv)) {
++			log_error(INTERNAL_ERROR
++				  "LVs must be set visible before removing.");
++			return 0;
++		}
++		/* Got to get any cluster lock an SubLVs to be removed. */
++		if (!activate_lv_excl_local(vg->cmd, lvl->lv))
++			return_0;
++	}
++
++	dm_list_iterate_items(lvl, removal_lvs) {
+ 		if (!deactivate_lv(vg->cmd, lvl->lv))
+ 			return_0;
+ 		if (!lv_remove(lvl->lv))
+@@ -379,23 +409,6 @@ int lv_raid_in_sync(const struct logical_volume *lv)
+ 	return _raid_in_sync(lv);
+ }
+ 
+-/* Check if RaidLV @lv is synced or any raid legs of @lv are not synced */
+-static int _raid_devs_sync_healthy(struct logical_volume *lv)
+-{
+-	char *raid_health;
+-
+-	if (!_raid_in_sync(lv))
+-		return 0;
+-
+-	if (!seg_is_raid1(first_seg(lv)))
+-		return 1;
+-
+-	if (!lv_raid_dev_health(lv, &raid_health))
+-		return_0;
+-
+-	return (strchr(raid_health, 'a') || strchr(raid_health, 'D')) ? 0 : 1;
+-}
+-
+ /*
+  * _raid_remove_top_layer
+  * @lv
+@@ -427,8 +440,10 @@ static int _raid_remove_top_layer(struct logical_volume *lv,
+ 		return 0;
+ 	}
+ 
+-	if (!(lvl_array = dm_pool_alloc(lv->vg->vgmem, 2 * sizeof(*lvl))))
++	if (!(lvl_array = dm_pool_alloc(lv->vg->vgmem, 2 * sizeof(*lvl)))) {
++		log_error("Memory allocation failed.");
+ 		return_0;
++	}
+ 
+ 	/* Add last metadata area to removal_lvs */
+ 	lvl_array[0].lv = seg_metalv(seg, 0);
+@@ -786,8 +801,10 @@ static int _reorder_raid10_near_seg_areas(struct lv_segment *seg, enum raid0_rai
+ 	/* FIXME: once more data copies supported with raid10 */
+ 	stripes /= data_copies;
+ 
+-	if (!(idx = dm_pool_zalloc(seg_lv(seg, 0)->vg->vgmem, seg->area_count * sizeof(*idx))))
+-		return 0;
++	if (!(idx = dm_pool_zalloc(seg_lv(seg, 0)->vg->vgmem, seg->area_count * sizeof(*idx)))) {
++		log_error("Memory allocation failed.");
++		return_0;
++	}
+ 
+ 	/* Set up positional index array */
+ 	switch (conv) {
+@@ -1056,8 +1073,10 @@ static int _alloc_image_components(struct logical_volume *lv,
+ 	const char *raid_segtype;
+ 
+ 	if (!(lvl_array = dm_pool_alloc(lv->vg->vgmem,
+-					sizeof(*lvl_array) * count * 2)))
++					sizeof(*lvl_array) * count * 2))) {
++		log_error("Memory allocation failed.");
+ 		return_0;
++	}
+ 
+ 	if (!(parallel_areas = build_parallel_areas_from_lv(lv, 0, 1)))
+ 		return_0;
+@@ -1250,6 +1269,10 @@ static int _cmp_level(const struct segment_type *t1, const struct segment_type *
+ 	    (!segtype_is_any_raid10(t1) && segtype_is_any_raid10(t2)))
+ 		return 0;
+ 
++	if ((segtype_is_raid4(t1) && segtype_is_raid5_n(t2)) ||
++	    (segtype_is_raid5_n(t1) && segtype_is_raid4(t2)))
++		return 1;
++
+ 	return !strncmp(t1->name, t2->name, 5);
+ }
+ 
+@@ -1627,6 +1650,8 @@ static int _lv_free_reshape_space_with_status(struct logical_volume *lv, enum al
+ 	} else if (where_it_was)
+ 		*where_it_was = alloc_none;
+ 
++	lv->status &= ~LV_RESHAPE;
++
+ 	return 1;
+ }
+ 
+@@ -1834,6 +1859,9 @@ static int _raid_reshape_add_images(struct logical_volume *lv,
+ 
+ 	seg->stripe_size = new_stripe_size;
+ 
++	/* Define image adding reshape (used as SEGTYPE_FLAG to avoid incompatible activations on old runtime) */
++	lv->status |= LV_RESHAPE;
++
+ 	return 1;
+ }
+ 
+@@ -1933,6 +1961,8 @@ static int _raid_reshape_remove_images(struct logical_volume *lv,
+ 		if (seg_is_any_raid5(seg) && new_image_count == 2)
+ 			seg->data_copies = 2;
+ 
++		/* Define image removing reshape (used as SEGTYPE_FLAG to avoid incompatible activations on old runtime) */
++		lv ->status |= LV_RESHAPE;
+ 		break;
+ 
+ 	case 1:
+@@ -1971,7 +2001,6 @@ static int _raid_reshape_remove_images(struct logical_volume *lv,
+ 			return 0;
+ 
+ 		seg->area_count = new_image_count;
+-
+ 		break;
+ 
+ 	default:
+@@ -1986,10 +2015,11 @@ static int _raid_reshape_remove_images(struct logical_volume *lv,
+ /*
+  * HM Helper:
+  *
+- * Reshape: keep images in RAID @lv but change stripe size or data copies
++ * Reshape: keep images in RAID @lv but change layout, stripe size or data copies
+  *
+  */
+ static const char *_get_segtype_alias(const struct segment_type *segtype);
++static const char *_get_segtype_alias_str(const struct logical_volume *lv, const struct segment_type *segtype);
+ static int _raid_reshape_keep_images(struct logical_volume *lv,
+ 				     const struct segment_type *new_segtype,
+ 				     int yes, int force, int *force_repair,
+@@ -2001,10 +2031,13 @@ static int _raid_reshape_keep_images(struct logical_volume *lv,
+ 	struct lv_segment *seg = first_seg(lv);
+ 
+ 	if (seg->segtype != new_segtype)
+-		log_print_unless_silent("Converting %s LV %s to %s.",
+-					lvseg_name(seg), display_lvname(lv), new_segtype->name);
+-	if (!yes && yes_no_prompt("Are you sure you want to convert %s LV %s to %s? [y/n]: ",
+-				  lvseg_name(seg), display_lvname(lv), new_segtype->name) == 'n') {
++		log_print_unless_silent("Converting %s%s LV %s to %s%s.",
++					lvseg_name(seg), _get_segtype_alias_str(lv, seg->segtype),
++					display_lvname(lv), new_segtype->name,
++					_get_segtype_alias_str(lv, new_segtype));
++
++	if (!yes && yes_no_prompt("Are you sure you want to convert %s LV %s? [y/n]: ",
++				  lvseg_name(seg), display_lvname(lv)) == 'n') {
+ 			log_error("Logical volume %s NOT converted.", display_lvname(lv));
+ 			return 0;
+ 	}
+@@ -2022,12 +2055,9 @@ static int _raid_reshape_keep_images(struct logical_volume *lv,
+ 	 * The dm-raid target is able to use the space whereever it
+ 	 * is found by appropriately selecting forward or backward reshape.
+ 	 */
+-	if (seg->segtype != new_segtype) {
+-		const char *alias = _get_segtype_alias(seg->segtype);
+-
+-		if (!strcmp(alias, new_segtype->name))
+-			alloc_reshape_space = 0;
+-	}
++	if (seg->segtype != new_segtype &&
++	    !strcmp(_get_segtype_alias(seg->segtype), new_segtype->name))
++		alloc_reshape_space = 0;
+ 
+ 	if (seg->stripe_size != new_stripe_size)
+ 		alloc_reshape_space = 1;
+@@ -2043,6 +2073,9 @@ static int _raid_reshape_keep_images(struct logical_volume *lv,
+ 
+ 	seg->segtype = new_segtype;
+ 
++	/* Define stripesize/raid algorithm reshape (used as SEGTYPE_FLAG to avoid incompatible activations on old runtime) */
++	lv->status |= LV_RESHAPE;
++
+ 	return 1;
+ }
+ 
+@@ -2226,6 +2259,8 @@ static int _raid_reshape(struct logical_volume *lv,
+ 		return 0;
+ 	}
+ 
++	lv->status &= ~LV_RESHAPE; /* Reset any reshaping segtype flag */
++
+ 	dm_list_init(&removal_lvs);
+ 
+ 	/* No change in layout requested ? */
+@@ -2311,6 +2346,12 @@ static int _raid_reshape(struct logical_volume *lv,
+ 
+ 	/* Handle disk addition reshaping */
+ 	if (old_image_count < new_image_count) {
++		/* FIXME: remove once MD kernel rhbz1443999 got fixed. */
++		if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
++			log_error("Can't add stripes to LV %s on single core.", display_lvname(lv));
++			return 0;
++		}
++
+ 		if (!_raid_reshape_add_images(lv, new_segtype, yes,
+ 					      old_image_count, new_image_count,
+ 					      new_stripes, new_stripe_size, allocate_pvs))
+@@ -2318,6 +2359,12 @@ static int _raid_reshape(struct logical_volume *lv,
+ 
+ 	/* Handle disk removal reshaping */
+ 	} else if (old_image_count > new_image_count) {
++		/* FIXME: remove once MD kernel rhbz1443999 got fixed. */
++		if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
++			log_error("Can't remove stripes from LV %s on single core.", display_lvname(lv));
++			return 0;
++		}
++
+ 		if (!_raid_reshape_remove_images(lv, new_segtype, yes, force,
+ 						 old_image_count, new_image_count,
+ 						 new_stripes, new_stripe_size,
+@@ -2505,6 +2552,7 @@ static int _raid_add_images_without_commit(struct logical_volume *lv,
+ 	struct dm_list meta_lvs, data_lvs;
+ 	struct lv_list *lvl;
+ 	struct lv_segment_area *new_areas;
++	struct segment_type *segtype;
+ 
+ 	if (lv_is_not_synced(lv)) {
+ 		log_error("Can't add image to out-of-sync RAID LV:"
+@@ -2536,8 +2584,19 @@ static int _raid_add_images_without_commit(struct logical_volume *lv,
+ 	 * LV to accompany it.
+ 	 */
+ 	if (seg_is_linear(seg)) {
+-		/* A complete resync will be done, no need to mark each sub-lv */
+-		status_mask = ~(LV_REBUILD);
++		/*
++		 * As of dm-raid version 1.9.0, it is possible to specify
++		 * RAID table lines with the 'rebuild' parameters necessary
++		 * to force a "recover" instead of a "resync" on upconvert.
++		 *
++		 * LVM's interaction with older kernels should be as before -
++		 * performing a complete resync rather than a set of rebuilds.
++		 */
++		if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_RAID1)))
++			return_0;
++
++		if (!_rebuild_with_emptymeta_is_supported(lv->vg->cmd, segtype))
++			status_mask = ~(LV_REBUILD);
+ 
+ 		/* FIXME: allow setting region size on upconvert from linear */
+ 		seg->region_size = get_default_region_size(lv->vg->cmd);
+@@ -2803,6 +2862,87 @@ static int _extract_image_components(struct lv_segment *seg, uint32_t idx,
+ }
+ 
+ /*
++ * _raid_allow_extraction
++ * @lv
++ * @extract_count
++ * @target_pvs
++ *
++ * returns: 0 if no, 1 if yes
++ */
++static int _raid_allow_extraction(struct logical_volume *lv,
++				  int extract_count,
++				  struct dm_list *target_pvs)
++{
++	int s, redundancy = 0;
++	char *dev_health;
++	char *sync_action;
++	struct lv_segment *seg = first_seg(lv);
++	struct cmd_context *cmd = lv->vg->cmd;
++
++	/* If in-sync or hanlding repairs, allow to proceed. */
++	if (_raid_in_sync(lv) || lv->vg->cmd->handles_missing_pvs)
++		return 1;
++
++	/*
++	 * FIXME:
++	 * Right now, we are primarily concerned with down-converting of
++	 * RAID1 LVs, but parity RAIDs and RAID10 will also have to be
++	 * considered.
++	 * (e.g. It would not be good to allow extracting a dev from a
++	 * stripe set while upconverting to RAID5/6.)
++	 */
++	if (!segtype_is_raid1(seg->segtype))
++		return 1;
++
++	/*
++	 * We can allow extracting images if the array is performing a
++	 * sync operation as long as it is "recover" and the image is not
++	 * a primary image or if "resync".
++	 */
++	if (!lv_raid_sync_action(lv, &sync_action) ||
++	    !lv_raid_dev_health(lv, &dev_health))
++		return_0;
++
++	if (!strcmp("idle", sync_action)) {
++		log_error(INTERNAL_ERROR
++			  "RAID LV should not be out-of-sync and \"idle\"");
++		return 0;
++	}
++
++	if (!strcmp("resync", sync_action))
++		return 1;
++
++	/* If anything other than "recover" */
++	if (strcmp("recover", sync_action)) {
++		log_error("Unable to remove RAID image while array"
++			  " is performing \"%s\"", sync_action);
++		return 0;
++	}
++
++	if (seg->area_count != strlen(dev_health)) {
++		log_error(INTERNAL_ERROR
++			  "RAID LV area_count differs from number of health characters");
++		return 0;
++	}
++
++	for (s = 0; s < seg->area_count; s++)
++		if (dev_health[s] == 'A')
++			redundancy++;
++
++	for (s = 0; (s < seg->area_count) && extract_count; s++) {
++		if (!lv_is_on_pvs(seg_lv(seg, s), target_pvs) &&
++		    !lv_is_on_pvs(seg_metalv(seg, s), target_pvs))
++			continue;
++		if ((dev_health[s] == 'A') && !--redundancy) {
++			log_error("Unable to remove all primary source devices");
++			return 0;
++		}
++		extract_count--;
++	}
++	return 1;
++}
++
++/*
+  * _raid_extract_images
+  * @lv
+  * @force: force a replacement in case of primary mirror leg
+@@ -2833,6 +2973,10 @@ static int _raid_extract_images(struct logical_volume *lv,
+ 	struct segment_type *error_segtype;
+ 
+ 	extract = seg->area_count - new_count;
++
++	if (!_raid_allow_extraction(lv, extract, target_pvs))
++		return_0;
++
+ 	log_verbose("Extracting %u %s from %s.", extract,
+ 		    (extract > 1) ? "images" : "image",
+ 		    display_lvname(lv));
+@@ -2888,20 +3032,8 @@ static int _raid_extract_images(struct logical_volume *lv,
+ 			if (!lv_is_on_pvs(seg_lv(seg, s), target_pvs) &&
+ 			    !lv_is_on_pvs(seg_metalv(seg, s), target_pvs))
+ 				continue;
+-
+-			/*
+-			 * Kernel may report raid LV in-sync but still
+-			 * image devices may not be in-sync or faulty.
+-			 */
+-			if (!_raid_devs_sync_healthy(lv) &&
+-			    (!seg_is_mirrored(seg) || (s == 0 && !force))) {
+-				log_error("Unable to extract %sRAID image"
+-					  " while RAID array is not in-sync%s.",
+-					  seg_is_mirrored(seg) ? "primary " : "",
+-					  seg_is_mirrored(seg) ? " (use --force option to replace)" : "");
+-				return 0;
+-			}
+ 		}
++
+ 		if (!_extract_image_components(seg, s, &rmeta_lv, &rimage_lv)) {
+ 			log_error("Failed to extract %s from %s.",
+ 				  display_lvname(seg_lv(seg, s)),
+@@ -3035,6 +3167,13 @@ int lv_raid_change_image_count(struct logical_volume *lv, int yes, uint32_t new_
+ 	const char *level = seg->area_count == 1 ? "raid1 with " : "";
+ 	const char *resil = new_count < seg->area_count ? "reducing" : "enhancing";
+ 
++	/* LV must be active to perform raid conversion operations */
++	if (!lv_is_active(lv)) {
++		log_error("%s must be active to perform this operation.",
++			  display_lvname(lv));
++		return 0;
++	}
++
+ 	if (new_count != 1 && /* Already prompted for in _raid_remove_images() */
+ 	    !yes && yes_no_prompt("Are you sure you want to convert %s LV %s to %s%u images %s resilience? [y/n]: ",
+ 				  lvseg_name(first_seg(lv)), display_lvname(lv), level, new_count, resil) == 'n') {
+@@ -4437,6 +4576,7 @@ static int _log_possible_conversion(uint64_t *processed_segtypes, void *data)
+ 	return 1;
+ }
+ 
++/* Return any segment type alias name for @segtype or empty string */
+ static const char *_get_segtype_alias(const struct segment_type *segtype)
+ {
+ 	if (!strcmp(segtype->name, SEG_TYPE_NAME_RAID5))
+@@ -4460,12 +4600,28 @@ static const char *_get_segtype_alias(const struct segment_type *segtype)
+ 	return "";
+ }
+ 
++/* Return any segment type alias string (format " (same as raid*)") for @segtype or empty string */
++static const char *_get_segtype_alias_str(const struct logical_volume *lv, const struct segment_type *segtype)
++{
++	const char *alias = _get_segtype_alias(segtype);
++
++	if (*alias) {
++		const char *msg = " (same as ";
++		size_t sz = strlen(msg) + strlen(alias) + 2;
++		char *buf = dm_pool_alloc(lv->vg->cmd->mem, sz);
++
++		if (buf)
++			alias = (dm_snprintf(buf, sz, "%s%s)", msg, alias) < 0) ? "" : buf;
++	}
++
++	return alias;
++}
++
+ static int _log_possible_conversion_types(const struct logical_volume *lv, const struct segment_type *new_segtype)
+ {
+ 	unsigned possible_conversions = 0;
+ 	const struct lv_segment *seg = first_seg(lv);
+ 	struct possible_type *pt = NULL;
+-	const char *alias;
+ 	uint64_t processed_segtypes = UINT64_C(0);
+ 
+ 	/* Count any possible segment types @seg an be directly converted to */
+@@ -4476,12 +4632,10 @@ static int _log_possible_conversion_types(const struct logical_volume *lv, const
+ 	if (!possible_conversions)
+ 		log_error("Direct conversion of %s LV %s is not possible.", lvseg_name(seg), display_lvname(lv));
+ 	else {
+-			alias = _get_segtype_alias(seg->segtype);
+-
+-			log_error("Converting %s from %s%s%s%s is "
++			log_error("Converting %s from %s%s is "
+ 				  "directly possible to the following layout%s:",
+ 				  display_lvname(lv), lvseg_name(seg),
+-				  *alias ? " (same as " : "", alias, *alias ? ")" : "",
++				  _get_segtype_alias_str(lv, seg->segtype),
+ 				  possible_conversions > 1 ? "s" : "");
+ 
+ 			pt = NULL;
+@@ -4526,10 +4680,16 @@ static int _takeover_noop(TAKEOVER_FN_ARGS)
+ 
+ static int _takeover_unsupported(TAKEOVER_FN_ARGS)
+ {
+-	log_error("Converting the segment type for %s from %s to %s is not supported.",
+-		  display_lvname(lv), lvseg_name(first_seg(lv)),
+-		  (segtype_is_striped_target(new_segtype) &&
+-		   (new_stripes == 1)) ? SEG_TYPE_NAME_LINEAR : new_segtype->name);
++	struct lv_segment *seg = first_seg(lv);
++
++	if (seg->segtype == new_segtype)
++		log_error("Logical volume %s already is type %s.",
++			  display_lvname(lv), lvseg_name(seg));
++	else
++		log_error("Converting the segment type for %s from %s to %s is not supported.",
++			  display_lvname(lv), lvseg_name(seg),
++			  (segtype_is_striped_target(new_segtype) &&
++			  (new_stripes == 1)) ? SEG_TYPE_NAME_LINEAR : new_segtype->name);
+ 
+ 	if (!_log_possible_conversion_types(lv, new_segtype))
+ 		stack;
+@@ -4749,9 +4909,6 @@ static int _rename_area_lvs(struct logical_volume *lv, const char *suffix)
+ 			return_0;
+ 	}
+ 
+-	for (s = 0; s < SLV_COUNT; s++)
+-		dm_pool_free(lv->vg->cmd->mem, sfx[s]);
+-
+ 	return 1;
+ }
+ 
+@@ -4844,6 +5001,15 @@ static int _raid45_to_raid54_wrapper(TAKEOVER_FN_ARGS)
+ 		return 0;
+ 	}
+ 
++	if (!yes && yes_no_prompt("Are you sure you want to convert %s%s LV %s to %s%s type? [y/n]: ",
++				  lvseg_name(seg), _get_segtype_alias_str(lv, seg->segtype),
++				  display_lvname(lv), new_segtype->name,
++				  _get_segtype_alias_str(lv, new_segtype)) == 'n') {
++		log_error("Logical volume %s NOT converted to \"%s\".",
++			  display_lvname(lv), new_segtype->name);
++		return 0;
++	}
++
+ 	log_debug_metadata("Converting LV %s from %s to %s.", display_lvname(lv),
+ 			   (seg_is_raid4(seg) ? SEG_TYPE_NAME_RAID4 : SEG_TYPE_NAME_RAID5_N),
+ 			   (seg_is_raid4(seg) ? SEG_TYPE_NAME_RAID5_N : SEG_TYPE_NAME_RAID4));
+@@ -5018,7 +5184,7 @@ static int _takeover_downconvert_wrapper(TAKEOVER_FN_ARGS)
+ 	}
+ 
+ 	if (segtype_is_raid4(new_segtype))
+-		return _raid45_to_raid54_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count,
++		return _raid45_to_raid54_wrapper(lv, new_segtype, 1 /* yes */, force, first_seg(lv)->area_count,
+ 						 1 /* data_copies */, 0, 0, 0, allocate_pvs);
+ 
+ 	return 1;
+@@ -5200,7 +5366,7 @@ static int _takeover_upconvert_wrapper(TAKEOVER_FN_ARGS)
+ 		if (!(raid5_n_segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID5_N)))
+ 			return_0;
+ 
+-		/* raid6 upconvert: vonvert to raid5_n preserving already allocated new image component pair */
++		/* raid6 upconvert: convert to raid5_n preserving already allocated new image component pair */
+ 		if (segtype_is_any_raid6(new_segtype)) {
+ 			struct logical_volume *meta_lv, *data_lv;
+ 
+@@ -5217,7 +5383,7 @@ static int _takeover_upconvert_wrapper(TAKEOVER_FN_ARGS)
+ 						      extents_copied, seg_len);
+ 			seg->area_count--;
+ 
+-			if (!_raid45_to_raid54_wrapper(lv, raid5_n_segtype, yes, force, seg->area_count,
++			if (!_raid45_to_raid54_wrapper(lv, raid5_n_segtype, 1 /* yes */, force, seg->area_count,
+ 						       1 /* data_copies */, 0, 0, 0, allocate_pvs))
+ 				return 0;
+ 
+@@ -5751,94 +5917,172 @@ static uint64_t _r5_to_r6[][2] = {
+ 
+ 
+ /* Return segment type flag for raid5 -> raid6 conversions */
+-static uint64_t _get_r56_flag(const struct lv_segment *seg, unsigned idx)
++static uint64_t _get_r56_flag(const struct segment_type *segtype, unsigned idx)
+ {
+ 	unsigned elems = ARRAY_SIZE(_r5_to_r6);
+ 
+ 	while (elems--)
+-		if (seg->segtype->flags & _r5_to_r6[elems][idx])
++		if (segtype->flags & _r5_to_r6[elems][idx])
+ 			return _r5_to_r6[elems][!idx];
+ 
+ 	return 0;
+ }
+ 
+-/* Return segment type flag for raid5 -> raid6 conversions */
++/* Return segment type flag of @seg for raid5 -> raid6 conversions */
+ static uint64_t _raid_seg_flag_5_to_6(const struct lv_segment *seg)
+ {
+-	return _get_r56_flag(seg, 0);
++	return _get_r56_flag(seg->segtype, 0);
+ }
+ 
+-/* Return segment type flag for raid6 -> raid5 conversions */
++/* Return segment type flag of @seg for raid6 -> raid5 conversions */
+ static uint64_t _raid_seg_flag_6_to_5(const struct lv_segment *seg)
+ {
+-	return _get_r56_flag(seg, 1);
++	return _get_r56_flag(seg->segtype, 1);
+ }
+ 
+-/* Change segtype for raid4 <-> raid5 <-> raid6 where necessary. */
+-static int _set_convenient_raid1456_segtype_to(const struct lv_segment *seg_from,
+-					       const struct segment_type **segtype,
+-					       int yes)
++/* Return segment type flag of @segtype for raid5 -> raid6 conversions */
++static uint64_t _raid_segtype_flag_5_to_6(const struct segment_type *segtype)
+ {
+-	size_t len = min(strlen((*segtype)->name), strlen(lvseg_name(seg_from)));
+-	uint64_t seg_flag;
++	return _get_r56_flag(segtype, 0);
++}
++
++/* Change segtype for raid* for convenience where necessary. */
++/* FIXME: do this like _conversion_options_allowed()? */
++static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_from,
++						 const struct segment_type **segtype,
++						 int yes)
++{
++	uint64_t seg_flag = 0;
+ 	struct cmd_context *cmd = seg_from->lv->vg->cmd;
+ 	const struct segment_type *segtype_sav = *segtype;
+ 
+ 	/* Bail out if same RAID level is requested. */
+-	if (!strncmp((*segtype)->name, lvseg_name(seg_from), len))
++	if (is_same_level(seg_from->segtype, *segtype))
+ 		return 1;
+ 
+-	/* Striped/raid0 -> raid5/6 */
++	log_debug("Checking LV %s requested %s segment type for convenience",
++		  display_lvname(seg_from->lv), (*segtype)->name);
++
++	/* striped/raid0 -> raid5/6 */
+ 	if (seg_is_striped(seg_from) || seg_is_any_raid0(seg_from)) {
+ 		/* If this is any raid5 conversion request -> enforce raid5_n, because we convert from striped */
+-		if (segtype_is_any_raid5(*segtype) && !segtype_is_raid5_n(*segtype)) {
++		if (segtype_is_any_raid5(*segtype) && !segtype_is_raid5_n(*segtype))
+ 			seg_flag = SEG_RAID5_N;
+-			goto replaced;
+ 
+ 		/* If this is any raid6 conversion request -> enforce raid6_n_6, because we convert from striped */
+-		} else if (segtype_is_any_raid6(*segtype) && !segtype_is_raid6_n_6(*segtype)) {
++		else if (segtype_is_any_raid6(*segtype) && !segtype_is_raid6_n_6(*segtype))
+ 			seg_flag = SEG_RAID6_N_6;
+-			goto replaced;
++
++	/* raid1 -> */
++	} else if (seg_is_raid1(seg_from) && !segtype_is_mirror(*segtype)) {
++		if (seg_from->area_count != 2) {
++			log_warn("Convert %s LV %s to 2 images first.",
++				 lvseg_name(seg_from), display_lvname(seg_from->lv));
++			return 0;
++
++		} else if (segtype_is_striped(*segtype) ||
++			   segtype_is_any_raid0(*segtype) ||
++			   segtype_is_raid10(*segtype))
++			seg_flag = SEG_RAID5_N;
++
++		else if (!segtype_is_raid4(*segtype) && !segtype_is_any_raid5(*segtype))
++			seg_flag = SEG_RAID5_LS;
++
++	/* raid4/raid5 -> striped/raid0/raid1/raid6/raid10 */
++	} else if (seg_is_raid4(seg_from) || seg_is_any_raid5(seg_from)) {
++		if (segtype_is_raid1(*segtype) &&
++		    seg_from->area_count != 2) {
++			log_warn("Convert %s LV %s to 2 stripes first (i.e. --stripes 1).",
++				 lvseg_name(seg_from), display_lvname(seg_from->lv));
++			return 0;
++
++		} else if (seg_is_raid4(seg_from) &&
++			   segtype_is_any_raid5(*segtype) &&
++			   !segtype_is_raid5_n(*segtype))
++			seg_flag = SEG_RAID5_N;
++
++		else if (seg_is_any_raid5(seg_from) &&
++			 segtype_is_raid4(*segtype) &&
++			 !segtype_is_raid5_n(*segtype))
++			seg_flag = SEG_RAID5_N;
++
++		else if (segtype_is_raid10(*segtype)) {
++			if (seg_from->area_count < 3) {
++				log_warn("Convert %s LV %s to minimum 3 stripes first (i.e. --stripes 2).",
++					 lvseg_name(seg_from), display_lvname(seg_from->lv));
++				return 0;
++			}
++
++			seg_flag = SEG_RAID0_META;
++
++		} else if (segtype_is_any_raid6(*segtype)) {
++			if (seg_from->area_count < 4) {
++				log_warn("Convert %s LV %s to minimum 4 stripes first (i.e. --stripes 3).",
++					 lvseg_name(seg_from), display_lvname(seg_from->lv));
++				return 0;
++
++			} else if (seg_is_raid4(seg_from) && !segtype_is_raid6_n_6(*segtype))
++				seg_flag = SEG_RAID6_N_6;
++			else
++				seg_flag = _raid_seg_flag_5_to_6(seg_from);
+ 		}
+ 
+-	/* raid4 -> raid5_n */
+-	} else if (seg_is_raid4(seg_from) && segtype_is_any_raid5(*segtype)) {
+-		seg_flag = SEG_RAID5_N;
+-		goto replaced;
++	/* raid6 -> striped/raid0/raid5/raid10 */
++	} else if (seg_is_any_raid6(seg_from)) {
++		if (segtype_is_raid1(*segtype)) {
++			/* No result for raid6_{zr,nr,nc} */
++			if (!(seg_flag = _raid_seg_flag_6_to_5(seg_from)) ||
++			    !(seg_flag & (*segtype)->flags))
++				seg_flag = SEG_RAID6_LS_6;
+ 
+-	/* raid4/raid5_n -> striped/raid0/raid6 */
+-	} else if ((seg_is_raid4(seg_from) || seg_is_raid5_n(seg_from)) &&
+-		   !segtype_is_striped(*segtype) &&
+-		   !segtype_is_any_raid0(*segtype) &&
+-		   !segtype_is_raid1(*segtype) &&
+-		   !segtype_is_raid4(*segtype) &&
+-		   !segtype_is_raid5_n(*segtype) &&
+-		   !segtype_is_raid6_n_6(*segtype)) {
+-		seg_flag = SEG_RAID6_N_6;
+-		goto replaced;
+-
+-	/* Got to do check for raid5 -> raid6 ... */
+-	} else if (seg_is_any_raid5(seg_from) && segtype_is_any_raid6(*segtype)) {
+-		if (!(seg_flag = _raid_seg_flag_5_to_6(seg_from)))
+-			return_0;
+-		goto replaced;
++		} else if (segtype_is_any_raid10(*segtype)) {
++			seg_flag = seg_is_raid6_n_6(seg_from) ? SEG_RAID0_META : SEG_RAID6_N_6;
++
++		} else if ((segtype_is_striped(*segtype) || segtype_is_any_raid0(*segtype)) &&
++			   !seg_is_raid6_n_6(seg_from)) {
++			seg_flag = SEG_RAID6_N_6;
++
++		} else if (segtype_is_raid4(*segtype) && !seg_is_raid6_n_6(seg_from)) {
++			seg_flag = SEG_RAID6_N_6;
+ 
+-	/* ... and raid6 -> raid5 */
+-	} else if (seg_is_any_raid6(seg_from) && segtype_is_any_raid5(*segtype)) {
+-		/* No result for raid6_{zr,nr,nc} */
+-		if (!(seg_flag = _raid_seg_flag_6_to_5(seg_from)))
++		} else if (segtype_is_any_raid5(*segtype))
++			/* No result for raid6_{zr,nr,nc} */
++			if (!(seg_flag = _raid_seg_flag_6_to_5(seg_from)) ||
++			    !(seg_flag & (*segtype)->flags))
++				seg_flag = _raid_segtype_flag_5_to_6(*segtype);
++
++	/* -> raid1 */
++	} else if (!seg_is_mirror(seg_from) && segtype_is_raid1(*segtype)) {
++		if (!seg_is_raid4(seg_from) && !seg_is_any_raid5(seg_from)) {
++			log_warn("Convert %s LV %s to raid4/raid5 first.",
++				 lvseg_name(seg_from), display_lvname(seg_from->lv));
+ 			return 0;
+-		goto replaced;
+-	}
+ 
+-	return 1;
++		} else if (seg_from->area_count != 2) {
++			log_warn("Convert %s LV %s to 2 stripes first (i.e. --stripes 1).",
++				 lvseg_name(seg_from), display_lvname(seg_from->lv));
++			return 0;
++
++		}
++
++	/* raid10 -> ... */
++	} else if (seg_is_raid10(seg_from) &&
++		   !segtype_is_striped(*segtype) &&
++		   !segtype_is_any_raid0(*segtype))
++		seg_flag = SEG_RAID0_META;
++
++	if (seg_flag) {
++		if (!(*segtype = get_segtype_from_flag(cmd, seg_flag)))
++			return_0;
++		if (segtype_sav != *segtype) {
++			log_warn("Replaced LV type %s%s with possible type %s.",
++				 segtype_sav->name, _get_segtype_alias_str(seg_from->lv, segtype_sav),
++				 (*segtype)->name);
++			log_warn("Repeat this command to convert to %s after an interim conversion has finished.",
++				 segtype_sav->name);
++		}
++	}
+ 
+-replaced:
+-	if (!(*segtype = get_segtype_from_flag(cmd, seg_flag)))
+-		return_0;
+-	if (segtype_sav != *segtype)
+-		log_warn("Replaced LV type %s with possible type %s.",
+-			 segtype_sav->name, (*segtype)->name);
+ 	return 1;
+ }
+ 
+@@ -5905,6 +6149,8 @@ static int _region_size_change_requested(struct logical_volume *lv, int yes, con
+ 		return 0;
+ 	}
+ 
++	lv->status &= ~LV_RESHAPE;
++
+ 	if (!lv_update_and_reload_origin(lv))
+ 		return_0;
+ 
+@@ -5924,7 +6170,7 @@ static int _conversion_options_allowed(const struct lv_segment *seg_from,
+ 	int r = 1;
+ 	uint32_t opts;
+ 
+-	if (!new_image_count && !_set_convenient_raid1456_segtype_to(seg_from, segtype_to, yes))
++	if (!new_image_count && !_set_convenient_raid145610_segtype_to(seg_from, segtype_to, yes))
+ 		return_0;
+ 
+ 	if (!_get_allowed_conversion_options(seg_from, *segtype_to, new_image_count, &opts)) {
+@@ -5952,12 +6198,28 @@ static int _conversion_options_allowed(const struct lv_segment *seg_from,
+ 	}
+ 
+ 	if (r &&
++	    !yes &&
+ 	    strcmp((*segtype_to)->name, SEG_TYPE_NAME_MIRROR) && /* "mirror" is prompted for later */
+-	    !yes && yes_no_prompt("Are you sure you want to convert %s LV %s to %s type? [y/n]: ",
+-				  lvseg_name(seg_from), display_lvname(seg_from->lv),
++	    !is_same_level(seg_from->segtype, *segtype_to)) { /* Prompt here for takeover */
++		const char *basic_fmt = "Are you sure you want to convert %s LV %s";
++		const char *type_fmt = " to %s type";
++		const char *question_fmt = "? [y/n]: ";
++		char *fmt;
++		size_t sz = strlen(basic_fmt) + ((seg_from->segtype == *segtype_to) ? 0 : strlen(type_fmt)) + strlen(question_fmt) + 1;
++
++		if (!(fmt = dm_pool_alloc(seg_from->lv->vg->cmd->mem, sz)))
++			return_0;
++
++		if (dm_snprintf(fmt, sz, "%s%s%s", basic_fmt, (seg_from->segtype == *segtype_to) ? "" : type_fmt, question_fmt) < 0) {
++			log_error(INTERNAL_ERROR "dm_snprintf failed.");
++			return_0;
++		}
++
++		if (yes_no_prompt(fmt, lvseg_name(seg_from), display_lvname(seg_from->lv),
+ 				  (*segtype_to)->name) == 'n') {
+-		log_error("Logical volume %s NOT converted.", display_lvname(seg_from->lv));
+-		r = 0;
++			log_error("Logical volume %s NOT converted.", display_lvname(seg_from->lv));
++			r = 0;
++		}
+ 	}
+ 
+ 	return r;
+@@ -6014,6 +6276,15 @@ int lv_raid_convert(struct logical_volume *lv,
+ 	uint32_t available_slvs, removed_slvs;
+ 	takeover_fn_t takeover_fn;
+ 
++	/* FIXME If not active, prompt and activate */
++	/* FIXME Some operations do not require the LV to be active */
++	/* LV must be active to perform raid conversion operations */
++	if (!lv_is_active(lv)) {
++		log_error("%s must be active to perform this operation.",
++			  display_lvname(lv));
++		return 0;
++	}
++
+ 	new_segtype = new_segtype ? : seg->segtype;
+ 	if (!new_segtype) {
+ 		log_error(INTERNAL_ERROR "New segtype not specified.");
+@@ -6040,6 +6311,15 @@ int lv_raid_convert(struct logical_volume *lv,
+ 	region_size = region_size ? : get_default_region_size(lv->vg->cmd);
+ 
+ 	/*
++	 * Check acceptible options mirrors, region_size,
++	 * stripes and/or stripe_size have been provided.
++	 */
++	if (!_conversion_options_allowed(seg, &new_segtype, yes,
++					 0 /* Takeover */, 0 /*new_data_copies*/, new_region_size,
++					 new_stripes, new_stripe_size_supplied))
++		return _log_possible_conversion_types(lv, new_segtype);
++
++	/*
+ 	 * reshape of capable raid type requested
+ 	 */
+ 	switch (_reshape_requested(lv, new_segtype, data_copies, region_size, stripes, stripe_size)) {
+@@ -6074,15 +6354,6 @@ int lv_raid_convert(struct logical_volume *lv,
+ 		return 0;
+ 	}
+ 
+-	/*
+-	 * Check acceptible options mirrors, region_size,
+-	 * stripes and/or stripe_size have been provided.
+-	 */
+-	if (!_conversion_options_allowed(seg, &new_segtype, yes,
+-					 0 /* Takeover */, 0 /*new_data_copies*/, new_region_size,
+-					 new_stripes, new_stripe_size_supplied))
+-		return _log_possible_conversion_types(lv, new_segtype);
+-	
+ 	takeover_fn = _get_takeover_fn(first_seg(lv), new_segtype, new_image_count);
+ 
+ 	/* Exit without doing activation checks if the combination isn't possible */
+@@ -6117,15 +6388,6 @@ int lv_raid_convert(struct logical_volume *lv,
+ 		    (segtype_is_striped_target(new_segtype) &&
+ 		    (new_stripes == 1)) ? SEG_TYPE_NAME_LINEAR : new_segtype->name);
+ 
+-	/* FIXME If not active, prompt and activate */
+-	/* FIXME Some operations do not require the LV to be active */
+-	/* LV must be active to perform raid conversion operations */
+-	if (!lv_is_active(lv)) {
+-		log_error("%s must be active to perform this operation.",
+-			  display_lvname(lv));
+-		return 0;
+-	}
+-
+ 	/* In clustered VGs, the LV must be active on this node exclusively. */
+ 	if (vg_is_clustered(lv->vg) && !lv_is_active_exclusive_locally(lv)) {
+ 		log_error("%s must be active exclusive locally to "
+@@ -6140,6 +6402,8 @@ int lv_raid_convert(struct logical_volume *lv,
+ 		return 0;
+ 	}
+ 
++	lv->status &= ~LV_RESHAPE;
++
+ 	return takeover_fn(lv, new_segtype, yes, force, new_image_count, 0, new_stripes, stripe_size,
+ 			   region_size, allocate_pvs);
+ }
+@@ -6229,6 +6493,39 @@ has_enough_space:
+ }
+ 
+ /*
++ * _lv_raid_has_primary_failure_on_recover
++ * @lv
++ *
++ * The kernel behaves strangely in the presense of a primary failure
++ * during a "recover" sync operation.  It's not technically a bug, I
++ * suppose, but the output of the status line can make it difficult
++ * to determine that we are in this state.  The sync ratio will be
++ * 100% and the sync action will be "idle", but the health characters
++ * will be e.g. "Aaa" or "Aa", where the 'A' is the dead
++ * primary source that cannot be marked dead by the kernel b/c
++ * it is the only source for the remainder of data.
++ *
++ * This function helps to detect that condition.
++ *
++ * Returns: 1 if the state is detected, 0 otherwise.
++ * FIXME: would be better to return -1,0,1 to allow error report.
++ */
++int _lv_raid_has_primary_failure_on_recover(struct logical_volume *lv)
++{
++	char *tmp_dev_health;
++	char *tmp_sync_action;
++
++	if (!lv_raid_sync_action(lv, &tmp_sync_action) ||
++	    !lv_raid_dev_health(lv, &tmp_dev_health))
++		return_0;
++
++	if (!strcmp(tmp_sync_action, "idle") && strchr(tmp_dev_health, 'a'))
++		return 1;
++
++	return 0;
++}
++
++/*
+  * Helper:
+  *
+  * _lv_raid_rebuild_or_replace
+@@ -6279,11 +6576,38 @@ static int _lv_raid_rebuild_or_replace(struct logical_volume *lv,
+ 	}
+ 
+ 	if (!_raid_in_sync(lv)) {
++		/*
++		 * FIXME: There is a bug in the kernel that prevents 'rebuild'
++		 *        from being specified when the array is not in-sync.
++		 *        There are conditions where this should be allowed,
++		 *        but only when we are doing a repair - as indicated by
++		 *        'lv->vg->cmd->handles_missing_pvs'.  The above
++		 *        conditional should be:
++		 (!lv->vg->cmd->handles_missing_pvs && !_raid_in_sync(lv))
++		 */
+ 		log_error("Unable to replace devices in %s while it is "
+ 			  "not in-sync.", display_lvname(lv));
+ 		return 0;
+ 	}
+ 
++	if (_lv_raid_has_primary_failure_on_recover(lv)) {
++		/*
++		 * I hate having multiple error lines, but this
++		 * seems to work best for syslog and CLI.
++		 */
++		log_error("Unable to repair %s/%s.  Source devices failed"
++			  " before the RAID could synchronize.",
++			  lv->vg->name, lv->name);
++		log_error("You should choose one of the following:");
++		log_error("  1) deactivate %s/%s, revive failed "
++			  "device, re-activate LV, and proceed.",
++			  lv->vg->name, lv->name);
++		log_error("  2) remove the LV (all data is lost).");
++		log_error("  3) Seek expert advice to attempt to salvage any"
++			  " data from remaining devices.");
++		return 0;
++	}
++
+ 	/*
+ 	 * How many sub-LVs are being removed?
+ 	 */
+diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
+index 93132c3..2acb894 100644
+--- a/lib/metadata/segtype.h
++++ b/lib/metadata/segtype.h
+@@ -290,6 +290,24 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
+ #define RAID_FEATURE_RAID4			(1U << 3) /* ! version 1.8 or 1.9.0 */
+ #define RAID_FEATURE_SHRINK			(1U << 4) /* version 1.9.0 */
+ #define RAID_FEATURE_RESHAPE			(1U << 5) /* version 1.10.1 */
++/*
++ * RAID_FEATURE_NEW_DEVICES_ACCEPT_REBUILD
++ * This signifies a behavioral change in dm-raid.  Prior to upstream kernel
++ * commit 33e53f068, the kernel would refuse to allow 'rebuild' CTR args to
++ * be submitted when other devices in the array had uninitialized superblocks.
++ * After the commit, these parameters were allowed.
++ *
++ * The most obvious useful case of this new behavior is up-converting a
++ * linear device to RAID1.  A new superblock is allocated for the linear dev
++ * and it will be uninitialized, while all the new images are specified for
++ * 'rebuild'.  This valid scenario would not have been allowed prior to
++ * commit 33e53f068.
++ *
++ * Commit 33e53f068 did not bump the dm-raid version number.  So it exists
++ * in some, but not all 1.8.1 versions of dm-raid.  The only way to be
++ * certain the new behavior exists is to check for version 1.9.0.
++ */
++#define RAID_FEATURE_NEW_DEVICES_ACCEPT_REBUILD	(1U << 6) /* version 1.9.0 */
+ 
+ #ifdef RAID_INTERNAL
+ int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
+diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
+index f9cd3d0..ad45ce9 100644
+--- a/lib/metadata/thin_manip.c
++++ b/lib/metadata/thin_manip.c
+@@ -563,6 +563,12 @@ static uint64_t _estimate_metadata_size(uint32_t data_extents, uint32_t extent_s
+ 	return _estimate_size(data_extents, extent_size, chunk_size);
+ }
+ 
++/* Estimate maximal supportable thin pool data size for given chunk_size */
++static uint64_t _estimate_max_data_size(uint32_t chunk_size)
++{
++	return  chunk_size * (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2) * SECTOR_SIZE / UINT64_C(64);
++}
++
+ /* Estimate thin pool chunk size from data and metadata size (in sector units) */
+ static uint32_t _estimate_chunk_size(uint32_t data_extents, uint32_t extent_size,
+ 				     uint64_t metadata_size, int attr)
+@@ -628,6 +634,7 @@ int update_thin_pool_params(struct cmd_context *cmd,
+ {
+ 	uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
+ 	uint32_t estimate_chunk_size;
++	uint64_t max_pool_data_size;
+ 	const char *str;
+ 
+ 	if (!*chunk_size &&
+@@ -666,7 +673,7 @@ int update_thin_pool_params(struct cmd_context *cmd,
+ 
+ 			/* Check if we should eventually use bigger chunk size */
+ 			while ((pool_metadata_size >
+-				(DEFAULT_THIN_POOL_OPTIMAL_SIZE / SECTOR_SIZE)) &&
++				(DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE * 2)) &&
+ 			       (*chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE)) {
+ 				*chunk_size <<= 1;
+ 				pool_metadata_size >>= 1;
+@@ -704,6 +711,16 @@ int update_thin_pool_params(struct cmd_context *cmd,
+ 		}
+ 	}
+ 
++	max_pool_data_size = _estimate_max_data_size(*chunk_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));
++		return 0;
++	}
++
++	log_print_unless_silent("Thin pool volume with chunk size %s can address at most %s of data.",
++				display_size(cmd, *chunk_size), display_size(cmd, max_pool_data_size));
++
+ 	if (!validate_thin_pool_chunk_size(cmd, *chunk_size))
+ 		return_0;
+ 
+diff --git a/lib/raid/raid.c b/lib/raid/raid.c
+index 25009f6..8a53d7e 100644
+--- a/lib/raid/raid.c
++++ b/lib/raid/raid.c
+@@ -474,6 +474,7 @@ static int _raid_target_present(struct cmd_context *cmd,
+ 		{ 1, 3, 0, RAID_FEATURE_RAID10, SEG_TYPE_NAME_RAID10 },
+ 		{ 1, 7, 0, RAID_FEATURE_RAID0, SEG_TYPE_NAME_RAID0 },
+ 		{ 1, 9, 0, RAID_FEATURE_SHRINK, "shrinking" },
++		{ 1, 9, 0, RAID_FEATURE_NEW_DEVICES_ACCEPT_REBUILD, "rebuild+emptymeta" },
+ 		{ 1, 10, 1, RAID_FEATURE_RESHAPE, "reshaping" },
+ 	};
+ 
+diff --git a/libdm/libdm-stats.c b/libdm/libdm-stats.c
+index 6ce6c57..b0c9e4b 100644
+--- a/libdm/libdm-stats.c
++++ b/libdm/libdm-stats.c
+@@ -4466,6 +4466,7 @@ static struct _extent *_stats_get_extents_for_file(struct dm_pool *mem, int fd,
+ 	return extents;
+ 
+ bad:
++	*count = 0;
+ 	dm_pool_abandon_object(mem);
+ 	dm_free(buf);
+ 	return NULL;
+@@ -4536,7 +4537,7 @@ static int _stats_unmap_regions(struct dm_stats *dms, uint64_t group_id,
+ 		region = &dms->regions[i];
+ 		nr_old++;
+ 
+-		if (_find_extent(*count, extents,
++		if (extents && _find_extent(*count, extents,
+ 				  region->start, region->len)) {
+ 			ext.start = region->start;
+ 			ext.len = region->len;
+@@ -4653,11 +4654,12 @@ static uint64_t *_stats_map_file_regions(struct dm_stats *dms, int fd,
+          * causing complications in the error path.
+          */
+ 	if (!(extent_mem = dm_pool_create("extents", sizeof(*extents))))
+-		return_0;
++		return_NULL;
+ 
+ 	if (!(extents = _stats_get_extents_for_file(extent_mem, fd, count))) {
+-		dm_pool_destroy(extent_mem);
+-		return_0;
++		log_very_verbose("No extents found in fd %d", fd);
++		if (!update)
++			goto out;
+ 	}
+ 
+ 	if (update) {
+@@ -4734,7 +4736,10 @@ static uint64_t *_stats_map_file_regions(struct dm_stats *dms, int fd,
+ 	if (bounds)
+ 		dm_free(hist_arg);
+ 
+-	dm_pool_free(extent_mem, extents);
++	/* the extent table will be empty if the file has been truncated. */
++	if (extents)
++		dm_pool_free(extent_mem, extents);
++
+ 	dm_pool_destroy(extent_mem);
+ 
+ 	return regions;
+@@ -4755,12 +4760,6 @@ out_remove:
+ 	*count = 0;
+ 
+ out:
+-	/*
+-	 * The table of file extents in 'extents' is always built, so free
+-	 * it explicitly: this will also free any 'old_extents' table that
+-	 * was later allocated from the 'extent_mem' pool by this function.
+-	 */
+-	dm_pool_free(extent_mem, extents);
+ 	dm_pool_destroy(extent_mem);
+ 	dm_free(hist_arg);
+ 	dm_free(regions);
+@@ -4872,7 +4871,8 @@ uint64_t *dm_stats_update_regions_from_fd(struct dm_stats *dms, int fd,
+ 	if (!dm_stats_list(dms, NULL))
+ 		goto bad;
+ 
+-	if (regroup)
++	/* regroup if there are regions to group */
++	if (regroup && (*regions != DM_STATS_REGION_NOT_PRESENT))
+ 		if (!_stats_group_file_regions(dms, regions, count, alias))
+ 			goto bad;
+ 
+diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
+index d5ca821..13d6cbf 100644
+--- a/liblvm/lvm_lv.c
++++ b/liblvm/lvm_lv.c
+@@ -507,7 +507,7 @@ static int _lv_set_pool_params(struct lvcreate_params *lp,
+ 		pool_metadata_size = extents * vg->extent_size /
+ 			(lp->chunk_size * (SECTOR_SIZE / 64));
+ 		while ((pool_metadata_size >
+-			(2 * DEFAULT_THIN_POOL_OPTIMAL_SIZE / SECTOR_SIZE)) &&
++			(DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE * 2)) &&
+ 		       lp->chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE) {
+ 			lp->chunk_size <<= 1;
+ 			pool_metadata_size >>= 1;
+diff --git a/man/clvmd.8_main b/man/clvmd.8_main
+index 8e9921d..de6ce25 100644
+--- a/man/clvmd.8_main
++++ b/man/clvmd.8_main
+@@ -31,6 +31,9 @@ clvmd \(em cluster LVM daemon
+ clvmd is the daemon that distributes LVM metadata updates around a cluster.
+ It must be running on all nodes in the cluster and will give an error
+ if a node in the cluster does not have this daemon running.
++
++Also see \fBlvmlockd\fP(8) for a newer method of using LVM on shared
++storage.
+ .
+ .SH OPTIONS
+ .
+@@ -196,4 +199,6 @@ Defaults to \fI#LVM_PATH#\fP.
+ .SH SEE ALSO
+ .BR syslog (3),
+ .BR lvm.conf (5),
+-.BR lvm (8)
++.BR lvm (8),
++.BR lvmlockd (8),
++.BR lvmsystemid (7)
+diff --git a/man/lvm-fullreport.8_des b/man/lvm-fullreport.8_des
+index f350a0a..741cd12 100644
+--- a/man/lvm-fullreport.8_des
++++ b/man/lvm-fullreport.8_des
+@@ -3,4 +3,3 @@ and LV segments. The information is all gathered together for each VG
+ (under a per-VG lock) so it is consistent. Information gathered from
+ separate calls to \fBvgs\fP, \fBpvs\fP, and \fBlvs\fP can be inconsistent
+ if information changes between commands.
+-
+diff --git a/man/lvm.8_main b/man/lvm.8_main
+index 7506eaf..bd5d8a7 100644
+--- a/man/lvm.8_main
++++ b/man/lvm.8_main
+@@ -537,6 +537,8 @@ directly.
+ .BR lvs (8)
+ .BR lvscan (8)
+ 
++.BR lvm-fullreport (8)
++.BR lvm-lvpoll (8)
+ .BR lvm2-activation-generator (8)
+ .BR blkdeactivate (8)
+ .BR lvmdump (8)
+diff --git a/man/lvm.conf.5_main b/man/lvm.conf.5_main
+index 7b777af..3a45f1c 100644
+--- a/man/lvm.conf.5_main
++++ b/man/lvm.conf.5_main
+@@ -10,6 +10,10 @@ being loaded - settings read in later override earlier
+ settings.  File timestamps are checked between commands and if
+ any have changed, all the files are reloaded.
+ 
++For a description of each lvm.conf setting, run:
++
++.B lvmconfig --typeconfig default --withcomments --withspaces
++
+ The settings defined in lvm.conf can be overridden by any
+ of these extended configuration methods:
+ .TP
+diff --git a/man/lvmcache.7_main b/man/lvmcache.7_main
+index e573b58..1f29185 100644
+--- a/man/lvmcache.7_main
++++ b/man/lvmcache.7_main
+@@ -404,6 +404,24 @@ This is equivalent to:
+ .B lvconvert --type cache --cachepool VG/CachePoolLV VG/OriginLV
+ 
+ 
++.SS Cache metadata formats
++
++\&
++
++There are two disk formats for cache metadata.  The metadata format can be
++specified when a cache pool is created, and cannot be changed.
++Format \fB2\fP has better performance; it is more compact, and stores
++dirty bits in a separate btree, which improves the speed of shutting down
++the cache.
++With \fBauto\fP, lvm selects the best option provided by the current
++dm-cache kernel target.
++
++.B lvconvert --type cache-pool --cachemetadataformat auto|1|2
++.RS
++.B VG/CacheDataLV
++.RE
++
++
+ .SH SEE ALSO
+ .BR lvm.conf (5),
+ .BR lvchange (8),
+diff --git a/man/lvmetad.8_main b/man/lvmetad.8_main
+index 31a89cc..ec55171 100644
+--- a/man/lvmetad.8_main
++++ b/man/lvmetad.8_main
+@@ -53,10 +53,13 @@ metadata.
+ In some cases, lvmetad will be temporarily disabled while it continues
+ running.  In this state, LVM commands will ignore the lvmetad cache and
+ revert to scanning disks.  A warning will also be printed which includes
+-the reason why lvmetad is not being used.  The most common reason is the
+-existence of duplicate PVs (lvmetad cannot cache data for duplicate PVs.)
+-Once duplicates have been resolved, the lvmetad cache is can be updated
+-with pvscan --cache and commands will return to using the cache.
++the reason why lvmetad is not being used.  The most common reasons are the
++existence of duplicate PVs (lvmetad cannot cache data for duplicate PVs),
++or an 'lvconvert --repair' command has been run (the lvmetad cache may
++not be reliable while repairs are neeeded.)
++Once duplicates have been resolved, or repairs have been completed,
++the lvmetad cache is can be updated with pvscan --cache and commands
++will return to using the cache.
+ 
+ Use of lvmetad is enabled/disabled by:
+ .br
+diff --git a/man/lvmlockd.8_main b/man/lvmlockd.8_main
+index 1a1c2fc..552eb94 100644
+--- a/man/lvmlockd.8_main
++++ b/man/lvmlockd.8_main
+@@ -117,17 +117,22 @@ Assign each host a unique host_id in the range 1-2000 by setting
+ 
+ .SS 3. start lvmlockd
+ 
+-Use a service/init file if available, or just run "lvmlockd".
++Use a unit/init file, or run the lvmlockd daemon directly:
++.br
++systemctl start lvm2-lvmlockd
+ 
+ .SS 4. start lock manager
+ 
+ .I sanlock
+ .br
++Use unit/init files, or start wdmd and sanlock daemons directly:
++.br
+ systemctl start wdmd sanlock
+ 
+ .I dlm
+ .br
+-Follow external clustering documentation when applicable, otherwise:
++Follow external clustering documentation when applicable, or use
++unit/init files:
+ .br
+ systemctl start corosync dlm
+ 
+@@ -146,8 +151,8 @@ vgchange --lock-start
+ lvmlockd requires shared VGs to be started before they are used.  This is
+ a lock manager operation to start (join) the VG lockspace, and it may take
+ some time.  Until the start completes, locks for the VG are not available.
+-LVM commands are allowed to read the VG while start is in progress.  (An
+-init/unit file can also be used to start VGs.)
++LVM commands are allowed to read the VG while start is in progress.  (A
++unit/init file can also be used to start VGs.)
+ 
+ .SS 7. create and activate LVs
+ 
+@@ -247,9 +252,9 @@ clvmd for clustering.  See below for converting a clvm VG to a lockd VG.
+ .SS lockd VGs from hosts not using lvmlockd
+ 
+ Only hosts that use lockd VGs should be configured to run lvmlockd.
+-However, shared devices used by lockd VGs may be visible from hosts not
+-using lvmlockd.  From a host not using lvmlockd, visible lockd VGs are
+-ignored in the same way as foreign VGs (see
++However, shared devices in lockd VGs may be visible from hosts not
++using lvmlockd.  From a host not using lvmlockd, lockd VGs are ignored
++in the same way as foreign VGs (see
+ .BR lvmsystemid (7).)
+ 
+ The --shared option for reporting and display commands causes lockd VGs
+@@ -267,9 +272,9 @@ for all vgcreate options.
+ .B vgcreate <vgname> <devices>
+ 
+ .IP \[bu] 2
+-Creates a local VG with the local system ID when neither lvmlockd nor clvm are configured.
++Creates a local VG with the local host's system ID when neither lvmlockd nor clvm are configured.
+ .IP \[bu] 2
+-Creates a local VG with the local system ID when lvmlockd is configured.
++Creates a local VG with the local host's system ID when lvmlockd is configured.
+ .IP \[bu] 2
+ Creates a clvm VG when clvm is configured.
+ 
+@@ -300,10 +305,11 @@ LVM commands request locks from clvmd to use the VG.
+ 
+ .SS creating the first sanlock VG
+ 
+-Creating the first sanlock VG is not protected by locking and requires
+-special attention.  This is because sanlock locks exist within the VG, so
+-they are not available until the VG exists.  The first sanlock VG will
+-contain the "global lock".
++Creating the first sanlock VG is not protected by locking, so it requires
++special attention.  This is because sanlock locks exist on storage within
++the VG, so they are not available until the VG exists.  The first sanlock
++VG created will automatically contain the "global lock".  Be aware of the
++following special considerations:
+ 
+ .IP \[bu] 2
+ The first vgcreate command needs to be given the path to a device that has
+@@ -313,6 +319,11 @@ global lock, which will not be available until after the first sanlock VG
+ is created.
+ 
+ .IP \[bu] 2
++Because the first sanlock VG will contain the global lock, this VG needs
++to be accessible to all hosts that will use sanlock shared VGs.  All hosts
++will need to use the global lock from the first sanlock VG.
++
++.IP \[bu] 2
+ While running vgcreate for the first sanlock VG, ensure that the device
+ being used is not used by another LVM command.  Allocation of shared
+ devices is usually protected by the global lock, but this cannot be done
+@@ -323,11 +334,6 @@ While running vgcreate for the first sanlock VG, ensure that the VG name
+ being used is not used by another LVM command.  Uniqueness of VG names is
+ usually ensured by the global lock.
+ 
+-.IP \[bu] 2
+-Because the first sanlock VG will contain the global lock, this VG needs
+-to be accessible to all hosts that will use sanlock shared VGs.  All hosts
+-will need to use the global lock from the first sanlock VG.
+-
+ See below for more information about managing the sanlock global lock.
+ 
+ 
+@@ -383,7 +389,7 @@ lvmlockd is running
+ the lock manager is running
+ .br
+ \[bu]
+-the VG is visible to the system
++the VG's devices are visible on the system
+ .br
+ 
+ A lockd VG can be stopped if all LVs are deactivated.
+@@ -425,22 +431,23 @@ activation {
+ 
+ .SS automatic starting and automatic activation
+ 
+-Scripts or programs on a host that automatically start VGs will use the
+-"auto" option to indicate that the command is being run automatically by
+-the system:
++When system-level scripts/programs automatically start VGs, they should
++use the "auto" option.  This option indicates that the command is being
++run automatically by the system:
+ 
+ vgchange --lock-start --lock-opt auto [<vgname> ...]
+ 
+-Without any additional configuration, including the "auto" option has no
+-effect; all VGs are started unless restricted by lock_start_list.
++The "auto" option causes the command to follow the lvm.conf
++activation/auto_lock_start_list.  If auto_lock_start_list is undefined,
++all VGs are started, just as if the auto option was not used.
+ 
+-However, when the lvm.conf activation/auto_lock_start_list is defined, the
+-auto start command performs an additional filtering phase to all VGs being
+-started, testing each VG name against the auto_lock_start_list.  The
+-auto_lock_start_list defines lockd VGs that will be started by the auto
+-start command.  Visible lockd VGs not included in the list are ignored by
+-the auto start command.  If the list is undefined, all VG names pass this
+-filter.  (The lock_start_list is also still used to filter all VGs.)
++When auto_lock_start_list is defined, it lists the lockd VGs that should
++be started by the auto command.  VG names that do not match an item in the
++list will be ignored by the auto start command.
++
++(The lock_start_list is also still used to filter VG names from all start
++commands, i.e. with or without the auto option.  When the lock_start_list
++is defined, only VGs matching a list item can be started with vgchange.)
+ 
+ The auto_lock_start_list allows a user to select certain lockd VGs that
+ should be automatically started by the system (or indirectly, those that
+@@ -470,14 +477,12 @@ The set of orphan PVs and unused devices.
+ The properties of orphan PVs, e.g. PV size.
+ .br
+ 
+-The global lock is used in shared mode by commands that read this
+-information, or in exclusive mode by commands that change it.
+-
+-The command 'vgs' acquires the global lock in shared mode because it
+-reports the list of all VG names.
+-
+-The vgcreate command acquires the global lock in exclusive mode because it
+-creates a new VG name, and it takes a PV from the list of unused PVs.
++The global lock is acquired in shared mode by commands that read this
++information, or in exclusive mode by commands that change it.  For
++example, the command 'vgs' acquires the global lock in shared mode because
++it reports the list of all VG names, and the vgcreate command acquires the
++global lock in exclusive mode because it creates a new VG name, and it
++takes a PV from the list of unused PVs.
+ 
+ When an LVM command is given a tag argument, or uses select, it must read
+ all VGs to match the tag or selection, which causes the global lock to be
+@@ -485,10 +490,10 @@ acquired.
+ 
+ .I VG lock
+ 
+-A VG lock is associated with each VG.  The VG lock is acquired in shared
+-mode to read the VG and in exclusive mode to change the VG (modify the VG
+-metadata or activate LVs).  This lock serializes access to a VG with all
+-other LVM commands accessing the VG from all hosts.
++A VG lock is associated with each lockd VG.  The VG lock is acquired in
++shared mode to read the VG and in exclusive mode to change the VG (modify
++the VG metadata or activating LVs).  This lock serializes access to a VG
++with all other LVM commands accessing the VG from all hosts.
+ 
+ The command 'vgs' will not only acquire the GL lock to read the list of
+ all VG names, but will acquire the VG lock for each VG prior to reading
+@@ -502,7 +507,7 @@ argument.
+ 
+ An LV lock is acquired before the LV is activated, and is released after
+ the LV is deactivated.  If the LV lock cannot be acquired, the LV is not
+-activated.  LV locks are persistent and remain in place after the
++activated.  LV locks are persistent and remain in place when the
+ activation command is done.  GL and VG locks are transient, and are held
+ only while an LVM command is running.
+ 
+@@ -822,8 +827,8 @@ While lvmlockd and clvmd are entirely different systems, LVM command usage
+ remains similar.  Differences are more notable when using lvmlockd's
+ sanlock option.
+ 
+-Visible usage differences between lockd VGs with lvmlockd and clvm VGs
+-with clvmd:
++Visible usage differences between lockd VGs (using lvmlockd) and clvm VGs
++(using clvmd):
+ 
+ .IP \[bu] 2
+ lvm.conf must be configured to use either lvmlockd (use_lvmlockd=1) or
+diff --git a/man/lvmraid.7_main b/man/lvmraid.7_main
+index f0d28f5..c27f1fa 100644
+--- a/man/lvmraid.7_main
++++ b/man/lvmraid.7_main
+@@ -896,7 +896,7 @@ between linear and raid1.
+ .IP \(bu 3
+ between mirror and raid1.
+ .IP \(bu 3
+-between 2-legged raid1 and raid4/5.
++between raid1 with two images and raid4/5.
+ .IP \(bu 3
+ between striped/raid0 and raid4.
+ .IP \(bu 3
+@@ -912,39 +912,90 @@ between striped/raid0 and raid10.
+ .IP \(bu 3
+ between striped and raid4.
+ 
+-.SS Examples
++.SS Indirect conversions
+ 
+-1. Converting an LV from \fBlinear\fP to \fBraid1\fP.
++Converting from one raid level to another may require multiple steps,
++converting first to intermediate raid levels.
+ 
+-.nf
+-# lvs -a -o name,segtype,size vg
+-  LV   Type   LSize
+-  lv   linear 300.00g
++.B linear to raid6
+ 
+-# lvconvert --type raid1 --mirrors 1 vg/lv
++To convert an LV from linear to raid6:
++.br
++1. convert to raid1 with two images
++.br
++2. convert to raid5 (internally raid5_ls) with two images
++.br
++3. convert to raid5 with three or more stripes (reshape)
++.br
++4. convert to raid6 (internally raid6_ls_6)
++.br
++5. convert to raid6 (internally raid6_zr, reshape)
+ 
+-# lvs -a -o name,segtype,size vg
+-  LV            Type   LSize
+-  lv            raid1  300.00g
+-  [lv_rimage_0] linear 300.00g
+-  [lv_rimage_1] linear 300.00g
+-  [lv_rmeta_0]  linear   3.00m
+-  [lv_rmeta_1]  linear   3.00m
+-.fi
++The commands to perform the steps above are:
++.br
++1. lvconvert --type raid1 --mirrors 1 LV
++.br
++2. lvconvert --type raid5 LV
++.br
++3. lvconvert --stripes 3 LV
++.br
++4. lvconvert --type raid6 LV
++.br
++5. lvconvert --type raid6 LV
+ 
+-2. Converting an LV from \fBmirror\fP to \fBraid1\fP.
++The final conversion from raid6_ls_6 to raid6_zr is done to avoid the
++potential write/recovery performance reduction in raid6_ls_6 because of
++the dedicated parity device.  raid6_zr rotates data and parity blocks to
++avoid this.
++
++.B linear to striped
++
++To convert an LV from linear to striped:
++.br
++1. convert to raid1 with two images
++.br
++2. convert to raid5_n
++.br
++3. convert to raid5_n with five 128k stripes (reshape)
++.br
++4. convert raid5_n to striped
++
++The commands to perform the steps above are:
++.br
++1. lvconvert --type raid1 --mirrors 1 LV
++.br
++2. lvconvert --type raid5_n LV
++.br
++3. lvconvert --stripes 5 --stripesize 128k LV
++.br
++4. lvconvert --type striped LV
++
++The raid5_n type in step 2 is used because it has dedicated parity SubLVs
++at the end, and can be converted to striped directly.  The stripe size is
++increased in step 3 to add extra space for the conversion process.  This
++step grows the LV size by a factor of five.  After conversion, this extra
++space can be reduced (or used to grow the file system using the LV).
++
++Reversing these steps will convert a striped LV to linear.
++
++.B raid6 to striped
++
++To convert an LV from raid6_nr to striped:
++.br
++1. convert to raid6_n_6
++.br
++2. convert to striped
++
++The commands to perform the steps above are:
++.br
++1. lvconvert --type raid6_n_6 LV
++.br
++2. lvconvert --type striped LV
+ 
+-.nf
+-# lvs -a -o name,segtype,size vg
+-  LV            Type   LSize
+-  lv            mirror 100.00g
+-  [lv_mimage_0] linear 100.00g
+-  [lv_mimage_1] linear 100.00g
+-  [lv_mlog]     linear   3.00m
+ 
+ .SS Examples
+ 
+-1. Converting an LV from \fBlinear\fP to \fBraid1\fP.
++Converting an LV from \fBlinear\fP to \fBraid1\fP.
+ 
+ .nf
+ # lvs -a -o name,segtype,size vg
+@@ -962,7 +1013,7 @@ between striped and raid4.
+   [lv_rmeta_1]  linear   3.00m
+ .fi
+ 
+-2. Converting an LV from \fBmirror\fP to \fBraid1\fP.
++Converting an LV from \fBmirror\fP to \fBraid1\fP.
+ 
+ .nf
+ # lvs -a -o name,segtype,size vg
+@@ -983,28 +1034,17 @@ between striped and raid4.
+   [lv_rmeta_1]  linear   3.00m
+ .fi
+ 
+-3. Converting an LV from \fBlinear\fP to \fBraid1\fP (with 3 images).
++Converting an LV from \fBlinear\fP to \fBraid1\fP (with 3 images).
+ 
+ .nf
+-Start with a linear LV:
+-
+-# lvcreate -L1G -n lv vg
+-
+-Convert the linear LV to raid1 with three images
+-(original linear image plus 2 mirror images):
+-
+ # lvconvert --type raid1 --mirrors 2 vg/lv
+ .fi
+ 
+-4. Converting an LV from \fBstriped\fP (with 4 stripes) to \fBraid6_n_6\fP.
++Converting an LV from \fBstriped\fP (with 4 stripes) to \fBraid6_n_6\fP.
+ 
+ .nf
+-Start with a striped LV:
+-
+ # lvcreate --stripes 4 -L64M -n lv vg
+ 
+-Convert the striped LV to raid6_n_6:
+-
+ # lvconvert --type raid6 vg/lv
+ 
+ # lvs -a -o lv_name,segtype,sync_percent,data_copies
+@@ -1051,7 +1091,9 @@ that is done, the new stripe is unquiesced and used.)
+ 
+ .SS Examples
+ 
+-1. Converting raid6_n_6 to raid6_nr with rotating data/parity.
++(Command output shown in examples may change.)
++
++Converting raid6_n_6 to raid6_nr with rotating data/parity.
+ 
+ This conversion naturally follows a previous conversion from striped/raid0
+ to raid6_n_6 (shown above).  It completes the transition to a more
+@@ -1318,7 +1360,8 @@ In case the RaidLV should be converted to striped:
+ .nf
+ # lvconvert --type striped vg/lv
+   Unable to convert LV vg/lv from raid6_nr to striped.
+-  Converting vg/lv from raid6_nr is directly possible to the following layouts:
++  Converting vg/lv from raid6_nr is directly possible to the \\
++  following layouts:
+     raid6_nc
+     raid6_zr
+     raid6_la_6
+@@ -1621,7 +1664,9 @@ RAID6 last parity devices
+ .br
+ \[bu]
+ Fixed dedicated last devices (P-Syndrome N-1 and Q-Syndrome N)
++.RS 2
+ with striped data used for striped/raid0 conversions
++.RE
+ .br
+ \[bu]
+ Used for RAID Takeover
+@@ -1632,7 +1677,10 @@ raid6_{ls,rs,la,ra}_6
+ RAID6 last parity device
+ .br
+ \[bu]
+-Dedicated last parity device used for conversions from/to raid5_{ls,rs,la,ra}
++Dedicated last parity device used for conversions from/to
++.RS 2
++raid5_{ls,rs,la,ra}
++.RE
+ 
+ raid6_ls_6
+ .br
+diff --git a/man/lvmreport.7_main b/man/lvmreport.7_main
+index 7a26401..7167df0 100644
+--- a/man/lvmreport.7_main
++++ b/man/lvmreport.7_main
+@@ -948,7 +948,7 @@ configuration directly on command line.
+ 
+ You can obtain the same information with single command where all the
+ information about PVs, PV segments, LVs and LV segments are obtained
+-per VG under a single VG lock for consistency, see also \fBlvm fullreport\fP(8)
++per VG under a single VG lock for consistency, see also \fBlvm-fullreport\fP(8)
+ man page for more information. The fullreport has its own configuration
+ settings to define field sets to use, similar to individual reports as
+ displayed above, but configuration settings have "_full" suffix now.
+diff --git a/man/lvmsystemid.7_main b/man/lvmsystemid.7_main
+index 8c57042..9b36dc3 100644
+--- a/man/lvmsystemid.7_main
++++ b/man/lvmsystemid.7_main
+@@ -94,19 +94,18 @@ corrupting the PVs.  See the
+ section for more information.
+ 
+ .IP \[bu] 2
+-The system ID does not protect devices in VG from programs other than LVM.
++The system ID does not protect devices in a VG from programs other than LVM.
+ 
+ .IP \[bu] 2
+-A host using an old version of LVM without the system ID feature will not
+-recognize a system ID in VGs from other hosts.  Even though the old
+-version of LVM is not blocked from reading a VG with a system ID, it is
+-blocked from writing to the VG (or its LVs).  The system ID feature
+-changes the write mode of a VG, making it appear read-only to previous
+-versions of LVM.
+-
+-This also means that if a host downgrades its version of LVM, it would
++A host using an old LVM version (without the system ID feature) will not
++recognize a system ID set in VGs.  The old LVM can read a VG with a
++system ID, but is prevented from writing to the VG (or its LVs).
++The system ID feature changes the write mode of a VG, making it appear
++read-only to previous versions of LVM.
++
++This also means that if a host downgrades to the old LVM version, it would
+ lose access to any VGs it had created with a system ID.  To avoid this,
+-the system ID should be removed from VGs before downgrading to an LVM
++the system ID should be removed from local VGs before downgrading LVM to a
+ version without the system ID feature.
+ 
+ 
+diff --git a/man/pvchange.8_des b/man/pvchange.8_des
+index 802850f..e914e13 100644
+--- a/man/pvchange.8_des
++++ b/man/pvchange.8_des
+@@ -1 +1,4 @@
+ pvchange changes PV attributes in the VG.
++
++For options listed in parentheses, any one is required, after which the
++others are optional.
+diff --git a/man/see_also.end b/man/see_also.end
+index 9e7d3b2..5b07719 100644
+--- a/man/see_also.end
++++ b/man/see_also.end
+@@ -46,6 +46,8 @@
+ .BR lvs (8)
+ .BR lvscan (8)
+ 
++.BR lvm-fullreport (8)
++.BR lvm-lvpoll (8)
+ .BR lvm2-activation-generator (8)
+ .BR blkdeactivate (8)
+ .BR lvmdump (8)
+diff --git a/man/vgexport.8_des b/man/vgexport.8_des
+index f9fa49c..66d3af3 100644
+--- a/man/vgexport.8_des
++++ b/man/vgexport.8_des
+@@ -1,6 +1,6 @@
+ vgexport makes inactive VGs unknown to the system. In this state, all the
+ PVs in the VG can be moved to a different system, from which
+-\fBvgimport\fP can then be run.
++\fBvgimport\fP(8) can then be run.
+ 
+ Most LVM tools ignore exported VGs.
+ 
+diff --git a/scripts/fsadm.sh b/scripts/fsadm.sh
+index 26be102..ea14efe 100755
+--- a/scripts/fsadm.sh
++++ b/scripts/fsadm.sh
+@@ -75,8 +75,9 @@ BLOCKCOUNT=
+ MOUNTPOINT=
+ MOUNTED=
+ REMOUNT=
+-PROCMOUNTS="/proc/mounts"
+-PROCSELFMOUNTINFO="/proc/self/mountinfo"
++PROCDIR="/proc"
++PROCMOUNTS="$PROCDIR/mounts"
++PROCSELFMOUNTINFO="$PROCDIR/self/mountinfo"
+ NULL="$DM_DEV_DIR/null"
+ 
+ IFS_OLD=$IFS
+@@ -113,8 +114,11 @@ verbose() {
+ 	test -n "$VERB" && echo "$TOOL: $@" || true
+ }
+ 
++# Support multi-line error messages
+ error() {
+-	echo "$TOOL: $@" >&2
++	for i in "$@" ;  do
++		echo "$TOOL: $i" >&2
++	done
+ 	cleanup 1
+ }
+ 
+@@ -178,52 +182,135 @@ decode_size() {
+ 	fi
+ }
+ 
++decode_major_minor() {
++	# 0x00000fff00  mask MAJOR
++	# 0xfffff000ff  mask MINOR
++
++	#MINOR=$(( $1 / 1048576 ))
++	#MAJOR=$(( ($1 - ${MINOR} * 1048576) / 256 ))
++	#MINOR=$(( $1 - ${MINOR} * 1048576 - ${MAJOR} * 256 + ${MINOR} * 256))
++
++	echo "$(( ( $1 >> 8 ) & 4095 )):$(( ( ( $1 >> 12 ) & 268435200 ) | ( $1 & 255 ) ))"
++}
++
+ # detect filesystem on the given device
+ # dereference device name if it is symbolic link
+ detect_fs() {
+ 	VOLUME_ORIG=$1
+ 	VOLUME=${1/#"${DM_DEV_DIR}/"/}
+-	VOLUME=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$VOLUME") || error "Cannot get readlink \"$1\""
++	VOLUME=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$VOLUME")
++	test -n "$VOLUME" || error "Cannot get readlink \"$1\"."
+ 	RVOLUME=$VOLUME
+ 	case "$RVOLUME" in
+-          # hardcoded /dev  since udev does not create these entries elsewhere
++	  # hardcoded /dev  since udev does not create these entries elsewhere
+ 	  /dev/dm-[0-9]*)
+ 		read </sys/block/${RVOLUME#/dev/}/dm/name SYSVOLUME 2>&1 && VOLUME="$DM_DEV_DIR/mapper/$SYSVOLUME"
+-		read </sys/block/${RVOLUME#/dev/}/dev MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$VOLUME\""
++		read </sys/block/${RVOLUME#/dev/}/dev MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$VOLUME\"."
++		MAJOR=${MAJORMINOR%%:*}
++		MINOR=${MAJORMINOR##*:}
+ 		;;
+ 	  *)
+-		STAT=$(stat --format "MAJOR=%t MINOR=%T" ${RVOLUME}) || error "Cannot get major:minor for \"$VOLUME\""
+-		eval $STAT
+-		MAJOR=$((0x${MAJOR}))
+-		MINOR=$((0x${MINOR}))
+-		MAJORMINOR=${MAJOR}:${MINOR}
++		STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" ${RVOLUME})
++		test -n "$STAT" || error "Cannot get major:minor for \"$VOLUME\"."
++		eval "$STAT"
++		MAJORMINOR="${MAJOR}:${MINOR}"
+ 		;;
+ 	esac
+ 	# use null device as cache file to be sure about the result
+ 	# not using option '-o value' to be compatible with older version of blkid
+-	FSTYPE=$("$BLKID" -c "$NULL" -s TYPE "$VOLUME") || error "Cannot get FSTYPE of \"$VOLUME\""
++	FSTYPE=$("$BLKID" -c "$NULL" -s TYPE "$VOLUME")
++	test -n "$FSTYPE" || error "Cannot get FSTYPE of \"$VOLUME\"."
+ 	FSTYPE=${FSTYPE##*TYPE=\"} # cut quotation marks
+ 	FSTYPE=${FSTYPE%%\"*}
+-	verbose "\"$FSTYPE\" filesystem found on \"$VOLUME\""
++	verbose "\"$FSTYPE\" filesystem found on \"$VOLUME\"."
++}
++
++
++# Check that passed mounted MAJOR:MINOR is not matching $MAJOR:MINOR of resized $VOLUME
++validate_mounted_major_minor() {
++	test "$1" = "$MAJORMINOR" || {
++		local REFNAME=$(dmsetup info -c -j "${1%%:*}" -m "${1##*:}" -o name --noheadings 2>/dev/null)
++		local CURNAME=$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o name --noheadings 2>/dev/null)
++		error "Cannot ${CHECK+CHECK}${RESIZE+RESIZE} device \"$VOLUME\" without umounting filesystem $MOUNTED first." \
++		      "Mounted filesystem is using device $CURNAME, but referenced device is $REFNAME." \
++		      "Filesystem utilities currently do not support renamed devices."
++	}
++}
++
++# ATM fsresize & fsck tools are not able to work properly
++# when mounted device has changed its name.
++# So whenever such device no longer exists with original name
++# abort further command processing
++check_valid_mounted_device() {
++	local MOUNTEDMAJORMINOR
++	local VOL=$("$READLINK" $READLINK_E "$1")
++	local CURNAME=$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o name --noheadings)
++	local SUGGEST="Possibly device \"$1\" has been renamed to \"$CURNAME\"?"
++
++	# more confused, device is not DM....
++	test -n "$CURNAME" || SUGGEST="Mounted volume is not a device mapper device???"
++
++	test -n "$VOL" ||
++		error "Cannot access device \"$1\" referenced by mounted filesystem \"$MOUNTED\"." \
++		"$SUGGEST" \
++		"Filesystem utilities currently do not support renamed devices."
++
++	case "$VOL" in
++	  # hardcoded /dev  since udev does not create these entries elsewhere
++	  /dev/dm-[0-9]*)
++		read </sys/block/${VOL#/dev/}/dev MOUNTEDMAJORMINOR 2>&1 || error "Cannot get major:minor for \"$VOLUME\"."
++		;;
++	  *)
++		STAT=$(stat --format "MOUNTEDMAJORMINOR=\$((0x%t)):\$((0x%T))" "$VOL")
++		test -n "$STAT" || error "Cannot get major:minor for \"$VOLUME\"."
++		eval "$STAT"
++		;;
++	esac
++
++	validate_mounted_major_minor "$MOUNTEDMAJORMINOR"
+ }
+ 
+-detect_mounted_with_proc_self_mountinfo()  {
+-	MOUNTED=$("$GREP" "^[0-9]* [0-9]* $MAJORMINOR " "$PROCSELFMOUNTINFO")
++detect_mounted_with_proc_self_mountinfo() {
++	# Check self mountinfo
++	# grab major:minor mounted_device mount_point
++	MOUNTED=$("$GREP" "^[0-9]* [0-9]* $MAJORMINOR " "$PROCSELFMOUNTINFO" 2>/dev/null | head -1)
++
++	# If device is opened and not yet found as self mounted
++	# check all other mountinfos (since it can be mounted in cgroups)
++	# Use 'find' to not fail on to long list of args with too many pids
++	# only 1st. line is needed
++	test -z "$MOUNTED" &&
++		test $(dmsetup info -c --noheading -o open -j "$MAJOR" -m "$MINOR") -gt 0 &&
++		MOUNTED=$(find "$PROCDIR" -maxdepth 2 -name mountinfo -print0 |  xargs -0 "$GREP" "^[0-9]* [0-9]* $MAJORMINOR " 2>/dev/null | head -1 2>/dev/null)
+ 
+-	# extract 5th field which is mount point
++	# TODO: for performance compare with sed and stop with 1st. match:
++	# sed -n "/$MAJORMINOR/ {;p;q;}"
++
++	# extract 2nd field after ' - ' separator as mouted device
++	MOUNTDEV=$(echo ${MOUNTED##* - } | cut -d ' ' -f 2)
++	MOUNTDEV=$(echo -n -e ${MOUNTDEV})
++
++	# extract 5th field as mount point
+ 	# echo -e translates \040 to spaces
+-	MOUNTED=$(echo ${MOUNTED} | cut -d " " -f 5)
++	MOUNTED=$(echo ${MOUNTED} | cut -d ' ' -f 5)
+ 	MOUNTED=$(echo -n -e ${MOUNTED})
+ 
+-	test -n "$MOUNTED"
++	test -n "$MOUNTED" || return 1   # Not seen mounted anywhere
++
++	check_valid_mounted_device "$MOUNTDEV"
+ }
+ 
+-detect_mounted_with_proc_mounts()  {
++# With older systems without /proc/*/mountinfo we may need to check
++# every mount point as cannot easily depend on the name of mounted
++# device (which could have been renamed).
++# We need to visit every mount point and check it's major minor
++detect_mounted_with_proc_mounts() {
+ 	MOUNTED=$("$GREP" "^$VOLUME[ \t]" "$PROCMOUNTS")
+ 
+ 	# for empty string try again with real volume name
+ 	test -z "$MOUNTED" && MOUNTED=$("$GREP" "^$RVOLUME[ \t]" "$PROCMOUNTS")
+ 
++	MOUNTDEV=$(echo -n -e ${MOUNTED%% *})
+ 	# cut device name prefix and trim everything past mountpoint
+ 	# echo translates \040 to spaces
+ 	MOUNTED=${MOUNTED#* }
+@@ -231,24 +318,43 @@ detect_mounted_with_proc_mounts()  {
+ 
+ 	# for systems with different device names - check also mount output
+ 	if test -z "$MOUNTED" ; then
++		# will not work with spaces in paths
+ 		MOUNTED=$(LC_ALL=C "$MOUNT" | "$GREP" "^$VOLUME[ \t]")
+ 		test -z "$MOUNTED" && MOUNTED=$(LC_ALL=C "$MOUNT" | "$GREP" "^$RVOLUME[ \t]")
++		MOUNTDEV=${MOUNTED%% on *}
+ 		MOUNTED=${MOUNTED##* on }
+ 		MOUNTED=${MOUNTED% type *} # allow type in the mount name
+ 	fi
+ 
+-	test -n "$MOUNTED"
++	if test -n "$MOUNTED" ; then
++		check_valid_mounted_device "$MOUNTDEV"
++		return 0  # mounted
++	fi
++
++	# If still nothing found and volume is in use
++	# check every known mount point against MAJOR:MINOR
++	if test $(dmsetup info -c --noheading -o open -j "$MAJOR" -m "$MINOR") -gt 0 ; then
++		while IFS=$'\n' read -r i ; do
++			MOUNTDEV=$(echo -n -e ${i%% *})
++			MOUNTED=${i#* }
++			MOUNTED=$(echo -n -e ${MOUNTED%% *})
++			STAT=$(stat --format "%d" $MOUNTED)
++			validate_mounted_major_minor $(decode_major_minor "$STAT")
++		done < "$PROCMOUNTS"
++	fi
++
++	return 1  # nothing is mounted
+ }
+ 
+ # check if the given device is already mounted and where
+ # FIXME: resolve swap usage and device stacking
+-detect_mounted()  {
++detect_mounted() {
+ 	if test -e "$PROCSELFMOUNTINFO"; then
+ 		detect_mounted_with_proc_self_mountinfo
+ 	elif test -e "$PROCMOUNTS"; then
+ 		detect_mounted_with_proc_mounts
+ 	else
+-		error "Cannot detect mounted device \"$VOLUME\""
++		error "Cannot detect mounted device \"$VOLUME\"."
+ 	fi
+ }
+ 
+@@ -257,10 +363,13 @@ detect_device_size() {
+ 	# check if blockdev supports getsize64
+ 	"$BLOCKDEV" 2>&1 | "$GREP" getsize64 >"$NULL"
+ 	if test $? -eq 0; then
+-		DEVSIZE=$("$BLOCKDEV" --getsize64 "$VOLUME") || error "Cannot read size of device \"$VOLUME\""
++		DEVSIZE=$("$BLOCKDEV" --getsize64 "$VOLUME")
++		test -n "$DEVSIZE" || error "Cannot read size of device \"$VOLUME\"."
+ 	else
+-		DEVSIZE=$("$BLOCKDEV" --getsize "$VOLUME") || error "Cannot read size of device \"$VOLUME\""
+-		SSSIZE=$("$BLOCKDEV" --getss "$VOLUME") || error "Cannot block size read device \"$VOLUME\""
++		DEVSIZE=$("$BLOCKDEV" --getsize "$VOLUME")
++		test -n "$DEVSIZE" || error "Cannot read size of device \"$VOLUME\"."
++		SSSIZE=$("$BLOCKDEV" --getss "$VOLUME")
++		test -n "$SSSIZE" || error "Cannot read sector size of device \"$VOLUME\"."
+ 		DEVSIZE=$(($DEVSIZE * $SSSIZE))
+ 	fi
+ }
+@@ -273,14 +382,14 @@ round_up_block_size() {
+ }
+ 
+ temp_mount() {
+-	dry "$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR"
+-	dry "$MOUNT" "$VOLUME" "$TEMPDIR" || error "Failed to mount $TEMPDIR"
++	dry "$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR."
++	dry "$MOUNT" "$VOLUME" "$TEMPDIR" || error "Failed to mount $TEMPDIR."
+ }
+ 
+ temp_umount() {
+-	dry "$UMOUNT" "$TEMPDIR" || error "Failed to umount \"$TEMPDIR\""
+-	dry "$RMDIR" "${TEMPDIR}" || error "Failed to remove \"$TEMPDIR\""
+-	dry "$RMDIR" "${TEMPDIR%%m}" || error "Failed to remove \"${TEMPDIR%%m}\""
++	dry "$UMOUNT" "$TEMPDIR" || error "Failed to umount \"$TEMPDIR\"."
++	dry "$RMDIR" "${TEMPDIR}" || error "Failed to remove \"$TEMPDIR\","
++	dry "$RMDIR" "${TEMPDIR%%m}" || error "Failed to remove \"${TEMPDIR%%m}\"."
+ }
+ 
+ yes_no() {
+@@ -292,19 +401,24 @@ yes_no() {
+ 
+ 	while read -r -s -n 1 ANS ; do
+ 		case "$ANS" in
+-		 "y" | "Y" | "") echo y ; return 0 ;;
+-		 "n" | "N") echo n ; return 1 ;;
++		 "y" | "Y" ) echo y ; return 0 ;;
++		 "" ) if [ -t 1 ] ; then
++			echo y ; return 0
++		      fi ;;
+ 		esac
+ 	done
++
++	echo n
++	return 1
+ }
+ 
+ try_umount() {
+ 	yes_no "Do you want to unmount \"$MOUNTED\"" && dry "$UMOUNT" "$MOUNTED" && return 0
+-	error "Cannot proceed with mounted filesystem \"$MOUNTED\""
++	error "Cannot proceed with mounted filesystem \"$MOUNTED\"."
+ }
+ 
+ validate_parsing() {
+-	test -n "$BLOCKSIZE" && test -n "$BLOCKCOUNT" || error "Cannot parse $1 output"
++	test -n "$BLOCKSIZE" && test -n "$BLOCKCOUNT" || error "Cannot parse $1 output."
+ }
+ ####################################
+ # Resize ext2/ext3/ext4 filesystem
+@@ -312,6 +426,9 @@ validate_parsing() {
+ # - unmounted for downsize
+ ####################################
+ resize_ext() {
++	local IS_MOUNTED=0
++	detect_mounted && IS_MOUNTED=1
++
+ 	verbose "Parsing $TUNE_EXT -l \"$VOLUME\""
+ 	for i in $(LC_ALL=C "$TUNE_EXT" -l "$VOLUME"); do
+ 		case "$i" in
+@@ -324,7 +441,7 @@ resize_ext() {
+ 	FSFORCE=$FORCE
+ 
+ 	if [ "$NEWBLOCKCOUNT" -lt "$BLOCKCOUNT" -o "$EXTOFF" -eq 1 ]; then
+-		detect_mounted && verbose "$RESIZE_EXT needs unmounted filesystem" && try_umount
++		test $IS_MOUNTED -eq 1 && verbose "$RESIZE_EXT needs unmounted filesystem" && try_umount
+ 		REMOUNT=$MOUNTED
+ 		if test -n "$MOUNTED" ; then
+ 			# Forced fsck -f for umounted extX filesystem.
+@@ -374,7 +491,7 @@ resize_xfs() {
+ 	MOUNTPOINT=$MOUNTED
+ 	if [ -z "$MOUNTED" ]; then
+ 		MOUNTPOINT=$TEMPDIR
+-		temp_mount || error "Cannot mount Xfs filesystem"
++		temp_mount || error "Cannot mount Xfs filesystem."
+ 	fi
+ 	verbose "Parsing $TUNE_XFS \"$MOUNTPOINT\""
+ 	for i in $(LC_ALL=C "$TUNE_XFS" "$MOUNTPOINT"); do
+@@ -392,7 +509,7 @@ resize_xfs() {
+ 	elif [ $NEWBLOCKCOUNT -eq $BLOCKCOUNT ]; then
+ 		verbose "Xfs filesystem already has the right size"
+ 	else
+-		error "Xfs filesystem shrinking is unsupported"
++		error "Xfs filesystem shrinking is unsupported."
+ 	fi
+ }
+ 
+@@ -412,8 +529,8 @@ resize() {
+ 	  "ext3"|"ext2"|"ext4") resize_ext $NEWSIZE ;;
+ 	  "reiserfs") resize_reiser $NEWSIZE ;;
+ 	  "xfs") resize_xfs $NEWSIZE ;;
+-	  *) error "Filesystem \"$FSTYPE\" on device \"$VOLUME\" is not supported by this tool" ;;
+-	esac || error "Resize $FSTYPE failed"
++	  *) error "Filesystem \"$FSTYPE\" on device \"$VOLUME\" is not supported by this tool." ;;
++	esac || error "Resize $FSTYPE failed."
+ 	cleanup 0
+ }
+ 
+@@ -494,12 +611,12 @@ for i in "$TUNE_EXT" "$RESIZE_EXT" "$TUNE_REISER" "$RESIZE_REISER" \
+ 	test -n "$i" || error "Required command definitions in the script are missing!"
+ done
+ 
+-"$LVM" version >"$NULL" 2>&1 || error "Could not run lvm binary \"$LVM\""
++"$LVM" version >"$NULL" 2>&1 || error "Could not run lvm binary \"$LVM\"."
+ $("$READLINK" -e / >"$NULL" 2>&1) || READLINK_E="-f"
+ TEST64BIT=$(( 1000 * 1000000000000 ))
+-test "$TEST64BIT" -eq 1000000000000000 || error "Shell does not handle 64bit arithmetic"
+-$(echo Y | "$GREP" Y >"$NULL") || error "Grep does not work properly"
+-test $("$DATE" -u -d"Jan 01 00:00:01 1970" +%s) -eq 1 || error "Date translation does not work"
++test "$TEST64BIT" -eq 1000000000000000 || error "Shell does not handle 64bit arithmetic."
++$(echo Y | "$GREP" Y >"$NULL") || error "Grep does not work properly."
++test $("$DATE" -u -d"Jan 01 00:00:01 1970" +%s) -eq 1 || error "Date translation does not work."
+ 
+ 
+ if [ "$#" -eq 0 ] ; then
+diff --git a/test/dbus/lvmdbustest.py b/test/dbus/lvmdbustest.py
+index 50f6ad4..3dca9d5 100755
+--- a/test/dbus/lvmdbustest.py
++++ b/test/dbus/lvmdbustest.py
+@@ -18,6 +18,8 @@ import pyudev
+ from testlib import *
+ import testlib
+ from subprocess import Popen, PIPE
++from glob import glob
++import os
+ 
+ g_tmo = 0
+ 
+@@ -68,8 +70,12 @@ def lv_n(suffix=None):
+ 	return g_prefix + rs(8, s)
+ 
+ 
++def _is_testsuite_pv(pv_name):
++	return g_prefix != "" and pv_name[-1].isdigit() and pv_name[:-1].endswith(g_prefix + "pv")
++
++
+ def is_nested_pv(pv_name):
+-	return pv_name.count('/') == 3
++	return pv_name.count('/') == 3 and not _is_testsuite_pv(pv_name)
+ 
+ 
+ def _root_pv_name(res, pv_name):
+@@ -239,6 +245,7 @@ class TestDbusService(unittest.TestCase):
+ 
+ 		# Check to make sure the PVs we had to start exist, else re-create
+ 		# them
++		self.objs, self.bus = get_objects()
+ 		if len(self.pvs) != len(self.objs[PV_INT]):
+ 			for p in self.pvs:
+ 				found = False
+@@ -714,9 +721,9 @@ class TestDbusService(unittest.TestCase):
+ 			LV_BASE_INT)
+ 		self._validate_lookup("%s/%s" % (vg.Name, lv_name), lv.object_path)
+ 
+-	def _create_lv(self, thinpool=False, size=None, vg=None):
++	def _create_lv(self, thinpool=False, size=None, vg=None, suffix=None):
+ 
+-		lv_name = lv_n()
++		lv_name = lv_n(suffix=suffix)
+ 		interfaces = list(LV_BASE_INT)
+ 
+ 		if thinpool:
+@@ -1840,7 +1847,8 @@ class TestDbusService(unittest.TestCase):
+ 		self.assertIn(pv_object_path, vg.Vg.Pvs,
+ 						"Expecting PV object path in Vg.Pvs")
+ 
+-		lv = self._create_lv(vg=vg.Vg, size=vg.Vg.FreeBytes)
++		lv = self._create_lv(vg=vg.Vg, size=vg.Vg.FreeBytes,
++								suffix="_pv")
+ 		device_path = '/dev/%s/%s' % (vg.Vg.Name, lv.LvCommon.Name)
+ 		new_pv_object_path = self._pv_create(device_path)
+ 
+@@ -1865,6 +1873,46 @@ class TestDbusService(unittest.TestCase):
+ 		for i in range(0, 5):
+ 			pv_object_path = self._create_nested(pv_object_path)
+ 
++	def test_pv_symlinks(self):
++		# Lets take one of our test PVs, pvremove it, find a symlink to it
++		# and re-create using the symlink to ensure we return an object
++		# 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.
++		symlink = None
++
++		pv = self.objs[PV_INT][0]
++		pv_device_path = pv.Pv.Name
++
++		self._pv_remove(pv)
++
++		# Make sure we no longer find the pv
++		rc = self._lookup(pv_device_path)
++		self.assertEqual(rc, '/')
++
++		# Lets locate a symlink for it
++		devices = glob('/dev/disk/*/*')
++		for d in devices:
++			if pv_device_path == os.path.realpath(d):
++				symlink = d
++				break
++
++		self.assertIsNotNone(symlink, "We expected to find at least 1 symlink!")
++
++		# Make sure symlink look up fails too
++		rc = self._lookup(symlink)
++		self.assertEqual(rc, '/')
++
++		pv_object_path = self._pv_create(symlink)
++		self.assertNotEqual(pv_object_path, '/')
++
++		pv_proxy = ClientProxy(self.bus, pv_object_path, interfaces=(PV_INT, ))
++		self.assertEqual(pv_proxy.Pv.Name, pv_device_path)
++
++		# Lets check symlink lookup
++		self.assertEqual(pv_object_path, self._lookup(symlink))
++		self.assertEqual(pv_object_path, self._lookup(pv_device_path))
++
+ 
+ class AggregateResults(object):
+ 
+diff --git a/test/shell/fsadm-renamed.sh b/test/shell/fsadm-renamed.sh
+new file mode 100644
+index 0000000..9f3cd3c
+--- /dev/null
++++ b/test/shell/fsadm-renamed.sh
+@@ -0,0 +1,116 @@
++#!/bin/sh
++# Copyright (C) 2017 Red Hat, Inc. All rights reserved.
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions
++# of the GNU General Public License v.2.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software Foundation,
++# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++
++test_description='Exercise fsadm operation on renamed device'
++SKIP_WITH_LVMLOCKD=1
++SKIP_WITH_LVMPOLLD=1
++
++. lib/inittest
++
++aux prepare_vg 1 80
++
++vg_lv=$vg/$lv1
++vg_lv_ren=${vg_lv}_renamed
++
++dev_vg_lv="$DM_DEV_DIR/$vg_lv"
++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
++export LVM_BINARY=$(which lvm)
++
++test ! -d "$mount_dir" && mkdir "$mount_dir"
++test ! -d "$mount_space_dir" && mkdir "$mount_space_dir"
++test ! -d "$mount_dolar_dir" && mkdir "$mount_dolar_dir"
++
++cleanup_mounted_and_teardown()
++{
++	umount "$mount_dir" || true
++	umount "$mount_space_dir" || true
++	umount "$mount_dolar_dir" || true
++	aux teardown
++}
++
++# Test for block sizes != 1024 (rhbz #480022)
++trap 'cleanup_mounted_and_teardown' EXIT
++
++# Iterate over supported filesystems
++for i in mkfs.ext3 mkfs.xfs mkfs.reiserfs
++do
++
++if not which "$i" ; then
++	echo "Skipping tests for missing $i"
++	continue
++fi
++
++lvcreate -n $lv1 -L20M $vg
++
++case "$i" in
++*ext3)		MKFS_ARGS="-b1024 -j" ;;
++*xfs)		MKFS_ARGS="-l internal,size=1000b -f" ;;
++*reiserfs)	MKFS_ARGS="-s 513 -f" ;;
++esac
++
++echo "$i"
++"$i" $MKFS_ARGS "$dev_vg_lv"
++
++# Adding couple udev wait ops as some older systemd
++# might get confused and was 'randomly/racy' umounting
++# devices  just mounted.
++# 
++# See for explanation: 
++#   https://github.com/systemd/systemd/commit/628c89cc68ab96fce2de7ebba5933725d147aecc
++#   https://github.com/systemd/systemd/pull/2017
++aux udev_wait
++
++mount "$dev_vg_lv" "$mount_dir"
++
++aux udev_wait
++
++lvrename $vg_lv $vg_lv_ren
++
++mount | tee out
++grep $vg out
++
++# fails on renamed LV
++fail lvresize -L+10M -r $vg_lv_ren
++
++# fails on unknown mountpoint  (FIXME: umount)
++not umount "$dev_vg_lv"
++
++lvcreate -L20 -n $lv1 $vg
++"$i" $MKFS_ARGS "$dev_vg_lv"
++
++aux udev_wait
++
++mount "$dev_vg_lv" "$mount_dolar_dir"
++
++mount | tee out
++grep $vg out
++
++not lvresize -L+10M -r $vg_lv_ren
++
++umount "$mount_dir"
++
++# FIXME:  lvresize  CANNOT handle/propagage '--yes' to fsadm
++echo y | lvresize -L+10M -r $vg_lv
++
++aux udev_wait
++
++umount "$mount_dolar_dir"
++
++lvremove -ff $vg
++
++done
++
++vgremove -ff $vg
+diff --git a/test/shell/lvchange-raid.sh b/test/shell/lvchange-raid.sh
+index 34a40dc..7418cd5 100644
+--- a/test/shell/lvchange-raid.sh
++++ b/test/shell/lvchange-raid.sh
+@@ -42,6 +42,7 @@ run_writemostly_check() {
+ 
+ 	printf "#\n#\n#\n# %s/%s (%s): run_writemostly_check\n#\n#\n#\n" \
+ 		$vg $lv $segtype
++	aux wait_for_sync $vg $lv
+ 
+ 	# No writemostly flag should be there yet.
+ 	check lv_attr_bit health $vg/${lv}_rimage_0 "-"
+diff --git a/test/shell/lvconvert-raid-regionsize.sh b/test/shell/lvconvert-raid-regionsize.sh
+index 9884c1b..d2c8a54 100644
+--- a/test/shell/lvconvert-raid-regionsize.sh
++++ b/test/shell/lvconvert-raid-regionsize.sh
+@@ -64,6 +64,7 @@ _test_regionsizes raid1
+ # Clean up
+ lvremove --yes $vg
+ 
++if aux have_raid 1 10 1; then
+ # Create 5-way raid6
+ lvcreate --yes -aey --type raid6 -i 3 --stripesize 128K -R 256K -L8M -n $lv1 $vg
+ check lv_field $vg/$lv1 segtype "raid6"
+@@ -78,7 +79,11 @@ _test_regionsizes raid6
+ 
+ # Clean up
+ lvremove --yes $vg
++else
++  echo "Skipping RAID6 tests"
++fi
+ 
++if aux have_raid 1 10 1; then
+ # Create 6-way raid01
+ lvcreate --yes -aey --type raid10 -i 3 -m 1 --stripesize 128K -R 256K -L8M -n $lv1 $vg
+ check lv_field $vg/$lv1 segtype "raid10"
+@@ -90,5 +95,8 @@ aux wait_for_sync $vg $lv1
+ fsck -fn "$DM_DEV_DIR/$vg/$lv1"
+ 
+ _test_regionsizes raid10
++else
++  echo "Skipping RAID10 tests"
++fi
+ 
+ vgremove -ff $vg
+diff --git a/test/shell/lvconvert-raid-reshape-striped_to_linear.sh b/test/shell/lvconvert-raid-reshape-striped_to_linear.sh
+index 4051862..d926827 100644
+--- a/test/shell/lvconvert-raid-reshape-striped_to_linear.sh
++++ b/test/shell/lvconvert-raid-reshape-striped_to_linear.sh
+@@ -79,7 +79,7 @@ aux wait_for_sync $vg $lv1 1
+ fsck -fn $DM_DEV_DIR/$vg/$lv1
+ 
+ # Remove the now freed legs
+-lvconvert --stripes 1 $vg/$lv1
++lvconvert -y --stripes 1 $vg/$lv1
+ check lv_first_seg_field $vg/$lv1 segtype "raid5_n"
+ check lv_first_seg_field $vg/$lv1 data_stripes 1
+ check lv_first_seg_field $vg/$lv1 stripes 2
+diff --git a/test/shell/lvconvert-raid.sh b/test/shell/lvconvert-raid.sh
+index e173d66..fba7864 100644
+--- a/test/shell/lvconvert-raid.sh
++++ b/test/shell/lvconvert-raid.sh
+@@ -223,6 +223,67 @@ for i in 1 2 3 ; do
+ done
+ 
+ ###########################################
++# Upconverted RAID1 should not allow loss of primary
++#  - don't allow removal of primary while syncing
++#  - DO allow removal of secondaries while syncing
++###########################################
++aux delay_dev $dev2 0 100
++lvcreate -aey -l 2 -n $lv1 $vg $dev1 $dev2
++lvconvert -y -m 1 $vg/$lv1 \
++	--config 'global { mirror_segtype_default = "raid1" }'
++lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*r'
++not lvconvert --yes -m 0 $vg/$lv1 $dev1
++lvconvert --yes -m 0 $vg/$lv1 $dev2
++aux enable_dev $dev2
++lvremove -ff $vg
++
++###########################################
++# lvcreated RAID1 should allow all down-conversion
++#  - DO allow removal of primary while syncing
++#  - DO allow removal of secondaries while syncing
++###########################################
++aux delay_dev $dev2 0 100
++lvcreate --type raid1 -m 2 -aey -l 2 -n $lv1 $vg $dev1 $dev2 $dev3
++lvconvert --yes -m 1 $vg/$lv1 $dev3
++lvconvert --yes -m 0 $vg/$lv1 $dev1
++aux enable_dev $dev2
++lvremove -ff $vg
++
++###########################################
++# Converting from 2-way RAID1 to 3-way
++#  - DO allow removal of one of primary sources
++#  - Do not allow removal of all primary sources
++###########################################
++lvcreate --type raid1 -m 1 -aey -l 2 -n $lv1 $vg $dev1 $dev2
++aux wait_for_sync $vg $lv1
++aux delay_dev $dev3 0 100
++lvconvert --yes -m +1 $vg/$lv1 $dev3
++# should allow 1st primary to be removed
++lvconvert --yes -m -1 $vg/$lv1 $dev1
++# should NOT allow last primary to be removed
++not lvconvert --yes -m -1 $vg/$lv1 $dev2
++# should allow non-primary to be removed
++lvconvert --yes -m 0 $vg/$lv1 $dev3
++aux enable_dev $dev3
++lvremove -ff $vg
++
++###########################################
++# Converting from 2-way RAID1 to 3-way
++#  - Should allow removal of two devices,
++#    as long as they aren't both primary
++###########################################
++lvcreate --type raid1 -m 1 -aey -l 2 -n $lv1 $vg $dev1 $dev2
++aux wait_for_sync $vg $lv1
++aux delay_dev $dev3 0 100
++lvconvert --yes -m +1 $vg/$lv1 $dev3
++# should NOT allow both primaries to be removed
++not lvconvert -m 0 $vg/$lv1 $dev1 $dev2
++# should allow primary + non-primary
++lvconvert --yes -m 0 $vg/$lv1 $dev1 $dev3
++aux enable_dev $dev3
++lvremove -ff $vg
++
++###########################################
+ # Device Replacement Testing
+ ###########################################
+ # RAID1: Replace up to n-1 devices - trying different combinations
+diff --git a/test/shell/lvconvert-thin.sh b/test/shell/lvconvert-thin.sh
+index c08b95a..992a1f2 100644
+--- a/test/shell/lvconvert-thin.sh
++++ b/test/shell/lvconvert-thin.sh
+@@ -135,7 +135,7 @@ lvremove -f $vg
+ if test "$TSIZE" = 64T; then
+ lvcreate -L24T -n $lv1 $vg
+ # Warning about bigger then needed (24T data and 16G -> 128K chunk)
+-lvconvert --yes -c 64 --thinpool $vg/$lv1 2>&1 | tee err
++fail lvconvert --yes -c 64 --thinpool $vg/$lv1 2>&1 | tee err
+ grep "WARNING: Chunk size is too small" err
+ lvremove -f $vg
+ fi
+diff --git a/test/shell/lvcreate-cache.sh b/test/shell/lvcreate-cache.sh
+index faa78b2..410e105 100644
+--- a/test/shell/lvcreate-cache.sh
++++ b/test/shell/lvcreate-cache.sh
+@@ -26,6 +26,7 @@ aux prepare_vg 5 80000
+ 
+ aux lvmconf 'global/cache_disabled_features = [ "policy_smq" ]'
+ 
++
+ #######################
+ # Cache_Pool creation #
+ #######################
+@@ -62,6 +63,11 @@ grep "No command with matching syntax recognised" err
+ # Check nothing has been created yet
+ check vg_field $vg lv_count 0
+ 
++# Checks that argument passed with --cachepool is really a cache-pool
++lvcreate -an -l 1 -n $lv1 $vg
++# Hint: nice way to 'tee' only stderr.log so we can check it's log_error()
++fail lvcreate -L10 --cachepool $vg/$lv1 2> >(tee -a stderr.log >&2)
++grep "not a cache pool" stderr.log
+ 
+ # With --type cache-pool we are clear which segtype has to be created
+ lvcreate -l 1 --type cache-pool $vg/pool1
+diff --git a/test/shell/lvcreate-large-raid.sh b/test/shell/lvcreate-large-raid.sh
+index ca3f715..7ec140b 100644
+--- a/test/shell/lvcreate-large-raid.sh
++++ b/test/shell/lvcreate-large-raid.sh
+@@ -101,7 +101,15 @@ lvremove -ff $vg1
+ lvcreate -aey -L 200T -n $lv1 $vg1
+ lvconvert -y --type raid1 -m 1 $vg1/$lv1
+ check lv_field $vg1/$lv1 size "200.00t"
+-check raid_leg_status $vg1 $lv1 "aa"
++if aux have_raid 1 9 0; then
++	# The 1.9.0 version of dm-raid is capable of performing
++	# linear -> RAID1 upconverts as "recover" not "resync"
++	# The LVM code now checks the dm-raid version when
++	# upconverting and if 1.9.0+ is found, it uses "recover"
++	check raid_leg_status $vg1 $lv1 "Aa"
++else
++	check raid_leg_status $vg1 $lv1 "aa"
++fi
+ lvremove -ff $vg1
+ 
+ # bz837927 END
+diff --git a/test/shell/lvcreate-raid-nosync.sh b/test/shell/lvcreate-raid-nosync.sh
+index 1f01f47..bd7ec81 100644
+--- a/test/shell/lvcreate-raid-nosync.sh
++++ b/test/shell/lvcreate-raid-nosync.sh
+@@ -35,7 +35,7 @@ _sync() {
+ 
+ # Delay 1st leg so that rebuilding status characters
+ #  can be read before resync finished too quick.
+-aux delay_dev "$dev1" 0 90 $(get first_extent_sector "$dev1")
++aux delay_dev "$dev1" 0 100 $(get first_extent_sector "$dev1")
+ 
+ # raid0/raid0_meta don't support resynchronization
+ for r in raid0 raid0_meta
+@@ -58,7 +58,7 @@ lvremove --yes $vg/$lv1
+ for r in $segtypes
+ do
+ 	# raid4/5 support resynchronization
+-	lvcreate --type $r -Zn -i 3 -l 4 -n $lv1 $vg
++	lvcreate --type $r -Zn -i 3 -L10 -n $lv1 $vg
+ 	check raid_leg_status $vg $lv1 "aaaa"
+ 	_sync "AAAA"
+ 
+@@ -77,7 +77,7 @@ _sync "AAAAA"
+ not lvcreate --type raid6 --nosync -Zn -i 3 -l 1 -n $lv1 $vg
+ 
+ # raid10 supports resynchronization
+-lvcreate --type raid10 -m 1 -Zn -i 3 -l 4 -n $lv1 $vg
++lvcreate --type raid10 -m 1 -Zn -i 3 -L10 -n $lv1 $vg
+ check raid_leg_status $vg $lv1 "aaaaaa"
+ _sync "AAAAAA"
+ 
+diff --git a/test/shell/lvcreate-thin-big.sh b/test/shell/lvcreate-thin-big.sh
+index da7812f..9c84288 100644
+--- a/test/shell/lvcreate-thin-big.sh
++++ b/test/shell/lvcreate-thin-big.sh
+@@ -36,7 +36,7 @@ grep "WARNING: Minimum" out
+ lvcreate -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>out
+ grep "WARNING: Maximum" out
+ check lv_field $vg/pool1_tmeta size "2.00m"
+-check lv_field $vg/pool2_tmeta size "16.00g"
++check lv_field $vg/pool2_tmeta size "15.81g"
+ 
+ # Check can start and see thinpool with metadata size above kernel limit
+ lvcreate -L4M --poolmetadatasize 16G -T $vg/poolM
+diff --git a/test/shell/lvresize-full.sh b/test/shell/lvresize-full.sh
+index 17ee6aa..3eef11a 100644
+--- a/test/shell/lvresize-full.sh
++++ b/test/shell/lvresize-full.sh
+@@ -20,6 +20,7 @@ SKIP_WITH_LVMPOLLD=1
+ FSCK=${FSCK-fsck}
+ MKFS=${MKFS-mkfs.ext3}
+ RESIZEFS=${RESIZEFS-resize2fs}
++export LVM_BINARY=$(which lvm)
+ 
+ which $FSCK || skip
+ which $MKFS || skip
+diff --git a/test/shell/thin-dmeventd-warns.sh b/test/shell/thin-dmeventd-warns.sh
+new file mode 100644
+index 0000000..d22863b
+--- /dev/null
++++ b/test/shell/thin-dmeventd-warns.sh
+@@ -0,0 +1,85 @@
++#!/bin/sh
++
++# Copyright (C) 2017 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 if dmeventd produces multiple warnings when pools runs above 80%
++
++SKIP_WITH_LVMLOCKD=1
++SKIP_WITH_LVMPOLLD=1
++SKIP_WITH_CLVMD=1
++SKIP_WITH_LVMETAD=1
++
++. lib/inittest
++
++which blkdiscard || skip
++
++percent_() {
++	get lv_field $vg/pool data_percent | cut -d. -f1
++}
++
++wait_warn_() {
++
++	for i in $(seq 1 7)
++	do
++		test $(egrep "WARNING: Thin pool.*is now" debug.log_DMEVENTD_out | wc -l) -eq $1 && return 0
++		sleep 2
++	done
++
++	die "Waiting too log for dmeventd log warning"
++}
++#
++# Main
++#
++aux have_thin 1 0 0 || skip
++
++aux prepare_dmeventd
++aux prepare_vg
++
++lvcreate -L8 -V8 -T $vg/pool -n $lv1
++
++
++dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=256K count=26
++test $(percent_) -gt 80
++
++# Give it some time to dmeventd to log WARNING
++wait_warn_ 1
++
++dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=256K count=30
++test $(percent_) -gt 90
++
++# Give it some time to dmeventd to log WARNING
++wait_warn_ 2
++
++dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=8
++test $(percent_) -eq 100
++
++wait_warn_ 3
++
++blkdiscard "$DM_DEV_DIR/$vg/$lv1"
++
++# FIXME: Enforce thin-pool metadata commit with flushing status
++dmsetup status ${vg}-pool-tpool
++# Wait for thin-pool monitoring to notice lower values
++sleep 11
++# ATM dmeventd is not logging event for thin-pool getting
++# below 'WARNED' threshold.
++
++
++dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=256K count=30
++test $(percent_) -gt 90
++
++lvs -a $vg
++dmsetup status ${vg}-pool-tpool
++
++# Check pool again Warns
++wait_warn_ 4
++
++vgremove -f $vg
+diff --git a/test/shell/thin-large.sh b/test/shell/thin-large.sh
+new file mode 100644
+index 0000000..da5a7ec
+--- /dev/null
++++ b/test/shell/thin-large.sh
+@@ -0,0 +1,54 @@
++#!/bin/sh
++# Copyright (C) 2017 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
++
++# 'Exercise logic around boundary sizes of thin-pool data and chunksize
++
++SKIP_WITH_LVMLOCKD=1
++SKIP_WITH_LVMPOLLD=1
++
++. lib/inittest
++
++# FIXME  update test to make something useful on <16T
++aux can_use_16T || skip
++
++aux have_thin 1 0 0 || skip
++
++# Prepare ~1P sized devices
++aux prepare_vg 1 1000000000
++
++lvcreate -an -T -L250T $vg/pool250
++
++lvcreate -an -T -L250T --poolmetadatasize 16G $vg/pool16
++
++fail lvcreate -an -T -L250T --chunksize 64K --poolmetadatasize 16G $vg/pool64
++
++# Creation of thin-pool with proper chunk-size but not enough metadata size
++# which can grow later needs to pass
++lvcreate -an -T -L250T --chunksize 1M --poolmetadatasize 4G $vg/pool1024
++
++# Creation of chunk should fit
++lvcreate -an -T -L12T --chunksize 64K --poolmetadatasize 16G $vg/pool64
++
++check lv_field $vg/pool64 chunksize "64.00k"
++
++lvremove -ff $vg
++
++
++### Check also lvconvert ###
++
++lvcreate -an -L250T -n pool $vg
++
++fail lvconvert -y --chunksize 64 --thinpool $vg/pool
++lvconvert -y --chunksize 1M --thinpool $vg/pool
++
++check lv_field $vg/pool chunksize "1.00m"
++
++vgremove -ff $vg
+diff --git a/test/shell/thin-resize-match.sh b/test/shell/thin-resize-match.sh
+index c78842f..46b4531 100644
+--- a/test/shell/thin-resize-match.sh
++++ b/test/shell/thin-resize-match.sh
+@@ -12,13 +12,12 @@
+ # ensure there is no data loss during thin-pool resize
+ 
+ SKIP_WITH_LVMLOCKD=1
++SKIP_WITH_LVMPOLLD=1
+ 
+ export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false}
+ 
+ . lib/inittest
+ 
+-test -e LOCAL_LVMPOLLD && skip
+-
+ which md5sum || skip
+ 
+ aux have_thin 1 0 0 || skip
+diff --git a/test/shell/unknown-segment.sh b/test/shell/unknown-segment.sh
+index 27cea88..20fc920 100644
+--- a/test/shell/unknown-segment.sh
++++ b/test/shell/unknown-segment.sh
+@@ -18,9 +18,10 @@ aux prepare_vg 4
+ 
+ lvcreate -an -Zn -l 1 -n $lv1 $vg
+ lvcreate -an -Zn -l 2 --type mirror -m 1 -n $lv2 $vg
++lvcreate -an -Zn --type zero -l 1 -n $lv3 $vg
+ 
+ vgcfgbackup -f bak0 $vg
+-sed -e 's,striped,unstriped,;s,mirror,unmirror,' -i.orig bak0
++sed -e 's,striped,unstriped,;s,mirror,unmirror,;s,zero,zero+NEWFLAG,' -i.orig bak0
+ vgcfgrestore -f bak0 $vg
+ 
+ # we have on-disk metadata with unknown segments now
+@@ -28,11 +29,13 @@ not lvchange -aey $vg/$lv1 # check that activation is refused
+ 
+ # try once more to catch invalid memory access with valgrind
+ # when clvmd flushes cmd mem pool
+-not lvchange -aey $vg/$lv1 # check that activation is refused
++not lvchange -aey $vg/$lv2 # check that activation is refused
++
++not lvchange -aey $vg/$lv3 # check that activation is refused
+ 
+ vgcfgbackup -f bak1 $vg
+ cat bak1
+-sed -e 's,unstriped,striped,;s,unmirror,mirror,' -i.orig bak1
++sed -e 's,unstriped,striped,;s,unmirror,mirror,;s,zero+NEWFLAG,zero,' -i.orig bak1
+ vgcfgrestore -f bak1 $vg
+ vgcfgbackup -f bak2 $vg
+ 
+diff --git a/test/unit/Makefile.in b/test/unit/Makefile.in
+index 70b7e79..7aa180f 100644
+--- a/test/unit/Makefile.in
++++ b/test/unit/Makefile.in
+@@ -1,4 +1,4 @@
+-# Copyright (C) 2011-2015 Red Hat, Inc. All rights reserved.
++# Copyright (C) 2011-2017 Red Hat, Inc. All rights reserved.
+ #
+ # This file is part of LVM2.
+ #
+@@ -24,15 +24,15 @@ UNITS = \
+ 	string_t.c\
+ 	run.c
+ 
+-include $(top_builddir)/make.tmpl
+-
+-ifeq ($(MAKECMDGOALS),distclean)
++ifeq ("@TESTING@", "yes")
+ SOURCES = $(UNITS)
++TARGETS = run
+ endif
+ 
+-ifeq ("$(TESTING)", "yes")
++include $(top_builddir)/make.tmpl
++
++ifeq ($(MAKECMDGOALS),distclean)
+ SOURCES = $(UNITS)
+-TARGETS = run
+ endif
+ 
+ ifeq ("$(TESTING)", "yes")
+@@ -42,6 +42,8 @@ CFLAGS += @CUNIT_CFLAGS@
+ check: unit
+ 
+ $(TARGETS): $(OBJECTS) $(top_builddir)/libdm/libdevmapper.$(LIB_SUFFIX)
++	$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) -L$(top_builddir)/libdm \
++	      -o $@ $(OBJECTS) $(LDLIBS)
+ 
+ unit: $(TARGETS)
+ 	@echo Running unit tests
+diff --git a/tools/args.h b/tools/args.h
+index 87b33e7..f5e864f 100644
+--- a/tools/args.h
++++ b/tools/args.h
+@@ -42,7 +42,7 @@ arg(activationmode_ARG, '\0', "activationmode", activationmode_VAL, 0, 0,
+ 
+ arg(addtag_ARG, '\0', "addtag", tag_VAL, ARG_GROUPABLE, 0,
+     "Adds a tag to a PV, VG or LV. This option can be repeated to add\n"
+-    "multiple tags at once. See lvm(8) for information about tags.\n")
++    "multiple tags at once. See \\fBlvm\\fP(8) for information about tags.\n")
+ 
+ arg(aligned_ARG, '\0', "aligned", 0, 0, 0,
+     "Use with --separator to align the output columns\n")
+@@ -132,10 +132,41 @@ arg(config_ARG, '\0', "config", string_VAL, 0, 0,
+     "See \\fBlvm.conf\\fP(5) for more information about config.\n")
+ 
+ arg(configreport_ARG, '\0', "configreport", configreport_VAL, ARG_GROUPABLE, 1,
+-    "See lvmreport(7).\n")
++    "See \\fBlvmreport\\fP(7).\n")
+ 
+ arg(configtype_ARG, '\0', "typeconfig", configtype_VAL, 0, 0,
+-    "See lvmreport(7).\n")
++    "\\fBcurrent\\fP prints the config settings that would be applied\n"
++    "to an lvm command (assuming the command does not override them\n"
++    "on the command line.) This includes:\n"
++    "settings that have been modified in lvm config files,\n"
++    "settings that get their default values from config files,\n"
++    "and default settings that have been uncommented in config files.\n"
++    "\\fBdefault\\fP prints all settings with their default values.\n"
++    "Changes made in lvm config files are not reflected in the output.\n"
++    "Some settings get their default values internally,\n"
++    "and these settings are printed as comments.\n"
++    "Other settings get their default values from config files,\n"
++    "and these settings are not printed as comments.\n"
++    "\\fBdiff\\fP prints only config settings that have been modified\n"
++    "from their default values in config files (the difference between\n"
++    "current and default.)\n"
++    "\\fBfull\\fP prints every setting uncommented and set to the\n"
++    "current value, i.e. how it would be used by an lvm command.\n"
++    "This includes settings modified in config files, settings that usually\n"
++    "get defaults internally, and settings that get defaults from config files.\n"
++    "\\fBlist\\fP prints all config names without values.\n"
++    "\\fBmissing\\fP prints settings that are missing from the\n"
++    "lvm config files. A missing setting that usually gets its default\n"
++    "from config files is printed uncommented and set to the internal default.\n"
++    "Settings that get their default internally and are not set in config files\n"
++    "are printed commented with the internal default.\n"
++    "\\fBnew\\fP prints config settings that have been added since\n"
++    "the lvm version specified by --sinceversion. They are printed\n"
++    "with their default values.\n"
++    "\\fBprofilable\\fP prints settings with their default values that can be set from a profile.\n"
++    "\\fBprofilable-command\\fP prints settings with their default values that can be set from a command profile.\n"
++    "\\fBprofilable-metadata\\fP prints settings with their default values that can be set from a metadata profile.\n"
++    "Also see \\fBlvm.conf\\fP(5).\n")
+ 
+ arg(dataalignment_ARG, '\0', "dataalignment", sizekb_VAL, 0, 0,
+     "Align the start of the data to a multiple of this number.\n"
+@@ -149,7 +180,7 @@ arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", sizekb_VAL, 0, 0,
+ 
+ arg(deltag_ARG, '\0', "deltag", tag_VAL, ARG_GROUPABLE, 0,
+     "Deletes a tag from a PV, VG or LV. This option can be repeated to delete\n"
+-    "multiple tags at once. See lvm(8) for information about tags.\n")
++    "multiple tags at once. See \\fBlvm\\fP(8) for information about tags.\n")
+ 
+ arg(detachprofile_ARG, '\0', "detachprofile", 0, 0, 0,
+     "Detaches a metadata profile from a VG or LV.\n"
+@@ -188,7 +219,7 @@ arg(force_long_ARG, '\0', "force", 0, ARG_COUNTABLE, 0,
+ 
+ arg(foreign_ARG, '\0', "foreign", 0, 0, 0,
+     "Report/display foreign VGs that would otherwise be skipped.\n"
+-    "See lvmsystemid(7) for more information about foreign VGs.\n")
++    "See \\fBlvmsystemid\\fP(7) for more information about foreign VGs.\n")
+ 
+ arg(handlemissingpvs_ARG, '\0', "handlemissingpvs", 0, 0, 0,
+     "Allows a polling operation to continue when PVs are missing,\n"
+@@ -198,7 +229,10 @@ arg(ignoreadvanced_ARG, '\0', "ignoreadvanced", 0, 0, 0,
+     "Exclude advanced configuration settings from the output.\n")
+ 
+ arg(ignorelocal_ARG, '\0', "ignorelocal", 0, 0, 0,
+-    "Ignore local section.\n")
++    "Ignore the local section. The local section should be defined in\n"
++    "the lvmlocal.conf file, and should contain config settings\n"
++    "specific to the local host which should not be copied to\n"
++    "other hosts.\n")
+ 
+ arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", 0, 0, 0,
+     "Allows a command to continue with read-only metadata\n"
+@@ -227,25 +261,25 @@ arg(labelsector_ARG, '\0', "labelsector", number_VAL, 0, 0,
+ 
+ arg(lockopt_ARG, '\0', "lockopt", string_VAL, 0, 0,
+     "Used to pass options for special cases to lvmlockd.\n"
+-    "See lvmlockd(8) for more information.\n")
++    "See \\fBlvmlockd\\fP(8) for more information.\n")
+ 
+ arg(lockstart_ARG, '\0', "lockstart", 0, 0, 0,
+     "Start the lockspace of a shared VG in lvmlockd.\n"
+     "lvmlockd locks becomes available for the VG, allowing LVM to use the VG.\n"
+-    "See lvmlockd(8) for more information.\n")
++    "See \\fBlvmlockd\\fP(8) for more information.\n")
+ 
+ arg(lockstop_ARG, '\0', "lockstop", 0, 0, 0,
+     "Stop the lockspace of a shared VG in lvmlockd.\n"
+     "lvmlockd locks become unavailable for the VG, preventing LVM from using the VG.\n"
+-    "See lvmlockd(8) for more information.\n")
++    "See \\fBlvmlockd\\fP(8) for more information.\n")
+ 
+ arg(locktype_ARG, '\0', "locktype", locktype_VAL, 0, 0,
+     "#vgchange\n"
+     "Change the VG lock type to or from a shared lock type used with lvmlockd.\n"
+-    "See lvmlockd(8) for more information.\n"
++    "See \\fBlvmlockd\\fP(8) for more information.\n"
+     "#vgcreate\n"
+     "Specify the VG lock type directly in place of using --shared.\n"
+-    "See lvmlockd(8) for more information.\n")
++    "See \\fBlvmlockd\\fP(8) for more information.\n")
+ 
+ arg(logonly_ARG, '\0', "logonly", 0, 0, 0,
+     "Suppress command report and display only log report.\n")
+@@ -345,7 +379,7 @@ arg(monitor_ARG, '\0', "monitor", bool_VAL, 0, 0,
+     "Start (yes) or stop (no) monitoring an LV with dmeventd.\n"
+     "dmeventd monitors kernel events for an LV, and performs\n"
+     "automated maintenance for the LV in reponse to specific events.\n"
+-    "See dmeventd(8) for more information.\n")
++    "See \\fBdmeventd\\fP(8) for more information.\n")
+ 
+ arg(nameprefixes_ARG, '\0', "nameprefixes", 0, 0, 0,
+     "Add an \"LVM2_\" prefix plus the field name to the output. Useful\n"
+@@ -552,7 +586,7 @@ arg(shared_ARG, '\0', "shared", 0, 0, 0,
+     "manager is running. This allows multiple hosts to share a VG on shared\n"
+     "devices. lvmlockd and a lock manager must be configured and running.\n"
+     "(A shared VG using lvmlockd is different from a clustered VG using clvmd.)\n"
+-    "See lvmlockd(8) for more information about shared VGs.\n"
++    "See \\fBlvmlockd\\fP(8) for more information about shared VGs.\n"
+     "#vgs\n"
+     "#lvs\n"
+     "#pvs\n"
+@@ -562,7 +596,7 @@ arg(shared_ARG, '\0', "shared", 0, 0, 0,
+     "#pvdisplay\n"
+     "Report/display shared VGs that would otherwise be skipped when\n"
+     "lvmlockd is not being used on the host.\n"
+-    "See lvmlockd(8) for more information about shared VGs.\n")
++    "See \\fBlvmlockd\\fP(8) for more information about shared VGs.\n")
+ 
+ arg(sinceversion_ARG, '\0', "sinceversion", string_VAL, 0, 0,
+     "Specify an LVM version in x.y.z format where x is the major version,\n"
+@@ -644,12 +678,12 @@ arg(systemid_ARG, '\0', "systemid", string_VAL, 0, 0,
+     "the host creating it. Using this option requires caution because the\n"
+     "system ID of the new VG may not match the system ID of the host running\n"
+     "the command, leaving the VG inaccessible to the host.\n"
+-    "See lvmsystemid(7) for more information.\n"
++    "See \\fBlvmsystemid\\fP(7) for more information.\n"
+     "#vgchange\n"
+     "Changes the system ID of the VG.  Using this option requires caution\n"
+     "because the VG may become foreign to the host running the command,\n"
+     "leaving the host unable to access it.\n"
+-    "See lvmsystemid(7) for more information.\n")
++    "See \\fBlvmsystemid\\fP(7) for more information.\n")
+ 
+ arg(thinpool_ARG, '\0', "thinpool", lv_VAL, 0, 0,
+     "The name of a thin pool LV.\n")
+@@ -808,6 +842,9 @@ arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_VAL, 0, 0, NULL)
+  * ... and now the short args.
+  */
+ arg(activate_ARG, 'a', "activate", activation_VAL, 0, 0,
++    "#pvscan\n"
++    "Auto-activate LVs in a VG when the PVs scanned have completed the VG.\n"
++    "(Only \\fBay\\fP is applicable.)\n"
+     "#lvchange\n"
+     "#vgchange\n"
+     "Change the active state of LVs.\n"
+@@ -828,8 +865,8 @@ arg(activate_ARG, 'a', "activate", activation_VAL, 0, 0,
+     "if the list is set but empty, no LVs match.\n"
+     "Autoactivation should be used during system boot to make it possible\n"
+     "to select which LVs should be automatically activated by the system.\n"
+-    "See lvmlockd(8) for more information about activation options \\fBey\\fP and \\fBsy\\fP for shared VGs.\n"
+-    "See clvmd(8) for more information about activation options \\fBey\\fP, \\fBsy\\fP, \\fBly\\fP and \\fBln\\fP for clustered VGs.\n"
++    "See \\fBlvmlockd\\fP(8) for more information about activation options \\fBey\\fP and \\fBsy\\fP for shared VGs.\n"
++    "See \\fBclvmd\\fP(8) for more information about activation options \\fBey\\fP, \\fBsy\\fP, \\fBly\\fP and \\fBln\\fP for clustered VGs.\n"
+     "#lvcreate\n"
+     "Controls the active state of the new LV.\n"
+     "\\fBy\\fP makes the LV active, or available.\n"
+@@ -842,12 +879,16 @@ arg(activate_ARG, 'a', "activate", activation_VAL, 0, 0,
+     "If autoactivation \\fBay\\fP is used, the LV is only activated\n"
+     "if it matches an item in lvm.conf activation/auto_activation_volume_list.\n"
+     "\\fBay\\fP implies --zero n and --wipesignatures n.\n"
+-    "See lvmlockd(8) for more information about activation options for shared VGs.\n"
+-    "See clvmd(8) for more information about activation options for clustered VGs.\n")
++    "See \\fBlvmlockd\\fP(8) for more information about activation options for shared VGs.\n"
++    "See \\fBclvmd\\fP(8) for more information about activation options for clustered VGs.\n")
+ 
+ arg(all_ARG, 'a', "all", 0, 0, 0,
+     "#vgreduce\n"
+     "Removes all empty PVs if none are named on the command line.\n"
++    "#pvchange\n"
++    "Change all visible PVs.\n"
++    "#vgimport\n"
++    "Import all visible VGs.\n"
+     "#lvscan\n"
+     "#lvdisplay\n"
+     "#lvs\n"
+@@ -863,7 +904,7 @@ arg(all_ARG, 'a', "all", 0, 0, 0,
+ 
+ arg(autobackup_ARG, 'A', "autobackup", bool_VAL, 0, 0,
+     "Specifies if metadata should be backed up automatically after a change.\n"
+-    "Enabling this is strongly advised! See vgcfgbackup(8) for more information.\n")
++    "Enabling this is strongly advised! See \\fBvgcfgbackup\\fP(8) for more information.\n")
+ 
+ arg(activevolumegroups_ARG, 'A', "activevolumegroups", 0, 0, 0,
+     "Only select active VGs. The VG is considered active\n"
+@@ -907,20 +948,20 @@ arg(clustered_ARG, 'c', "clustered", bool_VAL, 0, 0,
+     "This allows multiple hosts to share a VG on shared devices.\n"
+     "clvmd and a lock manager must be configured and running.\n"
+     "(A clustered VG using clvmd is different from a shared VG using lvmlockd.)\n"
+-    "See clvmd(8) for more information about clustered VGs.\n"
++    "See \\fBclvmd\\fP(8) for more information about clustered VGs.\n"
+     "#vgchange\n"
+     "Change the clustered property of a VG using clvmd.\n"
+-    "See clvmd(8) for more information about clustered VGs.\n"
++    "See \\fBclvmd\\fP(8) for more information about clustered VGs.\n"
+     "#vgsplit\n"
+     "Specifies the clustered property of the new VG.\n")
+ 
+ arg(colon_ARG, 'c', "colon", 0, 0, 0,
+     "Generate colon separated output for easier parsing in scripts or programs.\n"
+-    "Also see vgs(8) which provides considerably more control over the output.\n")
++    "Also see \\fBvgs\\fP(8) which provides considerably more control over the output.\n")
+ 
+ arg(columns_ARG, 'C', "columns", 0, 0, 0,
+-    "Display output in columns, the equivalent of vgs(8).\n"
+-    "Options listed are the same as options given in vgs(8).\n")
++    "Display output in columns, the equivalent of \\fBvgs\\fP(8).\n"
++    "Options listed are the same as options given in \\fBvgs\\fP(8).\n")
+ 
+ arg(contiguous_ARG, 'C', "contiguous", bool_VAL, 0, 0,
+     "Sets or resets the contiguous allocation policy for LVs.\n"
+@@ -1208,7 +1249,7 @@ arg(options_ARG, 'o', "options", string_VAL, ARG_GROUPABLE, 0,
+     "\\fBseg_all\\fP all LV segment fields, and\n"
+     "\\fBpvseg_all\\fP all PV segment columns.\n"
+     "See the lvm.conf report section for more config options.\n"
+-    "See lvmreport(7) for more information about reporting.\n")
++    "See \\fBlvmreport\\fP(7) for more information about reporting.\n")
+ 
+ arg(sort_ARG, 'O', "sort", string_VAL, ARG_GROUPABLE, 0,
+     "Comma-separated ordered list of columns to sort by. Replaces the default\n"
+@@ -1348,11 +1389,11 @@ arg(uuidstr_ARG, 'u', "uuid", string_VAL, 0, 0,
+     "Specify a UUID for the device.\n"
+     "Without this option, a random UUID is generated.\n"
+     "This option is needed before restoring a backup of LVM metadata\n"
+-    "onto a replacement device; see vgcfgrestore(8). As such, use of\n"
++    "onto a replacement device; see \\fBvgcfgrestore\\fP(8). As such, use of\n"
+     "--restorefile is compulsory unless the --norestorefile is used.\n"
+     "All PVs must have unique UUIDs, and LVM will prevent certain operations\n"
+     "if multiple devices are seen with the same UUID.\n"
+-    "See vgimportclone(8) for more information.\n")
++    "See \\fBvgimportclone\\fP(8) for more information.\n")
+ 
+ /* Not used */
+ arg(uuidlist_ARG, 'U', "uuidlist", 0, 0, 0, NULL)
+diff --git a/tools/command-lines.in b/tools/command-lines.in
+index 2d9e48e..7f9c31f 100644
+--- a/tools/command-lines.in
++++ b/tools/command-lines.in
+@@ -1417,7 +1417,7 @@ DESC: Display PV information.
+ 
+ pvscan --cache_long
+ OO: --ignorelockingfailure, --reportformat ReportFmt, --background,
+---activate Active, --major Number, --minor Number
++--activate ay, --major Number, --minor Number
+ OP: PV|String ...
+ ID: pvscan_cache
+ DESC: Populate the lvmetad cache by scanning PVs.
+diff --git a/tools/command.c b/tools/command.c
+index 0f69bbb..a08d068 100644
+--- a/tools/command.c
++++ b/tools/command.c
+@@ -40,6 +40,8 @@
+  */
+ #ifdef MAN_PAGE_GENERATOR
+ 
++#define stack
++
+ struct cmd_context {
+ 	void *libmem;
+ };
+@@ -699,9 +701,16 @@ static void set_opt_def(struct cmd_context *cmdtool, struct command *cmd, char *
+ 		if (val_enum == constnum_VAL)
+ 			def->num = (uint64_t)atoi(name);
+ 
+-		if (val_enum == conststr_VAL)
++		if (val_enum == conststr_VAL) {
+ 			def->str = dm_pool_strdup(cmdtool->libmem, name);
+ 
++			if (!def->str) {
++				/* FIXME */
++				stack;
++				return;
++			}
++		}
++
+ 		if (val_enum == lv_VAL) {
+ 			if (strchr(name, '_'))
+ 				def->lvt_bits = lv_to_bits(cmd, name);
+@@ -1416,6 +1425,12 @@ int define_commands(struct cmd_context *cmdtool, const char *run_name)
+ 			cmd_count++;
+ 			cmd->name = dm_pool_strdup(cmdtool->libmem, name);
+ 
++			if (!cmd->name) {
++				/* FIXME */
++				stack;
++				return 0;
++			}
++
+ 			if (run_name && strcmp(run_name, name)) {
+ 				skip = 1;
+ 				prev_was_oo_def = 0;
+@@ -1447,6 +1462,10 @@ int define_commands(struct cmd_context *cmdtool, const char *run_name)
+ 					memset(newdesc, 0, newlen);
+ 					snprintf(newdesc, newlen, "%s %s", cmd->desc, desc);
+ 					cmd->desc = newdesc;
++				} else {
++					/* FIXME */
++					stack;
++					return 0;
+ 				}
+ 			} else
+ 				cmd->desc = desc;
+@@ -1465,6 +1484,12 @@ int define_commands(struct cmd_context *cmdtool, const char *run_name)
+ 
+ 		if (is_id_line(line_argv[0]) && cmd) {
+ 			cmd->command_id = dm_pool_strdup(cmdtool->libmem, line_argv[1]);
++
++			if (!cmd->command_id) {
++				/* FIXME */
++				stack;
++				return 0;
++			}
+ 			continue;
+ 		}
+ 
+diff --git a/tools/lvchange.c b/tools/lvchange.c
+index 660570a..92161e2 100644
+--- a/tools/lvchange.c
++++ b/tools/lvchange.c
+@@ -1238,6 +1238,16 @@ static int _lvchange_properties_check(struct cmd_context *cmd,
+ 				     int lv_is_named_arg)
+ {
+ 	if (!lv_is_visible(lv)) {
++		/*
++		 * Exceptions where we allow lvchange properties on
++		 * a hidden sub lv.
++		 *
++		 * lv_is_thin_pool_data: e.g. needed when the data sublv
++		 * is a cache lv and we need to change cache properties.
++		 */
++		if (lv_is_thin_pool_data(lv))
++			return 1;
++
+ 		if (lv_is_named_arg)
+ 			log_error("Operation not permitted on hidden LV %s.", display_lvname(lv));
+ 		return 0;
+diff --git a/tools/lvcreate.c b/tools/lvcreate.c
+index f775290..f464896 100644
+--- a/tools/lvcreate.c
++++ b/tools/lvcreate.c
+@@ -251,6 +251,7 @@ static int _update_extents_params(struct volume_group *vg,
+ 	uint32_t size_rest;
+ 	uint32_t stripesize_extents;
+ 	uint32_t extents;
++	uint32_t base_calc_extents;
+ 
+ 	if (lcp->size &&
+ 	    !(lp->extents = extents_from_size(vg->cmd, lcp->size,
+@@ -275,17 +276,17 @@ static int _update_extents_params(struct volume_group *vg,
+ 
+ 	switch (lcp->percent) {
+ 		case PERCENT_VG:
+-			extents = percent_of_extents(lp->extents, vg->extent_count, 0);
++			extents = percent_of_extents(lp->extents, base_calc_extents = vg->extent_count, 0);
+ 			break;
+ 		case PERCENT_FREE:
+-			extents = percent_of_extents(lp->extents, vg->free_count, 0);
++			extents = percent_of_extents(lp->extents, base_calc_extents = vg->free_count, 0);
+ 			break;
+ 		case PERCENT_PVS:
+ 			if (lcp->pv_count) {
+ 				pv_extent_count = pv_list_extents_free(lp->pvh);
+-				extents = percent_of_extents(lp->extents, pv_extent_count, 0);
++				extents = percent_of_extents(lp->extents, base_calc_extents = pv_extent_count, 0);
+ 			} else
+-				extents = percent_of_extents(lp->extents, vg->extent_count, 0);
++				extents = percent_of_extents(lp->extents, base_calc_extents = vg->extent_count, 0);
+ 			break;
+ 		case PERCENT_LV:
+ 			log_error("Please express size as %%FREE%s, %%PVS or %%VG.",
+@@ -304,7 +305,7 @@ static int _update_extents_params(struct volume_group *vg,
+ 			}
+ 			/* Add whole metadata size estimation */
+ 			extents = cow_max_extents(origin_lv, lp->chunk_size) - origin_lv->le_count +
+-				percent_of_extents(lp->extents, origin_lv->le_count, 1);
++				percent_of_extents(lp->extents, base_calc_extents = origin_lv->le_count, 1);
+ 			break;
+ 		case PERCENT_NONE:
+ 			extents = lp->extents;
+@@ -314,10 +315,27 @@ static int _update_extents_params(struct volume_group *vg,
+ 			return 0;
+ 	}
+ 
+-	if (lcp->percent) {
++	if (lcp->percent != PERCENT_NONE) {
+ 		/* FIXME Don't do the adjustment for parallel allocation with PERCENT_ORIGIN! */
+ 		lp->approx_alloc = 1;
+-		log_verbose("Converted %" PRIu32 "%%%s into %" PRIu32 " extents.", lp->extents, get_percent_string(lcp->percent), extents);
++		if (!extents) {
++			log_error("Calculated size of logical volume is 0 extents. Needs to be larger.");
++			return 0;
++		}
++
++		/* For mirrors and raid with percentages based on physical extents, convert the total number of PEs 
++		 * into the number of logical extents per image (minimum 1) */
++		/* FIXME Handle all the supported raid layouts here based on already-known segtype. */
++		if ((lcp->percent != PERCENT_ORIGIN) && lp->mirrors) {
++			extents /= lp->mirrors;
++			if (!extents)
++				extents = 1;
++		}
++
++		log_verbose("Converted %" PRIu32 "%% of %s (%" PRIu32 ") extents into %" PRIu32 " (with mimages %" PRIu32 " and stripes %" PRIu32
++			    " for segtype %s).", lp->extents, get_percent_string(lcp->percent), base_calc_extents,
++			    extents, lp->mirrors, lp->stripes, lp->segtype->name);
++
+ 		lp->extents = extents;
+ 	}
+ 
+@@ -389,6 +407,11 @@ static int _update_extents_params(struct volume_group *vg,
+ 		}
+ 	}
+ 
++	if ((lcp->percent != PERCENT_NONE) && !lp->extents) {
++		log_error("Adjusted size of logical volume is 0 extents. Needs to be larger.");
++		return 0;
++	}
++
+ 	return 1;
+ }
+ 
+@@ -1170,6 +1193,13 @@ static int _determine_cache_argument(struct volume_group *vg,
+ 		lp->create_pool = 0;
+ 		lp->origin_name = NULL;
+ 	} else if (lv) {
++		if (arg_is_set(cmd, cachepool_ARG)) {
++			/* Argument of --cachepool has to be a cache-pool */
++			log_error("Logical volume %s is not a cache pool.",
++				  display_lvname(lv));
++			return 0;
++		}
++
+ 		/* Origin exists, create cache pool volume */
+ 		if (!validate_lv_cache_create_origin(lv))
+ 			return_0;
+diff --git a/tools/reporter.c b/tools/reporter.c
+index 980f39c..b9c4153 100644
+--- a/tools/reporter.c
++++ b/tools/reporter.c
+@@ -172,7 +172,7 @@ static int _do_lvs_with_info_and_status_single(struct cmd_context *cmd,
+ 	if (lv_is_merging_origin(lv)) {
+ 		if (!_check_merging_origin(lv, &status, &merged))
+ 		      goto_out;
+-		if (merged)
++		if (merged && lv_is_thin_volume(lv->snapshot->lv))
+ 			lv = lv->snapshot->lv;
+ 	}
+ 
+@@ -234,13 +234,13 @@ static int _do_segs_with_info_and_status_single(struct cmd_context *cmd,
+ 	if (lv_is_merging_origin(seg->lv)) {
+ 		if (!_check_merging_origin(seg->lv, &status, &merged))
+ 			goto_out;
+-		if (merged)
++		if (merged && lv_is_thin_volume(seg->lv->snapshot->lv))
+ 			seg = seg->lv->snapshot;
+ 	}
+ 
+ 	if (!report_object(sh ? : handle->custom_handle, sh != NULL,
+ 			   seg->lv->vg, seg->lv, NULL, seg, NULL, &status, NULL))
+-	goto_out;
++		goto_out;
+ 
+ 	r = ECMD_PROCESSED;
+ out:
+diff --git a/tools/toollib.c b/tools/toollib.c
+index f3cf4ca..e5a854f 100644
+--- a/tools/toollib.c
++++ b/tools/toollib.c
+@@ -1335,9 +1335,17 @@ int get_stripe_params(struct cmd_context *cmd, const struct segment_type *segtyp
+ 	return _validate_stripe_params(cmd, segtype, stripes, stripe_size);
+ }
+ 
+-static int _validate_cachepool_params(const char *name,
+-				      const struct dm_config_tree *settings)
++static int _validate_cachepool_params(const char *policy_name, cache_mode_t cache_mode)
+ {
++	/*
++	 * FIXME: it might be nice if cmd def rules could check option values,
++	 * then a rule could do this.
++	 */
++	if ((cache_mode == CACHE_MODE_WRITEBACK) && policy_name && !strcmp(policy_name, "cleaner")) {
++		log_error("Cache mode \"writeback\" is not compatible with cache policy \"cleaner\".");
++		return 0;
++	}
++
+ 	return 1;
+ }
+ 
+@@ -1371,6 +1379,9 @@ int get_cache_params(struct cmd_context *cmd,
+ 
+ 	*name = arg_str_value(cmd, cachepolicy_ARG, NULL);
+ 
++	if (!_validate_cachepool_params(*name, *cache_mode))
++		goto_out;
++
+ 	dm_list_iterate_items(group, &cmd->arg_value_groups) {
+ 		if (!grouped_arg_is_set(group->arg_values, cachesettings_ARG))
+ 			continue;
+@@ -1401,9 +1412,6 @@ int get_cache_params(struct cmd_context *cmd,
+ 			cn->child = result->root;
+ 			result->root = cn;
+ 		}
+-
+-		if (!_validate_cachepool_params(*name, result))
+-			goto_out;
+ 	}
+ 
+ 	ok = 1;
diff --git a/SOURCES/lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection.patch b/SOURCES/lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection.patch
index 949983d..028db8e 100644
--- a/SOURCES/lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection.patch
+++ b/SOURCES/lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection.patch
@@ -4,10 +4,10 @@
  3 files changed, 13 insertions(+), 14 deletions(-)
 
 diff --git a/configure b/configure
-index 8253bfc..587b978 100755
+index ffef9b9..1e4e744 100755
 --- a/configure
 +++ b/configure
-@@ -11951,12 +11951,12 @@ if test -n "$BLKID_CFLAGS"; then
+@@ -12246,12 +12246,12 @@ if test -n "$BLKID_CFLAGS"; then
      pkg_cv_BLKID_CFLAGS="$BLKID_CFLAGS"
   elif test -n "$PKG_CONFIG"; then
      if test -n "$PKG_CONFIG" && \
@@ -23,7 +23,7 @@ index 8253bfc..587b978 100755
  		      test "x$?" != "x0" && pkg_failed=yes
  else
    pkg_failed=yes
-@@ -11968,12 +11968,12 @@ if test -n "$BLKID_LIBS"; then
+@@ -12263,12 +12263,12 @@ if test -n "$BLKID_LIBS"; then
      pkg_cv_BLKID_LIBS="$BLKID_LIBS"
   elif test -n "$PKG_CONFIG"; then
      if test -n "$PKG_CONFIG" && \
@@ -39,7 +39,7 @@ index 8253bfc..587b978 100755
  		      test "x$?" != "x0" && pkg_failed=yes
  else
    pkg_failed=yes
-@@ -11994,9 +11994,9 @@ else
+@@ -12289,9 +12289,9 @@ else
          _pkg_short_errors_supported=no
  fi
          if test $_pkg_short_errors_supported = yes; then
@@ -51,7 +51,7 @@ index 8253bfc..587b978 100755
          fi
  	# Put the nasty error message in config.log where it belongs
  	echo "$BLKID_PKG_ERRORS" >&5
-@@ -12004,7 +12004,7 @@ fi
+@@ -12299,7 +12299,7 @@ fi
  	if test "$BLKID_WIPING" = maybe; then
  				BLKID_WIPING=no
  			   else
@@ -60,7 +60,7 @@ index 8253bfc..587b978 100755
  			   fi
  elif test $pkg_failed = untried; then
       	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-@@ -12012,7 +12012,7 @@ $as_echo "no" >&6; }
+@@ -12307,7 +12307,7 @@ $as_echo "no" >&6; }
  	if test "$BLKID_WIPING" = maybe; then
  				BLKID_WIPING=no
  			   else
@@ -70,10 +70,10 @@ index 8253bfc..587b978 100755
  else
  	BLKID_CFLAGS=$pkg_cv_BLKID_CFLAGS
 diff --git a/configure.in b/configure.in
-index 33b5c76..9ed6226 100644
+index 2ff4f99..7d2baa0 100644
 --- a/configure.in
 +++ b/configure.in
-@@ -1302,12 +1302,12 @@ AC_MSG_RESULT($BLKID_WIPING)
+@@ -1319,12 +1319,12 @@ AC_MSG_RESULT($BLKID_WIPING)
  
  if test "$BLKID_WIPING" != no; then
  	pkg_config_init
@@ -89,10 +89,10 @@ index 33b5c76..9ed6226 100644
  	if test "$BLKID_WIPING" = yes; then
  		BLKID_PC="blkid"
 diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
-index 0246c09..bae984a 100644
+index 325b66b..cf7f992 100644
 --- a/lib/device/dev-type.c
 +++ b/lib/device/dev-type.c
-@@ -703,8 +703,7 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
+@@ -713,8 +713,7 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
  						 BLKID_SUBLKS_TYPE |
  						 BLKID_SUBLKS_USAGE |
  						 BLKID_SUBLKS_VERSION |
diff --git a/SOURCES/lvm2-revert-fix-for-lvconvert-repair-for-raid-lvs.patch b/SOURCES/lvm2-revert-fix-for-lvconvert-repair-for-raid-lvs.patch
deleted file mode 100644
index 77869ae..0000000
--- a/SOURCES/lvm2-revert-fix-for-lvconvert-repair-for-raid-lvs.patch
+++ /dev/null
@@ -1,323 +0,0 @@
- WHATS_NEW                                     |   1 -
- daemons/dmeventd/plugins/raid/dmeventd_raid.c |  42 +++--------
- lib/metadata/lv.c                             |   7 ++
- lib/metadata/raid_manip.c                     |   2 +-
- test/shell/lvconvert-repair-raid.sh           | 104 ++------------------------
- tools/lvconvert.c                             |  19 +++++
- 6 files changed, 41 insertions(+), 134 deletions(-)
-
-diff --git a/WHATS_NEW b/WHATS_NEW
-index 25f6742..977e578 100644
---- a/WHATS_NEW
-+++ b/WHATS_NEW
-@@ -3,7 +3,6 @@ Version 2.02.166 - 26th September 2016
-   Fix lvm2-activation-generator to read all LVM2 config sources. (2.02.155)
-   Fix lvchange-rebuild-raid.sh to cope with older target versions.
-   Use dm_config_parse_without_dup_node_check() to speedup metadata reading.
--  Fix lvconvert --repair regression
-   Fix reported origin lv field for cache volumes. (2.02.133)
-   Always specify snapshot cow LV for monitoring not internal LV. (2.02.165)
-   Fix lvchange --discard|--zero for active thin-pool.
-diff --git a/daemons/dmeventd/plugins/raid/dmeventd_raid.c b/daemons/dmeventd/plugins/raid/dmeventd_raid.c
-index bec594a..770fbc6 100644
---- a/daemons/dmeventd/plugins/raid/dmeventd_raid.c
-+++ b/daemons/dmeventd/plugins/raid/dmeventd_raid.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (C) 2005-2016 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
-  *
-  * This file is part of LVM2.
-  *
-@@ -13,20 +13,14 @@
-  */
- 
- #include "lib.h"
--#include "defaults.h"
- #include "dmeventd_lvm.h"
- #include "libdevmapper-event.h"
- 
--/* Hold enough elements for the mximum number of RAID images */
--#define	RAID_DEVS_ELEMS	((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
--
- struct dso_state {
- 	struct dm_pool *mem;
- 	char cmd_lvscan[512];
- 	char cmd_lvconvert[512];
--	uint64_t raid_devs[RAID_DEVS_ELEMS];
- 	int failed;
--	int warned;
- };
- 
- DM_EVENT_LOG_FN("raid")
-@@ -37,39 +31,20 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
- {
- 	struct dm_status_raid *status;
- 	const char *d;
--	int dead = 0, r = 1;
- 
- 	if (!dm_get_status_raid(state->mem, params, &status)) {
- 		log_error("Failed to process status line for %s.", device);
- 		return 0;
- 	}
- 
--	d = status->dev_health;
--	while ((d = strchr(d, 'D'))) {
--		uint32_t dev = (uint32_t)(d - status->dev_health);
--
--		if (!(state->raid_devs[dev / 64] & (1 << (dev % 64))))
--			log_error("Device #%u of %s array, %s, has failed.",
--				  dev, status->raid_type, device);
--
--		state->raid_devs[dev / 64] |= (1 << (dev % 64));
--		d++;
--		dead = 1;
--	}
--
--	if (dead) {
--		if (status->insync_regions < status->total_regions) {
--			if (!state->warned)
--				log_warn("WARNING: waiting for resynchronization to finish "
--					 "before initiating repair on RAID device %s", device);
--
--			state->warned = 1;
--			goto out; /* Not yet done syncing with accessible devices */
--		}
--
-+	if ((d = strchr(status->dev_health, 'D'))) {
- 		if (state->failed)
- 			goto out; /* already reported */
- 
-+		log_error("Device #%d of %s array, %s, has failed.",
-+			  (int)(d - status->dev_health),
-+			  status->raid_type, device);
-+
- 		state->failed = 1;
- 		if (!dmeventd_lvm2_run_with_lock(state->cmd_lvscan))
- 			log_warn("WARNING: Re-scan of RAID device %s failed.", device);
-@@ -77,7 +52,8 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
- 		/* if repair goes OK, report success even if lvscan has failed */
- 		if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) {
- 			log_info("Repair of RAID device %s failed.", device);
--			r = 0;
-+			dm_pool_free(state->mem, status);
-+			return 0;
- 		}
- 	} else {
- 		state->failed = 0;
-@@ -88,7 +64,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
- out:
- 	dm_pool_free(state->mem, status);
- 
--	return r;
-+	return 1;
- }
- 
- void process_event(struct dm_task *dmt,
-diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
-index 70036f9..53a1044 100644
---- a/lib/metadata/lv.c
-+++ b/lib/metadata/lv.c
-@@ -988,6 +988,7 @@ int lv_mirror_image_in_sync(const struct logical_volume *lv)
- int lv_raid_image_in_sync(const struct logical_volume *lv)
- {
- 	unsigned s;
-+	dm_percent_t percent;
- 	char *raid_health;
- 	struct lv_segment *seg, *raid_seg = NULL;
- 
-@@ -1017,6 +1018,12 @@ int lv_raid_image_in_sync(const struct logical_volume *lv)
- 		return 0;
- 	}
- 
-+	if (!lv_raid_percent(raid_seg->lv, &percent))
-+		return_0;
-+
-+	if (percent == DM_PERCENT_100)
-+		return 1;
-+
- 	/* Find out which sub-LV this is. */
- 	for (s = 0; s < raid_seg->area_count; s++)
- 		if (seg_lv(raid_seg, s) == lv)
-diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
-index deb88a2..e5fdf4f 100644
---- a/lib/metadata/raid_manip.c
-+++ b/lib/metadata/raid_manip.c
-@@ -3658,7 +3658,7 @@ static int _lv_raid_rebuild_or_replace(struct logical_volume *lv,
- 		return 0;
- 	}
- 
--	if (!_raid_in_sync(lv)) {
-+	if (!mirror_in_sync() && !_raid_in_sync(lv)) {
- 		log_error("Unable to replace devices in %s/%s while it is"
- 			  " not in-sync.", lv->vg->name, lv->name);
- 		return 0;
-diff --git a/test/shell/lvconvert-repair-raid.sh b/test/shell/lvconvert-repair-raid.sh
-index b51d8fe..1ef91c4 100644
---- a/test/shell/lvconvert-repair-raid.sh
-+++ b/test/shell/lvconvert-repair-raid.sh
-@@ -22,52 +22,11 @@ aux lvmconf 'allocation/maximise_cling = 0' \
- 
- aux prepare_vg 8
- 
--function delay
--{
--	for d in $(< DEVICES)
--	do
--		aux delay_dev "$d" 0 $1 $(get first_extent_sector "$d")
--	done
--}
--
- # It's possible small raid arrays do have problems with reporting in-sync.
- # So try bigger size
--RAID_SIZE=32
--
--# Fast sync and repair afterwards
--delay 0
--
--# RAID1 dual-leg single replace after initial sync
--lvcreate --type raid1 -m 1 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2"
--aux wait_for_sync $vg $lv1
--aux disable_dev "$dev2"
--lvconvert -y --repair $vg/$lv1
--vgreduce --removemissing $vg
--aux enable_dev "$dev2"
--vgextend $vg "$dev2"
--lvremove -ff $vg/$lv1
--
--# Delayed sync to allow for repair during rebuild
--delay 50
--
--# RAID1 triple-leg single replace during initial sync
--lvcreate --type raid1 -m 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3"
--aux disable_dev "$dev2" "$dev3"
--not lvconvert -y --repair $vg/$lv1
--aux wait_for_sync $vg $lv1
--lvconvert -y --repair $vg/$lv1
--vgreduce --removemissing $vg
--aux enable_dev "$dev2" "$dev3"
--vgextend $vg "$dev2" "$dev3"
--lvremove -ff $vg/$lv1
--
--
--# Larger RAID size possible for striped RAID
- RAID_SIZE=64
- 
--# Fast sync and repair afterwards
--delay 0
--# RAID5 single replace after initial sync
-+# RAID5 single replace
- lvcreate --type raid5 -i 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3"
- aux wait_for_sync $vg $lv1
- aux disable_dev "$dev3"
-@@ -75,69 +34,16 @@ lvconvert -y --repair $vg/$lv1
- vgreduce --removemissing $vg
- aux enable_dev "$dev3"
- vgextend $vg "$dev3"
--lvremove -ff $vg/$lv1
-+lvremove -ff $vg
- 
--# Delayed sync to allow for repair during rebuild
--delay 50
--
--# RAID5 single replace during initial sync
--lvcreate --type raid5 -i 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3"
--aux disable_dev "$dev3"
--not lvconvert -y --repair $vg/$lv1
--aux wait_for_sync $vg $lv1
--lvconvert -y --repair $vg/$lv1
--vgreduce --removemissing $vg
--aux enable_dev "$dev3"
--vgextend $vg "$dev3"
--lvremove -ff $vg/$lv1
--
--# Fast sync and repair afterwards
--delay 0
--
--# RAID6 double replace after initial sync
-+# RAID6 double replace
- lvcreate --type raid6 -i 3 -L $RAID_SIZE -n $lv1 $vg \
-     "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
- aux wait_for_sync $vg $lv1
- aux disable_dev "$dev4" "$dev5"
- lvconvert -y --repair $vg/$lv1
- vgreduce --removemissing $vg
--aux enable_dev "$dev4" "$dev5"
--vgextend $vg "$dev4" "$dev5"
--lvremove -ff $vg/$lv1
--
--# Delayed sync to allow for repair during rebuild
--delay 50
--
--# RAID6 single replace after initial sync
--lvcreate --type raid6 -i 3 -L $RAID_SIZE -n $lv1 $vg \
--    "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
--aux disable_dev "$dev4"
--not lvconvert -y --repair $vg/$lv1
--delay 0 # Fast sync and repair afterwards
--aux disable_dev "$dev4" # Need to disable again after changing delay
--aux wait_for_sync $vg $lv1
--lvconvert -y --repair $vg/$lv1
--vgreduce --removemissing $vg
- aux enable_dev "$dev4"
--vgextend $vg "$dev4"
--lvremove -ff $vg/$lv1
--
--# Delayed sync to allow for repair during rebuild
--delay 50
--
--# RAID10 single replace after initial sync
--lvcreate --type raid10 -m 1 -i 2 -L $RAID_SIZE -n $lv1 $vg \
--    "$dev1" "$dev2" "$dev3" "$dev4"
--aux disable_dev "$dev4"
--not lvconvert -y --repair $vg/$lv1
--delay 0 # Fast sync and repair afterwards
--aux disable_dev "$dev4" # Need to disable again after changing delay
--aux disable_dev "$dev1"
--aux wait_for_sync $vg $lv1
--lvconvert -y --repair $vg/$lv1
--vgreduce --removemissing $vg
--aux enable_dev "$dev4"
--vgextend $vg "$dev4"
--lvremove -ff $vg/$lv1
--
-+aux enable_dev "$dev5"
-+vgextend $vg "$dev4" "$dev5"
- vgremove -ff $vg
-diff --git a/tools/lvconvert.c b/tools/lvconvert.c
-index 3607247..d1d21b6 100644
---- a/tools/lvconvert.c
-+++ b/tools/lvconvert.c
-@@ -1826,6 +1826,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
- 	struct dm_list *failed_pvs;
- 	struct cmd_context *cmd = lv->vg->cmd;
- 	struct lv_segment *seg = first_seg(lv);
-+	dm_percent_t sync_percent;
- 
- 	if (_linear_type_requested(lp->type_str)) {
- 		if (arg_is_set(cmd, mirrors_ARG) && (arg_uint_value(cmd, mirrors_ARG, 0) != 0)) {
-@@ -1973,6 +1974,24 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
- 			return 0;
- 		}
- 
-+		if (!lv_raid_percent(lv, &sync_percent)) {
-+			log_error("Unable to determine sync status of %s.",
-+				  display_lvname(lv));
-+			return 0;
-+		}
-+
-+		if (sync_percent != DM_PERCENT_100) {
-+			log_warn("WARNING: %s is not in-sync.", display_lvname(lv));
-+			log_warn("WARNING: Portions of the array may be unrecoverable.");
-+
-+			/*
-+			 * The kernel will not allow a device to be replaced
-+			 * in an array that is not in-sync unless we override
-+			 * by forcing the array to be considered "in-sync".
-+			 */
-+			init_mirror_in_sync(1);
-+		}
-+
- 		_lvconvert_raid_repair_ask(cmd, lp, &replace);
- 
- 		if (replace) {
diff --git a/SOURCES/lvm2-rhel7-fix-StartLimitInterval.patch b/SOURCES/lvm2-rhel7-fix-StartLimitInterval.patch
new file mode 100644
index 0000000..e5f79e2
--- /dev/null
+++ b/SOURCES/lvm2-rhel7-fix-StartLimitInterval.patch
@@ -0,0 +1,23 @@
+ scripts/lvm2_pvscan_systemd_red_hat@.service.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/lvm2_pvscan_systemd_red_hat@.service.in b/scripts/lvm2_pvscan_systemd_red_hat@.service.in
+index 0989590..9e3d19c 100644
+--- a/scripts/lvm2_pvscan_systemd_red_hat@.service.in
++++ b/scripts/lvm2_pvscan_systemd_red_hat@.service.in
+@@ -2,7 +2,6 @@
+ Description=LVM2 PV scan on device %i
+ Documentation=man:pvscan(8)
+ DefaultDependencies=no
+-StartLimitInterval=0
+ BindsTo=dev-block-%i.device
+ Requires=lvm2-lvmetad.socket
+ After=lvm2-lvmetad.socket lvm2-lvmetad.service
+@@ -14,3 +13,4 @@ Type=oneshot
+ RemainAfterExit=yes
+ ExecStart=@sbindir@/lvm pvscan --cache --activate ay %i
+ ExecStop=@sbindir@/lvm pvscan --cache %i
++StartLimitInterval=0
+-- 
+1.8.3.1
+
diff --git a/SOURCES/lvm2-rhel7.patch b/SOURCES/lvm2-rhel7.patch
index b029dce..7bceb41 100644
--- a/SOURCES/lvm2-rhel7.patch
+++ b/SOURCES/lvm2-rhel7.patch
@@ -1,18 +1,18 @@
  VERSION    | 2 +-
  VERSION_DM | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-) 
+ 2 files changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/VERSION b/VERSION
-index dd4e60e..39d6c15 100644
+index 1f63cd7..0b41bd1 100644
 --- a/VERSION
 +++ b/VERSION
 @@ -1 +1 @@
--2.02.166(2) (2016-09-26)
-+2.02.166(2)-RHEL7 (2016-11-16)
+-2.02.171(2) (2017-05-03)
++2.02.171(2)-RHEL7 (2017-05-03)
 diff --git a/VERSION_DM b/VERSION_DM
-index d53f47a..005fbd4 100644
+index 030d9c2..56b50a2 100644
 --- a/VERSION_DM
 +++ b/VERSION_DM
 @@ -1 +1 @@
--1.02.135 (2016-09-26)
-+1.02.135-RHEL7 (2016-11-16)
+-1.02.140 (2017-05-03)
++1.02.140-RHEL7 (2017-05-03)
diff --git a/SOURCES/lvm2-set-default-preferred_names.patch b/SOURCES/lvm2-set-default-preferred_names.patch
index 1c44605..c545662 100644
--- a/SOURCES/lvm2-set-default-preferred_names.patch
+++ b/SOURCES/lvm2-set-default-preferred_names.patch
@@ -3,7 +3,7 @@
  2 files changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/conf/example.conf.in b/conf/example.conf.in
-index c0afcb7..ec12918 100644
+index ed34b91..b9fe1d9 100644
 --- a/conf/example.conf.in
 +++ b/conf/example.conf.in
 @@ -106,7 +106,7 @@ devices {
@@ -16,10 +16,10 @@ index c0afcb7..ec12918 100644
  	# Configuration option devices/filter.
  	# Limit the block devices that are used by LVM commands.
 diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
-index 9017043..c06b6f0 100644
+index 3b0eebb..9a87e20 100644
 --- a/lib/config/config_settings.h
 +++ b/lib/config/config_settings.h
-@@ -205,7 +205,7 @@ cfg(devices_external_device_info_source_CFG, "external_device_info_source", devi
+@@ -211,7 +211,7 @@ cfg(devices_external_device_info_source_CFG, "external_device_info_source", devi
  	"    compiled with udev support.\n"
  	"#\n")
  
diff --git a/SPECS/lvm2.spec b/SPECS/lvm2.spec
index 4ca2dff..279c607 100644
--- a/SPECS/lvm2.spec
+++ b/SPECS/lvm2.spec
@@ -1,4 +1,4 @@
-%global device_mapper_version 1.02.135
+%global device_mapper_version 1.02.140
 
 %global enable_cache 1
 %global enable_cluster 1
@@ -8,6 +8,7 @@
 %global enable_lvmpolld 1
 %global enable_python 1
 %global enable_thin 1
+%global enable_dmfilemapd 1
 
 %global systemd_version 189-3
 %global dracut_version 002-18
@@ -15,22 +16,22 @@
 %global bash_version 4.0
 %global corosync_version 1.99.9-1
 %global resource_agents_version 3.9.5-25
-%global dlm_version 3.99.1-1
+%global dlm_version 4.0.6-2
 %global libselinux_version 1.30.19-4
-%global persistent_data_version 0.6.3-1
+%global persistent_data_version 0.7.0-0.1.rc6
 %global sanlock_version 3.3.0-1
 
 %global enable_lockd_sanlock %{enable_lvmlockd}
 %global enable_lockd_dlm %{enable_lvmlockd}
 
 %if 0%{?rhel}
-  %ifnarch i686 x86_64 s390x
+  %ifnarch i686 x86_64 ppc64le s390x
     %global enable_cluster 0
     %global enable_cmirror 0
     %global enable_lockd_dlm 0
   %endif
 
-  %ifnarch x86_64 ppc64le ppc64 aarch64
+  %ifnarch x86_64 ppc64 aarch64
     %global enable_lockd_sanlock 0
   %endif
 %endif
@@ -50,8 +51,8 @@
 Summary: Userland logical volume management tools 
 Name: lvm2
 Epoch: 7
-Version: 2.02.166
-Release: 1%{?dist}.5
+Version: 2.02.171
+Release: 8%{?dist}
 License: GPLv2
 Group: System Environment/Base
 URL: http://sources.redhat.com/lvm2
@@ -61,14 +62,15 @@ Patch1: lvm2-set-default-preferred_names.patch
 Patch2: lvm2-fix-libdm-versioning-for-dm_tree_node_size_changed-symbol.patch
 Patch3: lvm2-drop-unavailable-libblkid-2_24-BLKID_SUBLKS_BADCSUM-for-signature-detection.patch
 Patch4: lvm2-default-allow-changes-with-duplicate-pvs.patch
-Patch5: lvm2-revert-fix-for-lvconvert-repair-for-raid-lvs.patch
-Patch6: lvm2-2_02_167-disable-lvconvert-of-thin-pool-to-raid-while-active.patch
-Patch7: lvm2-2_02_167-fix-inability-of-lvconvert-repair-for-cache-raid-volumes.patch
-Patch8: lvm2-2_02_167-fix-raid4-coversion-from-striped.patch
-Patch9: lvm2-2_02_167-prevent-raid4-creation-and-conversion-on-non-supporting-kernels.patch
-Patch10: lvm2-2_02_169-fix-segfault-in-lvmetad-from-missing-null-in-daemon_reply_simple.patch
-Patch11: lvm2-2_02_169-clvmd-add-mutex-protection-for-cpg_-call.patch
-Patch12: lvm2-2_02_169-lvcreate-fix-striped-limit.patch
+Patch5: lvm2-rhel7-fix-StartLimitInterval.patch
+# up to commit: 6c4b2a6aa16cdb4aff2bd80909dcf43032348a3a:
+Patch6: lvm2-2_02_172-upstream.patch
+# up to commit: 93fbfa2ed397d7b87d4088e19303748c242f24d1
+Patch7: lvm2-2_02_172-upstream-6.patch
+# upstream patch: 64fac77e8a551f4dfe8f4cfaaf1ca984c9b5146c
+Patch8: lvm2-2_02_172-fix-raid-segfault.patch
+# upstream patch: 4e4067dd94f52f90f0aaae30c522102ccbaa2826
+Patch9: lvm2-2_02_172-libdm-initialization-of-reused-struct.patch
 
 BuildRequires: libselinux-devel >= %{libselinux_version}, libsepol-devel
 BuildRequires: libblkid-devel >= %{util_linux_version}
@@ -119,14 +121,11 @@ or more physical volumes and creating one or more logical volumes
 %patch2 -p1 -b .libdm_symbol_versioning
 %patch3 -p1 -b .blkid_sublks_badcsum
 %patch4 -p1 -b .default_allow_dup
-%patch5 -p1 -b .lvconvert_repair_raid
-%patch6 -p1 -b .lvconvert_disable_thin_pool_to_raid
-%patch7 -p1 -b .lvconvert_cache_raid
-%patch8 -p1 -b .raid4_from_striped
-%patch9 -p1 -b .raid4_vs_kernel
-%patch10 -p1 -b .lvmetad_segfault
-%patch11 -p1 -b .ipc_ring_corruption
-%patch12 -p1 -b .striped_limit
+%patch5 -p1 -b .startlimitinterval
+%patch6 -p1 -b .v172
+%patch7 -p1 -b .v172_6
+%patch8 -p1 -b .raid_segfault
+%patch9 -p1 -b .libdm_init
 
 %build
 %global _default_pid_dir /run
@@ -152,11 +151,11 @@ or more physical volumes and creating one or more logical volumes
 %endif
 
 %if %{enable_lockd_dlm}
-%global configure_lockd_dlm --enable-lockd-dlm
+%global configure_lockd_dlm --enable-lvmlockd-dlm
 %endif
 
 %if %{enable_lockd_sanlock}
-%global configure_lockd_sanlock --enable-lockd-sanlock
+%global configure_lockd_sanlock --enable-lvmlockd-sanlock
 %endif
 
 %if %{enable_lvmpolld}
@@ -167,7 +166,11 @@ or more physical volumes and creating one or more logical volumes
 %global configure_python --enable-python2-bindings
 %endif
 
-%configure --with-default-dm-run-dir=%{_default_dm_run_dir} --with-default-run-dir=%{_default_run_dir} --with-default-pid-dir=%{_default_pid_dir} --with-default-locking-dir=%{_default_locking_dir} --with-usrlibdir=%{_libdir} --enable-lvm1_fallback --enable-fsadm --with-pool=internal --enable-write_install --with-user= --with-group= --with-device-uid=0 --with-device-gid=6 --with-device-mode=0660 --enable-pkgconfig --enable-applib --enable-cmdlib --enable-dmeventd --enable-blkid_wiping %{?configure_python} %{?configure_cluster} %{?configure_cmirror} %{?configure_udev} %{?configure_thin} %{?configure_lvmetad} %{?configure_cache} %{?configure_lvmpolld} %{?configure_lockd_dlm} %{?configure_lockd_sanlock}
+%if %{enable_dmfilemapd}
+%global configure_dmfilemapd --enable-dmfilemapd
+%endif
+
+%configure --with-default-dm-run-dir=%{_default_dm_run_dir} --with-default-run-dir=%{_default_run_dir} --with-default-pid-dir=%{_default_pid_dir} --with-default-locking-dir=%{_default_locking_dir} --with-usrlibdir=%{_libdir} --enable-lvm1_fallback --enable-fsadm --with-pool=internal --enable-write_install --with-user= --with-group= --with-device-uid=0 --with-device-gid=6 --with-device-mode=0660 --enable-pkgconfig --enable-applib --enable-cmdlib --enable-dmeventd --enable-blkid_wiping %{?configure_python} %{?configure_cluster} %{?configure_cmirror} %{?configure_udev} %{?configure_thin} %{?configure_lvmetad} %{?configure_cache} %{?configure_lvmpolld} %{?configure_lockd_dlm} %{?configure_lockd_sanlock} %{?configure_dmfilemapd}
 
 make %{?_smp_mflags}
 
@@ -262,7 +265,6 @@ systemctl start lvm2-lvmpolld.socket
 %{_sbindir}/lvcreate
 %{_sbindir}/lvdisplay
 %{_sbindir}/lvextend
-%{_sbindir}/lvmchange
 %{_sbindir}/lvmdiskscan
 %{_sbindir}/lvmsadc
 %{_sbindir}/lvmsar
@@ -317,7 +319,6 @@ systemctl start lvm2-lvmpolld.socket
 %{_mandir}/man8/lvm-config.8.gz
 %{_mandir}/man8/lvmconfig.8.gz
 %{_mandir}/man8/lvm-dumpconfig.8.gz
-%{_mandir}/man8/lvmchange.8.gz
 %{_mandir}/man8/lvmconf.8.gz
 %{_mandir}/man8/lvmdiskscan.8.gz
 %{_mandir}/man8/lvmdump.8.gz
@@ -701,10 +702,14 @@ for the kernel device-mapper.
 %defattr(444,root,root,-)
 %attr(555, -, -) %{_sbindir}/dmsetup
 %attr(555, -, -) %{_sbindir}/blkdeactivate
-%{_sbindir}/dmstats
+%attr(555, -, -) %{_sbindir}/dmstats
 %{_mandir}/man8/dmsetup.8.gz
 %{_mandir}/man8/dmstats.8.gz
 %{_mandir}/man8/blkdeactivate.8.gz
+%if %{enable_dmfilemapd}
+%attr(555, -, -) %{_sbindir}/dmfilemapd
+%{_mandir}/man8/dmfilemapd.8.gz
+%endif
 %{_udevdir}/10-dm.rules
 %{_udevdir}/13-dm-disk.rules
 %{_udevdir}/95-dm-notify.rules
@@ -829,12 +834,81 @@ the device-mapper event library.
 %{_libdir}/pkgconfig/devmapper-event.pc
 
 %changelog
-* Fri Jun 09 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.166-1.el7_3.5
-- Fix limit of stripes in lvcreate.
+* Wed Jun 28 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-8
+- Fix reusing of dm_task structure for status reading (used by dmeventd).
+
+* Thu Jun 22 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-7
+- Fix a segfault in RAID.
+
+* Wed Jun 21 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-6
+- Reenable conversion of data and metadata thin-pool volumes to raid.
+- Improve handling of RAID status in lvs.
+- Disable RAID reshape/take-over in a cluster or when snapshot exists.
+
+* Wed Jun 14 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-5
+- Improve lvcreate --cachepool arg validation.
+- Limit maximal size of thin-pool for specific chunk size.
+- Accept truncated files in calls to dm_stats_update_regions_from_fd().
+
+* Wed Jun 07 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-4
+- Converting linear to raid1 using "recover" not "resync".
+- Print a warning about in-use PVs with no VG using them.
+- Disable automatic clearing of PVs that look like in-use orphans.
+
+* Wed Jun 07 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-4
+- Converting linear to raid1 using "recover" not "resync".
+- Print a warning about in-use PVs with no VG using them.
+- Disable automatic clearing of PVs that look like in-use orphans.
+
+* Wed May 31 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-3
+- Cache format2 flag is now using segment name type field compatible with
+  previous versions.
+
+* Wed May 24 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-2
+- Stop using '--yes' mode when fsadm runs without terminal.
+- Extend validation of filesystems resized by fsadm.
+- Enhance lvconvert automatic settings of possible (raid) LV types.
+- Allow lvchange to change properties on a thin pool data sub LV.
+- Fix lvcreate extent percentage calculation for mirrors.
+- Don't reinstate still-missing devices when correcting inconsistent metadata.
+- Properly handle subshell return codes in fsadm.
+- Disallow cachepool creation with policy cleaner and mode writeback.
+
+* Wed May 03 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.171-1
+- Fix dmstats and dmfilemapd permissions.
+- Fix memory warnings by using mempools for command definition processing.
+- Fix running commands from a script file.
+- Adjust pvresize/pvcreate messages and prompt if underlying device size
+  differs.
+- Preserve region size on raid1 image count changes.
+- Handle insufficient space on RAID takeover.
+- Raise mirror/raid default regionsize to 2MiB.
+
+* Thu Apr 13 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.170-2
+- Fix RPM build - missing upstrem and sources.
+
+* Thu Apr 13 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.170-1
+- Introduce global/fsadm_executable to make fsadm path configurable.
+- Look for limited thin pool metadata size when using 16G metadata.
+- Fix missing lvmlockd LV locks in lvchange and lvconvert.
+- Allow valid lvconvert --regionsize change.
+- Handle insufficient PVs on lvconvert takeover.
+- Fix SIGINT blocking to prevent corrupted metadata.
+- Fix systemd unit existence check for lvmconf --services --startstopservices.
+
+* Wed Mar 29 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.169-3
+- Fix dmfilemapd's Makefile.
+- Update dependencies.
+
+* Wed Mar 29 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.169-2
+- Enable dmfilemapd.
+
+* Tue Mar 28 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.169-1
+- Update to latest upstream release with various fixes and
+  enhancements documented in WHATS_NEW and WHATS_NEW_DM file.
 
-* Tue Apr 04 2017 Marian Csontos <mcsontos@redhat.com> - 7:2.02.166-1.el7_3.4
-- Fix stuck corosync due to unsafe thread access to CPG causing IPC ringbuffer
-  corruption.
+* Thu Mar 23 2017 Alasdair Kergon <agk@redhat.com> - 7:2.02.166-2
+- Add clustered ppc64le support to build.
 
 * Thu Feb 09 2017 Peter Rajnoha <prajnoha@redhat.com> - 7:2.02.166-1.el7_3.3
 - Fix segfault in lvmetad from missing NULL in daemon_reply_simple.
@@ -1563,7 +1637,7 @@ the device-mapper event library.
 - Report blank origin_size field if the LV doesn't have an origin instead of 0.
 - Report partial and in-sync RAID attribute based on kernel status
 - Log output also to syslog when abort_on_internal_error is set.
-- Change lvs heading Copy% to Cpy%Sync and print RAID4/5/6 sync% there too.
+- Change lvs heading Copy% to Cpy%%Sync and print RAID4/5/6 sync% there too.
 - Report error for nonexisting devices in dmeventd communication.
 - Reduce some log_error messages to log_warn where we don't fail.
 - o Configuration:
@@ -1897,7 +1971,7 @@ the device-mapper event library.
 - Update man pages to give them all the same look&feel.
 - Fix lvresize of thin pool for striped devices.
 - For lvresize round upward when specifying number of extents.
-- For lvcreate with %FREE support rounding downward stripe alignment.
+- For lvcreate with %%FREE support rounding downward stripe alignment.
 - Change message severity to log_very_verbose for missing dev info in udev db.
 - Fix lvconvert when specifying removal of a RAID device other than last one.
 - Fix ability to handle failures in mirrored log in dmeventd plugin. (2.02.89)