mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +03:00
thin: add missing 64KB rounding
When chunk size needs to be estimated, the code missed to round to proper 64kb boundaries (or power of 2 for older thin pool driver). So for some data and metadata size (i.e. 10GB and 4MB) it resulted in incorrect chunk size (not being a multiple of 64KB) Fix it by adding proper rounding and also use 1 routine for 2 places where the same calculation is made. Fix also incorrect printed warning that has used 'ffs()' (which returns first 'least significant' bit in word) and it was not really giving any useful size info and replace it with properly estimated chunk size.
This commit is contained in:
parent
13e2049c32
commit
2de11c9e9e
@ -1,5 +1,6 @@
|
||||
Version 2.02.114 -
|
||||
=====================================
|
||||
Fix missing rounding to 64KB when estimating optimal thin pool chunk size.
|
||||
Fix typo in clvmd initscript causing CLVMD_STOP_TIMEOUT variable to be ignored.
|
||||
Fix size in pvresize "Resizing to ..." verbose msg to show proper result size.
|
||||
|
||||
|
@ -394,6 +394,33 @@ int update_pool_lv(struct logical_volume *lv, int activate)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Estimate thin pool chunk size from data and metadata size (in sector units) */
|
||||
static size_t _estimate_chunk_size(uint64_t data_size, uint64_t metadata_size, int attr)
|
||||
{
|
||||
/*
|
||||
* nr_pool_blocks = data_size / metadata_size
|
||||
* chunk_size = nr_pool_blocks * 64b / sector_size
|
||||
*/
|
||||
size_t chunk_size = data_size / (metadata_size * (SECTOR_SIZE / 64));
|
||||
|
||||
if (attr & THIN_FEATURE_BLOCK_SIZE) {
|
||||
/* Round up to 64KB */
|
||||
chunk_size += DM_THIN_MIN_DATA_BLOCK_SIZE - 1;
|
||||
chunk_size &= ~(size_t)(DM_THIN_MIN_DATA_BLOCK_SIZE - 1);
|
||||
} else {
|
||||
/* Round up to nearest power of 2 */
|
||||
chunk_size--;
|
||||
chunk_size |= chunk_size >> 1;
|
||||
chunk_size |= chunk_size >> 2;
|
||||
chunk_size |= chunk_size >> 4;
|
||||
chunk_size |= chunk_size >> 8;
|
||||
chunk_size |= chunk_size >> 16;
|
||||
chunk_size++;
|
||||
}
|
||||
|
||||
return chunk_size;
|
||||
}
|
||||
|
||||
int update_thin_pool_params(const struct segment_type *segtype,
|
||||
struct volume_group *vg,
|
||||
unsigned attr, int passed_args,
|
||||
@ -465,18 +492,20 @@ int update_thin_pool_params(const struct segment_type *segtype,
|
||||
display_size(cmd, *chunk_size));
|
||||
} else if (pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) {
|
||||
/* Suggest bigger chunk size */
|
||||
estimate_chunk_size = (uint64_t) pool_data_extents * extent_size /
|
||||
(DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2 * (SECTOR_SIZE / UINT64_C(64)));
|
||||
estimate_chunk_size =
|
||||
_estimate_chunk_size((uint64_t) pool_data_extents * extent_size,
|
||||
(DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2), attr);
|
||||
log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.",
|
||||
display_size(cmd, UINT64_C(1) << (ffs(estimate_chunk_size) + 1)));
|
||||
display_size(cmd, estimate_chunk_size));
|
||||
}
|
||||
|
||||
/* Round up to extent size silently */
|
||||
if (pool_metadata_size % extent_size)
|
||||
pool_metadata_size += extent_size - pool_metadata_size % extent_size;
|
||||
} else {
|
||||
estimate_chunk_size = (uint64_t) pool_data_extents * extent_size /
|
||||
(pool_metadata_size * (SECTOR_SIZE / UINT64_C(64)));
|
||||
estimate_chunk_size =
|
||||
_estimate_chunk_size((uint64_t) pool_data_extents * extent_size,
|
||||
pool_metadata_size, attr);
|
||||
if (estimate_chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE)
|
||||
estimate_chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
|
||||
else if (estimate_chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE)
|
||||
|
@ -261,4 +261,20 @@ lvcreate -L10G --chunksize 256 -T $vg/pool1
|
||||
lvcreate -L60G --chunksize 1024 -T $vg/pool2
|
||||
check lv_field $vg/pool1_tmeta size "2.50m"
|
||||
check lv_field $vg/pool2_tmeta size "3.75m"
|
||||
lvremove -ff $vg
|
||||
|
||||
# Block size of multiple 64KB needs >= 1.4
|
||||
if aux have_thin 1 4 0 ; then
|
||||
# Test chunk size is rounded to 64KB boundary
|
||||
lvcreate -L10G --poolmetadatasize 4M -T $vg/pool
|
||||
check lv_field $vg/pool chunk_size "192.00k"
|
||||
fi
|
||||
# Old thinpool target required rounding to power of 2
|
||||
aux lvmconf "global/thin_disabled_features = [ \"block_size\" ]"
|
||||
lvcreate -L10G --poolmetadatasize 4M -T $vg/pool_old
|
||||
check lv_field $vg/pool_old chunk_size "256.00k"
|
||||
lvremove -ff $vg
|
||||
# reset
|
||||
#aux lvmconf "global/thin_disabled_features = []"
|
||||
|
||||
vgremove -ff $vg
|
||||
|
Loading…
Reference in New Issue
Block a user