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

thin: validate usable volume for external origin

When creating external origin via 'lvcreate --type thin'
add the validation for LV being usable as external origin
since certain LVs cannot be really used this way.
Also call this function early during lvcreate cmdline arg
validation se we do not need to do unecesary operation.
This commit is contained in:
Zdenek Kabelac 2024-03-03 23:23:04 +01:00
parent 9e2870cc9f
commit 27bdd038a8
4 changed files with 47 additions and 17 deletions

View File

@ -9344,24 +9344,10 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
return NULL; return NULL;
} }
lp->virtual_extents = origin_lv->le_count; if (!validate_thin_external_origin(origin_lv, pool_lv))
return_NULL;
/* lp->virtual_extents = origin_lv->le_count;
* Check if using 'external origin' or the 'normal' snapshot
* within the same thin pool
*/
if (first_seg(origin_lv)->pool_lv != pool_lv) {
if (!thin_pool_supports_external_origin(first_seg(pool_lv), origin_lv))
return_NULL;
if (origin_lv->status & LVM_WRITE) {
log_error("Cannot use writable LV as the external origin.");
return NULL; /* FIXME conversion for inactive */
}
if (lv_is_active(origin_lv) && !lv_is_external_origin(origin_lv)) {
log_error("Cannot use active LV for the external origin.");
return NULL; /* We can't be sure device is read-only */
}
}
} }
} else if (lp->snapshot) { } else if (lp->snapshot) {
if (!lp->virtual_extents) { if (!lp->virtual_extents) {

View File

@ -896,6 +896,8 @@ int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
int validate_cache_chunk_size(struct cmd_context *cmd, uint32_t chunk_size); int validate_cache_chunk_size(struct cmd_context *cmd, uint32_t chunk_size);
int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size); int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size);
int validate_pool_chunk_size(struct cmd_context *cmd, const struct segment_type *segtype, uint32_t chunk_size); int validate_pool_chunk_size(struct cmd_context *cmd, const struct segment_type *segtype, uint32_t chunk_size);
int validate_thin_external_origin(const struct logical_volume *lv,
const struct logical_volume *pool_lv);
int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct profile *profile, int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct profile *profile,
uint32_t *chunk_size, int *chunk_size_calc_method); uint32_t *chunk_size, int *chunk_size_calc_method);
int update_thin_pool_params(struct cmd_context *cmd, int update_thin_pool_params(struct cmd_context *cmd,

View File

@ -1100,3 +1100,42 @@ uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent
{ {
return _estimate_metadata_size(data_extents, extent_size, chunk_size); return _estimate_metadata_size(data_extents, extent_size, chunk_size);
} }
/* Validates whtether the LV can be used as external origin */
int validate_thin_external_origin(const struct logical_volume *lv,
const struct logical_volume *pool_lv)
{
const char *type = NULL;
/*
* Check if using 'external origin' or the 'normal' snapshot
* within the same thin pool
*/
if (first_seg(lv)->pool_lv == pool_lv)
return 1;
if (!lv_is_visible(lv))
type = "internal";
else if (lv_is_cow(lv))
type = "snapshot";
else if (lv_is_pool(lv) || lv_is_vdo_pool(lv))
type = "pool";
else if (lv->status & LVM_WRITE)
type = "writable"; /* TODO: maybe support conversion for inactive */
if (type) {
log_error("Cannot use %s volume %s as external origin.",
type, display_lvname(lv));
return 0;
}
if (!thin_pool_supports_external_origin(first_seg(pool_lv), lv))
return_0;
if (!lv_is_external_origin(lv) && lv_is_active(lv)) {
log_error("Cannot use active LV for the external origin.");
return 0; /* We can't be sure device is read-only */
}
return 1;
}

View File

@ -1427,6 +1427,9 @@ static int _determine_snapshot_type(struct volume_group *vg,
display_lvname(pool_lv)); display_lvname(pool_lv));
return 0; return 0;
} }
if (!validate_thin_external_origin(origin_lv, pool_lv))
return_0;
} else { } else {
if (!lv_is_thin_volume(origin_lv)) { if (!lv_is_thin_volume(origin_lv)) {
if (!seg_is_thin(lp)) if (!seg_is_thin(lp))