[lvm-devel] [PATCH 5 of 5] LVM RAID: Add '--splitmirrors' support for RAID1

Jonathan Brassow jbrassow at redhat.com
Wed Aug 3 14:44:40 UTC 2011


Index: LVM2/lib/metadata/raid_manip.c
===================================================================
--- LVM2.orig/lib/metadata/raid_manip.c
+++ LVM2/lib/metadata/raid_manip.c
@@ -37,6 +37,22 @@ uint32_t lv_raid_image_count(const struc
 	return seg->area_count;
 }
 
+static int do_correct_activate(struct logical_volume *orig_lv,
+			       struct logical_volume *new_lv)
+{
+	struct cmd_context *cmd = orig_lv->vg->cmd;
+
+	/* If top RAID was EX, use EX */
+	if (lv_is_active_exclusive_locally(orig_lv)) {
+		if (!activate_lv_excl(cmd, new_lv))
+			return_0;
+	} else {
+		if (!activate_lv(cmd, new_lv))
+			return_0;
+	}
+	return 1;
+}
+
 static int lv_is_on_pvs(struct logical_volume *lv, struct dm_list *pvs)
 {
 	struct pv_list *pvl;
@@ -380,18 +396,9 @@ int lv_raid_change_image_count(struct lo
 	 * Bring extracted LVs into existance, so there are no
 	 * conflicts for the main RAID device's resume
 	 */
-	if (!dm_list_empty(&removal_list)) {
-		dm_list_iterate_items(lvl, &removal_list) {
-			/* If top RAID was EX, use EX */
-			if (lv_is_active_exclusive_locally(lv)) {
-				if (!activate_lv_excl(lv->vg->cmd, lvl->lv))
-					return_0;
-			} else {
-				if (!activate_lv(lv->vg->cmd, lvl->lv))
-					return_0;
-			}
-		}
-	}
+	dm_list_iterate_items(lvl, &removal_list)
+		if (!do_correct_activate(lv, lvl->lv))
+			return_0;
 
 	if (!resume_lv(lv->vg->cmd, lv)) {
 		log_error("Failed to resume %s/%s after committing changes",
@@ -416,3 +423,99 @@ int lv_raid_change_image_count(struct lo
 
 	return 1;
 }
+
+int lv_raid_split(struct logical_volume *lv, const char *split_name,
+		  uint32_t new_count, struct dm_list *splittable_pvs)
+{
+	int r;
+	struct lv_list *lvl;
+	struct dm_list meta_list, data_list;
+	uint32_t old_count = lv_raid_image_count(lv);
+
+	dm_list_init(&meta_list);
+	dm_list_init(&data_list);
+
+	if ((old_count - new_count) != 1) {
+		log_error("Unable to split more than one image from %s/%s",
+			  lv->vg->name, lv->name);
+		return 0;
+	}
+
+	if (!seg_is_mirrored(first_seg(lv))) {
+		log_error("Unable to split logical volume of segment type, %s",
+			  first_seg(lv)->segtype->name);
+		return 0;
+	}
+
+	if (find_lv_in_vg(lv->vg, split_name)) {
+		log_error("Logical Volume \"%s\" already exists in %s",
+			  split_name, lv->vg->name);
+		return 0;
+	}
+
+	if (!raid_in_sync(lv)) {
+		log_error("Unable to split %s/%s while it is not in-sync.",
+			  lv->vg->name, lv->name);
+		return 0;
+	}
+
+	r = raid_extract_images(lv, new_count, splittable_pvs, 1,
+				&meta_list, &data_list);
+	if (!r)
+		return 0;
+
+	/* Get first item */
+	dm_list_iterate_items(lvl, &data_list)
+		break;
+
+	lvl->lv->name = split_name;
+
+	if (!vg_write(lv->vg)) {
+		log_error("Failed to write changes to %s in %s",
+			  lv->name, lv->vg->name);
+		return 0;
+	}
+
+	if (!suspend_lv(lv->vg->cmd, lv)) {
+		log_error("Failed to suspend %s/%s before committing changes",
+			  lv->vg->name, lv->name);
+		return 0;
+	}
+
+	if (!vg_commit(lv->vg)) {
+		log_error("Failed to commit changes to %s in %s",
+			  lv->name, lv->vg->name);
+		return 0;
+	}
+
+	/*
+	 * Bring extracted LVs into existance, so there are no
+	 * conflicts for the main RAID device's resume
+	 */
+	dm_list_iterate_items(lvl, &meta_list)
+		if (!do_correct_activate(lv, lvl->lv))
+			return 0;
+	dm_list_iterate_items(lvl, &data_list)
+		if (!do_correct_activate(lv, lvl->lv))
+			return 0;
+
+	/* Resume original LV */
+	if (!resume_lv(lv->vg->cmd, lv)) {
+		log_error("Failed to resume %s/%s after committing changes",
+			  lv->vg->name, lv->name);
+		return 0;
+	}
+
+	/* Remove the meta LVs */
+	dm_list_iterate_items(lvl, &meta_list) {
+		if (!deactivate_lv(lv->vg->cmd, lvl->lv))
+			return_0;
+		if (!lv_remove(lvl->lv))
+			return_0;
+	}
+
+	if (!vg_write(lv->vg) || !vg_commit(lv->vg))
+		return_0;
+
+	return 1;
+}
Index: LVM2/tools/lvconvert.c
===================================================================
--- LVM2.orig/tools/lvconvert.c
+++ LVM2/tools/lvconvert.c
@@ -1401,7 +1401,7 @@ static int lvconvert_raid(struct logical
 	}
 
 	/* Change number of RAID1 images */
-	if (arg_count(cmd, mirrors_ARG)) {
+	if (arg_count(cmd, mirrors_ARG) || arg_count(cmd, splitmirrors_ARG)) {
 		image_count = lv_raid_image_count(lv);
 		if (lp->mirrors_sign == SIGN_PLUS)
 			image_count += lp->mirrors;
@@ -1411,11 +1411,18 @@ static int lvconvert_raid(struct logical
 			image_count = lp->mirrors + 1;
 
 		if (image_count < 1) {
-			log_error("Unable to reduce images by specified amount");
+			log_error("Unable to %s images by specified amount",
+				  arg_count(cmd, splitmirrors_ARG) ?
+				  "split" : "reduce");
 			return 0;
 		}
 
-		return lv_raid_change_image_count(lv, image_count, lp->pvh);
+		if (arg_count(cmd, splitmirrors_ARG))
+			return lv_raid_split(lv, lp->lv_split_name,
+					     image_count, lp->pvh);
+		else
+			return lv_raid_change_image_count(lv, image_count,
+							  lp->pvh);
 	}
 
 	log_error("Conversion operation not yet supported.");
Index: LVM2/lib/metadata/metadata-exported.h
===================================================================
--- LVM2.orig/lib/metadata/metadata-exported.h
+++ LVM2/lib/metadata/metadata-exported.h
@@ -748,6 +748,9 @@ struct logical_volume *first_replicator_
 uint32_t lv_raid_image_count(const struct logical_volume *lv);
 int lv_raid_change_image_count(struct logical_volume *lv,
 			       uint32_t new_count, struct dm_list *pvs);
+int lv_raid_split(struct logical_volume *lv, const char *split_name,
+		  uint32_t new_count, struct dm_list *splittable_pvs);
+
 /* --  metadata/raid_manip.c */
 
 struct cmd_vg *cmd_vg_add(struct dm_pool *mem, struct dm_list *cmd_vgs,






More information about the lvm-devel mailing list