From ff822ee3ef2804df9d68e51f1f8987049e9ee910 Mon Sep 17 00:00:00 2001
From: Heinz Mauelshagen <heinzm@redhat.com>
Date: Tue, 2 Jun 2015 22:24:03 +0200
Subject: [PATCH] raid_manip: remove old functions

---
 lib/metadata/raid_manip.c | 1181 ++++---------------------------------
 1 file changed, 116 insertions(+), 1065 deletions(-)

diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index 918228368..678263288 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -274,14 +274,16 @@ static int _extract_image_component(struct lv_segment *seg,
 				    uint64_t type, uint32_t idx,
 				    struct logical_volume **extracted_lv);
 static int _convert_raid_to_linear(struct logical_volume *lv,
-				  struct dm_list *removal_list)
+				   struct dm_list *removal_list)
 {
+	unsigned i = 0;
 	struct lv_list *lvl_array, *lvl;
 	struct logical_volume *lv_tmp;
 	struct lv_segment *seg = first_seg(lv);
 
-	if (!seg_is_mirrored(seg) &&
-	    !(seg_is_any_raid0(seg) || seg_is_raid4(seg) || seg_is_any_raid5(seg))) {
+PFL();
+	if (!seg_is_mirrored(seg) && !seg_is_any_raid0(seg) &&
+	    !seg_is_raid4(seg) && !seg_is_any_raid5(seg)) {
 		log_error(INTERNAL_ERROR
 			  "Unable to remove RAID layer from segment type %s",
 			  lvseg_name(seg));
@@ -296,14 +298,15 @@ static int _convert_raid_to_linear(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,
+					(seg->meta_areas ? 2 : 1) * sizeof(*lvl))))
 		return_0;
 
 	if (seg->meta_areas) {
-		if (!_extract_image_component(seg, RAID_META, 0, &lvl_array[0].lv))
+		if (!_extract_image_component(seg, RAID_META, 0, &lvl_array[i].lv))
 			return 0;
 
-		dm_list_add(removal_list, &(lvl_array[0].list));
+		dm_list_add(removal_list, &(lvl_array[i++].list));
 		seg->meta_areas = NULL;
 	}
 PFL();
@@ -311,8 +314,8 @@ PFL();
 	lv_tmp = seg_lv(seg, 0);
 	lv_tmp->status &= ~RAID_IMAGE;
 	lv_set_visible(lv_tmp);
-	lvl_array[1].lv = lv_tmp;
-	dm_list_add(removal_list, &(lvl_array[1].list));
+	lvl_array[i].lv = lv_tmp;
+	dm_list_add(removal_list, &(lvl_array[i].list));
 PFL();
 	if (!remove_layer_from_lv(lv, lv_tmp))
 		return_0;
@@ -599,16 +602,16 @@ PFLA("name=%s", name);
 /*
  * Eliminate the extracted LVs on @removal_list from @vg incl. vg write, commit and backup 
  */
-static int _eliminate_extracted_lvs(struct volume_group *vg, struct dm_list *removal_list)
+static int _eliminate_extracted_lvs(struct volume_group *vg, struct dm_list *removal_lvs)
 {
-	if (dm_list_empty(removal_list))
+	if (!removal_lvs || dm_list_empty(removal_lvs))
 		return 1;
 
 	sync_local_dev_names(vg->cmd);
 
 PFL();
-	if (!dm_list_empty(removal_list)) {
-		if (!_deactivate_and_remove_lvs(vg, removal_list))
+	if (!dm_list_empty(removal_lvs)) {
+		if (!_deactivate_and_remove_lvs(vg, removal_lvs))
 			return 0;
 
 		if (!vg_write(vg) || !vg_commit(vg))
@@ -1401,7 +1404,7 @@ static int _lv_free_reshape_space(struct logical_volume *lv)
  * Convert linear @lv to raid by making the linear lv
  * the one data sub lv of a new top-level lv
  */
-static struct lv_segment *_convert_linear_to_raid(struct logical_volume *lv)
+static struct lv_segment *_convert_linear_to_raid1(struct logical_volume *lv)
 {
 	struct lv_segment *seg = first_seg(lv);
 	uint64_t flags = RAID | LVM_READ | LVM_WRITE;
@@ -1429,22 +1432,15 @@ static int _reset_flags_passed_to_kernel(struct logical_volume *lv, int *flag_cl
 {
 	uint32_t s;
 	struct lv_segment *seg = first_seg(lv);
+	uint64_t reset_flags = LV_REBUILD | LV_RESHAPE_DELTA_DISKS_PLUS | LV_RESHAPE_DELTA_DISKS_MINUS;
 
 	*flag_cleared = 0;
-	for (s = 0; s < seg->area_count; s++) {
-		if ((seg_metalv(seg, s)->status & (LV_REBUILD|LV_RESHAPE_DELTA_DISKS_PLUS|LV_RESHAPE_DELTA_DISKS_MINUS)) ||
-		    (seg_lv(seg, s)->status & (LV_REBUILD|LV_RESHAPE_DELTA_DISKS_PLUS|LV_RESHAPE_DELTA_DISKS_MINUS))) {
-			seg_metalv(seg, s)->status &= ~(LV_REBUILD|LV_RESHAPE_DELTA_DISKS_PLUS|LV_RESHAPE_DELTA_DISKS_MINUS);
-			seg_lv(seg, s)->status &= ~(LV_REBUILD|LV_RESHAPE_DELTA_DISKS_PLUS|LV_RESHAPE_DELTA_DISKS_MINUS);
+	for (s = 0; s < seg->area_count; s++)
+		if ((*flag_cleared += (seg_lv(seg, s)->status & reset_flags)))
+			seg_lv(seg, s)->status &= ~reset_flags;
 
-			*flag_cleared = 1;
-		}
-	}
-
-	if (seg->data_offset) {
+	if ((*flag_cleared += (seg->data_offset ? 1 : 0)))
 		seg->data_offset = 0;
-		*flag_cleared = 1;
-	}
 
 	if (*flag_cleared) {
 		if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
@@ -1531,228 +1527,6 @@ for (s = 0; s < seg->area_count; s++)
 PFLA("seg_lv(seg, %u)->name=%s", s, seg_lv(seg, s)->name);
 }
 
-/* HM FIXME: REMOVE: replaced by _lv_change_image_count */
-#if 0
-/*
- * Add raid rmeta/rimage pair(s) to @lv to get to
- * absolute @new_count using @pvs to allocate from
- *
- */
-static int _raid_add_images(struct logical_volume *lv,
-			    const struct segment_type *segtype,
-			    uint32_t new_count, struct dm_list *pvs)
-{
-	struct lv_segment *seg = first_seg(lv);
-	int add_all_rmeta = 0, linear, flag_cleared;
-	int reshape_disks = (seg_is_striped_raid(seg) && segtype && is_same_level(seg->segtype, segtype));
-	uint32_t s;
-	uint32_t old_count = lv_raid_image_count(lv);
-	uint32_t count = new_count - old_count;
-	uint64_t lv_flags = LV_REBUILD;
-	struct dm_list data_lvs, meta_lvs;
-
-PFLA("seg->meta_areas=%p", seg->meta_areas);
-	segtype = segtype ?: seg->segtype;
-PFLA("segtype->name=%s seg->segtype->name=%s, seg->area_count=%u new_count=%u old_count=%u count=%u", segtype->name, seg->segtype->name, seg->area_count, new_count, old_count, count);
-
-	if (!(linear = seg_is_linear(seg)) &&
-	    !seg_is_raid(seg)) {
-		log_error("Unable to add RAID images to %s of segment type %s",
-			  lv->name, lvseg_name(seg));
-		return 0;
-	}
-
-PFL();
-	if (lv->status & LV_NOTSYNCED) {
-		log_error("Can't add image to out-of-sync RAID LV:"
-			  " use 'lvchange --resync' first.");
-		return 0;
-	}
-
-	dm_list_init(&data_lvs); /* For data image additions */
-	dm_list_init(&meta_lvs); /* For metadata image additions */
-
-PFLA("seg->meta_areas=%p", seg->meta_areas);
-	/*
-	 * If the segtype is linear, then we must allocate a metadata
-	 * LV to accompany it.
-	 */
-	if (linear) {
-PFL();
-		/*
-		 * A complete resync will be done because of
-		 * the new raid set, no need to mark each sub-lv
-		 *
-		 * -> reset rebuild flag
-		 */
-		/* HM FIXME: avoid lv_flags altogether and better always define rebuild settings? */
-		lv_flags = 0;
-		add_all_rmeta = 1;
-
-		/* Convert linear to raid by inserting a layer */
-	    	if (!_convert_linear_to_raid(lv))
-			return 0;
-
-		/*
-		 * Need to add an rmeta device to pair it
-		 * with the given linear device as well
-		 */
-		if (!_alloc_rmeta_devs_for_lv(lv, &meta_lvs))
-			return 0;
-
-		/*
-		 * Need access to the new first segment after the
-		 * linear -> raid conversion having inserted an
-		 * additional layer
-		 */
-		seg = first_seg(lv);
-
-	/*
-	 * In case this is a conversion from raid0 to raid4/5/6,
-	 * add the metadata image LVs for the raid0 rimage LVs
-	 * presumably they don't exist already.
-	 */
-	} else if (!seg->meta_areas) {
-		add_all_rmeta = 1;
-
-		if (!_alloc_rmeta_devs_for_lv(lv, &meta_lvs))
-			return 0;
-	}
-
-
-PFLA("seg->segtype->flags=%llX lv_flags=%llX", (long long unsigned) seg->segtype->flags, (long long unsigned) lv_flags);
-	/* Allocate the additional meta and data lvs requested */
-	log_debug_metadata("Allocating new data and metadata LVs for %s", display_lvname(lv));
-	if (!_alloc_image_components(lv, 1, pvs, count, &meta_lvs, &data_lvs)) {
-		log_error("Failed to allocate new data and metadata LVs for %s", display_lvname(lv));
-		return_0;
-	}
-PFL();
-	/* Metadata LVs must be cleared before being added to the array */
-	log_debug_metadata("Clearing newly allocated metadata LVs for %s", display_lvname(lv));
-	if (!_clear_lvs(&meta_lvs)) {
-		log_error("Failed to clear newly allocated metadata LVs for %s", display_lvname(lv));
-		goto fail;
-	}
-PFL();
-	/*
-	 * FIXME: It would be proper to activate the new LVs here, instead of having
-	 * them activated by the suspend.  However, this causes residual device nodes
-	 * to be left for these sub-lvs.
-	 */
-
-	/* Grow areas arrays for metadata and data devs  */
-	log_debug_metadata("Reallocating areas arrays");
-	if (!_realloc_meta_and_data_seg_areas(lv, seg, new_count)) {
-		log_error("Relocation of areas arrays failed.");
-		return 0;
-	}
-
-	seg->area_count = new_count;
-PFL();
-	/*
-	 * Set segment areas for metadata sub_lvs adding
-	 * an extra meta area when converting from linear
-	 */
-	log_debug_metadata("Adding new metadata LVs");
-	if (!_add_image_component_list(seg, 0, 0, &meta_lvs, add_all_rmeta ? 0 : old_count)) {
-PFL();
-		seg->area_count = old_count;
-		goto fail;
-	}
-
-	/* Set segment areas for data sub_lvs */
-	log_debug_metadata("Adding new data LVs");
-	if (!_add_image_component_list(seg, 0, lv_flags, &data_lvs, old_count)) {
-PFL();
-		if (!_extract_image_component_list(seg, RAID_META, add_all_rmeta ? 0 : old_count, &meta_lvs))
-			return 0;
-
-		seg->area_count = old_count;
-		goto fail;
-	}
-
-	/* Reorder the areas in case this is a raid0 -> raid10 conversion */
-	if (seg_is_any_raid0(seg) && segtype_is_raid10(segtype)) {
-		log_debug_metadata("Reordering areas for raid0 -> raid10 takeover");
-		_raid10_reorder_seg_areas(seg, 1);
-	}
-
-	/*
-	 * Conversion from linear to raid1 -> set rebuild flags properly
-	 *
-	 * We might as well clear all flags and the raid set
-	 * will be resnchronized properly because it is new,
-	 * but this shows proper status chars.
-	 */
-	if (linear || (seg_is_any_raid0(seg) && old_count == 1)) {
-		seg_lv(seg, 0)->status &= ~LV_REBUILD;
-		
-		for (s = old_count; s < new_count; s++)
-			seg_lv(seg, s)->status |= LV_REBUILD;
-
-	} else if (reshape_disks) {
-		uint32_t plus_extents = count * (lv->le_count / _data_rimages_count(seg, old_count));
-PFL();
-		/*
-		 * Reshape adding image component pairs:
-		 *
-		 * - reset rebuild flag on new image LVs
-		 * - set delta disks plus flag on new image LVs
-		 */
-		for (s = old_count; s < new_count; s++) {
-PFL();
-			seg_lv(seg, s)->status &= ~LV_REBUILD;
-			seg_lv(seg, s)->status |= LV_RESHAPE_DELTA_DISKS_PLUS;
-		}
-PFL();
-		/* Reshape adding image component pairs -> change sizes accordingly */
-PFLA("lv->le_count=%u data_rimages=%u plus_extents=%u", lv->le_count, _data_rimages_count(seg, old_count), plus_extents);
-		lv->le_count += plus_extents;
-		lv->size = lv->le_count * lv->vg->extent_size;
-		seg->len += plus_extents;
-		seg->area_len += plus_extents;
-		seg->reshape_len = seg->reshape_len / _data_rimages_count(seg, old_count) *
-						      _data_rimages_count(seg, new_count);
-		if (old_count == 2 && !seg->stripe_size)
-			seg->stripe_size = DEFAULT_STRIPESIZE;
-PFLA("lv->le_count=%u", lv->le_count);
-	}
-
-	seg->segtype = segtype;
-
-PFL();
-	if (!lv_update_and_reload_origin(lv)) {
-		if (!_extract_image_component_list(seg, RAID_META, add_all_rmeta ? 0 : old_count, &meta_lvs) ||
-		    !_extract_image_component_list(seg, RAID_IMAGE, old_count, &data_lvs))
-			return 0;
-PFL();
-
-		goto fail;
-	}
-
-PFL();
-	/*
-	 * Now that the 'REBUILD' or 'RESHAPE_DELTA_DISKS' has/have made its/their
-	 * way to the kernel, we must remove the flag(s) so that the individual
-	 * devices are not rebuilt/reshaped upon every activation.
-	 */
-	if (!_reset_flags_passed_to_kernel(lv, &flag_cleared))
-		return 0;
-PFL();
-	return flag_cleared ? lv_update_and_reload_origin(lv) : 1;
-
-fail:
-PFL();
-	/* Cleanly remove newly-allocated LVs that failed insertion attempt */
-	if (!_eliminate_extracted_lvs(lv->vg, &meta_lvs) ||
-	    !_eliminate_extracted_lvs(lv->vg, &data_lvs))
-		return_0;
-
-	return 0;
-}
-#endif
-
 /* Write vg of @lv, suspend @lv and commit the vg */
 static int _vg_write_lv_suspend_vg_commit(struct logical_volume *lv)
 {
@@ -1900,141 +1674,6 @@ PFLA("seg_lv(seg, %u)=%s", s, seg_lv(seg,s)->name);
 	return 1;
 }
 
-/* HM FIXME: REMOVE: replaced by _lv_change_image_count */
-#if 0
-/* Remove image component pairs from @lv defined by @new_count (< old_count) */
-static int _raid_remove_images(struct logical_volume *lv,
-			       const struct segment_type *segtype,
-			       uint32_t new_count, struct dm_list *pvs)
-{
-	struct lv_segment *seg = first_seg(lv);
-	int reshape_disks = (seg_is_striped_raid(seg) && segtype && is_same_level(seg->segtype, segtype));
-	unsigned old_count = seg->area_count;
-	struct dm_list removal_list;
-	struct lv_list *lvl;
-
-	/* HM FIXME: TESTME: allow to remove out-of-sync dedicated parity/Q syndrome devices */
-	if (seg_is_striped_raid(seg) &&
-	    (lv->status & LV_NOTSYNCED) &&
-	    !((seg_is_raid5_n(seg) || seg_is_raid6_n_6(seg)) &&
-	      old_count - new_count == 1)) {
-		log_error("Can't remove image(s) from out-of-sync striped RAID LV:"
-			  " use 'lvchange --resync' first.");
-		return 0;
-	}
-
-PFLA("seg->segtype=%s segtype=%s new_count=%u", seg->segtype->name, segtype->name, new_count);
-	dm_list_init(&removal_list);
-
-	/* If we convert away from raid4/5/6/10 -> remove any reshape space */
-	if (!(segtype_is_raid10(segtype) ||
-	      segtype_is_raid4(segtype) ||
-	      segtype_is_any_raid5(segtype) ||
-	      segtype_is_any_raid6(segtype)) &&
-	    !_lv_free_reshape_space(lv)) {
-		log_error(INTERNAL_ERROR "Failed to remove reshape space from %s",
-			  display_lvname(lv));
-		return 0;
-	}
-PFL();
-	/* Reorder the areas in case this is a raid10 -> raid0 conversion */
-	if (seg_is_raid10(seg) && segtype_is_any_raid0(segtype)) {
-		log_debug_metadata("Reordering areas for raid10 -> raid0 takeover");
-		_raid10_reorder_seg_areas(seg, 0);
-	}
-PFL();
-
-	/* Extract all image and any metadata lvs past new_count */
-	if (!_raid_extract_images(lv, new_count, pvs, 1,
-				  &removal_list, &removal_list)) {
-		log_error("Failed to extract images from %s", display_lvname(lv));
-		return 0;
-	}
-PFL();
-	/* Shrink areas arrays for metadata and data devs after the extration */
-	if (!_realloc_meta_and_data_seg_areas(lv, seg, new_count)) {
-		log_error("Relocation of areas arrays failed.");
-		return 0;
-	}
-
-	/* Set before any optional removal of metadata devs following immediately */
-	seg->area_count = new_count;
-
-	/*
-	 * In case this is a conversion to raid0 (i.e. no metadata devs),
-	 * remove the metadata image LVs.
-	 */
-	if (segtype_is_raid0(segtype) &&
-	    seg->meta_areas &&
-	    !_extract_image_component_list(seg, RAID_META, 0, &removal_list))
-		return 0;
-PFL();
-
-	/* raid0* does not have a bitmap -> no region size */
-	if (segtype_is_any_raid0(segtype))
-		seg->region_size = 0;
-
-PFL();
-	/* Reshape removing image component pairs -> change sizes accordingly */
-	if (reshape_disks) {
-		uint32_t minus_extents = (old_count - new_count) * (lv->le_count / _data_rimages_count(seg, old_count));
-
-PFLA("lv->le_count=%u data_rimages=%u minus_extents=%u", lv->le_count, _data_rimages_count(seg, old_count), minus_extents);
-		lv->le_count -= minus_extents;
-		lv->size = lv->le_count * lv->vg->extent_size;
-		seg->len -= minus_extents;
-		seg->area_len -= minus_extents;
-		seg->reshape_len = seg->reshape_len / _data_rimages_count(seg, old_count) *
-						      _data_rimages_count(seg, new_count);
-PFLA("lv->le_count=%u", lv->le_count);
-	}
-
-	/* Convert to linear? */
-	if (segtype_is_linear(segtype)) { /* new_count == 1 */
-		if (!(seg->segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID1)))
-			return_0;
-
-		if (!_convert_raid_to_linear(lv, &removal_list)) {
-			log_error("Failed to remove RAID layer"
-			  	" after linear conversion");
-			return 0;
-		}
-
-		lv->status &= ~(LV_NOTSYNCED | LV_WRITEMOSTLY);
-		seg->stripe_size = 0;
-		seg->writebehind = 0;
-	}
-
-PFL();
-	seg->segtype = segtype;
-	if (!_vg_write_lv_suspend_vg_commit(lv))
-		return 0;
-
-	/*
-	 * We activate the extracted sub-LVs first so they are
-	 * renamed and won't conflict with the remaining sub-LVs.
-	 */
-PFL();
-	dm_list_iterate_items(lvl, &removal_list) {
-		if (!activate_lv_excl_local(lv->vg->cmd, lvl->lv)) {
-			log_error("Failed to resume extracted LVs");
-			return 0;
-		}
-	}
-
-PFL();
-	if (!resume_lv(lv->vg->cmd, lv)) {
-		log_error("Failed to resume %s after committing changes",
-			  display_lvname(lv));
-		return 0;
-	}
-
-PFL();
-	/* Eliminate the residual LVs, write VG, commit it and take a backup */
-	return _eliminate_extracted_lvs(lv->vg, &removal_list);
-}
-#endif
-
 
 /****************************************************************************/
 /*
@@ -2102,59 +1741,15 @@ PFL();
 			return_0;
 
 		/* If any residual LVs, eliminate them, write VG, commit it and take a backup */
-		return dm_list_empty(removal_lvs) ? 1 : _eliminate_extracted_lvs(lv->vg, removal_lvs);
+		return _eliminate_extracted_lvs(lv->vg, removal_lvs);
 	}
 
 	return 1;
 }
 
-/* HM FIXME: REMOVE: replaced by _lv_change_image_count */
-#if 0
 /*
- * _lv_raid_change_image_count
- * @lv
- * @new_count: The absolute count of images (e.g. '2' for a 2-way mirror)
- * @pvs: The list of PVs that are candidates for removal (or empty list)
- *
- * RAID arrays have 'images' which are composed of two parts, they are:
- *    - 'rimage': The data/parity/syndrome holding portion
- *    - 'rmeta' : The metadata holding portion (i.e. superblock/bitmap area)
- * This function adds or removes _both_ portions of the image and commits
- * the results.
- *
- * Returns: 1 on success, 0 on failure
- */
-static int _lv_raid_change_image_count(struct logical_volume *lv,
-				       const struct segment_type *segtype,
-				       uint32_t new_count, struct dm_list *pvs)
-{
-	uint32_t old_count = lv_raid_image_count(lv);
-
-	if (old_count == new_count) {
-		log_warn("%s already has image count of %d.",
-			 display_lvname(lv), new_count);
-		return 1;
-	}
-
-	segtype = segtype ?: first_seg(lv)->segtype;
-PFLA("segtype=%s old_count=%u new_count=%u", segtype->name, old_count, new_count);
-
-	/* Check for maximum supported raid devices */
-	if (!_check_maximum_devices(new_count))
-		return 0;
-
-	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;
-	}
-
-	return (old_count > new_count ? _raid_remove_images : _raid_add_images)(lv, segtype, new_count, pvs);
-}
-#endif
-
-/*
- *
+ * Split off raid1 images of @lv, prefix with @split_name,
+ * leave @new_count in the raid1 set and find them on @splittable_pvs
  */
 int lv_raid_split(struct logical_volume *lv, const char *split_name,
 		  uint32_t new_count, struct dm_list *splittable_pvs)
@@ -3263,7 +2858,7 @@ PFLA("new_segtype=%s seg->area_count=%u", new_segtype->name, seg->area_count);
 		if (!lv_update_and_reload_origin(lv))
 			return_0;
 
-		if (!dm_list_empty(&removal_lvs) && !_eliminate_extracted_lvs(lv->vg, &removal_lvs))
+		if (!_eliminate_extracted_lvs(lv->vg, &removal_lvs))
 			return_0;
 PFL();
 		/* HM FIXME: i don't like the flow doing this here and in _raid_add_images on addition of component images */
@@ -3470,538 +3065,9 @@ static uint64_t _raid_seg_flag_6_to_5(const struct lv_segment *seg)
 
 	return _seg_flag_to_new_flag(seg->segtype->flags, r6_to_r5, ARRAY_SIZE(r6_to_r5));
 }
-
-/* HM FIXME: REMOVEME: because of takeover function table */
-#if 0
-/*
- * Check, if @new_segtype is possible to convert to for
- * given segment type of @lv or try to adjust it.
- *
- * E.g. conversion raid5_la -> raid6 (ie. "--type raid6", which is equal to raid6_zr)
- * actually needs raid6_la_6
- *
- * HM FIXME: complete?
- */
-static int _adjust_segtype(struct logical_volume *lv,
-			   struct segment_type **new_segtype)
-{
-	uint64_t seg_flag = 0;
-	struct lv_segment *seg = first_seg(lv);
-
-	if (seg_is_raid10(seg))
-		return 0;
-
-	if (is_level_up(seg->segtype, *new_segtype)) {
-		/*
-		 * Up convert
-		 */
-		/* multi-striped/raid0 -> raid5/6 */
-		if (seg_is_striped(seg) || seg_is_any_raid0(seg) || seg_is_raid4(seg)) {
-			if (segtype_is_any_raid5(*new_segtype))
-				seg_flag = SEG_RAID5_N;
-			else if (segtype_is_any_raid6(*new_segtype))
-				seg_flag = SEG_RAID6_N_6;
-			else
-				return 0;
-		}
-
-		if (seg_is_any_raid5(seg))
-			seg_flag = _raid_seg_flag_5_to_6(seg);
-
-	} else {
-		/*
-		 * Down convert
-		 */
-		/* raid6 -> raid5/raid0 */
-		if (seg_is_any_raid6(seg)) {
-			if (segtype_is_any_raid5(*new_segtype))
-				seg_flag = _raid_seg_flag_6_to_5(seg);
-			else if (segtype_is_any_raid0(*new_segtype)) {
-				if (!seg_is_raid6_n_6(seg))
-					seg_flag = SEG_RAID6_N_6;
-			} else
-				return 0;
-		}
-
-		/* raid5 -> 5/raid0 */
-		if (seg_is_any_raid5(seg) && !seg_is_raid5_n(seg)) {
-			if (!segtype_is_raid1(*new_segtype))
-				seg_flag = SEG_RAID5_N;
-		}
-	}
-
-	if (seg_flag) {
-		const struct segment_type *saved_segtype = *new_segtype;
-
-	    	if (!(*new_segtype = get_segtype_from_flag(lv->vg->cmd, seg_flag)))
-			return_0;
-
-		log_warn("Overwriting requested raid type %s for %s with %s to allow for conversion",
-			 saved_segtype->name, display_lvname(lv), (*new_segtype)->name);
-		log_warn("Repeat the command after the conversion of %s to %s has finished",
-			 display_lvname(lv), (*new_segtype)->name);
-	}
-
-	return 1;
-}
-#endif
-
-#if 0
-/* Process one level up takeover on @lv to @segtype allocating fron @allocate_pvs */
-static int _raid_takeover(struct logical_volume *lv,
-			  int up,
-			  const struct segment_type *segtype,
-			  struct dm_list *allocate_pvs,
-			  const char *error_msg)
-{
-	struct lv_segment *seg = first_seg(lv);
-	uint32_t new_count = seg->area_count + segtype->parity_devs - seg->segtype->parity_devs;
-
-	/* Make sure to set default region size on takeover from raid0 */
-	_check_and_init_region_size(lv);
-
-PFLA("segtype=%s old_count=%u new_count=%u", segtype->name, seg->area_count, new_count);
-	/* Takeover raid4 <-> raid5_n */
-	if (new_count == seg->area_count) {
-PFL();
-		if (seg->area_count == 2 ||
-		    ((segtype_is_raid5_n(seg->segtype) && segtype_is_raid4(segtype)) ||
-		     (segtype_is_raid4(seg->segtype)   && segtype_is_raid5_n(segtype)))) {
-			seg->segtype = segtype;
-			return lv_update_and_reload(lv);
-		}
-
-		return 0;
-	}
-
-	if (seg_is_any_raid5(seg) && segtype_is_raid1(segtype) && seg->area_count != 2) {
-		uint32_t remove_count = seg->area_count - 2;
-
-		log_error("Device count is incorrect. "
-			  "Forgotten \"lvconvert --stripes 1 %s\" to remove %u image%s after reshape?",
-			   display_lvname(lv), remove_count, remove_count > 1 ? "s" : "");
-		return 0;
-	}
-
-	/*
-	 * Takeover of raid sets with 2 image component pairs (2-legged):
-	 *
-	 * - in case of raid1 -> raid5, takeover will run a degraded 2 disk raid5 set with the same content
-	 *   in each leg (i.e. a redundant raid1 mapping) which will get an additional disk allocated afterwards
-	 *   and reloaded starting reshaping to reach the raid4/5 layout.
-	 *
-	 * - in case of raid4/raid5_n -> all set, just reload
-	 *
-	 * - in case of raid1 -> raid0, remove the second leg and conditionally the meta device
-	 *   of the first leg if raid0 requested and reload
-	 */
-	/* HM FIXME: is this doubled with _check_linear_or_raid0_from_to_raid0145()? */
-	if (!seg_is_any_raid0(seg) && seg->area_count == 2) {
-		int valid_conversion = 0;
-
-		/* Current segtype is raid1 */
-		if (seg_is_raid1(seg)) {
-			if (segtype_is_any_raid0(segtype))
-				valid_conversion = 1;
-
-			if (segtype_is_raid4(segtype) || segtype_is_any_raid5(segtype))
-				valid_conversion = 1;
-		}
-
-		/* Current segtype is raid4 or any raid5 */
-		if (seg_is_raid4(seg) || seg_is_any_raid5(seg))
-			if (segtype_is_any_raid0(segtype) || segtype_is_raid1(segtype))
-				valid_conversion = 1;
-
-		if (!valid_conversion) {
-			log_error(error_msg, display_lvname(lv));
-			return 0;
-		}
-PFL();
-		/* raid1 does not preset stripe size */
-		if (!seg->stripe_size &&
-		    !(seg->stripe_size = find_config_tree_int(lv->vg->cmd, global_raid_stripe_size_default_CFG, NULL)))
-			return 0;
-
-PFL();
-		if (segtype_is_any_raid0(segtype))
-			new_count = 1;
-
-		else {
-			seg->segtype = segtype;
-			return lv_update_and_reload_origin(lv);
-			// return resume_lv(lv->vg->cmd, lv_lock_holder(lv));
-		}
-	}
-
-PFL();
-	/*
-	 * The top-level LV is being reloaded and the VG
-	 * written and committed in the course of this call
-	 */
-	return _lv_raid_change_image_count(lv, segtype, new_count, allocate_pvs);
-}
-#endif
-
-/* HM FIXME: REMOVEME: because of takeover function table */
-#if 0
-/* Process one level up takeover on @lv to @segtype */
-static int _raid_level_up(struct logical_volume *lv,
-			  const struct segment_type *segtype,
-			  struct dm_list *allocate_pvs)
-{
-	return _raid_takeover(lv, 1, segtype, allocate_pvs,
-			      "raid1 set %s has to have 2 operational disks.");
-}
-
-/* Process one level down takeover on @lv to @segtype */
-static int _raid_level_down(struct logical_volume *lv,
-			    const struct segment_type *segtype,
-			    struct dm_list *allocate_pvs)
-{
-	return _raid_takeover(lv, 0, segtype, allocate_pvs,
-			      "raid1/4/5 set %s has to have 1 mirror/stripe. Use \"lvconvert --stripes 1 ...\"");
-}
-
-/*
- * Convert a RAID set in @lv to another RAID level and algorithm defined
- * by @requested_segtype, stripe size set by @new_stripe_size or number
- * of RAID devices requested by @new_stripes.
- *
- * Returns: 1 on success, 0 on failure
- */
-static int _convert_raid_to_raid(struct logical_volume *lv,
-				 struct segment_type *new_segtype,
-				 const struct segment_type *final_segtype,
-				 int yes, int force,
-				 const unsigned new_stripes,
-				 const unsigned new_stripe_size,
-				 struct dm_list *allocate_pvs)
-{
-	struct lv_segment *seg = first_seg(lv);
-	unsigned stripes = new_stripes ?: _data_rimages_count(seg, seg->area_count);
-	unsigned stripe_size = new_stripe_size ?: seg->stripe_size;
-
-PFLA("seg->segtype=%s new_segtype=%s final_segtype=%s stripes=%u new_stripes=%u", seg->segtype->name, new_segtype->name, final_segtype ? final_segtype->name : "NULL", stripes, new_stripes);
-	if (new_segtype == seg->segtype &&
-	    stripes == _data_rimages_count(seg, seg->area_count) &&
-	    stripe_size == seg->stripe_size) {
-PFLA("stripes=%u stripe_size=%u seg->stripe_size=%u", stripes, stripe_size, seg->stripe_size);
-		log_error("Nothing to do");
-		return 0;
-	}
-
-	/* Check + apply stripe size change */
-	if (stripe_size &&
-	    (stripe_size & (stripe_size - 1) ||
-	     stripe_size < 8)) {
-		log_error("Invalid stripe size on %s", lv->name);
-		return 0;
-	}
-
-	if (seg->stripe_size != stripe_size) {
-		if (seg_is_striped(seg) || seg_is_any_raid0(seg)) {
-			log_error("Cannot change stripe size on \"%s\"", lv->name);
-			return 0;
-		}
-
-		if (stripe_size > lv->vg->extent_size) {
-			log_error("Stripe size for %s too large for volume group extent size", lv->name);
-			return 0;
-		}
-
-		if (stripe_size > seg->region_size) {
-			log_error("New stripe size for %s is larger than region size", lv->name);
-			return 0;
-		}
-	}
-
-	/* linear/raid1 do not preset stripe size */
-	if (!seg->stripe_size &&
-	    !(seg->stripe_size = find_config_tree_int(lv->vg->cmd, global_raid_stripe_size_default_CFG, NULL)))
-		return 0;
-
-PFLA("seg->segtype=%s new_segtype->name=%s", seg->segtype->name, new_segtype->name);
-	/* If we're taking over, adjust segment type to make it possible (e.g. raid5_la -> raid6 needs raid6_la_6) */
-	/* Done before adding any metadata devices */
-	if (!is_same_level(seg->segtype, new_segtype) &&
-	    !_adjust_segtype(lv, &new_segtype))
-		return 0;
-
-	/*
-	 * raid0 <-> raid0_meta adding metadata image devices
-	 * on converting from raid0 -> raid0_meta or removing
-	 * them going the other way.
-	 */
-	if ((seg_is_raid0(seg) && segtype_is_raid0_meta(new_segtype)) ||
-	    (seg_is_raid0_meta(seg) && segtype_is_raid0(new_segtype)))
-		return _raid0_add_or_remove_metadata_lvs(lv, 1, NULL);
-
-	/*
-	 * Staying on the same level -> reshape required to change
-	 * stripes (i.e. # of disks), stripe size or algorithm
-	 */
-	if (is_same_level(seg->segtype, new_segtype))
-		return _raid_reshape(lv, new_segtype, yes, force, stripes, stripe_size, allocate_pvs);
-
-	/*
-	 * HM
-	 *
-	 * Up/down takeover of raid levels
-	 *
-	 * In order to takeover the raid set level N to M (M > N) in @lv, all existing
-	 * rimages in that set need to be paired with rmeta devs (if not yet present)
-	 * to store superblocks and bitmaps of the to be taken over raid0/raid1/raid4/raid5/raid6
-	 * set plus another rimage/rmeta pair has to be allocated for dedicated xor/q.
-	 *
-	 * In order to postprocess the takeover of a raid set from level M to M (M > N)
-	 * in @lv, the last rimage/rmeta devs pair need to be droped in the metadata.
-	 */
-
-PFLA("segtype=%s new_segtype->name=%s", seg->segtype->name, new_segtype->name);
-	/* Down convert from raid4/5 to linear in case of more than 2 legs */
-	if (segtype_is_linear(new_segtype) && seg->area_count > 2) {
-		log_error("Can't convert striped %s from %s to %s directly",
-			  display_lvname(lv), lvseg_name(seg), new_segtype->name);
-		log_error("Convert to single stripe first!");
-		return 0;
-	}
-
-	if (!(is_level_up(seg->segtype, new_segtype) ?
-	      _raid_level_up : _raid_level_down)(lv, new_segtype, allocate_pvs))
-		return 0;
-PFLA("seg->segtype=%s new_segtype->name=%s", seg->segtype->name, new_segtype->name);
-
-	return 1;
-} /* _convert_raid_to_raid() */
-#endif
 /******* END: raid <-> raid conversion *******/
 
 
-/* HM FIXME: REMOVEME: because of takeover function table */
-#if 0
-/****************************************************************************/
-/* Special case raid check/convert functions */
-
-/*
- * Linear/raid0 (1 image) <-> raid0/4/5 conversions of @lv defined by @new_segtype
- */
-static int _check_linear_or_raid0_from_to_raid0145(struct logical_volume *lv,
-						   const struct segment_type *new_segtype,
-						   uint32_t new_image_count,
-						   uint32_t new_stripes,
-						   uint32_t new_stripe_size,
-						   struct dm_list *allocate_pvs)
-{
-	int convert;
-	struct lv_segment *seg = first_seg(lv);
-
-PFL();
-	/* linear -> raid1 with N > 1 images */
-	if ((convert = seg_is_linear(seg) &&
-		       (segtype_is_raid1(new_segtype) || new_image_count > 1)))
-		/* "lvconvert --type raid1 ..." does not set new_image_count */
-		new_image_count = new_image_count > 1 ? new_image_count : 2;
-
-	/* linear -> raid4/5 with 2 images */
-	else if ((convert = (seg_is_linear(seg) &&
-			     (segtype_is_raid4(new_segtype) || segtype_is_any_raid5(new_segtype))))) {
-		new_image_count = 2;
-
-	/* raid0 with _one_ image -> raid1/4/5 with 2 images */
-	} else if ((convert = (seg_is_any_raid0(seg) && seg->area_count == 1 &&
-			       ((segtype_is_raid1(new_segtype) || new_image_count == 2) ||
-				segtype_is_raid4(new_segtype) ||
-				segtype_is_any_raid5(new_segtype))))) {
-		if (seg->segtype == new_segtype)
-			if (!(new_segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID1)))
-				return_0;
-
-		new_image_count = 2;
-
-	/* raid1 with N images -> linear with one image */
-	} else if ((convert = (seg_is_raid1(seg) && segtype_is_linear(new_segtype))))
-		new_image_count = 1;
-
-	/* raid1 with N images -> raid0 with 1 image */
-	else if ((convert = (seg_is_raid1(seg) && segtype_is_any_raid0(new_segtype))))
-		new_image_count = 1;
-
-	/* raid1 <-> raid10/4/5 with 2 images */
-	else if ((convert = ((seg_is_raid1(seg) || seg_is_raid4(seg) || seg_is_any_raid5(seg)) &&
-			     seg->area_count == 2 &&
-			     !new_stripes &&
-			     (segtype_is_raid1(new_segtype) ||
-			      segtype_is_raid10(new_segtype) ||
-			      segtype_is_raid4(new_segtype) ||
-			      segtype_is_any_raid5(new_segtype))))) {
-		if (seg->segtype == new_segtype) {
-			log_error("No change requested");
-			return 0;
-		}
-
-		if (new_image_count != 2)
-			log_warn("Ignoring new image count");
-
-		if (new_stripes)
-			log_warn("Ignoring stripes");
-
-		if (new_stripe_size)
-			log_warn("Ignoring stripe size");
-
-		seg->segtype = new_segtype;
-
-		return lv_update_and_reload(lv);
-
-	/* raid10 with 2 images -> raid1 with 2 images */
-	} else if (seg_is_raid10(seg) && seg->area_count == 2 &&
-		   segtype_is_raid1(new_segtype)) {
-		seg->segtype = new_segtype;
-
-		return lv_update_and_reload(lv);
-
-#if 0
-	/* HM FIXME: CODEME: */
-	/* raid10 with N > 2 images -> raid10 with M images */
-	} else if ((convert = (seg_is_raid10(seg) && seg->segtype == new_segtype &&
-		   new_image_count != seg->area_count))) {
-		/* Need to support raid10_copies and raid_format! */
-		;
-#endif
-
-	/* raid4/5 with 2 images -> linear/raid0 with 1 image */
-	} else if ((convert = (seg_is_raid4(seg) || seg_is_any_raid5(seg)) && seg->area_count == 2 &&
-		   (segtype_is_linear(new_segtype) || segtype_is_any_raid0(new_segtype))))
-		new_image_count = 1;
-
-	/* No way to convert raid4/5/6 with > 2 images -> linear! */
-	else if ((seg_is_raid4(seg) || seg_is_any_raid5(seg) || seg_is_any_raid6(seg)) &&
-		   segtype_is_linear(new_segtype))
-		return 0;
-
-	if (!seg->stripe_size)
-		seg->stripe_size = new_stripe_size ?: DEFAULT_STRIPESIZE;
-
-	if (convert) {
-		if ((segtype_is_raid0(new_segtype) || segtype_is_raid1(new_segtype)) && new_stripes) {
-			log_error("--stripes N incompatible with raid0/1");
-			return 0;
-		}
-
-PFLA("linear/raid1/4/5 new_segtype=%s new_image_count=%u stripe_size=%u", new_segtype->name, new_image_count, seg->stripe_size);
-		return _lv_raid_change_image_count(lv, new_segtype, new_image_count, allocate_pvs);
-	}
-
-	return 2; /* Indicate that no conversion happened */
-}
-
-/****************************************************************************/
-/*
- * Mirror <-> RAID1 conversion
- */
-static int _check_mirror_from_to_raid(struct logical_volume *lv,
-				      int yes,
-				      const struct segment_type *new_segtype,
-				      struct dm_list *allocate_pvs)
-{
-	int r;
-	struct lv_segment *seg = first_seg(lv);
-
-	/*
-	 * Mirror -> RAID1/5 conversion
-	 */
-	if (seg_is_mirror(seg) && (segtype_is_raid1(new_segtype) || segtype_is_any_raid5(new_segtype)))
-		r = _convert_mirror_to_raid(lv, new_segtype, 1);
-
-	/*
-	 * RAID1/5 -> Mirror conversion
-	 */
-	/*
-	 * FIXME: support this conversion or don't invite users to switch back to "mirror"?
-	 *        I find this at least valuable in case of an erroneous conversion to raid1
-	 */
-	else if (((seg_is_any_raid5(seg) && seg->area_count == 2) || seg_is_raid1(seg)) &&
-		 segtype_is_mirror(new_segtype)) {
-		struct dm_list removal_lvs;
-
-		dm_list_init(&removal_lvs);
-
-		if (!yes && yes_no_prompt("WARNING: Do you really want to convert %s to "
-					  "non-recommended \"%s\" type? [y/n]: ",
-				  display_lvname(lv), SEG_TYPE_NAME_MIRROR) == 'n') {
-			log_warn("Logical volume %s NOT converted to \"%s\"",
-				  display_lvname(lv), SEG_TYPE_NAME_MIRROR);
-			return 0;
-		}
-		if (sigint_caught())
-			return_0;
-
-		if ((seg_is_any_raid5(seg) &&
-		    !(seg->segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID1))))
-			return 0;
-
-		r = _convert_raid1_to_mirror(lv, new_segtype, allocate_pvs, 1, &removal_lvs);
-
-	} else
-		return 2; /* Indicate no conversion to caller */
-
-	return r;
-}
-
-/*
- * raid0 <-> raid10 comversion
- *
- * md raid10 "near" is a stripe on top of stripes number of 2-way mirrors
- */
-/* HM FIXME: move to _raid_takeover() rather than special case here */
-/* HM FIXME: support far and offset formats */
-static int _check_raid0_to_from_raid10(struct logical_volume *lv,
-				       struct segment_type *new_segtype,
-				       struct dm_list *allocate_pvs)
-{
-	struct lv_segment *seg = first_seg(lv);
-	struct dm_list removal_lvs;
-
-	dm_list_init(&removal_lvs);
-
-	if (segtype_is_raid10(new_segtype)) {
-		if (seg_is_striped(seg) || seg_is_any_raid0(seg)) {
-			if (seg_is_striped(seg) &&
-			    !_convert_striped_to_raid0(lv, 1, 0))
-				return 0;
-
-			return _lv_raid_change_image_count(lv, new_segtype, lv_raid_image_count(lv) * 2, allocate_pvs);
-
-		}
-
-		return 3; /* Indicate that conversion is not possible */
-	}
-
-	if (seg_is_raid10(seg)) {
-		if (segtype_is_striped(new_segtype) || segtype_is_any_raid0(new_segtype)) {
-			struct segment_type *final_segtype;
-
-			if (segtype_is_striped(new_segtype)) {
-				final_segtype = new_segtype;
-				if (!(new_segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID0)))
-					return_0;
-			} else
-				final_segtype = NULL;
-
-			if (!_lv_raid_change_image_count(lv, new_segtype, lv_raid_image_count(lv) / 2, allocate_pvs))
-				return 0;
-
-			return final_segtype ? _convert_raid0_to_striped(lv, 1, &removal_lvs) : 1;
-
-		}
-
-		return 3; /* Indicate that conversion is not possible */
-	}
-
-	return 2; /* Indicate that no conversion happened */
-}
-#endif
-
 /*
  * Report current number of redundant disks for @total_images and @segtype 
  */
@@ -4162,19 +3228,25 @@ PFLA("lv->le_count=%u", lv->le_count);
 }
 
 /*
- * Update metadata, reload origin @lv and afterwards clear any flags passed to the kernel
+ * Update metadata, reload origin @lv, eliminate any LVs listed on @remova_lvs
+ * and then clear any flags passed to the kernel in the metadata
  */
-static int _lv_update_and_reload_origin_clear_any_flags(struct logical_volume *lv)
+static int _lv_update_and_reload_origin_eliminate_lvs(struct logical_volume *lv,
+						      struct dm_list *removal_lvs)
 {
 	int flag_cleared;
 
 	if (!lv_update_and_reload_origin(lv))
-		return 0;
+		return_0;
+
+	/* Eliminate any residual LV, write VG, commit it and take a backup */
+	if (!_eliminate_extracted_lvs(lv->vg, removal_lvs))
+		return_0;
 
 	/*
-	 * Now that the 'REBUILD' or 'RESHAPE_DELTA_DISKS' has/have made its/their
-	 * way to the kernel, we must remove the flag(s) so that the individual
-	 * devices are not rebuilt/reshaped upon every activation.
+	 * Now that any 'REBUILD' or 'RESHAPE_DELTA_DISKS' etc. has/have made
+	 * its/their way to the kernel, we must remove the flag(s) so that the
+	 * individual devices are not rebuilt/reshaped upon every activation.
 	 */
 	if (!_reset_flags_passed_to_kernel(lv, &flag_cleared))
 		return 0;
@@ -4182,20 +3254,6 @@ static int _lv_update_and_reload_origin_clear_any_flags(struct logical_volume *l
 	return flag_cleared ? lv_update_and_reload_origin(lv) : 1;
 }
 
-/*
- * Update metadata, reload origin @lv and eliminate any LVs listed on @remova_lvs
- */
-static int _lv_update_and_reload_origin_eliminate_lvs(struct logical_volume *lv,
-						      struct dm_list *removal_lvs)
-{
-	if (!_lv_update_and_reload_origin_clear_any_flags(lv))
-		return_0;
-
-	/* Eliminate any residual LV, write VG, commit it and take a backup */
-	return (!removal_lvs || dm_list_empty(removal_lvs)) ?
-		1 : _eliminate_extracted_lvs(lv->vg, removal_lvs);
-}
-
 /* Return 1 if @lv is synced, else 0 and display error message */
 static int _lv_is_synced(struct logical_volume *lv)
 {
@@ -4253,7 +3311,7 @@ static int _noop(struct logical_volume *lv, int yes, int force,
 	return 1;
 }
 
-/* Error takeover handler for @lv: logs what's (im)possible to convert to */
+/* Error takeover handler for @lv: logs what's (im)possible to convert to and mabye added */
 static int _error(struct logical_volume *lv, int yes, int force,
 		const struct segment_type *new_segtype,
 		unsigned new_image_count, const unsigned new_stripes,
@@ -4271,12 +3329,14 @@ static int _error(struct logical_volume *lv, int yes, int force,
 	return 0;
 }
 
-/* Macroto define raid takeover helper function header */
-#define TAKEOVER_FN_HEADER(name) 						\
-static int name(struct logical_volume *lv, int yes, int force,			\
-		  const struct segment_type *new_segtype,			\
-		  unsigned new_image_count, const unsigned new_stripes,		\
-		  unsigned new_stripe_size, struct dm_list *allocate_pvs)
+/* Macro to define raid takeover helper function header */
+#define TAKEOVER_FN_HEADER(name) 					\
+static int name(struct logical_volume *lv,				\
+		int yes, int force,					\
+		const struct segment_type *new_segtype,			\
+		unsigned new_image_count,				\
+		const unsigned new_stripes,				\
+		unsigned new_stripe_size, struct dm_list *allocate_pvs)	\
 /* Macro to spot takeover helper functions easily */
 #define TAKEOVER_HELPER_FN_HEADER(name) \
 TAKEOVER_FN_HEADER(name)
@@ -4291,11 +3351,68 @@ TAKEOVER_FN_HEADER(name)			\
 
 /* Begin takeover helper funtions */
 
+/* Helper: linear -> raid0* */
+TAKEOVER_HELPER_FN_HEADER(_linear_raid0)
+{
+	struct dm_list meta_lvs;
+	struct lv_segment *seg;
+
+	dm_list_init(&meta_lvs);
+
+	if (new_image_count != 1) {
+		log_error(INTERNAL_ERROR "Image count has to be 1");
+		return 0;
+	}
+
+	/* Convert linear to raid1 by inserting a layer and presetting segtype as raid1 */
+	if (!(seg =_convert_linear_to_raid1(lv)))
+		return 0;
+
+	if (segtype_is_raid0_meta(new_segtype)) {
+PFL();
+		/* Need to add an rmeta device to pair it with the given linear device as well */
+		if (!_alloc_rmeta_devs_for_lv(lv, &meta_lvs))
+			return 0;
+
+		/* Metadata LV must be cleared before being added to the array */
+		log_debug_metadata("Clearing newly allocated metadata LVs of %s", display_lvname(lv));
+		if (!_clear_lvs(&meta_lvs)) {
+			log_error("Failed to clear newly allocated metadata LVs of %s", display_lvname(lv));
+			return_0;
+		}
+
+		/* Grow areas arrays for metadata and data devs  */
+		log_debug_metadata("Realocating areas arrays of %s", display_lvname(lv));
+		if (!_realloc_seg_areas(lv, seg, 1 /* new_image_count */, &seg->meta_areas)) {
+			log_error("Relocation of areas arrays for %s failed", display_lvname(lv));
+			return_0;
+		}
+
+		log_debug_metadata("Adding new metadata LV to %s", display_lvname(lv));
+		if (!_add_image_component_list(seg, 1, 0, &meta_lvs, 0 /* area_offset */)) {
+			log_error("Failed to add new metadata LV to %s", display_lvname(lv));
+			return_0;
+		}
+	}
+
+
+	/* We may be called to convert to !raid0* */
+	if (!force) {
+		seg->segtype = new_segtype;
+		seg->region_size = 0;
+
+		return lv_update_and_reload_origin(lv);
+	}
+
+	return 1;
+}
+
 /* Helper: linear <-> raid1/4/5 takeover handler for @lv */
 TAKEOVER_HELPER_FN_HEADER(_linear_to_raid456)
 {
 	struct dm_list data_lvs, meta_lvs;
-	struct lv_segment *seg;
+	struct lv_segment *seg = first_seg(lv);
+	struct segment_type *segtype;
 
 	dm_list_init(&data_lvs);
 	dm_list_init(&meta_lvs);
@@ -4309,40 +3426,20 @@ TAKEOVER_HELPER_FN_HEADER(_linear_to_raid456)
 
 	new_image_count = new_image_count > 1 ? new_image_count : 2;
 
-	/* Convert linear to raid by inserting a layer and presetting segtype as raid1 */
-	if (!(seg =_convert_linear_to_raid(lv)))
+	/*
+	 * Use helper _linear_raid0() to create the initial raid0_meta wtih one image pair up
+	 *
+	 * HM FIXME: overloding froce argument to avoid metadata update in _linear_raid0()
+	 */
+	if (!(segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID0_META)) ||
+	    !_linear_raid0(lv, 0, 1, segtype, 1, 0, 0, allocate_pvs))
 		return 0;
 
-	/* Need to add an rmeta device to pair it with the given linear device as well */
-	if (!_alloc_rmeta_devs_for_lv(lv, &meta_lvs))
-		return 0;
-
-	/* HM FIXME: clear the new meta lv in one go in _clear_lvs()? */
-
-	/* Metadata LVs must be cleared before being added to the array */
-	log_debug_metadata("Clearing newly allocated metadata LV for %s", display_lvname(lv));
-	if (!_clear_lvs(&meta_lvs)) {
-		log_error("Failed to clear newly allocated metadata LV for %s", display_lvname(lv));
-		return 0;
-	}
-
-	/* Grow areas arrays for metadata and data devs  */
-	log_debug_metadata("Realocating metadata areas array of %s", display_lvname(lv));
-	if (!_realloc_seg_areas(lv, seg, 1 /* area_count */, &seg->meta_areas)) {
-		log_error("Relocation of metadata areas array for %s failed", display_lvname(lv));
-		return_0;
-	}
-
-	log_debug_metadata("Adding new metadata LV to %s", display_lvname(lv));
-	if (!_add_image_component_list(seg, 1, 0, &meta_lvs, 0)) {
-		log_error("Failed to add new metadata LV to %s", display_lvname(lv));
-		return_0;
-	}
-
 	/* Allocate the additional meta and data lvs requested */
 	if (!_lv_change_image_count(lv, new_segtype, new_image_count, allocate_pvs, NULL))
 		return 0;
 
+	seg = first_seg(lv);
 	seg->segtype = new_segtype;
 
 	return _lv_update_and_reload_origin_eliminate_lvs(lv, NULL);
@@ -4353,7 +3450,7 @@ TAKEOVER_HELPER_FN_HEADER(_striped_r0_r456)
 {
 	struct lv_segment *seg = first_seg(lv);
 
-	/* This helper can be used to covert from raid0* -> raid4/5/6 too */
+	/* This helper can be used to convert from raid0* -> raid4/5/6 too */
 	if (seg_is_striped(seg)) {
 		if (!_convert_striped_to_raid0(lv, 1 /* alloc_metadata_devs */, 0 /* !update_and_reload */))
 			return 0;
@@ -4385,6 +3482,7 @@ TAKEOVER_HELPER_FN_HEADER(_striped_raid0_raid10)
 {
 	struct lv_segment *seg = first_seg(lv);
 
+	/* This helper can be used to convert from raid0* -> raid10 too */
 	if (seg_is_striped(seg) &&
 	    !_convert_striped_to_raid0(lv, 0 /* alloc_metadata_devs */, 0 /* update_and_reload */))
 		return 0;
@@ -4590,57 +3688,10 @@ TAKEOVER_HELPER_FN_HEADER(_raid10_striped_r0)
 
 /* HM FIXME: All TAKEOVER_FN_DUMMY macro instances need coding into TAKEOVER_FN_HEADER functions! */
 
-/* Linear -> raid0_meta */
-TAKEOVER_FN_HEADER(_l_r0m)
-{
-	struct dm_list meta_lvs;
-	struct lv_segment *seg;
-
-	dm_list_init(&meta_lvs);
-
-	if (new_image_count != 1)
-		return 0;
-
-	/* Convert linear to raid by inserting a layer and presetting segtype as raid1 */
-	if (!(seg =_convert_linear_to_raid(lv)))
-		return 0;
-
-	if (segtype_is_raid0_meta(new_segtype)) {
-		/* Need to add an rmeta device to pair it with the given linear device as well */
-		if (!_alloc_rmeta_devs_for_lv(lv, &meta_lvs))
-			return 0;
-
-		/* Metadata LV must be cleared before being added to the array */
-		log_debug_metadata("Clearing newly allocated metadata LVs of %s", display_lvname(lv));
-		if (!_clear_lvs(&meta_lvs)) {
-			log_error("Failed to clear newly allocated metadata LVs of %s", display_lvname(lv));
-			return_0;
-		}
-
-		/* Grow areas arrays for metadata and data devs  */
-		log_debug_metadata("Realocating areas arrays of %s", display_lvname(lv));
-		if (!_realloc_meta_and_data_seg_areas(lv, seg, new_image_count)) {
-			log_error("Relocation of areas arrays for %s failed", display_lvname(lv));
-			return_0;
-		}
-
-		log_debug_metadata("Adding new metadata LV to %s", display_lvname(lv));
-		if (!_add_image_component_list(seg, 1, 0, &meta_lvs, 0)) {
-			log_error("Failed to add new metadata LV to %s", display_lvname(lv));
-			return_0;
-		}
-	}
-
-	seg->segtype = new_segtype;
-	seg->region_size = 0;
-
-	return lv_update_and_reload_origin(lv);
-}
-
 /* Linear -> raid0 */
 TAKEOVER_FN_HEADER(_l_r0)
 {
-	return _l_r0m(lv, 0, 0, new_segtype, 0, 0, 0, allocate_pvs);
+	return _linear_raid0(lv, 0, 0, new_segtype, 1, 0, 0, allocate_pvs);
 }
 
 /* Linear -> r1 */
@@ -5182,7 +4233,7 @@ TAKEOVER_FN_HEADER(_r10_r45)
 static takeover_fn _takeover_fn_table[9][9] = {
 	/* from |, to ->    linear  striped   mirror   raid0    raid0_meta  raid1    raid4/5     raid6  raid10 */
 	/*      v */
-	/* linear      */ { _noop,   _error,  _error,  _l_r0,   _l_r0m,     _l_r1,   _l_r45,    _error,  _l_r10   },
+	/* linear      */ { _noop,   _error,  _error,  _l_r0,   _l_r0,      _l_r1,   _l_r45,    _error,  _l_r10   },
 	/* striped     */ { _error,  _noop,   _error,  _s_r0,   _s_r0m,     _error,  _s_r45,    _s_r6,   _s_r10   },
 	/* mirror      */ { _error,  _error,  _noop,   _m_r0,   _m_r0m,     _m_r1,   _m_r45,    _error,  _m_r10   },
 	/* raid0       */ { _r0_l,   _r0_s,   _r0_m,   _noop,   _r0_r0m,    _r0_r1,  _r0_r45,   _r0_r6,  _r0_r10  },