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

[lvm-devel] [PATCH lvconvert 1/6] Add insert_layer_for_lv() / remove_layer_from_lv()



Add insert_layer_for_lv() / remove_layer_from_lv().

insert_layer_for_lv() simply creates an layer LV with specified suffix,
move all segments of the LV to the layer LV ,then maps linearly
from the LV to the layer LV.

remove_layer_from_lv() removes the top-level layer from the LV.
This might be too simple.

Thanks,
-- 
Jun'ichi Nomura, NEC Corporation of America
Add insert_layer_for_lv() / remove_layer_from_lv()

Index: LVM2.work/lib/metadata/lv_manip.c
===================================================================
--- LVM2.work.orig/lib/metadata/lv_manip.c
+++ LVM2.work/lib/metadata/lv_manip.c
@@ -2185,6 +2185,117 @@ int remove_layers_for_segments_all(struc
 	return 1;
 }
 
+static void _move_lv_segments(struct logical_volume *lv_to,
+			      struct logical_volume *lv_from,
+			      uint32_t set_status, uint32_t reset_status)
+{
+	struct lv_segment *seg;
+
+	lv_to->segments = lv_from->segments;
+	lv_to->segments.n->p = &lv_to->segments;
+	lv_to->segments.p->n = &lv_to->segments;
+
+	list_iterate_items(seg, &lv_to->segments) {
+		seg->lv = lv_to;
+		seg->status &= ~reset_status;
+		seg->status |= set_status;
+	}
+
+	/* FIXME: how to handle snapshot segments? */
+
+	list_init(&lv_from->segments);
+
+	lv_to->le_count = lv_from->le_count;
+	lv_to->size = lv_from->size;
+
+	lv_from->le_count = 0;
+	lv_from->size = 0;
+}
+
+/* Remove a layer from the LV */
+/* FIXME: how to specify what should be removed if multiple layers stacked? */
+int remove_layer_from_lv(struct logical_volume *lv)
+{
+	struct logical_volume *orig_lv;
+
+	/*
+	 * Before removal, the layer should be cleaned up,
+	 * i.e. additional segments and areas should have been removed.
+	 */
+	if (list_size(&lv->segments) != 1 ||
+	    first_seg(lv)->area_count != 1 ||
+	    seg_type(first_seg(lv), 0) != AREA_LV)
+		return 0;
+
+	orig_lv = seg_lv(first_seg(lv), 0);
+	_move_lv_segments(lv, orig_lv, 0, 0);
+
+	return 1;
+}
+
+/*
+ * Create and insert a linear LV "above" lv_where.
+ * After the insertion, a new LV named lv_where->name + suffix is created
+ * and all segments of lv_where is moved to the new LV.
+ * lv_where will have a single segment which maps linearly to the new LV.
+ */
+struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
+					   struct logical_volume *lv_where,
+					   uint32_t status,
+					   const char *layer_suffix)
+{
+	struct logical_volume *layer_lv;
+	char *name;
+	size_t len;
+	struct segment_type *segtype;
+	struct lv_segment *mapseg;
+
+	if (!(segtype = get_segtype_from_string(lv_where->vg->cmd, "striped")))
+		return_NULL;
+
+	/* create an empty layer LV */
+
+	len = strlen(lv_where->name) + 32;
+	if (!(name = alloca(len))) {
+		log_error("layer name allocation failed. "
+			  "Remove new LV and retry.");
+		return NULL;
+	}
+
+	if (dm_snprintf(name, len, "%s%s", lv_where->name, layer_suffix) < 0) {
+		log_error("layer name allocation failed. "
+			  "Remove new LV and retry.");
+		return NULL;
+	}
+
+	if (!(layer_lv = lv_create_empty(name, NULL, LVM_READ | LVM_WRITE,
+					 ALLOC_INHERIT, 0, lv_where->vg))) {
+		log_error("Creation of layer LV failed");
+		return NULL;
+	}
+
+	log_very_verbose("Inserting layer %s for %s",
+			 layer_lv->name, lv_where->name);
+
+	_move_lv_segments(layer_lv, lv_where, 0, 0);
+
+	/* 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,
+					0, 0, 0)))
+		return_NULL;
+
+	/* map the new segment to the original underlying are */
+	set_lv_segment_area_lv(mapseg, 0, layer_lv, 0, 0);
+
+	/* add the new segment to the layer LV */
+	list_add(&lv_where->segments, &mapseg->list);
+	lv_where->le_count = layer_lv->le_count;
+	lv_where->size = lv_where->le_count * lv_where->vg->extent_size;
+
+	return layer_lv;
+}
 
 /*
  * Extend and insert a linear layer LV beneath the source segment area.
Index: LVM2.work/lib/metadata/metadata-exported.h
===================================================================
--- LVM2.work.orig/lib/metadata/metadata-exported.h
+++ LVM2.work/lib/metadata/metadata-exported.h
@@ -398,6 +398,11 @@ int remove_layers_for_segments_all(struc
 				   struct list *lvs_changed);
 int split_parent_segments_for_layer(struct cmd_context *cmd,
 				    struct logical_volume *layer_lv);
+int remove_layer_from_lv(struct logical_volume *lv);
+struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
+					   struct logical_volume *lv_where,
+					   uint32_t status,
+					   const char *layer_suffix);
 
 /* Find a PV within a given VG */
 struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name);
Index: LVM2.work/lib/metadata/mirror.c
===================================================================
--- LVM2.work.orig/lib/metadata/mirror.c
+++ LVM2.work/lib/metadata/mirror.c
@@ -196,7 +196,7 @@ int remove_mirror_images(struct lv_segme
 	if (num_mirrors == 1) {
 		lv1 = seg_lv(mirrored_seg, 0);
 		extents = lv1->le_count;
-		_move_lv_segments(mirrored_seg->lv, lv1);
+		remove_layer_from_lv(mirrored_seg->lv);
 		mirrored_seg->lv->status &= ~MIRRORED;
 		mirrored_seg->lv->status &= ~MIRROR_NOTSYNCED;
 		remove_log = 1;

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