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

[lvm-devel] [PATCH mirror 9/13] Add collapsing feature for stacked mirror



This is the main patch of this patchset.

Add collapsing feature to the stacked mirror.
dmeventd should be changed to call it when it detects the
completion of resync.

Thanks,
-- 
Jun'ichi Nomura, NEC Corporation of America
Add collapse_mirrored_lv() to collapse the mirror layers by
removing intermediate LVs when the resync completes.

Changes since rev1:
  * Extend _remove_mirror_images() so that it can return removed
    images to the caller instead of removing by itself.
    Collapsing function can use it.
  * _merge_mirror_images() uses lv_add_mirror_lvs()

Index: LVM2.work/lib/metadata/metadata-exported.h
===================================================================
--- LVM2.work.orig/lib/metadata/metadata-exported.h
+++ LVM2.work/lib/metadata/metadata-exported.h
@@ -485,6 +485,7 @@ int add_mirror_log(struct cmd_context *c
 
 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);
Index: LVM2.work/lib/metadata/mirror.c
===================================================================
--- LVM2.work.orig/lib/metadata/mirror.c
+++ LVM2.work/lib/metadata/mirror.c
@@ -135,7 +135,7 @@ static int _delete_lv(struct logical_vol
 static int _remove_mirror_images(struct logical_volume *lv,
 				 uint32_t num_removed,
 				 struct list *removable_pvs,
-				 unsigned remove_log)
+				 unsigned remove_log, struct list *orphan_lvs)
 {
 	uint32_t m;
 	uint32_t s, s1;
@@ -266,10 +266,16 @@ static int _remove_mirror_images(struct 
 		return 0;
 	}
 
-	/* Delete the 'orphan' LVs */
-	list_iterate_items(lvl, &tmp_orphan_lvs)
-		if (!_delete_lv(lv, lvl->lv))
-			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(lv, lv1))
 		return 0;
@@ -298,7 +304,7 @@ int remove_mirror_images(struct logical_
 			removed_once = first_seg(lv)->area_count - 1;
 
 		if (!_remove_mirror_images(lv, removed_once,
-				           removable_pvs, remove_log))
+				           removable_pvs, remove_log, NULL))
 			return_0;
 
 		num_removed -= removed_once;
@@ -307,6 +313,105 @@ int remove_mirror_images(struct logical_
 	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;
+}
+
 static int get_mirror_fault_policy(struct cmd_context *cmd __attribute((unused)),
 				   int log_policy)
 {
@@ -403,19 +508,13 @@ int reconfigure_mirror_images(struct lv_
 			      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.

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