diff options
author | Zdenek Kabelac <zkabelac@redhat.com> | 2014-10-26 18:17:40 +0100 |
---|---|---|
committer | Zdenek Kabelac <zkabelac@redhat.com> | 2014-10-26 18:37:13 +0100 |
commit | 25307e4add1e3f25cf5ae00d942df61afa46fe60 (patch) | |
tree | e6fdf11c9671bc3fc15916e673071635a47b5757 | |
parent | 618d818c0d31bbfa1ed4af2e8954c8a4b53127af (diff) | |
download | lvm2-25307e4add1e3f25cf5ae00d942df61afa46fe60.tar.gz |
pools: prefetch pool_lv and origin_lv
Load pool_lv and origin_lv at a single place and
use it for more types as they need them.
-rw-r--r-- | lib/metadata/lv_manip.c | 105 |
1 files changed, 55 insertions, 50 deletions
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 335a1bd4a..8523b58a7 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -6602,7 +6602,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, const char *new_lv_name) { struct cmd_context *cmd = vg->cmd; - uint32_t size_rest; + uint32_t size_rest, size; uint64_t status = lp->permission | VISIBLE_LV; const struct segment_type *create_segtype = lp->segtype; struct logical_volume *lv, *origin_lv = NULL; @@ -6702,18 +6702,46 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, if (seg_is_pool(lp)) status |= LVM_WRITE; /* Pool is always writable */ + else if (seg_is_cache(lp) || seg_is_thin_volume(lp)) { + /* Resolve pool volume */ + if (!lp->pool_name) { + /* Should be already checked */ + log_error(INTERNAL_ERROR "Cannot create %s volume without %s pool.", + lp->segtype->name, lp->segtype->name); + return NULL; + } - if (seg_is_cache_pool(lp) && lp->origin_name) { - /* Converting exiting origin and creating cache pool */ - if (!(origin_lv = find_lv(vg, lp->origin_name))) { - log_error("Cache origin volume %s not found in Volume group %s.", - lp->origin_name, vg->name); + if (!(pool_lv = find_lv(vg, lp->pool_name))) { + log_error("Couldn't find volume %s in Volume group %s.", + lp->pool_name, vg->name); return NULL; } + if (lv_is_locked(pool_lv)) { + log_error("Cannot use locked pool volume %s.", + display_lvname(pool_lv)); + return NULL; + } + } + + /* Resolve origin volume */ + if (lp->origin_name && + !(origin_lv = find_lv(vg, lp->origin_name))) { + log_error("Origin volume %s not found in Volume group %s.", + lp->origin_name, vg->name); + return NULL; + } + + if (origin_lv && seg_is_cache_pool(lp)) { + /* Converting exiting origin and creating cache pool */ if (!validate_lv_cache_create_origin(origin_lv)) return_NULL; + if (origin_lv->size < lp->chunk_size) { + log_error("Caching of origin cache volume smaller then chunk size is unsupported."); + return NULL; + } + /* Validate cache origin is exclusively active */ if (vg_is_clustered(origin_lv->vg) && locking_is_clustered() && @@ -6724,29 +6752,12 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, display_lvname(origin_lv)); return NULL; } - } else if (seg_is_cache(lp)) { - if (!lp->pool_name) { - log_error(INTERNAL_ERROR "Cannot create thin volume without thin pool."); - return NULL; - } - if (!(pool_lv = find_lv(vg, lp->pool_name))) { - log_error("Couldn't find volume %s in Volume group %s.", - lp->pool_name, vg->name); - return NULL; - } - + } else if (pool_lv && seg_is_cache(lp)) { if (!lv_is_cache_pool(pool_lv)) { log_error("Logical volume %s is not a cache pool.", display_lvname(pool_lv)); return NULL; } - - if (lv_is_locked(pool_lv)) { - log_error("Cannot use locked cache pool %s.", - display_lvname(pool_lv)); - return NULL; - } - /* Create cache origin for cache pool */ /* TODO: eventually support raid/mirrors with -m */ if (!(create_segtype = get_segtype_from_string(vg->cmd, "striped"))) @@ -6765,39 +6776,16 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, lp->region_size = adjusted_mirror_region_size(vg->extent_size, lp->extents, lp->region_size, 0); - } else if (seg_is_thin_volume(lp)) { - if (!lp->pool_name) { - log_error(INTERNAL_ERROR "Cannot create thin volume without thin pool."); - return NULL; - } - - if (!(pool_lv = find_lv(vg, lp->pool_name))) { - log_error("Unable to find existing pool LV %s in VG %s.", - lp->pool_name, vg->name); - return NULL; - } - + } else if (pool_lv && seg_is_thin_volume(lp)) { if (!lv_is_thin_pool(pool_lv)) { log_error("Logical volume %s is not a thin pool.", display_lvname(pool_lv)); return NULL; } - if (lv_is_locked(pool_lv)) { - log_error("Cannot use locked thin pool %s.", - display_lvname(pool_lv)); - return NULL; - } - thin_name = lp->pool_name; - if (lp->origin_name) { - if (!(origin_lv = find_lv(vg, lp->origin_name))) { - log_error("Couldn't find origin volume '%s'.", - lp->origin_name); - return NULL; - } - + if (origin_lv) { if (lv_is_locked(origin_lv)) { log_error("Snapshots of locked devices are not supported."); return NULL; @@ -6809,10 +6797,27 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, thin_name = origin_lv->name; lp->voriginextents = 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 (!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; // TODO 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) { if (!lp->voriginsize) { - if (!(origin_lv = find_lv(vg, lp->origin_name))) { + if (!origin_lv) { log_error("Couldn't find origin volume '%s'.", lp->origin_name); return NULL; |