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