summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2016-12-20 15:17:48 -0600
committerDavid Teigland <teigland@redhat.com>2016-12-22 13:40:35 -0600
commit0e525225ed668b9f7676def744f86d26127c794c (patch)
tree1abca2bad26fb5641dd696a1dbb9f224a12f38b0
parent0dcb767fec6749fb324a3fe58af0b0e19e680319 (diff)
downloadlvm2-dev-dct-cmd-defs65.tar.gz
lvconvert: remove unused codedev-dct-cmd-defs65
-rw-r--r--tools/lvconvert.c2056
1 files changed, 325 insertions, 1731 deletions
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index e65e49799..4070a6045 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -19,25 +19,6 @@
#include "lvconvert_poll.h"
#include "command-lines-count.h"
-/*
- * Guidelines for mapping options to operations.
- *
- * There should be a clear and unique correspondence between an option
- * name and the operation to be performed.
- *
- * An option with a given name should always perform the same operation.
- * If the same operation applies to two types of LV, then the same option
- * name can be used with both LV types. But, a given option name should
- * not be used to perform different operations depending on the LV type it
- * is used with.
- *
- * --merge and --split are examples where a single option name has been
- * overloaded with different operations. The case of --split has been
- * corrected with the clear and unique variations --splitcache,
- * --splitsnapshot, --splitmirror, which should allow --split to be
- * deprecated. (The same is still needed for --merge.)
- */
-
typedef enum {
/* Split:
* For a mirrored or raid LV, split mirror into two mirrors, optionally tracking
@@ -52,23 +33,13 @@ typedef enum {
struct lvconvert_params {
/* Exactly one of these 12 command categories is determined */
- int merge; /* 1 */
- int split; /* 2 */
- int splitsnapshot; /* 3 */
- int splitcache; /* 4 */
- int keep_mimages; /* 5 */ /* --splitmirrors */
- int cache; /* 6 */
- int uncache; /* 7 */
- int snapshot; /* 8 */
- int thin; /* 11 */
- /* other */ /* 12 */
+ int split; /* 1 */
+ int keep_mimages; /* 2 */ /* --splitmirrors */
+ /* other */ /* 3 */
/* FIXME Eliminate all cases where more than one of the above are set then use conv_type instead */
conversion_type_t conv_type;
- int merge_snapshot; /* CONV_MERGE is set */
- int merge_mirror; /* CONV_MERGE is set */
-
int track_changes; /* CONV_SPLIT_MIRRORS is set */
int corelog; /* Equivalent to --mirrorlog core */
@@ -80,7 +51,6 @@ struct lvconvert_params {
const struct segment_type *segtype; /* Holds what segment type you will get */
- int poolmetadataspare;
int force;
int yes;
int zero;
@@ -92,8 +62,6 @@ struct lvconvert_params {
int wait_completion;
int need_polling;
- int thin_chunk_size_calc_policy;
- uint32_t chunk_size;
uint32_t region_size;
uint32_t mirrors;
@@ -103,9 +71,6 @@ struct lvconvert_params {
unsigned stripes_supplied;
unsigned stripe_size_supplied;
uint32_t read_ahead;
- cache_mode_t cache_mode; /* cache */
- const char *policy_name; /* cache */
- struct dm_config_tree *policy_settings; /* cache */
unsigned target_attr;
@@ -118,15 +83,7 @@ struct lvconvert_params {
struct logical_volume *lv_to_poll;
struct dm_list idls;
- uint32_t pool_metadata_extents;
- int passed_args;
- uint64_t pool_metadata_size;
const char *origin_name;
- const char *pool_data_name;
- struct logical_volume *pool_data_lv;
- const char *pool_metadata_name;
- struct logical_volume *pool_metadata_lv;
- thin_discards_t discards;
};
struct convert_poll_id_list {
@@ -145,12 +102,6 @@ static void _set_conv_type(struct lvconvert_params *lp, int conv_type)
lp->conv_type = conv_type;
}
-/* -s/--snapshot and --type snapshot are synonyms */
-static int _snapshot_type_requested(struct cmd_context *cmd, const char *type_str)
-{
- return (arg_is_set(cmd, snapshot_ARG) || !strcmp(type_str, SEG_TYPE_NAME_SNAPSHOT));
-}
-
static int _raid0_type_requested(const char *type_str)
{
return (!strcmp(type_str, SEG_TYPE_NAME_RAID0) || !strcmp(type_str, SEG_TYPE_NAME_RAID0_META));
@@ -1282,11 +1233,6 @@ static int _lvconvert_mirrors(struct cmd_context *cmd,
return 0;
}
- if (lp->merge_mirror) {
- log_error("Unable to merge mirror images of segment type 'mirror'.");
- return 0;
- }
-
if (!_lvconvert_validate_thin(lv, lp))
return_0;
@@ -1424,7 +1370,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
if (!_is_valid_raid_conversion(seg->segtype, lp->segtype))
goto try_new_takeover_or_reshape;
- if (seg_is_linear(seg) && !lp->merge_mirror && !lp->mirrors_supplied) {
+ if (seg_is_linear(seg) && !lp->mirrors_supplied) {
if (_raid0_type_requested(lp->type_str)) {
log_error("Linear LV %s cannot be converted to %s.",
display_lvname(lv), lp->type_str);
@@ -1466,9 +1412,6 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
return 0;
}
- if (lp->merge_mirror)
- return lv_raid_merge(lv);
-
if (lp->track_changes)
return lv_raid_split_and_track(lv, lp->pvh);
@@ -1555,6 +1498,322 @@ try_new_takeover_or_reshape:
return 0;
}
+/*
+ * 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.
+ */
+
+/*
+ * Change the number of images in a mirror LV.
+ * lvconvert --mirrors Number LV
+ */
+static int _convert_mirror_number(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+/*
+ * Split images from a mirror LV and use them to create a new LV.
+ * lvconvert --splitmirrors Number LV
+ *
+ * Required options:
+ * --name Name
+ */
+
+static int _convert_mirror_splitmirrors(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+/*
+ * Change the type of log used by a mirror LV.
+ * lvconvert --mirrorlog Type LV
+ */
+static int _convert_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+/*
+ * Convert mirror LV to linear LV.
+ * lvconvert --type linear LV
+ *
+ * Alternate syntax:
+ * lvconvert --mirrors 0 LV
+ */
+static int _convert_mirror_linear(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+/*
+ * Convert mirror LV to raid1 LV.
+ * lvconvert --type raid1 LV
+ */
+static int _convert_mirror_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+/*
+ * Change the number of images in a raid1 LV.
+ * lvconvert --mirrors Number LV
+ */
+static int _convert_raid_number(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+/*
+ * Split images from a raid1 LV and use them to create a new LV.
+ * lvconvert --splitmirrors Number LV
+ *
+ * Required options:
+ * --trackchanges | --name Name
+ */
+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);
+}
+
+/*
+ * Convert a raid* LV to use a different raid level.
+ * lvconvert --type raid* LV
+ */
+static int _convert_raid_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+/*
+ * Convert a raid* LV to a mirror LV.
+ * lvconvert --type mirror LV
+ */
+static int _convert_raid_mirror(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+/*
+ * Convert a raid* LV to a striped LV.
+ * lvconvert --type striped LV
+ */
+static int _convert_raid_striped(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+/*
+ * Convert a raid* LV to a linear LV.
+ * lvconvert --type linear LV
+ */
+static int _convert_raid_linear(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+/*
+ * Convert a striped/linear LV to a mirror LV.
+ * lvconvert --type mirror LV
+ *
+ * Required options:
+ * --mirrors Number
+ *
+ * Alternate syntax:
+ * This is equivalent to above when global/mirror_segtype_default="mirror".
+ * lvconvert --mirrors Number LV
+ */
+static int _convert_striped_mirror(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+/*
+ * Convert a striped/linear LV to a raid* LV.
+ * lvconvert --type raid* LV
+ *
+ * Required options:
+ * --mirrors Number
+ *
+ * Alternate syntax:
+ * This is equivalent to above when global/mirror_segtype_default="raid1".
+ * lvconvert --mirrors Number LV
+ */
+static int _convert_striped_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_mirror(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ if (arg_is_set(cmd, mirrors_ARG))
+ return _convert_mirror_number(cmd, lv, lp);
+
+ if (arg_is_set(cmd, splitmirrors_ARG))
+ return _convert_mirror_splitmirrors(cmd, lv, lp);
+
+ if (arg_is_set(cmd, mirrorlog_ARG) || arg_is_set(cmd, corelog_ARG))
+ return _convert_mirror_log(cmd, lv, lp);
+
+ if (_linear_type_requested(lp->type_str))
+ return _convert_mirror_linear(cmd, lv, lp);
+
+ if (segtype_is_raid(lp->segtype))
+ return _convert_mirror_raid(cmd, lv, lp);
+
+ log_error("Unknown operation on mirror LV %s.", display_lvname(lv));
+ return 0;
+}
+
+static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ if (arg_is_set(cmd, mirrors_ARG))
+ return _convert_raid_number(cmd, lv, lp);
+
+ if (arg_is_set(cmd, splitmirrors_ARG))
+ return _convert_raid_splitmirrors(cmd, lv, lp);
+
+ if (segtype_is_raid(lp->segtype))
+ return _convert_raid_raid(cmd, lv, lp);
+
+ if (segtype_is_mirror(lp->segtype))
+ return _convert_raid_mirror(cmd, lv, lp);
+
+ if (!strcmp(lp->type_str, SEG_TYPE_NAME_STRIPED))
+ return _convert_raid_striped(cmd, lv, lp);
+
+ if (_linear_type_requested(lp->type_str))
+ return _convert_raid_linear(cmd, lv, lp);
+
+ log_error("Unknown operation on raid LV %s.", display_lvname(lv));
+ return 0;
+}
+
+static int _convert_striped(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ const char *mirrors_type = find_config_tree_str(cmd, global_mirror_segtype_default_CFG, NULL);
+
+ if (!strcmp(lp->type_str, SEG_TYPE_NAME_MIRROR))
+ return _convert_striped_mirror(cmd, lv, lp);
+
+ if (segtype_is_raid(lp->segtype))
+ return _convert_striped_raid(cmd, lv, lp);
+
+ /* --mirrors can mean --type mirror or --type raid1 depending on config setting. */
+
+ if (arg_is_set(cmd, mirrors_ARG) && mirrors_type && !strcmp(mirrors_type, SEG_TYPE_NAME_MIRROR))
+ return _convert_striped_mirror(cmd, lv, lp);
+
+ if (arg_is_set(cmd, mirrors_ARG) && mirrors_type && !strcmp(mirrors_type, SEG_TYPE_NAME_RAID1))
+ return _convert_striped_raid(cmd, lv, lp);
+
+ log_error("Unknown operation on striped or linear LV %s.", display_lvname(lv));
+ return 0;
+}
+
+static int _lvconvert_raid_types(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct lv_segment *seg = first_seg(lv);
+ int ret = 0;
+
+ /* Set up segtype either from type_str or else to match the existing one. */
+ if (!*lp->type_str)
+ lp->segtype = seg->segtype;
+ else if (!(lp->segtype = get_segtype_from_string(cmd, lp->type_str)))
+ goto_out;
+
+ if (!strcmp(lp->type_str, SEG_TYPE_NAME_MIRROR)) {
+ if (!lp->mirrors_supplied && !seg_is_raid1(seg)) {
+ log_error("Conversions to --type mirror require -m/--mirrors");
+ goto out;
+ }
+ }
+
+ /* lv->segtype can't be NULL */
+ if (activation() && lp->segtype->ops->target_present &&
+ !lp->segtype->ops->target_present(cmd, NULL, &lp->target_attr)) {
+ log_error("%s: Required device-mapper target(s) not "
+ "detected in your kernel.", lp->segtype->name);
+ goto out;
+ }
+
+ /* Process striping parameters */
+ /* FIXME This is incomplete */
+ if (_mirror_or_raid_type_requested(cmd, lp->type_str) || _raid0_type_requested(lp->type_str) ||
+ _striped_type_requested(lp->type_str) || lp->mirrorlog || lp->corelog) {
+ /* FIXME Handle +/- adjustments too? */
+ if (!get_stripe_params(cmd, lp->segtype, &lp->stripes, &lp->stripe_size, &lp->stripes_supplied, &lp->stripe_size_supplied))
+ goto_out;
+
+ if (_raid0_type_requested(lp->type_str) || _striped_type_requested(lp->type_str))
+ /* FIXME Shouldn't need to override get_stripe_params which defaults to 1 stripe (i.e. linear)! */
+ /* The default keeps existing number of stripes, handled inside the library code */
+ if (!arg_is_set(cmd, stripes_long_ARG))
+ lp->stripes = 0;
+ }
+
+ if (lv_is_cache(lv))
+ lv = seg_lv(first_seg(lv), 0);
+
+ 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 which is caught by the test above.
+ * If operations differ between striped and linear, split this case.
+ */
+ if (segtype_is_striped(seg->segtype) || segtype_is_linear(seg->segtype)) {
+ ret = _convert_striped(cmd, lv, lp);
+ goto out;
+ }
+
+ /*
+ * 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));
+
+out:
+ return ret ? ECMD_PROCESSED : ECMD_FAILED;
+}
+
static int _lvconvert_splitsnapshot(struct cmd_context *cmd, struct logical_volume *cow)
{
struct volume_group *vg = cow->vg;
@@ -2164,142 +2423,6 @@ deactivate_pmslv:
return 1;
}
-/* Currently converts only to thin volume with external origin */
-static int _lvconvert_thin(struct cmd_context *cmd,
- struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- struct logical_volume *torigin_lv, *pool_lv = lp->pool_data_lv;
- struct volume_group *vg = lv->vg;
- struct lvcreate_params lvc = {
- .activate = CHANGE_AEY,
- .alloc = ALLOC_INHERIT,
- .lv_name = lp->origin_name,
- .major = -1,
- .minor = -1,
- .suppress_zero_warn = 1, /* Suppress warning for this thin */
- .permission = LVM_READ,
- .pool_name = pool_lv->name,
- .pvh = &vg->pvs,
- .read_ahead = DM_READ_AHEAD_AUTO,
- .stripes = 1,
- .virtual_extents = lv->le_count,
- };
-
- if (lv == pool_lv) {
- log_error("Can't use same LV %s for thin pool and thin volume.",
- display_lvname(pool_lv));
- return 0;
- }
-
- if (lv_is_locked(lv) ||
- !lv_is_visible(lv) ||
- lv_is_cow(lv) ||
- lv_is_pool(lv) ||
- lv_is_pool_data(lv) ||
- lv_is_pool_metadata(lv)) {
- log_error("Can't use%s%s %s %s as external origin.",
- lv_is_locked(lv) ? " locked" : "",
- lv_is_visible(lv) ? "" : " hidden",
- lvseg_name(first_seg(lv)),
- display_lvname(lv));
- return 0;
- }
-
- if (is_lockd_type(lv->vg->lock_type)) {
- /*
- * FIXME: external origins don't work in lockd VGs.
- * Prior to the lvconvert, there's a lock associated with
- * the uuid of the external origin LV. After the convert,
- * that uuid belongs to the new thin LV, and a new LV with
- * a new uuid exists as the non-thin, readonly external LV.
- * We'd need to remove the lock for the previous uuid
- * (the new thin LV will have no lock), and create a new
- * lock for the new LV uuid used by the external LV.
- */
- log_error("Can't use lock_type %s LV as external origin.",
- lv->vg->lock_type);
- return 0;
- }
-
- dm_list_init(&lvc.tags);
-
- if (!pool_supports_external_origin(first_seg(pool_lv), lv))
- return_0;
-
- if (!(lvc.segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_THIN)))
- return_0;
-
- if (!archive(vg))
- return_0;
-
- /* New thin LV needs to be created (all messages sent to pool)
- * In this case thin volume is created READ-ONLY and
- * also warn about not zeroing is suppressed. */
- if (!(torigin_lv = lv_create_single(vg, &lvc)))
- return_0;
-
- /* Deactivate prepared Thin LV */
- if (!deactivate_lv(cmd, torigin_lv)) {
- log_error("Aborting. Unable to deactivate new LV. "
- "Manual intervention required.");
- return 0;
- }
-
- /*
- * Crashing till this point will leave plain thin volume
- * which could be easily removed by the user after i.e. power-off
- */
-
- if (!swap_lv_identifiers(cmd, torigin_lv, lv)) {
- stack;
- goto revert_new_lv;
- }
-
- /* Preserve read-write status of original LV here */
- torigin_lv->status |= (lv->status & LVM_WRITE);
-
- if (!attach_thin_external_origin(first_seg(torigin_lv), lv)) {
- stack;
- goto revert_new_lv;
- }
-
- if (!lv_update_and_reload(torigin_lv)) {
- stack;
- goto deactivate_and_revert_new_lv;
- }
-
- log_print_unless_silent("Converted %s to thin volume with "
- "external origin %s.",
- display_lvname(torigin_lv),
- display_lvname(lv));
-
- return 1;
-
-deactivate_and_revert_new_lv:
- if (!swap_lv_identifiers(cmd, torigin_lv, lv))
- stack;
-
- if (!deactivate_lv(cmd, torigin_lv)) {
- log_error("Unable to deactivate failed new LV. "
- "Manual intervention required.");
- return 0;
- }
-
- if (!detach_thin_external_origin(first_seg(torigin_lv)))
- return_0;
-
-revert_new_lv:
- /* FIXME Better to revert to backup of metadata? */
- if (!lv_remove(torigin_lv) || !vg_write(vg) || !vg_commit(vg))
- log_error("Manual intervention may be required to remove "
- "abandoned LV(s) before retrying.");
- else
- backup(vg);
-
- return 0;
-}
-
static int _lvconvert_to_thin_with_external(struct cmd_context *cmd,
struct logical_volume *lv,
struct logical_volume *thinpool_lv)
@@ -2438,581 +2561,6 @@ revert_new_lv:
return 0;
}
-static int _lvconvert_update_pool_params(struct logical_volume *pool_lv,
- struct lvconvert_params *lp)
-{
- if (lp->pool_metadata_size &&
- !(lp->pool_metadata_extents =
- extents_from_size(pool_lv->vg->cmd, lp->pool_metadata_size, pool_lv->vg->extent_size)))
- return_0;
-
- return update_pool_params(lp->segtype,
- pool_lv->vg,
- lp->target_attr,
- lp->passed_args,
- pool_lv->le_count,
- &lp->pool_metadata_extents,
- &lp->thin_chunk_size_calc_policy,
- &lp->chunk_size,
- &lp->discards,
- &lp->zero);
-}
-
-/*
- * Converts a data lv and a metadata lv into a thin or cache pool lv.
- *
- * Thin lvconvert version which
- * rename metadata
- * convert/layers thinpool over data
- * attach metadata
- *
- * pool_lv might or might not already be a pool.
- */
-static int _lvconvert_pool(struct cmd_context *cmd,
- struct logical_volume *pool_lv,
- struct lvconvert_params *lp)
-{
- int r = 0;
- const char *old_name;
- struct lv_segment *seg;
- struct volume_group *vg = pool_lv->vg;
- struct logical_volume *data_lv;
- struct logical_volume *metadata_lv = NULL;
- struct logical_volume *pool_metadata_lv;
- char *lockd_data_args = NULL;
- char *lockd_meta_args = NULL;
- char *lockd_data_name = NULL;
- char *lockd_meta_name = NULL;
- struct id lockd_data_id;
- struct id lockd_meta_id;
- char metadata_name[NAME_LEN], data_name[NAME_LEN];
- int zero_metadata = 1;
- int activate_pool;
-
- if (lp->pool_data_name) {
- if ((lp->thin || lp->cache) &&
- !strcmp(lp->pool_data_name, pool_lv->name)) {
- log_error("Converted volume %s and pool volume must differ.",
- display_lvname(pool_lv));
- return 0;
- }
- if (!(pool_lv = find_lv(vg, lp->pool_data_name))) {
- log_error("Unknown pool data LV %s.", lp->pool_data_name);
- return 0;
- }
- }
-
- /* An existing LV needs to have its lock freed once it becomes a data LV. */
- if (is_lockd_type(vg->lock_type) && !lv_is_pool(pool_lv) && pool_lv->lock_args) {
- lockd_data_args = dm_pool_strdup(cmd->mem, pool_lv->lock_args);
- lockd_data_name = dm_pool_strdup(cmd->mem, pool_lv->name);
- memcpy(&lockd_data_id, &pool_lv->lvid.id[1], sizeof(struct id));
- }
-
- if (!lv_is_visible(pool_lv)) {
- log_error("Can't convert internal LV %s.", display_lvname(pool_lv));
- return 0;
- }
-
- if (lv_is_locked(pool_lv)) {
- log_error("Can't convert locked LV %s.", display_lvname(pool_lv));
- return 0;
- }
-
- if (lv_is_thin_pool(pool_lv) && (segtype_is_cache_pool(lp->segtype) || lp->cache)) {
- log_error("Can't convert thin pool LV %s.", display_lvname(pool_lv));
- return 0;
- }
-
- if (lv_is_cache(pool_lv) && !segtype_is_thin_pool(lp->segtype)) {
- log_error("Cached LV %s could be only converted into a thin pool volume.",
- display_lvname(pool_lv));
- return 0;
- }
-
- if (lv_is_cache_pool(pool_lv) && (segtype_is_thin_pool(lp->segtype) || lp->thin)) {
- log_error("Cannot convert cache pool %s as pool data volume.",
- display_lvname(pool_lv));
- return 0;
- }
-
- if (lv_is_mirror(pool_lv)) {
- log_error("Mirror logical volumes cannot be used as pools.");
- log_print_unless_silent("Try \"%s\" segment type instead.", SEG_TYPE_NAME_RAID1);
- return 0;
- }
-
- /*
- * Only linear, striped and raid supported.
- * FIXME Tidy up all these type restrictions.
- */
- if (!lv_is_pool(pool_lv) &&
- (lv_is_thin_type(pool_lv) ||
- lv_is_cow(pool_lv) || lv_is_merging_cow(pool_lv) ||
- lv_is_origin(pool_lv) ||lv_is_merging_origin(pool_lv) ||
- lv_is_external_origin(pool_lv) ||
- lv_is_virtual(pool_lv))) {
- log_error("Pool data LV %s is of an unsupported type.", display_lvname(pool_lv));
- return 0;
- }
-
- if (lp->pool_metadata_name) {
- if (!(lp->pool_metadata_lv = find_lv(vg, lp->pool_metadata_name))) {
- log_error("Unknown pool metadata LV %s.", lp->pool_metadata_name);
- return 0;
- }
- lp->pool_metadata_extents = lp->pool_metadata_lv->le_count;
- metadata_lv = lp->pool_metadata_lv;
-
- /* An existing LV needs to have its lock freed once it becomes a meta LV. */
- if (is_lockd_type(vg->lock_type) && metadata_lv->lock_args) {
- lockd_meta_args = dm_pool_strdup(cmd->mem, metadata_lv->lock_args);
- lockd_meta_name = dm_pool_strdup(cmd->mem, metadata_lv->name);
- memcpy(&lockd_meta_id, &metadata_lv->lvid.id[1], sizeof(struct id));
- }
-
- if (metadata_lv == pool_lv) {
- log_error("Can't use same LV for pool data and metadata LV %s.",
- display_lvname(metadata_lv));
- return 0;
- }
-
- if (!lv_is_visible(metadata_lv)) {
- log_error("Can't convert internal LV %s.",
- display_lvname(metadata_lv));
- return 0;
- }
-
- if (lv_is_locked(metadata_lv)) {
- log_error("Can't convert locked LV %s.",
- display_lvname(metadata_lv));
- return 0;
- }
-
- if (lv_is_mirror(metadata_lv)) {
- log_error("Mirror logical volumes cannot be used for pool metadata.");
- log_print_unless_silent("Try \"%s\" segment type instead.", SEG_TYPE_NAME_RAID1);
- return 0;
- }
-
- /* FIXME Tidy up all these type restrictions. */
- if (lv_is_cache_type(metadata_lv) ||
- lv_is_thin_type(metadata_lv) ||
- lv_is_cow(metadata_lv) || lv_is_merging_cow(metadata_lv) ||
- lv_is_origin(metadata_lv) || lv_is_merging_origin(metadata_lv) ||
- lv_is_external_origin(metadata_lv) ||
- lv_is_virtual(metadata_lv)) {
- log_error("Pool metadata LV %s is of an unsupported type.",
- display_lvname(metadata_lv));
- return 0;
- }
-
- if (!lv_is_pool(pool_lv)) {
- if (!_lvconvert_update_pool_params(pool_lv, lp))
- return_0;
-
- if (lp->pool_metadata_extents > metadata_lv->le_count) {
- log_error("Logical volume %s is too small for metadata.",
- display_lvname(metadata_lv));
- return 0;
- }
- }
- }
-
- if (lv_is_pool(pool_lv)) {
- lp->pool_data_lv = pool_lv;
-
- if (!metadata_lv) {
- if (arg_from_list_is_set(cmd, "is invalid with existing pool",
- discards_ARG,
- poolmetadatasize_ARG, -1))
- return_0;
-
- if (lp->thin &&
- arg_from_list_is_set(cmd, "is invalid with existing thin pool",
- chunksize_ARG, zero_ARG, -1))
- return_0;
-
- if (lp->cache) {
- if (!lp->chunk_size)
- lp->chunk_size = first_seg(pool_lv)->chunk_size;
-
- if (!validate_lv_cache_chunk_size(pool_lv, lp->chunk_size))
- return_0;
-
- /* Check is user requested zeroing logic via [-Z y|n] */
- if (!arg_is_set(cmd, zero_ARG)) {
- /* Note: requires rather deep know-how to skip zeroing */
- if (!lp->yes &&
- yes_no_prompt("Do you want wipe existing metadata of "
- "cache pool volume %s? [y/n]: ",
- display_lvname(pool_lv)) == 'n') {
- log_error("Conversion aborted.");
- log_error("To preserve cache metadata add option \"--zero n\".");
- log_warn("WARNING: Reusing mismatched cache pool metadata "
- "MAY DESTROY YOUR DATA!");
- return 0;
- }
- /* Wiping confirmed, go ahead */
- if (!wipe_cache_pool(pool_lv))
- return_0;
- } else if (arg_int_value(cmd, zero_ARG, 0)) {
- if (!wipe_cache_pool(pool_lv)) /* Wipe according to -Z y|n */
- return_0;
- } else
- log_warn("WARNING: Reusing cache pool metadata %s "
- "for volume caching.", display_lvname(pool_lv));
- }
-
- if (lp->thin || lp->cache)
- /* already pool, can continue converting volume */
- return 1;
-
- log_error("LV %s is already pool.", display_lvname(pool_lv));
- return 0;
- }
-
- if (lp->thin || lp->cache) {
- log_error("--%s and pool metadata swap is not supported.",
- lp->thin ? "thin" : "cache");
- return 0;
- }
-
- /* FIXME cache pool */
- if (lv_is_thin_pool(pool_lv) && pool_is_active(pool_lv)) {
- /* If any volume referencing pool active - abort here */
- log_error("Cannot convert pool %s with active volumes.",
- display_lvname(pool_lv));
- return 0;
- }
-
- lp->passed_args |= PASS_ARG_CHUNK_SIZE | PASS_ARG_DISCARDS | PASS_ARG_ZERO;
- seg = first_seg(pool_lv);
-
- /* Normally do NOT change chunk size when swapping */
- if (arg_is_set(cmd, chunksize_ARG) &&
- (lp->chunk_size != seg->chunk_size) &&
- !dm_list_empty(&pool_lv->segs_using_this_lv)) {
- if (lp->force == PROMPT) {
- log_error("Chunk size can be only changed with --force. Conversion aborted.");
- return 0;
- }
- log_warn("WARNING: Changing chunk size %s to "
- "%s for %s pool volume.",
- display_size(cmd, seg->chunk_size),
- display_size(cmd, lp->chunk_size),
- display_lvname(pool_lv));
- /* Ok, user has likely some serious reason for this */
- if (!lp->yes &&
- yes_no_prompt("Do you really want to change chunk size "
- "for %s pool volume? [y/n]: ",
- display_lvname(pool_lv)) == 'n') {
- log_error("Conversion aborted.");
- return 0;
- }
- } else
- lp->chunk_size = seg->chunk_size;
-
- if (!_lvconvert_update_pool_params(pool_lv, lp))
- return_0;
-
- if (metadata_lv->le_count < lp->pool_metadata_extents)
- log_print_unless_silent("Continuing with swap...");
-
- if (!arg_is_set(cmd, discards_ARG))
- lp->discards = seg->discards;
- if (!arg_is_set(cmd, zero_ARG))
- lp->zero = seg->zero_new_blocks;
-
- if (!lp->yes &&
- yes_no_prompt("Do you want to swap metadata of %s "
- "pool with metadata volume %s? [y/n]: ",
- display_lvname(pool_lv),
- display_lvname(metadata_lv)) == 'n') {
- log_error("Conversion aborted.");
- return 0;
- }
- } else {
- /* Only cache pool conversion may suppress metadata zeroing
- * TODO: Maybe similar support could be useful for thin-pool, but --zero
- * is already overloade and we would also need to possibly match transaction Id. */
- if (segtype_is_cache_pool(lp->segtype) && metadata_lv)
- /* Check is user requested zeroing logic via [-Z y|n] (default is yes) */
- zero_metadata = arg_int_value(cmd, zero_ARG, 1);
-
- log_warn("WARNING: Converting logical volume %s%s%s to %s pool's data%s %s metadata wiping.",
- display_lvname(pool_lv),
- metadata_lv ? " and " : "",
- metadata_lv ? display_lvname(metadata_lv) : "",
- segtype_is_cache_pool(lp->segtype) ? "cache" : "thin",
- metadata_lv ? " and metadata volumes" : " volume",
- zero_metadata ? "with" : "WITHOUT");
-
- if (zero_metadata)
- log_warn("THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.)");
- else /* ATM supported only for cache pools */
- log_warn("WARNING: Using mismatched cache pool metadata "
- "MAY DESTROY YOUR DATA!");
-
- if (!lp->yes &&
- yes_no_prompt("Do you really want to convert %s%s%s? [y/n]: ",
- display_lvname(pool_lv),
- metadata_lv ? " and " : "",
- metadata_lv ? display_lvname(metadata_lv) : "") == 'n') {
- log_error("Conversion aborted.");
- return 0;
- }
- }
-
- if (segtype_is_cache_pool(lp->segtype))
- activate_pool = 0; /* Cannot activate cache pool */
- else
- /* Allow to have only thinpool active and restore it's active state */
- activate_pool = lv_is_active(pool_lv);
-
- if ((dm_snprintf(metadata_name, sizeof(metadata_name), "%s%s",
- pool_lv->name,
- (segtype_is_cache_pool(lp->segtype)) ?
- "_cmeta" : "_tmeta") < 0) ||
- (dm_snprintf(data_name, sizeof(data_name), "%s%s",
- pool_lv->name,
- (segtype_is_cache_pool(lp->segtype)) ?
- "_cdata" : "_tdata") < 0)) {
- log_error("Failed to create internal lv names, "
- "pool name is too long.");
- return 0;
- }
-
- if (!metadata_lv) {
- if (!_lvconvert_update_pool_params(pool_lv, lp))
- return_0;
-
- if (!get_stripe_params(cmd, get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED),
- &lp->stripes, &lp->stripe_size, &lp->stripes_supplied, &lp->stripe_size_supplied))
- return_0;
-
- if (!archive(vg))
- return_0;
-
- if (!(metadata_lv = alloc_pool_metadata(pool_lv, metadata_name,
- lp->read_ahead, lp->stripes,
- lp->stripe_size,
- lp->pool_metadata_extents,
- lp->alloc, lp->pvh)))
- return_0;
- } else {
- if (!deactivate_lv(cmd, metadata_lv)) {
- log_error("Aborting. Failed to deactivate %s.",
- display_lvname(metadata_lv));
- return 0;
- }
-
- if (!archive(vg))
- return_0;
-
- /* Swap normal LV with pool's metadata LV ? */
- if (lv_is_pool(pool_lv)) {
- /* Swap names between old and new metadata LV */
- seg = first_seg(pool_lv);
- if (!detach_pool_metadata_lv(seg, &pool_metadata_lv))
- return_0;
- old_name = metadata_lv->name;
- if (!lv_rename_update(cmd, metadata_lv, "pvmove_tmeta", 0))
- return_0;
- if (!lv_rename_update(cmd, pool_metadata_lv, old_name, 0))
- return_0;
-
- goto mda_write;
- }
-
- if (zero_metadata) {
- metadata_lv->status |= LV_TEMPORARY;
- if (!activate_lv_local(cmd, metadata_lv)) {
- log_error("Aborting. Failed to activate metadata lv.");
- return 0;
- }
-
- if (!wipe_lv(metadata_lv, (struct wipe_params) { .do_zero = 1 })) {
- log_error("Aborting. Failed to wipe metadata lv.");
- return 0;
- }
- }
- }
-
- /* We are changing target type, so deactivate first */
- if (!deactivate_lv(cmd, metadata_lv)) {
- log_error("Aborting. Failed to deactivate metadata lv. "
- "Manual intervention required.");
- return 0;
- }
-
- if (!deactivate_lv(cmd, pool_lv)) {
- log_error("Aborting. Failed to deactivate logical volume %s.",
- display_lvname(pool_lv));
- return 0;
- }
-
- data_lv = pool_lv;
- old_name = data_lv->name; /* Use for pool name */
- /*
- * Since we wish to have underlaying devs to match _[ct]data
- * rename data LV to match pool LV subtree first,
- * also checks for visible LV.
- */
- /* FIXME: any more types prohibited here? */
- if (!lv_rename_update(cmd, data_lv, data_name, 0))
- return_0;
-
- if (!(pool_lv = lv_create_empty(old_name, NULL,
- ((segtype_is_cache_pool(lp->segtype)) ?
- CACHE_POOL : THIN_POOL) |
- VISIBLE_LV | LVM_READ | LVM_WRITE,
- ALLOC_INHERIT, vg))) {
- log_error("Creation of pool LV failed.");
- return 0;
- }
-
- /* Allocate a new pool segment */
- if (!(seg = alloc_lv_segment(lp->segtype, pool_lv, 0, data_lv->le_count,
- pool_lv->status, 0, NULL, 1,
- data_lv->le_count, 0, 0, 0, NULL)))
- return_0;
-
- /* Add the new segment to the layer LV */
- dm_list_add(&pool_lv->segments, &seg->list);
- pool_lv->le_count = data_lv->le_count;
- pool_lv->size = data_lv->size;
-
- if (!attach_pool_data_lv(seg, data_lv))
- return_0;
-
- /*
- * Create a new lock for a thin pool LV. A cache pool LV has no lock.
- * Locks are removed from existing LVs that are being converted to
- * data and meta LVs (they are unlocked and deleted below.)
- */
- if (is_lockd_type(vg->lock_type)) {
- if (segtype_is_cache_pool(lp->segtype)) {
- data_lv->lock_args = NULL;
- metadata_lv->lock_args = NULL;
- } else {
- data_lv->lock_args = NULL;
- metadata_lv->lock_args = NULL;
-
- if (!strcmp(vg->lock_type, "sanlock"))
- pool_lv->lock_args = "pending";
- else if (!strcmp(vg->lock_type, "dlm"))
- pool_lv->lock_args = "dlm";
- /* The lock_args will be set in vg_write(). */
- }
- }
-
- /* FIXME: revert renamed LVs in fail path? */
- /* FIXME: any common code with metadata/thin_manip.c extend_pool() ? */
-
- seg->transaction_id = 0;
-
-mda_write:
- seg->chunk_size = lp->chunk_size;
- seg->discards = lp->discards;
- seg->zero_new_blocks = lp->zero ? 1 : 0;
-
- if (lp->cache_mode &&
- !cache_set_cache_mode(seg, lp->cache_mode))
- return_0;
-
- if ((lp->policy_name || lp->policy_settings) &&
- !cache_set_policy(seg, lp->policy_name, lp->policy_settings))
- return_0;
-
- /* Rename deactivated metadata LV to have _tmeta suffix */
- /* Implicit checks if metadata_lv is visible */
- if (lp->pool_metadata_name &&
- !lv_rename_update(cmd, metadata_lv, metadata_name, 0))
- return_0;
-
- if (!attach_pool_metadata_lv(seg, metadata_lv))
- return_0;
-
- if (!handle_pool_metadata_spare(vg, metadata_lv->le_count,
- lp->pvh, lp->poolmetadataspare))
- return_0;
-
- if (!vg_write(vg) || !vg_commit(vg))
- return_0;
-
- if (seg->zero_new_blocks &&
- seg->chunk_size >= DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE * 2)
- log_warn("WARNING: Pool zeroing and large %s chunk size slows down "
- "provisioning.", display_size(cmd, seg->chunk_size));
-
- if (activate_pool && !lockd_lv(cmd, pool_lv, "ex", LDLV_PERSISTENT)) {
- log_error("Failed to lock pool LV %s.", display_lvname(pool_lv));
- goto out;
- }
-
- if (activate_pool &&
- !activate_lv_excl(cmd, pool_lv)) {
- log_error("Failed to activate pool logical volume %s.",
- display_lvname(pool_lv));
- /* Deactivate subvolumes */
- if (!deactivate_lv(cmd, seg_lv(seg, 0)))
- log_error("Failed to deactivate pool data logical volume %s.",
- display_lvname(seg_lv(seg, 0)));
- if (!deactivate_lv(cmd, seg->metadata_lv))
- log_error("Failed to deactivate pool metadata logical volume %s.",
- display_lvname(seg->metadata_lv));
- goto out;
- }
-
- r = 1;
- lp->pool_data_lv = pool_lv;
-
-out:
- backup(vg);
-
- if (r)
- log_print_unless_silent("Converted %s to %s pool.",
- display_lvname(pool_lv),
- (segtype_is_cache_pool(lp->segtype)) ?
- "cache" : "thin");
-
- /*
- * Unlock and free the locks from existing LVs that became pool data
- * and meta LVs.
- */
- if (lockd_data_name) {
- if (!lockd_lv_name(cmd, vg, lockd_data_name, &lockd_data_id, lockd_data_args, "un", LDLV_PERSISTENT))
- log_error("Failed to unlock pool data LV %s/%s", vg->name, lockd_data_name);
- lockd_free_lv(cmd, vg, lockd_data_name, &lockd_data_id, lockd_data_args);
- }
-
- if (lockd_meta_name) {
- if (!lockd_lv_name(cmd, vg, lockd_meta_name, &lockd_meta_id, lockd_meta_args, "un", LDLV_PERSISTENT))
- log_error("Failed to unlock pool metadata LV %s/%s", vg->name, lockd_meta_name);
- lockd_free_lv(cmd, vg, lockd_meta_name, &lockd_meta_id, lockd_meta_args);
- }
-
- return r;
-#if 0
-revert_new_lv:
- /* TBD */
- if (!lp->pool_metadata_lv_name) {
- if (!deactivate_lv(cmd, metadata_lv)) {
- log_error("Failed to deactivate metadata lv.");
- return 0;
- }
- if (!lv_remove(metadata_lv) || !vg_write(vg) || !vg_commit(vg))
- log_error("Manual intervention may be required to remove "
- "abandoned LV(s) before retrying.");
- else
- backup(vg);
- }
-
- return 0;
-#endif
-}
-
static int _lvconvert_swap_pool_metadata(struct cmd_context *cmd,
struct logical_volume *lv,
struct logical_volume *metadata_lv)
@@ -3673,42 +3221,6 @@ revert_new_lv:
#endif
}
-/*
- * Convert origin into a cache LV by attaching a cache pool.
- */
-static int _lvconvert_cache(struct cmd_context *cmd,
- struct logical_volume *origin_lv,
- struct lvconvert_params *lp)
-{
- struct logical_volume *pool_lv = lp->pool_data_lv;
- struct logical_volume *cache_lv;
-
- if (!validate_lv_cache_create_pool(pool_lv))
- return_0;
-
- if (!archive(origin_lv->vg))
- return_0;
-
- if (!(cache_lv = lv_cache_create(pool_lv, origin_lv)))
- return_0;
-
- if (!cache_set_cache_mode(first_seg(cache_lv), lp->cache_mode))
- return_0;
-
- if (!cache_set_policy(first_seg(cache_lv), lp->policy_name, lp->policy_settings))
- return_0;
-
- cache_check_for_warns(first_seg(cache_lv));
-
- if (!lv_update_and_reload(cache_lv))
- return_0;
-
- log_print_unless_silent("Logical volume %s is now cached.",
- display_lvname(cache_lv));
-
- return 1;
-}
-
static int _lvconvert_to_cache_vol(struct cmd_context *cmd,
struct logical_volume *lv,
struct logical_volume *cachepool_lv)
@@ -3750,919 +3262,6 @@ static int _lvconvert_to_cache_vol(struct cmd_context *cmd,
return 1;
}
-/*
- * 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.
- */
-
-/*
- * Separate a COW snapshot LV from its origin.
- * lvconvert --splitsnapshot LV
- */
-static int _convert_cow_snapshot_splitsnapshot(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_splitsnapshot(cmd, lv);
-}
-
-/*
- * Merge a COW snapshot LV into its origin.
- * lvconvert --merge LV
- */
-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); */
-}
-
-/*
- * Merge a snapshot thin LV into its origin.
- * lvconvert --merge LV
- */
-
-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);
-}
-
-/*
- * Split and preserve a cache pool from the data portion of a thin pool LV.
- * lvconvert --splitcache LV
- */
-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 0;
- }
-
- /* return _lvconvert_split_cached(cmd, sublv1); */
- return 0;
-}
-
-/*
- * Split and remove a cache pool from the data portion of a thin pool LV.
- * lvconvert --uncache LV
- */
-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 0;
- }
-
- /* return _lvconvert_uncache(cmd, sublv1, lp); */
- return 0;
-}
-
-/*
- * Convert the data portion of a thin pool LV to a cache LV.
- * lvconvert --type cache LV
- *
- * Required options:
- * --cachepool LV
- *
- * Auxiliary operation:
- * Converts the --cachepool arg to a cache pool if it is not already.
- *
- * Alternate syntax:
- * lvconvert --cache LV
- */
-static int _convert_thin_pool_cache(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- /* lvconvert --type 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 0;
- }
-
- /* Do we need to grab the tdata sub LV to pass on? */
-
- return _lvconvert_cache(cmd, lv, lp);
-}
-
-/*
- * Replace the metadata LV in a thin pool LV.
- * lvconvert --poolmetadata NewLV --thinpool LV
- * FIXME: this will change so --swap-poolmetadata defines the operation.
- * FIXME: should be lvconvert --swap-poolmetadata NewLV LV
- */
-static int _convert_thin_pool_swapmetadata(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_pool(cmd, lv, lp);
-}
-
-/*
- * Split and preserve a cache pool from a cache LV.
- * lvconvert --splitcache LV
- */
-static int _convert_cache_volume_splitcache(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- /* return _lvconvert_split_cached(cmd, lv); */
- return 0;
-}
-
-/*
- * Split and remove a cache pool from a cache LV.
- * lvconvert --uncache 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); */
- return 0;
-}
-
-/*
- * Split images from the raid1|mirror origin of a cache LV and use them to create a new LV.
- * lvconvert --splitmirrors Number LV
- *
- * Required options:
- * --trackchanges | --name Name
- */
-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 0;
-}
-
-/*
- * Convert a cache LV to a thin pool (using the cache LV for thin pool data).
- * lvconvert --type thin-pool LV
- *
- * Convert a cache LV to a thin volume with cached external origin using given
- * thinpool tpLV (when not yet Thinpool convert it to thin-pool first).
- * Conversion is 2-step process in this case.
- * Only writethrough cacheLV can be converted as external origin is read-only.
- * lvconvert --thin cacheLV --thinpool tpLV
- *
- * Alternate syntax:
- * This is equivalent to above, but not preferred because it's ambiguous and inconsistent.
- * lvconvert --thinpool LV
- */
-static int _convert_cache_volume_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- int is_clean;
- const struct lv_segment *pool_seg;
-
- if (!_lvconvert_pool(cmd, lv, lp))
- return_0;
-
- if (lv_is_cache(lv) && !lv_is_pool_data(lv)) {
- pool_seg = first_seg(first_seg(lv)->pool_lv);
- if (pool_seg->cache_mode != CACHE_MODE_WRITETHROUGH) {
- log_error("Cannot convert cache volume %s with %s cache mode to external origin.",
- display_lvname(lv),
- get_cache_mode_name(pool_seg));
- log_error("To proceed, run 'lvchange --cachemode writethrough %s'.",
- display_lvname(lv));
- return 0;
- }
-
- if (!lv_cache_wait_for_clean(lv, &is_clean))
- return_0;
-
- if (!is_clean) {
- log_error("Cache %s is not clean, refusing to convert to external origin.",
- display_lvname(lv));
- return 0;
- }
-
- if (!_lvconvert_thin(cmd, lv, lp))
- return_0;
- }
-
- return 1;
-}
-
-/*
- * Convert/Recombine cacheLV to be an origin for snapshot
- * lvconvert --type snapshot cacheLV snapshotLV
- */
-static int _convert_cache_volume_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_snapshot(cmd, lv, lp->origin_name);
-}
-
-/*
- * Split a cache volume from a cache pool LV.
- * lvconvert --splitcache LV
- */
-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 0;
- }
-
- if (!lv_is_cache(sublv1)) {
- log_error("Sub LV %s must be cache.", display_lvname(sublv1));
- return 0;
- }
-
- /* return _lvconvert_split_cached(cmd, sublv1); */
- return 0;
-}
-
-/*
- * Replace the metadata LV in a cache pool LV.
- * lvconvert --poolmetadata NewLV --cachepool LV
- * FIXME: this will change so --swap-poolmetadata defines the operation.
- * FIXME: should be lvconvert --swap-poolmetadata NewLV LV
- */
-static int _convert_cache_pool_swapmetadata(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_pool(cmd, lv, lp);
-}
-
-/*
- * Change the number of images in a mirror LV.
- * lvconvert --mirrors Number LV
- */
-static int _convert_mirror_number(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_mirrors(cmd, lv, lp);
-}
-
-/*
- * Split images from a mirror LV and use them to create a new LV.
- * lvconvert --splitmirrors Number LV
- *
- * Required options:
- * --name Name
- */
-
-static int _convert_mirror_splitmirrors(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_mirrors(cmd, lv, lp);
-}
-
-/*
- * Change the type of log used by a mirror LV.
- * lvconvert --mirrorlog Type LV
- */
-static int _convert_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_mirrors(cmd, lv, lp);
-}
-
-/*
- * Convert mirror LV to linear LV.
- * lvconvert --type linear LV
- *
- * Alternate syntax:
- * lvconvert --mirrors 0 LV
- */
-static int _convert_mirror_linear(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_mirrors(cmd, lv, lp);
-}
-
-/*
- * Convert mirror LV to raid1 LV.
- * lvconvert --type raid1 LV
- */
-static int _convert_mirror_raid(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_raid(lv, lp);
-}
-
-/*
- * Change the number of images in a raid1 LV.
- * lvconvert --mirrors Number LV
- */
-static int _convert_raid_number(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_raid(lv, lp);
-}
-
-/*
- * Split images from a raid1 LV and use them to create a new LV.
- * lvconvert --splitmirrors Number LV
- *
- * Required options:
- * --trackchanges | --name Name
- */
-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);
-}
-
-/*
- * Merge a raid1 LV into originalLV if the raid1 LV was
- * previously split from the originalLV using --trackchanges.
- * lvconvert --merge LV
- */
-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);
-}
-
-/*
- * Combine a raid* LV with a snapshot LV that was previously
- * split from the raid* LV using --splitsnapshot.
- * lvconvert --type snapshot LV SnapshotLV
- *
- * Alternate syntax:
- * lvconvert --snapshot LV SnapshotLV
- */
-static int _convert_raid_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_snapshot(cmd, lv, lp->origin_name);
-}
-
-/*
- * Convert a raid* LV to a thin LV with an external origin.
- * lvconvert --type thin LV
- *
- * Required options:
- * --thinpool LV
- *
- * Auxiliary operation:
- * Converts the --thinpool arg to a thin pool if it is not already.
- *
- * Alternate syntax:
- * lvconvert --thin LV
- */
-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 0;
- }
-
- return _lvconvert_thin(cmd, lv, lp);
-}
-
-/*
- * Convert a raid* LV to a cache LV.
- * lvconvert --type cache LV
- *
- * Required options:
- * --cachepool LV
- *
- * Auxiliary operation:
- * Converts the --cachepool arg to a cache pool if it is not already.
- *
- * Alternate syntax:
- * lvconvert --cache LV
- */
-static int _convert_raid_cache(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- /* lvconvert --type 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 0;
- }
-
- return _lvconvert_cache(cmd, lv, lp);
-}
-
-/*
- * Convert a raid* LV to a thin-pool LV.
- * lvconvert --type thin-pool LV
- *
- * Alternate syntax:
- * This is equivalent to above, but not preferred because it's ambiguous and inconsistent.
- * lvconvert --thinpool LV
- */
-static int _convert_raid_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_pool(cmd, lv, lp);
-}
-
-/*
- * Convert a raid* LV to cache-pool LV.
- * lvconvert --type cache-pool LV
- */
-static int _convert_raid_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_pool(cmd, lv, lp);
-}
-
-/*
- * Convert a raid* LV to use a different raid level.
- * lvconvert --type raid* LV
- */
-static int _convert_raid_raid(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_raid(lv, lp);
-}
-
-/*
- * Convert a raid* LV to a mirror LV.
- * lvconvert --type mirror LV
- */
-static int _convert_raid_mirror(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_raid(lv, lp);
-}
-
-/*
- * Convert a raid* LV to a striped LV.
- * lvconvert --type striped LV
- */
-static int _convert_raid_striped(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_raid(lv, lp);
-}
-
-/*
- * Convert a raid* LV to a linear LV.
- * lvconvert --type linear LV
- */
-static int _convert_raid_linear(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_raid(lv, lp);
-}
-
-/*
- * Merge a striped/linear LV into a raid1 LV if the striped/linear LV was
- * previously split from the raid1 LV using --trackchanges.
- * lvconvert --merge LV
- */
-static int _convert_striped_merge(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_raid(lv, lp);
-}
-
-/*
- * Combine a linear/striped LV with a snapshot LV that was previously
- * split from the linear/striped LV using --splitsnapshot.
- * lvconvert --type snapshot LV SnapshotLV
- *
- * Alternate syntax:
- * lvconvert --snapshot LV SnapshotLV
- */
-static int _convert_striped_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_snapshot(cmd, lv, lp->origin_name);
-}
-
-/*
- * Convert a striped/linear LV to a thin LV with an external origin.
- * lvconvert --type thin LV
- *
- * Required options:
- * --thinpool LV
- *
- * Auxiliary operation:
- * Converts the --thinpool arg to a thin pool if it is not already.
- *
- * Alternate syntax:
- * lvconvert --thin LV
- */
-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("Conversion of --thinpool arg to type thin-pool failed.");
- return 0;
- }
-
- return _lvconvert_thin(cmd, lv, lp);
-}
-
-/*
- * Convert a striped/linear LV to a cache LV.
- * lvconvert --type cache LV
- *
- * Required options:
- * --cachepool LV
- *
- * Auxiliary operation:
- * Converts the --cachepool arg to a cache pool if it is not already.
- *
- * Alternate syntax:
- * lvconvert --cache LV
- */
-
-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("Conversion of --cachepool arg to type cache-pool failed.");
- return 0;
- }
-
- return _lvconvert_cache(cmd, lv, lp);
-}
-
-/*
- * Convert a striped/linear LV to a thin-pool LV.
- * lvconvert --type thin-pool LV
- *
- * Alternate syntax:
- * This is equivalent to above, but not preferred because it's ambiguous and inconsistent.
- * lvconvert --thinpool LV
- */
-static int _convert_striped_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_pool(cmd, lv, lp);
-}
-
-/*
- * Convert a striped/linear LV to a cache-pool LV.
- * lvconvert --type cache-pool LV
- */
-static int _convert_striped_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_pool(cmd, lv, lp);
-}
-
-/*
- * Convert a striped/linear LV to a mirror LV.
- * lvconvert --type mirror LV
- *
- * Required options:
- * --mirrors Number
- *
- * Alternate syntax:
- * This is equivalent to above when global/mirror_segtype_default="mirror".
- * lvconvert --mirrors Number LV
- */
-static int _convert_striped_mirror(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_mirrors(cmd, lv, lp);
-}
-
-/*
- * Convert a striped/linear LV to a raid* LV.
- * lvconvert --type raid* LV
- *
- * Required options:
- * --mirrors Number
- *
- * Alternate syntax:
- * This is equivalent to above when global/mirror_segtype_default="raid1".
- * lvconvert --mirrors Number LV
- */
-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);
-
- /* FIXME: add --merge-snapshot to make this distinct from --merge-mirror. */
- 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 0;
-}
-
-static int _convert_thin_volume(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- /* FIXME: add --merge-snapshot to make this distinct from --merge-mirror. */
- 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 0;
-}
-
-static int _convert_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- if (lp->splitcache)
- return _convert_thin_pool_splitcache(cmd, lv, lp);
-
- if (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);
-
- /* FIXME: swapping the thin pool metadata LV needs a specific option like --swapmetadata */
- if (arg_is_set(cmd, poolmetadata_ARG))
- return _convert_thin_pool_swapmetadata(cmd, lv, lp);
-
- /* FIXME: add --swapmetadata to list of permitted operations. */
-
- 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"
- " --type cache (operates on data sub LV)\n"
- " --repair\n");
- return 0;
-}
-
-static int _convert_cache_volume(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- if (lp->splitcache)
- return _convert_cache_volume_splitcache(cmd, lv, lp);
-
- if (lp->split)
- return _convert_cache_volume_splitcache(cmd, lv, lp);
-
- if (lp->uncache)
- return _convert_cache_volume_uncache(cmd, lv, lp);
-
- if (arg_is_set(cmd, splitmirrors_ARG))
- return _convert_cache_volume_splitmirrors(cmd, lv, lp);
-
- if (!strcmp(lp->type_str, SEG_TYPE_NAME_THIN_POOL) ||
- arg_is_set(cmd, thinpool_ARG))
- return _convert_cache_volume_thin_pool(cmd, lv, lp);
-
- if (!strcmp(lp->type_str, SEG_TYPE_NAME_SNAPSHOT) ||
- arg_is_set(cmd, snapshot_ARG))
- return _convert_cache_volume_snapshot(cmd, lv, lp);
-
- /* The --thinpool alternative for --type thin-pool is not preferred, so not shown. */
-
- 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 0;
-}
-
-static int _convert_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- if (lp->splitcache)
- return _convert_cache_pool_splitcache(cmd, lv, lp);
-
- if (lp->split)
- return _convert_cache_pool_splitcache(cmd, lv, lp);
-
- /* FIXME: swapping the cache pool metadata LV needs a specific option like --swapmetadata */
- if (arg_is_set(cmd, poolmetadata_ARG))
- return _convert_cache_pool_swapmetadata(cmd, lv, lp);
-
- /* FIXME: add --swapmetadata to list of permitted operations. */
-
- 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 0;
-}
-
-static int _convert_mirror(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- if (arg_is_set(cmd, mirrors_ARG))
- return _convert_mirror_number(cmd, lv, lp);
-
- if (arg_is_set(cmd, splitmirrors_ARG))
- return _convert_mirror_splitmirrors(cmd, lv, lp);
-
- if (arg_is_set(cmd, mirrorlog_ARG) || arg_is_set(cmd, corelog_ARG))
- return _convert_mirror_log(cmd, lv, lp);
-
- if (_linear_type_requested(lp->type_str))
- return _convert_mirror_linear(cmd, lv, lp);
-
- if (segtype_is_raid(lp->segtype))
- return _convert_mirror_raid(cmd, lv, lp);
-
- log_error("Unknown operation on mirror LV %s.", display_lvname(lv));
- return 0;
-}
-
-static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- if (arg_is_set(cmd, mirrors_ARG))
- return _convert_raid_number(cmd, lv, lp);
-
- if (arg_is_set(cmd, splitmirrors_ARG))
- return _convert_raid_splitmirrors(cmd, lv, lp);
-
- if (segtype_is_raid(lp->segtype))
- return _convert_raid_raid(cmd, lv, lp);
-
- if (segtype_is_mirror(lp->segtype))
- return _convert_raid_mirror(cmd, lv, lp);
-
- if (!strcmp(lp->type_str, SEG_TYPE_NAME_STRIPED))
- return _convert_raid_striped(cmd, lv, lp);
-
- if (_linear_type_requested(lp->type_str))
- return _convert_raid_linear(cmd, lv, lp);
-
- log_error("Unknown operation on raid LV %s.", display_lvname(lv));
- return 0;
-}
-
-static int _convert_striped(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- const char *mirrors_type = find_config_tree_str(cmd, global_mirror_segtype_default_CFG, NULL);
-
- if (!strcmp(lp->type_str, SEG_TYPE_NAME_MIRROR))
- return _convert_striped_mirror(cmd, lv, lp);
-
- if (segtype_is_raid(lp->segtype))
- return _convert_striped_raid(cmd, lv, lp);
-
- /* --mirrors can mean --type mirror or --type raid1 depending on config setting. */
-
- if (arg_is_set(cmd, mirrors_ARG) && mirrors_type && !strcmp(mirrors_type, SEG_TYPE_NAME_MIRROR))
- return _convert_striped_mirror(cmd, lv, lp);
-
- if (arg_is_set(cmd, mirrors_ARG) && mirrors_type && !strcmp(mirrors_type, SEG_TYPE_NAME_RAID1))
- return _convert_striped_raid(cmd, lv, lp);
-
- log_error("Unknown operation on striped or linear LV %s.", display_lvname(lv));
- return 0;
-}
-
-/*
- * Main entry point.
- * lvconvert performs a specific <operation> on a specific <lv_type>.
- *
- * The <operation> is specified by command line args.
- * The <lv_type> is found using lv_is_foo(lv) functions.
- *
- * for each lvtype,
- * _convert_lvtype();
- * for each arg_is_set(operation)
- * _convert_lvtype_operation();
- *
- * FIXME: this code (identifying/routing each unique operation through
- * _convert_lvtype_op) was designed to work based on the new type that
- * the user entered after --type, not the final segment type in lp->type_str.
- * Sometimes the two differ because tricks are played with lp->type_str.
- * So, when the use of arg_type_str(type_ARG) here was replaced with
- * lp->type_str, some commands are no longer identified/routed correctly.
- */
-static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- struct lv_segment *seg = first_seg(lv);
- int ret = 0;
-
- /* Set up segtype either from type_str or else to match the existing one. */
- if (!*lp->type_str)
- lp->segtype = seg->segtype;
- else if (!(lp->segtype = get_segtype_from_string(cmd, lp->type_str)))
- goto_out;
-
- if (!strcmp(lp->type_str, SEG_TYPE_NAME_MIRROR)) {
- if (!lp->mirrors_supplied && !seg_is_raid1(seg)) {
- log_error("Conversions to --type mirror require -m/--mirrors");
- goto out;
- }
- }
-
- /* lv->segtype can't be NULL */
- if (activation() && lp->segtype->ops->target_present &&
- !lp->segtype->ops->target_present(cmd, NULL, &lp->target_attr)) {
- log_error("%s: Required device-mapper target(s) not "
- "detected in your kernel.", lp->segtype->name);
- goto out;
- }
-
- /* Process striping parameters */
- /* FIXME This is incomplete */
- if (_mirror_or_raid_type_requested(cmd, lp->type_str) || _raid0_type_requested(lp->type_str) ||
- _striped_type_requested(lp->type_str) || lp->mirrorlog || lp->corelog) {
- /* FIXME Handle +/- adjustments too? */
- if (!get_stripe_params(cmd, lp->segtype, &lp->stripes, &lp->stripe_size, &lp->stripes_supplied, &lp->stripe_size_supplied))
- goto_out;
-
- if (_raid0_type_requested(lp->type_str) || _striped_type_requested(lp->type_str))
- /* FIXME Shouldn't need to override get_stripe_params which defaults to 1 stripe (i.e. linear)! */
- /* The default keeps existing number of stripes, handled inside the library code */
- if (!arg_is_set(cmd, stripes_long_ARG))
- lp->stripes = 0;
- }
-
- if (lv_is_cache(lv))
- lv = seg_lv(first_seg(lv), 0);
-
- 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 which is caught by the test above.
- * If operations differ between striped and linear, split this case.
- */
- if (segtype_is_striped(seg->segtype) || segtype_is_linear(seg->segtype)) {
- ret = _convert_striped(cmd, lv, lp);
- goto out;
- }
-
- /*
- * 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));
-
-out:
- return ret ? ECMD_PROCESSED : ECMD_FAILED;
-}
-
static struct convert_poll_id_list* _convert_poll_id_list_create(struct cmd_context *cmd,
const struct logical_volume *lv)
{
@@ -4975,11 +3574,6 @@ int lvconvert_replace_pv_cmd(struct cmd_context *cmd, int argc, char **argv)
/*
- * snapshot-related lvconvert utilities
- */
-
-
-/*
* Merge a COW snapshot LV into its origin.
*/
@@ -5646,7 +4240,7 @@ static int _lvconvert_raid_types_single(struct cmd_context *cmd, struct logical_
lp->lv_to_poll = lv;
- ret = _lvconvert(cmd, lv, lp);
+ ret = _lvconvert_raid_types(cmd, lv, lp);
if (ret != ECMD_PROCESSED)
return_ECMD_FAILED;
@@ -5790,8 +4384,8 @@ static int _lvconvert_change_mirrorlog_single(struct cmd_context *cmd, struct lo
lp->pvh = use_pvh;
- /* FIXME: extract the mirrorlog functionality out of _lvconvert()? */
- return _lvconvert(cmd, lv, lp);
+ /* FIXME: extract the mirrorlog functionality out of _lvconvert_raid_types()? */
+ return _lvconvert_raid_types(cmd, lv, lp);
}
int lvconvert_change_mirrorlog_cmd(struct cmd_context * cmd, int argc, char **argv)
@@ -5846,8 +4440,8 @@ static int _lvconvert_split_mirror_images_single(struct cmd_context *cmd, struct
lp->pvh = use_pvh;
- /* FIXME: extract the split functionality out of _lvconvert()? */
- return _lvconvert(cmd, lv, lp);
+ /* FIXME: extract the split functionality out of _lvconvert_raid_types()? */
+ return _lvconvert_raid_types(cmd, lv, lp);
}
int lvconvert_split_mirror_images_cmd(struct cmd_context * cmd, int argc, char **argv)