1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-02 01:18:26 +03:00

thin: validate external origin size

Avoid use of external origin with size unaligned/incompatible with
thin pool chunk size, since the last chunk is not correctly provisioned
when it is overwritten.
This commit is contained in:
Zdenek Kabelac 2014-01-29 14:27:13 +01:00
parent 8074d8056a
commit 155405b0e1
6 changed files with 31 additions and 1 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.106 - 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. Avoid trying to convert single to thin pool and volume at the same time.
Add support for partitions on ZFS zvol. Add support for partitions on ZFS zvol.
Fix unwanted drop of hold flocks on forked children. Fix unwanted drop of hold flocks on forked children.

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * 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. * 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 * within the same thin pool
*/ */
if (lp->snapshot && (first_seg(org)->pool_lv != pool_lv)) { 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) { if (org->status & LVM_WRITE) {
log_error("Cannot use writable LV as the external origin."); log_error("Cannot use writable LV as the external origin.");
return 0; // TODO conversion for inactive return 0; // TODO conversion for inactive

View File

@ -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); struct logical_volume *find_pool_lv(const struct logical_volume *lv);
int pool_is_active(const struct logical_volume *pool_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 thin_pool_feature_supported(const struct logical_volume *pool_lv, int feature);
int update_pool_lv(struct logical_volume *lv, int activate); int update_pool_lv(struct logical_volume *lv, int activate);
int update_profilable_pool_params(struct cmd_context *cmd, struct profile *profile, int update_profilable_pool_params(struct cmd_context *cmd, struct profile *profile,

View File

@ -252,6 +252,27 @@ int pool_below_threshold(const struct lv_segment *pool_seg)
return 1; 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 logical_volume *find_pool_lv(const struct logical_volume *lv)
{ {
struct lv_segment *seg; struct lv_segment *seg;

View File

@ -561,6 +561,8 @@ static int _thin_add_target_line(struct dev_manager *dm,
/* Add external origin LV */ /* Add external origin LV */
if (seg->external_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) { if (seg->external_lv->size < seg->lv->size) {
/* Validate target supports smaller external origin */ /* Validate target supports smaller external origin */
if (!_thin_target_present(cmd, first_seg(seg->pool_lv), &attr) || if (!_thin_target_present(cmd, first_seg(seg->pool_lv), &attr) ||

View File

@ -2483,6 +2483,9 @@ static int _lvconvert_thinpool_external(struct cmd_context *cmd,
dm_list_init(&lvc.tags); 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"))) if (!(lvc.segtype = get_segtype_from_string(cmd, "thin")))
return_0; return_0;