import lvm2-2.03.14-3.el8

This commit is contained in:
CentOS Sources 2022-05-10 03:16:11 -04:00 committed by Stepan Oksanichenko
parent 0102d121d2
commit 6777e26a90
62 changed files with 3217 additions and 4337 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/LVM2.2.03.12.tgz
SOURCES/LVM2.2.03.14.tgz

View File

@ -1 +1 @@
6d74d987b474dd0b45f239eb6dcc050622ad6962 SOURCES/LVM2.2.03.12.tgz
e5d4364e823d72b9a08b3aecc13cd677972830f0 SOURCES/LVM2.2.03.14.tgz

View File

@ -0,0 +1,545 @@
From 63c4458aaf67d114c677baf657a7e9e43440f349 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Mon, 20 Dec 2021 14:22:02 -0600
Subject: [PATCH 01/23] Revert "new udev autoactivation"
This reverts commit 67722b312390cdab29c076c912e14bd739c5c0f6.
---
scripts/Makefile.in | 1 +
test/shell/udev-pvscan-vgchange.sh | 403 -----------------------------
udev/69-dm-lvm.rules.in | 87 -------
udev/Makefile.in | 2 +-
5 files changed, 4 insertions(+), 492 deletions(-)
delete mode 100644 test/shell/udev-pvscan-vgchange.sh
delete mode 100644 udev/69-dm-lvm.rules.in
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index 0d7f45680..ee0acb6f6 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -92,6 +92,7 @@ install_systemd_generators:
install_systemd_units: install_dbus_service
@echo " [INSTALL] systemd_units"
$(Q) $(INSTALL_DIR) $(systemd_unit_dir)
+ $(Q) $(INSTALL_DATA) lvm2-pvscan.service $(systemd_unit_dir)/lvm2-pvscan@.service
ifeq ("@BUILD_DMEVENTD@", "yes")
$(Q) $(INSTALL_DATA) dm_event_systemd_red_hat.socket $(systemd_unit_dir)/dm-event.socket
$(Q) $(INSTALL_DATA) dm_event_systemd_red_hat.service $(systemd_unit_dir)/dm-event.service
diff --git a/test/shell/udev-pvscan-vgchange.sh b/test/shell/udev-pvscan-vgchange.sh
deleted file mode 100644
index c81acf0ce..000000000
--- a/test/shell/udev-pvscan-vgchange.sh
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/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
-
-#
-# $ cat /tmp/devs
-# /dev/sdb
-# /dev/sdc
-# /dev/sdd
-#
-# Specify this file as LVM_TEST_DEVICE_LIST=/tmp/devs
-# when running the test.
-#
-# This test will wipe these devices.
-#
-
-if [ -z ${LVM_TEST_DEVICE_LIST+x} ]; then echo "LVM_TEST_DEVICE_LIST is unset" && skip; else echo "LVM_TEST_DEVICE_LIST is set to '$LVM_TEST_DEVICE_LIST'"; fi
-
-test -e "$LVM_TEST_DEVICE_LIST" || skip
-
-num_devs=$(cat $LVM_TEST_DEVICE_LIST | wc -l)
-
-RUNDIR="/run"
-test -d "$RUNDIR" || RUNDIR="/var/run"
-PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online"
-VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online"
-PVS_LOOKUP_DIR="$RUNDIR/lvm/pvs_lookup"
-
-_clear_online_files() {
- # wait till udev is finished
- aux udev_wait
- rm -f "$PVS_ONLINE_DIR"/*
- rm -f "$VGS_ONLINE_DIR"/*
- rm -f "$PVS_LOOKUP_DIR"/*
-}
-
-test -d "$PVS_ONLINE_DIR" || mkdir -p "$PVS_ONLINE_DIR"
-test -d "$VGS_ONLINE_DIR" || mkdir -p "$VGS_ONLINE_DIR"
-test -d "$PVS_LOOKUP_DIR" || mkdir -p "$PVS_LOOKUP_DIR"
-_clear_online_files
-
-aux prepare_real_devs
-
-aux lvmconf 'devices/dir = "/dev"'
-aux lvmconf 'devices/use_devicesfile = 1'
-DFDIR="$LVM_SYSTEM_DIR/devices"
-DF="$DFDIR/system.devices"
-mkdir $DFDIR || true
-not ls $DF
-
-get_real_devs
-
-wipe_all() {
- for dev in "${REAL_DEVICES[@]}"; do
- wipefs -a $dev
- done
-}
-
-# udevadm trigger runs udev rule which runs systemd-run --no-wait vgchange -aay
-# Because of --no-wait, we need to wait for the transient systemd
-# service to be gone before checking the effects of the vgchange.
-
-wait_lvm_activate() {
- local vgw=$1
- local wait=0
-
- while systemctl status lvm-activate-$vgw > /dev/null && test "$wait" -le 30; do
- sleep .2
- wait=$(( wait + 1 ))
- done
-}
-
-# Test requires 3 devs
-test $num_devs -gt 2 || skip
-BDEV1=$(basename "$dev1")
-BDEV2=$(basename "$dev2")
-BDEV3=$(basename "$dev3")
-
-wipe_all
-touch $DF
-for dev in "${REAL_DEVICES[@]}"; do
- pvcreate $dev
-done
-
-# 1 dev, 1 vg, 1 lv
-
-vgcreate $vg1 "$dev1"
-lvcreate -l1 -an -n $lv1 $vg1 "$dev1"
-
-PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}')
-
-_clear_online_files
-udevadm trigger --settle -c add /sys/block/$BDEV1
-
-wait_lvm_activate $vg1
-
-ls "$RUNDIR/lvm/pvs_online/$PVID1"
-ls "$RUNDIR/lvm/vgs_online/$vg1"
-journalctl -u lvm-activate-$vg1 | tee out || true
-grep "now active" out
-check lv_field $vg1/$lv1 lv_active "active"
-
-vgchange -an $vg1
-vgremove -y $vg1
-
-
-# 2 devs, 1 vg, 2 lvs
-
-vgcreate $vg2 "$dev1" "$dev2"
-lvcreate -l1 -an -n $lv1 $vg2 "$dev1"
-lvcreate -l1 -an -n $lv2 $vg2 "$dev2"
-
-PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}')
-PVID2=$(pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}')
-
-_clear_online_files
-
-udevadm trigger --settle -c add /sys/block/$BDEV1
-ls "$RUNDIR/lvm/pvs_online/$PVID1"
-not ls "$RUNDIR/lvm/vgs_online/$vg2"
-journalctl -u lvm-activate-$vg2 | tee out || true
-not grep "now active" out
-check lv_field $vg2/$lv1 lv_active ""
-check lv_field $vg2/$lv2 lv_active ""
-
-udevadm trigger --settle -c add /sys/block/$BDEV2
-ls "$RUNDIR/lvm/pvs_online/$PVID2"
-ls "$RUNDIR/lvm/vgs_online/$vg2"
-
-wait_lvm_activate $vg2
-
-journalctl -u lvm-activate-$vg2 | tee out || true
-grep "now active" out
-check lv_field $vg2/$lv1 lv_active "active"
-check lv_field $vg2/$lv2 lv_active "active"
-
-vgchange -an $vg2
-vgremove -y $vg2
-
-
-# 3 devs, 1 vg, 4 lvs, concurrent pvscans
-# (attempting to have the pvscans run concurrently and race
-# to activate the VG)
-
-vgcreate $vg3 "$dev1" "$dev2" "$dev3"
-lvcreate -l1 -an -n $lv1 $vg3 "$dev1"
-lvcreate -l1 -an -n $lv2 $vg3 "$dev2"
-lvcreate -l1 -an -n $lv3 $vg3 "$dev3"
-lvcreate -l8 -an -n $lv4 -i 2 $vg3 "$dev1" "$dev2"
-
-PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}')
-PVID2=$(pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}')
-PVID3=$(pvs "$dev3" --noheading -o uuid | tr -d - | awk '{print $1}')
-
-_clear_online_files
-
-udevadm trigger -c add /sys/block/$BDEV1 &
-udevadm trigger -c add /sys/block/$BDEV2 &
-udevadm trigger -c add /sys/block/$BDEV3
-
-aux udev_wait
-wait_lvm_activate $vg3
-
-ls "$RUNDIR/lvm/pvs_online/$PVID1"
-ls "$RUNDIR/lvm/pvs_online/$PVID2"
-ls "$RUNDIR/lvm/pvs_online/$PVID3"
-ls "$RUNDIR/lvm/vgs_online/$vg3"
-journalctl -u lvm-activate-$vg3 | tee out || true
-grep "now active" out
-check lv_field $vg3/$lv1 lv_active "active"
-check lv_field $vg3/$lv2 lv_active "active"
-check lv_field $vg3/$lv3 lv_active "active"
-check lv_field $vg3/$lv4 lv_active "active"
-
-vgchange -an $vg3
-vgremove -y $vg3
-
-
-# 3 devs, 1 vg, 4 lvs, concurrent pvscans, metadata on only 1 PV
-
-wipe_all
-rm $DF
-touch $DF
-pvcreate --metadatacopies 0 "$dev1"
-pvcreate --metadatacopies 0 "$dev2"
-pvcreate "$dev3"
-
-vgcreate $vg4 "$dev1" "$dev2" "$dev3"
-lvcreate -l1 -an -n $lv1 $vg4 "$dev1"
-lvcreate -l1 -an -n $lv2 $vg4 "$dev2"
-lvcreate -l1 -an -n $lv3 $vg4 "$dev3"
-lvcreate -l8 -an -n $lv4 -i 2 $vg4 "$dev1" "$dev2"
-
-PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}')
-PVID2=$(pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}')
-PVID3=$(pvs "$dev3" --noheading -o uuid | tr -d - | awk '{print $1}')
-
-_clear_online_files
-
-udevadm trigger -c add /sys/block/$BDEV1 &
-udevadm trigger -c add /sys/block/$BDEV2 &
-udevadm trigger -c add /sys/block/$BDEV3
-
-aux udev_wait
-wait_lvm_activate $vg4
-
-ls "$RUNDIR/lvm/pvs_online/$PVID1"
-ls "$RUNDIR/lvm/pvs_online/$PVID2"
-ls "$RUNDIR/lvm/pvs_online/$PVID3"
-ls "$RUNDIR/lvm/vgs_online/$vg4"
-journalctl -u lvm-activate-$vg4 | tee out || true
-grep "now active" out
-check lv_field $vg4/$lv1 lv_active "active"
-check lv_field $vg4/$lv2 lv_active "active"
-check lv_field $vg4/$lv3 lv_active "active"
-check lv_field $vg4/$lv4 lv_active "active"
-
-vgchange -an $vg4
-vgremove -y $vg4
-
-
-# 3 devs, 3 vgs, 2 lvs in each vg, concurrent pvscans
-
-wipe_all
-rm $DF
-touch $DF
-
-vgcreate $vg5 "$dev1"
-vgcreate $vg6 "$dev2"
-vgcreate $vg7 "$dev3"
-lvcreate -l1 -an -n $lv1 $vg5
-lvcreate -l1 -an -n $lv2 $vg5
-lvcreate -l1 -an -n $lv1 $vg6
-lvcreate -l1 -an -n $lv2 $vg6
-lvcreate -l1 -an -n $lv1 $vg7
-lvcreate -l1 -an -n $lv2 $vg7
-
-_clear_online_files
-
-udevadm trigger -c add /sys/block/$BDEV1 &
-udevadm trigger -c add /sys/block/$BDEV2 &
-udevadm trigger -c add /sys/block/$BDEV3
-
-aux udev_wait
-wait_lvm_activate $vg5
-wait_lvm_activate $vg6
-wait_lvm_activate $vg7
-
-ls "$RUNDIR/lvm/vgs_online/$vg5"
-ls "$RUNDIR/lvm/vgs_online/$vg6"
-ls "$RUNDIR/lvm/vgs_online/$vg7"
-journalctl -u lvm-activate-$vg5 | tee out || true
-grep "now active" out
-journalctl -u lvm-activate-$vg6 | tee out || true
-grep "now active" out
-journalctl -u lvm-activate-$vg7 | tee out || true
-grep "now active" out
-check lv_field $vg5/$lv1 lv_active "active"
-check lv_field $vg5/$lv2 lv_active "active"
-check lv_field $vg6/$lv1 lv_active "active"
-check lv_field $vg6/$lv2 lv_active "active"
-check lv_field $vg7/$lv1 lv_active "active"
-check lv_field $vg7/$lv2 lv_active "active"
-
-vgchange -an $vg5
-vgremove -y $vg5
-vgchange -an $vg6
-vgremove -y $vg6
-vgchange -an $vg7
-vgremove -y $vg7
-
-# 3 devs, 1 vg, 1000 LVs
-
-wipe_all
-rm $DF
-touch $DF
-pvcreate --metadatacopies 0 "$dev1"
-pvcreate "$dev2"
-pvcreate "$dev3"
-vgcreate -s 128K $vg8 "$dev1" "$dev2" "$dev3"
-
-# Number of LVs to create
-TEST_DEVS=1000
-# On low-memory boxes let's not stress too much
-test "$(aux total_mem)" -gt 524288 || TEST_DEVS=256
-
-vgcfgbackup -f data $vg8
-
-# Generate a lot of devices (size of 1 extent)
-awk -v TEST_DEVS=$TEST_DEVS '/^\t\}/ {
- printf("\t}\n\tlogical_volumes {\n");
- cnt=0;
- for (i = 0; i < TEST_DEVS; i++) {
- printf("\t\tlvol%06d {\n", i);
- printf("\t\t\tid = \"%06d-1111-2222-3333-2222-1111-%06d\"\n", i, i);
- print "\t\t\tstatus = [\"READ\", \"WRITE\", \"VISIBLE\"]";
- print "\t\t\tsegment_count = 1";
- print "\t\t\tsegment1 {";
- print "\t\t\t\tstart_extent = 0";
- print "\t\t\t\textent_count = 1";
- print "\t\t\t\ttype = \"striped\"";
- print "\t\t\t\tstripe_count = 1";
- print "\t\t\t\tstripes = [";
- print "\t\t\t\t\t\"pv0\", " cnt++;
- printf("\t\t\t\t]\n\t\t\t}\n\t\t}\n");
- }
- }
- {print}
-' data >data_new
-
-vgcfgrestore -f data_new $vg8
-
-_clear_online_files
-
-udevadm trigger -c add /sys/block/$BDEV1 &
-udevadm trigger -c add /sys/block/$BDEV2 &
-udevadm trigger -c add /sys/block/$BDEV3
-
-aux udev_wait
-wait_lvm_activate $vg8
-
-ls "$RUNDIR/lvm/vgs_online/$vg8"
-journalctl -u lvm-activate-$vg8 | tee out || true
-grep "now active" out
-
-num_active=$(lvs $vg8 --noheading -o active | grep active | wc -l)
-
-test $num_active -eq $TEST_DEVS
-
-vgchange -an $vg8
-vgremove -y $vg8
-
-# 1 pv on an md dev, 1 vg
-
-wait_md_create() {
- local md=$1
-
- while :; do
- if ! grep "$(basename $md)" /proc/mdstat; then
- echo "$md not ready"
- cat /proc/mdstat
- sleep 2
- else
- break
- fi
- done
- echo "$md" > WAIT_MD_DEV
-}
-
-test -f /proc/mdstat && grep -q raid1 /proc/mdstat || \
- modprobe raid1 || skip
-
-mddev="/dev/md33"
-not grep $mddev /proc/mdstat || skip
-
-wipe_all
-rm $DF
-touch $DF
-
-mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
-wait_md_create "$mddev"
-vgcreate $vg9 "$mddev"
-
-PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
-BDEVMD=$(basename "$mddev")
-
-lvcreate -l1 -an -n $lv1 $vg9
-lvcreate -l1 -an -n $lv2 $vg9
-
-_clear_online_files
-
-udevadm trigger --settle -c add /sys/block/$BDEVMD
-
-wait_lvm_activate $vg9
-
-ls "$RUNDIR/lvm/vgs_online/$vg9"
-journalctl -u lvm-activate-$vg9 | tee out || true
-grep "now active" out
-check lv_field $vg9/$lv1 lv_active "active"
-check lv_field $vg9/$lv2 lv_active "active"
-
-vgchange -an $vg9
-vgremove -y $vg9
-
-mdadm --stop "$mddev"
-aux udev_wait
-wipe_all
-
diff --git a/udev/69-dm-lvm.rules.in b/udev/69-dm-lvm.rules.in
deleted file mode 100644
index 39e5b9807..000000000
--- a/udev/69-dm-lvm.rules.in
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright (C) 2012,2021 Red Hat, Inc. All rights reserved.
-#
-# This file is part of LVM.
-#
-# This rule requires blkid to be called on block devices before so only devices
-# used as LVM PVs are processed (ID_FS_TYPE="LVM2_member").
-
-SUBSYSTEM!="block", GOTO="lvm_end"
-(LVM_EXEC_RULE)
-
-ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="lvm_end"
-
-# Only process devices already marked as a PV - this requires blkid to be called before.
-ENV{ID_FS_TYPE}!="LVM2_member", GOTO="lvm_end"
-ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="lvm_end"
-ACTION=="remove", GOTO="lvm_end"
-
-# Create /dev/disk/by-id/lvm-pv-uuid-<PV_UUID> symlink for each PV
-ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-id/lvm-pv-uuid-$env{ID_FS_UUID_ENC}"
-
-# If the PV is a special device listed below, scan only if the device is
-# properly activated. These devices are not usable after an ADD event,
-# but they require an extra setup and they are ready after a CHANGE event.
-# Also support coldplugging with ADD event but only if the device is already
-# properly activated.
-# This logic should be eventually moved to rules where those particular
-# devices are processed primarily (MD and loop).
-
-# DM device:
-KERNEL!="dm-[0-9]*", GOTO="next"
-ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", ENV{DM_ACTIVATION}=="1", GOTO="lvm_scan"
-GOTO="lvm_end"
-
-# MD device:
-LABEL="next"
-KERNEL!="md[0-9]*", GOTO="next"
-IMPORT{db}="LVM_MD_PV_ACTIVATED"
-ACTION=="add", ENV{LVM_MD_PV_ACTIVATED}=="1", GOTO="lvm_scan"
-ACTION=="change", ENV{LVM_MD_PV_ACTIVATED}!="1", TEST=="md/array_state", ENV{LVM_MD_PV_ACTIVATED}="1", GOTO="lvm_scan"
-ACTION=="add", KERNEL=="md[0-9]*p[0-9]*", GOTO="lvm_scan"
-ENV{LVM_MD_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0"
-GOTO="lvm_end"
-
-# Loop device:
-LABEL="next"
-KERNEL!="loop[0-9]*", GOTO="next"
-ACTION=="add", ENV{LVM_LOOP_PV_ACTIVATED}=="1", GOTO="lvm_scan"
-ACTION=="change", ENV{LVM_LOOP_PV_ACTIVATED}!="1", TEST=="loop/backing_file", ENV{LVM_LOOP_PV_ACTIVATED}="1", GOTO="lvm_scan"
-ENV{LVM_LOOP_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0"
-GOTO="lvm_end"
-
-LABEL="next"
-ACTION!="add", GOTO="lvm_end"
-
-LABEL="lvm_scan"
-
-ENV{SYSTEMD_READY}="1"
-
-# pvscan will check if this device completes a VG,
-# i.e. all PVs in the VG are now present with the
-# arrival of this PV. If so, it prints to stdout:
-# LVM_VG_NAME_COMPLETE='foo'
-#
-# When the VG is complete it can be activated, so
-# vgchange -aay <vgname> is run. It is run via
-# systemd since it can take longer to run than
-# udev wants to block when processing rules.
-# (if there are hundreds of LVs to activate,
-# the vgchange can take many seconds.)
-#
-# pvscan only reads the single device specified,
-# and uses temp files under /run/lvm to check if
-# other PVs in the VG are present.
-#
-# If event_activation=0 in lvm.conf, this pvscan
-# (using checkcomplete) will do nothing, so that
-# no event-based autoactivation will be happen.
-#
-# TODO: adjust the output of vgchange -aay so that
-# it's better suited to appearing in the journal.
-
-IMPORT{program}="(LVM_EXEC)/lvm pvscan --cache --listvg --checkcomplete --vgonline --udevoutput --journal=output $env{DEVNAME}"
-ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/usr/bin/systemd-run -r --no-block --property DefaultDependencies=no --unit lvm-activate-$env{LVM_VG_NAME_COMPLETE} lvm vgchange -aay --nohints $env{LVM_VG_NAME_COMPLETE}"
-GOTO="lvm_end"
-
-LABEL="lvm_end"
-
diff --git a/udev/Makefile.in b/udev/Makefile.in
index e777dda16..e32cba921 100644
--- a/udev/Makefile.in
+++ b/udev/Makefile.in
@@ -18,7 +18,7 @@ top_builddir = @top_builddir@
include $(top_builddir)/make.tmpl
DM_RULES=10-dm.rules 13-dm-disk.rules 95-dm-notify.rules
-LVM_RULES=11-dm-lvm.rules 69-dm-lvm.rules
+LVM_RULES=11-dm-lvm.rules 69-dm-lvm-metad.rules
DM_DIR=$(shell $(GREP) "\#define DM_DIR" $(top_srcdir)/libdm/misc/dm-ioctl.h | $(AWK) '{print $$3}')
--
2.31.1

View File

@ -0,0 +1,450 @@
From 2091305b796d5552fd991c527a0359a0b4d8fde0 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Mon, 20 Dec 2021 13:38:23 -0600
Subject: [PATCH 02/23] Revert "pvscan: only add device args to dev cache"
This reverts commit 33e47182f773c1a902b533580b63a803906de55d.
---
lib/device/dev-cache.c | 204 +++-----------------------------
lib/device/dev-cache.h | 6 +-
lib/device/device_id.c | 27 ++---
lib/device/device_id.h | 1 -
test/shell/devicesfile-basic.sh | 2 +-
tools/pvscan.c | 58 ++++-----
6 files changed, 52 insertions(+), 246 deletions(-)
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 33b75a9a9..c6e5f68cf 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -1852,7 +1852,7 @@ int setup_devices_file(struct cmd_context *cmd)
* Add all system devices to dev-cache, and attempt to
* match all devices_file entries to dev-cache entries.
*/
-int setup_devices(struct cmd_context *cmd)
+static int _setup_devices(struct cmd_context *cmd, int no_file_match)
{
int file_exists;
int lock_mode = 0;
@@ -1979,6 +1979,13 @@ int setup_devices(struct cmd_context *cmd)
*/
dev_cache_scan(cmd);
+ /*
+ * The caller uses "no_file_match" if it wants to match specific devs
+ * itself, instead of matching everything in device_ids_match.
+ */
+ if (no_file_match && cmd->enable_devices_file)
+ return 1;
+
/*
* Match entries from cmd->use_devices with device structs in dev-cache.
*/
@@ -1987,6 +1994,16 @@ int setup_devices(struct cmd_context *cmd)
return 1;
}
+int setup_devices(struct cmd_context *cmd)
+{
+ return _setup_devices(cmd, 0);
+}
+
+int setup_devices_no_file_match(struct cmd_context *cmd)
+{
+ return _setup_devices(cmd, 1);
+}
+
/*
* The alternative to setup_devices() when the command is interested
* in using only one PV.
@@ -2055,188 +2072,3 @@ int setup_device(struct cmd_context *cmd, const char *devname)
return 1;
}
-/*
- * pvscan --cache is specialized/optimized to look only at command args,
- * so this just sets up the devices file, then individual devices are
- * added to dev-cache and matched with device_ids later in pvscan.
- */
-
-int setup_devices_for_pvscan_cache(struct cmd_context *cmd)
-{
- if (cmd->enable_devices_list) {
- if (!_setup_devices_list(cmd))
- return_0;
- return 1;
- }
-
- if (!setup_devices_file(cmd))
- return_0;
-
- if (!cmd->enable_devices_file)
- return 1;
-
- if (!devices_file_exists(cmd)) {
- log_debug("Devices file not found, ignoring.");
- cmd->enable_devices_file = 0;
- return 1;
- }
-
- if (!lock_devices_file(cmd, LOCK_SH)) {
- log_error("Failed to lock the devices file to read.");
- return 0;
- }
-
- if (!device_ids_read(cmd)) {
- log_error("Failed to read the devices file.");
- unlock_devices_file(cmd);
- return 0;
- }
-
- unlock_devices_file(cmd);
- return 1;
-}
-
-
-/* Get a device name from a devno. */
-
-static char *_get_devname_from_devno(struct cmd_context *cmd, dev_t devno)
-{
- char path[PATH_MAX];
- char devname[PATH_MAX];
- char namebuf[NAME_LEN];
- char line[1024];
- int major = MAJOR(devno);
- int minor = MINOR(devno);
- int line_major;
- int line_minor;
- uint64_t line_blocks;
- DIR *dir;
- struct dirent *dirent;
- FILE *fp;
-
- /*
- * $ ls /sys/dev/block/8:0/device/block/
- * sda
- */
- if (major_is_scsi_device(cmd->dev_types, major)) {
- if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/device/block",
- dm_sysfs_dir(), major, minor) < 0) {
- return NULL;
- }
-
- if (!(dir = opendir(path)))
- return NULL;
-
- while ((dirent = readdir(dir))) {
- if (dirent->d_name[0] == '.')
- continue;
- if (dm_snprintf(devname, sizeof(devname), "/dev/%s", dirent->d_name) < 0) {
- devname[0] = '\0';
- stack;
- }
- break;
- }
- closedir(dir);
-
- if (devname[0]) {
- log_debug("Found %s for %d:%d from sys", devname, major, minor);
- return _strdup(devname);
- }
- return NULL;
- }
-
- /*
- * $ cat /sys/dev/block/253:3/dm/name
- * mpatha
- */
- if (major == cmd->dev_types->device_mapper_major) {
- if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/dm/name",
- dm_sysfs_dir(), major, minor) < 0) {
- return NULL;
- }
-
- if (!get_sysfs_value(path, namebuf, sizeof(namebuf), 0))
- return NULL;
-
- if (dm_snprintf(devname, sizeof(devname), "/dev/mapper/%s", namebuf) < 0) {
- devname[0] = '\0';
- stack;
- }
-
- if (devname[0]) {
- log_debug("Found %s for %d:%d from sys", devname, major, minor);
- return _strdup(devname);
- }
- return NULL;
- }
-
- /*
- * /proc/partitions lists
- * major minor #blocks name
- */
-
- if (!(fp = fopen("/proc/partitions", "r")))
- return NULL;
-
- while (fgets(line, sizeof(line), fp)) {
- if (sscanf(line, "%u %u %llu %s", &line_major, &line_minor, (unsigned long long *)&line_blocks, namebuf) != 4)
- continue;
- if (line_major != major)
- continue;
- if (line_minor != minor)
- continue;
-
- if (dm_snprintf(devname, sizeof(devname), "/dev/%s", namebuf) < 0) {
- devname[0] = '\0';
- stack;
- }
- break;
- }
- fclose(fp);
-
- if (devname[0]) {
- log_debug("Found %s for %d:%d from proc", devname, major, minor);
- return _strdup(devname);
- }
-
- /*
- * If necessary, this could continue searching by stat'ing /dev entries.
- */
-
- return NULL;
-}
-
-int setup_devname_in_dev_cache(struct cmd_context *cmd, const char *devname)
-{
- struct stat buf;
- struct device *dev;
-
- if (stat(devname, &buf) < 0) {
- log_error("Cannot access device %s.", devname);
- return 0;
- }
-
- if (!S_ISBLK(buf.st_mode)) {
- log_error("Invaild device type %s.", devname);
- return 0;
- }
-
- if (!_insert_dev(devname, buf.st_rdev))
- return_0;
-
- if (!(dev = (struct device *) dm_hash_lookup(_cache.names, devname)))
- return_0;
-
- return 1;
-}
-
-int setup_devno_in_dev_cache(struct cmd_context *cmd, dev_t devno)
-{
- const char *devname;
-
- if (!(devname = _get_devname_from_devno(cmd, devno)))
- return_0;
-
- return setup_devname_in_dev_cache(cmd, devname);
-}
-
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
index 143848d6d..635dc4fc9 100644
--- a/lib/device/dev-cache.h
+++ b/lib/device/dev-cache.h
@@ -77,11 +77,7 @@ int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor);
int setup_devices_file(struct cmd_context *cmd);
int setup_devices(struct cmd_context *cmd);
+int setup_devices_no_file_match(struct cmd_context *cmd);
int setup_device(struct cmd_context *cmd, const char *devname);
-/* Normal device setup functions are split up for pvscan optimization. */
-int setup_devices_for_pvscan_cache(struct cmd_context *cmd);
-int setup_devname_in_dev_cache(struct cmd_context *cmd, const char *devname);
-int setup_devno_in_dev_cache(struct cmd_context *cmd, dev_t devno);
-
#endif
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index 167bf661b..eb06109ff 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -1534,22 +1534,6 @@ int device_ids_match_dev(struct cmd_context *cmd, struct device *dev)
* passes the filter.
*/
-void device_ids_match_device_list(struct cmd_context *cmd)
-{
- struct dev_use *du;
-
- dm_list_iterate_items(du, &cmd->use_devices) {
- if (du->dev)
- continue;
- if (!(du->dev = dev_cache_get(cmd, du->devname, NULL))) {
- log_warn("Device not found for %s.", du->devname);
- } else {
- /* Should we set dev->id? Which idtype? Use --deviceidtype? */
- du->dev->flags |= DEV_MATCHED_USE_ID;
- }
- }
-}
-
void device_ids_match(struct cmd_context *cmd)
{
struct dev_iter *iter;
@@ -1557,7 +1541,16 @@ void device_ids_match(struct cmd_context *cmd)
struct device *dev;
if (cmd->enable_devices_list) {
- device_ids_match_device_list(cmd);
+ dm_list_iterate_items(du, &cmd->use_devices) {
+ if (du->dev)
+ continue;
+ if (!(du->dev = dev_cache_get(cmd, du->devname, NULL))) {
+ log_warn("Device not found for %s.", du->devname);
+ } else {
+ /* Should we set dev->id? Which idtype? Use --deviceidtype? */
+ du->dev->flags |= DEV_MATCHED_USE_ID;
+ }
+ }
return;
}
diff --git a/lib/device/device_id.h b/lib/device/device_id.h
index 0ada35c94..939b3a0f4 100644
--- a/lib/device/device_id.h
+++ b/lib/device/device_id.h
@@ -32,7 +32,6 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid,
void device_id_pvremove(struct cmd_context *cmd, struct device *dev);
void device_ids_match(struct cmd_context *cmd);
int device_ids_match_dev(struct cmd_context *cmd, struct device *dev);
-void device_ids_match_device_list(struct cmd_context *cmd);
void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs, int *device_ids_invalid, int noupdate);
int device_ids_version_unchanged(struct cmd_context *cmd);
void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_list, int *search_count, int noupdate);
diff --git a/test/shell/devicesfile-basic.sh b/test/shell/devicesfile-basic.sh
index 9c3455c76..7ba9e2c7f 100644
--- a/test/shell/devicesfile-basic.sh
+++ b/test/shell/devicesfile-basic.sh
@@ -283,7 +283,7 @@ not ls "$RUNDIR/lvm/pvs_online/$PVID3"
# arg in devices list
_clear_online_files
pvscan --devices "$dev3" --cache -aay "$dev3"
-pvscan --devices "$dev4","$dev3" --cache -aay "$dev4"
+pvscan --devices "$dev4" --cache -aay "$dev4"
check lv_field $vg2/$lv2 lv_active "active"
vgchange -an $vg2
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 95d593d57..8e2611361 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -857,21 +857,11 @@ static int _get_devs_from_saved_vg(struct cmd_context *cmd, const char *vgname,
devno = MKDEV(file_major, file_minor);
- if (!setup_devno_in_dev_cache(cmd, devno)) {
- log_error_pvscan(cmd, "No device set up for %d:%d PVID %s", file_major, file_minor, pvid);
- goto bad;
- }
-
if (!(dev = dev_cache_get_by_devt(cmd, devno, NULL, NULL))) {
log_error_pvscan(cmd, "No device found for %d:%d PVID %s", file_major, file_minor, pvid);
goto bad;
}
- /*
- * Do not need to match device_id here, see comment after
- * get_devs_from_saved_vg about relying on pvid online file.
- */
-
name1 = dev_name(dev);
name2 = pvl->pv->device_hint;
@@ -1109,11 +1099,17 @@ static int _pvscan_aa(struct cmd_context *cmd, struct pvscan_aa_params *pp,
* PROCESS_SKIP_SCAN: we have already done lvmcache_label_scan
* so tell process_each to skip it.
*/
+ if (do_all)
+ read_flags |= PROCESS_SKIP_SCAN;
+ /*
+ * When the command is processing specific devs (not all), it
+ * has done setup_devices_no_file_match() to avoid matching ids
+ * fo all devs unnecessarily, but now that we're falling back
+ * to process_each_vg() we need to complete the id matching.
+ */
if (!do_all)
- lvmcache_label_scan(cmd);
-
- read_flags |= PROCESS_SKIP_SCAN;
+ device_ids_match(cmd);
ret = process_each_vg(cmd, 0, NULL, NULL, vgnames, read_flags, 0, handle, _pvscan_aa_single);
}
@@ -1196,15 +1192,11 @@ static int _get_args_devs(struct cmd_context *cmd, struct dm_list *pvscan_args,
/* in common usage, no dev will be found for a devno */
dm_list_iterate_items(arg, pvscan_args) {
- if (arg->devname) {
- if (!setup_devname_in_dev_cache(cmd, arg->devname))
- log_error_pvscan(cmd, "No device set up for name arg %s", arg->devname);
+ if (arg->devname)
arg->dev = dev_cache_get(cmd, arg->devname, NULL);
- } else if (arg->devno) {
- if (!setup_devno_in_dev_cache(cmd, arg->devno))
- log_error_pvscan(cmd, "No device set up for devno arg %d", (int)arg->devno);
+ else if (arg->devno)
arg->dev = dev_cache_get_by_devt(cmd, arg->devno, NULL, NULL);
- } else
+ else
return_0;
}
@@ -1680,13 +1672,11 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv,
cmd->pvscan_cache_single = 1;
/*
- * Special pvscan-specific setup steps to avoid looking
- * at any devices except for device args.
- * Read devices file and determine if devices file will be used.
- * Does not do dev_cache_scan (adds nothing to dev-cache), and
- * does not do any device id matching.
+ * "no_file_match" means that when the devices file is used,
+ * setup_devices will skip matching devs to devices file entries.
+ * Specific devs must be matched later with device_ids_match_dev().
*/
- if (!setup_devices_for_pvscan_cache(cmd)) {
+ if (!setup_devices_no_file_match(cmd)) {
log_error_pvscan(cmd, "Failed to set up devices.");
return 0;
}
@@ -1745,21 +1735,17 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv,
log_debug("pvscan_cache_args: filter devs nodata");
/*
- * Match dev args with the devices file because special/optimized
- * device setup was used above which does not check the devices file.
- * If a match fails here do not exclude it, that will be done below by
- * passes_filter() which runs filter-deviceid. The
- * relax_deviceid_filter case needs to be able to work around
+ * Match dev args with the devices file because
+ * setup_devices_no_file_match() was used above which skipped checking
+ * the devices file. If a match fails here do not exclude it, that
+ * will be done below by passes_filter() which runs filter-deviceid.
+ * The relax_deviceid_filter case needs to be able to work around
* unmatching devs.
*/
-
if (cmd->enable_devices_file) {
- dm_list_iterate_items(devl, &pvscan_devs)
+ dm_list_iterate_items_safe(devl, devl2, &pvscan_devs)
device_ids_match_dev(cmd, devl->dev);
-
}
- if (cmd->enable_devices_list)
- device_ids_match_device_list(cmd);
if (cmd->enable_devices_file && device_ids_use_devname(cmd)) {
relax_deviceid_filter = 1;
--
2.31.1

View File

@ -0,0 +1,34 @@
From a5a2d5fa1ec47a5a548db4cf435dc84de7ce7c31 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Wed, 20 Oct 2021 16:12:41 -0500
Subject: [PATCH 03/23] pvscan: fix messages from coverity changes
---
tools/pvscan.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 8e2611361..f60c4a2ca 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -1354,7 +1354,7 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
devsize = dev->size;
if (!devsize &&
!dev_get_size(dev, &devsize)) {
- log_print("pvscan[%d] PV %s can get device size.", getpid(), dev_name(dev));
+ log_print_pvscan(cmd, "PV %s missing device size.", dev_name(dev));
release_vg(vg);
continue;
}
@@ -1786,7 +1786,7 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv,
int has_pvid;
if (!label_read_pvid(devl->dev, &has_pvid)) {
- log_print("pvscan[%d] %s cannot read.", getpid(), dev_name(devl->dev));
+ log_print_pvscan(cmd, "%s cannot read label.", dev_name(devl->dev));
dm_list_del(&devl->list);
continue;
}
--
2.31.1

View File

@ -0,0 +1,39 @@
From 074fce5c73c55e7a1547d5efff65a9f96e6db3b1 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Mon, 25 Oct 2021 12:11:17 -0500
Subject: [PATCH 04/23] vgimportdevices: skip lvmlockd locking
Help bootstrapping existing shared vgs into the devices file.
Reading the vg in vgimportdevices would require locking to be
started, but vgchange lockstart won't see the vg if it's not
in the devices file. The lvmlockd locks are not protecting
vg modifications so skipping them here won't be a problem.
---
tools/vgimportdevices.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/tools/vgimportdevices.c b/tools/vgimportdevices.c
index 3f315f98f..2580613c4 100644
--- a/tools/vgimportdevices.c
+++ b/tools/vgimportdevices.c
@@ -172,6 +172,17 @@ int vgimportdevices(struct cmd_context *cmd, int argc, char **argv)
cmd->filter_regex_with_devices_file = 1;
cmd->create_edit_devices_file = 1;
+ /*
+ * This helps a user bootstrap existing shared VGs into the devices
+ * file. Reading the vg to import devices requires locking, but
+ * lockstart won't find the vg before it's in the devices file.
+ * So, allow importing devices without an lvmlockd lock (in a
+ * a shared vg the vg metadata won't be updated with device ids,
+ * so the lvmlockd lock isn't protecting vg modification.)
+ */
+ cmd->lockd_gl_disable = 1;
+ cmd->lockd_vg_disable = 1;
+
/*
* For each VG:
* device_id_add() each PV in the VG
--
2.31.1

View File

@ -0,0 +1,95 @@
From 00ebabfe6e1ebfceffcef335d44a6156a1c15418 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Mon, 1 Nov 2021 16:01:09 -0500
Subject: [PATCH 05/23] hints: remove the cmd hints list
which is no longer used after commit
"toollib: remove all devices list from process_each_pv"
---
lib/commands/toolcontext.c | 2 --
lib/commands/toolcontext.h | 1 -
lib/label/hints.c | 1 -
lib/label/label.c | 8 ++------
4 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 105aecd5d..1b7170de1 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -1605,7 +1605,6 @@ struct cmd_context *create_config_context(void)
dm_list_init(&cmd->config_files);
dm_list_init(&cmd->tags);
- dm_list_init(&cmd->hints);
if (!_init_lvm_conf(cmd))
goto_out;
@@ -1670,7 +1669,6 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
dm_list_init(&cmd->formats);
dm_list_init(&cmd->segtypes);
dm_list_init(&cmd->tags);
- dm_list_init(&cmd->hints);
dm_list_init(&cmd->config_files);
label_init();
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 701b7a739..356c79f8a 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -206,7 +206,6 @@ struct cmd_context {
* Devices and filtering.
*/
struct dev_filter *filter;
- struct dm_list hints;
struct dm_list use_devices; /* struct dev_use for each entry in devices file */
const char *md_component_checks;
const char *search_for_devnames; /* config file setting */
diff --git a/lib/label/hints.c b/lib/label/hints.c
index 3dba9f8ec..e444a0c82 100644
--- a/lib/label/hints.c
+++ b/lib/label/hints.c
@@ -365,7 +365,6 @@ static void _unlock_hints(struct cmd_context *cmd)
void hints_exit(struct cmd_context *cmd)
{
- free_hints(&cmd->hints);
if (_hints_fd == -1)
return;
_unlock_hints(cmd);
diff --git a/lib/label/label.c b/lib/label/label.c
index 3cd912270..479a5037a 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1207,8 +1207,6 @@ int label_scan(struct cmd_context *cmd)
(unsigned long long)want_size_kb);
}
- dm_list_init(&cmd->hints);
-
/*
* If we're using hints to limit which devs we scanned, verify
* that those hints were valid, and if not we need to scan the
@@ -1220,18 +1218,16 @@ int label_scan(struct cmd_context *cmd)
_scan_list(cmd, cmd->filter, &all_devs, 0, NULL);
/* scan_devs are the devs that have been scanned */
dm_list_splice(&scan_devs, &all_devs);
- free_hints(&hints_list);
using_hints = 0;
create_hints = 0;
/* invalid hints means a new dev probably appeared and
we should search for any missing pvids again. */
unlink_searched_devnames(cmd);
- } else {
- /* The hints may be used by another device iteration. */
- dm_list_splice(&cmd->hints, &hints_list);
}
}
+ free_hints(&hints_list);
+
/*
* Check if the devices_file content is up to date and
* if not update it.
--
2.31.1

View File

@ -0,0 +1,422 @@
From f73be4480a5dd104a77e3ef84d7dcc80b834e593 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 2 Nov 2021 15:42:26 -0500
Subject: [PATCH 06/23] 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
to match the device id. So, checking for a sysfs entry for the
device in filter-sysfs is redundant. For any other cases not
covered by this (e.g. devname ids), have filter-sysfs simply
stat /sys/dev/block/major:minor to test if the device exists
in sysfs.
The extensive processing done by filter-sysfs init is removed.
It was taking an immense amount of time with many devices, e.g.
. 1024 PVs in 520 VGs
. 520 concurrent vgchange -ay <vgname> commands
. vgchange scans only PVs in the named VG (based on pvs_online
files from a pending patch)
A large number of the vgchange commands were taking over 1 min,
and nearly half of that time was used by filter-sysfs init.
With this patch, the vgchange commands take about half the time.
---
lib/commands/toolcontext.c | 24 ++-
lib/filters/filter-sysfs.c | 296 +++----------------------------------
2 files changed, 32 insertions(+), 288 deletions(-)
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 1b7170de1..a0c78ddd6 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -1143,19 +1143,6 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
* Update MAX_FILTERS definition above when adding new filters.
*/
- /*
- * sysfs filter. Only available on 2.6 kernels. Non-critical.
- * Listed first because it's very efficient at eliminating
- * unavailable devices.
- *
- * TODO: I suspect that using the lvm_type and device_id
- * filters before this one may be more efficient.
- */
- if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG, NULL)) {
- if ((filters[nr_filt] = sysfs_filter_create()))
- nr_filt++;
- }
-
/* internal filter used by command processing. */
if (!(filters[nr_filt] = internal_filter_create())) {
log_error("Failed to create internal device filter");
@@ -1195,6 +1182,17 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
}
nr_filt++;
+ /*
+ * sysfs filter. Only available on 2.6 kernels. Non-critical.
+ * Eliminates unavailable devices.
+ * TODO: this may be unnecessary now with device ids
+ * (currently not used for devs match to device id using syfs)
+ */
+ if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG, NULL)) {
+ if ((filters[nr_filt] = sysfs_filter_create()))
+ nr_filt++;
+ }
+
/* usable device filter. Required. */
if (!(filters[nr_filt] = usable_filter_create(cmd, cmd->dev_types, FILTER_MODE_NO_LVMETAD))) {
log_error("Failed to create usabled device filter");
diff --git a/lib/filters/filter-sysfs.c b/lib/filters/filter-sysfs.c
index 32ac324dd..672211057 100644
--- a/lib/filters/filter-sysfs.c
+++ b/lib/filters/filter-sysfs.c
@@ -17,288 +17,49 @@
#ifdef __linux__
-#include <sys/sysmacros.h>
-#include <dirent.h>
-
-static int _locate_sysfs_blocks(const char *sysfs_dir, char *path, size_t len,
- unsigned *sysfs_depth)
+static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
+ char path[PATH_MAX];
+ const char *sysfs_dir;
struct stat info;
- unsigned i;
- static const struct dir_class {
- const char path[32];
- int depth;
- } classes[] = {
- /*
- * unified classification directory for all kernel subsystems
- *
- * /sys/subsystem/block/devices
- * |-- sda -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
- * |-- sda1 -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1
- * `-- sr0 -> ../../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
- *
- */
- { "subsystem/block/devices", 0 },
-
- /*
- * block subsystem as a class
- *
- * /sys/class/block
- * |-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
- * |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1
- * `-- sr0 -> ../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
- *
- */
- { "class/block", 0 },
-
- /*
- * old block subsystem layout with nested directories
- *
- * /sys/block/
- * |-- sda
- * | |-- capability
- * | |-- dev
- * ...
- * | |-- sda1
- * | | |-- dev
- * ...
- * |
- * `-- sr0
- * |-- capability
- * |-- dev
- * ...
- *
- */
-
- { "block", 1 }
- };
-
- for (i = 0; i < DM_ARRAY_SIZE(classes); ++i)
- if ((dm_snprintf(path, len, "%s%s", sysfs_dir, classes[i].path) >= 0) &&
- (stat(path, &info) == 0)) {
- *sysfs_depth = classes[i].depth;
- return 1;
- }
-
- return 0;
-}
-
-/*----------------------------------------------------------------
- * We need to store a set of dev_t.
- *--------------------------------------------------------------*/
-struct entry {
- struct entry *next;
- dev_t dev;
-};
-
-#define SET_BUCKETS 64
-struct dev_set {
- struct dm_pool *mem;
- const char *sys_block;
- unsigned sysfs_depth;
- int initialised;
- struct entry *slots[SET_BUCKETS];
-};
-
-static struct dev_set *_dev_set_create(struct dm_pool *mem,
- const char *sys_block,
- unsigned sysfs_depth)
-{
- struct dev_set *ds;
-
- if (!(ds = dm_pool_zalloc(mem, sizeof(*ds))))
- return NULL;
-
- ds->mem = mem;
- if (!(ds->sys_block = dm_pool_strdup(mem, sys_block)))
- return NULL;
-
- ds->sysfs_depth = sysfs_depth;
- ds->initialised = 0;
-
- return ds;
-}
-
-static unsigned _hash_dev(dev_t dev)
-{
- return (major(dev) ^ minor(dev)) & (SET_BUCKETS - 1);
-}
-/*
- * Doesn't check that the set already contains dev.
- */
-static int _set_insert(struct dev_set *ds, dev_t dev)
-{
- struct entry *e;
- unsigned h = _hash_dev(dev);
-
- if (!(e = dm_pool_alloc(ds->mem, sizeof(*e))))
- return 0;
-
- e->next = ds->slots[h];
- e->dev = dev;
- ds->slots[h] = e;
-
- return 1;
-}
+ dev->filtered_flags &= ~DEV_FILTERED_SYSFS;
-static int _set_lookup(struct dev_set *ds, dev_t dev)
-{
- unsigned h = _hash_dev(dev);
- struct entry *e;
+ /*
+ * Any kind of device id other than devname has been set
+ * using sysfs so we know that sysfs info exists for dev.
+ */
+ if (dev->id && dev->id->idtype && (dev->id->idtype != DEV_ID_TYPE_DEVNAME))
+ return 1;
- for (e = ds->slots[h]; e; e = e->next)
- if (e->dev == dev)
+ sysfs_dir = dm_sysfs_dir();
+ if (sysfs_dir && *sysfs_dir) {
+ if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d",
+ sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
+ log_debug("failed to create sysfs path");
return 1;
-
- return 0;
-}
-
-/*----------------------------------------------------------------
- * filter methods
- *--------------------------------------------------------------*/
-static int _parse_dev(const char *file, FILE *fp, dev_t *result)
-{
- unsigned major, minor;
- char buffer[64];
-
- if (!fgets(buffer, sizeof(buffer), fp)) {
- log_error("Empty sysfs device file: %s", file);
- return 0;
- }
-
- if (sscanf(buffer, "%u:%u", &major, &minor) != 2) {
- log_error("Incorrect format for sysfs device file: %s.", file);
- return 0;
- }
-
- *result = makedev(major, minor);
- return 1;
-}
-
-static int _read_dev(const char *file, dev_t *result)
-{
- int r;
- FILE *fp;
-
- if (!(fp = fopen(file, "r"))) {
- log_sys_error("fopen", file);
- return 0;
- }
-
- r = _parse_dev(file, fp, result);
-
- if (fclose(fp))
- log_sys_error("fclose", file);
-
- return r;
-}
-
-/*
- * Recurse through sysfs directories, inserting any devs found.
- */
-static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
-{
- struct dirent *d;
- DIR *dr;
- struct stat info;
- char path[PATH_MAX];
- char file[PATH_MAX];
- dev_t dev = { 0 };
- int r = 1;
-
- if (!(dr = opendir(dir))) {
- log_sys_error("opendir", dir);
- return 0;
- }
-
- while ((d = readdir(dr))) {
- if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
- continue;
-
- if (dm_snprintf(path, sizeof(path), "%s/%s", dir,
- d->d_name) < 0) {
- log_warn("WARNING: sysfs path name too long: %s in %s.",
- d->d_name, dir);
- continue;
}
- /* devices have a "dev" file */
- if (dm_snprintf(file, sizeof(file), "%s/dev", path) < 0) {
- log_warn("WARNING: sysfs path name too long: %s in %s.",
- d->d_name, dir);
- continue;
- }
-
- if (!stat(file, &info)) {
- /* recurse if we found a device and expect subdirs */
- if (sysfs_depth)
- _read_devs(ds, path, sysfs_depth - 1);
-
- /* add the device we have found */
- if (_read_dev(file, &dev))
- _set_insert(ds, dev);
+ if (lstat(path, &info)) {
+ log_debug_devs("%s: Skipping (sysfs)", dev_name(dev));
+ dev->filtered_flags |= DEV_FILTERED_SYSFS;
+ return 0;
}
}
- if (closedir(dr))
- log_sys_debug("closedir", dir);
-
- return r;
-}
-
-static int _init_devs(struct dev_set *ds)
-{
- if (!_read_devs(ds, ds->sys_block, ds->sysfs_depth)) {
- ds->initialised = -1;
- return 0;
- }
-
- ds->initialised = 1;
-
- return 1;
-}
-
-
-static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
-{
- struct dev_set *ds = (struct dev_set *) f->private;
-
- dev->filtered_flags &= ~DEV_FILTERED_SYSFS;
-
- if (!ds->initialised)
- _init_devs(ds);
-
- /* Pass through if initialisation failed */
- if (ds->initialised != 1)
- return 1;
-
- if (!_set_lookup(ds, dev->dev)) {
- log_debug_devs("%s: Skipping (sysfs)", dev_name(dev));
- dev->filtered_flags |= DEV_FILTERED_SYSFS;
- return 0;
- }
-
return 1;
}
static void _destroy(struct dev_filter *f)
{
- struct dev_set *ds = (struct dev_set *) f->private;
-
if (f->use_count)
log_error(INTERNAL_ERROR "Destroying sysfs filter while in use %u times.", f->use_count);
-
- dm_pool_destroy(ds->mem);
+ free(f);
}
struct dev_filter *sysfs_filter_create(void)
{
const char *sysfs_dir = dm_sysfs_dir();
- char sys_block[PATH_MAX];
- unsigned sysfs_depth;
- struct dm_pool *mem;
- struct dev_set *ds;
struct dev_filter *f;
if (!*sysfs_dir) {
@@ -306,26 +67,12 @@ struct dev_filter *sysfs_filter_create(void)
return NULL;
}
- if (!_locate_sysfs_blocks(sysfs_dir, sys_block, sizeof(sys_block), &sysfs_depth))
- return NULL;
-
- if (!(mem = dm_pool_create("sysfs", 256))) {
- log_error("sysfs pool creation failed");
- return NULL;
- }
-
- if (!(ds = _dev_set_create(mem, sys_block, sysfs_depth))) {
- log_error("sysfs dev_set creation failed");
- goto bad;
- }
-
- if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
+ if (!(f = zalloc(sizeof(*f))))
goto_bad;
f->passes_filter = _accept_p;
f->destroy = _destroy;
f->use_count = 0;
- f->private = ds;
f->name = "sysfs";
log_debug_devs("Sysfs filter initialised.");
@@ -333,7 +80,6 @@ struct dev_filter *sysfs_filter_create(void)
return f;
bad:
- dm_pool_destroy(mem);
return NULL;
}
--
2.31.1

View File

@ -0,0 +1,61 @@
From f732f3d53faee3732d0f4a666c378709e6c2f5e9 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 29 Oct 2021 14:49:36 -0500
Subject: [PATCH 07/23] lvmdevices: increase open file limit
---
lib/label/label.c | 4 ++--
lib/label/label.h | 2 ++
tools/lvmdevices.c | 3 +++
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/lib/label/label.c b/lib/label/label.c
index 479a5037a..9fac3e464 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -891,7 +891,7 @@ static int _setup_bcache(void)
#define BASE_FD_COUNT 32 /* Number of open files we want apart from devs */
-static void _prepare_open_file_limit(struct cmd_context *cmd, unsigned int num_devs)
+void prepare_open_file_limit(struct cmd_context *cmd, unsigned int num_devs)
{
#ifdef HAVE_PRLIMIT
struct rlimit old = { 0 }, new;
@@ -1165,7 +1165,7 @@ int label_scan(struct cmd_context *cmd)
* which we want to keep open) is higher than the current
* soft limit.
*/
- _prepare_open_file_limit(cmd, dm_list_size(&scan_devs));
+ prepare_open_file_limit(cmd, dm_list_size(&scan_devs));
/*
* Do the main scan.
diff --git a/lib/label/label.h b/lib/label/label.h
index 8b510eb79..34563efd0 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -134,4 +134,6 @@ void dev_invalidate(struct device *dev);
void dev_set_last_byte(struct device *dev, uint64_t offset);
void dev_unset_last_byte(struct device *dev);
+void prepare_open_file_limit(struct cmd_context *cmd, unsigned int num_devs);
+
#endif
diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c
index 8d9634848..3f104f7de 100644
--- a/tools/lvmdevices.c
+++ b/tools/lvmdevices.c
@@ -176,6 +176,9 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
log_error("Failed to read the devices file.");
return ECMD_FAILED;
}
+
+ prepare_open_file_limit(cmd, dm_list_size(&cmd->use_devices));
+
dev_cache_scan(cmd);
device_ids_match(cmd);
--
2.31.1

View File

@ -0,0 +1,73 @@
From fad2b3dc8c44ba1222508ee78b5f161994efe638 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 9 Nov 2021 11:54:48 -0600
Subject: [PATCH 08/23] filter-sysfs: support old kernels without sys/dev/block
rhel5 for example doesn't have /sys/dev/block
---
lib/filters/filter-sysfs.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/lib/filters/filter-sysfs.c b/lib/filters/filter-sysfs.c
index 672211057..d8de7940b 100644
--- a/lib/filters/filter-sysfs.c
+++ b/lib/filters/filter-sysfs.c
@@ -15,6 +15,8 @@
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
+static int _sys_dev_block_found;
+
#ifdef __linux__
static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
@@ -23,6 +25,9 @@ static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct devic
const char *sysfs_dir;
struct stat info;
+ if (!_sys_dev_block_found)
+ return 1;
+
dev->filtered_flags &= ~DEV_FILTERED_SYSFS;
/*
@@ -57,6 +62,26 @@ static void _destroy(struct dev_filter *f)
free(f);
}
+static void _check_sys_dev_block(void)
+{
+ char path[PATH_MAX];
+ const char *sysfs_dir;
+ struct stat info;
+
+ sysfs_dir = dm_sysfs_dir();
+ if (sysfs_dir && *sysfs_dir) {
+ if (dm_snprintf(path, sizeof(path), "%sdev/block", sysfs_dir) < 0)
+ return;
+
+ if (lstat(path, &info)) {
+ log_debug("filter-sysfs disabled: /sys/dev/block not found");
+ _sys_dev_block_found = 0;
+ } else {
+ _sys_dev_block_found = 1;
+ }
+ }
+}
+
struct dev_filter *sysfs_filter_create(void)
{
const char *sysfs_dir = dm_sysfs_dir();
@@ -67,6 +92,9 @@ struct dev_filter *sysfs_filter_create(void)
return NULL;
}
+ /* support old kernels that don't have this */
+ _check_sys_dev_block();
+
if (!(f = zalloc(sizeof(*f))))
goto_bad;
--
2.31.1

View File

@ -0,0 +1,155 @@
From 459d931a9bfe4c9adcbbf2e76fdf35fda5b13c61 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 12 Nov 2021 16:42:51 -0600
Subject: [PATCH 09/23] 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.
---
lib/device/device_id.c | 81 +++++++++++++++++++++++++++++++++++-------
1 file changed, 69 insertions(+), 12 deletions(-)
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index eb06109ff..dea739fc4 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -1360,6 +1360,10 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg,
static int _idtype_compatible_with_major_number(struct cmd_context *cmd, int idtype, int major)
{
+ /* devname can be used with any kind of device */
+ if (idtype == DEV_ID_TYPE_DEVNAME)
+ return 1;
+
if (idtype == DEV_ID_TYPE_MPATH_UUID ||
idtype == DEV_ID_TYPE_CRYPT_UUID ||
idtype == DEV_ID_TYPE_LVMLV_UUID)
@@ -1388,6 +1392,43 @@ static int _idtype_compatible_with_major_number(struct cmd_context *cmd, int idt
return 1;
}
+static int _match_dm_devnames(struct cmd_context *cmd, struct device *dev,
+ struct dev_id *id, struct dev_use *du)
+{
+ struct stat buf;
+
+ if (MAJOR(dev->dev) != cmd->dev_types->device_mapper_major)
+ return 0;
+
+ if (id->idname && du->idname && !strcmp(id->idname, du->idname))
+ return 1;
+
+ if (du->idname && !strcmp(du->idname, dev_name(dev))) {
+ log_debug("Match device_id %s %s to %s: ignoring idname %s",
+ idtype_to_str(du->idtype), du->idname, dev_name(dev), id->idname ?: ".");
+ return 1;
+ }
+
+ if (!du->idname)
+ return 0;
+
+ /* detect that a du entry is for a dm device */
+
+ if (!strncmp(du->idname, "/dev/dm-", 8) || !strncmp(du->idname, "/dev/mapper/", 12)) {
+ if (stat(du->idname, &buf))
+ return 0;
+
+ if ((MAJOR(buf.st_rdev) == cmd->dev_types->device_mapper_major) &&
+ (MINOR(buf.st_rdev) == MINOR(dev->dev))) {
+ log_debug("Match device_id %s %s to %s: using other dm name, ignoring %s",
+ idtype_to_str(du->idtype), du->idname, dev_name(dev), id->idname ?: ".");
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/*
* check for dev->ids entry with du->idtype, if found compare it,
* if not, system_read of this type and add entry to dev->ids, compare it.
@@ -1408,35 +1449,52 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct
* so we can skip trying to match certain du entries based simply on
* the major number of dev.
*/
- if (!_idtype_compatible_with_major_number(cmd, du->idtype, (int)MAJOR(dev->dev)))
+ if (!_idtype_compatible_with_major_number(cmd, du->idtype, (int)MAJOR(dev->dev))) {
+ /*
+ log_debug("Mismatch device_id %s %s to %s: wrong major",
+ idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev));
+ */
return 0;
+ }
if (!dev_get_partition_number(dev, &part)) {
- log_debug("compare %s failed to get dev partition", dev_name(dev));
+ /*
+ log_debug("Mismatch device_id %s %s to %s: no partition",
+ idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev));
+ */
return 0;
}
if (part != du->part) {
/*
- log_debug("compare mis %s %s part %d to %s part %d",
- idtype_to_str(du->idtype), du->idname ?: ".", du->part, dev_name(dev), part);
+ log_debug("Mismatch device_id %s %s to %s: wrong partition %d vs %d",
+ idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev), du->part, part);
*/
return 0;
}
dm_list_iterate_items(id, &dev->ids) {
if (id->idtype == du->idtype) {
- if (id->idname && !strcmp(id->idname, du->idname)) {
+ if ((id->idtype == DEV_ID_TYPE_DEVNAME) && _match_dm_devnames(cmd, dev, id, du)) {
+ /* dm devs can have differing names that we know still match */
+ du->dev = dev;
+ dev->id = id;
+ dev->flags |= DEV_MATCHED_USE_ID;
+ log_debug("Match device_id %s %s to %s: dm names",
+ idtype_to_str(du->idtype), du->idname, dev_name(dev));
+ return 1;
+
+ } else if (id->idname && !strcmp(id->idname, du->idname)) {
du->dev = dev;
dev->id = id;
dev->flags |= DEV_MATCHED_USE_ID;
log_debug("Match device_id %s %s to %s",
idtype_to_str(du->idtype), du->idname, dev_name(dev));
return 1;
+
} else {
/*
- log_debug("compare mis %s %s to %s %s",
- idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev),
- ((id->idtype != DEV_ID_TYPE_DEVNAME) && id->idname) ? id->idname : "");
+ log_debug("Mismatch device_id %s %s to %s: idname %s",
+ idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev), id->idname ?: ":");
*/
return 0;
}
@@ -1456,7 +1514,7 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct
id->dev = dev;
dm_list_add(&dev->ids, &id->list);
/*
- log_debug("compare mis %s %s to %s no idtype",
+ log_debug("Mismatch device_id %s %s to %s: no idtype",
idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev));
*/
return 0;
@@ -1481,9 +1539,8 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct
}
/*
- log_debug("compare mis %s %s to %s %s",
- idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev),
- ((id->idtype != DEV_ID_TYPE_DEVNAME) && id->idname) ? id->idname : "");
+ log_debug("Mismatch device_id %s %s to %s: idname %s",
+ idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev), idname);
*/
return 0;
}
--
2.31.1

View File

@ -0,0 +1,134 @@
From 5533cd7bf4c1edc5d8fb0e95d2f83b2b2d446339 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 16 Nov 2021 09:29:24 -0600
Subject: [PATCH 10/23] 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
devname is now used by a filtered device, this was preventing
the code from searching for the new device, so the PV was
reported as missing.
---
lib/device/device_id.c | 16 ++++++-
test/shell/devicesfile-devname.sh | 69 +++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index dea739fc4..48f1682a3 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -2025,12 +2025,19 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l
search_auto = !strcmp(cmd->search_for_devnames, "auto");
dm_list_iterate_items(du, &cmd->use_devices) {
- if (du->dev)
- continue;
if (!du->pvid)
continue;
if (du->idtype != DEV_ID_TYPE_DEVNAME)
continue;
+
+ /*
+ * if the old incorrect devname is now a device that's
+ * filtered and not scanned, e.g. an mpath component,
+ * then we want to look for the pvid on a new device.
+ */
+ if (du->dev && !du->dev->filtered_flags)
+ continue;
+
if (!(dil = dm_pool_zalloc(cmd->mem, sizeof(*dil))))
continue;
@@ -2055,6 +2062,11 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l
* the searched file, so a subsequent lvm command will do the search
* again. In future perhaps we could add a policy to automatically
* remove a devices file entry that's not been found for some time.
+ *
+ * TODO: like the hint file, add a hash of all devnames to the searched
+ * file so it can be ignored and removed if the devs/hash change.
+ * If hints are enabled, the hints invalidation could also remove the
+ * searched file.
*/
if (_searched_devnames_exists(cmd)) {
log_debug("Search for PVIDs skipped for %s", _searched_file);
diff --git a/test/shell/devicesfile-devname.sh b/test/shell/devicesfile-devname.sh
index f95be52b1..a99fe3e9a 100644
--- a/test/shell/devicesfile-devname.sh
+++ b/test/shell/devicesfile-devname.sh
@@ -545,4 +545,73 @@ grep "$PVID2" "$DF" |tee out
grep "$dev2" out
not grep "$dev1" out
+vgchange -an $vg1
+vgchange -an $vg2
+vgremove -ff $vg1
+vgremove -ff $vg2
+
+# devnames change so the new devname now refers to a filtered device,
+# e.g. an mpath or md component, which is not scanned
+
+wait_md_create() {
+ local md=$1
+
+ while :; do
+ if ! grep "$(basename $md)" /proc/mdstat; then
+ echo "$md not ready"
+ cat /proc/mdstat
+ sleep 2
+ else
+ break
+ fi
+ done
+ echo "$md" > WAIT_MD_DEV
+}
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+aux wipefs_a "$dev4"
+
+mddev="/dev/md33"
+not grep $mddev /proc/mdstat || skip
+
+rm "$DF"
+touch "$DF"
+vgcreate $vg1 "$dev1" "$dev2"
+cat "$DF"
+cp "$DF" "$ORIG"
+
+# PVID with dashes for matching pvs -o+uuid output
+OPVID1=`pvs "$dev1" --noheading -o uuid | awk '{print $1}'`
+OPVID2=`pvs "$dev2" --noheading -o uuid | awk '{print $1}'`
+
+# PVID without dashes for matching devices file fields
+PVID1=`pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}'`
+PVID2=`pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}'`
+
+mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev3" "$dev4"
+wait_md_create "$mddev"
+
+sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > tmp1.devices
+sed -e "s|IDNAME=$dev1|IDNAME=$dev3|" tmp1.devices > "$DF"
+cat "$DF"
+pvs -o+uuid |tee out
+grep "$dev1" out
+grep "$dev2" out
+grep "$OPVID1" out
+grep "$OPVID2" out
+not grep "$dev3" out
+not grep "$dev4" out
+
+grep "$dev1" "$DF"
+grep "$dev2" "$DF"
+grep "$PVID1" "$DF"
+grep "$PVID2" "$DF"
+not grep "$dev3" "$DF"
+not grep "$dev4" "$DF"
+
+mdadm --stop "$mddev"
+aux udev_wait
+
vgremove -ff $vg1
--
2.31.1

View File

@ -0,0 +1,102 @@
From 39adf3e513ac7b1cbbbf0189f973573ade3c8939 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 16 Nov 2021 11:26:41 -0600
Subject: [PATCH 11/23] 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
devices file entry could be found by searching devices
again.
. When a devices file entry devname is first found to be
incorrect, a new search for missing entries may be
useful.
---
lib/device/device_id.c | 28 ++++++++++++++++++++++++++--
lib/label/hints.c | 10 ++++++++++
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index 48f1682a3..ce7ded154 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -74,6 +74,8 @@ void unlink_searched_devnames(struct cmd_context *cmd)
if (unlink(_searched_file))
log_debug("unlink %s errno %d", _searched_file, errno);
+ else
+ log_debug("unlink %s", _searched_file);
}
static int _searched_devnames_exists(struct cmd_context *cmd)
@@ -780,7 +782,7 @@ static void _device_ids_update_try(struct cmd_context *cmd)
/* Defer updates to non-pvscan-cache commands. */
if (cmd->pvscan_cache_single) {
- log_print("pvscan[%d] skip updating devices file.", getpid());
+ log_print("Devices file update skipped.");
return;
}
@@ -1441,8 +1443,22 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct
const char *idname;
int part;
- if (!du->idname || !du->idtype)
+ /*
+ * The idname will be removed from an entry with devname type when the
+ * devname is read and found to hold a different PVID than the PVID in
+ * the entry. At that point we only have the PVID and no known
+ * location for it.
+ */
+ if (!du->idname || !du->idtype) {
+ /*
+ log_debug("Mismatch device_id %s %s %s to %s",
+ du->idtype ? idtype_to_str(du->idtype) : "idtype_missing",
+ du->idname ? du->idname : "idname_missing",
+ du->devname ? du->devname : "devname_missing",
+ dev_name(dev));
+ */
return 0;
+ }
/*
* Some idtypes can only match devices with a specific major number,
@@ -1957,6 +1973,14 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
*device_ids_invalid = 1;
}
+ /*
+ * When a new devname/pvid mismatch is discovered, a new search for the
+ * pvid should be permitted (searched_devnames may exist to suppress
+ * searching for other pvids.)
+ */
+ if (update_file)
+ unlink_searched_devnames(cmd);
+
/* FIXME: for wrong devname cases, wait to write new until device_ids_find_renamed_devs? */
/*
diff --git a/lib/label/hints.c b/lib/label/hints.c
index e444a0c82..3ce9634f2 100644
--- a/lib/label/hints.c
+++ b/lib/label/hints.c
@@ -1390,6 +1390,16 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
log_debug("get_hints: needs refresh");
free_hints(&hints_list);
+ /*
+ * This is not related to hints, and is probably unnecessary,
+ * but it could possibly help. When hints become invalid it's
+ * usually becaues devs on the system have changed, and that
+ * also means that a missing devices file entry might be found
+ * by searching devices again. (the searched_devnames
+ * mechanism should eventually be replaced)
+ */
+ unlink_searched_devnames(cmd);
+
if (!_lock_hints(cmd, LOCK_EX, NONBLOCK))
return 0;
--
2.31.1

View File

@ -0,0 +1,40 @@
From 9c9bf13186d387d807f279c112745768c8b32513 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 16 Nov 2021 14:21:07 -0600
Subject: [PATCH 12/23] tests pv-ext-flags: work with devices file
---
test/shell/pv-ext-flags.sh | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/test/shell/pv-ext-flags.sh b/test/shell/pv-ext-flags.sh
index 3e6bcff76..ae4d6b7ff 100644
--- a/test/shell/pv-ext-flags.sh
+++ b/test/shell/pv-ext-flags.sh
@@ -57,9 +57,11 @@ dd if="$dev1" of=dev1_backup bs=1M
# pvcreate and pvremove can be forced even if the PV is marked as used
pvremove -ff -y "$dev1"
+lvmdevices --deldev "$dev1" || true
dd if=dev1_backup of="$dev1" bs=1M
pvcreate -ff -y "$dev1"
dd if=dev1_backup of="$dev1" bs=1M
+lvmdevices --adddev "$dev1" || true
# prepare a VG with $dev1 and $dev both having 1 MDA
aux enable_dev "$dev2"
@@ -116,9 +118,11 @@ dd if="$dev1" of=dev1_backup bs=1M
# pvcreate and pvremove can be forced even if the PV is marked as used
pvremove -ff -y "$dev1"
+lvmdevices --deldev "$dev1" || true
dd if=dev1_backup of="$dev1" bs=1M
pvcreate -ff -y "$dev1"
dd if=dev1_backup of="$dev1" bs=1M
+lvmdevices --adddev "$dev1" || true
# prepare a VG with $dev1 and $dev both having 1 MDA
aux enable_dev "$dev2"
--
2.31.1

View File

@ -0,0 +1,91 @@
From 594c1fec1644fdf291aa0ff23de20db65c4cfadf Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Wed, 17 Nov 2021 10:40:27 -0600
Subject: [PATCH 13/23] display: ignore --reportformat
Using the option would do nothing useful but would
print extraneous braces.
---
tools/command-lines.in | 12 ++++++------
tools/lvmcmdline.c | 15 +++++++++++++++
2 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/tools/command-lines.in b/tools/command-lines.in
index 10b23e75d..00ac08934 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1359,10 +1359,10 @@ OO: --aligned, --all, --binary, --colon, --columns,
--configreport ConfigReport, --foreign, --history, --ignorelockingfailure,
--logonly, --maps, --noheadings,
--nosuffix, --options String, --sort String, --readonly,
---reportformat ReportFmt, --segments, --select String, --separator String,
+--segments, --select String, --separator String,
--shared, --unbuffered, --units Units
OP: VG|LV|Tag ...
-IO: --partial, --ignoreskippedcluster
+IO: --partial, --ignoreskippedcluster, --reportformat ReportFmt
ID: lvdisplay_general
---
@@ -1590,10 +1590,10 @@ pvdisplay
OO: --aligned, --all, --binary, --colon, --columns, --configreport ConfigReport,
--foreign, --ignorelockingfailure,
--logonly, --maps, --noheadings, --nosuffix, --options String,
---readonly, --reportformat ReportFmt, --select String, --separator String, --shared,
+--readonly, --select String, --separator String, --shared,
--short, --sort String, --unbuffered, --units Units
OP: PV|Tag ...
-IO: --ignoreskippedcluster
+IO: --ignoreskippedcluster, --reportformat ReportFmt
ID: pvdisplay_general
---
@@ -1809,10 +1809,10 @@ vgdisplay
OO: --activevolumegroups, --aligned, --binary, --colon, --columns,
--configreport ConfigReport, --foreign, --ignorelockingfailure,
--logonly, --noheadings, --nosuffix,
---options String, --readonly, --reportformat ReportFmt, --select String,
+--options String, --readonly, --select String,
--shared, --short, --separator String, --sort String, --unbuffered, --units Units
OP: VG|Tag ...
-IO: --partial, --ignoreskippedcluster
+IO: --partial, --ignoreskippedcluster, --reportformat ReportFmt
ID: vgdisplay_general
---
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 1e12bedca..1727ba089 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -3058,6 +3058,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
int i;
int skip_hyphens;
int refresh_done = 0;
+ int io;
/* Avoid excessive access to /etc/localtime and set TZ variable for glibc
* so it does not need to check /etc/localtime everytime that needs that info */
@@ -3140,6 +3141,20 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
if (!(cmd->command = _find_command(cmd, cmd->name, &argc, argv)))
return EINVALID_CMD_LINE;
+ /*
+ * If option --foo is set which is listed in IO (ignore option) in
+ * command-lines.in, then unset foo. Commands won't usually use an
+ * ignored option, but there can be shared code that checks for --foo,
+ * and should not find it to be set.
+ */
+ for (io = 0; io < cmd->command->io_count; io++) {
+ int opt = cmd->command->ignore_opt_args[io].opt;
+ if (arg_is_set(cmd, opt)) {
+ log_debug("Ignore opt %d", opt);
+ cmd->opt_arg_values[opt].count = 0;
+ }
+ }
+
/*
* Remaining position args after command name and --options are removed.
*/
--
2.31.1

View File

@ -0,0 +1,25 @@
From 7ac0b3c119b1cbb8e0b4969ece0b279637ace8c3 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 19 Nov 2021 12:02:35 -0600
Subject: [PATCH 14/23] fix spelling of pruning
---
lib/format_text/archive.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/format_text/archive.c b/lib/format_text/archive.c
index 09a472b4c..2e8792a93 100644
--- a/lib/format_text/archive.c
+++ b/lib/format_text/archive.c
@@ -219,7 +219,7 @@ static void _remove_expired(const char *dir, const char *vgname,
sum /= 1024 * 1024;
if (sum > 128 || archives_size > 8192)
- log_print_unless_silent("Consider prunning %s VG archive with more then %u MiB in %u files (check archiving is needed in lvm.conf).",
+ log_print_unless_silent("Consider pruning %s VG archive with more then %u MiB in %u files (check archiving is needed in lvm.conf).",
vgname, (unsigned)sum, archives_size);
}
--
2.31.1

View File

@ -0,0 +1,416 @@
From 25dbe3dd825a629ff7f67cb43342cc345071d3f7 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Wed, 24 Nov 2021 16:03:39 -0600
Subject: [PATCH 15/23] man: lvmautoactivation
new topical man page describing autoactivation
---
man/Makefile.in | 2 +-
man/lvm.8_main | 1 +
man/lvmautoactivation.7_main | 280 +++++++++++++++++++++++++++++++++++
man/pvscan.8_des | 63 ++++----
4 files changed, 309 insertions(+), 37 deletions(-)
create mode 100644 man/lvmautoactivation.7_main
diff --git a/man/Makefile.in b/man/Makefile.in
index 40248d640..ba6f2046f 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -33,7 +33,7 @@ CMIRRORDMAN = cmirrord.8
LVMDBUSDMAN = lvmdbusd.8
MAN5=lvm.conf.5
-MAN7=lvmsystemid.7 lvmreport.7 lvmraid.7
+MAN7=lvmsystemid.7 lvmreport.7 lvmraid.7 lvmautoactivation.7
MAN8=lvm.8 lvmdump.8 lvm-fullreport.8 lvm-lvpoll.8 \
lvcreate.8 lvchange.8 lvmconfig.8 lvconvert.8 lvdisplay.8 \
diff --git a/man/lvm.8_main b/man/lvm.8_main
index 6f86d0353..a008a3bc0 100644
--- a/man/lvm.8_main
+++ b/man/lvm.8_main
@@ -579,6 +579,7 @@ Prepends source file name and code line number with libdm debugging.
.BR lvmraid (7),
.BR lvmthin (7),
.BR lvmcache (7),
+.BR lvmautoactivation (7),
.P
.BR dmsetup (8),
.BR dmstats (8),
diff --git a/man/lvmautoactivation.7_main b/man/lvmautoactivation.7_main
new file mode 100644
index 000000000..87c15a3d1
--- /dev/null
+++ b/man/lvmautoactivation.7_main
@@ -0,0 +1,280 @@
+.TH "LVMAUTOACTIVATION" "7" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
+.
+.SH NAME
+.
+lvmautoactivation \(em LVM autoactivation
+.
+.SH DESCRIPTION
+.
+Autoactivation is the activation of LVs performed automatically by the
+system in response to LVM devices being attached to the machine. When all
+PVs in a VG have been attached, the VG is complete, and LVs in the VG are
+activated.
+.P
+Autoactivation of VGs, or specific LVs, can be prevented using vgchange or
+lvchange --setautoactivation n. The lvm.conf auto_activation_volume_list
+is another way to limit autoactivation.
+.P
+The most common form of autoactivation is "event based", in which complete
+VGs are activated in response to uevents which occur during system startup
+or at any time after the system has started. Another form of
+autoactivation is "service based" in which complete VGs are activated at a
+fixed point during system startup by a systemd service, and are not
+activated in response to uevents. This can be controlled with the
+lvm.conf setting event_activation.
+.P
+Event based autoactivation is driven by udev, udev rules, and systemd.
+When a device is attached to a machine, a uevent is generated by the
+kernel to notify userspace of the new device. systemd-udev runs udev
+rules to process the new device. Udev rules use blkid to identify the
+device as an LVM PV and then execute the lvm-specific udev rule for the
+device, which triggers autoactivation.
+.P
+There are two variations of event based autoactivation that may be used a
+system, depending on the LVM udev rule that is installed (found in
+/lib/udev/rules.d/.) The following summarizes the steps in each rule
+which lead to autoactivation:
+.P
+.B 69-dm-lvm-metad.rules
+.
+.IP \[bu] 2
+device /dev/name with major:minor X:Y is attached to the machine
+.
+.IP \[bu] 2
+systemd/udev runs blkid to identify /dev/name as an LVM PV
+.
+.IP \[bu] 2
+udev rule 69-dm-lvm-metad.rules is run for /dev/name
+.
+.IP \[bu] 2
+the lvm udev rule runs the systemd service lvm2-pvscan@X:Yservice
+.
+.IP \[bu] 2
+the lvm2-pvscan service runs:
+.br
+pvscan --cache -aay --major X --minor Y
+.
+.IP \[bu] 2
+pvscan reads the device, records that the PV is online
+(see pvs_online), and checks if the VG is complete.
+.
+.IP \[bu] 2
+if the VG is complete, pvscan creates the vgs_online temp file,
+and activates the VG.
+.
+.IP \[bu] 2
+the activation command output can be seen from
+systemctl status lvm2-pvscan*
+.P
+.B 69-dm-lvm.rules
+.
+.IP \[bu] 2
+device /dev/name with major:minor X:Y is attached to the machine
+.
+.IP \[bu] 2
+systemd/udev runs blkid to identify /dev/name as an LVM PV
+.
+.IP \[bu] 2
+udev rule 69-dm-lvm.rules is run for /dev/name
+.
+.IP \[bu] 2
+the lvm udev rule runs:
+.br
+pvscan --cache --listvg --checkcomplete --vgonline
+.br
+--autoactivation event --udevoutput --journal=output /dev/name
+.
+.IP \[bu] 2
+pvscan reads the device, records that the PV is online
+(see pvs_online), and checks if the VG is complete.
+.
+.IP \[bu] 2
+if the VG is complete, pvscan creates the vgs_online temp file,
+and prints the name of the VG for the udev rule to import:
+LVM_VG_NAME_COMPLETE='vgname'
+.
+.IP \[bu] 2
+if the lvm udev rule sees LVM_VG_NAME_COMPLETE from pvscan,
+it activates the VG using a transient systemd service named
+lvm-activate-<vgname>.
+.
+.IP \[bu] 2
+the lvm-activate-<vgname> service runs
+.br
+vgchange -aay --autoactivation event <vgname>
+.
+.IP \[bu] 2
+the activation command output can be seen from
+systemctl status lvm-activate-<vgname>
+.P
+.
+.SS pvscan options
+.P
+.B --cache
+.br
+Read the <device> arg (and only that device), and record that
+the PV is online by creating the /run/lvm/pvs_online/<pvid>
+file containing the name of the VG and the device for the PV.
+.P
+.B -aay
+.br
+Activate the VG from the pvscan command
+(includes implicit --checkcomplete and --vgonline.)
+.P
+.B --checkcomplete
+.br
+Check if the VG is complete, i.e. all PVs are present on
+the system, by checking /run/lvm/pvs_online/<pvid> files.
+.P
+.B --vgonline
+.br
+Create /run/lvm/vgs_online/<vgname> if the VG is complete
+(used to ensure only one command performs activation.)
+.P
+.B --autoactivation event
+.br
+Inform the command it is used for event based autoactivation.
+.P
+.B --listvg
+.br
+Print the name of the VG using the device.
+.P
+.B --udevoutput
+.br
+Only print output that can be imported to the udev rule,
+using the udev environment key format, i.e. NAME='value'.
+.P
+.B --journal=output
+.br
+Send standard command output to the journal (when stdout
+is reserved for udev output.)
+.P
+.SS Temp files
+.P
+Autoactivation commands use a number of temp files in /run/lvm (with the
+expectation that /run is cleared between boots.)
+.P
+.B pvs_online
+.br
+pvscan --cache creates a file here for each PV that is attached. The file
+is named with the PVID and contains the VG name and device information.
+The existence of the file is used to determine when all PVs for a given VG
+are present. The device information in these files is also used to
+optimize locating devices for a VG when the VG is activated.
+.P
+.B pvs_lookup
+.br
+pvscan --cache creates a file here named for a VG (if one doesn't already
+exist.) The file contains a list of PVIDs in the VG. This is needed when
+a PV is processed which has no VG metadata, in which case the list of
+PVIDs from the lookup file is used to check if the VG is complete.
+.P
+.B vgs_online
+.br
+The first activation command (pvscan or vgchange) to create a file here,
+named for the VG, will activate the VG. This resolves a race when
+concurrent commands attempt to activate a VG at once.
+.
+.SH EXAMPLES
+.P
+VG "vg" contains two PVs:
+.nf
+$ pvs -o name,vgname,uuid /dev/sdb /dev/sdc
+ PV VG PV UUID
+ /dev/sdb vg 1uKpaT-lFOZ-NLHX-j4jI-OBi1-QpdE-HZ5hZY
+ /dev/sdc vg 5J3tM8-aIPe-2vbd-DBe7-bvRq-TGj0-DaKV2G
+.fi
+.P
+use of --cache:
+.nf
+$ pvscan --cache /dev/sdb
+ pvscan[12922] PV /dev/sdb online.
+$ pvscan --cache /dev/sdc
+ pvscan[12923] PV /dev/sdc online.
+
+$ cat /run/lvm/pvs_online/1uKpaTlFOZNLHXj4jIOBi1QpdEHZ5hZY
+8:16
+vg:vg
+dev:/dev/sdb
+$ cat /run/lvm/pvs_online/5J3tM8aIPe2vbdDBe7bvRqTGj0DaKV2G
+8:32
+vg:vg
+dev:/dev/sdc
+.fi
+.P
+use of -aay:
+.nf
+$ pvscan --cache -aay /dev/sdb
+ pvscan[12935] PV /dev/sdb online, VG vg incomplete (need 1).
+$ pvscan --cache -aay /dev/sdc
+ pvscan[12936] PV /dev/sdc online, VG vg is complete.
+ pvscan[12936] VG vg run autoactivation.
+ 1 logical volume(s) in volume group "vg" now active
+
+$ cat /run/lvm/pvs_online/1uKpaTlFOZNLHXj4jIOBi1QpdEHZ5hZY
+8:16
+vg:vg
+dev:/dev/sdb
+$ cat /run/lvm/pvs_online/5J3tM8aIPe2vbdDBe7bvRqTGj0DaKV2G
+8:32
+vg:vg
+dev:/dev/sdc
+$ ls /run/lvm/vgs_online/vg
+/run/lvm/vgs_online/vg
+.fi
+.P
+use of --listvg:
+.nf
+$ pvscan --cache --listvg /dev/sdb
+ VG vg
+$ pvscan --cache --listvg /dev/sdc
+ VG vg
+
+$ cat /run/lvm/pvs_online/1uKpaTlFOZNLHXj4jIOBi1QpdEHZ5hZY
+8:16
+vg:vg
+dev:/dev/sdb
+$ cat /run/lvm/pvs_online/5J3tM8aIPe2vbdDBe7bvRqTGj0DaKV2G
+8:32
+vg:vg
+dev:/dev/sdc
+.fi
+.P
+use of --checkcomplete:
+.nf
+$ pvscan --cache --listvg --checkcomplete --vgonline /dev/sdb
+ pvscan[12996] PV /dev/sdb online, VG vg incomplete (need 1).
+ VG vg incomplete
+$ pvscan --cache --listvg --checkcomplete --vgonline /dev/sdc
+ pvscan[12997] PV /dev/sdc online, VG vg is complete.
+ VG vg complete
+.fi
+.P
+use of --udevoutput:
+.nf
+$ pvscan --cache --listvg --checkcomplete --vgonline --udevoutput /dev/sdb
+LVM_VG_NAME_INCOMPLETE='vg'
+$ pvscan --cache --listvg --checkcomplete --vgonline --udevoutput /dev/sdc
+LVM_VG_NAME_COMPLETE='vg'
+.fi
+.P
+use of --listlvs:
+.nf
+$ lvs -o name,devices vg
+ LV Devices
+ lvol0 /dev/sdb(0)
+ lvol1 /dev/sdc(0)
+ lvol2 /dev/sdb(1),/dev/sdc(1)
+
+$ pvscan --cache --listlvs --checkcomplete /dev/sdb
+ pvscan[13288] PV /dev/sdb online, VG vg incomplete (need 1).
+ VG vg incomplete
+ LV vg/lvol0 complete
+ LV vg/lvol2 incomplete
+$ pvscan --cache --listlvs --checkcomplete /dev/sdc
+ pvscan[13289] PV /dev/sdc online, VG vg is complete.
+ VG vg complete
+ LV vg/lvol1 complete
+ LV vg/lvol2 complete
+.fi
+
diff --git a/man/pvscan.8_des b/man/pvscan.8_des
index b20b987da..4c5929955 100644
--- a/man/pvscan.8_des
+++ b/man/pvscan.8_des
@@ -4,56 +4,47 @@ like
or
.BR pvdisplay (8).
.P
-When the --cache and -aay options are used, pvscan records which PVs are
-available on the system, and activates LVs in completed VGs. A VG is
-complete when pvscan sees that the final PV in the VG has appeared. This
-is used by event-based system startup (systemd, udev) to activate LVs.
-.P
-The four main variations of this are:
+When --cache is used, pvscan updates runtime lvm state on the system, or
+with -aay performs autoactivation.
.P
.B pvscan --cache
.I device
.P
-If device is present, lvm adds a record that the PV on device is online.
+If device is present, lvm records that the PV on device is online.
If device is not present, lvm removes the online record for the PV.
-In most cases, the pvscan will only read the named devices.
+pvscan only reads the named device.
.P
-.B pvscan --cache -aay
-.IR device ...
+.B pvscan --cache
.P
-This begins by performing the same steps as above. Afterward, if the VG
-for the specified PV is complete, then pvscan will activate LVs in the VG
-(the same as vgchange -aay vgname would do.)
+Updates the runtime state for all lvm devices.
.P
-.B pvscan --cache
+.B pvscan --cache -aay
+.I device
.P
-This first clears all existing PV online records, then scans all devices
-on the system, adding PV online records for any PVs that are found.
+Performs the --cache steps for the device, then checks if the VG using the
+device is complete. If so, LVs in the VG are autoactivated, the same as
+vgchange -aay vgname would do. (A device name may be replaced with major
+and minor numbers.)
.P
.B pvscan --cache -aay
.P
-This begins by performing the same steps as pvscan --cache. Afterward, it
-activates LVs in any complete VGs.
+Performs the --cache steps for all devices, then autoactivates any complete VGs.
.P
-To prevent devices from being scanned by pvscan --cache, add them
-to
-.BR lvm.conf (5)
-.B devices/global_filter.
-For more information, see:
-.br
-.B lvmconfig --withcomments devices/global_filter
+.B pvscan --cache --listvg|--listlvs
+.I device
+.P
+Performs the --cache steps for the device, then prints the name of the VG
+using the device, or the names of LVs using the device. --checkcomplete
+is usually included to check if all PVs for the VG or LVs are online.
+When this command is called by a udev rule, the output must conform to
+udev rule specifications (see --udevoutput.) The udev rule will use the
+results to perform autoactivation.
.P
-Auto-activation of VGs or LVs can be enabled/disabled using:
-.br
+Autoactivation of VGs or LVs can be enabled/disabled using vgchange or
+lvchange with --setautoactivation y|n, or by adding names to
.BR lvm.conf (5)
.B activation/auto_activation_volume_list
.P
-For more information, see:
-.br
-.B lvmconfig --withcomments activation/auto_activation_volume_list
-.P
-To disable auto-activation, explicitly set this list to an empty list,
-i.e. auto_activation_volume_list = [ ].
-.P
-When this setting is undefined (e.g. commented), then all LVs are
-auto-activated.
+See
+.BR lvmautoactivation (7)
+for more information about how pvscan is used for autoactivation.
--
2.31.1

View File

@ -0,0 +1,25 @@
From 10a4478e9b778dd8d4ff9737a503474b00ce9510 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Wed, 1 Dec 2021 08:56:05 -0600
Subject: [PATCH 17/23] tests devicesfile-devname.sh drop mdadm chunk
---
test/shell/devicesfile-devname.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/shell/devicesfile-devname.sh b/test/shell/devicesfile-devname.sh
index a99fe3e9a..338637275 100644
--- a/test/shell/devicesfile-devname.sh
+++ b/test/shell/devicesfile-devname.sh
@@ -590,7 +590,7 @@ OPVID2=`pvs "$dev2" --noheading -o uuid | awk '{print $1}'`
PVID1=`pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}'`
PVID2=`pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}'`
-mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev3" "$dev4"
+mdadm --create --metadata=1.0 "$mddev" --level 1 --raid-devices=2 "$dev3" "$dev4"
wait_md_create "$mddev"
sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > tmp1.devices
--
2.31.1

View File

@ -0,0 +1,26 @@
From 04770589b49effdb064c9b3790e8dd2fee2c3547 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Wed, 1 Dec 2021 10:08:08 -0600
Subject: [PATCH 18/23] devices file: don't write in test mode
---
lib/device/device_id.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index ce7ded154..4c2b5a3dd 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -673,6 +673,9 @@ int device_ids_write(struct cmd_context *cmd)
cmd->enable_devices_file = 1;
}
+ if (test_mode())
+ return 1;
+
if (_devices_file_version[0]) {
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

View File

@ -0,0 +1,24 @@
From 604fd528fb4f00a9f77e084a1b22eff2aeef0259 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Thu, 2 Dec 2021 12:40:52 -0600
Subject: [PATCH 19/23] print warning about unrecognized journal option value
---
lib/log/log.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/log/log.c b/lib/log/log.c
index 7b4d537b3..5771a1d01 100644
--- a/lib/log/log.c
+++ b/lib/log/log.c
@@ -892,6 +892,7 @@ uint32_t log_journal_str_to_val(const char *str)
return LOG_JOURNAL_OUTPUT;
if (!strcasecmp(str, "debug"))
return LOG_JOURNAL_DEBUG;
+ log_warn("Ignoring unrecognized journal value.");
return 0;
}
--
2.31.1

View File

@ -0,0 +1,50 @@
From 357a807e81bbd1430b045eb2601a64b17d588400 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Thu, 2 Dec 2021 13:30:36 -0600
Subject: [PATCH 20/23] device_id: handle wwid with spaces or control
characters
non-standard wwid can be reported from sysfs with spaces/etc.
replace with "_"
---
lib/device/device_id.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index 4c2b5a3dd..0621bc858 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -304,6 +304,7 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
{
char sysbuf[PATH_MAX] = { 0 };
const char *idname = NULL;
+ int i;
if (idtype == DEV_ID_TYPE_SYS_WWID) {
read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf));
@@ -311,10 +312,6 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
if (!sysbuf[0])
read_sys_block(cmd, dev, "wwid", sysbuf, sizeof(sysbuf));
- /* scsi_debug wwid begins "t10.Linux scsi_debug ..." */
- if (strstr(sysbuf, "scsi_debug"))
- sysbuf[0] = '\0';
-
/* qemu wwid begins "t10.ATA QEMU HARDDISK ..." */
if (strstr(sysbuf, "QEMU HARDDISK"))
sysbuf[0] = '\0';
@@ -355,6 +352,11 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
return idname;
}
+ for (i = 0; i < strlen(sysbuf); i++) {
+ if (isblank(sysbuf[i]) || isspace(sysbuf[i]) || iscntrl(sysbuf[i]))
+ sysbuf[i] = '_';
+ }
+
if (!sysbuf[0])
goto_bad;
--
2.31.1

View File

@ -0,0 +1,96 @@
From 7631c5b826b5a3eddfcd22db9b80574b249794c1 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Mon, 6 Dec 2021 13:20:32 -0600
Subject: [PATCH 21/23] man: add section about static autoactivation
---
man/lvmautoactivation.7_main | 48 ++++++++++++++++++++++++++++++------
1 file changed, 41 insertions(+), 7 deletions(-)
diff --git a/man/lvmautoactivation.7_main b/man/lvmautoactivation.7_main
index 87c15a3d1..bf885991d 100644
--- a/man/lvmautoactivation.7_main
+++ b/man/lvmautoactivation.7_main
@@ -14,14 +14,16 @@ activated.
Autoactivation of VGs, or specific LVs, can be prevented using vgchange or
lvchange --setautoactivation n. The lvm.conf auto_activation_volume_list
is another way to limit autoactivation.
+.
+.SS event autoactivation
.P
The most common form of autoactivation is "event based", in which complete
VGs are activated in response to uevents which occur during system startup
or at any time after the system has started. Another form of
-autoactivation is "service based" in which complete VGs are activated at a
-fixed point during system startup by a systemd service, and are not
-activated in response to uevents. This can be controlled with the
-lvm.conf setting event_activation.
+autoactivation is "static" in which complete VGs are activated at a fixed
+point during system startup by a systemd service, and not in response to
+events. This can be controlled with the lvm.conf setting
+event_activation.
.P
Event based autoactivation is driven by udev, udev rules, and systemd.
When a device is attached to a machine, a uevent is generated by the
@@ -30,8 +32,8 @@ rules to process the new device. Udev rules use blkid to identify the
device as an LVM PV and then execute the lvm-specific udev rule for the
device, which triggers autoactivation.
.P
-There are two variations of event based autoactivation that may be used a
-system, depending on the LVM udev rule that is installed (found in
+There are two variations of event baed autoactivation that may be used on
+a system, depending on the LVM udev rule that is installed (found in
/lib/udev/rules.d/.) The following summarizes the steps in each rule
which lead to autoactivation:
.P
@@ -149,7 +151,7 @@ using the udev environment key format, i.e. NAME='value'.
Send standard command output to the journal (when stdout
is reserved for udev output.)
.P
-.SS Temp files
+.SS run files
.P
Autoactivation commands use a number of temp files in /run/lvm (with the
expectation that /run is cleared between boots.)
@@ -175,6 +177,38 @@ The first activation command (pvscan or vgchange) to create a file here,
named for the VG, will activate the VG. This resolves a race when
concurrent commands attempt to activate a VG at once.
.
+.SS static autoactivation
+.P
+When event autoactivation is disabled by setting lvm.conf
+event_activation=0, autoactivation is performed at one or more static
+points during system startup. At these points, a vgchange -aay command is
+run to activate complete VGs from devices that are present on the system
+at that time. pvscan commands (and lvm2-pvscan services) do not perform
+autoactivation in this mode. pvscan commands may still be run from
+uevents but will do nothing when they read the event_activation=0 setting.
+.P
+The static vgchange -aay commands are run by three systemd services at
+three points during startup: lvm2-activation-early, lvm2-activation, and
+lvm2-activation-net. These static activation services are "generated
+services", so the service files are created at run time by the
+lvm2-activation-generator command (run by systemd).
+lvm2-activation-generator creates the services if lvm.conf
+event_activation=0.
+.P
+The limitation of this method is that devices may not be attached to the
+system (or set up) at a reliable point in time during startup, and they
+may not be present when the services run vgchange. In this case, the VGs
+will not be autoactivated. So, the timing of device attachment/setup
+determines whether static autoactivation will produce the same results as
+event autoactivation. For this reason, static autoactivation is not
+recommended.
+.P
+Sometimes, static autoactivation is mistakenly expected to disable all
+autoactivation of particular VGs. This may appear to be effective if those
+VGs are slow to be attached or set up. But, the only correct and reliable
+way to disable autoactivation is using vgchange/lvchange
+--setautoactivation n, or lvm.conf auto_activation_volume_list.
+.
.SH EXAMPLES
.P
VG "vg" contains two PVs:
--
2.31.1

View File

@ -0,0 +1,35 @@
From af4bfa1f1f84194000bc50f43ddc906c0cd4b104 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Mon, 13 Dec 2021 08:59:31 -0600
Subject: [PATCH 22/23] lvcreate: include recent options
The permitted option list in lvcreate has not kept
up with command-lines.in.
---
tools/lvcreate.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 0121c09a8..79af42685 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -824,12 +824,16 @@ static int _lvcreate_params(struct cmd_context *cmd,
autobackup_ARG,\
available_ARG,\
contiguous_ARG,\
+ devices_ARG,\
+ devicesfile_ARG,\
ignoreactivationskip_ARG,\
ignoremonitoring_ARG,\
+ journal_ARG,\
metadataprofile_ARG,\
monitor_ARG,\
mirrors_ARG,\
name_ARG,\
+ nohints_ARG,\
noudevsync_ARG,\
permission_ARG,\
persistent_ARG,\
--
2.31.1

View File

@ -0,0 +1,26 @@
From 61833dd5b6117e8ace84289cff656d1dfb0ed123 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 14 Dec 2021 12:02:08 -0600
Subject: [PATCH 23/23] man lvmautoactivation: replace systemctl with
journalctl
---
man/lvmautoactivation.7_main | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/man/lvmautoactivation.7_main b/man/lvmautoactivation.7_main
index bf885991d..54dab718b 100644
--- a/man/lvmautoactivation.7_main
+++ b/man/lvmautoactivation.7_main
@@ -107,7 +107,7 @@ vgchange -aay --autoactivation event <vgname>
.
.IP \[bu] 2
the activation command output can be seen from
-systemctl status lvm-activate-<vgname>
+journalctl -u lvm-activate-<vgname>
.P
.
.SS pvscan options
--
2.31.1

View File

@ -0,0 +1,196 @@
From 4b26fb3543049f3d179b620ff937c44e922ada58 Mon Sep 17 00:00:00 2001
From: Marian Csontos <mcsontos@redhat.com>
Date: Tue, 4 Jan 2022 17:15:56 +0100
Subject: [PATCH] make: generate
---
man/lvdisplay.8_pregen | 12 --------
man/pvdisplay.8_pregen | 12 --------
man/pvscan.8_pregen | 63 ++++++++++++++++++------------------------
man/vgdisplay.8_pregen | 12 --------
4 files changed, 27 insertions(+), 72 deletions(-)
diff --git a/man/lvdisplay.8_pregen b/man/lvdisplay.8_pregen
index a1740ebed..04aab4c09 100644
--- a/man/lvdisplay.8_pregen
+++ b/man/lvdisplay.8_pregen
@@ -61,8 +61,6 @@ and more, using a more compact and configurable output format.
.br
[ \fB--readonly\fP ]
.br
-[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
-.br
[ \fB--segments\fP ]
.br
[ \fB--separator\fP \fIString\fP ]
@@ -332,16 +330,6 @@ device-mapper kernel driver, so this option is unable to report whether
or not LVs are actually in use.
.
.HP
-\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
-.br
-Overrides current output format for reports which is defined globally by
-the report/output_format setting in \fBlvm.conf\fP(5).
-\fBbasic\fP is the original format with columns and rows.
-If there is more than one report per command, each report is prefixed
-with the report name for identification. \fBjson\fP produces report
-output in JSON format. See \fBlvmreport\fP(7) for more information.
-.
-.HP
\fB--segments\fP
.br
.
diff --git a/man/pvdisplay.8_pregen b/man/pvdisplay.8_pregen
index 22a0992b5..2f26a8727 100644
--- a/man/pvdisplay.8_pregen
+++ b/man/pvdisplay.8_pregen
@@ -61,8 +61,6 @@ and more, using a more compact and configurable output format.
.br
[ \fB--readonly\fP ]
.br
-[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
-.br
[ \fB--separator\fP \fIString\fP ]
.br
[ \fB--shared\fP ]
@@ -320,16 +318,6 @@ device-mapper kernel driver, so this option is unable to report whether
or not LVs are actually in use.
.
.HP
-\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
-.br
-Overrides current output format for reports which is defined globally by
-the report/output_format setting in \fBlvm.conf\fP(5).
-\fBbasic\fP is the original format with columns and rows.
-If there is more than one report per command, each report is prefixed
-with the report name for identification. \fBjson\fP produces report
-output in JSON format. See \fBlvmreport\fP(7) for more information.
-.
-.HP
\fB-S\fP|\fB--select\fP \fIString\fP
.br
Select objects for processing and reporting based on specified criteria.
diff --git a/man/pvscan.8_pregen b/man/pvscan.8_pregen
index 9eb6b5bf9..1c96d5aab 100644
--- a/man/pvscan.8_pregen
+++ b/man/pvscan.8_pregen
@@ -91,59 +91,50 @@ like
or
.BR pvdisplay (8).
.P
-When the --cache and -aay options are used, pvscan records which PVs are
-available on the system, and activates LVs in completed VGs. A VG is
-complete when pvscan sees that the final PV in the VG has appeared. This
-is used by event-based system startup (systemd, udev) to activate LVs.
-.P
-The four main variations of this are:
+When --cache is used, pvscan updates runtime lvm state on the system, or
+with -aay performs autoactivation.
.P
.B pvscan --cache
.I device
.P
-If device is present, lvm adds a record that the PV on device is online.
+If device is present, lvm records that the PV on device is online.
If device is not present, lvm removes the online record for the PV.
-In most cases, the pvscan will only read the named devices.
+pvscan only reads the named device.
.P
-.B pvscan --cache -aay
-.IR device ...
+.B pvscan --cache
.P
-This begins by performing the same steps as above. Afterward, if the VG
-for the specified PV is complete, then pvscan will activate LVs in the VG
-(the same as vgchange -aay vgname would do.)
+Updates the runtime state for all lvm devices.
.P
-.B pvscan --cache
+.B pvscan --cache -aay
+.I device
.P
-This first clears all existing PV online records, then scans all devices
-on the system, adding PV online records for any PVs that are found.
+Performs the --cache steps for the device, then checks if the VG using the
+device is complete. If so, LVs in the VG are autoactivated, the same as
+vgchange -aay vgname would do. (A device name may be replaced with major
+and minor numbers.)
.P
.B pvscan --cache -aay
.P
-This begins by performing the same steps as pvscan --cache. Afterward, it
-activates LVs in any complete VGs.
+Performs the --cache steps for all devices, then autoactivates any complete VGs.
.P
-To prevent devices from being scanned by pvscan --cache, add them
-to
-.BR lvm.conf (5)
-.B devices/global_filter.
-For more information, see:
-.br
-.B lvmconfig --withcomments devices/global_filter
+.B pvscan --cache --listvg|--listlvs
+.I device
.P
-Auto-activation of VGs or LVs can be enabled/disabled using:
-.br
+Performs the --cache steps for the device, then prints the name of the VG
+using the device, or the names of LVs using the device. --checkcomplete
+is usually included to check if all PVs for the VG or LVs are online.
+When this command is called by a udev rule, the output must conform to
+udev rule specifications (see --udevoutput.) The udev rule will use the
+results to perform autoactivation.
+.P
+Autoactivation of VGs or LVs can be enabled/disabled using vgchange or
+lvchange with --setautoactivation y|n, or by adding names to
.BR lvm.conf (5)
.B activation/auto_activation_volume_list
.P
-For more information, see:
-.br
-.B lvmconfig --withcomments activation/auto_activation_volume_list
-.P
-To disable auto-activation, explicitly set this list to an empty list,
-i.e. auto_activation_volume_list = [ ].
-.P
-When this setting is undefined (e.g. commented), then all LVs are
-auto-activated.
+See
+.BR lvmautoactivation (7)
+for more information about how pvscan is used for autoactivation.
.
.SH USAGE
.
diff --git a/man/vgdisplay.8_pregen b/man/vgdisplay.8_pregen
index 9c694921d..0a12b3c39 100644
--- a/man/vgdisplay.8_pregen
+++ b/man/vgdisplay.8_pregen
@@ -58,8 +58,6 @@ and more, using a more compact and configurable output format.
.br
[ \fB--readonly\fP ]
.br
-[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
-.br
[ \fB--shared\fP ]
.br
[ \fB--separator\fP \fIString\fP ]
@@ -312,16 +310,6 @@ device-mapper kernel driver, so this option is unable to report whether
or not LVs are actually in use.
.
.HP
-\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
-.br
-Overrides current output format for reports which is defined globally by
-the report/output_format setting in \fBlvm.conf\fP(5).
-\fBbasic\fP is the original format with columns and rows.
-If there is more than one report per command, each report is prefixed
-with the report name for identification. \fBjson\fP produces report
-output in JSON format. See \fBlvmreport\fP(7) for more information.
-.
-.HP
\fB-S\fP|\fB--select\fP \fIString\fP
.br
Select objects for processing and reporting based on specified criteria.
--
2.31.1

View File

@ -1,18 +0,0 @@
lib/device/device_id.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index f158e4f..9cc82f1 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -308,6 +308,10 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
if (!sysbuf[0])
_read_sys_block(cmd, dev, "wwid", sysbuf, sizeof(sysbuf));
+
+ /* scsi_debug wwid begins "t10.Linux scsi_debug ..." */
+ if (strstr(sysbuf, "scsi_debug"))
+ sysbuf[0] = '\0';
}
else if (idtype == DEV_ID_TYPE_SYS_SERIAL)

View File

@ -1,21 +0,0 @@
lib/device/device_id.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index 67f72e5..1b98487 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -325,8 +325,12 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
else if (idtype == DEV_ID_TYPE_MD_UUID)
_read_sys_block(cmd, dev, "md/uuid", sysbuf, sizeof(sysbuf));
- else if (idtype == DEV_ID_TYPE_LOOP_FILE)
+ else if (idtype == DEV_ID_TYPE_LOOP_FILE) {
_read_sys_block(cmd, dev, "loop/backing_file", sysbuf, sizeof(sysbuf));
+ /* if backing file is deleted, fall back to devname */
+ if (strstr(sysbuf, "(deleted)"))
+ sysbuf[0] = '\0';
+ }
else if (idtype == DEV_ID_TYPE_DEVNAME) {
if (!(idname = strdup(dev_name(dev))))

View File

@ -1,25 +0,0 @@
tools/command-lines.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/command-lines.in b/tools/command-lines.in
index 1107c1e..67c37ff 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -534,7 +534,7 @@ RULE: all and lv_is_visible
---
-lvconvert --type thin-pool LV_linear_striped_raid_cache_error_zero
+lvconvert --type thin-pool LV_linear_striped_raid_cache_writecache_error_zero
OO: --stripes_long Number, --stripesize SizeKB,
OO_LVCONVERT_THINPOOL, OO_LVCONVERT_POOL, OO_LVCONVERT
OP: PV ...
@@ -566,7 +566,7 @@ RULE: --poolmetadata not --readahead --stripesize --stripes_long
# This command syntax is deprecated, and the primary forms
# of creating a pool or swapping metadata should be used.
-lvconvert --thinpool LV_linear_striped_raid_cache_thinpool
+lvconvert --thinpool LV_linear_striped_raid_cache_writecache_thinpool
OO: --stripes_long Number, --stripesize SizeKB,
OO_LVCONVERT_THINPOOL, OO_LVCONVERT_POOL, OO_LVCONVERT
OP: PV ...

View File

@ -1,16 +0,0 @@
tools/lvconvert.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 8dd8a15..6066d1f 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -4803,7 +4803,7 @@ static int _lvconvert_to_pool_or_swap_metadata_single(struct cmd_context *cmd,
switch (cmd->command->command_enum) {
case lvconvert_to_thinpool_or_swap_metadata_CMD:
- if (lv_is_cache(lv))
+ if (lv_is_cache(lv) || lv_is_writecache(lv))
/* For cached LV check the cache origin LV type */
lvt_enum = get_lvt_enum(seg_lv(first_seg(lv), 0));
to_thinpool = 1;

View File

@ -1,17 +0,0 @@
lib/metadata/vdo_manip.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/metadata/vdo_manip.c b/lib/metadata/vdo_manip.c
index 7d5a2cb..afc513a 100644
--- a/lib/metadata/vdo_manip.c
+++ b/lib/metadata/vdo_manip.c
@@ -393,7 +393,8 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
} else {
log_verbose("Skiping VDO formating %s.", display_lvname(data_lv));
/* TODO: parse existing VDO data and retrieve vdo_logical_size */
- vdo_logical_size = data_lv->size;
+ if (!*virtual_extents)
+ vdo_logical_size = data_lv->size;
}
if (!deactivate_lv(data_lv->vg->cmd, data_lv)) {

View File

@ -1,211 +0,0 @@
lib/device/device_id.c | 32 ++++++++++++++----------
man/lvmdevices.8_des | 68 +++++++++++++++++++++++++++++++++++++++-----------
tools/args.h | 5 ++++
tools/command-lines.in | 1 +
tools/lvmdevices.c | 7 ++++--
5 files changed, 84 insertions(+), 29 deletions(-)
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index 1b98487..f158e4f 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -931,6 +931,7 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
/*
* Choose the device_id type for the device being added.
*
+ * 0. use an idtype specified by the user
* 1. use an idtype specific to a special/virtual device type
* e.g. loop, mpath, crypt, lvmlv, md, etc.
* 2. use an idtype specified by user option.
@@ -939,6 +940,24 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
* 5. use devname as the last resort.
*/
+ if (idtype_arg) {
+ if (!(idtype = idtype_from_str(idtype_arg)))
+ log_warn("WARNING: ignoring unknown device_id type %s.", idtype_arg);
+ else {
+ if (id_arg) {
+ if ((idname = strdup(id_arg)))
+ goto id_done;
+ log_warn("WARNING: ignoring device_id name %s.", id_arg);
+ }
+
+ if ((idname = device_id_system_read(cmd, dev, idtype)))
+ goto id_done;
+
+ log_warn("WARNING: ignoring deviceidtype %s which is not available for device.", idtype_arg);
+ idtype = 0;
+ }
+ }
+
if (MAJOR(dev->dev) == cmd->dev_types->device_mapper_major) {
if (_dev_has_mpath_uuid(cmd, dev, &idname)) {
idtype = DEV_ID_TYPE_MPATH_UUID;
@@ -972,19 +991,6 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
log_warn("Missing support for DRBD idtype");
}
- if (idtype_arg) {
- if (!(idtype = idtype_from_str(idtype_arg)))
- log_warn("WARNING: ignoring unknown device_id type %s.", idtype_arg);
- else {
- if (id_arg) {
- if (!(idname = strdup(id_arg)))
- stack;
- goto id_done;
- }
- goto id_name;
- }
- }
-
/*
* No device-specific, existing, or user-specified idtypes,
* so use first available of sys_wwid / sys_serial / devname.
diff --git a/man/lvmdevices.8_des b/man/lvmdevices.8_des
index 015aa11..2335456 100644
--- a/man/lvmdevices.8_des
+++ b/man/lvmdevices.8_des
@@ -9,18 +9,18 @@ remove it from the devices file with lvmdevices --deldev. The
vgimportdevices(8) command adds all PVs from a VG to the devices file,
and updates the VG metadata to include device IDs of the PVs.
.P
-Commands adding new devices to the devices file necessarily look outside
-the existing devices file to find the devices to add. pvcreate, vgcreate,
-and vgextend also look outside the devices file to create new PVs and add
-them to the devices file.
+Commands that add new devices to the devices file necessarily look outside
+the existing devices file to find the devices being added. pvcreate,
+vgcreate, and vgextend also look outside the devices file to create new
+PVs and add those PVs to the devices file.
.P
LVM records devices in the devices file using hardware-specific IDs, such
as the WWID, and attempts to use subsystem-specific IDs for virtual device
-types (which also aim to be as unique and stable as possible.)
-These device IDs are also written in the VG metadata. When no hardware or
+types (which also aim to be as unique and stable as possible.) These
+device IDs are also written in the VG metadata. When no hardware or
virtual ID is available, lvm falls back using the unstable device name as
-the device ID. When devnames are used, lvm performs extra scanning to
-find devices if their devname changes, e.g. after reboot.
+the device ID. When devnames are used as IDs, lvm performs extra scanning
+to find devices if their devname changes, e.g. after reboot.
.P
When proper device IDs are used, an lvm command will not look at devices
outside the devices file, but when devnames are used as a fallback, lvm
@@ -34,12 +34,13 @@ overriding the devices file. The listed devices act as a sort of devices
file in terms of limiting which devices lvm will see and use. Devices
that are not listed will appear to be missing to the lvm command.
.P
-Multiple devices files can be kept in \fI#DEFAULT_SYS_DIR#/devices\fP, which allows lvm
-to be used with different sets of devices, e.g. system devices do not need
-to be exposed to a specific application, and the application can use lvm on
-its own devices that are not exposed to the system. The option
---devicesfile <filename> is used to select the devices file to use with the
-command. Without the option set, the default system devices file is used.
+Multiple devices files can be kept \fI#DEFAULT_SYS_DIR#/devices\fP, which
+allows lvm to be used with different sets of devices. For example, system
+devices do not need to be exposed to a specific application, and the
+application can use lvm on its own devices that are not exposed to the
+system. The option --devicesfile <filename> is used to select the devices
+file to use with the command. Without the option set, the default system
+devices file is used.
.P
Setting --devicesfile "" causes lvm to not use a devices file.
.P
@@ -59,3 +60,42 @@ if it does not yet exist.
.P
It is recommended to use lvm commands to make changes to the devices file to
ensure proper updates.
+.P
+The device ID and device ID type are included in the VG metadata and can
+be reported with pvs -o deviceid,deviceidtype. (Note that the lvmdevices
+command does not update VG metadata, but subsequent lvm commands modifying
+the metadata will include the device ID.)
+.P
+Possible device ID types are:
+.br
+.IP \[bu] 2
+.B sys_wwid
+uses the wwid reported by sysfs. This is the first choice for non-virtual
+devices.
+.IP \[bu] 2
+.B sys_serial
+uses the serial number reported by sysfs. This is the second choice for
+non-virtual devices.
+.IP \[bu] 2
+.B mpath_uuid
+is used for dm multipath devices, reported by sysfs.
+.IP \[bu] 2
+.B crypt_uuid
+is used for dm crypt devices, reported by sysfs.
+.IP \[bu] 2
+.B md_uuid
+is used for md devices, reported by sysfs.
+.B lvmlv_uuid
+is used if a PV is placed on top of an lvm LV, reported by sysfs.
+.IP \[bu] 2
+.B loop_file
+is used for loop devices, the backing file name repored by sysfs.
+.IP \[bu] 2
+.B devname
+the device name is used if no other type applies.
+.P
+
+The default choice for device ID type can be overriden using lvmdevices
+--addev --deviceidtype <type>. If the specified type is available for the
+device it will be used, otherwise the device will be added using the type
+that would otherwise be chosen.
diff --git a/tools/args.h b/tools/args.h
index 741c82b..d4f23f8 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -228,6 +228,11 @@ arg(detachprofile_ARG, '\0', "detachprofile", 0, 0, 0,
"Detaches a metadata profile from a VG or LV.\n"
"See \\fBlvm.conf\\fP(5) for more information about profiles.\n")
+arg(deviceidtype_ARG, '\0', "deviceidtype", string_VAL, 0, 0,
+ "The type of device ID to use for the device.\n"
+ "If the specified type is available for the device,\n"
+ "then it will override the default type that lvm would use.\n")
+
arg(devices_ARG, '\0', "devices", pv_VAL, ARG_GROUPABLE, 0,
"Devices that the command can use. This option can be repeated\n"
"or accepts a comma separated list of devices. This overrides\n"
diff --git a/tools/command-lines.in b/tools/command-lines.in
index 67c37ff..8607305 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1430,6 +1430,7 @@ ID: lvmdevices_update
DESC: Update the devices file to fix incorrect values.
lvmdevices --adddev PV
+OO: --deviceidtype String
ID: lvmdevices_edit
DESC: Add a device to the devices file.
diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c
index 6b3e056..3448bdd 100644
--- a/tools/lvmdevices.c
+++ b/tools/lvmdevices.c
@@ -265,6 +265,7 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
if (arg_is_set(cmd, adddev_ARG)) {
const char *devname;
+ const char *deviceidtype;
if (!(devname = arg_str_value(cmd, adddev_ARG, NULL)))
goto_bad;
@@ -311,8 +312,10 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
dev_name(dev), dev_filtered_reason(dev));
}
- /* allow deviceidtype_ARG/deviceid_ARG ? */
- if (!device_id_add(cmd, dev, dev->pvid, NULL, NULL))
+ /* also allow deviceid_ARG ? */
+ deviceidtype = arg_str_value(cmd, deviceidtype_ARG, NULL);
+
+ if (!device_id_add(cmd, dev, dev->pvid, deviceidtype, NULL))
goto_bad;
if (!device_ids_write(cmd))
goto_bad;

View File

@ -1,150 +0,0 @@
lib/metadata/lv_manip.c | 19 +++++++++
lib/metadata/metadata-exported.h | 2 +
lib/metadata/thin_manip.c | 12 ++++++
test/shell/lvremove-thindata-caches.sh | 71 ++++++++++++++++++++++++++++++++++
4 files changed, 104 insertions(+)
create mode 100644 test/shell/lvremove-thindata-caches.sh
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 508f78c..37dd361 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -6692,6 +6692,25 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
return_0;
}
+ /* if thin pool data lv is writecache, then detach and remove the writecache */
+ if (lv_is_thin_pool(lv)) {
+ struct logical_volume *data_lv = data_lv_from_thin_pool(lv);
+
+ if (data_lv && lv_is_writecache(data_lv)) {
+ struct logical_volume *cachevol_lv = first_seg(data_lv)->writecache;
+
+ if (!lv_detach_writecache_cachevol(data_lv, 1)) {
+ log_error("Failed to detach writecache from %s", display_lvname(data_lv));
+ return 0;
+ }
+
+ if (!lv_remove_single(cmd, cachevol_lv, force, 1)) {
+ log_error("Failed to remove cachevol %s.", display_lvname(cachevol_lv));
+ return 0;
+ }
+ }
+ }
+
if (lv_is_writecache(lv)) {
struct logical_volume *cachevol_lv = first_seg(lv)->writecache;
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index c611635..54bc0d0 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -927,6 +927,8 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
int vg_set_pool_metadata_spare(struct logical_volume *lv);
int vg_remove_pool_metadata_spare(struct volume_group *vg);
+struct logical_volume *data_lv_from_thin_pool(struct logical_volume *pool_lv);
+
int attach_thin_external_origin(struct lv_segment *seg,
struct logical_volume *external_lv);
int detach_thin_external_origin(struct lv_segment *seg);
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 451c382..6ce88bd 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -21,6 +21,18 @@
#include "lib/config/defaults.h"
#include "lib/display/display.h"
+struct logical_volume *data_lv_from_thin_pool(struct logical_volume *pool_lv)
+{
+ struct lv_segment *seg_thinpool = first_seg(pool_lv);
+
+ if (!seg_thinpool || !seg_is_thin_pool(seg_thinpool)) {
+ log_error(INTERNAL_ERROR "data_lv_from_thin_pool arg not thin pool %s", pool_lv->name);
+ return NULL;
+ }
+
+ return seg_thinpool->areas[0].u.lv.lv;
+}
+
/* TODO: drop unused no_update */
int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type,
struct logical_volume *lv, uint32_t delete_id,
diff --git a/test/shell/lvremove-thindata-caches.sh b/test/shell/lvremove-thindata-caches.sh
new file mode 100644
index 0000000..ba099c3
--- /dev/null
+++ b/test/shell/lvremove-thindata-caches.sh
@@ -0,0 +1,71 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2017-2020 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux have_cache 1 10 0 || skip
+aux have_writecache 1 0 0 || skip
+which mkfs.xfs || skip
+
+aux prepare_devs 6 70 # want 64M of usable space from each dev
+
+vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6"
+
+# lv1 is thinpool LV: 128M
+# lv2 is fast LV: 64M
+# lv3 is thin LV: 1G
+
+#
+# Test lvremove of a thinpool that uses cache|writecache on data
+#
+
+# attach writecache to thinpool data
+lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2"
+lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg
+lvcreate -n $lv2 -L64M -an $vg "$dev3"
+lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1
+lvchange -ay $vg/$lv1
+lvs -a $vg
+mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3"
+lvremove -y $vg/$lv1
+
+# attach cache/writeback (cachevol) to thinpool data
+lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2"
+lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg
+lvcreate -n $lv2 -L64M -an $vg "$dev3"
+lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1
+lvchange -ay $vg/$lv1
+mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3"
+lvremove -y $vg/$lv1
+
+# attach cache/writethrough (cachevol) to thinpool data
+lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2"
+lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg
+lvcreate -n $lv2 -L64M -an $vg "$dev3"
+lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1
+lvchange -ay $vg/$lv1
+mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3"
+lvremove -y $vg/$lv1
+
+# attach cache (cachepool) to thinpool data
+lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2"
+lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg
+lvcreate -y --type cache-pool -n $lv2 -L64M --poolmetadataspare n $vg "$dev3" "$dev6"
+lvconvert -y --type cache --cachepool $lv2 --poolmetadataspare n $vg/$lv1
+lvchange -ay $vg/$lv1
+mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3"
+lvremove -y $vg/$lv1
+
+vgremove -f $vg
+

View File

@ -1,102 +0,0 @@
man/vdoimport.8_main | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
create mode 100644 man/vdoimport.8_main
diff --git a/man/vdoimport.8_main b/man/vdoimport.8_main
new file mode 100644
index 0000000..1f32909
--- /dev/null
+++ b/man/vdoimport.8_main
@@ -0,0 +1,92 @@
+.TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
+.
+.SH "NAME"
+.
+vdoimport \(em utility to import VDO volumes into a new volume group.
+.
+.SH SYNOPSIS
+.
+.PD 0
+.ad l
+.TP 10
+.B vdoimport
+.RI [ options ]
+.IR device
+.
+.PD
+.
+.SH DESCRIPTION
+.
+vdoimport utility imports VDO volumes created and managed by
+.BR vdo (8)
+manager into
+.BR lvm2 (8)
+managed VDO LV. This is realized by moving VDO superblock by 2MiB
+and creating lvm2 metadata at the front of this device. The operation is not reversible,
+thus after conversion to lvm2 the access to VDO data is only possible with
+.BR lvm2 (8)
+commands,
+.BR vdo (8)
+manager no longer control such volume.
+.
+.SH OPTIONS
+.
+.TP
+.BR -f | --force
+Bypass some sanity checks.
+.
+.TP
+.BR -h | --help
+Display the help text.
+.
+.TP
+.BR -n | --name
+Specifies the name of converted VDO LV. When the name is not specified,
+some automatic name is selected. In case the converted VDO volume is
+already using LV a backend device, the name of this LV is used for VDO LV.
+In this case also the of volume group must stay same.
+.
+.TP
+.BR -v | --verbose
+Be more verbose.
+.
+.TP
+.BR -y | --yes
+Answer "yes" at any prompts.
+.
+.TP
+.BR --dry-run
+Print commands without running them.
+.
+.
+.SH DIAGNOSTICS
+.
+On successful completion, the status code is 0.
+A status code of 1 is used for failure.
+.
+.SH EXAMPLES
+.
+Convert VDO volume created by vdo manager into logical volume LV1 with within volume group VG1.
+.P
+#
+.B vdoimport --name VG1/LV1 /dev/mapper/vdo-volume
+.
+.SH ENVIRONMENT VARIABLES
+.
+.TP
+.B TMPDIR
+The temporary directory name for mount points. Defaults to "\fI/tmp\fP".
+.TP
+.B DM_DEV_DIR
+The device directory name.
+Defaults to "\fI/dev\fP" and must be an absolute path.
+.
+.SH SEE ALSO
+.
+.nh
+.ad l
+.BR lvm (8),
+.BR lvm.conf (5),
+.P
+.BR vdo (8),
+.BR vdo2lvm (8),

View File

@ -1,61 +0,0 @@
test/shell/vgsplit-cache.sh | 47 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/test/shell/vgsplit-cache.sh b/test/shell/vgsplit-cache.sh
index eba85be..202e4b5 100644
--- a/test/shell/vgsplit-cache.sh
+++ b/test/shell/vgsplit-cache.sh
@@ -75,6 +75,53 @@ lvremove -y $vg
vgremove -ff $vg
vgremove -ff $vg1
+#
+# Check we handle pmspare for splitted VGs
+#
+aux prepare_vg 7
+
+# Create cache-pool and pmspare on single PV1
+lvcreate -L10 --type cache-pool $vg/cpool "$dev1"
+# Move spare to separate PV3
+pvmove -n $vg/lvol0_pmspare "$dev1" "$dev3"
+# Create origin on PV2
+lvcreate -L10 -n orig $vg "$dev2"
+lvconvert -H -y --cachepool $vg/cpool $vg/orig
+
+vgchange -an $vg
+
+# Check we do not create new _pmspare
+vgsplit --poolmetadataspare n $vg $vg1 "$dev2" "$dev1"
+
+check lv_exists $vg/lvol0_pmspare
+check lv_not_exists $vg1/lvol0_pmspare
+
+vgremove $vg
+vgremove -f $vg1
+
+
+aux prepare_vg 7
+
+# Again - now with handling _pmspare by vgsplit
+lvcreate -L10 --type cache-pool $vg/cpool "$dev1"
+# Move spare to separate PV3
+pvmove -n $vg/lvol0_pmspare "$dev1" "$dev3"
+# Create origin on PV2
+lvcreate -L10 -n orig $vg "$dev2"
+lvconvert -H -y --cachepool $vg/cpool $vg/orig
+
+vgchange -an $vg
+
+# Handle _pmspare (default)
+vgsplit --poolmetadataspare y $vg $vg1 "$dev2" "$dev1"
+
+check lv_not_exists $vg/lvol0_pmspare
+check lv_exists $vg1/lvol0_pmspare
+
+vgremove $vg
+vgremove -f $vg1
+
+
vgcreate $vg "$dev1" "$dev2" "$dev3" "$dev4"
lvcreate -L6 -n $lv1 -an $vg "$dev2"

View File

@ -1,53 +0,0 @@
test/shell/vgmerge-operation.sh | 42 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/test/shell/vgmerge-operation.sh b/test/shell/vgmerge-operation.sh
index 21889e9..0bf517d 100644
--- a/test/shell/vgmerge-operation.sh
+++ b/test/shell/vgmerge-operation.sh
@@ -80,3 +80,45 @@ grep "Duplicate logical volume name \"$lv1\" in \"$vg2\" and \"$vg1" err
check pvlv_counts $vg1 2 1 0
check pvlv_counts $vg2 2 1 0
vgremove -f $vg1 $vg2
+
+
+# 'vgmerge' handle pmspare for merged VG
+if aux have_thin 1 5 0; then
+
+# With disabled pmspare nothing is created
+vgcreate $vg1 "$dev1" "$dev2"
+vgcreate $vg2 "$dev3" "$dev4"
+lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M --poolmetadataspare n
+lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M --poolmetadataspare n
+vgchange -an $vg1 $vg2
+
+vgmerge --poolmetadataspare n $vg1 $vg2
+check lv_not_exists $vg/lvol0_pmspare
+vgremove -ff $vg1
+
+
+# With pmspare handling there are one created
+vgcreate $vg1 "$dev1" "$dev2"
+vgcreate $vg2 "$dev3" "$dev4"
+lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M --poolmetadataspare n
+lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M --poolmetadataspare n
+vgchange -an $vg1 $vg2
+
+vgmerge $vg1 $vg2
+check lv_field $vg1/lvol0_pmspare size "8.00m"
+vgremove -ff $vg1
+
+
+# When merged, bigger pmspare is preserved
+vgcreate $vg1 "$dev1" "$dev2"
+vgcreate $vg2 "$dev3" "$dev4"
+lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M
+lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M
+vgchange -an $vg1 $vg2
+
+vgmerge $vg1 $vg2
+
+check lv_field $vg1/lvol0_pmspare size "8.00m"
+vgremove -ff $vg1
+
+fi

View File

@ -1,63 +0,0 @@
WHATS_NEW | 1 +
lib/activate/activate.c | 5 ++++-
test/shell/lvconvert-cache-thin.sh | 22 ++++++++++++++++++++++
3 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 5806ecb..097160e 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.03.13 -
===============================
+ Fix detection of active components of external origin volume.
Add vdoimport tool to support conversion of VDO volumes.
Support configurable allocation/vdo_pool_header_size.
Fix handling of lvconvert --type vdo-pool --virtualsize.
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 6bda738..94fc944 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -2740,7 +2740,10 @@ static int _component_cb(struct logical_volume *lv, void *data)
(lv_is_thin_pool(lv) && pool_is_active(lv)))
return -1;
- if (lv_is_active(lv)) {
+ /* External origin is activated through thinLV and uses -real suffix.
+ * Note: for old clustered logic we would need to check for all thins */
+ if ((lv_is_external_origin(lv) && lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0)) ||
+ lv_is_active(lv)) {
if (!lv_is_component(lv) || lv_is_visible(lv))
return -1; /* skip whole subtree */
diff --git a/test/shell/lvconvert-cache-thin.sh b/test/shell/lvconvert-cache-thin.sh
index 7dda6e6..9254239 100644
--- a/test/shell/lvconvert-cache-thin.sh
+++ b/test/shell/lvconvert-cache-thin.sh
@@ -67,4 +67,26 @@ fail lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv
# Thin-pool CAN use cached data LV
lvconvert --yes --thinpool $vg/$lv
+lvremove -f $vg
+
+# Check we can active snapshot of cached external origin (BZ: 1967744)
+lvcreate -T -L10M $vg/pool "$dev1"
+
+lvcreate -L10M -n origin $vg "$dev1"
+lvcreate -H -L4M -n CPOOL $vg/origin "$dev2"
+
+# Use cached origin as external origin
+lvconvert -y -T --thinpool $vg/pool --originname extorig origin
+
+# Check we can easily create snapshot of such LV
+lvcreate -y -kn -n snap -s $vg/origin
+
+# Deactivate everything and do a component activation of _cmeta volume
+lvchange -an $vg
+lvchange -ay -y $vg/CPOOL_cpool_cmeta
+
+# Now this must fail since component volume is active
+not lvcreate -y -kn -n snap2 -s $vg/origin |& tee err
+grep "cmeta is active" err
+
vgremove -f $vg

View File

@ -1,729 +0,0 @@
WHATS_NEW | 3 +
configure | 25 +++
configure.ac | 15 ++
include/configure.h.in | 3 +
man/Makefile.in | 7 +-
scripts/Makefile.in | 4 +
scripts/vdoimport.sh | 376 ++++++++++++++++++++++++++++++++++++++++++++++
test/Makefile.in | 1 +
test/shell/vdo-convert.sh | 110 ++++++++++++++
9 files changed, 543 insertions(+), 1 deletion(-)
create mode 100755 scripts/vdoimport.sh
create mode 100644 test/shell/vdo-convert.sh
diff --git a/WHATS_NEW b/WHATS_NEW
index 04c6dcd..5806ecb 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,8 @@
Version 2.03.13 -
===============================
+ Add vdoimport tool to support conversion of VDO volumes.
+ Support configurable allocation/vdo_pool_header_size.
+ Fix handling of lvconvert --type vdo-pool --virtualsize.
Fix load of kvdo target when it is not present in memory (2.03.12).
Version 2.03.12 - 07th May 2021
diff --git a/configure b/configure
index 7c6bd48..661702d 100755
--- a/configure
+++ b/configure
@@ -643,6 +643,8 @@ WRITE_INSTALL
WRITECACHE
VDO_LIB
VDO_INCLUDE
+VDOIMPORT_PATH
+VDOIMPORT
VDO
VALGRIND_POOL
USRSBINDIR
@@ -966,6 +968,7 @@ enable_dbus_service
enable_pkgconfig
enable_write_install
enable_fsadm
+enable_vdoimport
enable_blkdeactivate
enable_dmeventd
enable_selinux
@@ -1701,6 +1704,7 @@ Optional Features:
--enable-pkgconfig install pkgconfig support
--enable-write_install install user writable files
--disable-fsadm disable fsadm
+ --disable-vdoimport disable vdoimport
--disable-blkdeactivate disable blkdeactivate
--enable-dmeventd enable the device-mapper event daemon
--disable-selinux disable selinux support
@@ -3128,6 +3132,7 @@ case "$host_os" in
DM_IOCTLS=yes
SELINUX=yes
FSADM=yes
+ VDOIMPORT=yes
BLKDEACTIVATE=yes
;;
darwin*)
@@ -3141,6 +3146,7 @@ case "$host_os" in
DM_IOCTLS=no
SELINUX=no
FSADM=no
+ VDOIMPORT=no
BLKDEACTIVATE=no
;;
*)
@@ -12371,6 +12377,18 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $FSADM" >&5
$as_echo "$FSADM" >&6; }
+
+################################################################################
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install vdoimport" >&5
+$as_echo_n "checking whether to install vdoimport... " >&6; }
+# Check whether --enable-vdoimport was given.
+if test "${enable_vdoimport+set}" = set; then :
+ enableval=$enable_vdoimport; VDOIMPORT=$enableval
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $VDOIMPORT" >&5
+$as_echo "$VDOIMPORT" >&6; }
+
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install blkdeactivate" >&5
$as_echo_n "checking whether to install blkdeactivate... " >&6; }
@@ -13857,6 +13875,13 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+VDOIMPORT_PATH="$SBINDIR/vdoimport"
+
+cat >>confdefs.h <<_ACEOF
+#define VDOIMPORT_PATH "$VDOIMPORT_PATH"
+_ACEOF
+
+
################################################################################
if test "$BUILD_DMEVENTD" = yes; then
diff --git a/configure.ac b/configure.ac
index 1a49e7f..5a8b486 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,6 +45,7 @@ case "$host_os" in
DM_IOCTLS=yes
SELINUX=yes
FSADM=yes
+ VDOIMPORT=yes
BLKDEACTIVATE=yes
;;
darwin*)
@@ -58,6 +59,7 @@ case "$host_os" in
DM_IOCTLS=no
SELINUX=no
FSADM=no
+ VDOIMPORT=no
BLKDEACTIVATE=no
;;
*)
@@ -1291,6 +1293,14 @@ AC_ARG_ENABLE(fsadm, AC_HELP_STRING([--disable-fsadm], [disable fsadm]),
FSADM=$enableval)
AC_MSG_RESULT($FSADM)
+
+################################################################################
+dnl -- Enable vdoimport
+AC_MSG_CHECKING(whether to install vdoimport)
+AC_ARG_ENABLE(vdoimport, AC_HELP_STRING([--disable-vdoimport], [disable vdoimport]),
+ VDOIMPORT=$enableval)
+AC_MSG_RESULT($VDOIMPORT)
+
################################################################################
dnl -- Enable blkdeactivate
AC_MSG_CHECKING(whether to install blkdeactivate)
@@ -1646,6 +1656,9 @@ USRSBINDIR="$(eval echo $(eval echo $usrsbindir))"
FSADM_PATH="$SBINDIR/fsadm"
AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
+VDOIMPORT_PATH="$SBINDIR/vdoimport"
+AC_DEFINE_UNQUOTED(VDOIMPORT_PATH, ["$VDOIMPORT_PATH"], [Path to vdoimport binary.])
+
################################################################################
dnl -- dmeventd pidfile and executable path
if test "$BUILD_DMEVENTD" = yes; then
@@ -1882,6 +1895,8 @@ AC_SUBST(SILENT_RULES)
AC_SUBST(USRSBINDIR)
AC_SUBST(VALGRIND_POOL)
AC_SUBST(VDO)
+AC_SUBST(VDOIMPORT)
+AC_SUBST(VDOIMPORT_PATH)
AC_SUBST(VDO_FORMAT_CMD)
AC_SUBST(VDO_INCLUDE)
AC_SUBST(VDO_LIB)
diff --git a/include/configure.h.in b/include/configure.h.in
index 671d201..6df8d89 100644
--- a/include/configure.h.in
+++ b/include/configure.h.in
@@ -684,6 +684,9 @@
/* Enable a valgrind aware build of pool */
#undef VALGRIND_POOL
+/* Path to vdoimport binary. */
+#undef VDOIMPORT_PATH
+
/* The path to 'vdoformat', if available. */
#undef VDO_FORMAT_CMD
diff --git a/man/Makefile.in b/man/Makefile.in
index 29afc77..d60a92c 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -23,6 +23,7 @@ else
endif
FSADMMAN = fsadm.8
+VDOIMPORTMAN = vdoimport.8
BLKDEACTIVATEMAN = blkdeactivate.8
DMEVENTDMAN = dmeventd.8
DMFILEMAPDMAN = dmfilemapd.8
@@ -50,7 +51,7 @@ MAN8SYSTEMD_GENERATORS=lvm2-activation-generator.8
ifeq (,$(findstring $(MAKECMDGOALS), distclean all_man install_all_man))
MAN7 += lvmcache.7 lvmthin.7 lvmvdo.7
- MAN8+=$(FSADMMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN)
+ MAN8+=$(FSADMMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN) $(VDOIMPORTMAN)
MAN8DM+=$(BLKDEACTIVATEMAN) $(DMEVENTDMAN) $(DMFILEMAPDMAN)
MAN8CLUSTER+=$(CMIRRORDMAN)
else
@@ -58,6 +59,10 @@ else
MAN8+=$(FSADMMAN)
endif
+ ifeq ("@VDOIMPORT@", "yes")
+ MAN8+=$(VDOIMPORTMAN)
+ endif
+
ifeq ("@BUILD_LVMDBUSD@", "yes")
MAN8+=$(LVMDBUSDMAN)
endif
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index e8f6742..1fe88ca 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -31,6 +31,10 @@ ifeq ("@FSADM@", "yes")
LVM_SCRIPTS += fsadm.sh
endif
+ifeq ("@VDOIMPORT@", "yes")
+ LVM_SCRIPTS += vdoimport.sh
+endif
+
ifeq ("@BLKDEACTIVATE@", "yes")
DM_SCRIPTS += blkdeactivate.sh
endif
diff --git a/scripts/vdoimport.sh b/scripts/vdoimport.sh
new file mode 100755
index 0000000..ef96591
--- /dev/null
+++ b/scripts/vdoimport.sh
@@ -0,0 +1,376 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Author: Zdenek Kabelac <zkabelac at redhat.com>
+#
+# Script for converting VDO volumes to lvm2 VDO LVs
+#
+# Needed utilities:
+# lvm, dmsetup,
+# vdo, vdo2lvm,
+# grep, awk, sed, blockdev, readlink, mkdir
+#
+# Conversion is using 'vdo convert' support from VDO manager to move
+# existing VDO header by 2M which makes space to place in PV header
+# and VG metadata area, and then create VDOPOOL LV and VDO LV in such VG.
+#
+
+set -euE -o pipefail
+
+TOOL=vdoimport
+
+_SAVEPATH=$PATH
+PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH"
+
+# user may override lvm location by setting LVM_BINARY
+LVM=${LVM_BINARY:-lvm}
+VDO=${VDO_BINARY:-vdo}
+VDOCONF=${VDOCONF:-}
+BLOCKDEV="blockdev"
+READLINK="readlink"
+READLINK_E="-e"
+MKDIR="mkdir"
+
+TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$"
+DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
+
+DRY=0
+VERB=""
+FORCE=""
+YES=""
+
+# default name for converted VG and its VDO LV
+NAME="vdovg/vdolvol"
+
+# help message
+tool_usage() {
+ echo "${TOOL}: Utility to convert VDO volume to VDO LV."
+ echo
+ echo " ${TOOL} [options] <vdo_device_path>"
+ echo
+ echo " Options:"
+ echo " -f | --force Bypass sanity checks"
+ echo " -h | --help Show this help message"
+ echo " -n | --name Specifies VG/LV name for converted VDO volume"
+ echo " -v | --verbose Be verbose"
+ echo " -y | --yes Answer \"yes\" at any prompts"
+ echo " --dry-run Print commands without running them"
+
+ exit
+}
+
+verbose() {
+ test -z "$VERB" || echo "$TOOL:" "$@"
+}
+
+# Support multi-line error messages
+error() {
+ for i in "$@" ; do
+ echo "$TOOL: $i" >&2
+ done
+ cleanup 1
+}
+
+dry() {
+ if [ "$DRY" -ne 0 ]; then
+ verbose "Dry execution" "$@"
+ return 0
+ fi
+ verbose "Executing" "$@"
+ "$@"
+}
+
+cleanup() {
+ trap '' 2
+
+ rm -rf "$TEMPDIR"
+ # error exit status for break
+ exit "${1:-1}"
+}
+
+get_enabled_value_() {
+ case "$1" in
+ enabled) echo "1" ;;
+ *) echo "0" ;;
+ esac
+}
+
+get_kb_size_with_unit_() {
+ case "$1" in
+ *[kK]) echo $(( ${1%[kK]} )) ;;
+ *[mM]) echo $(( ${1%[mM]} * 1024 )) ;;
+ *[gG]) echo $(( ${1%[gG]} * 1024 * 1024 )) ;;
+ *[tT]) echo $(( ${1%[tT]} * 1024 * 1024 * 1024 )) ;;
+ *[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 * 1024 )) ;;
+ esac
+}
+
+get_mb_size_with_unit_() {
+ case "$1" in
+ *[mM]) echo $(( ${1%[mM]} )) ;;
+ *[gG]) echo $(( ${1%[gG]} * 1024 )) ;;
+ *[tT]) echo $(( ${1%[tT]} * 1024 * 1024 )) ;;
+ *[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 )) ;;
+ esac
+}
+
+# Figure out largest possible extent size usable for VG
+# $1 physical size
+# $2 logical size
+get_largest_extent_size_() {
+ local max=4
+ local i
+ local d
+
+ for i in 8 16 32 64 128 256 512 1024 2048 4096 ; do
+ d=$(( $1 / i ))
+ test $(( d * i )) -eq "$1" || break
+ d=$(( $2 / i ))
+ test $(( d * i )) -eq "$2" || break
+ max=$i
+ done
+ echo "$max"
+}
+
+# detect LV on the given device
+# dereference device name if it is symbolic link
+detect_lv_() {
+ local DEVICE=$1
+ local MAJOR
+ local MINOR
+ local SYSVOLUME
+ local MAJORMINOR
+
+ DEVICE=${1/#"${DM_DEV_DIR}/"/}
+ DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE")
+ test -n "$DEVICE" || error "Cannot get readlink \"$1\"."
+ RDEVICE=$DEVICE
+ case "$RDEVICE" in
+ # hardcoded /dev since udev does not create these entries elsewhere
+ /dev/dm-[0-9]*)
+ read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME"
+ read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"."
+ MAJOR=${MAJORMINOR%%:*}
+ MINOR=${MAJORMINOR##*:}
+ ;;
+ *)
+ STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE")
+ test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"."
+ eval "$STAT"
+ ;;
+ esac
+
+ eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
+}
+
+# parse yaml config files into 'prefix_yaml_part_names=("value")' strings
+parse_yaml_() {
+ local yaml_file=$1
+ local prefix=$2
+ local s
+ local w
+ local fs
+
+ s='[[:space:]]*'
+ w='[a-zA-Z0-9_.-]*'
+ fs="$(echo @|tr @ '\034')"
+
+ (
+ sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/[[:space:]]*$//g;' \
+ -e 's/\$/\\\$/g' \
+ -e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \
+ -e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
+ -e "s|^\($s\)\($w\)${s}[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" |
+
+ awk -F"$fs" '{
+ indent = length($1)/2;
+ if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";}
+ vname[indent] = $2;
+ for (i in vname) {if (i > indent) {delete vname[i]}}
+ if (length($3) > 0) {
+ vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
+ printf("%s%s%s%s=(\"%s\")\n", "'"$prefix"'",vn, $2, conj[indent-1], $3);
+ }
+ }' |
+
+ sed -e 's/_=/+=/g' |
+
+ awk 'BEGIN {
+ FS="=";
+ OFS="="
+ }
+ /(-|\.).*=/ {
+ gsub("-|\\.", "_", $1)
+ }
+ { print }'
+ ) < "$yaml_file"
+}
+
+# convert existing VDO volume into lvm2 volume
+convert2lvm_() {
+ local DEVICE=$1
+ local VGNAME=${NAME%/*}
+ local LVNAME=${NAME#*/}
+ local VDONAME
+ local TRVDONAME
+ local EXTENTSZ
+ local IS_LV=1
+
+ DM_UUID=""
+ detect_lv_ "$DEVICE"
+ case "$DM_UUID" in
+ LVM-*) eval "$(dmsetup splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
+ if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then
+ VGNAME=$DM_VG_NAME
+ elif test "$VGNAME" != "$DM_VG_NAME" ; then
+ error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"."
+ fi
+ ;;
+ *) IS_LV=0
+ # Check $VGNANE does not already exists
+ "$LVM" vgs "$VGNAME" && error "Cannot use already existing volume group name \"$VGNAME\"."
+ ;;
+ esac
+
+ verbose "Checked whether device $1 is already LV ($IS_LV)."
+
+ "$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR."
+
+ verbose "Getting YAML VDO configuration."
+ "$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml"
+
+ VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
+ TRVDONAME=$(echo "$VDONAME" | tr '-' '_')
+
+ # When VDO volume is 'active', check it's not mounted/being used
+ eval "$(dmsetup info -c -o open "$VDONAME" --noheadings --nameprefixes || true)"
+ test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
+
+ #parse_yaml_ "$TEMPDIR/vdoconf.yml" _
+ eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")"
+
+ vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize")
+ vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize")
+
+ verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB."
+ verbose "With logical volume of size $vdo_logicalSize KiB."
+
+ PARAMS=$(cat <<EOF
+allocation {
+ vdo_use_compression = $(get_enabled_value_ "$vdo_compression")
+ 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_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_ack_threads = $vdo_ackThreads
+ vdo_bio_threads = $vdo_bioThreads
+ vdo_bio_rotation = $vdo_bioRotationInterval
+ vdo_cpu_threads = $vdo_cpuThreads
+ vdo_hash_zone_threads = $vdo_hashZoneThreads
+ vdo_logical_threads = $vdo_logicalThreads
+ vdo_physical_threads = $vdo_physicalThreads
+ vdo_write_policy = $vdo_writePolicy
+ vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") * 1024 ))
+ vdo_pool_header_size = 0
+}
+EOF
+)
+ verbose "VDO conversion paramaters: $PARAMS"
+
+ verbose "Stopping VDO volume."
+ dry "$VDO" stop $VDOCONF --name "$VDONAME"
+
+ if [ "$IS_LV" = "0" ]; then
+ verbose "Moving VDO header by 2MiB."
+ dry "$VDO" convert $VDOCONF --force --name "$VDONAME"
+
+ dry "$LVM" pvcreate $YES --dataalignment 2M "$DEVICE" || {
+ error "Creation of PV on \"$DEVICE\" failed, while VDO header has been already moved!"
+ }
+
+ # Obtain free space in this new PV
+ # after 'vdo convert/vdo2lvm' call there is +2M free space at the front of the device
+ case "$DRY" in
+ 0) pvfree=$("$LVM" pvs -o devsize --units b --nosuffix --noheadings "$DEVICE") ;;
+ *) pvfree=$("$BLOCKDEV" --getsize64 "$DEVICE") ;;
+ esac
+
+ pvfree=$(( pvfree / 1024 - 2048 )) # to KiB
+ else
+ pvfree=$("$LVM" lvs -o size --units b --nosuffix --noheadings "$VGNAME/$LVNAME")
+ pvfree=$(( pvfree / 1024 )) # to KiB
+ fi
+
+ # select largest possible extent size that can exactly express both sizes
+ EXTENTSZ=$(get_largest_extent_size_ "$pvfree" "$vdo_logicalSize")
+
+ if [ "$IS_LV" = "0" ]; then
+ verbose "Creating VG \"${NAME%/*}\" with extent size $EXTENTSZ KiB."
+ dry "$LVM" vgcreate $YES $VERB -s "${EXTENTSZ}k" "$VGNAME" "$DEVICE" || {
+ error "Creation of VG \"$VGNAME\" failed, while VDO header has been already moved!"
+ }
+
+ verbose "Creating VDO pool data LV from all extents in volume group $VGNAME."
+ dry "$LVM" lvcreate -Zn -Wn $YES $VERB -l100%VG -n "${LVNAME}_vpool" "$VGNAME"
+ else
+ # validate existing VG extent_size can express virtual VDO size
+ vg_extent_size=$("$LVM" vgs -o vg_extent_size --units b --nosuffix --noheadings "$VGNAME" || true)
+ vg_extent_size=$(( vg_extent_size / 1024 ))
+
+ test "$vg_extent_size" -le "$EXTENTSZ" || {
+ error "Please vgchange extent_size to at most $EXTENTSZ KiB or extend and align virtual size on $vg_extent_size KiB."
+ }
+ verbose "Renaming existing LV to be used as _vdata volume for VDO pool LV."
+ dry "$LVM" lvrename $YES $VERB "$VGNAME/$LVNAME" "$VGNAME/${LVNAME}_vpool" || {
+ error "Rename of LV \"$VGNAME/$LVNAME\" failed, while VDO header has been already moved!"
+ }
+ fi
+
+ verbose "Converting to VDO pool."
+ dry "$LVM" lvconvert $YES $VERB $FORCE --config "$PARAMS" -Zn -V "${vdo_logicalSize}k" -n "$LVNAME" --type vdo-pool "$VGNAME/${LVNAME}_vpool"
+
+ rm -fr "$TEMPDIR"
+}
+
+#############################
+# start point of this script
+# - parsing parameters
+#############################
+trap "cleanup 2" 2
+
+test "$#" -eq 0 && tool_usage
+
+while [ "$#" -ne 0 ]
+do
+ case "$1" in
+ "") ;;
+ "-f"|"--force" ) FORCE="-f" ;;
+ "-h"|"--help" ) tool_usage ;;
+ "-n"|"--name" ) shift; NAME=$1 ;;
+ "-v"|"--verbose") VERB="-v" ;;
+ "-y"|"--yes" ) YES="-y" ;;
+ "--dry-run" ) DRY="1" ;;
+ "-*") error "Wrong argument \"$1\". (see: $TOOL --help)" ;;
+ *) DEVICENAME=$1 ;; # device name does not start with '-'
+ esac
+ shift
+done
+
+# do conversion
+convert2lvm_ "$DEVICENAME"
diff --git a/test/Makefile.in b/test/Makefile.in
index e4cd3aa..6be03aa 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -353,6 +353,7 @@ LIB = $(addprefix lib/, $(LIB_SECURETEST) $(LIB_DMSECURETEST) $(LIB_SHARED) $(LI
$(Q) $(LN_S) -f $(abs_top_srcdir)/conf/lvmdbusd.profile lib/
$(Q) $(LN_S) -f $(abs_top_srcdir)/conf/thin-performance.profile lib/
$(Q) $(LN_S) -f $(abs_top_srcdir)/scripts/fsadm.sh lib/fsadm
+ $(Q) $(LN_S) -f $(abs_top_srcdir)/scripts/vdoimport.sh lib/vdoimport
@test "$(srcdir)" = . || \
for i in $(LIB_LVMLOCKD_CONF) $(LIB_MKE2FS_CONF); do \
test -n "$(Q)" || echo "$(LN_S) -f $(abs_top_srcdir)/test/lib/$$i lib/"; \
diff --git a/test/shell/vdo-convert.sh b/test/shell/vdo-convert.sh
new file mode 100644
index 0000000..538147b
--- /dev/null
+++ b/test/shell/vdo-convert.sh
@@ -0,0 +1,110 @@
+#!/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 conversion of VDO volumes made by vdo manager into VDO LV.
+
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+# Use local for this test vdo configuratoin
+VDOCONF="-f vdotestconf.yml"
+#VDOCONF=""
+export VDOCONF
+VDONAME="${PREFIX}-TESTVDO"
+
+# VDO automatically starts dmeventd
+aux prepare_dmeventd
+
+#
+# Main
+#
+which vdo || skip
+which mkfs.ext4 || skip
+export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf"
+
+aux have_vdo 6 2 0 || skip
+
+aux prepare_devs 2 10000
+
+aux extend_filter_LVMTEST
+
+
+#
+# Check conversion of VDO volume made on some LV
+#
+# In this case we do not need to move any VDO headers.
+#
+vgcreate $vg "$dev1"
+
+lvcreate -L5G -n $lv1 $vg
+
+vdo create $VDOCONF --name "$VDONAME" --device="$DM_DEV_DIR/$vg/$lv1" --vdoLogicalSize=10G
+
+mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
+
+# Different VG name fails
+not vdoimport -y -v --name $vg1/$lv1 "$DM_DEV_DIR/$vg/$lv1"
+
+# Try just dry run and observe logging
+vdoimport --dry-run -y -v --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
+
+vdoimport -y --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
+
+# ATM needed - since we do not call 'vdo convert' in this case
+vdo remove $VDOCONF --force --name "$VDONAME" || true
+
+vgremove -f $vg
+
+aux wipefs_a "$dev1"
+
+# prepare 'unused' $vg2
+vgcreate $vg2 "$dev2"
+
+#
+# Check conversion of VDO volume on non-LV device
+#
+vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=31G
+
+mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
+
+# Fail with an already existing volume group $vg2
+not vdoimport --dry-run -y -v --name $vg2/$lv1 "$dev1" |& tee err
+grep "already existing volume group" err
+
+# User can also convert already stopped VDO volume
+vdo stop $VDOCONF --name "$VDONAME"
+
+vdoimport -y -v --name $vg/$lv1 "$dev1"
+
+fsck -n "$DM_DEV_DIR/$vg/$lv1"
+
+vgremove -f $vg
+
+
+#
+# Try once again with different vgname/lvname and sizes
+#
+aux teardown_devs
+aux prepare_devs 1 23456
+
+vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=23G
+
+mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
+
+vdoimport -y -v --name $vg1/$lv2 "$dev1"
+
+fsck -n "$DM_DEV_DIR/$vg1/$lv2"
+
+vgremove -f $vg1
+

View File

@ -1,37 +0,0 @@
WHATS_NEW | 4 ++++
lib/activate/activate.c | 10 +++-------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 6f339a5..04c6dcd 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,3 +1,7 @@
+Version 2.03.13 -
+===============================
+ Fix load of kvdo target when it is not present in memory (2.03.12).
+
Version 2.03.12 - 07th May 2021
===============================
Allow attaching cache to thin data volume.
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 71db981..6bda738 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -574,13 +574,9 @@ int module_present(struct cmd_context *cmd, const char *target_name)
}
#ifdef MODPROBE_CMD
- if (strcmp(target_name, MODULE_NAME_VDO) == 0) {
- argv[1] = target_name; /* ATM kvdo is without dm- prefix */
- if ((ret = exec_cmd(cmd, argv, NULL, 0)))
- return ret;
- }
-
- if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
+ if (strcmp(target_name, TARGET_NAME_VDO) == 0)
+ argv[1] = MODULE_NAME_VDO; /* ATM kvdo is without dm- prefix */
+ else if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
log_error("module_present module name too long: %s",
target_name);
return 0;

View File

@ -1,50 +0,0 @@
tools/lvconvert.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 6066d1f..8488596 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -5438,7 +5438,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
struct processing_handle *handle)
{
const char *vg_name = NULL;
- unsigned int zero_vdopool;
+ unsigned int vdo_pool_zero;
struct volume_group *vg = lv->vg;
struct logical_volume *vdo_lv;
struct dm_vdo_target_params vdo_params; /* vdo */
@@ -5497,12 +5497,12 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
goto out;
}
- zero_vdopool = arg_int_value(cmd, zero_ARG, 1);
+ vdo_pool_zero = arg_int_value(cmd, zero_ARG, 1);
log_warn("WARNING: Converting logical volume %s to VDO pool volume %s formating.",
- display_lvname(lv), zero_vdopool ? "with" : "WITHOUT");
+ display_lvname(lv), vdo_pool_zero ? "with" : "WITHOUT");
- if (zero_vdopool)
+ if (vdo_pool_zero)
log_warn("THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.)");
else
log_warn("WARNING: Using invalid VDO pool data MAY DESTROY YOUR DATA!");
@@ -5514,7 +5514,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
goto out;
}
- if (zero_vdopool) {
+ if (vdo_pool_zero) {
if (!wipe_lv(lv, (struct wipe_params) { .do_zero = 1, .do_wipe_signatures = 1,
.yes = arg_count(cmd, yes_ARG),
.force = arg_count(cmd, force_ARG)})) {
@@ -5526,7 +5526,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
if (!archive(vg))
goto_out;
- if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents, zero_vdopool))
+ if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents, vdo_pool_zero))
goto_out;
dm_list_init(&lvc.tags);

View File

@ -1,197 +0,0 @@
conf/example.conf.in | 5 +++++
lib/config/config_settings.h | 3 +++
lib/config/defaults.h | 3 +--
lib/metadata/lv_manip.c | 3 ++-
lib/metadata/metadata-exported.h | 5 ++++-
lib/metadata/vdo_manip.c | 13 ++++++++-----
tools/lvconvert.c | 6 ++++--
tools/lvcreate.c | 2 +-
8 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index aaf73a4..78547a6 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -734,6 +734,11 @@ allocation {
# The default and minimum is 1. The maximum is UINT_MAX / 4096.
# This configuration option has an automatic default value.
# vdo_max_discard = 1
+
+ # Configuration option allocation/vdo_pool_header_size.
+ # Specified the emptry header size in KiB at the front and end of vdo pool device.
+ # This configuration option has an automatic default value.
+ # vdo_pool_header_size = 512
}
# Configuration section log.
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index f5dac4d..5217da8 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -816,6 +816,9 @@ cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, C
"increased latency for the individual discard requests.\n"
"The default and minimum is 1. The maximum is UINT_MAX / 4096.\n")
+cfg(allocation_vdo_pool_header_size_CFG, "vdo_pool_header_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_HEADER_SIZE_KB, vsn(2, 3, 12), NULL, 0, NULL,
+ "Specified the emptry header size in KiB at the front and end of vdo pool device.\n")
+
cfg(log_report_command_log_CFG, "report_command_log", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_BOOL, DEFAULT_COMMAND_LOG_REPORT, vsn(2, 2, 158), NULL, 0, NULL,
"Enable or disable LVM log reporting.\n"
"If enabled, LVM will collect a log of operations, messages,\n"
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 2870dee..d5e5b3b 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -181,8 +181,7 @@
* VDO pool will reverve some sectors in the front and the back of pool device to avoid
* seeing same device twice in the system.
*/
-#define DEFAULT_VDO_POOL_HEADER_SIZE (1024) // 512KiB
-
+#define DEFAULT_VDO_POOL_HEADER_SIZE_KB (512)
#define DEFAULT_FSADM_PATH FSADM_PATH
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 37dd361..43af474 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -8766,7 +8766,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
}
if (seg_is_vdo_pool(lp)) {
- if (!convert_vdo_pool_lv(lv, &lp->vdo_params, &lp->virtual_extents, 1)) {
+ if (!convert_vdo_pool_lv(lv, &lp->vdo_params, &lp->virtual_extents,
+ 1, lp->vdo_pool_header_size)) {
stack;
goto deactivate_and_revert_new_lv;
}
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 54bc0d0..adbbe76 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1033,6 +1033,7 @@ struct lvcreate_params {
int approx_alloc; /* all */
alloc_policy_t alloc; /* all */
struct dm_vdo_target_params vdo_params; /* vdo */
+ uint64_t vdo_pool_header_size; /* VDO */
int raidintegrity;
const char *raidintegritymode;
@@ -1367,10 +1368,12 @@ int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_
struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
const struct dm_vdo_target_params *vtp,
uint32_t *virtual_extents,
- int format);
+ int format,
+ uint64_t vdo_pool_header_size);
int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy);
int fill_vdo_target_params(struct cmd_context *cmd,
struct dm_vdo_target_params *vtp,
+ uint64_t *vdo_pool_header_size,
struct profile *profile);
/* -- metadata/vdo_manip.c */
diff --git a/lib/metadata/vdo_manip.c b/lib/metadata/vdo_manip.c
index afc513a..3f2de1a 100644
--- a/lib/metadata/vdo_manip.c
+++ b/lib/metadata/vdo_manip.c
@@ -356,9 +356,9 @@ static int _format_vdo_pool_data_lv(struct logical_volume *data_lv,
struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
const struct dm_vdo_target_params *vtp,
uint32_t *virtual_extents,
- int format)
+ int format,
+ uint64_t vdo_pool_header_size)
{
- const uint64_t header_size = DEFAULT_VDO_POOL_HEADER_SIZE;
const uint32_t extent_size = data_lv->vg->extent_size;
struct cmd_context *cmd = data_lv->vg->cmd;
struct logical_volume *vdo_pool_lv = data_lv;
@@ -379,7 +379,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
if (*virtual_extents)
vdo_logical_size =
- _get_virtual_size(*virtual_extents, extent_size, header_size);
+ _get_virtual_size(*virtual_extents, extent_size, vdo_pool_header_size);
if (!dm_vdo_validate_target_params(vtp, vdo_logical_size))
return_0;
@@ -403,7 +403,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
return NULL;
}
- vdo_logical_size -= 2 * header_size;
+ vdo_logical_size -= 2 * vdo_pool_header_size;
if (vdo_logical_size < extent_size) {
if (!*virtual_extents)
@@ -426,7 +426,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
vdo_pool_seg = first_seg(vdo_pool_lv);
vdo_pool_seg->segtype = vdo_pool_segtype;
vdo_pool_seg->vdo_params = *vtp;
- vdo_pool_seg->vdo_pool_header_size = DEFAULT_VDO_POOL_HEADER_SIZE;
+ vdo_pool_seg->vdo_pool_header_size = vdo_pool_header_size;
vdo_pool_seg->vdo_pool_virtual_extents = *virtual_extents;
vdo_pool_lv->status |= LV_VDO_POOL;
@@ -453,6 +453,7 @@ int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy)
int fill_vdo_target_params(struct cmd_context *cmd,
struct dm_vdo_target_params *vtp,
+ uint64_t *vdo_pool_header_size,
struct profile *profile)
{
const char *policy;
@@ -501,5 +502,7 @@ int fill_vdo_target_params(struct cmd_context *cmd,
if (!set_vdo_write_policy(&vtp->write_policy, policy))
return_0;
+ *vdo_pool_header_size = 2 * find_config_tree_int64(cmd, allocation_vdo_pool_header_size_CFG, profile);
+
return 1;
}
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 8488596..f87ee78 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -5439,6 +5439,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
{
const char *vg_name = NULL;
unsigned int vdo_pool_zero;
+ uint64_t vdo_pool_header_size;
struct volume_group *vg = lv->vg;
struct logical_volume *vdo_lv;
struct dm_vdo_target_params vdo_params; /* vdo */
@@ -5481,7 +5482,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
goto out;
}
- if (!fill_vdo_target_params(cmd, &vdo_params, vg->profile))
+ if (!fill_vdo_target_params(cmd, &vdo_params, &vdo_pool_header_size, vg->profile))
goto_out;
if (arg_is_set(cmd, compression_ARG))
@@ -5526,7 +5527,8 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
if (!archive(vg))
goto_out;
- if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents, vdo_pool_zero))
+ if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents,
+ vdo_pool_zero, vdo_pool_header_size))
goto_out;
dm_list_init(&lvc.tags);
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index a28f093..0def236 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -1097,7 +1097,7 @@ static int _lvcreate_params(struct cmd_context *cmd,
// FIXME: prefiling here - this is wrong place
// but will work for this moment
- if (!fill_vdo_target_params(cmd, &lp->vdo_params, NULL))
+ if (!fill_vdo_target_params(cmd, &lp->vdo_params, &lp->vdo_pool_header_size, NULL))
return_0;
if (arg_is_set(cmd, compression_ARG))

View File

@ -1,28 +0,0 @@
tools/vgmerge.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tools/vgmerge.c b/tools/vgmerge.c
index 895018a..884ad4b 100644
--- a/tools/vgmerge.c
+++ b/tools/vgmerge.c
@@ -92,6 +92,20 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
}
}
+ if (vg_from->pool_metadata_spare_lv &&
+ vg_to->pool_metadata_spare_lv) {
+ if (vg_from->pool_metadata_spare_lv->le_count >
+ vg_to->pool_metadata_spare_lv->le_count)
+ /* Preserve bigger pmspare from VG_FROM */
+ lv = vg_to->pool_metadata_spare_lv;
+ else
+ lv = vg_from->pool_metadata_spare_lv;
+
+ log_debug_metadata("Removing pool metadata spare %s.", display_lvname(lv));
+ if (!lv_remove_single(cmd, lv, DONT_PROMPT, 0))
+ return_ECMD_FAILED;
+ }
+
if (!vgs_are_compatible(cmd, vg_from, vg_to))
goto_bad;

View File

@ -1,82 +0,0 @@
WHATS_NEW | 2 +-
man/vgmerge.8_pregen | 9 +++++++++
tools/command-lines.in | 2 +-
tools/vgmerge.c | 6 ++++++
4 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 0b8e3f2..5556789 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,6 +1,6 @@
Version 2.03.13 -
===============================
- Support --poolmetadataspare with vgsplit.
+ Support --poolmetadataspare with vgsplit and vgmerge.
Fix detection of active components of external origin volume.
Add vdoimport tool to support conversion of VDO volumes.
Support configurable allocation/vdo_pool_header_size.
diff --git a/man/vgmerge.8_pregen b/man/vgmerge.8_pregen
index 1264bb5..e229218 100644
--- a/man/vgmerge.8_pregen
+++ b/man/vgmerge.8_pregen
@@ -27,6 +27,8 @@ of both VGs fit into the destination VG's limits.
.br
[ \fB-l\fP|\fB--list\fP ]
.br
+[ \fB--poolmetadataspare\fP \fBy\fP|\fBn\fP ]
+.br
[ COMMON_OPTIONS ]
.ad b
.RE
@@ -147,6 +149,13 @@ Display long help text.
Disable locking.
.
.HP
+\fB--poolmetadataspare\fP \fBy\fP|\fBn\fP
+.br
+Enable or disable the automatic creation and management of a
+spare pool metadata LV in the VG. A spare metadata LV is reserved
+space that can be used when repairing a pool.
+.
+.HP
\fB--profile\fP \fIString\fP
.br
An alias for --commandprofile or --metadataprofile, depending
diff --git a/tools/command-lines.in b/tools/command-lines.in
index a4785b3..0bc5a49 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1847,7 +1847,7 @@ DESC: Add devices from all accessible VGs to the devices file.
---
vgmerge VG VG
-OO: --autobackup Bool, --list
+OO: --autobackup Bool, --list, --poolmetadataspare Bool
ID: vgmerge_general
---
diff --git a/tools/vgmerge.c b/tools/vgmerge.c
index 884ad4b..08615cd 100644
--- a/tools/vgmerge.c
+++ b/tools/vgmerge.c
@@ -64,6 +64,8 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
struct lv_list *lvl1, *lvl2;
int r = ECMD_FAILED;
int lock_vg_from_first = 0;
+ struct logical_volume *lv;
+ int poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG, DEFAULT_POOL_METADATA_SPARE);
if (!strcmp(vg_name_to, vg_name_from)) {
log_error("Duplicate volume group name \"%s\"", vg_name_from);
@@ -185,6 +187,10 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
/* Flag up that some PVs have moved from another VG */
vg_to->old_name = vg_from->name;
+ /* Check whether size of pmspare is big enough now for merged VG */
+ if (!handle_pool_metadata_spare(vg_to, 0, &vg_to->pvs, poolmetadataspare))
+ goto_bad;
+
/* store it on disks */
log_verbose("Writing out updated volume group");
if (!vg_write(vg_to) || !vg_commit(vg_to))

View File

@ -1,18 +0,0 @@
tools/vgremove.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/vgremove.c b/tools/vgremove.c
index 8f73297..b6685ae 100644
--- a/tools/vgremove.c
+++ b/tools/vgremove.c
@@ -65,6 +65,10 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
}
}
+ if (vg->pool_metadata_spare_lv &&
+ !lvremove_single(cmd, vg->pool_metadata_spare_lv, &void_handle))
+ return_ECMD_FAILED;
+
if (!lockd_free_vg_before(cmd, vg, 0))
return_ECMD_FAILED;

View File

@ -1,106 +0,0 @@
WHATS_NEW | 1 +
lib/metadata/pool_manip.c | 11 +++++++++++
man/vgsplit.8_pregen | 9 +++++++++
tools/command-lines.in | 2 +-
tools/vgsplit.c | 8 ++++++++
5 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 097160e..0b8e3f2 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.03.13 -
===============================
+ Support --poolmetadataspare with vgsplit.
Fix detection of active components of external origin volume.
Add vdoimport tool to support conversion of VDO volumes.
Support configurable allocation/vdo_pool_header_size.
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index 9ceec3a..e451e92 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -722,6 +722,17 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
return 1;
}
+ if (!extents) {
+ /* pmspare is not needed */
+ if (lv) {
+ log_debug_metadata("Dropping unused pool metadata spare LV %s.",
+ display_lvname(lv));
+ if (!lv_remove_single(vg->cmd, lv, DONT_PROMPT, 0))
+ return_0;
+ }
+ return 1;
+ }
+
if (extents > MAX_SIZE)
extents = MAX_SIZE;
diff --git a/man/vgsplit.8_pregen b/man/vgsplit.8_pregen
index 331c6e4..8a0ae59 100644
--- a/man/vgsplit.8_pregen
+++ b/man/vgsplit.8_pregen
@@ -70,6 +70,8 @@ Common options for command:
.hy
]
.br
+[ \fB--poolmetadataspare\fP \fBy\fP|\fBn\fP ]
+.br
[ \fB--\fP[\fBvg\fP]\fBmetadatacopies\fP \fBall\fP|\fBunmanaged\fP|\fINumber\fP ]
.ad b
.RE
@@ -235,6 +237,13 @@ Move only PVs used by the named LV.
Disable locking.
.
.HP
+\fB--poolmetadataspare\fP \fBy\fP|\fBn\fP
+.br
+Enable or disable the automatic creation and management of a
+spare pool metadata LV in the VG. A spare metadata LV is reserved
+space that can be used when repairing a pool.
+.
+.HP
\fB--profile\fP \fIString\fP
.br
An alias for --commandprofile or --metadataprofile, depending
diff --git a/tools/command-lines.in b/tools/command-lines.in
index 8607305..a4785b3 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1912,7 +1912,7 @@ ID: vgscan_general
---
-OO_VGSPLIT: --autobackup Bool
+OO_VGSPLIT: --autobackup Bool, --poolmetadataspare Bool
# used only when the destination VG is new
OO_VGSPLIT_NEW: --alloc Alloc,
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
index 296248e..a085ac2 100644
--- a/tools/vgsplit.c
+++ b/tools/vgsplit.c
@@ -525,6 +525,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
int existing_vg = 0;
int r = ECMD_FAILED;
const char *lv_name;
+ int poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG, DEFAULT_POOL_METADATA_SPARE);
if ((arg_is_set(cmd, name_ARG) + argc) < 3) {
log_error("Existing VG, new VG and either physical volumes "
@@ -699,6 +700,13 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
*/
vg_to->status |= EXPORTED_VG;
+
+ if (!handle_pool_metadata_spare(vg_to, 0, &vg_to->pvs, poolmetadataspare))
+ goto_bad;
+
+ if (!handle_pool_metadata_spare(vg_from, 0, &vg_from->pvs, poolmetadataspare))
+ goto_bad;
+
if (!archive(vg_to))
goto_bad;

View File

@ -1,23 +0,0 @@
tools/pvmove.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/tools/pvmove.c b/tools/pvmove.c
index da635a6..bb372f7 100644
--- a/tools/pvmove.c
+++ b/tools/pvmove.c
@@ -387,6 +387,15 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
return NULL;
}
+ if (lv_is_writecache(lv)) {
+ struct logical_volume *lv_cachevol = first_seg(lv)->writecache;
+ if (lv_is_on_pvs(lv_cachevol, source_pvl)) {
+ log_error("Unable to move device used for writecache cachevol %s.", display_lvname(lv_cachevol));
+ return NULL;
+ }
+
+ }
+
if (lv_is_raid(lv) && lv_raid_has_integrity(lv)) {
log_error("Unable to pvmove device used for raid with integrity.");
return NULL;

View File

@ -1,17 +0,0 @@
lib/metadata/metadata.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 002d80c..1f65045 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -4402,6 +4402,9 @@ int lv_on_pmem(struct logical_volume *lv)
dm_list_iterate_items(seg, &lv->segments) {
for (s = 0; s < seg->area_count; s++) {
+ if (seg_type(seg, s) != AREA_PV)
+ continue;
+
pv = seg_pv(seg, s);
if (dev_is_pmem(lv->vg->cmd->dev_types, pv->dev)) {

View File

@ -1,35 +0,0 @@
From 317bc732073134159bc74e126339f8e498bdb376 Mon Sep 17 00:00:00 2001
From: Yi Wang <wang.yi59@zte.com.cn>
Date: Fri, 13 Aug 2021 13:49:13 +0800
Subject: [PATCH] lvchange: fix lvchange refresh failed for dm suspend or
resume failed
When multiple lvchange refresh processes executed at the same time,
suspend/resume ioctl on the same dm, some of these commands will be failed
for dm aready change status, and ioctl will return EINVAL in _do_dm_ioctl function.
to avoid this problem, add READ_FOR_ACTIVATE flags in lvchange refresh process,
it will hold LCK_WRITE lock and avoid suspend/resume dm at the same time.
Signed-off-by: Long YunJian <long.yunjian@zte.com.cn>
Signed-off-by: Yi Wang <wang.yi59@zte.com.cn>
(cherry picked from commit 47bcb446b83f9aa4fca74301fda109a8bf670fbb)
---
tools/lvchange.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 8293f5035..fb9ac895f 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -1620,7 +1620,7 @@ int lvchange_refresh_cmd(struct cmd_context *cmd, int argc, char **argv)
cmd->handles_missing_pvs = 1;
cmd->lockd_vg_default_sh = 1;
- return process_each_lv(cmd, argc, argv, NULL, NULL, 0,
+ return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_ACTIVATE,
NULL, &_lvchange_refresh_check, &_lvchange_refresh_single);
}
--
2.34.1

View File

@ -1,25 +0,0 @@
From 155d8c55086b09528de799425e77f7aeafd9b165 Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Thu, 9 Sep 2021 15:22:20 +0200
Subject: [PATCH 2/5] tests: check lvm2 parses vdo statistics
(cherry picked from commit bd2dae464386033241afa35934cdeddfe47f6a77)
---
test/shell/lvcreate-vdo.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/test/shell/lvcreate-vdo.sh b/test/shell/lvcreate-vdo.sh
index d66e353..5b370fb 100644
--- a/test/shell/lvcreate-vdo.sh
+++ b/test/shell/lvcreate-vdo.sh
@@ -47,6 +47,7 @@ fi
check lv_field $vg/$lv1 size "<1.24g"
check lv_field $vg/${lv2} size "4.00g"
check lv_field $vg/${lv2}_vdata size "4.00g"
+check lv_field $vg/${lv1} data_percent "0.00"
lvremove -ff $vg
--
1.8.3.1

View File

@ -1,86 +0,0 @@
From deb36d236e2dd86ddc16b33d5ca8c648cc8ed369 Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Wed, 1 Sep 2021 15:46:04 +0200
Subject: [PATCH 3/5] vdo: better message for missing device
Show readable message when passed device cannot be accessed.
And use STAT shell var wrapper to call 'stat' command.
(cherry picked from commit 3287d37f440ca272b52f900fc60ee5effcf73697)
Conflicts:
scripts/lvm_import_vdo.sh
---
scripts/lvm_import_vdo.sh | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
index f8dd71f..dec32bc 100755
--- a/scripts/lvm_import_vdo.sh
+++ b/scripts/lvm_import_vdo.sh
@@ -18,8 +18,8 @@
#
# Needed utilities:
# lvm, dmsetup,
-# vdo, vdo2lvm,
-# grep, awk, sed, blockdev, readlink, mkdir
+# vdo,
+# grep, awk, sed, blockdev, readlink, stat, mkdir
#
# Conversion is using 'vdo convert' support from VDO manager to move
# existing VDO header by 2M which makes space to place in PV header
@@ -40,6 +40,7 @@ VDOCONF=${VDOCONF:-}
BLOCKDEV="blockdev"
READLINK="readlink"
READLINK_E="-e"
+STAT="stat"
MKDIR="mkdir"
DMSETUP="dmsetup"
@@ -156,8 +157,8 @@ detect_lv_() {
local MAJORMINOR
DEVICE=${1/#"${DM_DEV_DIR}/"/}
- DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE")
- test -n "$DEVICE" || error "Cannot get readlink \"$1\"."
+ DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE" || true)
+ test -n "$DEVICE" || error "Readlink cannot access device \"$1\"."
RDEVICE=$DEVICE
case "$RDEVICE" in
# hardcoded /dev since udev does not create these entries elsewhere
@@ -168,9 +169,9 @@ detect_lv_() {
DEVMINOR=${MAJORMINOR##*:}
;;
*)
- STAT=$(stat --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE")
- test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"."
- eval "$STAT"
+ RSTAT=$("$STAT" --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE" || true)
+ test -n "$RSTAT" || error "Cannot get major:minor for \"$DEVICE\"."
+ eval "$RSTAT"
;;
esac
@@ -269,8 +270,8 @@ convert2lvm_() {
for i in $(awk '/.*device:/ {print $2}' "$TEMPDIR/vdoconf.yml") ; do
local DEV
DEV=$("$READLINK" $READLINK_E "$i") || continue
- STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue
- eval "$STAT"
+ RSTAT=$("$STAT" --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue
+ eval "$RSTAT"
test "$MAJOR" = "$DEVMAJOR" && test "$MINOR" = "$DEVMINOR" && {
test -z "$FOUND" || error "VDO configuration contains duplicate entries $FOUND and $i"
FOUND=$i
@@ -287,7 +288,7 @@ convert2lvm_() {
DM_OPEN="$("$DMSETUP" info -c -o open "$VDONAME" --noheadings --nameprefixes 2>/dev/null || true)"
case "$DM_OPEN" in
Device*) ;; # no devices
- *) eval "$DM_OPEN"
+ *) eval "$DM_OPEN"
test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
;;
esac
--
1.8.3.1

View File

@ -1,28 +0,0 @@
From 70467e905cea0811c269faf7e84f24d4e1c758cc Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Mon, 30 Aug 2021 18:12:59 +0200
Subject: [PATCH 5/5] vdo: fix conversion of large virtual sizes
Properly accept virtual sizes above 2TiB.
(cherry picked from commit 4afe872fd6c43fcfcd519c862574d010cdbda653)
---
tools/lvconvert.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index f87ee78..518b48f 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -5462,7 +5462,7 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
return_0;
lvc.virtual_extents = extents_from_size(cmd,
- arg_uint_value(cmd, virtualsize_ARG, 0),
+ arg_uint64_value(cmd, virtualsize_ARG, UINT64_C(0)),
vg->extent_size);
if (!(lvc.segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_VDO)))
--
1.8.3.1

View File

@ -1,256 +0,0 @@
From 5d0756fc33bced8453fb5cf5807c5a3fa2b59dbb Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Tue, 31 Aug 2021 20:52:26 +0200
Subject: [PATCH 1/5] vdo: fixes
Better identify VDO device with major:minor.
Handle different LV name from originally converted origin LV.
Improve --dry-run handling.
(cherry picked from commit 1ae157a0f67e984ef3037d19d62b84a3b0201c84)
---
WHATS_NEW | 4 +++
scripts/lvm_import_vdo.sh | 70 +++++++++++++++++++++++++++++++++++------------
test/shell/vdo-convert.sh | 28 ++++++++++++++-----
3 files changed, 78 insertions(+), 24 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 3637e31..b751009 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,9 @@
Version 2.03.14 -
==================================
+ Improve lvm_import_vdo script.
+ Support VDO LV with lvcreate -ky.
+ Fix lvconvert for VDO LV bigger then 2T.
+ Create VDO LVs automatically without zeroing.
Rename vdoimport to lvm_import_vdo.
Version 2.03.13 -
diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
index 35140a0..bc73306 100755
--- a/scripts/lvm_import_vdo.sh
+++ b/scripts/lvm_import_vdo.sh
@@ -41,10 +41,15 @@ BLOCKDEV="blockdev"
READLINK="readlink"
READLINK_E="-e"
MKDIR="mkdir"
+DMSETUP="dmsetup"
TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$"
DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
+DEVICENAME=""
+DEVMAJOR=0
+DEVMINOR=0
+
DRY=0
VERB=""
FORCE=""
@@ -147,8 +152,6 @@ get_largest_extent_size_() {
# dereference device name if it is symbolic link
detect_lv_() {
local DEVICE=$1
- local MAJOR
- local MINOR
local SYSVOLUME
local MAJORMINOR
@@ -161,17 +164,21 @@ detect_lv_() {
/dev/dm-[0-9]*)
read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME"
read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"."
- MAJOR=${MAJORMINOR%%:*}
- MINOR=${MAJORMINOR##*:}
+ DEVMAJOR=${MAJORMINOR%%:*}
+ DEVMINOR=${MAJORMINOR##*:}
;;
*)
- STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE")
+ STAT=$(stat --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE")
test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"."
eval "$STAT"
;;
esac
- eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
+ DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ' 2>/dev/null)"
+ case "$DEV" in
+ Device*) ;; # no devices
+ *) eval "$DEV" ;;
+ esac
}
# parse yaml config files into 'prefix_yaml_part_names=("value")' strings
@@ -226,20 +233,26 @@ convert2lvm_() {
local TRVDONAME
local EXTENTSZ
local IS_LV=1
+ local FOUND=""
+ local MAJOR=0
+ local MINOR=0
+ local DM_VG_NAME
+ local DM_LV_NAME
DM_UUID=""
detect_lv_ "$DEVICE"
case "$DM_UUID" in
- LVM-*) eval "$(dmsetup splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
+ LVM-*) eval "$("$DMSETUP" splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then
VGNAME=$DM_VG_NAME
+ LVNAME=$DM_LV_NAME
elif test "$VGNAME" != "$DM_VG_NAME" ; then
error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"."
fi
;;
*) IS_LV=0
# Check $VGNANE does not already exists
- "$LVM" vgs "$VGNAME" && error "Cannot use already existing volume group name \"$VGNAME\"."
+ "$LVM" vgs "$VGNAME" >/dev/null 2>&1 && error "Cannot use already existing volume group name \"$VGNAME\"."
;;
esac
@@ -247,15 +260,37 @@ convert2lvm_() {
"$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR."
+ # TODO: might use directly /etc/vdoconf.yml (avoding need of 'vdo' manager)
verbose "Getting YAML VDO configuration."
"$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml"
- VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
+ # Check list of devices in VDO configure file for their major:minor
+ # and match with given $DEVICE devmajor:devminor
+ for i in $(awk '/.*device:/ {print $2}' "$TEMPDIR/vdoconf.yml") ; do
+ local DEV
+ DEV=$("$READLINK" $READLINK_E "$i") || continue
+ STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue
+ eval "$STAT"
+ test "$MAJOR" = "$DEVMAJOR" && test "$MINOR" = "$DEVMINOR" && {
+ test -z "$FOUND" || error "VDO configuration contains duplicate entries $FOUND and $i"
+ FOUND=$i
+ }
+ done
+
+ test -n "$FOUND" || error "Can't find matching device in vdo configuration file."
+ verbose "Found matching device $FOUND $MAJOR:$MINOR"
+
+ VDONAME=$(awk -v DNAME="$FOUND" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
TRVDONAME=$(echo "$VDONAME" | tr '-' '_')
# When VDO volume is 'active', check it's not mounted/being used
- eval "$(dmsetup info -c -o open "$VDONAME" --noheadings --nameprefixes || true)"
- test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
+ DM_OPEN="$("$DMSETUP" info -c -o open "$VDONAME" --noheadings --nameprefixes 2>/dev/null || true)"
+ case "$DM_OPEN" in
+ Device*) ;; # no devices
+ *) eval "$DM_OPEN"
+ test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
+ ;;
+ esac
#parse_yaml_ "$TEMPDIR/vdoconf.yml" _
eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")"
@@ -263,8 +298,7 @@ convert2lvm_() {
vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize")
vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize")
- verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB."
- verbose "With logical volume of size $vdo_logicalSize KiB."
+ verbose "Converted VDO device has logical/physical size $vdo_logicalSize/$vdo_physicalSize KiB."
PARAMS=$(cat <<EOF
allocation {
@@ -313,7 +347,7 @@ EOF
pvfree=$(( pvfree / 1024 - 2048 )) # to KiB
else
- pvfree=$("$LVM" lvs -o size --units b --nosuffix --noheadings "$VGNAME/$LVNAME")
+ pvfree=$("$LVM" lvs -o size --units b --nosuffix --noheadings "$DM_VG_NAME/$DM_LV_NAME")
pvfree=$(( pvfree / 1024 )) # to KiB
fi
@@ -334,11 +368,11 @@ EOF
vg_extent_size=$(( vg_extent_size / 1024 ))
test "$vg_extent_size" -le "$EXTENTSZ" || {
- error "Please vgchange extent_size to at most $EXTENTSZ KiB or extend and align virtual size on $vg_extent_size KiB."
+ error "Please vgchange extent_size to at most $EXTENTSZ KiB or extend and align virtual size of VDO device on $vg_extent_size KiB."
}
verbose "Renaming existing LV to be used as _vdata volume for VDO pool LV."
- dry "$LVM" lvrename $YES $VERB "$VGNAME/$LVNAME" "$VGNAME/${LVNAME}_vpool" || {
- error "Rename of LV \"$VGNAME/$LVNAME\" failed, while VDO header has been already moved!"
+ dry "$LVM" lvrename $YES $VERB "$VGNAME/$DM_LV_NAME" "$VGNAME/${LVNAME}_vpool" || {
+ error "Rename of LV \"$VGNAME/$DM_LV_NAME\" failed, while VDO header has been already moved!"
}
fi
@@ -372,5 +406,7 @@ do
shift
done
+test -n "$DEVICENAME" || error "Device name is not specified. (see: $TOOL --help)"
+
# do conversion
convert2lvm_ "$DEVICENAME"
diff --git a/test/shell/vdo-convert.sh b/test/shell/vdo-convert.sh
index 2d16c97..493f415 100644
--- a/test/shell/vdo-convert.sh
+++ b/test/shell/vdo-convert.sh
@@ -61,22 +61,36 @@ lvm_import_vdo --dry-run -y -v --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
lvm_import_vdo -y --name $lv1 "$DM_DEV_DIR/$vg/$lv1"
-# ATM needed - since we do not call 'vdo convert' in this case
-vdo remove $VDOCONF --force --name "$VDONAME" || true
+# ensure VDO device is not left in config file
+vdo remove $VDOCONF --force --name "$VDONAME" 2>/dev/null || true
+
+lvremove -f $vg
+
+
+# Test user can specify different VDO LV name (so the original LV is renamed)
+lvcreate -y -L5G -n $lv1 $vg
+
+vdo create $VDOCONF --name "$VDONAME" --device="$DM_DEV_DIR/$vg/$lv1" --vdoLogicalSize=10G
+
+lvm_import_vdo -y --name $vg/$lv2 "$DM_DEV_DIR/$vg/$lv1"
+
+check lv_exists $vg $lv2
+check lv_not_exists $vg $lv1
vgremove -f $vg
+# ensure VDO device is not left in config file
+vdo remove $VDOCONF --force --name "$VDONAME" 2>/dev/null || true
+
aux wipefs_a "$dev1"
# prepare 'unused' $vg2
vgcreate $vg2 "$dev2"
#
-# Check conversion of VDO volume on non-LV device
+# Check conversion of VDO volume on non-LV device and with >2T size
#
-vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=31G
-
-mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
+vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=3T
# Fail with an already existing volume group $vg2
not lvm_import_vdo --dry-run -y -v --name $vg2/$lv1 "$dev1" |& tee err
@@ -87,7 +101,7 @@ vdo stop $VDOCONF --name "$VDONAME"
lvm_import_vdo -y -v --name $vg/$lv1 "$dev1"
-fsck -n "$DM_DEV_DIR/$vg/$lv1"
+check lv_field $vg/$lv1 size "3.00t"
vgremove -f $vg
--
1.8.3.1

View File

@ -1,28 +0,0 @@
From 60eb37394b536e3b969496611ff4b59b71123476 Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Mon, 6 Sep 2021 14:57:43 +0200
Subject: [PATCH 2/5] vdo: lvm_import_vdo fix max_discard size
Use correct 4K units in lvm2 for max_discard VDO option.
(cherry picked from commit 8d5b7de54f21ce5e34d533599f9d5a42f2977cd5)
---
scripts/lvm_import_vdo.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
index bc73306..f8dd71f 100755
--- a/scripts/lvm_import_vdo.sh
+++ b/scripts/lvm_import_vdo.sh
@@ -320,7 +320,7 @@ allocation {
vdo_logical_threads = $vdo_logicalThreads
vdo_physical_threads = $vdo_physicalThreads
vdo_write_policy = $vdo_writePolicy
- vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") * 1024 ))
+ vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") / 4 ))
vdo_pool_header_size = 0
}
EOF
--
1.8.3.1

View File

@ -1,29 +0,0 @@
From 4cf3e8bd846a171b4b945f289bf0c6f9c7b5864c Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Thu, 9 Sep 2021 18:10:13 +0200
Subject: [PATCH 3/5] vdo: lvm_import_vdo script needs to continue when vgname
does not exist
When the script cannot find vgname - it needs to continue to run.
(cherry picked from commit 9db4ddabc1cf912dee30e0e6293767f01c976a4a)
---
scripts/lvm_import_vdo.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
index 70904f7..e5b30d8 100755
--- a/scripts/lvm_import_vdo.sh
+++ b/scripts/lvm_import_vdo.sh
@@ -262,7 +262,7 @@ convert2lvm_() {
if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then
VGNAME=${DEFAULT_NAME%/*}
# Find largest matching VG name to our 'default' vgname
- LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~${VGNAME} | grep -E "$VGNAME[0-9]? ?" | head -1)
+ LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~${VGNAME} | grep -E "$VGNAME[0-9]? ?" | head -1 || true)
if test -n "$LASTVGNAME" ; then
LASTVGNAME=${LASTVGNAME#*${VGNAME}}
# If the number is becoming too high, try some random number
--
1.8.3.1

View File

@ -1,27 +0,0 @@
From 073cdd0ba8c39a0330e73773c92d78546d06e687 Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Fri, 10 Sep 2021 01:15:01 +0200
Subject: [PATCH 4/5] vdo: man page updates
(cherry picked from commit 812653d59806439379d80bb8124f6962ae42d46a)
---
man/lvm_import_vdo.8_main | 3 +++
1 file changed, 3 insertions(+)
diff --git a/man/lvm_import_vdo.8_main b/man/lvm_import_vdo.8_main
index ee817a0..c6cb5c3 100644
--- a/man/lvm_import_vdo.8_main
+++ b/man/lvm_import_vdo.8_main
@@ -45,6 +45,9 @@ Specifies the name of converted VDO LV. When the name is not specified,
some automatic name is selected. In case the converted VDO volume is
already using LV a backend device, the name of this LV is used for VDO LV.
In this case also the of volume group must stay same.
+Automatic name may change between releases and currently selects
+"vdolv" as LV name and VG name is selected from sequence
+"vdovg", "vdovg1", ...
.
.TP
.BR -v | --verbose
--
1.8.3.1

View File

@ -1,185 +0,0 @@
From 6621116b61f4c9ee53166a994be2ef7d80a3c346 Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Mon, 6 Sep 2021 15:06:32 +0200
Subject: [PATCH 4/5] vdo: more lvm_import_vdo fixes
Do not call 'dmsetup info' for non-dm devices.
Better handling for VGNAME and LVNAME - so when convering LV as
backend device automatically recognize it and reuse LV name for VDOLV.
Add prompt for final confirmation before actual conversion is started
(once confirmed, lvm2 commands no longer prompts to avoid leaving
conversion in the middle of its process.)
(cherry picked from commit 89595a366554191c3df1a18e1f82b79c450a21ad)
---
scripts/lvm_import_vdo.sh | 48 ++++++++++++++++++++++++++++++++++------
test/shell/vdo-convert.sh | 56 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+), 7 deletions(-)
diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
index dec32bc..70904f7 100755
--- a/scripts/lvm_import_vdo.sh
+++ b/scripts/lvm_import_vdo.sh
@@ -50,6 +50,7 @@ DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
DEVICENAME=""
DEVMAJOR=0
DEVMINOR=0
+PROMPTING=""
DRY=0
VERB=""
@@ -57,7 +58,8 @@ FORCE=""
YES=""
# default name for converted VG and its VDO LV
-NAME="vdovg/vdolvol"
+DEFAULT_NAME="vdovg/vdolvol"
+NAME=""
# help message
tool_usage() {
@@ -100,6 +102,7 @@ dry() {
cleanup() {
trap '' 2
+ test -z "$PROMPTING" || echo "No"
rm -rf "$TEMPDIR"
# error exit status for break
exit "${1:-1}"
@@ -175,7 +178,9 @@ detect_lv_() {
;;
esac
- DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ' 2>/dev/null)"
+ test "$DEVMAJOR" != "$(grep device-mapper /proc/devices | cut -f1 -d' ')" && return
+
+ DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
case "$DEV" in
Device*) ;; # no devices
*) eval "$DEV" ;;
@@ -244,15 +249,31 @@ convert2lvm_() {
detect_lv_ "$DEVICE"
case "$DM_UUID" in
LVM-*) eval "$("$DMSETUP" splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
- if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then
+ if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then
VGNAME=$DM_VG_NAME
- LVNAME=$DM_LV_NAME
+ verbose "Using existing volume group name $VGNAME."
+ test -n "$LVNAME" || LVNAME=$DM_LV_NAME
elif test "$VGNAME" != "$DM_VG_NAME" ; then
- error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"."
+ error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for VDO device \"$DEVICE\"."
fi
;;
- *) IS_LV=0
- # Check $VGNANE does not already exists
+ *) IS_LV=0
+ # Check if we need to generate unused $VGNANE
+ if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then
+ VGNAME=${DEFAULT_NAME%/*}
+ # Find largest matching VG name to our 'default' vgname
+ LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~${VGNAME} | grep -E "$VGNAME[0-9]? ?" | head -1)
+ if test -n "$LASTVGNAME" ; then
+ LASTVGNAME=${LASTVGNAME#*${VGNAME}}
+ # If the number is becoming too high, try some random number
+ test "$LASTVGNAME" -gt 99999999 2>/dev/null && LASTVGNAME=$RANDOM
+ # Generate new unused VG name
+ VGNAME="${VGNAME}$(( ${LASTVGNAME} + 1 ))"
+ verbose "Selected unused volume group name $VGNAME."
+ fi
+ fi
+ # New VG is created, LV name should be always unused.
+ test -n "$LVNAME" || LVNAME=${DEFAULT_NAME#*/}
"$LVM" vgs "$VGNAME" >/dev/null 2>&1 && error "Cannot use already existing volume group name \"$VGNAME\"."
;;
esac
@@ -328,6 +349,19 @@ EOF
)
verbose "VDO conversion paramaters: $PARAMS"
+ # If user has not provided '--yes', prompt before conversion
+ if test -z "$YES" ; then
+ PROMPTING=yes
+ echo -n "Convert VDO device \"$DEVICE\" to VDO LV \"$VGNAME/$LVNAME\"? [y|N]: "
+ read -n 1 -s ANSWER
+ case "${ANSWER:0:1}" in
+ y|Y ) echo "Yes" ;;
+ * ) echo "No" ; PROMPTING=""; exit ;;
+ esac
+ PROMPTING=""
+ YES="-y" # From now, now prompting
+ fi
+
verbose "Stopping VDO volume."
dry "$VDO" stop $VDOCONF --name "$VDONAME"
diff --git a/test/shell/vdo-convert.sh b/test/shell/vdo-convert.sh
index 493f415..632f86a 100644
--- a/test/shell/vdo-convert.sh
+++ b/test/shell/vdo-convert.sh
@@ -122,3 +122,59 @@ fsck -n "$DM_DEV_DIR/$vg1/$lv2"
vgremove -f $vg1
+aux teardown_devs
+
+
+# Check with some real non-DM device from system
+# this needs to dropping DM_DEV_DIR
+
+aux prepare_loop 60000 || skip
+
+test -f LOOP
+LOOP=$(< LOOP)
+
+aux extend_filter "a|$LOOP|"
+aux extend_devices "$LOOP"
+
+#
+# Unfortunatelly generates this in syslog:
+#
+# vdo-start-by-dev@loop0.service: Main process exited, code=exited, status=1/FAILURE
+# vdo-start-by-dev@loop0.service: Failed with result 'exit-code'.
+# Failed to start Start VDO volume backed by loop0.
+#
+# TODO: Could be handled by:
+#
+# systemctl mask vdo-start-by-dev@
+# systemctl unmask vdo-start-by-dev@
+#
+# automate...
+#
+vdo create $VDOCONF --name "$VDONAME" --device="$LOOP" --vdoLogicalSize=23G \
+ --blockMapCacheSize 192 \
+ --blockMapPeriod 2048 \
+ --emulate512 disabled \
+ --indexMem 0.5 \
+ --maxDiscardSize 10 \
+ --sparseIndex disabled \
+ --vdoAckThreads 2 \
+ --vdoBioRotationInterval 8 \
+ --vdoBioThreads 2 \
+ --vdoCpuThreads 5 \
+ --vdoHashZoneThreads 3 \
+ --vdoLogicalThreads 3 \
+ --writePolicy async-unsafe
+
+# Get VDO table line
+dmsetup table "$VDONAME" | tr " " "\n" | sed -e '5,6d' -e '12d' | tee vdo-orig
+
+DM_DEV_DIR= lvm_import_vdo -y --name $vg/$lv "$LOOP"
+lvs -a $vg
+
+dmsetup table "$vg-${lv}_vpool-vpool" | tr " " "\n" | sed -e '5,6d' -e '12d' | tee new-vdo-lv
+
+# Check there is a match between VDO and LV managed volume
+# (when differentiating parameters are deleted first)
+diff -u vdo-orig new-vdo-lv || die "Found mismatching VDO table lines!"
+
+check lv_field $vg/$lv size "23.00g"
--
1.8.3.1

View File

@ -1,28 +0,0 @@
From f3f99d45b89d415528e21a66f94ab4576f95ba56 Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Fri, 10 Sep 2021 22:39:23 +0200
Subject: [PATCH 5/5] vdo: prompt with no return failure
Exit 1 (failure) when prompt for conversion is answered as 'No'.
(cherry picked from commit 3b24c0fe4e197383101eae53b14f19586cf2eda1)
---
scripts/lvm_import_vdo.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh
index e5b30d8..06a043c 100755
--- a/scripts/lvm_import_vdo.sh
+++ b/scripts/lvm_import_vdo.sh
@@ -356,7 +356,7 @@ EOF
read -n 1 -s ANSWER
case "${ANSWER:0:1}" in
y|Y ) echo "Yes" ;;
- * ) echo "No" ; PROMPTING=""; exit ;;
+ * ) echo "No" ; PROMPTING=""; exit 1 ;;
esac
PROMPTING=""
YES="-y" # From now, now prompting
--
1.8.3.1

View File

@ -1,184 +0,0 @@
From 1c6992d37eff5af7134a11b662eacc1bab538ac2 Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Thu, 9 Sep 2021 14:59:38 +0200
Subject: [PATCH 1/5] vdo: read new sysfs path
New versions of kvdo module exposes statistics at new location:
/sys/block/dm-XXX/vdo/statistics/...
Enhance lvm2 to access this location first.
Also if the statistic info is missing - make it 'debug' level info,
so it is not failing 'lvs' command.
(cherry picked from commit e6f735d411e5911de186a610932c9bb9638275eb)
Conflicts:
WHATS_NEW
---
WHATS_NEW | 1 +
lib/activate/dev_manager.c | 7 +++---
lib/metadata/metadata-exported.h | 3 ++-
lib/metadata/vdo_manip.c | 46 ++++++++++++++++++++++------------------
4 files changed, 32 insertions(+), 25 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index b751009..c5a5ca5 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.03.14 -
==================================
+ Support newer location for VDO statistics.
Improve lvm_import_vdo script.
Support VDO LV with lvcreate -ky.
Fix lvconvert for VDO LV bigger then 2T.
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index c4a6739..0d954d1 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -157,6 +157,7 @@ out:
static int _get_segment_status_from_target_params(const char *target_name,
const char *params,
+ const struct dm_info *dminfo,
struct lv_seg_status *seg_status)
{
const struct lv_segment *seg = seg_status->seg;
@@ -216,7 +217,7 @@ static int _get_segment_status_from_target_params(const char *target_name,
return_0;
seg_status->type = SEG_STATUS_SNAPSHOT;
} else if (segtype_is_vdo_pool(segtype)) {
- if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, &seg_status->vdo_pool))
+ if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, dminfo, &seg_status->vdo_pool))
return_0;
seg_status->type = SEG_STATUS_VDO_POOL;
} else if (segtype_is_writecache(segtype)) {
@@ -320,7 +321,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
} while (target);
if (!target_name ||
- !_get_segment_status_from_target_params(target_name, target_params, seg_status))
+ !_get_segment_status_from_target_params(target_name, target_params, dminfo, seg_status))
stack;
}
@@ -1886,7 +1887,7 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
goto out;
}
- if (!parse_vdo_pool_status(dm->mem, lv, params, *status))
+ if (!parse_vdo_pool_status(dm->mem, lv, params, &info, *status))
goto_out;
(*status)->mem = dm->mem;
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index adbbe76..7c21b4d 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1364,7 +1364,8 @@ const char *get_vdo_write_policy_name(enum dm_vdo_write_policy policy);
uint64_t get_vdo_pool_virtual_size(const struct lv_segment *vdo_pool_seg);
int update_vdo_pool_virtual_size(struct lv_segment *vdo_pool_seg);
int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_pool_lv,
- const char *params, struct lv_status_vdo *status);
+ const char *params, const struct dm_info *dminfo,
+ struct lv_status_vdo *status);
struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
const struct dm_vdo_target_params *vtp,
uint32_t *virtual_extents,
diff --git a/lib/metadata/vdo_manip.c b/lib/metadata/vdo_manip.c
index 3f2de1a..2917f29 100644
--- a/lib/metadata/vdo_manip.c
+++ b/lib/metadata/vdo_manip.c
@@ -123,48 +123,56 @@ int update_vdo_pool_virtual_size(struct lv_segment *vdo_pool_seg)
return 1;
}
-static int _sysfs_get_kvdo_value(const char *dm_name, const char *vdo_param, uint64_t *value)
+static int _sysfs_get_kvdo_value(const char *dm_name, const struct dm_info *dminfo,
+ const char *vdo_param, uint64_t *value)
{
char path[PATH_MAX];
char temp[64];
int fd, size, r = 0;
- if (dm_snprintf(path, sizeof(path), "%skvdo/%s/%s",
- dm_sysfs_dir(), dm_name, vdo_param) < 0) {
- log_error("Failed to build kmod path.");
+ if (dm_snprintf(path, sizeof(path), "%s/block/dm-%d/vdo/%s",
+ dm_sysfs_dir(), dminfo->minor, vdo_param) < 0) {
+ log_debug("Failed to build kvdo path.");
return 0;
}
if ((fd = open(path, O_RDONLY)) < 0) {
- if (errno != ENOENT)
- log_sys_error("open", path);
- else
+ /* try with older location */
+ if (dm_snprintf(path, sizeof(path), "%skvdo/%s/%s",
+ dm_sysfs_dir(), dm_name, vdo_param) < 0) {
+ log_debug("Failed to build kvdo path.");
+ return 0;
+ }
+
+ if ((fd = open(path, O_RDONLY)) < 0) {
log_sys_debug("open", path);
- goto bad;
+ goto bad;
+ }
}
if ((size = read(fd, temp, sizeof(temp) - 1)) < 0) {
- log_sys_error("read", path);
+ log_sys_debug("read", path);
goto bad;
}
temp[size] = 0;
errno = 0;
*value = strtoll(temp, NULL, 0);
if (errno) {
- log_sys_error("strtool", path);
+ log_sys_debug("strtool", path);
goto bad;
}
r = 1;
bad:
if (fd >= 0 && close(fd))
- log_sys_error("close", path);
+ log_sys_debug("close", path);
return r;
}
int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_pool_lv,
- const char *params, struct lv_status_vdo *status)
+ const char *params, const struct dm_info *dminfo,
+ struct lv_status_vdo *status)
{
struct dm_vdo_status_parse_result result;
char *dm_name;
@@ -188,15 +196,11 @@ int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_
status->vdo = result.status;
- if (result.status->operating_mode == DM_VDO_MODE_NORMAL) {
- if (!_sysfs_get_kvdo_value(dm_name, "statistics/data_blocks_used",
- &status->data_blocks_used))
- return_0;
-
- if (!_sysfs_get_kvdo_value(dm_name, "statistics/logical_blocks_used",
- &status->logical_blocks_used))
- return_0;
-
+ if ((result.status->operating_mode == DM_VDO_MODE_NORMAL) &&
+ _sysfs_get_kvdo_value(dm_name, dminfo, "statistics/data_blocks_used",
+ &status->data_blocks_used) &&
+ _sysfs_get_kvdo_value(dm_name, dminfo, "statistics/logical_blocks_used",
+ &status->logical_blocks_used)) {
status->usage = dm_make_percent(result.status->used_blocks,
result.status->total_blocks);
status->saving = dm_make_percent(status->logical_blocks_used - status->data_blocks_used,
--
1.8.3.1

View File

@ -1,146 +0,0 @@
man/lvconvert.8_pregen | 2 +-
man/lvmdevices.8_pregen | 79 ++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 66 insertions(+), 15 deletions(-)
diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen
index d733ab6..4fafe5d 100644
--- a/man/lvconvert.8_pregen
+++ b/man/lvconvert.8_pregen
@@ -670,7 +670,7 @@ Convert LV to type thin-pool.
.RE
.P
.RS 4
-LV1 types: linear striped cache raid error zero
+LV1 types: linear striped cache raid error zero writecache
.RE
.P
\(em
diff --git a/man/lvmdevices.8_pregen b/man/lvmdevices.8_pregen
index 267ce96..fa85362 100644
--- a/man/lvmdevices.8_pregen
+++ b/man/lvmdevices.8_pregen
@@ -28,6 +28,8 @@ lvmdevices \(em Manage the devices file
.br
\fB--delpvid\fP \fIString\fP
.br
+ \fB--deviceidtype\fP \fIString\fP
+.br
\fB--devices\fP \fIPV\fP
.br
\fB--devicesfile\fP \fIString\fP
@@ -70,18 +72,18 @@ remove it from the devices file with lvmdevices --deldev. The
vgimportdevices(8) command adds all PVs from a VG to the devices file,
and updates the VG metadata to include device IDs of the PVs.
.P
-Commands adding new devices to the devices file necessarily look outside
-the existing devices file to find the devices to add. pvcreate, vgcreate,
-and vgextend also look outside the devices file to create new PVs and add
-them to the devices file.
+Commands that add new devices to the devices file necessarily look outside
+the existing devices file to find the devices being added. pvcreate,
+vgcreate, and vgextend also look outside the devices file to create new
+PVs and add those PVs to the devices file.
.P
LVM records devices in the devices file using hardware-specific IDs, such
as the WWID, and attempts to use subsystem-specific IDs for virtual device
-types (which also aim to be as unique and stable as possible.)
-These device IDs are also written in the VG metadata. When no hardware or
+types (which also aim to be as unique and stable as possible.) These
+device IDs are also written in the VG metadata. When no hardware or
virtual ID is available, lvm falls back using the unstable device name as
-the device ID. When devnames are used, lvm performs extra scanning to
-find devices if their devname changes, e.g. after reboot.
+the device ID. When devnames are used as IDs, lvm performs extra scanning
+to find devices if their devname changes, e.g. after reboot.
.P
When proper device IDs are used, an lvm command will not look at devices
outside the devices file, but when devnames are used as a fallback, lvm
@@ -95,12 +97,13 @@ overriding the devices file. The listed devices act as a sort of devices
file in terms of limiting which devices lvm will see and use. Devices
that are not listed will appear to be missing to the lvm command.
.P
-Multiple devices files can be kept in \fI#DEFAULT_SYS_DIR#/devices\fP, which allows lvm
-to be used with different sets of devices, e.g. system devices do not need
-to be exposed to a specific application, and the application can use lvm on
-its own devices that are not exposed to the system. The option
---devicesfile <filename> is used to select the devices file to use with the
-command. Without the option set, the default system devices file is used.
+Multiple devices files can be kept \fI#DEFAULT_SYS_DIR#/devices\fP, which
+allows lvm to be used with different sets of devices. For example, system
+devices do not need to be exposed to a specific application, and the
+application can use lvm on its own devices that are not exposed to the
+system. The option --devicesfile <filename> is used to select the devices
+file to use with the command. Without the option set, the default system
+devices file is used.
.P
Setting --devicesfile "" causes lvm to not use a devices file.
.P
@@ -120,6 +123,45 @@ if it does not yet exist.
.P
It is recommended to use lvm commands to make changes to the devices file to
ensure proper updates.
+.P
+The device ID and device ID type are included in the VG metadata and can
+be reported with pvs -o deviceid,deviceidtype. (Note that the lvmdevices
+command does not update VG metadata, but subsequent lvm commands modifying
+the metadata will include the device ID.)
+.P
+Possible device ID types are:
+.br
+.IP \[bu] 2
+.B sys_wwid
+uses the wwid reported by sysfs. This is the first choice for non-virtual
+devices.
+.IP \[bu] 2
+.B sys_serial
+uses the serial number reported by sysfs. This is the second choice for
+non-virtual devices.
+.IP \[bu] 2
+.B mpath_uuid
+is used for dm multipath devices, reported by sysfs.
+.IP \[bu] 2
+.B crypt_uuid
+is used for dm crypt devices, reported by sysfs.
+.IP \[bu] 2
+.B md_uuid
+is used for md devices, reported by sysfs.
+.B lvmlv_uuid
+is used if a PV is placed on top of an lvm LV, reported by sysfs.
+.IP \[bu] 2
+.B loop_file
+is used for loop devices, the backing file name repored by sysfs.
+.IP \[bu] 2
+.B devname
+the device name is used if no other type applies.
+.P
+
+The default choice for device ID type can be overriden using lvmdevices
+--addev --deviceidtype <type>. If the specified type is available for the
+device it will be used, otherwise the device will be added using the type
+that would otherwise be chosen.
.
.SH USAGE
.
@@ -169,6 +211,8 @@ Add a device to the devices file.
.br
.RS 4
.ad l
+[ \fB--deviceidtype\fP \fIString\fP ]
+.br
[ COMMON_OPTIONS ]
.ad b
.RE
@@ -308,6 +352,13 @@ Remove a device from the devices file.
Remove a device with the PVID from the devices file.
.
.HP
+\fB--deviceidtype\fP \fIString\fP
+.br
+The type of device ID to use for the device.
+If the specified type is available for the device,
+then it will override the default type that lvm would use.
+.
+.HP
\fB--devices\fP \fIPV\fP
.br
Devices that the command can use. This option can be repeated

View File

@ -3,16 +3,16 @@
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/VERSION b/VERSION
index d9c3e23..2610861 100644
index 0a36180..57ed15e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.03.12(2) (2021-05-07)
+2.03.12(2)-RHEL8 (2021-05-19)
-2.03.14(2) (2021-10-20)
+2.03.14(2)-RHEL8 (2021-10-20)
diff --git a/VERSION_DM b/VERSION_DM
index 6105a0f..0991c69 100644
index 52cb622..bf97bda 100644
--- a/VERSION_DM
+++ b/VERSION_DM
@@ -1 +1 @@
-1.02.177 (2021-05-07)
+1.02.177-RHEL8 (2021-05-19)
-1.02.181 (2021-10-20)
+1.02.181-RHEL8 (2021-10-20)

View File

@ -1,33 +0,0 @@
conf/example.conf.in | 5 +++--
lib/config/config_settings.h | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index b4a55ae..aaf73a4 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -121,8 +121,9 @@ devices {
#
# Example
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
- #
- # This configuration option does not have a default value defined.
+ #
+ # This configuration option has an automatic default value.
+ # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
# Configuration option devices/use_devicesfile.
# Enable or disable the use of a devices file.
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index d3a42a1..f5dac4d 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -269,7 +269,7 @@ cfg(devices_hints_CFG, "hints", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_
" Use no hints.\n"
"#\n")
-cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED , CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL, 0, NULL,
+cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#S^/dev/mpath/#S^/dev/mapper/mpath#S^/dev/[hs]d", vsn(1, 2, 19), NULL, 0, NULL,
"Select which path name to display for a block device.\n"
"If multiple path names exist for a block device, and LVM needs to\n"
"display a name for the device, the path names are matched against\n"

View File

@ -1,4 +1,4 @@
%global device_mapper_version 1.02.177
%global device_mapper_version 1.02.181
%global enable_cache 1
%global enable_cluster 1
@ -41,6 +41,15 @@
%endif
%endif
%if %{enable_cluster}
%global configure_cluster --with-cluster=internal
%if %{enable_cmirror}
%global configure_cmirror --enable-cmirrord
%endif
%else
%global configure_cluster --with-cluster=internal
%endif
%global from_snapshot 0
%if 0%{?from_snapshot}
%global commit 4dc5d4ac7e7a9457ccc46ff04796b347e58bf4da
@ -55,11 +64,11 @@ Name: lvm2
%if 0%{?rhel}
Epoch: %{rhel}
%endif
Version: 2.03.12
Version: 2.03.14
%if 0%{?from_snapshot}
Release: 0.1.20210426git%{shortcommit}%{?dist}%{?rel_suffix}
%else
Release: 11%{?dist}%{?rel_suffix}
Release: 3%{?dist}%{?rel_suffix}
%endif
License: GPLv2
URL: http://sourceware.org/lvm2
@ -69,55 +78,31 @@ Source0: lvm2-%{shortcommit}.tgz
Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz
Patch0: lvm2-rhel8.patch
%endif
Patch1: lvm2-set-default-preferred_names.patch
Patch2: lvm2-test-skip-problematic-tests.patch
# BZ 1961890
Patch3: lvm2-2_03_13-vdo-fix-preload-of-kvdo.patch
# BZ 1964622:
Patch4: lvm2-2_03_13-lvremove-fix-removing-thin-pool-with-writecache-on-d.patch
# BZ 1957898:
Patch5: lvm2-2_03_13-enable-command-syntax-for-thin-and-writecache.patch
# BZ 1872903:
Patch6: lvm2-2_03_13-writecache-fix-lv_on_pmem.patch
Patch7: lvm2-2_03_13-writecache-don-t-pvmove-device-used-by-writecache.patch
# BZ 1957898:
Patch8: lvm2-2_03_13-lvconvert-allow-writecache-with-other-thinpool-comma.patch
# BZ 1922312:
Patch9: lvm2-2_03_13-devices-don-t-use-deleted-loop-backing-file-for-devi.patch
Patch10: lvm2-2_03_13-lvmdevices-add-deviceidtype-option.patch
# BZ 1974901:
Patch11: lvm2-2_03_13-device_id-handle-scsi_debug-wwid.patch
# BZ 1930261:
Patch12: lvm2-2_03_13-lvconvert-fix-vdo-virtual-size-when-specified.patch
Patch13: lvm2-2_03_13-vdo-rename-variable-vdo_pool_zero.patch
Patch14: lvm2-2_03_13-vdo-support-vdo_pool_header_size.patch
Patch15: lvm2-2_03_13-vdo-add-vdoimport-support.patch
Patch16: lvm2-2_03_13-man-vdoimport-page.patch
Patch17: lvm2-make-generate.patch
# BZ 1967744:
Patch18: lvm2-2_03_13-thin-fix-component-detection-of-external-origin.patch
# BZ 1899263:
Patch19: lvm2-2_03_13-vgremove-remove-forgotten-pmspare.patch
Patch20: lvm2-2_03_13-vgsplit-add-support-for-option-poolmetadataspare.patch
Patch21: lvm2-2_03_13-test.patch
Patch22: lvm2-2_03_13-vgmerge-remove-one-of-merge-pmspare-LVs.patch
Patch23: lvm2-2_03_13-vgmerge-support-option-poolmetadataspare.patch
Patch24: lvm2-2_03_13-tests-extend-vgmerge-testing.patch
# BZ 1986930:
Patch25: lvm2-2_03_14-vdo-Rename-vdoimport-to-lvm_import_vdo.patch
# BZs #1930261 #1986885 #1986915 #1988504 #1989650 #1996227:
Patch26: lvm2-2_03_14-vdo-fixes.patch
Patch27: lvm2-2_03_14-vdo-lvm_import_vdo-fix-max_discard-size.patch
Patch28: lvm2-2_03_14-vdo-better-message-for-missing-device.patch
Patch29: lvm2-2_03_14-vdo-more-lvm_import_vdo-fixes.patch
Patch30: lvm2-2_03_14-vdo-fix-conversion-of-large-virtual-sizes.patch
Patch31: lvm2-2_03_14-vdo-read-new-sysfs-path.patch
Patch32: lvm2-2_03_14-tests-check-lvm2-parses-vdo-statistics.patch
Patch33: lvm2-2_03_14-vdo-lvm_import_vdo-script-needs-to-continue-when-vgn.patch
Patch34: lvm2-2_03_14-vdo-man-page-updates.patch
Patch35: lvm2-2_03_14-vdo-prompt-with-no-return-failure.patch
# BZ 2040514:
Patch36: lvm2-2_03_14-lvchange-fix-lvchange-refresh-failed-for-dm-suspend-.patch
Patch1: lvm2-test-skip-problematic-tests.patch
Patch2: 0001-Revert-new-udev-autoactivation.patch
Patch3: 0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch
Patch4: 0003-pvscan-fix-messages-from-coverity-changes.patch
Patch5: 0004-vgimportdevices-skip-lvmlockd-locking.patch
Patch6: 0005-hints-remove-the-cmd-hints-list.patch
Patch7: 0006-filter-sysfs-skip-when-device-id-is-set.patch
Patch8: 0007-lvmdevices-increase-open-file-limit.patch
Patch9: 0008-filter-sysfs-support-old-kernels-without-sys-dev-blo.patch
Patch10: 0009-device_id-match-different-dm-device-names.patch
Patch11: 0010-device_id-fix-search-on-filtered-device.patch
Patch12: 0011-device_id-searched_devnames-improvements.patch
Patch13: 0012-tests-pv-ext-flags-work-with-devices-file.patch
Patch14: 0013-display-ignore-reportformat.patch
Patch15: 0014-fix-spelling-of-pruning.patch
Patch16: 0015-man-lvmautoactivation.patch
#Patch17: 0016-spec-Add-lvmautoactivation-man-page.patch
Patch18: 0017-tests-devicesfile-devname.sh-drop-mdadm-chunk.patch
Patch19: 0018-devices-file-don-t-write-in-test-mode.patch
Patch20: 0019-print-warning-about-unrecognized-journal-option-valu.patch
Patch21: 0020-device_id-handle-wwid-with-spaces-or-control-charact.patch
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
BuildRequires: gcc
%if %{enable_testsuite}
@ -194,7 +179,7 @@ or more physical volumes and creating one or more logical volumes
%patch14 -p1 -b .backup14
%patch15 -p1 -b .backup15
%patch16 -p1 -b .backup16
%patch17 -p1 -b .backup17
#%%patch17 -p1 -b .backup17
%patch18 -p1 -b .backup18
%patch19 -p1 -b .backup19
%patch20 -p1 -b .backup20
@ -203,17 +188,6 @@ or more physical volumes and creating one or more logical volumes
%patch23 -p1 -b .backup23
%patch24 -p1 -b .backup24
%patch25 -p1 -b .backup25
%patch26 -p1 -b .backup26
%patch27 -p1 -b .backup27
%patch28 -p1 -b .backup28
%patch29 -p1 -b .backup29
%patch30 -p1 -b .backup30
%patch31 -p1 -b .backup31
%patch32 -p1 -b .backup32
%patch33 -p1 -b .backup33
%patch34 -p1 -b .backup34
%patch35 -p1 -b .backup35
%patch36 -p1 -b .backup36
%build
%global _default_pid_dir /run
@ -223,17 +197,7 @@ or more physical volumes and creating one or more logical volumes
%global _udevdir %{_prefix}/lib/udev/rules.d
# FIXME: Dropped in rhel9, do we need to keep this for "compatibility"?
%if %{enable_cluster}
%global configure_cluster --with-cluster=internal
%if %{enable_cmirror}
%global configure_cmirror --enable-cmirrord
%endif
%else
%global configure_cluster --with-cluster=internal
%endif
%configure\
%configure \
--with-default-dm-run-dir=%{_default_dm_run_dir} \
--with-default-run-dir=%{_default_run_dir} \
--with-default-pid-dir=%{_default_pid_dir} \
@ -280,7 +244,6 @@ or more physical volumes and creating one or more logical volumes
%if %{enable_vdo}
--with-vdo=internal --with-vdo-format=%{_bindir}/vdoformat \
%endif
%{?configure_integrity} \
%if %{enable_integrity}
--with-integrity=internal \
%endif
@ -400,6 +363,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
%{_sbindir}/vgscan
%{_sbindir}/vgsplit
%{_mandir}/man5/lvm.conf.5.gz
%{_mandir}/man7/lvmautoactivation.7.gz
%{_mandir}/man7/lvmcache.7.gz
%{_mandir}/man7/lvmraid.7.gz
%{_mandir}/man7/lvmreport.7.gz
@ -842,8 +806,15 @@ An extensive functional testsuite for LVM2.
%endif
%changelog
* Wed Feb 16 2022 Marian Csontos <mcsontos@redhat.com> - 2.03.12-11
- Fix multiple concurrent LV refreshes failures.
* Tue Jan 04 2022 Marian Csontos <mcsontos@redhat.com> - 2.03.14-3
- Fix devices file and autoactivation related issues.
* Fri Dec 17 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.14-2
- Revert autoactivation changes.
* Wed Oct 20 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.14-1
- Update to upstream version 2.03.14.
- See WHATS_NEW for list of changes.
* Mon Sep 20 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.12-10
- Fix incorrect memory free.