[lvm-devel] master - raid: conditionally reject convert to striped/raid0*

Heinz Mauelshagen heinzm at sourceware.org
Fri Mar 17 13:00:15 UTC 2017


Gitweb:        https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=17bee733d16e88d260b7de826c747c6ade9f797c
Commit:        17bee733d16e88d260b7de826c747c6ade9f797c
Parent:        5e7bc8d854bb6752e6987692791750a48e871442
Author:        Heinz Mauelshagen <heinzm at redhat.com>
AuthorDate:    Fri Mar 17 13:58:54 2017 +0100
Committer:     Heinz Mauelshagen <heinzm at redhat.com>
CommitterDate: Fri Mar 17 13:58:54 2017 +0100

raid: conditionally reject convert to striped/raid0*

If SubLVs to be removed still exist after an image removing
conversion (i.e. "lvconvert --yes --force --stripes N "
with N < total stripes) any request to convert to a different
striped/raid* level has to be rejected until after those freed
SubLVs got removed by running the aforementioned lvconvert again.

Add tests to check conversion to striped/raid* gets rejected.
Enhance a test comment.

Related: rhbz1191935
Related: rhbz1366296
---
 lib/metadata/raid_manip.c            |   54 +++++++++++++++++++++++++--------
 test/shell/lvconvert-raid-reshape.sh |   14 +++++++-
 2 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index dbffc5a..df48897 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -171,6 +171,33 @@ char *top_level_lv_name(struct volume_group *vg, const char *lv_name)
 	return new_lv_name;
 }
 
+/* Get available and removed SubLVs for @lv */
+static int _get_available_removed_sublvs(const struct logical_volume *lv, uint32_t *available_slvs, uint32_t *removed_slvs)
+{
+	uint32_t s;
+	struct lv_segment *seg = first_seg(lv);
+
+	*available_slvs = 0;
+	*removed_slvs = 0;
+
+	if (!lv_is_raid(lv))
+		return 1;
+
+	for (s = 0; s < seg->area_count; s++) {
+		struct logical_volume *slv;
+
+		if (seg_type(seg, s) != AREA_LV || !(slv = seg_lv(seg, s))) {
+			log_error(INTERNAL_ERROR "Missing image sub lv in area %" PRIu32 " of LV %s.",
+				  s, display_lvname(lv));
+			return_0;
+		}
+
+		(slv->status & LV_REMOVE_AFTER_RESHAPE) ? (*removed_slvs)++ : (*available_slvs)++;
+	}
+
+	return 1;
+}
+
 static int _lv_is_raid_with_tracking(const struct logical_volume *lv,
 				     struct logical_volume **tracking)
 {
@@ -1916,19 +1943,8 @@ static int _raid_reshape_remove_images(struct logical_volume *lv,
 		 * -> remove the freed up images and reduce LV size
 		 *
 		 */
-		for (active_lvs = removed_lvs = s = 0; s < seg->area_count; s++) {
-			struct logical_volume *slv;
-
-			if (!seg_lv(seg, s) || !(slv = seg_lv(seg, s))) {
-				log_error("Missing image sub lv off LV %s.", display_lvname(lv));
-				return 0;
-			}
-
-			if (slv->status & LV_REMOVE_AFTER_RESHAPE)
-				removed_lvs++;
-			else
-				active_lvs++;
-		}
+		if (!_get_available_removed_sublvs(lv, &active_lvs,  &removed_lvs))
+			return_0;
 
 		if (devs_in_sync != new_image_count) {
 			log_error("No correct kernel/lvm active LV count on %s.", display_lvname(lv));
@@ -5965,6 +5981,7 @@ int lv_raid_convert(struct logical_volume *lv,
 	uint32_t new_image_count = seg->area_count;
 	uint32_t region_size = new_region_size;
 	uint32_t data_copies = seg->data_copies;
+	uint32_t available_slvs, removed_slvs;
 	takeover_fn_t takeover_fn;
 
 	new_segtype = new_segtype ? : seg->segtype;
@@ -6016,6 +6033,17 @@ int lv_raid_convert(struct logical_volume *lv,
 		return 0;
 	}
 
+	/* 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;
+	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);
+		log_error("Run \"lvconvert --stripes %" PRIu32 " %s\" first.",
+			  seg->area_count - removed_slvs - 1, display_lvname(lv));
+		return 0;
+	}
+
 	/*
 	 * Check acceptible options mirrors, region_size,
 	 * stripes and/or stripe_size have been provided.
diff --git a/test/shell/lvconvert-raid-reshape.sh b/test/shell/lvconvert-raid-reshape.sh
index 05c4784..f9ff744 100644
--- a/test/shell/lvconvert-raid-reshape.sh
+++ b/test/shell/lvconvert-raid-reshape.sh
@@ -110,7 +110,7 @@ aux wait_for_sync $vg $lv1
 _reshape_layout raid5_ls 3 4 $vg $lv1 --stripesize 256K
 check lv_first_seg_field $vg/$lv1 stripesize "256.00k"
 
-# Convert raid5(_n) -> striped
+# Convert raid5(_n) -> striped testing raid5_ls gets rejected
 not _lvconvert striped striped 3 3 $vg $lv1 512k
 _reshape_layout raid5_n 3 4 $vg $lv1
 _lvconvert striped striped 3 3 $vg $lv1
@@ -144,8 +144,18 @@ _reshape_layout raid5_ls 63 64 $vg $lv1 --stripes 63
 _reshape_layout raid5_ls 27 64 $vg $lv1 --stripes 27 --force
 _reshape_layout raid5_ls 27 28 $vg $lv1 --stripes 27
 
-# Convert raid5_ls back to 4 stripes
+# Convert raid5_ls back to 4 stripes checking
+# conversion to striped/raid* gets rejected
+# with existing LVs to be removed afer reshape
 _reshape_layout raid5_ls 4 28 $vg $lv1 --stripes 4 --force
+
+# No we got the data reshaped and the freed SubLVs still present
+# -> check takeover request gets rejected
+not lvconvert --yes --type striped $vg/$lv1
+not lvconvert --yes --type raid0 $vg/$lv1
+not lvconvert --yes --type raid0_meta $vg/$lv1
+not lvconvert --yes --type raid6 $vg/$lv1
+# Remove the freed SubLVs
 _reshape_layout raid5_ls 4 5 $vg $lv1 --stripes 4
 
 # Convert raid5_ls back to 3 stripes




More information about the lvm-devel mailing list