1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

thin and cache: improve conversion validation

More validations before any thin or cache related conversion begins.

We allow to use and stack:

pool data: cache or raid
pool metadata: raid

pool:  linear, striped
cache: linear, striped, raid
thin(extorig): linear, origin, cow, virtual, thin
This commit is contained in:
Zdenek Kabelac 2014-09-22 14:15:13 +02:00
parent cd3345a5b0
commit 13c07c685a

View File

@ -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;