diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 5d0eebfa3..e4ab1b86f 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -9344,24 +9344,10 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, return NULL; } - lp->virtual_extents = origin_lv->le_count; + if (!validate_thin_external_origin(origin_lv, pool_lv)) + return_NULL; - /* - * 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 */ - } - } + lp->virtual_extents = origin_lv->le_count; } } else if (lp->snapshot) { if (!lp->virtual_extents) { diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index c9825799b..9c372a7f0 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -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_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_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, uint32_t *chunk_size, int *chunk_size_calc_method); int update_thin_pool_params(struct cmd_context *cmd, diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c index 234241efe..fb6e99821 100644 --- a/lib/metadata/thin_manip.c +++ b/lib/metadata/thin_manip.c @@ -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); } + +/* 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; +} diff --git a/tools/lvcreate.c b/tools/lvcreate.c index c40c37b9f..8b01999ea 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -1427,6 +1427,9 @@ static int _determine_snapshot_type(struct volume_group *vg, display_lvname(pool_lv)); return 0; } + + if (!validate_thin_external_origin(origin_lv, pool_lv)) + return_0; } else { if (!lv_is_thin_volume(origin_lv)) { if (!seg_is_thin(lp))