[lvm-devel] master - lvcreate: Fix mirror percentage size calculations.

Alasdair Kergon agk at sourceware.org
Fri May 12 01:31:52 UTC 2017


Gitweb:        https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=cf73f6cf61793e9d71391bb7a8f35162509898a4
Commit:        cf73f6cf61793e9d71391bb7a8f35162509898a4
Parent:        d49a20b7bdc9b741def219be897c5057db5e05ff
Author:        Alasdair G Kergon <agk at redhat.com>
AuthorDate:    Fri May 12 02:04:05 2017 +0100
Committer:     Alasdair G Kergon <agk at redhat.com>
CommitterDate: Fri May 12 02:31:35 2017 +0100

lvcreate: Fix mirror percentage size calculations.

Trap cases where the percentage calculation currently leads to an empty
LV and the message:

  Internal error: Unable to create new logical volume with no extents

Additionally convert the calculated number of extents from physical to
logical when creating a mirror using a percentage that is based on
Physical Extents.  Otherwise a command like 'lvcreate -m3 -l80%FREE'
can never leave any free space.

This brings the behaviour closer to that of lvresize.
(A further patch is needed to cover all the raid types.)
---
 WHATS_NEW        |    1 +
 tools/lvcreate.c |   37 ++++++++++++++++++++++++++++++-------
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/WHATS_NEW b/WHATS_NEW
index e0741a9..abe4641 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.02.172 - 
 ===============================
+  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.
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index f775290..dddf8ad 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 (!lp->extents) {
+		log_error("Adjusted size of logical volume is 0 extents. Needs to be larger.");
+		return 0;
+	}
+
 	return 1;
 }
 




More information about the lvm-devel mailing list