diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 62e560cd8..57975d1d5 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -2662,30 +2662,48 @@ static int _lvconvert_pool(struct cmd_context *cmd, return 0; } + 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("Cannot convert thin pool volume %s as cache pool data 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 thin 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 \"raid1\" segment type instead."); + return 0; + } + /* * Only linear, striped and raid supported. * FIXME Tidy up all these type restrictions. */ if (!lv_is_pool(pool_lv) && - (lv_is_external_origin(pool_lv) || lv_is_origin(pool_lv) || lv_is_thin_type(pool_lv) || - lv_is_mirror_type(pool_lv) || lv_is_cache_type(pool_lv) || lv_is_virtual(pool_lv) || - lv_is_cache_origin(pool_lv) || lv_is_merging_origin(pool_lv) || lv_is_merging_cow(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 (arg_is_set(cmd, cachepool_ARG) && lv_is_thin_pool(pool_lv)) { - log_error("--cachepool requires a cache pool. %s is a thin pool.", - display_lvname(pool_lv)); - return 0; - } - - if (arg_is_set(cmd, thinpool_ARG) && lv_is_cache_pool(pool_lv)) { - log_error("--thinpool requires a thin pool. %s is a cache pool.", - display_lvname(pool_lv)); - return 0; - } - 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); @@ -2694,16 +2712,15 @@ 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.", + 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_mirror(metadata_lv)) { - log_error("Mirror logical volumes cannot be used " - "for pool metadata."); - log_error("Try \"raid1\" segment type instead."); + if (!lv_is_visible(metadata_lv)) { + log_error("Can't convert internal LV %s.", + display_lvname(metadata_lv)); return 0; } @@ -2713,24 +2730,19 @@ static int _lvconvert_pool(struct cmd_context *cmd, return 0; } - 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_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)); + if (lv_is_mirror(metadata_lv)) { + log_error("Mirror logical volumes cannot be used for pool metadata."); + log_print_unless_silent("Try \"raid1\" segment type instead."); return 0; } /* FIXME Tidy up all these type restrictions. */ - if (lv_is_external_origin(metadata_lv) || lv_is_virtual(metadata_lv) || - lv_is_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)) { + 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; @@ -2748,39 +2760,21 @@ 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_mirror(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)) ? - "_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 (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", - cachemode_ARG,chunksize_ARG, discards_ARG, + cachemode_ARG, chunksize_ARG, discards_ARG, zero_ARG, poolmetadatasize_ARG, -1)) return_0; - return 1; + + 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) { @@ -2841,10 +2835,6 @@ static int _lvconvert_pool(struct cmd_context *cmd, log_error("Conversion aborted."); return 0; } - } else if (lv_is_thin_type(pool_lv)) { - log_error("Can't use thin type logical volume %s for thin pool data.", - display_lvname(pool_lv)); - return 0; } else { log_warn("WARNING: Converting logical volume %s%s%s to pool's data%s.", display_lvname(pool_lv), @@ -2869,6 +2859,19 @@ static int _lvconvert_pool(struct cmd_context *cmd, /* 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; @@ -3068,13 +3071,23 @@ static int _lvconvert_cache(struct cmd_context *cmd, return 0; } + /* We support conversion of _tdata */ + if (!lv_is_visible(origin) && !lv_is_thin_pool_data(origin)) { + log_error("Can't convert internal LV %s.", display_lvname(origin)); + return 0; + } + /* * Only linear, striped or raid supported. * FIXME Tidy up all these type restrictions. */ - if (lv_is_external_origin(origin) || lv_is_origin(origin) || lv_is_thin_type(origin) || - lv_is_mirror_type(origin) || lv_is_cache_origin(origin) || lv_is_virtual(origin) || - lv_is_cow(origin) || lv_is_merging_origin(origin) || lv_is_merging_cow(origin)) { + if (lv_is_cache_origin(origin) || + lv_is_mirror_type(origin) || + lv_is_thin_volume(origin) || lv_is_thin_pool_metadata(origin) || + lv_is_origin(origin) || lv_is_merging_origin(origin) || + lv_is_cow(origin) || lv_is_merging_cow(origin) || + lv_is_external_origin(origin) || + lv_is_virtual(origin)) { log_error("Cache is not supported with origin LV %s type.", display_lvname(origin)); return 0;