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

[lvm-devel] [PATCH pvmove 2/3] support splitted destinations of pvmove



Currently, pvmove can't split destination area.
This patch removes the restriction.
(Actually, a prepration for removing the restriction.)

If you have 1GB LV on a contiguous area of PV1
and would like to move it to 2 x 500MB PVs, PV2 and PV3,
you have to manually split the pvmove session into 2.

It's because pvmove assumes 1-1 relationship between
source area and destination area and forces a contiguous allocation.

This patch changes pvmove completion to split the original segment
to map to the destination areas.

Other patch ("3/3" of this series) allows allocation of splitted areas
for a single source area.

Thanks,
-- 
Jun'ichi Nomura, NEC Corporation of America
If a source area is splitted to multiple destinations during pvmove,
remove_pvmove_mirrors() has to split the LV segment to match with
the new areas.

Index: LVM2.work/lib/metadata/mirror.c
===================================================================
--- LVM2.work.orig/lib/metadata/mirror.c
+++ LVM2.work/lib/metadata/mirror.c
@@ -593,6 +590,46 @@ static int add_area_to_pvmove(struct log
 	return 1;
 }
 
+/*
+ * split the source lv_segment if pvmove segment is splitted
+ */
+static int _split_source_lv_segment(struct logical_volume *lv_mirr,
+				    struct lv_segment *seg, uint32_t s)
+{
+	struct lv_segment *mir_seg;
+	uint32_t src_area_len, src_le, mirr_le;
+	uint32_t area_multiple;
+
+	if (seg_is_striped(seg))
+		area_multiple = seg->area_count;
+	else
+		area_multiple = 1;
+
+	src_area_len = seg->area_len;
+	src_le = seg->le;
+	mirr_le = seg_le(seg, s);
+
+	while (src_area_len > 0) {
+		/* Find the mirror segment pointed at */
+		if (!(mir_seg = find_seg_by_le(lv_mirr, mirr_le))) {
+			log_error("pvmove segment for %s:%" PRIu32 " not found",
+				  seg->lv->name, src_le);
+			return 0;
+		}
+
+		if (mir_seg->area_len < src_area_len) {
+			src_le += mir_seg->area_len * area_multiple;
+			if (!lv_split_segment(seg->lv, src_le))
+				return_0;
+		}
+
+		src_area_len -= mir_seg->area_len;
+		mirr_le += mir_seg->area_len;
+	}
+
+	return 1;
+}
+
 /* 
  * Replace any LV segments on given PV with temporary mirror.
  * Returns list of LVs changed.
@@ -743,6 +780,9 @@ int remove_pvmove_mirrors(struct volume_
 					return 0;
 				}
 
+				if (!_split_source_lv_segment(lv_mirr, seg, s))
+					return_0;
+
 				/* Check the segment params are compatible */
 				/* FIXME Improve error mesg & remove restrcn */
 				if (!seg_is_mirrored(mir_seg) ||

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