summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2016-06-28 12:24:41 -0500
committerDavid Teigland <teigland@redhat.com>2016-06-29 11:36:29 -0500
commit59138eb69d98cc042d6945f9b0c7f6986e40ac8e (patch)
treeff665b09210b3fd28a05b8f8e274845d28f9844c
parentf8e17d9af660fbfec9baadc4b05652e3dcc2a345 (diff)
downloadlvm2-dev-dct-lvconvert-cleanup-3.tar.gz
lvconvert: rework routing of operationsdev-dct-lvconvert-cleanup-3
Add new logic to identify each unique operation and route it to the correct function to perform it. The functions that perform the conversions remain unchanged. This new code checks every allowed combination of LV type and requested operation, and for each valid combination calls the function that performs that conversion. The first stage of option validation which checks for disallowed combinations of command line options, is done done before process_each is called. This is unchanged. (This new code would allow that first stage validation to be simplified in a future commit.) The second stage of checking options against the specific LV type is done by this new code. For each valid combination of operation + LV type, the new code calls an existing function that implements it. With this in place, the ad hoc checks for valid combinations of LV types and operations can be removed from the existing code in a future commit.
-rw-r--r--tools/lvconvert.c705
1 files changed, 705 insertions, 0 deletions
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index f99291aad..b7a086a23 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -2020,6 +2020,7 @@ static int _lvconvert_split_cached(struct cmd_context *cmd,
return 1;
}
+#if 0
static int _lvconvert_splitcache(struct cmd_context *cmd,
struct logical_volume *lv,
struct lvconvert_params *lp)
@@ -2047,7 +2048,9 @@ static int _lvconvert_splitcache(struct cmd_context *cmd,
return 1;
}
+#endif
+#if 0
static int _lvconvert_split(struct cmd_context *cmd,
struct logical_volume *lv,
struct lvconvert_params *lp)
@@ -2077,6 +2080,7 @@ static int _lvconvert_split(struct cmd_context *cmd,
return 1;
}
+#endif
static int _lvconvert_uncache(struct cmd_context *cmd,
struct logical_volume *lv,
@@ -3334,6 +3338,7 @@ static int _lvconvert_cache(struct cmd_context *cmd,
return 1;
}
+#if 0
static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3490,6 +3495,706 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_PROCESSED;
}
+#endif
+
+/*
+ * Functions called to perform a specific operation on a specific LV type.
+ *
+ * _convert_<lvtype>_<operation>
+ *
+ * For cases where an operation does not apply to the LV itself, but
+ * is implicitly redirected to a sub-LV, these functions locate the
+ * correct sub-LV and call the operation on that sub-LV. If a sub-LV
+ * of the proper type is not found, these functions report the error.
+ *
+ * FIXME: the _lvconvert_foo() functions can be cleaned up since they
+ * are now only called for valid combinations of LV type and operation.
+ * After that happens, the code remaining in those functions can be
+ * moved into the _convert_lvtype_operation() functions below.
+ */
+
+static int _convert_cow_snapshot_splitsnapshot(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_splitsnapshot(cmd, lv, lp);
+}
+
+static int _convert_cow_snapshot_merge(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_merge_old_snapshot(cmd, lv, lp);
+}
+
+static int _convert_thin_volume_merge(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_merge_thin_snapshot(cmd, lv, lp);
+}
+
+static int _convert_thin_pool_splitcache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct logical_volume *sublv1;
+
+ sublv1 = seg_lv(first_seg(lv), 0); /* cached _tdata ? */
+
+ if (!lv_is_cache(sublv1)) {
+ log_error("Sub LV %s must be cache.", display_lvname(sublv1));
+ return ECMD_FAILED;
+ }
+
+ return _lvconvert_split_cached(cmd, sublv1);
+}
+
+static int _convert_thin_pool_uncache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct logical_volume *sublv1 = NULL;
+
+ sublv1 = seg_lv(first_seg(lv), 0); /* cached _tdata ? */
+
+ if (!lv_is_cache(sublv1)) {
+ log_error("Sub LV %s must be cache.", display_lvname(sublv1));
+ return ECMD_FAILED;
+ }
+
+ return _lvconvert_uncache(cmd, sublv1, lp);
+}
+
+static int _convert_thin_pool_repair(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_thin_pool_repair(cmd, lv, lp);
+}
+
+static int _convert_thin_pool_cache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* lvconvert --cache includes an implicit conversion of the cachepool arg to type cache-pool. */
+ if (!_lvconvert_pool(cmd, lv, lp)) {
+ log_error("Implicit conversion of --cachepool arg to type cache-pool failed.");
+ return ECMD_FAILED;
+ }
+
+ /* Do we need to grab the tdata sub LV to pass on? */
+
+ return _lvconvert_cache(cmd, lv, lp);
+}
+
+static int _convert_cache_volume_splitcache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_split_cached(cmd, lv);
+}
+
+static int _convert_cache_volume_uncache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_uncache(cmd, lv, lp);
+}
+
+static int _convert_cache_volume_splitmirrors(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct logical_volume *sublv1;
+
+ sublv1 = seg_lv(first_seg(lv), 0);
+
+ if (lv_is_raid(sublv1))
+ return _lvconvert_raid(sublv1, lp);
+
+ if (lv_is_mirror(sublv1))
+ return _lvconvert_mirrors(cmd, lv, lp);
+
+ log_error("Sub LV %s must be raid or mirror.", display_lvname(sublv1));
+ return ECMD_FAILED;
+}
+
+static int _convert_cache_volume_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_cache_pool_splitcache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct logical_volume *sublv1;
+ struct lv_segment *seg;
+
+ /* When passed used cache-pool of used cached LV -> split cached LV */
+
+ if ((dm_list_size(&lv->segs_using_this_lv) == 1) &&
+ (seg = get_only_segment_using_this_lv(lv)) &&
+ seg_is_cache(seg))
+ sublv1 = seg->lv;
+ else {
+ log_error("Sub LV of cache type not found.");
+ return ECMD_FAILED;
+ }
+
+ if (!lv_is_cache(sublv1)) {
+ log_error("Sub LV %s must be cache.", display_lvname(sublv1));
+ return ECMD_FAILED;
+ }
+
+ return _lvconvert_split_cached(cmd, sublv1);
+}
+
+static int _convert_mirror_number(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+static int _convert_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+static int _convert_mirror_repair(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct dm_list *failed_pvs;
+ int ret;
+
+ ret = _lvconvert_mirrors_repair(cmd, lv, lp);
+
+ if (ret && arg_is_set(cmd, usepolicies_ARG)) {
+ if ((failed_pvs = _failed_pv_list(lv->vg)))
+ _remove_missing_empty_pv(lv->vg, failed_pvs);
+ }
+
+ return ret;
+}
+
+static int _convert_raid_number(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_splitmirrors(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* FIXME: split the splitmirrors section out of _lvconvert_raid and call it here. */
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_merge(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* FIXME: split the merge section out of _lvconvert_raid and call it here. */
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_repair(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct dm_list *failed_pvs;
+ int ret;
+
+ /* FIXME: split the repair section out of _lvconvert_raid and call it here. */
+ ret = _lvconvert_raid(lv, lp);
+
+ if (ret && arg_is_set(cmd, usepolicies_ARG)) {
+ if ((failed_pvs = _failed_pv_list(lv->vg)))
+ _remove_missing_empty_pv(lv->vg, failed_pvs);
+ }
+
+ return ret;
+}
+
+static int _convert_raid_replace(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* FIXME: remove the replace section from _lvconvert_raid */
+ return lv_raid_replace(lv, lp->replace_pvh, lp->pvh);
+}
+
+static int _convert_raid_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_snapshot(cmd, lv, lp);
+}
+
+static int _convert_raid_thin(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* lvconvert --thin includes an implicit conversion of the thinpool arg to type thin-pool. */
+ if (!_lvconvert_pool(cmd, lv, lp)) {
+ log_error("Implicit conversion of --thinpool arg to type thin-pool failed.");
+ return ECMD_FAILED;
+ }
+
+ return _lvconvert_thin(cmd, lv, lp);
+}
+
+static int _convert_raid_cache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* lvconvert --cache includes an implicit conversion of the cachepool arg to type cache-pool. */
+ if (!_lvconvert_pool(cmd, lv, lp)) {
+ log_error("Implicit conversion of --cachepool arg to type cache-pool failed.");
+ return ECMD_FAILED;
+ }
+
+ return _lvconvert_cache(cmd, lv, lp);
+}
+
+static int _convert_raid_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_raid_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_raid_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_striped(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_linear(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_striped_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_snapshot(cmd, lv, lp);
+}
+
+static int _convert_striped_thin(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* lvconvert --thin includes an implicit conversion of the thinpool arg to type thin-pool. */
+ if (!_lvconvert_pool(cmd, lv, lp)) {
+ log_error("Implicit conversion of --thinpool arg to type thin-pool failed.");
+ return ECMD_FAILED;
+ }
+
+ return _lvconvert_thin(cmd, lv, lp);
+}
+
+static int _convert_striped_cache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* lvconvert --cache includes an implicit conversion of the cachepool arg to type cache-pool. */
+ if (!_lvconvert_pool(cmd, lv, lp)) {
+ log_error("Implicit conversion of --cachepool arg to type cache-pool failed.");
+ return ECMD_FAILED;
+ }
+
+ return _lvconvert_cache(cmd, lv, lp);
+}
+
+static int _convert_striped_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_striped_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_striped_mirror(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+static int _convert_striped_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+/*
+ * Functions called to perform all valid operations on a given LV type.
+ *
+ * _convert_<lvtype>
+ */
+
+static int _convert_cow_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ if (lp->splitsnapshot)
+ return _convert_cow_snapshot_splitsnapshot(cmd, lv, lp);
+
+ if (lp->merge)
+ return _convert_cow_snapshot_merge(cmd, lv, lp);
+
+ log_error("Operation not permitted on COW snapshot LV %s", display_lvname(lv));
+ log_error("Operations permitted on a COW snapshot LV are:\n"
+ " --splitsnapshot\n"
+ " --merge\n");
+ return ECMD_FAILED;
+}
+
+static int _convert_thin_volume(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ if (lp->merge)
+ return _convert_thin_volume_merge(cmd, lv, lp);
+
+ log_error("Operation not permitted on thin LV %s", display_lvname(lv));
+ log_error("Operations permitted on a thin LV are:\n"
+ " --merge\n");
+ return ECMD_FAILED;
+}
+
+static int _convert_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ if (lp->splitcache || lp->split)
+ return _convert_thin_pool_splitcache(cmd, lv, lp);
+
+ if (lp->uncache)
+ return _convert_thin_pool_uncache(cmd, lv, lp);
+
+ if (lp->cache)
+ return _convert_thin_pool_cache(cmd, lv, lp);
+
+ if (lp->repair)
+ return _convert_thin_pool_repair(cmd, lv, lp);
+
+ /* FIXME: swapping the thin pool metadata LV needs a specific option. */
+ /*
+ if (lp->swapmetadata)
+ return _convert_thin_pool_swapmetadata(cmd, lv, lp);
+ */
+
+ log_error("Operation not permitted on thin pool LV %s", display_lvname(lv));
+ log_error("Operations permitted on a thin pool LV are:\n"
+ " --splitcache (operates on cache sub LV)\n"
+ " --uncache (operates on cache sub LV)\n"
+ " --cache (operates on data sub LV)\n"
+ " --repair\n");
+ return ECMD_FAILED;
+}
+
+static int _convert_cache_volume(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ const char *new_type = arg_str_value(cmd, type_ARG, NULL);
+
+ if (lp->splitcache || lp->split)
+ return _convert_cache_volume_splitcache(cmd, lv, lp);
+
+ if (lp->uncache)
+ return _convert_cache_volume_uncache(cmd, lv, lp);
+
+ /* FIXME: add lp->splitmirrors to reflect the arg. */
+ if (arg_is_set(cmd, splitmirrors_ARG))
+ return _convert_cache_volume_splitmirrors(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "thin-pool"))
+ return _convert_cache_volume_thin_pool(cmd, lv, lp);
+
+ log_error("Operation not permitted on cache LV %s", display_lvname(lv));
+ log_error("Operations permitted on a cache LV are:\n"
+ " --splitcache\n"
+ " --uncache\n"
+ " --splitmirrors (operates on mirror or raid sub LV)\n"
+ " --type thin-pool\n");
+ return ECMD_FAILED;
+}
+
+static int _convert_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ if (lp->splitcache || lp->split)
+ return _convert_cache_pool_splitcache(cmd, lv, lp);
+
+ /* FIXME: swapping the cache pool metadata LV needs a specific option. */
+ /*
+ if (lp->swapmetadata)
+ return _convert_cache_pool_swapmetadata(cmd, lv, lp);
+ */
+
+ log_error("Operation not permitted on cache pool LV %s", display_lvname(lv));
+ log_error("Operations permitted on a cache pool LV are:\n"
+ " --splitcache (operates on cache LV)\n");
+ return ECMD_FAILED;
+}
+
+static int _convert_mirror(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* FIXME: add lp->splitmirrors to reflect the arg. */
+ if (lp->mirrors_supplied || arg_is_set(cmd, splitmirrors_ARG))
+ return _convert_mirror_number(cmd, lv, lp);
+
+ if (lp->mirrorlog || lp->corelog)
+ return _convert_mirror_log(cmd, lv, lp);
+
+ if (lp->repair)
+ return _convert_mirror_repair(cmd, lv, lp);
+
+ log_error("Operation not permitted on mirror LV %s", display_lvname(lv));
+ log_error("Operations permitted on a mirror LV are:\n"
+ " --mirrors\n"
+ " --splitmirrors\n"
+ " --mirrorlog\n"
+ " --repair\n");
+ return ECMD_FAILED;
+}
+
+static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ const char *new_type = arg_str_value(cmd, type_ARG, NULL);
+ const struct segment_type *new_segtype = NULL;
+
+ if (new_type)
+ new_segtype = get_segtype_from_string(cmd, new_type);
+
+ if (lp->mirrors_supplied)
+ return _convert_raid_number(cmd, lv, lp);
+
+ /* FIXME: add lp->splitmirrors to reflect the arg. */
+ if (arg_is_set(cmd, splitmirrors_ARG))
+ return _convert_raid_splitmirrors(cmd, lv, lp);
+
+ if (lp->merge_mirror)
+ return _convert_raid_merge(cmd, lv, lp);
+
+ if (lp->repair)
+ return _convert_raid_repair(cmd, lv, lp);
+
+ if (lp->replace)
+ return _convert_raid_replace(cmd, lv, lp);
+
+ if (lp->snapshot)
+ return _convert_raid_snapshot(cmd, lv, lp);
+
+ if (lp->thin)
+ return _convert_raid_thin(cmd, lv, lp);
+
+ if (lp->cache)
+ return _convert_raid_cache(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "thin-pool"))
+ return _convert_raid_thin_pool(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "cache-pool"))
+ return _convert_raid_cache_pool(cmd, lv, lp);
+
+ if (new_type && new_segtype && segtype_is_raid(new_segtype))
+ return _convert_raid_raid(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "striped"))
+ return _convert_raid_striped(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "linear"))
+ return _convert_raid_linear(cmd, lv, lp);
+
+ log_error("Operation not permitted on raid LV %s", display_lvname(lv));
+ log_error("Operations permitted on a raid LV are:\n"
+ " --mirrors\n"
+ " --splitmirrors\n"
+ " --merge\n"
+ " --repair\n"
+ " --replace\n"
+ " --snapshot\n"
+ " --thin\n"
+ " --cache\n"
+ " --type thin-pool\n"
+ " --type cache-pool\n"
+ " --type raid\n"
+ " --type striped\n"
+ " --type linear\n");
+ return ECMD_FAILED;
+}
+
+static int _convert_striped(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ const char *new_type = arg_str_value(cmd, type_ARG, NULL);
+ const struct segment_type *new_segtype = NULL;
+
+ if (new_type)
+ new_segtype = get_segtype_from_string(cmd, new_type);
+
+ if (lp->snapshot)
+ return _convert_striped_snapshot(cmd, lv, lp);
+
+ if (lp->thin)
+ return _convert_striped_thin(cmd, lv, lp);
+
+ if (lp->cache)
+ return _convert_striped_cache(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "thin-pool"))
+ return _convert_striped_thin_pool(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "cache-pool"))
+ return _convert_striped_cache_pool(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "mirror"))
+ return _convert_striped_mirror(cmd, lv, lp);
+
+ if (new_type && new_segtype && segtype_is_raid(new_segtype))
+ return _convert_striped_raid(cmd, lv, lp);
+
+ log_error("Operation not permitted on striped or linear LV %s", display_lvname(lv));
+ log_error("Operations permitted on a striped or linear LV are:\n"
+ " --snapshot\n"
+ " --thin\n"
+ " --cache\n"
+ " --type thin-pool\n"
+ " --type cache-pool\n"
+ " --type mirror\n"
+ " --type raid\n");
+ return ECMD_FAILED;
+}
+
+/*
+ * lvconvert performs a specific <operation> on a specific <lv_type>.
+ *
+ * The <operation> is specified by command args found in lp fields.
+ * The <lv_type> is found using lv_is_foo(lv) functions.
+ *
+ * lvconvert --operation LV
+ *
+ * lp->operation = arg_value(operation);
+ * lv_type = lv_is_foo(LV);
+ *
+ * for each lvtype,
+ * _convert_lvtype();
+ * for each lp->operation
+ * _convert_lvtype_operation();
+ */
+
+static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct lv_segment *lv_seg = first_seg(lv);
+ int ret;
+
+ log_debug("lvconvert lv %s is type %s status %llx to type %s",
+ display_lvname(lv),
+ lv_seg->segtype->name,
+ (unsigned long long)lv->status,
+ arg_str_value(cmd, type_ARG, ""));
+
+ /*
+ * Check some conditions that can never be processed.
+ */
+
+ if (lv_is_locked(lv)) {
+ log_error("Cannot convert locked LV %s.", display_lvname(lv));
+ ret = ECMD_FAILED;
+ goto out;
+ }
+
+ if (lv_is_pvmove(lv)) {
+ log_error("Cannot convert pvmove LV %s.", display_lvname(lv));
+ ret = ECMD_FAILED;
+ goto out;
+ }
+
+ if (!lv_is_visible(lv)) {
+ /*
+ * FIXME: there are some exceptions to the rule of only
+ * operating on visible LVs. These should be fixed by running
+ * the command on the visible LV with an option indicating
+ * which sub LV is intended rather than naming the !visible LV.
+ */
+ if (!lv_is_cache_pool_metadata(lv) &&
+ !lv_is_cache_pool_data(lv) &&
+ !lv_is_thin_pool_metadata(lv) &&
+ !lv_is_thin_pool_data(lv) &&
+ !lv_is_raid_image(lv)) {
+ log_error("Cannot convert internal LV %s.", display_lvname(lv));
+ ret = ECMD_FAILED;
+ goto out;
+ }
+ }
+
+ /*
+ * Each LV type that can be converted.
+ * (The existing type of the LV, not a requested type.)
+ */
+
+ if (lv_is_cow(lv)) {
+ ret = _convert_cow_snapshot(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_thin_volume(lv)) {
+ ret = _convert_thin_volume(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_thin_pool(lv)) {
+ ret = _convert_thin_pool(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_cache(lv)) {
+ ret = _convert_cache_volume(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_cache_pool(lv)) {
+ ret = _convert_cache_pool(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_mirror(lv)) {
+ ret = _convert_mirror(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_raid(lv)) {
+ ret = _convert_raid(cmd, lv, lp);
+ goto out;
+ }
+
+ /*
+ * FIXME: add lv_is_striped() and lv_is_linear()?
+ * This does not include raid0.
+ * If operations differ between striped and linear, split this case.
+ */
+ if (segtype_is_striped(lv_seg->segtype) || segtype_is_linear(lv_seg->segtype)) {
+ ret = _convert_striped(cmd, lv, lp);
+ goto out;
+ }
+
+ /*
+ * Check for LV types that cannot be converted and print an error.
+ */
+
+ /*
+ * The intention is to explicitly check all cases above and never
+ * reach here, but this covers anything that was missed.
+ */
+ log_error("Cannot convert LV %s.", display_lvname(lv));
+ ret = ECMD_FAILED;
+
+out:
+ return ret;
+
+}
static struct convert_poll_id_list* _convert_poll_id_list_create(struct cmd_context *cmd,
const struct logical_volume *lv)