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

[lvm-devel] LVM2 ./WHATS_NEW lib/metadata/lv_manip.c lib/m ...



CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	agk sourceware org	2007-12-20 18:55:46

Modified files:
	.              : WHATS_NEW 
	lib/metadata   : lv_manip.c metadata-exported.h metadata.c 
	                 metadata.h mirror.c 
	tools          : lvconvert.c lvresize.c toollib.c 

Log message:
	stacked mirror support (incomplete)

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.747&r2=1.748
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.137&r2=1.138
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.26&r2=1.27
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.144&r2=1.145
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.h.diff?cvsroot=lvm2&r1=1.175&r2=1.176
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/mirror.c.diff?cvsroot=lvm2&r1=1.46&r2=1.47
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.48&r2=1.49
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvresize.c.diff?cvsroot=lvm2&r1=1.89&r2=1.90
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/toollib.c.diff?cvsroot=lvm2&r1=1.119&r2=1.120

--- LVM2/WHATS_NEW	2007/12/20 15:42:55	1.747
+++ LVM2/WHATS_NEW	2007/12/20 18:55:46	1.748
@@ -1,5 +1,6 @@
 Version 2.02.30 -
 ===================================
+  Add support for stacked mirrors.
   Major restructuring of pvmove and lvconvert layer manipulation code.
   Replace tools/fsadm with scripts/fsadm.sh.
   Append fields to report/pvsegs_cols_verbose.
--- LVM2/lib/metadata/lv_manip.c	2007/12/20 15:42:55	1.137
+++ LVM2/lib/metadata/lv_manip.c	2007/12/20 18:55:46	1.138
@@ -1407,6 +1407,7 @@
 	for (m = old_area_count; m < new_area_count; m++) {
 		set_lv_segment_area_lv(seg, m, sub_lvs[m - old_area_count], 0, status);
 		first_seg(sub_lvs[m - old_area_count])->mirror_seg = seg;
+		sub_lvs[m - old_area_count]->status &= ~VISIBLE_LV;
 	}
 
 	return 1;
@@ -1451,6 +1452,39 @@
 	return 1;
 }
 
+static int _lv_extend_mirror(struct alloc_handle *ah,
+			     struct logical_volume *lv,
+			     uint32_t extents, uint32_t first_area)
+{
+	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))
+				return_0;
+			m += lv_mirror_count(seg_lv(seg, s));
+			continue;
+		}
+
+		if (!lv_add_segment(ah, m++, 1, seg_lv(seg, s),
+				    get_segtype_from_string(lv->vg->cmd,
+							    "striped"),
+				    0, 0, 0, NULL)) {
+			log_error("Aborting. Failed to extend %s.",
+				  seg_lv(seg, s)->name);
+			return 0;
+		}
+	}
+	seg->area_len += extents;
+	seg->len += extents;
+	lv->le_count += extents;
+	lv->size += (uint64_t) extents *lv->vg->extent_size;
+
+	return 1;
+}
+
 /*
  * Entry point for single-step LV allocation + extension.
  */
@@ -1464,9 +1498,7 @@
 	      alloc_policy_t alloc)
 {
 	int r = 1;
-	uint32_t m;
 	struct alloc_handle *ah;
-	struct lv_segment *seg;
 
 	if (segtype_is_virtual(segtype))
 		return lv_add_virtual_segment(lv, status, extents, segtype);
@@ -1482,21 +1514,8 @@
 			goto out;
 		}
 	} else {
-		seg = first_seg(lv);
-		for (m = 0; m < mirrors; m++) {
-			if (!lv_add_segment(ah, m, 1, seg_lv(seg, m),
-					    get_segtype_from_string(lv->vg->cmd,
-								    "striped"),
-					    0, 0, 0, NULL)) {
-				log_error("Aborting. Failed to extend %s.",
-					  seg_lv(seg, m)->name);
-				return 0;
-			}
-		}
-		seg->area_len += extents;
-		seg->len += extents;
-		lv->le_count += extents;
-		lv->size += (uint64_t) extents *lv->vg->extent_size;
+		if (!_lv_extend_mirror(ah, lv, extents, 0))
+			return_0;
 	}
 
       out:
@@ -1599,10 +1618,14 @@
 	list_iterate_items(seg, &lv->segments) {
 		if (seg->log_lv && !func(cmd, seg->log_lv, data))
 			return 0;
-		for (s = 0; s < seg->area_count; s++)
-			if (seg_type(seg, s) == AREA_LV &&
-			    !func(cmd, seg_lv(seg, s), data))
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) != AREA_LV)
+				continue;
+			if (!func(cmd, seg_lv(seg, s), data))
 				return 0;
+			if (!_for_each_sub_lv(cmd, seg_lv(seg, s), func, data))
+				return 0;
+		}
 	}
 
 	return 1;
@@ -2180,23 +2203,62 @@
 	lv_from->size = 0;
 }
 
+/*
+ * Find a parent LV for the layer_lv in the lv
+ */
+struct logical_volume *find_parent_for_layer(struct logical_volume *lv,
+                                            struct logical_volume *layer_lv)
+{
+	struct logical_volume *parent;
+	struct lv_segment *seg;
+	uint32_t s;
+
+	list_iterate_items(seg, &lv->segments) {
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) != AREA_LV)
+				continue;
+			if (seg_lv(seg, s) == layer_lv)
+				return lv;
+			parent = find_parent_for_layer(seg_lv(seg, s),
+						       layer_lv);
+			if (parent)
+				return parent;
+		}
+	}
+	return NULL;
+}
+
 /* Remove a layer from the LV */
-/* FIXME: how to specify what should be removed if multiple layers stacked? */
-int remove_layer_from_lv(struct logical_volume *lv)
+int remove_layer_from_lv(struct logical_volume *lv,
+			 struct logical_volume *layer_lv)
 {
-	struct logical_volume *orig_lv;
+	struct logical_volume *parent;
+	struct segment_type *segtype;
+
+	parent = find_parent_for_layer(lv, layer_lv);
+	if (!parent) {
+		log_error("Failed to find layer %s in %s",
+		layer_lv->name, lv->name);
+		return 0;
+	}
 
 	/*
 	 * Before removal, the layer should be cleaned up,
 	 * i.e. additional segments and areas should have been removed.
 	 */
-	if (list_size(&lv->segments) != 1 ||
-	    first_seg(lv)->area_count != 1 ||
-	    seg_type(first_seg(lv), 0) != AREA_LV)
-		return 0;
+	if (list_size(&parent->segments) != 1 ||
+	    first_seg(parent)->area_count != 1 ||
+	    seg_type(first_seg(parent), 0) != AREA_LV ||
+	    layer_lv != seg_lv(first_seg(parent), 0) ||
+	    parent->le_count != layer_lv->le_count)
+		return_0;
 
-	orig_lv = seg_lv(first_seg(lv), 0);
-	_move_lv_segments(lv, orig_lv, 0, 0);
+	_move_lv_segments(parent, layer_lv, 0, 0);
+
+	/* Replace the empty layer with error segment */
+	segtype = get_segtype_from_string(lv->vg->cmd, "error");
+	if (!lv_add_virtual_segment(layer_lv, 0, parent->le_count, segtype))
+		return_0;
 
 	return 1;
 }
--- LVM2/lib/metadata/metadata-exported.h	2007/12/20 15:42:55	1.26
+++ LVM2/lib/metadata/metadata-exported.h	2007/12/20 18:55:46	1.27
@@ -398,7 +398,10 @@
 				   struct list *lvs_changed);
 int split_parent_segments_for_layer(struct cmd_context *cmd,
 				    struct logical_volume *layer_lv);
-int remove_layer_from_lv(struct logical_volume *lv);
+struct logical_volume *find_parent_for_layer(struct logical_volume *lv,
+					     struct logical_volume *layer_lv);
+int remove_layer_from_lv(struct logical_volume *lv,
+			 struct logical_volume *layer_lv);
 struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
 					   struct logical_volume *lv_where,
 					   uint32_t status,
@@ -417,7 +420,7 @@
 					const char *pv_name);
 
 /* Find LV segment containing given LE */
-struct lv_segment *first_seg(struct logical_volume *lv);
+struct lv_segment *first_seg(const struct logical_volume *lv);
 
 
 /*
@@ -458,8 +461,8 @@
 #define MIRROR_BY_SEG	0x00000001U	/* segment-by-segment mirror */
 #define MIRROR_BY_LV	0x00000002U	/* mirror by mimage LVs */
 
-uint32_t lv_mirror_count(struct logical_volume *lv);
-struct alloc_handle;
+int is_temporary_mirror_layer(const struct logical_volume *lv);
+uint32_t lv_mirror_count(const struct logical_volume *lv);
 uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
                                     uint32_t region_size);
 int remove_mirrors_from_segments(struct logical_volume *lv,
@@ -468,7 +471,7 @@
 			    uint32_t mirrors, uint32_t region_size,
 			    struct list *allocatable_pvs, alloc_policy_t alloc);
 
-int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
+int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
 			 struct list *removable_pvs, unsigned remove_log);
 int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
 		      uint32_t mirrors, uint32_t stripes, uint32_t region_size,
@@ -482,6 +485,7 @@
 
 int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
 			      struct list *removable_pvs, unsigned remove_log);
+int collapse_mirrored_lv(struct logical_volume *lv);
 
 struct logical_volume *find_pvmove_lv(struct volume_group *vg,
 				      struct device *dev, uint32_t lv_type);
--- LVM2/lib/metadata/metadata.c	2007/11/15 02:20:03	1.144
+++ LVM2/lib/metadata/metadata.c	2007/12/20 18:55:46	1.145
@@ -937,7 +937,7 @@
 }
 
 /* Find segment at a given logical extent in an LV */
-struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le)
+struct lv_segment *find_seg_by_le(const struct logical_volume *lv, uint32_t le)
 {
 	struct lv_segment *seg;
 
@@ -948,7 +948,7 @@
 	return NULL;
 }
 
-struct lv_segment *first_seg(struct logical_volume *lv)
+struct lv_segment *first_seg(const struct logical_volume *lv)
 {
 	struct lv_segment *seg = NULL;
 
@@ -959,7 +959,7 @@
 }
 
 /* Find segment at a given physical extent in a PV */
-struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe)
+struct pv_segment *find_peg_by_pe(const struct physical_volume *pv, uint32_t pe)
 {
 	struct pv_segment *peg;
 
--- LVM2/lib/metadata/metadata.h	2007/12/20 15:42:55	1.175
+++ LVM2/lib/metadata/metadata.h	2007/12/20 18:55:46	1.176
@@ -264,10 +264,10 @@
 struct physical_volume *find_pv(struct volume_group *vg, struct device *dev);
 
 /* Find LV segment containing given LE */
-struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le);
+struct lv_segment *find_seg_by_le(const struct logical_volume *lv, uint32_t le);
 
 /* Find PV segment containing given LE */
-struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe);
+struct pv_segment *find_peg_by_pe(const struct physical_volume *pv, uint32_t pe);
 
 /*
  * Remove a dev_dir if present.
--- LVM2/lib/metadata/mirror.c	2007/12/20 15:42:55	1.46
+++ LVM2/lib/metadata/mirror.c	2007/12/20 18:55:46	1.47
@@ -33,11 +33,40 @@
 #define MIRROR_ALLOCATE_ANYWHERE 2
 
 /*
+ * Returns true if the lv is temporary mirror layer for resync
+ */
+int is_temporary_mirror_layer(const struct logical_volume *lv)
+{
+	if (lv->status & MIRROR_IMAGE
+	    && lv->status & MIRRORED
+	    && !(lv->status & LOCKED))
+		return 1;
+
+	return 0;
+}
+
+/*
  * Returns the number of mirrors of the LV
  */
-uint32_t lv_mirror_count(struct logical_volume *lv)
+uint32_t lv_mirror_count(const struct logical_volume *lv)
 {
-	return (lv->status & MIRRORED) ? first_seg(lv)->area_count : 1;
+	struct lv_segment *seg;
+	uint32_t s, mirrors;
+
+	if (!(lv->status & MIRRORED))
+		return 1;
+
+	seg = first_seg(lv);
+	mirrors = seg->area_count;
+
+	for (s = 0; s < seg->area_count; s++) {
+		if (seg_type(seg, s) != AREA_LV)
+			continue;
+		if (is_temporary_mirror_layer(seg_lv(seg, s)))
+			mirrors += lv_mirror_count(seg_lv(seg, s)) - 1;
+	}
+
+	return mirrors;
 }
 
 struct lv_segment *find_mirror_seg(struct lv_segment *seg)
@@ -68,21 +97,21 @@
 /*
  * Delete independent/orphan LV, it must acquire lock.
  */
-static int _delete_lv(struct lv_segment *mirrored_seg, struct logical_volume *lv)
+static int _delete_lv(struct logical_volume *mirror_lv, struct logical_volume *lv)
 {
-	struct cmd_context *cmd = mirrored_seg->lv->vg->cmd;
+	struct cmd_context *cmd = mirror_lv->vg->cmd;
 	struct str_list *sl;
 
 	/* Inherit tags - maybe needed for activation */
-	if (!str_list_match_list(&mirrored_seg->lv->tags, &lv->tags)) {
-		list_iterate_items(sl, &mirrored_seg->lv->tags)
+	if (!str_list_match_list(&mirror_lv->tags, &lv->tags)) {
+		list_iterate_items(sl, &mirror_lv->tags)
 			if (!str_list_add(cmd->mem, &lv->tags, sl->str)) {
 				log_error("Aborting. Unable to tag.");
 				return 0;
 			}
 
-		if (!vg_write(mirrored_seg->lv->vg) ||
-		    !vg_commit(mirrored_seg->lv->vg)) {
+		if (!vg_write(mirror_lv->vg) ||
+		    !vg_commit(mirror_lv->vg)) {
 			log_error("Intermediate VG commit for orphan volume failed.");
 			return 0;
 		}
@@ -101,29 +130,31 @@
 }
 
 /*
- * Reduce mirrored_seg to num_mirrors images.
+ * Remove num_removed images from mirrored_seg
  */
-int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
-			 struct list *removable_pvs, unsigned remove_log)
+static int _remove_mirror_images(struct logical_volume *lv,
+				 uint32_t num_removed,
+				 struct list *removable_pvs,
+				 unsigned remove_log, struct list *orphan_lvs)
 {
 	uint32_t m;
-	uint32_t extents;
 	uint32_t s, s1;
 	struct logical_volume *sub_lv;
 	struct logical_volume *log_lv = NULL;
 	struct logical_volume *lv1 = NULL;
 	struct physical_volume *pv;
-	struct lv_segment *seg;
+	struct lv_segment *seg, *mirrored_seg = first_seg(lv);
 	struct lv_segment_area area;
 	int all_pvs_removable, pv_found;
 	struct pv_list *pvl;
 	uint32_t old_area_count = mirrored_seg->area_count;
 	uint32_t new_area_count = mirrored_seg->area_count;
-	struct segment_type *segtype;
+	struct lv_list *lvl;
+	struct list tmp_orphan_lvs;
 
 	log_very_verbose("Reducing mirror set from %" PRIu32 " to %"
 			 PRIu32 " image(s)%s.",
-			 old_area_count, num_mirrors,
+			 old_area_count, old_area_count - num_removed,
 			 remove_log ? " and no log volume" : "");
 
 	/* Move removable_pvs to end of array */
@@ -162,39 +193,46 @@
 				mirrored_seg->areas[s] = area;
 			}
 			/* Found enough matches? */
-			if (new_area_count == num_mirrors)
+			if (old_area_count - new_area_count == num_removed)
 				break;
 		}
-		if (new_area_count == mirrored_seg->area_count) {
+		if (old_area_count == new_area_count) {
 			log_error("No mirror images found using specified PVs.");
 			return 0;
 		}
-	}
+	} else
+		new_area_count = old_area_count - num_removed;
 
-	for (m = num_mirrors; m < mirrored_seg->area_count; m++) {
+	/* Remove mimage LVs from the segment */
+	list_init(&tmp_orphan_lvs);
+	for (m = new_area_count; m < mirrored_seg->area_count; m++) {
 		seg_lv(mirrored_seg, m)->status &= ~MIRROR_IMAGE;
 		seg_lv(mirrored_seg, m)->status |= VISIBLE_LV;
+		if (!(lvl = dm_pool_alloc(lv->vg->cmd->mem, sizeof(*lvl)))) {
+			log_error("lv_list alloc failed");
+			return 0;
+		}
+		lvl->lv = seg_lv(mirrored_seg, m);
+		list_add(&tmp_orphan_lvs, &lvl->list);
 	}
+	mirrored_seg->area_count = new_area_count;
 
-	mirrored_seg->area_count = num_mirrors;
+	/* Save log_lv as mirrored_seg may not be available after
+	 * remove_layer_from_lv(), */
+	log_lv = mirrored_seg->log_lv;
 
 	/* If no more mirrors, remove mirror layer */
-	if (num_mirrors == 1) {
+	if (new_area_count == 1) {
 		lv1 = seg_lv(mirrored_seg, 0);
-		extents = lv1->le_count;
-		remove_layer_from_lv(mirrored_seg->lv);
-		mirrored_seg->lv->status &= ~MIRRORED;
-		mirrored_seg->lv->status &= ~MIRROR_NOTSYNCED;
-		remove_log = 1;
-		/* Replace mirror with error segment */
-		segtype = get_segtype_from_string(mirrored_seg->lv->vg->cmd, "error");
-		if (!lv_add_virtual_segment(lv1, 0, extents, segtype))
+		mirrored_seg->log_lv = NULL;
+		if (!remove_layer_from_lv(lv, lv1))
 			return_0;
+		lv->status &= ~MIRRORED;
+		lv->status &= ~MIRROR_NOTSYNCED;
+		remove_log = 1;
 	}
 
-	if (remove_log && mirrored_seg->log_lv) {
-		log_lv = mirrored_seg->log_lv;
-		mirrored_seg->log_lv = NULL;
+	if (remove_log && log_lv) {
 		log_lv->status &= ~MIRROR_LOG;
 		log_lv->status |= VISIBLE_LV;
 	}
@@ -228,16 +266,148 @@
 		return 0;
 	}
 
-	/* Delete the 'orphan' LVs */
-	for (m = num_mirrors; m < old_area_count; m++)
-		if (!_delete_lv(mirrored_seg, seg_lv(mirrored_seg, m)))
-			return 0;
+	/* Save or delete the 'orphan' LVs */
+	if (orphan_lvs) {
+		*orphan_lvs = tmp_orphan_lvs;
+		orphan_lvs->n->p = orphan_lvs;
+		orphan_lvs->p->n = orphan_lvs;
+	} else {
+		list_iterate_items(lvl, &tmp_orphan_lvs)
+			if (!_delete_lv(lv, lvl->lv))
+				return 0;
+	}
 
-	if (lv1 && !_delete_lv(mirrored_seg, lv1))
+	if (lv1 && !_delete_lv(lv, lv1))
 		return 0;
 
-	if (log_lv && !_delete_lv(mirrored_seg, log_lv))
+	if (remove_log && log_lv && !_delete_lv(lv, log_lv))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Remove the number of mirror images from the LV
+ */
+int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
+			 struct list *removable_pvs, unsigned remove_log)
+{
+	uint32_t num_removed, removed_once;
+	uint32_t existing_mirrors = lv_mirror_count(lv);
+
+	num_removed = existing_mirrors - num_mirrors;
+
+	while (num_removed) {
+		if (num_removed < first_seg(lv)->area_count)
+			removed_once = num_removed;
+		else
+			removed_once = first_seg(lv)->area_count - 1;
+
+		if (!_remove_mirror_images(lv, removed_once,
+				           removable_pvs, remove_log, NULL))
+			return_0;
+
+		num_removed -= removed_once;
+	}
+
+	return 1;
+}
+
+static int _mirrored_lv_in_sync(struct logical_volume *lv)
+{
+	float sync_percent;
+
+	if (!lv_mirror_percent(lv->vg->cmd, lv, 0, &sync_percent, NULL)) {
+		log_error("Unable to determine mirror sync status of %s/%s.",
+			  lv->vg->name, lv->name);
 		return 0;
+	}
+
+	if (sync_percent >= 100.0)
+		return 1;
+
+	return 0;
+}
+
+static int _merge_mirror_images(struct logical_volume *lv,
+				const struct list *mimages)
+{
+	int addition = list_size(mimages);
+	struct logical_volume **img_lvs;
+	struct lv_list *lvl;
+	int i = 0;
+
+	if (!addition)
+		return 1;
+
+	if (!(img_lvs = alloca(sizeof(*img_lvs) * addition)))
+		return_0;
+
+	list_iterate_items(lvl, mimages)
+		img_lvs[i++] = lvl->lv;
+
+	return lv_add_mirror_lvs(lv, img_lvs, addition,
+				 MIRROR_IMAGE, first_seg(lv)->region_size);
+}
+
+/*
+ * Return a temporary LV for resyncing added mirror image.
+ * Add other mirror legs to lvs list.
+ */
+static struct logical_volume *_find_tmp_mirror(struct logical_volume *lv)
+{
+	struct lv_segment *seg;
+
+	if (!(lv->status & MIRRORED))
+		return NULL;
+
+	seg = first_seg(lv);
+
+	/* Temporary mirror is always area_num == 0 */
+	if (seg_type(seg, 0) == AREA_LV &&
+	    is_temporary_mirror_layer(seg_lv(seg, 0)))
+		return seg_lv(seg, 0);
+
+	return NULL;
+}
+
+/*
+ * Collapsing temporary mirror layers.
+ *
+ * When mirrors are added to already-mirrored LV, a temporary mirror layer
+ * is inserted at the top of the stack to reduce resync work.
+ * The function will remove the intermediate layer and collapse the stack
+ * as far as mirrors are in-sync.
+ *
+ * The function is destructive: to remove intermediate mirror layers,
+ * VG metadata commits and suspend/resume are necessary.
+ */
+int collapse_mirrored_lv(struct logical_volume *lv)
+{
+	struct logical_volume *tmp_lv, *parent_lv;
+	struct list lvlist;
+
+	while ((tmp_lv = _find_tmp_mirror(lv))) {
+		parent_lv = find_parent_for_layer(lv, tmp_lv);
+		if (!_mirrored_lv_in_sync(parent_lv)) {
+			log_verbose("Not collapsing %s: out-of-sync",
+				    parent_lv->name);
+			return 1;
+		}
+
+		list_init(&lvlist);
+		if (!_remove_mirror_images(parent_lv,
+					   first_seg(parent_lv)->area_count - 1,
+					   NULL, 1, &lvlist)) {
+			log_error("Failed to release mirror images");
+			return 0;
+		}
+
+		if (!_merge_mirror_images(parent_lv, &lvlist)) {
+			log_error("Failed to add mirror images");
+			return 0;
+		}
+	}
 
 	return 1;
 }
@@ -338,19 +508,13 @@
 			      struct list *removable_pvs, unsigned remove_log)
 {
 	int r;
-	int in_sync = 0;
+	int in_sync;
 	int log_policy, dev_policy;
 	uint32_t old_num_mirrors = mirrored_seg->area_count;
 	int had_log = (mirrored_seg->log_lv) ? 1 : 0;
-	float sync_percent = 0;
 
 	/* was the mirror in-sync before problems? */
-	if (!lv_mirror_percent(mirrored_seg->lv->vg->cmd,
-			       mirrored_seg->lv, 0, &sync_percent, NULL))
-		log_error("WARNING: Unable to determine mirror sync status of %s/%s.",
-			  mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
-	else if (sync_percent >= 100.0)
-		in_sync = 1;
+	in_sync = _mirrored_lv_in_sync(mirrored_seg->lv);
 
 	/*
 	 * While we are only removing devices, we can have sync set.
@@ -359,7 +523,7 @@
 	 */
 	init_mirror_in_sync(in_sync);
 
-	r = remove_mirror_images(mirrored_seg, num_mirrors,
+	r = remove_mirror_images(mirrored_seg->lv, num_mirrors,
 				 removable_pvs, remove_log);
 	if (!r)
 		/* Unable to remove bad devices */
@@ -721,7 +885,7 @@
 		init_mirror_in_sync(0);
 	}
 
-	if (!remove_mirror_images(first_seg(lv), lv_mirror_count(lv),
+	if (!remove_mirror_images(lv, lv_mirror_count(lv),
 				  removable_pvs, 1U))
 		return_0;
 
@@ -1195,17 +1359,17 @@
 		return 0;
 	}
 
-	if (seg->area_count <= mirrors) {
+	if (lv_mirror_count(lv) <= mirrors) {
 		log_error("Removing more than existing: %d <= %d",
 			  seg->area_count, mirrors);
 		return 0;
 	}
-	new_mirrors = seg->area_count - mirrors - 1;
+	new_mirrors = lv_mirror_count(lv) - mirrors - 1;
 
 	/* MIRROR_BY_LV */
 	if (seg_type(seg, 0) == AREA_LV &&
 	    seg_lv(seg, 0)->status & MIRROR_IMAGE) {
-		return remove_mirror_images(first_seg(lv), new_mirrors + 1,
+		return remove_mirror_images(lv, new_mirrors + 1,
 					    pvs, log_count ? 1U : 0);
 	}
 
--- LVM2/tools/lvconvert.c	2007/12/20 15:42:55	1.48
+++ LVM2/tools/lvconvert.c	2007/12/20 18:55:46	1.49
@@ -369,14 +369,20 @@
 			return 1;
 		}
 	} else if (lp->mirrors > existing_mirrors) {
-		/* FIXME Unless anywhere, remove PV of log_lv
-		 * from allocatable_pvs & allocate
-		 * (mirrors - existing_mirrors) new areas
-		 */
-		/* FIXME Create mirror hierarchy to sync */
-		log_error("Adding mirror images is not "
-			  "supported yet.");
-		return 0;
+		/* FIXME: can't have multiple mlogs. force corelog. */
+		corelog = 1;
+		if (!insert_layer_for_lv(cmd, lv, 0, "_resync%d")) {
+			log_error("Failed to insert resync layer");
+			return 0;
+		}
+		if (!lv_add_mirrors(cmd, lv, lp->mirrors - existing_mirrors, 1,
+				    adjusted_mirror_region_size(
+						lv->vg->extent_size,
+						lv->le_count,
+						lp->region_size),
+				    corelog ? 0U : 1U, lp->pvh, lp->alloc,
+				    MIRROR_BY_LV))
+			return_0;
 	} else {
 		/* Reduce number of mirrors */
 		if (!lv_remove_mirrors(cmd, lv, existing_mirrors - lp->mirrors,
--- LVM2/tools/lvresize.c	2007/11/15 02:20:03	1.89
+++ LVM2/tools/lvresize.c	2007/12/20 18:55:46	1.90
@@ -435,7 +435,7 @@
 	if ((lp->extents > lv->le_count)) {
 		list_iterate_back_items(seg, &lv->segments) {
 			if (seg_is_mirrored(seg))
-				seg_mirrors = seg->area_count;
+				seg_mirrors = lv_mirror_count(seg->lv);
 			else
 				seg_mirrors = 0;
 			break;
@@ -469,7 +469,7 @@
 			}
 
 			if (seg_is_mirrored(seg))
-				seg_mirrors = seg->area_count;
+				seg_mirrors = lv_mirror_count(seg->lv);
 			else
 				seg_mirrors = 0;
 
--- LVM2/tools/toollib.c	2007/12/20 15:42:55	1.119
+++ LVM2/tools/toollib.c	2007/12/20 18:55:46	1.120
@@ -1222,6 +1222,12 @@
 		return 0;
 	}
 
+	if (strstr(name, "_resync")) {
+		log_error("Names including \"_resync\" are reserved. "
+			  "Please choose a different LV name.");
+		return 0;
+	}
+
 	return 1;
 }
 


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