From 263516cfb9b28005e007a55ba70ee72ab9b78c3c Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 2 Aug 2022 08:13:55 +0000 Subject: [PATCH] Auto sync2gitlab import of lvm2-2.03.14-5.el8.src.rpm --- 0001-Revert-new-udev-autoactivation.patch | 4 +- ...an-only-add-device-args-to-dev-cache.patch | 4 +- ...n-fix-messages-from-coverity-changes.patch | 4 +- ...gimportdevices-skip-lvmlockd-locking.patch | 4 +- 0005-hints-remove-the-cmd-hints-list.patch | 4 +- ...ter-sysfs-skip-when-device-id-is-set.patch | 4 +- ...-lvmdevices-increase-open-file-limit.patch | 4 +- ...port-old-kernels-without-sys-dev-blo.patch | 4 +- ...e_id-match-different-dm-device-names.patch | 4 +- ...ice_id-fix-search-on-filtered-device.patch | 4 +- ...ce_id-searched_devnames-improvements.patch | 4 +- ...-pv-ext-flags-work-with-devices-file.patch | 4 +- 0013-display-ignore-reportformat.patch | 4 +- 0014-fix-spelling-of-pruning.patch | 4 +- 0015-man-lvmautoactivation.patch | 4 +- ...icesfile-devname.sh-drop-mdadm-chunk.patch | 4 +- ...evices-file-don-t-write-in-test-mode.patch | 4 +- ...out-unrecognized-journal-option-valu.patch | 4 +- ...-wwid-with-spaces-or-control-charact.patch | 4 +- ...-section-about-static-autoactivation.patch | 4 +- 0022-lvcreate-include-recent-options.patch | 4 +- ...ation-replace-systemctl-with-journal.patch | 4 +- 0024-make-generate.patch | 4 +- ...te-overwrite-partition-header-with-f.patch | 141 +++ ...check-error-exit-if-update-is-needed.patch | 166 ++++ ...te-overwrite-partition-header-with-f.patch | 140 +++ ...multipath-components-based-on-matchi.patch | 462 +++++++++ ...md-components-when-duplicate-pvs-are.patch | 268 +++++ ...vices-fix-checks-when-adding-entries.patch | 246 +++++ ...-make-deldev-work-for-missing-device.patch | 106 ++ ...-do-not-clear-PVID-of-unread-devices.patch | 144 +++ ...ache-mention-writecache-memory-usage.patch | 35 + ...itecache-display-block-size-from-lvs.patch | 102 ++ ...vices-simplify-dev_cache_get_by_devt.patch | 148 +++ ...op-incorrect-paths-from-aliases-list.patch | 467 +++++++++ ...vices-initial-use-of-existing-option.patch | 70 ++ 0038-devices-fix-dev_name-assumptions.patch | 270 +++++ ...cache-aliases-handling-from-label-sc.patch | 272 ++++++ 0040-writecache-check-memory-usage.patch | 101 ++ ...ange-messages-about-filtered-devices.patch | 108 ++ ...ces-fix-incorrect-deviceidtype-usage.patch | 31 + ...-error-from-vgcreate-init_vg_sanlock.patch | 32 + ...move-extraneous-unlock-in-vgchange-u.patch | 45 + ...filter-mpath-use-multipath-blacklist.patch | 93 +- ...mprove-description-of-devices-option.patch | 28 + 0047-vdo-support-vdosettings.patch | 576 +++++++++++ ...ault-when-handling-selection-with-hi.patch | 45 + ...e-move-clean-up-after-command-is-run.patch | 39 + ...l-if-devicesfile-filename-doesn-t-ex.patch | 53 + ...handle-other-wwid-types-in-blacklist.patch | 8 +- ...o-fix-conversion-of-vdo_slab_size_mb.patch | 56 ++ ...-mpath-get-wwids-from-sysfs-vpd_pg83.patch | 741 ++++++++++++++ ...ake-rpm-with-VERSION_DM-without-dash.patch | 29 + 0055-make-generate.patch | 921 ++++++++++++++++++ ...-when-devicesfile-name-doesn-t-exist.patch | 246 +++++ lvm2.spec | 78 +- 56 files changed, 6221 insertions(+), 138 deletions(-) create mode 100644 0025-pvcreate-overwrite-partition-header-with-f.patch create mode 100644 0026-lvmdevices-check-error-exit-if-update-is-needed.patch create mode 100644 0027-Revert-pvcreate-overwrite-partition-header-with-f.patch create mode 100644 0028-devices-exclude-multipath-components-based-on-matchi.patch create mode 100644 0029-devices-exclude-md-components-when-duplicate-pvs-are.patch create mode 100644 0030-lvmdevices-fix-checks-when-adding-entries.patch create mode 100644 0031-lvmdevices-make-deldev-work-for-missing-device.patch create mode 100644 0032-devices-file-do-not-clear-PVID-of-unread-devices.patch create mode 100644 0033-man-lvmcache-mention-writecache-memory-usage.patch create mode 100644 0034-writecache-display-block-size-from-lvs.patch create mode 100644 0035-devices-simplify-dev_cache_get_by_devt.patch create mode 100644 0036-devices-drop-incorrect-paths-from-aliases-list.patch create mode 100644 0037-devices-initial-use-of-existing-option.patch create mode 100644 0038-devices-fix-dev_name-assumptions.patch create mode 100644 0039-devices-use-dev-cache-aliases-handling-from-label-sc.patch create mode 100644 0040-writecache-check-memory-usage.patch create mode 100644 0041-change-messages-about-filtered-devices.patch create mode 100644 0042-vgimportdevices-fix-incorrect-deviceidtype-usage.patch create mode 100644 0043-lvmlockd-return-error-from-vgcreate-init_vg_sanlock.patch create mode 100644 0044-devices-file-remove-extraneous-unlock-in-vgchange-u.patch rename 0025-filter-mpath-use-multipath-blacklist.patch => 0045-filter-mpath-use-multipath-blacklist.patch (82%) create mode 100644 0046-improve-description-of-devices-option.patch create mode 100644 0047-vdo-support-vdosettings.patch create mode 100644 0048-toollib-fix-segfault-when-handling-selection-with-hi.patch create mode 100644 0049-devices-file-move-clean-up-after-command-is-run.patch create mode 100644 0050-devices-file-fail-if-devicesfile-filename-doesn-t-ex.patch rename 0026-filter-mpath-handle-other-wwid-types-in-blacklist.patch => 0051-filter-mpath-handle-other-wwid-types-in-blacklist.patch (85%) create mode 100644 0052-vdo-fix-conversion-of-vdo_slab_size_mb.patch create mode 100644 0053-filter-mpath-get-wwids-from-sysfs-vpd_pg83.patch create mode 100644 0054-build-Fix-make-rpm-with-VERSION_DM-without-dash.patch create mode 100644 0055-make-generate.patch create mode 100644 0056-exit-with-error-when-devicesfile-name-doesn-t-exist.patch diff --git a/0001-Revert-new-udev-autoactivation.patch b/0001-Revert-new-udev-autoactivation.patch index 2b096a7..971fc3a 100644 --- a/0001-Revert-new-udev-autoactivation.patch +++ b/0001-Revert-new-udev-autoactivation.patch @@ -1,7 +1,7 @@ From 63c4458aaf67d114c677baf657a7e9e43440f349 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 20 Dec 2021 14:22:02 -0600 -Subject: [PATCH 01/23] Revert "new udev autoactivation" +Subject: [PATCH 01/54] Revert "new udev autoactivation" This reverts commit 67722b312390cdab29c076c912e14bd739c5c0f6. --- @@ -541,5 +541,5 @@ index e777dda16..e32cba921 100644 DM_DIR=$(shell $(GREP) "\#define DM_DIR" $(top_srcdir)/libdm/misc/dm-ioctl.h | $(AWK) '{print $$3}') -- -2.31.1 +2.34.3 diff --git a/0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch b/0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch index 8e73676..9f309a3 100644 --- a/0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch +++ b/0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch @@ -1,7 +1,7 @@ From 2091305b796d5552fd991c527a0359a0b4d8fde0 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 20 Dec 2021 13:38:23 -0600 -Subject: [PATCH 02/23] Revert "pvscan: only add device args to dev cache" +Subject: [PATCH 02/54] Revert "pvscan: only add device args to dev cache" This reverts commit 33e47182f773c1a902b533580b63a803906de55d. --- @@ -446,5 +446,5 @@ index 95d593d57..8e2611361 100644 if (cmd->enable_devices_file && device_ids_use_devname(cmd)) { relax_deviceid_filter = 1; -- -2.31.1 +2.34.3 diff --git a/0003-pvscan-fix-messages-from-coverity-changes.patch b/0003-pvscan-fix-messages-from-coverity-changes.patch index 5ff1c9d..7756188 100644 --- a/0003-pvscan-fix-messages-from-coverity-changes.patch +++ b/0003-pvscan-fix-messages-from-coverity-changes.patch @@ -1,7 +1,7 @@ From a5a2d5fa1ec47a5a548db4cf435dc84de7ce7c31 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 20 Oct 2021 16:12:41 -0500 -Subject: [PATCH 03/23] pvscan: fix messages from coverity changes +Subject: [PATCH 03/54] pvscan: fix messages from coverity changes --- tools/pvscan.c | 4 ++-- @@ -30,5 +30,5 @@ index 8e2611361..f60c4a2ca 100644 continue; } -- -2.31.1 +2.34.3 diff --git a/0004-vgimportdevices-skip-lvmlockd-locking.patch b/0004-vgimportdevices-skip-lvmlockd-locking.patch index d84d9d9..450ead9 100644 --- a/0004-vgimportdevices-skip-lvmlockd-locking.patch +++ b/0004-vgimportdevices-skip-lvmlockd-locking.patch @@ -1,7 +1,7 @@ From 074fce5c73c55e7a1547d5efff65a9f96e6db3b1 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 25 Oct 2021 12:11:17 -0500 -Subject: [PATCH 04/23] vgimportdevices: skip lvmlockd locking +Subject: [PATCH 04/54] vgimportdevices: skip lvmlockd locking Help bootstrapping existing shared vgs into the devices file. Reading the vg in vgimportdevices would require locking to be @@ -35,5 +35,5 @@ index 3f315f98f..2580613c4 100644 * For each VG: * device_id_add() each PV in the VG -- -2.31.1 +2.34.3 diff --git a/0005-hints-remove-the-cmd-hints-list.patch b/0005-hints-remove-the-cmd-hints-list.patch index 09ef5d4..ea26c2a 100644 --- a/0005-hints-remove-the-cmd-hints-list.patch +++ b/0005-hints-remove-the-cmd-hints-list.patch @@ -1,7 +1,7 @@ From 00ebabfe6e1ebfceffcef335d44a6156a1c15418 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 1 Nov 2021 16:01:09 -0500 -Subject: [PATCH 05/23] hints: remove the cmd hints list +Subject: [PATCH 05/54] hints: remove the cmd hints list which is no longer used after commit "toollib: remove all devices list from process_each_pv" @@ -91,5 +91,5 @@ index 3cd912270..479a5037a 100644 * Check if the devices_file content is up to date and * if not update it. -- -2.31.1 +2.34.3 diff --git a/0006-filter-sysfs-skip-when-device-id-is-set.patch b/0006-filter-sysfs-skip-when-device-id-is-set.patch index 61d8fe7..7afc6a9 100644 --- a/0006-filter-sysfs-skip-when-device-id-is-set.patch +++ b/0006-filter-sysfs-skip-when-device-id-is-set.patch @@ -1,7 +1,7 @@ From f73be4480a5dd104a77e3ef84d7dcc80b834e593 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 2 Nov 2021 15:42:26 -0500 -Subject: [PATCH 06/23] filter-sysfs: skip when device id is set +Subject: [PATCH 06/54] filter-sysfs: skip when device id is set When a device id is set for a device, using an idtype other than devname, it means that sysfs has been used with the device @@ -418,5 +418,5 @@ index 32ac324dd..672211057 100644 } -- -2.31.1 +2.34.3 diff --git a/0007-lvmdevices-increase-open-file-limit.patch b/0007-lvmdevices-increase-open-file-limit.patch index 6a586d7..435d851 100644 --- a/0007-lvmdevices-increase-open-file-limit.patch +++ b/0007-lvmdevices-increase-open-file-limit.patch @@ -1,7 +1,7 @@ From f732f3d53faee3732d0f4a666c378709e6c2f5e9 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Fri, 29 Oct 2021 14:49:36 -0500 -Subject: [PATCH 07/23] lvmdevices: increase open file limit +Subject: [PATCH 07/54] lvmdevices: increase open file limit --- lib/label/label.c | 4 ++-- @@ -57,5 +57,5 @@ index 8d9634848..3f104f7de 100644 device_ids_match(cmd); -- -2.31.1 +2.34.3 diff --git a/0008-filter-sysfs-support-old-kernels-without-sys-dev-blo.patch b/0008-filter-sysfs-support-old-kernels-without-sys-dev-blo.patch index cd4a4e3..d334f92 100644 --- a/0008-filter-sysfs-support-old-kernels-without-sys-dev-blo.patch +++ b/0008-filter-sysfs-support-old-kernels-without-sys-dev-blo.patch @@ -1,7 +1,7 @@ From fad2b3dc8c44ba1222508ee78b5f161994efe638 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 9 Nov 2021 11:54:48 -0600 -Subject: [PATCH 08/23] filter-sysfs: support old kernels without sys/dev/block +Subject: [PATCH 08/54] filter-sysfs: support old kernels without sys/dev/block rhel5 for example doesn't have /sys/dev/block --- @@ -69,5 +69,5 @@ index 672211057..d8de7940b 100644 goto_bad; -- -2.31.1 +2.34.3 diff --git a/0009-device_id-match-different-dm-device-names.patch b/0009-device_id-match-different-dm-device-names.patch index 94ec305..f1d6c1c 100644 --- a/0009-device_id-match-different-dm-device-names.patch +++ b/0009-device_id-match-different-dm-device-names.patch @@ -1,7 +1,7 @@ From 459d931a9bfe4c9adcbbf2e76fdf35fda5b13c61 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Fri, 12 Nov 2021 16:42:51 -0600 -Subject: [PATCH 09/23] device_id: match different dm device names +Subject: [PATCH 09/54] device_id: match different dm device names If a devices file entry for a dm device is using the devname for the device id, then recognize different dm names as matching. @@ -151,5 +151,5 @@ index eb06109ff..dea739fc4 100644 return 0; } -- -2.31.1 +2.34.3 diff --git a/0010-device_id-fix-search-on-filtered-device.patch b/0010-device_id-fix-search-on-filtered-device.patch index edc2d3e..b8c9ed4 100644 --- a/0010-device_id-fix-search-on-filtered-device.patch +++ b/0010-device_id-fix-search-on-filtered-device.patch @@ -1,7 +1,7 @@ From 5533cd7bf4c1edc5d8fb0e95d2f83b2b2d446339 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 16 Nov 2021 09:29:24 -0600 -Subject: [PATCH 10/23] device_id: fix search on filtered device +Subject: [PATCH 10/54] device_id: fix search on filtered device When devnames are used as device ids and devnames change, then new devices need to be located for the PVs. If the old @@ -130,5 +130,5 @@ index f95be52b1..a99fe3e9a 100644 + vgremove -ff $vg1 -- -2.31.1 +2.34.3 diff --git a/0011-device_id-searched_devnames-improvements.patch b/0011-device_id-searched_devnames-improvements.patch index d8a658e..7c3f423 100644 --- a/0011-device_id-searched_devnames-improvements.patch +++ b/0011-device_id-searched_devnames-improvements.patch @@ -1,7 +1,7 @@ From 39adf3e513ac7b1cbbbf0189f973573ade3c8939 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 16 Nov 2021 11:26:41 -0600 -Subject: [PATCH 11/23] device_id: searched_devnames improvements +Subject: [PATCH 11/54] device_id: searched_devnames improvements Remove the searched_devnames file in a couple more places: . When hints need refreshing it's possible that a missing @@ -98,5 +98,5 @@ index e444a0c82..3ce9634f2 100644 return 0; -- -2.31.1 +2.34.3 diff --git a/0012-tests-pv-ext-flags-work-with-devices-file.patch b/0012-tests-pv-ext-flags-work-with-devices-file.patch index 1e421c0..dcf9507 100644 --- a/0012-tests-pv-ext-flags-work-with-devices-file.patch +++ b/0012-tests-pv-ext-flags-work-with-devices-file.patch @@ -1,7 +1,7 @@ From 9c9bf13186d387d807f279c112745768c8b32513 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 16 Nov 2021 14:21:07 -0600 -Subject: [PATCH 12/23] tests pv-ext-flags: work with devices file +Subject: [PATCH 12/54] tests pv-ext-flags: work with devices file --- test/shell/pv-ext-flags.sh | 4 ++++ @@ -36,5 +36,5 @@ index 3e6bcff76..ae4d6b7ff 100644 # prepare a VG with $dev1 and $dev both having 1 MDA aux enable_dev "$dev2" -- -2.31.1 +2.34.3 diff --git a/0013-display-ignore-reportformat.patch b/0013-display-ignore-reportformat.patch index f7dc091..33b7e28 100644 --- a/0013-display-ignore-reportformat.patch +++ b/0013-display-ignore-reportformat.patch @@ -1,7 +1,7 @@ From 594c1fec1644fdf291aa0ff23de20db65c4cfadf Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 17 Nov 2021 10:40:27 -0600 -Subject: [PATCH 13/23] display: ignore --reportformat +Subject: [PATCH 13/54] display: ignore --reportformat Using the option would do nothing useful but would print extraneous braces. @@ -87,5 +87,5 @@ index 1e12bedca..1727ba089 100644 * Remaining position args after command name and --options are removed. */ -- -2.31.1 +2.34.3 diff --git a/0014-fix-spelling-of-pruning.patch b/0014-fix-spelling-of-pruning.patch index e24450a..61afdb4 100644 --- a/0014-fix-spelling-of-pruning.patch +++ b/0014-fix-spelling-of-pruning.patch @@ -1,7 +1,7 @@ From 7ac0b3c119b1cbb8e0b4969ece0b279637ace8c3 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Fri, 19 Nov 2021 12:02:35 -0600 -Subject: [PATCH 14/23] fix spelling of pruning +Subject: [PATCH 14/54] fix spelling of pruning --- lib/format_text/archive.c | 2 +- @@ -21,5 +21,5 @@ index 09a472b4c..2e8792a93 100644 } -- -2.31.1 +2.34.3 diff --git a/0015-man-lvmautoactivation.patch b/0015-man-lvmautoactivation.patch index 0128098..6abef88 100644 --- a/0015-man-lvmautoactivation.patch +++ b/0015-man-lvmautoactivation.patch @@ -1,7 +1,7 @@ From 25dbe3dd825a629ff7f67cb43342cc345071d3f7 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 24 Nov 2021 16:03:39 -0600 -Subject: [PATCH 15/23] man: lvmautoactivation +Subject: [PATCH 15/54] man: lvmautoactivation new topical man page describing autoactivation --- @@ -412,5 +412,5 @@ index b20b987da..4c5929955 100644 +.BR lvmautoactivation (7) +for more information about how pvscan is used for autoactivation. -- -2.31.1 +2.34.3 diff --git a/0017-tests-devicesfile-devname.sh-drop-mdadm-chunk.patch b/0017-tests-devicesfile-devname.sh-drop-mdadm-chunk.patch index ef22830..a4147e6 100644 --- a/0017-tests-devicesfile-devname.sh-drop-mdadm-chunk.patch +++ b/0017-tests-devicesfile-devname.sh-drop-mdadm-chunk.patch @@ -1,7 +1,7 @@ From 10a4478e9b778dd8d4ff9737a503474b00ce9510 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 1 Dec 2021 08:56:05 -0600 -Subject: [PATCH 17/23] tests devicesfile-devname.sh drop mdadm chunk +Subject: [PATCH 17/54] tests devicesfile-devname.sh drop mdadm chunk --- test/shell/devicesfile-devname.sh | 2 +- @@ -21,5 +21,5 @@ index a99fe3e9a..338637275 100644 sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > tmp1.devices -- -2.31.1 +2.34.3 diff --git a/0018-devices-file-don-t-write-in-test-mode.patch b/0018-devices-file-don-t-write-in-test-mode.patch index feb3bf7..3e79410 100644 --- a/0018-devices-file-don-t-write-in-test-mode.patch +++ b/0018-devices-file-don-t-write-in-test-mode.patch @@ -1,7 +1,7 @@ From 04770589b49effdb064c9b3790e8dd2fee2c3547 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 1 Dec 2021 10:08:08 -0600 -Subject: [PATCH 18/23] devices file: don't write in test mode +Subject: [PATCH 18/54] devices file: don't write in test mode --- lib/device/device_id.c | 3 +++ @@ -22,5 +22,5 @@ index ce7ded154..4c2b5a3dd 100644 if (sscanf(_devices_file_version, "%u.%u.%u", &df_major, &df_minor, &df_counter) != 3) { /* don't update a file we can't parse */ -- -2.31.1 +2.34.3 diff --git a/0019-print-warning-about-unrecognized-journal-option-valu.patch b/0019-print-warning-about-unrecognized-journal-option-valu.patch index 5fc92af..177f936 100644 --- a/0019-print-warning-about-unrecognized-journal-option-valu.patch +++ b/0019-print-warning-about-unrecognized-journal-option-valu.patch @@ -1,7 +1,7 @@ From 604fd528fb4f00a9f77e084a1b22eff2aeef0259 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Thu, 2 Dec 2021 12:40:52 -0600 -Subject: [PATCH 19/23] print warning about unrecognized journal option value +Subject: [PATCH 19/54] print warning about unrecognized journal option value --- lib/log/log.c | 1 + @@ -20,5 +20,5 @@ index 7b4d537b3..5771a1d01 100644 } -- -2.31.1 +2.34.3 diff --git a/0020-device_id-handle-wwid-with-spaces-or-control-charact.patch b/0020-device_id-handle-wwid-with-spaces-or-control-charact.patch index e254e36..007cd75 100644 --- a/0020-device_id-handle-wwid-with-spaces-or-control-charact.patch +++ b/0020-device_id-handle-wwid-with-spaces-or-control-charact.patch @@ -1,7 +1,7 @@ From 357a807e81bbd1430b045eb2601a64b17d588400 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Thu, 2 Dec 2021 13:30:36 -0600 -Subject: [PATCH 20/23] device_id: handle wwid with spaces or control +Subject: [PATCH 20/54] device_id: handle wwid with spaces or control characters non-standard wwid can be reported from sysfs with spaces/etc. @@ -46,5 +46,5 @@ index 4c2b5a3dd..0621bc858 100644 goto_bad; -- -2.31.1 +2.34.3 diff --git a/0021-man-add-section-about-static-autoactivation.patch b/0021-man-add-section-about-static-autoactivation.patch index a6d10cf..f5494dc 100644 --- a/0021-man-add-section-about-static-autoactivation.patch +++ b/0021-man-add-section-about-static-autoactivation.patch @@ -1,7 +1,7 @@ From 7631c5b826b5a3eddfcd22db9b80574b249794c1 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 6 Dec 2021 13:20:32 -0600 -Subject: [PATCH 21/23] man: add section about static autoactivation +Subject: [PATCH 21/54] man: add section about static autoactivation --- man/lvmautoactivation.7_main | 48 ++++++++++++++++++++++++++++++------ @@ -92,5 +92,5 @@ index 87c15a3d1..bf885991d 100644 .P VG "vg" contains two PVs: -- -2.31.1 +2.34.3 diff --git a/0022-lvcreate-include-recent-options.patch b/0022-lvcreate-include-recent-options.patch index 38a729d..3ad1a54 100644 --- a/0022-lvcreate-include-recent-options.patch +++ b/0022-lvcreate-include-recent-options.patch @@ -1,7 +1,7 @@ From af4bfa1f1f84194000bc50f43ddc906c0cd4b104 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 13 Dec 2021 08:59:31 -0600 -Subject: [PATCH 22/23] lvcreate: include recent options +Subject: [PATCH 22/54] lvcreate: include recent options The permitted option list in lvcreate has not kept up with command-lines.in. @@ -31,5 +31,5 @@ index 0121c09a8..79af42685 100644 permission_ARG,\ persistent_ARG,\ -- -2.31.1 +2.34.3 diff --git a/0023-man-lvmautoactivation-replace-systemctl-with-journal.patch b/0023-man-lvmautoactivation-replace-systemctl-with-journal.patch index 16b08c43..c5af575 100644 --- a/0023-man-lvmautoactivation-replace-systemctl-with-journal.patch +++ b/0023-man-lvmautoactivation-replace-systemctl-with-journal.patch @@ -1,7 +1,7 @@ From 61833dd5b6117e8ace84289cff656d1dfb0ed123 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 14 Dec 2021 12:02:08 -0600 -Subject: [PATCH 23/23] man lvmautoactivation: replace systemctl with +Subject: [PATCH 23/54] man lvmautoactivation: replace systemctl with journalctl --- @@ -22,5 +22,5 @@ index bf885991d..54dab718b 100644 . .SS pvscan options -- -2.31.1 +2.34.3 diff --git a/0024-make-generate.patch b/0024-make-generate.patch index f5a15ad..54cc1cf 100644 --- a/0024-make-generate.patch +++ b/0024-make-generate.patch @@ -1,7 +1,7 @@ From 4b26fb3543049f3d179b620ff937c44e922ada58 Mon Sep 17 00:00:00 2001 From: Marian Csontos Date: Tue, 4 Jan 2022 17:15:56 +0100 -Subject: [PATCH] make: generate +Subject: [PATCH 24/54] make: generate --- man/lvdisplay.8_pregen | 12 -------- @@ -192,5 +192,5 @@ index 9c694921d..0a12b3c39 100644 .br Select objects for processing and reporting based on specified criteria. -- -2.31.1 +2.34.3 diff --git a/0025-pvcreate-overwrite-partition-header-with-f.patch b/0025-pvcreate-overwrite-partition-header-with-f.patch new file mode 100644 index 0000000..e3a9f54 --- /dev/null +++ b/0025-pvcreate-overwrite-partition-header-with-f.patch @@ -0,0 +1,141 @@ +From a5c37afdca97d6565ea02bc4bc7d52f360823cd3 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 8 Sep 2021 16:30:11 -0500 +Subject: [PATCH 25/54] pvcreate: overwrite partition header with -f + +$ pvcreate /dev/sdc + Cannot use /dev/sdc: device is partitioned +$ pvcreate -f /dev/sdc + Physical volume "/dev/sdc" successfully created. +--- + lib/commands/toolcontext.h | 1 + + lib/filters/filter-partitioned.c | 3 +++ + man/pvcreate.8_des | 7 ++++--- + test/shell/test-partition.sh | 12 ++++++++++-- + tools/toollib.c | 10 ++++++++++ + 5 files changed, 28 insertions(+), 5 deletions(-) + +diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h +index 356c79f8a..b83883fb8 100644 +--- a/lib/commands/toolcontext.h ++++ b/lib/commands/toolcontext.h +@@ -201,6 +201,7 @@ struct cmd_context { + unsigned ignore_device_name_mismatch:1; /* skip updating devices file names */ + unsigned backup_disabled:1; /* skip repeated debug message */ + unsigned event_activation:1; /* whether event_activation is set */ ++ unsigned filter_partitioned_skip:1; /* don't use filter-partitioned */ + + /* + * Devices and filtering. +diff --git a/lib/filters/filter-partitioned.c b/lib/filters/filter-partitioned.c +index 642553ef2..8f468a567 100644 +--- a/lib/filters/filter-partitioned.c ++++ b/lib/filters/filter-partitioned.c +@@ -27,6 +27,9 @@ static int _passes_partitioned_filter(struct cmd_context *cmd, struct dev_filter + if (cmd->filter_nodata_only) + return 1; + ++ if (cmd->filter_partitioned_skip) ++ return 1; ++ + dev->filtered_flags &= ~DEV_FILTERED_PARTITIONED; + + ret = dev_is_partitioned(cmd, dev); +diff --git a/man/pvcreate.8_des b/man/pvcreate.8_des +index 69bd133aa..4048eb71c 100644 +--- a/man/pvcreate.8_des ++++ b/man/pvcreate.8_des +@@ -7,9 +7,10 @@ Use \fBvgcreate\fP(8) to create a new VG on the PV, or \fBvgextend\fP(8) + to add the PV to an existing VG. Use \fBpvremove\fP(8) to remove the LVM + disk label from the device. + .P +-The force option will create a PV without confirmation. Repeating the +-force option (\fB-ff\fP) will forcibly create a PV, overriding checks that +-normally prevent it, e.g. if the PV is already in a VG. ++The force option will create a PV without confirmation, and will overwrite ++partition headers. Repeating the force option (\fB-ff\fP) will override other ++checks that would normally prevent a pvcreate, e.g. if the PV is already in a ++VG. + .P + .B Metadata location, size, and alignment + .P +diff --git a/test/shell/test-partition.sh b/test/shell/test-partition.sh +index 0e92f00db..3a45f9089 100644 +--- a/test/shell/test-partition.sh ++++ b/test/shell/test-partition.sh +@@ -16,7 +16,6 @@ + # + + +- + SKIP_WITH_LVMPOLLD=1 + + LVM_TEST_CONFIG_DEVICES="types = [\"device-mapper\", 142]" +@@ -25,7 +24,7 @@ LVM_TEST_CONFIG_DEVICES="types = [\"device-mapper\", 142]" + + which sfdisk || skip + +-aux prepare_pvs 1 30 ++aux prepare_pvs 2 30 + + pvs "$dev1" + +@@ -33,3 +32,12 @@ pvs "$dev1" + echo "1 2" | sfdisk --force "$dev1" + + not pvs "$dev1" ++ ++wipefs -a "$dev2" ++echo "1 2" | sfdisk --force "$dev2" ++partprobe ++not pvcreate "$dev2" ++pvcreate -f "$dev2" ++pvs "$dev2" ++pvremove "$dev2" ++ +diff --git a/tools/toollib.c b/tools/toollib.c +index d6f48aad2..80d3de57c 100644 +--- a/tools/toollib.c ++++ b/tools/toollib.c +@@ -5243,6 +5243,10 @@ int pvcreate_each_device(struct cmd_context *cmd, + if (cmd->enable_devices_file && !pp->is_remove) + cmd->filter_deviceid_skip = 1; + ++ /* pvcreate -f overwrites partitions */ ++ if (pp->force && !pp->is_remove) ++ cmd->filter_partitioned_skip = 1; ++ + log_debug("Scanning and filtering device args (%u).", dm_list_size(&scan_devs)); + label_scan_devs(cmd, cmd->filter, &scan_devs); + +@@ -5257,6 +5261,7 @@ int pvcreate_each_device(struct cmd_context *cmd, + } + } + cmd->filter_deviceid_skip = 0; ++ cmd->filter_partitioned_skip = 0; + + /* + * Can the command continue if some specified devices were not found? +@@ -5469,6 +5474,9 @@ do_command: + if (cmd->enable_devices_file && !pp->is_remove) + cmd->filter_deviceid_skip = 1; + ++ if (pp->force && !pp->is_remove) ++ cmd->filter_partitioned_skip = 1; ++ + log_debug("Rescanning and filtering device args with exclusive open"); + if (!label_scan_devs_excl(cmd, cmd->filter, &rescan_devs)) { + log_debug("Failed to rescan devs excl"); +@@ -5482,7 +5490,9 @@ do_command: + dm_list_add(&pp->arg_fail, &pd->list); + } + } ++ + cmd->filter_deviceid_skip = 0; ++ cmd->filter_partitioned_skip = 0; + + if (dm_list_empty(&pp->arg_process) && dm_list_empty(&remove_duplicates)) { + log_debug("No devices to process."); +-- +2.34.3 + diff --git a/0026-lvmdevices-check-error-exit-if-update-is-needed.patch b/0026-lvmdevices-check-error-exit-if-update-is-needed.patch new file mode 100644 index 0000000..485b697 --- /dev/null +++ b/0026-lvmdevices-check-error-exit-if-update-is-needed.patch @@ -0,0 +1,166 @@ +From bb477d63e336a10e5959962a9f26a028ea9e55eb Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 13 Jan 2022 14:52:54 -0600 +Subject: [PATCH 26/54] lvmdevices check: error exit if update is needed + +. error exit means that lvmdevices --update would make a change. + +. remove check of PART field from --check because it isn't used. + +. unlink searched_devnames file to ensure check|update will search +--- + lib/device/device_id.c | 3 ++- + test/shell/devicesfile-realdevs.sh | 8 +++---- + tools/args.h | 3 ++- + tools/lvmdevices.c | 37 +++++++++++++----------------- + 4 files changed, 24 insertions(+), 27 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 0621bc858..a33dcebe0 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -2271,7 +2271,8 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l + continue; + } + +- log_warn("Devices file PVID %s updating IDNAME to %s.", dev->pvid, devname); ++ if (!noupdate) ++ log_warn("Devices file PVID %s updating IDNAME to %s.", dev->pvid, devname); + + free(du->idname); + free(du->devname); +diff --git a/test/shell/devicesfile-realdevs.sh b/test/shell/devicesfile-realdevs.sh +index 8d4aa3e67..23d4bedb4 100644 +--- a/test/shell/devicesfile-realdevs.sh ++++ b/test/shell/devicesfile-realdevs.sh +@@ -423,7 +423,7 @@ sed "s/$pvid1/badpvid/" "$DF.orig" |tee $DF + not grep $pvid1 $DF + grep $did1 $DF + +-lvmdevices --check 2>&1|tee out ++not lvmdevices --check 2>&1|tee out + grep $dev1 out + grep badpvid out + grep $pvid1 out +@@ -493,7 +493,7 @@ rm $DF + d1=$(basename $dev1) + d3=$(basename $dev3) + sed "s/$d1/$d3/" "$DF.orig" |tee $DF +-lvmdevices --check 2>&1 |tee out ++not lvmdevices --check 2>&1 |tee out + grep $dev1 out + + lvmdevices --update +@@ -515,7 +515,7 @@ sed "s/$d1/tmp/" "$DF.orig" |tee ${DF}_1 + sed "s/$d2/$d1/" "${DF}_1" |tee ${DF}_2 + sed "s/tmp/$d2/" "${DF}_2" |tee $DF + rm ${DF}_1 ${DF}_2 +-lvmdevices --check 2>&1 |tee out ++not lvmdevices --check 2>&1 |tee out + grep $dev1 out + grep $dev2 out + +@@ -536,7 +536,7 @@ rm $DF + d1=$(basename $dev1) + d3=$(basename $dev3) + sed "s/$d1/$d3/" "$DF.orig" |tee $DF +-lvmdevices --check 2>&1 |tee out ++not lvmdevices --check 2>&1 |tee out + grep $dev1 out + + pvs -o+uuid,deviceid | grep $vg |tee out +diff --git a/tools/args.h b/tools/args.h +index 774ce33f4..9a7bf81b2 100644 +--- a/tools/args.h ++++ b/tools/args.h +@@ -153,7 +153,8 @@ arg(cachesize_ARG, '\0', "cachesize", sizemb_VAL, 0, 0, + "The size of cache to use.\n") + + arg(check_ARG, '\0', "check", 0, 0, 0, +- "Check the content of the devices file.\n") ++ "Checks the content of the devices file.\n" ++ "Reports incorrect device names or PVIDs for entries.\n") + + arg(commandprofile_ARG, '\0', "commandprofile", string_VAL, 0, 0, + "The command profile to use for command configuration.\n" +diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c +index 3f104f7de..c50c09f90 100644 +--- a/tools/lvmdevices.c ++++ b/tools/lvmdevices.c +@@ -128,7 +128,6 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv) + struct device *dev; + struct dev_use *du, *du2; + const char *deviceidtype; +- int changes = 0; + + dm_list_init(&search_pvids); + dm_list_init(&found_devs); +@@ -184,8 +183,11 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv) + + if (arg_is_set(cmd, check_ARG) || arg_is_set(cmd, update_ARG)) { + int search_count = 0; ++ int update_needed = 0; + int invalid = 0; + ++ unlink_searched_devnames(cmd); ++ + label_scan_setup_bcache(); + + dm_list_iterate_items(du, &cmd->use_devices) { +@@ -225,6 +227,8 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv) + * run just above. + */ + device_ids_validate(cmd, NULL, &invalid, 1); ++ if (invalid) ++ update_needed = 1; + + /* + * Find and fix any devname entries that have moved to a +@@ -240,33 +244,24 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv) + label_scan_invalidate(du->dev); + } + +- /* +- * check du->part +- */ +- dm_list_iterate_items(du, &cmd->use_devices) { +- int part = 0; +- if (!du->dev) +- continue; +- dev = du->dev; +- +- dev_get_partition_number(dev, &part); +- +- if (part != du->part) { +- log_warn("Device %s partition %u has incorrect PART in devices file (%u)", +- dev_name(dev), part, du->part); +- du->part = part; +- changes++; +- } +- } +- + if (arg_is_set(cmd, update_ARG)) { +- if (invalid || !dm_list_empty(&found_devs)) { ++ if (update_needed || !dm_list_empty(&found_devs)) { + if (!device_ids_write(cmd)) + goto_bad; + log_print("Updated devices file to version %s", devices_file_version()); + } else { + log_print("No update for devices file is needed."); + } ++ } else { ++ /* ++ * --check exits with an error if the devices file ++ * needs updates, i.e. running --update would make ++ * changes. ++ */ ++ if (update_needed) { ++ log_error("Updates needed for devices file."); ++ goto bad; ++ } + } + goto out; + } +-- +2.34.3 + diff --git a/0027-Revert-pvcreate-overwrite-partition-header-with-f.patch b/0027-Revert-pvcreate-overwrite-partition-header-with-f.patch new file mode 100644 index 0000000..337a61d --- /dev/null +++ b/0027-Revert-pvcreate-overwrite-partition-header-with-f.patch @@ -0,0 +1,140 @@ +From 9375aebad1db72267dd67e3ed768aa3b0e698d52 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 18 Jan 2022 12:16:52 -0600 +Subject: [PATCH 27/54] Revert "pvcreate: overwrite partition header with -f" + +This reverts commit a5c37afdca97d6565ea02bc4bc7d52f360823cd3. + +This commit did not properly recognize GPT cases. +--- + lib/commands/toolcontext.h | 1 - + lib/filters/filter-partitioned.c | 3 --- + man/pvcreate.8_des | 7 +++---- + test/shell/test-partition.sh | 12 ++---------- + tools/toollib.c | 10 ---------- + 5 files changed, 5 insertions(+), 28 deletions(-) + +diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h +index b83883fb8..356c79f8a 100644 +--- a/lib/commands/toolcontext.h ++++ b/lib/commands/toolcontext.h +@@ -201,7 +201,6 @@ struct cmd_context { + unsigned ignore_device_name_mismatch:1; /* skip updating devices file names */ + unsigned backup_disabled:1; /* skip repeated debug message */ + unsigned event_activation:1; /* whether event_activation is set */ +- unsigned filter_partitioned_skip:1; /* don't use filter-partitioned */ + + /* + * Devices and filtering. +diff --git a/lib/filters/filter-partitioned.c b/lib/filters/filter-partitioned.c +index 8f468a567..642553ef2 100644 +--- a/lib/filters/filter-partitioned.c ++++ b/lib/filters/filter-partitioned.c +@@ -27,9 +27,6 @@ static int _passes_partitioned_filter(struct cmd_context *cmd, struct dev_filter + if (cmd->filter_nodata_only) + return 1; + +- if (cmd->filter_partitioned_skip) +- return 1; +- + dev->filtered_flags &= ~DEV_FILTERED_PARTITIONED; + + ret = dev_is_partitioned(cmd, dev); +diff --git a/man/pvcreate.8_des b/man/pvcreate.8_des +index 4048eb71c..69bd133aa 100644 +--- a/man/pvcreate.8_des ++++ b/man/pvcreate.8_des +@@ -7,10 +7,9 @@ Use \fBvgcreate\fP(8) to create a new VG on the PV, or \fBvgextend\fP(8) + to add the PV to an existing VG. Use \fBpvremove\fP(8) to remove the LVM + disk label from the device. + .P +-The force option will create a PV without confirmation, and will overwrite +-partition headers. Repeating the force option (\fB-ff\fP) will override other +-checks that would normally prevent a pvcreate, e.g. if the PV is already in a +-VG. ++The force option will create a PV without confirmation. Repeating the ++force option (\fB-ff\fP) will forcibly create a PV, overriding checks that ++normally prevent it, e.g. if the PV is already in a VG. + .P + .B Metadata location, size, and alignment + .P +diff --git a/test/shell/test-partition.sh b/test/shell/test-partition.sh +index 3a45f9089..0e92f00db 100644 +--- a/test/shell/test-partition.sh ++++ b/test/shell/test-partition.sh +@@ -16,6 +16,7 @@ + # + + ++ + SKIP_WITH_LVMPOLLD=1 + + LVM_TEST_CONFIG_DEVICES="types = [\"device-mapper\", 142]" +@@ -24,7 +25,7 @@ LVM_TEST_CONFIG_DEVICES="types = [\"device-mapper\", 142]" + + which sfdisk || skip + +-aux prepare_pvs 2 30 ++aux prepare_pvs 1 30 + + pvs "$dev1" + +@@ -32,12 +33,3 @@ pvs "$dev1" + echo "1 2" | sfdisk --force "$dev1" + + not pvs "$dev1" +- +-wipefs -a "$dev2" +-echo "1 2" | sfdisk --force "$dev2" +-partprobe +-not pvcreate "$dev2" +-pvcreate -f "$dev2" +-pvs "$dev2" +-pvremove "$dev2" +- +diff --git a/tools/toollib.c b/tools/toollib.c +index 80d3de57c..d6f48aad2 100644 +--- a/tools/toollib.c ++++ b/tools/toollib.c +@@ -5243,10 +5243,6 @@ int pvcreate_each_device(struct cmd_context *cmd, + if (cmd->enable_devices_file && !pp->is_remove) + cmd->filter_deviceid_skip = 1; + +- /* pvcreate -f overwrites partitions */ +- if (pp->force && !pp->is_remove) +- cmd->filter_partitioned_skip = 1; +- + log_debug("Scanning and filtering device args (%u).", dm_list_size(&scan_devs)); + label_scan_devs(cmd, cmd->filter, &scan_devs); + +@@ -5261,7 +5257,6 @@ int pvcreate_each_device(struct cmd_context *cmd, + } + } + cmd->filter_deviceid_skip = 0; +- cmd->filter_partitioned_skip = 0; + + /* + * Can the command continue if some specified devices were not found? +@@ -5474,9 +5469,6 @@ do_command: + if (cmd->enable_devices_file && !pp->is_remove) + cmd->filter_deviceid_skip = 1; + +- if (pp->force && !pp->is_remove) +- cmd->filter_partitioned_skip = 1; +- + log_debug("Rescanning and filtering device args with exclusive open"); + if (!label_scan_devs_excl(cmd, cmd->filter, &rescan_devs)) { + log_debug("Failed to rescan devs excl"); +@@ -5490,9 +5482,7 @@ do_command: + dm_list_add(&pp->arg_fail, &pd->list); + } + } +- + cmd->filter_deviceid_skip = 0; +- cmd->filter_partitioned_skip = 0; + + if (dm_list_empty(&pp->arg_process) && dm_list_empty(&remove_duplicates)) { + log_debug("No devices to process."); +-- +2.34.3 + diff --git a/0028-devices-exclude-multipath-components-based-on-matchi.patch b/0028-devices-exclude-multipath-components-based-on-matchi.patch new file mode 100644 index 0000000..8646d04 --- /dev/null +++ b/0028-devices-exclude-multipath-components-based-on-matchi.patch @@ -0,0 +1,462 @@ +From 5403a6f05987b21addb50c9b056e36567d631df7 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 17 Nov 2021 17:10:45 -0600 +Subject: [PATCH 28/54] devices: exclude multipath components based on matching + wwid + +If multipath component devices get through the filter and +cause lvm to see duplicate PVs, then check the wwid of the +devs and drop the component devices as if they had been +filtered. If a dm mpath device was found among the duplicates +then use that as the PV, otherwise do not use any of the +components as the PV. + +"duplicate PVs" associated with multipath configs will no +longer stop commands from working. +--- + lib/cache/lvmcache.c | 186 +++++++++++++++++++++++++- + lib/device/dev-mpath.c | 71 ++++++++++ + lib/device/dev-type.h | 2 + + lib/device/device_id.c | 4 +- + lib/device/device_id.h | 2 + + test/shell/duplicate-pvs-multipath.sh | 67 ++++++++++ + 6 files changed, 323 insertions(+), 9 deletions(-) + create mode 100644 test/shell/duplicate-pvs-multipath.sh + +diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c +index bee63ebb4..a0811d4ea 100644 +--- a/lib/cache/lvmcache.c ++++ b/lib/cache/lvmcache.c +@@ -625,6 +625,102 @@ static void _warn_unused_duplicates(struct cmd_context *cmd) + } + } + ++static int _all_multipath_components(struct cmd_context *cmd, struct lvmcache_info *info, const char *pvid, ++ struct dm_list *altdevs, struct device **dev_mpath) ++{ ++ struct device_list *devl; ++ struct device *dev_mp = NULL; ++ struct device *dev1 = NULL; ++ struct device *dev; ++ const char *wwid1 = NULL; ++ const char *wwid; ++ int diff_wwid = 0; ++ int same_wwid = 0; ++ int dev_is_mp; ++ ++ *dev_mpath = NULL; ++ ++ /* This function only makes sense with more than one dev. */ ++ if ((info && dm_list_empty(altdevs)) || (!info && (dm_list_size(altdevs) == 1))) { ++ log_debug("Skip multipath component checks with single device for PVID %s", pvid); ++ return 0; ++ } ++ ++ log_debug("Checking for multipath components for duplicate PVID %s", pvid); ++ ++ if (info) { ++ dev = info->dev; ++ dev_is_mp = (cmd->dev_types->device_mapper_major == MAJOR(dev->dev)) && dev_has_mpath_uuid(cmd, dev, NULL); ++ ++ if (dev_is_mp) { ++ if ((wwid1 = dev_mpath_component_wwid(cmd, dev))) { ++ dev_mp = dev; ++ dev1 = dev; ++ } ++ } else { ++ if ((wwid1 = device_id_system_read(cmd, dev, DEV_ID_TYPE_SYS_WWID))) ++ dev1 = dev; ++ } ++ } ++ ++ dm_list_iterate_items(devl, altdevs) { ++ dev = devl->dev; ++ dev_is_mp = (cmd->dev_types->device_mapper_major == MAJOR(dev->dev)) && dev_has_mpath_uuid(cmd, dev, NULL); ++ ++ if (dev_is_mp) ++ wwid = dev_mpath_component_wwid(cmd, dev); ++ else ++ wwid = device_id_system_read(cmd, dev, DEV_ID_TYPE_SYS_WWID); ++ ++ if (!wwid && wwid1) { ++ log_print("Different wwids for duplicate PVs %s %s %s none", ++ dev_name(dev1), wwid1, dev_name(dev)); ++ diff_wwid++; ++ continue; ++ } ++ ++ if (!wwid) ++ continue; ++ ++ if (!wwid1) { ++ wwid1 = wwid; ++ dev1 = dev; ++ continue; ++ } ++ ++ /* Different wwids indicates these are not multipath components. */ ++ if (strcmp(wwid1, wwid)) { ++ log_print("Different wwids for duplicate PVs %s %s %s %s", ++ dev_name(dev1), wwid1, dev_name(dev), wwid); ++ diff_wwid++; ++ continue; ++ } ++ ++ /* Different mpath devs with the same wwid shouldn't happen. */ ++ if (dev_is_mp && dev_mp) { ++ log_print("Found multiple multipath devices for PVID %s WWID %s: %s %s", ++ pvid, wwid1, dev_name(dev_mp), dev_name(dev)); ++ continue; ++ } ++ ++ log_debug("Same wwids for duplicate PVs %s %s", dev_name(dev1), dev_name(dev)); ++ same_wwid++; ++ ++ /* Save the mpath device so it can be used as the PV. */ ++ if (dev_is_mp) ++ dev_mp = dev; ++ } ++ ++ if (diff_wwid || !same_wwid) ++ return 0; ++ ++ if (dev_mp) ++ log_debug("Found multipath device %s for PVID %s WWID %s.", dev_name(dev_mp), pvid, wwid1); ++ ++ *dev_mpath = dev_mp; ++ return 1; ++} ++ + /* + * If we've found devices with the same PVID, decide which one + * to use. +@@ -680,6 +776,8 @@ static void _choose_duplicates(struct cmd_context *cmd, + struct device_list *devl, *devl_safe, *devl_add, *devl_del; + struct lvmcache_info *info; + struct device *dev1, *dev2; ++ struct device *dev_mpath; ++ struct device *dev_drop; + const char *device_id = NULL, *device_id_type = NULL; + const char *idname1 = NULL, *idname2 = NULL; + uint32_t dev1_major, dev1_minor, dev2_major, dev2_minor; +@@ -702,6 +800,7 @@ static void _choose_duplicates(struct cmd_context *cmd, + next: + dm_list_init(&altdevs); + pvid = NULL; ++ dev_mpath = NULL; + + dm_list_iterate_items_safe(devl, devl_safe, &_initial_duplicates) { + if (!pvid) { +@@ -720,23 +819,97 @@ next: + return; + } + ++ info = lvmcache_info_from_pvid(pvid, NULL, 0); ++ + /* +- * Get rid of any md components before comparing alternatives. +- * (Since an md component can never be used, it's not an +- * option to use like other kinds of alternatives.) ++ * Usually and ideally, components of md and multipath devs should have ++ * been excluded by filters, and not scanned for a PV. In some unusual ++ * cases the components can get through the filters, and a PV can be ++ * found on them. Detecting the same PVID on both the component and ++ * the md/mpath device gives us a last chance to drop the component. ++ * An md/mpath component device is completely ignored, as if it had ++ * been filtered, and not kept in the list unused duplicates. + */ + +- info = lvmcache_info_from_pvid(pvid, NULL, 0); ++ /* ++ * Get rid of multipath components based on matching wwids. ++ */ ++ if (_all_multipath_components(cmd, info, pvid, &altdevs, &dev_mpath)) { ++ if (info && dev_mpath && (info->dev != dev_mpath)) { ++ /* ++ * info should be dropped from lvmcache and info->dev ++ * should be treated as if it had been excluded by a filter. ++ * dev_mpath should be added to lvmcache by the caller. ++ */ ++ dev_drop = info->dev; ++ ++ /* Have caller add dev_mpath to lvmcache. */ ++ log_debug("Using multipath device %s for PVID %s.", dev_name(dev_mpath), pvid); ++ if ((devl_add = zalloc(sizeof(*devl_add)))) { ++ devl_add->dev = dev_mpath; ++ dm_list_add(add_cache_devs, &devl_add->list); ++ } ++ ++ /* Remove dev_mpath from altdevs. */ ++ if ((devl = _get_devl_in_device_list(dev_mpath, &altdevs))) ++ dm_list_del(&devl->list); ++ ++ /* Remove info from lvmcache that came from the component dev. */ ++ log_debug("Ignoring multipath component %s with PVID %s (dropping info)", dev_name(dev_drop), pvid); ++ lvmcache_del(info); ++ info = NULL; ++ ++ /* Make the component dev look like it was filtered. */ ++ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL); ++ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL; ++ } ++ ++ if (info && !dev_mpath) { ++ /* ++ * Only mpath component devs were found and no actual ++ * multipath dev, so drop the component from lvmcache. ++ */ ++ dev_drop = info->dev; ++ ++ log_debug("Ignoring multipath component %s with PVID %s (dropping info)", dev_name(dev_drop), pvid); ++ lvmcache_del(info); ++ info = NULL; ++ ++ /* Make the component dev look like it was filtered. */ ++ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL); ++ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL; ++ } ++ ++ dm_list_iterate_items_safe(devl, devl_safe, &altdevs) { ++ /* ++ * The altdevs are all mpath components that should look ++ * like they were filtered, they are not in lvmcache. ++ */ ++ dev_drop = devl->dev; ++ ++ log_debug("Ignoring multipath component %s with PVID %s (dropping duplicate)", dev_name(dev_drop), pvid); ++ dm_list_del(&devl->list); ++ ++ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL); ++ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL; ++ } ++ goto next; ++ } ++ ++ /* ++ * Get rid of any md components. ++ * FIXME: use a function like _all_multipath_components to pick the actual md device. ++ */ + if (info && dev_is_md_component(cmd, info->dev, NULL, 1)) { + /* does not go in del_cache_devs which become unused_duplicates */ +- log_debug_cache("PV %s drop MD component from scan selection %s", pvid, dev_name(info->dev)); ++ log_debug("Ignoring md component %s with PVID %s (dropping info)", dev_name(info->dev), pvid); + lvmcache_del(info); + info = NULL; + } + + dm_list_iterate_items_safe(devl, devl_safe, &altdevs) { + if (dev_is_md_component(cmd, devl->dev, NULL, 1)) { +- log_debug_cache("PV %s drop MD component from scan duplicates %s", pvid, dev_name(devl->dev)); ++ log_debug("Ignoring md component %s with PVID %s (dropping duplicate)", dev_name(devl->dev), pvid); + dm_list_del(&devl->list); + } + } +@@ -744,7 +917,6 @@ next: + if (dm_list_empty(&altdevs)) + goto next; + +- + /* + * Find the device for the pvid that's currently in lvmcache. + */ +diff --git a/lib/device/dev-mpath.c b/lib/device/dev-mpath.c +index ba7bf9740..cbbad9dc9 100644 +--- a/lib/device/dev-mpath.c ++++ b/lib/device/dev-mpath.c +@@ -482,3 +482,74 @@ found: + return 1; + } + ++const char *dev_mpath_component_wwid(struct cmd_context *cmd, struct device *dev) ++{ ++ char slaves_path[PATH_MAX]; ++ char wwid_path[PATH_MAX]; ++ char sysbuf[PATH_MAX] = { 0 }; ++ char *slave_name; ++ const char *wwid = NULL; ++ struct stat info; ++ DIR *dr; ++ struct dirent *de; ++ ++ /* /sys/dev/block/253:7/slaves/sda/device/wwid */ ++ ++ if (dm_snprintf(slaves_path, sizeof(slaves_path), "%s/dev/block/%d:%d/slaves", ++ dm_sysfs_dir(), (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) { ++ log_warn("Sysfs path to check mpath components is too long."); ++ return NULL; ++ } ++ ++ if (stat(slaves_path, &info)) ++ return NULL; ++ ++ if (!S_ISDIR(info.st_mode)) { ++ log_warn("Path %s is not a directory.", slaves_path); ++ return NULL; ++ } ++ ++ /* Get wwid from first component */ ++ ++ if (!(dr = opendir(slaves_path))) { ++ log_debug("Device %s has no slaves dir", dev_name(dev)); ++ return NULL; ++ } ++ ++ while ((de = readdir(dr))) { ++ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) ++ continue; ++ ++ /* slave_name "sda" */ ++ slave_name = de->d_name; ++ ++ /* read /sys/block/sda/device/wwid */ ++ ++ if (dm_snprintf(wwid_path, sizeof(wwid_path), "%s/block/%s/device/wwid", ++ dm_sysfs_dir(), slave_name) < 0) { ++ log_warn("Failed to create sysfs wwid path for %s", slave_name); ++ continue; ++ } ++ ++ get_sysfs_value(wwid_path, sysbuf, sizeof(sysbuf), 0); ++ if (!sysbuf[0]) ++ continue; ++ ++ if (strstr(sysbuf, "scsi_debug")) { ++ int i; ++ for (i = 0; i < strlen(sysbuf); i++) { ++ if (sysbuf[i] == ' ') ++ sysbuf[i] = '_'; ++ } ++ } ++ ++ if ((wwid = dm_pool_strdup(cmd->mem, sysbuf))) ++ break; ++ } ++ if (closedir(dr)) ++ stack; ++ ++ return wwid; ++} ++ ++ +diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h +index f3521c6e0..36fb8f258 100644 +--- a/lib/device/dev-type.h ++++ b/lib/device/dev-type.h +@@ -63,6 +63,8 @@ int dev_is_swap(struct cmd_context *cmd, struct device *dev, uint64_t *signature + int dev_is_luks(struct cmd_context *cmd, struct device *dev, uint64_t *signature, int full); + int dasd_is_cdl_formatted(struct device *dev); + ++const char *dev_mpath_component_wwid(struct cmd_context *cmd, struct device *dev); ++ + int dev_is_lvm1(struct device *dev, char *buf, int buflen); + int dev_is_pool(struct device *dev, char *buf, int buflen); + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index a33dcebe0..625576ec6 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -243,7 +243,7 @@ static int _dm_uuid_has_prefix(char *sysbuf, const char *prefix) + } + + /* the dm uuid uses the wwid of the underlying dev */ +-static int _dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out) ++int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out) + { + char sysbuf[PATH_MAX] = { 0 }; + const char *idname; +@@ -988,7 +988,7 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_ + } + + if (MAJOR(dev->dev) == cmd->dev_types->device_mapper_major) { +- if (_dev_has_mpath_uuid(cmd, dev, &idname)) { ++ if (dev_has_mpath_uuid(cmd, dev, &idname)) { + idtype = DEV_ID_TYPE_MPATH_UUID; + goto id_done; + } +diff --git a/lib/device/device_id.h b/lib/device/device_id.h +index 939b3a0f4..4cf1374c8 100644 +--- a/lib/device/device_id.h ++++ b/lib/device/device_id.h +@@ -55,4 +55,6 @@ void unlink_searched_devnames(struct cmd_context *cmd); + + int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize); + ++int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out); ++ + #endif +diff --git a/test/shell/duplicate-pvs-multipath.sh b/test/shell/duplicate-pvs-multipath.sh +new file mode 100644 +index 000000000..a145e4afb +--- /dev/null ++++ b/test/shell/duplicate-pvs-multipath.sh +@@ -0,0 +1,67 @@ ++#!/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_description='udev rule and systemd unit run vgchange' ++ ++SKIP_WITH_LVMPOLLD=1 ++SKIP_WITH_LVMLOCKD=1 ++ ++. lib/inittest ++ ++# FIXME: skip until mpath/scsi_debug cleanup works after a failure ++skip ++ ++modprobe --dry-run scsi_debug || skip ++multipath -l || skip ++multipath -l | grep scsi_debug && skip ++ ++# Turn off multipath_component_detection so that the duplicate ++# resolution of mpath components is used. ++aux lvmconf 'devices/multipath_component_detection = 0' ++# Prevent wwids from being used for filtering. ++aux lvmconf 'devices/multipath_wwids_file = "/dev/null"' ++# Need to use /dev/mapper/mpath ++aux lvmconf 'devices/dir = "/dev"' ++aux lvmconf 'devices/scan = "/dev"' ++# Could set filter to $MP and the component /dev/sd devs ++aux lvmconf "devices/filter = [ \"a|.*|\" ]" ++aux lvmconf "devices/global_filter = [ \"a|.*|\" ]" ++ ++modprobe scsi_debug dev_size_mb=100 num_tgts=1 vpd_use_hostno=0 add_host=4 delay=20 max_luns=2 no_lun_0=1 ++sleep 2 ++ ++multipath -r ++sleep 2 ++ ++MPB=$(multipath -l | grep scsi_debug | cut -f1 -d ' ') ++echo $MPB ++MP=/dev/mapper/$MPB ++echo $MP ++ ++pvcreate $MP ++vgcreate $vg1 $MP ++lvcreate -l1 $vg1 ++vgchange -an $vg1 ++ ++pvs |tee out ++grep $MP out ++for i in $(grep -H scsi_debug /sys/block/sd*/device/model | cut -f4 -d /); do ++ not grep /dev/$i out; ++done ++ ++vgchange -an $vg1 ++vgremove -y $vg1 ++ ++sleep 2 ++multipath -f $MP ++sleep 1 ++rmmod scsi_debug +-- +2.34.3 + diff --git a/0029-devices-exclude-md-components-when-duplicate-pvs-are.patch b/0029-devices-exclude-md-components-when-duplicate-pvs-are.patch new file mode 100644 index 0000000..6dbb455 --- /dev/null +++ b/0029-devices-exclude-md-components-when-duplicate-pvs-are.patch @@ -0,0 +1,268 @@ +From 7b79acc6161b2cff81a03848c160dd6993a4477b Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 22 Nov 2021 15:10:43 -0600 +Subject: [PATCH 29/54] devices: exclude md components when duplicate pvs are + seen + +Improve handling of md components that get through the +filter, like the previous improvement for multipath. +If md components get through the filter and trigger +duplicate PV code, then eliminate any devs entirely +that are not an md device. +--- + lib/cache/lvmcache.c | 168 ++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 149 insertions(+), 19 deletions(-) + +diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c +index a0811d4ea..0e62cd267 100644 +--- a/lib/cache/lvmcache.c ++++ b/lib/cache/lvmcache.c +@@ -673,7 +673,7 @@ static int _all_multipath_components(struct cmd_context *cmd, struct lvmcache_in + wwid = device_id_system_read(cmd, dev, DEV_ID_TYPE_SYS_WWID); + + if (!wwid && wwid1) { +- log_print("Different wwids for duplicate PVs %s %s %s none", ++ log_debug("Different wwids for duplicate PVs %s %s %s none", + dev_name(dev1), wwid1, dev_name(dev)); + diff_wwid++; + continue; +@@ -690,7 +690,7 @@ static int _all_multipath_components(struct cmd_context *cmd, struct lvmcache_in + + /* Different wwids indicates these are not multipath components. */ + if (strcmp(wwid1, wwid)) { +- log_print("Different wwids for duplicate PVs %s %s %s %s", ++ log_debug("Different wwids for duplicate PVs %s %s %s %s", + dev_name(dev1), wwid1, dev_name(dev), wwid); + diff_wwid++; + continue; +@@ -721,6 +721,52 @@ static int _all_multipath_components(struct cmd_context *cmd, struct lvmcache_in + return 1; + } + ++static int _all_md_components(struct cmd_context *cmd, struct lvmcache_info *info, const char *pvid, ++ struct dm_list *altdevs, struct device **dev_md_out) ++{ ++ struct device_list *devl; ++ struct device *dev_md = NULL; ++ struct device *dev; ++ int real_dup = 0; ++ ++ *dev_md_out = NULL; ++ ++ /* There will often be no info struct because of the extra_md_checks function. */ ++ ++ if (info && (cmd->dev_types->md_major == MAJOR(info->dev->dev))) ++ dev_md = info->dev; ++ ++ dm_list_iterate_items(devl, altdevs) { ++ dev = devl->dev; ++ ++ if (cmd->dev_types->md_major == MAJOR(dev->dev)) { ++ if (dev_md) { ++ /* md devs themselves are dups */ ++ log_debug("Found multiple md devices for PVID %s: %s %s", ++ pvid, dev_name(dev_md), dev_name(dev)); ++ real_dup = 1; ++ break; ++ } else ++ dev_md = dev; ++ } else { ++ if (!dev_is_md_component(cmd, dev, NULL, 1)) { ++ /* md dev copied to another device */ ++ real_dup = 1; ++ break; ++ } ++ } ++ } ++ ++ if (real_dup) ++ return 0; ++ ++ if (dev_md) ++ log_debug("Found md device %s for PVID %s.", dev_name(dev_md), pvid); ++ ++ *dev_md_out = dev_md; ++ return 1; ++} ++ + /* + * If we've found devices with the same PVID, decide which one + * to use. +@@ -776,7 +822,7 @@ static void _choose_duplicates(struct cmd_context *cmd, + struct device_list *devl, *devl_safe, *devl_add, *devl_del; + struct lvmcache_info *info; + struct device *dev1, *dev2; +- struct device *dev_mpath; ++ struct device *dev_mpath, *dev_md; + struct device *dev_drop; + const char *device_id = NULL, *device_id_type = NULL; + const char *idname1 = NULL, *idname2 = NULL; +@@ -801,6 +847,7 @@ next: + dm_list_init(&altdevs); + pvid = NULL; + dev_mpath = NULL; ++ dev_md = NULL; + + dm_list_iterate_items_safe(devl, devl_safe, &_initial_duplicates) { + if (!pvid) { +@@ -829,6 +876,11 @@ next: + * the md/mpath device gives us a last chance to drop the component. + * An md/mpath component device is completely ignored, as if it had + * been filtered, and not kept in the list unused duplicates. ++ * ++ * One issue related to eliminating mpath/md duplicate PVs here is ++ * that it occurs after label_scan, and hints are created based ++ * on what label_scan finds, so hints are disabled due to duplicate ++ * PVs that are later resolved here. + */ + + /* +@@ -898,24 +950,89 @@ next: + + /* + * Get rid of any md components. +- * FIXME: use a function like _all_multipath_components to pick the actual md device. + */ +- if (info && dev_is_md_component(cmd, info->dev, NULL, 1)) { +- /* does not go in del_cache_devs which become unused_duplicates */ +- log_debug("Ignoring md component %s with PVID %s (dropping info)", dev_name(info->dev), pvid); +- lvmcache_del(info); +- info = NULL; +- } ++ if (_all_md_components(cmd, info, pvid, &altdevs, &dev_md)) { ++ if (info && dev_md && (info->dev != dev_md)) { ++ /* ++ * info should be dropped from lvmcache and info->dev ++ * should be treated as if it had been excluded by a filter. ++ * dev_md should be added to lvmcache by the caller. ++ * Often this info struct has been removed by ++ * lvmcache_extra_md_component_checks. ++ */ ++ dev_drop = info->dev; + +- dm_list_iterate_items_safe(devl, devl_safe, &altdevs) { +- if (dev_is_md_component(cmd, devl->dev, NULL, 1)) { +- log_debug("Ignoring md component %s with PVID %s (dropping duplicate)", dev_name(devl->dev), pvid); +- dm_list_del(&devl->list); ++ /* Have caller add dev_md to lvmcache. */ ++ log_debug("Using md device %s for PVID %s.", dev_name(dev_md), pvid); ++ if ((devl_add = zalloc(sizeof(*devl_add)))) { ++ devl_add->dev = dev_md; ++ dm_list_add(add_cache_devs, &devl_add->list); ++ } ++ ++ /* Remove dev_md from altdevs. */ ++ if ((devl = _get_devl_in_device_list(dev_md, &altdevs))) ++ dm_list_del(&devl->list); ++ ++ /* Remove info from lvmcache that came from the component dev. */ ++ log_debug("Ignoring md component %s with PVID %s (dropping info)", dev_name(dev_drop), pvid); ++ lvmcache_del(info); ++ info = NULL; ++ ++ /* Make the component dev look like it was filtered. */ ++ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL); ++ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL; + } +- } + +- if (dm_list_empty(&altdevs)) ++ if (!info && dev_md) { ++ /* ++ * The info struct was from a component and was dropped ++ * and the actual md dev was found on initial_duplicates ++ * and the caller should add it to lvmcache. ++ */ ++ ++ /* Have caller add dev_md to lvmcache. */ ++ log_debug("Using md device %s for PVID %s.", dev_name(dev_md), pvid); ++ if ((devl_add = zalloc(sizeof(*devl_add)))) { ++ devl_add->dev = dev_md; ++ dm_list_add(add_cache_devs, &devl_add->list); ++ } ++ ++ /* Remove dev_md from altdevs. */ ++ if ((devl = _get_devl_in_device_list(dev_md, &altdevs))) ++ dm_list_del(&devl->list); ++ } ++ ++ if (info && !dev_md) { ++ /* ++ * Only md component devs were found and no actual ++ * md dev, so drop the component from lvmcache. ++ */ ++ dev_drop = info->dev; ++ ++ log_debug("Ignoring md component %s with PVID %s (dropping info)", dev_name(dev_drop), pvid); ++ lvmcache_del(info); ++ info = NULL; ++ ++ /* Make the component dev look like it was filtered. */ ++ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL); ++ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL; ++ } ++ ++ dm_list_iterate_items_safe(devl, devl_safe, &altdevs) { ++ /* ++ * The altdevs are all md components that should look ++ * like they were filtered, they are not in lvmcache. ++ */ ++ dev_drop = devl->dev; ++ ++ log_debug("Ignoring md component %s with PVID %s (dropping duplicate)", dev_name(dev_drop), pvid); ++ dm_list_del(&devl->list); ++ ++ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL); ++ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL; ++ } + goto next; ++ } + + /* + * Find the device for the pvid that's currently in lvmcache. +@@ -1321,6 +1438,18 @@ int lvmcache_label_reopen_vg_rw(struct cmd_context *cmd, const char *vgname, con + * times it can be a clue that label_scan mistakenly read the pv from an md + * component device instead of from the md device itself. So for unmatching + * sizes, we do a full md component check on the device. ++ * ++ * It might be nice to do this checking in the filter (when passes_filter is ++ * called after the initial read), but that doesn't work because passes_filter ++ * is called before _text_read so metadata/pvsummary info is not yet available ++ * which this function uses. ++ * ++ * The unique value of this function is that it can eliminate md components ++ * without there being duplicate PVs. But, there will often be duplicate PVs, ++ * handled by _all_md_components(), where other devs with the same pvid will be ++ * in _initial_duplicates. One could be the md device itself which will be ++ * added to lvmcache by choose_duplicates, and other duplicates that are ++ * components will be dropped. + */ + + void lvmcache_extra_md_component_checks(struct cmd_context *cmd) +@@ -1382,7 +1511,8 @@ void lvmcache_extra_md_component_checks(struct cmd_context *cmd) + */ + if (pvsize && devsize && (pvsize != devsize)) + do_check_size = 1; +- if (device_hint && !strncmp(device_hint, "/dev/md", 7)) ++ if (device_hint && !strncmp(device_hint, "/dev/md", 7) && ++ (MAJOR(info->dev->dev) != cmd->dev_types->md_major)) + do_check_name = 1; + + if (!do_check_size && !do_check_name) +@@ -1412,11 +1542,11 @@ void lvmcache_extra_md_component_checks(struct cmd_context *cmd) + device_hint ?: "none", dev_name(dev)); + + if (dev_is_md_component(cmd, dev, NULL, 1)) { +- log_debug("dropping PV from md component %s", dev_name(dev)); ++ log_debug("Ignoring PV from md component %s with PVID %s (metadata %s %llu)", ++ dev_name(dev), dev->pvid, device_hint ?: "none", (unsigned long long)pvsize); + dev->flags &= ~DEV_SCAN_FOUND_LABEL; + /* lvmcache_del will also delete vginfo if info was last one */ + lvmcache_del(info); +- lvmcache_del_dev_from_duplicates(dev); + cmd->filter->wipe(cmd, cmd->filter, dev, NULL); + } + } +-- +2.34.3 + diff --git a/0030-lvmdevices-fix-checks-when-adding-entries.patch b/0030-lvmdevices-fix-checks-when-adding-entries.patch new file mode 100644 index 0000000..75eb9b1 --- /dev/null +++ b/0030-lvmdevices-fix-checks-when-adding-entries.patch @@ -0,0 +1,246 @@ +From 4e72068216b006edc69c8bafba5198051e3ed1dd Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 25 Jan 2022 11:35:36 -0600 +Subject: [PATCH 30/54] lvmdevices: fix checks when adding entries + +Removes some incorrect and unnecessary checks for other entries +when adding a new devices. The removed checks and corrections were +mostly redundant with what is already done by device id matching. +Other checking is reworked so the warnings are a bit different. +--- + lib/device/device_id.c | 153 +++++++++++++---------------------------- + 1 file changed, 48 insertions(+), 105 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 625576ec6..ccc5f43a1 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -935,6 +935,10 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_ + struct dev_use *du, *update_du = NULL, *du_dev, *du_pvid, *du_devname, *du_devid; + struct dev_id *id; + int found_id = 0; ++ int part = 0; ++ ++ if (!dev_get_partition_number(dev, &part)) ++ return_0; + + /* + * When enable_devices_file=0 and pending_devices_file=1 we let +@@ -953,10 +957,6 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_ + */ + memcpy(&pvid, pvid_arg, ID_LEN); + +- du_dev = get_du_for_dev(cmd, dev); +- du_pvid = get_du_for_pvid(cmd, pvid); +- du_devname = _get_du_for_devname(cmd, dev_name(dev)); +- + /* + * Choose the device_id type for the device being added. + * +@@ -1072,6 +1072,9 @@ id_done: + idtype = 0; + + /* ++ * "dev" is the device we are adding. ++ * "id" is the device_id it's using, set in dev->id. ++ * + * Update the cmd->use_devices list for the new device. The + * use_devices list will be used to update the devices file. + * +@@ -1083,23 +1086,57 @@ id_done: + * those other entries to fix any incorrect info. + */ + ++ /* Is there already an entry matched to this device? */ ++ du_dev = get_du_for_dev(cmd, dev); ++ ++ /* Is there already an entry matched to this device's pvid? */ ++ du_pvid = get_du_for_pvid(cmd, pvid); ++ ++ /* Is there already an entry using this device's name? */ ++ du_devname = _get_du_for_devname(cmd, dev_name(dev)); ++ ++ /* Is there already an entry using the device_id for this device? */ + du_devid = _get_du_for_device_id(cmd, id->idtype, id->idname); + + if (du_dev) +- log_debug("device_id_add %s pvid %s matches du_dev %p dev %s", ++ log_debug("device_id_add %s pvid %s matches entry %p dev %s", + dev_name(dev), pvid, du_dev, dev_name(du_dev->dev)); + if (du_pvid) +- log_debug("device_id_add %s pvid %s matches du_pvid %p dev %s pvid %s", ++ log_debug("device_id_add %s pvid %s matches entry %p dev %s with same pvid %s", + dev_name(dev), pvid, du_pvid, du_pvid->dev ? dev_name(du_pvid->dev) : ".", + du_pvid->pvid); + if (du_devid) +- log_debug("device_id_add %s pvid %s matches du_devid %p dev %s pvid %s", ++ log_debug("device_id_add %s pvid %s matches entry %p dev %s with same device_id %d %s", + dev_name(dev), pvid, du_devid, du_devid->dev ? dev_name(du_devid->dev) : ".", +- du_devid->pvid); ++ du_devid->idtype, du_devid->idname); + if (du_devname) +- log_debug("device_id_add %s pvid %s matches du_devname %p dev %s pvid %s", ++ log_debug("device_id_add %s pvid %s matches entry %p dev %s with same devname %s", + dev_name(dev), pvid, du_devname, du_devname->dev ? dev_name(du_devname->dev) : ".", +- du_devname->pvid); ++ du_devname->devname); ++ ++ if (du_pvid && (du_pvid->dev != dev)) ++ log_warn("WARNING: adding device %s with PVID %s which is already used for %s.", ++ dev_name(dev), pvid, du_pvid->dev ? dev_name(du_pvid->dev) : "missing device"); ++ ++ if (du_devid && (du_devid->dev != dev)) { ++ if (!du_devid->dev) { ++ log_warn("WARNING: adding device %s with idname %s which is already used for missing device.", ++ dev_name(dev), id->idname); ++ } else { ++ int ret1, ret2; ++ dev_t devt1, devt2; ++ /* Check if both entries are partitions of the same device. */ ++ ret1 = dev_get_primary_dev(cmd->dev_types, dev, &devt1); ++ ret2 = dev_get_primary_dev(cmd->dev_types, du_devid->dev, &devt2); ++ if ((ret1 == 2) && (ret2 == 2) && (devt1 == devt2)) { ++ log_debug("Using separate entries for partitions of same device %s part %d %s part %d.", ++ dev_name(dev), part, dev_name(du_devid->dev), du_devid->part); ++ } else { ++ log_warn("WARNING: adding device %s with idname %s which is already used for %s.", ++ dev_name(dev), id->idname, dev_name(du_devid->dev)); ++ } ++ } ++ } + + /* + * If one of the existing entries (du_dev, du_pvid, du_devid, du_devname) +@@ -1112,29 +1149,6 @@ id_done: + dm_list_del(&update_du->list); + update_matching_kind = "device"; + update_matching_name = dev_name(dev); +- +- if (du_devid && (du_devid != du_dev)) { +- log_warn("WARNING: device %s (%s) and %s (%s) have duplicate device ID.", +- dev_name(dev), id->idname, +- (du_pvid && du_pvid->dev) ? dev_name(du_pvid->dev) : "none", +- du_pvid ? du_pvid->idname : ""); +- } +- +- if (du_pvid && (du_pvid != du_dev)) { +- log_warn("WARNING: device %s (%s) and %s (%s) have duplicate PVID %s", +- dev_name(dev), id->idname, +- du_pvid->dev ? dev_name(du_pvid->dev) : "none", du_pvid->idname, +- pvid); +- } +- +- if (du_devname && (du_devname != du_dev)) { +- /* clear devname in another entry with our devname */ +- log_warn("Devices file PVID %s clearing wrong DEVNAME %s.", +- du_devname->pvid, du_devname->devname); +- free(du_devname->devname); +- du_devname->devname = NULL; +- } +- + } else if (du_pvid) { + /* + * If the device_id of the existing entry for PVID is the same +@@ -1154,11 +1168,6 @@ id_done: + update_matching_kind = "PVID"; + update_matching_name = pvid; + } else { +- log_warn("WARNING: device %s (%s) and %s (%s) have duplicate PVID %s", +- dev_name(dev), id->idname, +- du_pvid->dev ? dev_name(du_pvid->dev) : "none", du_pvid->idname, +- pvid); +- + if (!cmd->current_settings.yes && + yes_no_prompt("Add device with duplicate PV to devices file?") == 'n') { + log_print("Device not added."); +@@ -1166,21 +1175,6 @@ id_done: + return 1; + } + } +- +- if (du_devid && (du_devid != du_pvid)) { +- /* warn about another entry using the same device_id */ +- log_warn("WARNING: duplicate device_id %s for PVIDs %s %s", +- du_devid->idname, du_devid->pvid, du_pvid->pvid); +- } +- +- if (du_devname && (du_devname != du_pvid)) { +- /* clear devname in another entry with our devname */ +- log_warn("Devices file PVID %s clearing wrong DEVNAME %s.", +- du_devname->pvid, du_devname->devname); +- free(du_devname->devname); +- du_devname->devname = NULL; +- } +- + } else if (du_devid) { + /* + * Do we create a new du or update the existing du? +@@ -1195,64 +1189,13 @@ id_done: + * the same device_id (create a new du for dev.) + * If not, then update the existing du_devid. + */ +- +- if (du_devid->dev != dev) +- check_idname = device_id_system_read(cmd, du_devid->dev, id->idtype); +- +- if (check_idname && !strcmp(check_idname, id->idname)) { +- int ret1, ret2; +- dev_t devt1, devt2; +- +- /* +- * two different devices have the same device_id, +- * create a new du for the device being added +- */ +- +- /* dev_is_partitioned() the dev open to read it. */ +- if (!label_scan_open(du_devid->dev)) +- log_warn("Cannot open %s", dev_name(du_devid->dev)); +- +- if (dev_is_partitioned(cmd, du_devid->dev)) { +- /* Check if existing entry is whole device and new entry is a partition of it. */ +- ret1 = dev_get_primary_dev(cmd->dev_types, dev, &devt1); +- if ((ret1 == 2) && (devt1 == du_devid->dev->dev)) +- log_warn("Remove partitioned device %s from devices file.", dev_name(du_devid->dev)); +- } else { +- /* Check if both entries are partitions of the same device. */ +- ret1 = dev_get_primary_dev(cmd->dev_types, dev, &devt1); +- ret2 = dev_get_primary_dev(cmd->dev_types, du_devid->dev, &devt2); +- +- if ((ret1 == 2) && (ret2 == 2) && (devt1 == devt2)) { +- log_warn("Partitions %s %s have same device_id %s", +- dev_name(dev), dev_name(du_devid->dev), id->idname); +- } else { +- log_warn("Duplicate device_id %s %s for %s and %s", +- idtype_to_str(id->idtype), check_idname, +- dev_name(dev), dev_name(du_devid->dev)); +- } +- } +- } else { ++ if (du_devid->dev == dev) { + /* update the existing entry with matching devid */ + update_du = du_devid; + dm_list_del(&update_du->list); + update_matching_kind = "device_id"; + update_matching_name = id->idname; + } +- +- if (du_devname && (du_devname != du_devid)) { +- /* clear devname in another entry with our devname */ +- log_warn("Devices file PVID %s clearing wrong DEVNAME %s", +- du_devname->pvid, du_devname->devname); +- free(du_devname->devname); +- du_devname->devname = NULL; +- } +- +- } else if (du_devname) { +- /* clear devname in another entry with our devname */ +- log_warn("Devices file PVID %s clearing wrong DEVNAME %s", +- du_devname->pvid, du_devname->devname); +- free(du_devname->devname); +- du_devname->devname = NULL; + } + + free((void *)check_idname); +-- +2.34.3 + diff --git a/0031-lvmdevices-make-deldev-work-for-missing-device.patch b/0031-lvmdevices-make-deldev-work-for-missing-device.patch new file mode 100644 index 0000000..633e1d4 --- /dev/null +++ b/0031-lvmdevices-make-deldev-work-for-missing-device.patch @@ -0,0 +1,106 @@ +From df2b1555aff71452cde156badec70117065c9e2c Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 3 Feb 2022 16:56:03 -0600 +Subject: [PATCH 31/54] lvmdevices: make deldev work for missing device + +--- + lib/device/device_id.c | 6 +++--- + lib/device/device_id.h | 1 + + tools/lvmdevices.c | 33 ++++++++++++++++----------------- + 3 files changed, 20 insertions(+), 20 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index ccc5f43a1..aeaa1ffc6 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -894,7 +894,7 @@ struct dev_use *get_du_for_pvid(struct cmd_context *cmd, const char *pvid) + return NULL; + } + +-static struct dev_use *_get_du_for_devname(struct cmd_context *cmd, const char *devname) ++struct dev_use *get_du_for_devname(struct cmd_context *cmd, const char *devname) + { + struct dev_use *du; + +@@ -1093,7 +1093,7 @@ id_done: + du_pvid = get_du_for_pvid(cmd, pvid); + + /* Is there already an entry using this device's name? */ +- du_devname = _get_du_for_devname(cmd, dev_name(dev)); ++ du_devname = get_du_for_devname(cmd, dev_name(dev)); + + /* Is there already an entry using the device_id for this device? */ + du_devid = _get_du_for_device_id(cmd, id->idtype, id->idname); +@@ -1514,7 +1514,7 @@ int device_ids_match_dev(struct cmd_context *cmd, struct device *dev) + struct dev_use *du; + + /* First check the du entry with matching devname since it's likely correct. */ +- if ((du = _get_du_for_devname(cmd, dev_name(dev)))) { ++ if ((du = get_du_for_devname(cmd, dev_name(dev)))) { + if (_match_du_to_dev(cmd, du, dev)) + return 1; + } +diff --git a/lib/device/device_id.h b/lib/device/device_id.h +index 4cf1374c8..2cd2fd7c6 100644 +--- a/lib/device/device_id.h ++++ b/lib/device/device_id.h +@@ -40,6 +40,7 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg, + + struct dev_use *get_du_for_dev(struct cmd_context *cmd, struct device *dev); + struct dev_use *get_du_for_pvid(struct cmd_context *cmd, const char *pvid); ++struct dev_use *get_du_for_devname(struct cmd_context *cmd, const char *devname); + + char *devices_file_version(void); + int devices_file_exists(struct cmd_context *cmd); +diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c +index c50c09f90..662b35f9a 100644 +--- a/tools/lvmdevices.c ++++ b/tools/lvmdevices.c +@@ -383,28 +383,27 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv) + * No filter because we always want to allow removing a device + * by name from the devices file. + */ +- if (!(dev = dev_cache_get(cmd, devname, NULL))) { +- log_error("No device found for %s.", devname); +- goto bad; +- } +- +- /* +- * dev_cache_scan uses sysfs to check if an LV is using each dev +- * and sets this flag is so. +- */ +- if (dev_is_used_by_active_lv(cmd, dev, NULL, NULL, NULL, NULL)) { +- if (!arg_count(cmd, yes_ARG) && +- yes_no_prompt("Device %s is used by an active LV, continue to remove? ", devname) == 'n') { +- log_error("Device not removed."); +- goto bad; ++ if ((dev = dev_cache_get(cmd, devname, NULL))) { ++ /* ++ * dev_cache_scan uses sysfs to check if an LV is using each dev ++ * and sets this flag is so. ++ */ ++ if (dev_is_used_by_active_lv(cmd, dev, NULL, NULL, NULL, NULL)) { ++ if (!arg_count(cmd, yes_ARG) && ++ yes_no_prompt("Device %s is used by an active LV, continue to remove? ", devname) == 'n') { ++ log_error("Device not removed."); ++ goto bad; ++ } + } ++ if ((du = get_du_for_dev(cmd, dev))) ++ goto dev_del; + } + +- if (!(du = get_du_for_dev(cmd, dev))) { +- log_error("Device not found in devices file."); ++ if (!(du = get_du_for_devname(cmd, devname))) { ++ log_error("No devices file entry for %s.", devname); + goto bad; + } +- ++ dev_del: + dm_list_del(&du->list); + free_du(du); + device_ids_write(cmd); +-- +2.34.3 + diff --git a/0032-devices-file-do-not-clear-PVID-of-unread-devices.patch b/0032-devices-file-do-not-clear-PVID-of-unread-devices.patch new file mode 100644 index 0000000..ca4d5eb --- /dev/null +++ b/0032-devices-file-do-not-clear-PVID-of-unread-devices.patch @@ -0,0 +1,144 @@ +From 08a5619a1d7a5a8dd6e0df6e4dedec47ce2533b7 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 10 Feb 2022 14:00:25 -0600 +Subject: [PATCH 32/54] devices file: do not clear PVID of unread devices + +In a certain disconnected state, a block device is present on +the system, can be opened, reports a valid size, reports the +correct device id (wwid), and matches a devices file entry. +But, reading the device can still fail. In this case, +device_ids_validate() was misinterpreting the read error as +the device having no data/label on it (and no PVID). +The validate function would then clear the PVID from the +devices file entry for the device, thinking that it was +fixing the devices file (making it consistent with the on disk +state.) Fix this by not attempting to check and correct a +devices file entry that cannot be read. Also make this case +explicit in the hints validation code (which was doing the +right thing but indirectly.) +--- + lib/device/device.h | 1 + + lib/device/device_id.c | 14 ++++++++++++++ + lib/label/hints.c | 14 ++++++++++++++ + lib/label/label.c | 8 ++++++++ + 4 files changed, 37 insertions(+) + +diff --git a/lib/device/device.h b/lib/device/device.h +index 9e471a9b5..8c3a8c30e 100644 +--- a/lib/device/device.h ++++ b/lib/device/device.h +@@ -40,6 +40,7 @@ + #define DEV_IS_NVME 0x00040000 /* set if dev is nvme */ + #define DEV_MATCHED_USE_ID 0x00080000 /* matched an entry from cmd->use_devices */ + #define DEV_SCAN_FOUND_NOLABEL 0x00100000 /* label_scan read, passed filters, but no lvm label */ ++#define DEV_SCAN_NOT_READ 0x00200000 /* label_scan not able to read dev */ + + /* + * Support for external device info. +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index aeaa1ffc6..7fe581571 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -1724,6 +1724,13 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs, + if (scanned_devs && !dev_in_device_list(dev, scanned_devs)) + continue; + ++ /* ++ * The matched device could not be read so we do not have ++ * the PVID from disk and cannot verify the devices file entry. ++ */ ++ if (dev->flags & DEV_SCAN_NOT_READ) ++ continue; ++ + /* + * du and dev may have been matched, but the dev could still + * have been excluded by other filters during label scan. +@@ -1806,6 +1813,13 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs, + if (scanned_devs && !dev_in_device_list(dev, scanned_devs)) + continue; + ++ /* ++ * The matched device could not be read so we do not have ++ * the PVID from disk and cannot verify the devices file entry. ++ */ ++ if (dev->flags & DEV_SCAN_NOT_READ) ++ continue; ++ + if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) { + log_warn("Devices file %s is excluded by filter: %s.", + dev_name(dev), dev_filtered_reason(dev)); +diff --git a/lib/label/hints.c b/lib/label/hints.c +index 3ce9634f2..95d5d77b8 100644 +--- a/lib/label/hints.c ++++ b/lib/label/hints.c +@@ -234,6 +234,7 @@ static int _touch_newhints(void) + return_0; + if (fclose(fp)) + stack; ++ log_debug("newhints created"); + return 1; + } + +@@ -504,6 +505,19 @@ int validate_hints(struct cmd_context *cmd, struct dm_list *hints) + if (!hint->chosen) + continue; + ++ /* ++ * label_scan was unable to read the dev so we don't know its pvid. ++ * Since we are unable to verify the hint is correct, it's possible ++ * that the PVID is actually found on a different device, so don't ++ * depend on hints. (This would also fail the following pvid check.) ++ */ ++ if (dev->flags & DEV_SCAN_NOT_READ) { ++ log_debug("Uncertain hint for unread device %d:%d %s", ++ major(hint->devt), minor(hint->devt), dev_name(dev)); ++ ret = 0; ++ continue; ++ } ++ + if (strcmp(dev->pvid, hint->pvid)) { + log_debug("Invalid hint device %d:%d %s pvid %s had hint pvid %s", + major(hint->devt), minor(hint->devt), dev_name(dev), +diff --git a/lib/label/label.c b/lib/label/label.c +index 9fac3e464..354ab35e2 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -686,6 +686,8 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f, + + dm_list_iterate_items_safe(devl, devl2, devs) { + ++ devl->dev->flags &= ~DEV_SCAN_NOT_READ; ++ + /* + * If we prefetch more devs than blocks in the cache, then the + * cache will wait for earlier reads to complete, toss the +@@ -701,6 +703,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f, + log_debug_devs("Scan failed to open %s.", dev_name(devl->dev)); + dm_list_del(&devl->list); + dm_list_add(&reopen_devs, &devl->list); ++ devl->dev->flags |= DEV_SCAN_NOT_READ; + continue; + } + } +@@ -724,6 +727,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f, + log_debug_devs("Scan failed to read %s.", dev_name(devl->dev)); + scan_read_errors++; + scan_failed_count++; ++ devl->dev->flags |= DEV_SCAN_NOT_READ; + lvmcache_del_dev(devl->dev); + if (bb) + bcache_put(bb); +@@ -1113,6 +1117,10 @@ int label_scan(struct cmd_context *cmd) + * filter", and this result needs to be cleared (wiped) so that the + * complete set of filters (including those that require data) can be + * checked in _process_block, where headers have been read. ++ * ++ * FIXME: devs that are filtered with data in _process_block ++ * are not moved to the filtered_devs list like devs filtered ++ * here without data. Does that have any effect? + */ + log_debug_devs("Filtering devices to scan (nodata)"); + +-- +2.34.3 + diff --git a/0033-man-lvmcache-mention-writecache-memory-usage.patch b/0033-man-lvmcache-mention-writecache-memory-usage.patch new file mode 100644 index 0000000..a8314e4 --- /dev/null +++ b/0033-man-lvmcache-mention-writecache-memory-usage.patch @@ -0,0 +1,35 @@ +From cdefd8635de24200b55822fa0b6bc23a638fb87a Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 21 Feb 2022 11:35:58 -0600 +Subject: [PATCH 33/54] man lvmcache: mention writecache memory usage + +--- + man/lvmcache.7_main | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/man/lvmcache.7_main b/man/lvmcache.7_main +index 48cf7b492..73680235b 100644 +--- a/man/lvmcache.7_main ++++ b/man/lvmcache.7_main +@@ -240,6 +240,18 @@ The writecache block size should be chosen to match the xfs sectsz value. + It is also possible to specify a sector size of 4096 to mkfs.xfs when + creating the file system. In this case the writecache block size of 4096 + can be used. ++.P ++.SS dm-writecache memory usage ++.P ++The amount of main system memory used by dm-writecache can be a factor ++when selecting the writecache cachevol size and the writecache block size. ++.P ++.IP \[bu] 2 ++writecache block size 4096: each 100 GiB of writecache cachevol uses ++slighly over 2 GiB of system memory. ++.IP \[bu] 2 ++writecache block size 512: each 100 GiB of writecache cachevol uses ++a little over 16 GiB of system memory. + . + .SS dm-writecache settings + . +-- +2.34.3 + diff --git a/0034-writecache-display-block-size-from-lvs.patch b/0034-writecache-display-block-size-from-lvs.patch new file mode 100644 index 0000000..5167d68 --- /dev/null +++ b/0034-writecache-display-block-size-from-lvs.patch @@ -0,0 +1,102 @@ +From c047ff61f68d1b853569b153251f8bc5f88e23cd Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 21 Feb 2022 16:09:57 -0600 +Subject: [PATCH 34/54] writecache: display block size from lvs + +lvs was missing the ability to display writecache block size. +now possible with lvs -o writecache_block_size +--- + lib/report/columns.h | 1 + + lib/report/properties.c | 2 ++ + lib/report/report.c | 20 ++++++++++++++++++++ + man/lvmcache.7_main | 4 ++++ + test/shell/writecache-cache-blocksize.sh | 2 ++ + 5 files changed, 29 insertions(+) + +diff --git a/lib/report/columns.h b/lib/report/columns.h +index 12b78b766..7e450dace 100644 +--- a/lib/report/columns.h ++++ b/lib/report/columns.h +@@ -108,6 +108,7 @@ FIELD(LVS, lv, TIM, "RTime", lvid, 26, lvtimeremoved, lv_time_removed, "Removal + FIELD(LVS, lv, STR, "Host", lvid, 10, lvhost, lv_host, "Creation host of the LV, if known.", 0) + FIELD(LVS, lv, STR_LIST, "Modules", lvid, 0, modules, lv_modules, "Kernel device-mapper modules required for this LV.", 0) + FIELD(LVS, lv, BIN, "Historical", lvid, 0, lvhistorical, lv_historical, "Set if the LV is historical.", 0) ++FIELD(LVS, lv, NUM, "WCacheBlkSize", lvid, 0, writecache_block_size, writecache_block_size, "The writecache block size", 0) + /* + * End of LVS type fields + */ +diff --git a/lib/report/properties.c b/lib/report/properties.c +index 12ea890f4..6f302360f 100644 +--- a/lib/report/properties.c ++++ b/lib/report/properties.c +@@ -353,6 +353,8 @@ GET_PV_STR_PROPERTY_FN(pv_device_id_type, pv->device_id_type) + #define _writecache_writeback_blocks_get prop_not_implemented_get + #define _writecache_error_set prop_not_implemented_set + #define _writecache_error_get prop_not_implemented_get ++#define _writecache_block_size_set prop_not_implemented_set ++#define _writecache_block_size_get prop_not_implemented_get + + #define _vdo_operating_mode_set prop_not_implemented_set + #define _vdo_operating_mode_get prop_not_implemented_get +diff --git a/lib/report/report.c b/lib/report/report.c +index 60df417a4..c06b22674 100644 +--- a/lib/report/report.c ++++ b/lib/report/report.c +@@ -3346,6 +3346,26 @@ static int _integritymismatches_disp(struct dm_report *rh __attribute__((unused) + return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64)); + } + ++static int _writecache_block_size_disp(struct dm_report *rh __attribute__((unused)), ++ struct dm_pool *mem, ++ struct dm_report_field *field, ++ const void *data, ++ void *private __attribute__((unused))) ++{ ++ struct logical_volume *lv = (struct logical_volume *) data; ++ uint32_t bs = 0; ++ ++ if (lv_is_writecache(lv)) { ++ struct lv_segment *seg = first_seg(lv); ++ bs = seg->writecache_block_size; ++ } ++ ++ if (!bs) ++ return dm_report_field_int32(rh, field, &GET_TYPE_RESERVED_VALUE(num_undef_32)); ++ ++ return dm_report_field_uint32(rh, field, &bs); ++} ++ + static int _datapercent_disp(struct dm_report *rh, struct dm_pool *mem, + struct dm_report_field *field, + const void *data, void *private) +diff --git a/man/lvmcache.7_main b/man/lvmcache.7_main +index 73680235b..519e352cb 100644 +--- a/man/lvmcache.7_main ++++ b/man/lvmcache.7_main +@@ -241,6 +241,10 @@ It is also possible to specify a sector size of 4096 to mkfs.xfs when + creating the file system. In this case the writecache block size of 4096 + can be used. + .P ++The writecache block size is displayed by the command: ++.br ++lvs -o writecacheblocksize VG/LV ++.P + .SS dm-writecache memory usage + .P + The amount of main system memory used by dm-writecache can be a factor +diff --git a/test/shell/writecache-cache-blocksize.sh b/test/shell/writecache-cache-blocksize.sh +index 2579ef7b7..4e17effe5 100644 +--- a/test/shell/writecache-cache-blocksize.sh ++++ b/test/shell/writecache-cache-blocksize.sh +@@ -222,6 +222,8 @@ vgextend $vg "$dev2" + lvcreate -n $lv1 -l 8 -an $vg "$dev1" + lvcreate -n $lv2 -l 4 -an $vg "$dev2" + lvconvert --yes --type writecache --cachevol $lv2 --cachesettings "block_size=4096" $vg/$lv1 ++lvs -o writecacheblocksize $vg/$lv1 |tee out ++grep 4096 out + lvchange -ay $vg/$lv1 + mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" |tee out + grep "sectsz=4096" out +-- +2.34.3 + diff --git a/0035-devices-simplify-dev_cache_get_by_devt.patch b/0035-devices-simplify-dev_cache_get_by_devt.patch new file mode 100644 index 0000000..2f8a911 --- /dev/null +++ b/0035-devices-simplify-dev_cache_get_by_devt.patch @@ -0,0 +1,148 @@ +From 8552290efae4905fd1a942be8e752842b11f1881 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 24 Feb 2022 15:57:29 -0600 +Subject: [PATCH 35/54] devices: simplify dev_cache_get_by_devt + +remove unused args, and no callers need or want a +repeated dev_cache_scan if there is no dev from the +lookup. +--- + lib/device/dev-cache.c | 60 ++++-------------------------------------- + lib/device/dev-cache.h | 2 +- + lib/label/label.c | 2 +- + tools/pvscan.c | 6 ++--- + 4 files changed, 10 insertions(+), 60 deletions(-) + +diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c +index c6e5f68cf..cc1af7c7a 100644 +--- a/lib/device/dev-cache.c ++++ b/lib/device/dev-cache.c +@@ -1577,63 +1577,13 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d + return dev; + } + +-struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct dev_filter *f, int *filtered) ++struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt) + { +- char path[PATH_MAX]; +- const char *sysfs_dir; +- struct stat info; +- struct device *d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev); +- int ret; +- +- if (filtered) +- *filtered = 0; +- +- if (!d) { +- sysfs_dir = dm_sysfs_dir(); +- if (sysfs_dir && *sysfs_dir) { +- /* First check if dev is sysfs to avoid useless scan */ +- if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d", +- sysfs_dir, (int)MAJOR(dev), (int)MINOR(dev)) < 0) { +- log_error("dm_snprintf partition failed."); +- return NULL; +- } +- +- if (lstat(path, &info)) { +- log_debug("No sysfs entry for %d:%d errno %d at %s.", +- (int)MAJOR(dev), (int)MINOR(dev), errno, path); +- return NULL; +- } +- } +- +- log_debug_devs("Device num not found in dev_cache repeat dev_cache_scan for %d:%d", +- (int)MAJOR(dev), (int)MINOR(dev)); +- dev_cache_scan(cmd); +- d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev); +- +- if (!d) +- return NULL; +- } +- +- if (d->flags & DEV_REGULAR) +- return d; +- +- if (!f) +- return d; +- +- ret = f->passes_filter(cmd, f, d, NULL); +- +- if (ret == -EAGAIN) { +- log_debug_devs("get device by number defer filter %s", dev_name(d)); +- d->flags |= DEV_FILTER_AFTER_SCAN; +- ret = 1; +- } +- +- if (ret) +- return d; +- +- if (filtered) +- *filtered = 1; ++ struct device *dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devt); + ++ if (dev) ++ return dev; ++ log_debug_devs("No devno %d:%d in dev cache.", (int)MAJOR(devt), (int)MINOR(devt)); + return NULL; + } + +diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h +index 635dc4fc9..7305eeb0e 100644 +--- a/lib/device/dev-cache.h ++++ b/lib/device/dev-cache.h +@@ -54,7 +54,7 @@ int dev_cache_has_scanned(void); + int dev_cache_add_dir(const char *path); + struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f); + +-struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t device, struct dev_filter *f, int *filtered); ++struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt); + + struct device *dev_hash_get(const char *name); + +diff --git a/lib/label/label.c b/lib/label/label.c +index 354ab35e2..ffe925254 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -1443,7 +1443,7 @@ void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv + if (lv_info(cmd, lv, 0, &lvinfo, 0, 0) && lvinfo.exists) { + /* FIXME: Still unclear what is it supposed to find */ + devt = MKDEV(lvinfo.major, lvinfo.minor); +- if ((dev = dev_cache_get_by_devt(cmd, devt, NULL, NULL))) ++ if ((dev = dev_cache_get_by_devt(cmd, devt))) + label_scan_invalidate(dev); + } + } +diff --git a/tools/pvscan.c b/tools/pvscan.c +index f60c4a2ca..160a2c9a0 100644 +--- a/tools/pvscan.c ++++ b/tools/pvscan.c +@@ -857,7 +857,7 @@ static int _get_devs_from_saved_vg(struct cmd_context *cmd, const char *vgname, + + devno = MKDEV(file_major, file_minor); + +- if (!(dev = dev_cache_get_by_devt(cmd, devno, NULL, NULL))) { ++ if (!(dev = dev_cache_get_by_devt(cmd, devno))) { + log_error_pvscan(cmd, "No device found for %d:%d PVID %s", file_major, file_minor, pvid); + goto bad; + } +@@ -1195,7 +1195,7 @@ static int _get_args_devs(struct cmd_context *cmd, struct dm_list *pvscan_args, + if (arg->devname) + arg->dev = dev_cache_get(cmd, arg->devname, NULL); + else if (arg->devno) +- arg->dev = dev_cache_get_by_devt(cmd, arg->devno, NULL, NULL); ++ arg->dev = dev_cache_get_by_devt(cmd, arg->devno); + else + return_0; + } +@@ -1257,7 +1257,7 @@ static void _set_pv_devices_online(struct cmd_context *cmd, struct volume_group + + devno = MKDEV(major, minor); + +- if (!(dev = dev_cache_get_by_devt(cmd, devno, NULL, NULL))) { ++ if (!(dev = dev_cache_get_by_devt(cmd, devno))) { + log_print_pvscan(cmd, "VG %s PV %s no device found for %d:%d", + vg->name, pvid, major, minor); + pvl->pv->status |= MISSING_PV; +-- +2.34.3 + diff --git a/0036-devices-drop-incorrect-paths-from-aliases-list.patch b/0036-devices-drop-incorrect-paths-from-aliases-list.patch new file mode 100644 index 0000000..010f2f3 --- /dev/null +++ b/0036-devices-drop-incorrect-paths-from-aliases-list.patch @@ -0,0 +1,467 @@ +From 8ba6259b24cd4b99e061f2610c5cd0bcde890039 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 24 Feb 2022 16:03:21 -0600 +Subject: [PATCH 36/54] devices: drop incorrect paths from aliases list + +along with some basic checks for cases when a device +has no aliases. + +lvm itself creates many situations where a struct device +has no valid paths, when it activates and opens an LV, +does something with it, e.g. zeroing, and then closes +and deactivates it. (dev-cache is intended for PVs, and +the use of LVs should be moved out of dev-cache in a +future patch.) +--- + lib/device/dev-cache.c | 223 ++++++++++++++++++++++++++--------------- + lib/device/dev-cache.h | 2 +- + lib/device/dev-io.c | 34 ++++--- + lib/device/device.h | 3 - + 4 files changed, 164 insertions(+), 98 deletions(-) + +diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c +index cc1af7c7a..58e67e130 100644 +--- a/lib/device/dev-cache.c ++++ b/lib/device/dev-cache.c +@@ -351,7 +351,7 @@ static int _add_alias(struct device *dev, const char *path, enum add_hash hash) + goto out; + } + +- if (!(path = dm_pool_strdup(_cache.mem, path)) || ++ if (!(path = _strdup(path)) || + !(sl = _zalloc(sizeof(*sl)))) { + log_error("Failed to add allias to dev cache."); + return 0; +@@ -1162,6 +1162,17 @@ static int _insert(const char *path, const struct stat *info, + return 1; + } + ++static void _drop_all_aliases(struct device *dev) ++{ ++ struct dm_str_list *strl, *strl2; ++ ++ dm_list_iterate_items_safe(strl, strl2, &dev->aliases) { ++ log_debug("Drop alias for %d:%d %s.", (int)MAJOR(dev->dev), (int)MINOR(dev->dev), strl->str); ++ dm_hash_remove(_cache.names, strl->str); ++ dm_list_del(&strl->list); ++ } ++} ++ + void dev_cache_scan(struct cmd_context *cmd) + { + log_debug_devs("Creating list of system devices."); +@@ -1371,59 +1382,6 @@ int dev_cache_add_dir(const char *path) + return 1; + } + +-/* Check cached device name is still valid before returning it */ +-/* This should be a rare occurrence */ +-/* set quiet if the cache is expected to be out-of-date */ +-/* FIXME Make rest of code pass/cache struct device instead of dev_name */ +-const char *dev_name_confirmed(struct device *dev, int quiet) +-{ +- struct stat buf; +- const char *name; +- int r; +- +- if ((dev->flags & DEV_REGULAR)) +- return dev_name(dev); +- +- while ((r = stat(name = dm_list_item(dev->aliases.n, +- struct dm_str_list)->str, &buf)) || +- (buf.st_rdev != dev->dev)) { +- if (r < 0) { +- if (quiet) +- log_sys_debug("stat", name); +- else +- log_sys_error("stat", name); +- } +- if (quiet) +- log_debug_devs("Path %s no longer valid for device(%d,%d)", +- name, (int) MAJOR(dev->dev), +- (int) MINOR(dev->dev)); +- else +- log_warn("Path %s no longer valid for device(%d,%d)", +- name, (int) MAJOR(dev->dev), +- (int) MINOR(dev->dev)); +- +- /* Remove the incorrect hash entry */ +- dm_hash_remove(_cache.names, name); +- +- /* Leave list alone if there isn't an alternative name */ +- /* so dev_name will always find something to return. */ +- /* Otherwise add the name to the correct device. */ +- if (dm_list_size(&dev->aliases) > 1) { +- dm_list_del(dev->aliases.n); +- if (!r) +- _insert(name, &buf, 0, obtain_device_list_from_udev()); +- continue; +- } +- +- /* Scanning issues this inappropriately sometimes. */ +- log_debug_devs("Aborting - please provide new pathname for what " +- "used to be %s", name); +- return NULL; +- } +- +- return dev_name(dev); +-} +- + struct device *dev_hash_get(const char *name) + { + return (struct device *) dm_hash_lookup(_cache.names, name); +@@ -1452,26 +1410,23 @@ static void _remove_alias(struct device *dev, const char *name) + * deactivated LV. Those old paths are all invalid and are dropped here. + */ + +-static void _verify_aliases(struct device *dev, const char *newname) ++static void _verify_aliases(struct device *dev) + { + 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 ?: ""); ++ log_debug("Drop alias for %d:%d invalid path %s %d:%d.", ++ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), strl->str, ++ (int)MAJOR(st.st_rdev), (int)MINOR(st.st_rdev)); + 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) ++static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f, int existing) + { + struct device *dev = (struct device *) dm_hash_lookup(_cache.names, name); + struct stat st; +@@ -1485,13 +1440,18 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d + if (dev && (dev->flags & DEV_REGULAR)) + return dev; + ++ if (dev && dm_list_empty(&dev->aliases)) { ++ /* shouldn't happen */ ++ log_warn("Ignoring dev with no valid paths for %s.", name); ++ return NULL; ++ } ++ + /* +- * The requested path is invalid, remove any dev-cache +- * info for it. ++ * 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.", ++ log_debug("Device path %s is invalid for %d:%d %s.", + name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev)); + + dm_hash_remove(_cache.names, name); +@@ -1499,11 +1459,17 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d + _remove_alias(dev, name); + + /* Remove any other names in dev->aliases that are incorrect. */ +- _verify_aliases(dev, NULL); ++ _verify_aliases(dev); + } + return NULL; + } + ++ if (dev && dm_list_empty(&dev->aliases)) { ++ /* shouldn't happen */ ++ log_warn("Ignoring dev with no valid paths for %s.", name); ++ return NULL; ++ } ++ + if (!S_ISBLK(st.st_mode)) { + log_debug("Not a block device %s.", name); + return NULL; +@@ -1514,26 +1480,110 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d + * Remove incorrect info and then add new dev-cache entry. + */ + if (dev && (st.st_rdev != dev->dev)) { +- log_debug("Device path %s does not match %d:%d %s.", +- name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev)); ++ struct device *dev_by_devt = (struct device *) btree_lookup(_cache.devices, (uint32_t) st.st_rdev); ++ ++ /* ++ * lvm commands create this condition when they ++ * activate/deactivate LVs combined with creating new LVs. ++ * The command does not purge dev structs when deactivating ++ * an LV (which it probably should do), but the better ++ * approach would be not using dev-cache at all for LVs. ++ */ + +- dm_hash_remove(_cache.names, name); ++ log_debug("Dropping aliases for device entry %d:%d %s for new device %d:%d %s.", ++ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev), ++ (int)MAJOR(st.st_rdev), (int)MINOR(st.st_rdev), name); + +- _remove_alias(dev, name); ++ _drop_all_aliases(dev); + +- /* Remove any other names in dev->aliases that are incorrect. */ +- _verify_aliases(dev, NULL); ++ if (dev_by_devt) { ++ log_debug("Dropping aliases for device entry %d:%d %s for new device %d:%d %s.", ++ (int)MAJOR(dev_by_devt->dev), (int)MINOR(dev_by_devt->dev), dev_name(dev_by_devt), ++ (int)MAJOR(st.st_rdev), (int)MINOR(st.st_rdev), name); + +- /* Add new dev-cache entry next. */ +- dev = NULL; ++ _drop_all_aliases(dev_by_devt); ++ } ++ ++#if 0 ++ /* ++ * I think only lvm's own dm devs should be added here, so use ++ * a warning to look for any other unknown cases. ++ */ ++ if (MAJOR(st.st_rdev) != cmd->dev_types->device_mapper_major) { ++ log_warn("WARNING: new device appeared %d:%d %s", ++ (int)MAJOR(st.st_rdev), (int)(MINOR(st.st_rdev)), name); ++ } ++#endif ++ ++ if (!_insert_dev(name, st.st_rdev)) ++ return_NULL; ++ ++ /* Get the struct dev that was just added. */ ++ dev = (struct device *) dm_hash_lookup(_cache.names, name); ++ ++ if (!dev) { ++ log_error("Failed to get device %s", name); ++ return NULL; ++ } ++ ++ goto out; + } + ++ if (dev && dm_list_empty(&dev->aliases)) { ++ /* shouldn't happen */ ++ log_warn("Ignoring dev with no valid paths for %s.", name); ++ return NULL; ++ } ++ ++ if (!dev && existing) ++ return_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. ++ * This case should never be hit for a PV. It should only ++ * happen when the command is opening a new LV it has created. ++ * Add an arg to all callers indicating when the arg should be ++ * new (for an LV) and not existing. ++ * FIXME: fix this further by not using dev-cache struct devs ++ * at all for new dm devs (LVs) that lvm uses. Make the ++ * dev-cache contain only devs for PVs. ++ * Places to fix that use a dev for LVs include: ++ * . lv_resize opening lv to discard ++ * . wipe_lv opening lv to zero it ++ * . _extend_sanlock_lv opening lv to extend it ++ * . _write_log_header opening lv to write header ++ * Also, io to LVs should not go through bcache. ++ * bcache should contain only labels and metadata ++ * scanned from PVs. + */ + if (!dev) { ++ /* ++ * This case should only be used for new devices created by this ++ * command (opening LVs it's created), so if a dev exists for the ++ * dev_t referenced by the name, then drop all aliases for before ++ * _insert_dev adds the new name. lvm commands actually hit this ++ * fairly often when it uses some LV, deactivates the LV, then ++ * creates some new LV which ends up with the same major:minor. ++ * Without dropping the aliases, it's plausible that lvm commands ++ * could end up using the wrong dm device. ++ */ ++ struct device *dev_by_devt = (struct device *) btree_lookup(_cache.devices, (uint32_t) st.st_rdev); ++ if (dev_by_devt) { ++ log_debug("Dropping aliases for %d:%d before adding new path %s.", ++ (int)MAJOR(st.st_rdev), (int)(MINOR(st.st_rdev)), name); ++ _drop_all_aliases(dev_by_devt); ++ } ++ ++#if 0 ++ /* ++ * I think only lvm's own dm devs should be added here, so use ++ * a warning to look for any other unknown cases. ++ */ ++ if (MAJOR(st.st_rdev) != cmd->dev_types->device_mapper_major) { ++ log_warn("WARNING: new device appeared %d:%d %s", ++ (int)MAJOR(st.st_rdev), (int)(MINOR(st.st_rdev)), name); ++ } ++#endif ++ + if (!_insert_dev(name, st.st_rdev)) + return_NULL; + +@@ -1544,10 +1594,9 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d + log_error("Failed to get device %s", name); + return NULL; + } +- +- _verify_aliases(dev, name); + } + ++ out: + /* + * The caller passed a filter if they only want the dev if it + * passes filters. +@@ -1577,6 +1626,16 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d + return dev; + } + ++struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f) ++{ ++ return _dev_cache_get(cmd, name, f, 1); ++} ++ ++struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f) ++{ ++ return _dev_cache_get(cmd, name, f, 0); ++} ++ + struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt) + { + struct device *dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devt); +@@ -1653,8 +1712,10 @@ int dev_fd(struct device *dev) + + const char *dev_name(const struct device *dev) + { +- return (dev && dev->aliases.n) ? dm_list_item(dev->aliases.n, struct dm_str_list)->str : +- unknown_device_name(); ++ if (dev && dev->aliases.n && !dm_list_empty(&dev->aliases)) ++ return dm_list_item(dev->aliases.n, struct dm_str_list)->str; ++ else ++ return unknown_device_name(); + } + + bool dev_cache_has_md_with_end_superblock(struct dev_types *dt) +diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h +index 7305eeb0e..51c3fc6c3 100644 +--- a/lib/device/dev-cache.h ++++ b/lib/device/dev-cache.h +@@ -53,7 +53,7 @@ int dev_cache_has_scanned(void); + + int dev_cache_add_dir(const char *path); + struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f); +- ++struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f); + struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt); + + struct device *dev_hash_get(const char *name); +diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c +index b4f1930b1..811ad8978 100644 +--- a/lib/device/dev-io.c ++++ b/lib/device/dev-io.c +@@ -58,6 +58,9 @@ static int _dev_get_size_file(struct device *dev, uint64_t *size) + const char *name = dev_name(dev); + struct stat info; + ++ if (dm_list_empty(&dev->aliases)) ++ return_0; ++ + if (dev->size_seqno == _dev_size_seqno) { + log_very_verbose("%s: using cached size %" PRIu64 " sectors", + name, dev->size); +@@ -87,7 +90,7 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size) + int do_close = 0; + + if (dm_list_empty(&dev->aliases)) +- return 0; ++ return_0; + + if (dev->size_seqno == _dev_size_seqno) { + log_very_verbose("%s: using cached size %" PRIu64 " sectors", +@@ -305,6 +308,13 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) + if ((flags & O_EXCL)) + need_excl = 1; + ++ if (dm_list_empty(&dev->aliases)) { ++ /* shouldn't happen */ ++ log_print("Cannot open device %d:%d with no valid paths.", (int)MAJOR(dev->dev), (int)MINOR(dev->dev)); ++ return 0; ++ } ++ name = dev_name(dev); ++ + if (dev->fd >= 0) { + if (((dev->flags & DEV_OPENED_RW) || !need_rw) && + ((dev->flags & DEV_OPENED_EXCL) || !need_excl)) { +@@ -314,7 +324,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) + + if (dev->open_count && !need_excl) + log_debug_devs("%s: Already opened read-only. Upgrading " +- "to read-write.", dev_name(dev)); ++ "to read-write.", name); + + /* dev_close_immediate will decrement this */ + dev->open_count++; +@@ -327,11 +337,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) + + if (critical_section()) + /* FIXME Make this log_error */ +- log_verbose("dev_open(%s) called while suspended", +- dev_name(dev)); +- +- if (!(name = dev_name_confirmed(dev, quiet))) +- return_0; ++ log_verbose("dev_open(%s) called while suspended", name); + + #ifdef O_DIRECT_SUPPORT + if (direct) { +@@ -372,9 +378,9 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) + } + #endif + if (quiet) +- log_sys_debug("open", name); ++ log_debug("Failed to open device path %s (%d).", name, errno); + else +- log_sys_error("open", name); ++ log_error("Failed to open device path %s (%d).", name, errno); + + dev->flags |= DEV_OPEN_FAILURE; + return 0; +@@ -415,10 +421,12 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) + if ((flags & O_CREAT) && !(flags & O_TRUNC)) + dev->end = lseek(dev->fd, (off_t) 0, SEEK_END); + +- log_debug_devs("Opened %s %s%s%s", dev_name(dev), +- dev->flags & DEV_OPENED_RW ? "RW" : "RO", +- dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "", +- dev->flags & DEV_O_DIRECT ? " O_DIRECT" : ""); ++ if (!quiet) { ++ log_debug_devs("Opened %s %s%s%s", name, ++ dev->flags & DEV_OPENED_RW ? "RW" : "RO", ++ dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "", ++ dev->flags & DEV_O_DIRECT ? " O_DIRECT" : ""); ++ } + + dev->flags &= ~DEV_OPEN_FAILURE; + return 1; +diff --git a/lib/device/device.h b/lib/device/device.h +index 8c3a8c30e..572994bb9 100644 +--- a/lib/device/device.h ++++ b/lib/device/device.h +@@ -204,9 +204,6 @@ struct device *dev_create_file(const char *filename, struct device *dev, + struct dm_str_list *alias, int use_malloc); + void dev_destroy_file(struct device *dev); + +-/* Return a valid device name from the alias list; NULL otherwise */ +-const char *dev_name_confirmed(struct device *dev, int quiet); +- + int dev_mpath_init(const char *config_wwids_file); + void dev_mpath_exit(void); + +-- +2.34.3 + diff --git a/0037-devices-initial-use-of-existing-option.patch b/0037-devices-initial-use-of-existing-option.patch new file mode 100644 index 0000000..79fe5f3 --- /dev/null +++ b/0037-devices-initial-use-of-existing-option.patch @@ -0,0 +1,70 @@ +From 7dc7ab8e99005da29aba22df2bb67e58e19a50f0 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 24 Feb 2022 16:10:37 -0600 +Subject: [PATCH 37/54] devices: initial use of existing option + +Use dev_cache_get_existing() in a few common, high level +locations where it's obvious that only existing dev-cache +entries are wanted. This can be expanded and used in more +locations (or dev_cache_get can stop creating new entries.) +--- + lib/device/device_id.c | 4 ++-- + tools/toollib.c | 6 +++--- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 7fe581571..bcb2e6bcf 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -1565,7 +1565,7 @@ void device_ids_match(struct cmd_context *cmd) + dm_list_iterate_items(du, &cmd->use_devices) { + if (du->dev) + continue; +- if (!(du->dev = dev_cache_get(cmd, du->devname, NULL))) { ++ if (!(du->dev = dev_cache_get_existing(cmd, du->devname, NULL))) { + log_warn("Device not found for %s.", du->devname); + } else { + /* Should we set dev->id? Which idtype? Use --deviceidtype? */ +@@ -1603,7 +1603,7 @@ void device_ids_match(struct cmd_context *cmd) + * the du/dev pairs in preparation for using the filters. + */ + if (du->devname && +- (dev = dev_cache_get(cmd, du->devname, NULL))) { ++ (dev = dev_cache_get_existing(cmd, du->devname, NULL))) { + /* On successful match, du, dev, and id are linked. */ + if (_match_du_to_dev(cmd, du, dev)) + continue; +diff --git a/tools/toollib.c b/tools/toollib.c +index d6f48aad2..16be336d4 100644 +--- a/tools/toollib.c ++++ b/tools/toollib.c +@@ -1434,7 +1434,7 @@ int process_each_label(struct cmd_context *cmd, int argc, char **argv, + goto out; + } + +- if (!(dev = dev_cache_get(cmd, argv[opt], cmd->filter))) { ++ if (!(dev = dev_cache_get_existing(cmd, argv[opt], cmd->filter))) { + log_error("Failed to find device " + "\"%s\".", argv[opt]); + ret_max = ECMD_FAILED; +@@ -3870,7 +3870,7 @@ static int _get_arg_devices(struct cmd_context *cmd, + return ECMD_FAILED; + } + +- if (!(dil->dev = dev_cache_get(cmd, sl->str, cmd->filter))) { ++ if (!(dil->dev = dev_cache_get_existing(cmd, sl->str, cmd->filter))) { + log_error("Cannot use %s: %s", sl->str, devname_error_reason(sl->str)); + ret_max = EINIT_FAILED; + } else { +@@ -5206,7 +5206,7 @@ int pvcreate_each_device(struct cmd_context *cmd, + struct device *dev; + + /* No filter used here */ +- if (!(dev = dev_cache_get(cmd, pd->name, NULL))) { ++ if (!(dev = dev_cache_get_existing(cmd, pd->name, NULL))) { + log_error("No device found for %s.", pd->name); + dm_list_del(&pd->list); + dm_list_add(&pp->arg_fail, &pd->list); +-- +2.34.3 + diff --git a/0038-devices-fix-dev_name-assumptions.patch b/0038-devices-fix-dev_name-assumptions.patch new file mode 100644 index 0000000..4608b4c --- /dev/null +++ b/0038-devices-fix-dev_name-assumptions.patch @@ -0,0 +1,270 @@ +From 591b5f006fca7e06bfbf0d5512da3ae5b0f6bbdd Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 22 Feb 2022 15:03:11 -0600 +Subject: [PATCH 38/54] devices: fix dev_name assumptions + +dev_name(dev) returns "[unknown]" if there are no names +on dev->aliases. It's meant mainly for log messages. + +Many places assume a valid path name is returned, and +use it directly. A caller that wants to use the path +from dev_name() must first check if the dev has any +paths with dm_list_empty(&dev->aliases). +--- + lib/activate/dev_manager.c | 9 ++++++++- + lib/device/dev-type.c | 3 +++ + lib/device/device_id.c | 13 +++++++++++-- + lib/label/hints.c | 2 ++ + lib/label/label.c | 16 +++++++++++++++- + lib/locking/lvmlockd.c | 4 ++++ + lib/metadata/mirror.c | 17 +++++++++++++---- + lib/metadata/pv_list.c | 5 +++++ + lib/metadata/vg.c | 5 +++++ + test/shell/losetup-partscan.sh | 2 ++ + 10 files changed, 68 insertions(+), 8 deletions(-) + +diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c +index a73a556b2..284254d68 100644 +--- a/lib/activate/dev_manager.c ++++ b/lib/activate/dev_manager.c +@@ -2875,6 +2875,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg, + + /* FIXME Avoid repeating identical stat in dm_tree_node_add_target_area */ + for (s = start_area; s < areas; s++) { ++ ++ /* FIXME: dev_name() does not return NULL! It needs to check if dm_list_empty(&dev->aliases) ++ but this knot of logic is too complex to pull apart without careful deconstruction. */ ++ + if ((seg_type(seg, s) == AREA_PV && + (!seg_pvseg(seg, s) || !seg_pv(seg, s) || !seg_dev(seg, s) || + !(name = dev_name(seg_dev(seg, s))) || !*name || +@@ -2893,7 +2897,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg, + return_0; + num_error_areas++; + } else if (seg_type(seg, s) == AREA_PV) { +- if (!dm_tree_node_add_target_area(node, dev_name(seg_dev(seg, s)), NULL, ++ struct device *dev = seg_dev(seg, s); ++ name = dm_list_empty(&dev->aliases) ? NULL : dev_name(dev); ++ ++ if (!dm_tree_node_add_target_area(node, name, NULL, + (seg_pv(seg, s)->pe_start + (extent_size * seg_pe(seg, s))))) + return_0; + num_existing_areas++; +diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c +index 0e77a009d..c67a86fa3 100644 +--- a/lib/device/dev-type.c ++++ b/lib/device/dev-type.c +@@ -966,6 +966,9 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam + + /* TODO: Should we check for valid dev - _dev_is_valid(dev)? */ + ++ if (dm_list_empty(&dev->aliases)) ++ goto_out; ++ + if (!(probe = blkid_new_probe_from_filename(dev_name(dev)))) { + log_error("Failed to create a new blkid probe for device %s.", dev_name(dev)); + goto out; +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index bcb2e6bcf..82db6e4a5 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -347,6 +347,8 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u + } + + else if (idtype == DEV_ID_TYPE_DEVNAME) { ++ if (dm_list_empty(&dev->aliases)) ++ goto_bad; + if (!(idname = strdup(dev_name(dev)))) + goto_bad; + return idname; +@@ -940,6 +942,10 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_ + if (!dev_get_partition_number(dev, &part)) + return_0; + ++ /* Ensure valid dev_name(dev) below. */ ++ if (dm_list_empty(&dev->aliases)) ++ return_0; ++ + /* + * When enable_devices_file=0 and pending_devices_file=1 we let + * pvcreate/vgcreate add new du's to cmd->use_devices. These du's may +@@ -1820,6 +1826,9 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs, + if (dev->flags & DEV_SCAN_NOT_READ) + continue; + ++ if (dm_list_empty(&dev->aliases)) ++ continue; ++ + if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) { + log_warn("Devices file %s is excluded by filter: %s.", + dev_name(dev), dev_filtered_reason(dev)); +@@ -2197,14 +2206,14 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l + dm_list_iterate_items(dil, &search_pvids) { + char *dup_devname1, *dup_devname2, *dup_devname3; + +- if (!dil->dev) { ++ if (!dil->dev || dm_list_empty(&dil->dev->aliases)) { + not_found++; + continue; + } +- found++; + + dev = dil->dev; + devname = dev_name(dev); ++ found++; + + if (!(du = get_du_for_pvid(cmd, dil->pvid))) { + /* shouldn't happen */ +diff --git a/lib/label/hints.c b/lib/label/hints.c +index 95d5d77b8..2a7b3dca7 100644 +--- a/lib/label/hints.c ++++ b/lib/label/hints.c +@@ -498,6 +498,8 @@ int validate_hints(struct cmd_context *cmd, struct dm_list *hints) + if (!(iter = dev_iter_create(NULL, 0))) + return 0; + while ((dev = dev_iter_get(cmd, iter))) { ++ if (dm_list_empty(&dev->aliases)) ++ continue; + if (!(hint = _find_hint_name(hints, dev_name(dev)))) + continue; + +diff --git a/lib/label/label.c b/lib/label/label.c +index ffe925254..cf707f7a3 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -1565,10 +1565,24 @@ int label_scan_open_rw(struct device *dev) + + int label_scan_reopen_rw(struct device *dev) + { ++ const char *name; + int flags = 0; + int prev_fd = dev->bcache_fd; + int fd; + ++ if (dm_list_empty(&dev->aliases)) { ++ log_error("Cannot reopen rw device %d:%d with no valid paths di %d fd %d.", ++ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev->bcache_di, dev->bcache_fd); ++ return 0; ++ } ++ ++ name = dev_name(dev); ++ if (!name || name[0] != '/') { ++ log_error("Cannot reopen rw device %d:%d with no valid name di %d fd %d.", ++ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev->bcache_di, dev->bcache_fd); ++ return 0; ++ } ++ + if (!(dev->flags & DEV_IN_BCACHE)) { + if ((dev->bcache_fd != -1) || (dev->bcache_di != -1)) { + /* shouldn't happen */ +@@ -1598,7 +1612,7 @@ int label_scan_reopen_rw(struct device *dev) + flags |= O_NOATIME; + flags |= O_RDWR; + +- fd = open(dev_name(dev), flags, 0777); ++ fd = open(name, flags, 0777); + if (fd < 0) { + log_error("Failed to open rw %s errno %d di %d fd %d.", + dev_name(dev), errno, dev->bcache_di, dev->bcache_fd); +diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c +index b598df3d6..60c80f1b1 100644 +--- a/lib/locking/lvmlockd.c ++++ b/lib/locking/lvmlockd.c +@@ -272,6 +272,8 @@ static void _lockd_retrive_vg_pv_list(struct volume_group *vg, + + i = 0; + dm_list_iterate_items(pvl, &vg->pvs) { ++ if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases)) ++ continue; + lock_pvs->path[i] = strdup(pv_dev_name(pvl->pv)); + if (!lock_pvs->path[i]) { + log_error("Fail to allocate PV path for VG %s", vg->name); +@@ -341,6 +343,8 @@ static void _lockd_retrive_lv_pv_list(struct volume_group *vg, + + dm_list_iterate_items(pvl, &vg->pvs) { + if (lv_is_on_pv(lv, pvl->pv)) { ++ if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases)) ++ continue; + lock_pvs->path[i] = strdup(pv_dev_name(pvl->pv)); + if (!lock_pvs->path[i]) { + log_error("Fail to allocate PV path for LV %s/%s", +diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c +index e2bf191a1..46da57948 100644 +--- a/lib/metadata/mirror.c ++++ b/lib/metadata/mirror.c +@@ -1231,14 +1231,23 @@ int remove_mirrors_from_segments(struct logical_volume *lv, + const char *get_pvmove_pvname_from_lv_mirr(const struct logical_volume *lv_mirr) + { + struct lv_segment *seg; ++ struct device *dev; + + dm_list_iterate_items(seg, &lv_mirr->segments) { + if (!seg_is_mirrored(seg)) + continue; +- if (seg_type(seg, 0) == AREA_PV) +- return dev_name(seg_dev(seg, 0)); +- if (seg_type(seg, 0) == AREA_LV) +- return dev_name(seg_dev(first_seg(seg_lv(seg, 0)), 0)); ++ if (seg_type(seg, 0) == AREA_PV) { ++ dev = seg_dev(seg, 0); ++ if (!dev || dm_list_empty(&dev->aliases)) ++ return NULL; ++ return dev_name(dev); ++ } ++ if (seg_type(seg, 0) == AREA_LV) { ++ dev = seg_dev(first_seg(seg_lv(seg, 0)), 0); ++ if (!dev || dm_list_empty(&dev->aliases)) ++ return NULL; ++ return dev_name(dev); ++ } + } + + return NULL; +diff --git a/lib/metadata/pv_list.c b/lib/metadata/pv_list.c +index 813e8e525..fc3667db0 100644 +--- a/lib/metadata/pv_list.c ++++ b/lib/metadata/pv_list.c +@@ -152,6 +152,11 @@ static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl, + struct pv_list *new_pvl = NULL, *pvl2; + struct dm_list *pe_ranges; + ++ if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases)) { ++ log_error("Failed to create PV entry for missing device."); ++ return 0; ++ } ++ + pvname = pv_dev_name(pvl->pv); + if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) { + log_warn("WARNING: Physical volume %s not allocatable.", pvname); +diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c +index 85482552a..adc954bab 100644 +--- a/lib/metadata/vg.c ++++ b/lib/metadata/vg.c +@@ -679,6 +679,11 @@ int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg, + return r; + } + ++ if (!pv->dev || dm_list_empty(&pv->dev->aliases)) { ++ log_error("No device found for PV."); ++ return r; ++ } ++ + log_debug("vgreduce_single VG %s PV %s", vg->name, pv_dev_name(pv)); + + if (pv_pe_alloc_count(pv)) { +diff --git a/test/shell/losetup-partscan.sh b/test/shell/losetup-partscan.sh +index 99f552ad1..670568945 100644 +--- a/test/shell/losetup-partscan.sh ++++ b/test/shell/losetup-partscan.sh +@@ -33,6 +33,8 @@ aux udev_wait + ls -la "${LOOP}"* + test -e "${LOOP}p1" + ++aux lvmconf 'devices/scan = "/dev"' ++ + aux extend_filter "a|$LOOP|" + aux extend_devices "$LOOP" + +-- +2.34.3 + diff --git a/0039-devices-use-dev-cache-aliases-handling-from-label-sc.patch b/0039-devices-use-dev-cache-aliases-handling-from-label-sc.patch new file mode 100644 index 0000000..49a63fe --- /dev/null +++ b/0039-devices-use-dev-cache-aliases-handling-from-label-sc.patch @@ -0,0 +1,272 @@ +From 932b9720bb074e49ac920642b3fe9c3d84019787 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 28 Feb 2022 17:37:12 -0600 +Subject: [PATCH 39/54] devices: use dev-cache aliases handling from label scan + functions + +The label scan functions where doing some device alias validation +which is now better handled by the dev-cache layer, so just use +that. +--- + lib/device/dev-cache.c | 4 +- + lib/device/dev-cache.h | 1 + + lib/label/label.c | 143 ++++++++++------------------------------- + 3 files changed, 36 insertions(+), 112 deletions(-) + +diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c +index 58e67e130..b0759b06c 100644 +--- a/lib/device/dev-cache.c ++++ b/lib/device/dev-cache.c +@@ -1410,7 +1410,7 @@ static void _remove_alias(struct device *dev, const char *name) + * deactivated LV. Those old paths are all invalid and are dropped here. + */ + +-static void _verify_aliases(struct device *dev) ++void dev_cache_verify_aliases(struct device *dev) + { + struct dm_str_list *strl, *strl2; + struct stat st; +@@ -1459,7 +1459,7 @@ static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name, + _remove_alias(dev, name); + + /* Remove any other names in dev->aliases that are incorrect. */ +- _verify_aliases(dev); ++ dev_cache_verify_aliases(dev); + } + return NULL; + } +diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h +index 51c3fc6c3..321a56d7b 100644 +--- a/lib/device/dev-cache.h ++++ b/lib/device/dev-cache.h +@@ -55,6 +55,7 @@ int dev_cache_add_dir(const char *path); + struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f); + struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f); + struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt); ++void dev_cache_verify_aliases(struct device *dev); + + struct device *dev_hash_get(const char *name); + +diff --git a/lib/label/label.c b/lib/label/label.c +index cf707f7a3..06958b502 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -458,7 +458,6 @@ static int _scan_dev_open(struct device *dev) + const char *name; + const char *modestr; + struct stat sbuf; +- int retried = 0; + int flags = 0; + int fd, di; + +@@ -478,14 +477,23 @@ static int _scan_dev_open(struct device *dev) + return 0; + } + ++ next_name: + /* + * All the names for this device (major:minor) are kept on + * dev->aliases, the first one is the primary/preferred name. ++ * ++ * The default name preferences in dev-cache mean that the first ++ * name in dev->aliases is not a symlink for scsi devices, but is ++ * the /dev/mapper/ symlink for mpath devices. ++ * ++ * If preferred names are set to symlinks, should this ++ * first attempt to open using a non-symlink? ++ * ++ * dm_list_first() returns NULL if the list is empty. + */ + if (!(name_list = dm_list_first(&dev->aliases))) { +- /* Shouldn't happen */ +- log_error("Device open %s %d:%d has no path names.", +- dev_name(dev), (int)MAJOR(dev->dev), (int)MINOR(dev->dev)); ++ log_error("Device open %d:%d has no path names.", ++ (int)MAJOR(dev->dev), (int)MINOR(dev->dev)); + return 0; + } + name_sl = dm_list_item(name_list, struct dm_str_list); +@@ -513,50 +521,34 @@ static int _scan_dev_open(struct device *dev) + modestr = "ro"; + } + +-retry_open: +- + fd = open(name, flags, 0777); +- + if (fd < 0) { + if ((errno == EBUSY) && (flags & O_EXCL)) { + log_error("Can't open %s exclusively. Mounted filesystem?", + dev_name(dev)); ++ return 0; + } else { +- int major, minor; +- + /* +- * Shouldn't happen, if it does, print stat info to help figure +- * out what's wrong. ++ * drop name from dev->aliases and use verify_aliases to ++ * drop any other invalid aliases before retrying open with ++ * any remaining valid paths. + */ +- +- major = (int)MAJOR(dev->dev); +- minor = (int)MINOR(dev->dev); +- +- log_error("Device open %s %d:%d failed errno %d", name, major, minor, errno); +- +- if (stat(name, &sbuf)) { +- log_debug_devs("Device open %s %d:%d stat failed errno %d", +- name, major, minor, errno); +- } else if (sbuf.st_rdev != dev->dev) { +- log_debug_devs("Device open %s %d:%d stat %d:%d does not match.", +- name, major, minor, +- (int)MAJOR(sbuf.st_rdev), (int)MINOR(sbuf.st_rdev)); +- } +- +- if (!retried) { +- /* +- * FIXME: remove this, the theory for this retry is that +- * there may be a udev race that we can sometimes mask by +- * retrying. This is here until we can figure out if it's +- * needed and if so fix the real problem. +- */ +- usleep(5000); +- log_debug_devs("Device open %s retry", dev_name(dev)); +- retried = 1; +- goto retry_open; +- } ++ log_debug("Drop alias for %d:%d failed open %s (%d)", ++ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), name, errno); ++ dev_cache_failed_path(dev, name); ++ dev_cache_verify_aliases(dev); ++ goto next_name; + } +- return 0; ++ } ++ ++ /* Verify that major:minor from the path still match dev. */ ++ if ((fstat(fd, &sbuf) < 0) || (sbuf.st_rdev != dev->dev)) { ++ log_warn("Invalid path %s for device %d:%d, trying different path.", ++ name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)); ++ (void)close(fd); ++ dev_cache_failed_path(dev, name); ++ dev_cache_verify_aliases(dev); ++ goto next_name; + } + + dev->flags |= DEV_IN_BCACHE; +@@ -604,37 +596,6 @@ static int _scan_dev_close(struct device *dev) + return 1; + } + +-static void _drop_bad_aliases(struct device *dev) +-{ +- struct dm_str_list *strl, *strl2; +- const char *name; +- struct stat sbuf; +- int major = (int)MAJOR(dev->dev); +- int minor = (int)MINOR(dev->dev); +- int bad; +- +- dm_list_iterate_items_safe(strl, strl2, &dev->aliases) { +- name = strl->str; +- bad = 0; +- +- if (stat(name, &sbuf)) { +- bad = 1; +- log_debug_devs("Device path check %d:%d %s stat failed errno %d", +- major, minor, name, errno); +- } else if (sbuf.st_rdev != dev->dev) { +- bad = 1; +- log_debug_devs("Device path check %d:%d %s stat %d:%d does not match.", +- major, minor, name, +- (int)MAJOR(sbuf.st_rdev), (int)MINOR(sbuf.st_rdev)); +- } +- +- if (bad) { +- log_debug_devs("Device path check %d:%d dropping path %s.", major, minor, name); +- dev_cache_failed_path(dev, name); +- } +- } +-} +- + // Like bcache_invalidate, only it throws any dirty data away if the + // write fails. + static void _invalidate_di(struct bcache *cache, int di) +@@ -662,10 +623,8 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f, + char headers_buf[HEADERS_BUF_SIZE]; + struct dm_list wait_devs; + struct dm_list done_devs; +- struct dm_list reopen_devs; + struct device_list *devl, *devl2; + struct block *bb; +- int retried_open = 0; + int scan_read_errors = 0; + int scan_process_errors = 0; + int scan_failed_count = 0; +@@ -676,7 +635,6 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f, + + dm_list_init(&wait_devs); + dm_list_init(&done_devs); +- dm_list_init(&reopen_devs); + + log_debug_devs("Scanning %d devices for VG info", dm_list_size(devs)); + +@@ -700,9 +658,9 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f, + + if (!_in_bcache(devl->dev)) { + if (!_scan_dev_open(devl->dev)) { +- log_debug_devs("Scan failed to open %s.", dev_name(devl->dev)); ++ log_debug_devs("Scan failed to open %d:%d %s.", ++ (int)MAJOR(devl->dev->dev), (int)MINOR(devl->dev->dev), dev_name(devl->dev)); + dm_list_del(&devl->list); +- dm_list_add(&reopen_devs, &devl->list); + devl->dev->flags |= DEV_SCAN_NOT_READ; + continue; + } +@@ -786,41 +744,6 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f, + if (!dm_list_empty(devs)) + goto scan_more; + +- /* +- * We're done scanning all the devs. If we failed to open any of them +- * the first time through, refresh device paths and retry. We failed +- * to open the devs on the reopen_devs list. +- * +- * FIXME: it's not clear if or why this helps. +- */ +- if (!dm_list_empty(&reopen_devs)) { +- if (retried_open) { +- /* Don't try again. */ +- scan_failed_count += dm_list_size(&reopen_devs); +- dm_list_splice(&done_devs, &reopen_devs); +- goto out; +- } +- retried_open = 1; +- +- dm_list_iterate_items_safe(devl, devl2, &reopen_devs) { +- _drop_bad_aliases(devl->dev); +- +- if (dm_list_empty(&devl->dev->aliases)) { +- log_warn("WARNING: Scan ignoring device %d:%d with no paths.", +- (int)MAJOR(devl->dev->dev), +- (int)MINOR(devl->dev->dev)); +- +- dm_list_del(&devl->list); +- lvmcache_del_dev(devl->dev); +- scan_failed_count++; +- } +- } +- +- /* Put devs that failed to open back on the original list to retry. */ +- dm_list_splice(devs, &reopen_devs); +- goto scan_more; +- } +-out: + log_debug_devs("Scanned devices: read errors %d process errors %d failed %d", + scan_read_errors, scan_process_errors, scan_failed_count); + +-- +2.34.3 + diff --git a/0040-writecache-check-memory-usage.patch b/0040-writecache-check-memory-usage.patch new file mode 100644 index 0000000..774e7a7 --- /dev/null +++ b/0040-writecache-check-memory-usage.patch @@ -0,0 +1,101 @@ +From 10a598075a0fdf6d93cc2fefa73fc4a5f1d0de48 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 1 Mar 2022 14:31:39 -0600 +Subject: [PATCH 40/54] writecache: check memory usage + +warn if writecache neds > 50% of system memory, and +confirm if writecache needs > 90% of system memory. +--- + tools/lvconvert.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 69 insertions(+) + +diff --git a/tools/lvconvert.c b/tools/lvconvert.c +index 34b82ea02..a90946173 100644 +--- a/tools/lvconvert.c ++++ b/tools/lvconvert.c +@@ -6072,6 +6072,69 @@ bad: + return 0; + } + ++static int _check_writecache_memory(struct cmd_context *cmd, struct logical_volume *lv_fast, ++ uint32_t block_size_sectors) ++{ ++ char line[128]; ++ FILE *fp; ++ uint64_t cachevol_size_bytes = lv_fast->size * SECTOR_SIZE; ++ uint64_t need_mem_bytes = 0; ++ uint64_t proc_mem_bytes = 0; ++ uint64_t need_mem_gb; ++ uint64_t proc_mem_gb; ++ unsigned long long proc_mem_kb = 0; ++ ++ if (!(fp = fopen("/proc/meminfo", "r"))) ++ goto skip_proc; ++ ++ while (fgets(line, sizeof(line), fp)) { ++ if (strncmp(line, "MemTotal:", 9)) ++ continue; ++ if (sscanf(line, "%*s%llu%*s", &proc_mem_kb) != 1) ++ break; ++ break; ++ } ++ (void)fclose(fp); ++ ++ proc_mem_bytes = proc_mem_kb * 1024; ++ ++ skip_proc: ++ /* dm-writecache memory consumption per block is 88 bytes */ ++ if (block_size_sectors == 8) { ++ need_mem_bytes = cachevol_size_bytes * 88 / 4096; ++ } else if (block_size_sectors == 1) { ++ need_mem_bytes = cachevol_size_bytes * 88 / 512; ++ } else { ++ /* shouldn't happen */ ++ log_warn("Unknown memory usage for unknown writecache block_size_sectors %u", block_size_sectors); ++ return 1; ++ } ++ ++ need_mem_gb = need_mem_bytes / 1073741824; ++ proc_mem_gb = proc_mem_bytes / 1073741824; ++ ++ /* ++ * warn if writecache needs > 50% of main memory, and ++ * confirm if writecache needs > 90% of main memory. ++ */ ++ if (need_mem_bytes >= (proc_mem_bytes / 2)) { ++ log_warn("WARNING: writecache size %s will use %llu GiB of system memory (%llu GiB).", ++ display_size(cmd, lv_fast->size), ++ (unsigned long long)need_mem_gb, ++ (unsigned long long)proc_mem_gb); ++ ++ if (need_mem_gb >= (proc_mem_gb * 9 / 10)) { ++ if (!arg_is_set(cmd, yes_ARG) && ++ yes_no_prompt("Continue adding writecache? [y/n]: ") == 'n') { ++ log_error("Conversion aborted."); ++ return 0; ++ } ++ } ++ } ++ ++ return 1; ++} ++ + int lvconvert_writecache_attach_single(struct cmd_context *cmd, + struct logical_volume *lv, + struct processing_handle *handle) +@@ -6160,6 +6223,12 @@ int lvconvert_writecache_attach_single(struct cmd_context *cmd, + goto_bad; + } + ++ if (!_check_writecache_memory(cmd, lv_fast, block_size_sectors)) { ++ if (!is_active && !deactivate_lv(cmd, lv)) ++ stack; ++ goto_bad; ++ } ++ + if (!is_active) { + if (!deactivate_lv(cmd, lv)) { + log_error("Failed to deactivate LV after checking block size %s", display_lvname(lv)); +-- +2.34.3 + diff --git a/0041-change-messages-about-filtered-devices.patch b/0041-change-messages-about-filtered-devices.patch new file mode 100644 index 0000000..e1b7aa0 --- /dev/null +++ b/0041-change-messages-about-filtered-devices.patch @@ -0,0 +1,108 @@ +From 090dc0c320f0abee8ab79f4eaea6561c195b5009 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 31 Mar 2022 11:38:08 -0500 +Subject: [PATCH 41/54] change messages about filtered devices + +Change messages that refer to devices being "excluded by filters" +to say just "excluded". This will avoid mistaking the word +"filters" with the lvm.conf filter setting. +--- + lib/device/device_id.c | 6 +++--- + tools/lvmdevices.c | 4 ++-- + tools/pvscan.c | 4 ++-- + tools/vgimportclone.c | 4 ++-- + 4 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 82db6e4a5..6133e700a 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -1744,7 +1744,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs, + * probably wants to do something about it. + */ + if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) { +- log_warn("Devices file %s is excluded by filter: %s.", ++ log_warn("Devices file %s is excluded: %s.", + dev_name(dev), dev_filtered_reason(dev)); + continue; + } +@@ -1830,7 +1830,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs, + continue; + + if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) { +- log_warn("Devices file %s is excluded by filter: %s.", ++ log_warn("Devices file %s is excluded: %s.", + dev_name(dev), dev_filtered_reason(dev)); + /* FIXME: what if this dev is wrongly matched and should be checked below? */ + continue; +@@ -2266,7 +2266,7 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l + + if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) { + /* I don't think this would happen */ +- log_warn("WARNING: new device %s for PVID %s does not pass filter %s.", ++ log_warn("WARNING: new device %s for PVID %s is excluded: %s.", + dev_name(dev), dil->pvid, dev_filtered_reason(dev)); + if (du) /* Should not happen 'du' is NULL */ + du->dev = NULL; +diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c +index 662b35f9a..8521b89ea 100644 +--- a/tools/lvmdevices.c ++++ b/tools/lvmdevices.c +@@ -112,7 +112,7 @@ static void _search_devs_for_pvids(struct cmd_context *cmd, struct dm_list *sear + dev = devl->dev; + cmd->filter->wipe(cmd, cmd->filter, dev, NULL); + if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) { +- log_warn("WARNING: PVID %s found on %s which is excluded by filter: %s", ++ log_warn("WARNING: PVID %s found on %s which is excluded: %s", + dev->pvid, dev_name(dev), dev_filtered_reason(dev)); + dm_list_del(&devl->list); + } +@@ -310,7 +310,7 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv) + cmd->filter_deviceid_skip = 1; + + if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) { +- log_warn("WARNING: adding device %s that is excluded by filter: %s.", ++ log_warn("WARNING: adding device %s that is excluded: %s.", + dev_name(dev), dev_filtered_reason(dev)); + } + +diff --git a/tools/pvscan.c b/tools/pvscan.c +index 160a2c9a0..50d46051a 100644 +--- a/tools/pvscan.c ++++ b/tools/pvscan.c +@@ -1756,7 +1756,7 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv, + + dm_list_iterate_items_safe(devl, devl2, &pvscan_devs) { + if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, NULL)) { +- log_print_pvscan(cmd, "%s excluded by filters: %s.", ++ log_print_pvscan(cmd, "%s excluded: %s.", + dev_name(devl->dev), dev_filtered_reason(devl->dev)); + dm_list_del(&devl->list); + } +@@ -1813,7 +1813,7 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv, + + /* Applies all filters, including those that need data from dev. */ + if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, NULL)) { +- log_print_pvscan(cmd, "%s excluded by filters: %s.", ++ log_print_pvscan(cmd, "%s excluded: %s.", + dev_name(devl->dev), dev_filtered_reason(devl->dev)); + dm_list_del(&devl->list); + } +diff --git a/tools/vgimportclone.c b/tools/vgimportclone.c +index 23bb6271f..cab501619 100644 +--- a/tools/vgimportclone.c ++++ b/tools/vgimportclone.c +@@ -311,8 +311,8 @@ int vgimportclone(struct cmd_context *cmd, int argc, char **argv) + */ + dm_list_iterate_items(devl, &vp.new_devs) { + if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, "persistent")) { +- /* FIXME: print which filter */ +- log_error("Device %s was excluded by filters.", dev_name(devl->dev)); ++ log_error("Device %s is excluded: %s.", ++ dev_name(devl->dev), dev_filtered_reason(devl->dev)); + goto out; + } + } +-- +2.34.3 + diff --git a/0042-vgimportdevices-fix-incorrect-deviceidtype-usage.patch b/0042-vgimportdevices-fix-incorrect-deviceidtype-usage.patch new file mode 100644 index 0000000..fbf6ee7 --- /dev/null +++ b/0042-vgimportdevices-fix-incorrect-deviceidtype-usage.patch @@ -0,0 +1,31 @@ +From 4aa92f3e18cb49470ee9b5d928abe6b4c86f3074 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 6 Apr 2022 12:20:26 -0500 +Subject: [PATCH 42/54] vgimportdevices: fix incorrect deviceidtype usage + +When a VG has PVs with different device id types, +it would try to use the idtype of the previous PV +in the loop. This would produce an unncessary warning, +or could lead to using the devname idtype when a better +idtype is available. +--- + tools/vgimportdevices.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/tools/vgimportdevices.c b/tools/vgimportdevices.c +index 2580613c4..ea205d941 100644 +--- a/tools/vgimportdevices.c ++++ b/tools/vgimportdevices.c +@@ -57,8 +57,7 @@ static int _vgimportdevices_single(struct cmd_context *cmd, + dm_list_iterate_items(pvl, &vg->pvs) { + pv = pvl->pv; + +- if (!idtypestr && pv->device_id_type) +- idtypestr = pv->device_id_type; ++ idtypestr = pv->device_id_type; + + memcpy(pvid, &pvl->pv->id.uuid, ID_LEN); + device_id_add(cmd, pv->dev, pvid, idtypestr, NULL); +-- +2.34.3 + diff --git a/0043-lvmlockd-return-error-from-vgcreate-init_vg_sanlock.patch b/0043-lvmlockd-return-error-from-vgcreate-init_vg_sanlock.patch new file mode 100644 index 0000000..f67d1a5 --- /dev/null +++ b/0043-lvmlockd-return-error-from-vgcreate-init_vg_sanlock.patch @@ -0,0 +1,32 @@ +From 6de2a6a378a7673168fad34aebe8ddcb564a5911 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Fri, 8 Apr 2022 11:28:53 -0500 +Subject: [PATCH 43/54] lvmlockd: return error from vgcreate init_vg_sanlock + +in vgcreate for shared sanlock vg, if sanlock_write_resource +returns an unexpected error, then make init_vg_sanlock fail +which will cause the vgcreate to fail. +--- + daemons/lvmlockd/lvmlockd-sanlock.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c +index e595eeffd..d87d1093b 100644 +--- a/daemons/lvmlockd/lvmlockd-sanlock.c ++++ b/daemons/lvmlockd/lvmlockd-sanlock.c +@@ -684,10 +684,10 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar + break; + } + +- if (rv) { ++ if (rv < 0) { + log_error("clear lv resource area %llu error %d", + (unsigned long long)offset, rv); +- break; ++ return rv; + } + offset += align_size; + } +-- +2.34.3 + diff --git a/0044-devices-file-remove-extraneous-unlock-in-vgchange-u.patch b/0044-devices-file-remove-extraneous-unlock-in-vgchange-u.patch new file mode 100644 index 0000000..8009d2f --- /dev/null +++ b/0044-devices-file-remove-extraneous-unlock-in-vgchange-u.patch @@ -0,0 +1,45 @@ +From d96432835532fbcd8c72694c6ed68fca3ce98d5c Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 13 Apr 2022 12:16:57 -0500 +Subject: [PATCH 44/54] devices file: remove extraneous unlock in vgchange -u + +vgchange -u exit path was unlocking the devices file in cases +when it wasn't needed, which produced an warning. +--- + lib/device/device_id.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 6133e700a..20901ab90 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -1272,15 +1272,15 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg, + int update = 0; + + if (!cmd->enable_devices_file) +- goto out; ++ return; + + /* Without this setting there is no stacking LVs on PVs. */ + if (!cmd->scan_lvs) +- goto out; ++ return; + + /* Check if any devices file entries are stacked on LVs. */ + if (!_device_ids_use_lvmlv(cmd)) +- goto out; ++ return; + + memcpy(old_vgid, old_vg_id, ID_LEN); + memcpy(new_vgid, &vg->id, ID_LEN); +@@ -1310,7 +1310,6 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg, + if (update && + !device_ids_write(cmd)) + stack; +- out: + unlock_devices_file(cmd); + } + +-- +2.34.3 + diff --git a/0025-filter-mpath-use-multipath-blacklist.patch b/0045-filter-mpath-use-multipath-blacklist.patch similarity index 82% rename from 0025-filter-mpath-use-multipath-blacklist.patch rename to 0045-filter-mpath-use-multipath-blacklist.patch index b8bc200..c2f921a 100644 --- a/0025-filter-mpath-use-multipath-blacklist.patch +++ b/0045-filter-mpath-use-multipath-blacklist.patch @@ -1,25 +1,22 @@ -From 1199fd6af6d57c45e857bff218c817d8d0cac986 Mon Sep 17 00:00:00 2001 +From 5d40b91bd4aa8580ee1f40d467b848f7847f39e3 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Thu, 21 Apr 2022 13:45:01 -0500 -Subject: [PATCH 1/2] filter-mpath: use multipath blacklist +Subject: [PATCH 45/54] filter-mpath: use multipath blacklist Explicit wwid's from these sections control whether the same wwid in /etc/multipath/wwids is recognized as a multipath component. Other non-wwid keywords are not used, and may require disabling the use of the multipath wwids file in lvm.conf. - -(cherry picked from commit 5d40b91bd4aa8580ee1f40d467b848f7847f39e3) --- lib/device/dev-mpath.c | 181 ++++++++++++++++++++++++-- - test/shell/duplicate-pvs-multipath.sh | 67 ++++++++++ + test/shell/duplicate-pvs-multipath.sh | 2 +- test/shell/multipath-config.sh | 171 ++++++++++++++++++++++++ - 3 files changed, 408 insertions(+), 11 deletions(-) - create mode 100644 test/shell/duplicate-pvs-multipath.sh + 3 files changed, 342 insertions(+), 12 deletions(-) create mode 100644 test/shell/multipath-config.sh diff --git a/lib/device/dev-mpath.c b/lib/device/dev-mpath.c -index ba7bf9740..580ab31a5 100644 +index cbbad9dc9..6eed03c5b 100644 --- a/lib/device/dev-mpath.c +++ b/lib/device/dev-mpath.c @@ -17,12 +17,14 @@ @@ -267,78 +264,18 @@ index ba7bf9740..580ab31a5 100644 diff --git a/test/shell/duplicate-pvs-multipath.sh b/test/shell/duplicate-pvs-multipath.sh -new file mode 100644 -index 000000000..59c15b0d4 ---- /dev/null +index a145e4afb..59c15b0d4 100644 +--- a/test/shell/duplicate-pvs-multipath.sh +++ b/test/shell/duplicate-pvs-multipath.sh -@@ -0,0 +1,67 @@ -+#!/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 -+ +@@ -10,7 +10,7 @@ + # along with this program; if not, write to the Free Software Foundation, + # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +-test_description='udev rule and systemd unit run vgchange' +test_description='duplicate pv detection of mpath components using wwid' -+ -+SKIP_WITH_LVMPOLLD=1 -+SKIP_WITH_LVMLOCKD=1 -+ -+. lib/inittest -+ -+# FIXME: skip until mpath/scsi_debug cleanup works after a failure -+skip -+ -+modprobe --dry-run scsi_debug || skip -+multipath -l || skip -+multipath -l | grep scsi_debug && skip -+ -+# Turn off multipath_component_detection so that the duplicate -+# resolution of mpath components is used. -+aux lvmconf 'devices/multipath_component_detection = 0' -+# Prevent wwids from being used for filtering. -+aux lvmconf 'devices/multipath_wwids_file = "/dev/null"' -+# Need to use /dev/mapper/mpath -+aux lvmconf 'devices/dir = "/dev"' -+aux lvmconf 'devices/scan = "/dev"' -+# Could set filter to $MP and the component /dev/sd devs -+aux lvmconf "devices/filter = [ \"a|.*|\" ]" -+aux lvmconf "devices/global_filter = [ \"a|.*|\" ]" -+ -+modprobe scsi_debug dev_size_mb=100 num_tgts=1 vpd_use_hostno=0 add_host=4 delay=20 max_luns=2 no_lun_0=1 -+sleep 2 -+ -+multipath -r -+sleep 2 -+ -+MPB=$(multipath -l | grep scsi_debug | cut -f1 -d ' ') -+echo $MPB -+MP=/dev/mapper/$MPB -+echo $MP -+ -+pvcreate $MP -+vgcreate $vg1 $MP -+lvcreate -l1 $vg1 -+vgchange -an $vg1 -+ -+pvs |tee out -+grep $MP out -+for i in $(grep -H scsi_debug /sys/block/sd*/device/model | cut -f4 -d /); do -+ not grep /dev/$i out; -+done -+ -+vgchange -an $vg1 -+vgremove -y $vg1 -+ -+sleep 2 -+multipath -f $MP -+sleep 1 -+rmmod scsi_debug + + SKIP_WITH_LVMPOLLD=1 + SKIP_WITH_LVMLOCKD=1 diff --git a/test/shell/multipath-config.sh b/test/shell/multipath-config.sh new file mode 100644 index 000000000..ffb7d632a diff --git a/0046-improve-description-of-devices-option.patch b/0046-improve-description-of-devices-option.patch new file mode 100644 index 0000000..3ec4a9e --- /dev/null +++ b/0046-improve-description-of-devices-option.patch @@ -0,0 +1,28 @@ +From e027f4da9bc7b4ed9b225af75089e3443595bf81 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 2 May 2022 09:46:28 -0500 +Subject: [PATCH 46/54] improve description of devices option + +--- + tools/args.h | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/tools/args.h b/tools/args.h +index 9a7bf81b2..00a2ec817 100644 +--- a/tools/args.h ++++ b/tools/args.h +@@ -235,8 +235,9 @@ arg(deviceidtype_ARG, '\0', "deviceidtype", string_VAL, 0, 0, + "then it will override the default type that lvm would use.\n") + + arg(devices_ARG, '\0', "devices", pv_VAL, ARG_GROUPABLE, 0, +- "Devices that the command can use. This option can be repeated\n" +- "or accepts a comma separated list of devices. This overrides\n" ++ "Restricts the devices that are visible and accessible to the command.\n" ++ "Devices not listed will appear to be missing. This option can be\n" ++ "repeated, or accepts a comma separated list of devices. This overrides\n" + "the devices file.\n") + + arg(devicesfile_ARG, '\0', "devicesfile", string_VAL, 0, 0, +-- +2.34.3 + diff --git a/0047-vdo-support-vdosettings.patch b/0047-vdo-support-vdosettings.patch new file mode 100644 index 0000000..e6d91f3 --- /dev/null +++ b/0047-vdo-support-vdosettings.patch @@ -0,0 +1,576 @@ +From 9c6954bc61b22ca03df8897d88eb9618e65fc3c6 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Wed, 13 Apr 2022 15:09:08 +0200 +Subject: [PATCH 47/54] vdo: support --vdosettings + +Allow to use --vdosettings with lvcreate,lvconvert,lvchange. +Support settings currenly only configurable via lvm.conf. +With lvchange we require inactivate LV for changes to be applied. + +Settings block_map_era_length has supported alias block_map_period. +--- + device_mapper/vdo/target.h | 6 +- + man/lvmvdo.7_main | 39 ++++++-- + test/shell/lvchange-vdo.sh | 8 ++ + test/shell/lvconvert-vdo.sh | 8 +- + test/shell/lvcreate-vdo.sh | 6 +- + tools/args.h | 9 ++ + tools/command-lines.in | 6 +- + tools/lvchange.c | 43 ++++++++- + tools/lvconvert.c | 9 +- + tools/lvcreate.c | 34 ++++--- + tools/toollib.c | 177 ++++++++++++++++++++++++++++++++++++ + tools/toollib.h | 6 ++ + 12 files changed, 312 insertions(+), 39 deletions(-) + +diff --git a/device_mapper/vdo/target.h b/device_mapper/vdo/target.h +index 51dde3f4d..60c5bff56 100644 +--- a/device_mapper/vdo/target.h ++++ b/device_mapper/vdo/target.h +@@ -77,8 +77,10 @@ enum dm_vdo_write_policy { + struct dm_vdo_target_params { + uint32_t minimum_io_size; // in sectors + uint32_t block_map_cache_size_mb; +- uint32_t block_map_era_length; // format period +- ++ union { ++ uint32_t block_map_era_length; // format period ++ uint32_t block_map_period; // supported alias ++ }; + uint32_t check_point_frequency; + uint32_t index_memory_size_mb; // format + +diff --git a/man/lvmvdo.7_main b/man/lvmvdo.7_main +index 3b77173c4..14bd640b5 100644 +--- a/man/lvmvdo.7_main ++++ b/man/lvmvdo.7_main +@@ -132,6 +132,19 @@ that can keep 100% incompressible data there. + # lvconvert --type vdo-pool -n vdo0 -V10G vg/ExistingLV + .fi + . ++.SS \n+[step]. 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). ++.P ++.B lvchange --compression y|n --deduplication y|n VG/VDOPoolLV ++.P ++.I Example ++.nf ++# lvchange --compression n vg/vdopool0 ++# lvchange --deduplication y vg/vdopool1 ++.fi ++. + .SS \n+[step]. Change the default settings used for creating a VDOPoolLV + . + VDO allows to set a large variety of options. Lots of these settings +@@ -173,17 +186,27 @@ EOF + # lvcreate --vdo -L10G --config 'allocation/vdo_cpu_threads=4' vg/vdopool1 + .fi + . +-.SS \n+[step]. 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). +-.P +-.B lvchange --compression y|n --deduplication y|n VG/VDOPoolLV ++.SS \n+[step]. Set or change VDO settings with option --vdosettings ++. ++Use the form 'option=value' or 'option1=value option2=value', ++or repeat --vdosettings for each option being set. ++Options are listed in the Example section above, for the full description see ++.BR lvm.conf (5). ++Options can omit 'vdo_' and 'vdo_use_' prefixes and all its underscores. ++So i.e. vdo_use_metadata_hints=1 and metadatahints=1 are equivalent. ++To change the option for an already existing VDOPoolLV use ++.BR lvchange (8) ++command. However not all option can be changed. ++Only compression and deduplication options can be also changed for an active VDO LV. ++Lowest priority options are specified with configuration file, ++then with --vdosettings and highest are expliction option --compression ++and --deduplication. + .P + .I Example ++.P + .nf +-# lvchange --compression n vg/vdopool0 +-# lvchange --deduplication y vg/vdopool1 ++# lvcreate --vdo -L10G --vdosettings 'ack_threads=1 hash_zone_threads=2' vg/vdopool0 ++# lvchange --vdosettings 'bio_threads=2 deduplication=1' vg/vdopool0 + .fi + . + .SS \n+[step]. Checking the usage of VDOPoolLV +diff --git a/test/shell/lvchange-vdo.sh b/test/shell/lvchange-vdo.sh +index 461b7821f..7cc44d6bc 100644 +--- a/test/shell/lvchange-vdo.sh ++++ b/test/shell/lvchange-vdo.sh +@@ -48,9 +48,17 @@ check grep_dmsetup status $vg-vdopool-vpool " online online " + lvchange --compression n --deduplication n $vg/vdopool + check grep_dmsetup status $vg-vdopool-vpool " offline offline " + ++# --vdosettings needs inactive LV ++not lvchange --vdosettings 'ack_threads=8' $vg/vdopool + + lvchange -an $vg/$lv1 + ++# With inactive vdo-pool changes are applied ++# explicit option --compression has highest priority ++lvchange --vdosettings 'ack_threads=5 compression=0' --compression y $vg/vdopool ++check lv_field $vg/$lv1 vdo_ack_threads "5" ++check lv_field $vg/$lv1 vdo_compression "enabled" ++ + # Test activation + lvchange -aly $vg/$lv1 + check active $vg $lv1 +diff --git a/test/shell/lvconvert-vdo.sh b/test/shell/lvconvert-vdo.sh +index 529f325bd..c42d8f25a 100644 +--- a/test/shell/lvconvert-vdo.sh ++++ b/test/shell/lvconvert-vdo.sh +@@ -28,12 +28,12 @@ lvcreate -L5G -n $lv1 $vg + not lvconvert --type vdo-pool $vg/$lv1 |& tee out + grep "WARNING" out + +- +-lvconvert -y --type vdo-pool $vg/$lv1 ++# Check --vdosettings is also applied to converted vdo-pool ++lvconvert -y --type vdo-pool --vdosettings 'ack_threads=5' $vg/$lv1 ++check lv_field $vg/$lv1 vdo_ack_threads "5" + lvremove -f $vg + +- +-# ++# + lvcreate -L5G -n $lv1 $vg + lvconvert -y --vdopool $vg/$lv1 + lvremove -f $vg +diff --git a/test/shell/lvcreate-vdo.sh b/test/shell/lvcreate-vdo.sh +index 44f8bf094..3e807ac94 100644 +--- a/test/shell/lvcreate-vdo.sh ++++ b/test/shell/lvcreate-vdo.sh +@@ -79,8 +79,12 @@ not fsck -n "$DM_DEV_DIR/mapper/$vg-${lv2}" + + lvremove -ff $vg + ++# Unknown settings does not pass ++# TODO: try to catch this in parser and 'fail' ++not lvcreate --type vdo --vdosettings 'ack_Xthreads=4' -L10G -V1T -ky -n $lv1 $vg + +-lvcreate --type vdo -L10G -V1T -ky -n $lv1 $vg ++lvcreate --type vdo --vdosettings 'ack_threads=4' -L10G -V1T -ky -n $lv1 $vg ++check lv_field $vg/$lv1 vdo_ack_threads "4" + lvs -a $vg + lvremove -ff $vg + +diff --git a/tools/args.h b/tools/args.h +index 00a2ec817..bfd848ce9 100644 +--- a/tools/args.h ++++ b/tools/args.h +@@ -900,6 +900,15 @@ arg(vdopool_ARG, '\0', "vdopool", lv_VAL, 0, 0, + "The name of a VDO pool LV.\n" + "See \\fBlvmvdo\\fP(7) for more information about VDO usage.\n") + ++arg(vdosettings_ARG, '\0', "vdosettings", string_VAL, ARG_GROUPABLE, 0, ++ "Specifies tunable VDO options for VDO LVs.\n" ++ "Use the form 'option=value' or 'option1=value option2=value', or\n" ++ "repeat --vdosettings for each option being set.\n" ++ "These settings override the default VDO behaviors.\n" ++ "To remove vdosettings and revert to the default\n" ++ "VDO behaviors, use --vdosettings 'default'.\n" ++ "See \\fBlvmvdo\\fP(7) for more information.\n") ++ + arg(version_ARG, '\0', "version", 0, 0, 0, + "Display version information.\n") + +diff --git a/tools/command-lines.in b/tools/command-lines.in +index 00ac08934..08302b34f 100644 +--- a/tools/command-lines.in ++++ b/tools/command-lines.in +@@ -243,6 +243,7 @@ OO_LVCHANGE_META: --addtag Tag, --deltag Tag, + --setautoactivation Bool, --errorwhenfull Bool, --discards Discards, --zero Bool, + --cachemode CacheMode, --cachepolicy String, --cachesettings String, + --minrecoveryrate SizeKB, --maxrecoveryrate SizeKB, ++--vdosettings String, + --writebehind Number, --writemostly WriteMostlyPV, --persistent n + + # It's unfortunate that activate needs to be optionally allowed here; +@@ -341,7 +342,8 @@ OO_LVCONVERT_CACHE: --cachemetadataformat CacheMetadataFormat, + --cachesettings String, --zero Bool + + OO_LVCONVERT_VDO: --metadataprofile String, --readahead Readahead, +---compression Bool, --deduplication Bool, --zero Bool ++--compression Bool, --deduplication Bool, --vdosettings String, ++--zero Bool + + OO_LVCONVERT: --alloc Alloc, --background, --force, --noudevsync + +@@ -839,7 +841,7 @@ OO_LVCREATE_POOL: --poolmetadatasize SizeMB, --poolmetadataspare Bool, --chunksi + + OO_LVCREATE_THINPOOL: --discards Discards, --errorwhenfull Bool + +-OO_LVCREATE_VDO: --compression Bool, --deduplication Bool ++OO_LVCREATE_VDO: --compression Bool, --deduplication Bool, --vdosettings String + --- + + lvcreate --type error --size SizeMB VG +diff --git a/tools/lvchange.c b/tools/lvchange.c +index 0525bc53c..dc51786d7 100644 +--- a/tools/lvchange.c ++++ b/tools/lvchange.c +@@ -755,6 +755,43 @@ out: + return r; + } + ++static int _lvchange_vdo(struct cmd_context *cmd, ++ struct logical_volume *lv, ++ uint32_t *mr) ++{ ++ struct lv_segment *seg; ++ int updated = 0; ++ ++ seg = first_seg(lv); ++ ++ // With VDO LV given flip to VDO pool ++ if (seg_is_vdo(seg)) ++ seg = first_seg(seg_lv(seg, 0)); ++ ++ if (!get_vdo_settings(cmd, &seg->vdo_params, &updated)) ++ return_0; ++ ++ if ((updated & VDO_CHANGE_OFFLINE) && ++ lv_info(cmd, seg->lv, 1, NULL, 0, 0)) { ++ log_error("Cannot change VDO settings for active VDO pool %s.", ++ display_lvname(seg->lv)); ++ // TODO maybe add --force support with prompt here ++ log_print_unless_silent("VDO pool %s with all its LVs needs to be deactivated.", ++ display_lvname(seg->lv)); ++ return 0; ++ } ++ ++ if (updated) { ++ if (!dm_vdo_validate_target_params(&seg->vdo_params, 0 /* vdo_size */)) ++ return_0; ++ ++ /* Request caller to commit and reload metadata */ ++ *mr |= MR_RELOAD; ++ } ++ ++ return 1; ++} ++ + static int _lvchange_tag(struct cmd_context *cmd, struct logical_volume *lv, + int arg, uint32_t *mr) + { +@@ -1154,6 +1191,7 @@ static int _option_requires_direct_commit(int opt_enum) + cachemode_ARG, + cachepolicy_ARG, + cachesettings_ARG, ++ vdosettings_ARG, + -1 + }; + +@@ -1354,7 +1392,10 @@ static int _lvchange_properties_single(struct cmd_context *cmd, + docmds++; + doit += _lvchange_cache(cmd, lv, &mr); + break; +- ++ case vdosettings_ARG: ++ docmds++; ++ doit += _lvchange_vdo(cmd, lv, &mr); ++ break; + default: + log_error(INTERNAL_ERROR "Failed to check for option %s", + arg_long_option_name(i)); +diff --git a/tools/lvconvert.c b/tools/lvconvert.c +index a90946173..3d4b24fe3 100644 +--- a/tools/lvconvert.c ++++ b/tools/lvconvert.c +@@ -5456,13 +5456,8 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd, + if (!fill_vdo_target_params(cmd, &vdo_params, &vdo_pool_header_size, vg->profile)) + goto_out; + +- if (arg_is_set(cmd, compression_ARG)) +- vdo_params.use_compression = +- arg_int_value(cmd, compression_ARG, 0); +- +- if (arg_is_set(cmd, deduplication_ARG)) +- vdo_params.use_deduplication = +- arg_int_value(cmd, deduplication_ARG, 0); ++ if (!get_vdo_settings(cmd, &vdo_params, NULL)) ++ return_0; + + if (!activate_lv(cmd, lv)) { + log_error("Cannot activate %s.", display_lvname(lv)); +diff --git a/tools/lvcreate.c b/tools/lvcreate.c +index 79af42685..8de6f3408 100644 +--- a/tools/lvcreate.c ++++ b/tools/lvcreate.c +@@ -698,6 +698,23 @@ static int _read_cache_params(struct cmd_context *cmd, + return 1; + } + ++static int _read_vdo_params(struct cmd_context *cmd, ++ struct lvcreate_params *lp) ++{ ++ if (!seg_is_vdo(lp)) ++ return 1; ++ ++ // prefiling settings here ++ if (!fill_vdo_target_params(cmd, &lp->vdo_params, &lp->vdo_pool_header_size, NULL)) ++ return_0; ++ ++ // override with optional vdo settings ++ if (!get_vdo_settings(cmd, &lp->vdo_params, NULL)) ++ return_0; ++ ++ return 1; ++} ++ + static int _read_activation_params(struct cmd_context *cmd, + struct volume_group *vg, + struct lvcreate_params *lp) +@@ -888,7 +905,8 @@ static int _lvcreate_params(struct cmd_context *cmd, + #define VDO_POOL_ARGS \ + vdopool_ARG,\ + compression_ARG,\ +- deduplication_ARG ++ deduplication_ARG,\ ++ vdosettings_ARG + + /* Cache and cache-pool segment type */ + if (seg_is_cache(lp)) { +@@ -1098,19 +1116,6 @@ static int _lvcreate_params(struct cmd_context *cmd, + zero_ARG, + -1)) + return_0; +- +- // FIXME: prefiling here - this is wrong place +- // but will work for this moment +- if (!fill_vdo_target_params(cmd, &lp->vdo_params, &lp->vdo_pool_header_size, NULL)) +- return_0; +- +- if (arg_is_set(cmd, compression_ARG)) +- lp->vdo_params.use_compression = +- arg_int_value(cmd, compression_ARG, 0); +- +- if (arg_is_set(cmd, deduplication_ARG)) +- lp->vdo_params.use_deduplication = +- arg_int_value(cmd, deduplication_ARG, 0); + } + + /* Check options shared between more segment types */ +@@ -1198,6 +1203,7 @@ static int _lvcreate_params(struct cmd_context *cmd, + &lp->pool_metadata_size, &lp->pool_metadata_spare, + &lp->chunk_size, &lp->discards, &lp->zero_new_blocks)) || + !_read_cache_params(cmd, lp) || ++ !_read_vdo_params(cmd, lp) || + !_read_mirror_and_raid_params(cmd, lp)) + return_0; + +diff --git a/tools/toollib.c b/tools/toollib.c +index 16be336d4..697baee82 100644 +--- a/tools/toollib.c ++++ b/tools/toollib.c +@@ -1192,6 +1192,183 @@ out: + return ok; + } + ++/* ++ * Compare VDO option name, skip any '_' in name ++ * and also allow to use it without vdo_[use_] prefix ++ */ ++static int _compare_vdo_option(const char *b1, const char *b2) ++{ ++ if (strncasecmp(b1, "vdo", 3) == 0) // skip vdo prefix ++ b1 += 3; ++ ++ if ((tolower(*b1) != tolower(*b2)) && ++ (strncmp(b2, "use_", 4) == 0)) ++ b2 += 4; // try again with skipped prefix 'use_' ++ ++ while (*b1 && *b2) { ++ if (tolower(*b1) == tolower(*b2)) { ++ ++b1; ++ ++b2; ++ continue; // matching char ++ } ++ ++ if (*b1 == '_') ++ ++b1; // skip to next char ++ else if (*b2 == '_') ++ ++b2; // skip to next char ++ else ++ break; // mismatch ++ } ++ ++ return (*b1 || *b2) ? 0 : 1; ++} ++ ++#define CHECK_AND_SET(var, onoff) \ ++ option = #var;\ ++ if (_compare_vdo_option(cn->key, option)) {\ ++ if (is_lvchange || !cn->v || (cn->v->type != DM_CFG_INT))\ ++ goto err;\ ++ if (vtp->var != cn->v->v.i) {\ ++ vtp->var = cn->v->v.i;\ ++ u |= onoff;\ ++ }\ ++ continue;\ ++ } ++ ++#define DO_OFFLINE(var) \ ++ CHECK_AND_SET(var, VDO_CHANGE_OFFLINE) ++ ++#define DO_ONLINE(var) \ ++ CHECK_AND_SET(var, VDO_CHANGE_ONLINE) ++ ++int get_vdo_settings(struct cmd_context *cmd, ++ struct dm_vdo_target_params *vtp, ++ int *updated) ++{ ++ const char *str, *option = NULL; ++ struct arg_value_group_list *group; ++ struct dm_config_tree *result = NULL, *prev = NULL, *current = NULL; ++ struct dm_config_node *cn; ++ int r = 0, u = 0, is_lvchange; ++ int use_compression = vtp->use_compression; ++ int use_deduplication = vtp->use_deduplication; ++ int checked_lvchange; ++ ++ if (updated) ++ *updated = 0; ++ ++ // Group all --vdosettings ++ dm_list_iterate_items(group, &cmd->arg_value_groups) { ++ if (!grouped_arg_is_set(group->arg_values, vdosettings_ARG)) ++ continue; ++ ++ if (!(current = dm_config_create())) ++ goto_out; ++ if (prev) ++ current->cascade = prev; ++ prev = current; ++ ++ if (!(str = grouped_arg_str_value(group->arg_values, ++ vdosettings_ARG, ++ NULL))) ++ goto_out; ++ ++ if (!dm_config_parse_without_dup_node_check(current, str, str + strlen(str))) ++ goto_out; ++ } ++ ++ if (current) { ++ if (!(result = dm_config_flatten(current))) ++ goto_out; ++ ++ checked_lvchange = !strcmp(cmd->name, "lvchange"); ++ ++ /* Use all acceptable VDO options */ ++ for (cn = result->root; cn; cn = cn->sib) { ++ is_lvchange = 0; ++ DO_OFFLINE(ack_threads); ++ DO_OFFLINE(bio_rotation); ++ DO_OFFLINE(bio_threads); ++ DO_OFFLINE(block_map_cache_size_mb); ++ DO_OFFLINE(block_map_era_length); ++ DO_OFFLINE(block_map_period); // alias for block_map_era_length ++ DO_OFFLINE(cpu_threads); ++ DO_OFFLINE(hash_zone_threads); ++ DO_OFFLINE(logical_threads); ++ DO_OFFLINE(max_discard); ++ DO_OFFLINE(physical_threads); ++ ++ // Support also these - even when we have regular opts for them ++ DO_ONLINE(use_compression); ++ DO_ONLINE(use_deduplication); ++ ++ // Settings bellow cannot be changed with lvchange command ++ is_lvchange = checked_lvchange; ++ ++ DO_OFFLINE(check_point_frequency); ++ DO_OFFLINE(index_memory_size_mb); ++ DO_OFFLINE(minimum_io_size); ++ DO_OFFLINE(slab_size_mb); ++ DO_OFFLINE(use_metadata_hints); ++ DO_OFFLINE(use_sparse_index); ++ ++ option = "write_policy"; ++ if (_compare_vdo_option(cn->key, option)) { ++ if (is_lvchange || !cn->v || (cn->v->type != DM_CFG_STRING)) ++ goto err; ++ if (!set_vdo_write_policy(&vtp->write_policy, cn->v->v.str)) ++ goto_out; ++ u |= VDO_CHANGE_OFFLINE; ++ continue; ++ } ++ ++ log_error("Unknown VDO setting \"%s\".", cn->key); ++ goto out; ++ } ++ } ++ ++ if (arg_is_set(cmd, compression_ARG)) { ++ vtp->use_compression = arg_int_value(cmd, compression_ARG, 0); ++ if (vtp->use_compression != use_compression) ++ u |= VDO_CHANGE_ONLINE; ++ } ++ ++ if (arg_is_set(cmd, deduplication_ARG)) { ++ vtp->use_deduplication = arg_int_value(cmd, deduplication_ARG, 0); ++ if (vtp->use_deduplication != use_deduplication) ++ u |= VDO_CHANGE_ONLINE; ++ } ++ ++ if (updated) { ++ // validation of updated VDO option ++ if (!dm_vdo_validate_target_params(vtp, 0 /* vdo_size */)) { ++err: ++ if (is_lvchange) ++ log_error("Cannot change VDO setting \"vdo_%s\" in existing VDO pool.", ++ option); ++ else ++ log_error("Invalid argument for VDO setting \"vdo_%s\".", ++ option); ++ goto out; ++ } ++ ++ *updated = u; ++ } ++ ++ r = 1; ++out: ++ if (result) ++ dm_config_destroy(result); ++ ++ while (prev) { ++ current = prev->cascade; ++ dm_config_destroy(prev); ++ prev = current; ++ } ++ ++ return r; ++} ++ + static int _get_one_writecache_setting(struct cmd_context *cmd, struct writecache_settings *settings, + char *key, char *val, uint32_t *block_size_sectors) + { +diff --git a/tools/toollib.h b/tools/toollib.h +index f3a60fbc4..2b38e4e4f 100644 +--- a/tools/toollib.h ++++ b/tools/toollib.h +@@ -217,6 +217,12 @@ int get_cache_params(struct cmd_context *cmd, + const char **name, + struct dm_config_tree **settings); + ++#define VDO_CHANGE_ONLINE 1 ++#define VDO_CHANGE_OFFLINE 2 ++int get_vdo_settings(struct cmd_context *cmd, ++ struct dm_vdo_target_params *vtp, ++ int *updated); ++ + int get_writecache_settings(struct cmd_context *cmd, struct writecache_settings *settings, + uint32_t *block_size_sectors); + +-- +2.34.3 + diff --git a/0048-toollib-fix-segfault-when-handling-selection-with-hi.patch b/0048-toollib-fix-segfault-when-handling-selection-with-hi.patch new file mode 100644 index 0000000..6a0b3e0 --- /dev/null +++ b/0048-toollib-fix-segfault-when-handling-selection-with-hi.patch @@ -0,0 +1,45 @@ +From 45a2ccfa3bdf4c5b3f8b9e0cc5330fca345b0d26 Mon Sep 17 00:00:00 2001 +From: Peter Rajnoha +Date: Thu, 5 May 2022 11:02:32 +0200 +Subject: [PATCH 48/54] toollib: fix segfault when handling selection with + historical LVs + +When processing historical LVs inside process_each_lv_in_vg for +selection, we need to use dummy "_historical_lv" for select_match_lv. + +This is because a historical LV is not an actual LV, but only a tiny +representation with subset of original properties that we recorded +(name, uuid...). + +To use the same processing functions we use for full-fledged non-historical +LVs, we need to use the prefilled "_historical_lv" structure which has all +the other missing properties hard-coded. +--- + tools/toollib.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/tools/toollib.c b/tools/toollib.c +index 697baee82..01ba03658 100644 +--- a/tools/toollib.c ++++ b/tools/toollib.c +@@ -3392,13 +3392,14 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg, + process_lv = 1; + } + +- process_lv = process_lv && select_match_lv(cmd, handle, vg, lvl->lv) && _select_matches(handle); ++ _historical_lv.this_glv = glvl->glv; ++ _historical_lv.name = glvl->glv->historical->name; ++ ++ process_lv = process_lv && select_match_lv(cmd, handle, vg, &_historical_lv) && _select_matches(handle); + + if (!process_lv) + continue; + +- _historical_lv.this_glv = glvl->glv; +- _historical_lv.name = glvl->glv->historical->name; + log_very_verbose("Processing historical LV %s in VG %s.", glvl->glv->historical->name, vg->name); + + ret = process_single_lv(cmd, &_historical_lv, handle); +-- +2.34.3 + diff --git a/0049-devices-file-move-clean-up-after-command-is-run.patch b/0049-devices-file-move-clean-up-after-command-is-run.patch new file mode 100644 index 0000000..2fbfdbc --- /dev/null +++ b/0049-devices-file-move-clean-up-after-command-is-run.patch @@ -0,0 +1,39 @@ +From eda98e4b9418568d6793d2c853aaa54db051cc9f Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Fri, 27 May 2022 12:38:43 -0500 +Subject: [PATCH 49/54] devices file: move clean up after command is run + +devices_file_exit wasn't being called between lvm_shell +commands, so the file lock wouldn't be released. +--- + lib/commands/toolcontext.c | 1 - + tools/lvmcmdline.c | 1 + + 2 files changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c +index a0c78ddd6..7db5e11a1 100644 +--- a/lib/commands/toolcontext.c ++++ b/lib/commands/toolcontext.c +@@ -1912,7 +1912,6 @@ int refresh_toolcontext(struct cmd_context *cmd) + _destroy_segtypes(&cmd->segtypes); + _destroy_formats(cmd, &cmd->formats); + +- devices_file_exit(cmd); + if (!dev_cache_exit()) + stack; + _destroy_dev_types(cmd); +diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c +index 1727ba089..eb63fd9b5 100644 +--- a/tools/lvmcmdline.c ++++ b/tools/lvmcmdline.c +@@ -3306,6 +3306,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) + hints_exit(cmd); + lvmcache_destroy(cmd, 1, 1); + label_scan_destroy(cmd); ++ devices_file_exit(cmd); + + if ((config_string_cft = remove_config_tree_by_source(cmd, CONFIG_STRING))) + dm_config_destroy(config_string_cft); +-- +2.34.3 + diff --git a/0050-devices-file-fail-if-devicesfile-filename-doesn-t-ex.patch b/0050-devices-file-fail-if-devicesfile-filename-doesn-t-ex.patch new file mode 100644 index 0000000..0adf7b6 --- /dev/null +++ b/0050-devices-file-fail-if-devicesfile-filename-doesn-t-ex.patch @@ -0,0 +1,53 @@ +From bf0b3962088fb18f4a2aba00f38955e1fc6e31fe Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Fri, 27 May 2022 14:27:03 -0500 +Subject: [PATCH 50/54] devices file: fail if --devicesfile filename doesn't + exist + +A typo of the filename after --devicesfile should result in a +command error rather than the command falling back to using no +devices file at all. Exception is vgcreate|pvcreate which +create a new devices file if the file name doesn't exist. +--- + lib/device/dev-cache.c | 9 +++++++++ + test/shell/devicesfile-basic.sh | 4 ++++ + 2 files changed, 13 insertions(+) + +diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c +index b0759b06c..0eb2568b5 100644 +--- a/lib/device/dev-cache.c ++++ b/lib/device/dev-cache.c +@@ -1882,6 +1882,15 @@ static int _setup_devices(struct cmd_context *cmd, int no_file_match) + + file_exists = devices_file_exists(cmd); + ++ /* ++ * Fail if user specifies a file name that doesn't exist and ++ * the command is not creating a new devices file. ++ */ ++ if (!file_exists && !cmd->create_edit_devices_file && cmd->devicesfile && strlen(cmd->devicesfile)) { ++ log_error("Devices file not found: %s", cmd->devices_file_path); ++ return 0; ++ } ++ + /* + * Removing the devices file is another way of disabling the use of + * a devices file, unless the command creates the devices file. +diff --git a/test/shell/devicesfile-basic.sh b/test/shell/devicesfile-basic.sh +index 7ba9e2c7f..d1cfb6a35 100644 +--- a/test/shell/devicesfile-basic.sh ++++ b/test/shell/devicesfile-basic.sh +@@ -104,6 +104,10 @@ not ls "$DFDIR/system.devices" + vgs --devicesfile test.devices $vg1 + not vgs --devicesfile test.devices $vg2 + ++# misspelled override name fails ++not vgs --devicesfile doesnotexist $vg1 ++not vgs --devicesfile doesnotexist $vg2 ++ + # devicesfile and devices cannot be used together + not vgs --devicesfile test.devices --devices "$dev1","$dev1" $vg1 + +-- +2.34.3 + diff --git a/0026-filter-mpath-handle-other-wwid-types-in-blacklist.patch b/0051-filter-mpath-handle-other-wwid-types-in-blacklist.patch similarity index 85% rename from 0026-filter-mpath-handle-other-wwid-types-in-blacklist.patch rename to 0051-filter-mpath-handle-other-wwid-types-in-blacklist.patch index 5dc8ccc..820ed88 100644 --- a/0026-filter-mpath-handle-other-wwid-types-in-blacklist.patch +++ b/0051-filter-mpath-handle-other-wwid-types-in-blacklist.patch @@ -1,20 +1,18 @@ -From 1f3ce86bf26bc7173dfde516ab1ace71e0c8074b Mon Sep 17 00:00:00 2001 +From 25abb5730f4d8f79df69f0817881ffb9eed195a9 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 6 Jun 2022 11:39:02 -0500 -Subject: [PATCH 2/2] filter-mpath: handle other wwid types in blacklist +Subject: [PATCH 51/54] filter-mpath: handle other wwid types in blacklist Fixes commit 494372b4eed0c8f6040e3357939eb7511ac25745 "filter-mpath: use multipath blacklist" to handle wwids with initial type digits 1 and 2 used for t10 and eui ids. Originally recognized type 3 naa. - -(cherry picked from commit 25abb5730f4d8f79df69f0817881ffb9eed195a9) --- lib/device/dev-mpath.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/device/dev-mpath.c b/lib/device/dev-mpath.c -index 580ab31a5..3d0626fe3 100644 +index 6eed03c5b..7abbfb289 100644 --- a/lib/device/dev-mpath.c +++ b/lib/device/dev-mpath.c @@ -54,7 +54,7 @@ static void _read_blacklist_file(const char *path) diff --git a/0052-vdo-fix-conversion-of-vdo_slab_size_mb.patch b/0052-vdo-fix-conversion-of-vdo_slab_size_mb.patch new file mode 100644 index 0000000..7bb6100 --- /dev/null +++ b/0052-vdo-fix-conversion-of-vdo_slab_size_mb.patch @@ -0,0 +1,56 @@ +From 7cb63b05dad453d015bbe462b799fb031dd6952c Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Tue, 31 May 2022 22:48:38 +0200 +Subject: [PATCH 52/54] vdo: fix conversion of vdo_slab_size_mb + +When converting VDO volume, the parameter vdo_slabSize was +incorrectly copied as vdo_blockMapCacheSize, however this parameter +is then no longer used for any table line creation so the wrong +value was only stored in metadata. + +Also use just single get_kb_size_with_unit_ and remove it's duplicate +functionality with get_mb_size_with_unit_. + +Use $VERB for vdo remove call. +--- + scripts/lvm_import_vdo.sh | 13 ++----------- + 1 file changed, 2 insertions(+), 11 deletions(-) + +diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh +index 61a82e41e..beb55dbdb 100755 +--- a/scripts/lvm_import_vdo.sh ++++ b/scripts/lvm_import_vdo.sh +@@ -125,15 +125,6 @@ get_kb_size_with_unit_() { + esac + } + +-get_mb_size_with_unit_() { +- case "$1" in +- *[mM]) echo $(( ${1%[mM]} )) ;; +- *[gG]) echo $(( ${1%[gG]} * 1024 )) ;; +- *[tT]) echo $(( ${1%[tT]} * 1024 * 1024 )) ;; +- *[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 )) ;; +- esac +-} +- + # Figure out largest possible extent size usable for VG + # $1 physical size + # $2 logical size +@@ -328,12 +319,12 @@ allocation { + vdo_use_deduplication = $(get_enabled_value_ "$vdo_deduplication") + vdo_use_metadata_hints=1 + vdo_minimum_io_size = $vdo_logicalBlockSize +- vdo_block_map_cache_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize") ++ vdo_block_map_cache_size_mb = $(( $(get_kb_size_with_unit_ "$vdo_blockMapCacheSize") / 1024 )) + vdo_block_map_period = $vdo_blockMapPeriod + vdo_check_point_frequency = $vdo_indexCfreq + vdo_use_sparse_index = $(get_enabled_value_ "$vdo_indexSparse") + vdo_index_memory_size_mb = $(awk "BEGIN {print $vdo_indexMemory * 1024}") +- vdo_slab_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize") ++ vdo_slab_size_mb = $(( $(get_kb_size_with_unit_ "$vdo_blockMapCacheSize") / 1024 )) + vdo_ack_threads = $vdo_ackThreads + vdo_bio_threads = $vdo_bioThreads + vdo_bio_rotation = $vdo_bioRotationInterval +-- +2.34.3 + diff --git a/0053-filter-mpath-get-wwids-from-sysfs-vpd_pg83.patch b/0053-filter-mpath-get-wwids-from-sysfs-vpd_pg83.patch new file mode 100644 index 0000000..3c98ac4 --- /dev/null +++ b/0053-filter-mpath-get-wwids-from-sysfs-vpd_pg83.patch @@ -0,0 +1,741 @@ +From e36b180a6983c4fa07d6714a0bf81e6935487359 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 6 Jun 2022 14:04:20 -0500 +Subject: [PATCH 53/54] filter-mpath: get wwids from sysfs vpd_pg83 + +to compare with wwids in /etc/multipath/wwids when +excluding multipath components. The wwid printed +from the sysfs wwid file may not be the wwid used +in multipath wwids. Save the wwids found for each +device on dev->wwids to avoid repeating reading +and parsing the sysfs files. +--- + lib/Makefile.in | 1 + + lib/device/dev-cache.c | 18 ++++ + lib/device/dev-cache.h | 1 + + lib/device/dev-mpath.c | 232 ++++++++++++++++++++++++++++++++++------- + lib/device/device.h | 13 +++ + lib/device/device_id.c | 31 +++++- + lib/device/device_id.h | 2 + + lib/device/parse_vpd.c | 199 +++++++++++++++++++++++++++++++++++ + 8 files changed, 454 insertions(+), 43 deletions(-) + create mode 100644 lib/device/parse_vpd.c + +diff --git a/lib/Makefile.in b/lib/Makefile.in +index 8b3eac60a..3077825d2 100644 +--- a/lib/Makefile.in ++++ b/lib/Makefile.in +@@ -40,6 +40,7 @@ SOURCES =\ + device/dev-luks.c \ + device/dev-dasd.c \ + device/dev-lvm1-pool.c \ ++ device/parse_vpd.c \ + display/display.c \ + error/errseg.c \ + unknown/unknown.c \ +diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c +index 0eb2568b5..65e1cb138 100644 +--- a/lib/device/dev-cache.c ++++ b/lib/device/dev-cache.c +@@ -80,6 +80,7 @@ static void _dev_init(struct device *dev) + + dm_list_init(&dev->aliases); + dm_list_init(&dev->ids); ++ dm_list_init(&dev->wwids); + } + + void dev_destroy_file(struct device *dev) +@@ -383,6 +384,22 @@ out: + return 1; + } + ++int get_sysfs_binary(const char *path, char *buf, size_t buf_size, int *retlen) ++{ ++ int ret; ++ int fd; ++ ++ fd = open(path, O_RDONLY); ++ if (fd < 0) ++ return 0; ++ ret = read(fd, buf, buf_size); ++ close(fd); ++ if (ret <= 0) ++ return 0; ++ *retlen = ret; ++ return 1; ++} ++ + int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value) + { + FILE *fp; +@@ -1336,6 +1353,7 @@ int dev_cache_exit(void) + dm_hash_iterate(n, _cache.names) { + dev = (struct device *) dm_hash_get_data(_cache.names, n); + free_dids(&dev->ids); ++ free_wwids(&dev->wwids); + } + } + +diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h +index 321a56d7b..c49e6265d 100644 +--- a/lib/device/dev-cache.h ++++ b/lib/device/dev-cache.h +@@ -74,6 +74,7 @@ void dev_cache_failed_path(struct device *dev, const char *path); + bool dev_cache_has_md_with_end_superblock(struct dev_types *dt); + + int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value); ++int get_sysfs_binary(const char *path, char *buf, size_t buf_size, int *retlen); + int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor); + + int setup_devices_file(struct cmd_context *cmd); +diff --git a/lib/device/dev-mpath.c b/lib/device/dev-mpath.c +index 7abbfb289..3795c992d 100644 +--- a/lib/device/dev-mpath.c ++++ b/lib/device/dev-mpath.c +@@ -200,11 +200,12 @@ static void _read_wwid_exclusions(void) + log_debug("multipath config ignored %d wwids", rem_count); + } + +-static void _read_wwid_file(const char *config_wwids_file) ++static void _read_wwid_file(const char *config_wwids_file, int *entries) + { + FILE *fp; + char line[MAX_WWID_LINE]; + char *wwid, *p; ++ char typestr[2] = { 0 }; + int count = 0; + + if (config_wwids_file[0] != '/') { +@@ -226,8 +227,17 @@ static void _read_wwid_file(const char *config_wwids_file) + if (line[0] == '/') + wwid++; + +- /* skip the initial '3' */ +- wwid++; ++ ++ /* ++ * the initial character is the id type, ++ * 1 is t10, 2 is eui, 3 is naa, 8 is scsi name. ++ * wwids are stored in the hash table without the type charater. ++ * It seems that sometimes multipath does not include ++ * the type charater (seen with t10 scsi_debug devs). ++ */ ++ typestr[0] = *wwid; ++ if (typestr[0] == '1' || typestr[0] == '2' || typestr[0] == '3') ++ wwid++; + + if ((p = strchr(wwid, '/'))) + *p = '\0'; +@@ -240,6 +250,7 @@ static void _read_wwid_file(const char *config_wwids_file) + stack; + + log_debug("multipath wwids read %d from %s", count, config_wwids_file); ++ *entries = count; + } + + int dev_mpath_init(const char *config_wwids_file) +@@ -247,6 +258,7 @@ int dev_mpath_init(const char *config_wwids_file) + struct dm_pool *mem; + struct dm_hash_table *minor_tab; + struct dm_hash_table *wwid_tab; ++ int entries = 0; + + dm_list_init(&_ignored); + dm_list_init(&_ignored_exceptions); +@@ -283,10 +295,16 @@ int dev_mpath_init(const char *config_wwids_file) + _wwid_hash_tab = wwid_tab; + + if (config_wwids_file) { +- _read_wwid_file(config_wwids_file); ++ _read_wwid_file(config_wwids_file, &entries); + _read_wwid_exclusions(); + } + ++ if (!entries) { ++ /* reading dev wwids is skipped with null wwid_hash_tab */ ++ dm_hash_destroy(_wwid_hash_tab); ++ _wwid_hash_tab = NULL; ++ } ++ + return 1; + } + +@@ -432,10 +450,10 @@ static int _dev_is_mpath_component_udev(struct device *dev) + } + #endif + +-static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev) ++static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev, ++ int primary_result, dev_t primary_dev) + { + struct dev_types *dt = cmd->dev_types; +- 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/" */ +@@ -449,25 +467,15 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device + int dm_dev_major; + int dm_dev_minor; + struct stat info; +- dev_t primary_dev; + int is_mpath_component = 0; + +- /* multipathing is only known to exist for 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)) { ++ switch (primary_result) { + + case 2: /* The dev is partition. */ +- part_name = dev_name(dev); /* name of original dev for log_debug msg */ + + /* 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. */ +@@ -589,47 +597,189 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device + return is_mpath_component; + } + +-static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev) ++static int _read_sys_wwid(struct cmd_context *cmd, struct device *dev, ++ char *idbuf, int idbufsize) + { +- char sysbuf[PATH_MAX] = { 0 }; +- char *wwid; +- long look; ++ char idtmp[DEV_WWID_SIZE]; + +- if (!_wwid_hash_tab) ++ if (!read_sys_block(cmd, dev, "device/wwid", idbuf, idbufsize)) { ++ /* the wwid file is not under device for nvme devs */ ++ if (!read_sys_block(cmd, dev, "wwid", idbuf, idbufsize)) ++ return 0; ++ } ++ if (!idbuf[0]) + return 0; + +- if (!read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf))) ++ /* in t10 id, replace series of spaces with one _ like multipath */ ++ if (!strncmp(idbuf, "t10.", 4) && strchr(idbuf, ' ')) { ++ if (idbufsize < DEV_WWID_SIZE) ++ return 0; ++ memcpy(idtmp, idbuf, DEV_WWID_SIZE); ++ memset(idbuf, 0, idbufsize); ++ format_t10_id((const unsigned char *)idtmp, DEV_WWID_SIZE, (unsigned char *)idbuf, idbufsize); ++ } ++ return 1; ++} ++ ++#define VPD_SIZE 4096 ++ ++static int _read_sys_vpd_wwids(struct cmd_context *cmd, struct device *dev, ++ struct dm_list *ids) ++{ ++ unsigned char vpd_data[VPD_SIZE] = { 0 }; ++ int vpd_datalen = 0; ++ ++ if (!read_sys_block_binary(cmd, dev, "device/vpd_pg83", (char *)vpd_data, VPD_SIZE, &vpd_datalen)) ++ return 0; ++ if (!vpd_datalen) + return 0; + +- if (!sysbuf[0]) ++ /* adds dev_wwid entry to dev->wwids for each id in vpd data */ ++ parse_vpd_ids(vpd_data, vpd_datalen, ids); ++ return 1; ++} ++ ++void free_wwids(struct dm_list *ids) ++{ ++ struct dev_wwid *dw, *safe; ++ ++ dm_list_iterate_items_safe(dw, safe, ids) { ++ dm_list_del(&dw->list); ++ free(dw); ++ } ++} ++ ++static int _wwid_type_num(char *id) ++{ ++ if (!strncmp(id, "naa.", 4)) ++ return 3; ++ else if (!strncmp(id, "eui.", 4)) ++ return 2; ++ else if (!strncmp(id, "t10.", 4)) ++ return 1; ++ else ++ return -1; ++} ++ ++/* ++ * TODO: if each of the different wwid types (naa/eui/t10) were ++ * represented by different DEV_ID_TYPE_FOO values, and used ++ * as device_id types, then we could drop struct dev_wwid and ++ * drop dev->wwids, and just use dev->ids for each of the ++ * different wwids found in vpd_pg83. This would also require ++ * the ability to handle both the original method of replacing ++ * every space in the id string with _ and the new/multipath ++ * format_t10_id replacing series of spaces with one _. ++ */ ++struct dev_wwid *add_wwid(char *id, int id_type, struct dm_list *ids) ++{ ++ struct dev_wwid *dw; ++ int len; ++ ++ if (!id_type) { ++ id_type = _wwid_type_num(id); ++ if (id_type == -1) ++ log_debug("unknown wwid type %s", id); ++ } ++ ++ if (!(dw = zalloc(sizeof(struct dev_wwid)))) ++ return NULL; ++ len = strlen(id); ++ if (len >= DEV_WWID_SIZE) ++ len = DEV_WWID_SIZE - 1; ++ memcpy(dw->id, id, len); ++ dw->type = id_type; ++ dm_list_add(ids, &dw->list); ++ return dw; ++} ++ ++/* ++ * we save ids with format: naa., eui., t10.. ++ * multipath wwids file uses format: 3, 2, 1. ++ * The values are saved in wwid_hash_tab without the type prefix. ++ */ ++ ++static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev, ++ int primary_result, dev_t primary_dev) ++{ ++ char idbuf[DEV_WWID_SIZE] = { 0 }; ++ struct dev_wwid *dw; ++ char *wwid; ++ ++ if (!_wwid_hash_tab) + return 0; + + /* +- * sysfs prints wwid as . +- * multipath wwid uses '3' +- * does "." always correspond to "3"? ++ * Check the primary device, not the partition. + */ +- if (!(wwid = strchr(sysbuf, '.'))) +- return 0; ++ if (primary_result == 2) { ++ if (!(dev = dev_cache_get_by_devt(cmd, primary_dev))) { ++ log_debug("dev_is_mpath_component %s no primary dev", dev_name(dev)); ++ return 0; ++ } ++ } + +- /* skip the type and dot, just as '3' was skipped from wwids entry */ +- wwid++; +- +- look = (long) dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid)); ++ /* ++ * This function may be called multiple times for the same device, in ++ * particular if partitioned for each partition. ++ */ ++ if (!dm_list_empty(&dev->wwids)) ++ goto lookup; + +- if (look) { +- log_debug_devs("dev_is_mpath_component %s multipath wwid %s", dev_name(dev), wwid); +- return 1; ++ /* ++ * Get all the ids for the device from vpd_pg83 and check if any of ++ * those are in /etc/multipath/wwids. These ids should include the ++ * value printed from the sysfs wwid file. ++ */ ++ _read_sys_vpd_wwids(cmd, dev, &dev->wwids); ++ if (!dm_list_empty(&dev->wwids)) ++ goto lookup; ++ ++ /* ++ * This will read the sysfs wwid file, nvme devices in particular have ++ * a wwid file but not a vpd_pg83 file. ++ */ ++ if (_read_sys_wwid(cmd, dev, idbuf, sizeof(idbuf))) ++ add_wwid(idbuf, 0, &dev->wwids); ++ ++ lookup: ++ dm_list_iterate_items(dw, &dev->wwids) { ++ if (dw->type == 1 || dw->type == 2 || dw->type == 3) ++ wwid = &dw->id[4]; ++ else ++ wwid = dw->id; ++ ++ if (dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid))) { ++ log_debug_devs("dev_is_mpath_component %s %s in wwids file", dev_name(dev), dw->id); ++ return 1; ++ } + } ++ + return 0; + } + + int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev) + { +- if (_dev_is_mpath_component_sysfs(cmd, dev) == 1) ++ struct dev_types *dt = cmd->dev_types; ++ int primary_result; ++ dev_t primary_dev; ++ ++ /* ++ * multipath only uses SCSI or NVME devices ++ */ ++ if (!major_is_scsi_device(dt, MAJOR(dev->dev)) && !dev_is_nvme(dt, dev)) ++ return 0; ++ ++ /* ++ * primary_result 2: dev is a partition, primary_dev is the whole device ++ * primary_result 1: dev is a whole device ++ */ ++ primary_result = dev_get_primary_dev(dt, dev, &primary_dev); ++ ++ if (_dev_is_mpath_component_sysfs(cmd, dev, primary_result, primary_dev) == 1) + goto found; + +- if (_dev_in_wwid_file(cmd, dev)) ++ if (_dev_in_wwid_file(cmd, dev, primary_result, primary_dev)) + goto found; + + if (external_device_info_source() == DEV_EXT_UDEV) { +@@ -637,6 +787,12 @@ int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev) + goto found; + } + ++ /* ++ * TODO: save the result of this function in dev->flags and use those ++ * flags on repeated calls to avoid repeating the work multiple times ++ * for the same device when there are partitions on the device. ++ */ ++ + return 0; + found: + return 1; +diff --git a/lib/device/device.h b/lib/device/device.h +index 572994bb9..1c85f37a9 100644 +--- a/lib/device/device.h ++++ b/lib/device/device.h +@@ -59,6 +59,14 @@ struct dev_ext { + void *handle; + }; + ++#define DEV_WWID_SIZE 128 ++ ++struct dev_wwid { ++ struct dm_list list; ++ int type; ++ char id[DEV_WWID_SIZE]; ++}; ++ + #define DEV_ID_TYPE_SYS_WWID 0x0001 + #define DEV_ID_TYPE_SYS_SERIAL 0x0002 + #define DEV_ID_TYPE_MPATH_UUID 0x0003 +@@ -105,6 +113,7 @@ struct dev_use { + */ + struct device { + struct dm_list aliases; /* struct dm_str_list */ ++ struct dm_list wwids; /* struct dev_wwid, used for multipath component detection */ + struct dm_list ids; /* struct dev_id, different entries for different idtypes */ + struct dev_id *id; /* points to the the ids entry being used for this dev */ + dev_t dev; +@@ -206,5 +215,9 @@ void dev_destroy_file(struct device *dev); + + int dev_mpath_init(const char *config_wwids_file); + void dev_mpath_exit(void); ++struct dev_wwid *add_wwid(char *id, int id_type, struct dm_list *ids); ++void free_wwids(struct dm_list *ids); ++int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list *ids); ++int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes); + + #endif +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 20901ab90..4d8fa5c9c 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -182,7 +182,9 @@ void free_dids(struct dm_list *ids) + } + } + +-int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize) ++static int _read_sys_block(struct cmd_context *cmd, struct device *dev, ++ const char *suffix, char *sysbuf, int sysbufsize, ++ int binary, int *retlen) + { + char path[PATH_MAX]; + dev_t devt = dev->dev; +@@ -196,11 +198,17 @@ int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suff + return 0; + } + +- get_sysfs_value(path, sysbuf, sysbufsize, 0); ++ if (binary) { ++ ret = get_sysfs_binary(path, sysbuf, sysbufsize, retlen); ++ if (ret && !*retlen) ++ ret = 0; ++ } else { ++ ret = get_sysfs_value(path, sysbuf, sysbufsize, 0); ++ if (ret && !sysbuf[0]) ++ ret = 0; ++ } + +- if (sysbuf[0]) { +- if (prim) +- log_debug("Using primary device_id for partition %s.", dev_name(dev)); ++ if (ret) { + sysbuf[sysbufsize - 1] = '\0'; + return 1; + } +@@ -220,6 +228,19 @@ int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suff + return 0; + } + ++int read_sys_block(struct cmd_context *cmd, struct device *dev, ++ const char *suffix, char *sysbuf, int sysbufsize) ++{ ++ return _read_sys_block(cmd, dev, suffix, sysbuf, sysbufsize, 0, NULL); ++} ++ ++int read_sys_block_binary(struct cmd_context *cmd, struct device *dev, ++ const char *suffix, char *sysbuf, int sysbufsize, ++ int *retlen) ++{ ++ return _read_sys_block(cmd, dev, suffix, sysbuf, sysbufsize, 1, retlen); ++} ++ + static int _dm_uuid_has_prefix(char *sysbuf, const char *prefix) + { + if (!strncmp(sysbuf, prefix, strlen(prefix))) +diff --git a/lib/device/device_id.h b/lib/device/device_id.h +index 2cd2fd7c6..e049e2333 100644 +--- a/lib/device/device_id.h ++++ b/lib/device/device_id.h +@@ -55,6 +55,8 @@ void devices_file_exit(struct cmd_context *cmd); + void unlink_searched_devnames(struct cmd_context *cmd); + + int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize); ++int read_sys_block_binary(struct cmd_context *cmd, struct device *dev, ++ const char *suffix, char *sysbuf, int sysbufsize, int *retlen); + + int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out); + +diff --git a/lib/device/parse_vpd.c b/lib/device/parse_vpd.c +new file mode 100644 +index 000000000..4bafa7b9e +--- /dev/null ++++ b/lib/device/parse_vpd.c +@@ -0,0 +1,199 @@ ++/* ++ * Copyright (C) 2022 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 "base/memory/zalloc.h" ++#include "lib/misc/lib.h" ++#include "lib/device/device.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Replace series of spaces with a single _. ++ */ ++int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes) ++{ ++ int in_space = 0; ++ int retlen = 0; ++ int j = 0; ++ int i; ++ ++ for (i = 0; i < in_bytes; i++) { ++ if (!in[i]) ++ break; ++ if (j >= (out_bytes - 2)) ++ break; ++ /* skip leading spaces */ ++ if (!retlen && (in[i] == ' ')) ++ continue; ++ /* replace one or more spaces with _ */ ++ if (in[i] == ' ') { ++ in_space = 1; ++ continue; ++ } ++ /* spaces are finished so insert _ */ ++ if (in_space) { ++ out[j++] = '_'; ++ in_space = 0; ++ retlen++; ++ } ++ out[j++] = in[i]; ++ retlen++; ++ } ++ return retlen; ++} ++ ++static int _to_hex(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes) ++{ ++ int off = 0; ++ int num; ++ int i; ++ ++ for (i = 0; i < in_bytes; i++) { ++ num = sprintf((char *)out + off, "%02x", in[i]); ++ if (num < 0) ++ break; ++ off += num; ++ if (off + 2 >= out_bytes) ++ break; ++ } ++ return off; ++} ++ ++#define ID_BUFSIZE 1024 ++ ++/* ++ * based on linux kernel function ++ */ ++int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list *ids) ++{ ++ char id[ID_BUFSIZE]; ++ unsigned char tmp_str[ID_BUFSIZE]; ++ const unsigned char *d, *cur_id_str; ++ size_t id_len = ID_BUFSIZE; ++ int id_size = -1; ++ uint8_t cur_id_size = 0; ++ ++ memset(id, 0, ID_BUFSIZE); ++ for (d = vpd_data + 4; ++ d < vpd_data + vpd_datalen; ++ d += d[3] + 4) { ++ memset(tmp_str, 0, sizeof(tmp_str)); ++ ++ switch (d[1] & 0xf) { ++ case 0x1: ++ /* T10 Vendor ID */ ++ cur_id_size = d[3]; ++ if (cur_id_size + 4 > id_len) ++ cur_id_size = id_len - 4; ++ cur_id_str = d + 4; ++ format_t10_id(cur_id_str, cur_id_size, tmp_str, sizeof(tmp_str)); ++ id_size = snprintf(id, ID_BUFSIZE, "t10.%s", tmp_str); ++ if (id_size < 0) ++ break; ++ if (id_size >= ID_BUFSIZE) ++ id_size = ID_BUFSIZE - 1; ++ add_wwid(id, 1, ids); ++ break; ++ case 0x2: ++ /* EUI-64 */ ++ cur_id_size = d[3]; ++ cur_id_str = d + 4; ++ switch (cur_id_size) { ++ case 8: ++ _to_hex(cur_id_str, 8, tmp_str, sizeof(tmp_str)); ++ id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str); ++ break; ++ case 12: ++ _to_hex(cur_id_str, 12, tmp_str, sizeof(tmp_str)); ++ id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str); ++ break; ++ case 16: ++ _to_hex(cur_id_str, 16, tmp_str, sizeof(tmp_str)); ++ id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str); ++ break; ++ default: ++ break; ++ } ++ if (id_size < 0) ++ break; ++ if (id_size >= ID_BUFSIZE) ++ id_size = ID_BUFSIZE - 1; ++ add_wwid(id, 2, ids); ++ break; ++ case 0x3: ++ /* NAA */ ++ cur_id_size = d[3]; ++ cur_id_str = d + 4; ++ switch (cur_id_size) { ++ case 8: ++ _to_hex(cur_id_str, 8, tmp_str, sizeof(tmp_str)); ++ id_size = snprintf(id, ID_BUFSIZE, "naa.%s", tmp_str); ++ break; ++ case 16: ++ _to_hex(cur_id_str, 16, tmp_str, sizeof(tmp_str)); ++ id_size = snprintf(id, ID_BUFSIZE, "naa.%s", tmp_str); ++ break; ++ default: ++ break; ++ } ++ if (id_size < 0) ++ break; ++ if (id_size >= ID_BUFSIZE) ++ id_size = ID_BUFSIZE - 1; ++ add_wwid(id, 3, ids); ++ break; ++ case 0x8: ++ /* SCSI name string */ ++ cur_id_size = d[3]; ++ cur_id_str = d + 4; ++ if (cur_id_size >= id_len) ++ cur_id_size = id_len - 1; ++ memcpy(id, cur_id_str, cur_id_size); ++ id_size = cur_id_size; ++ ++ /* ++ * Not in the kernel version, copying multipath code, ++ * which checks if this string begins with naa or eui ++ * and if so does tolower() on the chars. ++ */ ++ if (!strncmp(id, "naa.", 4) || !strncmp(id, "eui.", 4)) { ++ int i; ++ for (i = 0; i < id_size; i++) ++ id[i] = tolower(id[i]); ++ } ++ add_wwid(id, 8, ids); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return id_size; ++} +-- +2.34.3 + diff --git a/0054-build-Fix-make-rpm-with-VERSION_DM-without-dash.patch b/0054-build-Fix-make-rpm-with-VERSION_DM-without-dash.patch new file mode 100644 index 0000000..c1ce567 --- /dev/null +++ b/0054-build-Fix-make-rpm-with-VERSION_DM-without-dash.patch @@ -0,0 +1,29 @@ +From e60d7ce8e748cb6d51552879c162d01aafa17160 Mon Sep 17 00:00:00 2001 +From: Marian Csontos +Date: Wed, 15 Jun 2022 11:53:51 +0200 +Subject: [PATCH 54/54] build: Fix make rpm with VERSION_DM without dash + +When building RPM from a branch based on a release tag the expected -git +suffix is missing breaking the script producing error like following one: + + error: line 215: Unterminated rich dependency: (2021-53.ge36b180a6.el9: Requires: device-mapper-devel >= 1.02.181 (2021-53.ge36b180a6.el9 +--- + Makefile.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.in b/Makefile.in +index 3b7e0ecaa..f7a46269a 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -110,7 +110,7 @@ rpm: dist + $(LN_S) -f $(abs_top_srcdir)/spec/build.inc $(rpmbuilddir)/SOURCES + $(LN_S) -f $(abs_top_srcdir)/spec/macros.inc $(rpmbuilddir)/SOURCES + $(LN_S) -f $(abs_top_srcdir)/spec/packages.inc $(rpmbuilddir)/SOURCES +- DM_VER=$$(cut -d- -f1 $(top_srcdir)/VERSION_DM);\ ++ DM_VER=$$(cut -d' ' -f1 $(top_srcdir)/VERSION_DM | cut -d- -f1);\ + GIT_VER=$$(cd $(top_srcdir); git describe | cut -d- --output-delimiter=. -f2,3 || echo 0);\ + $(SED) -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \ + -e "s,^\(Version:[^0-9%]*\)[0-9.]*$$,\1 $(LVM_VER)," \ +-- +2.34.3 + diff --git a/0055-make-generate.patch b/0055-make-generate.patch new file mode 100644 index 0000000..03629e4 --- /dev/null +++ b/0055-make-generate.patch @@ -0,0 +1,921 @@ +From 13b8c209f39ab018f34b3ccd369590a89fe71a57 Mon Sep 17 00:00:00 2001 +From: Marian Csontos +Date: Wed, 15 Jun 2022 19:58:18 +0200 +Subject: [PATCH] make: generate + +--- + man/lvchange.8_pregen | 20 ++++++++++++++++++-- + man/lvconvert.8_pregen | 22 ++++++++++++++++++++-- + man/lvcreate.8_pregen | 24 ++++++++++++++++++++++-- + man/lvdisplay.8_pregen | 5 +++-- + man/lvextend.8_pregen | 5 +++-- + man/lvm-fullreport.8_pregen | 5 +++-- + man/lvm-lvpoll.8_pregen | 5 +++-- + man/lvmconfig.8_pregen | 5 +++-- + man/lvmdevices.8_pregen | 8 +++++--- + man/lvmdiskscan.8_pregen | 5 +++-- + man/lvreduce.8_pregen | 5 +++-- + man/lvremove.8_pregen | 5 +++-- + man/lvrename.8_pregen | 5 +++-- + man/lvresize.8_pregen | 5 +++-- + man/lvs.8_pregen | 5 +++-- + man/lvscan.8_pregen | 5 +++-- + man/pvchange.8_pregen | 5 +++-- + man/pvck.8_pregen | 5 +++-- + man/pvcreate.8_pregen | 5 +++-- + man/pvdisplay.8_pregen | 5 +++-- + man/pvmove.8_pregen | 5 +++-- + man/pvremove.8_pregen | 5 +++-- + man/pvresize.8_pregen | 5 +++-- + man/pvs.8_pregen | 5 +++-- + man/pvscan.8_pregen | 5 +++-- + man/vgcfgbackup.8_pregen | 5 +++-- + man/vgcfgrestore.8_pregen | 5 +++-- + man/vgchange.8_pregen | 5 +++-- + man/vgck.8_pregen | 5 +++-- + man/vgconvert.8_pregen | 5 +++-- + man/vgcreate.8_pregen | 5 +++-- + man/vgdisplay.8_pregen | 5 +++-- + man/vgexport.8_pregen | 5 +++-- + man/vgextend.8_pregen | 5 +++-- + man/vgimport.8_pregen | 5 +++-- + man/vgimportclone.8_pregen | 5 +++-- + man/vgimportdevices.8_pregen | 5 +++-- + man/vgmerge.8_pregen | 5 +++-- + man/vgmknodes.8_pregen | 5 +++-- + man/vgreduce.8_pregen | 5 +++-- + man/vgremove.8_pregen | 5 +++-- + man/vgrename.8_pregen | 5 +++-- + man/vgs.8_pregen | 5 +++-- + man/vgscan.8_pregen | 5 +++-- + man/vgsplit.8_pregen | 5 +++-- + 45 files changed, 188 insertions(+), 91 deletions(-) + +diff --git a/man/lvchange.8_pregen b/man/lvchange.8_pregen +index b559c89c9..27bee0f14 100644 +--- a/man/lvchange.8_pregen ++++ b/man/lvchange.8_pregen +@@ -126,6 +126,8 @@ lvchange \(em Change the attributes of logical volume(s) + \fB--sysinit\fP + .br + \fB-t\fP|\fB--test\fP ++.br ++ \fB--vdosettings\fP \fIString\fP + .br + \fB-v\fP|\fB--verbose\fP + .br +@@ -202,6 +204,8 @@ required, after which the others are optional. + \fB--\fP[\fBraid\fP]\fBminrecoveryrate\fP \fISize\fP[k|UNIT] + .br + \fB--\fP[\fBraid\fP]\fBmaxrecoveryrate\fP \fISize\fP[k|UNIT] ++.br ++ \fB--vdosettings\fP \fIString\fP + .br + \fB--\fP[\fBraid\fP]\fBwritebehind\fP \fINumber\fP + .br +@@ -609,8 +613,9 @@ See \fBlvm.conf\fP(5) for more information about profiles. + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +@@ -927,6 +932,17 @@ error messages in multi-stage operations if a tool relies on reading + back metadata it believes has changed but hasn't. + . + .HP ++\fB--vdosettings\fP \fIString\fP ++.br ++Specifies tunable VDO options for VDO LVs. ++Use the form 'option=value' or 'option1=value option2=value', or ++repeat --vdosettings for each option being set. ++These settings override the default VDO behaviors. ++To remove vdosettings and revert to the default ++VDO behaviors, use --vdosettings 'default'. ++See \fBlvmvdo\fP(7) for more information. ++. ++.HP + \fB-v\fP|\fB--verbose\fP ... + .br + Set verbose level. Repeat from 1 to 4 times to increase the detail +diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen +index 679519303..fa52da55c 100644 +--- a/man/lvconvert.8_pregen ++++ b/man/lvconvert.8_pregen +@@ -155,6 +155,8 @@ lvconvert \(em Change logical volume layout + \fB--usepolicies\fP + .br + \fB--vdopool\fP \fILV\fP ++.br ++ \fB--vdosettings\fP \fIString\fP + .br + \fB-v\fP|\fB--verbose\fP + .br +@@ -742,6 +744,8 @@ Convert LV to type vdopool. + .br + [ \fB--deduplication\fP \fBy\fP|\fBn\fP ] + .br ++[ \fB--vdosettings\fP \fIString\fP ] ++.br + [ COMMON_OPTIONS ] + .ad b + .RE +@@ -1131,8 +1135,9 @@ See \fBlvmvdo\fP(7) for more information about VDO usage. + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +@@ -1535,6 +1540,17 @@ The name of a VDO pool LV. + See \fBlvmvdo\fP(7) for more information about VDO usage. + . + .HP ++\fB--vdosettings\fP \fIString\fP ++.br ++Specifies tunable VDO options for VDO LVs. ++Use the form 'option=value' or 'option1=value option2=value', or ++repeat --vdosettings for each option being set. ++These settings override the default VDO behaviors. ++To remove vdosettings and revert to the default ++VDO behaviors, use --vdosettings 'default'. ++See \fBlvmvdo\fP(7) for more information. ++. ++.HP + \fB-v\fP|\fB--verbose\fP ... + .br + Set verbose level. Repeat from 1 to 4 times to increase the detail +@@ -1808,6 +1824,8 @@ Convert LV to type vdopool. + .br + [ \fB--deduplication\fP \fBy\fP|\fBn\fP ] + .br ++[ \fB--vdosettings\fP \fIString\fP ] ++.br + [ COMMON_OPTIONS ] + .ad b + .RE +diff --git a/man/lvcreate.8_pregen b/man/lvcreate.8_pregen +index 2cccbbe56..0ffe92a94 100644 +--- a/man/lvcreate.8_pregen ++++ b/man/lvcreate.8_pregen +@@ -157,6 +157,8 @@ lvcreate \(em Create a logical volume + \fB--vdo\fP + .br + \fB--vdopool\fP \fILV\fP ++.br ++ \fB--vdosettings\fP \fIString\fP + .br + \fB-v\fP|\fB--verbose\fP + .br +@@ -537,6 +539,8 @@ Create a LV that returns VDO when used. + .br + [ \fB--deduplication\fP \fBy\fP|\fBn\fP ] + .br ++[ \fB--vdosettings\fP \fIString\fP ] ++.br + [ COMMON_OPTIONS ] + .ad b + .RE +@@ -1003,8 +1007,9 @@ See \fBlvmvdo\fP(7) for more information about VDO usage. + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +@@ -1438,6 +1443,17 @@ The name of a VDO pool LV. + See \fBlvmvdo\fP(7) for more information about VDO usage. + . + .HP ++\fB--vdosettings\fP \fIString\fP ++.br ++Specifies tunable VDO options for VDO LVs. ++Use the form 'option=value' or 'option1=value option2=value', or ++repeat --vdosettings for each option being set. ++These settings override the default VDO behaviors. ++To remove vdosettings and revert to the default ++VDO behaviors, use --vdosettings 'default'. ++See \fBlvmvdo\fP(7) for more information. ++. ++.HP + \fB-v\fP|\fB--verbose\fP ... + .br + Set verbose level. Repeat from 1 to 4 times to increase the detail +@@ -1966,6 +1982,8 @@ Create a VDO LV with VDO pool. + .br + [ \fB--deduplication\fP \fBy\fP|\fBn\fP ] + .br ++[ \fB--vdosettings\fP \fIString\fP ] ++.br + [ COMMON_OPTIONS ] + .ad b + .RE +@@ -1996,6 +2014,8 @@ Create a VDO LV with VDO pool. + .br + [ \fB--deduplication\fP \fBy\fP|\fBn\fP ] + .br ++[ \fB--vdosettings\fP \fIString\fP ] ++.br + [ COMMON_OPTIONS ] + .ad b + .RE +diff --git a/man/lvdisplay.8_pregen b/man/lvdisplay.8_pregen +index 04aab4c09..387a7d30d 100644 +--- a/man/lvdisplay.8_pregen ++++ b/man/lvdisplay.8_pregen +@@ -186,8 +186,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvextend.8_pregen b/man/lvextend.8_pregen +index be6992e94..8a3e1ea4e 100644 +--- a/man/lvextend.8_pregen ++++ b/man/lvextend.8_pregen +@@ -328,8 +328,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvm-fullreport.8_pregen b/man/lvm-fullreport.8_pregen +index 02b38ef40..edae0efe3 100644 +--- a/man/lvm-fullreport.8_pregen ++++ b/man/lvm-fullreport.8_pregen +@@ -169,8 +169,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvm-lvpoll.8_pregen b/man/lvm-lvpoll.8_pregen +index 7f45f6eb3..fa8027f8e 100644 +--- a/man/lvm-lvpoll.8_pregen ++++ b/man/lvm-lvpoll.8_pregen +@@ -115,8 +115,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvmconfig.8_pregen b/man/lvmconfig.8_pregen +index 51946e1ec..e6762f989 100644 +--- a/man/lvmconfig.8_pregen ++++ b/man/lvmconfig.8_pregen +@@ -156,8 +156,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvmdevices.8_pregen b/man/lvmdevices.8_pregen +index d64c3a31a..a2397e50f 100644 +--- a/man/lvmdevices.8_pregen ++++ b/man/lvmdevices.8_pregen +@@ -322,7 +322,8 @@ Find a device with the PVID and add the device to the devices file. + .HP + \fB--check\fP + .br +-Check the content of the devices file. ++Checks the content of the devices file. ++Reports incorrect device names or PVIDs for entries. + . + .HP + \fB--commandprofile\fP \fIString\fP +@@ -364,8 +365,9 @@ then it will override the default type that lvm would use. + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvmdiskscan.8_pregen b/man/lvmdiskscan.8_pregen +index 7fd3d941d..ac0931c88 100644 +--- a/man/lvmdiskscan.8_pregen ++++ b/man/lvmdiskscan.8_pregen +@@ -102,8 +102,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvreduce.8_pregen b/man/lvreduce.8_pregen +index ea960eb53..cd2e38e5b 100644 +--- a/man/lvreduce.8_pregen ++++ b/man/lvreduce.8_pregen +@@ -130,8 +130,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvremove.8_pregen b/man/lvremove.8_pregen +index 2bd7997a3..8a4afbdff 100644 +--- a/man/lvremove.8_pregen ++++ b/man/lvremove.8_pregen +@@ -136,8 +136,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvrename.8_pregen b/man/lvrename.8_pregen +index d41a4c241..27ce2caeb 100644 +--- a/man/lvrename.8_pregen ++++ b/man/lvrename.8_pregen +@@ -120,8 +120,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvresize.8_pregen b/man/lvresize.8_pregen +index f3ea2536c..10e7dda7c 100644 +--- a/man/lvresize.8_pregen ++++ b/man/lvresize.8_pregen +@@ -286,8 +286,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvs.8_pregen b/man/lvs.8_pregen +index 2b2c5f193..94a74f9dd 100644 +--- a/man/lvs.8_pregen ++++ b/man/lvs.8_pregen +@@ -172,8 +172,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/lvscan.8_pregen b/man/lvscan.8_pregen +index f459ab35b..8d79f22dd 100644 +--- a/man/lvscan.8_pregen ++++ b/man/lvscan.8_pregen +@@ -119,8 +119,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/pvchange.8_pregen b/man/pvchange.8_pregen +index 4add9ca69..010845274 100644 +--- a/man/pvchange.8_pregen ++++ b/man/pvchange.8_pregen +@@ -179,8 +179,9 @@ multiple tags at once. See \fBlvm\fP(8) for information about tags. + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/pvck.8_pregen b/man/pvck.8_pregen +index 88200f21e..7d6652342 100644 +--- a/man/pvck.8_pregen ++++ b/man/pvck.8_pregen +@@ -351,8 +351,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/pvcreate.8_pregen b/man/pvcreate.8_pregen +index a74a5ec2a..6ffd596fe 100644 +--- a/man/pvcreate.8_pregen ++++ b/man/pvcreate.8_pregen +@@ -229,8 +229,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/pvdisplay.8_pregen b/man/pvdisplay.8_pregen +index 2f26a8727..59628bedd 100644 +--- a/man/pvdisplay.8_pregen ++++ b/man/pvdisplay.8_pregen +@@ -183,8 +183,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/pvmove.8_pregen b/man/pvmove.8_pregen +index 0f70497a2..f633b97d2 100644 +--- a/man/pvmove.8_pregen ++++ b/man/pvmove.8_pregen +@@ -206,8 +206,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/pvremove.8_pregen b/man/pvremove.8_pregen +index 3d4a86c09..51c589fd7 100644 +--- a/man/pvremove.8_pregen ++++ b/man/pvremove.8_pregen +@@ -103,8 +103,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/pvresize.8_pregen b/man/pvresize.8_pregen +index 87d87c8ce..9ce57e325 100644 +--- a/man/pvresize.8_pregen ++++ b/man/pvresize.8_pregen +@@ -98,8 +98,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/pvs.8_pregen b/man/pvs.8_pregen +index 32c28e4d1..955b3f887 100644 +--- a/man/pvs.8_pregen ++++ b/man/pvs.8_pregen +@@ -169,8 +169,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/pvscan.8_pregen b/man/pvscan.8_pregen +index 1c96d5aab..1e1cc11ab 100644 +--- a/man/pvscan.8_pregen ++++ b/man/pvscan.8_pregen +@@ -369,8 +369,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgcfgbackup.8_pregen b/man/vgcfgbackup.8_pregen +index 5e658093a..cf984b04b 100644 +--- a/man/vgcfgbackup.8_pregen ++++ b/man/vgcfgbackup.8_pregen +@@ -123,8 +123,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgcfgrestore.8_pregen b/man/vgcfgrestore.8_pregen +index 695e05582..6165cd36e 100644 +--- a/man/vgcfgrestore.8_pregen ++++ b/man/vgcfgrestore.8_pregen +@@ -208,8 +208,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgchange.8_pregen b/man/vgchange.8_pregen +index 05c67aead..7c7030c0d 100644 +--- a/man/vgchange.8_pregen ++++ b/man/vgchange.8_pregen +@@ -556,8 +556,9 @@ See \fBlvm.conf\fP(5) for more information about profiles. + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgck.8_pregen b/man/vgck.8_pregen +index a8fa33f4b..cfb828ff9 100644 +--- a/man/vgck.8_pregen ++++ b/man/vgck.8_pregen +@@ -114,8 +114,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgconvert.8_pregen b/man/vgconvert.8_pregen +index 4d54c2b27..b99de39b8 100644 +--- a/man/vgconvert.8_pregen ++++ b/man/vgconvert.8_pregen +@@ -124,8 +124,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgcreate.8_pregen b/man/vgcreate.8_pregen +index 9bb8d3868..d5316aa1c 100644 +--- a/man/vgcreate.8_pregen ++++ b/man/vgcreate.8_pregen +@@ -206,8 +206,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgdisplay.8_pregen b/man/vgdisplay.8_pregen +index 0a12b3c39..b6cd294d5 100644 +--- a/man/vgdisplay.8_pregen ++++ b/man/vgdisplay.8_pregen +@@ -180,8 +180,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgexport.8_pregen b/man/vgexport.8_pregen +index a87058946..6af64b82a 100644 +--- a/man/vgexport.8_pregen ++++ b/man/vgexport.8_pregen +@@ -139,8 +139,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgextend.8_pregen b/man/vgextend.8_pregen +index 2b2650527..e55e0a110 100644 +--- a/man/vgextend.8_pregen ++++ b/man/vgextend.8_pregen +@@ -147,8 +147,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgimport.8_pregen b/man/vgimport.8_pregen +index 5cd8fab84..9f8614205 100644 +--- a/man/vgimport.8_pregen ++++ b/man/vgimport.8_pregen +@@ -128,8 +128,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgimportclone.8_pregen b/man/vgimportclone.8_pregen +index bf0af5841..80da5454b 100644 +--- a/man/vgimportclone.8_pregen ++++ b/man/vgimportclone.8_pregen +@@ -113,8 +113,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgimportdevices.8_pregen b/man/vgimportdevices.8_pregen +index 5897e29ad..44e5fc663 100644 +--- a/man/vgimportdevices.8_pregen ++++ b/man/vgimportdevices.8_pregen +@@ -132,8 +132,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgmerge.8_pregen b/man/vgmerge.8_pregen +index a36e0c7bd..dfe8e2f0f 100644 +--- a/man/vgmerge.8_pregen ++++ b/man/vgmerge.8_pregen +@@ -107,8 +107,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgmknodes.8_pregen b/man/vgmknodes.8_pregen +index 0a03e1582..d7cd722a4 100644 +--- a/man/vgmknodes.8_pregen ++++ b/man/vgmknodes.8_pregen +@@ -108,8 +108,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgreduce.8_pregen b/man/vgreduce.8_pregen +index f3178a618..63b0a20f3 100644 +--- a/man/vgreduce.8_pregen ++++ b/man/vgreduce.8_pregen +@@ -199,8 +199,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgremove.8_pregen b/man/vgremove.8_pregen +index 779c0f13e..661ada673 100644 +--- a/man/vgremove.8_pregen ++++ b/man/vgremove.8_pregen +@@ -109,8 +109,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgrename.8_pregen b/man/vgrename.8_pregen +index d3e776ca4..2b849d180 100644 +--- a/man/vgrename.8_pregen ++++ b/man/vgrename.8_pregen +@@ -133,8 +133,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgs.8_pregen b/man/vgs.8_pregen +index ee5083a93..2ca98b0b0 100644 +--- a/man/vgs.8_pregen ++++ b/man/vgs.8_pregen +@@ -166,8 +166,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgscan.8_pregen b/man/vgscan.8_pregen +index 824e7f673..a8da70d99 100644 +--- a/man/vgscan.8_pregen ++++ b/man/vgscan.8_pregen +@@ -101,8 +101,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +diff --git a/man/vgsplit.8_pregen b/man/vgsplit.8_pregen +index 065c8b52a..99938a4e3 100644 +--- a/man/vgsplit.8_pregen ++++ b/man/vgsplit.8_pregen +@@ -175,8 +175,9 @@ messages sent to the log file and/or syslog (if configured). + .HP + \fB--devices\fP \fIPV\fP + .br +-Devices that the command can use. This option can be repeated +-or accepts a comma separated list of devices. This overrides ++Restricts the devices that are visible and accessible to the command. ++Devices not listed will appear to be missing. This option can be ++repeated, or accepts a comma separated list of devices. This overrides + the devices file. + . + .HP +-- +2.34.3 + diff --git a/0056-exit-with-error-when-devicesfile-name-doesn-t-exist.patch b/0056-exit-with-error-when-devicesfile-name-doesn-t-exist.patch new file mode 100644 index 0000000..710790e --- /dev/null +++ b/0056-exit-with-error-when-devicesfile-name-doesn-t-exist.patch @@ -0,0 +1,246 @@ +From 73b9a2805ca2f2c70f6f631b405f8fea3f72f23b Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 5 Jul 2022 17:08:00 -0500 +Subject: [PATCH] exit with error when --devicesfile name doesn't exist + +--- + lib/cache/lvmcache.c | 3 ++- + lib/label/label.c | 4 ++-- + test/shell/devicesfile-basic.sh | 1 + + tools/pvcreate.c | 3 ++- + tools/pvremove.c | 3 ++- + tools/pvscan.c | 3 ++- + tools/toollib.c | 27 +++++++++++++++++++++------ + tools/vgcfgrestore.c | 5 ++++- + tools/vgcreate.c | 5 ++++- + tools/vgextend.c | 3 ++- + tools/vgmerge.c | 3 ++- + tools/vgsplit.c | 3 ++- + 12 files changed, 46 insertions(+), 17 deletions(-) + +diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c +index 0e62cd267..61a2fee6d 100644 +--- a/lib/cache/lvmcache.c ++++ b/lib/cache/lvmcache.c +@@ -1600,7 +1600,8 @@ int lvmcache_label_scan(struct cmd_context *cmd) + * with infos/vginfos based on reading headers from + * each device, and a vg summary from each mda. + */ +- label_scan(cmd); ++ if (!label_scan(cmd)) ++ return_0; + + /* + * When devnames are used as device ids (which is dispreferred), +diff --git a/lib/label/label.c b/lib/label/label.c +index 06958b502..00ede2b76 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -800,7 +800,7 @@ static int _setup_bcache(void) + } + + if (!(scan_bcache = bcache_create(BCACHE_BLOCK_SIZE_IN_SECTORS, cache_blocks, ioe))) { +- log_error("Failed to create bcache with %d cache blocks.", cache_blocks); ++ log_error("Failed to set up io layer with %d blocks.", cache_blocks); + return 0; + } + +@@ -1015,7 +1015,7 @@ int label_scan(struct cmd_context *cmd) + * data to invalidate.) + */ + if (!(iter = dev_iter_create(NULL, 0))) { +- log_error("Scanning failed to get devices."); ++ log_error("Failed to get device list."); + return 0; + } + while ((dev = dev_iter_get(cmd, iter))) { +diff --git a/test/shell/devicesfile-basic.sh b/test/shell/devicesfile-basic.sh +index d1cfb6a35..2d197a73a 100644 +--- a/test/shell/devicesfile-basic.sh ++++ b/test/shell/devicesfile-basic.sh +@@ -107,6 +107,7 @@ not vgs --devicesfile test.devices $vg2 + # misspelled override name fails + not vgs --devicesfile doesnotexist $vg1 + not vgs --devicesfile doesnotexist $vg2 ++not vgs --devicesfile doesnotexist + + # devicesfile and devices cannot be used together + not vgs --devicesfile test.devices --devices "$dev1","$dev1" $vg1 +diff --git a/tools/pvcreate.c b/tools/pvcreate.c +index 71eb060a3..a1ef0e9e1 100644 +--- a/tools/pvcreate.c ++++ b/tools/pvcreate.c +@@ -144,7 +144,8 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv) + + cmd->create_edit_devices_file = 1; + +- lvmcache_label_scan(cmd); ++ if (!lvmcache_label_scan(cmd)) ++ return_ECMD_FAILED; + + if (!(handle = init_processing_handle(cmd, NULL))) { + log_error("Failed to initialize processing handle."); +diff --git a/tools/pvremove.c b/tools/pvremove.c +index 2dfdbd016..5c39ee0c7 100644 +--- a/tools/pvremove.c ++++ b/tools/pvremove.c +@@ -45,7 +45,8 @@ int pvremove(struct cmd_context *cmd, int argc, char **argv) + + clear_hint_file(cmd); + +- lvmcache_label_scan(cmd); ++ if (!lvmcache_label_scan(cmd)) ++ return_ECMD_FAILED; + + /* When forcibly clearing a PV we don't care about a VG lock. */ + if (pp.force == DONT_PROMPT_OVERRIDE) +diff --git a/tools/pvscan.c b/tools/pvscan.c +index 50d46051a..bce1fbb40 100644 +--- a/tools/pvscan.c ++++ b/tools/pvscan.c +@@ -1626,7 +1626,8 @@ static int _pvscan_cache_all(struct cmd_context *cmd, int argc, char **argv, + * which we want 'pvscan --cache' to do, and that uses + * info from lvmcache, e.g. duplicate pv info. + */ +- lvmcache_label_scan(cmd); ++ if (!lvmcache_label_scan(cmd)) ++ return_0; + + cmd->pvscan_recreate_hints = 0; + cmd->use_hints = 0; +diff --git a/tools/toollib.c b/tools/toollib.c +index 01ba03658..210b3dca5 100644 +--- a/tools/toollib.c ++++ b/tools/toollib.c +@@ -1601,7 +1601,10 @@ int process_each_label(struct cmd_context *cmd, int argc, char **argv, + + log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_LABEL); + +- lvmcache_label_scan(cmd); ++ if (!lvmcache_label_scan(cmd)) { ++ ret_max = ECMD_FAILED; ++ goto_out; ++ } + + if (argc) { + for (; opt < argc; opt++) { +@@ -2381,8 +2384,13 @@ int process_each_vg(struct cmd_context *cmd, + * Scan all devices to populate lvmcache with initial + * list of PVs and VGs. + */ +- if (!(read_flags & PROCESS_SKIP_SCAN)) +- lvmcache_label_scan(cmd); ++ if (!(read_flags & PROCESS_SKIP_SCAN)) { ++ if (!lvmcache_label_scan(cmd)) { ++ ret_max = ECMD_FAILED; ++ goto_out; ++ } ++ } ++ + + /* + * A list of all VGs on the system is needed when: +@@ -3932,7 +3940,10 @@ int process_each_lv(struct cmd_context *cmd, + * Scan all devices to populate lvmcache with initial + * list of PVs and VGs. + */ +- lvmcache_label_scan(cmd); ++ if (!lvmcache_label_scan(cmd)) { ++ ret_max = ECMD_FAILED; ++ goto_out; ++ } + + /* + * A list of all VGs on the system is needed when: +@@ -4568,8 +4579,12 @@ int process_each_pv(struct cmd_context *cmd, + goto_out; + } + +- if (!(read_flags & PROCESS_SKIP_SCAN)) +- lvmcache_label_scan(cmd); ++ if (!(read_flags & PROCESS_SKIP_SCAN)) { ++ if (!lvmcache_label_scan(cmd)) { ++ ret_max = ECMD_FAILED; ++ goto_out; ++ } ++ } + + if (!lvmcache_get_vgnameids(cmd, &all_vgnameids, only_this_vgname, 1)) { + ret_max = ret; +diff --git a/tools/vgcfgrestore.c b/tools/vgcfgrestore.c +index e49313d14..9fcba89d4 100644 +--- a/tools/vgcfgrestore.c ++++ b/tools/vgcfgrestore.c +@@ -132,7 +132,10 @@ int vgcfgrestore(struct cmd_context *cmd, int argc, char **argv) + + clear_hint_file(cmd); + +- lvmcache_label_scan(cmd); ++ if (!lvmcache_label_scan(cmd)) { ++ unlock_vg(cmd, NULL, vg_name); ++ return_ECMD_FAILED; ++ } + + cmd->handles_unknown_segments = 1; + +diff --git a/tools/vgcreate.c b/tools/vgcreate.c +index dde3f1eac..14608777f 100644 +--- a/tools/vgcreate.c ++++ b/tools/vgcreate.c +@@ -84,7 +84,10 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv) + + cmd->create_edit_devices_file = 1; + +- lvmcache_label_scan(cmd); ++ if (!lvmcache_label_scan(cmd)) { ++ unlock_vg(cmd, NULL, vp_new.vg_name); ++ return_ECMD_FAILED; ++ } + + if (lvmcache_vginfo_from_vgname(vp_new.vg_name, NULL)) { + unlock_vg(cmd, NULL, vp_new.vg_name); +diff --git a/tools/vgextend.c b/tools/vgextend.c +index 0856b4c78..fecd6bdd5 100644 +--- a/tools/vgextend.c ++++ b/tools/vgextend.c +@@ -160,7 +160,8 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv) + + cmd->edit_devices_file = 1; + +- lvmcache_label_scan(cmd); ++ if (!lvmcache_label_scan(cmd)) ++ return_ECMD_FAILED; + + if (!(handle = init_processing_handle(cmd, NULL))) { + log_error("Failed to initialize processing handle."); +diff --git a/tools/vgmerge.c b/tools/vgmerge.c +index 08615cd62..4ed4a8f0b 100644 +--- a/tools/vgmerge.c ++++ b/tools/vgmerge.c +@@ -72,7 +72,8 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to, + return ECMD_FAILED; + } + +- lvmcache_label_scan(cmd); ++ if (!lvmcache_label_scan(cmd)) ++ return_ECMD_FAILED; + + if (strcmp(vg_name_to, vg_name_from) > 0) + lock_vg_from_first = 1; +diff --git a/tools/vgsplit.c b/tools/vgsplit.c +index a085ac2ba..9d6534e89 100644 +--- a/tools/vgsplit.c ++++ b/tools/vgsplit.c +@@ -559,7 +559,8 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) + return ECMD_FAILED; + } + +- lvmcache_label_scan(cmd); ++ if (!lvmcache_label_scan(cmd)) ++ return_ECMD_FAILED; + + if (!(vginfo_to = lvmcache_vginfo_from_vgname(vg_name_to, NULL))) { + if (!validate_name(vg_name_to)) { +-- +2.34.3 + diff --git a/lvm2.spec b/lvm2.spec index 07615e8..3d7b748 100644 --- a/lvm2.spec +++ b/lvm2.spec @@ -55,7 +55,7 @@ %global commit 4dc5d4ac7e7a9457ccc46ff04796b347e58bf4da %global shortcommit %(c=%{commit}; echo ${c:0:7}) %endif -%global rel_suffix .2 +#%%global rel_suffix .test # Do not reset Release to 1 unless both lvm2 and device-mapper # versions are increased together. @@ -68,7 +68,7 @@ Version: 2.03.14 %if 0%{?from_snapshot} Release: 0.1.20210426git%{shortcommit}%{?dist}%{?rel_suffix} %else -Release: 3%{?dist}%{?rel_suffix} +Release: 5%{?dist}%{?rel_suffix} %endif License: GPLv2 URL: http://sourceware.org/lvm2 @@ -103,9 +103,39 @@ Patch22: 0021-man-add-section-about-static-autoactivation.patch Patch23: 0022-lvcreate-include-recent-options.patch Patch24: 0023-man-lvmautoactivation-replace-systemctl-with-journal.patch Patch25: 0024-make-generate.patch -# BZ 2100133: -Patch26: 0025-filter-mpath-use-multipath-blacklist.patch -Patch27: 0026-filter-mpath-handle-other-wwid-types-in-blacklist.patch +Patch26: 0025-pvcreate-overwrite-partition-header-with-f.patch +Patch27: 0026-lvmdevices-check-error-exit-if-update-is-needed.patch +Patch28: 0027-Revert-pvcreate-overwrite-partition-header-with-f.patch +Patch29: 0028-devices-exclude-multipath-components-based-on-matchi.patch +Patch30: 0029-devices-exclude-md-components-when-duplicate-pvs-are.patch +Patch31: 0030-lvmdevices-fix-checks-when-adding-entries.patch +Patch32: 0031-lvmdevices-make-deldev-work-for-missing-device.patch +Patch33: 0032-devices-file-do-not-clear-PVID-of-unread-devices.patch +Patch34: 0033-man-lvmcache-mention-writecache-memory-usage.patch +Patch35: 0034-writecache-display-block-size-from-lvs.patch +Patch36: 0035-devices-simplify-dev_cache_get_by_devt.patch +Patch37: 0036-devices-drop-incorrect-paths-from-aliases-list.patch +Patch38: 0037-devices-initial-use-of-existing-option.patch +Patch39: 0038-devices-fix-dev_name-assumptions.patch +Patch40: 0039-devices-use-dev-cache-aliases-handling-from-label-sc.patch +Patch41: 0040-writecache-check-memory-usage.patch +Patch42: 0041-change-messages-about-filtered-devices.patch +Patch43: 0042-vgimportdevices-fix-incorrect-deviceidtype-usage.patch +Patch44: 0043-lvmlockd-return-error-from-vgcreate-init_vg_sanlock.patch +Patch45: 0044-devices-file-remove-extraneous-unlock-in-vgchange-u.patch +Patch46: 0045-filter-mpath-use-multipath-blacklist.patch +Patch47: 0046-improve-description-of-devices-option.patch +Patch48: 0047-vdo-support-vdosettings.patch +Patch49: 0048-toollib-fix-segfault-when-handling-selection-with-hi.patch +Patch50: 0049-devices-file-move-clean-up-after-command-is-run.patch +Patch51: 0050-devices-file-fail-if-devicesfile-filename-doesn-t-ex.patch +Patch52: 0051-filter-mpath-handle-other-wwid-types-in-blacklist.patch +Patch53: 0052-vdo-fix-conversion-of-vdo_slab_size_mb.patch +Patch54: 0053-filter-mpath-get-wwids-from-sysfs-vpd_pg83.patch +Patch55: 0054-build-Fix-make-rpm-with-VERSION_DM-without-dash.patch +Patch56: 0055-make-generate.patch +# BZ 2090949: +Patch57: 0056-exit-with-error-when-devicesfile-name-doesn-t-exist.patch BuildRequires: gcc %if %{enable_testsuite} @@ -193,6 +223,36 @@ or more physical volumes and creating one or more logical volumes %patch25 -p1 -b .backup25 %patch26 -p1 -b .backup26 %patch27 -p1 -b .backup27 +%patch28 -p1 -b .backup28 +%patch29 -p1 -b .backup29 +%patch30 -p1 -b .backup30 +%patch31 -p1 -b .backup31 +%patch32 -p1 -b .backup32 +%patch33 -p1 -b .backup33 +%patch34 -p1 -b .backup34 +%patch35 -p1 -b .backup35 +%patch36 -p1 -b .backup36 +%patch37 -p1 -b .backup37 +%patch38 -p1 -b .backup38 +%patch39 -p1 -b .backup39 +%patch40 -p1 -b .backup40 +%patch41 -p1 -b .backup41 +%patch42 -p1 -b .backup42 +%patch43 -p1 -b .backup43 +%patch44 -p1 -b .backup44 +%patch45 -p1 -b .backup45 +%patch46 -p1 -b .backup46 +%patch47 -p1 -b .backup47 +%patch48 -p1 -b .backup48 +%patch49 -p1 -b .backup49 +%patch50 -p1 -b .backup50 +%patch51 -p1 -b .backup51 +%patch52 -p1 -b .backup52 +%patch53 -p1 -b .backup53 +%patch54 -p1 -b .backup54 +%patch55 -p1 -b .backup55 +%patch56 -p1 -b .backup56 +%patch57 -p1 -b .backup57 %build %global _default_pid_dir /run @@ -811,11 +871,11 @@ An extensive functional testsuite for LVM2. %endif %changelog -* Tue Jul 12 2022 Marian Csontos - 2.03.14-3.el8_6.2 -- Fix packaging. +* Thu Jul 14 2022 Marian Csontos - 2.03.14-5 +- Exit with error when --devicesfile used does not exist. -* Tue Jun 28 2022 Marian Csontos - 2.03.14-3.el8_6.1 -- Fix filter not respecting blacklisted multipath devices. +* Wed Jun 15 2022 Marian Csontos - 2.03.14-4 +- Additional important fixes from upstream up to commit 3b0f9ce. * Tue Jan 04 2022 Marian Csontos - 2.03.14-3 - Fix devices file and autoactivation related issues.