diff --git a/WHATS_NEW b/WHATS_NEW index 3a4c7ecb0..d28ec3c39 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.106 - ==================================== + Prohibit use of external origin with size incompatible with thin pool. Avoid trying to convert single to thin pool and volume at the same time. Add support for partitions on ZFS zvol. Fix unwanted drop of hold flocks on forked children. diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 2e240fc64..a2831cf96 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -5980,6 +5980,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, * within the same thin pool */ if (lp->snapshot && (first_seg(org)->pool_lv != pool_lv)) { + if (!pool_supports_external_origin(first_seg(pool_lv), org)) + return_0; if (org->status & LVM_WRITE) { log_error("Cannot use writable LV as the external origin."); return 0; // TODO conversion for inactive diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index bdf5c9d59..1ebf69fe5 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -682,6 +682,7 @@ uint64_t extents_from_size(struct cmd_context *cmd, uint64_t size, struct logical_volume *find_pool_lv(const struct logical_volume *lv); int pool_is_active(const struct logical_volume *pool_lv); +int pool_supports_external_origin(const struct lv_segment *pool_seg, const struct logical_volume *external_lv); int thin_pool_feature_supported(const struct logical_volume *pool_lv, int feature); int update_pool_lv(struct logical_volume *lv, int activate); int update_profilable_pool_params(struct cmd_context *cmd, struct profile *profile, diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c index 1abc2f164..60e93f0ac 100644 --- a/lib/metadata/thin_manip.c +++ b/lib/metadata/thin_manip.c @@ -252,6 +252,27 @@ int pool_below_threshold(const struct lv_segment *pool_seg) return 1; } +/* + * Validate given external origin could be used with thin pool + */ +int pool_supports_external_origin(const struct lv_segment *pool_seg, const struct logical_volume *external_lv) +{ + uint32_t csize = pool_seg->chunk_size; + + if ((external_lv->size < csize) || (external_lv->size % csize)) { + /* TODO: Validate with thin feature flag once, it will be supported */ + log_error("Can't use \"%s/%s\" as external origin with \"%s/%s\" pool. " + "Size %s is not a multiple of pool's chunk size %s.", + external_lv->vg->name, external_lv->name, + pool_seg->lv->vg->name, pool_seg->lv->name, + display_size(external_lv->vg->cmd, external_lv->size), + display_size(external_lv->vg->cmd, csize)); + return 0; + } + + return 1; +} + struct logical_volume *find_pool_lv(const struct logical_volume *lv) { struct lv_segment *seg; diff --git a/lib/thin/thin.c b/lib/thin/thin.c index 0b8eaf8b5..8eaa73d78 100644 --- a/lib/thin/thin.c +++ b/lib/thin/thin.c @@ -561,6 +561,8 @@ static int _thin_add_target_line(struct dev_manager *dm, /* Add external origin LV */ if (seg->external_lv) { + if (!pool_supports_external_origin(first_seg(seg->pool_lv), seg->external_lv)) + return_0; if (seg->external_lv->size < seg->lv->size) { /* Validate target supports smaller external origin */ if (!_thin_target_present(cmd, first_seg(seg->pool_lv), &attr) || diff --git a/tools/lvconvert.c b/tools/lvconvert.c index ffbf76877..2ab41155f 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -2483,6 +2483,9 @@ static int _lvconvert_thinpool_external(struct cmd_context *cmd, dm_list_init(&lvc.tags); + if (!pool_supports_external_origin(first_seg(pool_lv), external_lv)) + return_0; + if (!(lvc.segtype = get_segtype_from_string(cmd, "thin"))) return_0;