[lvm-devel] [PATCH 1/6] Misc: Make get_pv_list_for_lv() available to more than just RAID

Jonathan Brassow jbrassow at redhat.com
Mon Aug 5 20:03:12 UTC 2013


The function 'get_pv_list_for_lv' will assemble all the PVs that are
used by the specified LV.
---
 lib/metadata/lv_manip.c          |   76 ++++++++++++++++++++++++++++++++++++++
 lib/metadata/metadata-exported.h |    2 +
 lib/metadata/raid_manip.c        |   59 ++++++++---------------------
 3 files changed, 95 insertions(+), 42 deletions(-)

diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 24c66ef..d835411 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -162,6 +162,82 @@ int lv_is_on_pvs(struct logical_volume *lv, struct dm_list *pvs)
 }
 
 /*
+ * get_pv_list_for_lv
+ * @mem - mempool to allocate the list from.
+ * @lv
+ * @pvs - The list to add pv_list items to.
+ *
+ * 'pvs' is filled with 'pv_list' items for PVs that compose the LV.
+ * If the 'pvs' list already has items in it, duplicates will not be
+ * added.  So, it is safe to repeatedly call this function for different
+ * LVs and build up a list of PVs for them all.
+ * Currently handles:
+ *  - linear
+ *  - stripe
+ *  - raid
+ * It is up to the caller to free the pv_list when they are finished
+ * with it.
+ *
+ * Returns: 1 on success, 0 on error
+ */
+int get_pv_list_for_lv(struct dm_pool *mem,
+		       struct logical_volume *lv, struct dm_list *pvs)
+{
+	int dup_found;
+	uint32_t s;
+	struct pv_list *pvl;
+	struct lv_segment *seg = first_seg(lv);
+
+	log_debug_metadata("Getting list of PVs that %s/%s is on:",
+			   lv->vg->name, lv->name);
+
+	dm_list_iterate_items(seg, &lv->segments) {
+		for (s = 0; s < seg->area_count; s++) {
+			dup_found = 0;
+
+			if (seg_is_raid(seg) && /* RAID metadata areas */
+			    (seg_type(seg, s) == AREA_LV) &&
+			    !get_pv_list_for_lv(mem, seg_metalv(seg, s), pvs))
+				return_0;
+
+			if (seg_type(seg, s) == AREA_LV) { /* Recurse */
+				if (!get_pv_list_for_lv(mem,
+							seg_lv(seg, s), pvs))
+					return_0;
+				continue;
+			}
+
+			if (seg_type(seg, s) != AREA_PV) {
+				log_error(INTERNAL_ERROR
+					  "Linear seg_type should be AREA_PV");
+				return 0;
+			}
+
+			/* do not add duplicates */
+			dm_list_iterate_items(pvl, pvs)
+				if (pvl->pv == seg_pv(seg, s))
+					dup_found = 1;
+
+			if (dup_found)
+				continue;
+
+			if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
+				log_error("Failed to allocate memory");
+				return 0;
+			}
+
+			pvl->pv = seg_pv(seg, s);
+			log_debug_metadata("  %s/%s is on %s", lv->vg->name,
+					   lv->name, pv_dev_name(pvl->pv));
+
+			dm_list_add(pvs, &pvl->list);
+		}
+	}
+
+	return 1;
+}
+
+/*
  * get_default_region_size
  * @cmd
  *
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 67dc7f7..31c46ad 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -825,6 +825,8 @@ const char *find_vgname_from_pvid(struct cmd_context *cmd,
 
 int lv_is_on_pv(struct logical_volume *lv, struct physical_volume *pv);
 int lv_is_on_pvs(struct logical_volume *lv, struct dm_list *pvs);
+int get_pv_list_for_lv(struct dm_pool *mem,
+		       struct logical_volume *lv, struct dm_list *pvs);
 
 
 /* Find LV segment containing given LE */
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index 05f509a..17514c2 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -93,45 +93,6 @@ static int _activate_sublv_preserving_excl(struct logical_volume *top_lv,
 	return 1;
 }
 
-static int _get_pv_list_for_lv(struct logical_volume *lv, struct dm_list *pvs)
-{
-	uint32_t s;
-	struct pv_list *pvl;
-	struct lv_segment *seg = first_seg(lv);
-
-	if (!seg_is_linear(seg)) {
-		log_error(INTERNAL_ERROR
-			  "_get_pv_list_for_lv only handles linear volumes");
-		return 0;
-	}
-
-	log_debug_metadata("Getting list of PVs that %s/%s is on:",
-			   lv->vg->name, lv->name);
-
-	dm_list_iterate_items(seg, &lv->segments) {
-		for (s = 0; s < seg->area_count; s++) {
-			if (seg_type(seg, s) != AREA_PV) {
-				log_error(INTERNAL_ERROR
-					  "Linear seg_type should be AREA_PV");
-				return 0;
-			}
-
-			if (!(pvl = dm_pool_zalloc(lv->vg->cmd->mem,
-						   sizeof(*pvl)))) {
-				log_error("Failed to allocate memory");
-				return 0;
-			}
-
-			pvl->pv = seg_pv(seg, s);
-			log_debug_metadata("  %s/%s is on %s", lv->vg->name, lv->name,
-					   pv_dev_name(pvl->pv));
-			dm_list_add(pvs, &pvl->list);
-		}
-	}
-
-	return 1;
-}
-
 /*
  * _raid_in_sync
  * @lv
@@ -513,6 +474,7 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
 {
 	struct dm_list allocatable_pvs;
 	struct alloc_handle *ah;
+	struct pv_list *pvl, *tmp_pvl;
 	struct lv_segment *seg = first_seg(data_lv);
 	char *p, base_name[strlen(data_lv->name) + 1];
 
@@ -528,7 +490,8 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
 	if ((p = strstr(base_name, "_mimage_")))
 		*p = '\0';
 
-	if (!_get_pv_list_for_lv(data_lv, &allocatable_pvs)) {
+	if (!get_pv_list_for_lv(data_lv->vg->cmd->mem,
+				data_lv, &allocatable_pvs)) {
 		log_error("Failed to build list of PVs for %s/%s",
 			  data_lv->vg->name, data_lv->name);
 		return 0;
@@ -545,6 +508,11 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
 		return_0;
 
 	alloc_destroy(ah);
+
+	dm_list_iterate_items_safe(pvl, tmp_pvl, &allocatable_pvs) {
+		dm_list_del(&pvl->list);
+		dm_pool_free(data_lv->vg->cmd->mem, pvl);
+	}
 	return 1;
 }
 
@@ -1104,9 +1072,11 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
 	uint32_t old_count = lv_raid_image_count(lv);
 	struct logical_volume *tracking;
 	struct dm_list tracking_pvs;
+	struct pv_list *pvl, *tmp_pvl;
 
 	dm_list_init(&removal_list);
 	dm_list_init(&data_list);
+	dm_list_init(&tracking_pvs);
 
 	if ((old_count - new_count) != 1) {
 		log_error("Unable to split more than one image from %s/%s",
@@ -1145,9 +1115,9 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
 			return 0;
 		} else {
 			/* Ensure we only split the tracking image */
-			dm_list_init(&tracking_pvs);
 			splittable_pvs = &tracking_pvs;
-			if (!_get_pv_list_for_lv(tracking, splittable_pvs))
+			if (!get_pv_list_for_lv(tracking->vg->cmd->mem,
+						tracking, splittable_pvs))
 				return_0;
 		}
 	}
@@ -1159,6 +1129,11 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
 		return 0;
 	}
 
+	dm_list_iterate_items_safe(pvl, tmp_pvl, &tracking_pvs) {
+		dm_list_del(&pvl->list);
+		dm_pool_free(lv->vg->cmd->mem, pvl);
+	}
+
 	/* Convert to linear? */
 	if ((new_count == 1) && !_raid_remove_top_layer(lv, &removal_list)) {
 		log_error("Failed to remove RAID layer after linear conversion");
-- 
1.7.7.6




More information about the lvm-devel mailing list