New upstream release v2.03.11

This commit is contained in:
Marian Csontos 2021-02-22 16:38:55 +01:00
parent a875f27880
commit d2cc5b0434
30 changed files with 3466 additions and 24 deletions

View File

@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
iQIcBAABAgAGBQJfMBQmAAoJELkRJDHlCQOfTCoP/RF9P2RY7NXhXVxfpKbTqqhW
Xag1M5HAMmxflbiYI8Lrh1S7NrSHicWWitiHeKkYTwZxiC8E/HVwZq4UJyl5EDcA
F7FoZuVKB/NPVCjrnvDTwm9pZGZcYErufqb1sT/8cSCtr+vOvRQB5wAWtiu0lQA6
OgcqAzM6Vvx04DiufKYfGoii+VvvfmICtOcQtMBfXpMmp7MCtOlTVeMYCbyiKYr1
4YutnoB41lIyfARA6vu0E+VfbpgJX0KwJS01cWV5XES4kDGBdqqFPJVgagMRCCGo
ssBETAFybQBWVs1OUipIhiZAn1JGXmoZ10UIBPs1GBfKisz+NOr4UQtQV+hMKLex
Wx6fqRzZsof1hOLn/XO8h6626fDcf2YGV5ayIFAyv2IGpMJN0iqBkw4PHOtcP1ft
RqkjwWTm56q97eZN5o8clvAnIN6Anyyx8t1BJUWmZ/QTzMYC98CMZTa0/foq7kw4
qBrsqz1PmdKhWL8xtBdrEcwiuDyPaP/hfdfGEDNBiqVN9zVEVIfbJ2OK4xSUfIr5
hdyjYC+gGRQ/CX0o0YC8PQifzxXthw17XDiH15MhlplCrLJk2CwLMQqKLThe9ksE
3OcQnynS59gI2AfQdALVgSIvzUSMBY7V3I2H9kkBGhywJ64Ow2qpNWXd1wF9DDb5
6F0ElaB5hDrghbwMcFTg
=0jtu
-----END PGP SIGNATURE-----

17
LVM2.2.03.11.tgz.asc Normal file
View File

@ -0,0 +1,17 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
iQIcBAABAgAGBQJf+CGBAAoJELkRJDHlCQOfbcAQAIky3+aEOxnpeT5T2XFRvsCJ
Uk71G70q24JupybEEYvhehf3RmeQkLP3c0TeNMFweqzUwpZBIhpbymglhaNG2AZc
3Bbnl1SAGZ5IzdqacrKfCIas1b/UZMbRAhjcCFQ3oD0SApl+dED2RUacJCnlZxkE
NX3+MG4S6po84uQdHwZGtAw2+HQ0G5GwIETjxJHcQ+q8SZdWJRhKU25Z7UC1LI5u
648SmSlsy2KoNIOSM/sWwgz1MXSWnN0y1mBxfBrR7bdnrPW+ExumzTqZrECIuiyl
bbD3Me/wEfyk4XZt2SoZF9k0Hf3QcSULeTeJlHOqUfLRGKm9E9ngkR/yfb2De/zP
tMzvFyu/tiCfFRXmQbS7K8dFzUzs6KQCHIPuJYnv+BjxOW9gjeyK5JPgBCsOLu//
mEf64ttDDKmCx1qOEnMhxTckvSH8YedmbQRov3g0ZXE3syG4OrhT1DHTyAnv69/f
fNVhOjd4POAoQx2UQzftgU7f4LiMPrQyRiUnQ0DRxHSEYXnIngpqokaVodfvpJp5
8YEuce9Xvq9JCplzKc1OXNtZQUHMybeyVzeenPVYvRV11ZbHzMAzwB6Byhwc9xgt
iKIuWpxMiPveKih3l/THoGOj19OUAN2XvWcGbOa6hTy6m/wsnoJQ0Xx5b5Ysfc1s
U60q2IDLJUS0H2R2raoc
=NE9u
-----END PGP SIGNATURE-----

View File

@ -0,0 +1,15 @@
WHATS_NEW | 2 ++
1 file changed, 2 insertions(+)
diff --git a/WHATS_NEW b/WHATS_NEW
index ffefc9d..3953c7e 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,7 @@
Version 2.03.12 -
===================================
+ Fix problem with wiping of converted LVs.
+ Fix memleak in scanning (2.03.11).
Fix corner case allocation for thin-pools.
Version 2.03.11 - 08th January 2021

View File

@ -0,0 +1,47 @@
WHATS_NEW | 10 ++++++++--
lib/metadata/lv_manip.c | 10 +++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 452a631..fe347f7 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,3 +1,7 @@
+Version 2.03.12 -
+===================================
+ Fix corner case allocation for thin-pools.
+
Version 2.03.11 - 08th January 2021
===================================
Fix pvck handling MDA at offset different from 4096.
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 7046436..443d32c 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1850,11 +1850,13 @@ static uint32_t _mirror_log_extents(uint32_t region_size, uint32_t pe_size, uint
/* Is there enough total space or should we give up immediately? */
static int _sufficient_pes_free(struct alloc_handle *ah, struct dm_list *pvms,
- uint32_t allocated, uint32_t extents_still_needed)
+ uint32_t allocated, uint32_t log_still_needed,
+ uint32_t extents_still_needed)
{
uint32_t area_extents_needed = (extents_still_needed - allocated) * ah->area_count / ah->area_multiple;
uint32_t parity_extents_needed = (extents_still_needed - allocated) * ah->parity_count / ah->area_multiple;
- uint32_t metadata_extents_needed = ah->alloc_and_split_meta ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN + ah->log_len; /* One each */
+ uint32_t metadata_extents_needed = (ah->alloc_and_split_meta ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN) +
+ (log_still_needed ? ah->log_len : 0); /* One each */
uint64_t total_extents_needed = (uint64_t)area_extents_needed + parity_extents_needed + metadata_extents_needed;
uint32_t free_pes = pv_maps_size(pvms);
@@ -3359,7 +3361,9 @@ static int _allocate(struct alloc_handle *ah,
old_allocated = alloc_state.allocated;
log_debug_alloc("Trying allocation using %s policy.", get_alloc_string(alloc));
- if (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated, ah->new_extents))
+ if (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated,
+ alloc_state.log_area_count_still_needed,
+ ah->new_extents))
goto_out;
_init_alloc_parms(ah, &alloc_parms, alloc, prev_lvseg,

View File

@ -0,0 +1,107 @@
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 2c4cc92..90ebd94 100644
--- a/lib/metadata/cache_manip.c
+++ b/lib/metadata/cache_manip.c
@@ -204,6 +204,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;
@@ -252,39 +253,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 0e57722..c0fa564 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1319,6 +1319,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 ce90279..416e8a7 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -3189,6 +3189,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 1ee9e14..1ce561f 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -403,6 +403,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;

View File

@ -0,0 +1,613 @@
conf/example.conf.in | 146 +++++++++++++++++++++++++-------------------------
conf/lvmlocal.conf.in | 4 +-
lib/config/config.c | 2 +-
3 files changed, 76 insertions(+), 76 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index d149ed9..cd53147 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -78,14 +78,14 @@ devices {
# routines to acquire this information. For example, this information
# is used to drive LVM filtering like MD component detection, multipath
# component detection, partition detection and others.
- #
+ #
# Accepted values:
# none
# No external device information source is used.
# udev
# Reuse existing udev database records. Applicable only if LVM is
# compiled with udev support.
- #
+ #
external_device_info_source = "none"
# Configuration option devices/hints.
@@ -94,13 +94,13 @@ devices {
# scanning, and will only scan the listed PVs. Removing the hint file
# will cause lvm to generate a new one. Disable hints if PVs will
# be copied onto devices using non-lvm commands, like dd.
- #
+ #
# Accepted values:
# all
# Use all hints.
# none
# Use no hints.
- #
+ #
# This configuration option has an automatic default value.
# hints = "all"
@@ -118,11 +118,11 @@ devices {
# Prefer the name with the least number of slashes.
# Prefer a name that is a symlink.
# Prefer the path with least value in lexicographical order.
- #
+ #
# Example
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
- #
- # This configuration option has an automatic default value.
+ #
+ # This configuration option does not have a default value defined.
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
# Configuration option devices/filter.
@@ -140,7 +140,7 @@ devices {
# then the device is accepted. Be careful mixing 'a' and 'r' patterns,
# as the combination might produce unexpected results (test changes.)
# Run vgscan after changing the filter to regenerate the cache.
- #
+ #
# Example
# Accept every block device:
# filter = [ "a|.*|" ]
@@ -152,7 +152,7 @@ devices {
# filter = [ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
# Use anchors to be very specific:
# filter = [ "a|^/dev/hda8$|", "r|.*|" ]
- #
+ #
# This configuration option has an automatic default value.
# filter = [ "a|.*|" ]
@@ -170,10 +170,10 @@ devices {
# List of additional acceptable block device types.
# These are of device type names from /proc/devices, followed by the
# maximum number of partitions.
- #
+ #
# Example
# types = [ "fd", 16 ]
- #
+ #
# This configuration option is advanced.
# This configuration option does not have a default value defined.
@@ -215,7 +215,7 @@ devices {
# Configuration option devices/md_component_checks.
# The checks LVM should use to detect MD component devices.
# MD component devices are block devices used by MD software RAID.
- #
+ #
# Accepted values:
# auto
# LVM will skip scanning the end of devices when it has other
@@ -226,7 +226,7 @@ devices {
# full
# LVM will scan the start and end of devices for MD superblocks.
# This requires an extra read at the end of devices.
- #
+ #
# This configuration option has an automatic default value.
# md_component_checks = "auto"
@@ -368,7 +368,7 @@ allocation {
# defined here, it will check whether any of them are attached to the
# PVs concerned and then seek to match those PV tags between existing
# extents and new extents.
- #
+ #
# Example
# Use the special tag "@*" as a wildcard to match any PV tag:
# cling_tag_list = [ "@*" ]
@@ -376,7 +376,7 @@ allocation {
# PVs are tagged with either @site1 or @site2 to indicate where
# they are situated:
# cling_tag_list = [ "@site1", "@site2" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option allocation/maximise_cling.
@@ -435,25 +435,25 @@ allocation {
# Configuration option allocation/cache_metadata_format.
# Sets default metadata format for new cache.
- #
+ #
# Accepted values:
# 0 Automatically detected best available format
# 1 Original format
# 2 Improved 2nd. generation format
- #
+ #
# This configuration option has an automatic default value.
# cache_metadata_format = 0
# Configuration option allocation/cache_mode.
# The default cache mode used for new cache.
- #
+ #
# Accepted values:
# writethrough
# Data blocks are immediately written from the cache to disk.
# writeback
# Data blocks are written from the cache back to disk after some
# delay to improve performance.
- #
+ #
# This setting replaces allocation/cache_pool_cachemode.
# This configuration option has an automatic default value.
# cache_mode = "writethrough"
@@ -502,18 +502,18 @@ allocation {
# Configuration option allocation/thin_pool_discards.
# The discards behaviour of thin pool volumes.
- #
+ #
# Accepted values:
# ignore
# nopassdown
# passdown
- #
+ #
# This configuration option has an automatic default value.
# thin_pool_discards = "passdown"
# Configuration option allocation/thin_pool_chunk_size_policy.
# The chunk size calculation policy for thin pool volumes.
- #
+ #
# Accepted values:
# generic
# If thin_pool_chunk_size is defined, use it. Otherwise, calculate
@@ -525,7 +525,7 @@ allocation {
# the chunk size for performance based on device hints exposed in
# sysfs - the optimal_io_size. The chunk size is always at least
# 512KiB.
- #
+ #
# This configuration option has an automatic default value.
# thin_pool_chunk_size_policy = "generic"
@@ -962,7 +962,7 @@ global {
# Configuration option global/mirror_segtype_default.
# The segment type used by the short mirroring option -m.
# The --type mirror|raid1 option overrides this setting.
- #
+ #
# Accepted values:
# mirror
# The original RAID1 implementation from LVM/DM. It is
@@ -982,16 +982,16 @@ global {
# handling a failure. This mirror implementation is not
# cluster-aware and cannot be used in a shared (active/active)
# fashion in a cluster.
- #
+ #
mirror_segtype_default = "@DEFAULT_MIRROR_SEGTYPE@"
# Configuration option global/support_mirrored_mirror_log.
# Enable mirrored 'mirror' log type for testing.
- #
+ #
# This type is deprecated to create or convert to but can
# be enabled to test that activation of existing mirrored
# logs and conversion to disk/core works.
- #
+ #
# Not supported for regular operation!
# This configuration option has an automatic default value.
# support_mirrored_mirror_log = 0
@@ -1002,7 +1002,7 @@ global {
# The --stripes/-i and --mirrors/-m options can both be specified
# during the creation of a logical volume to use both striping and
# mirroring for the LV. There are two different implementations.
- #
+ #
# Accepted values:
# raid10
# LVM uses MD's RAID10 personality through DM. This is the
@@ -1012,7 +1012,7 @@ global {
# is done by creating a mirror LV on top of striped sub-LVs,
# effectively creating a RAID 0+1 array. The layering is suboptimal
# in terms of providing redundancy and performance.
- #
+ #
raid10_segtype_default = "@DEFAULT_RAID10_SEGTYPE@"
# Configuration option global/sparse_segtype_default.
@@ -1020,7 +1020,7 @@ global {
# The --type snapshot|thin option overrides this setting.
# The combination of -V and -L options creates a sparse LV. There are
# two different implementations.
- #
+ #
# Accepted values:
# snapshot
# The original snapshot implementation from LVM/DM. It uses an old
@@ -1032,7 +1032,7 @@ global {
# bigger minimal chunk size (64KiB) and uses a separate volume for
# metadata. It has better performance, especially when more data
# is used. It also supports full snapshots.
- #
+ #
sparse_segtype_default = "@DEFAULT_SPARSE_SEGTYPE@"
# Configuration option global/lvdisplay_shows_full_device_path.
@@ -1130,20 +1130,20 @@ global {
# causing problems. Features include: block_size, discards,
# discards_non_power_2, external_origin, metadata_resize,
# external_origin_extend, error_if_no_space.
- #
+ #
# Example
# thin_disabled_features = [ "discards", "block_size" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option global/cache_disabled_features.
# Features to not use in the cache driver.
# This can be helpful for testing, or to avoid using a feature that is
# causing problems. Features include: policy_mq, policy_smq, metadata2.
- #
+ #
# Example
# cache_disabled_features = [ "policy_smq" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option global/cache_check_executable.
@@ -1207,7 +1207,7 @@ global {
# or vgimport.) A VG on shared storage devices is accessible only to
# the host with a matching system ID. See 'man lvmsystemid' for
# information on limitations and correct usage.
- #
+ #
# Accepted values:
# none
# The host has no system ID.
@@ -1224,7 +1224,7 @@ global {
# file
# Use the contents of another file (system_id_file) to set the
# system ID.
- #
+ #
system_id_source = "none"
# Configuration option global/system_id_file.
@@ -1350,7 +1350,7 @@ activation {
# If this list is defined, an LV is only activated if it matches an
# entry in this list. If this list is undefined, it imposes no limits
# on LV activation (all are allowed).
- #
+ #
# Accepted values:
# vgname
# The VG name is matched exactly and selects all LVs in the VG.
@@ -1364,10 +1364,10 @@ activation {
# or VG. See tags/hosttags. If any host tags exist but volume_list
# is not defined, a default single-entry list containing '@*'
# is assumed.
- #
+ #
# Example
# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option activation/auto_activation_volume_list.
@@ -1387,7 +1387,7 @@ activation {
# commands run directly by a user. A user may also use the 'a' flag
# directly to perform auto-activation. Also see pvscan(8) for more
# information about auto-activation.
- #
+ #
# Accepted values:
# vgname
# The VG name is matched exactly and selects all LVs in the VG.
@@ -1401,10 +1401,10 @@ activation {
# or VG. See tags/hosttags. If any host tags exist but volume_list
# is not defined, a default single-entry list containing '@*'
# is assumed.
- #
+ #
# Example
# auto_activation_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option activation/read_only_volume_list.
@@ -1413,7 +1413,7 @@ activation {
# against this list, and if it matches, it is activated in read-only
# mode. This overrides the permission setting stored in the metadata,
# e.g. from --permission rw.
- #
+ #
# Accepted values:
# vgname
# The VG name is matched exactly and selects all LVs in the VG.
@@ -1427,10 +1427,10 @@ activation {
# or VG. See tags/hosttags. If any host tags exist but volume_list
# is not defined, a default single-entry list containing '@*'
# is assumed.
- #
+ #
# Example
# read_only_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option activation/raid_region_size.
@@ -1453,13 +1453,13 @@ activation {
# Configuration option activation/readahead.
# Setting to use when there is no readahead setting in metadata.
- #
+ #
# Accepted values:
# none
# Disable readahead.
# auto
# Use default value chosen by kernel.
- #
+ #
# This configuration option has an automatic default value.
# readahead = "auto"
@@ -1471,7 +1471,7 @@ activation {
# performed by dmeventd automatically, and the steps perfomed by the
# manual command lvconvert --repair --use-policies.
# Automatic handling requires dmeventd to be monitoring the LV.
- #
+ #
# Accepted values:
# warn
# Use the system log to warn the user that a device in the RAID LV
@@ -1482,7 +1482,7 @@ activation {
# allocate
# Attempt to use any extra physical volumes in the VG as spares and
# replace faulty devices.
- #
+ #
raid_fault_policy = "warn"
# Configuration option activation/mirror_image_fault_policy.
@@ -1494,7 +1494,7 @@ activation {
# determines the steps perfomed by dmeventd automatically, and the steps
# performed by the manual command lvconvert --repair --use-policies.
# Automatic handling requires dmeventd to be monitoring the LV.
- #
+ #
# Accepted values:
# remove
# Simply remove the faulty device and run without it. If the log
@@ -1519,7 +1519,7 @@ activation {
# the redundant nature of the mirror. This policy acts like
# 'remove' if no suitable device and space can be allocated for the
# replacement.
- #
+ #
mirror_image_fault_policy = "remove"
# Configuration option activation/mirror_log_fault_policy.
@@ -1534,26 +1534,26 @@ activation {
# The minimum value is 50 (a smaller value is treated as 50.)
# Also see snapshot_autoextend_percent.
# Automatic extension requires dmeventd to be monitoring the LV.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
# snapshot exceeds 700M, it is extended to 1.2G, and when it exceeds
# 840M, it is extended to 1.44G:
# snapshot_autoextend_threshold = 70
- #
+ #
snapshot_autoextend_threshold = 100
# Configuration option activation/snapshot_autoextend_percent.
# Auto-extending a snapshot adds this percent extra space.
# The amount of additional space added to a snapshot is this
# percent of its current size.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
# snapshot exceeds 700M, it is extended to 1.2G, and when it exceeds
# 840M, it is extended to 1.44G:
# snapshot_autoextend_percent = 20
- #
+ #
snapshot_autoextend_percent = 20
# Configuration option activation/thin_pool_autoextend_threshold.
@@ -1562,26 +1562,26 @@ activation {
# The minimum value is 50 (a smaller value is treated as 50.)
# Also see thin_pool_autoextend_percent.
# Automatic extension requires dmeventd to be monitoring the LV.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
# thin pool exceeds 700M, it is extended to 1.2G, and when it exceeds
# 840M, it is extended to 1.44G:
# thin_pool_autoextend_threshold = 70
- #
+ #
thin_pool_autoextend_threshold = 100
# Configuration option activation/thin_pool_autoextend_percent.
# Auto-extending a thin pool adds this percent extra space.
# The amount of additional space added to a thin pool is this
# percent of its current size.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
# thin pool exceeds 700M, it is extended to 1.2G, and when it exceeds
# 840M, it is extended to 1.44G:
# thin_pool_autoextend_percent = 20
- #
+ #
thin_pool_autoextend_percent = 20
# Configuration option activation/vdo_pool_autoextend_threshold.
@@ -1590,13 +1590,13 @@ activation {
# The minimum value is 50 (a smaller value is treated as 50.)
# Also see vdo_pool_autoextend_percent.
# Automatic extension requires dmeventd to be monitoring the LV.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 10G
# VDO pool exceeds 7G, it is extended to 12G, and when it exceeds
# 8.4G, it is extended to 14.4G:
# vdo_pool_autoextend_threshold = 70
- #
+ #
# This configuration option has an automatic default value.
# vdo_pool_autoextend_threshold = 100
@@ -1604,7 +1604,7 @@ activation {
# Auto-extending a VDO pool adds this percent extra space.
# The amount of additional space added to a VDO pool is this
# percent of its current size.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 10G
# VDO pool exceeds 7G, it is extended to 12G, and when it exceeds
@@ -1623,10 +1623,10 @@ activation {
# pages corresponding to lines that match are not pinned. On some
# systems, locale-archive was found to make up over 80% of the memory
# used by the process.
- #
+ #
# Example
# mlock_filter = [ "locale/locale-archive", "gconv/gconv-modules.cache" ]
- #
+ #
# This configuration option is advanced.
# This configuration option does not have a default value defined.
@@ -1667,7 +1667,7 @@ activation {
# Configuration option activation/activation_mode.
# How LVs with missing devices are activated.
# The --activationmode option overrides this setting.
- #
+ #
# Accepted values:
# complete
# Only allow activation of an LV if all of the Physical Volumes it
@@ -1682,7 +1682,7 @@ activation {
# could cause data loss with a portion of the LV inaccessible.
# This setting should not normally be used, but may sometimes
# assist with data recovery.
- #
+ #
activation_mode = "degraded"
# Configuration option activation/lock_start_list.
@@ -1730,7 +1730,7 @@ activation {
# Configuration option metadata/pvmetadatacopies.
# Number of copies of metadata to store on each PV.
# The --pvmetadatacopies option overrides this setting.
- #
+ #
# Accepted values:
# 2
# Two copies of the VG metadata are stored on the PV, one at the
@@ -1740,7 +1740,7 @@ activation {
# 0
# No copies of VG metadata are stored on the PV. This may be
# useful for VGs containing large numbers of PVs.
- #
+ #
# This configuration option is advanced.
# This configuration option has an automatic default value.
# pvmetadatacopies = 1
@@ -1890,7 +1890,7 @@ activation {
# sequences are copied verbatim. Each special character sequence is
# introduced by the '%' character and such sequence is then
# substituted with a value as described below.
- #
+ #
# Accepted values:
# %a
# The abbreviated name of the day of the week according to the
@@ -2013,7 +2013,7 @@ activation {
# The timezone name or abbreviation.
# %%
# A literal '%' character.
- #
+ #
# This configuration option has an automatic default value.
# time_format = "%Y-%m-%d %T %z"
@@ -2282,12 +2282,12 @@ dmeventd {
# applied to the local machine as a 'host tag'. If this subsection is
# empty (has no host_list), then the subsection name is always applied
# as a 'host tag'.
- #
+ #
# Example
# The host tag foo is given to all hosts, and the host tag
# bar is given to the hosts named machine1 and machine2.
# tags { foo { } bar { host_list = [ "machine1", "machine2" ] } }
- #
+ #
# This configuration section has variable name.
# This configuration section has an automatic default value.
# tag {
diff --git a/conf/lvmlocal.conf.in b/conf/lvmlocal.conf.in
index 04414bf..12214ea 100644
--- a/conf/lvmlocal.conf.in
+++ b/conf/lvmlocal.conf.in
@@ -28,13 +28,13 @@ local {
# main configuration file, e.g. lvm.conf. When used, it must be set to
# a unique value among all hosts sharing access to the storage,
# e.g. a host name.
- #
+ #
# Example
# Set no system ID:
# system_id = ""
# Set the system_id to a specific name:
# system_id = "host1"
- #
+ #
# This configuration option has an automatic default value.
# system_id = ""
diff --git a/lib/config/config.c b/lib/config/config.c
index a25b7db..f9ca566 100644
--- a/lib/config/config.c
+++ b/lib/config/config.c
@@ -1738,7 +1738,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
continue;
commentline[0] = '\0';
}
- fprintf(out->fp, "%s# %s\n", line, commentline);
+ fprintf(out->fp, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline);
/* withsummary prints only the first comment line. */
if (!out->tree_spec->withcomments)
break;

View File

@ -0,0 +1,48 @@
From b3719266bd5e3a9e6737d6bda60e543121ddf343 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 9 Feb 2021 09:47:08 -0600
Subject: [PATCH] dev_get_primary_dev: fix invalid path check
Fix commit bee9f4efdd81 "filter-mpath: work with nvme devices"
which removed setting the path for readlink.
(cherry picked from commit f74f94c2ddb1d33d75d325c959344a566a621fd5)
Conflicts:
lib/device/dev-type.c
---
lib/device/dev-type.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 379afa8..1342e97 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -434,7 +434,7 @@ static int _has_sys_partition(struct device *dev)
int minor = (int) MINOR(dev->dev);
/* check if dev is a partition */
- if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
+ if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/partition",
dm_sysfs_dir(), major, minor) < 0) {
log_error("dm_snprintf partition failed");
return 0;
@@ -660,8 +660,13 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
* - basename ../../block/md0/md0 = md0
* Parent's 'dev' sysfs attribute = /sys/block/md0/dev
*/
- if ((size = readlink(dirname(path), temp_path, sizeof(temp_path) - 1)) < 0) {
- log_sys_error("readlink", path);
+ if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d",
+ dm_sysfs_dir(), major, minor) < 0) {
+ log_warn("WARNING: %s: major:minor sysfs path is too long.", dev_name(dev));
+ return 0;
+ }
+ if ((size = readlink(path, temp_path, sizeof(temp_path) - 1)) < 0) {
+ log_warn("WARNING: Readlink of %s failed.", path);
goto out;
}
--
1.8.3.1

View File

@ -0,0 +1,255 @@
lib/device/dev-cache.c | 161 ++++++++++++++++++++++++++++++++++++----------
test/shell/dev-aliases.sh | 53 +++++++++++++++
2 files changed, 179 insertions(+), 35 deletions(-)
create mode 100644 test/shell/dev-aliases.sh
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index d5f18ff..8082efa 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -1428,60 +1428,151 @@ struct device *dev_hash_get(const char *name)
return (struct device *) dm_hash_lookup(_cache.names, name);
}
+static void _remove_alias(struct device *dev, const char *name)
+{
+ struct dm_str_list *strl;
+
+ dm_list_iterate_items(strl, &dev->aliases) {
+ if (!strcmp(strl->str, name)) {
+ dm_list_del(&strl->list);
+ return;
+ }
+ }
+}
+
+/*
+ * Check that paths for this dev still refer to the same dev_t. This is known
+ * to drop invalid paths in the case where lvm deactivates an LV, which causes
+ * that LV path to go away, but that LV path is not removed from dev-cache (it
+ * probably should be). Later a new path to a different LV is added to
+ * dev-cache, where the new LV has the same major:minor as the previously
+ * deactivated LV. The new LV will find the existing struct dev, and that
+ * struct dev will have dev->aliases entries that refer to the name of the old
+ * deactivated LV. Those old paths are all invalid and are dropped here.
+ */
+
+static void _verify_aliases(struct device *dev, const char *newname)
+{
+ struct dm_str_list *strl, *strl2;
+ struct stat st;
+
+ dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
+ /* newname was just stat'd and added by caller */
+ if (newname && !strcmp(strl->str, newname))
+ continue;
+
+ if (stat(strl->str, &st) || (st.st_rdev != dev->dev)) {
+ log_debug("Drop invalid path %s for %d:%d (new path %s).",
+ strl->str, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), newname ?: "");
+ dm_hash_remove(_cache.names, strl->str);
+ dm_list_del(&strl->list);
+ }
+ }
+}
+
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f)
{
- struct stat buf;
- struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
- int info_available = 0;
- int ret = 1;
+ struct device *dev = (struct device *) dm_hash_lookup(_cache.names, name);
+ struct stat st;
+ int ret;
- if (d && (d->flags & DEV_REGULAR))
- return d;
+ /*
+ * DEV_REGULAR means that is "dev" is actually a file, not a device.
+ * FIXME: I don't think dev-cache is used for files any more and this
+ * can be dropped?
+ */
+ if (dev && (dev->flags & DEV_REGULAR))
+ return dev;
+
+ /*
+ * The requested path is invalid, remove any dev-cache
+ * info for it.
+ */
+ if (stat(name, &st)) {
+ if (dev) {
+ log_print("Device path %s is invalid for %d:%d %s.",
+ name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
- /* If the entry's wrong, remove it */
- if (stat(name, &buf) < 0) {
- if (d)
dm_hash_remove(_cache.names, name);
- log_sys_very_verbose("stat", name);
- d = NULL;
- } else
- info_available = 1;
- if (d && (buf.st_rdev != d->dev)) {
- dm_hash_remove(_cache.names, name);
- d = NULL;
- }
+ _remove_alias(dev, name);
- if (!d) {
- _insert(name, info_available ? &buf : NULL, 0, obtain_device_list_from_udev());
- d = (struct device *) dm_hash_lookup(_cache.names, name);
- if (!d) {
- log_debug_devs("Device name not found in dev_cache repeat dev_cache_scan for %s", name);
- dev_cache_scan();
- d = (struct device *) dm_hash_lookup(_cache.names, name);
+ /* Remove any other names in dev->aliases that are incorrect. */
+ _verify_aliases(dev, NULL);
}
+ return NULL;
}
- if (!d)
+ if (!S_ISBLK(st.st_mode)) {
+ log_debug("Not a block device %s.", name);
return NULL;
+ }
- if (d && (d->flags & DEV_REGULAR))
- return d;
+ /*
+ * dev-cache has incorrect info for the requested path.
+ * Remove incorrect info and then add new dev-cache entry.
+ */
+ if (dev && (st.st_rdev != dev->dev)) {
+ log_print("Device path %s does not match %d:%d %s.",
+ name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
+
+ dm_hash_remove(_cache.names, name);
+
+ _remove_alias(dev, name);
+
+ /* Remove any other names in dev->aliases that are incorrect. */
+ _verify_aliases(dev, NULL);
+
+ /* Add new dev-cache entry next. */
+ dev = NULL;
+ }
+
+ /*
+ * Either add a new struct dev for st_rdev and name,
+ * or add name as a new alias for an existing struct dev
+ * for st_rdev.
+ */
+ if (!dev) {
+ _insert_dev(name, st.st_rdev);
- if (f && !(d->flags & DEV_REGULAR)) {
- ret = f->passes_filter(cmd, f, d, NULL);
+ /* Get the struct dev that was just added. */
+ dev = (struct device *) dm_hash_lookup(_cache.names, name);
- if (ret == -EAGAIN) {
- log_debug_devs("get device by name defer filter %s", dev_name(d));
- d->flags |= DEV_FILTER_AFTER_SCAN;
- ret = 1;
+ if (!dev) {
+ log_error("Failed to get device %s", name);
+ return NULL;
}
+
+ _verify_aliases(dev, name);
}
- if (f && !(d->flags & DEV_REGULAR) && !ret)
+ /*
+ * The caller passed a filter if they only want the dev if it
+ * passes filters.
+ */
+
+ if (!f)
+ return dev;
+
+ ret = f->passes_filter(cmd, f, dev, NULL);
+
+ /*
+ * This might happen if this function is called before
+ * filters can do i/o. I don't think this will happen
+ * any longer and this EAGAIN case can be removed.
+ */
+ if (ret == -EAGAIN) {
+ log_debug_devs("dev_cache_get filter deferred %s", dev_name(dev));
+ dev->flags |= DEV_FILTER_AFTER_SCAN;
+ ret = 1;
+ }
+
+ if (!ret) {
+ log_debug_devs("dev_cache_get filter excludes %s", dev_name(dev));
return NULL;
+ }
- return d;
+ return dev;
}
static struct device *_dev_cache_seek_devt(dev_t dev)
diff --git a/test/shell/dev-aliases.sh b/test/shell/dev-aliases.sh
new file mode 100644
index 0000000..c97cd5d
--- /dev/null
+++ b/test/shell/dev-aliases.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2012 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
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux prepare_devs 3
+
+vgcreate $vg $dev1 $dev2 $dev3
+
+#
+# This lvconvert command will deactivate LV1, then internally create a new
+# lv, lvol0, as a poolmetadataspare, then activate lvol0 to zero it.
+# lvol0 will get the same major:minor that LV1 had. When the code gets
+# the struct dev for lvol0, the new path to lvol0 is added to the
+# dev-cache with it's major:minor. That major:minor already exists in
+# dev-cache and has the stale LV1 as an alias. So the path to lvol0 is
+# added as an alias to the existing struct dev (with the correct
+# major:minor), but that struct dev has the stale LV1 path on its aliases
+# list. The code will now validate all the aliases before returning the
+# dev for lvol0, and will find that the LV1 path is stale and remove it
+# from the aliases. That will prevent the stale path from being used for
+# the dev in place of the new path.
+#
+# The preferred_name is set to /dev/mapper so that if the stale path still
+# exists, that stale path would be used as the name for the dev, and the
+# wiping code would fail to open that stale name.
+#
+
+lvcreate -n $lv1 -L32M $vg $dev1
+lvcreate -n $lv2 -L16M $vg $dev2
+lvconvert -y --type cache-pool --poolmetadata $lv2 --cachemode writeback $vg/$lv1 --config='devices { preferred_names=["/dev/mapper/"] }'
+lvremove -y $vg/$lv1
+
+lvcreate -n $lv1 -L32M $vg $dev1
+lvcreate -n $lv2 -L16M $vg $dev2
+lvconvert -y --type cache-pool --poolmetadata $lv2 $vg/$lv1
+lvremove -y $vg/$lv1
+
+# TODO: add more validation of dev aliases being specified as command
+# args in combination with various preferred_names settings.
+
+vgremove -ff $vg

View File

@ -0,0 +1,494 @@
lib/device/dev-type.c | 81 +++++++++++++++++++----
lib/device/dev-type.h | 2 +
lib/device/device.h | 1 +
lib/filters/filter-mpath.c | 156 ++++++++++++++++++++++++++++++---------------
4 files changed, 177 insertions(+), 63 deletions(-)
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 896821d..379afa8 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -21,6 +21,7 @@
#include "lib/metadata/metadata.h"
#include "lib/device/bcache.h"
#include "lib/label/label.h"
+#include "lib/commands/toolcontext.h"
#ifdef BLKID_WIPING_SUPPORT
#include <blkid.h>
@@ -67,6 +68,31 @@ int dev_is_pmem(struct device *dev)
return is_pmem ? 1 : 0;
}
+/*
+ * An nvme device has major number 259 (BLKEXT), minor number <minor>,
+ * and reading /sys/dev/block/259:<minor>/device/dev shows a character
+ * device cmajor:cminor where cmajor matches the major number of the
+ * nvme character device entry in /proc/devices. Checking all of that
+ * is excessive and unnecessary compared to just comparing /dev/name*.
+ */
+
+int dev_is_nvme(struct dev_types *dt, struct device *dev)
+{
+ struct dm_str_list *strl;
+
+ if (dev->flags & DEV_IS_NVME)
+ return 1;
+
+ dm_list_iterate_items(strl, &dev->aliases) {
+ if (!strncmp(strl->str, "/dev/nvme", 9)) {
+ log_debug("Found nvme device %s", dev_name(dev));
+ dev->flags |= DEV_IS_NVME;
+ return 1;
+ }
+ }
+ return 0;
+}
+
int dev_is_lv(struct device *dev)
{
FILE *fp;
@@ -302,6 +328,9 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
const char *dev_subsystem_name(struct dev_types *dt, struct device *dev)
{
+ if (dev->flags & DEV_IS_NVME)
+ return "NVME";
+
if (MAJOR(dev->dev) == dt->device_mapper_major)
return "DM";
@@ -348,7 +377,6 @@ int major_is_scsi_device(struct dev_types *dt, int major)
return (dt->dev_type_array[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0;
}
-
static int _loop_is_with_partscan(struct device *dev)
{
FILE *fp;
@@ -398,6 +426,28 @@ struct partition {
uint32_t nr_sects;
} __attribute__((packed));
+static int _has_sys_partition(struct device *dev)
+{
+ char path[PATH_MAX];
+ struct stat info;
+ int major = (int) MAJOR(dev->dev);
+ int minor = (int) MINOR(dev->dev);
+
+ /* check if dev is a partition */
+ if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
+ dm_sysfs_dir(), major, minor) < 0) {
+ log_error("dm_snprintf partition failed");
+ return 0;
+ }
+
+ if (stat(path, &info) == -1) {
+ if (errno != ENOENT)
+ log_sys_error("stat", path);
+ return 0;
+ }
+ return 1;
+}
+
static int _is_partitionable(struct dev_types *dt, struct device *dev)
{
int parts = major_max_partitions(dt, MAJOR(dev->dev));
@@ -414,6 +464,13 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
_loop_is_with_partscan(dev))
return 1;
+ if (dev_is_nvme(dt, dev)) {
+ /* If this dev is already a partition then it's not partitionable. */
+ if (_has_sys_partition(dev))
+ return 0;
+ return 1;
+ }
+
if ((parts <= 1) || (MINOR(dev->dev) % parts))
return 0;
@@ -557,11 +614,18 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
char path[PATH_MAX];
char temp_path[PATH_MAX];
char buffer[64];
- struct stat info;
FILE *fp = NULL;
int parts, residue, size, ret = 0;
/*
+ * /dev/nvme devs don't use the major:minor numbering like
+ * block dev types that have their own major number, so
+ * the calculation based on minor number doesn't work.
+ */
+ if (dev_is_nvme(dt, dev))
+ goto sys_partition;
+
+ /*
* Try to get the primary dev out of the
* list of known device types first.
*/
@@ -576,23 +640,14 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
goto out;
}
+ sys_partition:
/*
* If we can't get the primary dev out of the list of known device
* types, try to look at sysfs directly then. This is more complex
* way and it also requires certain sysfs layout to be present
* which might not be there in old kernels!
*/
-
- /* check if dev is a partition */
- if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
- sysfs_dir, major, minor) < 0) {
- log_error("dm_snprintf partition failed");
- goto out;
- }
-
- if (stat(path, &info) == -1) {
- if (errno != ENOENT)
- log_sys_error("stat", path);
+ if (!_has_sys_partition(dev)) {
*result = dev->dev;
ret = 1;
goto out; /* dev is not a partition! */
diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
index fdf7791..8b94b79 100644
--- a/lib/device/dev-type.h
+++ b/lib/device/dev-type.h
@@ -95,6 +95,8 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev);
int dev_is_pmem(struct device *dev);
+int dev_is_nvme(struct dev_types *dt, struct device *dev);
+
int dev_is_lv(struct device *dev);
int get_fs_block_size(struct device *dev, uint32_t *fs_block_size);
diff --git a/lib/device/device.h b/lib/device/device.h
index a58bff8..816db31 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -38,6 +38,7 @@
#define DEV_SCAN_FOUND_LABEL 0x00010000 /* label scan read dev and found label */
#define DEV_IS_MD_COMPONENT 0x00020000 /* device is an md component */
#define DEV_UDEV_INFO_MISSING 0x00040000 /* we have no udev info for this device */
+#define DEV_IS_NVME 0x00080000 /* set if dev is nvme */
/*
* Support for external device info.
diff --git a/lib/filters/filter-mpath.c b/lib/filters/filter-mpath.c
index 85d1625..40e7df6 100644
--- a/lib/filters/filter-mpath.c
+++ b/lib/filters/filter-mpath.c
@@ -16,6 +16,7 @@
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
#include "lib/activate/activate.h"
+#include "lib/commands/toolcontext.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "lib/device/dev-ext-udev-constants.h"
@@ -27,7 +28,6 @@
#define MPATH_PREFIX "mpath-"
-
struct mpath_priv {
struct dm_pool *mem;
struct dev_filter f;
@@ -35,6 +35,9 @@ struct mpath_priv {
struct dm_hash_table *hash;
};
+/*
+ * given "/dev/foo" return "foo"
+ */
static const char *_get_sysfs_name(struct device *dev)
{
const char *name;
@@ -53,6 +56,11 @@ static const char *_get_sysfs_name(struct device *dev)
return name;
}
+/*
+ * given major:minor
+ * readlink translates /sys/dev/block/major:minor to /sys/.../foo
+ * from /sys/.../foo return "foo"
+ */
static const char *_get_sysfs_name_by_devt(const char *sysfs_dir, dev_t devno,
char *buf, size_t buf_size)
{
@@ -102,27 +110,28 @@ static int _get_sysfs_string(const char *path, char *buffer, int max_size)
return r;
}
-static int _get_sysfs_get_major_minor(const char *sysfs_dir, const char *kname, int *major, int *minor)
+static int _get_sysfs_dm_mpath(struct dev_types *dt, const char *sysfs_dir, const char *holder_name)
{
- char path[PATH_MAX], buffer[64];
+ char path[PATH_MAX];
+ char buffer[128];
- if (dm_snprintf(path, sizeof(path), "%s/block/%s/dev", sysfs_dir, kname) < 0) {
+ if (dm_snprintf(path, sizeof(path), "%sblock/%s/dm/uuid", sysfs_dir, holder_name) < 0) {
log_error("Sysfs path string is too long.");
return 0;
}
+ buffer[0] = '\0';
+
if (!_get_sysfs_string(path, buffer, sizeof(buffer)))
return_0;
- if (sscanf(buffer, "%d:%d", major, minor) != 2) {
- log_error("Failed to parse major minor from %s", buffer);
- return 0;
- }
+ if (!strncmp(buffer, MPATH_PREFIX, 6))
+ return 1;
- return 1;
+ return 0;
}
-static int _get_parent_mpath(const char *dir, char *name, int max_size)
+static int _get_holder_name(const char *dir, char *name, int max_size)
{
struct dirent *d;
DIR *dr;
@@ -155,7 +164,7 @@ static int _get_parent_mpath(const char *dir, char *name, int max_size)
}
#ifdef UDEV_SYNC_SUPPORT
-static int _udev_dev_is_mpath(struct device *dev)
+static int _udev_dev_is_mpath_component(struct device *dev)
{
const char *value;
struct dev_ext *ext;
@@ -174,95 +183,148 @@ static int _udev_dev_is_mpath(struct device *dev)
return 0;
}
#else
-static int _udev_dev_is_mpath(struct device *dev)
+static int _udev_dev_is_mpath_component(struct device *dev)
{
return 0;
}
#endif
-static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
+static int _native_dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
{
struct mpath_priv *mp = (struct mpath_priv *) f->private;
struct dev_types *dt = mp->dt;
- const char *part_name, *name;
- struct stat info;
- char path[PATH_MAX], parent_name[PATH_MAX];
+ const char *part_name;
+ const char *name; /* e.g. "sda" for "/dev/sda" */
+ char link_path[PATH_MAX]; /* some obscure, unpredictable sysfs path */
+ char holders_path[PATH_MAX]; /* e.g. "/sys/block/sda/holders/" */
+ char dm_dev_path[PATH_MAX]; /* e.g. "/dev/dm-1" */
+ char holder_name[128] = { 0 }; /* e.g. "dm-1" */
const char *sysfs_dir = dm_sysfs_dir();
- int major = MAJOR(dev->dev);
- int minor = MINOR(dev->dev);
+ int dev_major = MAJOR(dev->dev);
+ int dev_minor = MINOR(dev->dev);
+ int dm_dev_major;
+ int dm_dev_minor;
+ struct stat info;
dev_t primary_dev;
long look;
- /* Limit this filter only to SCSI devices */
- if (!major_is_scsi_device(dt, MAJOR(dev->dev)))
+ /* Limit this filter to SCSI or NVME devices */
+ if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
return 0;
switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
+
case 2: /* The dev is partition. */
part_name = dev_name(dev); /* name of original dev for log_debug msg */
- if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, parent_name, sizeof(parent_name))))
+
+ /* gets "foo" for "/dev/foo" where "/dev/foo" comes from major:minor */
+ if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
return_0;
+
log_debug_devs("%s: Device is a partition, using primary "
"device %s for mpath component detection",
part_name, name);
break;
+
case 1: /* The dev is already a primary dev. Just continue with the dev. */
+
+ /* gets "foo" for "/dev/foo" */
if (!(name = _get_sysfs_name(dev)))
return_0;
break;
+
default: /* 0, error. */
- log_warn("Failed to get primary device for %d:%d.", major, minor);
+ log_warn("Failed to get primary device for %d:%d.", dev_major, dev_minor);
return 0;
}
- if (dm_snprintf(path, sizeof(path), "%s/block/%s/holders", sysfs_dir, name) < 0) {
+ if (dm_snprintf(holders_path, sizeof(holders_path), "%sblock/%s/holders", sysfs_dir, name) < 0) {
log_warn("Sysfs path to check mpath is too long.");
return 0;
}
/* also will filter out partitions */
- if (stat(path, &info))
+ if (stat(holders_path, &info))
return 0;
if (!S_ISDIR(info.st_mode)) {
- log_warn("Path %s is not a directory.", path);
+ log_warn("Path %s is not a directory.", holders_path);
return 0;
}
- if (!_get_parent_mpath(path, parent_name, sizeof(parent_name)))
+ /*
+ * If holders dir contains an entry such as "dm-1", then this sets
+ * holder_name to "dm-1".
+ *
+ * If holders dir is empty, return 0 (this is generally where
+ * devs that are not mpath components return.)
+ */
+ if (!_get_holder_name(holders_path, holder_name, sizeof(holder_name)))
return 0;
- if (!_get_sysfs_get_major_minor(sysfs_dir, parent_name, &major, &minor))
- return_0;
+ if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0) {
+ log_warn("dm device path to check mpath is too long.");
+ return 0;
+ }
- if (major != dt->device_mapper_major)
+ /*
+ * stat "/dev/dm-1" which is the holder of the dev we're checking
+ * dm_dev_major:dm_dev_minor come from stat("/dev/dm-1")
+ */
+ if (stat(dm_dev_path, &info)) {
+ log_debug("filter-mpath %s holder %s stat result %d",
+ dev_name(dev), dm_dev_path, errno);
return 0;
+ }
+ dm_dev_major = (int)MAJOR(info.st_rdev);
+ dm_dev_minor = (int)MINOR(info.st_rdev);
+
+ if (dm_dev_major != dt->device_mapper_major) {
+ log_debug_devs("filter-mpath %s holder %s %d:%d does not have dm major",
+ dev_name(dev), dm_dev_path, dm_dev_major, dm_dev_minor);
+ return 0;
+ }
- /* Avoid repeated detection of multipath device and use first checked result */
- look = (long) dm_hash_lookup_binary(mp->hash, &minor, sizeof(minor));
+ /*
+ * Save the result of checking that "/dev/dm-1" is an mpath device
+ * to avoid repeating it for each path component.
+ * The minor number of "/dev/dm-1" is added to the hash table with
+ * const value 2 meaning that dm minor 1 (for /dev/dm-1) is a multipath dev
+ * and const value 1 meaning that dm minor 1 is not a multipath dev.
+ */
+ look = (long) dm_hash_lookup_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor));
if (look > 0) {
- log_debug_devs("%s(%u:%u): already checked as %sbeing mpath.",
- parent_name, major, minor, (look > 1) ? "" : "not ");
+ log_debug_devs("filter-mpath %s holder %s %u:%u already checked as %sbeing mpath.",
+ dev_name(dev), holder_name, dm_dev_major, dm_dev_minor, (look > 1) ? "" : "not ");
return (look > 1) ? 1 : 0;
}
- if (lvm_dm_prefix_check(major, minor, MPATH_PREFIX)) {
- (void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)2);
+ /*
+ * Returns 1 if /sys/block/<holder_name>/dm/uuid indicates that
+ * <holder_name> is a dm device with dm uuid prefix mpath-.
+ * When true, <holder_name> will be something like "dm-1".
+ *
+ * (Is a hash table worth it to avoid reading one sysfs file?)
+ */
+ if (_get_sysfs_dm_mpath(dt, sysfs_dir, holder_name)) {
+ log_debug_devs("filter-mpath %s holder %s %u:%u ignore mpath component",
+ dev_name(dev), holder_name, dm_dev_major, dm_dev_minor);
+ (void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)2);
return 1;
}
- (void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)1);
+ (void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)1);
return 0;
}
-static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
+static int _dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
{
if (dev->ext.src == DEV_EXT_NONE)
- return _native_dev_is_mpath(f, dev);
+ return _native_dev_is_mpath_component(cmd, f, dev);
if (dev->ext.src == DEV_EXT_UDEV)
- return _udev_dev_is_mpath(dev);
+ return _udev_dev_is_mpath_component(dev);
log_error(INTERNAL_ERROR "Missing hook for mpath recognition "
"using external device info source %s", dev_ext_name(dev));
@@ -272,11 +334,11 @@ static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
#define MSG_SKIPPING "%s: Skipping mpath component device"
-static int _ignore_mpath(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
+static int _ignore_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
dev->filtered_flags &= ~DEV_FILTERED_MPATH_COMPONENT;
- if (_dev_is_mpath(f, dev) == 1) {
+ if (_dev_is_mpath_component(cmd, f, dev) == 1) {
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else
@@ -303,8 +365,8 @@ static void _destroy(struct dev_filter *f)
struct dev_filter *mpath_filter_create(struct dev_types *dt)
{
const char *sysfs_dir = dm_sysfs_dir();
- struct dm_pool *mem;
struct mpath_priv *mp;
+ struct dm_pool *mem;
struct dm_hash_table *hash;
if (!*sysfs_dir) {
@@ -328,19 +390,13 @@ struct dev_filter *mpath_filter_create(struct dev_types *dt)
goto bad;
}
- if (!(mp = dm_pool_zalloc(mem, sizeof(*mp)))) {
- log_error("mpath filter allocation failed.");
- goto bad;
- }
-
- mp->f.passes_filter = _ignore_mpath;
+ mp->f.passes_filter = _ignore_mpath_component;
mp->f.destroy = _destroy;
mp->f.use_count = 0;
mp->f.private = mp;
mp->f.name = "mpath";
-
- mp->mem = mem;
mp->dt = dt;
+ mp->mem = mem;
mp->hash = hash;
log_debug_devs("mpath filter initialised.");

View File

@ -0,0 +1,24 @@
lib/metadata/integrity_manip.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/lib/metadata/integrity_manip.c b/lib/metadata/integrity_manip.c
index 53ab1b3..abf90d8 100644
--- a/lib/metadata/integrity_manip.c
+++ b/lib/metadata/integrity_manip.c
@@ -773,9 +773,13 @@ int lv_add_integrity_to_raid(struct logical_volume *lv, struct integrity_setting
bad:
log_error("Failed to add integrity.");
- for (s = 0; s < revert_meta_lvs; s++) {
- if (!lv_remove(imeta_lvs[s]))
- log_error("New integrity metadata LV may require manual removal.");
+ if (revert_meta_lvs) {
+ for (s = 0; s < DEFAULT_RAID_MAX_IMAGES; s++) {
+ if (!imeta_lvs[s])
+ continue;
+ if (!lv_remove(imeta_lvs[s]))
+ log_error("New integrity metadata LV may require manual removal.");
+ }
}
if (!vg_write(vg) || !vg_commit(vg))

View File

@ -0,0 +1,19 @@
lib/label/label.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/label/label.c b/lib/label/label.c
index e067a6b..e6dd4a1 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1243,6 +1243,11 @@ int label_scan(struct cmd_context *cmd)
free(devl);
}
+ dm_list_iterate_items_safe(devl, devl2, &filtered_devs) {
+ dm_list_del(&devl->list);
+ free(devl);
+ }
+
/*
* If hints were not available/usable, then we scanned all devs,
* and we now know which are PVs. Save this list of PVs we've

View File

@ -0,0 +1,66 @@
WHATS_NEW | 4 ++++
lib/activate/activate.c | 5 +++++
lib/activate/activate.h | 2 ++
lib/metadata/lv_manip.c | 6 ++++++
4 files changed, 17 insertions(+)
diff --git a/WHATS_NEW b/WHATS_NEW
index 3953c7e..c8f869c 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,9 @@
Version 2.03.12 -
===================================
+ Check if lvcreate passes read_only_volume_list with tags and skips zeroing.
+ Limit pool metadata spare to 16GiB.
+ Improves conversion and allocation of pool metadata.
+ Support thin pool metadata 15.88GiB, adds 64MiB, thin_pool_crop_metadata=0.
Fix problem with wiping of converted LVs.
Fix memleak in scanning (2.03.11).
Fix corner case allocation for thin-pools.
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 7ed6441..de866fb 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -466,6 +466,11 @@ static int _passes_readonly_filter(struct cmd_context *cmd,
return _lv_passes_volumes_filter(cmd, lv, cn, activation_read_only_volume_list_CFG);
}
+int lv_passes_readonly_filter(const struct logical_volume *lv)
+{
+ return _passes_readonly_filter(lv->vg->cmd, lv);
+}
+
int library_version(char *version, size_t size)
{
if (!activation())
diff --git a/lib/activate/activate.h b/lib/activate/activate.h
index 3f4d128..53c8631 100644
--- a/lib/activate/activate.h
+++ b/lib/activate/activate.h
@@ -208,6 +208,8 @@ int lvs_in_vg_opened(const struct volume_group *vg);
int lv_is_active(const struct logical_volume *lv);
+int lv_passes_readonly_filter(const struct logical_volume *lv);
+
/* Check is any component LV is active */
const struct logical_volume *lv_component_is_active(const struct logical_volume *lv);
const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv);
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 445c4ad..5ff64a3 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -7976,6 +7976,12 @@ static int _should_wipe_lv(struct lvcreate_params *lp,
first_seg(first_seg(lv)->pool_lv)->zero_new_blocks))
return 0;
+ if (warn && (lv_passes_readonly_filter(lv))) {
+ log_warn("WARNING: Read-only activated logical volume %s not zeroed.",
+ display_lvname(lv));
+ return 0;
+ }
+
/* Cannot zero read-only volume */
if ((lv->status & LVM_WRITE) &&
(lp->zero || lp->wipe_signatures))

View File

@ -0,0 +1,29 @@
daemons/lvmlockd/lvmlockd-core.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
index fea8ee6..c4abf66 100644
--- a/daemons/lvmlockd/lvmlockd-core.c
+++ b/daemons/lvmlockd/lvmlockd-core.c
@@ -896,8 +896,9 @@ static int read_adopt_file(struct list_head *vg_lockd)
goto fail;
memset(vg_uuid, 0, sizeof(vg_uuid));
+ memset(lm_type_str, 0, sizeof(lm_type_str));
- if (sscanf(adopt_line, "VG: %63s %64s %16s %64s",
+ if (sscanf(adopt_line, "VG: %63s %64s %15s %64s",
vg_uuid, ls->vg_name, lm_type_str, ls->vg_args) != 4) {
goto fail;
}
@@ -916,8 +917,9 @@ static int read_adopt_file(struct list_head *vg_lockd)
r->type = LD_RT_LV;
memset(vg_uuid, 0, sizeof(vg_uuid));
+ memset(mode, 0, sizeof(mode));
- if (sscanf(adopt_line, "LV: %64s %64s %s %8s %u",
+ if (sscanf(adopt_line, "LV: %64s %64s %s %7s %u",
vg_uuid, r->name, r->lv_args, mode, &r->version) != 5) {
goto fail;
}

View File

@ -0,0 +1,18 @@
man/lvconvert.8_pregen | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen
index a47ccac..170eec8 100644
--- a/man/lvconvert.8_pregen
+++ b/man/lvconvert.8_pregen
@@ -772,6 +772,10 @@ Add a cache to an LV, using a specified cache device.
.br
.RS 4
.ad l
+[ \fB-c\fP|\fB--chunksize\fP \fISize\fP[k|UNIT] ]
+.ad b
+.br
+.ad l
[ \fB--cachesize\fP \fISize\fP[m|UNIT] ]
.ad b
.br

View File

@ -0,0 +1,86 @@
man/lvmthin.7_main | 37 +++++++++++++++++++++++++------------
1 file changed, 25 insertions(+), 12 deletions(-)
diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main
index ce23431..e6f1d63 100644
--- a/man/lvmthin.7_main
+++ b/man/lvmthin.7_main
@@ -394,7 +394,7 @@ the pmspare LV.
\&
If thin pool metadata is damaged, it may be repairable.
-Checking and repairing thin pool metadata is analagous to
+Checking and repairing thin pool metadata is analogous to
running fsck/repair on a file system.
When a thin pool LV is activated, lvm runs the thin_check command
@@ -437,14 +437,24 @@ copy to the VG's pmspare LV.
If step 1 is successful, the thin pool metadata LV is replaced
with the pmspare LV containing the corrected metadata.
The previous thin pool metadata LV, containing the damaged metadata,
-becomes visible with the new name ThinPoolLV_tmetaN (where N is 0,1,...).
-
-If the repair works, the thin pool LV and its thin LVs can be activated,
-and the LV containing the damaged thin pool metadata can be removed.
-It may be useful to move the new metadata LV (previously pmspare) to a
-better PV.
-
-If the repair does not work, the thin pool LV and its thin LVs are lost.
+becomes visible with the new name ThinPoolLV_metaN (where N is 0,1,...).
+
+If the repair works, the thin pool LV and its thin LVs can be activated.
+User should manually check if repaired thin pool kernel metadata
+has all data for all lvm2 known LVs by individual activation of
+every thin LV. When all works, user should continue with fsck of
+all filesystems present these such volumes.
+Once the thin pool is considered fully functional user may remove ThinPoolLV_metaN
+(the LV containing the damaged thin pool metadata) for possible
+space reuse.
+For a better performance it may be useful to pvmove the new repaired metadata LV
+(written to previous pmspare volume) to a better PV (i.e. SSD)
+
+If the repair operation fails, the thin pool LV and its thin LVs
+are not accessible and it may be necessary to restore their content
+from a backup. In such case the content of unmodified original damaged
+ThinPoolLV_metaN volume can be used by your support for more
+advanced recovery methods.
If metadata is manually restored with thin_repair directly,
the pool metadata LV can be manually swapped with another LV
@@ -452,6 +462,9 @@ containing new metadata:
.B lvconvert --thinpool VG/ThinPoolLV --poolmetadata VG/NewThinMetaLV
+Note: Thin pool metadata is compact so even small corruptions
+in them may result in significant portions of mappings to be lost.
+It is recommended to use fast resilient storage for them.
.SS Activation of thin snapshots
@@ -549,7 +562,7 @@ Command to extend thin pool data space:
.fi
Other methods of increasing free data space in a thin pool LV
-include removing a thin LV and its related snapsots, or running
+include removing a thin LV and its related snapshots, or running
fstrim on the file system using a thin LV.
@@ -689,7 +702,7 @@ with two configuration settings:
.B thin_pool_autoextend_threshold
.br
is a percentage full value that defines when the thin pool LV should be
-extended. Setting this to 100 disables automatic extention. The minimum
+extended. Setting this to 100 disables automatic extension. The minimum
value is 50.
.BR lvm.conf (5)
@@ -716,7 +729,7 @@ the --ignoremonitoring option can be used. With this option, the command
will not ask dmeventd to monitor the thin pool LV.
.IP \[bu]
-Setting thin_pool_autoextend_threshould to 100 disables automatic
+Setting thin_pool_autoextend_threshold to 100 disables automatic
extension of thin pool LVs, even if they are being monitored by dmeventd.
.P

View File

@ -0,0 +1,39 @@
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 b67882e..1975cb4 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -697,6 +697,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;
@@ -706,8 +708,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' ? */
@@ -718,6 +723,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;

View File

@ -0,0 +1,92 @@
lib/metadata/lv_manip.c | 48 ++++++++++++++++++++++++------------------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 443d32c..c740ba2 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1470,6 +1470,8 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
struct logical_volume *external_lv = NULL;
int is_raid10 = 0;
uint32_t data_copies = 0;
+ struct lv_list *lvl;
+ int is_last_pool = lv_is_pool(lv);
if (!dm_list_empty(&lv->segments)) {
seg = first_seg(lv);
@@ -1581,6 +1583,28 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
!lv_update_and_reload(external_lv))
return_0;
+ /* When removing last pool, automatically drop the spare volume */
+ if (is_last_pool && lv->vg->pool_metadata_spare_lv) {
+ /* TODO: maybe use a list of pools or a counter to avoid linear search through VG */
+ dm_list_iterate_items(lvl, &lv->vg->lvs)
+ if (lv_is_thin_type(lvl->lv) ||
+ lv_is_cache_type(lvl->lv)) {
+ is_last_pool = 0;
+ break;
+ }
+
+ if (is_last_pool) {
+ /* This is purely internal LV volume, no question */
+ if (!deactivate_lv(lv->vg->cmd, lv->vg->pool_metadata_spare_lv)) {
+ log_error("Unable to deactivate spare logical volume %s.",
+ display_lvname(lv->vg->pool_metadata_spare_lv));
+ return 0;
+ }
+ if (!lv_remove(lv->vg->pool_metadata_spare_lv))
+ return_0;
+ }
+ }
+
return 1;
}
@@ -6433,10 +6457,8 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
struct logical_volume *lock_lv = lv;
struct lv_segment *cache_seg = NULL;
int ask_discard;
- struct lv_list *lvl;
struct seg_list *sl;
struct lv_segment *seg = first_seg(lv);
- int is_last_pool = lv_is_pool(lv);
vg = lv->vg;
@@ -6558,9 +6580,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
*/
struct logical_volume *cachevol_lv = first_seg(lv)->pool_lv;
- if (lv_is_cache_pool(cachevol_lv))
- is_last_pool = 1;
-
if (!archive(vg))
return_0;
@@ -6667,25 +6686,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
return 0;
}
- if (is_last_pool && vg->pool_metadata_spare_lv) {
- /* When removed last pool, also remove the spare */
- dm_list_iterate_items(lvl, &vg->lvs)
- if (lv_is_pool_metadata(lvl->lv)) {
- is_last_pool = 0;
- break;
- }
- if (is_last_pool) {
- /* This is purely internal LV volume, no question */
- if (!deactivate_lv(cmd, vg->pool_metadata_spare_lv)) {
- log_error("Unable to deactivate spare logical volume %s.",
- display_lvname(vg->pool_metadata_spare_lv));
- return 0;
- }
- if (!lv_remove(vg->pool_metadata_spare_lv))
- return_0;
- }
- }
-
/* store it on disks */
if (!vg_write(vg) || !vg_commit(vg))
return_0;

View File

@ -0,0 +1,24 @@
tools/pvck.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/tools/pvck.c b/tools/pvck.c
index c36e182..88350de 100644
--- a/tools/pvck.c
+++ b/tools/pvck.c
@@ -1140,9 +1140,13 @@ static int _dump_label_and_pv_header(struct cmd_context *cmd, uint64_t labelsect
*mda1_offset = xlate64(dlocn->offset);
*mda1_size = xlate64(dlocn->size);
- if (*mda1_offset != 4096) {
- log_print("CHECK: pv_header.disk_locn[%d].offset expected 4096 # for first mda", di);
- bad++;
+ /*
+ * mda1 offset is page size from machine that created it,
+ * warn if it's not one of the expected page sizes.
+ */
+ if ((*mda1_offset != 4096) && (*mda1_offset != 8192) && (*mda1_offset != 65536)) {
+ log_print("WARNING: pv_header.disk_locn[%d].offset %llu is unexpected # for first mda",
+ di, (unsigned long long)*mda1_offset);
}
} else {
*mda2_offset = xlate64(dlocn->offset);

View File

@ -0,0 +1,19 @@
test/shell/tags.sh | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/test/shell/tags.sh b/test/shell/tags.sh
index fd1b332..5b636a8 100644
--- a/test/shell/tags.sh
+++ b/test/shell/tags.sh
@@ -52,6 +52,11 @@ check lv_field @firstlvtag1 tags "firstlvtag1"
not check lv_field @secondlvtag1 tags "firstlvtag1"
check lv_field $vg1/$lv2 tags "secondlvtag1"
not check lv_field $vg1/$lv1 tags "secondlvtag1"
+
+# LV is not zeroed when tag matches read only volume list
+lvcreate -l1 $vg1 --addtag "RO" --config "activation/read_only_volume_list = [ \"@RO\" ]" 2>&1 | tee out
+grep "not zeroed" out
+
vgremove -f $vg1
# lvchange with --addtag and --deltag

View File

@ -0,0 +1,98 @@
test/shell/thin-16g.sh | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 test/shell/thin-16g.sh
diff --git a/test/shell/thin-16g.sh b/test/shell/thin-16g.sh
new file mode 100644
index 0000000..ee7e22e
--- /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

View File

@ -0,0 +1,78 @@
test/shell/thin-zero-meta.sh | 68 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
create mode 100644 test/shell/thin-zero-meta.sh
diff --git a/test/shell/thin-zero-meta.sh b/test/shell/thin-zero-meta.sh
new file mode 100644
index 0000000..6a15a73
--- /dev/null
+++ b/test/shell/thin-zero-meta.sh
@@ -0,0 +1,68 @@
+#!/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 how zeroing of thin-pool metadata works
+
+SKIP_WITH_LVMLOCKD=1
+SKIP_WITH_LVMPOLLD=1
+
+export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false}
+
+. lib/inittest
+
+#
+# Main
+#
+aux have_thin 1 3 0 || skip
+aux have_cache 1 3 0 || skip
+
+aux prepare_vg 3 40000
+
+# Create mostly-zero devs only front of it has some 'real' back-end
+aux zero_dev "$dev1" "$(( $(get first_extent_sector "$dev1") + 8192 )):"
+aux zero_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 8192 )):"
+aux zero_dev "$dev3" "$(( $(get first_extent_sector "$dev3") + 8192 )):"
+
+# Prepare randomly filled 4M LV on dev2
+lvcreate -L16G -n $lv1 $vg "$dev2"
+dd if=/dev/urandom of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=4 oflag=direct || true
+lvremove -f $vg
+
+for i in 0 1
+do
+ aux lvmconf "allocation/zero_metadata = $i"
+
+ # Lvm2 should allocate metadata on dev2
+ lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2"
+ lvchange -an $vg
+
+ lvs -ao+seg_pe_ranges $vg
+ lvchange -ay $vg/pool_tmeta --yes
+
+ # Skip past 1.2M which is 'created' by thin-pool initialization
+ hexdump -C -n 200 -s 2000000 "$DM_DEV_DIR/$vg/pool_tmeta" | tee out
+
+ # When fully zeroed, it should be zero - so almost no output from hexdump
+ case "$i" in
+ 0) test $(wc -l < out) -ge 10 ;; # should not be zeroed
+ 1) test $(wc -l < out) -le 10 ;; # should be zeroed
+ esac
+
+ lvremove -f $vg/pool
+done
+
+# Check lvm2 spots error during full zeroing of metadata device
+aux error_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 32 )):"
+not lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2" |& tee err
+grep "Failed to initialize logical volume" err
+
+vgremove -ff $vg

View File

@ -0,0 +1,128 @@
test/shell/lvcreate-vdo-cache.sh | 17 +-------
test/shell/lvrename-vdo.sh | 88 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 90 insertions(+), 15 deletions(-)
create mode 100644 test/shell/lvrename-vdo.sh
diff --git a/test/shell/lvcreate-vdo-cache.sh b/test/shell/lvcreate-vdo-cache.sh
index c31cccc..6cf8437 100644
--- a/test/shell/lvcreate-vdo-cache.sh
+++ b/test/shell/lvcreate-vdo-cache.sh
@@ -32,22 +32,9 @@ export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf"
aux prepare_vg 1 9000
-lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
-
+lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool
# Test caching VDOPoolLV
-lvcreate -H -L10 $vg/vpool1
-
-# Current VDO target driver cannot handle online rename
-# once this will be supported - update this test
-not lvrename $vg/vpool1 $vg/vpool 2>&1 | tee out
-grep "Cannot rename" out
-
-lvchange -an $vg
-
-# Ofline should work
-lvrename $vg/vpool1 $vg/vpool
-
-lvchange -ay $vg
+lvcreate -H -L10 $vg/vpool
mkfs.ext4 -E nodiscard "$DM_DEV_DIR/$vg/$lv1"
diff --git a/test/shell/lvrename-vdo.sh b/test/shell/lvrename-vdo.sh
new file mode 100644
index 0000000..1417d9f
--- /dev/null
+++ b/test/shell/lvrename-vdo.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
+
+# Check online renaming of VDO devices works
+
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+#
+# Main
+#
+
+aux have_vdo 6 2 1 || skip
+aux have_cache 1 3 0 || skip
+aux have_raid 1 3 0 || skip
+
+aux prepare_vg 2 5000
+
+lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
+lvrename $vg/vpool1 vpool2
+check lv_exists $vg $lv1 vpool2 vpool2_vdata
+
+lvremove -ff $vg
+
+# With version >= 6.2.3 online rename should work
+if aux have_vdo 6 2 3 ; then
+
+### CACHE ####
+lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
+lvcreate -H -L10 $vg/vpool1
+lvrename $vg/vpool1 $vg/vpool2
+check lv_exists $vg vpool2 vpool2_vdata
+lvremove -ff $vg
+
+### RAID ####
+lvcreate --type raid1 -L4G --nosync --name vpool1 $vg
+lvconvert --yes --type vdo-pool $vg/vpool1
+lvrename $vg/vpool1 $vg/vpool2
+check lv_exists $vg vpool2 vpool2_vdata vpool2_vdata_rimage_0
+lvremove -ff $vg
+
+fi # >= 6.2.3
+
+# Check when VDO target does not support online resize
+aux lvmconf "global/vdo_disabled_features = [ \"online_rename\" ]"
+
+
+### CACHE ####
+lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
+lvcreate -H -L10 $vg/vpool1
+
+# VDO target driver cannot handle online rename
+not lvrename $vg/vpool1 $vg/vpool2 2>&1 | tee out
+grep "Cannot rename" out
+
+# Ofline should work
+lvchange -an $vg
+lvrename $vg/vpool1 $vg/vpool2
+lvchange -ay $vg
+check lv_exists $vg $lv1 vpool2 vpool2_vdata
+lvremove -ff $vg
+
+
+### RAID ####
+lvcreate --type raid1 -L4G --nosync --name vpool1 $vg
+lvconvert --yes --type vdo-pool $vg/vpool1
+not lvrename $vg/vpool1 $vg/vpool2 2>&1 | tee out
+grep "Cannot rename" out
+
+# Ofline should work
+lvchange -an $vg
+lvrename $vg/vpool1 $vg/vpool2
+lvchange -ay $vg
+check lv_exists $vg vpool2 vpool2_vdata vpool2_vdata_rimage_0
+lvremove -ff $vg
+
+vgremove -ff $vg

View File

@ -0,0 +1,47 @@
test/shell/lvcreate-thin-limits.sh | 30 ++++++++++++++++++++++++++----
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/test/shell/lvcreate-thin-limits.sh b/test/shell/lvcreate-thin-limits.sh
index 6a9c33d..5dcc160 100644
--- a/test/shell/lvcreate-thin-limits.sh
+++ b/test/shell/lvcreate-thin-limits.sh
@@ -27,13 +27,35 @@ aux can_use_16T || skip
aux have_thin 1 0 0 || skip
which mkfs.ext4 || skip
-aux prepare_pvs 1 16777216
+# 16T device
+aux prepare_pvs 2 8388608
get_devs
-vgcreate $SHARED -s 4K "$vg" "${DEVICES[@]}"
+# gives 16777215M device
+vgcreate $SHARED -s 4M "$vg" "${DEVICES[@]}"
-not lvcreate -T -L15.995T --poolmetadatasize 5G $vg/pool
+# For 1st. pass only single PV
+lvcreate -l100%PV --name $lv1 $vg "$dev2"
-lvs -ao+seg_pe_ranges $vg
+for i in 1 0
+do
+ SIZE=$(get vg_field "$vg" vg_free --units m)
+ SIZE=${SIZE%%\.*}
+
+ # ~16T - 2 * 5G + something -> should not fit
+ not lvcreate -Zn -T -L$(( SIZE - 2 * 5 * 1024 + 1 )) --poolmetadatasize 5G $vg/pool
+
+ check vg_field "$vg" lv_count "$i"
+
+ # Should fit data + metadata + pmspare
+ lvcreate -Zn -T -L$(( SIZE - 2 * 5 * 1024 )) --poolmetadatasize 5G $vg/pool
+
+ check vg_field "$vg" vg_free "0"
+
+ lvs -ao+seg_pe_ranges $vg
+
+ # Remove everything for 2nd. pass
+ lvremove -ff $vg
+done
vgremove -ff $vg

View File

@ -0,0 +1,77 @@
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 1319655..ee85691 100644
--- a/test/shell/lvconvert-thin.sh
+++ b/test/shell/lvconvert-thin.sh
@@ -128,7 +128,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 2c46e21..4d9d75e 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 0b622b7..2549035 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

View File

@ -0,0 +1,694 @@
conf/example.conf.in | 7 +++
device_mapper/all.h | 16 +++++--
device_mapper/libdm-deptree.c | 39 ++++++++++++-----
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 +
17 files changed, 256 insertions(+), 55 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index d149ed9..107a071 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -494,6 +494,13 @@ allocation {
# This configuration option has an automatic default value.
# 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/device_mapper/all.h b/device_mapper/all.h
index 1080d25..489ca1c 100644
--- a/device_mapper/all.h
+++ b/device_mapper/all.h
@@ -1072,10 +1072,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)
@@ -1088,6 +1088,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/device_mapper/libdm-deptree.c b/device_mapper/libdm-deptree.c
index 6ce956f..5b60dc9 100644
--- a/device_mapper/libdm-deptree.c
+++ b/device_mapper/libdm-deptree.c
@@ -3979,6 +3979,24 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
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;
@@ -4005,17 +4023,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);
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 8d27bd3..9a25482 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -261,7 +261,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;
@@ -297,7 +297,7 @@ 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;
/* Uses virtual size with headers for VDO pool device */
if (lv_is_vdo_pool(seg_status->seg->lv))
@@ -310,7 +310,9 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
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 3c4032e..cb4e23a 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -628,6 +628,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, CFG_DEFAULT_COMMENTED, 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, 3, 12), 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 708a575..bcc20cc 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -118,6 +118,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 bc93a5d..4cee14a 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_CACHE_VOL, "CACHE_VOL", COMPATIBLE_FLAG},
{LV_CACHE_USES_CACHEVOL, "CACHE_USES_CACHEVOL", SEGTYPE_FLAG},
{LV_NOSCAN, NULL, 0},
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 443d32c..445c4ad 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5384,6 +5384,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);
@@ -5544,6 +5546,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)
@@ -8388,6 +8417,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 0aa2293..eff59ae 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -495,6 +495,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 54dc29f..0e57722 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -143,6 +143,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 */
@@ -326,6 +327,12 @@ typedef enum {
} 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,
CACHE_MODE_WRITEBACK,
@@ -502,6 +509,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 */
@@ -885,6 +893,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);
@@ -1011,6 +1021,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 2c22450..0f230e4 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -512,8 +512,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 a9dc611..b67882e 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -742,6 +742,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 4591dd7..451c382 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 ba0da71..51bc269 100644
--- a/lib/thin/thin.c
+++ b/lib/thin/thin.c
@@ -86,6 +86,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");
@@ -131,6 +132,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))
@@ -177,6 +185,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) {
@@ -307,11 +318,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 e6f1d63..3ce34a5 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 7b74afb..ce90279 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -3032,6 +3032,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;
@@ -3196,6 +3197,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))
@@ -3401,6 +3404,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 e384291..1ee9e14 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -391,6 +391,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,

View File

@ -0,0 +1,194 @@
conf/example.conf.in | 10 ++++++++++
lib/config/config_settings.h | 9 +++++++++
lib/metadata/lv_manip.c | 14 +++++++++++---
lib/metadata/segtype.h | 2 ++
lib/vdo/vdo.c | 46 ++++++++++++++++++++++++++++++++++++--------
5 files changed, 70 insertions(+), 11 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index cd53147..d02965e 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -1195,6 +1195,16 @@ global {
# This configuration option has an automatic default value.
# vdo_format_options = [ "" ]
+ # Configuration option global/vdo_disabled_features.
+ # Features to not use in the vdo driver.
+ # This can be helpful for testing, or to avoid using a feature that is
+ # causing problems. Features include: online_rename
+ #
+ # Example
+ # vdo_disabled_features = [ "online_rename" ]
+ #
+ # This configuration option does not have a default value defined.
+
# Configuration option global/fsadm_executable.
# The full path to the fsadm command.
# LVM uses this command to help with lvresize -r operations.
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 3c4032e..f844594 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -1206,6 +1206,15 @@ cfg(global_vdo_format_executable_CFG, "vdo_format_executable", global_CFG_SECTIO
cfg_array(global_vdo_format_options_CFG, "vdo_format_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VDO_FORMAT_OPTIONS_CONFIG, VDO_1ST_VSN, NULL, 0, NULL,
"List of options passed added to standard vdoformat command.\n")
+cfg_array(global_vdo_disabled_features_CFG, "vdo_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 3, 11), NULL, 0, NULL,
+ "Features to not use in the vdo driver.\n"
+ "This can be helpful for testing, or to avoid using a feature that is\n"
+ "causing problems. Features include: online_rename\n"
+ "#\n"
+ "Example\n"
+ "vdo_disabled_features = [ \"online_rename\" ]\n"
+ "#\n")
+
cfg(global_fsadm_executable_CFG, "fsadm_executable", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FSADM_PATH, vsn(2, 2, 170), "@FSADM_PATH@", 0, NULL,
"The full path to the fsadm command.\n"
"LVM uses this command to help with lvresize -r operations.\n")
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index c740ba2..6c71263 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -4738,6 +4738,8 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
struct lv_names lv_names = { .old = lv->name };
int old_lv_is_historical = lv_is_historical(lv);
int historical;
+ unsigned attrs;
+ const struct segment_type *segtype;
/*
* rename is not allowed on sub LVs except for pools
@@ -4763,9 +4765,15 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
}
if (lv_is_vdo_pool(lv) && lv_is_active(lv_lock_holder(lv))) {
- log_error("Cannot rename active VDOPOOL volume %s.",
- display_lvname(lv));
- return 0;
+ segtype = first_seg(lv)->segtype;
+ if (!segtype->ops->target_present ||
+ !segtype->ops->target_present(lv->vg->cmd, NULL, &attrs) ||
+ !(attrs & VDO_FEATURE_ONLINE_RENAME)) {
+ log_error("Cannot rename active VDOPOOL volume %s, "
+ "VDO target feature support is missing.",
+ display_lvname(lv));
+ return 0;
+ }
}
if (update_mda && !archive(vg))
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index 08ddc35..2714a6b 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -349,6 +349,8 @@ int init_cache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib)
int init_vdo_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
#endif
+#define VDO_FEATURE_ONLINE_RENAME (1U << 0) /* version 6.2.3 */
+
int init_writecache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
int init_integrity_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
diff --git a/lib/vdo/vdo.c b/lib/vdo/vdo.c
index c43a5dc..bb7c784 100644
--- a/lib/vdo/vdo.c
+++ b/lib/vdo/vdo.c
@@ -25,6 +25,7 @@
#include "lib/metadata/segtype.h"
#include "base/memory/zalloc.h"
+static const char _vdo_module[] = MODULE_NAME_VDO;
static unsigned _feature_mask;
static int _bad_field(const char *field)
@@ -391,18 +392,21 @@ static int _vdo_target_present(struct cmd_context *cmd,
static const struct feature {
uint32_t maj;
uint32_t min;
+ uint32_t patchlevel;
unsigned vdo_feature;
const char *feature;
} _features[] = {
- { 1, 1, 0, "" },
- //{ 9, 9, VDO_FEATURE_RESIZE, "resize" },
+ { 6, 2, 3, VDO_FEATURE_ONLINE_RENAME, "online_rename" },
};
- //static const char _lvmconf[] = "global/vdo_disabled_features";
+ static const char _lvmconf[] = "global/vdo_disabled_features";
static int _vdo_checked = 0;
static int _vdo_present = 0;
static unsigned _vdo_attrs = 0;
uint32_t i, maj, min, patchlevel;
const struct segment_type *segtype;
+ const struct dm_config_node *cn;
+ const struct dm_config_value *cv;
+ const char *str;
if (!activation())
return 0;
@@ -419,8 +423,8 @@ static int _vdo_target_present(struct cmd_context *cmd,
}
if (maj < 6 || (maj == 6 && min < 2)) {
- log_warn("WARNING: VDO target version %u.%u.%u is too old.",
- maj, min, patchlevel);
+ log_warn("WARNING: Target %s version %u.%u.%u is too old.",
+ _vdo_module, maj, min, patchlevel);
return 0;
}
@@ -437,15 +441,41 @@ static int _vdo_target_present(struct cmd_context *cmd,
/* Prepare for adding supported features */
for (i = 0; i < DM_ARRAY_SIZE(_features); ++i)
if ((maj > _features[i].maj) ||
- (maj == _features[i].maj && min >= _features[i].min))
+ ((maj == _features[i].maj) && (min > _features[i].min)) ||
+ ((maj == _features[i].maj) && (min == _features[i].min) && (patchlevel >= _features[i].patchlevel)))
_vdo_attrs |= _features[i].vdo_feature;
else
log_very_verbose("Target %s does not support %s.",
- TARGET_NAME_VDO,
+ _vdo_module,
_features[i].feature);
}
if (attributes) {
+ if (!_feature_mask) {
+ /* Support runtime lvm.conf changes, N.B. avoid 32 feature */
+ if ((cn = find_config_tree_array(cmd, global_vdo_disabled_features_CFG, NULL))) {
+ for (cv = cn->v; cv; cv = cv->next) {
+ if (cv->type != DM_CFG_STRING) {
+ log_warn("WARNING: Ignoring invalid string in config file %s.",
+ _lvmconf);
+ continue;
+ }
+ str = cv->v.str;
+ if (!*str)
+ continue;
+ for (i = 0; i < DM_ARRAY_SIZE(_features); ++i)
+ if (strcasecmp(str, _features[i].feature) == 0)
+ _feature_mask |= _features[i].vdo_feature;
+ }
+ }
+ _feature_mask = ~_feature_mask;
+ for (i = 0; i < DM_ARRAY_SIZE(_features); ++i)
+ if ((_vdo_attrs & _features[i].vdo_feature) &&
+ !(_feature_mask & _features[i].vdo_feature))
+ log_very_verbose("Target %s %s support disabled by %s.",
+ _vdo_module,
+ _features[i].feature, _lvmconf);
+ }
*attributes = _vdo_attrs & _feature_mask;
}
@@ -456,7 +486,7 @@ static int _vdo_modules_needed(struct dm_pool *mem,
const struct lv_segment *seg __attribute__((unused)),
struct dm_list *modules)
{
- if (!str_list_add(mem, modules, MODULE_NAME_VDO)) {
+ if (!str_list_add(mem, modules, _vdo_module)) {
log_error("String list allocation failed for VDO module.");
return 0;
}

View File

@ -0,0 +1,45 @@
lib/metadata/writecache_manip.c | 10 +++++++---
tools/lvconvert.c | 2 ++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/lib/metadata/writecache_manip.c b/lib/metadata/writecache_manip.c
index 5004aa9..8150d07 100644
--- a/lib/metadata/writecache_manip.c
+++ b/lib/metadata/writecache_manip.c
@@ -75,7 +75,7 @@ static int _get_writecache_kernel_status(struct cmd_context *cmd,
return 0;
}
- if (!lv_info_with_seg_status(cmd, first_seg(lv), &status, 1, 1)) {
+ if (!lv_info_with_seg_status(cmd, first_seg(lv), &status, 0, 0)) {
log_error("Failed to get device mapper status for %s", display_lvname(lv));
goto fail;
}
@@ -434,8 +434,12 @@ int lv_writecache_set_cleaner(struct logical_volume *lv)
seg->writecache_settings.cleaner_set = 1;
if (lv_is_active(lv)) {
- if (!lv_update_and_reload(lv)) {
- log_error("Failed to update VG and reload LV.");
+ if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
+ log_error("Failed to update VG.");
+ return 0;
+ }
+ if (!lv_writecache_message(lv, "cleaner")) {
+ log_error("Failed to set writecache cleaner for %s.", display_lvname(lv));
return 0;
}
} else {
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 4323965..7b74afb 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -5720,6 +5720,8 @@ static int _lvconvert_detach_writecache_when_clean(struct cmd_context *cmd,
return 0;
}
+ log_debug("detach writecache check clean reading vg %s", id->vg_name);
+
vg = vg_read(cmd, id->vg_name, NULL, READ_FOR_UPDATE, lockd_state, &error_flags, NULL);
if (!vg) {

View File

@ -1,4 +1,4 @@
%global device_mapper_version 1.02.173
%global device_mapper_version 1.02.175
%global enable_cache 1
%global enable_cluster 1
@ -11,6 +11,7 @@
%global enable_testsuite 1
%global enable_vdo 1
%global enable_writecache 1
%global enable_integrity 1
%global system_release_version 23
%global systemd_version 189-3
@ -56,12 +57,42 @@ Name: lvm2
%if 0%{?rhel}
Epoch: %{rhel}
%endif
Version: 2.03.10
Release: 2%{?dist}
Version: 2.03.11
Release: 1%{?dist}
License: GPLv2
URL: http://sourceware.org/lvm2
Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz
Patch0: lvm2-set-default-preferred_names.patch
Patch3: lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch
# BZ 1915497:
Patch4: lvm2-2_03_12-alloc-enhance-estimation-of-sufficient_pes_free.patch
Patch5: lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch
Patch6: lvm2-2_03_12-tests-check-full-zeroing-of-thin-pool-metadata.patch
# BZ 1915580:
Patch7: lvm2-2_03_12-integrity-fix-segfault-on-error-path-when-replacing-.patch
# BZ 1872695:
Patch8: lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch
Patch9: lvm2-2_03_12-make-generate.patch
Patch10: lvm2-2_03_12-label_scan-fix-missing-free-of-filtered_devs.patch
# BZ 1917920:
Patch11: lvm2-2_03_12-pvck-fix-warning-and-exit-code-for-non-4k-mda1-offse.patch
Patch12: lvm2-2_03_12-WHATS_NEW-update.patch
# BZ 1921214:
Patch13: lvm2-2_03_12-writecache-use-cleaner-message-instead-of-table-relo.patch
# BZ 1909699:
Patch14: lvm2-2_03_12-man-update-lvmthin.patch
Patch15: lvm2-2_03_12-thin-improve-16g-support-for-thin-pool-metadata.patch
Patch16: lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch
Patch17: lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch
Patch18: lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch
Patch19: lvm2-2_03_12-tests-update-thin-and-cache-checked-messages.patch
# BZ 1914389:
Patch20: lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch
Patch21: lvm2-2_03_12-test-check-read_only_volume_list-tagging-works.patch
# BZ 1859659:
Patch22: lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch
# BZ 1925871:
Patch23: lvm2-2_03_12-dev_get_primary_dev-fix-invalid-path-check.patch
BuildRequires: make
BuildRequires: gcc
@ -118,7 +149,28 @@ or more physical volumes and creating one or more logical volumes
%prep
%setup -q -n LVM2.%{version}
%patch0 -p1 -b .preferred_names
%patch0 -p1 -b .backup0
%patch3 -p1 -b .backup3
%patch4 -p1 -b .backup4
%patch5 -p1 -b .backup5
%patch6 -p1 -b .backup6
%patch7 -p1 -b .backup7
%patch8 -p1 -b .backup8
%patch9 -p1 -b .backup9
%patch10 -p1 -b .backup10
%patch11 -p1 -b .backup11
%patch12 -p1 -b .backup12
%patch13 -p1 -b .backup13
%patch14 -p1 -b .backup14
%patch15 -p1 -b .backup15
%patch16 -p1 -b .backup16
%patch17 -p1 -b .backup17
%patch18 -p1 -b .backup18
%patch19 -p1 -b .backup19
%patch20 -p1 -b .backup20
%patch21 -p1 -b .backup21
%patch22 -p1 -b .backup22
%patch23 -p1 -b .backup23
%build
%global _default_pid_dir /run
@ -165,12 +217,16 @@ or more physical volumes and creating one or more logical volumes
%global configure_writecache --with-writecache=internal
%endif
%if %{enable_integrity}
%global configure_integrity --with-integrity=internal
%endif
# NOTE: Using CFLAGS and LDFLAGS would override the fedora default flags, thus
# using paths here...
export CPATH="%{_includedir}/readline5"
export LIBRARY_PATH="%{_libdir}/readline5"
%configure --with-default-dm-run-dir=%{_default_dm_run_dir} --with-default-run-dir=%{_default_run_dir} --with-default-pid-dir=%{_default_pid_dir} --with-default-locking-dir=%{_default_locking_dir} --with-usrlibdir=%{_libdir} --enable-fsadm --enable-write_install --with-user= --with-group= --with-device-uid=0 --with-device-gid=6 --with-device-mode=0660 --enable-pkgconfig --enable-cmdlib --enable-dmeventd --enable-blkid_wiping %{?configure_cluster} %{?configure_cmirror} %{?configure_udev} %{?configure_thin} %{?configure_cache} %{?configure_lvmpolld} %{?configure_lockd_dlm} %{?configure_lockd_sanlock} %{?configure_lvmdbusd} %{?configure_dmfilemapd} %{?configure_writecache} %{?configure_vdo} --disable-silent-rules
%configure --with-default-dm-run-dir=%{_default_dm_run_dir} --with-default-run-dir=%{_default_run_dir} --with-default-pid-dir=%{_default_pid_dir} --with-default-locking-dir=%{_default_locking_dir} --with-usrlibdir=%{_libdir} --enable-fsadm --enable-write_install --with-user= --with-group= --with-device-uid=0 --with-device-gid=6 --with-device-mode=0660 --enable-pkgconfig --enable-cmdlib --enable-dmeventd --enable-blkid_wiping %{?configure_cluster} %{?configure_cmirror} %{?configure_udev} %{?configure_thin} %{?configure_cache} %{?configure_lvmpolld} %{?configure_lockd_dlm} %{?configure_lockd_sanlock} %{?configure_lvmdbusd} %{?configure_dmfilemapd} %{?configure_writecache} %{?configure_vdo} %{?configure_integrity} --disable-silent-rules
%make_build
@ -724,6 +780,36 @@ An extensive functional testsuite for LVM2.
%endif
%changelog
* Mon Feb 22 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.11-1
- Fix mpath filtering of NVMe devices.
- Check if lvcreate passes read_only_volume_list with tags and skips zeroing.
- Limit pool metadata spare to 16GiB.
- Improves conversion and allocation of pool metadata.
- Fix different limits used for metadata by lvm2 and thin-tools.
- Fix interrupting lvconvert --splitcache command with striped origin volumes.
- Fix problem with wiping of converted LVs.
- Fix memleak in scanning.
- Fix corner case allocation for thin-pools.
- Fix pvck handling MDA at offset different from 4096.
- Partial or degraded activation of writecache is not allowed.
- Enhance error handling in fsadm and handle correct fsck result.
- Dmeventd lvm plugin ignores higher reserved_stack lvm.conf values.
- Support using BLKZEROOUT for clearing devices.
- Fixed interrup handling.
- Fix block cache when device has too many failing writes.
- Fix block cache waiting for IO completion with failing disks.
- Add configure --enable-editline support as an alternative to readline.
- Enhance reporting and error handling when creating thin volumes.
- Enable vgsplit for VDO volumes.
- Lvextend of vdo pool volumes ensure at least 1 new VDO slab is added.
- Restore lost signal blocking while VG lock is held.
- Improve estimation of needed extents when creating thin-pool.
- Use extra 1% when resizing thin-pool metadata LV with --use-policy.
- Enhance --use-policy percentage rounding.
- Allow pvmove of writecache origin.
- Report integrity fields.
- Integrity volumes defaults to journal mode.
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.03.10-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild

View File

@ -1 +1 @@
SHA512 (LVM2.2.03.10.tgz) = 8678ae2f99739ccad0250f6f4b4b8e84520f2053835985a1ea9c80196a64df31a48858aebf983170c3dfcafecea83f2c6aa630ef73fd31dd84cf1627a1b421e4
SHA512 (LVM2.2.03.11.tgz) = 50f21337e397fc5b4692bb08e5d48409b907b96b39168343bab2d40bb74fd84ff466e15f3d664305bc044f3f6be4369fa7378399d5a838793632e74706f17653

View File

@ -1 +1 @@
LVM2.2.03.10.tgz
LVM2.2.03.11.tgz