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

[lvm-devel] [PATCH mirror 8/13] Allow removal of mirror images from not-collapsed mirror LV



remove_mirror_images() is existing function to remove mirror images
from mirrored LV.
This patch changes the function to walk through the mirror layers
to correctly remove mirror images.

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

Index: LVM2.work/lib/metadata/mirror.c
===================================================================
--- LVM2.work.orig/lib/metadata/mirror.c
+++ LVM2.work/lib/metadata/mirror.c
@@ -343,10 +343,12 @@ int collapse_mirrored_lv(struct logical_
 }
 
 /*
- * 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 lv_segment *mirrored_seg,
+				 uint32_t num_removed,
+				 struct list *removable_pvs,
+				 unsigned remove_log)
 {
 	uint32_t m;
 	uint32_t extents;
@@ -365,7 +367,7 @@ int remove_mirror_images(struct lv_segme
 
 	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 */
@@ -404,29 +406,29 @@ 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++) {
+	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;
 	}
 
-	mirrored_seg->area_count = num_mirrors;
+	mirrored_seg->area_count = new_area_count;
 
 	/* 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;
 		_move_lv_segments(mirrored_seg->lv, lv1);
-		mirrored_seg->lv->status &= ~MIRRORED;
-		mirrored_seg->lv->status &= ~MIRROR_NOTSYNCED;
+		mirrored_seg->lv->status = lv1->status & ~MIRROR_IMAGE;
 		remove_log = 1;
 		/* Replace mirror with error segment */
 		segtype = get_segtype_from_string(mirrored_seg->lv->vg->cmd, "error");
@@ -450,7 +452,7 @@ int remove_mirror_images(struct lv_segme
 		return_0;
 
 	/* Delete the 'orphan' LVs */
-	for (m = num_mirrors; m < old_area_count; m++)
+	for (m = new_area_count; m < old_area_count; m++)
 		if (!_delete_lv(mirrored_seg, seg_lv(mirrored_seg, m)))
 			return 0;
 
@@ -463,6 +465,42 @@ int remove_mirror_images(struct lv_segme
 	return 1;
 }
 
+/*
+ * Reduce mirrored_seg to num_mirrors images.
+ */
+int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
+			 struct list *removable_pvs, unsigned remove_log)
+{
+	struct logical_volume *lv = mirrored_seg->lv;
+	uint32_t num_removed, removed_once;
+	uint32_t existing_mirrors = lv_mirror_count(mirrored_seg->lv);
+	struct lv_segment *seg;
+
+	log_very_verbose("Reducing mirror set from %" PRIu32 " to %"
+			 PRIu32 " image(s)%s.",
+			 existing_mirrors, num_mirrors,
+			 remove_log ? " and no log volume" : "");
+
+	num_removed = existing_mirrors - num_mirrors;
+
+	while (num_removed) {
+		seg = first_seg(lv);
+
+		if (num_removed < seg->area_count)
+			removed_once = num_removed;
+		else
+			removed_once = seg->area_count - 1;
+
+		if (!_remove_mirror_images(seg, 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)
 {

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