[lvm-devel] [PATCH 2 of 2] LVM: allow lv_extend of empty layered volumes

Jonathan Brassow jbrassow at redhat.com
Tue Mar 29 13:04:52 UTC 2011


Patch name: lvm-allow-lv_extend-of-empty-layered-volumes.patch

This patch adds the ability to extend 0 length layered LVs.  This
allows us to allocate all images of a mirror (or RAID array) at one
time during create.

The current mirror implementation still requires a separate allocation
for the log, however.

Index: LVM2/lib/metadata/lv_manip.c
===================================================================
--- LVM2.orig/lib/metadata/lv_manip.c
+++ LVM2/lib/metadata/lv_manip.c
@@ -2106,29 +2106,90 @@ int lv_add_log_segment(struct alloc_hand
 			      0, status, 0);
 }
 
-static int _lv_extend_mirror(struct alloc_handle *ah,
-			     struct logical_volume *lv,
-			     uint32_t extents, uint32_t first_area,
-			     uint32_t stripes, uint32_t stripe_size)
+static int _lv_insert_empty_layer(struct logical_volume *lv,
+				  const struct segment_type *segtype,
+				  uint32_t region_size,
+				  uint32_t devices)
+{
+	struct logical_volume *sub_lv;
+	uint32_t i;
+	uint64_t status = 0;
+	char *img_name;
+	size_t len;
+	struct lv_segment *mapseg;
+
+	if (lv->le_count || first_seg(lv)) {
+		/*
+		 * This should never happen.  The message is meant
+		 * to help developers.
+		 */
+		log_error("Bad arguments to _lv_insert_empty_layer");
+		return 0;
+	}
+
+	/* FIXME: Mirror specific */
+	lv->status |= MIRRORED;
+
+	/*
+	 * First, create our top-level segment for our top-level LV
+	 */
+	if (!(mapseg = alloc_lv_segment(lv->vg->cmd->mem, segtype,
+					lv, 0, 0, lv->status, 0, NULL,
+					devices, 0, 0, region_size, 0, NULL))) {
+		log_error("Failed to create mapping segment for %s", lv->name);
+		return 0;
+	}
+
+	/*
+	 * Next, create all of our sub_lv's and link them in.
+	 */
+	len = strlen(lv->name) + 32;
+	if (!(img_name = alloca(len)))
+		return_0;
+	if (dm_snprintf(img_name, len, "%s%s", lv->name, "_mimage_%d") < 0)
+		return_0;
+
+	for (i = 0; i < devices; i++) {
+		sub_lv = lv_create_empty(img_name, NULL,
+					 MIRROR_IMAGE, lv->alloc, lv->vg);
+		if (!sub_lv) {
+			log_error("Failed to allocate sub_lv for %s", lv->name);
+			return 0;
+		}
+		if (!set_lv_segment_area_lv(mapseg, i, sub_lv, 0, status))
+			return_0;
+	}
+	dm_list_add(&lv->segments, &mapseg->list);
+
+	return 1;
+}
+
+static int _lv_extend_layered_lv(struct alloc_handle *ah,
+				 struct logical_volume *lv,
+				 uint32_t extents, uint32_t first_area,
+				 uint32_t stripes, uint32_t stripe_size)
 {
+	struct logical_volume *sub_lv;
 	struct lv_segment *seg;
 	uint32_t m, s;
 
 	seg = first_seg(lv);
 	for (m = first_area, s = 0; s < seg->area_count; s++) {
 		if (is_temporary_mirror_layer(seg_lv(seg, s))) {
-			if (!_lv_extend_mirror(ah, seg_lv(seg, s), extents, m, stripes, stripe_size))
+			if (!_lv_extend_layered_lv(ah, seg_lv(seg, s), extents,
+						   m, stripes, stripe_size))
 				return_0;
 			m += lv_mirror_count(seg_lv(seg, s));
 			continue;
 		}
 
-		if (!lv_add_segment(ah, m, stripes, seg_lv(seg, s),
+		sub_lv = seg_lv(seg, s);
+		if (!lv_add_segment(ah, m, stripes, sub_lv,
 				    get_segtype_from_string(lv->vg->cmd,
 							    "striped"),
-				    stripe_size, 0, 0)) {
-			log_error("Aborting. Failed to extend %s.",
-				  seg_lv(seg, s)->name);
+				    stripe_size, sub_lv->status, 0)) {
+			log_error("Aborting. Failed to extend %s in %s.",
+				  sub_lv->name, lv->name);
 			return 0;
 		}
 		m += stripes;
@@ -2147,9 +2208,9 @@ static int _lv_extend_mirror(struct allo
 int lv_extend(struct logical_volume *lv,
 	      const struct segment_type *segtype,
 	      uint32_t stripes, uint32_t stripe_size,
-	      uint32_t mirrors, uint32_t extents,
-	      struct dm_list *allocatable_pvs,
-	      alloc_policy_t alloc)
+	      uint32_t mirrors, uint32_t region_size,
+	      uint32_t extents,
+	      struct dm_list *allocatable_pvs, alloc_policy_t alloc)
 {
 	int r = 1;
 	struct alloc_handle *ah;
@@ -2161,12 +2222,34 @@ int lv_extend(struct logical_volume *lv,
 				    extents, allocatable_pvs, alloc, NULL)))
 		return_0;
 
-	if (mirrors < 2)
+	if (!segtype_is_mirrored(segtype))
 		r = lv_add_segment(ah, 0, ah->area_count, lv, segtype,
 				   stripe_size, 0u, 0);
-	else
-		r = _lv_extend_mirror(ah, lv, extents, 0, stripes, stripe_size);
+	else {
+		uint32_t dev_count;
+
+		/*
+		 * When RAID is introduced, all the devices are AREA_LV.
+		 * However, when LVM does 'mirror on stripe' using legacy
+		 * targets, the mirror legs are AREA_LV while the stripes
+		 * underneath are AREA_PV
+		 *
+		if (segtype_is_raid(segtype))
+			dev_count = mirrors * stripes;
+		else
+		*/
+		dev_count = mirrors;
+		if (!lv->le_count &&
+		    !_lv_insert_empty_layer(lv, segtype,
+					    region_size, dev_count)) {
+			log_error("Failed to insert layer for %s", lv->name);
+			alloc_destroy(ah);
+			return 0;
+		}
 
+		r = _lv_extend_layered_lv(ah, lv, extents, 0,
+					  stripes, stripe_size);
+	}
 	alloc_destroy(ah);
 	return r;
 }
@@ -3387,7 +3470,7 @@ static struct logical_volume *_create_vi
 				   ALLOC_INHERIT, vg)))
 		return_NULL;
 
-	if (!lv_extend(lv, segtype, 1, 0, 1, voriginextents,
+	if (!lv_extend(lv, segtype, 1, 0, 1, 0, voriginextents,
 		       NULL, ALLOC_INHERIT))
 		return_NULL;
 
@@ -3586,6 +3669,10 @@ int lv_create_single(struct volume_group
 				  "Don't read what you didn't write!");
 			status |= LV_NOTSYNCED;
 		}
+
+		lp->segtype = get_segtype_from_string(cmd, "mirror");
+		if (!lp->segtype)
+			return_0;
 	}
 
 	if (!(lv = lv_create_empty(lp->lv_name ? lp->lv_name : "lvol%d", NULL,
@@ -3609,19 +3696,17 @@ int lv_create_single(struct volume_group
 		dm_list_splice(&lv->tags, &lp->tags);
 
 	if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size,
-		       1, lp->extents, lp->pvh, lp->alloc))
+		       lp->mirrors,
+		       adjusted_mirror_region_size(vg->extent_size,
+						   lv->le_count,
+						   lp->region_size),
+		       lp->extents, lp->pvh, lp->alloc))
 		return_0;
 
 	if (lp->mirrors > 1) {
-		if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, lp->stripes,
-				    lp->stripe_size,
-				    adjusted_mirror_region_size(
-						vg->extent_size,
-						lv->le_count,
-						lp->region_size),
-				    lp->log_count, lp->pvh, lp->alloc,
-				    MIRROR_BY_LV |
-				    (lp->nosync ? MIRROR_SKIP_INIT_SYNC : 0))) {
+		if (!add_mirror_log(cmd, lv, lp->log_count,
+				    first_seg(lv)->region_size,
+				    lp->pvh, lp->alloc)) {
 			stack;
 			goto revert_new_lv;
 		}
Index: LVM2/lib/metadata/metadata-exported.h
===================================================================
--- LVM2.orig/lib/metadata/metadata-exported.h
+++ LVM2/lib/metadata/metadata-exported.h
@@ -500,9 +500,9 @@ int replace_lv_with_error_segment(struct
 int lv_extend(struct logical_volume *lv,
 	      const struct segment_type *segtype,
 	      uint32_t stripes, uint32_t stripe_size,
-	      uint32_t mirrors, uint32_t extents,
-	      struct dm_list *allocatable_pvs,
-	      alloc_policy_t alloc);
+	      uint32_t mirrors, uint32_t region_size,
+	      uint32_t extents,
+	      struct dm_list *allocatable_pvs, alloc_policy_t alloc);
 
 /* lv must be part of lv->vg->lvs */
 int lv_remove(struct logical_volume *lv);
Index: LVM2/tools/lvresize.c
===================================================================
--- LVM2.orig/tools/lvresize.c
+++ LVM2/tools/lvresize.c
@@ -670,8 +670,9 @@ static int _lvresize(struct cmd_context 
 			return ECMD_FAILED;
 		}
 	} else if ((lp->extents > lv->le_count) && /* Ensure we extend */
-		   !lv_extend(lv, lp->segtype, lp->stripes,
-			      lp->stripe_size, lp->mirrors,
+		   !lv_extend(lv, lp->segtype,
+			      lp->stripes, lp->stripe_size,
+			      lp->mirrors, first_seg(lv)->region_size,
 			      lp->extents - lv->le_count,
 			      pvh, alloc)) {
 		stack;




More information about the lvm-devel mailing list