import lvm2-2.03.11-5.el8

This commit is contained in:
CentOS Sources 2021-05-18 02:39:24 -04:00 committed by Andrew Lukoshko
parent 45bd5eb560
commit 03fc3e8e9e
45 changed files with 2524 additions and 17024 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/LVM2.2.03.09.tgz
SOURCES/LVM2.2.03.11.tgz

View File

@ -1 +1 @@
15a90d5039a2a1e9f67611a2a6c2faa72e8996aa SOURCES/LVM2.2.03.09.tgz
9484fd277914a85f330b4067aa222ee13f061189 SOURCES/LVM2.2.03.11.tgz

File diff suppressed because it is too large Load Diff

View File

@ -1,210 +0,0 @@
From f540a18fd7f5f65599a6c85c0bd3ba84e54f1cc8 Mon Sep 17 00:00:00 2001
From: Marian Csontos <mcsontos@redhat.com>
Date: Thu, 28 May 2020 18:02:16 +0200
Subject: [PATCH] Merge master up to commit be61bd6ff5c6
---
VERSION | 2 +-
VERSION_DM | 2 +-
test/shell/cache-single-usage.sh | 13 +++++++++++++
test/shell/integrity-dmeventd.sh | 8 ++++++++
test/shell/integrity-large.sh | 8 ++++++++
test/shell/integrity-misc.sh | 8 ++++++++
test/shell/integrity.sh | 8 ++++++++
test/shell/thin-foreign-repair.sh | 14 ++++++++++----
tools/lvconvert.c | 15 +++++++++++++++
9 files changed, 72 insertions(+), 6 deletions(-)
diff --git a/VERSION b/VERSION
index 00618e0..9ad7a70 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.03.09(2)-RHEL8 (2020-04-21)
+2.03.09(2)-RHEL8 (2020-05-28)
diff --git a/VERSION_DM b/VERSION_DM
index b9ec43e..bcd97de 100644
--- a/VERSION_DM
+++ b/VERSION_DM
@@ -1 +1 @@
-1.02.171-RHEL8 (2020-04-21)
+1.02.171-RHEL8 (2020-05-28)
diff --git a/test/shell/cache-single-usage.sh b/test/shell/cache-single-usage.sh
index a885bf7..8936aa3 100644
--- a/test/shell/cache-single-usage.sh
+++ b/test/shell/cache-single-usage.sh
@@ -127,4 +127,17 @@ umount "$mount_dir"
lvchange -an $vg/$lv1
lvchange -an $vg/$lv2
+# misc tests
+
+lvremove $vg
+
+lvcreate -n $lv1 -l 2 -an $vg "$dev1"
+lvcreate -n $lv2 -l 2 -an $vg "$dev1"
+lvcreate -n $lv3 -l 2 -an $vg "$dev2"
+
+lvconvert -y --type writecache --cachevol $lv3 $vg/$lv1
+not lvconvert -y --type writecache --cachevol ${lv3}_cvol $vg/$lv2
+not lvconvert -y --type cache --cachevol ${lv3}_cvol $vg/$lv2
+not lvconvert -y --type cache --cachepool ${lv3}_cvol $vg/$lv2
+
vgremove -ff $vg
diff --git a/test/shell/integrity-dmeventd.sh b/test/shell/integrity-dmeventd.sh
index ed2436a..296f556 100644
--- a/test/shell/integrity-dmeventd.sh
+++ b/test/shell/integrity-dmeventd.sh
@@ -109,6 +109,14 @@ _wait_recalc() {
sleep 1
done
+ # TODO: There is some strange bug, first leg of RAID with integrity
+ # enabled never gets in sync. I saw this in BB, but not when executing
+ # the commands manually
+ if test -z "$sync"; then
+ echo "TEST WARNING: Resync of dm-integrity device '$checklv' failed"
+ dmsetup status "$DM_DEV_DIR/mapper/${checklv/\//-}"
+ exit
+ fi
echo "timeout waiting for recalc"
return 1
}
diff --git a/test/shell/integrity-large.sh b/test/shell/integrity-large.sh
index 7a333c1..5aba80e 100644
--- a/test/shell/integrity-large.sh
+++ b/test/shell/integrity-large.sh
@@ -95,6 +95,14 @@ _wait_recalc() {
sleep 1
done
+ # TODO: There is some strange bug, first leg of RAID with integrity
+ # enabled never gets in sync. I saw this in BB, but not when executing
+ # the commands manually
+ if test -z "$sync"; then
+ echo "TEST WARNING: Resync of dm-integrity device '$checklv' failed"
+ dmsetup status "$DM_DEV_DIR/mapper/${checklv/\//-}"
+ exit
+ fi
echo "timeout waiting for recalc"
return 1
}
diff --git a/test/shell/integrity-misc.sh b/test/shell/integrity-misc.sh
index a176f18..0d05689 100644
--- a/test/shell/integrity-misc.sh
+++ b/test/shell/integrity-misc.sh
@@ -109,6 +109,14 @@ _wait_recalc() {
sleep 1
done
+ # TODO: There is some strange bug, first leg of RAID with integrity
+ # enabled never gets in sync. I saw this in BB, but not when executing
+ # the commands manually
+ if test -z "$sync"; then
+ echo "TEST WARNING: Resync of dm-integrity device '$checklv' failed"
+ dmsetup status "$DM_DEV_DIR/mapper/${checklv/\//-}"
+ exit
+ fi
echo "timeout waiting for recalc"
return 1
}
diff --git a/test/shell/integrity.sh b/test/shell/integrity.sh
index 6baccf0..77e9430 100644
--- a/test/shell/integrity.sh
+++ b/test/shell/integrity.sh
@@ -204,6 +204,14 @@ _wait_recalc() {
sleep 1
done
+ # TODO: There is some strange bug, first leg of RAID with integrity
+ # enabled never gets in sync. I saw this in BB, but not when executing
+ # the commands manually
+ if test -z "$sync"; then
+ echo "TEST WARNING: Resync of dm-integrity device '$checklv' failed"
+ dmsetup status "$DM_DEV_DIR/mapper/${checklv/\//-}"
+ exit
+ fi
echo "timeout waiting for recalc"
return 1
}
diff --git a/test/shell/thin-foreign-repair.sh b/test/shell/thin-foreign-repair.sh
index 8b4018e..55e9f62 100644
--- a/test/shell/thin-foreign-repair.sh
+++ b/test/shell/thin-foreign-repair.sh
@@ -17,9 +17,15 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
+clean_thin_()
+{
+ aux udev_wait
+ dmsetup remove "$THIN" || { sleep .5 ; dmsetup remove "$THIN" ; }
+}
+
cleanup_mounted_and_teardown()
{
- dmsetup remove $THIN || true
+ clean_thin_ || true
vgremove -ff $vg
aux teardown
}
@@ -56,9 +62,7 @@ dmsetup create "$THIN" --table "0 40960 thin $DM_DEV_DIR/mapper/$POOL 0"
mkfs.ext4 "$DM_DEV_DIR/mapper/$THIN"
-aux udev_wait
-
-dmsetup remove "$THIN" || { sleep .5 ; dmsetup remove "$THIN" }
+clean_thin_
lvchange -an $vg/pool
@@ -72,3 +76,5 @@ lvchange -ay $vg/pool
dmsetup create "$THIN" --table "0 40960 thin $DM_DEV_DIR/mapper/$POOL 0"
fsck -n "$DM_DEV_DIR/mapper/$THIN"
+
+# exit calls cleanup_mounted_and_teardown
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index cf93538..8652252 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -4264,6 +4264,11 @@ static int _lvconvert_cachevol_attach_single(struct cmd_context *cmd,
goto out;
}
+ if (lv_is_cache_vol(cachevol_lv)) {
+ log_error("LV %s is already used as a cachevol.", display_lvname(cachevol_lv));
+ goto out;
+ }
+
/* Ensure the LV is not active elsewhere. */
if (!lockd_lv(cmd, lv, "ex", 0))
goto_out;
@@ -4347,6 +4352,11 @@ static int _lvconvert_cachepool_attach_single(struct cmd_context *cmd,
goto out;
}
+ if (lv_is_cache_vol(cachepool_lv)) {
+ log_error("LV %s is already used as a cachevol.", display_lvname(cachepool_lv));
+ goto out;
+ }
+
if (cachepool_lv == lv) {
log_error("Use a different LV for cache pool LV and cache LV %s.",
display_lvname(cachepool_lv));
@@ -5629,6 +5639,11 @@ static int _lvconvert_writecache_attach_single(struct cmd_context *cmd,
goto bad;
}
+ if (lv_is_cache_vol(lv_fast)) {
+ log_error("LV %s is already used as a cachevol.", display_lvname(lv_fast));
+ goto bad;
+ }
+
/*
* To permit this we need to check the block size of the fs using lv
* (recently in libblkid) so that we can use a matching writecache
--
1.8.3.1

File diff suppressed because it is too large Load Diff

View File

@ -1,422 +0,0 @@
From 99b646d87469b5ca0e93fad6b77f51a00fbbd2b7 Mon Sep 17 00:00:00 2001
From: Marian Csontos <mcsontos@redhat.com>
Date: Wed, 12 Aug 2020 18:47:15 +0200
Subject: [PATCH] Revert "debug: missing stacktrace"
This reverts commit d0faad0db38fe733cae42d7df136d7ed4f7bcba6.
Revert "raid: no wiping when zeroing raid metadata device"
This reverts commit 9b9bf8786fb423a4430cc676301edadf2310098d.
Revert "lvconvert: more support for yes conversion"
This reverts commit b7f3667ce20b731bbda9b1d61df49abbcd1bd20e.
Revert "wipe_lv: always zero at least 4K"
This reverts commit fe78cd4082cb9af10580180d61898fcef93dc624.
Revert "tests: check pool metadata are zeroed"
This reverts commit 3f32f9811e01c8953d201c7c9b563561ad856130.
Revert "tests: failure of zeroing fails command"
This reverts commit 094d6f80ddb6d8a1c64977dfaae4073827063fe3.
Revert "make: make generate"
This reverts commit 88b92d4225b90db82047f3bac55d8059918e9c1b.
Conflicts:
man/lvconvert.8_pregen
Revert "pool: zero metadata"
This reverts commit bc39d5bec6fea787a8d8d16fa484084b7d2a7c29.
Conflicts:
WHATS_NEW
Revert "wipe_lv: make error a fatal event"
This reverts commit edbc5a62b26806e5c4de59b5292609e955303576.
Conflicts:
WHATS_NEW
build: make generate
---
WHATS_NEW | 2 -
conf/example.conf.in | 6 +--
lib/config/config_settings.h | 5 +--
lib/config/defaults.h | 1 -
lib/metadata/lv_manip.c | 78 ++++++++++++---------------------
lib/metadata/metadata-exported.h | 2 -
lib/metadata/pool_manip.c | 6 +--
test/lib/aux.sh | 1 -
test/shell/lvcreate-signature-wiping.sh | 7 ---
test/shell/lvcreate-thin.sh | 21 ---------
tools/lvconvert.c | 12 ++---
11 files changed, 36 insertions(+), 105 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index ac99e97..6a098b5 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -6,8 +6,6 @@ Version 2.03.10 -
warning.
Fix conversion to raid from striped lagging type.
Fix conversion to 'mirrored' mirror log with larger regionsize.
- Zero pool metadata on allocation (disable with allocation/zero_metadata=0).
- Failure in zeroing or wiping will fail command (bypass with -Zn, -Wn).
Fix running out of free buffers for async writing for larger writes.
Add integrity with raid capability.
Fix support for lvconvert --repair used by foreign apps (i.e. Docker).
diff --git a/conf/example.conf.in b/conf/example.conf.in
index d5807e6..88858fc 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -489,7 +489,7 @@ allocation {
# This configuration option does not have a default value defined.
# Configuration option allocation/thin_pool_metadata_require_separate_pvs.
- # Thin pool metadata and data will always use different PVs.
+ # Thin pool metdata and data will always use different PVs.
thin_pool_metadata_require_separate_pvs = 0
# Configuration option allocation/thin_pool_zero.
@@ -527,10 +527,6 @@ allocation {
# This configuration option has an automatic default value.
# thin_pool_chunk_size_policy = "generic"
- # Configuration option allocation/zero_metadata.
- # Zero whole metadata area before use with thin or cache pool.
- zero_metadata = 1
-
# Configuration option allocation/thin_pool_chunk_size.
# The minimal chunk size in KiB for thin pool volumes.
# Larger chunk sizes may improve performance for plain thin volumes,
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index b38ca11..dce9705 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -626,7 +626,7 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF
"Using cache pool with more chunks may degrade cache performance.\n")
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
- "Thin pool metadata and data will always use different PVs.\n")
+ "Thin pool metdata and data will always use different PVs.\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"
@@ -657,9 +657,6 @@ cfg(allocation_thin_pool_chunk_size_policy_CFG, "thin_pool_chunk_size_policy", a
" 512KiB.\n"
"#\n")
-cfg(allocation_zero_metadata_CFG, "zero_metadata", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ZERO_METADATA, vsn(2, 3, 10), NULL, 0, NULL,
- "Zero whole metadata area before use with thin or cache pool.\n")
-
cfg_runtime(allocation_thin_pool_chunk_size_CFG, "thin_pool_chunk_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(2, 2, 99), 0, NULL,
"The minimal chunk size in KiB for thin pool volumes.\n"
"Larger chunk sizes may improve performance for plain thin volumes,\n"
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 708a575..be4f5ff 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -129,7 +129,6 @@
#define DEFAULT_THIN_POOL_DISCARDS "passdown"
#define DEFAULT_THIN_POOL_ZERO 1
#define DEFAULT_POOL_METADATA_SPARE 1 /* thin + cache */
-#define DEFAULT_ZERO_METADATA 1 /* thin + cache */
#ifdef CACHE_CHECK_NEEDS_CHECK
# define DEFAULT_CACHE_CHECK_OPTION1 "-q"
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index f0ba3f0..1642b90 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -7576,22 +7576,20 @@ int wipe_lv(struct logical_volume *lv, struct wipe_params wp)
struct device *dev;
char name[PATH_MAX];
uint64_t zero_sectors;
- int zero_metadata = wp.is_metadata ?
- find_config_tree_bool(lv->vg->cmd, allocation_zero_metadata_CFG, NULL) : 0;
- if (!wp.do_zero && !wp.do_wipe_signatures && !wp.is_metadata)
+ if (!wp.do_zero && !wp.do_wipe_signatures)
/* nothing to do */
return 1;
if (!lv_is_active(lv)) {
- log_error("Volume %s is not active locally (volume_list activation filter?).",
- display_lvname(lv));
+ log_error("Volume \"%s/%s\" is not active locally (volume_list activation filter?).",
+ lv->vg->name, lv->name);
return 0;
}
/* Wait until devices are available */
if (!sync_local_dev_names(lv->vg->cmd)) {
- log_error("Failed to sync local devices before wiping volume %s.",
+ log_error("Failed to sync local devices before wiping LV %s.",
display_lvname(lv));
return 0;
}
@@ -7615,59 +7613,40 @@ int wipe_lv(struct logical_volume *lv, struct wipe_params wp)
}
if (!label_scan_open_rw(dev)) {
- log_error("Failed to open %s for wiping and zeroing.", display_lvname(lv));
- return 0;
+ log_error("Failed to open %s/%s for wiping and zeroing.", lv->vg->name, lv->name);
+ goto out;
}
if (wp.do_wipe_signatures) {
- log_verbose("Wiping known signatures on logical volume %s.",
- display_lvname(lv));
+ log_verbose("Wiping known signatures on logical volume \"%s/%s\"",
+ lv->vg->name, lv->name);
if (!wipe_known_signatures(lv->vg->cmd, dev, name, 0,
TYPE_DM_SNAPSHOT_COW,
- wp.yes, wp.force, NULL)) {
- log_error("Filed to wipe signatures of logical volume %s.",
- display_lvname(lv));
- return 0;
- }
+ wp.yes, wp.force, NULL))
+ stack;
}
- if (wp.do_zero || wp.is_metadata) {
- zero_metadata = !wp.is_metadata ? 0 :
- find_config_tree_bool(lv->vg->cmd, allocation_zero_metadata_CFG, NULL);
- if (zero_metadata) {
- log_debug("Metadata logical volume %s will be fully zeroed.",
- display_lvname(lv));
- zero_sectors = lv->size;
- } else {
- if (wp.is_metadata) /* Verbosely notify metadata will not be fully zeroed */
- log_verbose("Metadata logical volume %s not fully zeroed and may contain stale data.",
- display_lvname(lv));
- zero_sectors = UINT64_C(4096) >> SECTOR_SHIFT;
- if (wp.zero_sectors > zero_sectors)
- zero_sectors = wp.zero_sectors;
+ if (wp.do_zero) {
+ zero_sectors = wp.zero_sectors ? : UINT64_C(4096) >> SECTOR_SHIFT;
- if (zero_sectors > lv->size)
- zero_sectors = lv->size;
- }
+ if (zero_sectors > lv->size)
+ zero_sectors = lv->size;
- log_verbose("Initializing %s of logical volume %s with value %d.",
+ log_verbose("Initializing %s of logical volume \"%s/%s\" with value %d.",
display_size(lv->vg->cmd, zero_sectors),
- display_lvname(lv), wp.zero_value);
-
- if ((!wp.is_metadata &&
- wp.zero_value && !dev_set_bytes(dev, UINT64_C(0),
- (size_t) zero_sectors << SECTOR_SHIFT,
- (uint8_t)wp.zero_value)) ||
- !dev_write_zeros(dev, UINT64_C(0), (size_t) zero_sectors << SECTOR_SHIFT)) {
- log_error("Failed to initialize %s of logical volume %s with value %d.",
- display_size(lv->vg->cmd, zero_sectors),
- display_lvname(lv), wp.zero_value);
- return 0;
+ lv->vg->name, lv->name, wp.zero_value);
+
+ if (!wp.zero_value) {
+ if (!dev_write_zeros(dev, UINT64_C(0), (size_t) zero_sectors << SECTOR_SHIFT))
+ stack;
+ } else {
+ if (!dev_set_bytes(dev, UINT64_C(0), (size_t) zero_sectors << SECTOR_SHIFT, (uint8_t)wp.zero_value))
+ stack;
}
}
label_scan_invalidate(dev);
-
+out:
lv->status &= ~LV_NOSCAN;
return 1;
@@ -7731,10 +7710,12 @@ int activate_and_wipe_lvlist(struct dm_list *lv_list, int commit)
}
dm_list_iterate_items(lvl, lv_list) {
+ log_verbose("Wiping metadata area %s.", display_lvname(lvl->lv));
/* Wipe any know signatures */
- if (!wipe_lv(lvl->lv, (struct wipe_params) { .do_zero = 1 /* TODO: is_metadata = 1 */ })) {
+ if (!wipe_lv(lvl->lv, (struct wipe_params) { .do_wipe_signatures = 1, .do_zero = 1, .zero_sectors = 1 })) {
+ log_error("Failed to wipe %s.", display_lvname(lvl->lv));
r = 0;
- goto_out;
+ goto out;
}
}
out:
@@ -8479,8 +8460,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
.do_zero = lp->zero,
.do_wipe_signatures = lp->wipe_signatures,
.yes = lp->yes,
- .force = lp->force,
- .is_metadata = lp->is_metadata,
+ .force = lp->force
})) {
log_error("Aborting. Failed to wipe %s.", lp->snapshot
? "snapshot exception store" : "start of new LV");
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 06ea757..0cc5f37 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -803,7 +803,6 @@ struct wipe_params {
int do_wipe_signatures; /* should we wipe known signatures found on LV? */
int yes; /* answer yes automatically to all questions */
force_t force; /* force mode */
- int is_metadata; /* wipe volume is metadata LV */
};
/* Zero out LV and/or wipe signatures */
@@ -956,7 +955,6 @@ struct lvcreate_params {
unsigned suppress_zero_warn : 1;
unsigned needs_lockd_init : 1;
unsigned ignore_type : 1;
- unsigned is_metadata : 1; /* created LV will be used as metadata LV (and can be zeroed) */
const char *vg_name; /* only-used when VG is not yet opened (in /tools) */
const char *lv_name; /* all */
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index 23b5b63..bed51f1 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -545,8 +545,8 @@ int create_pool(struct logical_volume *pool_lv,
display_lvname(pool_lv));
goto bad;
}
- /* Clear pool metadata device. */
- if (!(r = wipe_lv(pool_lv, (struct wipe_params) { .is_metadata = 1 }))) {
+ /* Clear 4KB of pool metadata device. */
+ if (!(r = wipe_lv(pool_lv, (struct wipe_params) { .do_zero = 1 }))) {
log_error("Aborting. Failed to wipe pool metadata %s.",
display_lvname(pool_lv));
}
@@ -627,7 +627,6 @@ struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
.tags = DM_LIST_HEAD_INIT(lvc.tags),
.temporary = 1,
.zero = 1,
- .is_metadata = 1,
};
if (!(lvc.segtype = get_segtype_from_string(pool_lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
@@ -664,7 +663,6 @@ static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg
.tags = DM_LIST_HEAD_INIT(lp.tags),
.temporary = 1,
.zero = 1,
- .is_metadata = 1,
};
if (!(lp.segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_STRIPED)))
diff --git a/test/lib/aux.sh b/test/lib/aux.sh
index 17e7935..e40da95 100644
--- a/test/lib/aux.sh
+++ b/test/lib/aux.sh
@@ -1234,7 +1234,6 @@ activation/verify_udev_operations = $LVM_VERIFY_UDEV
activation/raid_region_size = 512
allocation/wipe_signatures_when_zeroing_new_lvs = 0
allocation/vdo_slab_size_mb = 128
-allocation/zero_metadata = 0
backup/archive = 0
backup/backup = 0
devices/cache_dir = "$TESTDIR/etc"
diff --git a/test/shell/lvcreate-signature-wiping.sh b/test/shell/lvcreate-signature-wiping.sh
index 18d7a2f..73fea54 100644
--- a/test/shell/lvcreate-signature-wiping.sh
+++ b/test/shell/lvcreate-signature-wiping.sh
@@ -42,13 +42,6 @@ init_lv_
test_blkid_ || skip
lvremove -f $vg/$lv1
-# Zeroing stops the command when there is a failure (write error in this case)
-aux error_dev "$dev1" "$(get first_extent_sector "$dev1"):2"
-not lvcreate -l1 -n $lv1 $vg 2>&1 | tee out
-grep "Failed to initialize" out
-aux enable_dev "$dev1"
-
-
aux lvmconf "allocation/wipe_signatures_when_zeroing_new_lvs = 0"
lvcreate -y -Zn -l1 -n $lv1 $vg 2>&1 | tee out
diff --git a/test/shell/lvcreate-thin.sh b/test/shell/lvcreate-thin.sh
index c073eaf..9ca7f11 100644
--- a/test/shell/lvcreate-thin.sh
+++ b/test/shell/lvcreate-thin.sh
@@ -248,25 +248,4 @@ not lvcreate -s $vg/lv1 -L4M -V2G --name $vg/lv4
not lvcreate -T mirpool -L4M --alloc anywhere -m1 $vg
not lvcreate --thinpool mirpool -L4M --alloc anywhere -m1 $vg
-
-# Check pool metadata volume is zeroed, when zero_metadata is enabled.
-# 1st. ensure 8megs of both PVs will have some non-0 data
-lvcreate -L8m -n $lv1 $vg "$dev1"
-lvextend -L+8m $vg/$lv1 "$dev2"
-dd if=/dev/urandom of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=16 oflag=direct conv=fdatasync
-lvremove -ff $vg/$lv1
-
-lvcreate -l1 --poolmetadatasize 4m --conf 'allocation/zero_metadata=1' -vvvv -T $vg/pool
-lvchange -an $vg
-# component activation to check device was zeroed
-lvchange -y -ay $vg/pool_tmeta
-dd if="$DM_DEV_DIR/$vg/pool_tmeta" of=file bs=1M count=3 skip=1 iflag=direct conv=fdatasync
-
-md5sum -b file | tee out
-# md5sum of 3M of zeros
-grep d1dd210d6b1312cb342b56d02bd5e651 out
-lvchange -an $vg
-lvremove -ff $vg
-
-
vgremove -ff $vg
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 524ed5a..6324ed7 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -3286,11 +3286,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
}
metadata_lv->status &= ~LV_ACTIVATION_SKIP;
- if (!wipe_lv(metadata_lv, (struct wipe_params) {
- .do_wipe_signatures = 1,
- .is_metadata = 1,
- .yes = arg_count(cmd, yes_ARG),
- .force = arg_count(cmd, force_ARG) } )) {
+ if (!wipe_lv(metadata_lv, (struct wipe_params) { .do_zero = 1 })) {
log_error("Aborting. Failed to wipe metadata lv.");
goto bad;
}
@@ -5527,8 +5523,7 @@ static int _writecache_zero(struct cmd_context *cmd, struct logical_volume *lv)
struct wipe_params wp = {
.do_wipe_signatures = 1, /* optional, to print warning if clobbering something */
.do_zero = 1, /* required for dm-writecache to work */
- .yes = arg_count(cmd, yes_ARG),
- .force = arg_count(cmd, force_ARG)
+ .zero_sectors = 1
};
int ret;
@@ -5545,8 +5540,7 @@ static int _writecache_zero(struct cmd_context *cmd, struct logical_volume *lv)
return 0;
}
- if (!(ret = wipe_lv(lv, wp)))
- stack;
+ ret = wipe_lv(lv, wp);
if (!deactivate_lv(cmd, lv)) {
log_error("Failed to deactivate LV %s for zeroing.", display_lvname(lv));
--
1.8.3.1

View File

@ -1,31 +0,0 @@
From 48105f492f7f8c157ba714217ae55c6fb50e76c0 Mon Sep 17 00:00:00 2001
From: Maxim Plotnikov <wgh@torlan.ru>
Date: Wed, 22 Apr 2020 00:16:29 +0300
Subject: [PATCH] Fix scripts/lvmlocks.service.in using nonexistent --lock-opt
autowait
The --lock-opt autowait was dropped back in 9ab6bdce01,
and attempting to specify it has quite an opposite effect:
no waiting is done, which makes the unit almost useless.
(cherry picked from commit a509776588a5c0c0bfc2394e4d1ed717531b0257)
---
scripts/lvmlocks.service.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/lvmlocks.service.in b/scripts/lvmlocks.service.in
index f6a951f..a3d0bd4 100644
--- a/scripts/lvmlocks.service.in
+++ b/scripts/lvmlocks.service.in
@@ -8,7 +8,7 @@ Type=oneshot
RemainAfterExit=yes
# start lockspaces and wait for them to finish starting
-ExecStart=@SBINDIR@/lvm vgchange --lock-start --lock-opt autowait
+ExecStart=@SBINDIR@/lvm vgchange --lock-start --lock-opt auto
# stop lockspaces and wait for them to finish stopping
ExecStop=@SBINDIR@/lvmlockctl --stop-lockspaces --wait 1
--
1.8.3.1

View File

@ -1,24 +0,0 @@
From a08afc8d0d18b2547176e731852b816df76c63eb Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Wed, 15 Apr 2020 11:04:12 -0500
Subject: [PATCH 3/3] WHATS_NEW: integrity with raid
(cherry picked from commit 211eaa284c4df992916e0a523d0ff932aa790a98)
---
WHATS_NEW | 1 +
1 file changed, 1 insertion(+)
diff --git a/WHATS_NEW b/WHATS_NEW
index 89583f7..c0267b7 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.03.10 -
=================================
+ Add integrity with raid capability.
Fix support for lvconvert --repair used by foreign apps (i.e. Docker).
Version 2.03.09 - 26th March 2020
--
1.8.3.1

View File

@ -1,15 +0,0 @@
WHATS_NEW | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/WHATS_NEW b/WHATS_NEW
index db914c0..89583f7 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,3 +1,7 @@
+Version 2.03.10 -
+=================================
+ Fix support for lvconvert --repair used by foreign apps (i.e. Docker).
+
Version 2.03.09 - 26th March 2020
=================================
Fix formating of vdopool (vdo_slab_size_mb was smaller by 2 bits).

View File

@ -1,179 +0,0 @@
WHATS_NEW_DM | 4 ++++
man/blkdeactivate.8_main | 11 +++++++++++
scripts/blkdeactivate.sh.in | 48 ++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 12bdcea..3ec9c3c 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,3 +1,7 @@
+Version 1.02.173 -
+==================================
+ Add support for VDO in blkdeactivate script.
+
Version 1.02.171 - 26th March 2020
==================================
Fix dm_list interators with gcc 10 optimization (-ftree-pta).
diff --git a/man/blkdeactivate.8_main b/man/blkdeactivate.8_main
index f3c19a8..06af52e 100644
--- a/man/blkdeactivate.8_main
+++ b/man/blkdeactivate.8_main
@@ -9,6 +9,7 @@ blkdeactivate \(em utility to deactivate block devices
.RB [ -l \ \fIlvm_options\fP ]
.RB [ -m \ \fImpath_options\fP ]
.RB [ -r \ \fImdraid_options\fP ]
+.RB [ -o \ \fIvdo_options\fP ]
.RB [ -u ]
.RB [ -v ]
.RI [ device ]
@@ -70,6 +71,15 @@ Comma-separated list of MD RAID specific options:
Wait MD device's resync, recovery or reshape action to complete
before deactivation.
.RE
+
+.TP
+.BR -o ", " --vdooptions \ \fIvdo_options\fP
+Comma-separated list of VDO specific options:
+.RS
+.IP \fIconfigfile=file\fP
+Use specified VDO configuration file.
+.RE
+
.TP
.BR -u ", " --umount
Unmount a mounted device before trying to deactivate it.
@@ -120,4 +130,5 @@ of a device-mapper device fails, retry it and force removal.
.BR lvm (8),
.BR mdadm (8),
.BR multipathd (8),
+.BR vdo (8),
.BR umount (8)
diff --git a/scripts/blkdeactivate.sh.in b/scripts/blkdeactivate.sh.in
index a4b8a8f..57b3e58 100644
--- a/scripts/blkdeactivate.sh.in
+++ b/scripts/blkdeactivate.sh.in
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
@@ -38,6 +38,7 @@ MDADM="/sbin/mdadm"
MOUNTPOINT="/bin/mountpoint"
MPATHD="/sbin/multipathd"
UMOUNT="/bin/umount"
+VDO="/bin/vdo"
sbindir="@SBINDIR@"
DMSETUP="$sbindir/dmsetup"
@@ -54,6 +55,7 @@ DMSETUP_OPTS=""
LVM_OPTS=""
MDADM_OPTS=""
MPATHD_OPTS=""
+VDO_OPTS=""
LSBLK="/bin/lsblk -r --noheadings -o TYPE,KNAME,NAME,MOUNTPOINT"
LSBLK_VARS="local devtype local kname local name local mnt"
@@ -124,6 +126,7 @@ usage() {
echo " -l | --lvmoptions LVM_OPTIONS Comma separated LVM specific options"
echo " -m | --mpathoptions MPATH_OPTIONS Comma separated DM-multipath specific options"
echo " -r | --mdraidoptions MDRAID_OPTIONS Comma separated MD RAID specific options"
+ echo " -o | --vdooptions VDO_OPTIONS Comma separated VDO specific options"
echo " -u | --umount Unmount the device if mounted"
echo " -v | --verbose Verbose mode (also implies -e)"
echo
@@ -138,6 +141,8 @@ usage() {
echo " wait wait for resync, recovery or reshape to complete first"
echo " MPATH_OPTIONS:"
echo " disablequeueing disable queueing on all DM-multipath devices first"
+ echo " VDO_OPTIONS:"
+ echo " configfile=file use specified VDO configuration file"
exit
}
@@ -319,6 +324,23 @@ deactivate_md () {
fi
}
+deactivate_vdo() {
+ local xname
+ xname=$(printf "%s" "$name")
+ test -b "$DEV_DIR/mapper/$xname" || return 0
+ test -z "${SKIP_DEVICE_LIST["$kname"]}" || return 1
+
+ deactivate_holders "$DEV_DIR/mapper/$xname" || return 1
+
+ echo -n " [VDO]: deactivating VDO volume $xname... "
+ if eval "$VDO" stop $VDO_OPTS --name="$xname" "$OUT" "$ERR"; then
+ echo "done"
+ else
+ echo "skipping"
+ add_device_to_skip_list
+ fi
+}
+
deactivate () {
######################################################################
# DEACTIVATION HOOKS FOR NEW DEVICE TYPES GO HERE! #
@@ -335,6 +357,8 @@ deactivate () {
######################################################################
if test "$devtype" = "lvm"; then
deactivate_lvm
+ elif test "$devtype" = "vdo"; then
+ deactivate_vdo
elif test "${kname:0:3}" = "dm-"; then
deactivate_dm
elif test "${kname:0:2}" = "md"; then
@@ -479,6 +503,20 @@ get_mpathopts() {
IFS=$ORIG_IFS
}
+get_vdoopts() {
+ ORIG_IFS=$IFS; IFS=','
+
+ for opt in $1; do
+ case "$opt" in
+ "") ;;
+ configfile=*) tmp=${opt#*=}; VDO_OPTS+="--confFile=${tmp%%,*} " ;;
+ *) echo "$opt: unknown VDO option"
+ esac
+ done
+
+ IFS=$ORIG_IFS
+}
+
set_env() {
if test "$ERRORS" -eq "1"; then
unset ERR
@@ -493,6 +531,7 @@ set_env() {
LVM_OPTS+="-vvvv"
MDADM_OPTS+="-vv"
MPATHD_OPTS+="-v 3"
+ VDO_OPTS+="--verbose "
else
OUT="1>$DEV_DIR/null"
fi
@@ -509,6 +548,12 @@ set_env() {
MDADM_AVAILABLE=0
fi
+ if test -f $VDO; then
+ VDO_AVAILABLE=1
+ else
+ VDO_AVAILABLE=0
+ fi
+
MPATHD_RUNNING=0
test "$MPATHD_DO_DISABLEQUEUEING" -eq 1 && {
if test -f "$MPATHD"; then
@@ -528,6 +573,7 @@ while test $# -ne 0; do
"-l"|"--lvmoptions") get_lvmopts "$2" ; shift ;;
"-m"|"--mpathoptions") get_mpathopts "$2" ; shift ;;
"-r"|"--mdraidoptions") get_mdraidopts "$2"; shift ;;
+ "-o"|"--vdooptions") get_vdoopts "$2"; shift ;;
"-u"|"--umount") DO_UMOUNT=1 ;;
"-v"|"--verbose") VERBOSE=1 ; ERRORS=1 ;;
"-vv") VERBOSE=1 ; ERRORS=1 ; set -x ;;

View File

@ -1,180 +0,0 @@
From 7def94164ae6c18d84e40f00db2e2b74a7662b35 Mon Sep 17 00:00:00 2001
From: Marian Csontos <mcsontos@redhat.com>
Date: Tue, 5 May 2020 10:20:18 +0200
Subject: [PATCH] build: make generate
(cherry picked from commit bcc149048440dce5fc7962f88ed523469dd39a32)
---
man/lvconvert.8_pregen | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
man/lvcreate.8_pregen | 53 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+)
diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen
index b676e72..7440984 100644
--- a/man/lvconvert.8_pregen
+++ b/man/lvconvert.8_pregen
@@ -163,6 +163,18 @@ lvconvert - Change logical volume layout
.ad b
.br
.ad l
+ \fB--raidintegrity\fP \fBy\fP|\fBn\fP
+.ad b
+.br
+.ad l
+ \fB--raidintegrityblocksize\fP \fINumber\fP
+.ad b
+.br
+.ad l
+ \fB--raidintegritymode\fP \fIString\fP
+.ad b
+.br
+.ad l
\fB-r\fP|\fB--readahead\fP \fBauto\fP|\fBnone\fP|\fINumber\fP
.ad b
.br
@@ -982,6 +994,28 @@ Poll LV to continue conversion.
.br
-
+Add or remove data integrity checksums to raid images.
+.br
+.P
+\fBlvconvert\fP \fB--raidintegrity\fP \fBy\fP|\fBn\fP \fILV\fP\fI_raid\fP
+.br
+.RS 4
+.ad l
+[ \fB--raidintegritymode\fP \fIString\fP ]
+.ad b
+.br
+.ad l
+[ \fB--raidintegrityblocksize\fP \fINumber\fP ]
+.ad b
+.br
+[ COMMON_OPTIONS ]
+.RE
+.br
+.RS 4
+[ \fIPV\fP ... ]
+.RE
+-
+
Common options for command:
.
.RS 4
@@ -1405,6 +1439,35 @@ Repeat once to also suppress any prompts with answer 'no'.
.ad b
.HP
.ad l
+\fB--raidintegrity\fP \fBy\fP|\fBn\fP
+.br
+Enable or disable data integrity checksums for raid images.
+.ad b
+.HP
+.ad l
+\fB--raidintegrityblocksize\fP \fINumber\fP
+.br
+The block size to use for dm-integrity on raid images.
+The integrity block size should usually match the device
+logical block size, or the file system block size.
+It may be less than the file system block size, but not
+less than the device logical block size.
+Possible values: 512, 1024, 2048, 4096.
+.ad b
+.HP
+.ad l
+\fB--raidintegritymode\fP \fIString\fP
+.br
+Use a journal (default) or bitmap for keeping integrity checksums consistent
+in case of a crash. The bitmap areas are recalculated after a crash, so corruption
+in those areas would not be detected. A journal does not have this problem.
+The journal mode doubles writes to storage, but can improve performance for
+scattered writes packed into a single journal write.
+bitmap mode can in theory achieve full write throughput of the device,
+but would not benefit from the potential scattered write optimization.
+.ad b
+.HP
+.ad l
\fB-r\fP|\fB--readahead\fP \fBauto\fP|\fBnone\fP|\fINumber\fP
.br
Sets read ahead sector count of an LV.
diff --git a/man/lvcreate.8_pregen b/man/lvcreate.8_pregen
index a80f9f5..be8e783 100644
--- a/man/lvcreate.8_pregen
+++ b/man/lvcreate.8_pregen
@@ -187,6 +187,18 @@ lvcreate - Create a logical volume
.ad b
.br
.ad l
+ \fB--raidintegrity\fP \fBy\fP|\fBn\fP
+.ad b
+.br
+.ad l
+ \fB--raidintegrityblocksize\fP \fINumber\fP
+.ad b
+.br
+.ad l
+ \fB--raidintegritymode\fP \fIString\fP
+.ad b
+.br
+.ad l
\fB-r\fP|\fB--readahead\fP \fBauto\fP|\fBnone\fP|\fINumber\fP
.ad b
.br
@@ -425,6 +437,18 @@ Create a raid LV (a specific raid level must be used, e.g. raid1).
[ \fB--[raid]maxrecoveryrate\fP \fISize\fP[k|UNIT] ]
.ad b
.br
+.ad l
+[ \fB--raidintegrity\fP \fBy\fP|\fBn\fP ]
+.ad b
+.br
+.ad l
+[ \fB--raidintegritymode\fP \fIString\fP ]
+.ad b
+.br
+.ad l
+[ \fB--raidintegrityblocksize\fP \fINumber\fP ]
+.ad b
+.br
[ COMMON_OPTIONS ]
.RE
.br
@@ -1420,6 +1444,35 @@ Repeat once to also suppress any prompts with answer 'no'.
.ad b
.HP
.ad l
+\fB--raidintegrity\fP \fBy\fP|\fBn\fP
+.br
+Enable or disable data integrity checksums for raid images.
+.ad b
+.HP
+.ad l
+\fB--raidintegrityblocksize\fP \fINumber\fP
+.br
+The block size to use for dm-integrity on raid images.
+The integrity block size should usually match the device
+logical block size, or the file system block size.
+It may be less than the file system block size, but not
+less than the device logical block size.
+Possible values: 512, 1024, 2048, 4096.
+.ad b
+.HP
+.ad l
+\fB--raidintegritymode\fP \fIString\fP
+.br
+Use a journal (default) or bitmap for keeping integrity checksums consistent
+in case of a crash. The bitmap areas are recalculated after a crash, so corruption
+in those areas would not be detected. A journal does not have this problem.
+The journal mode doubles writes to storage, but can improve performance for
+scattered writes packed into a single journal write.
+bitmap mode can in theory achieve full write throughput of the device,
+but would not benefit from the potential scattered write optimization.
+.ad b
+.HP
+.ad l
\fB-r\fP|\fB--readahead\fP \fBauto\fP|\fBnone\fP|\fINumber\fP
.br
Sets read ahead sector count of an LV.
--
1.8.3.1

View File

@ -1,17 +0,0 @@
tools/lvconvert.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index f6d9a29..bb40930 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -2388,7 +2388,8 @@ static int _lvconvert_thin_pool_repair(struct cmd_context *cmd,
goto deactivate_mlv;
}
- if (thin_dump[0]) {
+ /* Check matching transactionId when thin-pool is used by lvm2 (transactionId != 0) */
+ if (first_seg(pool_lv)->transaction_id && thin_dump[0]) {
argv[0] = thin_dump;
argv[1] = pms_path;
argv[2] = NULL;

View File

@ -1,641 +0,0 @@
From 945de675c47d891d1f181f15971d26ff959ac631 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 14 Jan 2020 14:12:20 -0600
Subject: [PATCH 1/3] move pv_list code into lib
(cherry picked from commit b6b4ad8e28eff7476cb04c4cb93312b06605b82f)
---
lib/Makefile.in | 1 +
lib/metadata/metadata-exported.h | 4 +
lib/metadata/pv_list.c | 291 +++++++++++++++++++++++++++++++++++++++
tools/toollib.c | 270 ------------------------------------
tools/toollib.h | 9 --
5 files changed, 296 insertions(+), 279 deletions(-)
create mode 100644 lib/metadata/pv_list.c
diff --git a/lib/Makefile.in b/lib/Makefile.in
index c037b41..2a064f3 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -74,6 +74,7 @@ SOURCES =\
metadata/mirror.c \
metadata/pool_manip.c \
metadata/pv.c \
+ metadata/pv_list.c \
metadata/pv_manip.c \
metadata/pv_map.c \
metadata/raid_manip.c \
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index c61c85c..35c1231 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1385,4 +1385,8 @@ int vg_is_foreign(struct volume_group *vg);
void vg_write_commit_bad_mdas(struct cmd_context *cmd, struct volume_group *vg);
+struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int argc,
+ char **argv, int allocatable_only);
+struct dm_list *clone_pv_list(struct dm_pool *mem, struct dm_list *pvsl);
+
#endif
diff --git a/lib/metadata/pv_list.c b/lib/metadata/pv_list.c
new file mode 100644
index 0000000..143b573
--- /dev/null
+++ b/lib/metadata/pv_list.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2017 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 Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#include "lib/misc/lib.h"
+#include "lib/misc/lvm-string.h"
+#include "lib/datastruct/str_list.h"
+#include "lib/device/device.h"
+#include "lib/metadata/metadata.h"
+
+/*
+ * Process physical extent range specifiers
+ */
+static int _add_pe_range(struct dm_pool *mem, const char *pvname,
+ struct dm_list *pe_ranges, uint32_t start, uint32_t count)
+{
+ struct pe_range *per;
+
+ log_debug("Adding PE range: start PE " FMTu32 " length " FMTu32 " on %s.",
+ start, count, pvname);
+
+ /* Ensure no overlap with existing areas */
+ dm_list_iterate_items(per, pe_ranges) {
+ if (((start < per->start) && (start + count - 1 >= per->start)) ||
+ ((start >= per->start) &&
+ (per->start + per->count - 1) >= start)) {
+ log_error("Overlapping PE ranges specified (" FMTu32
+ "-" FMTu32 ", " FMTu32 "-" FMTu32 ") on %s.",
+ start, start + count - 1, per->start,
+ per->start + per->count - 1, pvname);
+ return 0;
+ }
+ }
+
+ if (!(per = dm_pool_alloc(mem, sizeof(*per)))) {
+ log_error("Allocation of list failed.");
+ return 0;
+ }
+
+ per->start = start;
+ per->count = count;
+ dm_list_add(pe_ranges, &per->list);
+
+ return 1;
+}
+
+static int _xstrtouint32(const char *s, char **p, int base, uint32_t *result)
+{
+ unsigned long ul;
+
+ errno = 0;
+ ul = strtoul(s, p, base);
+
+ if (errno || *p == s || ul > UINT32_MAX)
+ return 0;
+
+ *result = ul;
+
+ return 1;
+}
+
+static int _parse_pes(struct dm_pool *mem, char *c, struct dm_list *pe_ranges,
+ const char *pvname, uint32_t size)
+{
+ char *endptr;
+ uint32_t start, end, len;
+
+ /* Default to whole PV */
+ if (!c) {
+ if (!_add_pe_range(mem, pvname, pe_ranges, UINT32_C(0), size))
+ return_0;
+ return 1;
+ }
+
+ while (*c) {
+ if (*c != ':')
+ goto error;
+
+ c++;
+
+ /* Disallow :: and :\0 */
+ if (*c == ':' || !*c)
+ goto error;
+
+ /* Default to whole range */
+ start = UINT32_C(0);
+ end = size - 1;
+
+ /* Start extent given? */
+ if (isdigit(*c)) {
+ if (!_xstrtouint32(c, &endptr, 10, &start))
+ goto error;
+ c = endptr;
+ /* Just one number given? */
+ if (!*c || *c == ':')
+ end = start;
+ }
+ /* Range? */
+ if (*c == '-') {
+ c++;
+ if (isdigit(*c)) {
+ if (!_xstrtouint32(c, &endptr, 10, &end))
+ goto error;
+ c = endptr;
+ }
+ } else if (*c == '+') { /* Length? */
+ c++;
+ if (isdigit(*c)) {
+ if (!_xstrtouint32(c, &endptr, 10, &len))
+ goto error;
+ c = endptr;
+ end = start + (len ? (len - 1) : 0);
+ }
+ }
+
+ if (*c && *c != ':')
+ goto error;
+
+ if ((start > end) || (end > size - 1)) {
+ log_error("PE range error: start extent %" PRIu32 " to "
+ "end extent %" PRIu32 ".", start, end);
+ return 0;
+ }
+
+ if (!_add_pe_range(mem, pvname, pe_ranges, start, end - start + 1))
+ return_0;
+
+ }
+
+ return 1;
+
+ error:
+ log_error("Physical extent parsing error at %s.", c);
+ return 0;
+}
+
+static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
+ char *colon, int allocatable_only, struct dm_list *r)
+{
+ const char *pvname;
+ struct pv_list *new_pvl = NULL, *pvl2;
+ struct dm_list *pe_ranges;
+
+ pvname = pv_dev_name(pvl->pv);
+ if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) {
+ log_warn("WARNING: Physical volume %s not allocatable.", pvname);
+ return 1;
+ }
+
+ if (allocatable_only && is_missing_pv(pvl->pv)) {
+ log_warn("WARNING: Physical volume %s is missing.", pvname);
+ return 1;
+ }
+
+ if (allocatable_only &&
+ (pvl->pv->pe_count == pvl->pv->pe_alloc_count)) {
+ log_warn("WARNING: No free extents on physical volume \"%s\".", pvname);
+ return 1;
+ }
+
+ dm_list_iterate_items(pvl2, r)
+ if (pvl->pv->dev == pvl2->pv->dev) {
+ new_pvl = pvl2;
+ break;
+ }
+
+ if (!new_pvl) {
+ if (!(new_pvl = dm_pool_alloc(mem, sizeof(*new_pvl)))) {
+ log_error("Unable to allocate physical volume list.");
+ return 0;
+ }
+
+ memcpy(new_pvl, pvl, sizeof(*new_pvl));
+
+ if (!(pe_ranges = dm_pool_alloc(mem, sizeof(*pe_ranges)))) {
+ log_error("Allocation of pe_ranges list failed.");
+ return 0;
+ }
+ dm_list_init(pe_ranges);
+ new_pvl->pe_ranges = pe_ranges;
+ dm_list_add(r, &new_pvl->list);
+ }
+
+ /* Determine selected physical extents */
+ if (!_parse_pes(mem, colon, new_pvl->pe_ranges, pv_dev_name(pvl->pv),
+ pvl->pv->pe_count))
+ return_0;
+
+ return 1;
+}
+
+struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int argc,
+ char **argv, int allocatable_only)
+{
+ struct dm_list *r;
+ struct pv_list *pvl;
+ struct dm_list tagsl, arg_pvnames;
+ char *pvname = NULL;
+ char *colon, *at_sign, *tagname;
+ int i;
+
+ /* Build up list of PVs */
+ if (!(r = dm_pool_alloc(mem, sizeof(*r)))) {
+ log_error("Allocation of list failed.");
+ return NULL;
+ }
+ dm_list_init(r);
+
+ dm_list_init(&tagsl);
+ dm_list_init(&arg_pvnames);
+
+ for (i = 0; i < argc; i++) {
+ dm_unescape_colons_and_at_signs(argv[i], &colon, &at_sign);
+
+ if (at_sign && (at_sign == argv[i])) {
+ tagname = at_sign + 1;
+ if (!validate_tag(tagname)) {
+ log_error("Skipping invalid tag %s.", tagname);
+ continue;
+ }
+ dm_list_iterate_items(pvl, &vg->pvs) {
+ if (str_list_match_item(&pvl->pv->tags,
+ tagname)) {
+ if (!_create_pv_entry(mem, pvl, NULL,
+ allocatable_only,
+ r))
+ return_NULL;
+ }
+ }
+ continue;
+ }
+
+ pvname = argv[i];
+
+ if (colon && !(pvname = dm_pool_strndup(mem, pvname,
+ (unsigned) (colon - pvname)))) {
+ log_error("Failed to clone PV name.");
+ return NULL;
+ }
+
+ if (!(pvl = find_pv_in_vg(vg, pvname))) {
+ log_error("Physical Volume \"%s\" not found in "
+ "Volume Group \"%s\".", pvname, vg->name);
+ return NULL;
+ }
+ if (!_create_pv_entry(mem, pvl, colon, allocatable_only, r))
+ return_NULL;
+ }
+
+ if (dm_list_empty(r))
+ log_error("No specified PVs have space available.");
+
+ return dm_list_empty(r) ? NULL : r;
+}
+
+struct dm_list *clone_pv_list(struct dm_pool *mem, struct dm_list *pvsl)
+{
+ struct dm_list *r;
+ struct pv_list *pvl, *new_pvl;
+
+ /* Build up list of PVs */
+ if (!(r = dm_pool_alloc(mem, sizeof(*r)))) {
+ log_error("Allocation of list failed.");
+ return NULL;
+ }
+ dm_list_init(r);
+
+ dm_list_iterate_items(pvl, pvsl) {
+ if (!(new_pvl = dm_pool_zalloc(mem, sizeof(*new_pvl)))) {
+ log_error("Unable to allocate physical volume list.");
+ return NULL;
+ }
+
+ memcpy(new_pvl, pvl, sizeof(*new_pvl));
+ dm_list_add(r, &new_pvl->list);
+ }
+
+ return r;
+}
+
diff --git a/tools/toollib.c b/tools/toollib.c
index a5304bf..6386a69 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -457,276 +457,6 @@ const char *extract_vgname(struct cmd_context *cmd, const char *lv_name)
return vg_name;
}
-/*
- * Process physical extent range specifiers
- */
-static int _add_pe_range(struct dm_pool *mem, const char *pvname,
- struct dm_list *pe_ranges, uint32_t start, uint32_t count)
-{
- struct pe_range *per;
-
- log_debug("Adding PE range: start PE " FMTu32 " length " FMTu32 " on %s.",
- start, count, pvname);
-
- /* Ensure no overlap with existing areas */
- dm_list_iterate_items(per, pe_ranges) {
- if (((start < per->start) && (start + count - 1 >= per->start)) ||
- ((start >= per->start) &&
- (per->start + per->count - 1) >= start)) {
- log_error("Overlapping PE ranges specified (" FMTu32
- "-" FMTu32 ", " FMTu32 "-" FMTu32 ") on %s.",
- start, start + count - 1, per->start,
- per->start + per->count - 1, pvname);
- return 0;
- }
- }
-
- if (!(per = dm_pool_alloc(mem, sizeof(*per)))) {
- log_error("Allocation of list failed.");
- return 0;
- }
-
- per->start = start;
- per->count = count;
- dm_list_add(pe_ranges, &per->list);
-
- return 1;
-}
-
-static int _xstrtouint32(const char *s, char **p, int base, uint32_t *result)
-{
- unsigned long ul;
-
- errno = 0;
- ul = strtoul(s, p, base);
-
- if (errno || *p == s || ul > UINT32_MAX)
- return 0;
-
- *result = ul;
-
- return 1;
-}
-
-static int _parse_pes(struct dm_pool *mem, char *c, struct dm_list *pe_ranges,
- const char *pvname, uint32_t size)
-{
- char *endptr;
- uint32_t start, end, len;
-
- /* Default to whole PV */
- if (!c) {
- if (!_add_pe_range(mem, pvname, pe_ranges, UINT32_C(0), size))
- return_0;
- return 1;
- }
-
- while (*c) {
- if (*c != ':')
- goto error;
-
- c++;
-
- /* Disallow :: and :\0 */
- if (*c == ':' || !*c)
- goto error;
-
- /* Default to whole range */
- start = UINT32_C(0);
- end = size - 1;
-
- /* Start extent given? */
- if (isdigit(*c)) {
- if (!_xstrtouint32(c, &endptr, 10, &start))
- goto error;
- c = endptr;
- /* Just one number given? */
- if (!*c || *c == ':')
- end = start;
- }
- /* Range? */
- if (*c == '-') {
- c++;
- if (isdigit(*c)) {
- if (!_xstrtouint32(c, &endptr, 10, &end))
- goto error;
- c = endptr;
- }
- } else if (*c == '+') { /* Length? */
- c++;
- if (isdigit(*c)) {
- if (!_xstrtouint32(c, &endptr, 10, &len))
- goto error;
- c = endptr;
- end = start + (len ? (len - 1) : 0);
- }
- }
-
- if (*c && *c != ':')
- goto error;
-
- if ((start > end) || (end > size - 1)) {
- log_error("PE range error: start extent %" PRIu32 " to "
- "end extent %" PRIu32 ".", start, end);
- return 0;
- }
-
- if (!_add_pe_range(mem, pvname, pe_ranges, start, end - start + 1))
- return_0;
-
- }
-
- return 1;
-
- error:
- log_error("Physical extent parsing error at %s.", c);
- return 0;
-}
-
-static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
- char *colon, int allocatable_only, struct dm_list *r)
-{
- const char *pvname;
- struct pv_list *new_pvl = NULL, *pvl2;
- struct dm_list *pe_ranges;
-
- pvname = pv_dev_name(pvl->pv);
- if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) {
- log_warn("WARNING: Physical volume %s not allocatable.", pvname);
- return 1;
- }
-
- if (allocatable_only && is_missing_pv(pvl->pv)) {
- log_warn("WARNING: Physical volume %s is missing.", pvname);
- return 1;
- }
-
- if (allocatable_only &&
- (pvl->pv->pe_count == pvl->pv->pe_alloc_count)) {
- log_warn("WARNING: No free extents on physical volume \"%s\".", pvname);
- return 1;
- }
-
- dm_list_iterate_items(pvl2, r)
- if (pvl->pv->dev == pvl2->pv->dev) {
- new_pvl = pvl2;
- break;
- }
-
- if (!new_pvl) {
- if (!(new_pvl = dm_pool_alloc(mem, sizeof(*new_pvl)))) {
- log_error("Unable to allocate physical volume list.");
- return 0;
- }
-
- memcpy(new_pvl, pvl, sizeof(*new_pvl));
-
- if (!(pe_ranges = dm_pool_alloc(mem, sizeof(*pe_ranges)))) {
- log_error("Allocation of pe_ranges list failed.");
- return 0;
- }
- dm_list_init(pe_ranges);
- new_pvl->pe_ranges = pe_ranges;
- dm_list_add(r, &new_pvl->list);
- }
-
- /* Determine selected physical extents */
- if (!_parse_pes(mem, colon, new_pvl->pe_ranges, pv_dev_name(pvl->pv),
- pvl->pv->pe_count))
- return_0;
-
- return 1;
-}
-
-struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int argc,
- char **argv, int allocatable_only)
-{
- struct dm_list *r;
- struct pv_list *pvl;
- struct dm_list tagsl, arg_pvnames;
- char *pvname = NULL;
- char *colon, *at_sign, *tagname;
- int i;
-
- /* Build up list of PVs */
- if (!(r = dm_pool_alloc(mem, sizeof(*r)))) {
- log_error("Allocation of list failed.");
- return NULL;
- }
- dm_list_init(r);
-
- dm_list_init(&tagsl);
- dm_list_init(&arg_pvnames);
-
- for (i = 0; i < argc; i++) {
- dm_unescape_colons_and_at_signs(argv[i], &colon, &at_sign);
-
- if (at_sign && (at_sign == argv[i])) {
- tagname = at_sign + 1;
- if (!validate_tag(tagname)) {
- log_error("Skipping invalid tag %s.", tagname);
- continue;
- }
- dm_list_iterate_items(pvl, &vg->pvs) {
- if (str_list_match_item(&pvl->pv->tags,
- tagname)) {
- if (!_create_pv_entry(mem, pvl, NULL,
- allocatable_only,
- r))
- return_NULL;
- }
- }
- continue;
- }
-
- pvname = argv[i];
-
- if (colon && !(pvname = dm_pool_strndup(mem, pvname,
- (unsigned) (colon - pvname)))) {
- log_error("Failed to clone PV name.");
- return NULL;
- }
-
- if (!(pvl = find_pv_in_vg(vg, pvname))) {
- log_error("Physical Volume \"%s\" not found in "
- "Volume Group \"%s\".", pvname, vg->name);
- return NULL;
- }
- if (!_create_pv_entry(mem, pvl, colon, allocatable_only, r))
- return_NULL;
- }
-
- if (dm_list_empty(r))
- log_error("No specified PVs have space available.");
-
- return dm_list_empty(r) ? NULL : r;
-}
-
-struct dm_list *clone_pv_list(struct dm_pool *mem, struct dm_list *pvsl)
-{
- struct dm_list *r;
- struct pv_list *pvl, *new_pvl;
-
- /* Build up list of PVs */
- if (!(r = dm_pool_alloc(mem, sizeof(*r)))) {
- log_error("Allocation of list failed.");
- return NULL;
- }
- dm_list_init(r);
-
- dm_list_iterate_items(pvl, pvsl) {
- if (!(new_pvl = dm_pool_zalloc(mem, sizeof(*new_pvl)))) {
- log_error("Unable to allocate physical volume list.");
- return NULL;
- }
-
- memcpy(new_pvl, pvl, sizeof(*new_pvl));
- dm_list_add(r, &new_pvl->list);
- }
-
- return r;
-}
-
const char _pe_size_may_not_be_negative_msg[] = "Physical extent size may not be negative.";
int vgcreate_params_set_defaults(struct cmd_context *cmd,
diff --git a/tools/toollib.h b/tools/toollib.h
index 9102f55..53a5e5b 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -182,15 +182,6 @@ void opt_array_to_str(struct cmd_context *cmd, int *opts, int count,
int pvcreate_params_from_args(struct cmd_context *cmd, struct pvcreate_params *pp);
int pvcreate_each_device(struct cmd_context *cmd, struct processing_handle *handle, struct pvcreate_params *pp);
-/*
- * Builds a list of pv's from the names in argv. Used in
- * lvcreate/extend.
- */
-struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int argc,
- char **argv, int allocatable_only);
-
-struct dm_list *clone_pv_list(struct dm_pool *mem, struct dm_list *pvs);
-
int vgcreate_params_set_defaults(struct cmd_context *cmd,
struct vgcreate_params *vp_def,
struct volume_group *vg);
--
1.8.3.1

View File

@ -1,82 +0,0 @@
test/shell/thin-foreign-repair.sh | 72 +++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
create mode 100644 test/shell/thin-foreign-repair.sh
diff --git a/test/shell/thin-foreign-repair.sh b/test/shell/thin-foreign-repair.sh
new file mode 100644
index 0000000..147a9a0
--- /dev/null
+++ b/test/shell/thin-foreign-repair.sh
@@ -0,0 +1,72 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 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
+
+# test foreing user of thin-pool
+
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+cleanup_mounted_and_teardown()
+{
+ dmsetup remove $THIN || true
+ vgremove -ff $vg
+ aux teardown
+}
+
+#
+# Main
+#
+aux have_thin 1 0 0 || skip
+which mkfs.ext4 || skip
+
+# Use our mkfs config file to get approximately same results
+# TODO: maybe use it for all test via some 'prepare' function
+export MKE2FS_CONFIG="$TESTOLDPWD/lib/mke2fs.conf"
+
+aux prepare_vg 2 64
+
+# Create named pool only
+lvcreate -L2 -T $vg/pool
+
+POOL="$vg-pool"
+THIN="${PREFIX}_thin"
+
+# Foreing user is using own ioctl command to create thin devices
+dmsetup message $POOL 0 "create_thin 0"
+dmsetup message $POOL 0 "set_transaction_id 0 2"
+
+# Once the transaction id has changed, lvm2 shall not be able to create thinLV
+fail lvcreate -V10 $vg/pool
+
+trap 'cleanup_mounted_and_teardown' EXIT
+
+# 20M thin device
+dmsetup create "$THIN" --table "0 40960 thin $DM_DEV_DIR/mapper/$POOL 0"
+
+mkfs.ext4 "$DM_DEV_DIR/mapper/$THIN"
+
+dmsetup remove "$THIN"
+
+lvchange -an $vg/pool
+
+# Repair thin-pool used by 'foreing' apps (setting their own tid)
+lvconvert --repair $vg/pool 2>&1 | tee out
+
+not grep "Transaction id" out
+
+lvchange -ay $vg/pool
+
+dmsetup create "$THIN" --table "0 40960 thin $DM_DEV_DIR/mapper/$POOL 0"
+
+fsck -n "$DM_DEV_DIR/mapper/$THIN"

View File

@ -1,481 +0,0 @@
man/lvmvdo.7_main | 321 +++++++++++++++++++++++++++++-------------------------
1 file changed, 173 insertions(+), 148 deletions(-)
diff --git a/man/lvmvdo.7_main b/man/lvmvdo.7_main
index 582f7a8..39dee39 100644
--- a/man/lvmvdo.7_main
+++ b/man/lvmvdo.7_main
@@ -1,32 +1,29 @@
.TH "LVMVDO" "7" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
.SH NAME
-lvmvdo \(em EXPERIMENTAL LVM Virtual Data Optimizer support
-
+lvmvdo \(em Support for Virtual Data Optimizer in LVM
.SH DESCRIPTION
-
-VDO (which includes kvdo and vdo) is software that provides inline
+VDO is software that provides inline
block-level deduplication, compression, and thin provisioning capabilities
for primary storage.
Deduplication is a technique for reducing the consumption of storage
resources by eliminating multiple copies of duplicate blocks. Compression
-takes the individual unique blocks and shrinks them with coding
-algorithms; these reduced blocks are then efficiently packed together into
-physical blocks. Thin provisioning manages the mapping from LBAs presented
-by VDO to where the data has actually been stored, and also eliminates any
-blocks of all zeroes.
-
-With deduplication, instead of writing the same data more than once each
-duplicate block is detected and recorded as a reference to the original
+takes the individual unique blocks and shrinks them. These reduced blocks are then efficiently packed together into
+physical blocks. Thin provisioning manages the mapping from logical blocks
+presented by VDO to where the data has actually been physically stored,
+and also eliminates any blocks of all zeroes.
+
+With deduplication, instead of writing the same data more than once, VDO detects and records each
+duplicate block as a reference to the original
block. VDO maintains a mapping from logical block addresses (used by the
storage layer above VDO) to physical block addresses (used by the storage
layer under VDO). After deduplication, multiple logical block addresses
may be mapped to the same physical block address; these are called shared
blocks and are reference-counted by the software.
-With VDO's compression, multiple blocks (or shared blocks) are compressed
-with the fast LZ4 algorithm, and binned together where possible so that
+With compression, VDO compresses multiple blocks (or shared blocks)
+with the fast LZ4 algorithm, and bins them together where possible so that
multiple compressed blocks fit within a 4 KB block on the underlying
storage. Mapping from LBA is to a physical block address and index within
it for the desired compressed data. All compressed blocks are individually
@@ -39,65 +36,55 @@ allocated for storing the new block data to ensure that other logical
block addresses that are mapped to the shared physical block are not
modified.
-For usage of VDO with \fBlvm\fP(8) standard VDO userspace tools
-\fBvdoformat\fP(8) and currently non-standard kernel VDO module
-"\fIkvdo\fP" needs to be installed on the system.
+To use VDO with \fBlvm\fP(8), you must install the standard VDO user-space tools
+\fBvdoformat\fP(8) and the currently non-standard kernel VDO module
+"\fIkvdo\fP".
The "\fIkvdo\fP" module implements fine-grained storage virtualization,
-thin provisioning, block sharing, and compression;
-the "\fIuds\fP" module provides memory-efficient duplicate
-identification. The userspace tools include \fBvdostats\fP(8)
-for extracting statistics from those volumes.
-
-
-.SH VDO Terms
-
+thin provisioning, block sharing, and compression.
+The "\fIuds\fP" module provides memory-efficient duplicate
+identification. The user-space tools include \fBvdostats\fP(8)
+for extracting statistics from VDO volumes.
+.SH VDO TERMS
.TP
VDODataLV
.br
VDO data LV
.br
-large hidden LV with suffix _vdata created in a VG.
+A large hidden LV with the _vdata suffix. It is created in a VG
.br
-used by VDO target to store all data and metadata blocks.
-
+used by the VDO kernel target to store all data and metadata blocks.
.TP
VDOPoolLV
.br
VDO pool LV
.br
-maintains virtual for LV(s) stored in attached VDO data LV
-and it has same size.
+A pool for virtual VDOLV(s) with the size of used VDODataLV.
.br
-contains VDOLV(s) (currently supports only a single VDOLV).
-
+Only a single VDOLV is currently supported.
.TP
VDOLV
.br
VDO LV
.br
-created from VDOPoolLV
+Created from VDOPoolLV.
.br
-appears blank after creation
-
-.SH VDO Usage
-
+Appears blank after creation.
+.SH VDO USAGE
The primary methods for using VDO with lvm2:
-
.SS 1. Create VDOPoolLV with VDOLV
-
-Create an VDOPoolLV that will holds VDO data together with
-virtual size VDOLV, that user can use. When the virtual size
-is not specified, then such LV is created with maximum size that
-always fits into data volume even if there cannot happen any
-deduplication and compression
-(i.e. it can hold uncompressible content of /dev/urandom).
-When the name of VDOPoolLV is not specified, it tales name from
-sequence of vpool0, vpool1 ...
-
-Note: As the performance of TRIM/Discard operation is slow for large
-volumes of VDO type, please try to avoid sending discard requests unless
-necessary as it may take considerable amount of time to finish discard
+Create a VDOPoolLV that will hold VDO data, and a
+virtual size VDOLV that the user can use. If you do not specify the virtual size,
+then the VDOLV is created with the maximum size that
+always fits into data volume even if no
+deduplication or compression can happen
+(i.e. it can hold the incompressible content of /dev/urandom).
+If you do not specify the name of VDOPoolLV, it is taken from
+the sequence of vpool0, vpool1 ...
+
+Note: The performance of TRIM/Discard operations is slow for large
+volumes of VDO type. Please try to avoid sending discard requests unless
+necessary because it might take considerable amount of time to finish the discard
operation.
.nf
@@ -106,22 +93,19 @@ operation.
.fi
.I Example
-.br
.nf
# lvcreate --type vdo -n vdo0 -L 10G -V 100G vg/vdopool0
# mkfs.ext4 -E nodiscard /dev/vg/vdo0
.fi
-
-.SS 2. Create VDOPoolLV and convert existing LV into VDODataLV
-
-Convert an already created/existing LV into a volume that can hold
-VDO data and metadata (a volume reference by VDOPoolLV).
-User will be prompted to confirm such conversion as it is \fBIRREVERSIBLY
-DESTROYING\fP content of such volume, as it's being immediately
-formatted by \fBvdoformat\fP(8) as VDO pool data volume. User can
-specify virtual size of associated VDOLV with this VDOPoolLV.
-When the virtual size is not specified, it will set to the maximum size
-that can keep 100% uncompressible data there.
+.SS 2. Create VDOPoolLV from conversion of an existing LV into VDODataLV
+Convert an already created or existing LV into a volume that can hold
+VDO data and metadata (volume referenced by VDOPoolLV).
+You will be prompted to confirm such conversion because it \fBIRREVERSIBLY
+DESTROYS\fP the content of such volume and the volume is immediately
+formatted by \fBvdoformat\fP(8) as a VDO pool data volume. You can
+specify the virtual size of the VDOLV associated with this VDOPoolLV.
+If you do not specify the virtual size, it will be set to the maximum size
+that can keep 100% incompressible data there.
.nf
.B lvconvert --type vdo-pool -n VDOLV -V VirtualSize VG/VDOPoolLV
@@ -129,23 +113,20 @@ that can keep 100% uncompressible data there.
.fi
.I Example
-.br
.nf
-# lvconvert --type vdo-pool -n vdo0 -V10G vg/existinglv
+# lvconvert --type vdo-pool -n vdo0 -V10G vg/ExistingLV
.fi
-
-.SS 3. Change default setting used for creating VDOPoolLV
-
-VDO allows to set large variety of option. Lots of these setting
-can be specified by lvm.conf or profile settings. User can prepare
-number of different profiles and just specify profile file name.
-Check output of \fBlvmconfig --type full\fP for detailed description
-of all individual vdo settings.
+.SS 3. Change the default settings used for creating a VDOPoolLV
+VDO allows to set a large variety of options. Lots of these settings
+can be specified in lvm.conf or profile settings. You can prepare
+a number of different profiles in the #DEFAULT_SYS_DIR#/profile directory
+and just specify the profile file name.
+Check the output of \fBlvmconfig --type full\fP for a detailed description
+of all individual VDO settings.
.I Example
-.br
.nf
-# cat <<EOF > vdo.profile
+# cat <<EOF > #DEFAULT_SYS_DIR#/profile/vdo_create.profile
allocation {
vdo_use_compression=1
vdo_use_deduplication=1
@@ -169,13 +150,11 @@ allocation {
}
EOF
-# lvcreate --vdo -L10G --metadataprofile vdo.profile vg/vdopool0
+# lvcreate --vdo -L10G --metadataprofile vdo_create vg/vdopool0
# lvcreate --vdo -L10G --config 'allocation/vdo_cpu_threads=4' vg/vdopool1
.fi
-
-.SS 4. Change compression and deduplication of VDOPoolLV
-
-Disable or enable compression and deduplication for VDO pool LV
+.SS 4. Change the compression and deduplication of a VDOPoolLV
+Disable or enable the compression and deduplication for VDOPoolLV
(the volume that maintains all VDO LV(s) associated with it).
.nf
@@ -183,24 +162,20 @@ Disable or enable compression and deduplication for VDO pool LV
.fi
.I Example
-.br
.nf
-# lvchange --compression n vg/vdpool0
-# lvchange --deduplication y vg/vdpool1
+# lvchange --compression n vg/vdopool0
+# lvchange --deduplication y vg/vdopool1
.fi
-
-.SS 4. Checking usage of VDOPoolLV
-
-To quickly check how much data of VDOPoolLV are already consumed
-use \fBlvs\fP(8). Field Data% will report how much data occupies
-content of virtual data for VDOLV and how much space is already
-consumed with all the data and metadata blocks in VDOPoolLV.
-For a detailed description use \fBvdostats\fP(8) command.
+.SS 5. Checking the usage of VDOPoolLV
+To quickly check how much data on a VDOPoolLV is already consumed,
+use \fBlvs\fP(8). The Data% field reports how much data is occupied
+in the content of the virtual data for the VDOLV and how much space is already
+consumed with all the data and metadata blocks in the VDOPoolLV.
+For a detailed description, use the \fBvdostats\fP(8) command.
Note: \fBvdostats\fP(8) currently understands only /dev/mapper device names.
.I Example
-.br
.nf
# lvcreate --type vdo -L10G -V20G -n vdo0 vg/vdopool0
# mkfs.ext4 -E nodiscard /dev/vg/vdo0
@@ -211,40 +186,43 @@ Note: \fBvdostats\fP(8) currently understands only /dev/mapper device names.
vdopool0 vg dwi-ao---- 10.00g 30.16
[vdopool0_vdata] vg Dwi-ao---- 10.00g
-# vdostats --all /dev/mapper/vg-vdopool0
+# vdostats --all /dev/mapper/vg-vdopool0-vpool
/dev/mapper/vg-vdopool0 :
version : 30
release version : 133524
data blocks used : 79
...
.fi
+.SS 6. Extending the VDOPoolLV size
+You can add more space to hold VDO data and metadata by
+extending the VDODataLV using the commands
+\fBlvresize\fP(8) and \fBlvextend\fP(8).
+The extension needs to add at least one new VDO slab. You can configure
+the slab size with the \fBallocation/vdo_slab_size_mb\fP setting.
-.SS 4. Extending VDOPoolLV size
+You can also enable automatic size extension of a monitored VDOPoolLV
+with the \fBactivation/vdo_pool_autoextend_percent\fP and
+\fBactivation/vdo_pool_autoextend_threshold\fP settings.
-Adding more space to hold VDO data and metadata can be made via
-extension of VDODataLV with commands
-\fBlvresize\fP(8), \fBlvextend\fP(8).
+Note: You cannot reduce the size of a VDOPoolLV.
-Note: Size of VDOPoolLV cannot be reduced.
+Note: You cannot change the size of a cached VDOPoolLV.
.nf
.B lvextend -L+AddingSize VG/VDOPoolLV
.fi
.I Example
-.br
.nf
# lvextend -L+50G vg/vdopool0
# lvresize -L300G vg/vdopool1
.fi
+.SS 7. Extending or reducing the VDOLV size
+You can extend or reduce a virtual VDO LV as a standard LV with the
+\fBlvresize\fP(8), \fBlvextend\fP(8), and \fBlvreduce\fP(8) commands.
-.SS 4. Extending or reducing VDOLV size
-
-VDO LV can be extended or reduced as standard LV with commands
-\fBlvresize\fP(8), \fBlvextend\fP(8), \fBlvreduce\fP(8).
-
-Note: Reduction needs to process TRIM for reduced disk area
-to unmap used data blocks from VDOPoolLV and it may take
+Note: The reduction needs to process TRIM for reduced disk area
+to unmap used data blocks from the VDOPoolLV, which might take
a long time.
.nf
@@ -253,74 +231,121 @@ a long time.
.fi
.I Example
-.br
.nf
# lvextend -L+50G vg/vdo0
# lvreduce -L-50G vg/vdo1
# lvresize -L200G vg/vdo2
.fi
-
-.SS 5. Component activation of VDODataLV
-
-VDODataLV can be activated separately as component LV for examination
-purposes. It activates data LV in read-only mode and cannot be modified.
-If the VDODataLV is active as component, any upper LV using this volume CANNOT
-be activated. User has to deactivate VDODataLV first to continue to use VDOPoolLV.
+.SS 8. Component activation of a VDODataLV
+You can activate a VDODataLV separately as a component LV for examination
+purposes. It activates the data LV in read-only mode, and the data LV cannot be modified.
+If the VDODataLV is active as a component, any upper LV using this volume CANNOT
+be activated. You have to deactivate the VDODataLV first to continue to use the VDOPoolLV.
.I Example
-.br
.nf
# lvchange -ay vg/vpool0_vdata
# lvchange -an vg/vpool0_vdata
.fi
-
-
-.SH VDO Topics
-
+.SH VDO TOPICS
.SS 1. Stacking VDO
-
-User can convert/stack VDO with existing volumes.
-
-.SS 2. VDO on top of raid
-
-Using Raid type LV for VDO Data LV.
+You can convert or stack a VDOPooLV with these currently supported
+volume types: linear, stripe, raid, and cache with cachepool.
+.SS 2. VDOPoolLV on top of raid
+Using a raid type LV for a VDODataLV.
.I Example
-.br
.nf
-# lvcreate --type raid1 -L 5G -n vpool vg
-# lvconvert --type vdo-pool -V 10G vg/vpool
+# lvcreate --type raid1 -L 5G -n vdopool vg
+# lvconvert --type vdo-pool -V 10G vg/vdopool
.fi
+.SS 3. Caching a VDODataLV or a VDOPoolLV
+VDODataLV (accepts also VDOPoolLV) caching provides a mechanism
+to accelerate reads and writes of already compressed and deduplicated
+data blocks together with VDO metadata.
-.SS 3. Caching VDODataLV, VDOPoolLV
-
-Cache VDO Data LV (accepts also VDOPoolLV.
+A cached VDO data LV cannot be currently resized. Also, the threshold
+based automatic resize will not work.
.I Example
-.br
.nf
-# lvcreate -L 5G -V 10G -n vdo1 vg/vpool
-# lvcreate --type cache-pool -L 1G -n cpool vg
-# lvconvert --cache --cachepool vg/cpool vg/vpool
-# lvconvert --uncache vg/vpool
+# lvcreate --type vdo -L 5G -V 10G -n vdo1 vg/vdopool
+# lvcreate --type cache-pool -L 1G -n cachepool vg
+# lvconvert --cache --cachepool vg/cachepool vg/vdopool
+# lvconvert --uncache vg/vdopool
.fi
-
-.SS 3. Caching VDOLV
-
-Cache VDO LV.
+.SS 4. Caching a VDOLV
+VDO LV cache allow you to 'cache' a device for better performance before
+it hits the processing of the VDO Pool LV layer.
.I Example
-.br
.nf
-# lvcreate -L 5G -V 10G -n vdo1 vg/vpool
-# lvcreate --type cache-pool -L 1G -n cpool vg
-# lvconvert --cache --cachepool vg/cpool vg/vdo1
+# lvcreate -L 5G -V 10G -n vdo1 vg/vdopool
+# lvcreate --type cache-pool -L 1G -n cachepool vg
+# lvconvert --cache --cachepool vg/cachepool vg/vdo1
# lvconvert --uncache vg/vdo1
.fi
-
-.br
-
-\&
+.SS 5. Usage of Discard/TRIM with a VDOLV
+You can discard data on a VDO LV and reduce used blocks on a VDOPoolLV.
+However, the current performance of discard operations is still not optimal
+and takes a considerable amount of time and CPU.
+Unless you really need it, you should avoid using discard.
+
+When a block device is going to be rewritten,
+block will be automatically reused for new data.
+Discard is useful in situations when it is known that the given portion of a VDO LV
+is not going to be used and the discarded space can be used for block
+provisioning in other regions of the VDO LV.
+For the same reason, you should avoid using mkfs with discard for
+a freshly created VDO LV to save a lot of time that this operation would
+take otherwise as device after create empty.
+.SS 6. Memory usage
+The VDO target requires 370 MiB of RAM plus an additional 268 MiB
+per each 1 TiB of physical storage managed by the volume.
+
+UDS requires a minimum of 250 MiB of RAM,
+which is also the default amount that deduplication uses.
+
+The memory required for the UDS index is determined by the index type
+and the required size of the deduplication window and
+is controlled by the \fBallocation/vdo_use_sparse_index\fP setting.
+
+With enabled UDS sparse indexing, it relies on the temporal locality of data
+and attempts to retain only the most relevant index entries in memory and
+can maintain a deduplication window that is ten times larger
+than with dense while using the same amount of memory.
+
+Although the sparse index provides the greatest coverage,
+the dense index provides more deduplication advice.
+For most workloads, given the same amount of memory,
+the difference in deduplication rates between dense
+and sparse indexes is negligible.
+
+A dense index with 1 GiB of RAM maintains a 1 TiB deduplication window,
+while a sparse index with 1 GiB of RAM maintains a 10 TiB deduplication window.
+In general, 1 GiB is sufficient for 4 TiB of physical space with
+a dense index and 40 TiB with a sparse index.
+.SS 7. Storage space requirements
+You can configure a VDOPoolLV to use up to 256 TiB of physical storage.
+Only a certain part of the physical storage is usable to store data.
+This section provides the calculations to determine the usable size
+of a VDO-managed volume.
+
+The VDO target requires storage for two types of VDO metadata and for the UDS index:
+.TP
+\(bu
+The first type of VDO metadata uses approximately 1 MiB for each 4 GiB
+of physical storage plus an additional 1 MiB per slab.
+.TP
+\(bu
+The second type of VDO metadata consumes approximately 1.25 MiB
+for each 1 GiB of logical storage, rounded up to the nearest slab.
+.TP
+\(bu
+The amount of storage required for the UDS index depends on the type of index
+and the amount of RAM allocated to the index. For each 1 GiB of RAM,
+a dense UDS index uses 17 GiB of storage and a sparse UDS index will use
+170 GiB of storage.
.SH SEE ALSO
.BR lvm (8),

View File

@ -1,83 +0,0 @@
man/lvmvdo.7_main | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/man/lvmvdo.7_main b/man/lvmvdo.7_main
index 39dee39..474d6dd 100644
--- a/man/lvmvdo.7_main
+++ b/man/lvmvdo.7_main
@@ -16,7 +16,7 @@ and also eliminates any blocks of all zeroes.
With deduplication, instead of writing the same data more than once, VDO detects and records each
duplicate block as a reference to the original
-block. VDO maintains a mapping from logical block addresses (used by the
+block. VDO maintains a mapping from Logical Block Addresses (LBA) (used by the
storage layer above VDO) to physical block addresses (used by the storage
layer under VDO). After deduplication, multiple logical block addresses
may be mapped to the same physical block address; these are called shared
@@ -59,7 +59,7 @@ VDOPoolLV
.br
VDO pool LV
.br
-A pool for virtual VDOLV(s) with the size of used VDODataLV.
+A pool for virtual VDOLV(s), which are the size of used VDODataLV.
.br
Only a single VDOLV is currently supported.
.TP
@@ -72,7 +72,7 @@ Created from VDOPoolLV.
Appears blank after creation.
.SH VDO USAGE
The primary methods for using VDO with lvm2:
-.SS 1. Create VDOPoolLV with VDOLV
+.SS 1. Create a VDOPoolLV and a VDOLV
Create a VDOPoolLV that will hold VDO data, and a
virtual size VDOLV that the user can use. If you do not specify the virtual size,
then the VDOLV is created with the maximum size that
@@ -97,9 +97,9 @@ operation.
# lvcreate --type vdo -n vdo0 -L 10G -V 100G vg/vdopool0
# mkfs.ext4 -E nodiscard /dev/vg/vdo0
.fi
-.SS 2. Create VDOPoolLV from conversion of an existing LV into VDODataLV
-Convert an already created or existing LV into a volume that can hold
-VDO data and metadata (volume referenced by VDOPoolLV).
+.SS 2. Convert an existing LV into VDOPoolLV
+Convert an already created or existing LV into a VDOPoolLV, which is a volume
+that can hold data and metadata.
You will be prompted to confirm such conversion because it \fBIRREVERSIBLY
DESTROYS\fP the content of such volume and the volume is immediately
formatted by \fBvdoformat\fP(8) as a VDO pool data volume. You can
@@ -238,7 +238,8 @@ a long time.
.fi
.SS 8. Component activation of a VDODataLV
You can activate a VDODataLV separately as a component LV for examination
-purposes. It activates the data LV in read-only mode, and the data LV cannot be modified.
+purposes. The activation of the VDODataLV activates the data LV in read-only mode,
+and the data LV cannot be modified.
If the VDODataLV is active as a component, any upper LV using this volume CANNOT
be activated. You have to deactivate the VDODataLV first to continue to use the VDOPoolLV.
@@ -280,7 +281,7 @@ it hits the processing of the VDO Pool LV layer.
.I Example
.nf
-# lvcreate -L 5G -V 10G -n vdo1 vg/vdopool
+# lvcreate --type vdo -L 5G -V 10G -n vdo1 vg/vdopool
# lvcreate --type cache-pool -L 1G -n cachepool vg
# lvconvert --cache --cachepool vg/cachepool vg/vdo1
# lvconvert --uncache vg/vdo1
@@ -292,13 +293,13 @@ and takes a considerable amount of time and CPU.
Unless you really need it, you should avoid using discard.
When a block device is going to be rewritten,
-block will be automatically reused for new data.
-Discard is useful in situations when it is known that the given portion of a VDO LV
+its blocks will be automatically reused for new data.
+Discard is useful in situations when user knows that the given portion of a VDO LV
is not going to be used and the discarded space can be used for block
provisioning in other regions of the VDO LV.
For the same reason, you should avoid using mkfs with discard for
a freshly created VDO LV to save a lot of time that this operation would
-take otherwise as device after create empty.
+take otherwise as device is already expected to be empty.
.SS 6. Memory usage
The VDO target requires 370 MiB of RAM plus an additional 268 MiB
per each 1 TiB of physical storage managed by the volume.

View File

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

View File

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

View File

@ -0,0 +1,107 @@
lib/metadata/cache_manip.c | 40 ++++++++++++++--------------------------
lib/metadata/metadata-exported.h | 1 +
tools/lvconvert.c | 1 +
tools/lvcreate.c | 1 +
4 files changed, 17 insertions(+), 26 deletions(-)
diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
index 2c4cc92..90ebd94 100644
--- a/lib/metadata/cache_manip.c
+++ b/lib/metadata/cache_manip.c
@@ -204,6 +204,7 @@ int update_cache_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
int *chunk_size_calc_method, uint32_t *chunk_size)
{
uint64_t min_meta_size;
@@ -252,39 +253,26 @@ int update_cache_pool_params(struct cmd_context *cmd,
if (!validate_cache_chunk_size(cmd, *chunk_size))
return_0;
- min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
+ if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
+ log_error("Size of %s data volume cannot be smaller than chunk size %s.",
+ segtype->name, display_size(cmd, *chunk_size));
+ return 0;
+ }
- /* Round up to extent size */
- if (min_meta_size % extent_size)
- min_meta_size += extent_size - min_meta_size % extent_size;
+ min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
+ min_meta_size = dm_round_up(min_meta_size, extent_size);
if (!pool_metadata_size)
pool_metadata_size = min_meta_size;
- if (pool_metadata_size > (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE)) {
- pool_metadata_size = 2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE;
- if (*pool_metadata_extents)
- log_warn("WARNING: Maximum supported pool metadata size is %s.",
- display_size(cmd, pool_metadata_size));
- } else if (pool_metadata_size < min_meta_size) {
- if (*pool_metadata_extents)
- log_warn("WARNING: Minimum required pool metadata size is %s "
- "(needs extra %s).",
- display_size(cmd, min_meta_size),
- display_size(cmd, min_meta_size - pool_metadata_size));
- pool_metadata_size = min_meta_size;
- }
-
- if (!(*pool_metadata_extents =
- extents_from_size(cmd, pool_metadata_size, extent_size)))
+ if (!update_pool_metadata_min_max(cmd, extent_size,
+ min_meta_size,
+ (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE),
+ &pool_metadata_size,
+ metadata_lv,
+ pool_metadata_extents))
return_0;
- if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
- log_error("Size of %s data volume cannot be smaller than chunk size %s.",
- segtype->name, display_size(cmd, *chunk_size));
- return 0;
- }
-
log_verbose("Preferred pool metadata size %s.",
display_size(cmd, (uint64_t)*pool_metadata_extents * extent_size));
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 0e57722..c0fa564 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1319,6 +1319,7 @@ int update_cache_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
int *chunk_size_calc_method, uint32_t *chunk_size);
int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size);
int validate_lv_cache_create_pool(const struct logical_volume *pool_lv);
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index ce90279..416e8a7 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -3189,6 +3189,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
pool_segtype, target_attr,
lv->le_count,
&meta_extents,
+ metadata_lv,
&chunk_calc,
&chunk_size))
goto_bad;
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 1ee9e14..1ce561f 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -403,6 +403,7 @@ static int _update_extents_params(struct volume_group *vg,
lp->segtype, lp->target_attr,
lp->extents,
&lp->pool_metadata_extents,
+ NULL,
&lp->thin_chunk_size_calc_policy,
&lp->chunk_size))
return_0;

View File

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

View File

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

View File

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

View File

@ -0,0 +1,16 @@
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,22 @@
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

View File

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

View File

@ -0,0 +1,39 @@
lib/metadata/pool_manip.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index b67882e..1975cb4 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -697,6 +697,8 @@ static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg
int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
struct dm_list *pvh, int poolmetadataspare)
{
+ /* Max usable size of any spare volume is currently 16GiB rouned to extent size */
+ const uint64_t MAX_SIZE = (UINT64_C(2 * 16) * 1024 * 1024 + vg->extent_size - 1) / vg->extent_size;
struct logical_volume *lv = vg->pool_metadata_spare_lv;
uint32_t seg_mirrors;
struct lv_segment *seg;
@@ -706,8 +708,11 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
/* Find maximal size of metadata LV */
dm_list_iterate_items(lvl, &vg->lvs)
if (lv_is_pool_metadata(lvl->lv) &&
- (lvl->lv->le_count > extents))
+ (lvl->lv->le_count > extents)) {
extents = lvl->lv->le_count;
+ if (extents >= MAX_SIZE)
+ break;
+ }
if (!poolmetadataspare) {
/* TODO: Not showing when lvm.conf would define 'n' ? */
@@ -718,6 +723,9 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
return 1;
}
+ if (extents > MAX_SIZE)
+ extents = MAX_SIZE;
+
if (!lv) {
if (!_alloc_pool_metadata_spare(vg, extents, pvh))
return_0;

View File

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

View File

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

View File

@ -0,0 +1,98 @@
test/shell/thin-16g.sh | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 test/shell/thin-16g.sh
diff --git a/test/shell/thin-16g.sh b/test/shell/thin-16g.sh
new file mode 100644
index 0000000..ee7e22e
--- /dev/null
+++ b/test/shell/thin-16g.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+# Test usability of 16g thin pool metadata LV
+
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux have_thin 1 0 0 || skip
+
+aux prepare_vg 1 50000
+
+lvcreate -T -L10 --poolmetadatasize 16g $vg/pool
+check lv_field $vg/pool_tmeta size "<15.88g"
+lvremove -f $vg
+
+# Cropped way
+lvcreate -T -L10 --poolmetadatasize 16g --config 'allocation/thin_pool_crop_metadata=1' $vg/pool
+check lv_field $vg/pool_tmeta size "15.81g"
+lvremove -f $vg
+
+lvcreate -L16G -n meta $vg
+lvcreate -L10 -n pool $vg
+lvconvert --yes --thinpool $vg/pool --poolmetadata meta
+# Uncropped size 33554432 sectors - 16GiB
+dmsetup table ${vg}-pool_tmeta | grep 33554432
+lvremove -f $vg
+
+# Uses 20G metadata volume, but crops the size in DM table
+lvcreate -L20G -n meta $vg
+lvcreate -L10 -n pool $vg
+lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1'
+check lv_field $vg/lvol0_pmspare size "16.00g"
+# Size should be cropped to 33161216 sectors ~15.81GiB
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+
+# Also size remains unchanged with activation has no cropping,
+# but metadata have no CROP_METADATA flag set
+lvchange -an $vg
+lvchange -ay $vg
+# Size still stays cropped to 33161216 sectors ~15.81GiB
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+lvremove -f $vg
+
+# Minimal size is 2M
+lvcreate -L1M -n meta $vg
+lvcreate -L10 -n pool $vg
+not lvconvert --yes --thinpool $vg/pool --poolmetadata meta
+lvremove -f $vg
+
+# Uses 20G metadata volume, but crops the size in DM table
+lvcreate -L1 --poolmetadatasize 10G -T $vg/pool
+lvresize -L+10G $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1'
+check lv_field $vg/lvol0_pmspare size "15.81g"
+# Size should be cropped to 33161216 sectors ~15.81GiB
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+
+# Without cropping we can grop to ~15.88GiB
+lvresize -L+10G $vg/pool_tmeta
+check lv_field $vg/lvol0_pmspare size "<15.88g"
+lvremove -f $vg
+
+# User has already 'bigger' metadata and wants them uncropped
+lvcreate -L16G -n meta $vg
+lvcreate -L10 -n pool $vg
+lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1'
+
+# No change with cropping
+lvresize -l+1 $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1'
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+
+# Resizes to 'uncropped' size 16GiB with ANY size
+lvresize -l+1 $vg/pool_tmeta
+dmsetup table ${vg}-pool_tmeta | grep 33554432
+check lv_field $vg/pool_tmeta size "16.00g"
+
+vgremove -ff $vg

View File

@ -0,0 +1,78 @@
test/shell/thin-zero-meta.sh | 68 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
create mode 100644 test/shell/thin-zero-meta.sh
diff --git a/test/shell/thin-zero-meta.sh b/test/shell/thin-zero-meta.sh
new file mode 100644
index 0000000..6a15a73
--- /dev/null
+++ b/test/shell/thin-zero-meta.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+# Test how zeroing of thin-pool metadata works
+
+SKIP_WITH_LVMLOCKD=1
+SKIP_WITH_LVMPOLLD=1
+
+export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false}
+
+. lib/inittest
+
+#
+# Main
+#
+aux have_thin 1 3 0 || skip
+aux have_cache 1 3 0 || skip
+
+aux prepare_vg 3 40000
+
+# Create mostly-zero devs only front of it has some 'real' back-end
+aux zero_dev "$dev1" "$(( $(get first_extent_sector "$dev1") + 8192 )):"
+aux zero_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 8192 )):"
+aux zero_dev "$dev3" "$(( $(get first_extent_sector "$dev3") + 8192 )):"
+
+# Prepare randomly filled 4M LV on dev2
+lvcreate -L16G -n $lv1 $vg "$dev2"
+dd if=/dev/urandom of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=4 oflag=direct || true
+lvremove -f $vg
+
+for i in 0 1
+do
+ aux lvmconf "allocation/zero_metadata = $i"
+
+ # Lvm2 should allocate metadata on dev2
+ lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2"
+ lvchange -an $vg
+
+ lvs -ao+seg_pe_ranges $vg
+ lvchange -ay $vg/pool_tmeta --yes
+
+ # Skip past 1.2M which is 'created' by thin-pool initialization
+ hexdump -C -n 200 -s 2000000 "$DM_DEV_DIR/$vg/pool_tmeta" | tee out
+
+ # When fully zeroed, it should be zero - so almost no output from hexdump
+ case "$i" in
+ 0) test $(wc -l < out) -ge 10 ;; # should not be zeroed
+ 1) test $(wc -l < out) -le 10 ;; # should be zeroed
+ esac
+
+ lvremove -f $vg/pool
+done
+
+# Check lvm2 spots error during full zeroing of metadata device
+aux error_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 32 )):"
+not lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2" |& tee err
+grep "Failed to initialize logical volume" err
+
+vgremove -ff $vg

View File

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

View File

@ -0,0 +1,61 @@
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

View File

@ -0,0 +1,77 @@
test/shell/lvconvert-thin.sh | 2 +-
test/shell/lvcreate-cache.sh | 12 +++++-------
test/shell/lvcreate-thin-big.sh | 10 +++++-----
3 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/test/shell/lvconvert-thin.sh b/test/shell/lvconvert-thin.sh
index 1319655..ee85691 100644
--- a/test/shell/lvconvert-thin.sh
+++ b/test/shell/lvconvert-thin.sh
@@ -128,7 +128,7 @@ lvcreate -L1T -n $lv1 $vg
lvcreate -L32G -n $lv2 $vg
# Warning about bigger then needed
lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 2>&1 | tee err
-grep "WARNING: Maximum" err
+grep -i "maximum" err
lvremove -f $vg
diff --git a/test/shell/lvcreate-cache.sh b/test/shell/lvcreate-cache.sh
index 2c46e21..4d9d75e 100644
--- a/test/shell/lvcreate-cache.sh
+++ b/test/shell/lvcreate-cache.sh
@@ -27,7 +27,6 @@ aux prepare_vg 5 80000
aux lvmconf 'global/cache_disabled_features = [ "policy_smq" ]'
-
#######################
# Cache_Pool creation #
#######################
@@ -173,17 +172,16 @@ dmsetup table ${vg}-$lv1 | grep cache # ensure it is loaded in kernel
lvremove -f $vg
-
# Check minimum cache pool metadata size
-lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>out
-grep "WARNING: Minimum" out
+lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>&1 | tee out
+grep -i "minimal" out
+
# FIXME: This test is failing in allocator with smaller VG sizes
-lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>out
-grep "WARNING: Maximum" out
+lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>&1 | tee out
+grep -i "maximum" out
lvremove -f $vg
-
########################################
# Cache conversion and r/w permissions #
########################################
diff --git a/test/shell/lvcreate-thin-big.sh b/test/shell/lvcreate-thin-big.sh
index 0b622b7..2549035 100644
--- a/test/shell/lvcreate-thin-big.sh
+++ b/test/shell/lvcreate-thin-big.sh
@@ -31,14 +31,14 @@ vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}"
# Size 0 is not valid
invalid lvcreate -L4M --chunksize 128 --poolmetadatasize 0 -T $vg/pool1 2>out
-lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 2>out
-grep "WARNING: Minimum" out
+lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 2>&1 >out
+grep -i "minimal" out
# FIXME: metadata allocation fails, if PV doesn't have at least 16GB
# i.e. pool metadata device cannot be multisegment
-lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>out
-grep "WARNING: Maximum" out
+lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>&1 >out
+grep "maximum" out
check lv_field $vg/pool1_tmeta size "2.00m"
-check lv_field $vg/pool2_tmeta size "15.81g"
+check lv_field $vg/pool2_tmeta size "<15.88g"
# Check we do report correct percent values.
lvcreate --type zero -L3G $vg -n pool3

View File

@ -0,0 +1,694 @@
conf/example.conf.in | 7 +++
device_mapper/all.h | 16 +++++--
device_mapper/libdm-deptree.c | 39 ++++++++++++-----
lib/activate/dev_manager.c | 8 ++--
lib/config/config_settings.h | 5 +++
lib/config/defaults.h | 2 +
lib/format_text/flags.c | 1 +
lib/metadata/lv_manip.c | 31 ++++++++++++++
lib/metadata/merge.c | 2 +
lib/metadata/metadata-exported.h | 11 +++++
lib/metadata/metadata.h | 13 ++++++
lib/metadata/pool_manip.c | 46 ++++++++++++++++++++
lib/metadata/thin_manip.c | 92 ++++++++++++++++++++++++++--------------
lib/thin/thin.c | 22 +++++++---
man/lvmthin.7_main | 10 ++++-
tools/lvconvert.c | 4 ++
tools/lvcreate.c | 2 +
17 files changed, 256 insertions(+), 55 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index d149ed9..107a071 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -494,6 +494,13 @@ allocation {
# This configuration option has an automatic default value.
# thin_pool_metadata_require_separate_pvs = 0
+ # Configuration option allocation/thin_pool_crop_metadata.
+ # Older version of lvm2 cropped pool's metadata size to 15.81 GiB.
+ # This is slightly less then the actual maximum 15.88 GiB.
+ # For compatibility with older version and use of cropped size set to 1.
+ # This configuration option has an automatic default value.
+ # thin_pool_crop_metadata = 0
+
# Configuration option allocation/thin_pool_zero.
# Thin pool data chunks are zeroed before they are first used.
# Zeroing with a larger thin pool chunk size reduces performance.
diff --git a/device_mapper/all.h b/device_mapper/all.h
index 1080d25..489ca1c 100644
--- a/device_mapper/all.h
+++ b/device_mapper/all.h
@@ -1072,10 +1072,10 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
#define DM_THIN_MIN_DATA_BLOCK_SIZE (UINT32_C(128))
#define DM_THIN_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152))
/*
- * Max supported size for thin pool metadata device (17112760320 bytes)
- * Limitation is hardcoded into the kernel and bigger device size
- * is not accepted.
+ * Max supported size for thin pool metadata device (17045913600 bytes)
* drivers/md/dm-thin-metadata.h THIN_METADATA_MAX_SECTORS
+ * But here DM_THIN_MAX_METADATA_SIZE got defined incorrectly
+ * Correct size is (UINT64_C(255) * ((1 << 14) - 64) * (4096 / (1 << 9)))
*/
#define DM_THIN_MAX_METADATA_SIZE (UINT64_C(255) * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024)
@@ -1088,6 +1088,16 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint64_t low_water_mark,
unsigned skip_block_zeroing);
+int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
+ uint64_t size,
+ uint64_t transaction_id,
+ const char *metadata_uuid,
+ const char *pool_uuid,
+ uint32_t data_block_size,
+ uint64_t low_water_mark,
+ unsigned skip_block_zeroing,
+ unsigned crop_metadata);
+
/* Supported messages for thin provision target */
typedef enum {
DM_THIN_MESSAGE_CREATE_SNAP, /* device_id, origin_id */
diff --git a/device_mapper/libdm-deptree.c b/device_mapper/libdm-deptree.c
index 6ce956f..5b60dc9 100644
--- a/device_mapper/libdm-deptree.c
+++ b/device_mapper/libdm-deptree.c
@@ -3979,6 +3979,24 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint64_t low_water_mark,
unsigned skip_block_zeroing)
{
+ return dm_tree_node_add_thin_pool_target_v1(node, size, transaction_id,
+ metadata_uuid, pool_uuid,
+ data_block_size,
+ low_water_mark,
+ skip_block_zeroing,
+ 1);
+}
+
+int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
+ uint64_t size,
+ uint64_t transaction_id,
+ const char *metadata_uuid,
+ const char *pool_uuid,
+ uint32_t data_block_size,
+ uint64_t low_water_mark,
+ unsigned skip_block_zeroing,
+ unsigned crop_metadata)
+{
struct load_segment *seg, *mseg;
uint64_t devsize = 0;
@@ -4005,17 +4023,18 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
if (!_link_tree_nodes(node, seg->metadata))
return_0;
- /* FIXME: more complex target may need more tweaks */
- dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
- devsize += mseg->size;
- if (devsize > DM_THIN_MAX_METADATA_SIZE) {
- log_debug_activation("Ignoring %" PRIu64 " of device.",
- devsize - DM_THIN_MAX_METADATA_SIZE);
- mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
- devsize = DM_THIN_MAX_METADATA_SIZE;
- /* FIXME: drop remaining segs */
+ if (crop_metadata)
+ /* FIXME: more complex target may need more tweaks */
+ dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
+ devsize += mseg->size;
+ if (devsize > DM_THIN_MAX_METADATA_SIZE) {
+ log_debug_activation("Ignoring %" PRIu64 " of device.",
+ devsize - DM_THIN_MAX_METADATA_SIZE);
+ mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
+ devsize = DM_THIN_MAX_METADATA_SIZE;
+ /* FIXME: drop remaining segs */
+ }
}
- }
if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, pool_uuid))) {
log_error("Missing pool uuid %s.", pool_uuid);
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 8d27bd3..9a25482 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -261,7 +261,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
int dmtask;
int with_flush; /* TODO: arg for _info_run */
void *target = NULL;
- uint64_t target_start, target_length, start, length;
+ uint64_t target_start, target_length, start, length, length_crop = 0;
char *target_name, *target_params;
const char *devname;
@@ -297,7 +297,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
/* Uses max DM_THIN_MAX_METADATA_SIZE sectors for metadata device */
if (lv_is_thin_pool_metadata(seg_status->seg->lv) &&
(length > DM_THIN_MAX_METADATA_SIZE))
- length = DM_THIN_MAX_METADATA_SIZE;
+ length_crop = DM_THIN_MAX_METADATA_SIZE;
/* Uses virtual size with headers for VDO pool device */
if (lv_is_vdo_pool(seg_status->seg->lv))
@@ -310,7 +310,9 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
target = dm_get_next_target(dmt, target, &target_start,
&target_length, &target_name, &target_params);
- if ((start == target_start) && (length == target_length))
+ if ((start == target_start) &&
+ ((length == target_length) ||
+ (length_crop && (length_crop == target_length))))
break; /* Keep target_params when matching segment is found */
target_params = NULL; /* Marking this target_params unusable */
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 3c4032e..cb4e23a 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -628,6 +628,11 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
"Thin pool metadata and data will always use different PVs.\n")
+cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 3, 12), NULL, 0, NULL,
+ "Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
+ "This is slightly less then the actual maximum 15.88 GiB.\n"
+ "For compatibility with older version and use of cropped size set to 1.\n")
+
cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL,
"Thin pool data chunks are zeroed before they are first used.\n"
"Zeroing with a larger thin pool chunk size reduces performance.\n")
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 708a575..bcc20cc 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -118,6 +118,8 @@
#define DEFAULT_THIN_REPAIR_OPTION1 ""
#define DEFAULT_THIN_REPAIR_OPTIONS_CONFIG "#S" DEFAULT_THIN_REPAIR_OPTION1
#define DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
+#define DEFAULT_THIN_POOL_CROP_METADATA 0
+#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB (UINT64_C(255) * ((1 << 14) - 64) * 4) /* KB */ /* 0x3f8040 blocks */
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (DM_THIN_MAX_METADATA_SIZE / 2) /* KB */
#define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048 /* KB */
#define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index bc93a5d..4cee14a 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -72,6 +72,7 @@ static const struct flag _lv_flags[] = {
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
{LV_METADATA_FORMAT, "METADATA_FORMAT", SEGTYPE_FLAG},
+ {LV_CROP_METADATA, "CROP_METADATA", SEGTYPE_FLAG},
{LV_CACHE_VOL, "CACHE_VOL", COMPATIBLE_FLAG},
{LV_CACHE_USES_CACHEVOL, "CACHE_USES_CACHEVOL", SEGTYPE_FLAG},
{LV_NOSCAN, NULL, 0},
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 443d32c..445c4ad 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5384,6 +5384,8 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
uint32_t existing_extents;
uint32_t seg_size = 0;
uint32_t new_extents;
+ uint64_t max_metadata_size;
+ thin_crop_metadata_t crop;
int reducing = 0;
seg_last = last_seg(lv);
@@ -5544,6 +5546,33 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
return 1;
}
}
+ } else if (lv_is_thin_pool_metadata(lv)) {
+ if (!(seg = get_only_segment_using_this_lv(lv)))
+ return_0;
+
+ max_metadata_size = get_thin_pool_max_metadata_size(cmd, vg->profile, &crop);
+
+ if (((uint64_t)lp->extents * vg->extent_size) > max_metadata_size) {
+ lp->extents = (max_metadata_size + vg->extent_size - 1) / vg->extent_size;
+ log_print_unless_silent("Reached maximum pool metadata size %s (%" PRIu32 " extents).",
+ display_size(vg->cmd, max_metadata_size), lp->extents);
+ }
+
+ if (existing_logical_extents >= lp->extents)
+ lp->extents = existing_logical_extents;
+
+ crop = get_thin_pool_crop_metadata(cmd, crop, (uint64_t)lp->extents * vg->extent_size);
+
+ if (seg->crop_metadata != crop) {
+ seg->crop_metadata = crop;
+ seg->lv->status |= LV_CROP_METADATA;
+ /* Crop change require reload even if there no size change */
+ lp->size_changed = 1;
+ log_print_unless_silent("Thin pool will use metadata without cropping.");
+ }
+
+ if (!(seg_size = lp->extents - existing_logical_extents))
+ return 1; /* No change in metadata size */
}
} else { /* If reducing, find stripes, stripesize & size of last segment */
if (lp->stripes || lp->stripe_size || lp->mirrors)
@@ -8388,6 +8417,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
first_seg(lv)->chunk_size = lp->chunk_size;
first_seg(lv)->zero_new_blocks = lp->zero_new_blocks;
first_seg(lv)->discards = lp->discards;
+ if ((first_seg(lv)->crop_metadata = lp->crop_metadata) == THIN_CROP_METADATA_NO)
+ lv->status |= LV_CROP_METADATA;
if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->thin_chunk_size_calc_policy)) {
stack;
goto revert_new_lv;
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 0aa2293..eff59ae 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -495,6 +495,8 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
seg_error("sets discards");
if (!dm_list_empty(&seg->thin_messages))
seg_error("sets thin_messages list");
+ if (seg->lv->status & LV_CROP_METADATA)
+ seg_error("sets CROP_METADATA flag");
}
if (seg_is_thin_volume(seg)) {
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 54dc29f..0e57722 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -143,6 +143,7 @@
#define LV_REMOVE_AFTER_RESHAPE UINT64_C(0x0400000000000000) /* LV needs to be removed after a shrinking reshape */
#define LV_METADATA_FORMAT UINT64_C(0x0800000000000000) /* LV has segments with metadata format */
+#define LV_CROP_METADATA UINT64_C(0x0000000000000400) /* LV - also VG CLUSTERED */
#define LV_RESHAPE UINT64_C(0x1000000000000000) /* Ongoing reshape (number of stripes, stripesize or raid algorithm change):
used as SEGTYPE_FLAG to prevent activation on old runtime */
@@ -326,6 +327,12 @@ typedef enum {
} thin_discards_t;
typedef enum {
+ THIN_CROP_METADATA_UNSELECTED = 0, /* 'auto' selects */
+ THIN_CROP_METADATA_NO,
+ THIN_CROP_METADATA_YES,
+} thin_crop_metadata_t;
+
+typedef enum {
CACHE_MODE_UNSELECTED = 0,
CACHE_MODE_WRITETHROUGH,
CACHE_MODE_WRITEBACK,
@@ -502,6 +509,7 @@ struct lv_segment {
uint64_t transaction_id; /* For thin_pool, thin */
thin_zero_t zero_new_blocks; /* For thin_pool */
thin_discards_t discards; /* For thin_pool */
+ thin_crop_metadata_t crop_metadata; /* For thin_pool */
struct dm_list thin_messages; /* For thin_pool */
struct logical_volume *external_lv; /* For thin */
struct logical_volume *pool_lv; /* For thin, cache */
@@ -885,6 +893,8 @@ int update_thin_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
+ unsigned *crop_metadata,
int *chunk_size_calc_method, uint32_t *chunk_size,
thin_discards_t *discards, thin_zero_t *zero_new_blocks);
@@ -1011,6 +1021,7 @@ struct lvcreate_params {
uint64_t permission; /* all */
unsigned error_when_full; /* when segment supports it */
+ thin_crop_metadata_t crop_metadata;
uint32_t read_ahead; /* all */
int approx_alloc; /* all */
alloc_policy_t alloc; /* all */
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 2c22450..0f230e4 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -512,8 +512,21 @@ int pool_below_threshold(const struct lv_segment *pool_seg);
int pool_check_overprovisioning(const struct logical_volume *lv);
int create_pool(struct logical_volume *pool_lv, const struct segment_type *segtype,
struct alloc_handle *ah, uint32_t stripes, uint32_t stripe_size);
+uint64_t get_thin_pool_max_metadata_size(struct cmd_context *cmd, struct profile *profile,
+ thin_crop_metadata_t *crop);
+thin_crop_metadata_t get_thin_pool_crop_metadata(struct cmd_context *cmd,
+ thin_crop_metadata_t crop,
+ uint64_t metadata_size);
uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size);
+int update_pool_metadata_min_max(struct cmd_context *cmd,
+ uint32_t extent_size,
+ uint64_t min_metadata_size, /* required min */
+ uint64_t max_metadata_size, /* writable max */
+ uint64_t *metadata_size, /* current calculated */
+ struct logical_volume *metadata_lv, /* name of converted LV or NULL */
+ uint32_t *metadata_extents); /* resulting extent count */
+
/*
* Begin skeleton for external LVM library
*/
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index a9dc611..b67882e 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -742,6 +742,52 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
return 1;
}
+int update_pool_metadata_min_max(struct cmd_context *cmd,
+ uint32_t extent_size,
+ uint64_t min_metadata_size, /* required min */
+ uint64_t max_metadata_size, /* writable max */
+ uint64_t *metadata_size, /* current calculated */
+ struct logical_volume *metadata_lv, /* name of converted LV or NULL */
+ uint32_t *metadata_extents) /* resulting extent count */
+{
+ max_metadata_size = dm_round_up(max_metadata_size, extent_size);
+ min_metadata_size = dm_round_up(min_metadata_size, extent_size);
+
+ if (*metadata_size > max_metadata_size) {
+ if (metadata_lv) {
+ log_print_unless_silent("Size %s of pool metadata volume %s is bigger then maximum usable size %s.",
+ display_size(cmd, *metadata_size),
+ display_lvname(metadata_lv),
+ display_size(cmd, max_metadata_size));
+ } else {
+ if (*metadata_extents)
+ log_print_unless_silent("Reducing pool metadata size %s to maximum usable size %s.",
+ display_size(cmd, *metadata_size),
+ display_size(cmd, max_metadata_size));
+ *metadata_size = max_metadata_size;
+ }
+ } else if (*metadata_size < min_metadata_size) {
+ if (metadata_lv) {
+ log_error("Can't use volume %s with size %s as pool metadata. Minimal required size is %s.",
+ display_lvname(metadata_lv),
+ display_size(cmd, *metadata_size),
+ display_size(cmd, min_metadata_size));
+ return 0;
+ } else {
+ if (*metadata_extents)
+ log_print_unless_silent("Extending pool metadata size %s to required minimal size %s.",
+ display_size(cmd, *metadata_size),
+ display_size(cmd, min_metadata_size));
+ *metadata_size = min_metadata_size;
+ }
+ }
+
+ if (!(*metadata_extents = extents_from_size(cmd, *metadata_size, extent_size)))
+ return_0;
+
+ return 1;
+}
+
int vg_set_pool_metadata_spare(struct logical_volume *lv)
{
char new_name[NAME_LEN];
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 4591dd7..451c382 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -610,9 +610,9 @@ static uint64_t _estimate_metadata_size(uint32_t data_extents, uint32_t extent_s
}
/* Estimate maximal supportable thin pool data size for given chunk_size */
-static uint64_t _estimate_max_data_size(uint32_t chunk_size)
+static uint64_t _estimate_max_data_size(uint64_t max_metadata_size, uint32_t chunk_size)
{
- return chunk_size * (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2) * SECTOR_SIZE / UINT64_C(64);
+ return max_metadata_size * chunk_size * SECTOR_SIZE / UINT64_C(64);
}
/* Estimate thin pool chunk size from data and metadata size (in sector units) */
@@ -662,6 +662,38 @@ int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct
return 1;
}
+/* Return max supported metadata size with selected cropping */
+uint64_t get_thin_pool_max_metadata_size(struct cmd_context *cmd, struct profile *profile,
+ thin_crop_metadata_t *crop)
+{
+ *crop = find_config_tree_bool(cmd, allocation_thin_pool_crop_metadata_CFG, profile) ?
+ THIN_CROP_METADATA_YES : THIN_CROP_METADATA_NO;
+
+ return (*crop == THIN_CROP_METADATA_NO) ?
+ (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB) : (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE);
+}
+
+/*
+ * With existing crop method, check if the metadata_size would need cropping.
+ * If not, set UNSELECTED, otherwise print some verbose info about selected cropping
+ */
+thin_crop_metadata_t get_thin_pool_crop_metadata(struct cmd_context *cmd,
+ thin_crop_metadata_t crop,
+ uint64_t metadata_size)
+{
+ const uint64_t crop_size = (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE);
+
+ if (metadata_size > crop_size) {
+ if (crop == THIN_CROP_METADATA_NO)
+ log_verbose("Using metadata size without cropping.");
+ else
+ log_verbose("Cropping metadata size to %s.", display_size(cmd, crop_size));
+ } else
+ crop = THIN_CROP_METADATA_UNSELECTED;
+
+ return crop;
+}
+
int update_thin_pool_params(struct cmd_context *cmd,
struct profile *profile,
uint32_t extent_size,
@@ -669,10 +701,13 @@ int update_thin_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
+ thin_crop_metadata_t *crop_metadata,
int *chunk_size_calc_method, uint32_t *chunk_size,
thin_discards_t *discards, thin_zero_t *zero_new_blocks)
{
- uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
+ uint64_t pool_metadata_size;
+ uint64_t max_metadata_size;
uint32_t estimate_chunk_size;
uint64_t max_pool_data_size;
const char *str;
@@ -702,7 +737,9 @@ int update_thin_pool_params(struct cmd_context *cmd,
*zero_new_blocks = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile)
? THIN_ZERO_YES : THIN_ZERO_NO;
- if (!pool_metadata_size) {
+ max_metadata_size = get_thin_pool_max_metadata_size(cmd, profile, crop_metadata);
+
+ if (!*pool_metadata_extents) {
if (!*chunk_size) {
if (!get_default_allocation_thin_pool_chunk_size(cmd, profile,
chunk_size,
@@ -723,20 +760,20 @@ int update_thin_pool_params(struct cmd_context *cmd,
} else {
pool_metadata_size = _estimate_metadata_size(pool_data_extents, extent_size, *chunk_size);
- if (pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) {
+ if (pool_metadata_size > max_metadata_size) {
/* Suggest bigger chunk size */
estimate_chunk_size =
_estimate_chunk_size(pool_data_extents, extent_size,
- (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2), attr);
+ max_metadata_size, attr);
log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.",
display_size(cmd, estimate_chunk_size));
}
}
/* Round up to extent size silently */
- if (pool_metadata_size % extent_size)
- pool_metadata_size += extent_size - pool_metadata_size % extent_size;
+ pool_metadata_size = dm_round_up(pool_metadata_size, extent_size);
} else {
+ pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
estimate_chunk_size = _estimate_chunk_size(pool_data_extents, extent_size,
pool_metadata_size, attr);
@@ -751,7 +788,19 @@ int update_thin_pool_params(struct cmd_context *cmd,
}
}
- max_pool_data_size = _estimate_max_data_size(*chunk_size);
+ /* Use not rounded max for data size */
+ max_pool_data_size = _estimate_max_data_size(max_metadata_size, *chunk_size);
+
+ if (!update_pool_metadata_min_max(cmd, extent_size,
+ 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE,
+ max_metadata_size,
+ &pool_metadata_size,
+ metadata_lv,
+ pool_metadata_extents))
+ return_0;
+
+ *crop_metadata = get_thin_pool_crop_metadata(cmd, *crop_metadata, pool_metadata_size);
+
if ((max_pool_data_size / extent_size) < pool_data_extents) {
log_error("Selected chunk size %s cannot address more then %s of thin pool data space.",
display_size(cmd, *chunk_size), display_size(cmd, max_pool_data_size));
@@ -764,22 +813,6 @@ int update_thin_pool_params(struct cmd_context *cmd,
if (!validate_thin_pool_chunk_size(cmd, *chunk_size))
return_0;
- if (pool_metadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
- pool_metadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
- if (*pool_metadata_extents)
- log_warn("WARNING: Maximum supported pool metadata size is %s.",
- display_size(cmd, pool_metadata_size));
- } else if (pool_metadata_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
- pool_metadata_size = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
- if (*pool_metadata_extents)
- log_warn("WARNING: Minimum supported pool metadata size is %s.",
- display_size(cmd, pool_metadata_size));
- }
-
- if (!(*pool_metadata_extents =
- extents_from_size(cmd, pool_metadata_size, extent_size)))
- return_0;
-
if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
log_error("Size of %s data volume cannot be smaller than chunk size %s.",
segtype->name, display_size(cmd, *chunk_size));
@@ -958,12 +991,5 @@ int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size)
uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size)
{
- uint64_t sz = _estimate_metadata_size(data_extents, extent_size, chunk_size);
-
- if (sz > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE))
- sz = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
- else if (sz < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE))
- sz = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
-
- return sz;
+ return _estimate_metadata_size(data_extents, extent_size, chunk_size);
}
diff --git a/lib/thin/thin.c b/lib/thin/thin.c
index ba0da71..51bc269 100644
--- a/lib/thin/thin.c
+++ b/lib/thin/thin.c
@@ -86,6 +86,7 @@ static int _thin_pool_text_import(struct lv_segment *seg,
struct logical_volume *pool_data_lv, *pool_metadata_lv;
const char *discards_str = NULL;
uint32_t zero = 0;
+ uint32_t crop = 0;
if (!dm_config_get_str(sn, "metadata", &lv_name))
return SEG_LOG_ERROR("Metadata must be a string in");
@@ -131,6 +132,13 @@ static int _thin_pool_text_import(struct lv_segment *seg,
seg->zero_new_blocks = (zero) ? THIN_ZERO_YES : THIN_ZERO_NO;
+ if (dm_config_has_node(sn, "crop_metadata")) {
+ if (!dm_config_get_uint32(sn, "crop_metadata", &crop))
+ return SEG_LOG_ERROR("Could not read crop_metadata for");
+ seg->crop_metadata = (crop) ? THIN_CROP_METADATA_YES : THIN_CROP_METADATA_NO;
+ seg->lv->status |= LV_CROP_METADATA;
+ }
+
/* Read messages */
for (; sn; sn = sn->sib)
if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child))
@@ -177,6 +185,9 @@ static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter
return 0;
}
+ if (seg->crop_metadata != THIN_CROP_METADATA_UNSELECTED)
+ outf(f, "crop_metadata = %u", (seg->crop_metadata == THIN_CROP_METADATA_YES) ? 1 : 0);
+
dm_list_iterate_items(tmsg, &seg->thin_messages) {
/* Extra validation */
switch (tmsg->type) {
@@ -307,11 +318,12 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
else
low_water_mark = 0;
- if (!dm_tree_node_add_thin_pool_target(node, len,
- seg->transaction_id,
- metadata_dlid, pool_dlid,
- seg->chunk_size, low_water_mark,
- (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1))
+ if (!dm_tree_node_add_thin_pool_target_v1(node, len,
+ seg->transaction_id,
+ metadata_dlid, pool_dlid,
+ seg->chunk_size, low_water_mark,
+ (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1,
+ (seg->crop_metadata == THIN_CROP_METADATA_YES) ? 1 : 0))
return_0;
if (attr & THIN_FEATURE_DISCARDS) {
diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main
index e6f1d63..3ce34a5 100644
--- a/man/lvmthin.7_main
+++ b/man/lvmthin.7_main
@@ -1104,7 +1104,7 @@ The default value is shown by:
The amount of thin metadata depends on how many blocks are shared between
thin LVs (i.e. through snapshots). A thin pool with many snapshots may
need a larger metadata LV. Thin pool metadata LV sizes can be from 2MiB
-to 16GiB.
+to approximately 16GiB.
When using lvcreate to create what will become a thin metadata LV, the
size is specified with the -L|--size option.
@@ -1119,6 +1119,14 @@ needed, so it is recommended to start with a size of 1GiB which should be
enough for all practical purposes. A thin pool metadata LV can later be
manually or automatically extended if needed.
+Configurable setting
+.BR lvm.conf (5)
+.BR allocation / thin_pool_crop_metadata
+gives control over cropping to 15.81GiB to stay backward compatible with older
+versions of lvm2. With enabled cropping there can be observed some problems when
+using volumes above this size with thin tools (i.e. thin_repair).
+Cropping should be enabled only when compatibility is required.
+
.SS Create a thin snapshot of an external, read only LV
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 7b74afb..ce90279 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -3032,6 +3032,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
const char *policy_name;
struct dm_config_tree *policy_settings = NULL;
int pool_metadata_spare;
+ thin_crop_metadata_t crop_metadata;
thin_discards_t discards;
thin_zero_t zero_new_blocks;
int r = 0;
@@ -3196,6 +3197,8 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
pool_segtype, target_attr,
lv->le_count,
&meta_extents,
+ metadata_lv,
+ &crop_metadata,
&chunk_calc,
&chunk_size,
&discards, &zero_new_blocks))
@@ -3401,6 +3404,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
goto_bad;
} else {
seg->transaction_id = 0;
+ seg->crop_metadata = crop_metadata;
seg->chunk_size = chunk_size;
seg->discards = discards;
seg->zero_new_blocks = zero_new_blocks;
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index e384291..1ee9e14 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -391,6 +391,8 @@ static int _update_extents_params(struct volume_group *vg,
lp->segtype, lp->target_attr,
lp->extents,
&lp->pool_metadata_extents,
+ NULL,
+ &lp->crop_metadata,
&lp->thin_chunk_size_calc_policy,
&lp->chunk_size,
&lp->discards,

View File

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

View File

@ -3,16 +3,16 @@
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/VERSION b/VERSION
index 8c4a9a8..00618e0 100644
index a6ba8f6..2a15962 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.03.09(2) (2020-03-26)
+2.03.09(2)-RHEL8 (2020-04-21)
-2.03.11(2) (2021-01-08)
+2.03.11(2)-RHEL8 (2021-01-28)
diff --git a/VERSION_DM b/VERSION_DM
index 0ae62fd..b9ec43e 100644
index f44bc5f..2475a11 100644
--- a/VERSION_DM
+++ b/VERSION_DM
@@ -1 +1 @@
-1.02.171 (2020-03-26)
+1.02.171-RHEL8 (2020-04-21)
-1.02.175 (2021-01-08)
+1.02.175-RHEL8 (2021-01-28)

View File

@ -1,15 +1,9 @@
From 6a078fe01b47fa165226a15263c8bd6350b1c307 Mon Sep 17 00:00:00 2001
From: Marian Csontos <mcsontos@redhat.com>
Date: Thu, 3 Jan 2019 13:49:08 +0100
Subject: [PATCH 2/8] lvm2: set default preferred_names
---
conf/example.conf.in | 3 ++-
lib/config/config_settings.h | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index 05b0857..88858fc 100644
index fe17942..d149ed9 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -122,7 +122,8 @@ devices {
@ -23,7 +17,7 @@ index 05b0857..88858fc 100644
# Configuration option devices/filter.
# Limit the block devices that are used by LVM commands.
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 2bb72ba..dce9705 100644
index 163e014..3c4032e 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_
@ -35,6 +29,3 @@ index 2bb72ba..dce9705 100644
"Select which path name to display for a block device.\n"
"If multiple path names exist for a block device, and LVM needs to\n"
"display a name for the device, the path names are matched against\n"
--
1.8.3.1

View File

@ -1,18 +1,12 @@
From 74f05f17ea3d1a3639a65ba337f2b7df7f4981bf Mon Sep 17 00:00:00 2001
From: Marian Csontos <mcsontos@redhat.com>
Date: Sun, 18 Aug 2019 17:31:30 +0200
Subject: [PATCH 3/8] lvm2: test: skip-problematic-tests
---
test/dbus/lvmdbustest.py | 1 +
test/shell/lvcreate-usage.sh | 6 +++---
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/test/dbus/lvmdbustest.py b/test/dbus/lvmdbustest.py
index 8753e65..b2986bf 100755
index efa1afb..473bb94 100755
--- a/test/dbus/lvmdbustest.py
+++ b/test/dbus/lvmdbustest.py
@@ -1821,6 +1821,7 @@ class TestDbusService(unittest.TestCase):
@@ -1851,6 +1851,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.
@ -43,6 +37,3 @@ index 6d46939..9e00f1c 100644
lvremove -ff $vg
#
--
1.8.3.1

View File

@ -1,4 +1,4 @@
%global device_mapper_version 1.02.171
%global device_mapper_version 1.02.175
%global enable_cache 1
%global enable_cluster 1
@ -51,37 +51,53 @@
# Do not reset Release to 1 unless both lvm2 and device-mapper
# versions are increased together.
Summary: Userland logical volume management tools
Name: lvm2
%if 0%{?rhel}
Epoch: %{rhel}
%endif
Version: 2.03.09
Release: 5%{?dist}.2
Version: 2.03.11
Release: 5%{?dist}
License: GPLv2
URL: http://sourceware.org/lvm2
Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz
Patch0: lvm2-rhel8.patch
Patch1: lvm2-set-default-preferred_names.patch
Patch2: lvm2-test-skip-problematic-tests.patch
Patch3: lvm2-2_03_10-lvconvert-no-validation-for-thin-pools-not-used-by-lvm.patch
Patch4: lvm2-2_03_10-test-repair-of-thin-pool-used-by-foreign-apps.patch
Patch5: lvm2-2_03_10-WHATS_NEWS-update.patch
Patch6: lvm2-2_03_10-blkdeactivate-add-support-for-VDO-in-blkdeactivate-script.patch
Patch7: lvm2-2_03_10-Fix-scripts-lvmlocks.service.in-using-nonexistent-lock-opt-autowait.patch
Patch8: lvm2-2_03_10-move-pv_list-code-into-lib.patch
Patch9: lvm2-2_03_10-Allow-dm-integrity-to-be-used-for-raid-images.patch
Patch10: lvm2-2_03_10-WHATS_NEW-integrity-with-raid.patch
Patch11: lvm2-2_03_10-build-make-generate.patch
Patch12: 0001-Merge-master-up-to-commit-53803821de16.patch
Patch13: 0002-Merge-master-up-to-commit-be61bd6ff5c6.patch
Patch14: 0003-Merge-master-up-to-commit-c1d136fea3d1.patch
# BZ 1868169:
Patch15: 0004-Revert-wipe_lv-changes.patch
# BZ 1895081:
Patch16: lvm2-2_03_11-man-lvmvdo-update.patch
Patch17: lvm2-2_03_11-man-update-lvmvdo.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
BuildRequires: gcc
%if %{enable_testsuite}
@ -155,6 +171,15 @@ or more physical volumes and creating one or more logical volumes
%patch15 -p1 -b .backup15
%patch16 -p1 -b .backup16
%patch17 -p1 -b .backup17
%patch18 -p1 -b .backup18
%patch19 -p1 -b .backup19
%patch20 -p1 -b .backup20
%patch21 -p1 -b .backup21
%patch22 -p1 -b .backup22
%patch23 -p1 -b .backup23
%patch24 -p1 -b .backup24
%patch25 -p1 -b .backup25
%patch26 -p1 -b .backup26
%build
%global _default_pid_dir /run
@ -759,11 +784,45 @@ An extensive functional testsuite for LVM2.
%endif
%changelog
* Wed Dec 09 2020 Marian Csontos <mcsontos@redhat.com> - 2.03.09-5.el8_3.2
- Update lvmvdo man page.
* Thu Feb 11 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.11-5
- Fix fsadm failure due to accessing unbound variable.
* Wed Dec 02 2020 Marian Csontos <mcsontos@redhat.com> - 2.03.09-5.el8_3.1
- Update lvmvdo man page.
* Thu Feb 11 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.11-4
- Fix "Failed to get primary device" for NVMe devices.
* Wed Feb 03 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.11-3
- Fix mpath filtering of NVMe devices.
- Check if lvcreate passes read_only_volume_list with tags and skips zeroing.
- Limit pool metadata spare to 16GiB.
- Improves conversion and allocation of pool metadata.
- Fix different limits used for metadata by lvm2 and thin-tools.
- Fix interrupting lvconvert --splitcache command with striped origin volumes.
* Thu Jan 28 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.11-2
- Fix problem with wiping of converted LVs.
- Fix memleak in scanning.
- Fix corner case allocation for thin-pools.
* Fri Jan 08 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.11-1
- Fix pvck handling MDA at offset different from 4096.
- Partial or degraded activation of writecache is not allowed.
- Enhance error handling in fsadm and handle correct fsck result.
- Dmeventd lvm plugin ignores higher reserved_stack lvm.conf values.
- Support using BLKZEROOUT for clearing devices.
- Fixed interrup handling.
- Fix block cache when device has too many failing writes.
- Fix block cache waiting for IO completion with failing disks.
- Add configure --enable-editline support as an alternative to readline.
- Enhance reporting and error handling when creating thin volumes.
- Enable vgsplit for VDO volumes.
- Lvextend of vdo pool volumes ensure at least 1 new VDO slab is added.
- Restore lost signal blocking while VG lock is held.
- Improve estimation of needed extents when creating thin-pool.
- Use extra 1% when resizing thin-pool metadata LV with --use-policy.
- Enhance --use-policy percentage rounding.
- Allow pvmove of writecache origin.
- Report integrity fields.
- Integrity volumes defaults to journal mode.
* Wed Aug 12 2020 Marian Csontos <mcsontos@redhat.com> - 2.03.09-5
- Revert wipe_lv changes.