stable-2.02 - aux: update thin_restore_needs_more_volumes
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=18677e24c1ab6e9dff3...
Commit: 18677e24c1ab6e9dff36c048d9e3f6a7fe541c4b
Parent: 99bdbc53ba391e1f58833d0bdf3df935ce6f73f2
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Jan 22 20:17:57 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 1 14:35:53 2021 +0100
aux: update thin_restore_needs_more_volumes
Version 0.8.5-2.el7 needs to return 0;
---
test/lib/aux.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/test/lib/aux.sh b/test/lib/aux.sh
index 728e6dc0e..4b303474a 100644
--- a/test/lib/aux.sh
+++ b/test/lib/aux.sh
@@ -1509,6 +1509,7 @@ thin_restore_needs_more_volumes() {
case $("$LVM_TEST_THIN_RESTORE_CMD" -V) in
# With older version of thin-tool we got slightly more compact metadata
0.[0-6]*|0.7.0*) return 0 ;;
+ 0.8.5-2.el7) return 0 ;;
esac
return 1
}
2 years, 10 months
stable-2.02 - tests: update thin and cache checked messages
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=99bdbc53ba391e1f588...
Commit: 99bdbc53ba391e1f58833d0bdf3df935ce6f73f2
Parent: f6025cdc733220ef8db8f3d4d7415e66a90705d7
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sat Jan 30 13:13:17 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 1 14:35:53 2021 +0100
tests: update thin and cache checked messages
Slightly changed messages for allocation of pool metadata.
---
test/shell/lvconvert-thin.sh | 2 +-
test/shell/lvcreate-cache.sh | 12 +++++-------
test/shell/lvcreate-thin-big.sh | 10 +++++-----
3 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/test/shell/lvconvert-thin.sh b/test/shell/lvconvert-thin.sh
index 1f8d2edb9..bfda8e50d 100644
--- a/test/shell/lvconvert-thin.sh
+++ b/test/shell/lvconvert-thin.sh
@@ -129,7 +129,7 @@ lvcreate -L1T -n $lv1 $vg
lvcreate -L32G -n $lv2 $vg
# Warning about bigger then needed
lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 2>&1 | tee err
-grep "WARNING: Maximum" err
+grep -i "maximum" err
lvremove -f $vg
diff --git a/test/shell/lvcreate-cache.sh b/test/shell/lvcreate-cache.sh
index 066303360..f41b797df 100644
--- a/test/shell/lvcreate-cache.sh
+++ b/test/shell/lvcreate-cache.sh
@@ -27,7 +27,6 @@ aux prepare_vg 5 80000
aux lvmconf 'global/cache_disabled_features = [ "policy_smq" ]'
-
#######################
# Cache_Pool creation #
#######################
@@ -173,17 +172,16 @@ dmsetup table ${vg}-$lv1 | grep cache # ensure it is loaded in kernel
lvremove -f $vg
-
# Check minimum cache pool metadata size
-lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>out
-grep "WARNING: Minimum" out
+lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>&1 | tee out
+grep -i "minimal" out
+
# FIXME: This test is failing in allocator with smaller VG sizes
-lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>out
-grep "WARNING: Maximum" out
+lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>&1 | tee out
+grep -i "maximum" out
lvremove -f $vg
-
########################################
# Cache conversion and r/w permissions #
########################################
diff --git a/test/shell/lvcreate-thin-big.sh b/test/shell/lvcreate-thin-big.sh
index 0b622b7a9..254903548 100644
--- a/test/shell/lvcreate-thin-big.sh
+++ b/test/shell/lvcreate-thin-big.sh
@@ -31,14 +31,14 @@ vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}"
# Size 0 is not valid
invalid lvcreate -L4M --chunksize 128 --poolmetadatasize 0 -T $vg/pool1 2>out
-lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 2>out
-grep "WARNING: Minimum" out
+lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 2>&1 >out
+grep -i "minimal" out
# FIXME: metadata allocation fails, if PV doesn't have at least 16GB
# i.e. pool metadata device cannot be multisegment
-lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>out
-grep "WARNING: Maximum" out
+lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>&1 >out
+grep "maximum" out
check lv_field $vg/pool1_tmeta size "2.00m"
-check lv_field $vg/pool2_tmeta size "15.81g"
+check lv_field $vg/pool2_tmeta size "<15.88g"
# Check we do report correct percent values.
lvcreate --type zero -L3G $vg -n pool3
2 years, 10 months
stable-2.02 - tests: check 16G thin pool metadata size
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=f6025cdc733220ef8db...
Commit: f6025cdc733220ef8db8f3d4d7415e66a90705d7
Parent: 1728f411834c20a93f465e99dedad5afbca45ea1
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sat Jan 30 13:13:34 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 1 14:35:53 2021 +0100
tests: check 16G thin pool metadata size
---
test/shell/thin-16g.sh | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
diff --git a/test/shell/thin-16g.sh b/test/shell/thin-16g.sh
new file mode 100644
index 000000000..ee7e22ed2
--- /dev/null
+++ b/test/shell/thin-16g.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+# Test usability of 16g thin pool metadata LV
+
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux have_thin 1 0 0 || skip
+
+aux prepare_vg 1 50000
+
+lvcreate -T -L10 --poolmetadatasize 16g $vg/pool
+check lv_field $vg/pool_tmeta size "<15.88g"
+lvremove -f $vg
+
+# Cropped way
+lvcreate -T -L10 --poolmetadatasize 16g --config 'allocation/thin_pool_crop_metadata=1' $vg/pool
+check lv_field $vg/pool_tmeta size "15.81g"
+lvremove -f $vg
+
+lvcreate -L16G -n meta $vg
+lvcreate -L10 -n pool $vg
+lvconvert --yes --thinpool $vg/pool --poolmetadata meta
+# Uncropped size 33554432 sectors - 16GiB
+dmsetup table ${vg}-pool_tmeta | grep 33554432
+lvremove -f $vg
+
+# Uses 20G metadata volume, but crops the size in DM table
+lvcreate -L20G -n meta $vg
+lvcreate -L10 -n pool $vg
+lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1'
+check lv_field $vg/lvol0_pmspare size "16.00g"
+# Size should be cropped to 33161216 sectors ~15.81GiB
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+
+# Also size remains unchanged with activation has no cropping,
+# but metadata have no CROP_METADATA flag set
+lvchange -an $vg
+lvchange -ay $vg
+# Size still stays cropped to 33161216 sectors ~15.81GiB
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+lvremove -f $vg
+
+# Minimal size is 2M
+lvcreate -L1M -n meta $vg
+lvcreate -L10 -n pool $vg
+not lvconvert --yes --thinpool $vg/pool --poolmetadata meta
+lvremove -f $vg
+
+# Uses 20G metadata volume, but crops the size in DM table
+lvcreate -L1 --poolmetadatasize 10G -T $vg/pool
+lvresize -L+10G $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1'
+check lv_field $vg/lvol0_pmspare size "15.81g"
+# Size should be cropped to 33161216 sectors ~15.81GiB
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+
+# Without cropping we can grop to ~15.88GiB
+lvresize -L+10G $vg/pool_tmeta
+check lv_field $vg/lvol0_pmspare size "<15.88g"
+lvremove -f $vg
+
+# User has already 'bigger' metadata and wants them uncropped
+lvcreate -L16G -n meta $vg
+lvcreate -L10 -n pool $vg
+lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1'
+
+# No change with cropping
+lvresize -l+1 $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1'
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+
+# Resizes to 'uncropped' size 16GiB with ANY size
+lvresize -l+1 $vg/pool_tmeta
+dmsetup table ${vg}-pool_tmeta | grep 33554432
+check lv_field $vg/pool_tmeta size "16.00g"
+
+vgremove -ff $vg
2 years, 10 months
stable-2.02 - WHATS_NEW: updates
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=1728f411834c20a93f4...
Commit: 1728f411834c20a93f465e99dedad5afbca45ea1
Parent: 1282e9e2984a6ad48e9ee09a15dce7f3aab3e833
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Feb 1 12:12:23 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 1 14:35:53 2021 +0100
WHATS_NEW: updates
---
WHATS_NEW | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/WHATS_NEW b/WHATS_NEW
index 311923204..a50762703 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,10 @@
Version 2.02.188 -
==================================
+ Allocation prints better error when metadata cannot fit on a single PV.
+ Pvmove can better resolve full thin-pool tree move.
+ Limit pool metadata spare to 16GiB.
+ Improves convertsion and allocation of pool metadata.
+ Support thin pool metadata 15.88GiB, adds 64MiB, thin_pool_crop_metadata=0.
Enhance lvdisplay to report raid availiable/partial.
Enhance error handling for fsadm and hanled correct fsck result.
Stop logging rename errors from persintent filter.
2 years, 10 months
stable-2.02 - allocation: report allocation error instead of crash
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=1282e9e2984a6ad48e9...
Commit: 1282e9e2984a6ad48e9ee09a15dce7f3aab3e833
Parent: 862a86982cef87779e361987fbcc62f15729ecef
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Feb 1 10:24:19 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 1 14:35:53 2021 +0100
allocation: report allocation error instead of crash
Current allocation limitation requires to fit metadata/log LV on
a single PV. This is usually not a big problem, but since
thin-pool and cache-pool is using this for allocating extents
for their metadata LVs it might be eventually causing errors
where the remaining free spaces for large metadata size is spread
over several PV.
---
lib/metadata/lv_manip.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 8bfa33a0a..e48e5d18f 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1934,15 +1934,18 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t max_to_allocat
aa[smeta].pv = pva->map->pv;
aa[smeta].pe = pva->start;
aa[smeta].len = ah->log_len;
-
+ if (aa[smeta].len > pva->count) {
+ log_error("Metadata does not fit on a single PV.");
+ return 0;
+ }
log_debug_alloc("Allocating parallel metadata area %" PRIu32
" on %s start PE %" PRIu32
" length %" PRIu32 ".",
(smeta - (ah->area_count + ah->parity_count)),
pv_dev_name(aa[smeta].pv), aa[smeta].pe,
- ah->log_len);
+ aa[smeta].len);
- consume_pv_area(pva, ah->log_len);
+ consume_pv_area(pva, aa[smeta].len);
dm_list_add(&ah->alloced_areas[smeta], &aa[smeta].list);
}
aa[s].len = (ah->alloc_and_split_meta && !ah->split_metadata_is_allocated) ? len - ah->log_len : len;
2 years, 10 months
stable-2.02 - pvmove: automatically resolve whole stacked LV
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=862a86982cef87779e3...
Commit: 862a86982cef87779e361987fbcc62f15729ecef
Parent: dd2501d64b02ae8426e501771272e9445be2ed8c
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Jan 25 01:17:14 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 1 14:35:53 2021 +0100
pvmove: automatically resolve whole stacked LV
When passing 'pvmove --name arg' try to automatically move
all associated dependencies with given LV.
i.e. 'pvmove --name thinpool vg vgnew'
moves all thins and data and metadata LV into a new VG vgnew.
---
lib/metadata/metadata.c | 57 ++++++++++++++++++++++++++++++-------------------
1 file changed, 35 insertions(+), 22 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 6c4683aa3..da53b32ef 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -377,14 +377,33 @@ int move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
return _move_pv(vg_from, vg_to, pv_name, 1);
}
+struct vg_from_to {
+ struct volume_group *from;
+ struct volume_group *to;
+};
+
+static int _move_pvs_used_by_lv_cb(struct logical_volume *lv, void *data)
+{
+ struct vg_from_to *v = (struct vg_from_to*) data;
+ struct lv_segment *lvseg;
+ unsigned s;
+
+ dm_list_iterate_items(lvseg, &lv->segments)
+ for (s = 0; s < lvseg->area_count; s++)
+ if (seg_type(lvseg, s) == AREA_PV)
+ if (!_move_pv(v->from, v->to,
+ pv_dev_name(seg_pv(lvseg, s)), 0))
+ return_0;
+
+ return 1;
+}
+
int move_pvs_used_by_lv(struct volume_group *vg_from,
struct volume_group *vg_to,
const char *lv_name)
{
- struct lv_segment *lvseg;
- unsigned s;
+ struct vg_from_to data = { .from = vg_from, .to = vg_to };
struct lv_list *lvl;
- struct logical_volume *lv;
/* FIXME: handle tags */
if (!(lvl = find_lv_in_vg(vg_from, lv_name))) {
@@ -393,28 +412,22 @@ int move_pvs_used_by_lv(struct volume_group *vg_from,
return 0;
}
- if (vg_bad_status_bits(vg_from, RESIZEABLE_VG) ||
- vg_bad_status_bits(vg_to, RESIZEABLE_VG))
+ if (vg_bad_status_bits(vg_from, RESIZEABLE_VG)) {
+ log_error("Cannot move PV(s) from non resize volume group %s.", vg_from->name);
return 0;
+ }
- dm_list_iterate_items(lvseg, &lvl->lv->segments) {
- if (lvseg->log_lv)
- if (!move_pvs_used_by_lv(vg_from, vg_to,
- lvseg->log_lv->name))
- return_0;
- for (s = 0; s < lvseg->area_count; s++) {
- if (seg_type(lvseg, s) == AREA_PV) {
- if (!_move_pv(vg_from, vg_to,
- pv_dev_name(seg_pv(lvseg, s)), 0))
- return_0;
- } else if (seg_type(lvseg, s) == AREA_LV) {
- lv = seg_lv(lvseg, s);
- if (!move_pvs_used_by_lv(vg_from, vg_to,
- lv->name))
- return_0;
- }
- }
+ if (vg_bad_status_bits(vg_to, RESIZEABLE_VG)) {
+ log_error("Cannot move PV(s) to non resize volume group %s.", vg_to->name);
+ return 0;
}
+
+ if (!for_each_sub_lv(lvl->lv, _move_pvs_used_by_lv_cb, &data))
+ return_0;
+
+ if (!_move_pvs_used_by_lv_cb(lvl->lv, &data))
+ return_0;
+
return 1;
}
2 years, 10 months
stable-2.02 - cache: reuse code for metadata min_max
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=dd2501d64b02ae8426e...
Commit: dd2501d64b02ae8426e501771272e9445be2ed8c
Parent: 72b12033a9ffb45b858d738b956dc39f71782ecd
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sat Jan 30 16:32:51 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 1 14:35:53 2021 +0100
cache: reuse code for metadata min_max
Use update_pool_metadata_min_max() which is shared with
thin-pool metadata min-max updating.
Gives improved messages when converting volumes to metadata.
---
lib/metadata/cache_manip.c | 40 ++++++++++++++--------------------------
lib/metadata/metadata-exported.h | 1 +
tools/lvconvert.c | 1 +
tools/lvcreate.c | 1 +
4 files changed, 17 insertions(+), 26 deletions(-)
diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
index 05a6efdf1..ffce73761 100644
--- a/lib/metadata/cache_manip.c
+++ b/lib/metadata/cache_manip.c
@@ -161,6 +161,7 @@ int update_cache_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
int *chunk_size_calc_method, uint32_t *chunk_size)
{
uint64_t min_meta_size;
@@ -206,39 +207,26 @@ int update_cache_pool_params(struct cmd_context *cmd,
if (!validate_cache_chunk_size(cmd, *chunk_size))
return_0;
- min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
+ if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
+ log_error("Size of %s data volume cannot be smaller than chunk size %s.",
+ segtype->name, display_size(cmd, *chunk_size));
+ return 0;
+ }
- /* Round up to extent size */
- if (min_meta_size % extent_size)
- min_meta_size += extent_size - min_meta_size % extent_size;
+ min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
+ min_meta_size = dm_round_up(min_meta_size, extent_size);
if (!pool_metadata_size)
pool_metadata_size = min_meta_size;
- if (pool_metadata_size > (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE)) {
- pool_metadata_size = 2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE;
- if (*pool_metadata_extents)
- log_warn("WARNING: Maximum supported pool metadata size is %s.",
- display_size(cmd, pool_metadata_size));
- } else if (pool_metadata_size < min_meta_size) {
- if (*pool_metadata_extents)
- log_warn("WARNING: Minimum required pool metadata size is %s "
- "(needs extra %s).",
- display_size(cmd, min_meta_size),
- display_size(cmd, min_meta_size - pool_metadata_size));
- pool_metadata_size = min_meta_size;
- }
-
- if (!(*pool_metadata_extents =
- extents_from_size(cmd, pool_metadata_size, extent_size)))
+ if (!update_pool_metadata_min_max(cmd, extent_size,
+ min_meta_size,
+ (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE),
+ &pool_metadata_size,
+ metadata_lv,
+ pool_metadata_extents))
return_0;
- if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
- log_error("Size of %s data volume cannot be smaller than chunk size %s.",
- segtype->name, display_size(cmd, *chunk_size));
- return 0;
- }
-
log_verbose("Preferred pool metadata size %s.",
display_size(cmd, (uint64_t)*pool_metadata_extents * extent_size));
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 629b3a457..16b5e654c 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1282,6 +1282,7 @@ int update_cache_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
int *chunk_size_calc_method, uint32_t *chunk_size);
int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size);
int validate_lv_cache_create_pool(const struct logical_volume *pool_lv);
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 50f438672..b885f9241 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -3093,6 +3093,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
pool_segtype, target_attr,
lv->le_count,
&meta_extents,
+ metadata_lv,
&chunk_calc,
&chunk_size))
goto_bad;
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index d54f152a3..0bbb03301 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -402,6 +402,7 @@ static int _update_extents_params(struct volume_group *vg,
lp->segtype, lp->target_attr,
lp->extents,
&lp->pool_metadata_extents,
+ NULL,
&lp->thin_chunk_size_calc_policy,
&lp->chunk_size))
return_0;
2 years, 10 months
stable-2.02 - pool: limit pmspare to 16GiB
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=72b12033a9ffb45b858...
Commit: 72b12033a9ffb45b858d738b956dc39f71782ecd
Parent: 586bac0b10d3c1757708129433e8401a4797a7ee
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Jan 29 23:20:18 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 1 14:35:53 2021 +0100
pool: limit pmspare to 16GiB
There is not much point to let allocate more then this size
even when i.e. converted LV is bigger then 16GiB (%extent_size)
ATM neither thin-pool nor cache-pool supports bigger metadata.
---
lib/metadata/pool_manip.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index ead302155..54b824a5e 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -683,6 +683,8 @@ static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg
int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
struct dm_list *pvh, int poolmetadataspare)
{
+ /* Max usable size of any spare volume is currently 16GiB rouned to extent size */
+ const uint64_t MAX_SIZE = (UINT64_C(2 * 16) * 1024 * 1024 + vg->extent_size - 1) / vg->extent_size;
struct logical_volume *lv = vg->pool_metadata_spare_lv;
uint32_t seg_mirrors;
struct lv_segment *seg;
@@ -692,8 +694,11 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
/* Find maximal size of metadata LV */
dm_list_iterate_items(lvl, &vg->lvs)
if (lv_is_pool_metadata(lvl->lv) &&
- (lvl->lv->le_count > extents))
+ (lvl->lv->le_count > extents)) {
extents = lvl->lv->le_count;
+ if (extents >= MAX_SIZE)
+ break;
+ }
if (!poolmetadataspare) {
/* TODO: Not showing when lvm.conf would define 'n' ? */
@@ -704,6 +709,9 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
return 1;
}
+ if (extents > MAX_SIZE)
+ extents = MAX_SIZE;
+
if (!lv) {
if (!_alloc_pool_metadata_spare(vg, extents, pvh))
return_0;
2 years, 10 months
stable-2.02 - thin: improve 16g support for thin pool metadata
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=586bac0b10d3c175770...
Commit: 586bac0b10d3c1757708129433e8401a4797a7ee
Parent: 5196392bcd1522580f19992397b603cbac077ffb
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Feb 1 14:13:23 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 1 14:35:53 2021 +0100
thin: improve 16g support for thin pool metadata
Initial support for thin-pool used slightly smaller max size 15.81GiB
for thin-pool metadata. However the real limit later settled at 15.88GiB
(difference is ~64MiB - 16448 4K blocks).
lvm2 could not simply increase the size as it has been using hard cropping
of the loaded metadata device to avoid warnings printing warning of kernel
when the size was bigger (i.e. due to bigger extent_size).
This patch adds the new lvm.conf configurable setting:
allocation/thin_pool_crop_metadata
which defaults to 0 -> no crop of metadata beyond 15.81GiB.
Only user with these sizes of metadata will be affected.
Without cropping lvm2 now limits metadata allocation size to 15.88GiB.
Any space beyond is currently not used by thin-pool target.
Even if i.e. bigger LV is used for metadata via lvconvert,
or allocated bigger because of to large extent size.
With cropping enabled (=1) lvm2 preserves the old limitation
15.81GiB and should allow to work in the evironement with
older lvm2 tools (i.e. older distribution).
Thin-pool metadata with size bigger then 15.81G is now using CROP_METADATA
flag within lvm2 metadata, so older lvm2 recognizes an
incompatible thin-pool and cannot activate such pool!
Users should use uncropped version as it is not suffering
from various issues between thin_repair results and allocated
metadata LV as thin_repair limit is 15.88GiB
Users should use cropping only when really needed!
Patch also better handles resize of thin-pool metadata and prevents resize
beoyond usable size 15.88GiB. Resize beyond 15.81GiB automatically
switches pool to no-crop version. Even with existing bigger thin-pool
metadata command 'lvextend -l+1 vg/pool_tmeta' does the change.
Patch gives better controls 'coverted' metadata LV and
reports less confusing message during conversion.
Patch set also moves the code for updating min/max into pool_manip.c
for better sharing with cache_pool code.
---
conf/example.conf.in | 7 +++
lib/activate/dev_manager.c | 8 ++--
lib/config/config_settings.h | 5 +++
lib/config/defaults.h | 2 +
lib/format_text/flags.c | 1 +
lib/metadata/lv_manip.c | 31 ++++++++++++++
lib/metadata/merge.c | 2 +
lib/metadata/metadata-exported.h | 11 +++++
lib/metadata/metadata.h | 13 ++++++
lib/metadata/pool_manip.c | 46 ++++++++++++++++++++
lib/metadata/thin_manip.c | 92 ++++++++++++++++++++++++++--------------
lib/thin/thin.c | 22 +++++++---
man/lvmthin.7_main | 10 ++++-
tools/lvconvert.c | 4 ++
tools/lvcreate.c | 2 +
15 files changed, 214 insertions(+), 42 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index a57c66e40..ee2b34c03 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -470,6 +470,13 @@ allocation {
# Thin pool metadata and data will always use different PVs.
thin_pool_metadata_require_separate_pvs = 0
+ # Configuration option allocation/thin_pool_crop_metadata.
+ # Older version of lvm2 cropped pool's metadata size to 15.81 GiB.
+ # This is slightly less then the actual maximum 15.88 GiB.
+ # For compatibility with older version and use of cropped size set to 1.
+ # This configuration option has an automatic default value.
+ # thin_pool_crop_metadata = 0
+
# Configuration option allocation/thin_pool_zero.
# Thin pool data chunks are zeroed before they are first used.
# Zeroing with a larger thin pool chunk size reduces performance.
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 7d9cb917e..370f90edd 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -249,7 +249,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
int dmtask;
int with_flush; /* TODO: arg for _info_run */
void *target = NULL;
- uint64_t target_start, target_length, start, length;
+ uint64_t target_start, target_length, start, length, length_crop = 0;
char *target_name, *target_params;
const char *devname;
@@ -285,13 +285,15 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
/* Uses max DM_THIN_MAX_METADATA_SIZE sectors for metadata device */
if (lv_is_thin_pool_metadata(seg_status->seg->lv) &&
(length > DM_THIN_MAX_METADATA_SIZE))
- length = DM_THIN_MAX_METADATA_SIZE;
+ length_crop = DM_THIN_MAX_METADATA_SIZE;
do {
target = dm_get_next_target(dmt, target, &target_start,
&target_length, &target_name, &target_params);
- if ((start == target_start) && (length == target_length))
+ if ((start == target_start) &&
+ ((length == target_length) ||
+ (length_crop && (length_crop == target_length))))
break; /* Keep target_params when matching segment is found */
target_params = NULL; /* Marking this target_params unusable */
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index d23ae49ff..9795bde8e 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -596,6 +596,11 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
"Thin pool metadata and data will always use different PVs.\n")
+cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 2, 188), NULL, 0, NULL,
+ "Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
+ "This is slightly less then the actual maximum 15.88 GiB.\n"
+ "For compatibility with older version and use of cropped size set to 1.\n")
+
cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL,
"Thin pool data chunks are zeroed before they are first used.\n"
"Zeroing with a larger thin pool chunk size reduces performance.\n")
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 2ffad243e..d6735241f 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -105,6 +105,8 @@
#define DEFAULT_THIN_REPAIR_OPTION1 ""
#define DEFAULT_THIN_REPAIR_OPTIONS_CONFIG "#S" DEFAULT_THIN_REPAIR_OPTION1
#define DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
+#define DEFAULT_THIN_POOL_CROP_METADATA 0
+#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB (UINT64_C(255) * ((1 << 14) - 64) * 4) /* KB */ /* 0x3f8040 blocks */
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (DM_THIN_MAX_METADATA_SIZE / 2) /* KB */
#define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048 /* KB */
#define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index 7e793b3d0..8f5e2b2e6 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -72,6 +72,7 @@ static const struct flag _lv_flags[] = {
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
{LV_METADATA_FORMAT, "METADATA_FORMAT", SEGTYPE_FLAG},
+ {LV_CROP_METADATA, "CROP_METADATA", SEGTYPE_FLAG},
{LV_NOSCAN, NULL, 0},
{LV_TEMPORARY, NULL, 0},
{POOL_METADATA_SPARE, NULL, 0},
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 346ec9f77..8bfa33a0a 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5061,6 +5061,8 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
uint32_t existing_extents;
uint32_t seg_size = 0;
uint32_t new_extents;
+ uint64_t max_metadata_size;
+ thin_crop_metadata_t crop;
int reducing = 0;
seg_last = last_seg(lv);
@@ -5200,6 +5202,33 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
return 1;
}
}
+ } else if (lv_is_thin_pool_metadata(lv)) {
+ if (!(seg = get_only_segment_using_this_lv(lv)))
+ return_0;
+
+ max_metadata_size = get_thin_pool_max_metadata_size(cmd, vg->profile, &crop);
+
+ if (((uint64_t)lp->extents * vg->extent_size) > max_metadata_size) {
+ lp->extents = (max_metadata_size + vg->extent_size - 1) / vg->extent_size;
+ log_print_unless_silent("Reached maximum pool metadata size %s (%" PRIu32 " extents).",
+ display_size(vg->cmd, max_metadata_size), lp->extents);
+ }
+
+ if (existing_logical_extents >= lp->extents)
+ lp->extents = existing_logical_extents;
+
+ crop = get_thin_pool_crop_metadata(cmd, crop, (uint64_t)lp->extents * vg->extent_size);
+
+ if (seg->crop_metadata != crop) {
+ seg->crop_metadata = crop;
+ seg->lv->status |= LV_CROP_METADATA;
+ /* Crop change require reload even if there no size change */
+ lp->size_changed = 1;
+ log_print_unless_silent("Thin pool will use metadata without cropping.");
+ }
+
+ if (!(seg_size = lp->extents - existing_logical_extents))
+ return 1; /* No change in metadata size */
}
} else { /* If reducing, find stripes, stripesize & size of last segment */
if (lp->stripes || lp->stripe_size || lp->mirrors)
@@ -7941,6 +7970,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
first_seg(lv)->chunk_size = lp->chunk_size;
first_seg(lv)->zero_new_blocks = lp->zero_new_blocks;
first_seg(lv)->discards = lp->discards;
+ if ((first_seg(lv)->crop_metadata = lp->crop_metadata) == THIN_CROP_METADATA_NO)
+ lv->status |= LV_CROP_METADATA;
if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->thin_chunk_size_calc_policy)) {
stack;
goto revert_new_lv;
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 054f1855f..69d755aeb 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -478,6 +478,8 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
seg_error("sets discards");
if (!dm_list_empty(&seg->thin_messages))
seg_error("sets thin_messages list");
+ if (seg->lv->status & LV_CROP_METADATA)
+ seg_error("sets CROP_METADATA flag");
}
if (seg_is_thin_volume(seg)) {
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 30ab47576..629b3a457 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -142,6 +142,7 @@
#define LV_REMOVE_AFTER_RESHAPE UINT64_C(0x0400000000000000) /* LV needs to be removed after a shrinking reshape */
#define LV_METADATA_FORMAT UINT64_C(0x0800000000000000) /* LV has segments with metadata format */
+#define LV_CROP_METADATA UINT64_C(0x0000000000000400) /* LV - also VG CLUSTERED */
#define LV_RESHAPE UINT64_C(0x1000000000000000) /* Ongoing reshape (number of stripes, stripesize or raid algorithm change):
used as SEGTYPE_FLAG to prevent activation on old runtime */
@@ -299,6 +300,12 @@ typedef enum {
THIN_DISCARDS_PASSDOWN,
} thin_discards_t;
+typedef enum {
+ THIN_CROP_METADATA_UNSELECTED = 0, /* 'auto' selects */
+ THIN_CROP_METADATA_NO,
+ THIN_CROP_METADATA_YES,
+} thin_crop_metadata_t;
+
typedef enum {
CACHE_MODE_UNSELECTED = 0,
CACHE_MODE_WRITETHROUGH,
@@ -476,6 +483,7 @@ struct lv_segment {
uint64_t transaction_id; /* For thin_pool, thin */
thin_zero_t zero_new_blocks; /* For thin_pool */
thin_discards_t discards; /* For thin_pool */
+ thin_crop_metadata_t crop_metadata; /* For thin_pool */
struct dm_list thin_messages; /* For thin_pool */
struct logical_volume *external_lv; /* For thin */
struct logical_volume *pool_lv; /* For thin, cache */
@@ -861,6 +869,8 @@ int update_thin_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
+ unsigned *crop_metadata,
int *chunk_size_calc_method, uint32_t *chunk_size,
thin_discards_t *discards, thin_zero_t *zero_new_blocks);
@@ -986,6 +996,7 @@ struct lvcreate_params {
uint64_t permission; /* all */
unsigned error_when_full; /* when segment supports it */
+ thin_crop_metadata_t crop_metadata;
uint32_t read_ahead; /* all */
int approx_alloc; /* all */
alloc_policy_t alloc; /* all */
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 96bbb5690..9aabafbc1 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -500,8 +500,21 @@ 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 *pool_lv, const struct segment_type *segtype,
struct alloc_handle *ah, uint32_t stripes, uint32_t stripe_size);
+uint64_t get_thin_pool_max_metadata_size(struct cmd_context *cmd, struct profile *profile,
+ thin_crop_metadata_t *crop);
+thin_crop_metadata_t get_thin_pool_crop_metadata(struct cmd_context *cmd,
+ thin_crop_metadata_t crop,
+ uint64_t metadata_size);
uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size);
+int update_pool_metadata_min_max(struct cmd_context *cmd,
+ uint32_t extent_size,
+ uint64_t min_metadata_size, /* required min */
+ uint64_t max_metadata_size, /* writable max */
+ uint64_t *metadata_size, /* current calculated */
+ struct logical_volume *metadata_lv, /* name of converted LV or NULL */
+ uint32_t *metadata_extents); /* resulting extent count */
+
/*
* Begin skeleton for external LVM library
*/
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index a93e230be..ead302155 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -728,6 +728,52 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
return 1;
}
+int update_pool_metadata_min_max(struct cmd_context *cmd,
+ uint32_t extent_size,
+ uint64_t min_metadata_size, /* required min */
+ uint64_t max_metadata_size, /* writable max */
+ uint64_t *metadata_size, /* current calculated */
+ struct logical_volume *metadata_lv, /* name of converted LV or NULL */
+ uint32_t *metadata_extents) /* resulting extent count */
+{
+ max_metadata_size = dm_round_up(max_metadata_size, extent_size);
+ min_metadata_size = dm_round_up(min_metadata_size, extent_size);
+
+ if (*metadata_size > max_metadata_size) {
+ if (metadata_lv) {
+ log_print_unless_silent("Size %s of pool metadata volume %s is bigger then maximum usable size %s.",
+ display_size(cmd, *metadata_size),
+ display_lvname(metadata_lv),
+ display_size(cmd, max_metadata_size));
+ } else {
+ if (*metadata_extents)
+ log_print_unless_silent("Reducing pool metadata size %s to maximum usable size %s.",
+ display_size(cmd, *metadata_size),
+ display_size(cmd, max_metadata_size));
+ *metadata_size = max_metadata_size;
+ }
+ } else if (*metadata_size < min_metadata_size) {
+ if (metadata_lv) {
+ log_error("Can't use volume %s with size %s as pool metadata. Minimal required size is %s.",
+ display_lvname(metadata_lv),
+ display_size(cmd, *metadata_size),
+ display_size(cmd, min_metadata_size));
+ return 0;
+ } else {
+ if (*metadata_extents)
+ log_print_unless_silent("Extending pool metadata size %s to required minimal size %s.",
+ display_size(cmd, *metadata_size),
+ display_size(cmd, min_metadata_size));
+ *metadata_size = min_metadata_size;
+ }
+ }
+
+ if (!(*metadata_extents = extents_from_size(cmd, *metadata_size, extent_size)))
+ return_0;
+
+ return 1;
+}
+
int vg_set_pool_metadata_spare(struct logical_volume *lv)
{
char new_name[NAME_LEN];
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 695aff101..fc5b0e6fb 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -610,9 +610,9 @@ static uint64_t _estimate_metadata_size(uint32_t data_extents, uint32_t extent_s
}
/* Estimate maximal supportable thin pool data size for given chunk_size */
-static uint64_t _estimate_max_data_size(uint32_t chunk_size)
+static uint64_t _estimate_max_data_size(uint64_t max_metadata_size, uint32_t chunk_size)
{
- return chunk_size * (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2) * SECTOR_SIZE / UINT64_C(64);
+ return max_metadata_size * chunk_size * SECTOR_SIZE / UINT64_C(64);
}
/* Estimate thin pool chunk size from data and metadata size (in sector units) */
@@ -662,6 +662,38 @@ int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct
return 1;
}
+/* Return max supported metadata size with selected cropping */
+uint64_t get_thin_pool_max_metadata_size(struct cmd_context *cmd, struct profile *profile,
+ thin_crop_metadata_t *crop)
+{
+ *crop = find_config_tree_bool(cmd, allocation_thin_pool_crop_metadata_CFG, profile) ?
+ THIN_CROP_METADATA_YES : THIN_CROP_METADATA_NO;
+
+ return (*crop == THIN_CROP_METADATA_NO) ?
+ (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB) : (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE);
+}
+
+/*
+ * With existing crop method, check if the metadata_size would need cropping.
+ * If not, set UNSELECTED, otherwise print some verbose info about selected cropping
+ */
+thin_crop_metadata_t get_thin_pool_crop_metadata(struct cmd_context *cmd,
+ thin_crop_metadata_t crop,
+ uint64_t metadata_size)
+{
+ const uint64_t crop_size = (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE);
+
+ if (metadata_size > crop_size) {
+ if (crop == THIN_CROP_METADATA_NO)
+ log_verbose("Using metadata size without cropping.");
+ else
+ log_verbose("Cropping metadata size to %s.", display_size(cmd, crop_size));
+ } else
+ crop = THIN_CROP_METADATA_UNSELECTED;
+
+ return crop;
+}
+
int update_thin_pool_params(struct cmd_context *cmd,
struct profile *profile,
uint32_t extent_size,
@@ -669,10 +701,13 @@ int update_thin_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
+ thin_crop_metadata_t *crop_metadata,
int *chunk_size_calc_method, uint32_t *chunk_size,
thin_discards_t *discards, thin_zero_t *zero_new_blocks)
{
- uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
+ uint64_t pool_metadata_size;
+ uint64_t max_metadata_size;
uint32_t estimate_chunk_size;
uint64_t max_pool_data_size;
const char *str;
@@ -702,7 +737,9 @@ int update_thin_pool_params(struct cmd_context *cmd,
*zero_new_blocks = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile)
? THIN_ZERO_YES : THIN_ZERO_NO;
- if (!pool_metadata_size) {
+ max_metadata_size = get_thin_pool_max_metadata_size(cmd, profile, crop_metadata);
+
+ if (!*pool_metadata_extents) {
if (!*chunk_size) {
if (!get_default_allocation_thin_pool_chunk_size(cmd, profile,
chunk_size,
@@ -723,20 +760,20 @@ int update_thin_pool_params(struct cmd_context *cmd,
} else {
pool_metadata_size = _estimate_metadata_size(pool_data_extents, extent_size, *chunk_size);
- if (pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) {
+ if (pool_metadata_size > max_metadata_size) {
/* Suggest bigger chunk size */
estimate_chunk_size =
_estimate_chunk_size(pool_data_extents, extent_size,
- (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2), attr);
+ max_metadata_size, attr);
log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.",
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;
+ pool_metadata_size = dm_round_up(pool_metadata_size, extent_size);
} else {
+ pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
estimate_chunk_size = _estimate_chunk_size(pool_data_extents, extent_size,
pool_metadata_size, attr);
@@ -751,7 +788,19 @@ int update_thin_pool_params(struct cmd_context *cmd,
}
}
- max_pool_data_size = _estimate_max_data_size(*chunk_size);
+ /* Use not rounded max for data size */
+ max_pool_data_size = _estimate_max_data_size(max_metadata_size, *chunk_size);
+
+ if (!update_pool_metadata_min_max(cmd, extent_size,
+ 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE,
+ max_metadata_size,
+ &pool_metadata_size,
+ metadata_lv,
+ pool_metadata_extents))
+ return_0;
+
+ *crop_metadata = get_thin_pool_crop_metadata(cmd, *crop_metadata, pool_metadata_size);
+
if ((max_pool_data_size / extent_size) < pool_data_extents) {
log_error("Selected chunk size %s cannot address more then %s of thin pool data space.",
display_size(cmd, *chunk_size), display_size(cmd, max_pool_data_size));
@@ -764,22 +813,6 @@ int update_thin_pool_params(struct cmd_context *cmd,
if (!validate_thin_pool_chunk_size(cmd, *chunk_size))
return_0;
- if (pool_metadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
- pool_metadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
- if (*pool_metadata_extents)
- log_warn("WARNING: Maximum supported pool metadata size is %s.",
- display_size(cmd, pool_metadata_size));
- } else if (pool_metadata_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
- pool_metadata_size = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
- if (*pool_metadata_extents)
- log_warn("WARNING: Minimum supported pool metadata size is %s.",
- display_size(cmd, pool_metadata_size));
- }
-
- if (!(*pool_metadata_extents =
- extents_from_size(cmd, pool_metadata_size, extent_size)))
- return_0;
-
if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
log_error("Size of %s data volume cannot be smaller than chunk size %s.",
segtype->name, display_size(cmd, *chunk_size));
@@ -958,12 +991,5 @@ int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size)
uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size)
{
- uint64_t sz = _estimate_metadata_size(data_extents, extent_size, chunk_size);
-
- if (sz > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE))
- sz = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
- else if (sz < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE))
- sz = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
-
- return sz;
+ return _estimate_metadata_size(data_extents, extent_size, chunk_size);
}
diff --git a/lib/thin/thin.c b/lib/thin/thin.c
index b7c80bcd2..8ab60ce1e 100644
--- a/lib/thin/thin.c
+++ b/lib/thin/thin.c
@@ -85,6 +85,7 @@ static int _thin_pool_text_import(struct lv_segment *seg,
struct logical_volume *pool_data_lv, *pool_metadata_lv;
const char *discards_str = NULL;
uint32_t zero = 0;
+ uint32_t crop = 0;
if (!dm_config_get_str(sn, "metadata", &lv_name))
return SEG_LOG_ERROR("Metadata must be a string in");
@@ -130,6 +131,13 @@ static int _thin_pool_text_import(struct lv_segment *seg,
seg->zero_new_blocks = (zero) ? THIN_ZERO_YES : THIN_ZERO_NO;
+ if (dm_config_has_node(sn, "crop_metadata")) {
+ if (!dm_config_get_uint32(sn, "crop_metadata", &crop))
+ return SEG_LOG_ERROR("Could not read crop_metadata for");
+ seg->crop_metadata = (crop) ? THIN_CROP_METADATA_YES : THIN_CROP_METADATA_NO;
+ seg->lv->status |= LV_CROP_METADATA;
+ }
+
/* Read messages */
for (; sn; sn = sn->sib)
if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child))
@@ -176,6 +184,9 @@ static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter
return 0;
}
+ if (seg->crop_metadata != THIN_CROP_METADATA_UNSELECTED)
+ outf(f, "crop_metadata = %u", (seg->crop_metadata == THIN_CROP_METADATA_YES) ? 1 : 0);
+
dm_list_iterate_items(tmsg, &seg->thin_messages) {
/* Extra validation */
switch (tmsg->type) {
@@ -306,11 +317,12 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
else
low_water_mark = 0;
- if (!dm_tree_node_add_thin_pool_target(node, len,
- seg->transaction_id,
- metadata_dlid, pool_dlid,
- seg->chunk_size, low_water_mark,
- (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1))
+ if (!dm_tree_node_add_thin_pool_target_v1(node, len,
+ seg->transaction_id,
+ metadata_dlid, pool_dlid,
+ seg->chunk_size, low_water_mark,
+ (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1,
+ (seg->crop_metadata == THIN_CROP_METADATA_YES) ? 1 : 0))
return_0;
if (attr & THIN_FEATURE_DISCARDS) {
diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main
index 39dcdfedc..ebb0b610d 100644
--- a/man/lvmthin.7_main
+++ b/man/lvmthin.7_main
@@ -1104,7 +1104,7 @@ The default value is shown by:
The amount of thin metadata depends on how many blocks are shared between
thin LVs (i.e. through snapshots). A thin pool with many snapshots may
need a larger metadata LV. Thin pool metadata LV sizes can be from 2MiB
-to 16GiB.
+to approximately 16GiB.
When using lvcreate to create what will become a thin metadata LV, the
size is specified with the -L|--size option.
@@ -1119,6 +1119,14 @@ needed, so it is recommended to start with a size of 1GiB which should be
enough for all practical purposes. A thin pool metadata LV can later be
manually or automatically extended if needed.
+Configurable setting
+.BR lvm.conf (5)
+.BR allocation / thin_pool_crop_metadata
+gives control over cropping to 15.81GiB to stay backward compatible with older
+versions of lvm2. With enabled cropping there can be observed some problems when
+using volumes above this size with thin tools (i.e. thin_repair).
+Cropping should be enabled only when compatibility is required.
+
.SS Create a thin snapshot of an external, read only LV
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index fb33cc4e8..50f438672 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -2937,6 +2937,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
const char *policy_name;
struct dm_config_tree *policy_settings = NULL;
int pool_metadata_spare;
+ thin_crop_metadata_t crop_metadata;
thin_discards_t discards;
thin_zero_t zero_new_blocks;
int r = 0;
@@ -3100,6 +3101,8 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
pool_segtype, target_attr,
lv->le_count,
&meta_extents,
+ metadata_lv,
+ &crop_metadata,
&chunk_calc,
&chunk_size,
&discards, &zero_new_blocks))
@@ -3305,6 +3308,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
goto_bad;
} else {
seg->transaction_id = 0;
+ seg->crop_metadata = crop_metadata;
seg->chunk_size = chunk_size;
seg->discards = discards;
seg->zero_new_blocks = zero_new_blocks;
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 4be8e035f..d54f152a3 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -390,6 +390,8 @@ static int _update_extents_params(struct volume_group *vg,
lp->segtype, lp->target_attr,
lp->extents,
&lp->pool_metadata_extents,
+ NULL,
+ &lp->crop_metadata,
&lp->thin_chunk_size_calc_policy,
&lp->chunk_size,
&lp->discards,
2 years, 10 months
stable-2.02 - libdm: add dm_tree_node_add_thin_pool_target_v1
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=5196392bcd1522580f1...
Commit: 5196392bcd1522580f19992397b603cbac077ffb
Parent: 5e97bc5e6786b2187f5326f35bcb82f47fd999a4
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Feb 1 14:06:31 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 1 14:32:07 2021 +0100
libdm: add dm_tree_node_add_thin_pool_target_v1
Supports thin-pool without crop.
---
WHATS_NEW_DM | 1 +
libdm/.exported_symbols.DM_1_02_172 | 1 +
libdm/libdevmapper.h | 16 ++++++++++++---
libdm/libdm-deptree.c | 39 +++++++++++++++++++++++++++----------
4 files changed, 44 insertions(+), 13 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 06e65b7d3..188ac8900 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.172 -
==================================
+ Add dm_tree_node_add_thin_pool_target_v1 with crop_metadata support.
Add support for VDO in blkdeactivate script.
Try to remove all created devices on dm preload tree error path.
Fix dm_list interators with gcc 10 optimization (-ftree-pta).
diff --git a/libdm/.exported_symbols.DM_1_02_172 b/libdm/.exported_symbols.DM_1_02_172
new file mode 100644
index 000000000..ed4cce7d6
--- /dev/null
+++ b/libdm/.exported_symbols.DM_1_02_172
@@ -0,0 +1 @@
+dm_tree_node_add_thin_pool_target_v1
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index a61ffe17e..26d64bf4e 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -1968,10 +1968,10 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
#define DM_THIN_MIN_DATA_BLOCK_SIZE (UINT32_C(128))
#define DM_THIN_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152))
/*
- * Max supported size for thin pool metadata device (17112760320 bytes)
- * Limitation is hardcoded into the kernel and bigger device size
- * is not accepted.
+ * Max supported size for thin pool metadata device (17045913600 bytes)
* drivers/md/dm-thin-metadata.h THIN_METADATA_MAX_SECTORS
+ * But here DM_THIN_MAX_METADATA_SIZE got defined incorrectly
+ * Correct size is (UINT64_C(255) * ((1 << 14) - 64) * (4096 / (1 << 9)))
*/
#define DM_THIN_MAX_METADATA_SIZE (UINT64_C(255) * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024)
@@ -1984,6 +1984,16 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint64_t low_water_mark,
unsigned skip_block_zeroing);
+int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
+ uint64_t size,
+ uint64_t transaction_id,
+ const char *metadata_uuid,
+ const char *pool_uuid,
+ uint32_t data_block_size,
+ uint64_t low_water_mark,
+ unsigned skip_block_zeroing,
+ unsigned crop_metadata);
+
/* Supported messages for thin provision target */
typedef enum {
DM_THIN_MESSAGE_CREATE_SNAP, /* device_id, origin_id */
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index 92f262073..4f71a7008 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -3502,6 +3502,24 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint32_t data_block_size,
uint64_t low_water_mark,
unsigned skip_block_zeroing)
+{
+ return dm_tree_node_add_thin_pool_target_v1(node, size, transaction_id,
+ metadata_uuid, pool_uuid,
+ data_block_size,
+ low_water_mark,
+ skip_block_zeroing,
+ 1);
+}
+
+int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
+ uint64_t size,
+ uint64_t transaction_id,
+ const char *metadata_uuid,
+ const char *pool_uuid,
+ uint32_t data_block_size,
+ uint64_t low_water_mark,
+ unsigned skip_block_zeroing,
+ unsigned crop_metadata)
{
struct load_segment *seg, *mseg;
uint64_t devsize = 0;
@@ -3529,17 +3547,18 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
if (!_link_tree_nodes(node, seg->metadata))
return_0;
- /* FIXME: more complex target may need more tweaks */
- dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
- devsize += mseg->size;
- if (devsize > DM_THIN_MAX_METADATA_SIZE) {
- log_debug_activation("Ignoring %" PRIu64 " of device.",
- devsize - DM_THIN_MAX_METADATA_SIZE);
- mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
- devsize = DM_THIN_MAX_METADATA_SIZE;
- /* FIXME: drop remaining segs */
+ if (crop_metadata)
+ /* FIXME: more complex target may need more tweaks */
+ dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
+ devsize += mseg->size;
+ if (devsize > DM_THIN_MAX_METADATA_SIZE) {
+ log_debug_activation("Ignoring %" PRIu64 " of device.",
+ devsize - DM_THIN_MAX_METADATA_SIZE);
+ mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
+ devsize = DM_THIN_MAX_METADATA_SIZE;
+ /* FIXME: drop remaining segs */
+ }
}
- }
if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, pool_uuid))) {
log_error("Missing pool uuid %s.", pool_uuid);
2 years, 10 months