summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZdenek Kabelac <zkabelac@redhat.com>2014-10-26 18:17:40 +0100
committerZdenek Kabelac <zkabelac@redhat.com>2014-10-26 18:37:13 +0100
commit25307e4add1e3f25cf5ae00d942df61afa46fe60 (patch)
treee6fdf11c9671bc3fc15916e673071635a47b5757
parent618d818c0d31bbfa1ed4af2e8954c8a4b53127af (diff)
downloadlvm2-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.c105
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;