[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[linux-lvm] [PATCH] recalculate free space on PE resize



Hi folks

This patch makes it possible to extend the size of PE. It recalculates
free space infos. Also it collects all errors which makes a resize fail
before bailing out.

Bastian

Index: lib/metadata/metadata.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/metadata/metadata.c,v
retrieving revision 1.195
diff -u -r1.195 metadata.c
--- lib/metadata/metadata.c	3 Nov 2008 22:14:29 -0000	1.195
+++ lib/metadata/metadata.c	7 Nov 2008 11:39:57 -0000
@@ -567,18 +567,12 @@
 	return NULL;
 }
 
-static int _recalc_extents(uint32_t *extents, const char *desc1,
-			   const char *desc2, uint32_t old_size,
-			   uint32_t new_size)
+static int _recalc_extents_adjust(uint32_t *extents, const char *desc1,
+		        	  const char *desc2, uint32_t old_size,
+			          uint32_t new_size)
 {
 	uint64_t size = (uint64_t) old_size * (*extents);
 
-	if (size % new_size) {
-		log_error("New size %" PRIu64 " for %s%s not an exact number "
-			  "of new extents.", size, desc1, desc2);
-		return 0;
-	}
-
 	size /= new_size;
 
 	if (size > UINT32_MAX) {
@@ -587,15 +581,35 @@
 		return 0;
 	}
 
+	log_debug("Changed %s%s from %u to %u.", desc1, desc2, *extents,
+		  (uint32_t)size);
+
 	*extents = (uint32_t) size;
 
 	return 1;
 }
 
+static int _recalc_extents(uint32_t *extents, const char *desc1,
+			   const char *desc2, uint32_t old_size,
+			   uint32_t new_size)
+{
+	uint64_t size = (uint64_t) old_size * (*extents);
+
+	if (size % new_size) {
+		log_error("New size %" PRIu64 " for %s%s not an exact number "
+			  "of new extents.", size, desc1, desc2);
+		return 0;
+	}
+
+	return _recalc_extents_adjust(extents, desc1, desc2, old_size,
+				      new_size);
+}
+
 int vg_change_pesize(struct cmd_context *cmd __attribute((unused)),
 		     struct volume_group *vg, uint32_t new_size)
 {
 	uint32_t old_size = vg->extent_size;
+	uint32_t new_extent_count = 0, new_free_count = 0;
 	struct pv_list *pvl;
 	struct lv_list *lvl;
 	struct physical_volume *pv;
@@ -603,6 +617,7 @@
 	struct lv_segment *seg;
 	struct pv_segment *pvseg;
 	uint32_t s;
+        int ret = 1;
 
 	vg->extent_size = new_size;
 
@@ -610,26 +625,21 @@
 	    !vg->fid->fmt->ops->vg_setup(vg->fid, vg))
 		return_0;
 
-	if (!_recalc_extents(&vg->extent_count, vg->name, "", old_size,
-			     new_size))
-		return_0;
-
-	if (!_recalc_extents(&vg->free_count, vg->name, " free space",
-			     old_size, new_size))
-		return_0;
-
 	/* foreach PV */
 	dm_list_iterate_items(pvl, &vg->pvs) {
 		pv = pvl->pv;
 
 		pv->pe_size = new_size;
-		if (!_recalc_extents(&pv->pe_count, pv_dev_name(pv), "",
-				     old_size, new_size))
-			return_0;
+		if (!_recalc_extents_adjust(&pv->pe_count, pv_dev_name(pv), "",
+					    old_size, new_size))
+			ret = 0;
 
 		if (!_recalc_extents(&pv->pe_alloc_count, pv_dev_name(pv),
 				     " allocated space", old_size, new_size))
-			return_0;
+			ret = 0;
+
+		new_extent_count += pv->pe_count;
+ 		new_free_count += pv->pe_count - pv->pe_alloc_count;
 
 		/* foreach free PV Segment */
 		dm_list_iterate_items(pvseg, &pv->segments) {
@@ -639,11 +649,11 @@
 			if (!_recalc_extents(&pvseg->pe, pv_dev_name(pv),
 					     " PV segment start", old_size,
 					     new_size))
-				return_0;
-			if (!_recalc_extents(&pvseg->len, pv_dev_name(pv),
-					     " PV segment length", old_size,
-					     new_size))
-				return_0;
+				ret = 0;
+			if (!_recalc_extents_adjust(&pvseg->len, pv_dev_name(pv),
+		        			    " PV segment length", old_size,
+			                	    new_size))
+				ret = 0;
 		}
 	}
 
@@ -653,28 +663,28 @@
 
 		if (!_recalc_extents(&lv->le_count, lv->name, "", old_size,
 				     new_size))
-			return_0;
+			ret = 0;
 
 		dm_list_iterate_items(seg, &lv->segments) {
 			if (!_recalc_extents(&seg->le, lv->name,
 					     " segment start", old_size,
 					     new_size))
-				return_0;
+				ret = 0;
 
 			if (!_recalc_extents(&seg->len, lv->name,
 					     " segment length", old_size,
 					     new_size))
-				return_0;
+				ret = 0;
 
 			if (!_recalc_extents(&seg->area_len, lv->name,
 					     " area length", old_size,
 					     new_size))
-				return_0;
+				ret = 0;
 
 			if (!_recalc_extents(&seg->extents_copied, lv->name,
 					     " extents moved", old_size,
 					     new_size))
-				return_0;
+				ret = 0;
 
 			/* foreach area */
 			for (s = 0; s < seg->area_count; s++) {
@@ -685,32 +695,38 @@
 					     lv->name,
 					     " pvseg start", old_size,
 					     new_size))
-						return_0;
+						ret = 0;
 					if (!_recalc_extents
 					    (&seg_pvseg(seg, s)->len,
 					     lv->name,
 					     " pvseg length", old_size,
 					     new_size))
-						return_0;
+						ret = 0;
 					break;
 				case AREA_LV:
 					if (!_recalc_extents
 					    (&seg_le(seg, s), lv->name,
 					     " area start", old_size,
 					     new_size))
-						return_0;
+						ret = 0;
 					break;
 				case AREA_UNASSIGNED:
 					log_error("Unassigned area %u found in "
 						  "segment", s);
-					return 0;
+					ret = 0;
 				}
 			}
 		}
 
 	}
 
-	return 1;
+	vg->extent_count = new_extent_count;
+	vg->free_count = new_free_count;
+
+	if (ret == 0)
+		stack;
+
+	return ret;
 }
 
 /*
Index: tools/vgchange.c
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/vgchange.c,v
retrieving revision 1.66
diff -u -r1.66 vgchange.c
--- tools/vgchange.c	3 Nov 2008 22:14:30 -0000	1.66
+++ tools/vgchange.c	7 Nov 2008 11:40:00 -0000
@@ -409,14 +409,6 @@
 		return EINVALID_CMD_LINE;
 	}
 
-	if (extent_size > vg->extent_size) {
-		if ((uint64_t) vg->extent_size * vg->extent_count % extent_size) {
-			/* FIXME Adjust used PV sizes instead */
-			log_error("New extent size is not a perfect fit");
-			return EINVALID_CMD_LINE;
-		}
-	}
-
 	if (!archive(vg))
 		return ECMD_FAILED;
 
-- 
First study the enemy.  Seek weakness.
		-- Romulan Commander, "Balance of Terror", stardate 1709.2

Attachment: signature.asc
Description: Digital signature


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]