diff --git a/.gitignore b/.gitignore index 5bf5c35..325731b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/LVM2.2.03.11.tgz +SOURCES/LVM2.2.03.12.tgz diff --git a/.lvm2.metadata b/.lvm2.metadata index c85bb4b..dc25d8a 100644 --- a/.lvm2.metadata +++ b/.lvm2.metadata @@ -1 +1 @@ -9484fd277914a85f330b4067aa222ee13f061189 SOURCES/LVM2.2.03.11.tgz +6d74d987b474dd0b45f239eb6dcc050622ad6962 SOURCES/LVM2.2.03.12.tgz diff --git a/SOURCES/lvm2-2_03_12-WHATS_NEW-update.patch b/SOURCES/lvm2-2_03_12-WHATS_NEW-update.patch deleted file mode 100644 index ed16b64..0000000 --- a/SOURCES/lvm2-2_03_12-WHATS_NEW-update.patch +++ /dev/null @@ -1,15 +0,0 @@ - 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 diff --git a/SOURCES/lvm2-2_03_12-alloc-enhance-estimation-of-sufficient_pes_free.patch b/SOURCES/lvm2-2_03_12-alloc-enhance-estimation-of-sufficient_pes_free.patch deleted file mode 100644 index a60a2b8..0000000 --- a/SOURCES/lvm2-2_03_12-alloc-enhance-estimation-of-sufficient_pes_free.patch +++ /dev/null @@ -1,47 +0,0 @@ - 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, diff --git a/SOURCES/lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch b/SOURCES/lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch deleted file mode 100644 index ce35731..0000000 --- a/SOURCES/lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch +++ /dev/null @@ -1,107 +0,0 @@ - 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; diff --git a/SOURCES/lvm2-2_03_12-dev_get_primary_dev-fix-invalid-path-check.patch b/SOURCES/lvm2-2_03_12-dev_get_primary_dev-fix-invalid-path-check.patch deleted file mode 100644 index add3525..0000000 --- a/SOURCES/lvm2-2_03_12-dev_get_primary_dev-fix-invalid-path-check.patch +++ /dev/null @@ -1,48 +0,0 @@ -From b3719266bd5e3a9e6737d6bda60e543121ddf343 Mon Sep 17 00:00:00 2001 -From: David Teigland -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 - diff --git a/SOURCES/lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch b/SOURCES/lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch deleted file mode 100644 index 0f00653..0000000 --- a/SOURCES/lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch +++ /dev/null @@ -1,255 +0,0 @@ - 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 diff --git a/SOURCES/lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch b/SOURCES/lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch deleted file mode 100644 index 3778134..0000000 --- a/SOURCES/lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch +++ /dev/null @@ -1,494 +0,0 @@ - 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 -@@ -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 , -+ * and reading /sys/dev/block/259:/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 - #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//dm/uuid indicates that -+ * is a dm device with dm uuid prefix mpath-. -+ * When true, 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."); diff --git a/SOURCES/lvm2-2_03_12-fsadm-avoid-access-to-unbound-variable.patch b/SOURCES/lvm2-2_03_12-fsadm-avoid-access-to-unbound-variable.patch deleted file mode 100644 index 6beff68..0000000 --- a/SOURCES/lvm2-2_03_12-fsadm-avoid-access-to-unbound-variable.patch +++ /dev/null @@ -1,16 +0,0 @@ - scripts/fsadm.sh | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/scripts/fsadm.sh b/scripts/fsadm.sh -index 2cb1fc7..4f59cee 100755 ---- a/scripts/fsadm.sh -+++ b/scripts/fsadm.sh -@@ -163,7 +163,7 @@ cleanup() { - _FSADM_EXTOFF=$EXTOFF - export _FSADM_YES _FSADM_EXTOFF - unset FSADM_RUNNING -- test -n "$LVM_BINARY" && PATH=$_SAVEPATH -+ test -n "${LVM_BINARY-}" && PATH=$_SAVEPATH - dry exec "$LVM" lvresize $VERB $FORCE -r -L"${NEWSIZE_ORIG}b" "$VOLUME_ORIG" - fi - diff --git a/SOURCES/lvm2-2_03_12-integrity-fix-segfault-on-error-path-when-replacing-.patch b/SOURCES/lvm2-2_03_12-integrity-fix-segfault-on-error-path-when-replacing-.patch deleted file mode 100644 index d4ece0d..0000000 --- a/SOURCES/lvm2-2_03_12-integrity-fix-segfault-on-error-path-when-replacing-.patch +++ /dev/null @@ -1,24 +0,0 @@ - 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)) diff --git a/SOURCES/lvm2-2_03_12-label_scan-fix-missing-free-of-filtered_devs.patch b/SOURCES/lvm2-2_03_12-label_scan-fix-missing-free-of-filtered_devs.patch deleted file mode 100644 index b5bccfb..0000000 --- a/SOURCES/lvm2-2_03_12-label_scan-fix-missing-free-of-filtered_devs.patch +++ /dev/null @@ -1,19 +0,0 @@ - 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 diff --git a/SOURCES/lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch b/SOURCES/lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch deleted file mode 100644 index bb28cd7..0000000 --- a/SOURCES/lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch +++ /dev/null @@ -1,66 +0,0 @@ - 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)) diff --git a/SOURCES/lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch b/SOURCES/lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch deleted file mode 100644 index 9bc2f48..0000000 --- a/SOURCES/lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch +++ /dev/null @@ -1,29 +0,0 @@ - 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; - } diff --git a/SOURCES/lvm2-2_03_12-make-generate.patch b/SOURCES/lvm2-2_03_12-make-generate.patch deleted file mode 100644 index 2f4f682..0000000 --- a/SOURCES/lvm2-2_03_12-make-generate.patch +++ /dev/null @@ -1,18 +0,0 @@ - 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 diff --git a/SOURCES/lvm2-2_03_12-man-Fix-wording-in-lvmthin-7.patch b/SOURCES/lvm2-2_03_12-man-Fix-wording-in-lvmthin-7.patch deleted file mode 100644 index 09088d5..0000000 --- a/SOURCES/lvm2-2_03_12-man-Fix-wording-in-lvmthin-7.patch +++ /dev/null @@ -1,22 +0,0 @@ - man/lvmthin.7_main | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main -index 3ce34a5..9568eca 100644 ---- a/man/lvmthin.7_main -+++ b/man/lvmthin.7_main -@@ -443,12 +443,12 @@ 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. -+all filesystems present on these 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) -+(written to previous pmspare volume) to a faster PV, e.g. 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 diff --git a/SOURCES/lvm2-2_03_12-man-update-lvmthin.patch b/SOURCES/lvm2-2_03_12-man-update-lvmthin.patch deleted file mode 100644 index f61660f..0000000 --- a/SOURCES/lvm2-2_03_12-man-update-lvmthin.patch +++ /dev/null @@ -1,86 +0,0 @@ - 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 diff --git a/SOURCES/lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch b/SOURCES/lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch deleted file mode 100644 index b41b370..0000000 --- a/SOURCES/lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch +++ /dev/null @@ -1,39 +0,0 @@ - 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; diff --git a/SOURCES/lvm2-2_03_12-pvck-fix-warning-and-exit-code-for-non-4k-mda1-offse.patch b/SOURCES/lvm2-2_03_12-pvck-fix-warning-and-exit-code-for-non-4k-mda1-offse.patch deleted file mode 100644 index 63020bd..0000000 --- a/SOURCES/lvm2-2_03_12-pvck-fix-warning-and-exit-code-for-non-4k-mda1-offse.patch +++ /dev/null @@ -1,24 +0,0 @@ - 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); diff --git a/SOURCES/lvm2-2_03_12-test-check-read_only_volume_list-tagging-works.patch b/SOURCES/lvm2-2_03_12-test-check-read_only_volume_list-tagging-works.patch deleted file mode 100644 index bdcc15b..0000000 --- a/SOURCES/lvm2-2_03_12-test-check-read_only_volume_list-tagging-works.patch +++ /dev/null @@ -1,19 +0,0 @@ - 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 diff --git a/SOURCES/lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch b/SOURCES/lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch deleted file mode 100644 index ae05b76..0000000 --- a/SOURCES/lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch +++ /dev/null @@ -1,98 +0,0 @@ - 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 diff --git a/SOURCES/lvm2-2_03_12-tests-check-full-zeroing-of-thin-pool-metadata.patch b/SOURCES/lvm2-2_03_12-tests-check-full-zeroing-of-thin-pool-metadata.patch deleted file mode 100644 index d7edcc7..0000000 --- a/SOURCES/lvm2-2_03_12-tests-check-full-zeroing-of-thin-pool-metadata.patch +++ /dev/null @@ -1,78 +0,0 @@ - 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 diff --git a/SOURCES/lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch b/SOURCES/lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch deleted file mode 100644 index 04962b8..0000000 --- a/SOURCES/lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch +++ /dev/null @@ -1,47 +0,0 @@ - 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 diff --git a/SOURCES/lvm2-2_03_12-tests-remove-local-setting-of-LVM_BINARY.patch b/SOURCES/lvm2-2_03_12-tests-remove-local-setting-of-LVM_BINARY.patch deleted file mode 100644 index 71f6272..0000000 --- a/SOURCES/lvm2-2_03_12-tests-remove-local-setting-of-LVM_BINARY.patch +++ /dev/null @@ -1,61 +0,0 @@ - test/shell/fsadm-crypt.sh | 3 --- - test/shell/fsadm-renamed.sh | 3 --- - test/shell/fsadm.sh | 3 --- - test/shell/lvresize-full.sh | 2 -- - 4 files changed, 11 deletions(-) - -diff --git a/test/shell/fsadm-crypt.sh b/test/shell/fsadm-crypt.sh -index 4b8fc4e..2004db9 100644 ---- a/test/shell/fsadm-crypt.sh -+++ b/test/shell/fsadm-crypt.sh -@@ -76,9 +76,6 @@ dev_vg_lv="$DM_DEV_DIR/$vg_lv" - dev_vg_lv2="$DM_DEV_DIR/$vg_lv2" - dev_vg_lv3="$DM_DEV_DIR/$vg_lv3" - mount_dir="mnt" --# for recursive call --LVM_BINARY=$(which lvm) --export LVM_BINARY - - test ! -d "$mount_dir" && mkdir "$mount_dir" - -diff --git a/test/shell/fsadm-renamed.sh b/test/shell/fsadm-renamed.sh -index 3218939..50c6d3e 100644 ---- a/test/shell/fsadm-renamed.sh -+++ b/test/shell/fsadm-renamed.sh -@@ -27,9 +27,6 @@ dev_vg_lv_ren="$DM_DEV_DIR/$vg_lv_ren" - mount_dir="mnt" - mount_space_dir="mnt space dir" - mount_dolar_dir="mnt \$SPACE dir" --# for recursive call --LVM_BINARY=$(which lvm) --export LVM_BINARY - - test ! -d "$mount_dir" && mkdir "$mount_dir" - test ! -d "$mount_space_dir" && mkdir "$mount_space_dir" -diff --git a/test/shell/fsadm.sh b/test/shell/fsadm.sh -index 67f9660..987b1a1 100644 ---- a/test/shell/fsadm.sh -+++ b/test/shell/fsadm.sh -@@ -45,9 +45,6 @@ dev_vg_lv="$DM_DEV_DIR/$vg_lv" - dev_vg_lv2="$DM_DEV_DIR/$vg_lv2" - mount_dir="mnt" - mount_space_dir="mnt space dir" --# for recursive call --LVM_BINARY=$(which lvm) --export LVM_BINARY - - test ! -d "$mount_dir" && mkdir "$mount_dir" - test ! -d "$mount_space_dir" && mkdir "$mount_space_dir" -diff --git a/test/shell/lvresize-full.sh b/test/shell/lvresize-full.sh -index 3cab522..dcf93a7 100644 ---- a/test/shell/lvresize-full.sh -+++ b/test/shell/lvresize-full.sh -@@ -21,8 +21,6 @@ SKIP_WITH_LVMPOLLD=1 - FSCK=${FSCK-fsck} - MKFS=${MKFS-mkfs.ext3} - RESIZEFS=${RESIZEFS-resize2fs} --LVM_BINARY=$(which lvm) --export LVM_BINARY - - which $FSCK || skip - which $MKFS || skip diff --git a/SOURCES/lvm2-2_03_12-tests-update-thin-and-cache-checked-messages.patch b/SOURCES/lvm2-2_03_12-tests-update-thin-and-cache-checked-messages.patch deleted file mode 100644 index f4ccd37..0000000 --- a/SOURCES/lvm2-2_03_12-tests-update-thin-and-cache-checked-messages.patch +++ /dev/null @@ -1,77 +0,0 @@ - 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 diff --git a/SOURCES/lvm2-2_03_12-thin-improve-16g-support-for-thin-pool-metadata.patch b/SOURCES/lvm2-2_03_12-thin-improve-16g-support-for-thin-pool-metadata.patch deleted file mode 100644 index 8347ad4..0000000 --- a/SOURCES/lvm2-2_03_12-thin-improve-16g-support-for-thin-pool-metadata.patch +++ /dev/null @@ -1,694 +0,0 @@ - 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, diff --git a/SOURCES/lvm2-2_03_12-writecache-use-cleaner-message-instead-of-table-relo.patch b/SOURCES/lvm2-2_03_12-writecache-use-cleaner-message-instead-of-table-relo.patch deleted file mode 100644 index 9f08576..0000000 --- a/SOURCES/lvm2-2_03_12-writecache-use-cleaner-message-instead-of-table-relo.patch +++ /dev/null @@ -1,45 +0,0 @@ - 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) { diff --git a/SOURCES/lvm2-2_03_13-device_id-handle-scsi_debug-wwid.patch b/SOURCES/lvm2-2_03_13-device_id-handle-scsi_debug-wwid.patch new file mode 100644 index 0000000..84cc940 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-device_id-handle-scsi_debug-wwid.patch @@ -0,0 +1,18 @@ + lib/device/device_id.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index f158e4f..9cc82f1 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -308,6 +308,10 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u + + if (!sysbuf[0]) + _read_sys_block(cmd, dev, "wwid", sysbuf, sizeof(sysbuf)); ++ ++ /* scsi_debug wwid begins "t10.Linux scsi_debug ..." */ ++ if (strstr(sysbuf, "scsi_debug")) ++ sysbuf[0] = '\0'; + } + + else if (idtype == DEV_ID_TYPE_SYS_SERIAL) diff --git a/SOURCES/lvm2-2_03_13-devices-don-t-use-deleted-loop-backing-file-for-devi.patch b/SOURCES/lvm2-2_03_13-devices-don-t-use-deleted-loop-backing-file-for-devi.patch new file mode 100644 index 0000000..6de11be --- /dev/null +++ b/SOURCES/lvm2-2_03_13-devices-don-t-use-deleted-loop-backing-file-for-devi.patch @@ -0,0 +1,21 @@ + lib/device/device_id.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 67f72e5..1b98487 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -325,8 +325,12 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u + else if (idtype == DEV_ID_TYPE_MD_UUID) + _read_sys_block(cmd, dev, "md/uuid", sysbuf, sizeof(sysbuf)); + +- else if (idtype == DEV_ID_TYPE_LOOP_FILE) ++ else if (idtype == DEV_ID_TYPE_LOOP_FILE) { + _read_sys_block(cmd, dev, "loop/backing_file", sysbuf, sizeof(sysbuf)); ++ /* if backing file is deleted, fall back to devname */ ++ if (strstr(sysbuf, "(deleted)")) ++ sysbuf[0] = '\0'; ++ } + + else if (idtype == DEV_ID_TYPE_DEVNAME) { + if (!(idname = strdup(dev_name(dev)))) diff --git a/SOURCES/lvm2-2_03_13-enable-command-syntax-for-thin-and-writecache.patch b/SOURCES/lvm2-2_03_13-enable-command-syntax-for-thin-and-writecache.patch new file mode 100644 index 0000000..652b0b7 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-enable-command-syntax-for-thin-and-writecache.patch @@ -0,0 +1,25 @@ + tools/command-lines.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/command-lines.in b/tools/command-lines.in +index 1107c1e..67c37ff 100644 +--- a/tools/command-lines.in ++++ b/tools/command-lines.in +@@ -534,7 +534,7 @@ RULE: all and lv_is_visible + + --- + +-lvconvert --type thin-pool LV_linear_striped_raid_cache_error_zero ++lvconvert --type thin-pool LV_linear_striped_raid_cache_writecache_error_zero + OO: --stripes_long Number, --stripesize SizeKB, + OO_LVCONVERT_THINPOOL, OO_LVCONVERT_POOL, OO_LVCONVERT + OP: PV ... +@@ -566,7 +566,7 @@ RULE: --poolmetadata not --readahead --stripesize --stripes_long + # This command syntax is deprecated, and the primary forms + # of creating a pool or swapping metadata should be used. + +-lvconvert --thinpool LV_linear_striped_raid_cache_thinpool ++lvconvert --thinpool LV_linear_striped_raid_cache_writecache_thinpool + OO: --stripes_long Number, --stripesize SizeKB, + OO_LVCONVERT_THINPOOL, OO_LVCONVERT_POOL, OO_LVCONVERT + OP: PV ... diff --git a/SOURCES/lvm2-2_03_13-lvconvert-allow-writecache-with-other-thinpool-comma.patch b/SOURCES/lvm2-2_03_13-lvconvert-allow-writecache-with-other-thinpool-comma.patch new file mode 100644 index 0000000..2875b22 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-lvconvert-allow-writecache-with-other-thinpool-comma.patch @@ -0,0 +1,16 @@ + tools/lvconvert.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lvconvert.c b/tools/lvconvert.c +index 8dd8a15..6066d1f 100644 +--- a/tools/lvconvert.c ++++ b/tools/lvconvert.c +@@ -4803,7 +4803,7 @@ static int _lvconvert_to_pool_or_swap_metadata_single(struct cmd_context *cmd, + + switch (cmd->command->command_enum) { + case lvconvert_to_thinpool_or_swap_metadata_CMD: +- if (lv_is_cache(lv)) ++ if (lv_is_cache(lv) || lv_is_writecache(lv)) + /* For cached LV check the cache origin LV type */ + lvt_enum = get_lvt_enum(seg_lv(first_seg(lv), 0)); + to_thinpool = 1; diff --git a/SOURCES/lvm2-2_03_13-lvconvert-fix-vdo-virtual-size-when-specified.patch b/SOURCES/lvm2-2_03_13-lvconvert-fix-vdo-virtual-size-when-specified.patch new file mode 100644 index 0000000..7758cca --- /dev/null +++ b/SOURCES/lvm2-2_03_13-lvconvert-fix-vdo-virtual-size-when-specified.patch @@ -0,0 +1,17 @@ + lib/metadata/vdo_manip.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/metadata/vdo_manip.c b/lib/metadata/vdo_manip.c +index 7d5a2cb..afc513a 100644 +--- a/lib/metadata/vdo_manip.c ++++ b/lib/metadata/vdo_manip.c +@@ -393,7 +393,8 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv, + } else { + log_verbose("Skiping VDO formating %s.", display_lvname(data_lv)); + /* TODO: parse existing VDO data and retrieve vdo_logical_size */ +- vdo_logical_size = data_lv->size; ++ if (!*virtual_extents) ++ vdo_logical_size = data_lv->size; + } + + if (!deactivate_lv(data_lv->vg->cmd, data_lv)) { diff --git a/SOURCES/lvm2-2_03_13-lvmdevices-add-deviceidtype-option.patch b/SOURCES/lvm2-2_03_13-lvmdevices-add-deviceidtype-option.patch new file mode 100644 index 0000000..6d4e6bf --- /dev/null +++ b/SOURCES/lvm2-2_03_13-lvmdevices-add-deviceidtype-option.patch @@ -0,0 +1,211 @@ + lib/device/device_id.c | 32 ++++++++++++++---------- + man/lvmdevices.8_des | 68 +++++++++++++++++++++++++++++++++++++++----------- + tools/args.h | 5 ++++ + tools/command-lines.in | 1 + + tools/lvmdevices.c | 7 ++++-- + 5 files changed, 84 insertions(+), 29 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 1b98487..f158e4f 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -931,6 +931,7 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_ + /* + * Choose the device_id type for the device being added. + * ++ * 0. use an idtype specified by the user + * 1. use an idtype specific to a special/virtual device type + * e.g. loop, mpath, crypt, lvmlv, md, etc. + * 2. use an idtype specified by user option. +@@ -939,6 +940,24 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_ + * 5. use devname as the last resort. + */ + ++ if (idtype_arg) { ++ if (!(idtype = idtype_from_str(idtype_arg))) ++ log_warn("WARNING: ignoring unknown device_id type %s.", idtype_arg); ++ else { ++ if (id_arg) { ++ if ((idname = strdup(id_arg))) ++ goto id_done; ++ log_warn("WARNING: ignoring device_id name %s.", id_arg); ++ } ++ ++ if ((idname = device_id_system_read(cmd, dev, idtype))) ++ goto id_done; ++ ++ log_warn("WARNING: ignoring deviceidtype %s which is not available for device.", idtype_arg); ++ idtype = 0; ++ } ++ } ++ + if (MAJOR(dev->dev) == cmd->dev_types->device_mapper_major) { + if (_dev_has_mpath_uuid(cmd, dev, &idname)) { + idtype = DEV_ID_TYPE_MPATH_UUID; +@@ -972,19 +991,6 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_ + log_warn("Missing support for DRBD idtype"); + } + +- if (idtype_arg) { +- if (!(idtype = idtype_from_str(idtype_arg))) +- log_warn("WARNING: ignoring unknown device_id type %s.", idtype_arg); +- else { +- if (id_arg) { +- if (!(idname = strdup(id_arg))) +- stack; +- goto id_done; +- } +- goto id_name; +- } +- } +- + /* + * No device-specific, existing, or user-specified idtypes, + * so use first available of sys_wwid / sys_serial / devname. +diff --git a/man/lvmdevices.8_des b/man/lvmdevices.8_des +index 015aa11..2335456 100644 +--- a/man/lvmdevices.8_des ++++ b/man/lvmdevices.8_des +@@ -9,18 +9,18 @@ remove it from the devices file with lvmdevices --deldev. The + vgimportdevices(8) command adds all PVs from a VG to the devices file, + and updates the VG metadata to include device IDs of the PVs. + .P +-Commands adding new devices to the devices file necessarily look outside +-the existing devices file to find the devices to add. pvcreate, vgcreate, +-and vgextend also look outside the devices file to create new PVs and add +-them to the devices file. ++Commands that add new devices to the devices file necessarily look outside ++the existing devices file to find the devices being added. pvcreate, ++vgcreate, and vgextend also look outside the devices file to create new ++PVs and add those PVs to the devices file. + .P + LVM records devices in the devices file using hardware-specific IDs, such + as the WWID, and attempts to use subsystem-specific IDs for virtual device +-types (which also aim to be as unique and stable as possible.) +-These device IDs are also written in the VG metadata. When no hardware or ++types (which also aim to be as unique and stable as possible.) These ++device IDs are also written in the VG metadata. When no hardware or + virtual ID is available, lvm falls back using the unstable device name as +-the device ID. When devnames are used, lvm performs extra scanning to +-find devices if their devname changes, e.g. after reboot. ++the device ID. When devnames are used as IDs, lvm performs extra scanning ++to find devices if their devname changes, e.g. after reboot. + .P + When proper device IDs are used, an lvm command will not look at devices + outside the devices file, but when devnames are used as a fallback, lvm +@@ -34,12 +34,13 @@ overriding the devices file. The listed devices act as a sort of devices + file in terms of limiting which devices lvm will see and use. Devices + that are not listed will appear to be missing to the lvm command. + .P +-Multiple devices files can be kept in \fI#DEFAULT_SYS_DIR#/devices\fP, which allows lvm +-to be used with different sets of devices, e.g. system devices do not need +-to be exposed to a specific application, and the application can use lvm on +-its own devices that are not exposed to the system. The option +---devicesfile is used to select the devices file to use with the +-command. Without the option set, the default system devices file is used. ++Multiple devices files can be kept \fI#DEFAULT_SYS_DIR#/devices\fP, which ++allows lvm to be used with different sets of devices. For example, system ++devices do not need to be exposed to a specific application, and the ++application can use lvm on its own devices that are not exposed to the ++system. The option --devicesfile is used to select the devices ++file to use with the command. Without the option set, the default system ++devices file is used. + .P + Setting --devicesfile "" causes lvm to not use a devices file. + .P +@@ -59,3 +60,42 @@ if it does not yet exist. + .P + It is recommended to use lvm commands to make changes to the devices file to + ensure proper updates. ++.P ++The device ID and device ID type are included in the VG metadata and can ++be reported with pvs -o deviceid,deviceidtype. (Note that the lvmdevices ++command does not update VG metadata, but subsequent lvm commands modifying ++the metadata will include the device ID.) ++.P ++Possible device ID types are: ++.br ++.IP \[bu] 2 ++.B sys_wwid ++uses the wwid reported by sysfs. This is the first choice for non-virtual ++devices. ++.IP \[bu] 2 ++.B sys_serial ++uses the serial number reported by sysfs. This is the second choice for ++non-virtual devices. ++.IP \[bu] 2 ++.B mpath_uuid ++is used for dm multipath devices, reported by sysfs. ++.IP \[bu] 2 ++.B crypt_uuid ++is used for dm crypt devices, reported by sysfs. ++.IP \[bu] 2 ++.B md_uuid ++is used for md devices, reported by sysfs. ++.B lvmlv_uuid ++is used if a PV is placed on top of an lvm LV, reported by sysfs. ++.IP \[bu] 2 ++.B loop_file ++is used for loop devices, the backing file name repored by sysfs. ++.IP \[bu] 2 ++.B devname ++the device name is used if no other type applies. ++.P ++ ++The default choice for device ID type can be overriden using lvmdevices ++--addev --deviceidtype . If the specified type is available for the ++device it will be used, otherwise the device will be added using the type ++that would otherwise be chosen. +diff --git a/tools/args.h b/tools/args.h +index 741c82b..d4f23f8 100644 +--- a/tools/args.h ++++ b/tools/args.h +@@ -228,6 +228,11 @@ arg(detachprofile_ARG, '\0', "detachprofile", 0, 0, 0, + "Detaches a metadata profile from a VG or LV.\n" + "See \\fBlvm.conf\\fP(5) for more information about profiles.\n") + ++arg(deviceidtype_ARG, '\0', "deviceidtype", string_VAL, 0, 0, ++ "The type of device ID to use for the device.\n" ++ "If the specified type is available for the device,\n" ++ "then it will override the default type that lvm would use.\n") ++ + arg(devices_ARG, '\0', "devices", pv_VAL, ARG_GROUPABLE, 0, + "Devices that the command can use. This option can be repeated\n" + "or accepts a comma separated list of devices. This overrides\n" +diff --git a/tools/command-lines.in b/tools/command-lines.in +index 67c37ff..8607305 100644 +--- a/tools/command-lines.in ++++ b/tools/command-lines.in +@@ -1430,6 +1430,7 @@ ID: lvmdevices_update + DESC: Update the devices file to fix incorrect values. + + lvmdevices --adddev PV ++OO: --deviceidtype String + ID: lvmdevices_edit + DESC: Add a device to the devices file. + +diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c +index 6b3e056..3448bdd 100644 +--- a/tools/lvmdevices.c ++++ b/tools/lvmdevices.c +@@ -265,6 +265,7 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv) + + if (arg_is_set(cmd, adddev_ARG)) { + const char *devname; ++ const char *deviceidtype; + + if (!(devname = arg_str_value(cmd, adddev_ARG, NULL))) + goto_bad; +@@ -311,8 +312,10 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv) + dev_name(dev), dev_filtered_reason(dev)); + } + +- /* allow deviceidtype_ARG/deviceid_ARG ? */ +- if (!device_id_add(cmd, dev, dev->pvid, NULL, NULL)) ++ /* also allow deviceid_ARG ? */ ++ deviceidtype = arg_str_value(cmd, deviceidtype_ARG, NULL); ++ ++ if (!device_id_add(cmd, dev, dev->pvid, deviceidtype, NULL)) + goto_bad; + if (!device_ids_write(cmd)) + goto_bad; diff --git a/SOURCES/lvm2-2_03_13-lvremove-fix-removing-thin-pool-with-writecache-on-d.patch b/SOURCES/lvm2-2_03_13-lvremove-fix-removing-thin-pool-with-writecache-on-d.patch new file mode 100644 index 0000000..45a878d --- /dev/null +++ b/SOURCES/lvm2-2_03_13-lvremove-fix-removing-thin-pool-with-writecache-on-d.patch @@ -0,0 +1,150 @@ + lib/metadata/lv_manip.c | 19 +++++++++ + lib/metadata/metadata-exported.h | 2 + + lib/metadata/thin_manip.c | 12 ++++++ + test/shell/lvremove-thindata-caches.sh | 71 ++++++++++++++++++++++++++++++++++ + 4 files changed, 104 insertions(+) + create mode 100644 test/shell/lvremove-thindata-caches.sh + +diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c +index 508f78c..37dd361 100644 +--- a/lib/metadata/lv_manip.c ++++ b/lib/metadata/lv_manip.c +@@ -6692,6 +6692,25 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv, + return_0; + } + ++ /* if thin pool data lv is writecache, then detach and remove the writecache */ ++ if (lv_is_thin_pool(lv)) { ++ struct logical_volume *data_lv = data_lv_from_thin_pool(lv); ++ ++ if (data_lv && lv_is_writecache(data_lv)) { ++ struct logical_volume *cachevol_lv = first_seg(data_lv)->writecache; ++ ++ if (!lv_detach_writecache_cachevol(data_lv, 1)) { ++ log_error("Failed to detach writecache from %s", display_lvname(data_lv)); ++ return 0; ++ } ++ ++ if (!lv_remove_single(cmd, cachevol_lv, force, 1)) { ++ log_error("Failed to remove cachevol %s.", display_lvname(cachevol_lv)); ++ return 0; ++ } ++ } ++ } ++ + if (lv_is_writecache(lv)) { + struct logical_volume *cachevol_lv = first_seg(lv)->writecache; + +diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h +index c611635..54bc0d0 100644 +--- a/lib/metadata/metadata-exported.h ++++ b/lib/metadata/metadata-exported.h +@@ -927,6 +927,8 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents, + int vg_set_pool_metadata_spare(struct logical_volume *lv); + int vg_remove_pool_metadata_spare(struct volume_group *vg); + ++struct logical_volume *data_lv_from_thin_pool(struct logical_volume *pool_lv); ++ + int attach_thin_external_origin(struct lv_segment *seg, + struct logical_volume *external_lv); + int detach_thin_external_origin(struct lv_segment *seg); +diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c +index 451c382..6ce88bd 100644 +--- a/lib/metadata/thin_manip.c ++++ b/lib/metadata/thin_manip.c +@@ -21,6 +21,18 @@ + #include "lib/config/defaults.h" + #include "lib/display/display.h" + ++struct logical_volume *data_lv_from_thin_pool(struct logical_volume *pool_lv) ++{ ++ struct lv_segment *seg_thinpool = first_seg(pool_lv); ++ ++ if (!seg_thinpool || !seg_is_thin_pool(seg_thinpool)) { ++ log_error(INTERNAL_ERROR "data_lv_from_thin_pool arg not thin pool %s", pool_lv->name); ++ return NULL; ++ } ++ ++ return seg_thinpool->areas[0].u.lv.lv; ++} ++ + /* TODO: drop unused no_update */ + int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type, + struct logical_volume *lv, uint32_t delete_id, +diff --git a/test/shell/lvremove-thindata-caches.sh b/test/shell/lvremove-thindata-caches.sh +new file mode 100644 +index 0000000..ba099c3 +--- /dev/null ++++ b/test/shell/lvremove-thindata-caches.sh +@@ -0,0 +1,71 @@ ++#!/usr/bin/env bash ++ ++# Copyright (C) 2017-2020 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 have_cache 1 10 0 || skip ++aux have_writecache 1 0 0 || skip ++which mkfs.xfs || skip ++ ++aux prepare_devs 6 70 # want 64M of usable space from each dev ++ ++vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" ++ ++# lv1 is thinpool LV: 128M ++# lv2 is fast LV: 64M ++# lv3 is thin LV: 1G ++ ++# ++# Test lvremove of a thinpool that uses cache|writecache on data ++# ++ ++# attach writecache to thinpool data ++lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2" ++lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg ++lvcreate -n $lv2 -L64M -an $vg "$dev3" ++lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 ++lvchange -ay $vg/$lv1 ++lvs -a $vg ++mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3" ++lvremove -y $vg/$lv1 ++ ++# attach cache/writeback (cachevol) to thinpool data ++lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2" ++lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg ++lvcreate -n $lv2 -L64M -an $vg "$dev3" ++lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 ++lvchange -ay $vg/$lv1 ++mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3" ++lvremove -y $vg/$lv1 ++ ++# attach cache/writethrough (cachevol) to thinpool data ++lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2" ++lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg ++lvcreate -n $lv2 -L64M -an $vg "$dev3" ++lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 ++lvchange -ay $vg/$lv1 ++mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3" ++lvremove -y $vg/$lv1 ++ ++# attach cache (cachepool) to thinpool data ++lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2" ++lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg ++lvcreate -y --type cache-pool -n $lv2 -L64M --poolmetadataspare n $vg "$dev3" "$dev6" ++lvconvert -y --type cache --cachepool $lv2 --poolmetadataspare n $vg/$lv1 ++lvchange -ay $vg/$lv1 ++mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3" ++lvremove -y $vg/$lv1 ++ ++vgremove -f $vg ++ diff --git a/SOURCES/lvm2-2_03_13-man-vdoimport-page.patch b/SOURCES/lvm2-2_03_13-man-vdoimport-page.patch new file mode 100644 index 0000000..fe6032c --- /dev/null +++ b/SOURCES/lvm2-2_03_13-man-vdoimport-page.patch @@ -0,0 +1,102 @@ + man/vdoimport.8_main | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 92 insertions(+) + create mode 100644 man/vdoimport.8_main + +diff --git a/man/vdoimport.8_main b/man/vdoimport.8_main +new file mode 100644 +index 0000000..1f32909 +--- /dev/null ++++ b/man/vdoimport.8_main +@@ -0,0 +1,92 @@ ++.TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\"" ++. ++.SH "NAME" ++. ++vdoimport \(em utility to import VDO volumes into a new volume group. ++. ++.SH SYNOPSIS ++. ++.PD 0 ++.ad l ++.TP 10 ++.B vdoimport ++.RI [ options ] ++.IR device ++. ++.PD ++. ++.SH DESCRIPTION ++. ++vdoimport utility imports VDO volumes created and managed by ++.BR vdo (8) ++manager into ++.BR lvm2 (8) ++managed VDO LV. This is realized by moving VDO superblock by 2MiB ++and creating lvm2 metadata at the front of this device. The operation is not reversible, ++thus after conversion to lvm2 the access to VDO data is only possible with ++.BR lvm2 (8) ++commands, ++.BR vdo (8) ++manager no longer control such volume. ++. ++.SH OPTIONS ++. ++.TP ++.BR -f | --force ++Bypass some sanity checks. ++. ++.TP ++.BR -h | --help ++Display the help text. ++. ++.TP ++.BR -n | --name ++Specifies the name of converted VDO LV. When the name is not specified, ++some automatic name is selected. In case the converted VDO volume is ++already using LV a backend device, the name of this LV is used for VDO LV. ++In this case also the of volume group must stay same. ++. ++.TP ++.BR -v | --verbose ++Be more verbose. ++. ++.TP ++.BR -y | --yes ++Answer "yes" at any prompts. ++. ++.TP ++.BR --dry-run ++Print commands without running them. ++. ++. ++.SH DIAGNOSTICS ++. ++On successful completion, the status code is 0. ++A status code of 1 is used for failure. ++. ++.SH EXAMPLES ++. ++Convert VDO volume created by vdo manager into logical volume LV1 with within volume group VG1. ++.P ++# ++.B vdoimport --name VG1/LV1 /dev/mapper/vdo-volume ++. ++.SH ENVIRONMENT VARIABLES ++. ++.TP ++.B TMPDIR ++The temporary directory name for mount points. Defaults to "\fI/tmp\fP". ++.TP ++.B DM_DEV_DIR ++The device directory name. ++Defaults to "\fI/dev\fP" and must be an absolute path. ++. ++.SH SEE ALSO ++. ++.nh ++.ad l ++.BR lvm (8), ++.BR lvm.conf (5), ++.P ++.BR vdo (8), ++.BR vdo2lvm (8), diff --git a/SOURCES/lvm2-2_03_13-test.patch b/SOURCES/lvm2-2_03_13-test.patch new file mode 100644 index 0000000..f6672b7 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-test.patch @@ -0,0 +1,61 @@ + test/shell/vgsplit-cache.sh | 47 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) + +diff --git a/test/shell/vgsplit-cache.sh b/test/shell/vgsplit-cache.sh +index eba85be..202e4b5 100644 +--- a/test/shell/vgsplit-cache.sh ++++ b/test/shell/vgsplit-cache.sh +@@ -75,6 +75,53 @@ lvremove -y $vg + vgremove -ff $vg + vgremove -ff $vg1 + ++# ++# Check we handle pmspare for splitted VGs ++# ++aux prepare_vg 7 ++ ++# Create cache-pool and pmspare on single PV1 ++lvcreate -L10 --type cache-pool $vg/cpool "$dev1" ++# Move spare to separate PV3 ++pvmove -n $vg/lvol0_pmspare "$dev1" "$dev3" ++# Create origin on PV2 ++lvcreate -L10 -n orig $vg "$dev2" ++lvconvert -H -y --cachepool $vg/cpool $vg/orig ++ ++vgchange -an $vg ++ ++# Check we do not create new _pmspare ++vgsplit --poolmetadataspare n $vg $vg1 "$dev2" "$dev1" ++ ++check lv_exists $vg/lvol0_pmspare ++check lv_not_exists $vg1/lvol0_pmspare ++ ++vgremove $vg ++vgremove -f $vg1 ++ ++ ++aux prepare_vg 7 ++ ++# Again - now with handling _pmspare by vgsplit ++lvcreate -L10 --type cache-pool $vg/cpool "$dev1" ++# Move spare to separate PV3 ++pvmove -n $vg/lvol0_pmspare "$dev1" "$dev3" ++# Create origin on PV2 ++lvcreate -L10 -n orig $vg "$dev2" ++lvconvert -H -y --cachepool $vg/cpool $vg/orig ++ ++vgchange -an $vg ++ ++# Handle _pmspare (default) ++vgsplit --poolmetadataspare y $vg $vg1 "$dev2" "$dev1" ++ ++check lv_not_exists $vg/lvol0_pmspare ++check lv_exists $vg1/lvol0_pmspare ++ ++vgremove $vg ++vgremove -f $vg1 ++ ++ + vgcreate $vg "$dev1" "$dev2" "$dev3" "$dev4" + + lvcreate -L6 -n $lv1 -an $vg "$dev2" diff --git a/SOURCES/lvm2-2_03_13-tests-extend-vgmerge-testing.patch b/SOURCES/lvm2-2_03_13-tests-extend-vgmerge-testing.patch new file mode 100644 index 0000000..22dca89 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-tests-extend-vgmerge-testing.patch @@ -0,0 +1,53 @@ + test/shell/vgmerge-operation.sh | 42 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/test/shell/vgmerge-operation.sh b/test/shell/vgmerge-operation.sh +index 21889e9..0bf517d 100644 +--- a/test/shell/vgmerge-operation.sh ++++ b/test/shell/vgmerge-operation.sh +@@ -80,3 +80,45 @@ grep "Duplicate logical volume name \"$lv1\" in \"$vg2\" and \"$vg1" err + check pvlv_counts $vg1 2 1 0 + check pvlv_counts $vg2 2 1 0 + vgremove -f $vg1 $vg2 ++ ++ ++# 'vgmerge' handle pmspare for merged VG ++if aux have_thin 1 5 0; then ++ ++# With disabled pmspare nothing is created ++vgcreate $vg1 "$dev1" "$dev2" ++vgcreate $vg2 "$dev3" "$dev4" ++lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M --poolmetadataspare n ++lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M --poolmetadataspare n ++vgchange -an $vg1 $vg2 ++ ++vgmerge --poolmetadataspare n $vg1 $vg2 ++check lv_not_exists $vg/lvol0_pmspare ++vgremove -ff $vg1 ++ ++ ++# With pmspare handling there are one created ++vgcreate $vg1 "$dev1" "$dev2" ++vgcreate $vg2 "$dev3" "$dev4" ++lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M --poolmetadataspare n ++lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M --poolmetadataspare n ++vgchange -an $vg1 $vg2 ++ ++vgmerge $vg1 $vg2 ++check lv_field $vg1/lvol0_pmspare size "8.00m" ++vgremove -ff $vg1 ++ ++ ++# When merged, bigger pmspare is preserved ++vgcreate $vg1 "$dev1" "$dev2" ++vgcreate $vg2 "$dev3" "$dev4" ++lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M ++lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M ++vgchange -an $vg1 $vg2 ++ ++vgmerge $vg1 $vg2 ++ ++check lv_field $vg1/lvol0_pmspare size "8.00m" ++vgremove -ff $vg1 ++ ++fi diff --git a/SOURCES/lvm2-2_03_13-thin-fix-component-detection-of-external-origin.patch b/SOURCES/lvm2-2_03_13-thin-fix-component-detection-of-external-origin.patch new file mode 100644 index 0000000..5b97d90 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-thin-fix-component-detection-of-external-origin.patch @@ -0,0 +1,63 @@ + WHATS_NEW | 1 + + lib/activate/activate.c | 5 ++++- + test/shell/lvconvert-cache-thin.sh | 22 ++++++++++++++++++++++ + 3 files changed, 27 insertions(+), 1 deletion(-) + +diff --git a/WHATS_NEW b/WHATS_NEW +index 5806ecb..097160e 100644 +--- a/WHATS_NEW ++++ b/WHATS_NEW +@@ -1,5 +1,6 @@ + Version 2.03.13 - + =============================== ++ Fix detection of active components of external origin volume. + Add vdoimport tool to support conversion of VDO volumes. + Support configurable allocation/vdo_pool_header_size. + Fix handling of lvconvert --type vdo-pool --virtualsize. +diff --git a/lib/activate/activate.c b/lib/activate/activate.c +index 6bda738..94fc944 100644 +--- a/lib/activate/activate.c ++++ b/lib/activate/activate.c +@@ -2740,7 +2740,10 @@ static int _component_cb(struct logical_volume *lv, void *data) + (lv_is_thin_pool(lv) && pool_is_active(lv))) + return -1; + +- if (lv_is_active(lv)) { ++ /* External origin is activated through thinLV and uses -real suffix. ++ * Note: for old clustered logic we would need to check for all thins */ ++ if ((lv_is_external_origin(lv) && lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0)) || ++ lv_is_active(lv)) { + if (!lv_is_component(lv) || lv_is_visible(lv)) + return -1; /* skip whole subtree */ + +diff --git a/test/shell/lvconvert-cache-thin.sh b/test/shell/lvconvert-cache-thin.sh +index 7dda6e6..9254239 100644 +--- a/test/shell/lvconvert-cache-thin.sh ++++ b/test/shell/lvconvert-cache-thin.sh +@@ -67,4 +67,26 @@ fail lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv + # Thin-pool CAN use cached data LV + lvconvert --yes --thinpool $vg/$lv + ++lvremove -f $vg ++ ++# Check we can active snapshot of cached external origin (BZ: 1967744) ++lvcreate -T -L10M $vg/pool "$dev1" ++ ++lvcreate -L10M -n origin $vg "$dev1" ++lvcreate -H -L4M -n CPOOL $vg/origin "$dev2" ++ ++# Use cached origin as external origin ++lvconvert -y -T --thinpool $vg/pool --originname extorig origin ++ ++# Check we can easily create snapshot of such LV ++lvcreate -y -kn -n snap -s $vg/origin ++ ++# Deactivate everything and do a component activation of _cmeta volume ++lvchange -an $vg ++lvchange -ay -y $vg/CPOOL_cpool_cmeta ++ ++# Now this must fail since component volume is active ++not lvcreate -y -kn -n snap2 -s $vg/origin |& tee err ++grep "cmeta is active" err ++ + vgremove -f $vg diff --git a/SOURCES/lvm2-2_03_13-vdo-add-vdoimport-support.patch b/SOURCES/lvm2-2_03_13-vdo-add-vdoimport-support.patch new file mode 100644 index 0000000..aed2254 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-vdo-add-vdoimport-support.patch @@ -0,0 +1,729 @@ + WHATS_NEW | 3 + + configure | 25 +++ + configure.ac | 15 ++ + include/configure.h.in | 3 + + man/Makefile.in | 7 +- + scripts/Makefile.in | 4 + + scripts/vdoimport.sh | 376 ++++++++++++++++++++++++++++++++++++++++++++++ + test/Makefile.in | 1 + + test/shell/vdo-convert.sh | 110 ++++++++++++++ + 9 files changed, 543 insertions(+), 1 deletion(-) + create mode 100755 scripts/vdoimport.sh + create mode 100644 test/shell/vdo-convert.sh + +diff --git a/WHATS_NEW b/WHATS_NEW +index 04c6dcd..5806ecb 100644 +--- a/WHATS_NEW ++++ b/WHATS_NEW +@@ -1,5 +1,8 @@ + Version 2.03.13 - + =============================== ++ Add vdoimport tool to support conversion of VDO volumes. ++ Support configurable allocation/vdo_pool_header_size. ++ Fix handling of lvconvert --type vdo-pool --virtualsize. + Fix load of kvdo target when it is not present in memory (2.03.12). + + Version 2.03.12 - 07th May 2021 +diff --git a/configure b/configure +index 7c6bd48..661702d 100755 +--- a/configure ++++ b/configure +@@ -643,6 +643,8 @@ WRITE_INSTALL + WRITECACHE + VDO_LIB + VDO_INCLUDE ++VDOIMPORT_PATH ++VDOIMPORT + VDO + VALGRIND_POOL + USRSBINDIR +@@ -966,6 +968,7 @@ enable_dbus_service + enable_pkgconfig + enable_write_install + enable_fsadm ++enable_vdoimport + enable_blkdeactivate + enable_dmeventd + enable_selinux +@@ -1701,6 +1704,7 @@ Optional Features: + --enable-pkgconfig install pkgconfig support + --enable-write_install install user writable files + --disable-fsadm disable fsadm ++ --disable-vdoimport disable vdoimport + --disable-blkdeactivate disable blkdeactivate + --enable-dmeventd enable the device-mapper event daemon + --disable-selinux disable selinux support +@@ -3128,6 +3132,7 @@ case "$host_os" in + DM_IOCTLS=yes + SELINUX=yes + FSADM=yes ++ VDOIMPORT=yes + BLKDEACTIVATE=yes + ;; + darwin*) +@@ -3141,6 +3146,7 @@ case "$host_os" in + DM_IOCTLS=no + SELINUX=no + FSADM=no ++ VDOIMPORT=no + BLKDEACTIVATE=no + ;; + *) +@@ -12371,6 +12377,18 @@ fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FSADM" >&5 + $as_echo "$FSADM" >&6; } + ++ ++################################################################################ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install vdoimport" >&5 ++$as_echo_n "checking whether to install vdoimport... " >&6; } ++# Check whether --enable-vdoimport was given. ++if test "${enable_vdoimport+set}" = set; then : ++ enableval=$enable_vdoimport; VDOIMPORT=$enableval ++fi ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $VDOIMPORT" >&5 ++$as_echo "$VDOIMPORT" >&6; } ++ + ################################################################################ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install blkdeactivate" >&5 + $as_echo_n "checking whether to install blkdeactivate... " >&6; } +@@ -13857,6 +13875,13 @@ cat >>confdefs.h <<_ACEOF + _ACEOF + + ++VDOIMPORT_PATH="$SBINDIR/vdoimport" ++ ++cat >>confdefs.h <<_ACEOF ++#define VDOIMPORT_PATH "$VDOIMPORT_PATH" ++_ACEOF ++ ++ + ################################################################################ + if test "$BUILD_DMEVENTD" = yes; then + +diff --git a/configure.ac b/configure.ac +index 1a49e7f..5a8b486 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -45,6 +45,7 @@ case "$host_os" in + DM_IOCTLS=yes + SELINUX=yes + FSADM=yes ++ VDOIMPORT=yes + BLKDEACTIVATE=yes + ;; + darwin*) +@@ -58,6 +59,7 @@ case "$host_os" in + DM_IOCTLS=no + SELINUX=no + FSADM=no ++ VDOIMPORT=no + BLKDEACTIVATE=no + ;; + *) +@@ -1291,6 +1293,14 @@ AC_ARG_ENABLE(fsadm, AC_HELP_STRING([--disable-fsadm], [disable fsadm]), + FSADM=$enableval) + AC_MSG_RESULT($FSADM) + ++ ++################################################################################ ++dnl -- Enable vdoimport ++AC_MSG_CHECKING(whether to install vdoimport) ++AC_ARG_ENABLE(vdoimport, AC_HELP_STRING([--disable-vdoimport], [disable vdoimport]), ++ VDOIMPORT=$enableval) ++AC_MSG_RESULT($VDOIMPORT) ++ + ################################################################################ + dnl -- Enable blkdeactivate + AC_MSG_CHECKING(whether to install blkdeactivate) +@@ -1646,6 +1656,9 @@ USRSBINDIR="$(eval echo $(eval echo $usrsbindir))" + FSADM_PATH="$SBINDIR/fsadm" + AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.]) + ++VDOIMPORT_PATH="$SBINDIR/vdoimport" ++AC_DEFINE_UNQUOTED(VDOIMPORT_PATH, ["$VDOIMPORT_PATH"], [Path to vdoimport binary.]) ++ + ################################################################################ + dnl -- dmeventd pidfile and executable path + if test "$BUILD_DMEVENTD" = yes; then +@@ -1882,6 +1895,8 @@ AC_SUBST(SILENT_RULES) + AC_SUBST(USRSBINDIR) + AC_SUBST(VALGRIND_POOL) + AC_SUBST(VDO) ++AC_SUBST(VDOIMPORT) ++AC_SUBST(VDOIMPORT_PATH) + AC_SUBST(VDO_FORMAT_CMD) + AC_SUBST(VDO_INCLUDE) + AC_SUBST(VDO_LIB) +diff --git a/include/configure.h.in b/include/configure.h.in +index 671d201..6df8d89 100644 +--- a/include/configure.h.in ++++ b/include/configure.h.in +@@ -684,6 +684,9 @@ + /* Enable a valgrind aware build of pool */ + #undef VALGRIND_POOL + ++/* Path to vdoimport binary. */ ++#undef VDOIMPORT_PATH ++ + /* The path to 'vdoformat', if available. */ + #undef VDO_FORMAT_CMD + +diff --git a/man/Makefile.in b/man/Makefile.in +index 29afc77..d60a92c 100644 +--- a/man/Makefile.in ++++ b/man/Makefile.in +@@ -23,6 +23,7 @@ else + endif + + FSADMMAN = fsadm.8 ++VDOIMPORTMAN = vdoimport.8 + BLKDEACTIVATEMAN = blkdeactivate.8 + DMEVENTDMAN = dmeventd.8 + DMFILEMAPDMAN = dmfilemapd.8 +@@ -50,7 +51,7 @@ MAN8SYSTEMD_GENERATORS=lvm2-activation-generator.8 + + ifeq (,$(findstring $(MAKECMDGOALS), distclean all_man install_all_man)) + MAN7 += lvmcache.7 lvmthin.7 lvmvdo.7 +- MAN8+=$(FSADMMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN) ++ MAN8+=$(FSADMMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN) $(VDOIMPORTMAN) + MAN8DM+=$(BLKDEACTIVATEMAN) $(DMEVENTDMAN) $(DMFILEMAPDMAN) + MAN8CLUSTER+=$(CMIRRORDMAN) + else +@@ -58,6 +59,10 @@ else + MAN8+=$(FSADMMAN) + endif + ++ ifeq ("@VDOIMPORT@", "yes") ++ MAN8+=$(VDOIMPORTMAN) ++ endif ++ + ifeq ("@BUILD_LVMDBUSD@", "yes") + MAN8+=$(LVMDBUSDMAN) + endif +diff --git a/scripts/Makefile.in b/scripts/Makefile.in +index e8f6742..1fe88ca 100644 +--- a/scripts/Makefile.in ++++ b/scripts/Makefile.in +@@ -31,6 +31,10 @@ ifeq ("@FSADM@", "yes") + LVM_SCRIPTS += fsadm.sh + endif + ++ifeq ("@VDOIMPORT@", "yes") ++ LVM_SCRIPTS += vdoimport.sh ++endif ++ + ifeq ("@BLKDEACTIVATE@", "yes") + DM_SCRIPTS += blkdeactivate.sh + endif +diff --git a/scripts/vdoimport.sh b/scripts/vdoimport.sh +new file mode 100755 +index 0000000..ef96591 +--- /dev/null ++++ b/scripts/vdoimport.sh +@@ -0,0 +1,376 @@ ++#!/bin/bash ++# ++# Copyright (C) 2021 Red Hat, Inc. All rights reserved. ++# ++# This file is part of LVM2. ++# ++# 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 ++# ++# Author: Zdenek Kabelac ++# ++# Script for converting VDO volumes to lvm2 VDO LVs ++# ++# Needed utilities: ++# lvm, dmsetup, ++# vdo, vdo2lvm, ++# grep, awk, sed, blockdev, readlink, mkdir ++# ++# Conversion is using 'vdo convert' support from VDO manager to move ++# existing VDO header by 2M which makes space to place in PV header ++# and VG metadata area, and then create VDOPOOL LV and VDO LV in such VG. ++# ++ ++set -euE -o pipefail ++ ++TOOL=vdoimport ++ ++_SAVEPATH=$PATH ++PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH" ++ ++# user may override lvm location by setting LVM_BINARY ++LVM=${LVM_BINARY:-lvm} ++VDO=${VDO_BINARY:-vdo} ++VDOCONF=${VDOCONF:-} ++BLOCKDEV="blockdev" ++READLINK="readlink" ++READLINK_E="-e" ++MKDIR="mkdir" ++ ++TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$" ++DM_DEV_DIR="${DM_DEV_DIR:-/dev}" ++ ++DRY=0 ++VERB="" ++FORCE="" ++YES="" ++ ++# default name for converted VG and its VDO LV ++NAME="vdovg/vdolvol" ++ ++# help message ++tool_usage() { ++ echo "${TOOL}: Utility to convert VDO volume to VDO LV." ++ echo ++ echo " ${TOOL} [options] " ++ echo ++ echo " Options:" ++ echo " -f | --force Bypass sanity checks" ++ echo " -h | --help Show this help message" ++ echo " -n | --name Specifies VG/LV name for converted VDO volume" ++ echo " -v | --verbose Be verbose" ++ echo " -y | --yes Answer \"yes\" at any prompts" ++ echo " --dry-run Print commands without running them" ++ ++ exit ++} ++ ++verbose() { ++ test -z "$VERB" || echo "$TOOL:" "$@" ++} ++ ++# Support multi-line error messages ++error() { ++ for i in "$@" ; do ++ echo "$TOOL: $i" >&2 ++ done ++ cleanup 1 ++} ++ ++dry() { ++ if [ "$DRY" -ne 0 ]; then ++ verbose "Dry execution" "$@" ++ return 0 ++ fi ++ verbose "Executing" "$@" ++ "$@" ++} ++ ++cleanup() { ++ trap '' 2 ++ ++ rm -rf "$TEMPDIR" ++ # error exit status for break ++ exit "${1:-1}" ++} ++ ++get_enabled_value_() { ++ case "$1" in ++ enabled) echo "1" ;; ++ *) echo "0" ;; ++ esac ++} ++ ++get_kb_size_with_unit_() { ++ case "$1" in ++ *[kK]) echo $(( ${1%[kK]} )) ;; ++ *[mM]) echo $(( ${1%[mM]} * 1024 )) ;; ++ *[gG]) echo $(( ${1%[gG]} * 1024 * 1024 )) ;; ++ *[tT]) echo $(( ${1%[tT]} * 1024 * 1024 * 1024 )) ;; ++ *[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 * 1024 )) ;; ++ esac ++} ++ ++get_mb_size_with_unit_() { ++ case "$1" in ++ *[mM]) echo $(( ${1%[mM]} )) ;; ++ *[gG]) echo $(( ${1%[gG]} * 1024 )) ;; ++ *[tT]) echo $(( ${1%[tT]} * 1024 * 1024 )) ;; ++ *[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 )) ;; ++ esac ++} ++ ++# Figure out largest possible extent size usable for VG ++# $1 physical size ++# $2 logical size ++get_largest_extent_size_() { ++ local max=4 ++ local i ++ local d ++ ++ for i in 8 16 32 64 128 256 512 1024 2048 4096 ; do ++ d=$(( $1 / i )) ++ test $(( d * i )) -eq "$1" || break ++ d=$(( $2 / i )) ++ test $(( d * i )) -eq "$2" || break ++ max=$i ++ done ++ echo "$max" ++} ++ ++# detect LV on the given device ++# dereference device name if it is symbolic link ++detect_lv_() { ++ local DEVICE=$1 ++ local MAJOR ++ local MINOR ++ local SYSVOLUME ++ local MAJORMINOR ++ ++ DEVICE=${1/#"${DM_DEV_DIR}/"/} ++ DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE") ++ test -n "$DEVICE" || error "Cannot get readlink \"$1\"." ++ RDEVICE=$DEVICE ++ case "$RDEVICE" in ++ # hardcoded /dev since udev does not create these entries elsewhere ++ /dev/dm-[0-9]*) ++ read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME" ++ read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"." ++ MAJOR=${MAJORMINOR%%:*} ++ MINOR=${MAJORMINOR##*:} ++ ;; ++ *) ++ STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE") ++ test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"." ++ eval "$STAT" ++ ;; ++ esac ++ ++ eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')" ++} ++ ++# parse yaml config files into 'prefix_yaml_part_names=("value")' strings ++parse_yaml_() { ++ local yaml_file=$1 ++ local prefix=$2 ++ local s ++ local w ++ local fs ++ ++ s='[[:space:]]*' ++ w='[a-zA-Z0-9_.-]*' ++ fs="$(echo @|tr @ '\034')" ++ ++ ( ++ sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/[[:space:]]*$//g;' \ ++ -e 's/\$/\\\$/g' \ ++ -e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \ ++ -e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ ++ -e "s|^\($s\)\($w\)${s}[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" | ++ ++ awk -F"$fs" '{ ++ indent = length($1)/2; ++ if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";} ++ vname[indent] = $2; ++ for (i in vname) {if (i > indent) {delete vname[i]}} ++ if (length($3) > 0) { ++ vn=""; for (i=0; i"$TEMPDIR/vdoconf.yml" ++ ++ VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml") ++ TRVDONAME=$(echo "$VDONAME" | tr '-' '_') ++ ++ # When VDO volume is 'active', check it's not mounted/being used ++ eval "$(dmsetup info -c -o open "$VDONAME" --noheadings --nameprefixes || true)" ++ test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!" ++ ++ #parse_yaml_ "$TEMPDIR/vdoconf.yml" _ ++ eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")" ++ ++ vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize") ++ vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize") ++ ++ verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB." ++ verbose "With logical volume of size $vdo_logicalSize KiB." ++ ++ PARAMS=$(cat <vg; + struct logical_volume *vdo_lv; + struct dm_vdo_target_params vdo_params; /* vdo */ +@@ -5497,12 +5497,12 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd, + goto out; + } + +- zero_vdopool = arg_int_value(cmd, zero_ARG, 1); ++ vdo_pool_zero = arg_int_value(cmd, zero_ARG, 1); + + log_warn("WARNING: Converting logical volume %s to VDO pool volume %s formating.", +- display_lvname(lv), zero_vdopool ? "with" : "WITHOUT"); ++ display_lvname(lv), vdo_pool_zero ? "with" : "WITHOUT"); + +- if (zero_vdopool) ++ if (vdo_pool_zero) + log_warn("THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.)"); + else + log_warn("WARNING: Using invalid VDO pool data MAY DESTROY YOUR DATA!"); +@@ -5514,7 +5514,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd, + goto out; + } + +- if (zero_vdopool) { ++ if (vdo_pool_zero) { + if (!wipe_lv(lv, (struct wipe_params) { .do_zero = 1, .do_wipe_signatures = 1, + .yes = arg_count(cmd, yes_ARG), + .force = arg_count(cmd, force_ARG)})) { +@@ -5526,7 +5526,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd, + if (!archive(vg)) + goto_out; + +- if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents, zero_vdopool)) ++ if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents, vdo_pool_zero)) + goto_out; + + dm_list_init(&lvc.tags); diff --git a/SOURCES/lvm2-2_03_13-vdo-support-vdo_pool_header_size.patch b/SOURCES/lvm2-2_03_13-vdo-support-vdo_pool_header_size.patch new file mode 100644 index 0000000..63235b0 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-vdo-support-vdo_pool_header_size.patch @@ -0,0 +1,197 @@ + conf/example.conf.in | 5 +++++ + lib/config/config_settings.h | 3 +++ + lib/config/defaults.h | 3 +-- + lib/metadata/lv_manip.c | 3 ++- + lib/metadata/metadata-exported.h | 5 ++++- + lib/metadata/vdo_manip.c | 13 ++++++++----- + tools/lvconvert.c | 6 ++++-- + tools/lvcreate.c | 2 +- + 8 files changed, 28 insertions(+), 12 deletions(-) + +diff --git a/conf/example.conf.in b/conf/example.conf.in +index aaf73a4..78547a6 100644 +--- a/conf/example.conf.in ++++ b/conf/example.conf.in +@@ -734,6 +734,11 @@ allocation { + # The default and minimum is 1. The maximum is UINT_MAX / 4096. + # This configuration option has an automatic default value. + # vdo_max_discard = 1 ++ ++ # Configuration option allocation/vdo_pool_header_size. ++ # Specified the emptry header size in KiB at the front and end of vdo pool device. ++ # This configuration option has an automatic default value. ++ # vdo_pool_header_size = 512 + } + + # Configuration section log. +diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h +index f5dac4d..5217da8 100644 +--- a/lib/config/config_settings.h ++++ b/lib/config/config_settings.h +@@ -816,6 +816,9 @@ cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, C + "increased latency for the individual discard requests.\n" + "The default and minimum is 1. The maximum is UINT_MAX / 4096.\n") + ++cfg(allocation_vdo_pool_header_size_CFG, "vdo_pool_header_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_HEADER_SIZE_KB, vsn(2, 3, 12), NULL, 0, NULL, ++ "Specified the emptry header size in KiB at the front and end of vdo pool device.\n") ++ + cfg(log_report_command_log_CFG, "report_command_log", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_BOOL, DEFAULT_COMMAND_LOG_REPORT, vsn(2, 2, 158), NULL, 0, NULL, + "Enable or disable LVM log reporting.\n" + "If enabled, LVM will collect a log of operations, messages,\n" +diff --git a/lib/config/defaults.h b/lib/config/defaults.h +index 2870dee..d5e5b3b 100644 +--- a/lib/config/defaults.h ++++ b/lib/config/defaults.h +@@ -181,8 +181,7 @@ + * VDO pool will reverve some sectors in the front and the back of pool device to avoid + * seeing same device twice in the system. + */ +-#define DEFAULT_VDO_POOL_HEADER_SIZE (1024) // 512KiB +- ++#define DEFAULT_VDO_POOL_HEADER_SIZE_KB (512) + + + #define DEFAULT_FSADM_PATH FSADM_PATH +diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c +index 37dd361..43af474 100644 +--- a/lib/metadata/lv_manip.c ++++ b/lib/metadata/lv_manip.c +@@ -8766,7 +8766,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, + } + + if (seg_is_vdo_pool(lp)) { +- if (!convert_vdo_pool_lv(lv, &lp->vdo_params, &lp->virtual_extents, 1)) { ++ if (!convert_vdo_pool_lv(lv, &lp->vdo_params, &lp->virtual_extents, ++ 1, lp->vdo_pool_header_size)) { + stack; + goto deactivate_and_revert_new_lv; + } +diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h +index 54bc0d0..adbbe76 100644 +--- a/lib/metadata/metadata-exported.h ++++ b/lib/metadata/metadata-exported.h +@@ -1033,6 +1033,7 @@ struct lvcreate_params { + int approx_alloc; /* all */ + alloc_policy_t alloc; /* all */ + struct dm_vdo_target_params vdo_params; /* vdo */ ++ uint64_t vdo_pool_header_size; /* VDO */ + + int raidintegrity; + const char *raidintegritymode; +@@ -1367,10 +1368,12 @@ int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_ + struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv, + const struct dm_vdo_target_params *vtp, + uint32_t *virtual_extents, +- int format); ++ int format, ++ uint64_t vdo_pool_header_size); + int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy); + int fill_vdo_target_params(struct cmd_context *cmd, + struct dm_vdo_target_params *vtp, ++ uint64_t *vdo_pool_header_size, + struct profile *profile); + /* -- metadata/vdo_manip.c */ + +diff --git a/lib/metadata/vdo_manip.c b/lib/metadata/vdo_manip.c +index afc513a..3f2de1a 100644 +--- a/lib/metadata/vdo_manip.c ++++ b/lib/metadata/vdo_manip.c +@@ -356,9 +356,9 @@ static int _format_vdo_pool_data_lv(struct logical_volume *data_lv, + struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv, + const struct dm_vdo_target_params *vtp, + uint32_t *virtual_extents, +- int format) ++ int format, ++ uint64_t vdo_pool_header_size) + { +- const uint64_t header_size = DEFAULT_VDO_POOL_HEADER_SIZE; + const uint32_t extent_size = data_lv->vg->extent_size; + struct cmd_context *cmd = data_lv->vg->cmd; + struct logical_volume *vdo_pool_lv = data_lv; +@@ -379,7 +379,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv, + + if (*virtual_extents) + vdo_logical_size = +- _get_virtual_size(*virtual_extents, extent_size, header_size); ++ _get_virtual_size(*virtual_extents, extent_size, vdo_pool_header_size); + + if (!dm_vdo_validate_target_params(vtp, vdo_logical_size)) + return_0; +@@ -403,7 +403,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv, + return NULL; + } + +- vdo_logical_size -= 2 * header_size; ++ vdo_logical_size -= 2 * vdo_pool_header_size; + + if (vdo_logical_size < extent_size) { + if (!*virtual_extents) +@@ -426,7 +426,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv, + vdo_pool_seg = first_seg(vdo_pool_lv); + vdo_pool_seg->segtype = vdo_pool_segtype; + vdo_pool_seg->vdo_params = *vtp; +- vdo_pool_seg->vdo_pool_header_size = DEFAULT_VDO_POOL_HEADER_SIZE; ++ vdo_pool_seg->vdo_pool_header_size = vdo_pool_header_size; + vdo_pool_seg->vdo_pool_virtual_extents = *virtual_extents; + + vdo_pool_lv->status |= LV_VDO_POOL; +@@ -453,6 +453,7 @@ int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy) + + int fill_vdo_target_params(struct cmd_context *cmd, + struct dm_vdo_target_params *vtp, ++ uint64_t *vdo_pool_header_size, + struct profile *profile) + { + const char *policy; +@@ -501,5 +502,7 @@ int fill_vdo_target_params(struct cmd_context *cmd, + if (!set_vdo_write_policy(&vtp->write_policy, policy)) + return_0; + ++ *vdo_pool_header_size = 2 * find_config_tree_int64(cmd, allocation_vdo_pool_header_size_CFG, profile); ++ + return 1; + } +diff --git a/tools/lvconvert.c b/tools/lvconvert.c +index 8488596..f87ee78 100644 +--- a/tools/lvconvert.c ++++ b/tools/lvconvert.c +@@ -5439,6 +5439,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd, + { + const char *vg_name = NULL; + unsigned int vdo_pool_zero; ++ uint64_t vdo_pool_header_size; + struct volume_group *vg = lv->vg; + struct logical_volume *vdo_lv; + struct dm_vdo_target_params vdo_params; /* vdo */ +@@ -5481,7 +5482,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd, + goto out; + } + +- if (!fill_vdo_target_params(cmd, &vdo_params, vg->profile)) ++ if (!fill_vdo_target_params(cmd, &vdo_params, &vdo_pool_header_size, vg->profile)) + goto_out; + + if (arg_is_set(cmd, compression_ARG)) +@@ -5526,7 +5527,8 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd, + if (!archive(vg)) + goto_out; + +- if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents, vdo_pool_zero)) ++ if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents, ++ vdo_pool_zero, vdo_pool_header_size)) + goto_out; + + dm_list_init(&lvc.tags); +diff --git a/tools/lvcreate.c b/tools/lvcreate.c +index a28f093..0def236 100644 +--- a/tools/lvcreate.c ++++ b/tools/lvcreate.c +@@ -1097,7 +1097,7 @@ static int _lvcreate_params(struct cmd_context *cmd, + + // FIXME: prefiling here - this is wrong place + // but will work for this moment +- if (!fill_vdo_target_params(cmd, &lp->vdo_params, NULL)) ++ if (!fill_vdo_target_params(cmd, &lp->vdo_params, &lp->vdo_pool_header_size, NULL)) + return_0; + + if (arg_is_set(cmd, compression_ARG)) diff --git a/SOURCES/lvm2-2_03_13-vgmerge-remove-one-of-merge-pmspare-LVs.patch b/SOURCES/lvm2-2_03_13-vgmerge-remove-one-of-merge-pmspare-LVs.patch new file mode 100644 index 0000000..62d6686 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-vgmerge-remove-one-of-merge-pmspare-LVs.patch @@ -0,0 +1,28 @@ + tools/vgmerge.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/tools/vgmerge.c b/tools/vgmerge.c +index 895018a..884ad4b 100644 +--- a/tools/vgmerge.c ++++ b/tools/vgmerge.c +@@ -92,6 +92,20 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to, + } + } + ++ if (vg_from->pool_metadata_spare_lv && ++ vg_to->pool_metadata_spare_lv) { ++ if (vg_from->pool_metadata_spare_lv->le_count > ++ vg_to->pool_metadata_spare_lv->le_count) ++ /* Preserve bigger pmspare from VG_FROM */ ++ lv = vg_to->pool_metadata_spare_lv; ++ else ++ lv = vg_from->pool_metadata_spare_lv; ++ ++ log_debug_metadata("Removing pool metadata spare %s.", display_lvname(lv)); ++ if (!lv_remove_single(cmd, lv, DONT_PROMPT, 0)) ++ return_ECMD_FAILED; ++ } ++ + if (!vgs_are_compatible(cmd, vg_from, vg_to)) + goto_bad; + diff --git a/SOURCES/lvm2-2_03_13-vgmerge-support-option-poolmetadataspare.patch b/SOURCES/lvm2-2_03_13-vgmerge-support-option-poolmetadataspare.patch new file mode 100644 index 0000000..002c060 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-vgmerge-support-option-poolmetadataspare.patch @@ -0,0 +1,82 @@ + WHATS_NEW | 2 +- + man/vgmerge.8_pregen | 9 +++++++++ + tools/command-lines.in | 2 +- + tools/vgmerge.c | 6 ++++++ + 4 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/WHATS_NEW b/WHATS_NEW +index 0b8e3f2..5556789 100644 +--- a/WHATS_NEW ++++ b/WHATS_NEW +@@ -1,6 +1,6 @@ + Version 2.03.13 - + =============================== +- Support --poolmetadataspare with vgsplit. ++ Support --poolmetadataspare with vgsplit and vgmerge. + Fix detection of active components of external origin volume. + Add vdoimport tool to support conversion of VDO volumes. + Support configurable allocation/vdo_pool_header_size. +diff --git a/man/vgmerge.8_pregen b/man/vgmerge.8_pregen +index 1264bb5..e229218 100644 +--- a/man/vgmerge.8_pregen ++++ b/man/vgmerge.8_pregen +@@ -27,6 +27,8 @@ of both VGs fit into the destination VG's limits. + .br + [ \fB-l\fP|\fB--list\fP ] + .br ++[ \fB--poolmetadataspare\fP \fBy\fP|\fBn\fP ] ++.br + [ COMMON_OPTIONS ] + .ad b + .RE +@@ -147,6 +149,13 @@ Display long help text. + Disable locking. + . + .HP ++\fB--poolmetadataspare\fP \fBy\fP|\fBn\fP ++.br ++Enable or disable the automatic creation and management of a ++spare pool metadata LV in the VG. A spare metadata LV is reserved ++space that can be used when repairing a pool. ++. ++.HP + \fB--profile\fP \fIString\fP + .br + An alias for --commandprofile or --metadataprofile, depending +diff --git a/tools/command-lines.in b/tools/command-lines.in +index a4785b3..0bc5a49 100644 +--- a/tools/command-lines.in ++++ b/tools/command-lines.in +@@ -1847,7 +1847,7 @@ DESC: Add devices from all accessible VGs to the devices file. + --- + + vgmerge VG VG +-OO: --autobackup Bool, --list ++OO: --autobackup Bool, --list, --poolmetadataspare Bool + ID: vgmerge_general + + --- +diff --git a/tools/vgmerge.c b/tools/vgmerge.c +index 884ad4b..08615cd 100644 +--- a/tools/vgmerge.c ++++ b/tools/vgmerge.c +@@ -64,6 +64,8 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to, + struct lv_list *lvl1, *lvl2; + int r = ECMD_FAILED; + int lock_vg_from_first = 0; ++ struct logical_volume *lv; ++ int poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG, DEFAULT_POOL_METADATA_SPARE); + + if (!strcmp(vg_name_to, vg_name_from)) { + log_error("Duplicate volume group name \"%s\"", vg_name_from); +@@ -185,6 +187,10 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to, + /* Flag up that some PVs have moved from another VG */ + vg_to->old_name = vg_from->name; + ++ /* Check whether size of pmspare is big enough now for merged VG */ ++ if (!handle_pool_metadata_spare(vg_to, 0, &vg_to->pvs, poolmetadataspare)) ++ goto_bad; ++ + /* store it on disks */ + log_verbose("Writing out updated volume group"); + if (!vg_write(vg_to) || !vg_commit(vg_to)) diff --git a/SOURCES/lvm2-2_03_13-vgremove-remove-forgotten-pmspare.patch b/SOURCES/lvm2-2_03_13-vgremove-remove-forgotten-pmspare.patch new file mode 100644 index 0000000..53fa667 --- /dev/null +++ b/SOURCES/lvm2-2_03_13-vgremove-remove-forgotten-pmspare.patch @@ -0,0 +1,18 @@ + tools/vgremove.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tools/vgremove.c b/tools/vgremove.c +index 8f73297..b6685ae 100644 +--- a/tools/vgremove.c ++++ b/tools/vgremove.c +@@ -65,6 +65,10 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name, + } + } + ++ if (vg->pool_metadata_spare_lv && ++ !lvremove_single(cmd, vg->pool_metadata_spare_lv, &void_handle)) ++ return_ECMD_FAILED; ++ + if (!lockd_free_vg_before(cmd, vg, 0)) + return_ECMD_FAILED; + diff --git a/SOURCES/lvm2-2_03_13-vgsplit-add-support-for-option-poolmetadataspare.patch b/SOURCES/lvm2-2_03_13-vgsplit-add-support-for-option-poolmetadataspare.patch new file mode 100644 index 0000000..1a9d26b --- /dev/null +++ b/SOURCES/lvm2-2_03_13-vgsplit-add-support-for-option-poolmetadataspare.patch @@ -0,0 +1,106 @@ + WHATS_NEW | 1 + + lib/metadata/pool_manip.c | 11 +++++++++++ + man/vgsplit.8_pregen | 9 +++++++++ + tools/command-lines.in | 2 +- + tools/vgsplit.c | 8 ++++++++ + 5 files changed, 30 insertions(+), 1 deletion(-) + +diff --git a/WHATS_NEW b/WHATS_NEW +index 097160e..0b8e3f2 100644 +--- a/WHATS_NEW ++++ b/WHATS_NEW +@@ -1,5 +1,6 @@ + Version 2.03.13 - + =============================== ++ Support --poolmetadataspare with vgsplit. + Fix detection of active components of external origin volume. + Add vdoimport tool to support conversion of VDO volumes. + Support configurable allocation/vdo_pool_header_size. +diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c +index 9ceec3a..e451e92 100644 +--- a/lib/metadata/pool_manip.c ++++ b/lib/metadata/pool_manip.c +@@ -722,6 +722,17 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents, + return 1; + } + ++ if (!extents) { ++ /* pmspare is not needed */ ++ if (lv) { ++ log_debug_metadata("Dropping unused pool metadata spare LV %s.", ++ display_lvname(lv)); ++ if (!lv_remove_single(vg->cmd, lv, DONT_PROMPT, 0)) ++ return_0; ++ } ++ return 1; ++ } ++ + if (extents > MAX_SIZE) + extents = MAX_SIZE; + +diff --git a/man/vgsplit.8_pregen b/man/vgsplit.8_pregen +index 331c6e4..8a0ae59 100644 +--- a/man/vgsplit.8_pregen ++++ b/man/vgsplit.8_pregen +@@ -70,6 +70,8 @@ Common options for command: + .hy + ] + .br ++[ \fB--poolmetadataspare\fP \fBy\fP|\fBn\fP ] ++.br + [ \fB--\fP[\fBvg\fP]\fBmetadatacopies\fP \fBall\fP|\fBunmanaged\fP|\fINumber\fP ] + .ad b + .RE +@@ -235,6 +237,13 @@ Move only PVs used by the named LV. + Disable locking. + . + .HP ++\fB--poolmetadataspare\fP \fBy\fP|\fBn\fP ++.br ++Enable or disable the automatic creation and management of a ++spare pool metadata LV in the VG. A spare metadata LV is reserved ++space that can be used when repairing a pool. ++. ++.HP + \fB--profile\fP \fIString\fP + .br + An alias for --commandprofile or --metadataprofile, depending +diff --git a/tools/command-lines.in b/tools/command-lines.in +index 8607305..a4785b3 100644 +--- a/tools/command-lines.in ++++ b/tools/command-lines.in +@@ -1912,7 +1912,7 @@ ID: vgscan_general + + --- + +-OO_VGSPLIT: --autobackup Bool ++OO_VGSPLIT: --autobackup Bool, --poolmetadataspare Bool + + # used only when the destination VG is new + OO_VGSPLIT_NEW: --alloc Alloc, +diff --git a/tools/vgsplit.c b/tools/vgsplit.c +index 296248e..a085ac2 100644 +--- a/tools/vgsplit.c ++++ b/tools/vgsplit.c +@@ -525,6 +525,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) + int existing_vg = 0; + int r = ECMD_FAILED; + const char *lv_name; ++ int poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG, DEFAULT_POOL_METADATA_SPARE); + + if ((arg_is_set(cmd, name_ARG) + argc) < 3) { + log_error("Existing VG, new VG and either physical volumes " +@@ -699,6 +700,13 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) + */ + vg_to->status |= EXPORTED_VG; + ++ ++ if (!handle_pool_metadata_spare(vg_to, 0, &vg_to->pvs, poolmetadataspare)) ++ goto_bad; ++ ++ if (!handle_pool_metadata_spare(vg_from, 0, &vg_from->pvs, poolmetadataspare)) ++ goto_bad; ++ + if (!archive(vg_to)) + goto_bad; + diff --git a/SOURCES/lvm2-2_03_13-writecache-don-t-pvmove-device-used-by-writecache.patch b/SOURCES/lvm2-2_03_13-writecache-don-t-pvmove-device-used-by-writecache.patch new file mode 100644 index 0000000..1457f7f --- /dev/null +++ b/SOURCES/lvm2-2_03_13-writecache-don-t-pvmove-device-used-by-writecache.patch @@ -0,0 +1,23 @@ + tools/pvmove.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/tools/pvmove.c b/tools/pvmove.c +index da635a6..bb372f7 100644 +--- a/tools/pvmove.c ++++ b/tools/pvmove.c +@@ -387,6 +387,15 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd, + return NULL; + } + ++ if (lv_is_writecache(lv)) { ++ struct logical_volume *lv_cachevol = first_seg(lv)->writecache; ++ if (lv_is_on_pvs(lv_cachevol, source_pvl)) { ++ log_error("Unable to move device used for writecache cachevol %s.", display_lvname(lv_cachevol)); ++ return NULL; ++ } ++ ++ } ++ + if (lv_is_raid(lv) && lv_raid_has_integrity(lv)) { + log_error("Unable to pvmove device used for raid with integrity."); + return NULL; diff --git a/SOURCES/lvm2-2_03_13-writecache-fix-lv_on_pmem.patch b/SOURCES/lvm2-2_03_13-writecache-fix-lv_on_pmem.patch new file mode 100644 index 0000000..b926cac --- /dev/null +++ b/SOURCES/lvm2-2_03_13-writecache-fix-lv_on_pmem.patch @@ -0,0 +1,17 @@ + lib/metadata/metadata.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c +index 002d80c..1f65045 100644 +--- a/lib/metadata/metadata.c ++++ b/lib/metadata/metadata.c +@@ -4402,6 +4402,9 @@ int lv_on_pmem(struct logical_volume *lv) + + dm_list_iterate_items(seg, &lv->segments) { + for (s = 0; s < seg->area_count; s++) { ++ if (seg_type(seg, s) != AREA_PV) ++ continue; ++ + pv = seg_pv(seg, s); + + if (dev_is_pmem(lv->vg->cmd->dev_types, pv->dev)) { diff --git a/SOURCES/lvm2-2_03_14-tests-check-lvm2-parses-vdo-statistics.patch b/SOURCES/lvm2-2_03_14-tests-check-lvm2-parses-vdo-statistics.patch new file mode 100644 index 0000000..1adbfdd --- /dev/null +++ b/SOURCES/lvm2-2_03_14-tests-check-lvm2-parses-vdo-statistics.patch @@ -0,0 +1,25 @@ +From 155d8c55086b09528de799425e77f7aeafd9b165 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Thu, 9 Sep 2021 15:22:20 +0200 +Subject: [PATCH 2/5] tests: check lvm2 parses vdo statistics + +(cherry picked from commit bd2dae464386033241afa35934cdeddfe47f6a77) +--- + test/shell/lvcreate-vdo.sh | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/test/shell/lvcreate-vdo.sh b/test/shell/lvcreate-vdo.sh +index d66e353..5b370fb 100644 +--- a/test/shell/lvcreate-vdo.sh ++++ b/test/shell/lvcreate-vdo.sh +@@ -47,6 +47,7 @@ fi + check lv_field $vg/$lv1 size "<1.24g" + check lv_field $vg/${lv2} size "4.00g" + check lv_field $vg/${lv2}_vdata size "4.00g" ++check lv_field $vg/${lv1} data_percent "0.00" + lvremove -ff $vg + + +-- +1.8.3.1 + diff --git a/SOURCES/lvm2-2_03_14-vdo-Rename-vdoimport-to-lvm_import_vdo.patch b/SOURCES/lvm2-2_03_14-vdo-Rename-vdoimport-to-lvm_import_vdo.patch new file mode 100644 index 0000000..2250e1c --- /dev/null +++ b/SOURCES/lvm2-2_03_14-vdo-Rename-vdoimport-to-lvm_import_vdo.patch @@ -0,0 +1,1137 @@ + WHATS_NEW | 4 + + configure | 6 +- + configure.ac | 8 +- + include/configure.h.in | 2 +- + man/Makefile.in | 2 +- + man/lvm_import_vdo.8_main | 92 ++++++++++++ + man/vdoimport.8_main | 92 ------------ + scripts/Makefile.in | 2 +- + scripts/lvm_import_vdo.sh | 376 ++++++++++++++++++++++++++++++++++++++++++++++ + scripts/vdoimport.sh | 376 ---------------------------------------------- + test/Makefile.in | 2 +- + test/shell/vdo-convert.sh | 12 +- + 12 files changed, 489 insertions(+), 485 deletions(-) + create mode 100644 man/lvm_import_vdo.8_main + delete mode 100644 man/vdoimport.8_main + create mode 100755 scripts/lvm_import_vdo.sh + delete mode 100755 scripts/vdoimport.sh + +diff --git a/WHATS_NEW b/WHATS_NEW +index 5556789..3637e31 100644 +--- a/WHATS_NEW ++++ b/WHATS_NEW +@@ -1,3 +1,7 @@ ++Version 2.03.14 - ++================================== ++ Rename vdoimport to lvm_import_vdo. ++ + Version 2.03.13 - + =============================== + Support --poolmetadataspare with vgsplit and vgmerge. +diff --git a/configure b/configure +index 661702d..897a810 100755 +--- a/configure ++++ b/configure +@@ -12379,8 +12379,8 @@ $as_echo "$FSADM" >&6; } + + + ################################################################################ +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install vdoimport" >&5 +-$as_echo_n "checking whether to install vdoimport... " >&6; } ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install lvm_import_vdo" >&5 ++$as_echo_n "checking whether to install lvm_import_vdo... " >&6; } + # Check whether --enable-vdoimport was given. + if test "${enable_vdoimport+set}" = set; then : + enableval=$enable_vdoimport; VDOIMPORT=$enableval +@@ -13875,7 +13875,7 @@ cat >>confdefs.h <<_ACEOF + _ACEOF + + +-VDOIMPORT_PATH="$SBINDIR/vdoimport" ++VDOIMPORT_PATH="$SBINDIR/lvm_import_vdo" + + cat >>confdefs.h <<_ACEOF + #define VDOIMPORT_PATH "$VDOIMPORT_PATH" +diff --git a/configure.ac b/configure.ac +index 5a8b486..f769a63 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1295,8 +1295,8 @@ AC_MSG_RESULT($FSADM) + + + ################################################################################ +-dnl -- Enable vdoimport +-AC_MSG_CHECKING(whether to install vdoimport) ++dnl -- Enable lvm_import_vdo ++AC_MSG_CHECKING(whether to install lvm_import_vdo) + AC_ARG_ENABLE(vdoimport, AC_HELP_STRING([--disable-vdoimport], [disable vdoimport]), + VDOIMPORT=$enableval) + AC_MSG_RESULT($VDOIMPORT) +@@ -1656,8 +1656,8 @@ USRSBINDIR="$(eval echo $(eval echo $usrsbindir))" + FSADM_PATH="$SBINDIR/fsadm" + AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.]) + +-VDOIMPORT_PATH="$SBINDIR/vdoimport" +-AC_DEFINE_UNQUOTED(VDOIMPORT_PATH, ["$VDOIMPORT_PATH"], [Path to vdoimport binary.]) ++VDOIMPORT_PATH="$SBINDIR/lvm_import_vdo" ++AC_DEFINE_UNQUOTED(VDOIMPORT_PATH, ["$VDOIMPORT_PATH"], [Path to lvm_import_vdo binary.]) + + ################################################################################ + dnl -- dmeventd pidfile and executable path +diff --git a/include/configure.h.in b/include/configure.h.in +index 6df8d89..028ae48 100644 +--- a/include/configure.h.in ++++ b/include/configure.h.in +@@ -684,7 +684,7 @@ + /* Enable a valgrind aware build of pool */ + #undef VALGRIND_POOL + +-/* Path to vdoimport binary. */ ++/* Path to lvm_import_vdo binary. */ + #undef VDOIMPORT_PATH + + /* The path to 'vdoformat', if available. */ +diff --git a/man/Makefile.in b/man/Makefile.in +index d60a92c..45ebf54 100644 +--- a/man/Makefile.in ++++ b/man/Makefile.in +@@ -23,7 +23,7 @@ else + endif + + FSADMMAN = fsadm.8 +-VDOIMPORTMAN = vdoimport.8 ++VDOIMPORTMAN = lvm_import_vdo.8 + BLKDEACTIVATEMAN = blkdeactivate.8 + DMEVENTDMAN = dmeventd.8 + DMFILEMAPDMAN = dmfilemapd.8 +diff --git a/man/lvm_import_vdo.8_main b/man/lvm_import_vdo.8_main +new file mode 100644 +index 0000000..ee817a0 +--- /dev/null ++++ b/man/lvm_import_vdo.8_main +@@ -0,0 +1,92 @@ ++.TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\"" ++. ++.SH "NAME" ++. ++lvm_import_vdo \(em utility to import VDO volumes into a new volume group. ++. ++.SH SYNOPSIS ++. ++.PD 0 ++.ad l ++.TP 10 ++.B lvm_import_vdo ++.RI [ options ] ++.IR device ++. ++.PD ++. ++.SH DESCRIPTION ++. ++lvm_import_vdo utility imports VDO volumes created and managed by ++.BR vdo (8) ++manager into ++.BR lvm2 (8) ++managed VDO LV. This is realized by moving VDO superblock by 2MiB ++and creating lvm2 metadata at the front of this device. The operation is not reversible, ++thus after conversion to lvm2 the access to VDO data is only possible with ++.BR lvm2 (8) ++commands, ++.BR vdo (8) ++manager no longer control such volume. ++. ++.SH OPTIONS ++. ++.TP ++.BR -f | --force ++Bypass some sanity checks. ++. ++.TP ++.BR -h | --help ++Display the help text. ++. ++.TP ++.BR -n | --name ++Specifies the name of converted VDO LV. When the name is not specified, ++some automatic name is selected. In case the converted VDO volume is ++already using LV a backend device, the name of this LV is used for VDO LV. ++In this case also the of volume group must stay same. ++. ++.TP ++.BR -v | --verbose ++Be more verbose. ++. ++.TP ++.BR -y | --yes ++Answer "yes" at any prompts. ++. ++.TP ++.BR --dry-run ++Print commands without running them. ++. ++. ++.SH DIAGNOSTICS ++. ++On successful completion, the status code is 0. ++A status code of 1 is used for failure. ++. ++.SH EXAMPLES ++. ++Convert VDO volume created by vdo manager into logical volume LV1 with within volume group VG1. ++.P ++# ++.B lvm_import_vdo --name VG1/LV1 /dev/mapper/vdo-volume ++. ++.SH ENVIRONMENT VARIABLES ++. ++.TP ++.B TMPDIR ++The temporary directory name for mount points. Defaults to "\fI/tmp\fP". ++.TP ++.B DM_DEV_DIR ++The device directory name. ++Defaults to "\fI/dev\fP" and must be an absolute path. ++. ++.SH SEE ALSO ++. ++.nh ++.ad l ++.BR lvm (8), ++.BR lvm.conf (5), ++.P ++.BR vdo (8), ++.BR vdo2lvm (8), +diff --git a/man/vdoimport.8_main b/man/vdoimport.8_main +deleted file mode 100644 +index 1f32909..0000000 +--- a/man/vdoimport.8_main ++++ /dev/null +@@ -1,92 +0,0 @@ +-.TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\"" +-. +-.SH "NAME" +-. +-vdoimport \(em utility to import VDO volumes into a new volume group. +-. +-.SH SYNOPSIS +-. +-.PD 0 +-.ad l +-.TP 10 +-.B vdoimport +-.RI [ options ] +-.IR device +-. +-.PD +-. +-.SH DESCRIPTION +-. +-vdoimport utility imports VDO volumes created and managed by +-.BR vdo (8) +-manager into +-.BR lvm2 (8) +-managed VDO LV. This is realized by moving VDO superblock by 2MiB +-and creating lvm2 metadata at the front of this device. The operation is not reversible, +-thus after conversion to lvm2 the access to VDO data is only possible with +-.BR lvm2 (8) +-commands, +-.BR vdo (8) +-manager no longer control such volume. +-. +-.SH OPTIONS +-. +-.TP +-.BR -f | --force +-Bypass some sanity checks. +-. +-.TP +-.BR -h | --help +-Display the help text. +-. +-.TP +-.BR -n | --name +-Specifies the name of converted VDO LV. When the name is not specified, +-some automatic name is selected. In case the converted VDO volume is +-already using LV a backend device, the name of this LV is used for VDO LV. +-In this case also the of volume group must stay same. +-. +-.TP +-.BR -v | --verbose +-Be more verbose. +-. +-.TP +-.BR -y | --yes +-Answer "yes" at any prompts. +-. +-.TP +-.BR --dry-run +-Print commands without running them. +-. +-. +-.SH DIAGNOSTICS +-. +-On successful completion, the status code is 0. +-A status code of 1 is used for failure. +-. +-.SH EXAMPLES +-. +-Convert VDO volume created by vdo manager into logical volume LV1 with within volume group VG1. +-.P +-# +-.B vdoimport --name VG1/LV1 /dev/mapper/vdo-volume +-. +-.SH ENVIRONMENT VARIABLES +-. +-.TP +-.B TMPDIR +-The temporary directory name for mount points. Defaults to "\fI/tmp\fP". +-.TP +-.B DM_DEV_DIR +-The device directory name. +-Defaults to "\fI/dev\fP" and must be an absolute path. +-. +-.SH SEE ALSO +-. +-.nh +-.ad l +-.BR lvm (8), +-.BR lvm.conf (5), +-.P +-.BR vdo (8), +-.BR vdo2lvm (8), +diff --git a/scripts/Makefile.in b/scripts/Makefile.in +index 1fe88ca..f16c37d 100644 +--- a/scripts/Makefile.in ++++ b/scripts/Makefile.in +@@ -32,7 +32,7 @@ ifeq ("@FSADM@", "yes") + endif + + ifeq ("@VDOIMPORT@", "yes") +- LVM_SCRIPTS += vdoimport.sh ++ LVM_SCRIPTS += lvm_import_vdo.sh + endif + + ifeq ("@BLKDEACTIVATE@", "yes") +diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh +new file mode 100755 +index 0000000..35140a0 +--- /dev/null ++++ b/scripts/lvm_import_vdo.sh +@@ -0,0 +1,376 @@ ++#!/bin/bash ++# ++# Copyright (C) 2021 Red Hat, Inc. All rights reserved. ++# ++# This file is part of LVM2. ++# ++# 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 ++# ++# Author: Zdenek Kabelac ++# ++# Script for converting VDO volumes to lvm2 VDO LVs ++# ++# Needed utilities: ++# lvm, dmsetup, ++# vdo, vdo2lvm, ++# grep, awk, sed, blockdev, readlink, mkdir ++# ++# Conversion is using 'vdo convert' support from VDO manager to move ++# existing VDO header by 2M which makes space to place in PV header ++# and VG metadata area, and then create VDOPOOL LV and VDO LV in such VG. ++# ++ ++set -euE -o pipefail ++ ++TOOL=lvm_import_vdo ++ ++_SAVEPATH=$PATH ++PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH" ++ ++# user may override lvm location by setting LVM_BINARY ++LVM=${LVM_BINARY:-lvm} ++VDO=${VDO_BINARY:-vdo} ++VDOCONF=${VDOCONF:-} ++BLOCKDEV="blockdev" ++READLINK="readlink" ++READLINK_E="-e" ++MKDIR="mkdir" ++ ++TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$" ++DM_DEV_DIR="${DM_DEV_DIR:-/dev}" ++ ++DRY=0 ++VERB="" ++FORCE="" ++YES="" ++ ++# default name for converted VG and its VDO LV ++NAME="vdovg/vdolvol" ++ ++# help message ++tool_usage() { ++ echo "${TOOL}: Utility to convert VDO volume to VDO LV." ++ echo ++ echo " ${TOOL} [options] " ++ echo ++ echo " Options:" ++ echo " -f | --force Bypass sanity checks" ++ echo " -h | --help Show this help message" ++ echo " -n | --name Specifies VG/LV name for converted VDO volume" ++ echo " -v | --verbose Be verbose" ++ echo " -y | --yes Answer \"yes\" at any prompts" ++ echo " --dry-run Print commands without running them" ++ ++ exit ++} ++ ++verbose() { ++ test -z "$VERB" || echo "$TOOL:" "$@" ++} ++ ++# Support multi-line error messages ++error() { ++ for i in "$@" ; do ++ echo "$TOOL: $i" >&2 ++ done ++ cleanup 1 ++} ++ ++dry() { ++ if [ "$DRY" -ne 0 ]; then ++ verbose "Dry execution" "$@" ++ return 0 ++ fi ++ verbose "Executing" "$@" ++ "$@" ++} ++ ++cleanup() { ++ trap '' 2 ++ ++ rm -rf "$TEMPDIR" ++ # error exit status for break ++ exit "${1:-1}" ++} ++ ++get_enabled_value_() { ++ case "$1" in ++ enabled) echo "1" ;; ++ *) echo "0" ;; ++ esac ++} ++ ++get_kb_size_with_unit_() { ++ case "$1" in ++ *[kK]) echo $(( ${1%[kK]} )) ;; ++ *[mM]) echo $(( ${1%[mM]} * 1024 )) ;; ++ *[gG]) echo $(( ${1%[gG]} * 1024 * 1024 )) ;; ++ *[tT]) echo $(( ${1%[tT]} * 1024 * 1024 * 1024 )) ;; ++ *[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 * 1024 )) ;; ++ esac ++} ++ ++get_mb_size_with_unit_() { ++ case "$1" in ++ *[mM]) echo $(( ${1%[mM]} )) ;; ++ *[gG]) echo $(( ${1%[gG]} * 1024 )) ;; ++ *[tT]) echo $(( ${1%[tT]} * 1024 * 1024 )) ;; ++ *[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 )) ;; ++ esac ++} ++ ++# Figure out largest possible extent size usable for VG ++# $1 physical size ++# $2 logical size ++get_largest_extent_size_() { ++ local max=4 ++ local i ++ local d ++ ++ for i in 8 16 32 64 128 256 512 1024 2048 4096 ; do ++ d=$(( $1 / i )) ++ test $(( d * i )) -eq "$1" || break ++ d=$(( $2 / i )) ++ test $(( d * i )) -eq "$2" || break ++ max=$i ++ done ++ echo "$max" ++} ++ ++# detect LV on the given device ++# dereference device name if it is symbolic link ++detect_lv_() { ++ local DEVICE=$1 ++ local MAJOR ++ local MINOR ++ local SYSVOLUME ++ local MAJORMINOR ++ ++ DEVICE=${1/#"${DM_DEV_DIR}/"/} ++ DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE") ++ test -n "$DEVICE" || error "Cannot get readlink \"$1\"." ++ RDEVICE=$DEVICE ++ case "$RDEVICE" in ++ # hardcoded /dev since udev does not create these entries elsewhere ++ /dev/dm-[0-9]*) ++ read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME" ++ read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"." ++ MAJOR=${MAJORMINOR%%:*} ++ MINOR=${MAJORMINOR##*:} ++ ;; ++ *) ++ STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE") ++ test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"." ++ eval "$STAT" ++ ;; ++ esac ++ ++ eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')" ++} ++ ++# parse yaml config files into 'prefix_yaml_part_names=("value")' strings ++parse_yaml_() { ++ local yaml_file=$1 ++ local prefix=$2 ++ local s ++ local w ++ local fs ++ ++ s='[[:space:]]*' ++ w='[a-zA-Z0-9_.-]*' ++ fs="$(echo @|tr @ '\034')" ++ ++ ( ++ sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/[[:space:]]*$//g;' \ ++ -e 's/\$/\\\$/g' \ ++ -e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \ ++ -e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ ++ -e "s|^\($s\)\($w\)${s}[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" | ++ ++ awk -F"$fs" '{ ++ indent = length($1)/2; ++ if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";} ++ vname[indent] = $2; ++ for (i in vname) {if (i > indent) {delete vname[i]}} ++ if (length($3) > 0) { ++ vn=""; for (i=0; i"$TEMPDIR/vdoconf.yml" ++ ++ VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml") ++ TRVDONAME=$(echo "$VDONAME" | tr '-' '_') ++ ++ # When VDO volume is 'active', check it's not mounted/being used ++ eval "$(dmsetup info -c -o open "$VDONAME" --noheadings --nameprefixes || true)" ++ test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!" ++ ++ #parse_yaml_ "$TEMPDIR/vdoconf.yml" _ ++ eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")" ++ ++ vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize") ++ vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize") ++ ++ verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB." ++ verbose "With logical volume of size $vdo_logicalSize KiB." ++ ++ PARAMS=$(cat < +-# +-# Script for converting VDO volumes to lvm2 VDO LVs +-# +-# Needed utilities: +-# lvm, dmsetup, +-# vdo, vdo2lvm, +-# grep, awk, sed, blockdev, readlink, mkdir +-# +-# Conversion is using 'vdo convert' support from VDO manager to move +-# existing VDO header by 2M which makes space to place in PV header +-# and VG metadata area, and then create VDOPOOL LV and VDO LV in such VG. +-# +- +-set -euE -o pipefail +- +-TOOL=vdoimport +- +-_SAVEPATH=$PATH +-PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH" +- +-# user may override lvm location by setting LVM_BINARY +-LVM=${LVM_BINARY:-lvm} +-VDO=${VDO_BINARY:-vdo} +-VDOCONF=${VDOCONF:-} +-BLOCKDEV="blockdev" +-READLINK="readlink" +-READLINK_E="-e" +-MKDIR="mkdir" +- +-TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$" +-DM_DEV_DIR="${DM_DEV_DIR:-/dev}" +- +-DRY=0 +-VERB="" +-FORCE="" +-YES="" +- +-# default name for converted VG and its VDO LV +-NAME="vdovg/vdolvol" +- +-# help message +-tool_usage() { +- echo "${TOOL}: Utility to convert VDO volume to VDO LV." +- echo +- echo " ${TOOL} [options] " +- echo +- echo " Options:" +- echo " -f | --force Bypass sanity checks" +- echo " -h | --help Show this help message" +- echo " -n | --name Specifies VG/LV name for converted VDO volume" +- echo " -v | --verbose Be verbose" +- echo " -y | --yes Answer \"yes\" at any prompts" +- echo " --dry-run Print commands without running them" +- +- exit +-} +- +-verbose() { +- test -z "$VERB" || echo "$TOOL:" "$@" +-} +- +-# Support multi-line error messages +-error() { +- for i in "$@" ; do +- echo "$TOOL: $i" >&2 +- done +- cleanup 1 +-} +- +-dry() { +- if [ "$DRY" -ne 0 ]; then +- verbose "Dry execution" "$@" +- return 0 +- fi +- verbose "Executing" "$@" +- "$@" +-} +- +-cleanup() { +- trap '' 2 +- +- rm -rf "$TEMPDIR" +- # error exit status for break +- exit "${1:-1}" +-} +- +-get_enabled_value_() { +- case "$1" in +- enabled) echo "1" ;; +- *) echo "0" ;; +- esac +-} +- +-get_kb_size_with_unit_() { +- case "$1" in +- *[kK]) echo $(( ${1%[kK]} )) ;; +- *[mM]) echo $(( ${1%[mM]} * 1024 )) ;; +- *[gG]) echo $(( ${1%[gG]} * 1024 * 1024 )) ;; +- *[tT]) echo $(( ${1%[tT]} * 1024 * 1024 * 1024 )) ;; +- *[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 * 1024 )) ;; +- esac +-} +- +-get_mb_size_with_unit_() { +- case "$1" in +- *[mM]) echo $(( ${1%[mM]} )) ;; +- *[gG]) echo $(( ${1%[gG]} * 1024 )) ;; +- *[tT]) echo $(( ${1%[tT]} * 1024 * 1024 )) ;; +- *[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 )) ;; +- esac +-} +- +-# Figure out largest possible extent size usable for VG +-# $1 physical size +-# $2 logical size +-get_largest_extent_size_() { +- local max=4 +- local i +- local d +- +- for i in 8 16 32 64 128 256 512 1024 2048 4096 ; do +- d=$(( $1 / i )) +- test $(( d * i )) -eq "$1" || break +- d=$(( $2 / i )) +- test $(( d * i )) -eq "$2" || break +- max=$i +- done +- echo "$max" +-} +- +-# detect LV on the given device +-# dereference device name if it is symbolic link +-detect_lv_() { +- local DEVICE=$1 +- local MAJOR +- local MINOR +- local SYSVOLUME +- local MAJORMINOR +- +- DEVICE=${1/#"${DM_DEV_DIR}/"/} +- DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE") +- test -n "$DEVICE" || error "Cannot get readlink \"$1\"." +- RDEVICE=$DEVICE +- case "$RDEVICE" in +- # hardcoded /dev since udev does not create these entries elsewhere +- /dev/dm-[0-9]*) +- read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME" +- read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"." +- MAJOR=${MAJORMINOR%%:*} +- MINOR=${MAJORMINOR##*:} +- ;; +- *) +- STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE") +- test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"." +- eval "$STAT" +- ;; +- esac +- +- eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')" +-} +- +-# parse yaml config files into 'prefix_yaml_part_names=("value")' strings +-parse_yaml_() { +- local yaml_file=$1 +- local prefix=$2 +- local s +- local w +- local fs +- +- s='[[:space:]]*' +- w='[a-zA-Z0-9_.-]*' +- fs="$(echo @|tr @ '\034')" +- +- ( +- sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/[[:space:]]*$//g;' \ +- -e 's/\$/\\\$/g' \ +- -e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \ +- -e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ +- -e "s|^\($s\)\($w\)${s}[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" | +- +- awk -F"$fs" '{ +- indent = length($1)/2; +- if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";} +- vname[indent] = $2; +- for (i in vname) {if (i > indent) {delete vname[i]}} +- if (length($3) > 0) { +- vn=""; for (i=0; i"$TEMPDIR/vdoconf.yml" +- +- VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml") +- TRVDONAME=$(echo "$VDONAME" | tr '-' '_') +- +- # When VDO volume is 'active', check it's not mounted/being used +- eval "$(dmsetup info -c -o open "$VDONAME" --noheadings --nameprefixes || true)" +- test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!" +- +- #parse_yaml_ "$TEMPDIR/vdoconf.yml" _ +- eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")" +- +- vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize") +- vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize") +- +- verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB." +- verbose "With logical volume of size $vdo_logicalSize KiB." +- +- PARAMS=$(cat < +Date: Wed, 1 Sep 2021 15:46:04 +0200 +Subject: [PATCH 3/5] vdo: better message for missing device + +Show readable message when passed device cannot be accessed. +And use STAT shell var wrapper to call 'stat' command. + +(cherry picked from commit 3287d37f440ca272b52f900fc60ee5effcf73697) + +Conflicts: + scripts/lvm_import_vdo.sh +--- + scripts/lvm_import_vdo.sh | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh +index f8dd71f..dec32bc 100755 +--- a/scripts/lvm_import_vdo.sh ++++ b/scripts/lvm_import_vdo.sh +@@ -18,8 +18,8 @@ + # + # Needed utilities: + # lvm, dmsetup, +-# vdo, vdo2lvm, +-# grep, awk, sed, blockdev, readlink, mkdir ++# vdo, ++# grep, awk, sed, blockdev, readlink, stat, mkdir + # + # Conversion is using 'vdo convert' support from VDO manager to move + # existing VDO header by 2M which makes space to place in PV header +@@ -40,6 +40,7 @@ VDOCONF=${VDOCONF:-} + BLOCKDEV="blockdev" + READLINK="readlink" + READLINK_E="-e" ++STAT="stat" + MKDIR="mkdir" + DMSETUP="dmsetup" + +@@ -156,8 +157,8 @@ detect_lv_() { + local MAJORMINOR + + DEVICE=${1/#"${DM_DEV_DIR}/"/} +- DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE") +- test -n "$DEVICE" || error "Cannot get readlink \"$1\"." ++ DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE" || true) ++ test -n "$DEVICE" || error "Readlink cannot access device \"$1\"." + RDEVICE=$DEVICE + case "$RDEVICE" in + # hardcoded /dev since udev does not create these entries elsewhere +@@ -168,9 +169,9 @@ detect_lv_() { + DEVMINOR=${MAJORMINOR##*:} + ;; + *) +- STAT=$(stat --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE") +- test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"." +- eval "$STAT" ++ RSTAT=$("$STAT" --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE" || true) ++ test -n "$RSTAT" || error "Cannot get major:minor for \"$DEVICE\"." ++ eval "$RSTAT" + ;; + esac + +@@ -269,8 +270,8 @@ convert2lvm_() { + for i in $(awk '/.*device:/ {print $2}' "$TEMPDIR/vdoconf.yml") ; do + local DEV + DEV=$("$READLINK" $READLINK_E "$i") || continue +- STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue +- eval "$STAT" ++ RSTAT=$("$STAT" --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue ++ eval "$RSTAT" + test "$MAJOR" = "$DEVMAJOR" && test "$MINOR" = "$DEVMINOR" && { + test -z "$FOUND" || error "VDO configuration contains duplicate entries $FOUND and $i" + FOUND=$i +@@ -287,7 +288,7 @@ convert2lvm_() { + DM_OPEN="$("$DMSETUP" info -c -o open "$VDONAME" --noheadings --nameprefixes 2>/dev/null || true)" + case "$DM_OPEN" in + Device*) ;; # no devices +- *) eval "$DM_OPEN" ++ *) eval "$DM_OPEN" + test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!" + ;; + esac +-- +1.8.3.1 + diff --git a/SOURCES/lvm2-2_03_14-vdo-fix-conversion-of-large-virtual-sizes.patch b/SOURCES/lvm2-2_03_14-vdo-fix-conversion-of-large-virtual-sizes.patch new file mode 100644 index 0000000..9899966 --- /dev/null +++ b/SOURCES/lvm2-2_03_14-vdo-fix-conversion-of-large-virtual-sizes.patch @@ -0,0 +1,28 @@ +From 70467e905cea0811c269faf7e84f24d4e1c758cc Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Mon, 30 Aug 2021 18:12:59 +0200 +Subject: [PATCH 5/5] vdo: fix conversion of large virtual sizes + +Properly accept virtual sizes above 2TiB. + +(cherry picked from commit 4afe872fd6c43fcfcd519c862574d010cdbda653) +--- + tools/lvconvert.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lvconvert.c b/tools/lvconvert.c +index f87ee78..518b48f 100644 +--- a/tools/lvconvert.c ++++ b/tools/lvconvert.c +@@ -5462,7 +5462,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd, + return_0; + + lvc.virtual_extents = extents_from_size(cmd, +- arg_uint_value(cmd, virtualsize_ARG, 0), ++ arg_uint64_value(cmd, virtualsize_ARG, UINT64_C(0)), + vg->extent_size); + + if (!(lvc.segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_VDO))) +-- +1.8.3.1 + diff --git a/SOURCES/lvm2-2_03_14-vdo-fixes.patch b/SOURCES/lvm2-2_03_14-vdo-fixes.patch new file mode 100644 index 0000000..ac6acb5 --- /dev/null +++ b/SOURCES/lvm2-2_03_14-vdo-fixes.patch @@ -0,0 +1,256 @@ +From 5d0756fc33bced8453fb5cf5807c5a3fa2b59dbb Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Tue, 31 Aug 2021 20:52:26 +0200 +Subject: [PATCH 1/5] vdo: fixes + +Better identify VDO device with major:minor. +Handle different LV name from originally converted origin LV. +Improve --dry-run handling. + +(cherry picked from commit 1ae157a0f67e984ef3037d19d62b84a3b0201c84) +--- + WHATS_NEW | 4 +++ + scripts/lvm_import_vdo.sh | 70 +++++++++++++++++++++++++++++++++++------------ + test/shell/vdo-convert.sh | 28 ++++++++++++++----- + 3 files changed, 78 insertions(+), 24 deletions(-) + +diff --git a/WHATS_NEW b/WHATS_NEW +index 3637e31..b751009 100644 +--- a/WHATS_NEW ++++ b/WHATS_NEW +@@ -1,5 +1,9 @@ + Version 2.03.14 - + ================================== ++ Improve lvm_import_vdo script. ++ Support VDO LV with lvcreate -ky. ++ Fix lvconvert for VDO LV bigger then 2T. ++ Create VDO LVs automatically without zeroing. + Rename vdoimport to lvm_import_vdo. + + Version 2.03.13 - +diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh +index 35140a0..bc73306 100755 +--- a/scripts/lvm_import_vdo.sh ++++ b/scripts/lvm_import_vdo.sh +@@ -41,10 +41,15 @@ BLOCKDEV="blockdev" + READLINK="readlink" + READLINK_E="-e" + MKDIR="mkdir" ++DMSETUP="dmsetup" + + TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$" + DM_DEV_DIR="${DM_DEV_DIR:-/dev}" + ++DEVICENAME="" ++DEVMAJOR=0 ++DEVMINOR=0 ++ + DRY=0 + VERB="" + FORCE="" +@@ -147,8 +152,6 @@ get_largest_extent_size_() { + # dereference device name if it is symbolic link + detect_lv_() { + local DEVICE=$1 +- local MAJOR +- local MINOR + local SYSVOLUME + local MAJORMINOR + +@@ -161,17 +164,21 @@ detect_lv_() { + /dev/dm-[0-9]*) + read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME" + read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"." +- MAJOR=${MAJORMINOR%%:*} +- MINOR=${MAJORMINOR##*:} ++ DEVMAJOR=${MAJORMINOR%%:*} ++ DEVMINOR=${MAJORMINOR##*:} + ;; + *) +- STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE") ++ STAT=$(stat --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE") + test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"." + eval "$STAT" + ;; + esac + +- eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')" ++ DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ' 2>/dev/null)" ++ case "$DEV" in ++ Device*) ;; # no devices ++ *) eval "$DEV" ;; ++ esac + } + + # parse yaml config files into 'prefix_yaml_part_names=("value")' strings +@@ -226,20 +233,26 @@ convert2lvm_() { + local TRVDONAME + local EXTENTSZ + local IS_LV=1 ++ local FOUND="" ++ local MAJOR=0 ++ local MINOR=0 ++ local DM_VG_NAME ++ local DM_LV_NAME + + DM_UUID="" + detect_lv_ "$DEVICE" + case "$DM_UUID" in +- LVM-*) eval "$(dmsetup splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")" ++ LVM-*) eval "$("$DMSETUP" splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")" + if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then + VGNAME=$DM_VG_NAME ++ LVNAME=$DM_LV_NAME + elif test "$VGNAME" != "$DM_VG_NAME" ; then + error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"." + fi + ;; + *) IS_LV=0 + # Check $VGNANE does not already exists +- "$LVM" vgs "$VGNAME" && error "Cannot use already existing volume group name \"$VGNAME\"." ++ "$LVM" vgs "$VGNAME" >/dev/null 2>&1 && error "Cannot use already existing volume group name \"$VGNAME\"." + ;; + esac + +@@ -247,15 +260,37 @@ convert2lvm_() { + + "$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR." + ++ # TODO: might use directly /etc/vdoconf.yml (avoding need of 'vdo' manager) + verbose "Getting YAML VDO configuration." + "$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml" + +- VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml") ++ # Check list of devices in VDO configure file for their major:minor ++ # and match with given $DEVICE devmajor:devminor ++ for i in $(awk '/.*device:/ {print $2}' "$TEMPDIR/vdoconf.yml") ; do ++ local DEV ++ DEV=$("$READLINK" $READLINK_E "$i") || continue ++ STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue ++ eval "$STAT" ++ test "$MAJOR" = "$DEVMAJOR" && test "$MINOR" = "$DEVMINOR" && { ++ test -z "$FOUND" || error "VDO configuration contains duplicate entries $FOUND and $i" ++ FOUND=$i ++ } ++ done ++ ++ test -n "$FOUND" || error "Can't find matching device in vdo configuration file." ++ verbose "Found matching device $FOUND $MAJOR:$MINOR" ++ ++ VDONAME=$(awk -v DNAME="$FOUND" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml") + TRVDONAME=$(echo "$VDONAME" | tr '-' '_') + + # When VDO volume is 'active', check it's not mounted/being used +- eval "$(dmsetup info -c -o open "$VDONAME" --noheadings --nameprefixes || true)" +- test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!" ++ DM_OPEN="$("$DMSETUP" info -c -o open "$VDONAME" --noheadings --nameprefixes 2>/dev/null || true)" ++ case "$DM_OPEN" in ++ Device*) ;; # no devices ++ *) eval "$DM_OPEN" ++ test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!" ++ ;; ++ esac + + #parse_yaml_ "$TEMPDIR/vdoconf.yml" _ + eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")" +@@ -263,8 +298,7 @@ convert2lvm_() { + vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize") + vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize") + +- verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB." +- verbose "With logical volume of size $vdo_logicalSize KiB." ++ verbose "Converted VDO device has logical/physical size $vdo_logicalSize/$vdo_physicalSize KiB." + + PARAMS=$(cat </dev/null || true ++ ++lvremove -f $vg ++ ++ ++# Test user can specify different VDO LV name (so the original LV is renamed) ++lvcreate -y -L5G -n $lv1 $vg ++ ++vdo create $VDOCONF --name "$VDONAME" --device="$DM_DEV_DIR/$vg/$lv1" --vdoLogicalSize=10G ++ ++lvm_import_vdo -y --name $vg/$lv2 "$DM_DEV_DIR/$vg/$lv1" ++ ++check lv_exists $vg $lv2 ++check lv_not_exists $vg $lv1 + + vgremove -f $vg + ++# ensure VDO device is not left in config file ++vdo remove $VDOCONF --force --name "$VDONAME" 2>/dev/null || true ++ + aux wipefs_a "$dev1" + + # prepare 'unused' $vg2 + vgcreate $vg2 "$dev2" + + # +-# Check conversion of VDO volume on non-LV device ++# Check conversion of VDO volume on non-LV device and with >2T size + # +-vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=31G +- +-mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME" ++vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=3T + + # Fail with an already existing volume group $vg2 + not lvm_import_vdo --dry-run -y -v --name $vg2/$lv1 "$dev1" |& tee err +@@ -87,7 +101,7 @@ vdo stop $VDOCONF --name "$VDONAME" + + lvm_import_vdo -y -v --name $vg/$lv1 "$dev1" + +-fsck -n "$DM_DEV_DIR/$vg/$lv1" ++check lv_field $vg/$lv1 size "3.00t" + + vgremove -f $vg + +-- +1.8.3.1 + diff --git a/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-fix-max_discard-size.patch b/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-fix-max_discard-size.patch new file mode 100644 index 0000000..0265448 --- /dev/null +++ b/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-fix-max_discard-size.patch @@ -0,0 +1,28 @@ +From 60eb37394b536e3b969496611ff4b59b71123476 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Mon, 6 Sep 2021 14:57:43 +0200 +Subject: [PATCH 2/5] vdo: lvm_import_vdo fix max_discard size + +Use correct 4K units in lvm2 for max_discard VDO option. + +(cherry picked from commit 8d5b7de54f21ce5e34d533599f9d5a42f2977cd5) +--- + scripts/lvm_import_vdo.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh +index bc73306..f8dd71f 100755 +--- a/scripts/lvm_import_vdo.sh ++++ b/scripts/lvm_import_vdo.sh +@@ -320,7 +320,7 @@ allocation { + vdo_logical_threads = $vdo_logicalThreads + vdo_physical_threads = $vdo_physicalThreads + vdo_write_policy = $vdo_writePolicy +- vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") * 1024 )) ++ vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") / 4 )) + vdo_pool_header_size = 0 + } + EOF +-- +1.8.3.1 + diff --git a/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-script-needs-to-continue-when-vgn.patch b/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-script-needs-to-continue-when-vgn.patch new file mode 100644 index 0000000..02bd359 --- /dev/null +++ b/SOURCES/lvm2-2_03_14-vdo-lvm_import_vdo-script-needs-to-continue-when-vgn.patch @@ -0,0 +1,29 @@ +From 4cf3e8bd846a171b4b945f289bf0c6f9c7b5864c Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Thu, 9 Sep 2021 18:10:13 +0200 +Subject: [PATCH 3/5] vdo: lvm_import_vdo script needs to continue when vgname + does not exist + +When the script cannot find vgname - it needs to continue to run. + +(cherry picked from commit 9db4ddabc1cf912dee30e0e6293767f01c976a4a) +--- + scripts/lvm_import_vdo.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh +index 70904f7..e5b30d8 100755 +--- a/scripts/lvm_import_vdo.sh ++++ b/scripts/lvm_import_vdo.sh +@@ -262,7 +262,7 @@ convert2lvm_() { + if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then + VGNAME=${DEFAULT_NAME%/*} + # Find largest matching VG name to our 'default' vgname +- LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~${VGNAME} | grep -E "$VGNAME[0-9]? ?" | head -1) ++ LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~${VGNAME} | grep -E "$VGNAME[0-9]? ?" | head -1 || true) + if test -n "$LASTVGNAME" ; then + LASTVGNAME=${LASTVGNAME#*${VGNAME}} + # If the number is becoming too high, try some random number +-- +1.8.3.1 + diff --git a/SOURCES/lvm2-2_03_14-vdo-man-page-updates.patch b/SOURCES/lvm2-2_03_14-vdo-man-page-updates.patch new file mode 100644 index 0000000..03ca40a --- /dev/null +++ b/SOURCES/lvm2-2_03_14-vdo-man-page-updates.patch @@ -0,0 +1,27 @@ +From 073cdd0ba8c39a0330e73773c92d78546d06e687 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Fri, 10 Sep 2021 01:15:01 +0200 +Subject: [PATCH 4/5] vdo: man page updates + +(cherry picked from commit 812653d59806439379d80bb8124f6962ae42d46a) +--- + man/lvm_import_vdo.8_main | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/man/lvm_import_vdo.8_main b/man/lvm_import_vdo.8_main +index ee817a0..c6cb5c3 100644 +--- a/man/lvm_import_vdo.8_main ++++ b/man/lvm_import_vdo.8_main +@@ -45,6 +45,9 @@ Specifies the name of converted VDO LV. When the name is not specified, + some automatic name is selected. In case the converted VDO volume is + already using LV a backend device, the name of this LV is used for VDO LV. + In this case also the of volume group must stay same. ++Automatic name may change between releases and currently selects ++"vdolv" as LV name and VG name is selected from sequence ++"vdovg", "vdovg1", ... + . + .TP + .BR -v | --verbose +-- +1.8.3.1 + diff --git a/SOURCES/lvm2-2_03_14-vdo-more-lvm_import_vdo-fixes.patch b/SOURCES/lvm2-2_03_14-vdo-more-lvm_import_vdo-fixes.patch new file mode 100644 index 0000000..fb70af2 --- /dev/null +++ b/SOURCES/lvm2-2_03_14-vdo-more-lvm_import_vdo-fixes.patch @@ -0,0 +1,185 @@ +From 6621116b61f4c9ee53166a994be2ef7d80a3c346 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Mon, 6 Sep 2021 15:06:32 +0200 +Subject: [PATCH 4/5] vdo: more lvm_import_vdo fixes + +Do not call 'dmsetup info' for non-dm devices. + +Better handling for VGNAME and LVNAME - so when convering LV as +backend device automatically recognize it and reuse LV name for VDOLV. + +Add prompt for final confirmation before actual conversion is started +(once confirmed, lvm2 commands no longer prompts to avoid leaving +conversion in the middle of its process.) + +(cherry picked from commit 89595a366554191c3df1a18e1f82b79c450a21ad) +--- + scripts/lvm_import_vdo.sh | 48 ++++++++++++++++++++++++++++++++++------ + test/shell/vdo-convert.sh | 56 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 97 insertions(+), 7 deletions(-) + +diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh +index dec32bc..70904f7 100755 +--- a/scripts/lvm_import_vdo.sh ++++ b/scripts/lvm_import_vdo.sh +@@ -50,6 +50,7 @@ DM_DEV_DIR="${DM_DEV_DIR:-/dev}" + DEVICENAME="" + DEVMAJOR=0 + DEVMINOR=0 ++PROMPTING="" + + DRY=0 + VERB="" +@@ -57,7 +58,8 @@ FORCE="" + YES="" + + # default name for converted VG and its VDO LV +-NAME="vdovg/vdolvol" ++DEFAULT_NAME="vdovg/vdolvol" ++NAME="" + + # help message + tool_usage() { +@@ -100,6 +102,7 @@ dry() { + cleanup() { + trap '' 2 + ++ test -z "$PROMPTING" || echo "No" + rm -rf "$TEMPDIR" + # error exit status for break + exit "${1:-1}" +@@ -175,7 +178,9 @@ detect_lv_() { + ;; + esac + +- DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ' 2>/dev/null)" ++ test "$DEVMAJOR" != "$(grep device-mapper /proc/devices | cut -f1 -d' ')" && return ++ ++ DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')" + case "$DEV" in + Device*) ;; # no devices + *) eval "$DEV" ;; +@@ -244,15 +249,31 @@ convert2lvm_() { + detect_lv_ "$DEVICE" + case "$DM_UUID" in + LVM-*) eval "$("$DMSETUP" splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")" +- if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then ++ if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then + VGNAME=$DM_VG_NAME +- LVNAME=$DM_LV_NAME ++ verbose "Using existing volume group name $VGNAME." ++ test -n "$LVNAME" || LVNAME=$DM_LV_NAME + elif test "$VGNAME" != "$DM_VG_NAME" ; then +- error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"." ++ error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for VDO device \"$DEVICE\"." + fi + ;; +- *) IS_LV=0 +- # Check $VGNANE does not already exists ++ *) IS_LV=0 ++ # Check if we need to generate unused $VGNANE ++ if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then ++ VGNAME=${DEFAULT_NAME%/*} ++ # Find largest matching VG name to our 'default' vgname ++ LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~${VGNAME} | grep -E "$VGNAME[0-9]? ?" | head -1) ++ if test -n "$LASTVGNAME" ; then ++ LASTVGNAME=${LASTVGNAME#*${VGNAME}} ++ # If the number is becoming too high, try some random number ++ test "$LASTVGNAME" -gt 99999999 2>/dev/null && LASTVGNAME=$RANDOM ++ # Generate new unused VG name ++ VGNAME="${VGNAME}$(( ${LASTVGNAME} + 1 ))" ++ verbose "Selected unused volume group name $VGNAME." ++ fi ++ fi ++ # New VG is created, LV name should be always unused. ++ test -n "$LVNAME" || LVNAME=${DEFAULT_NAME#*/} + "$LVM" vgs "$VGNAME" >/dev/null 2>&1 && error "Cannot use already existing volume group name \"$VGNAME\"." + ;; + esac +@@ -328,6 +349,19 @@ EOF + ) + verbose "VDO conversion paramaters: $PARAMS" + ++ # If user has not provided '--yes', prompt before conversion ++ if test -z "$YES" ; then ++ PROMPTING=yes ++ echo -n "Convert VDO device \"$DEVICE\" to VDO LV \"$VGNAME/$LVNAME\"? [y|N]: " ++ read -n 1 -s ANSWER ++ case "${ANSWER:0:1}" in ++ y|Y ) echo "Yes" ;; ++ * ) echo "No" ; PROMPTING=""; exit ;; ++ esac ++ PROMPTING="" ++ YES="-y" # From now, now prompting ++ fi ++ + verbose "Stopping VDO volume." + dry "$VDO" stop $VDOCONF --name "$VDONAME" + +diff --git a/test/shell/vdo-convert.sh b/test/shell/vdo-convert.sh +index 493f415..632f86a 100644 +--- a/test/shell/vdo-convert.sh ++++ b/test/shell/vdo-convert.sh +@@ -122,3 +122,59 @@ fsck -n "$DM_DEV_DIR/$vg1/$lv2" + + vgremove -f $vg1 + ++aux teardown_devs ++ ++ ++# Check with some real non-DM device from system ++# this needs to dropping DM_DEV_DIR ++ ++aux prepare_loop 60000 || skip ++ ++test -f LOOP ++LOOP=$(< LOOP) ++ ++aux extend_filter "a|$LOOP|" ++aux extend_devices "$LOOP" ++ ++# ++# Unfortunatelly generates this in syslog: ++# ++# vdo-start-by-dev@loop0.service: Main process exited, code=exited, status=1/FAILURE ++# vdo-start-by-dev@loop0.service: Failed with result 'exit-code'. ++# Failed to start Start VDO volume backed by loop0. ++# ++# TODO: Could be handled by: ++# ++# systemctl mask vdo-start-by-dev@ ++# systemctl unmask vdo-start-by-dev@ ++# ++# automate... ++# ++vdo create $VDOCONF --name "$VDONAME" --device="$LOOP" --vdoLogicalSize=23G \ ++ --blockMapCacheSize 192 \ ++ --blockMapPeriod 2048 \ ++ --emulate512 disabled \ ++ --indexMem 0.5 \ ++ --maxDiscardSize 10 \ ++ --sparseIndex disabled \ ++ --vdoAckThreads 2 \ ++ --vdoBioRotationInterval 8 \ ++ --vdoBioThreads 2 \ ++ --vdoCpuThreads 5 \ ++ --vdoHashZoneThreads 3 \ ++ --vdoLogicalThreads 3 \ ++ --writePolicy async-unsafe ++ ++# Get VDO table line ++dmsetup table "$VDONAME" | tr " " "\n" | sed -e '5,6d' -e '12d' | tee vdo-orig ++ ++DM_DEV_DIR= lvm_import_vdo -y --name $vg/$lv "$LOOP" ++lvs -a $vg ++ ++dmsetup table "$vg-${lv}_vpool-vpool" | tr " " "\n" | sed -e '5,6d' -e '12d' | tee new-vdo-lv ++ ++# Check there is a match between VDO and LV managed volume ++# (when differentiating parameters are deleted first) ++diff -u vdo-orig new-vdo-lv || die "Found mismatching VDO table lines!" ++ ++check lv_field $vg/$lv size "23.00g" +-- +1.8.3.1 + diff --git a/SOURCES/lvm2-2_03_14-vdo-prompt-with-no-return-failure.patch b/SOURCES/lvm2-2_03_14-vdo-prompt-with-no-return-failure.patch new file mode 100644 index 0000000..4642667 --- /dev/null +++ b/SOURCES/lvm2-2_03_14-vdo-prompt-with-no-return-failure.patch @@ -0,0 +1,28 @@ +From f3f99d45b89d415528e21a66f94ab4576f95ba56 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Fri, 10 Sep 2021 22:39:23 +0200 +Subject: [PATCH 5/5] vdo: prompt with no return failure + +Exit 1 (failure) when prompt for conversion is answered as 'No'. + +(cherry picked from commit 3b24c0fe4e197383101eae53b14f19586cf2eda1) +--- + scripts/lvm_import_vdo.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh +index e5b30d8..06a043c 100755 +--- a/scripts/lvm_import_vdo.sh ++++ b/scripts/lvm_import_vdo.sh +@@ -356,7 +356,7 @@ EOF + read -n 1 -s ANSWER + case "${ANSWER:0:1}" in + y|Y ) echo "Yes" ;; +- * ) echo "No" ; PROMPTING=""; exit ;; ++ * ) echo "No" ; PROMPTING=""; exit 1 ;; + esac + PROMPTING="" + YES="-y" # From now, now prompting +-- +1.8.3.1 + diff --git a/SOURCES/lvm2-2_03_14-vdo-read-new-sysfs-path.patch b/SOURCES/lvm2-2_03_14-vdo-read-new-sysfs-path.patch new file mode 100644 index 0000000..c2d5f72 --- /dev/null +++ b/SOURCES/lvm2-2_03_14-vdo-read-new-sysfs-path.patch @@ -0,0 +1,184 @@ +From 1c6992d37eff5af7134a11b662eacc1bab538ac2 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Thu, 9 Sep 2021 14:59:38 +0200 +Subject: [PATCH 1/5] vdo: read new sysfs path + +New versions of kvdo module exposes statistics at new location: +/sys/block/dm-XXX/vdo/statistics/... + +Enhance lvm2 to access this location first. +Also if the statistic info is missing - make it 'debug' level info, +so it is not failing 'lvs' command. + +(cherry picked from commit e6f735d411e5911de186a610932c9bb9638275eb) + +Conflicts: + WHATS_NEW +--- + WHATS_NEW | 1 + + lib/activate/dev_manager.c | 7 +++--- + lib/metadata/metadata-exported.h | 3 ++- + lib/metadata/vdo_manip.c | 46 ++++++++++++++++++++++------------------ + 4 files changed, 32 insertions(+), 25 deletions(-) + +diff --git a/WHATS_NEW b/WHATS_NEW +index b751009..c5a5ca5 100644 +--- a/WHATS_NEW ++++ b/WHATS_NEW +@@ -1,5 +1,6 @@ + Version 2.03.14 - + ================================== ++ Support newer location for VDO statistics. + Improve lvm_import_vdo script. + Support VDO LV with lvcreate -ky. + Fix lvconvert for VDO LV bigger then 2T. +diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c +index c4a6739..0d954d1 100644 +--- a/lib/activate/dev_manager.c ++++ b/lib/activate/dev_manager.c +@@ -157,6 +157,7 @@ out: + + static int _get_segment_status_from_target_params(const char *target_name, + const char *params, ++ const struct dm_info *dminfo, + struct lv_seg_status *seg_status) + { + const struct lv_segment *seg = seg_status->seg; +@@ -216,7 +217,7 @@ static int _get_segment_status_from_target_params(const char *target_name, + return_0; + seg_status->type = SEG_STATUS_SNAPSHOT; + } else if (segtype_is_vdo_pool(segtype)) { +- if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, &seg_status->vdo_pool)) ++ if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, dminfo, &seg_status->vdo_pool)) + return_0; + seg_status->type = SEG_STATUS_VDO_POOL; + } else if (segtype_is_writecache(segtype)) { +@@ -320,7 +321,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo, + } while (target); + + if (!target_name || +- !_get_segment_status_from_target_params(target_name, target_params, seg_status)) ++ !_get_segment_status_from_target_params(target_name, target_params, dminfo, seg_status)) + stack; + } + +@@ -1886,7 +1887,7 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm, + goto out; + } + +- if (!parse_vdo_pool_status(dm->mem, lv, params, *status)) ++ if (!parse_vdo_pool_status(dm->mem, lv, params, &info, *status)) + goto_out; + + (*status)->mem = dm->mem; +diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h +index adbbe76..7c21b4d 100644 +--- a/lib/metadata/metadata-exported.h ++++ b/lib/metadata/metadata-exported.h +@@ -1364,7 +1364,8 @@ const char *get_vdo_write_policy_name(enum dm_vdo_write_policy policy); + uint64_t get_vdo_pool_virtual_size(const struct lv_segment *vdo_pool_seg); + int update_vdo_pool_virtual_size(struct lv_segment *vdo_pool_seg); + int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_pool_lv, +- const char *params, struct lv_status_vdo *status); ++ const char *params, const struct dm_info *dminfo, ++ struct lv_status_vdo *status); + struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv, + const struct dm_vdo_target_params *vtp, + uint32_t *virtual_extents, +diff --git a/lib/metadata/vdo_manip.c b/lib/metadata/vdo_manip.c +index 3f2de1a..2917f29 100644 +--- a/lib/metadata/vdo_manip.c ++++ b/lib/metadata/vdo_manip.c +@@ -123,48 +123,56 @@ int update_vdo_pool_virtual_size(struct lv_segment *vdo_pool_seg) + return 1; + } + +-static int _sysfs_get_kvdo_value(const char *dm_name, const char *vdo_param, uint64_t *value) ++static int _sysfs_get_kvdo_value(const char *dm_name, const struct dm_info *dminfo, ++ const char *vdo_param, uint64_t *value) + { + char path[PATH_MAX]; + char temp[64]; + int fd, size, r = 0; + +- if (dm_snprintf(path, sizeof(path), "%skvdo/%s/%s", +- dm_sysfs_dir(), dm_name, vdo_param) < 0) { +- log_error("Failed to build kmod path."); ++ if (dm_snprintf(path, sizeof(path), "%s/block/dm-%d/vdo/%s", ++ dm_sysfs_dir(), dminfo->minor, vdo_param) < 0) { ++ log_debug("Failed to build kvdo path."); + return 0; + } + + if ((fd = open(path, O_RDONLY)) < 0) { +- if (errno != ENOENT) +- log_sys_error("open", path); +- else ++ /* try with older location */ ++ if (dm_snprintf(path, sizeof(path), "%skvdo/%s/%s", ++ dm_sysfs_dir(), dm_name, vdo_param) < 0) { ++ log_debug("Failed to build kvdo path."); ++ return 0; ++ } ++ ++ if ((fd = open(path, O_RDONLY)) < 0) { + log_sys_debug("open", path); +- goto bad; ++ goto bad; ++ } + } + + if ((size = read(fd, temp, sizeof(temp) - 1)) < 0) { +- log_sys_error("read", path); ++ log_sys_debug("read", path); + goto bad; + } + temp[size] = 0; + errno = 0; + *value = strtoll(temp, NULL, 0); + if (errno) { +- log_sys_error("strtool", path); ++ log_sys_debug("strtool", path); + goto bad; + } + + r = 1; + bad: + if (fd >= 0 && close(fd)) +- log_sys_error("close", path); ++ log_sys_debug("close", path); + + return r; + } + + int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_pool_lv, +- const char *params, struct lv_status_vdo *status) ++ const char *params, const struct dm_info *dminfo, ++ struct lv_status_vdo *status) + { + struct dm_vdo_status_parse_result result; + char *dm_name; +@@ -188,15 +196,11 @@ int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_ + + status->vdo = result.status; + +- if (result.status->operating_mode == DM_VDO_MODE_NORMAL) { +- if (!_sysfs_get_kvdo_value(dm_name, "statistics/data_blocks_used", +- &status->data_blocks_used)) +- return_0; +- +- if (!_sysfs_get_kvdo_value(dm_name, "statistics/logical_blocks_used", +- &status->logical_blocks_used)) +- return_0; +- ++ if ((result.status->operating_mode == DM_VDO_MODE_NORMAL) && ++ _sysfs_get_kvdo_value(dm_name, dminfo, "statistics/data_blocks_used", ++ &status->data_blocks_used) && ++ _sysfs_get_kvdo_value(dm_name, dminfo, "statistics/logical_blocks_used", ++ &status->logical_blocks_used)) { + status->usage = dm_make_percent(result.status->used_blocks, + result.status->total_blocks); + status->saving = dm_make_percent(status->logical_blocks_used - status->data_blocks_used, +-- +1.8.3.1 + diff --git a/SOURCES/lvm2-make-generate.patch b/SOURCES/lvm2-make-generate.patch new file mode 100644 index 0000000..0b37216 --- /dev/null +++ b/SOURCES/lvm2-make-generate.patch @@ -0,0 +1,146 @@ + man/lvconvert.8_pregen | 2 +- + man/lvmdevices.8_pregen | 79 ++++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 66 insertions(+), 15 deletions(-) + +diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen +index d733ab6..4fafe5d 100644 +--- a/man/lvconvert.8_pregen ++++ b/man/lvconvert.8_pregen +@@ -670,7 +670,7 @@ Convert LV to type thin-pool. + .RE + .P + .RS 4 +-LV1 types: linear striped cache raid error zero ++LV1 types: linear striped cache raid error zero writecache + .RE + .P + \(em +diff --git a/man/lvmdevices.8_pregen b/man/lvmdevices.8_pregen +index 267ce96..fa85362 100644 +--- a/man/lvmdevices.8_pregen ++++ b/man/lvmdevices.8_pregen +@@ -28,6 +28,8 @@ lvmdevices \(em Manage the devices file + .br + \fB--delpvid\fP \fIString\fP + .br ++ \fB--deviceidtype\fP \fIString\fP ++.br + \fB--devices\fP \fIPV\fP + .br + \fB--devicesfile\fP \fIString\fP +@@ -70,18 +72,18 @@ remove it from the devices file with lvmdevices --deldev. The + vgimportdevices(8) command adds all PVs from a VG to the devices file, + and updates the VG metadata to include device IDs of the PVs. + .P +-Commands adding new devices to the devices file necessarily look outside +-the existing devices file to find the devices to add. pvcreate, vgcreate, +-and vgextend also look outside the devices file to create new PVs and add +-them to the devices file. ++Commands that add new devices to the devices file necessarily look outside ++the existing devices file to find the devices being added. pvcreate, ++vgcreate, and vgextend also look outside the devices file to create new ++PVs and add those PVs to the devices file. + .P + LVM records devices in the devices file using hardware-specific IDs, such + as the WWID, and attempts to use subsystem-specific IDs for virtual device +-types (which also aim to be as unique and stable as possible.) +-These device IDs are also written in the VG metadata. When no hardware or ++types (which also aim to be as unique and stable as possible.) These ++device IDs are also written in the VG metadata. When no hardware or + virtual ID is available, lvm falls back using the unstable device name as +-the device ID. When devnames are used, lvm performs extra scanning to +-find devices if their devname changes, e.g. after reboot. ++the device ID. When devnames are used as IDs, lvm performs extra scanning ++to find devices if their devname changes, e.g. after reboot. + .P + When proper device IDs are used, an lvm command will not look at devices + outside the devices file, but when devnames are used as a fallback, lvm +@@ -95,12 +97,13 @@ overriding the devices file. The listed devices act as a sort of devices + file in terms of limiting which devices lvm will see and use. Devices + that are not listed will appear to be missing to the lvm command. + .P +-Multiple devices files can be kept in \fI#DEFAULT_SYS_DIR#/devices\fP, which allows lvm +-to be used with different sets of devices, e.g. system devices do not need +-to be exposed to a specific application, and the application can use lvm on +-its own devices that are not exposed to the system. The option +---devicesfile is used to select the devices file to use with the +-command. Without the option set, the default system devices file is used. ++Multiple devices files can be kept \fI#DEFAULT_SYS_DIR#/devices\fP, which ++allows lvm to be used with different sets of devices. For example, system ++devices do not need to be exposed to a specific application, and the ++application can use lvm on its own devices that are not exposed to the ++system. The option --devicesfile is used to select the devices ++file to use with the command. Without the option set, the default system ++devices file is used. + .P + Setting --devicesfile "" causes lvm to not use a devices file. + .P +@@ -120,6 +123,45 @@ if it does not yet exist. + .P + It is recommended to use lvm commands to make changes to the devices file to + ensure proper updates. ++.P ++The device ID and device ID type are included in the VG metadata and can ++be reported with pvs -o deviceid,deviceidtype. (Note that the lvmdevices ++command does not update VG metadata, but subsequent lvm commands modifying ++the metadata will include the device ID.) ++.P ++Possible device ID types are: ++.br ++.IP \[bu] 2 ++.B sys_wwid ++uses the wwid reported by sysfs. This is the first choice for non-virtual ++devices. ++.IP \[bu] 2 ++.B sys_serial ++uses the serial number reported by sysfs. This is the second choice for ++non-virtual devices. ++.IP \[bu] 2 ++.B mpath_uuid ++is used for dm multipath devices, reported by sysfs. ++.IP \[bu] 2 ++.B crypt_uuid ++is used for dm crypt devices, reported by sysfs. ++.IP \[bu] 2 ++.B md_uuid ++is used for md devices, reported by sysfs. ++.B lvmlv_uuid ++is used if a PV is placed on top of an lvm LV, reported by sysfs. ++.IP \[bu] 2 ++.B loop_file ++is used for loop devices, the backing file name repored by sysfs. ++.IP \[bu] 2 ++.B devname ++the device name is used if no other type applies. ++.P ++ ++The default choice for device ID type can be overriden using lvmdevices ++--addev --deviceidtype . If the specified type is available for the ++device it will be used, otherwise the device will be added using the type ++that would otherwise be chosen. + . + .SH USAGE + . +@@ -169,6 +211,8 @@ Add a device to the devices file. + .br + .RS 4 + .ad l ++[ \fB--deviceidtype\fP \fIString\fP ] ++.br + [ COMMON_OPTIONS ] + .ad b + .RE +@@ -308,6 +352,13 @@ Remove a device from the devices file. + Remove a device with the PVID from the devices file. + . + .HP ++\fB--deviceidtype\fP \fIString\fP ++.br ++The type of device ID to use for the device. ++If the specified type is available for the device, ++then it will override the default type that lvm would use. ++. ++.HP + \fB--devices\fP \fIPV\fP + .br + Devices that the command can use. This option can be repeated diff --git a/SOURCES/lvm2-rhel8.patch b/SOURCES/lvm2-rhel8.patch index 874c350..8af2792 100644 --- a/SOURCES/lvm2-rhel8.patch +++ b/SOURCES/lvm2-rhel8.patch @@ -3,16 +3,16 @@ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION -index a6ba8f6..2a15962 100644 +index d9c3e23..2610861 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ --2.03.11(2) (2021-01-08) -+2.03.11(2)-RHEL8 (2021-01-28) +-2.03.12(2) (2021-05-07) ++2.03.12(2)-RHEL8 (2021-05-19) diff --git a/VERSION_DM b/VERSION_DM -index f44bc5f..2475a11 100644 +index 6105a0f..0991c69 100644 --- a/VERSION_DM +++ b/VERSION_DM @@ -1 +1 @@ --1.02.175 (2021-01-08) -+1.02.175-RHEL8 (2021-01-28) +-1.02.177 (2021-05-07) ++1.02.177-RHEL8 (2021-05-19) diff --git a/SOURCES/lvm2-set-default-preferred_names.patch b/SOURCES/lvm2-set-default-preferred_names.patch index 26bef54..88912bb 100644 --- a/SOURCES/lvm2-set-default-preferred_names.patch +++ b/SOURCES/lvm2-set-default-preferred_names.patch @@ -1,23 +1,25 @@ - conf/example.conf.in | 3 ++- + conf/example.conf.in | 5 +++-- lib/config/config_settings.h | 2 +- - 2 files changed, 3 insertions(+), 2 deletions(-) + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/conf/example.conf.in b/conf/example.conf.in -index fe17942..d149ed9 100644 +index b4a55ae..aaf73a4 100644 --- a/conf/example.conf.in +++ b/conf/example.conf.in -@@ -122,7 +122,8 @@ devices { +@@ -121,8 +121,9 @@ devices { + # # Example # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] - # +- # - # This configuration option does not have a default value defined. ++ # + # This configuration option has an automatic default value. + # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] - # Configuration option devices/filter. - # Limit the block devices that are used by LVM commands. + # Configuration option devices/use_devicesfile. + # Enable or disable the use of a devices file. diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h -index 163e014..3c4032e 100644 +index d3a42a1..f5dac4d 100644 --- a/lib/config/config_settings.h +++ b/lib/config/config_settings.h @@ -269,7 +269,7 @@ cfg(devices_hints_CFG, "hints", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_ diff --git a/SOURCES/lvm2-test-skip-problematic-tests.patch b/SOURCES/lvm2-test-skip-problematic-tests.patch index b8c65d9..0f107ad 100644 --- a/SOURCES/lvm2-test-skip-problematic-tests.patch +++ b/SOURCES/lvm2-test-skip-problematic-tests.patch @@ -3,10 +3,10 @@ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/dbus/lvmdbustest.py b/test/dbus/lvmdbustest.py -index efa1afb..473bb94 100755 +index 6d69222..64faf84 100755 --- a/test/dbus/lvmdbustest.py +++ b/test/dbus/lvmdbustest.py -@@ -1851,6 +1851,7 @@ class TestDbusService(unittest.TestCase): +@@ -1856,6 +1856,7 @@ class TestDbusService(unittest.TestCase): # path to it. Additionally, we will take the symlink and do a lookup # (Manager.LookUpByLvmId) using it and the original device path to # ensure that we can find the PV. diff --git a/SPECS/lvm2.spec b/SPECS/lvm2.spec index 3262fe8..7da9aa8 100644 --- a/SPECS/lvm2.spec +++ b/SPECS/lvm2.spec @@ -1,4 +1,4 @@ -%global device_mapper_version 1.02.175 +%global device_mapper_version 1.02.177 %global enable_cache 1 %global enable_cluster 1 @@ -20,6 +20,7 @@ %global bash_version 4.0 %global corosync_version 1.99.9-1 %global resource_agents_version 3.9.5-12 +# TODO: This needs newer dlm - do I need a side tag??? :-/ %global dlm_version 4.0.9-1 %global libselinux_version 1.30.19-4 %global persistent_data_version 0.7.0-0.1.rc6 @@ -40,14 +41,12 @@ %endif %endif -%if %{enable_cluster} - %global configure_cluster --with-cluster=internal - %if %{enable_cmirror} - %global configure_cmirror --enable-cmirrord - %endif -%else - %global configure_cluster --with-cluster=internal +%global from_snapshot 0 +%if 0%{?from_snapshot} +%global commit 4dc5d4ac7e7a9457ccc46ff04796b347e58bf4da +%global shortcommit %(c=%{commit}; echo ${c:0:7}) %endif +#%%global rel_suffix .test # Do not reset Release to 1 unless both lvm2 and device-mapper # versions are increased together. @@ -56,48 +55,67 @@ Name: lvm2 %if 0%{?rhel} Epoch: %{rhel} %endif -Version: 2.03.11 -Release: 5%{?dist} +Version: 2.03.12 +%if 0%{?from_snapshot} +Release: 0.1.20210426git%{shortcommit}%{?dist}%{?rel_suffix} +%else +Release: 10%{?dist}%{?rel_suffix} +%endif License: GPLv2 URL: http://sourceware.org/lvm2 +%if 0%{?from_snapshot} +Source0: lvm2-%{shortcommit}.tgz +%else Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz Patch0: lvm2-rhel8.patch +%endif Patch1: lvm2-set-default-preferred_names.patch Patch2: lvm2-test-skip-problematic-tests.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 -# BZ 1931893: -Patch24: lvm2-2_03_12-fsadm-avoid-access-to-unbound-variable.patch -Patch25: lvm2-2_03_12-tests-remove-local-setting-of-LVM_BINARY.patch -Patch26: lvm2-2_03_12-man-Fix-wording-in-lvmthin-7.patch +# BZ 1961890 +Patch3: lvm2-2_03_13-vdo-fix-preload-of-kvdo.patch +# BZ 1964622: +Patch4: lvm2-2_03_13-lvremove-fix-removing-thin-pool-with-writecache-on-d.patch +# BZ 1957898: +Patch5: lvm2-2_03_13-enable-command-syntax-for-thin-and-writecache.patch +# BZ 1872903: +Patch6: lvm2-2_03_13-writecache-fix-lv_on_pmem.patch +Patch7: lvm2-2_03_13-writecache-don-t-pvmove-device-used-by-writecache.patch +# BZ 1957898: +Patch8: lvm2-2_03_13-lvconvert-allow-writecache-with-other-thinpool-comma.patch +# BZ 1922312: +Patch9: lvm2-2_03_13-devices-don-t-use-deleted-loop-backing-file-for-devi.patch +Patch10: lvm2-2_03_13-lvmdevices-add-deviceidtype-option.patch +# BZ 1974901: +Patch11: lvm2-2_03_13-device_id-handle-scsi_debug-wwid.patch +# BZ 1930261: +Patch12: lvm2-2_03_13-lvconvert-fix-vdo-virtual-size-when-specified.patch +Patch13: lvm2-2_03_13-vdo-rename-variable-vdo_pool_zero.patch +Patch14: lvm2-2_03_13-vdo-support-vdo_pool_header_size.patch +Patch15: lvm2-2_03_13-vdo-add-vdoimport-support.patch +Patch16: lvm2-2_03_13-man-vdoimport-page.patch +Patch17: lvm2-make-generate.patch +# BZ 1967744: +Patch18: lvm2-2_03_13-thin-fix-component-detection-of-external-origin.patch +# BZ 1899263: +Patch19: lvm2-2_03_13-vgremove-remove-forgotten-pmspare.patch +Patch20: lvm2-2_03_13-vgsplit-add-support-for-option-poolmetadataspare.patch +Patch21: lvm2-2_03_13-test.patch +Patch22: lvm2-2_03_13-vgmerge-remove-one-of-merge-pmspare-LVs.patch +Patch23: lvm2-2_03_13-vgmerge-support-option-poolmetadataspare.patch +Patch24: lvm2-2_03_13-tests-extend-vgmerge-testing.patch +# BZ 1986930: +Patch25: lvm2-2_03_14-vdo-Rename-vdoimport-to-lvm_import_vdo.patch +# BZs #1930261 #1986885 #1986915 #1988504 #1989650 #1996227: +Patch26: lvm2-2_03_14-vdo-fixes.patch +Patch27: lvm2-2_03_14-vdo-lvm_import_vdo-fix-max_discard-size.patch +Patch28: lvm2-2_03_14-vdo-better-message-for-missing-device.patch +Patch29: lvm2-2_03_14-vdo-more-lvm_import_vdo-fixes.patch +Patch30: lvm2-2_03_14-vdo-fix-conversion-of-large-virtual-sizes.patch +Patch31: lvm2-2_03_14-vdo-read-new-sysfs-path.patch +Patch32: lvm2-2_03_14-tests-check-lvm2-parses-vdo-statistics.patch +Patch33: lvm2-2_03_14-vdo-lvm_import_vdo-script-needs-to-continue-when-vgn.patch +Patch34: lvm2-2_03_14-vdo-man-page-updates.patch +Patch35: lvm2-2_03_14-vdo-prompt-with-no-return-failure.patch BuildRequires: gcc %if %{enable_testsuite} @@ -152,8 +170,12 @@ or more physical volumes and creating one or more logical volumes (kind of logical partitions) in volume groups. %prep +%if 0%{?from_snapshot} +%setup -q -n lvm2-%{commit} +%else %setup -q -n LVM2.%{version} %patch0 -p1 -b .backup0 +%endif %patch1 -p1 -b .backup1 %patch2 -p1 -b .backup2 %patch3 -p1 -b .backup3 @@ -180,6 +202,15 @@ or more physical volumes and creating one or more logical volumes %patch24 -p1 -b .backup24 %patch25 -p1 -b .backup25 %patch26 -p1 -b .backup26 +%patch27 -p1 -b .backup27 +%patch28 -p1 -b .backup28 +%patch29 -p1 -b .backup29 +%patch30 -p1 -b .backup30 +%patch31 -p1 -b .backup31 +%patch32 -p1 -b .backup32 +%patch33 -p1 -b .backup33 +%patch34 -p1 -b .backup34 +%patch35 -p1 -b .backup35 %build %global _default_pid_dir /run @@ -189,48 +220,68 @@ or more physical volumes and creating one or more logical volumes %global _udevdir %{_prefix}/lib/udev/rules.d -%global configure_udev --with-udevdir=%{_udevdir} --enable-udev_sync - -%if %{enable_cache} -%global configure_cache --with-cache=internal +# FIXME: Dropped in rhel9, do we need to keep this for "compatibility"? +%if %{enable_cluster} + %global configure_cluster --with-cluster=internal + %if %{enable_cmirror} + %global configure_cmirror --enable-cmirrord + %endif +%else + %global configure_cluster --with-cluster=internal %endif +%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} \ + --with-udevdir=%{_udevdir} --enable-udev_sync \ %if %{enable_thin} -%global configure_thin --with-thin=internal + --with-thin=internal \ +%endif +%if %{enable_cache} + --with-cache=internal \ +%endif +%if %{enable_lvmpolld} + --enable-lvmpolld \ %endif - %if %{enable_lockd_dlm} -%global configure_lockd_dlm --enable-lvmlockd-dlm --enable-lvmlockd-dlmcontrol + --enable-lvmlockd-dlm --enable-lvmlockd-dlmcontrol \ %endif %if %{enable_lockd_sanlock} -%global configure_lockd_sanlock --enable-lvmlockd-sanlock + --enable-lvmlockd-sanlock \ %endif - -%if %{enable_lvmpolld} -%global configure_lvmpolld --enable-lvmpolld -%endif - %if %{enable_lvmdbusd} -%global configure_lvmdbusd --enable-dbus-service --enable-notify-dbus + --enable-dbus-service --enable-notify-dbus \ %endif - %if %{enable_dmfilemapd} -%global configure_dmfilemapd --enable-dmfilemapd + --enable-dmfilemapd \ %endif - -%if %{enable_vdo} -%global configure_vdo --with-vdo=internal --with-vdo-format=%{_bindir}/vdoformat -%endif - %if %{enable_writecache} -%global configure_writecache --with-writecache=internal + --with-writecache=internal \ %endif - +%if %{enable_vdo} + --with-vdo=internal --with-vdo-format=%{_bindir}/vdoformat \ +%endif + %{?configure_integrity} \ %if %{enable_integrity} -%global configure_integrity --with-integrity=internal + --with-integrity=internal \ %endif - -%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 + --disable-silent-rules make %{?_smp_mflags} @@ -293,10 +344,12 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || : %{_sbindir}/fsadm %{_sbindir}/lvm %{_sbindir}/lvmconfig +%{_sbindir}/lvmdevices %{_sbindir}/lvmdump %if %{enable_lvmpolld} %{_sbindir}/lvmpolld %endif +%{_sbindir}/lvm_import_vdo # Other files %defattr(444,root,root,-) @@ -334,6 +387,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || : %{_sbindir}/vgextend %{_sbindir}/vgimport %{_sbindir}/vgimportclone +%{_sbindir}/vgimportdevices %{_sbindir}/vgmerge %{_sbindir}/vgmknodes %{_sbindir}/vgreduce @@ -359,6 +413,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || : %{_mandir}/man8/lvm2-activation-generator.8.gz %{_mandir}/man8/lvm-config.8.gz %{_mandir}/man8/lvmconfig.8.gz +%{_mandir}/man8/lvmdevices.8.gz %{_mandir}/man8/lvm-dumpconfig.8.gz %{_mandir}/man8/lvmdiskscan.8.gz %{_mandir}/man8/lvmdump.8.gz @@ -389,8 +444,10 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || : %{_mandir}/man8/vgdisplay.8.gz %{_mandir}/man8/vgexport.8.gz %{_mandir}/man8/vgextend.8.gz +%{_mandir}/man8/lvm_import_vdo.8.gz %{_mandir}/man8/vgimport.8.gz %{_mandir}/man8/vgimportclone.8.gz +%{_mandir}/man8/vgimportdevices.8.gz %{_mandir}/man8/vgmerge.8.gz %{_mandir}/man8/vgmknodes.8.gz %{_mandir}/man8/vgreduce.8.gz @@ -417,9 +474,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || : %{_sysconfdir}/lvm/profile/cache-mq.profile %{_sysconfdir}/lvm/profile/cache-smq.profile %{_sysconfdir}/lvm/profile/lvmdbusd.profile -%if %{enable_vdo} %{_sysconfdir}/lvm/profile/vdo-small.profile -%endif %dir %{_sysconfdir}/lvm/backup %dir %{_sysconfdir}/lvm/cache %dir %{_sysconfdir}/lvm/archive @@ -784,8 +839,41 @@ An extensive functional testsuite for LVM2. %endif %changelog -* Thu Feb 11 2021 Marian Csontos - 2.03.11-5 -- Fix fsadm failure due to accessing unbound variable. +* Mon Sep 20 2021 Marian Csontos - 2.03.12-10 +- Fix incorrect memory free. + +* Fri Sep 17 2021 Marian Csontos - 2.03.12-9 +- Fix various lvm_import_vdo issues. +- Fix conversion to vdo when virtual size is above 2TiB. + +* Thu Aug 26 2021 Marian Csontos - 2.03.12-8 +- Rename vdoimport to lvm_import_vdo. + +* Wed Aug 11 2021 Marian Csontos - 2.03.12-7 +- Fix missing executable flag on vdoimport. + +* Tue Aug 03 2021 Marian Csontos - 2.03.12-6 +- Fix handling of pmspare by vgsplit, vgmerge and vgremove. +- Fix detection of active components of external origin volume. + +* Tue Jul 13 2021 Marian Csontos - 2.03.12-5 +- Fix device_id handling of scsi_debug WWID. +- Add vdoimport support. + +* Tue Jun 22 2021 Marian Csontos - 2.03.12-4 +- Fix conversion of writecache LVs to thin pool data volume. +- Add deviceidtype option for lvmdevices. + +* Tue Jun 15 2021 Marian Csontos - 2.03.12-3 +- Allow extending thin-pool data with writecache on top. +- Fix removing thin-pool data converted to writeache. + +* Tue Jun 01 2021 Marian Csontos - 2.03.12-2 +- Fix loading of VDO kernel module. + +* Wed May 19 2021 Marian Csontos - 2.03.12-1 +- Update to upstream version 2.03.12. +- See WHATS_NEW for list of changes. * Thu Feb 11 2021 Marian Csontos - 2.03.11-4 - Fix "Failed to get primary device" for NVMe devices.