mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
thin: enforce there is some free space in thin pool metadata
Unconditionally guard there is at least 1/4 of metadata volume free (<16Mib) or 4MiB - whichever value is smaller. In case there is not enough free space do not let operation proceed and recommend thin-pool metadata resize (in case user has not enabled autoresize, manual 'lvextend --poolmetadatasize' is needed).
This commit is contained in:
parent
776d5a25b4
commit
c2c2721d00
@ -1,5 +1,6 @@
|
||||
Version 2.02.166 -
|
||||
=====================================
|
||||
Enforce 4MiB or 25% metadata free space for thin pool operations.
|
||||
Fix lock-holder device for thin pool with inactive thin volumes.
|
||||
Use --alloc normal for mirror logs even if the mimages were stricter.
|
||||
Use O_DIRECT to gather metadata in lvmdump.
|
||||
|
@ -4515,6 +4515,7 @@ static int _lvresize_adjust_policy(const struct logical_volume *lv,
|
||||
{
|
||||
struct cmd_context *cmd = lv->vg->cmd;
|
||||
dm_percent_t percent;
|
||||
dm_percent_t min_threshold;
|
||||
int policy_threshold, policy_amount;
|
||||
|
||||
*amount = *meta_amount = 0;
|
||||
@ -4562,7 +4563,10 @@ static int _lvresize_adjust_policy(const struct logical_volume *lv,
|
||||
if (!lv_thin_pool_percent(lv, 1, &percent))
|
||||
return_0;
|
||||
|
||||
*meta_amount = _adjust_amount(percent, policy_threshold, policy_amount);
|
||||
/* Resize below the minimal usable value */
|
||||
min_threshold = pool_metadata_min_threshold(first_seg(lv)) / DM_PERCENT_1;
|
||||
*meta_amount = _adjust_amount(percent, (min_threshold < policy_threshold) ?
|
||||
min_threshold : policy_threshold, policy_amount);
|
||||
|
||||
if (!lv_thin_pool_percent(lv, 0, &percent))
|
||||
return_0;
|
||||
|
@ -501,6 +501,7 @@ int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type,
|
||||
int lv_is_merging_thin_snapshot(const struct logical_volume *lv);
|
||||
int pool_has_message(const struct lv_segment *seg,
|
||||
const struct logical_volume *lv, uint32_t device_id);
|
||||
int pool_metadata_min_threshold(const struct lv_segment *pool_seg);
|
||||
int pool_below_threshold(const struct lv_segment *pool_seg);
|
||||
int pool_check_overprovisioning(const struct logical_volume *lv);
|
||||
int create_pool(struct logical_volume *lv, const struct segment_type *segtype,
|
||||
|
@ -215,9 +215,29 @@ int thin_pool_feature_supported(const struct logical_volume *lv, int feature)
|
||||
return (attr & feature) ? 1 : 0;
|
||||
}
|
||||
|
||||
int pool_metadata_min_threshold(const struct lv_segment *pool_seg)
|
||||
{
|
||||
/*
|
||||
* Hardcoded minimal requirment for thin pool target.
|
||||
*
|
||||
* In the metadata LV there should be minimum from either 4MiB of free space
|
||||
* or at least 25% of free space, which applies when the size of thin pool's
|
||||
* metadata is less then 16MiB.
|
||||
*/
|
||||
const dm_percent_t meta_min = DM_PERCENT_1 * 25;
|
||||
dm_percent_t meta_free = dm_make_percent(((4096 * 1024) >> SECTOR_SHIFT),
|
||||
pool_seg->metadata_lv->size);
|
||||
|
||||
if (meta_min < meta_free)
|
||||
meta_free = meta_min;
|
||||
|
||||
return DM_PERCENT_100 - meta_free;
|
||||
}
|
||||
|
||||
int pool_below_threshold(const struct lv_segment *pool_seg)
|
||||
{
|
||||
dm_percent_t percent;
|
||||
dm_percent_t min_threshold = pool_metadata_min_threshold(pool_seg);
|
||||
dm_percent_t threshold = DM_PERCENT_1 *
|
||||
find_config_tree_int(pool_seg->lv->vg->cmd, activation_thin_pool_autoextend_threshold_CFG,
|
||||
lv_config_profile(pool_seg->lv));
|
||||
@ -226,7 +246,7 @@ int pool_below_threshold(const struct lv_segment *pool_seg)
|
||||
if (!lv_thin_pool_percent(pool_seg->lv, 0, &percent))
|
||||
return_0;
|
||||
|
||||
if (percent > threshold) {
|
||||
if (percent > threshold || percent >= DM_PERCENT_100) {
|
||||
log_debug("Threshold configured for free data space in "
|
||||
"thin pool %s has been reached (%.2f%% >= %.2f%%).",
|
||||
display_lvname(pool_seg->lv),
|
||||
@ -239,6 +259,18 @@ int pool_below_threshold(const struct lv_segment *pool_seg)
|
||||
if (!lv_thin_pool_percent(pool_seg->lv, 1, &percent))
|
||||
return_0;
|
||||
|
||||
|
||||
if (percent >= min_threshold) {
|
||||
log_warn("WARNING: Remaining free space in metadata of thin pool %s "
|
||||
"is too low (%.2f%% >= %.2f%%). "
|
||||
"Resize is recommended.",
|
||||
display_lvname(pool_seg->lv),
|
||||
dm_percent_to_float(percent),
|
||||
dm_percent_to_float(min_threshold));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (percent > threshold) {
|
||||
log_debug("Threshold configured for free metadata space in "
|
||||
"thin pool %s has been reached (%.2f%% > %.2f%%).",
|
||||
|
@ -501,6 +501,9 @@ Supported values are in range between 2MiB and 16GiB for thin pool,
|
||||
and upto 16GiB for cache pool. The minimum value is computed from pool's
|
||||
data size.
|
||||
Default value for thin pool is (Pool_LV_size / Pool_LV_chunk_size * 64b).
|
||||
To work with a thin pool, there should be at least 25% of free space
|
||||
when the size of metadata is smaller then 16MiB,
|
||||
or at least 4MiB of free space otherwise.
|
||||
Default unit is megabytes.
|
||||
.
|
||||
.HP
|
||||
|
Loading…
Reference in New Issue
Block a user