[lvm-devel] [PATCH] lvconvert: limit lv types for cache use

David Teigland teigland at redhat.com
Tue Sep 2 20:56:00 UTC 2014


Cache data and metadata lvs can be only linear, striped or raid.
Origin lvs must be either linear, striped or raid to be converted
to a cache lv.
---
 lib/metadata/metadata-exported.h |   8 ++
 lib/metadata/snapshot_manip.c    |   5 ++
 tools/lvconvert.c                | 173 ++++++++++++++++++++++++++++++++-------
 3 files changed, 157 insertions(+), 29 deletions(-)

diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 0db43348dca2..7e29bb6e3307 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -180,6 +180,13 @@
 #define lv_is_raid_metadata(lv)	(((lv)->status & (RAID_META)) ? 1 : 0)
 #define lv_is_raid_type(lv)	(((lv)->status & (RAID | RAID_IMAGE | RAID_META)) ? 1 : 0)
 
+/*
+ * Unfortunately, raid1 and raid10 end up being reported as MIRRORED,
+ * so lv_is_mirror_type() is true for them... add this test until that
+ * can be untangled.
+ */
+#define lv_is_really_mirror_type(lv) (lv_is_mirror_type((lv)) && !lv_is_raid((lv)))
+
 #define lv_is_cache(lv)		(((lv)->status & (CACHE)) ? 1 : 0)
 #define lv_is_cache_pool(lv)	(((lv)->status & (CACHE_POOL)) ? 1 : 0)
 #define lv_is_cache_pool_data(lv)	(((lv)->status & (CACHE_POOL_DATA)) ? 1 : 0)
@@ -927,6 +934,7 @@ int lv_is_cow_covering_origin(const struct logical_volume *lv);
 
 /* Test if given LV is visible from user's perspective */
 int lv_is_visible(const struct logical_volume *lv);
+int lv_is_invisible(const struct logical_volume *lv);
 
 int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv);
 
diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c
index 278edc805391..611d919a5b50 100644
--- a/lib/metadata/snapshot_manip.c
+++ b/lib/metadata/snapshot_manip.c
@@ -129,6 +129,11 @@ int lv_is_visible(const struct logical_volume *lv)
 	return lv->status & VISIBLE_LV ? 1 : 0;
 }
 
+int lv_is_invisible(const struct logical_volume *lv)
+{
+	return !lv_is_visible(lv);
+}
+
 int lv_is_virtual_origin(const struct logical_volume *lv)
 {
 	return (lv->status & VIRTUAL_ORIGIN) ? 1 : 0;
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 185cd597aa1b..ba7c4bad29b4 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -15,6 +15,7 @@
 #include "tools.h"
 #include "polldaemon.h"
 #include "lv_alloc.h"
+#include "metadata.h"
 
 struct lvconvert_params {
 	int cache;
@@ -72,6 +73,62 @@ struct lvconvert_params {
 	thin_discards_t discards;
 };
 
+static const char *lv_is_name(struct logical_volume *lv)
+{
+	if (lv_is_external_origin(lv))
+		return "external_origin";
+
+	if (lv_is_thin_type(lv))
+		return "thin_type";
+
+	if (lv_is_external_origin(lv))
+		return "external_origin";
+
+	if (lv_is_really_mirror_type(lv))
+		return "mirror_type";
+
+	if (lv_is_raid_image(lv))
+		return "raid_image";
+
+	if (lv_is_raid_metadata(lv))
+		return "raid_metadata";
+
+	if (lv_is_cache_type(lv))
+		return "cache_type";
+
+	if (lv_is_virtual(lv))
+		return "virtual";
+
+	if (lv_is_pool_metadata_spare(lv))
+		return "metadata_spare";
+
+	if (lv_is_origin(lv))
+		return "origin";
+
+	if (lv_is_virtual_origin(lv))
+		return "virtual_origin";
+
+	if (lv_is_thin_origin(lv, NULL))
+		return "thin_origin";
+
+	if (lv_is_cache_origin(lv))
+		return "cache_origin";
+
+	if (lv_is_cow(lv))
+		return "cow";
+
+	if (lv_is_merging_origin(lv))
+		return "merging_origin";
+
+	if (lv_is_merging_cow(lv))
+		return "merging_cow";
+
+	if (lv_is_invisible(lv))
+		return "invisible";
+
+	return "unknown";
+}
+
 static int _lvconvert_vg_name(struct lvconvert_params *lp,
 			      struct cmd_context *cmd,
 			      const char **lv_name)
@@ -2662,6 +2719,8 @@ static int _lvconvert_update_pool_params(struct logical_volume *pool_lv,
 }
 
 /*
+ * convert a data lv and a metadata lv into a thin|cache pool lv
+ *
  * Thin lvconvert version which
  *  rename metadata
  *  convert/layers thinpool over data
@@ -2687,6 +2746,44 @@ static int _lvconvert_pool(struct cmd_context *cmd,
 		return 0;
 	}
 
+	/*
+	 * For some reason we're calling this function to create a pool lv
+	 * even when pool_lv is already a pool lv.  A pool data lv (the
+	 * usual arg here) cannot be a pool lv, so we need to skip this
+	 * validation when the arg is already a pool lv.
+	 */
+
+	if (lv_is_pool(pool_lv))
+		goto skip_data_lv_validation;
+
+	/*
+	 * pool data lv's and pool metadata lv's can be linear, striped or raid
+	 */
+
+	if (lv_is_external_origin(pool_lv) ||
+	    lv_is_thin_type(pool_lv) ||
+	    lv_is_external_origin(pool_lv) ||
+	    lv_is_really_mirror_type(pool_lv) ||
+	    lv_is_raid_image(pool_lv) ||
+	    lv_is_raid_metadata(pool_lv) ||
+	    lv_is_cache_type(pool_lv) ||
+	    lv_is_virtual(pool_lv) ||
+	    lv_is_pool_metadata_spare(pool_lv) ||
+	    lv_is_origin(pool_lv) ||
+	    lv_is_virtual_origin(pool_lv) ||
+	    lv_is_thin_origin(pool_lv, NULL) ||
+	    lv_is_cache_origin(pool_lv) ||
+	    lv_is_cow(pool_lv) ||
+	    lv_is_merging_origin(pool_lv) ||
+	    lv_is_merging_cow(pool_lv) ||
+	    lv_is_invisible(pool_lv)) {
+		log_error("Pool data LV %s is not supported with LV type %s",
+			  pool_lv->name, lv_is_name(pool_lv));
+		return 0;
+	}
+
+ skip_data_lv_validation:
+
 	if (lp->pool_metadata_lv_name) {
 		if (!(lp->pool_metadata_lv = find_lv(vg, lp->pool_metadata_lv_name))) {
 			log_error("Unknown pool metadata LV %s.", lp->pool_metadata_lv_name);
@@ -2695,17 +2792,28 @@ static int _lvconvert_pool(struct cmd_context *cmd,
 		lp->pool_metadata_size = lp->pool_metadata_lv->size;
 		metadata_lv = lp->pool_metadata_lv;
 
-		if (!lv_is_visible(metadata_lv)) {
-			log_error("Can't convert internal LV %s.",
-				  display_lvname(metadata_lv));
-			return 0;
-		}
-		if (lv_is_mirrored(metadata_lv) && !lv_is_raid_type(metadata_lv)) {
-			log_error("Mirror logical volumes cannot be used "
-				  "for pool metadata.");
-			log_error("Try \"raid1\" segment type instead.");
+		if (lv_is_external_origin(metadata_lv) ||
+		    lv_is_thin_type(metadata_lv) ||
+		    lv_is_external_origin(metadata_lv) ||
+		    lv_is_really_mirror_type(metadata_lv) ||
+		    lv_is_raid_image(metadata_lv) ||
+		    lv_is_raid_metadata(metadata_lv) ||
+		    lv_is_cache_type(metadata_lv) ||
+		    lv_is_virtual(metadata_lv) ||
+		    lv_is_pool_metadata_spare(metadata_lv) ||
+		    lv_is_origin(metadata_lv) ||
+		    lv_is_virtual_origin(metadata_lv) ||
+		    lv_is_thin_origin(metadata_lv, NULL) ||
+		    lv_is_cache_origin(metadata_lv) ||
+		    lv_is_cow(metadata_lv) ||
+		    lv_is_merging_origin(metadata_lv) ||
+		    lv_is_merging_cow(metadata_lv) ||
+		    lv_is_invisible(metadata_lv)) {
+			log_error("Pool metadata LV %s is not supported with LV type %s",
+				  metadata_lv->name, lv_is_name(metadata_lv));
 			return 0;
 		}
+
 		if (metadata_lv->status & LOCKED) {
 			log_error("Can't convert locked LV %s.",
 				  display_lvname(metadata_lv));
@@ -2716,12 +2824,6 @@ static int _lvconvert_pool(struct cmd_context *cmd,
 				  display_lvname(metadata_lv));
 			return 0;
 		}
-		if (lv_is_thin_type(metadata_lv) ||
-		    lv_is_cache_type(metadata_lv)) {
-			log_error("Can't use thin or cache type LV %s for pool metadata.",
-				  display_lvname(metadata_lv));
-			return 0;
-		}
 
 		if (!lv_is_pool(pool_lv)) {
 			if (!_lvconvert_update_pool_params(pool_lv, lp))
@@ -2735,17 +2837,6 @@ static int _lvconvert_pool(struct cmd_context *cmd,
 		}
 	}
 
-	if (!lv_is_visible(pool_lv)) {
-		log_error("Can't convert internal LV %s.", display_lvname(pool_lv));
-		return 0;
-	}
-
-	if (lv_is_mirrored(pool_lv) && !lv_is_raid_type(pool_lv)) {
-		log_error("Mirror logical volumes cannot be used as pools.\n"
-			  "Try \"raid1\" segment type instead.");
-		return 0;
-	}
-
 	if ((dm_snprintf(metadata_name, sizeof(metadata_name), "%s%s",
 			 pool_lv->name,
 			 (segtype_is_cache_pool(lp->segtype)) ?
@@ -3032,6 +3123,10 @@ revert_new_lv:
 #endif
 }
 
+/*
+ * convert an origin lv into a cache lv by attaching a cache pool to the origin
+ */
+
 static int _lvconvert_cache(struct cmd_context *cmd,
 			    struct logical_volume *origin,
 			    struct lvconvert_params *lp)
@@ -3045,9 +3140,29 @@ static int _lvconvert_cache(struct cmd_context *cmd,
 		return 0;
 	}
 
-	if (lv_is_pool(origin) || lv_is_cache_type(origin)) {
-		log_error("Can't cache pool or cache type volume %s.",
-			  display_lvname(origin));
+	/*
+	 * origin can be linear, striped or raid
+	 */
+
+	if (lv_is_external_origin(origin) ||
+	    lv_is_thin_type(origin) ||
+	    lv_is_external_origin(origin) ||
+	    lv_is_really_mirror_type(origin) ||
+	    lv_is_raid_image(origin) ||
+	    lv_is_raid_metadata(origin) ||
+	    lv_is_cache_type(origin) ||
+	    lv_is_virtual(origin) ||
+	    lv_is_pool_metadata_spare(origin) ||
+	    lv_is_origin(origin) ||
+	    lv_is_virtual_origin(origin) ||
+	    lv_is_thin_origin(origin, NULL) ||
+	    lv_is_cache_origin(origin) ||
+	    lv_is_cow(origin) ||
+	    lv_is_merging_origin(origin) ||
+	    lv_is_merging_cow(origin) ||
+	    lv_is_invisible(origin)) {
+		log_error("Cache is not supported with origin LV %s type %s",
+			  origin->name, lv_is_name(origin));
 		return 0;
 	}
 
-- 
1.8.3.1




More information about the lvm-devel mailing list