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

[lvm-devel] [PATCH mirror 6/13] remove_mirror_images() to cope with stacked mirror



Change remove_mirror_images()
  - take LV as an argument, instead of LV segment, because segment-lv
    relationship could change after the layer removal
  - to cope with the stacked mirror LV, check the difference between
    lv_mirror_count() and seg->area_count.
    Iterate in this way: remove legs from the top-level mirror, if
    the mirror is turned to linear, collapse one layer and restart
    with remainder.

Thanks,
-- 
Jun'ichi Nomura, NEC Corporation of America

Change remove_mirror_images()
  - take LV as an argument, instead of LV segment, because segment-lv
    relationship could change after the layer removal
  - to cope with the stacked mirror LV, check the difference between
    lv_mirror_count() and seg->area_count.
    Iterate in this way: remove legs from the top-level mirror, if
    the mirror is turned to linear, collapse one layer and restart
    with remainder.

Index: LVM2.work/lib/metadata/mirror.c
===================================================================
--- LVM2.work.orig/lib/metadata/mirror.c
+++ LVM2.work/lib/metadata/mirror.c
@@ -97,21 +97,21 @@ uint32_t adjusted_mirror_region_size(uin
 /*
  * 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;
 		}
@@ -130,29 +130,31 @@ static int _delete_lv(struct lv_segment 
 }
 
 /*
- * 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)
 {
 	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 */
@@ -191,39 +193,46 @@ int remove_mirror_images(struct lv_segme
 				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, lv1);
-		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;
 	}
@@ -258,19 +267,46 @@ int remove_mirror_images(struct lv_segme
 	}
 
 	/* Delete the 'orphan' LVs */
-	for (m = num_mirrors; m < old_area_count; m++)
-		if (!_delete_lv(mirrored_seg, seg_lv(mirrored_seg, m)))
+	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))
+			return_0;
+
+		num_removed -= removed_once;
+	}
+
+	return 1;
+}
+
 static int get_mirror_fault_policy(struct cmd_context *cmd __attribute((unused)),
 				   int log_policy)
 {
@@ -388,7 +424,7 @@ int reconfigure_mirror_images(struct lv_
 	 */
 	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 */
@@ -750,7 +786,7 @@ int remove_mirror_log(struct cmd_context
 		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;
 
@@ -1234,7 +1270,7 @@ int lv_remove_mirrors(struct cmd_context
 	/* 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);
 	}
 
Index: LVM2.work/lib/metadata/metadata-exported.h
===================================================================
--- LVM2.work.orig/lib/metadata/metadata-exported.h
+++ LVM2.work/lib/metadata/metadata-exported.h
@@ -471,7 +471,7 @@ int add_mirrors_to_segments(struct cmd_c
 			    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,

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