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

[lvm-devel] [PATCH lvconvert Appendix] Experimental: pvmove with disk log and seg-by-seg mirrored LV



This patch is experimental and just a proof-of-concept of new APIs.
(Some changes in lib were needed for adding pvmove support.)

Examples of commands and 'dmsetup ls --tree':
("/dev/mapper/d*" are PVs)

  Normal pvmove:
  # pvmove /dev/mapper/d1 /dev/mapper/d3 
    testvg-lvol2 (254:11)
     |-d2 (254:2)
     `-testvg-pvmove0 (254:13)
        |-d3 (254:3)
        `-d1 (254:1)
    testvg-lvol1 (254:10)
     `-testvg-pvmove0 (254:13)
        |-d3 (254:3)
        `-d1 (254:1)

  Disklog pvmove:
  # pvmove --mirrorlog disk /dev/mapper/d1 /dev/mapper/d3 /dev/mapper/d5:0-0
    testvg-lvol2 (254:11)
     |-d2 (254:2)
     `-testvg-pvmove0 (254:16)
        |-testvg-pvmove0_mimage_1 (254:15)
        |  `-d3 (254:3)
        |-testvg-pvmove0_mimage_0 (254:14)
        |  `-d1 (254:1)
        `-testvg-pvmove0_mlog (254:13)
           `-d5 (254:5)
    testvg-lvol1 (254:10)
     `-testvg-pvmove0 (254:16)
        |-testvg-pvmove0_mimage_1 (254:15)
        |  `-d3 (254:3)
        |-testvg-pvmove0_mimage_0 (254:14)
        |  `-d1 (254:1)
        `-testvg-pvmove0_mlog (254:13)
           `-d5 (254:5)

  Normal corelog mirror LV:
  # lvcreate -m1 -l1 --mirrorlog core testvg
    testvg-lvol0 (254:11)
     |-testvg-lvol0_mimage_1 (254:10)
     |  `-d2 (254:2)
     `-testvg-lvol0_mimage_0 (254:9)
        `-d1 (254:1)

  Seg-by-seg corelog mirror LV:
  # lvcreate -m1 -l1 --mirrorlog seg testvg
    testvg-lvol0 (254:9)
     |-d2 (254:2)
     `-d1 (254:1)

Thanks,
-- 
Jun'ichi Nomura, NEC Corporation of America
Experimental patch:
  - Add '--mirrorlog disk' option to pvmove to use persistent log.
    FIXME: PV specification for log device is not intuitive.
  - Add '--mirrorlog seg' option to lvcreate/lvconvert.
    (Segment-by-segment mirror LV. Just for experiment)

Index: LVM2.work/tools/commands.h
===================================================================
--- LVM2.work.orig/tools/commands.h
+++ LVM2.work/tools/commands.h
@@ -508,6 +508,7 @@ xx(pvmove,
    "\t[-d|--debug]\n "
    "\t[-h|-?|--help]\n"
    "\t[-i|--interval seconds]\n"
+   "\t[--mirrorlog {disk|core}]\n "
    "\t[-t|--test]\n "
    "\t[-v|--verbose]\n "
    "\t[--version]\n"
@@ -517,7 +518,7 @@ xx(pvmove,
    "\t[DestinationPhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]...]\n",
 
    abort_ARG, alloc_ARG, autobackup_ARG, background_ARG,
-   interval_ARG, name_ARG, test_ARG)
+   interval_ARG, mirrorlog_ARG, name_ARG, test_ARG)
 
 xx(pvremove,
    "Remove LVM label(s) from physical volume(s)",
Index: LVM2.work/tools/pvmove.c
===================================================================
--- LVM2.work.orig/tools/pvmove.c
+++ LVM2.work/tools/pvmove.c
@@ -147,11 +147,11 @@ static struct logical_volume *_set_up_pv
 						const char *lv_name,
 						struct list *allocatable_pvs,
 						alloc_policy_t alloc,
+						uint32_t log_count,
 						struct list **lvs_changed)
 {
 	struct logical_volume *lv_mirr, *lv;
 	struct lv_list *lvl;
-	uint32_t log_count = 0;
 
 	/* FIXME Cope with non-contiguous => splitting existing segments */
 	if (!(lv_mirr = lv_create_empty("pvmove%d", NULL,
@@ -209,8 +209,9 @@ static struct logical_volume *_set_up_pv
 		return NULL;
 	}
 
-	if (!lv_add_mirrors(cmd, lv_mirr, 1, 1, 0, log_count,
-			    allocatable_pvs, alloc, MIRROR_BY_SEG)) {
+	if (!lv_add_mirrors(cmd, lv_mirr, 1, 1, DEFAULT_MIRROR_REGION_SIZE, log_count,
+			    allocatable_pvs, alloc,
+			    log_count ? MIRROR_BY_LV : MIRROR_BY_SEG)) {
 		log_error("Failed to convert pvmove LV to mirrored");
 		return_NULL;
 	}
@@ -292,7 +293,7 @@ static int _update_metadata(struct cmd_c
 static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
 			  int argc, char **argv)
 {
-	const char *lv_name = NULL;
+	const char *lv_name = NULL, *mirrorlog;
 	char *pv_name_arg;
 	struct volume_group *vg;
 	struct list *source_pvl;
@@ -302,6 +303,7 @@ static int _set_up_pvmove(struct cmd_con
 	struct physical_volume *pv;
 	struct logical_volume *lv_mirr;
 	int first_time = 1;
+	uint32_t log_count;
 
 	pv_name_arg = argv[0];
 	argc--;
@@ -351,6 +353,17 @@ static int _set_up_pvmove(struct cmd_con
 
 		first_time = 0;
 	} else {
+		mirrorlog = arg_str_value(cmd, mirrorlog_ARG, "core");
+		if (!strcmp("disk", mirrorlog))
+			log_count = 1;
+		else if (!strcmp("core", mirrorlog))
+			log_count = 0;
+		else {
+			log_error("Unknown mirrorlog type: %s", mirrorlog);
+			return 0;
+		}
+		log_verbose("Setting logging type to %s", mirrorlog);
+
 		/* Determine PE ranges to be moved */
 		if (!(source_pvl = create_pv_list(cmd->mem, vg, 1,
 						  &pv_name_arg, 0))) {
@@ -379,7 +392,7 @@ static int _set_up_pvmove(struct cmd_con
 
 		if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, source_pvl, lv_name,
 						  allocatable_pvs, alloc,
-						  &lvs_changed))) {
+						  log_count, &lvs_changed))) {
 			stack;
 			unlock_vg(cmd, pv_vg_name(pv));
 			return ECMD_FAILED;
@@ -422,7 +435,7 @@ static int _finish_pvmove(struct cmd_con
 
 	/* Update metadata to remove mirror segments and break dependencies */
 	list_init(&lvs_completed);
-	if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, NULL, PVMOVE) ||
+	if (!lv_remove_mirrors(cmd, lv_mirr, 1, first_seg(lv_mirr)->log_lv ? 1 : 0, NULL, PVMOVE) ||
 	    !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE,
 					    &lvs_completed)) {
 		log_error("ABORTING: Removal of temporary mirror failed");
Index: LVM2.work/lib/metadata/mirror.c
===================================================================
--- LVM2.work.orig/lib/metadata/mirror.c
+++ LVM2.work/lib/metadata/mirror.c
@@ -169,6 +169,12 @@ int remove_mirror_images(struct lv_segme
 			log_error("No mirror images found using specified PVs.");
 			return 0;
 		}
+	} else if (mirrored_seg->extents_copied == mirrored_seg->area_len) {
+		/* Move source image to the end of the array */
+		new_area_count--;
+		area = mirrored_seg->areas[new_area_count];
+		mirrored_seg->areas[new_area_count] = mirrored_seg->areas[0];
+		mirrored_seg->areas[0] = area;
 	}
 
 	for (m = num_mirrors; m < mirrored_seg->area_count; m++) {
@@ -403,7 +409,8 @@ int reconfigure_mirror_images(struct lv_
 static int _create_mimage_lvs(struct alloc_handle *ah,
 			      uint32_t num_mirrors,
 			      struct logical_volume *lv,
-			      struct logical_volume **img_lvs)
+			      struct logical_volume **img_lvs,
+			      uint32_t status)
 {
 	uint32_t m;
 	char *img_name;
@@ -424,7 +431,7 @@ static int _create_mimage_lvs(struct all
 
 	for (m = 0; m < num_mirrors; m++) {
 		if (!(img_lvs[m] = lv_create_empty(img_name,
-					     NULL, LVM_READ | LVM_WRITE,
+					     NULL, LVM_READ | LVM_WRITE | status,
 					     ALLOC_INHERIT, 0, lv->vg))) {
 			log_error("Aborting. Failed to create mirror image LV. "
 				  "Remove new LV and retry.");
@@ -523,13 +530,32 @@ const char *get_pvmove_pvname_from_lv(st
 	return NULL;
 }
 
+static int _find_pvmove_lv(struct logical_volume *lv, struct device *dev)
+{
+	struct lv_segment *seg;
+
+	/* Check segment origins point to pvname */
+	list_iterate_items(seg, &lv->segments) {
+		if (seg_type(seg, 0) == AREA_LV) {
+			if (_find_pvmove_lv(seg_lv(seg, 0), dev))
+				return 1;
+			else
+				continue;
+		}
+		if (seg_dev(seg, 0) != dev)
+			continue;
+		return 1;
+	}
+
+	return 0;
+}
+
 struct logical_volume *find_pvmove_lv(struct volume_group *vg,
 				      struct device *dev,
 				      uint32_t lv_type)
 {
 	struct lv_list *lvl;
 	struct logical_volume *lv;
-	struct lv_segment *seg;
 
 	/* Loop through all LVs */
 	list_iterate_items(lvl, &vg->lvs) {
@@ -538,14 +564,8 @@ struct logical_volume *find_pvmove_lv(st
 		if (!(lv->status & lv_type))
 			continue;
 
-		/* Check segment origins point to pvname */
-		list_iterate_items(seg, &lv->segments) {
-			if (seg_type(seg, 0) != AREA_PV)
-				continue;
-			if (seg_dev(seg, 0) != dev)
-				continue;
+		if (_find_pvmove_lv(lv, dev))
 			return lv;
-		}
 	}
 
 	return NULL;
@@ -1103,7 +1123,7 @@ int add_mirror_images(struct cmd_context
 		goto out_remove_log;
 	}
 
-	if (!_create_mimage_lvs(ah, mirrors, lv, img_lvs))
+	if (!_create_mimage_lvs(ah, mirrors, lv, img_lvs, lv->status & LOCKED))
 		goto out_remove_log;
 
 	if (!lv_add_mirror_lvs(lv, img_lvs, mirrors,
Index: LVM2.work/lib/metadata/lv_manip.c
===================================================================
--- LVM2.work.orig/lib/metadata/lv_manip.c
+++ LVM2.work/lib/metadata/lv_manip.c
@@ -2196,7 +2196,7 @@ int remove_layer_from_lv(struct logical_
 		return 0;
 
 	orig_lv = seg_lv(first_seg(lv), 0);
-	_move_lv_segments(lv, orig_lv, 0, 0);
+	_move_lv_segments(lv, orig_lv, lv->status & PVMOVE, 0);
 
 	return 1;
 }
@@ -2245,12 +2245,12 @@ struct logical_volume *insert_layer_for_
 	log_very_verbose("Inserting layer %s for %s",
 			 layer_lv->name, lv_where->name);
 
-	_move_lv_segments(layer_lv, lv_where, 0, 0);
+	_move_lv_segments(layer_lv, lv_where, 0, lv_where->status & PVMOVE);
 
 	/* allocate a new linear segment */
 	if (!(mapseg = alloc_lv_segment(lv_where->vg->cmd->mem, segtype,
 					lv_where, 0, layer_lv->le_count,
-					status, 0, NULL, 1, layer_lv->le_count,
+					status | (lv_where->status & PVMOVE), 0, NULL, 1, layer_lv->le_count,
 					0, 0, 0)))
 		return_NULL;
 
Index: LVM2.work/lib/report/report.c
===================================================================
--- LVM2.work.orig/lib/report/report.c
+++ LVM2.work/lib/report/report.c
@@ -493,7 +493,10 @@ static int _movepv_disp(struct dm_report
 	list_iterate_items(seg, &lv->segments) {
 		if (!(seg->status & PVMOVE))
 			continue;
-		name = dev_name(seg_dev(seg, 0));
+		if (seg_type(seg, 0) == AREA_LV)
+			name = seg_lv(seg, 0)->name;
+		else
+			name = dev_name(seg_dev(seg, 0));
 		return dm_report_field_string(rh, field, &name);
 	}
 
Index: LVM2.work/tools/lvconvert.c
===================================================================
--- LVM2.work.orig/tools/lvconvert.c
+++ LVM2.work/tools/lvconvert.c
@@ -281,6 +281,8 @@ static int lvconvert_mirrors(struct cmd_
 		corelog = 0;
 	} else if (!strcmp("core", mirrorlog))
 		corelog = 1;
+	else if (!strcmp("seg", mirrorlog))
+		corelog = 2;
 	else {
 		log_error("Unknown mirrorlog type: %s", mirrorlog);
 		return 0;
@@ -308,7 +310,7 @@ static int lvconvert_mirrors(struct cmd_
 			return 1;
 		}
 
-		if (!lv_remove_mirrors(cmd, lv, existing_mirrors - 1, 1,
+		if (!lv_remove_mirrors(cmd, lv, existing_mirrors - 1, first_seg(lv)->log_lv ? 1 : 0,
 				       lp->pv_count ? lp->pvh : NULL, 0))
 			return_0;
 		goto commit_changes;
@@ -334,7 +336,7 @@ static int lvconvert_mirrors(struct cmd_
 						lv->le_count,
 						lp->region_size),
 				    corelog ? 0U : 1U, lp->pvh, lp->alloc,
-				    MIRROR_BY_LV))
+				    corelog == 2 ? MIRROR_BY_SEG : MIRROR_BY_LV))
 			return_0;
 		goto commit_changes;
 	}
Index: LVM2.work/tools/lvcreate.c
===================================================================
--- LVM2.work.orig/tools/lvcreate.c
+++ LVM2.work/tools/lvcreate.c
@@ -296,6 +296,8 @@ static int _read_mirror_params(struct lv
 		lp->corelog = 0;
 	} else if (!strcmp("core", mirrorlog))
 		lp->corelog = 1;
+	else if (!strcmp("seg", mirrorlog))
+		lp->corelog = 2;
 	else {
 		log_error("Unknown mirrorlog type: %s", mirrorlog);
 		return 0;
@@ -792,7 +794,7 @@ static int _lvcreate(struct cmd_context 
 						lv->le_count,
 						lp->region_size),
 				    lp->corelog ? 0U : 1U, pvh, lp->alloc,
-				    MIRROR_BY_LV)) {
+				    lp->corelog == 2 ? MIRROR_BY_SEG : MIRROR_BY_LV)) {
 			stack;
 			goto revert_new_lv;
 		}

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