Compare commits
No commits in common. "c8" and "c9-beta" have entirely different histories.
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
SOURCES/LVM2.2.03.14.tgz
|
||||
SOURCES/LVM2.2.03.33.tgz
|
||||
|
||||
@ -1 +1 @@
|
||||
e5d4364e823d72b9a08b3aecc13cd677972830f0 SOURCES/LVM2.2.03.14.tgz
|
||||
63bb26807fa2dc9b8df29525bd854335a278eed5 SOURCES/LVM2.2.03.33.tgz
|
||||
|
||||
28
SOURCES/0001-RHEL9.patch
Normal file
28
SOURCES/0001-RHEL9.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 826517119e31658ac9f91940816281a44b0af4e9 Mon Sep 17 00:00:00 2001
|
||||
From: Marian Csontos <mcsontos@redhat.com>
|
||||
Date: Thu, 3 Oct 2024 16:14:11 +0200
|
||||
Subject: [PATCH 01/47] RHEL9
|
||||
|
||||
(cherry picked from commit 4ed40e67197778b28e4b822558614a517242e3e1)
|
||||
---
|
||||
VERSION | 2 +-
|
||||
VERSION_DM | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/VERSION b/VERSION
|
||||
index 2d35b7660..4993d445a 100644
|
||||
--- a/VERSION
|
||||
+++ b/VERSION
|
||||
@@ -1 +1 @@
|
||||
-2.03.33(2) (2025-06-27)
|
||||
+2.03.33(2)-RHEL9 (2025-09-25)
|
||||
diff --git a/VERSION_DM b/VERSION_DM
|
||||
index 0e8dcd346..c0564e0ea 100644
|
||||
--- a/VERSION_DM
|
||||
+++ b/VERSION_DM
|
||||
@@ -1 +1 @@
|
||||
-1.02.207 (2025-06-27)
|
||||
+1.02.207-RHEL9 (2025-09-25)
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,545 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
From c7b8367ebd23acbc63d657d3be822069cdb22e29 Mon Sep 17 00:00:00 2001
|
||||
From: Marian Csontos <mcsontos@redhat.com>
|
||||
Date: Thu, 16 May 2024 15:30:02 +0200
|
||||
Subject: [PATCH 02/47] Revert "10-dm.rules: bump DM_UDEV_RULES_VSN to 3"
|
||||
|
||||
This reverts commit 038f9254d9554654197b59c160e3f775af27cdb1.
|
||||
|
||||
(cherry picked from commit 408a80fdd46d3854c92dfce1bff3a376aea611d1)
|
||||
---
|
||||
udev/10-dm.rules.in | 12 +-----------
|
||||
1 file changed, 1 insertion(+), 11 deletions(-)
|
||||
|
||||
diff --git a/udev/10-dm.rules.in b/udev/10-dm.rules.in
|
||||
index db4ee771d..ca255c793 100644
|
||||
--- a/udev/10-dm.rules.in
|
||||
+++ b/udev/10-dm.rules.in
|
||||
@@ -12,9 +12,6 @@
|
||||
# DM_NAME - actual DM device's name
|
||||
# DM_UUID - UUID set for DM device (blank if not specified)
|
||||
# DM_UDEV_RULES_VSN - DM udev rules version
|
||||
-# DM_UDEV_DISABLE_OTHER_RULES_FLAG - a flag that indicates that
|
||||
-# stacked layers shouldn't attempt to probe the device, and
|
||||
-# should try to import relevant properties from the udev db.
|
||||
#
|
||||
# These rules cover only basic device-mapper functionality in udev.
|
||||
#
|
||||
@@ -25,11 +22,6 @@
|
||||
# 11-dm-lvm.rules for LVM subsystem
|
||||
# 11-dm-mpath.rules for multipath subsystem (since version 0.6.0, recommended!)
|
||||
#
|
||||
-# 11-dm<subsystem_name>.rules may use other DM related properties besides
|
||||
-# those listed above, like .DM_SUSPENDED. These properties are considered
|
||||
-# internal to device mapper, and subject to change without notice.
|
||||
-# Rules that are executed after 13-dm-disk.rules shouldn't use them.
|
||||
-#
|
||||
# Even more specific rules may be required by subsystems so always
|
||||
# check subsystem's upstream repository for recent set of rules.
|
||||
# Also, keep in mind that recent rules may also require recent
|
||||
@@ -152,9 +144,7 @@ LABEL="dm_suspended_set"
|
||||
# possible future changes.
|
||||
# VSN 1 - original rules
|
||||
# VSN 2 - add support for synthesized events
|
||||
-# VSN 3 - use DM_UDEV_DISABLE_OTHER_RULES_FLAG as the only "API"
|
||||
-# to be consumed by non-dm rules.
|
||||
-ENV{DM_UDEV_RULES_VSN}="3"
|
||||
+ENV{DM_UDEV_RULES_VSN}="2"
|
||||
|
||||
ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="(DM_DIR)/$env{DM_NAME}"
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,450 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
From e7afa38ae6a12cb0ac0d4c7b923ec46c254df553 Mon Sep 17 00:00:00 2001
|
||||
From: Marian Csontos <mcsontos@redhat.com>
|
||||
Date: Thu, 16 May 2024 15:30:15 +0200
|
||||
Subject: [PATCH 03/47] Revert "dm udev rules: don't export and save DM_NOSCAN"
|
||||
|
||||
This reverts commit a196752969320cfc34a97cc97afa1978fa57da73.
|
||||
|
||||
(cherry picked from commit 6a15577cb02603512afce0f13a591183105c8f73)
|
||||
---
|
||||
udev/11-dm-lvm.rules.in | 2 +-
|
||||
udev/13-dm-disk.rules.in | 4 ++--
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/udev/11-dm-lvm.rules.in b/udev/11-dm-lvm.rules.in
|
||||
index 8b8d0561f..6dd556aa9 100644
|
||||
--- a/udev/11-dm-lvm.rules.in
|
||||
+++ b/udev/11-dm-lvm.rules.in
|
||||
@@ -30,7 +30,7 @@ IMPORT{program}="(DM_EXEC)/dmsetup splitname --nameprefixes --noheadings --rows
|
||||
# so those selected rules are surely skipped.
|
||||
# We don't need to save and restore the previous of DM_UDEV_DISABLE_OTHER_RULES_FLAG,
|
||||
# that's taken care of in 10-dm.rules.
|
||||
-ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{.DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||
+ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||
|
||||
ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}=="1", GOTO="lvm_end"
|
||||
|
||||
diff --git a/udev/13-dm-disk.rules.in b/udev/13-dm-disk.rules.in
|
||||
index 9bfeebe13..a9ad67e9f 100644
|
||||
--- a/udev/13-dm-disk.rules.in
|
||||
+++ b/udev/13-dm-disk.rules.in
|
||||
@@ -20,9 +20,9 @@ ENV{DM_UUID}=="?*", SYMLINK+="disk/by-id/dm-uuid-$env{DM_UUID}"
|
||||
ENV{DISKSEQ}=="?*", SYMLINK+="disk/by-diskseq/$env{DISKSEQ}"
|
||||
|
||||
ENV{.DM_SUSPENDED}=="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", GOTO="dm_import"
|
||||
-ENV{.DM_NOSCAN}=="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", GOTO="dm_import"
|
||||
+ENV{DM_NOSCAN}=="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", GOTO="dm_import"
|
||||
ENV{.DM_SUSPENDED}=="1", GOTO="dm_end"
|
||||
-ENV{.DM_NOSCAN}=="1", GOTO="dm_watch"
|
||||
+ENV{DM_NOSCAN}=="1", GOTO="dm_watch"
|
||||
|
||||
(BLKID_RULE)
|
||||
GOTO="dm_link"
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
From c58cdd59d2028c5eca83cdf5df16948b4277a21f Mon Sep 17 00:00:00 2001
|
||||
From: Marian Csontos <mcsontos@redhat.com>
|
||||
Date: Thu, 16 May 2024 15:30:24 +0200
|
||||
Subject: [PATCH 04/47] Revert "dm udev rules: don't export and save
|
||||
DM_SUSPENDED"
|
||||
|
||||
This reverts commit 21ca92c4325b6b161fb1e1f10942ad9f8d23c144.
|
||||
|
||||
(cherry picked from commit 2280f85310b82c03b43dfd88e0712c5921a36ffc)
|
||||
---
|
||||
udev/10-dm.rules.in | 14 ++++++--------
|
||||
udev/12-dm-permissions.rules | 1 +
|
||||
udev/13-dm-disk.rules.in | 4 ++--
|
||||
3 files changed, 9 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/udev/10-dm.rules.in b/udev/10-dm.rules.in
|
||||
index ca255c793..29fe71527 100644
|
||||
--- a/udev/10-dm.rules.in
|
||||
+++ b/udev/10-dm.rules.in
|
||||
@@ -11,6 +11,7 @@
|
||||
# for use in later rules:
|
||||
# DM_NAME - actual DM device's name
|
||||
# DM_UUID - UUID set for DM device (blank if not specified)
|
||||
+# DM_SUSPENDED - suspended state of DM device (0 or 1)
|
||||
# DM_UDEV_RULES_VSN - DM udev rules version
|
||||
#
|
||||
# These rules cover only basic device-mapper functionality in udev.
|
||||
@@ -122,18 +123,15 @@ LABEL="dm_no_coldplug"
|
||||
# The "suspended" item was added even later (kernels >= 2.6.31),
|
||||
# so we also have to call dmsetup if the kernel version used
|
||||
# is in between these releases.
|
||||
-TEST=="dm", ENV{DM_NAME}="$attr{dm/name}", ENV{DM_UUID}="$attr{dm/uuid}", ENV{.DM_SUSPENDED}="$attr{dm/suspended}"
|
||||
+TEST=="dm", ENV{DM_NAME}="$attr{dm/name}", ENV{DM_UUID}="$attr{dm/uuid}", ENV{DM_SUSPENDED}="$attr{dm/suspended}"
|
||||
TEST!="dm", IMPORT{program}="(DM_EXEC)/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o name,uuid,suspended"
|
||||
+ENV{DM_SUSPENDED}!="?*", IMPORT{program}="(DM_EXEC)/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o suspended"
|
||||
|
||||
-ENV{.DM_SUSPENDED}=="?*", GOTO="dm_suspended_set"
|
||||
-TEST=="dm", IMPORT{program}="(DM_EXEC)/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o suspended"
|
||||
# dmsetup tool provides suspended state information in textual
|
||||
# form with values "Suspended"/"Active". We translate it to
|
||||
# 0/1 respectively to be consistent with sysfs values.
|
||||
-ENV{DM_SUSPENDED}=="Active", ENV{.DM_SUSPENDED}="0"
|
||||
-ENV{DM_SUSPENDED}=="Suspended", ENV{.DM_SUSPENDED}="1"
|
||||
-ENV{DM_SUSPENDED}=""
|
||||
-LABEL="dm_suspended_set"
|
||||
+ENV{DM_SUSPENDED}=="Active", ENV{DM_SUSPENDED}="0"
|
||||
+ENV{DM_SUSPENDED}=="Suspended", ENV{DM_SUSPENDED}="1"
|
||||
|
||||
# This variable provides a reliable way to check that device-mapper
|
||||
# rules were installed. It means that all needed variables are set
|
||||
@@ -151,7 +149,7 @@ ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="(DM_DIR)/
|
||||
# Avoid processing and scanning a DM device in the other (foreign)
|
||||
# rules if it is in suspended state. However, we still keep 'disk'
|
||||
# and 'DM subsystem' related rules enabled in this case.
|
||||
-ENV{.DM_SUSPENDED}=="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||
+ENV{DM_SUSPENDED}=="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||
|
||||
GOTO="dm_end"
|
||||
|
||||
diff --git a/udev/12-dm-permissions.rules b/udev/12-dm-permissions.rules
|
||||
index 9624ddc5e..8d3bc224a 100644
|
||||
--- a/udev/12-dm-permissions.rules
|
||||
+++ b/udev/12-dm-permissions.rules
|
||||
@@ -14,6 +14,7 @@
|
||||
# DM_UDEV_RULES_VSN - DM udev rules version
|
||||
# DM_NAME - actual DM device's name
|
||||
# DM_UUID - UUID set for DM device (blank if not specified)
|
||||
+# DM_SUSPENDED - suspended state of DM device (0 or 1)
|
||||
# DM_LV_NAME - logical volume name (not set if LVM device not present)
|
||||
# DM_VG_NAME - volume group name (not set if LVM device not present)
|
||||
# DM_LV_LAYER - logical volume layer (not set if LVM device not present)
|
||||
diff --git a/udev/13-dm-disk.rules.in b/udev/13-dm-disk.rules.in
|
||||
index a9ad67e9f..e136ee441 100644
|
||||
--- a/udev/13-dm-disk.rules.in
|
||||
+++ b/udev/13-dm-disk.rules.in
|
||||
@@ -19,9 +19,9 @@ ENV{DM_UUID}=="?*", SYMLINK+="disk/by-id/dm-uuid-$env{DM_UUID}"
|
||||
|
||||
ENV{DISKSEQ}=="?*", SYMLINK+="disk/by-diskseq/$env{DISKSEQ}"
|
||||
|
||||
-ENV{.DM_SUSPENDED}=="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", GOTO="dm_import"
|
||||
+ENV{DM_SUSPENDED}=="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", GOTO="dm_import"
|
||||
ENV{DM_NOSCAN}=="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", GOTO="dm_import"
|
||||
-ENV{.DM_SUSPENDED}=="1", GOTO="dm_end"
|
||||
+ENV{DM_SUSPENDED}=="1", GOTO="dm_end"
|
||||
ENV{DM_NOSCAN}=="1", GOTO="dm_watch"
|
||||
|
||||
(BLKID_RULE)
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
From 1ab5db0e811306dafabcd7281ce84ffbe32b2566 Mon Sep 17 00:00:00 2001
|
||||
From: Marian Csontos <mcsontos@redhat.com>
|
||||
Date: Thu, 16 May 2024 15:30:37 +0200
|
||||
Subject: [PATCH 05/47] Revert "11-dm-lvm.rules: don't restore
|
||||
DM_UDEV_DISABLE_OTHER_RULES_FLAG from db"
|
||||
|
||||
This reverts commit 2b2f11a74cd5cc05f266fd0c65f0e55eb8bafd9f.
|
||||
|
||||
(cherry picked from commit 4316c786f25f8b01b831458f8baf1f77faad79ba)
|
||||
---
|
||||
udev/11-dm-lvm.rules.in | 13 ++++++++-----
|
||||
1 file changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/udev/11-dm-lvm.rules.in b/udev/11-dm-lvm.rules.in
|
||||
index 6dd556aa9..9836f41ca 100644
|
||||
--- a/udev/11-dm-lvm.rules.in
|
||||
+++ b/udev/11-dm-lvm.rules.in
|
||||
@@ -26,11 +26,14 @@ IMPORT{program}="(DM_EXEC)/dmsetup splitname --nameprefixes --noheadings --rows
|
||||
# to zero any stale metadata found within the LV data area. Such stale
|
||||
# metadata could cause false claim of the LV device, keeping it open etc.
|
||||
#
|
||||
-# If the NOSCAN flag is present, set DM_UDEV_DISABLE_OTHER_RULES_FLAG
|
||||
-# so those selected rules are surely skipped.
|
||||
-# We don't need to save and restore the previous of DM_UDEV_DISABLE_OTHER_RULES_FLAG,
|
||||
-# that's taken care of in 10-dm.rules.
|
||||
-ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||
+# If the NOSCAN flag is present, backup selected existing flags used to
|
||||
+# disable rules, then set them firmly so those selected rules are surely skipped.
|
||||
+# Restore these flags once the NOSCAN flag is dropped (which is normally any
|
||||
+# uevent that follows for this LV, even an artificially generated one).
|
||||
+ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_NOSCAN}="1", ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||
+ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", IMPORT{db}="DM_NOSCAN", IMPORT{db}="DM_DISABLE_OTHER_RULES_FLAG_OLD"
|
||||
+ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", ENV{DM_NOSCAN}=="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}", \
|
||||
+ ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="", ENV{DM_NOSCAN}=""
|
||||
|
||||
ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}=="1", GOTO="lvm_end"
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,95 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
From 2d8f649144bd95cf2df65f1d4bd99c96a8c5f786 Mon Sep 17 00:00:00 2001
|
||||
From: Marian Csontos <mcsontos@redhat.com>
|
||||
Date: Thu, 16 May 2024 15:30:48 +0200
|
||||
Subject: [PATCH 06/47] Revert "10-dm-rules: don't restore
|
||||
DM_UDEV_DISABLE_OTHER_RULES_FLAG from db"
|
||||
|
||||
This reverts commit f98d020eadafe7d8db7bec1f5a26915615e5a6a9.
|
||||
|
||||
(cherry picked from commit ebd5feaca2779c9379a14ba6f74a47214d03d94b)
|
||||
---
|
||||
udev/10-dm.rules.in | 12 ++----------
|
||||
1 file changed, 2 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/udev/10-dm.rules.in b/udev/10-dm.rules.in
|
||||
index 29fe71527..2c6903da7 100644
|
||||
--- a/udev/10-dm.rules.in
|
||||
+++ b/udev/10-dm.rules.in
|
||||
@@ -53,14 +53,7 @@ OPTIONS+="db_persist"
|
||||
# These flags are encoded in DM_COOKIE variable that was introduced in
|
||||
# kernel version 2.6.31. Therefore, we can use this feature with
|
||||
# kernels >= 2.6.31 only. Cookie is not decoded for remove event.
|
||||
-ENV{DM_COOKIE}!="?*", GOTO="dm_no_cookie"
|
||||
-IMPORT{program}="(DM_EXEC)/dmsetup udevflags $env{DM_COOKIE}"
|
||||
-
|
||||
-# Store the original flag from the cookie as DM_COOKIE_DISABLE_OTHER_RULES_FLAG
|
||||
-# in the udev db. DM_UDEV_DISABLE_OTHER_RULES_FLAG will be or'd with other
|
||||
-# conditions for use by upper, non-dm layers.
|
||||
-ENV{DM_COOKIE_DISABLE_OTHER_RULES_FLAG}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}"
|
||||
-LABEL="dm_no_cookie"
|
||||
+ENV{DM_COOKIE}=="?*", IMPORT{program}="(DM_EXEC)/dmsetup udevflags $env{DM_COOKIE}"
|
||||
|
||||
# There is no cookie set nor any flags encoded in events not originating
|
||||
# in libdevmapper so we need to detect this and try to behave correctly.
|
||||
@@ -70,13 +63,12 @@ ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", ENV{DM_ACTIVATION}="1", GOTO="dm_flags_do
|
||||
IMPORT{db}="DM_UDEV_DISABLE_DM_RULES_FLAG"
|
||||
IMPORT{db}="DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG"
|
||||
IMPORT{db}="DM_UDEV_DISABLE_DISK_RULES_FLAG"
|
||||
-IMPORT{db}="DM_COOKIE_DISABLE_OTHER_RULES_FLAG"
|
||||
+IMPORT{db}="DM_UDEV_DISABLE_OTHER_RULES_FLAG"
|
||||
IMPORT{db}="DM_UDEV_LOW_PRIORITY_FLAG"
|
||||
IMPORT{db}="DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG"
|
||||
IMPORT{db}="DM_UDEV_PRIMARY_SOURCE_FLAG"
|
||||
IMPORT{db}="DM_UDEV_FLAG7"
|
||||
IMPORT{db}="DM_UDEV_RULES_VSN"
|
||||
-ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_COOKIE_DISABLE_OTHER_RULES_FLAG}"
|
||||
LABEL="dm_flags_done"
|
||||
|
||||
# If DISK_RO is set, it's an uevent that changes the ro attribute of the device.
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,422 +0,0 @@
|
||||
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/54] filter-sysfs: skip when device id is set
|
||||
|
||||
When a device id is set for a device, using an idtype other
|
||||
than devname, it means that sysfs has been used with the device
|
||||
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.34.3
|
||||
|
||||
28
SOURCES/0007-WHATS_NEW_DM-update.patch
Normal file
28
SOURCES/0007-WHATS_NEW_DM-update.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 50a4afb468ffa1219ee2d315a29808697e2d14c1 Mon Sep 17 00:00:00 2001
|
||||
From: Marian Csontos <mcsontos@redhat.com>
|
||||
Date: Mon, 5 May 2025 17:36:05 +0200
|
||||
Subject: [PATCH 07/47] WHATS_NEW_DM: update
|
||||
|
||||
(cherry picked from commit 72f203a02d7f30d5afdaa853a082b2b1d1f56297)
|
||||
---
|
||||
WHATS_NEW_DM | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
|
||||
index 0bbdd1867..d4282ef20 100644
|
||||
--- a/WHATS_NEW_DM
|
||||
+++ b/WHATS_NEW_DM
|
||||
@@ -1,3 +1,10 @@
|
||||
+RHEL9 - 30th September 2025
|
||||
+===========================
|
||||
+ Revert Increase DM_UDEV_RULES_VSN to 3 to indicate changed udev rules.
|
||||
+ Revert Rename DM_NOSCAN to .DM_NOSCAN so it's not stored in udev db.
|
||||
+ Revert Rename DM_SUSPENDED to .DM_SUSPENDED so it's not stored in udev db.
|
||||
+ Revert Do not import DM_UDEV_DISABLE_OTHER_RULES_FLAG from db in 10-dm-disk.rules.
|
||||
+
|
||||
Version 1.02.207 - 27th June 2025
|
||||
=================================
|
||||
Escape the escape character itself on JSON report format output.
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -1,73 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
50
SOURCES/0008-lvmlockd-fix-missing-free-in-vg_status.patch
Normal file
50
SOURCES/0008-lvmlockd-fix-missing-free-in-vg_status.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 8920f236abae6a9e7b15a0b11c1b9d5bad370aae Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Thu, 26 Jun 2025 13:42:38 -0500
|
||||
Subject: [PATCH 08/47] lvmlockd: fix missing free in vg_status
|
||||
|
||||
and add more checking of get_hosts result.
|
||||
|
||||
used by lockd_vg_is_started() for the PR feature.
|
||||
|
||||
(cherry picked from commit 5f0ddd0fd891e769577f6cd3546326f18dbc3bca)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockd-sanlock.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
index 1af3c368f..97f06d115 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
@@ -2352,7 +2352,7 @@ int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
|
||||
|
||||
int lm_vg_status_sanlock(struct lockspace *ls, struct action *act)
|
||||
{
|
||||
- struct sanlk_host *hs;
|
||||
+ struct sanlk_host *hs = NULL;
|
||||
const char *host_state;
|
||||
int count = 0;
|
||||
int rv;
|
||||
@@ -2366,6 +2366,11 @@ int lm_vg_status_sanlock(struct lockspace *ls, struct action *act)
|
||||
return rv;
|
||||
}
|
||||
|
||||
+ if (!count || !hs) {
|
||||
+ log_error("S %s vg_status_san get_hosts empty", ls->name);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
act->owner.host_id = (uint32_t)hs->host_id;
|
||||
act->owner.generation = (uint32_t)hs->generation;
|
||||
act->owner.timestamp = (uint32_t)hs->timestamp;
|
||||
@@ -2373,6 +2378,7 @@ int lm_vg_status_sanlock(struct lockspace *ls, struct action *act)
|
||||
if ((host_state = _host_flags_to_str(hs->flags)))
|
||||
dm_strncpy(act->owner.state, host_state, OWNER_STATE_SIZE-1);
|
||||
|
||||
+ free(hs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,155 +0,0 @@
|
||||
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/54] device_id: match different dm device names
|
||||
|
||||
If a devices file entry for a dm device is using the devname
|
||||
for the device id, then recognize different dm names as matching.
|
||||
---
|
||||
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.34.3
|
||||
|
||||
@ -0,0 +1,686 @@
|
||||
From 5878a6dc3167e4f9fc4c1dcb04c3dd41e3d4db19 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Mon, 30 Jun 2025 12:59:49 -0500
|
||||
Subject: [PATCH 09/47] lvmlockd: add repair option to reinitialize sanlock
|
||||
leases
|
||||
|
||||
If sanlock leases become corrupted, adding --lockopt repair
|
||||
to the command will let lvmlockd reinitialize them.
|
||||
|
||||
(cherry picked from commit 4bc52d2dc5dee3c57f88d58c3143e8a2f4d44d9f)
|
||||
---
|
||||
configure.ac | 1 +
|
||||
daemons/lvmlockd/lvmlockd-core.c | 24 +--
|
||||
daemons/lvmlockd/lvmlockd-internal.h | 8 +-
|
||||
daemons/lvmlockd/lvmlockd-sanlock.c | 212 ++++++++++++++++++++++++---
|
||||
lib/locking/lvmlockd.c | 69 +++++++--
|
||||
lib/locking/lvmlockd.h | 4 +
|
||||
6 files changed, 277 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 6fcf6f2b5..11a735af5 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -936,6 +936,7 @@ dnl -- Look for sanlock libraries
|
||||
AS_IF([test "$BUILD_LOCKDSANLOCK" = "yes"], [
|
||||
LOCKDSANLOCK_SUPPORT=370
|
||||
PKG_CHECK_EXISTS(libsanlock_client >= 4.0.0, [LOCKDSANLOCK_SUPPORT=400])
|
||||
+ PKG_CHECK_EXISTS(libsanlock_client >= 4.1.0, [LOCKDSANLOCK_SUPPORT=410])
|
||||
PKG_CHECK_MODULES(LIBSANLOCKCLIENT, libsanlock_client >= 3.7.0, [BUILD_LVMLOCKD="yes"])
|
||||
AC_DEFINE_UNQUOTED([LOCKDSANLOCK_SUPPORT], [$LOCKDSANLOCK_SUPPORT], [Define version of sanlock.])
|
||||
])
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
|
||||
index 66a5d5e20..0cb10369a 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-core.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-core.c
|
||||
@@ -1057,7 +1057,7 @@ static void lm_vg_status(struct lockspace *ls, struct action *act)
|
||||
act->lm_rv = rv;
|
||||
}
|
||||
|
||||
-static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
|
||||
+static int lm_prepare_lockspace(struct lockspace *ls, struct action *act, int repair)
|
||||
{
|
||||
uint64_t prev_generation = 0;
|
||||
int rv = -1;
|
||||
@@ -1065,7 +1065,7 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
|
||||
if (ls->lm_type == LD_LM_DLM) {
|
||||
rv = lm_prepare_lockspace_dlm(ls);
|
||||
} else if (ls->lm_type == LD_LM_SANLOCK) {
|
||||
- rv = lm_prepare_lockspace_sanlock(ls, &prev_generation);
|
||||
+ rv = lm_prepare_lockspace_sanlock(ls, &prev_generation, repair);
|
||||
/* borrowing action.owner to avoid adding another action field */
|
||||
if (!rv)
|
||||
act->owner.generation = (uint32_t)prev_generation;
|
||||
@@ -1126,14 +1126,14 @@ static int lm_add_resource(struct lockspace *ls, struct resource *r)
|
||||
|
||||
static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct action *act,
|
||||
struct val_blk *vb_out, int *retry, struct owner *owner,
|
||||
- int adopt_only, int adopt_ok)
|
||||
+ int adopt_only, int adopt_ok, int repair)
|
||||
{
|
||||
int rv = -1;
|
||||
|
||||
if (ls->lm_type == LD_LM_DLM)
|
||||
rv = lm_lock_dlm(ls, r, mode, vb_out, adopt_only, adopt_ok);
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
- rv = lm_lock_sanlock(ls, r, mode, vb_out, retry, owner, adopt_only, adopt_ok);
|
||||
+ rv = lm_lock_sanlock(ls, r, mode, vb_out, retry, owner, adopt_only, adopt_ok, repair);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_lock_idm(ls, r, mode, vb_out, act->lv_uuid,
|
||||
&act->pvs, adopt_only, adopt_ok);
|
||||
@@ -1309,7 +1309,8 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
|
||||
|
||||
rv = lm_lock(ls, r, act->mode, act, &vb, retry, owner,
|
||||
act->flags & LD_AF_ADOPT_ONLY ? 1 : 0,
|
||||
- act->flags & LD_AF_ADOPT ? 1 : 0);
|
||||
+ act->flags & LD_AF_ADOPT ? 1 : 0,
|
||||
+ act->flags & LD_AF_REPAIR ? 1 : 0);
|
||||
|
||||
if (rv && r->use_vb)
|
||||
log_debug("%s:%s res_lock rv %d read vb %x %x %u",
|
||||
@@ -2577,6 +2578,7 @@ static void *lockspace_thread_main(void *arg_in)
|
||||
int error = 0;
|
||||
int adopt_only = 0;
|
||||
int adopt_ok = 0;
|
||||
+ int repair = 0;
|
||||
int wait_flag = 0;
|
||||
int nodelay = 0;
|
||||
int nocreate;
|
||||
@@ -2604,6 +2606,8 @@ static void *lockspace_thread_main(void *arg_in)
|
||||
adopt_ok = 1;
|
||||
if (add_act->flags & LD_AF_NODELAY)
|
||||
nodelay = 1;
|
||||
+ if (add_act->flags & LD_AF_REPAIR)
|
||||
+ repair = 1;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&ls->mutex);
|
||||
@@ -2613,14 +2617,14 @@ static void *lockspace_thread_main(void *arg_in)
|
||||
adopt_ok = 1;
|
||||
}
|
||||
|
||||
- log_debug("S %s lm_add_lockspace %s wait %d adopt_only %d adopt_ok %d",
|
||||
- ls->name, lm_str(ls->lm_type), wait_flag, adopt_only, adopt_ok);
|
||||
+ log_debug("S %s lm_add_lockspace %s act %d wait %d adopt_only %d adopt_ok %d repair %d",
|
||||
+ ls->name, lm_str(ls->lm_type), add_act ? 1 : 0, wait_flag, adopt_only, adopt_ok, repair);
|
||||
|
||||
/*
|
||||
* The prepare step does not wait for anything and is quick;
|
||||
* it tells us if the parameters are valid and the lm is running.
|
||||
*/
|
||||
- error = lm_prepare_lockspace(ls, add_act);
|
||||
+ error = lm_prepare_lockspace(ls, add_act, repair);
|
||||
|
||||
if (add_act && (!wait_flag || error)) {
|
||||
/* send initial join result back to client */
|
||||
@@ -4789,6 +4793,8 @@ static uint32_t str_to_opts(const char *str)
|
||||
flags |= LD_AF_DISABLE;
|
||||
if (strstr(str, "nodelay"))
|
||||
flags |= LD_AF_NODELAY;
|
||||
+ if (strstr(str, "repair"))
|
||||
+ flags |= LD_AF_REPAIR;
|
||||
|
||||
/* FIXME: parse the flag values properly */
|
||||
if (strstr(str, "adopt_only"))
|
||||
@@ -5310,7 +5316,7 @@ skip_pvs_path:
|
||||
dm_config_destroy(req.cft);
|
||||
buffer_destroy(&req.buffer);
|
||||
|
||||
- log_debug("recv %s[%d][%u] %s%s%s %s%s %s%s%s%s opts=%x",
|
||||
+ log_debug("recv %s[%d][%u] %s%s%s %s%s %s%s%s%s opts=0x%x",
|
||||
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
|
||||
op_mode_str(act->op, act->mode), act->rt ? "_" : "", rt_str(act->rt),
|
||||
act->vg_name[0] ? "vg=" : "",
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-internal.h b/daemons/lvmlockd/lvmlockd-internal.h
|
||||
index bf40c77f2..7999c2a03 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-internal.h
|
||||
+++ b/daemons/lvmlockd/lvmlockd-internal.h
|
||||
@@ -118,6 +118,7 @@ struct client {
|
||||
#define LD_AF_SH_EXISTS 0x00100000
|
||||
#define LD_AF_ADOPT_ONLY 0x00200000 /* adopt orphan or fail */
|
||||
#define LD_AF_NODELAY 0x00400000
|
||||
+#define LD_AF_REPAIR 0x00800000
|
||||
|
||||
/*
|
||||
* Number of times to repeat a lock request after
|
||||
@@ -209,6 +210,7 @@ struct lockspace {
|
||||
int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
|
||||
void *lm_data;
|
||||
uint32_t host_id;
|
||||
+ uint64_t generation;
|
||||
uint64_t free_lock_offset; /* for sanlock, start search for free lock here */
|
||||
struct pvs pvs; /* for idm: PV list */
|
||||
|
||||
@@ -561,13 +563,13 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
||||
int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, char *prev_args);
|
||||
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
|
||||
int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
|
||||
-int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation);
|
||||
+int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair);
|
||||
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay);
|
||||
int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
|
||||
int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r);
|
||||
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int *retry, struct owner *owner,
|
||||
- int adopt_only, int adopt_ok);
|
||||
+ int adopt_only, int adopt_ok, int repair);
|
||||
int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
|
||||
int ld_mode, uint32_t r_version);
|
||||
int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
|
||||
@@ -610,7 +612,7 @@ static inline int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t fl
|
||||
return -1;
|
||||
}
|
||||
|
||||
-static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation)
|
||||
+static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
index 97f06d115..ce5953faf 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
@@ -218,6 +218,18 @@ int lm_data_size_sanlock(void)
|
||||
|
||||
static uint64_t daemon_test_lv_count;
|
||||
|
||||
+static void _fclose(FILE *fp, char *name)
|
||||
+{
|
||||
+ if (fclose(fp))
|
||||
+ log_warn("fclose error %d %s", errno, name ?: "");
|
||||
+}
|
||||
+
|
||||
+static void _close(int fd)
|
||||
+{
|
||||
+ if (close(fd))
|
||||
+ log_warn("close error %d fd %d", errno, fd);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Copy a null-terminated string "str" into a fixed
|
||||
* size struct field "buf" which is not null terminated.
|
||||
@@ -308,14 +320,74 @@ static int read_host_id_file(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
- if (fclose(file))
|
||||
- log_debug("Failed to fclose host id file %s (%s).",
|
||||
- daemon_host_id_file, strerror(errno));
|
||||
+ _fclose(file, (char *)daemon_host_id_file);
|
||||
out:
|
||||
log_debug("host_id %d from %s", host_id, daemon_host_id_file);
|
||||
return host_id;
|
||||
}
|
||||
|
||||
+static int read_info_file(struct lockspace *ls, uint32_t *host_id, uint64_t *generation, int *sector_size, int *align_size)
|
||||
+{
|
||||
+ char line[MAX_LINE];
|
||||
+ char path[PATH_MAX] = { 0 };
|
||||
+ FILE *fp;
|
||||
+
|
||||
+ if (dm_snprintf(path, PATH_MAX-1, "/var/lib/lvm/lvmlockd_info_%s", ls->vg_name) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (!(fp = fopen(path, "r"))) {
|
||||
+ log_debug("Failed to open info file");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ while (fgets(line, sizeof(line), fp)) {
|
||||
+ if (line[0] == '#')
|
||||
+ continue;
|
||||
+ if (!strncmp(line, "host_id ", 8)) {
|
||||
+ sscanf(line, "host_id %u", host_id);
|
||||
+ } else if (!strncmp(line, "generation ", 11)) {
|
||||
+ sscanf(line, "generation %llu", (unsigned long long *)generation);
|
||||
+ } else if (!strncmp(line, "sector_size ", 12)) {
|
||||
+ sscanf(line, "sector_size %d", sector_size);
|
||||
+ } else if (!strncmp(line, "align_size ", 11)) {
|
||||
+ sscanf(line, "align_size %d", align_size);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ _fclose(fp, path);
|
||||
+ log_debug("info file: read %u %llu %d %d", *host_id, (unsigned long long)*generation, *sector_size, *align_size);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int write_info_file(struct lockspace *ls)
|
||||
+{
|
||||
+ struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
|
||||
+ char path[PATH_MAX] = { 0 };
|
||||
+ FILE *fp;
|
||||
+ time_t t;
|
||||
+
|
||||
+ if (dm_snprintf(path, PATH_MAX-1, "/var/lib/lvm/lvmlockd_info_%s", ls->vg_name) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (!(fp = fopen(path, "w"))) {
|
||||
+ log_debug("Failed to create info file");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ fprintf(fp, "# vg %s %s created %s", ls->vg_name, ls->vg_uuid, ctime(&t));
|
||||
+ fprintf(fp, "host_id %u\n", ls->host_id);
|
||||
+ fprintf(fp, "generation %llu\n", (unsigned long long)ls->generation);
|
||||
+ fprintf(fp, "sector_size %d\n", lms->sector_size);
|
||||
+ fprintf(fp, "align_size %d\n", lms->align_size);
|
||||
+
|
||||
+ if (fflush(fp))
|
||||
+ log_warn("Failed to write/flush %s", path);
|
||||
+ _fclose(fp, path);
|
||||
+
|
||||
+ log_debug("info file: wrote %u %llu %d %d", ls->host_id, (unsigned long long)ls->generation, lms->sector_size, lms->align_size);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* Prepare valid /dev/mapper/vgname-lvname with all the mangling */
|
||||
static int build_dm_path(char *path, size_t path_len,
|
||||
const char *vg_name, const char *lv_name)
|
||||
@@ -370,7 +442,7 @@ static void _read_sysfs_size(dev_t devno, const char *name, uint64_t *val)
|
||||
if (strlen(buf))
|
||||
*val = strtoull(buf, NULL, 0);
|
||||
out:
|
||||
- (void)fclose(fp);
|
||||
+ _fclose(fp, path);
|
||||
}
|
||||
|
||||
/* Select sector/align size for a new VG based on what the device reports for
|
||||
@@ -479,6 +551,7 @@ static int _lease_corrupt_error(int rv)
|
||||
{
|
||||
if (rv == SANLK_LEADER_MAGIC ||
|
||||
rv == SANLK_LEADER_VERSION ||
|
||||
+ rv == SANLK_LEADER_DIFF ||
|
||||
rv == SANLK_LEADER_LOCKSPACE ||
|
||||
rv == SANLK_LEADER_RESOURCE ||
|
||||
rv == SANLK_LEADER_CHECKSUM ||
|
||||
@@ -509,8 +582,10 @@ static int read_lockspace_info(char *path, uint32_t host_id, int *sector_size, i
|
||||
#endif
|
||||
rv = sanlock_read_lockspace(&ss, 0, &io_timeout);
|
||||
|
||||
- if (_lease_corrupt_error(rv))
|
||||
+ if (_lease_corrupt_error(rv)) {
|
||||
+ log_error("read_lockspace_info %s %u corrupt lease error %d", path, host_id, rv);
|
||||
return -ELOCKREPAIR;
|
||||
+ }
|
||||
|
||||
if (rv < 0) {
|
||||
log_error("read_lockspace_info %s %u error %d", path, host_id, rv);
|
||||
@@ -1471,7 +1546,7 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes)
|
||||
* This should also not create any major problems.
|
||||
*/
|
||||
|
||||
-int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation)
|
||||
+int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair)
|
||||
{
|
||||
struct stat st;
|
||||
struct lm_sanlock *lms = NULL;
|
||||
@@ -1486,6 +1561,7 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation
|
||||
int sector_size = 0;
|
||||
int align_size = 0;
|
||||
int align_mb = 0;
|
||||
+ int retries = 0;
|
||||
int gl_found;
|
||||
int ret, rv;
|
||||
|
||||
@@ -1502,6 +1578,8 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation
|
||||
memset(killargs, 0, sizeof(killargs));
|
||||
snprintf(killargs, SANLK_PATH_LEN, "--kill %s", ls->vg_name);
|
||||
|
||||
+ log_debug("S %s prepare_lockspace_san host_id %u repair %d", ls->name, ls->host_id, repair);
|
||||
+
|
||||
rv = check_args_version(ls->vg_args, VG_LOCK_ARGS_MAJOR);
|
||||
if (rv < 0) {
|
||||
ret = -EARGS;
|
||||
@@ -1602,7 +1680,63 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ repair_retry:
|
||||
+ sector_size = 0;
|
||||
+ align_size = 0;
|
||||
+
|
||||
rv = read_lockspace_info(disk_path, lms->ss.host_id, §or_size, &align_size, &align_mb, &ss_flags, &rs_flags, &hs);
|
||||
+
|
||||
+#if LOCKDSANLOCK_SUPPORT >= 410
|
||||
+ if ((rv == -ELOCKREPAIR) && repair && !retries) {
|
||||
+ uint64_t generation = 0;
|
||||
+ uint32_t host_id = 0;
|
||||
+
|
||||
+ rv = read_info_file(ls, &host_id, &generation, §or_size, &align_size);
|
||||
+ if (rv < 0) {
|
||||
+ log_error("S %s prepare_lockspace_san cannot repair lockspace no info file", lsname);
|
||||
+ ret = -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (host_id != lms->ss.host_id) {
|
||||
+ log_error("S %s prepare_lockspace_san cannot repair lockspace other info host_id", lsname);
|
||||
+ ret = -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ hs.generation = generation;
|
||||
+
|
||||
+ if (sector_size == 512) {
|
||||
+ lms->ss.flags |= SANLK_LSF_SECTOR512;
|
||||
+ lms->ss.flags |= SANLK_LSF_ALIGN1M;
|
||||
+ } else if (sector_size == 4096) {
|
||||
+ lms->ss.flags |= SANLK_LSF_SECTOR4K;
|
||||
+ if (align_size == ONE_MB)
|
||||
+ lms->ss.flags |= SANLK_LSF_ALIGN1M;
|
||||
+ else if (align_size == 2 * ONE_MB)
|
||||
+ lms->ss.flags |= SANLK_LSF_ALIGN2M;
|
||||
+ else if (align_size == 4 * ONE_MB)
|
||||
+ lms->ss.flags |= SANLK_LSF_ALIGN4M;
|
||||
+ else if (align_size == 8 * ONE_MB)
|
||||
+ lms->ss.flags |= SANLK_LSF_ALIGN8M;
|
||||
+ } else {
|
||||
+ log_error("S %s prepare_lockspace_san cannot repair lockspace invalid sector_size", lsname);
|
||||
+ ret = -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ log_debug("S %s prepare_lockspace_san repair host %u lease", lsname, host_id);
|
||||
+
|
||||
+ rv = sanlock_init_lockspace_host(&lms->ss, NULL, generation, 0, 0, 0);
|
||||
+ if (rv < 0) {
|
||||
+ log_error("S %s prepare_lockspace_san repair host %u lease error %d", lsname, host_id, rv);
|
||||
+ ret = -EMANAGER;
|
||||
+ }
|
||||
+ retries = 1;
|
||||
+ goto repair_retry;
|
||||
+ }
|
||||
+#else
|
||||
+ if ((rv == -ELOCKREPAIR) && repair && !retries)
|
||||
+ log_debug("S %s prepare_lockspace_san sanlock does not support repair.", lsname);
|
||||
+#endif
|
||||
+
|
||||
if (rv < 0) {
|
||||
log_error("S %s prepare_lockspace_san cannot read lockspace info %d", lsname, rv);
|
||||
ret = -EMANAGER;
|
||||
@@ -1675,7 +1809,7 @@ out:
|
||||
|
||||
fail:
|
||||
if (lms && lms->sock)
|
||||
- close(lms->sock);
|
||||
+ _close(lms->sock);
|
||||
free(lms);
|
||||
return ret;
|
||||
}
|
||||
@@ -1683,7 +1817,9 @@ fail:
|
||||
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay)
|
||||
{
|
||||
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
|
||||
+ struct sanlk_host *hs = NULL;
|
||||
uint32_t flags = 0;
|
||||
+ int count = 0;
|
||||
int rv;
|
||||
|
||||
if (daemon_test) {
|
||||
@@ -1710,6 +1846,33 @@ int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ rv = sanlock_get_hosts(ls->name, 0, &hs, &count, SANLK_GET_HOST_LOCAL);
|
||||
+ if (rv < 0) {
|
||||
+ log_error("S %s add_lockspace_san add_lockspace get_host error %d", ls->name, rv);
|
||||
+ goto fail_rem;
|
||||
+ }
|
||||
+
|
||||
+ if (!count || !hs) {
|
||||
+ log_error("S %s add_lockspace_san add_lockspace get_host empty", ls->name);
|
||||
+ goto fail_rem;
|
||||
+ }
|
||||
+
|
||||
+ if ((uint32_t)hs->host_id != ls->host_id) {
|
||||
+ log_error("S %s add_lockspace_san add_lockspace get_host invalid host_id", ls->name);
|
||||
+ goto fail_rem;
|
||||
+ }
|
||||
+
|
||||
+ if (!hs->generation) {
|
||||
+ log_error("S %s add_lockspace_san add_lockspace get_host zero generation", ls->name);
|
||||
+ goto fail_rem;
|
||||
+ }
|
||||
+
|
||||
+ ls->generation = hs->generation;
|
||||
+
|
||||
+ free(hs);
|
||||
+
|
||||
+ write_info_file(ls);
|
||||
+
|
||||
/*
|
||||
* Don't let the lockspace be cleanly released if orphan locks
|
||||
* exist, because the orphan locks are still protecting resources
|
||||
@@ -1721,17 +1884,17 @@ int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok,
|
||||
rv = sanlock_set_config(ls->name, 0, SANLK_CONFIG_USED_BY_ORPHANS, NULL);
|
||||
if (rv < 0) {
|
||||
log_error("S %s add_lockspace_san set_config error %d", ls->name, rv);
|
||||
- sanlock_rem_lockspace(&lms->ss, 0);
|
||||
- goto fail;
|
||||
+ goto fail_rem;
|
||||
}
|
||||
|
||||
out:
|
||||
log_debug("S %s add_lockspace_san done", ls->name);
|
||||
return 0;
|
||||
|
||||
+fail_rem:
|
||||
+ sanlock_rem_lockspace(&lms->ss, 0);
|
||||
fail:
|
||||
- if (close(lms->sock))
|
||||
- log_error("failed to close sanlock daemon socket connection");
|
||||
+ _close(lms->sock);
|
||||
free(lms);
|
||||
ls->lm_data = NULL;
|
||||
return rv;
|
||||
@@ -1767,8 +1930,7 @@ int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
|
||||
}
|
||||
}
|
||||
|
||||
- if (close(lms->sock))
|
||||
- log_error("failed to close sanlock daemon socket connection");
|
||||
+ _close(lms->sock);
|
||||
out:
|
||||
free(lms);
|
||||
ls->lm_data = NULL;
|
||||
@@ -1845,7 +2007,7 @@ static const char *_host_flags_to_str(uint32_t flags)
|
||||
|
||||
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int *retry, struct owner *owner,
|
||||
- int adopt_only, int adopt_ok)
|
||||
+ int adopt_only, int adopt_ok, int repair)
|
||||
{
|
||||
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
|
||||
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
|
||||
@@ -1857,6 +2019,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
uint32_t flags = 0;
|
||||
struct val_blk vb = { 0 };
|
||||
int added = 0;
|
||||
+ int retries = 0;
|
||||
int rv;
|
||||
|
||||
if (!r->lm_init) {
|
||||
@@ -1956,6 +2119,8 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
memset(&opt, 0, sizeof(opt));
|
||||
sprintf(opt.owner_name, "%s", "lvmlockd");
|
||||
|
||||
+ repair_retry:
|
||||
+
|
||||
#if LOCKDSANLOCK_SUPPORT >= 400
|
||||
rv = sanlock_acquire2(lms->sock, -1, flags, rs, &opt, &owner_host, &owner_name);
|
||||
#else
|
||||
@@ -2068,9 +2233,20 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
return -EIOTIMEOUT;
|
||||
}
|
||||
|
||||
+ if (_lease_corrupt_error(rv) && repair && !retries) {
|
||||
+ log_debug("%s:%s lock_san acquire lease_corrupt %d repair", ls->name, r->name, rv);
|
||||
+
|
||||
+ rv = sanlock_write_resource(rs, 0, 0, 0);
|
||||
+ if (rv < 0) {
|
||||
+ log_error("%s:%s lock_san acquire lease repair write_resource error %d", ls->name, r->name, rv);
|
||||
+ return rv;
|
||||
+ }
|
||||
+ retries = 1;
|
||||
+ goto repair_retry;
|
||||
+ }
|
||||
+
|
||||
if (rv < 0) {
|
||||
- log_error("%s:%s lock_san acquire error %d",
|
||||
- ls->name, r->name, rv);
|
||||
+ log_error("%s:%s lock_san acquire error %d", ls->name, r->name, rv);
|
||||
|
||||
/* if the gl has been disabled, remove and free the gl resource */
|
||||
if ((rv == SANLK_LEADER_RESOURCE) && (r->type == LD_RT_GL)) {
|
||||
@@ -2094,8 +2270,10 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
rv == SANLK_DBLOCK_WRITE)
|
||||
return -ELOCKIO;
|
||||
|
||||
- if (_lease_corrupt_error(rv))
|
||||
+ if (_lease_corrupt_error(rv)) {
|
||||
+ log_debug("%s:%s lock_san lease corrupt repair %d retries %d", ls->name, r->name, repair, retries);
|
||||
return -ELOCKREPAIR;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* The sanlock lockspace can disappear if the lease storage fails,
|
||||
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
|
||||
index f86007858..68dea52e0 100644
|
||||
--- a/lib/locking/lvmlockd.c
|
||||
+++ b/lib/locking/lvmlockd.c
|
||||
@@ -1466,11 +1466,17 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists
|
||||
|
||||
if ((cmd->lockopt & LOCKOPT_NODELAY) ||
|
||||
(cmd->lockopt & LOCKOPT_ADOPTLS) ||
|
||||
- (cmd->lockopt & LOCKOPT_ADOPT)) {
|
||||
- (void) dm_snprintf(opt_buf, sizeof(opt_buf), "%s%s%s",
|
||||
- (cmd->lockopt & LOCKOPT_NODELAY) ? "nodelay," : "",
|
||||
- (cmd->lockopt & LOCKOPT_ADOPTLS) ? "adopt_only" : "",
|
||||
- (cmd->lockopt & LOCKOPT_ADOPT) ? "adopt" : "");
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPT) ||
|
||||
+ (cmd->lockopt & LOCKOPT_REPAIRVG) ||
|
||||
+ (cmd->lockopt & LOCKOPT_REPAIR)) {
|
||||
+ if (dm_snprintf(opt_buf, sizeof(opt_buf), "%s%s%s%s",
|
||||
+ (cmd->lockopt & LOCKOPT_NODELAY) ? "nodelay," : "",
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPTLS) ? "adopt_only," : "",
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPT) ? "adopt," : "",
|
||||
+ (cmd->lockopt & (LOCKOPT_REPAIR|LOCKOPT_REPAIRVG)) ? "repair" : "") < 0) {
|
||||
+ log_error("Options string too long %x", cmd->lockopt);
|
||||
+ return 0;
|
||||
+ }
|
||||
opts = opt_buf;
|
||||
}
|
||||
|
||||
@@ -1967,6 +1973,7 @@ out:
|
||||
int lockd_global(struct cmd_context *cmd, const char *def_mode)
|
||||
{
|
||||
struct owner owner = { 0 };
|
||||
+ char opt_buf[64] = {};
|
||||
const char *mode = NULL;
|
||||
const char *opts = NULL;
|
||||
uint32_t lockd_flags;
|
||||
@@ -1996,10 +2003,19 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (cmd->lockopt & LOCKOPT_ADOPTGL)
|
||||
- opts = "adopt_only";
|
||||
- else if (cmd->lockopt & LOCKOPT_ADOPT)
|
||||
- opts = "adopt";
|
||||
+ if ((cmd->lockopt & LOCKOPT_ADOPTGL) ||
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPT) ||
|
||||
+ (cmd->lockopt & LOCKOPT_REPAIRGL) ||
|
||||
+ (cmd->lockopt & LOCKOPT_REPAIR)) {
|
||||
+ if (dm_snprintf(opt_buf, sizeof(opt_buf), "%s%s%s",
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPTGL) ? "adopt_only" : "",
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPT) ? "adopt" : "",
|
||||
+ (cmd->lockopt & (LOCKOPT_REPAIR|LOCKOPT_REPAIRGL)) ? "repair" : "") < 0) {
|
||||
+ log_error("Options string too long %x", cmd->lockopt);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ opts = opt_buf;
|
||||
+ }
|
||||
|
||||
if (!strcmp(mode, "sh") && cmd->lockd_global_ex)
|
||||
return 1;
|
||||
@@ -2255,6 +2271,7 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
|
||||
uint32_t flags, uint32_t *lockd_state)
|
||||
{
|
||||
struct owner owner = { 0 };
|
||||
+ char opt_buf[64] = {};
|
||||
const char *mode = NULL;
|
||||
const char *opts = NULL;
|
||||
uint32_t lockd_flags;
|
||||
@@ -2332,6 +2349,20 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
|
||||
else if (cmd->lockopt & LOCKOPT_ADOPT)
|
||||
opts = "adopt";
|
||||
|
||||
+ if ((cmd->lockopt & LOCKOPT_ADOPTVG) ||
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPT) ||
|
||||
+ (cmd->lockopt & LOCKOPT_REPAIRVG) ||
|
||||
+ (cmd->lockopt & LOCKOPT_REPAIR)) {
|
||||
+ if (dm_snprintf(opt_buf, sizeof(opt_buf), "%s%s%s",
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPTVG) ? "adopt_only" : "",
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPT) ? "adopt" : "",
|
||||
+ (cmd->lockopt & (LOCKOPT_REPAIR|LOCKOPT_REPAIRVG)) ? "repair" : "") < 0) {
|
||||
+ log_error("Options string too long %x.", cmd->lockopt);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ opts = opt_buf;
|
||||
+ }
|
||||
+
|
||||
if (!strcmp(mode, "ex"))
|
||||
*lockd_state |= LDST_EX;
|
||||
|
||||
@@ -2792,11 +2823,17 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
|
||||
|
||||
if ((flags & LDLV_PERSISTENT) ||
|
||||
(cmd->lockopt & LOCKOPT_ADOPTLV) ||
|
||||
- (cmd->lockopt & LOCKOPT_ADOPT)) {
|
||||
- (void) dm_snprintf(opt_buf, sizeof(opt_buf), "%s%s%s",
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPT) ||
|
||||
+ (cmd->lockopt & LOCKOPT_REPAIRLV) ||
|
||||
+ (cmd->lockopt & LOCKOPT_REPAIR)) {
|
||||
+ if (dm_snprintf(opt_buf, sizeof(opt_buf), "%s%s%s%s",
|
||||
(flags & LDLV_PERSISTENT) ? "persistent," : "",
|
||||
(cmd->lockopt & LOCKOPT_ADOPTLV) ? "adopt_only" : "",
|
||||
- (cmd->lockopt & LOCKOPT_ADOPT) ? "adopt" : "");
|
||||
+ (cmd->lockopt & LOCKOPT_ADOPT) ? "adopt" : "",
|
||||
+ (cmd->lockopt & (LOCKOPT_REPAIR|LOCKOPT_REPAIRLV)) ? "repair" : "") < 0) {
|
||||
+ log_error("Options string too long %x.", cmd->lockopt);
|
||||
+ return 0;
|
||||
+ }
|
||||
opts = opt_buf;
|
||||
}
|
||||
|
||||
@@ -4397,6 +4434,14 @@ void lockd_lockopt_get_flags(const char *str, uint32_t *flags)
|
||||
*flags |= LOCKOPT_ADOPT;
|
||||
else if (!strcmp(argv[i], "nodelay"))
|
||||
*flags |= LOCKOPT_NODELAY;
|
||||
+ else if (!strcmp(argv[i], "repair"))
|
||||
+ *flags |= LOCKOPT_REPAIR;
|
||||
+ else if (!strcmp(argv[i], "repairgl"))
|
||||
+ *flags |= LOCKOPT_REPAIRGL;
|
||||
+ else if (!strcmp(argv[i], "repairvg"))
|
||||
+ *flags |= LOCKOPT_REPAIRVG;
|
||||
+ else if (!strcmp(argv[i], "repairlv"))
|
||||
+ *flags |= LOCKOPT_REPAIRLV;
|
||||
else
|
||||
log_warn("Ignoring unknown lockopt value: %s", argv[i]);
|
||||
}
|
||||
diff --git a/lib/locking/lvmlockd.h b/lib/locking/lvmlockd.h
|
||||
index 85295852c..18f01cd23 100644
|
||||
--- a/lib/locking/lvmlockd.h
|
||||
+++ b/lib/locking/lvmlockd.h
|
||||
@@ -58,6 +58,10 @@
|
||||
#define LOCKOPT_ADOPTLV 0x00001000
|
||||
#define LOCKOPT_ADOPT 0x00002000
|
||||
#define LOCKOPT_NODELAY 0x00004000
|
||||
+#define LOCKOPT_REPAIR 0x00008000
|
||||
+#define LOCKOPT_REPAIRGL 0x00010000
|
||||
+#define LOCKOPT_REPAIRVG 0x00020000
|
||||
+#define LOCKOPT_REPAIRLV 0x00040000
|
||||
|
||||
#ifdef LVMLOCKD_SUPPORT
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,134 +0,0 @@
|
||||
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/54] device_id: fix search on filtered device
|
||||
|
||||
When devnames are used as device ids and devnames change,
|
||||
then new devices need to be located for the PVs. If the old
|
||||
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.34.3
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
From 4659eb9d2a7b58a9b199d7cf2ccaaf32d6605a76 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Wed, 9 Jul 2025 12:48:48 +0200
|
||||
Subject: [PATCH 10/47] udev: fix autoactivation on top of loop dev PVs
|
||||
|
||||
We already check loop devices for LVM_LOOP_PV_ACTIVATED="1" in udev
|
||||
rules to see if have executed pvscan before. If that is the case, we
|
||||
don't want to execute it again to avoid VG reactivation.
|
||||
|
||||
However, the rules missed the IMPORT{db}="LVM_LOOP_PV_ACTIVATED" rule
|
||||
to actually get the value already stored in udev db from previous event.
|
||||
As a result, the pvscan executed on each CHANGE udev event, hence the
|
||||
VG autoactivation triggered each time as well.
|
||||
|
||||
Fix this by adding the missing IMPORT{db}="LVM_LOOP_PV_ACTIVATED" rule
|
||||
(just like we already do for MD devices).
|
||||
|
||||
Note: Keep the behavior for ADD events. That is, we still want the
|
||||
autoactivation to trigger each time, otherwise coldplug will not work
|
||||
(again, we have the same principle used for MD devices).
|
||||
|
||||
(cherry picked from commit bd26e768efa534ba95f801c411a2a9581992a993)
|
||||
---
|
||||
WHATS_NEW | 4 ++++
|
||||
udev/69-dm-lvm.rules.in | 1 +
|
||||
2 files changed, 5 insertions(+)
|
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW
|
||||
index 635651863..e8db60d53 100644
|
||||
--- a/WHATS_NEW
|
||||
+++ b/WHATS_NEW
|
||||
@@ -1,3 +1,7 @@
|
||||
+Version 2.03.34 -
|
||||
+==================
|
||||
+ Fix autoactivation on top of loop dev PVs to trigger once for change uevents.
|
||||
+
|
||||
Version 2.03.33 - 27th June 2025
|
||||
================================
|
||||
Various spelling, grammar, formatting, test, and build script improvements.
|
||||
diff --git a/udev/69-dm-lvm.rules.in b/udev/69-dm-lvm.rules.in
|
||||
index f7a6eef8f..adcf63453 100644
|
||||
--- a/udev/69-dm-lvm.rules.in
|
||||
+++ b/udev/69-dm-lvm.rules.in
|
||||
@@ -52,6 +52,7 @@ GOTO="lvm_end"
|
||||
# Loop device:
|
||||
LABEL="next"
|
||||
KERNEL!="loop[0-9]*", GOTO="next"
|
||||
+IMPORT{db}="LVM_LOOP_PV_ACTIVATED"
|
||||
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"
|
||||
GOTO="lvm_end"
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,102 +0,0 @@
|
||||
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/54] device_id: searched_devnames improvements
|
||||
|
||||
Remove the searched_devnames file in a couple more places:
|
||||
. When hints need refreshing it's possible that a missing
|
||||
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.34.3
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
From 6ca7cd60fd6afcc0f95dfe20d33044a319621b6d Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Fri, 18 Jul 2025 15:06:36 +0200
|
||||
Subject: [PATCH 11/47] lv_manip.c: fix lvresize corruption in LV->crypt->FS
|
||||
stack if near crypt min size limit
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
If we have LV->crypt->FS stack, check that the adjustment for the crypt
|
||||
data offset will left space for the crypt data itself. Fix possible underflow.
|
||||
|
||||
Example:
|
||||
|
||||
❯ lvs -o name,size vg/lvol0
|
||||
lv_name lv_size
|
||||
lvol0 124.00m
|
||||
|
||||
❯ lsblk /dev/vg/lvol0
|
||||
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
|
||||
vg-lvol0 252:2 0 124M 0 lvm
|
||||
└─a 252:4 0 108M 0 crypt
|
||||
|
||||
Before this patch (the incorrect resulting underflowed file system size after adjustment
|
||||
for crypt data offset, crypt data then severed by the LV resize without proper
|
||||
crypt resize beforehand):
|
||||
|
||||
❯ lvreduce --yes --resizefs -L -123M vg/lvol0
|
||||
Rounding size to boundary between physical extents: 120.00 MiB.
|
||||
Checking crypt device /dev/dm-4 on LV vg/lvol0.
|
||||
File system size 18446744073696968704b is adjusted for crypt data offset 16777216b.
|
||||
File system ext4+crypto_LUKS found on vg/lvol0.
|
||||
File system size (108.00 MiB) is smaller than the requested size (<16.00 EiB).
|
||||
File system reduce is not needed, skipping.
|
||||
crypt device is already reduced to 113246208 bytes.
|
||||
Size of logical volume vg/lvol0 changed from 124.00 MiB (31 extents) to 4.00 MiB (1 extents).
|
||||
Logical volume vg/lvol0 successfully resized.
|
||||
|
||||
With this patch applied:
|
||||
|
||||
❯ lvreduce --yes --resizefs -L -123M vg/lvol0
|
||||
Rounding size to boundary between physical extents: 120.00 MiB.
|
||||
Checking crypt device /dev/dm-4 on LV vg/lvol0.
|
||||
Crypt header requires 16.00 MiB, not enough space left for crypt data.
|
||||
|
||||
(cherry picked from commit 5da3676ff3901fd099dcdd2bd7478fa9ea4f54dc)
|
||||
---
|
||||
WHATS_NEW | 1 +
|
||||
lib/metadata/lv_manip.c | 5 +++++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW
|
||||
index e8db60d53..723638042 100644
|
||||
--- a/WHATS_NEW
|
||||
+++ b/WHATS_NEW
|
||||
@@ -1,5 +1,6 @@
|
||||
Version 2.03.34 -
|
||||
==================
|
||||
+ Fix lvresize corruption in LV->crypt->FS stack if near crypt min size limit.
|
||||
Fix autoactivation on top of loop dev PVs to trigger once for change uevents.
|
||||
|
||||
Version 2.03.33 - 27th June 2025
|
||||
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
|
||||
index 193b1f403..577ffd0b3 100644
|
||||
--- a/lib/metadata/lv_manip.c
|
||||
+++ b/lib/metadata/lv_manip.c
|
||||
@@ -6478,6 +6478,11 @@ static int _fs_reduce(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
* 2MB for LUKS1 and 16MB for LUKS2.)
|
||||
*/
|
||||
if (fsinfo.needs_crypt) {
|
||||
+ if (fsinfo.crypt_offset_bytes >= fsinfo.new_size_bytes) {
|
||||
+ log_error("Crypt header requires %s, not enough space left for crypt data.",
|
||||
+ display_size(cmd, fsinfo.crypt_offset_bytes >> SECTOR_SHIFT));
|
||||
+ goto out;
|
||||
+ }
|
||||
fsinfo.new_size_bytes -= fsinfo.crypt_offset_bytes;
|
||||
log_print_unless_silent("File system size %llub is adjusted for crypt data offset %ub.",
|
||||
(unsigned long long)fsinfo.new_size_bytes, fsinfo.crypt_offset_bytes);
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
From 6d7837dc2b93a51bfdad7c796d2b8e3f7fe9f938 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Mon, 21 Jul 2025 13:40:30 +0200
|
||||
Subject: [PATCH 12/47] device_id: always log_error on device ids write error
|
||||
|
||||
(cherry picked from commit 03e3b27ba094cc6e58113713a0d36a8b3190a2f3)
|
||||
---
|
||||
lib/device/device_id.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index a3f341bfc..76165559f 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -1730,12 +1730,12 @@ int device_ids_write(struct cmd_context *cmd)
|
||||
log_sys_debug("unlink", tmppath);
|
||||
|
||||
if (!(fp = fopen(tmppath, "w+"))) {
|
||||
- log_warn("Cannot open to write %s.", tmppath);
|
||||
+ log_error("Cannot open to write %s.", tmppath);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((dir_fd = open(dirpath, O_RDONLY)) < 0) {
|
||||
- log_sys_debug("open", dirpath);
|
||||
+ log_sys_error("open", dirpath);
|
||||
goto out;
|
||||
}
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
From f697518550298ec4a571b72f0f6395b42e6fc85d Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Mon, 21 Jul 2025 13:41:32 +0200
|
||||
Subject: [PATCH 13/47] lvmdevices: return error if writing device ids fail for
|
||||
--delldev
|
||||
|
||||
(cherry picked from commit 1cd2f35655e79d880d28914998b738baa0be5c07)
|
||||
---
|
||||
tools/lvmdevices.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c
|
||||
index fd766e102..d7d3af59b 100644
|
||||
--- a/tools/lvmdevices.c
|
||||
+++ b/tools/lvmdevices.c
|
||||
@@ -925,7 +925,8 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
dev_del:
|
||||
dm_list_del(&du->list);
|
||||
free_du(du);
|
||||
- device_ids_write(cmd);
|
||||
+ if (!device_ids_write(cmd))
|
||||
+ goto_bad;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -967,7 +968,8 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
dm_list_del(&du->list);
|
||||
free_du(du);
|
||||
- device_ids_write(cmd);
|
||||
+ if (!device_ids_write(cmd))
|
||||
+ goto_bad;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1008,7 +1010,8 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
|
||||
free_du(du);
|
||||
- device_ids_write(cmd);
|
||||
+ if (!device_ids_write(cmd))
|
||||
+ goto_bad;
|
||||
goto out;
|
||||
}
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
24
SOURCES/0014-WHATS_NEW-update.patch
Normal file
24
SOURCES/0014-WHATS_NEW-update.patch
Normal file
@ -0,0 +1,24 @@
|
||||
From 7f6e08eb6d9dfdf82c50151b832c3f5663ea5b9b Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Tue, 22 Jul 2025 09:46:39 +0200
|
||||
Subject: [PATCH 14/47] WHATS_NEW: update
|
||||
|
||||
(cherry picked from commit 986ff7b9cdd6a4af1d79706c80e9660c4ccbf423)
|
||||
---
|
||||
WHATS_NEW | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW
|
||||
index 723638042..41fea1a7a 100644
|
||||
--- a/WHATS_NEW
|
||||
+++ b/WHATS_NEW
|
||||
@@ -1,5 +1,6 @@
|
||||
Version 2.03.34 -
|
||||
==================
|
||||
+ Fix lvmdevices --deldev/--delpvid to error out if devices file not writeable.
|
||||
Fix lvresize corruption in LV->crypt->FS stack if near crypt min size limit.
|
||||
Fix autoactivation on top of loop dev PVs to trigger once for change uevents.
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -0,0 +1,103 @@
|
||||
From cc809a01ac3059fa613473ce45bc75426ab000ad Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Wed, 23 Jul 2025 09:17:36 +0200
|
||||
Subject: [PATCH 15/47] device_id: log_warn instead of log_error in
|
||||
device_ids_write
|
||||
|
||||
It is not always the case that the whole command fails if
|
||||
device_ids_write fail so change all log_error to log_warn and let the
|
||||
caller decide.
|
||||
|
||||
(cherry picked from commit 80144223e700703f76267b8d033e2d7d04156ee9)
|
||||
---
|
||||
lib/device/device_id.c | 20 ++++++++++----------
|
||||
1 file changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index 76165559f..4bb92cb09 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -1730,12 +1730,12 @@ int device_ids_write(struct cmd_context *cmd)
|
||||
log_sys_debug("unlink", tmppath);
|
||||
|
||||
if (!(fp = fopen(tmppath, "w+"))) {
|
||||
- log_error("Cannot open to write %s.", tmppath);
|
||||
+ log_warn("WARNING: %s: cannot open for writing: %s.", tmppath, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((dir_fd = open(dirpath, O_RDONLY)) < 0) {
|
||||
- log_sys_error("open", dirpath);
|
||||
+ log_warn("WARNING: %s: cannot open directory: %s.", dirpath, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1748,7 +1748,7 @@ int device_ids_write(struct cmd_context *cmd)
|
||||
fb_size = names_len + 256 + (128 * dm_list_size(&cmd->use_devices));
|
||||
|
||||
if (!(fb = malloc(fb_size))) {
|
||||
- log_error("Failed to allocate buffer size %d for devices file.", fb_size);
|
||||
+ log_warn("Failed to allocate buffer size %d for devices file.", fb_size);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1762,7 +1762,7 @@ int device_ids_write(struct cmd_context *cmd)
|
||||
num = snprintf(fb + pos, len - pos, "HOSTNAME=%s\n", cmd->hostname);
|
||||
|
||||
if (num >= len - pos) {
|
||||
- log_error("Failed to write buffer for devices file content.");
|
||||
+ log_warn("Failed to write buffer for devices file content.");
|
||||
goto out;
|
||||
}
|
||||
pos += num;
|
||||
@@ -1772,7 +1772,7 @@ int device_ids_write(struct cmd_context *cmd)
|
||||
|
||||
num = snprintf(fb + pos, len - pos, "%s\n", version_buf);
|
||||
if (num >= len - pos) {
|
||||
- log_error("Failed to write buffer for devices file content.");
|
||||
+ log_warn("Failed to write buffer for devices file content.");
|
||||
goto out;
|
||||
}
|
||||
pos += num;
|
||||
@@ -1801,7 +1801,7 @@ int device_ids_write(struct cmd_context *cmd)
|
||||
du->idname ?: ".", devname, pvid);
|
||||
}
|
||||
if (num >= len - pos) {
|
||||
- log_error("Failed to write buffer for devices file content.");
|
||||
+ log_warn("Failed to write buffer for devices file content.");
|
||||
goto out;
|
||||
}
|
||||
pos += num;
|
||||
@@ -1820,17 +1820,17 @@ int device_ids_write(struct cmd_context *cmd)
|
||||
"# HASH=%u\n",
|
||||
cmd->name, cmd->device_ids_auto_import ? " (auto)" : "",
|
||||
getpid(), ctime(&t), hash)) < 0) {
|
||||
- log_error("Failed to write buffer for devices file content.");
|
||||
+ log_warn("Failed to write buffer for devices file content.");
|
||||
goto out;
|
||||
}
|
||||
fc[fc_bytes] = '\0';
|
||||
|
||||
if (fputs(fc, fp) < 0) {
|
||||
- log_error("Failed to write devices file header.");
|
||||
+ log_warn("Failed to write devices file header.");
|
||||
goto out;
|
||||
}
|
||||
if (fputs(fb, fp) < 0) {
|
||||
- log_error("Failed to write devices file.");
|
||||
+ log_warn("Failed to write devices file.");
|
||||
goto out;
|
||||
}
|
||||
if (fflush(fp) < 0)
|
||||
@@ -1845,7 +1845,7 @@ int device_ids_write(struct cmd_context *cmd)
|
||||
fp = NULL;
|
||||
|
||||
if (rename(tmppath, cmd->devices_file_path) < 0) {
|
||||
- log_error("Failed to replace devices file.");
|
||||
+ log_warn("WARNING: %s: failed to replace devices file: %s", cmd->devices_file_path, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,416 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -0,0 +1,97 @@
|
||||
From e845c1a99d660295735d6fd0dd5a048f3980fce7 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Wed, 23 Jul 2025 09:24:07 +0200
|
||||
Subject: [PATCH 16/47] lvmdevices: log_error when writing devices file fails
|
||||
|
||||
(cherry picked from commit d5abc55fcf31dbd8b52036340e085c9f7e8d61b2)
|
||||
---
|
||||
tools/lvmdevices.c | 25 +++++++++++++++++++------
|
||||
1 file changed, 19 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c
|
||||
index d7d3af59b..7f10038d4 100644
|
||||
--- a/tools/lvmdevices.c
|
||||
+++ b/tools/lvmdevices.c
|
||||
@@ -560,6 +560,7 @@ restart4:
|
||||
|
||||
int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
+ static const char failed_to_write_devices_file_msg[] = "Failed to write devices file.";
|
||||
struct dm_list search_pvids;
|
||||
struct dm_list found_devs;
|
||||
struct dm_list scan_devs;
|
||||
@@ -752,8 +753,10 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
if (arg_is_set(cmd, update_ARG)) {
|
||||
if (update_needed || !dm_list_empty(&found_devs) || cmd->devices_file_hash_mismatch) {
|
||||
- if (!device_ids_write(cmd))
|
||||
+ if (!device_ids_write(cmd)) {
|
||||
+ log_error(failed_to_write_devices_file_msg);
|
||||
goto_bad;
|
||||
+ }
|
||||
log_print("Updated devices file to version %s", devices_file_version());
|
||||
} else {
|
||||
log_print("No update for devices file is needed.");
|
||||
@@ -835,8 +838,10 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
if (!device_id_add(cmd, dev, dev->pvid, deviceidtype, NULL, 1))
|
||||
goto_bad;
|
||||
- if (!device_ids_write(cmd))
|
||||
+ if (!device_ids_write(cmd)) {
|
||||
+ log_error(failed_to_write_devices_file_msg);
|
||||
goto_bad;
|
||||
+ }
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -884,8 +889,10 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
if (!device_id_add(cmd, devl->dev, devl->dev->pvid, deviceidtype, NULL, 1))
|
||||
goto_bad;
|
||||
}
|
||||
- if (!device_ids_write(cmd))
|
||||
+ if (!device_ids_write(cmd)) {
|
||||
+ log_error(failed_to_write_devices_file_msg);
|
||||
goto_bad;
|
||||
+ }
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -925,8 +932,10 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
dev_del:
|
||||
dm_list_del(&du->list);
|
||||
free_du(du);
|
||||
- if (!device_ids_write(cmd))
|
||||
+ if (!device_ids_write(cmd)) {
|
||||
+ log_error(failed_to_write_devices_file_msg);
|
||||
goto_bad;
|
||||
+ }
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -968,8 +977,10 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
dm_list_del(&du->list);
|
||||
free_du(du);
|
||||
- if (!device_ids_write(cmd))
|
||||
+ if (!device_ids_write(cmd)) {
|
||||
+ log_error(failed_to_write_devices_file_msg);
|
||||
goto_bad;
|
||||
+ }
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1010,8 +1021,10 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
|
||||
free_du(du);
|
||||
- if (!device_ids_write(cmd))
|
||||
+ if (!device_ids_write(cmd)) {
|
||||
+ log_error(failed_to_write_devices_file_msg);
|
||||
goto_bad;
|
||||
+ }
|
||||
goto out;
|
||||
}
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
From 5653b3e38962d81264dd45db1aad356f6f59dd6c Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Fri, 8 Aug 2025 14:06:24 -0500
|
||||
Subject: [PATCH 17/47] lvmlockd: --lockopt was mistakenly ignored when
|
||||
--nolocking was set
|
||||
|
||||
(cherry picked from commit 3dc5c3fc9e1dcbca8f74fa5e7df3e0750d66975a)
|
||||
---
|
||||
tools/lvmcmdline.c | 24 +++++++++++++-----------
|
||||
1 file changed, 13 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
|
||||
index 22ae1e3bb..ebb1b87c9 100644
|
||||
--- a/tools/lvmcmdline.c
|
||||
+++ b/tools/lvmcmdline.c
|
||||
@@ -2969,6 +2969,19 @@ static int _init_lvmlockd(struct cmd_context *cmd)
|
||||
if (use_lvmlockd)
|
||||
cmd->enable_hints = 0;
|
||||
|
||||
+ if (arg_is_set(cmd, lockopt_ARG)) {
|
||||
+ lockd_lockopt_get_flags(arg_str_value(cmd, lockopt_ARG, ""), &cmd->lockopt);
|
||||
+
|
||||
+ if (use_lvmlockd) {
|
||||
+ if (cmd->lockopt & LOCKOPT_SKIPLV)
|
||||
+ cmd->lockd_lv_disable = 1;
|
||||
+ if (cmd->lockopt & LOCKOPT_SKIPVG)
|
||||
+ cmd->lockd_vg_disable = 1;
|
||||
+ if (cmd->lockopt & LOCKOPT_SKIPGL)
|
||||
+ cmd->lockd_gl_disable = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (use_lvmlockd && arg_is_set(cmd, nolocking_ARG)) {
|
||||
/* --nolocking is only allowed with vgs/lvs/pvs commands */
|
||||
cmd->lockd_gl_disable = 1;
|
||||
@@ -2977,17 +2990,6 @@ static int _init_lvmlockd(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
- if (use_lvmlockd && arg_is_set(cmd, lockopt_ARG)) {
|
||||
- lockd_lockopt_get_flags(arg_str_value(cmd, lockopt_ARG, ""), &cmd->lockopt);
|
||||
-
|
||||
- if (cmd->lockopt & LOCKOPT_SKIPLV)
|
||||
- cmd->lockd_lv_disable = 1;
|
||||
- if (cmd->lockopt & LOCKOPT_SKIPVG)
|
||||
- cmd->lockd_vg_disable = 1;
|
||||
- if (cmd->lockopt & LOCKOPT_SKIPGL)
|
||||
- cmd->lockd_gl_disable = 1;
|
||||
- }
|
||||
-
|
||||
lvmlockd_disconnect(); /* start over when tool context is refreshed */
|
||||
lvmlockd_socket = getenv("LVM_LVMLOCKD_SOCKET");
|
||||
if (!lvmlockd_socket)
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
26
SOURCES/0018-sanlock-match-lm_lock_sanlock-prototype.patch
Normal file
26
SOURCES/0018-sanlock-match-lm_lock_sanlock-prototype.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From a70dd84cfdd897a8b9d8cdddd98caaacaa1dff72 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Wed, 2 Jul 2025 11:46:20 +0200
|
||||
Subject: [PATCH 18/47] sanlock: match lm_lock_sanlock prototype
|
||||
|
||||
(cherry picked from commit 95c77bc922ec9867764ddd95df635444804c12ba)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockd-internal.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-internal.h b/daemons/lvmlockd/lvmlockd-internal.h
|
||||
index 7999c2a03..df69824b6 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-internal.h
|
||||
+++ b/daemons/lvmlockd/lvmlockd-internal.h
|
||||
@@ -634,7 +634,7 @@ static inline int lm_add_resource_sanlock(struct lockspace *ls, struct resource
|
||||
|
||||
static inline int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int *retry, struct owner *owner,
|
||||
- int adopt_only, int adopt_ok)
|
||||
+ int adopt_only, int adopt_ok, int repair)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
From de5bc8c70577b3d7483c43ce373d233d9089a990 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Tue, 1 Jul 2025 10:22:50 -0500
|
||||
Subject: [PATCH 19/47] lvmlockd-sanlock: fix struct pointer in release_rename
|
||||
|
||||
(cherry picked from commit 03a343dc9e49b164fe0d153b0b0dc815f18edd6e)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockd-sanlock.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
index ce5953faf..80def0449 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
@@ -2424,8 +2424,8 @@ static int release_rename(struct lockspace *ls, struct resource *r)
|
||||
memcpy(&rd1, &rds->rs, sizeof(struct rd_sanlock));
|
||||
memcpy(&rd2, &rds->rs, sizeof(struct rd_sanlock));
|
||||
|
||||
- res1 = (struct sanlk_resource *)&rd1;
|
||||
- res2 = (struct sanlk_resource *)&rd2;
|
||||
+ res1 = &rd1.rs;
|
||||
+ res2 = &rd2.rs;
|
||||
|
||||
if (memcmp(res1->name, r->name, SANLK_NAME_LEN))
|
||||
log_error("%s:%s unlock_san release rename bad name %.48s", ls->name, r->name, res1->name);
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -1,50 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
33
SOURCES/0020-lvmlockd-free-structs-in-adopt-error-path.patch
Normal file
33
SOURCES/0020-lvmlockd-free-structs-in-adopt-error-path.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From 20b81f31c29f416a9c397e41d6998b10fc379228 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Tue, 1 Jul 2025 10:53:33 -0500
|
||||
Subject: [PATCH 20/47] lvmlockd: free structs in adopt error path
|
||||
|
||||
(cherry picked from commit fcca60fda61b5a545c936e61380e047deb887779)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockd-core.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
|
||||
index 0cb10369a..369755ac7 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-core.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-core.c
|
||||
@@ -6331,6 +6331,15 @@ static void adopt_locks(void)
|
||||
return;
|
||||
|
||||
fail:
|
||||
+ list_for_each_entry_safe(ls, lsafe, &vg_lockd, list) {
|
||||
+ list_for_each_entry_safe(r, rsafe, &ls->resources, list) {
|
||||
+ list_del(&r->list);
|
||||
+ free_resource(r);
|
||||
+ }
|
||||
+ list_del(&ls->list);
|
||||
+ free(ls);
|
||||
+ }
|
||||
+
|
||||
(void) unlink(adopt_file);
|
||||
log_error("adopt_locks failed, reset host");
|
||||
}
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
From d4406030d3fcaa9286fa9ef86fe4ebed04303bbf Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Tue, 1 Jul 2025 11:23:16 -0500
|
||||
Subject: [PATCH 21/47] lvmlockd-sanlock: check lock_lv_offset_from_args result
|
||||
|
||||
(cherry picked from commit f35f074afdaa52b0db098911d97202b478a33085)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockd-sanlock.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
index 80def0449..89df4ec44 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
@@ -1212,8 +1212,7 @@ int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r)
|
||||
|
||||
strcpy_name_len(rs->name, "#unused", SANLK_NAME_LEN);
|
||||
|
||||
- if (!offset) {
|
||||
- lock_lv_offset_from_args(r->lv_args, &offset);
|
||||
+ if (!offset && !lock_lv_offset_from_args(r->lv_args, &offset)) {
|
||||
rds->rs.disks[0].offset = offset;
|
||||
log_debug("%s:%s free_lv_san lock_args offset %llu", ls->name, r->name, (unsigned long long)offset);
|
||||
}
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,96 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
From 2477a95fe1a47ff4e8c4c8afda7c4b95dddfaeda Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Fri, 5 Sep 2025 12:21:12 -0500
|
||||
Subject: [PATCH 22/47] lvmlockd: always free ls struct after ls thread exits
|
||||
|
||||
The ls struct was being freed after ls thread exit for common stop,
|
||||
but was missing when the ls thread was stopped for drop and rename.
|
||||
Also free ls->actions structs in case any still exist.
|
||||
|
||||
(cherry picked from commit 5b410e589c75d0d540e4ebe4f44cc71b5624cbc6)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockd-core.c | 20 +++++++++-----------
|
||||
1 file changed, 9 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
|
||||
index 369755ac7..f7340ff3e 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-core.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-core.c
|
||||
@@ -3553,6 +3553,7 @@ static int count_lockspace_starting(uint32_t client_id)
|
||||
static int for_each_lockspace(int do_stop, int do_free, int do_force)
|
||||
{
|
||||
struct lockspace *ls, *safe;
|
||||
+ struct action *act, *act2;
|
||||
int need_stop = 0;
|
||||
int need_free = 0;
|
||||
int stop_count = 0;
|
||||
@@ -3605,19 +3606,16 @@ static int for_each_lockspace(int do_stop, int do_free, int do_force)
|
||||
if ((perrno = pthread_join(ls->thread, NULL)))
|
||||
log_error("pthread_join error %d", perrno);
|
||||
|
||||
+ log_debug("free ls struct %s", ls->name);
|
||||
list_del(&ls->list);
|
||||
-
|
||||
- /* FIXME: will free_vg ever not be set? */
|
||||
-
|
||||
- log_debug("free ls %s", ls->name);
|
||||
-
|
||||
- if (ls->free_vg) {
|
||||
- /* In future we may need to free ls->actions here */
|
||||
- free_ls_resources(ls);
|
||||
- free_pvs_path(&ls->pvs);
|
||||
- free(ls);
|
||||
- free_count++;
|
||||
+ list_for_each_entry_safe(act, act2, &ls->actions, list) {
|
||||
+ list_del(&act->list);
|
||||
+ free_action(act);
|
||||
}
|
||||
+ free_ls_resources(ls);
|
||||
+ free_pvs_path(&ls->pvs);
|
||||
+ free(ls);
|
||||
+ free_count++;
|
||||
} else {
|
||||
need_free++;
|
||||
}
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
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/54] 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.34.3
|
||||
|
||||
582
SOURCES/0023-man-lvmlockd-updates.patch
Normal file
582
SOURCES/0023-man-lvmlockd-updates.patch
Normal file
@ -0,0 +1,582 @@
|
||||
From e193db35a368dcd9ac8c9737d774d3552d4cf877 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Tue, 23 Sep 2025 11:09:08 -0500
|
||||
Subject: [PATCH 23/47] man lvmlockd: updates
|
||||
|
||||
Major rewrite of the beginning description/setup/introduction.
|
||||
|
||||
(cherry picked from commit f15d948720b4a8b52b7929856ee52e20ab0da798)
|
||||
---
|
||||
man/lvmlockd.8_main | 470 +++++++++++++++++++++-----------------------
|
||||
1 file changed, 219 insertions(+), 251 deletions(-)
|
||||
|
||||
diff --git a/man/lvmlockd.8_main b/man/lvmlockd.8_main
|
||||
index 0c0c88ddd..621224df7 100644
|
||||
--- a/man/lvmlockd.8_main
|
||||
+++ b/man/lvmlockd.8_main
|
||||
@@ -20,33 +20,44 @@ lvmlockd \(em LVM locking daemon
|
||||
.
|
||||
.SH DESCRIPTION
|
||||
.
|
||||
-LVM commands use lvmlockd to coordinate access to shared storage.
|
||||
+
|
||||
+A shared Volume Group is a VG placed on shared storage devices, e.g. from a
|
||||
+SAN, that can be used by all the hosts that can access the devices. A
|
||||
+shared VG requires the use of lvmlockd, and an external lock manager.
|
||||
+.
|
||||
+.P
|
||||
+Different hosts may activate and use LVs in the same shared VG, and
|
||||
+different hosts can create, extend, or remove LVs in the VG. Locking,
|
||||
+through lvmlockd, ensures this is all done safely and consistently.
|
||||
+LVM commands request locks from lvmlockd, which passes the lock requests
|
||||
+to an external lock manager. Each shared VG has a
|
||||
+.B locktype
|
||||
+attribute, specifying the external lock manager to use for the VG.
|
||||
+.
|
||||
.P
|
||||
-When LVM is used on devices shared by multiple hosts, locks will:
|
||||
+The lock manager options are:
|
||||
+.B sanlock
|
||||
+which places locks on storage space reserved within the VG, and
|
||||
+.B dlm
|
||||
+which uses a network locking protocol, and has additional clustering
|
||||
+requirements.
|
||||
+.
|
||||
+.P
|
||||
+There are three types of locking performed through lvmlockd:
|
||||
.PD 0
|
||||
.IP \[bu] 2
|
||||
-coordinate reading and writing of LVM metadata
|
||||
+per-VG locks protect changes to the VG metadata.
|
||||
.IP \[bu]
|
||||
-validate caching of LVM metadata
|
||||
+LV locks limit LV activation to one host at a time.
|
||||
.IP \[bu]
|
||||
-prevent conflicting activation of logical volumes
|
||||
-.PD
|
||||
-.P
|
||||
-lvmlockd uses an external lock manager to perform basic locking.
|
||||
-.P
|
||||
-Lock manager (lock type) options are:
|
||||
-.
|
||||
-.TP 8
|
||||
-.B sanlock
|
||||
-\(en places locks on disk within LVM storage.
|
||||
-.
|
||||
-.TP
|
||||
-.B dlm
|
||||
-\(en uses network communication and a cluster manager.
|
||||
+A Global lock protects unused PVs and the VG namespace.
|
||||
.PD
|
||||
.
|
||||
.SH OPTIONS
|
||||
.
|
||||
+lvmlockd daemon command line options:
|
||||
+.P
|
||||
+.
|
||||
.TP
|
||||
.BR -h | --help
|
||||
Show this help information.
|
||||
@@ -108,193 +119,212 @@ Override the default sanlock I/O timeout.
|
||||
.BR -A | --adopt " " 0 | 1
|
||||
Enable (1) or disable (0) lock adoption.
|
||||
.
|
||||
-.SH USAGE
|
||||
-.
|
||||
-.SS Initial set up
|
||||
+.SH SETUP
|
||||
.
|
||||
-Setting up LVM to use lvmlockd and a shared VG for the first time includes
|
||||
-some one time set up steps:
|
||||
-.
|
||||
-.SS 1. choose a lock manager
|
||||
-.
|
||||
-.TP 8
|
||||
-.B sanlock
|
||||
-Choose sanlock if dlm/corosync are not otherwise required.
|
||||
-sanlock does not depend on any clustering software or configuration.
|
||||
-.
|
||||
-.TP
|
||||
-.B dlm
|
||||
-If dlm (or corosync) are already being used by other cluster
|
||||
-software, then select dlm. dlm uses corosync which requires additional
|
||||
-configuration beyond the scope of this document. See corosync and dlm
|
||||
-documentation for instructions on configuration, set up and usage.
|
||||
-.
|
||||
-.SS 2. configure hosts to use lvmlockd
|
||||
-.
|
||||
-On all hosts running lvmlockd, configure
|
||||
-.BR lvm.conf (5):
|
||||
+The following steps provide a quick overview of how to use shared VGs.
|
||||
+More details can be found under SETUP DETAILS.
|
||||
.P
|
||||
-.EX
|
||||
-use_lvmlockd = 1
|
||||
-.EE
|
||||
-.
|
||||
-.TP 8
|
||||
-.B sanlock
|
||||
-Assign each host a unique host_id in the range 1-2000 by setting
|
||||
+.I Devices
|
||||
+.P
|
||||
+Identify the shared device(s) that will be used in the shared VG,
|
||||
+and add them to each host's devices file (local device names often
|
||||
+differ, unless a WWN-based name from /dev/disk/by-id is used.)
|
||||
.br
|
||||
-.I #DEFAULT_SYS_DIR#/lvmlocal.conf
|
||||
-local/host_id
|
||||
-.
|
||||
-.SS 3. start lvmlockd
|
||||
-.
|
||||
-Start the lvmlockd daemon.
|
||||
+.B $ lvmdevices --adddev
|
||||
+.I device
|
||||
+.P
|
||||
+.I Configuration
|
||||
+.P
|
||||
+Edit lvm.conf, setting
|
||||
+.B use_lvmlockd=1
|
||||
+on each host using a shared VG.
|
||||
+.P
|
||||
+Edit lvmlocal.conf, setting
|
||||
+.B host_id
|
||||
+on each host (only required when using sanlock.)
|
||||
+The host_id is a unique integer for each host between 1 and 2000.
|
||||
+.P
|
||||
+.I Locking
|
||||
+.P
|
||||
+Start lvmlockd and the external lock manager (sanlock or dlm) on
|
||||
+each host.
|
||||
+.P
|
||||
+.I VG
|
||||
+.P
|
||||
+Create a shared VG from one host (uses the running lock manager):
|
||||
.br
|
||||
-Use systemctl, a cluster resource agent, or run directly, e.g.
|
||||
+.B $ vgcreate --shared
|
||||
+.I VG
|
||||
+.I devices
|
||||
.P
|
||||
-.EX
|
||||
-systemctl start lvmlockd
|
||||
-.EE
|
||||
-.
|
||||
-.SS 4. start lock manager
|
||||
-.
|
||||
-.TP 8
|
||||
-.B sanlock
|
||||
-Start the sanlock and wdmd daemons.
|
||||
+Start the lockspace for the shared VG on all hosts:
|
||||
.br
|
||||
-Use systemctl or run directly, e.g.
|
||||
-.sp
|
||||
-.EX
|
||||
-systemctl start wdmd sanlock
|
||||
-.EE
|
||||
-.
|
||||
-.TP
|
||||
-.B dlm
|
||||
-Start the dlm and corosync daemons.
|
||||
+.B $ vgchange --lockstart
|
||||
+.I VG
|
||||
+.P
|
||||
+.I Usage
|
||||
+.P
|
||||
+Begin using the VG, e.g. creating LVs.
|
||||
+.P
|
||||
+Regular shutdown steps:
|
||||
+.br
|
||||
+ $ vgchange -an VG
|
||||
+.br
|
||||
+ $ vgchange --lockstop VG
|
||||
+.br
|
||||
+ $ stop lvmlockd and lock manager
|
||||
.br
|
||||
-Use systemctl, a cluster resource agent, or run directly, e.g.
|
||||
-.sp
|
||||
-.EX
|
||||
-systemctl start corosync dlm
|
||||
-.EE
|
||||
-.
|
||||
-.SS 5. create VG on shared devices
|
||||
-.
|
||||
-vgcreate --shared <vgname> <devices>
|
||||
.P
|
||||
-The shared option sets the VG lock type to sanlock or dlm depending on
|
||||
-which lock manager is running. LVM commands acquire locks from lvmlockd,
|
||||
-and lvmlockd uses the chosen lock manager.
|
||||
-.
|
||||
-.SS 6. start VG on all hosts
|
||||
-.
|
||||
-.EX
|
||||
-vgchange --lockstart
|
||||
-.EE
|
||||
+Regular startup steps:
|
||||
+.br
|
||||
+ $ start lvmlockd and lock manager
|
||||
+.br
|
||||
+ $ vgchange --lockstart VG
|
||||
.P
|
||||
-Shared VGs must be started before they are used. Starting the VG performs
|
||||
-lock manager initialization that is necessary to begin using locks (i.e.
|
||||
-creating and joining a lockspace). Starting the VG may take some time,
|
||||
-and until the start completes the VG may not be modified or activated.
|
||||
.
|
||||
-.SS 7. create and activate LVs
|
||||
-.
|
||||
-Standard lvcreate and lvchange commands are used to create and activate
|
||||
-LVs in a shared VG.
|
||||
+.SH SETUP DETAILS
|
||||
+.P
|
||||
+.B Identifying devices
|
||||
+.br
|
||||
+Devices often have different local names on each host, e.g. /dev/sda
|
||||
+on one host is named /dev/sdb on another. One method to identify the
|
||||
+same device on each host is to run the command lsblk -o+WWN on each
|
||||
+host, looking for the same WWN, and its corresponding local device name.
|
||||
+Or, the WWN-based device symlinks under /dev/disk/by-id/ can be a
|
||||
+useful way to consistently identify a device across multiple hosts.
|
||||
+.P
|
||||
+.B Device access
|
||||
+.br
|
||||
+On each host, LVM needs to be given access to the shared devices by
|
||||
+adding them to the local system.devices file (unless the devices file
|
||||
+feature has been disabled.) Use the local device name identified
|
||||
+in the previous step, or a WWN-based device symlink, and run the
|
||||
+command lvmdevices --adddev device_path to add each of the shared
|
||||
+devices to the local system.devices file.
|
||||
+Alternatively, after the shared VG has been created from one host,
|
||||
+other hosts can run the command vgimportdevices VG to add devices
|
||||
+from VG to system.devices.
|
||||
+See
|
||||
+.BR lvmdevices (8)
|
||||
+for more information.
|
||||
+.P
|
||||
+.B Config files
|
||||
+.br
|
||||
+After #DEFAULT_SYS_DIR#/lvm.conf use_lvmlockd has been set to 1,
|
||||
+lvm commands will begin attempting to acquire locks from lvmlockd.
|
||||
+Failures to acquire the global lock from lvmlockd may appear until
|
||||
+the first shared VG is operational. These warnings won't interfere
|
||||
+with lvm commands doing read operations, but lvm commands attempting
|
||||
+to write may fail with a global lock error.
|
||||
+.P
|
||||
+The #DEFAULT_SYS_DIR#/lvmlocal.conf host_id setting is only required
|
||||
+when using VGs with lock type sanlock. Each host using sanlock VGs
|
||||
+must be configured with a unique host_id value. Valid host_ids are
|
||||
+integers in the range 1-2000. (The lvmlocal.conf descriptions of
|
||||
+host_id and sanlock_align_size mention special cases with 4K disks
|
||||
+in which the valid host_id range can be smaller, e.g. 1-250.)
|
||||
+.P
|
||||
+.B Lock managers
|
||||
+.br
|
||||
+A specific build of LVM may exclude support for sanlock or dlm
|
||||
+lock managers. To check this, run the command "lvm version" and
|
||||
+look for "--enable-lvmlockd-sanlock" or "--enable-lvmlockd-dlm".
|
||||
+.P
|
||||
+With the --shared option, vgcreate searches for a running lock manager
|
||||
+(dlm or sanlock), and uses the result for the VG lock type.
|
||||
+In place of --shared, vgcreate --locktype sanlock|dlm can be specified
|
||||
+directly.
|
||||
.P
|
||||
-An LV activated exclusively on one host cannot be activated on another.
|
||||
-When multiple hosts need to use the same LV concurrently, the LV can be
|
||||
-activated with a shared lock (see lvchange options -aey vs -asy.)
|
||||
-(Shared locks are disallowed for certain LV types that cannot be used from
|
||||
-multiple hosts.)
|
||||
+When using lvmlockd in a cluster which already uses corosync and
|
||||
+dlm, then the dlm lock type should be used for shared VGs. Otherwise,
|
||||
+using sanlock is usually more straight forward.
|
||||
+.P
|
||||
+Details on starting or setting up each lock manager are outside the
|
||||
+scope of LVM. sanlock can usually be started with a simple
|
||||
+"systemctl start wdmd sanlock". Steps for setting up and starting
|
||||
+corosync and dlm can be more complicated.
|
||||
+.P
|
||||
+.B Lock start
|
||||
+.br
|
||||
+Shared VGs must be started before they are used via vgchange --lockstart
|
||||
+VG. Starting the VG performs lock manager initialization that is necessary
|
||||
+to begin using locks (i.e. creating and joining a lockspace). Starting the
|
||||
+VG may take some time, and until the start completes the VG may not be
|
||||
+modified or activated. When shutting down, the lockspace is stopped with
|
||||
+vgchange --lockstop VG.
|
||||
.
|
||||
-.SS Normal start up and shut down
|
||||
+.SH TOPICS
|
||||
.
|
||||
-After initial set up, start up and shut down include the following steps.
|
||||
-They can be performed directly or may be automated using systemd or a
|
||||
-cluster resource manager/agents. When using lvmlockd.service, daemon
|
||||
-options can be set in
|
||||
-.I /etc/sysconfig/lvmlockd
|
||||
-as OPTIONS='-x1 -y2'.
|
||||
+.SS Displaying shared VGs
|
||||
+.P
|
||||
+The
|
||||
+.B vgs
|
||||
+command shows the letter
|
||||
+.B s
|
||||
+in the last (sixth) attr position for a shared VG:
|
||||
.
|
||||
-.IP \[bu] 2
|
||||
-start lvmlockd
|
||||
+.nf
|
||||
.
|
||||
-.IP \[bu]
|
||||
-start lock manager
|
||||
+.P
|
||||
+$ vgs
|
||||
+ VG #PV #LV #SN Attr VSize VFree
|
||||
+ vgfoo 1 0 0 wz--ns 992.00m 736.00m
|
||||
+.fi
|
||||
.
|
||||
-.IP \[bu]
|
||||
-vgchange --lockstart
|
||||
+.P
|
||||
.
|
||||
-.IP \[bu]
|
||||
-activate LVs in shared VGs
|
||||
+Or, the shared attribute can be displayed as a
|
||||
+.B vgs
|
||||
+reporting field:
|
||||
+.P
|
||||
+.nf
|
||||
+$ vgs -o+shared
|
||||
+ VG #PV #LV #SN Attr VSize VFree Shared
|
||||
+ vgfoo 1 0 0 wz--ns 992.00m 736.00m shared
|
||||
+.fi
|
||||
.P
|
||||
-The shut down sequence is the reverse:
|
||||
-.IP \[bu] 2
|
||||
-deactivate LVs in shared VGs
|
||||
-.IP \[bu]
|
||||
-vgchange --lockstop
|
||||
-.IP \[bu]
|
||||
-stop lock manager
|
||||
-.IP \[bu]
|
||||
-stop lvmlockd
|
||||
.
|
||||
-.SH TOPICS
|
||||
+The
|
||||
+.B vgs
|
||||
+command can also display the lock type:
|
||||
.
|
||||
-.SS Protecting VGs on shared devices
|
||||
+.P
|
||||
+.nf
|
||||
+$ vgs -o+locktype
|
||||
+ VG #PV #LV #SN Attr VSize VFree LockType
|
||||
+ vgfoo 1 0 0 wz--ns 992.00m 736.00m sanlock
|
||||
+.fi
|
||||
+.P
|
||||
.
|
||||
-The following terms are used to describe the different ways of accessing
|
||||
-VGs on shared devices.
|
||||
+On hosts that are attached to the shared devices, but do not have
|
||||
+lvmlockd enabled, the
|
||||
+.B vgs
|
||||
+command will not display shared VGs unless the
|
||||
+.B --shared
|
||||
+option is added:
|
||||
.
|
||||
-.TP
|
||||
-.I shared VG
|
||||
-A shared VG exists on shared storage that is visible to multiple hosts.
|
||||
-LVM acquires locks through lvmlockd to coordinate access to shared VGs.
|
||||
-A shared VG has lock_type "dlm" or "sanlock", which specifies the lock
|
||||
-manager lvmlockd will use.
|
||||
-.sp
|
||||
-When the lock manager for the lock type is not available (e.g. not started
|
||||
-or failed), lvmlockd is unable to acquire locks for LVM commands. In this
|
||||
-situation, LVM commands are only allowed to read and display the VG;
|
||||
-changes and activation will fail.
|
||||
+.P
|
||||
+.nf
|
||||
+$ vgs --shared
|
||||
+ VG #PV #LV #SN Attr VSize VFree
|
||||
+ vgfoo 1 0 0 wz--ns 992.00m 736.00m
|
||||
+.fi
|
||||
.
|
||||
-.TP
|
||||
-.I local VG
|
||||
-A local VG is meant to be used by a single host. It has no lock type or
|
||||
-lock type "none". A local VG typically exists on local (non-shared)
|
||||
-devices and cannot be used concurrently from different hosts.
|
||||
-.sp
|
||||
-If a local VG does exist on shared devices, it should be owned by a single
|
||||
-host by having the system ID set, see
|
||||
+.SS System ID
|
||||
+.br
|
||||
+In contrast to a shared VG, a local VG can only be used by one host
|
||||
+at a time, and does not use lvmlockd or a lock manager. If a local VG
|
||||
+is located on shared devices, then the LVM system ID feature should be
|
||||
+used to assign one host ownership of the VG. See
|
||||
.BR lvmsystemid (7).
|
||||
-The host with a matching system ID can use the local VG and other hosts
|
||||
-will ignore it. A VG with no lock type and no system ID should be
|
||||
-excluded from all but one host using
|
||||
-.BR lvm.conf (5)
|
||||
-filters.
|
||||
-Without any of these protections, a local VG on shared devices
|
||||
-can be easily damaged or destroyed.
|
||||
-.
|
||||
-.TP
|
||||
-.I clvm VG
|
||||
-A clvm VG (or clustered VG) is a VG on shared storage (like a shared VG)
|
||||
-that requires clvmd for clustering and locking. See below for converting
|
||||
-a clvm/clustered VG to a shared VG.
|
||||
-.
|
||||
-.SS Shared VGs from hosts not using lvmlockd
|
||||
-.
|
||||
-Hosts that do not use shared VGs will not be running lvmlockd. In this
|
||||
-case, shared VGs that are still visible to the host will be ignored
|
||||
-(like foreign VGs, see
|
||||
-.BR lvmsystemid (7)).
|
||||
.P
|
||||
-The --shared option for reporting and display commands causes shared VGs
|
||||
-to be displayed on a host not using lvmlockd, like the --foreign option
|
||||
-does for foreign VGs.
|
||||
+For additional protection, the shared devices in a local VG can be
|
||||
+excluded from the devices file (system.devices) on all hosts except
|
||||
+for the host that owns the VG.
|
||||
.
|
||||
.SS Creating the first sanlock VG
|
||||
.
|
||||
-When use_lvmlockd is first enabled in
|
||||
-.BR lvm.conf (5),
|
||||
+When use_lvmlockd is first enabled in lvm.conf,
|
||||
and before the first sanlock VG is created, no global lock will exist.
|
||||
In this initial state, LVM commands try
|
||||
and fail to acquire the global lock, producing a warning,
|
||||
@@ -327,27 +357,12 @@ from concurrent use by another vgcreate on another host.
|
||||
.P
|
||||
See below for more information about managing the sanlock global lock.
|
||||
.
|
||||
-.SS Using shared VGs
|
||||
+.SS Removing a shared VG
|
||||
.
|
||||
-In the
|
||||
-.BR vgs (8)
|
||||
-command, shared VGs are indicated by "s" (for shared)
|
||||
-in the sixth attr field,
|
||||
-and by "shared" in the "--options shared" report field.
|
||||
-The specific lock type and lock args for a shared VG can be
|
||||
-displayed with:
|
||||
-.P
|
||||
-.EX
|
||||
-# vgs -o+locktype,lockargs
|
||||
-.EE
|
||||
-.P
|
||||
-Shared VGs need to be "started" and "stopped", unlike other types of VGs.
|
||||
-See the following section for a full description of starting and stopping.
|
||||
-.P
|
||||
-Removing a shared VG will fail if other hosts have the VG started. Run
|
||||
-vgchange --lockstop <vgname> on all other hosts before vgremove. (It may
|
||||
-take several seconds before vgremove recognizes that all hosts have
|
||||
-stopped a sanlock VG.)
|
||||
+Removing a shared VG will fail if other hosts have the VG started (it must
|
||||
+be started on the host running vgremove.) Run vgchange --lockstop <vgname>
|
||||
+on all other hosts before vgremove. (It may take several seconds before
|
||||
+vgremove recognizes that all hosts have stopped a sanlock VG.)
|
||||
.
|
||||
.SS Starting and stopping VGs
|
||||
.
|
||||
@@ -366,32 +381,6 @@ When using the lock type sanlock, starting a VG can take a long time
|
||||
(potentially minutes if the host was previously shut down without cleanly
|
||||
stopping the VG.)
|
||||
.P
|
||||
-A shared VG can be started after all the following are true:
|
||||
-.P
|
||||
-\[bu]
|
||||
-lvmlockd is running
|
||||
-.br
|
||||
-\[bu]
|
||||
-the lock manager is running
|
||||
-.br
|
||||
-\[bu]
|
||||
-the VG's devices are visible on the system
|
||||
-.P
|
||||
-A shared VG can be stopped if all LVs are deactivated.
|
||||
-.P
|
||||
-All shared VGs can be started/stopped using:
|
||||
-.P
|
||||
-.EX
|
||||
-# vgchange --lockstart
|
||||
-# vgchange --lockstop
|
||||
-.EE
|
||||
-.P
|
||||
-Individual VGs can be started/stopped using:
|
||||
-.br
|
||||
-vgchange --lockstart <vgname> \&.\|.\|.
|
||||
-.br
|
||||
-vgchange --lockstop <vgname> \&.\|.\|.
|
||||
-.P
|
||||
To make vgchange not wait for start to complete:
|
||||
.br
|
||||
vgchange --lockstart --lockopt nowait \&.\|.\|.
|
||||
@@ -400,21 +389,6 @@ lvmlockd can be asked directly to stop all lockspaces:
|
||||
.br
|
||||
lvmlockctl -S|--stop-lockspaces
|
||||
.P
|
||||
-To start only selected shared VGs, use the
|
||||
-.BR lvm.conf (5)
|
||||
-\fBactivation/lock_start_list\fP.
|
||||
-When defined, only VG names in this list are
|
||||
-started by vgchange. If the list is not defined (the default), all
|
||||
-visible shared VGs are started. To start only "vg1", use the following
|
||||
-.BR lvm.conf (5)
|
||||
-configuration:
|
||||
-.P
|
||||
-.EX
|
||||
-activation {
|
||||
-\ lock_start_list = [ "vg1" ]
|
||||
-\ \&...
|
||||
-}
|
||||
-.EE
|
||||
.
|
||||
.SS Internal command locking
|
||||
.
|
||||
@@ -664,7 +638,7 @@ dmsetup wipe_table -S "uuid=~LVM && vgname=$VG && lv_layer=\\"\\""
|
||||
# check that the error target is in place
|
||||
dmsetup table -c -S "uuid=~LVM && vgname=$VG && lv_layer=\\"\\"" |grep -vw error
|
||||
if [[ $? -ne 0 ]] ; then
|
||||
-\ exit 0
|
||||
+exit 0
|
||||
fi
|
||||
exit 1
|
||||
.EE
|
||||
@@ -868,14 +842,11 @@ vgmerge
|
||||
.
|
||||
.SS lvmlockd changes from clvmd
|
||||
.
|
||||
-(See above for converting an existing clvm VG to a shared VG.)
|
||||
.P
|
||||
-While lvmlockd and clvmd are entirely different systems, LVM command usage
|
||||
-remains similar. Differences are more notable when using lvmlockd's
|
||||
-sanlock option.
|
||||
-.P
|
||||
-Visible usage differences between shared VGs (using lvmlockd) and
|
||||
-clvm/clustered VGs (using clvmd):
|
||||
+Prior to the introduction of lvmlockd, clvmd (CLVM) existed with similar
|
||||
+capabilities, but a very different design.
|
||||
+Some of the visible usage differences between shared VGs (using lvmlockd)
|
||||
+and cluster VGs (using clvmd):
|
||||
.
|
||||
.IP \[bu] 2
|
||||
.BR lvm.conf (5)
|
||||
@@ -945,9 +916,6 @@ unable to passively check the remote active or lock state of an LV.
|
||||
.
|
||||
.nh
|
||||
.na
|
||||
-.BR lvm (8),
|
||||
.BR lvmlockctl (8),
|
||||
-.BR lvchange (8),
|
||||
-.BR lvgs (8),
|
||||
-.BR vgs (8),
|
||||
-.BR lvm.conf (5)
|
||||
+.BR sanlock (8),
|
||||
+.BR dlm_controld (8)
|
||||
--
|
||||
2.51.0
|
||||
|
||||
44
SOURCES/0024-lvmlockd-allow-1-more-extra-character.patch
Normal file
44
SOURCES/0024-lvmlockd-allow-1-more-extra-character.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From 1fee1b03564bb807e7adedefb27180babcd861d0 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Fri, 27 Jun 2025 11:15:05 +0200
|
||||
Subject: [PATCH 24/47] lvmlockd: allow 1 more extra character
|
||||
|
||||
Function dm_strncpy() ensures the last character is \0,
|
||||
so pass whole array size for buffer size.
|
||||
|
||||
This give 1 extra character for use to store owner state and name.
|
||||
|
||||
(cherry picked from commit 879fb36f0a6c4fda783efbc02b4bf6477f18a4af)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockd-sanlock.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
index 89df4ec44..6ef59b591 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
@@ -2208,10 +2208,10 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
owner->timestamp = (uint32_t)owner_host.timestamp;
|
||||
|
||||
if ((host_state = _host_flags_to_str(owner_host.flags)))
|
||||
- dm_strncpy(owner->state, host_state, OWNER_STATE_SIZE-1);
|
||||
+ dm_strncpy(owner->state, host_state, sizeof(owner->state));
|
||||
|
||||
if (owner_name) {
|
||||
- dm_strncpy(owner->name, owner_name, OWNER_NAME_SIZE-1);
|
||||
+ dm_strncpy(owner->name, owner_name, sizeof(owner->name));
|
||||
free(owner_name);
|
||||
}
|
||||
|
||||
@@ -2553,7 +2553,7 @@ int lm_vg_status_sanlock(struct lockspace *ls, struct action *act)
|
||||
act->owner.timestamp = (uint32_t)hs->timestamp;
|
||||
|
||||
if ((host_state = _host_flags_to_str(hs->flags)))
|
||||
- dm_strncpy(act->owner.state, host_state, OWNER_STATE_SIZE-1);
|
||||
+ dm_strncpy(act->owner.state, host_state, sizeof(act->owner.state));
|
||||
|
||||
free(hs);
|
||||
return 0;
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,196 +0,0 @@
|
||||
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 24/54] 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.34.3
|
||||
|
||||
@ -0,0 +1,113 @@
|
||||
From 20a049ac3267240de7ffcfb55cf58c08fe7d88a6 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Fri, 27 Jun 2025 11:38:24 +0200
|
||||
Subject: [PATCH 25/47] libdm-stats: fix type mismatch in bit operations
|
||||
|
||||
The stats implementation was using uint64_t for group_id and loop variables
|
||||
while calling dm_bit_* functions that return int types. This created a
|
||||
potential issue where large values could be incorrectly handled due to
|
||||
implicit casting between signed and unsigned types.
|
||||
|
||||
Changes:
|
||||
- Change loop variables from uint64_t to int in _stats_group_tag_len()
|
||||
- Change loop variable from uint64_t to int in _stats_clear_group_regions()
|
||||
- Change loop variables from uint64_t to int in dm_stats_get_counter()
|
||||
- Change loop variable from uint64_t to int in dm_stats_get_region_len()
|
||||
- Fix _stats_create_group() to properly handle dm_bit_get_first() return value
|
||||
|
||||
This ensures consistent type usage and prevents potential issues with
|
||||
values exceeding INT_MAX (2^31 - 1). Also this limitats group_id to 31 bits
|
||||
as a constraint that may need addressing in the future.
|
||||
|
||||
FIXME: Maybe consider implementing 64-bit variants of dm_bit functions or
|
||||
documenting this limitation more prominently is this ever become an
|
||||
issue...
|
||||
|
||||
(cherry picked from commit 2dec6f5493e573b7a4012708931226bcbc9af32f)
|
||||
---
|
||||
libdm/libdm-stats.c | 25 +++++++++++++++----------
|
||||
1 file changed, 15 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/libdm/libdm-stats.c b/libdm/libdm-stats.c
|
||||
index c1b1cc466..cbcbb6754 100644
|
||||
--- a/libdm/libdm-stats.c
|
||||
+++ b/libdm/libdm-stats.c
|
||||
@@ -1859,7 +1859,8 @@ bad:
|
||||
static size_t _stats_group_tag_len(const struct dm_stats *dms,
|
||||
dm_bitset_t regions)
|
||||
{
|
||||
- int64_t i, j, next, nr_regions = 0;
|
||||
+ int i, j, next;
|
||||
+ int64_t nr_regions = 0;
|
||||
size_t buflen = 0, id_len = 0;
|
||||
|
||||
/* check region ids and find last set bit */
|
||||
@@ -2124,7 +2125,7 @@ out:
|
||||
static void _stats_clear_group_regions(struct dm_stats *dms, uint64_t group_id)
|
||||
{
|
||||
struct dm_stats_group *group;
|
||||
- uint64_t i;
|
||||
+ int i;
|
||||
|
||||
group = &dms->groups[group_id];
|
||||
for (i = dm_bit_get_first(group->regions);
|
||||
@@ -2499,7 +2500,7 @@ void dm_stats_destroy(struct dm_stats *dms)
|
||||
* i is a variable of type int that holds the current area_id.
|
||||
*/
|
||||
#define _foreach_region_area(dms, rid, i) \
|
||||
-for ((i) = 0; (i) < _nr_areas_region(&dms->regions[(rid)]); (i)++) \
|
||||
+for ((i) = 0; (int)(i) < (int)_nr_areas_region(&dms->regions[(rid)]); (i)++) \
|
||||
|
||||
/*
|
||||
* Walk each region that is a member of group_id gid.
|
||||
@@ -2507,7 +2508,7 @@ for ((i) = 0; (i) < _nr_areas_region(&dms->regions[(rid)]); (i)++) \
|
||||
*/
|
||||
#define _foreach_group_region(dms, gid, i) \
|
||||
for ((i) = dm_bit_get_first((dms)->groups[(gid)].regions); \
|
||||
- (i) != DM_STATS_GROUP_NOT_PRESENT; \
|
||||
+ (int)(i) != (int)DM_STATS_GROUP_NOT_PRESENT; \
|
||||
(i) = dm_bit_get_next((dms)->groups[(gid)].regions, (i))) \
|
||||
|
||||
/*
|
||||
@@ -2562,8 +2563,8 @@ uint64_t dm_stats_get_counter(const struct dm_stats *dms,
|
||||
dm_stats_counter_t counter,
|
||||
uint64_t region_id, uint64_t area_id)
|
||||
{
|
||||
- uint64_t i, j, sum = 0; /* aggregation */
|
||||
- int sum_regions = 0;
|
||||
+ uint64_t sum = 0; /* aggregation */
|
||||
+ int i, j, sum_regions = 0;
|
||||
struct dm_stats_region *region;
|
||||
struct dm_stats_counters *area;
|
||||
|
||||
@@ -3129,7 +3130,7 @@ int dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
|
||||
int dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
|
||||
uint64_t region_id)
|
||||
{
|
||||
- uint64_t i;
|
||||
+ int i;
|
||||
if (!dms || !dms->regions)
|
||||
return_0;
|
||||
|
||||
@@ -3970,11 +3971,15 @@ static int _stats_create_group(struct dm_stats *dms, dm_bitset_t regions,
|
||||
const char *alias, uint64_t *group_id)
|
||||
{
|
||||
struct dm_stats_group *group;
|
||||
- *group_id = dm_bit_get_first(regions);
|
||||
+ int i = dm_bit_get_first(regions);
|
||||
|
||||
- /* group has no regions? */
|
||||
- if (*group_id == DM_STATS_GROUP_NOT_PRESENT)
|
||||
+ if (i < 0) {
|
||||
+ /* group has no regions? */
|
||||
+ *group_id = DM_STATS_GROUP_NOT_PRESENT;
|
||||
return_0;
|
||||
+ }
|
||||
+
|
||||
+ *group_id = (uint64_t)i;
|
||||
|
||||
group = &dms->groups[*group_id];
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,141 +0,0 @@
|
||||
From a5c37afdca97d6565ea02bc4bc7d52f360823cd3 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Wed, 8 Sep 2021 16:30:11 -0500
|
||||
Subject: [PATCH 25/54] pvcreate: overwrite partition header with -f
|
||||
|
||||
$ pvcreate /dev/sdc
|
||||
Cannot use /dev/sdc: device is partitioned
|
||||
$ pvcreate -f /dev/sdc
|
||||
Physical volume "/dev/sdc" successfully created.
|
||||
---
|
||||
lib/commands/toolcontext.h | 1 +
|
||||
lib/filters/filter-partitioned.c | 3 +++
|
||||
man/pvcreate.8_des | 7 ++++---
|
||||
test/shell/test-partition.sh | 12 ++++++++++--
|
||||
tools/toollib.c | 10 ++++++++++
|
||||
5 files changed, 28 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
|
||||
index 356c79f8a..b83883fb8 100644
|
||||
--- a/lib/commands/toolcontext.h
|
||||
+++ b/lib/commands/toolcontext.h
|
||||
@@ -201,6 +201,7 @@ struct cmd_context {
|
||||
unsigned ignore_device_name_mismatch:1; /* skip updating devices file names */
|
||||
unsigned backup_disabled:1; /* skip repeated debug message */
|
||||
unsigned event_activation:1; /* whether event_activation is set */
|
||||
+ unsigned filter_partitioned_skip:1; /* don't use filter-partitioned */
|
||||
|
||||
/*
|
||||
* Devices and filtering.
|
||||
diff --git a/lib/filters/filter-partitioned.c b/lib/filters/filter-partitioned.c
|
||||
index 642553ef2..8f468a567 100644
|
||||
--- a/lib/filters/filter-partitioned.c
|
||||
+++ b/lib/filters/filter-partitioned.c
|
||||
@@ -27,6 +27,9 @@ static int _passes_partitioned_filter(struct cmd_context *cmd, struct dev_filter
|
||||
if (cmd->filter_nodata_only)
|
||||
return 1;
|
||||
|
||||
+ if (cmd->filter_partitioned_skip)
|
||||
+ return 1;
|
||||
+
|
||||
dev->filtered_flags &= ~DEV_FILTERED_PARTITIONED;
|
||||
|
||||
ret = dev_is_partitioned(cmd, dev);
|
||||
diff --git a/man/pvcreate.8_des b/man/pvcreate.8_des
|
||||
index 69bd133aa..4048eb71c 100644
|
||||
--- a/man/pvcreate.8_des
|
||||
+++ b/man/pvcreate.8_des
|
||||
@@ -7,9 +7,10 @@ Use \fBvgcreate\fP(8) to create a new VG on the PV, or \fBvgextend\fP(8)
|
||||
to add the PV to an existing VG. Use \fBpvremove\fP(8) to remove the LVM
|
||||
disk label from the device.
|
||||
.P
|
||||
-The force option will create a PV without confirmation. Repeating the
|
||||
-force option (\fB-ff\fP) will forcibly create a PV, overriding checks that
|
||||
-normally prevent it, e.g. if the PV is already in a VG.
|
||||
+The force option will create a PV without confirmation, and will overwrite
|
||||
+partition headers. Repeating the force option (\fB-ff\fP) will override other
|
||||
+checks that would normally prevent a pvcreate, e.g. if the PV is already in a
|
||||
+VG.
|
||||
.P
|
||||
.B Metadata location, size, and alignment
|
||||
.P
|
||||
diff --git a/test/shell/test-partition.sh b/test/shell/test-partition.sh
|
||||
index 0e92f00db..3a45f9089 100644
|
||||
--- a/test/shell/test-partition.sh
|
||||
+++ b/test/shell/test-partition.sh
|
||||
@@ -16,7 +16,6 @@
|
||||
#
|
||||
|
||||
|
||||
-
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
LVM_TEST_CONFIG_DEVICES="types = [\"device-mapper\", 142]"
|
||||
@@ -25,7 +24,7 @@ LVM_TEST_CONFIG_DEVICES="types = [\"device-mapper\", 142]"
|
||||
|
||||
which sfdisk || skip
|
||||
|
||||
-aux prepare_pvs 1 30
|
||||
+aux prepare_pvs 2 30
|
||||
|
||||
pvs "$dev1"
|
||||
|
||||
@@ -33,3 +32,12 @@ pvs "$dev1"
|
||||
echo "1 2" | sfdisk --force "$dev1"
|
||||
|
||||
not pvs "$dev1"
|
||||
+
|
||||
+wipefs -a "$dev2"
|
||||
+echo "1 2" | sfdisk --force "$dev2"
|
||||
+partprobe
|
||||
+not pvcreate "$dev2"
|
||||
+pvcreate -f "$dev2"
|
||||
+pvs "$dev2"
|
||||
+pvremove "$dev2"
|
||||
+
|
||||
diff --git a/tools/toollib.c b/tools/toollib.c
|
||||
index d6f48aad2..80d3de57c 100644
|
||||
--- a/tools/toollib.c
|
||||
+++ b/tools/toollib.c
|
||||
@@ -5243,6 +5243,10 @@ int pvcreate_each_device(struct cmd_context *cmd,
|
||||
if (cmd->enable_devices_file && !pp->is_remove)
|
||||
cmd->filter_deviceid_skip = 1;
|
||||
|
||||
+ /* pvcreate -f overwrites partitions */
|
||||
+ if (pp->force && !pp->is_remove)
|
||||
+ cmd->filter_partitioned_skip = 1;
|
||||
+
|
||||
log_debug("Scanning and filtering device args (%u).", dm_list_size(&scan_devs));
|
||||
label_scan_devs(cmd, cmd->filter, &scan_devs);
|
||||
|
||||
@@ -5257,6 +5261,7 @@ int pvcreate_each_device(struct cmd_context *cmd,
|
||||
}
|
||||
}
|
||||
cmd->filter_deviceid_skip = 0;
|
||||
+ cmd->filter_partitioned_skip = 0;
|
||||
|
||||
/*
|
||||
* Can the command continue if some specified devices were not found?
|
||||
@@ -5469,6 +5474,9 @@ do_command:
|
||||
if (cmd->enable_devices_file && !pp->is_remove)
|
||||
cmd->filter_deviceid_skip = 1;
|
||||
|
||||
+ if (pp->force && !pp->is_remove)
|
||||
+ cmd->filter_partitioned_skip = 1;
|
||||
+
|
||||
log_debug("Rescanning and filtering device args with exclusive open");
|
||||
if (!label_scan_devs_excl(cmd, cmd->filter, &rescan_devs)) {
|
||||
log_debug("Failed to rescan devs excl");
|
||||
@@ -5482,7 +5490,9 @@ do_command:
|
||||
dm_list_add(&pp->arg_fail, &pd->list);
|
||||
}
|
||||
}
|
||||
+
|
||||
cmd->filter_deviceid_skip = 0;
|
||||
+ cmd->filter_partitioned_skip = 0;
|
||||
|
||||
if (dm_list_empty(&pp->arg_process) && dm_list_empty(&remove_duplicates)) {
|
||||
log_debug("No devices to process.");
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
From c25e62f4e0532dfb55e2c81a6e236edfeffa8c11 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Sun, 29 Jun 2025 20:47:13 +0200
|
||||
Subject: [PATCH 26/47] cov: prevent potential negative array index
|
||||
|
||||
The _stats_map_extents() function processes file extents returned
|
||||
by FIEMAP ioctl calls. When handling the case where a file has
|
||||
only a single extent, the code accesses fm_ext[i - 1] to check
|
||||
if the logical offset is 0.
|
||||
|
||||
However, when i is 0 (no extents processed yet), this results in a negative
|
||||
array index access which can cause undefined behavior or crashes.
|
||||
|
||||
So check early whether there are fm_mapped_extents to process.
|
||||
This avoids using negative index array.
|
||||
|
||||
Existing code already checks fm_mapped_extents == 0 before calling
|
||||
this function so the patch is not fixing any real bug.
|
||||
|
||||
(cherry picked from commit 2a2ad7317f19f15982045d847aacd74922a28572)
|
||||
---
|
||||
libdm/libdm-stats.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/libdm/libdm-stats.c b/libdm/libdm-stats.c
|
||||
index cbcbb6754..53c3c5480 100644
|
||||
--- a/libdm/libdm-stats.c
|
||||
+++ b/libdm/libdm-stats.c
|
||||
@@ -4411,6 +4411,9 @@ static uint64_t _stats_map_extents(int fd, struct dm_pool *mem,
|
||||
uint64_t expected = 0, nr_extents = next_extent;
|
||||
unsigned int i;
|
||||
|
||||
+ if (!fiemap->fm_mapped_extents)
|
||||
+ return 0;
|
||||
+
|
||||
/*
|
||||
* Loop over the returned extents adding the fm_pending extent
|
||||
* to the table of extents each time a discontinuity (or eof)
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,166 +0,0 @@
|
||||
From bb477d63e336a10e5959962a9f26a028ea9e55eb Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Thu, 13 Jan 2022 14:52:54 -0600
|
||||
Subject: [PATCH 26/54] lvmdevices check: error exit if update is needed
|
||||
|
||||
. error exit means that lvmdevices --update would make a change.
|
||||
|
||||
. remove check of PART field from --check because it isn't used.
|
||||
|
||||
. unlink searched_devnames file to ensure check|update will search
|
||||
---
|
||||
lib/device/device_id.c | 3 ++-
|
||||
test/shell/devicesfile-realdevs.sh | 8 +++----
|
||||
tools/args.h | 3 ++-
|
||||
tools/lvmdevices.c | 37 +++++++++++++-----------------
|
||||
4 files changed, 24 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index 0621bc858..a33dcebe0 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -2271,7 +2271,8 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l
|
||||
continue;
|
||||
}
|
||||
|
||||
- log_warn("Devices file PVID %s updating IDNAME to %s.", dev->pvid, devname);
|
||||
+ if (!noupdate)
|
||||
+ log_warn("Devices file PVID %s updating IDNAME to %s.", dev->pvid, devname);
|
||||
|
||||
free(du->idname);
|
||||
free(du->devname);
|
||||
diff --git a/test/shell/devicesfile-realdevs.sh b/test/shell/devicesfile-realdevs.sh
|
||||
index 8d4aa3e67..23d4bedb4 100644
|
||||
--- a/test/shell/devicesfile-realdevs.sh
|
||||
+++ b/test/shell/devicesfile-realdevs.sh
|
||||
@@ -423,7 +423,7 @@ sed "s/$pvid1/badpvid/" "$DF.orig" |tee $DF
|
||||
not grep $pvid1 $DF
|
||||
grep $did1 $DF
|
||||
|
||||
-lvmdevices --check 2>&1|tee out
|
||||
+not lvmdevices --check 2>&1|tee out
|
||||
grep $dev1 out
|
||||
grep badpvid out
|
||||
grep $pvid1 out
|
||||
@@ -493,7 +493,7 @@ rm $DF
|
||||
d1=$(basename $dev1)
|
||||
d3=$(basename $dev3)
|
||||
sed "s/$d1/$d3/" "$DF.orig" |tee $DF
|
||||
-lvmdevices --check 2>&1 |tee out
|
||||
+not lvmdevices --check 2>&1 |tee out
|
||||
grep $dev1 out
|
||||
|
||||
lvmdevices --update
|
||||
@@ -515,7 +515,7 @@ sed "s/$d1/tmp/" "$DF.orig" |tee ${DF}_1
|
||||
sed "s/$d2/$d1/" "${DF}_1" |tee ${DF}_2
|
||||
sed "s/tmp/$d2/" "${DF}_2" |tee $DF
|
||||
rm ${DF}_1 ${DF}_2
|
||||
-lvmdevices --check 2>&1 |tee out
|
||||
+not lvmdevices --check 2>&1 |tee out
|
||||
grep $dev1 out
|
||||
grep $dev2 out
|
||||
|
||||
@@ -536,7 +536,7 @@ rm $DF
|
||||
d1=$(basename $dev1)
|
||||
d3=$(basename $dev3)
|
||||
sed "s/$d1/$d3/" "$DF.orig" |tee $DF
|
||||
-lvmdevices --check 2>&1 |tee out
|
||||
+not lvmdevices --check 2>&1 |tee out
|
||||
grep $dev1 out
|
||||
|
||||
pvs -o+uuid,deviceid | grep $vg |tee out
|
||||
diff --git a/tools/args.h b/tools/args.h
|
||||
index 774ce33f4..9a7bf81b2 100644
|
||||
--- a/tools/args.h
|
||||
+++ b/tools/args.h
|
||||
@@ -153,7 +153,8 @@ arg(cachesize_ARG, '\0', "cachesize", sizemb_VAL, 0, 0,
|
||||
"The size of cache to use.\n")
|
||||
|
||||
arg(check_ARG, '\0', "check", 0, 0, 0,
|
||||
- "Check the content of the devices file.\n")
|
||||
+ "Checks the content of the devices file.\n"
|
||||
+ "Reports incorrect device names or PVIDs for entries.\n")
|
||||
|
||||
arg(commandprofile_ARG, '\0', "commandprofile", string_VAL, 0, 0,
|
||||
"The command profile to use for command configuration.\n"
|
||||
diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c
|
||||
index 3f104f7de..c50c09f90 100644
|
||||
--- a/tools/lvmdevices.c
|
||||
+++ b/tools/lvmdevices.c
|
||||
@@ -128,7 +128,6 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
struct device *dev;
|
||||
struct dev_use *du, *du2;
|
||||
const char *deviceidtype;
|
||||
- int changes = 0;
|
||||
|
||||
dm_list_init(&search_pvids);
|
||||
dm_list_init(&found_devs);
|
||||
@@ -184,8 +183,11 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
if (arg_is_set(cmd, check_ARG) || arg_is_set(cmd, update_ARG)) {
|
||||
int search_count = 0;
|
||||
+ int update_needed = 0;
|
||||
int invalid = 0;
|
||||
|
||||
+ unlink_searched_devnames(cmd);
|
||||
+
|
||||
label_scan_setup_bcache();
|
||||
|
||||
dm_list_iterate_items(du, &cmd->use_devices) {
|
||||
@@ -225,6 +227,8 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
* run just above.
|
||||
*/
|
||||
device_ids_validate(cmd, NULL, &invalid, 1);
|
||||
+ if (invalid)
|
||||
+ update_needed = 1;
|
||||
|
||||
/*
|
||||
* Find and fix any devname entries that have moved to a
|
||||
@@ -240,33 +244,24 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
label_scan_invalidate(du->dev);
|
||||
}
|
||||
|
||||
- /*
|
||||
- * check du->part
|
||||
- */
|
||||
- dm_list_iterate_items(du, &cmd->use_devices) {
|
||||
- int part = 0;
|
||||
- if (!du->dev)
|
||||
- continue;
|
||||
- dev = du->dev;
|
||||
-
|
||||
- dev_get_partition_number(dev, &part);
|
||||
-
|
||||
- if (part != du->part) {
|
||||
- log_warn("Device %s partition %u has incorrect PART in devices file (%u)",
|
||||
- dev_name(dev), part, du->part);
|
||||
- du->part = part;
|
||||
- changes++;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
if (arg_is_set(cmd, update_ARG)) {
|
||||
- if (invalid || !dm_list_empty(&found_devs)) {
|
||||
+ if (update_needed || !dm_list_empty(&found_devs)) {
|
||||
if (!device_ids_write(cmd))
|
||||
goto_bad;
|
||||
log_print("Updated devices file to version %s", devices_file_version());
|
||||
} else {
|
||||
log_print("No update for devices file is needed.");
|
||||
}
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * --check exits with an error if the devices file
|
||||
+ * needs updates, i.e. running --update would make
|
||||
+ * changes.
|
||||
+ */
|
||||
+ if (update_needed) {
|
||||
+ log_error("Updates needed for devices file.");
|
||||
+ goto bad;
|
||||
+ }
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -1,140 +0,0 @@
|
||||
From 9375aebad1db72267dd67e3ed768aa3b0e698d52 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Tue, 18 Jan 2022 12:16:52 -0600
|
||||
Subject: [PATCH 27/54] Revert "pvcreate: overwrite partition header with -f"
|
||||
|
||||
This reverts commit a5c37afdca97d6565ea02bc4bc7d52f360823cd3.
|
||||
|
||||
This commit did not properly recognize GPT cases.
|
||||
---
|
||||
lib/commands/toolcontext.h | 1 -
|
||||
lib/filters/filter-partitioned.c | 3 ---
|
||||
man/pvcreate.8_des | 7 +++----
|
||||
test/shell/test-partition.sh | 12 ++----------
|
||||
tools/toollib.c | 10 ----------
|
||||
5 files changed, 5 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
|
||||
index b83883fb8..356c79f8a 100644
|
||||
--- a/lib/commands/toolcontext.h
|
||||
+++ b/lib/commands/toolcontext.h
|
||||
@@ -201,7 +201,6 @@ struct cmd_context {
|
||||
unsigned ignore_device_name_mismatch:1; /* skip updating devices file names */
|
||||
unsigned backup_disabled:1; /* skip repeated debug message */
|
||||
unsigned event_activation:1; /* whether event_activation is set */
|
||||
- unsigned filter_partitioned_skip:1; /* don't use filter-partitioned */
|
||||
|
||||
/*
|
||||
* Devices and filtering.
|
||||
diff --git a/lib/filters/filter-partitioned.c b/lib/filters/filter-partitioned.c
|
||||
index 8f468a567..642553ef2 100644
|
||||
--- a/lib/filters/filter-partitioned.c
|
||||
+++ b/lib/filters/filter-partitioned.c
|
||||
@@ -27,9 +27,6 @@ static int _passes_partitioned_filter(struct cmd_context *cmd, struct dev_filter
|
||||
if (cmd->filter_nodata_only)
|
||||
return 1;
|
||||
|
||||
- if (cmd->filter_partitioned_skip)
|
||||
- return 1;
|
||||
-
|
||||
dev->filtered_flags &= ~DEV_FILTERED_PARTITIONED;
|
||||
|
||||
ret = dev_is_partitioned(cmd, dev);
|
||||
diff --git a/man/pvcreate.8_des b/man/pvcreate.8_des
|
||||
index 4048eb71c..69bd133aa 100644
|
||||
--- a/man/pvcreate.8_des
|
||||
+++ b/man/pvcreate.8_des
|
||||
@@ -7,10 +7,9 @@ Use \fBvgcreate\fP(8) to create a new VG on the PV, or \fBvgextend\fP(8)
|
||||
to add the PV to an existing VG. Use \fBpvremove\fP(8) to remove the LVM
|
||||
disk label from the device.
|
||||
.P
|
||||
-The force option will create a PV without confirmation, and will overwrite
|
||||
-partition headers. Repeating the force option (\fB-ff\fP) will override other
|
||||
-checks that would normally prevent a pvcreate, e.g. if the PV is already in a
|
||||
-VG.
|
||||
+The force option will create a PV without confirmation. Repeating the
|
||||
+force option (\fB-ff\fP) will forcibly create a PV, overriding checks that
|
||||
+normally prevent it, e.g. if the PV is already in a VG.
|
||||
.P
|
||||
.B Metadata location, size, and alignment
|
||||
.P
|
||||
diff --git a/test/shell/test-partition.sh b/test/shell/test-partition.sh
|
||||
index 3a45f9089..0e92f00db 100644
|
||||
--- a/test/shell/test-partition.sh
|
||||
+++ b/test/shell/test-partition.sh
|
||||
@@ -16,6 +16,7 @@
|
||||
#
|
||||
|
||||
|
||||
+
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
LVM_TEST_CONFIG_DEVICES="types = [\"device-mapper\", 142]"
|
||||
@@ -24,7 +25,7 @@ LVM_TEST_CONFIG_DEVICES="types = [\"device-mapper\", 142]"
|
||||
|
||||
which sfdisk || skip
|
||||
|
||||
-aux prepare_pvs 2 30
|
||||
+aux prepare_pvs 1 30
|
||||
|
||||
pvs "$dev1"
|
||||
|
||||
@@ -32,12 +33,3 @@ pvs "$dev1"
|
||||
echo "1 2" | sfdisk --force "$dev1"
|
||||
|
||||
not pvs "$dev1"
|
||||
-
|
||||
-wipefs -a "$dev2"
|
||||
-echo "1 2" | sfdisk --force "$dev2"
|
||||
-partprobe
|
||||
-not pvcreate "$dev2"
|
||||
-pvcreate -f "$dev2"
|
||||
-pvs "$dev2"
|
||||
-pvremove "$dev2"
|
||||
-
|
||||
diff --git a/tools/toollib.c b/tools/toollib.c
|
||||
index 80d3de57c..d6f48aad2 100644
|
||||
--- a/tools/toollib.c
|
||||
+++ b/tools/toollib.c
|
||||
@@ -5243,10 +5243,6 @@ int pvcreate_each_device(struct cmd_context *cmd,
|
||||
if (cmd->enable_devices_file && !pp->is_remove)
|
||||
cmd->filter_deviceid_skip = 1;
|
||||
|
||||
- /* pvcreate -f overwrites partitions */
|
||||
- if (pp->force && !pp->is_remove)
|
||||
- cmd->filter_partitioned_skip = 1;
|
||||
-
|
||||
log_debug("Scanning and filtering device args (%u).", dm_list_size(&scan_devs));
|
||||
label_scan_devs(cmd, cmd->filter, &scan_devs);
|
||||
|
||||
@@ -5261,7 +5257,6 @@ int pvcreate_each_device(struct cmd_context *cmd,
|
||||
}
|
||||
}
|
||||
cmd->filter_deviceid_skip = 0;
|
||||
- cmd->filter_partitioned_skip = 0;
|
||||
|
||||
/*
|
||||
* Can the command continue if some specified devices were not found?
|
||||
@@ -5474,9 +5469,6 @@ do_command:
|
||||
if (cmd->enable_devices_file && !pp->is_remove)
|
||||
cmd->filter_deviceid_skip = 1;
|
||||
|
||||
- if (pp->force && !pp->is_remove)
|
||||
- cmd->filter_partitioned_skip = 1;
|
||||
-
|
||||
log_debug("Rescanning and filtering device args with exclusive open");
|
||||
if (!label_scan_devs_excl(cmd, cmd->filter, &rescan_devs)) {
|
||||
log_debug("Failed to rescan devs excl");
|
||||
@@ -5490,9 +5482,7 @@ do_command:
|
||||
dm_list_add(&pp->arg_fail, &pd->list);
|
||||
}
|
||||
}
|
||||
-
|
||||
cmd->filter_deviceid_skip = 0;
|
||||
- cmd->filter_partitioned_skip = 0;
|
||||
|
||||
if (dm_list_empty(&pp->arg_process) && dm_list_empty(&remove_duplicates)) {
|
||||
log_debug("No devices to process.");
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
From fa4c75d8e20019a11c722d1cc7f3923b3e4b5324 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Fri, 27 Jun 2025 13:46:01 +0200
|
||||
Subject: [PATCH 27/47] cov: fix integer underflow in _count handling
|
||||
|
||||
The _count variable was declared as uint64_t but used in arithmetic operations
|
||||
that could result in underflow when subtracting from smaller values. This
|
||||
could cause issues when calculating interval numbers or handling count-based
|
||||
reporting.
|
||||
|
||||
Changes:
|
||||
- Change _count variable type from uint64_t to int64_t
|
||||
- Update _interval_num() to use proper casting for arithmetic
|
||||
- Change UINT64_MAX to INT64_MAX for default count value
|
||||
- Remove unnecessary casting in count assignment
|
||||
|
||||
This prevents potential underflow issues when _count is decremented or used
|
||||
in subtraction operations, ensuring proper behavior for interval-based
|
||||
reporting and count tracking in dmsetup commands.
|
||||
|
||||
The fix maintains compatibility while providing safer integer arithmetic
|
||||
for the reporting loop logic.
|
||||
|
||||
(cherry picked from commit 8873599b66612852136b3dbcb4ebefe0164271dd)
|
||||
---
|
||||
libdm/dm-tools/dmsetup.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libdm/dm-tools/dmsetup.c b/libdm/dm-tools/dmsetup.c
|
||||
index bf8449e35..2d6ed0a71 100644
|
||||
--- a/libdm/dm-tools/dmsetup.c
|
||||
+++ b/libdm/dm-tools/dmsetup.c
|
||||
@@ -268,7 +268,7 @@ static struct dm_tree *_dtree;
|
||||
static struct dm_report *_report;
|
||||
static report_type_t _report_type;
|
||||
static dev_name_t _dev_name_type;
|
||||
-static uint64_t _count = 1; /* count of repeating reports */
|
||||
+static int64_t _count = 1; /* count of repeating reports */
|
||||
static struct dm_timestamp *_initial_timestamp = NULL;
|
||||
static uint64_t _disp_factor = 512; /* display sizes in sectors */
|
||||
static char _disp_units = 's';
|
||||
@@ -593,7 +593,7 @@ static struct dm_split_name *_get_split_name(const char *uuid, const char *name,
|
||||
static uint64_t _interval_num(void)
|
||||
{
|
||||
uint64_t count_arg = _int_args[COUNT_ARG];
|
||||
- return ((uint64_t) _int_args[COUNT_ARG] - _count) + !!count_arg;
|
||||
+ return (uint64_t)(_int_args[COUNT_ARG] - _count) + !!count_arg;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_TIMERFD_H
|
||||
@@ -7342,9 +7342,9 @@ unknown:
|
||||
}
|
||||
|
||||
if (_switches[COUNT_ARG] && _int_args[COUNT_ARG])
|
||||
- _count = (uint64_t)_int_args[COUNT_ARG];
|
||||
+ _count = _int_args[COUNT_ARG];
|
||||
else if (_switches[COUNT_ARG] || _switches[INTERVAL_ARG])
|
||||
- _count = UINT64_MAX;
|
||||
+ _count = INT64_MAX;
|
||||
|
||||
if (_switches[UNITS_ARG]) {
|
||||
_disp_factor = _factor_from_units(_string_args[UNITS_ARG],
|
||||
--
|
||||
2.51.0
|
||||
|
||||
39
SOURCES/0028-cov-fix-va_end-resource-leak-in-szscanf.patch
Normal file
39
SOURCES/0028-cov-fix-va_end-resource-leak-in-szscanf.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 15164d1c1f84cd583e93b13e277f4cbae310b03b Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Sat, 28 Jun 2025 22:42:17 +0200
|
||||
Subject: [PATCH 28/47] cov: fix va_end resource leak in szscanf()
|
||||
|
||||
- Fix potential resource leak by ensuring va_end() is called on error path
|
||||
- Set matched = -1 and break from while loop instead of immediate return
|
||||
- This ensures proper cleanup of va_list when unsupported format
|
||||
specifiers are encountered in lvmlockctl.
|
||||
|
||||
The szscanf function is a custom string scanner used for parsing lvmlockd
|
||||
status information. Previously, encountering an unsupported format
|
||||
specifier would cause an immediate return without calling va_end(),
|
||||
leading to undefined behavior and potential resource leaks.
|
||||
|
||||
This fix ensures proper cleanup of variable argument lists in all code paths.
|
||||
|
||||
(cherry picked from commit a53352b4aaa9277cec96f61c50b05d6334320bfe)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockctl.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockctl.c b/daemons/lvmlockd/lvmlockctl.c
|
||||
index 5a4512095..4623e349d 100644
|
||||
--- a/daemons/lvmlockd/lvmlockctl.c
|
||||
+++ b/daemons/lvmlockd/lvmlockctl.c
|
||||
@@ -181,7 +181,8 @@ static int szscanf(const char *input, const char *format, ...)
|
||||
|
||||
} else {
|
||||
/* unsupported format specifier */
|
||||
- return -1;
|
||||
+ matched = -1;
|
||||
+ break;
|
||||
}
|
||||
|
||||
/* advance past 'd', 'u', or 's' character */
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,462 +0,0 @@
|
||||
From 5403a6f05987b21addb50c9b056e36567d631df7 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Wed, 17 Nov 2021 17:10:45 -0600
|
||||
Subject: [PATCH 28/54] devices: exclude multipath components based on matching
|
||||
wwid
|
||||
|
||||
If multipath component devices get through the filter and
|
||||
cause lvm to see duplicate PVs, then check the wwid of the
|
||||
devs and drop the component devices as if they had been
|
||||
filtered. If a dm mpath device was found among the duplicates
|
||||
then use that as the PV, otherwise do not use any of the
|
||||
components as the PV.
|
||||
|
||||
"duplicate PVs" associated with multipath configs will no
|
||||
longer stop commands from working.
|
||||
---
|
||||
lib/cache/lvmcache.c | 186 +++++++++++++++++++++++++-
|
||||
lib/device/dev-mpath.c | 71 ++++++++++
|
||||
lib/device/dev-type.h | 2 +
|
||||
lib/device/device_id.c | 4 +-
|
||||
lib/device/device_id.h | 2 +
|
||||
test/shell/duplicate-pvs-multipath.sh | 67 ++++++++++
|
||||
6 files changed, 323 insertions(+), 9 deletions(-)
|
||||
create mode 100644 test/shell/duplicate-pvs-multipath.sh
|
||||
|
||||
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
|
||||
index bee63ebb4..a0811d4ea 100644
|
||||
--- a/lib/cache/lvmcache.c
|
||||
+++ b/lib/cache/lvmcache.c
|
||||
@@ -625,6 +625,102 @@ static void _warn_unused_duplicates(struct cmd_context *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
+static int _all_multipath_components(struct cmd_context *cmd, struct lvmcache_info *info, const char *pvid,
|
||||
+ struct dm_list *altdevs, struct device **dev_mpath)
|
||||
+{
|
||||
+ struct device_list *devl;
|
||||
+ struct device *dev_mp = NULL;
|
||||
+ struct device *dev1 = NULL;
|
||||
+ struct device *dev;
|
||||
+ const char *wwid1 = NULL;
|
||||
+ const char *wwid;
|
||||
+ int diff_wwid = 0;
|
||||
+ int same_wwid = 0;
|
||||
+ int dev_is_mp;
|
||||
+
|
||||
+ *dev_mpath = NULL;
|
||||
+
|
||||
+ /* This function only makes sense with more than one dev. */
|
||||
+ if ((info && dm_list_empty(altdevs)) || (!info && (dm_list_size(altdevs) == 1))) {
|
||||
+ log_debug("Skip multipath component checks with single device for PVID %s", pvid);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ log_debug("Checking for multipath components for duplicate PVID %s", pvid);
|
||||
+
|
||||
+ if (info) {
|
||||
+ dev = info->dev;
|
||||
+ dev_is_mp = (cmd->dev_types->device_mapper_major == MAJOR(dev->dev)) && dev_has_mpath_uuid(cmd, dev, NULL);
|
||||
+
|
||||
+ if (dev_is_mp) {
|
||||
+ if ((wwid1 = dev_mpath_component_wwid(cmd, dev))) {
|
||||
+ dev_mp = dev;
|
||||
+ dev1 = dev;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if ((wwid1 = device_id_system_read(cmd, dev, DEV_ID_TYPE_SYS_WWID)))
|
||||
+ dev1 = dev;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ dm_list_iterate_items(devl, altdevs) {
|
||||
+ dev = devl->dev;
|
||||
+ dev_is_mp = (cmd->dev_types->device_mapper_major == MAJOR(dev->dev)) && dev_has_mpath_uuid(cmd, dev, NULL);
|
||||
+
|
||||
+ if (dev_is_mp)
|
||||
+ wwid = dev_mpath_component_wwid(cmd, dev);
|
||||
+ else
|
||||
+ wwid = device_id_system_read(cmd, dev, DEV_ID_TYPE_SYS_WWID);
|
||||
+
|
||||
+ if (!wwid && wwid1) {
|
||||
+ log_print("Different wwids for duplicate PVs %s %s %s none",
|
||||
+ dev_name(dev1), wwid1, dev_name(dev));
|
||||
+ diff_wwid++;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (!wwid)
|
||||
+ continue;
|
||||
+
|
||||
+ if (!wwid1) {
|
||||
+ wwid1 = wwid;
|
||||
+ dev1 = dev;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Different wwids indicates these are not multipath components. */
|
||||
+ if (strcmp(wwid1, wwid)) {
|
||||
+ log_print("Different wwids for duplicate PVs %s %s %s %s",
|
||||
+ dev_name(dev1), wwid1, dev_name(dev), wwid);
|
||||
+ diff_wwid++;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Different mpath devs with the same wwid shouldn't happen. */
|
||||
+ if (dev_is_mp && dev_mp) {
|
||||
+ log_print("Found multiple multipath devices for PVID %s WWID %s: %s %s",
|
||||
+ pvid, wwid1, dev_name(dev_mp), dev_name(dev));
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ log_debug("Same wwids for duplicate PVs %s %s", dev_name(dev1), dev_name(dev));
|
||||
+ same_wwid++;
|
||||
+
|
||||
+ /* Save the mpath device so it can be used as the PV. */
|
||||
+ if (dev_is_mp)
|
||||
+ dev_mp = dev;
|
||||
+ }
|
||||
+
|
||||
+ if (diff_wwid || !same_wwid)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (dev_mp)
|
||||
+ log_debug("Found multipath device %s for PVID %s WWID %s.", dev_name(dev_mp), pvid, wwid1);
|
||||
+
|
||||
+ *dev_mpath = dev_mp;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* If we've found devices with the same PVID, decide which one
|
||||
* to use.
|
||||
@@ -680,6 +776,8 @@ static void _choose_duplicates(struct cmd_context *cmd,
|
||||
struct device_list *devl, *devl_safe, *devl_add, *devl_del;
|
||||
struct lvmcache_info *info;
|
||||
struct device *dev1, *dev2;
|
||||
+ struct device *dev_mpath;
|
||||
+ struct device *dev_drop;
|
||||
const char *device_id = NULL, *device_id_type = NULL;
|
||||
const char *idname1 = NULL, *idname2 = NULL;
|
||||
uint32_t dev1_major, dev1_minor, dev2_major, dev2_minor;
|
||||
@@ -702,6 +800,7 @@ static void _choose_duplicates(struct cmd_context *cmd,
|
||||
next:
|
||||
dm_list_init(&altdevs);
|
||||
pvid = NULL;
|
||||
+ dev_mpath = NULL;
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl_safe, &_initial_duplicates) {
|
||||
if (!pvid) {
|
||||
@@ -720,23 +819,97 @@ next:
|
||||
return;
|
||||
}
|
||||
|
||||
+ info = lvmcache_info_from_pvid(pvid, NULL, 0);
|
||||
+
|
||||
/*
|
||||
- * Get rid of any md components before comparing alternatives.
|
||||
- * (Since an md component can never be used, it's not an
|
||||
- * option to use like other kinds of alternatives.)
|
||||
+ * Usually and ideally, components of md and multipath devs should have
|
||||
+ * been excluded by filters, and not scanned for a PV. In some unusual
|
||||
+ * cases the components can get through the filters, and a PV can be
|
||||
+ * found on them. Detecting the same PVID on both the component and
|
||||
+ * the md/mpath device gives us a last chance to drop the component.
|
||||
+ * An md/mpath component device is completely ignored, as if it had
|
||||
+ * been filtered, and not kept in the list unused duplicates.
|
||||
*/
|
||||
|
||||
- info = lvmcache_info_from_pvid(pvid, NULL, 0);
|
||||
+ /*
|
||||
+ * Get rid of multipath components based on matching wwids.
|
||||
+ */
|
||||
+ if (_all_multipath_components(cmd, info, pvid, &altdevs, &dev_mpath)) {
|
||||
+ if (info && dev_mpath && (info->dev != dev_mpath)) {
|
||||
+ /*
|
||||
+ * info should be dropped from lvmcache and info->dev
|
||||
+ * should be treated as if it had been excluded by a filter.
|
||||
+ * dev_mpath should be added to lvmcache by the caller.
|
||||
+ */
|
||||
+ dev_drop = info->dev;
|
||||
+
|
||||
+ /* Have caller add dev_mpath to lvmcache. */
|
||||
+ log_debug("Using multipath device %s for PVID %s.", dev_name(dev_mpath), pvid);
|
||||
+ if ((devl_add = zalloc(sizeof(*devl_add)))) {
|
||||
+ devl_add->dev = dev_mpath;
|
||||
+ dm_list_add(add_cache_devs, &devl_add->list);
|
||||
+ }
|
||||
+
|
||||
+ /* Remove dev_mpath from altdevs. */
|
||||
+ if ((devl = _get_devl_in_device_list(dev_mpath, &altdevs)))
|
||||
+ dm_list_del(&devl->list);
|
||||
+
|
||||
+ /* Remove info from lvmcache that came from the component dev. */
|
||||
+ log_debug("Ignoring multipath component %s with PVID %s (dropping info)", dev_name(dev_drop), pvid);
|
||||
+ lvmcache_del(info);
|
||||
+ info = NULL;
|
||||
+
|
||||
+ /* Make the component dev look like it was filtered. */
|
||||
+ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL);
|
||||
+ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL;
|
||||
+ }
|
||||
+
|
||||
+ if (info && !dev_mpath) {
|
||||
+ /*
|
||||
+ * Only mpath component devs were found and no actual
|
||||
+ * multipath dev, so drop the component from lvmcache.
|
||||
+ */
|
||||
+ dev_drop = info->dev;
|
||||
+
|
||||
+ log_debug("Ignoring multipath component %s with PVID %s (dropping info)", dev_name(dev_drop), pvid);
|
||||
+ lvmcache_del(info);
|
||||
+ info = NULL;
|
||||
+
|
||||
+ /* Make the component dev look like it was filtered. */
|
||||
+ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL);
|
||||
+ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL;
|
||||
+ }
|
||||
+
|
||||
+ dm_list_iterate_items_safe(devl, devl_safe, &altdevs) {
|
||||
+ /*
|
||||
+ * The altdevs are all mpath components that should look
|
||||
+ * like they were filtered, they are not in lvmcache.
|
||||
+ */
|
||||
+ dev_drop = devl->dev;
|
||||
+
|
||||
+ log_debug("Ignoring multipath component %s with PVID %s (dropping duplicate)", dev_name(dev_drop), pvid);
|
||||
+ dm_list_del(&devl->list);
|
||||
+
|
||||
+ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL);
|
||||
+ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL;
|
||||
+ }
|
||||
+ goto next;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Get rid of any md components.
|
||||
+ * FIXME: use a function like _all_multipath_components to pick the actual md device.
|
||||
+ */
|
||||
if (info && dev_is_md_component(cmd, info->dev, NULL, 1)) {
|
||||
/* does not go in del_cache_devs which become unused_duplicates */
|
||||
- log_debug_cache("PV %s drop MD component from scan selection %s", pvid, dev_name(info->dev));
|
||||
+ log_debug("Ignoring md component %s with PVID %s (dropping info)", dev_name(info->dev), pvid);
|
||||
lvmcache_del(info);
|
||||
info = NULL;
|
||||
}
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl_safe, &altdevs) {
|
||||
if (dev_is_md_component(cmd, devl->dev, NULL, 1)) {
|
||||
- log_debug_cache("PV %s drop MD component from scan duplicates %s", pvid, dev_name(devl->dev));
|
||||
+ log_debug("Ignoring md component %s with PVID %s (dropping duplicate)", dev_name(devl->dev), pvid);
|
||||
dm_list_del(&devl->list);
|
||||
}
|
||||
}
|
||||
@@ -744,7 +917,6 @@ next:
|
||||
if (dm_list_empty(&altdevs))
|
||||
goto next;
|
||||
|
||||
-
|
||||
/*
|
||||
* Find the device for the pvid that's currently in lvmcache.
|
||||
*/
|
||||
diff --git a/lib/device/dev-mpath.c b/lib/device/dev-mpath.c
|
||||
index ba7bf9740..cbbad9dc9 100644
|
||||
--- a/lib/device/dev-mpath.c
|
||||
+++ b/lib/device/dev-mpath.c
|
||||
@@ -482,3 +482,74 @@ found:
|
||||
return 1;
|
||||
}
|
||||
|
||||
+const char *dev_mpath_component_wwid(struct cmd_context *cmd, struct device *dev)
|
||||
+{
|
||||
+ char slaves_path[PATH_MAX];
|
||||
+ char wwid_path[PATH_MAX];
|
||||
+ char sysbuf[PATH_MAX] = { 0 };
|
||||
+ char *slave_name;
|
||||
+ const char *wwid = NULL;
|
||||
+ struct stat info;
|
||||
+ DIR *dr;
|
||||
+ struct dirent *de;
|
||||
+
|
||||
+ /* /sys/dev/block/253:7/slaves/sda/device/wwid */
|
||||
+
|
||||
+ if (dm_snprintf(slaves_path, sizeof(slaves_path), "%s/dev/block/%d:%d/slaves",
|
||||
+ dm_sysfs_dir(), (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
|
||||
+ log_warn("Sysfs path to check mpath components is too long.");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (stat(slaves_path, &info))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!S_ISDIR(info.st_mode)) {
|
||||
+ log_warn("Path %s is not a directory.", slaves_path);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ /* Get wwid from first component */
|
||||
+
|
||||
+ if (!(dr = opendir(slaves_path))) {
|
||||
+ log_debug("Device %s has no slaves dir", dev_name(dev));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ while ((de = readdir(dr))) {
|
||||
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
|
||||
+ continue;
|
||||
+
|
||||
+ /* slave_name "sda" */
|
||||
+ slave_name = de->d_name;
|
||||
+
|
||||
+ /* read /sys/block/sda/device/wwid */
|
||||
+
|
||||
+ if (dm_snprintf(wwid_path, sizeof(wwid_path), "%s/block/%s/device/wwid",
|
||||
+ dm_sysfs_dir(), slave_name) < 0) {
|
||||
+ log_warn("Failed to create sysfs wwid path for %s", slave_name);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ get_sysfs_value(wwid_path, sysbuf, sizeof(sysbuf), 0);
|
||||
+ if (!sysbuf[0])
|
||||
+ continue;
|
||||
+
|
||||
+ if (strstr(sysbuf, "scsi_debug")) {
|
||||
+ int i;
|
||||
+ for (i = 0; i < strlen(sysbuf); i++) {
|
||||
+ if (sysbuf[i] == ' ')
|
||||
+ sysbuf[i] = '_';
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((wwid = dm_pool_strdup(cmd->mem, sysbuf)))
|
||||
+ break;
|
||||
+ }
|
||||
+ if (closedir(dr))
|
||||
+ stack;
|
||||
+
|
||||
+ return wwid;
|
||||
+}
|
||||
+
|
||||
+
|
||||
diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
|
||||
index f3521c6e0..36fb8f258 100644
|
||||
--- a/lib/device/dev-type.h
|
||||
+++ b/lib/device/dev-type.h
|
||||
@@ -63,6 +63,8 @@ int dev_is_swap(struct cmd_context *cmd, struct device *dev, uint64_t *signature
|
||||
int dev_is_luks(struct cmd_context *cmd, struct device *dev, uint64_t *signature, int full);
|
||||
int dasd_is_cdl_formatted(struct device *dev);
|
||||
|
||||
+const char *dev_mpath_component_wwid(struct cmd_context *cmd, struct device *dev);
|
||||
+
|
||||
int dev_is_lvm1(struct device *dev, char *buf, int buflen);
|
||||
int dev_is_pool(struct device *dev, char *buf, int buflen);
|
||||
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index a33dcebe0..625576ec6 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -243,7 +243,7 @@ static int _dm_uuid_has_prefix(char *sysbuf, const char *prefix)
|
||||
}
|
||||
|
||||
/* the dm uuid uses the wwid of the underlying dev */
|
||||
-static int _dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out)
|
||||
+int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out)
|
||||
{
|
||||
char sysbuf[PATH_MAX] = { 0 };
|
||||
const char *idname;
|
||||
@@ -988,7 +988,7 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
|
||||
}
|
||||
|
||||
if (MAJOR(dev->dev) == cmd->dev_types->device_mapper_major) {
|
||||
- if (_dev_has_mpath_uuid(cmd, dev, &idname)) {
|
||||
+ if (dev_has_mpath_uuid(cmd, dev, &idname)) {
|
||||
idtype = DEV_ID_TYPE_MPATH_UUID;
|
||||
goto id_done;
|
||||
}
|
||||
diff --git a/lib/device/device_id.h b/lib/device/device_id.h
|
||||
index 939b3a0f4..4cf1374c8 100644
|
||||
--- a/lib/device/device_id.h
|
||||
+++ b/lib/device/device_id.h
|
||||
@@ -55,4 +55,6 @@ void unlink_searched_devnames(struct cmd_context *cmd);
|
||||
|
||||
int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize);
|
||||
|
||||
+int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out);
|
||||
+
|
||||
#endif
|
||||
diff --git a/test/shell/duplicate-pvs-multipath.sh b/test/shell/duplicate-pvs-multipath.sh
|
||||
new file mode 100644
|
||||
index 000000000..a145e4afb
|
||||
--- /dev/null
|
||||
+++ b/test/shell/duplicate-pvs-multipath.sh
|
||||
@@ -0,0 +1,67 @@
|
||||
+#!/usr/bin/env bash
|
||||
+
|
||||
+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
|
||||
+#
|
||||
+# This copyrighted material is made available to anyone wishing to use,
|
||||
+# modify, copy, or redistribute it subject to the terms and conditions
|
||||
+# of the GNU General Public License v.2.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software Foundation,
|
||||
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
+
|
||||
+test_description='udev rule and systemd unit run vgchange'
|
||||
+
|
||||
+SKIP_WITH_LVMPOLLD=1
|
||||
+SKIP_WITH_LVMLOCKD=1
|
||||
+
|
||||
+. lib/inittest
|
||||
+
|
||||
+# FIXME: skip until mpath/scsi_debug cleanup works after a failure
|
||||
+skip
|
||||
+
|
||||
+modprobe --dry-run scsi_debug || skip
|
||||
+multipath -l || skip
|
||||
+multipath -l | grep scsi_debug && skip
|
||||
+
|
||||
+# Turn off multipath_component_detection so that the duplicate
|
||||
+# resolution of mpath components is used.
|
||||
+aux lvmconf 'devices/multipath_component_detection = 0'
|
||||
+# Prevent wwids from being used for filtering.
|
||||
+aux lvmconf 'devices/multipath_wwids_file = "/dev/null"'
|
||||
+# Need to use /dev/mapper/mpath
|
||||
+aux lvmconf 'devices/dir = "/dev"'
|
||||
+aux lvmconf 'devices/scan = "/dev"'
|
||||
+# Could set filter to $MP and the component /dev/sd devs
|
||||
+aux lvmconf "devices/filter = [ \"a|.*|\" ]"
|
||||
+aux lvmconf "devices/global_filter = [ \"a|.*|\" ]"
|
||||
+
|
||||
+modprobe scsi_debug dev_size_mb=100 num_tgts=1 vpd_use_hostno=0 add_host=4 delay=20 max_luns=2 no_lun_0=1
|
||||
+sleep 2
|
||||
+
|
||||
+multipath -r
|
||||
+sleep 2
|
||||
+
|
||||
+MPB=$(multipath -l | grep scsi_debug | cut -f1 -d ' ')
|
||||
+echo $MPB
|
||||
+MP=/dev/mapper/$MPB
|
||||
+echo $MP
|
||||
+
|
||||
+pvcreate $MP
|
||||
+vgcreate $vg1 $MP
|
||||
+lvcreate -l1 $vg1
|
||||
+vgchange -an $vg1
|
||||
+
|
||||
+pvs |tee out
|
||||
+grep $MP out
|
||||
+for i in $(grep -H scsi_debug /sys/block/sd*/device/model | cut -f4 -d /); do
|
||||
+ not grep /dev/$i out;
|
||||
+done
|
||||
+
|
||||
+vgchange -an $vg1
|
||||
+vgremove -y $vg1
|
||||
+
|
||||
+sleep 2
|
||||
+multipath -f $MP
|
||||
+sleep 1
|
||||
+rmmod scsi_debug
|
||||
--
|
||||
2.34.3
|
||||
|
||||
44
SOURCES/0029-cov-add-explicit-check-for-0-size.patch
Normal file
44
SOURCES/0029-cov-add-explicit-check-for-0-size.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From b2814746de3fac6809c07dbd74ca606388a57aa8 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Mon, 30 Jun 2025 13:55:11 +0200
|
||||
Subject: [PATCH 29/47] cov: add explicit check for 0 size
|
||||
|
||||
(cherry picked from commit ae407d2f3cb1d607463d6d5964e44f11857cdb1f)
|
||||
---
|
||||
device_mapper/libdm-report.c | 4 +++-
|
||||
libdm/libdm-report.c | 4 +++-
|
||||
2 files changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/device_mapper/libdm-report.c b/device_mapper/libdm-report.c
|
||||
index b2dc1b70c..1521708ed 100644
|
||||
--- a/device_mapper/libdm-report.c
|
||||
+++ b/device_mapper/libdm-report.c
|
||||
@@ -3832,7 +3832,9 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
goto bad;
|
||||
fs->value->v.l = *((struct selection_str_list **) custom);
|
||||
|
||||
- s_arr_size = dm_list_size(&fs->value->v.l->str_list.list);
|
||||
+ if (!(s_arr_size = dm_list_size(&fs->value->v.l->str_list.list)))
|
||||
+ break;
|
||||
+
|
||||
if (!(s_arr = malloc(sizeof(char *) * s_arr_size))) {
|
||||
log_error("dm_report: malloc failed for regex array "
|
||||
"for selection field %s", field_id);
|
||||
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
|
||||
index 18f7b6eb8..b8686901f 100644
|
||||
--- a/libdm/libdm-report.c
|
||||
+++ b/libdm/libdm-report.c
|
||||
@@ -3829,7 +3829,9 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
goto bad;
|
||||
fs->value->v.l = *((struct selection_str_list **) custom);
|
||||
|
||||
- s_arr_size = dm_list_size(&fs->value->v.l->str_list.list);
|
||||
+ if (!(s_arr_size = dm_list_size(&fs->value->v.l->str_list.list)))
|
||||
+ break;
|
||||
+
|
||||
if (!(s_arr = malloc(sizeof(char *) * s_arr_size))) {
|
||||
log_error("dm_report: malloc failed for regex array "
|
||||
"for selection field %s", field_id);
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,268 +0,0 @@
|
||||
From 7b79acc6161b2cff81a03848c160dd6993a4477b Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Mon, 22 Nov 2021 15:10:43 -0600
|
||||
Subject: [PATCH 29/54] devices: exclude md components when duplicate pvs are
|
||||
seen
|
||||
|
||||
Improve handling of md components that get through the
|
||||
filter, like the previous improvement for multipath.
|
||||
If md components get through the filter and trigger
|
||||
duplicate PV code, then eliminate any devs entirely
|
||||
that are not an md device.
|
||||
---
|
||||
lib/cache/lvmcache.c | 168 ++++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 149 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
|
||||
index a0811d4ea..0e62cd267 100644
|
||||
--- a/lib/cache/lvmcache.c
|
||||
+++ b/lib/cache/lvmcache.c
|
||||
@@ -673,7 +673,7 @@ static int _all_multipath_components(struct cmd_context *cmd, struct lvmcache_in
|
||||
wwid = device_id_system_read(cmd, dev, DEV_ID_TYPE_SYS_WWID);
|
||||
|
||||
if (!wwid && wwid1) {
|
||||
- log_print("Different wwids for duplicate PVs %s %s %s none",
|
||||
+ log_debug("Different wwids for duplicate PVs %s %s %s none",
|
||||
dev_name(dev1), wwid1, dev_name(dev));
|
||||
diff_wwid++;
|
||||
continue;
|
||||
@@ -690,7 +690,7 @@ static int _all_multipath_components(struct cmd_context *cmd, struct lvmcache_in
|
||||
|
||||
/* Different wwids indicates these are not multipath components. */
|
||||
if (strcmp(wwid1, wwid)) {
|
||||
- log_print("Different wwids for duplicate PVs %s %s %s %s",
|
||||
+ log_debug("Different wwids for duplicate PVs %s %s %s %s",
|
||||
dev_name(dev1), wwid1, dev_name(dev), wwid);
|
||||
diff_wwid++;
|
||||
continue;
|
||||
@@ -721,6 +721,52 @@ static int _all_multipath_components(struct cmd_context *cmd, struct lvmcache_in
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int _all_md_components(struct cmd_context *cmd, struct lvmcache_info *info, const char *pvid,
|
||||
+ struct dm_list *altdevs, struct device **dev_md_out)
|
||||
+{
|
||||
+ struct device_list *devl;
|
||||
+ struct device *dev_md = NULL;
|
||||
+ struct device *dev;
|
||||
+ int real_dup = 0;
|
||||
+
|
||||
+ *dev_md_out = NULL;
|
||||
+
|
||||
+ /* There will often be no info struct because of the extra_md_checks function. */
|
||||
+
|
||||
+ if (info && (cmd->dev_types->md_major == MAJOR(info->dev->dev)))
|
||||
+ dev_md = info->dev;
|
||||
+
|
||||
+ dm_list_iterate_items(devl, altdevs) {
|
||||
+ dev = devl->dev;
|
||||
+
|
||||
+ if (cmd->dev_types->md_major == MAJOR(dev->dev)) {
|
||||
+ if (dev_md) {
|
||||
+ /* md devs themselves are dups */
|
||||
+ log_debug("Found multiple md devices for PVID %s: %s %s",
|
||||
+ pvid, dev_name(dev_md), dev_name(dev));
|
||||
+ real_dup = 1;
|
||||
+ break;
|
||||
+ } else
|
||||
+ dev_md = dev;
|
||||
+ } else {
|
||||
+ if (!dev_is_md_component(cmd, dev, NULL, 1)) {
|
||||
+ /* md dev copied to another device */
|
||||
+ real_dup = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (real_dup)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (dev_md)
|
||||
+ log_debug("Found md device %s for PVID %s.", dev_name(dev_md), pvid);
|
||||
+
|
||||
+ *dev_md_out = dev_md;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* If we've found devices with the same PVID, decide which one
|
||||
* to use.
|
||||
@@ -776,7 +822,7 @@ static void _choose_duplicates(struct cmd_context *cmd,
|
||||
struct device_list *devl, *devl_safe, *devl_add, *devl_del;
|
||||
struct lvmcache_info *info;
|
||||
struct device *dev1, *dev2;
|
||||
- struct device *dev_mpath;
|
||||
+ struct device *dev_mpath, *dev_md;
|
||||
struct device *dev_drop;
|
||||
const char *device_id = NULL, *device_id_type = NULL;
|
||||
const char *idname1 = NULL, *idname2 = NULL;
|
||||
@@ -801,6 +847,7 @@ next:
|
||||
dm_list_init(&altdevs);
|
||||
pvid = NULL;
|
||||
dev_mpath = NULL;
|
||||
+ dev_md = NULL;
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl_safe, &_initial_duplicates) {
|
||||
if (!pvid) {
|
||||
@@ -829,6 +876,11 @@ next:
|
||||
* the md/mpath device gives us a last chance to drop the component.
|
||||
* An md/mpath component device is completely ignored, as if it had
|
||||
* been filtered, and not kept in the list unused duplicates.
|
||||
+ *
|
||||
+ * One issue related to eliminating mpath/md duplicate PVs here is
|
||||
+ * that it occurs after label_scan, and hints are created based
|
||||
+ * on what label_scan finds, so hints are disabled due to duplicate
|
||||
+ * PVs that are later resolved here.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -898,24 +950,89 @@ next:
|
||||
|
||||
/*
|
||||
* Get rid of any md components.
|
||||
- * FIXME: use a function like _all_multipath_components to pick the actual md device.
|
||||
*/
|
||||
- if (info && dev_is_md_component(cmd, info->dev, NULL, 1)) {
|
||||
- /* does not go in del_cache_devs which become unused_duplicates */
|
||||
- log_debug("Ignoring md component %s with PVID %s (dropping info)", dev_name(info->dev), pvid);
|
||||
- lvmcache_del(info);
|
||||
- info = NULL;
|
||||
- }
|
||||
+ if (_all_md_components(cmd, info, pvid, &altdevs, &dev_md)) {
|
||||
+ if (info && dev_md && (info->dev != dev_md)) {
|
||||
+ /*
|
||||
+ * info should be dropped from lvmcache and info->dev
|
||||
+ * should be treated as if it had been excluded by a filter.
|
||||
+ * dev_md should be added to lvmcache by the caller.
|
||||
+ * Often this info struct has been removed by
|
||||
+ * lvmcache_extra_md_component_checks.
|
||||
+ */
|
||||
+ dev_drop = info->dev;
|
||||
|
||||
- dm_list_iterate_items_safe(devl, devl_safe, &altdevs) {
|
||||
- if (dev_is_md_component(cmd, devl->dev, NULL, 1)) {
|
||||
- log_debug("Ignoring md component %s with PVID %s (dropping duplicate)", dev_name(devl->dev), pvid);
|
||||
- dm_list_del(&devl->list);
|
||||
+ /* Have caller add dev_md to lvmcache. */
|
||||
+ log_debug("Using md device %s for PVID %s.", dev_name(dev_md), pvid);
|
||||
+ if ((devl_add = zalloc(sizeof(*devl_add)))) {
|
||||
+ devl_add->dev = dev_md;
|
||||
+ dm_list_add(add_cache_devs, &devl_add->list);
|
||||
+ }
|
||||
+
|
||||
+ /* Remove dev_md from altdevs. */
|
||||
+ if ((devl = _get_devl_in_device_list(dev_md, &altdevs)))
|
||||
+ dm_list_del(&devl->list);
|
||||
+
|
||||
+ /* Remove info from lvmcache that came from the component dev. */
|
||||
+ log_debug("Ignoring md component %s with PVID %s (dropping info)", dev_name(dev_drop), pvid);
|
||||
+ lvmcache_del(info);
|
||||
+ info = NULL;
|
||||
+
|
||||
+ /* Make the component dev look like it was filtered. */
|
||||
+ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL);
|
||||
+ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL;
|
||||
}
|
||||
- }
|
||||
|
||||
- if (dm_list_empty(&altdevs))
|
||||
+ if (!info && dev_md) {
|
||||
+ /*
|
||||
+ * The info struct was from a component and was dropped
|
||||
+ * and the actual md dev was found on initial_duplicates
|
||||
+ * and the caller should add it to lvmcache.
|
||||
+ */
|
||||
+
|
||||
+ /* Have caller add dev_md to lvmcache. */
|
||||
+ log_debug("Using md device %s for PVID %s.", dev_name(dev_md), pvid);
|
||||
+ if ((devl_add = zalloc(sizeof(*devl_add)))) {
|
||||
+ devl_add->dev = dev_md;
|
||||
+ dm_list_add(add_cache_devs, &devl_add->list);
|
||||
+ }
|
||||
+
|
||||
+ /* Remove dev_md from altdevs. */
|
||||
+ if ((devl = _get_devl_in_device_list(dev_md, &altdevs)))
|
||||
+ dm_list_del(&devl->list);
|
||||
+ }
|
||||
+
|
||||
+ if (info && !dev_md) {
|
||||
+ /*
|
||||
+ * Only md component devs were found and no actual
|
||||
+ * md dev, so drop the component from lvmcache.
|
||||
+ */
|
||||
+ dev_drop = info->dev;
|
||||
+
|
||||
+ log_debug("Ignoring md component %s with PVID %s (dropping info)", dev_name(dev_drop), pvid);
|
||||
+ lvmcache_del(info);
|
||||
+ info = NULL;
|
||||
+
|
||||
+ /* Make the component dev look like it was filtered. */
|
||||
+ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL);
|
||||
+ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL;
|
||||
+ }
|
||||
+
|
||||
+ dm_list_iterate_items_safe(devl, devl_safe, &altdevs) {
|
||||
+ /*
|
||||
+ * The altdevs are all md components that should look
|
||||
+ * like they were filtered, they are not in lvmcache.
|
||||
+ */
|
||||
+ dev_drop = devl->dev;
|
||||
+
|
||||
+ log_debug("Ignoring md component %s with PVID %s (dropping duplicate)", dev_name(dev_drop), pvid);
|
||||
+ dm_list_del(&devl->list);
|
||||
+
|
||||
+ cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL);
|
||||
+ dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL;
|
||||
+ }
|
||||
goto next;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* Find the device for the pvid that's currently in lvmcache.
|
||||
@@ -1321,6 +1438,18 @@ int lvmcache_label_reopen_vg_rw(struct cmd_context *cmd, const char *vgname, con
|
||||
* times it can be a clue that label_scan mistakenly read the pv from an md
|
||||
* component device instead of from the md device itself. So for unmatching
|
||||
* sizes, we do a full md component check on the device.
|
||||
+ *
|
||||
+ * It might be nice to do this checking in the filter (when passes_filter is
|
||||
+ * called after the initial read), but that doesn't work because passes_filter
|
||||
+ * is called before _text_read so metadata/pvsummary info is not yet available
|
||||
+ * which this function uses.
|
||||
+ *
|
||||
+ * The unique value of this function is that it can eliminate md components
|
||||
+ * without there being duplicate PVs. But, there will often be duplicate PVs,
|
||||
+ * handled by _all_md_components(), where other devs with the same pvid will be
|
||||
+ * in _initial_duplicates. One could be the md device itself which will be
|
||||
+ * added to lvmcache by choose_duplicates, and other duplicates that are
|
||||
+ * components will be dropped.
|
||||
*/
|
||||
|
||||
void lvmcache_extra_md_component_checks(struct cmd_context *cmd)
|
||||
@@ -1382,7 +1511,8 @@ void lvmcache_extra_md_component_checks(struct cmd_context *cmd)
|
||||
*/
|
||||
if (pvsize && devsize && (pvsize != devsize))
|
||||
do_check_size = 1;
|
||||
- if (device_hint && !strncmp(device_hint, "/dev/md", 7))
|
||||
+ if (device_hint && !strncmp(device_hint, "/dev/md", 7) &&
|
||||
+ (MAJOR(info->dev->dev) != cmd->dev_types->md_major))
|
||||
do_check_name = 1;
|
||||
|
||||
if (!do_check_size && !do_check_name)
|
||||
@@ -1412,11 +1542,11 @@ void lvmcache_extra_md_component_checks(struct cmd_context *cmd)
|
||||
device_hint ?: "none", dev_name(dev));
|
||||
|
||||
if (dev_is_md_component(cmd, dev, NULL, 1)) {
|
||||
- log_debug("dropping PV from md component %s", dev_name(dev));
|
||||
+ log_debug("Ignoring PV from md component %s with PVID %s (metadata %s %llu)",
|
||||
+ dev_name(dev), dev->pvid, device_hint ?: "none", (unsigned long long)pvsize);
|
||||
dev->flags &= ~DEV_SCAN_FOUND_LABEL;
|
||||
/* lvmcache_del will also delete vginfo if info was last one */
|
||||
lvmcache_del(info);
|
||||
- lvmcache_del_dev_from_duplicates(dev);
|
||||
cmd->filter->wipe(cmd, cmd->filter, dev, NULL);
|
||||
}
|
||||
}
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
From 51f6e02a458f763d4066782549f0b3873317119d Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Mon, 30 Jun 2025 14:32:10 +0200
|
||||
Subject: [PATCH 30/47] cov: explicitly zero allocated mem for array
|
||||
|
||||
Replace malloc() with calloc() when allocating the string pointer array
|
||||
for regex pattern matching in _create_field_selection(). This ensures
|
||||
all array elements are initialized to NULL pointers, preventing potential
|
||||
use of uninitialized memory objected by Coverity.
|
||||
|
||||
Existing code sets all elements in the follow up loop.
|
||||
|
||||
(cherry picked from commit 2c5489dd13045624e9597d11a85a29c8408cc0e8)
|
||||
---
|
||||
device_mapper/libdm-report.c | 2 +-
|
||||
libdm/libdm-report.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/device_mapper/libdm-report.c b/device_mapper/libdm-report.c
|
||||
index 1521708ed..4c3f3266a 100644
|
||||
--- a/device_mapper/libdm-report.c
|
||||
+++ b/device_mapper/libdm-report.c
|
||||
@@ -3835,7 +3835,7 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
if (!(s_arr_size = dm_list_size(&fs->value->v.l->str_list.list)))
|
||||
break;
|
||||
|
||||
- if (!(s_arr = malloc(sizeof(char *) * s_arr_size))) {
|
||||
+ if (!(s_arr = calloc(s_arr_size, sizeof(char *)))) {
|
||||
log_error("dm_report: malloc failed for regex array "
|
||||
"for selection field %s", field_id);
|
||||
goto error;
|
||||
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
|
||||
index b8686901f..36d99f7d7 100644
|
||||
--- a/libdm/libdm-report.c
|
||||
+++ b/libdm/libdm-report.c
|
||||
@@ -3832,7 +3832,7 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
if (!(s_arr_size = dm_list_size(&fs->value->v.l->str_list.list)))
|
||||
break;
|
||||
|
||||
- if (!(s_arr = malloc(sizeof(char *) * s_arr_size))) {
|
||||
+ if (!(s_arr = calloc(s_arr_size, sizeof(char *)))) {
|
||||
log_error("dm_report: malloc failed for regex array "
|
||||
"for selection field %s", field_id);
|
||||
goto error;
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,246 +0,0 @@
|
||||
From 4e72068216b006edc69c8bafba5198051e3ed1dd Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Tue, 25 Jan 2022 11:35:36 -0600
|
||||
Subject: [PATCH 30/54] lvmdevices: fix checks when adding entries
|
||||
|
||||
Removes some incorrect and unnecessary checks for other entries
|
||||
when adding a new devices. The removed checks and corrections were
|
||||
mostly redundant with what is already done by device id matching.
|
||||
Other checking is reworked so the warnings are a bit different.
|
||||
---
|
||||
lib/device/device_id.c | 153 +++++++++++++----------------------------
|
||||
1 file changed, 48 insertions(+), 105 deletions(-)
|
||||
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index 625576ec6..ccc5f43a1 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -935,6 +935,10 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
|
||||
struct dev_use *du, *update_du = NULL, *du_dev, *du_pvid, *du_devname, *du_devid;
|
||||
struct dev_id *id;
|
||||
int found_id = 0;
|
||||
+ int part = 0;
|
||||
+
|
||||
+ if (!dev_get_partition_number(dev, &part))
|
||||
+ return_0;
|
||||
|
||||
/*
|
||||
* When enable_devices_file=0 and pending_devices_file=1 we let
|
||||
@@ -953,10 +957,6 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
|
||||
*/
|
||||
memcpy(&pvid, pvid_arg, ID_LEN);
|
||||
|
||||
- du_dev = get_du_for_dev(cmd, dev);
|
||||
- du_pvid = get_du_for_pvid(cmd, pvid);
|
||||
- du_devname = _get_du_for_devname(cmd, dev_name(dev));
|
||||
-
|
||||
/*
|
||||
* Choose the device_id type for the device being added.
|
||||
*
|
||||
@@ -1072,6 +1072,9 @@ id_done:
|
||||
idtype = 0;
|
||||
|
||||
/*
|
||||
+ * "dev" is the device we are adding.
|
||||
+ * "id" is the device_id it's using, set in dev->id.
|
||||
+ *
|
||||
* Update the cmd->use_devices list for the new device. The
|
||||
* use_devices list will be used to update the devices file.
|
||||
*
|
||||
@@ -1083,23 +1086,57 @@ id_done:
|
||||
* those other entries to fix any incorrect info.
|
||||
*/
|
||||
|
||||
+ /* Is there already an entry matched to this device? */
|
||||
+ du_dev = get_du_for_dev(cmd, dev);
|
||||
+
|
||||
+ /* Is there already an entry matched to this device's pvid? */
|
||||
+ du_pvid = get_du_for_pvid(cmd, pvid);
|
||||
+
|
||||
+ /* Is there already an entry using this device's name? */
|
||||
+ du_devname = _get_du_for_devname(cmd, dev_name(dev));
|
||||
+
|
||||
+ /* Is there already an entry using the device_id for this device? */
|
||||
du_devid = _get_du_for_device_id(cmd, id->idtype, id->idname);
|
||||
|
||||
if (du_dev)
|
||||
- log_debug("device_id_add %s pvid %s matches du_dev %p dev %s",
|
||||
+ log_debug("device_id_add %s pvid %s matches entry %p dev %s",
|
||||
dev_name(dev), pvid, du_dev, dev_name(du_dev->dev));
|
||||
if (du_pvid)
|
||||
- log_debug("device_id_add %s pvid %s matches du_pvid %p dev %s pvid %s",
|
||||
+ log_debug("device_id_add %s pvid %s matches entry %p dev %s with same pvid %s",
|
||||
dev_name(dev), pvid, du_pvid, du_pvid->dev ? dev_name(du_pvid->dev) : ".",
|
||||
du_pvid->pvid);
|
||||
if (du_devid)
|
||||
- log_debug("device_id_add %s pvid %s matches du_devid %p dev %s pvid %s",
|
||||
+ log_debug("device_id_add %s pvid %s matches entry %p dev %s with same device_id %d %s",
|
||||
dev_name(dev), pvid, du_devid, du_devid->dev ? dev_name(du_devid->dev) : ".",
|
||||
- du_devid->pvid);
|
||||
+ du_devid->idtype, du_devid->idname);
|
||||
if (du_devname)
|
||||
- log_debug("device_id_add %s pvid %s matches du_devname %p dev %s pvid %s",
|
||||
+ log_debug("device_id_add %s pvid %s matches entry %p dev %s with same devname %s",
|
||||
dev_name(dev), pvid, du_devname, du_devname->dev ? dev_name(du_devname->dev) : ".",
|
||||
- du_devname->pvid);
|
||||
+ du_devname->devname);
|
||||
+
|
||||
+ if (du_pvid && (du_pvid->dev != dev))
|
||||
+ log_warn("WARNING: adding device %s with PVID %s which is already used for %s.",
|
||||
+ dev_name(dev), pvid, du_pvid->dev ? dev_name(du_pvid->dev) : "missing device");
|
||||
+
|
||||
+ if (du_devid && (du_devid->dev != dev)) {
|
||||
+ if (!du_devid->dev) {
|
||||
+ log_warn("WARNING: adding device %s with idname %s which is already used for missing device.",
|
||||
+ dev_name(dev), id->idname);
|
||||
+ } else {
|
||||
+ int ret1, ret2;
|
||||
+ dev_t devt1, devt2;
|
||||
+ /* Check if both entries are partitions of the same device. */
|
||||
+ ret1 = dev_get_primary_dev(cmd->dev_types, dev, &devt1);
|
||||
+ ret2 = dev_get_primary_dev(cmd->dev_types, du_devid->dev, &devt2);
|
||||
+ if ((ret1 == 2) && (ret2 == 2) && (devt1 == devt2)) {
|
||||
+ log_debug("Using separate entries for partitions of same device %s part %d %s part %d.",
|
||||
+ dev_name(dev), part, dev_name(du_devid->dev), du_devid->part);
|
||||
+ } else {
|
||||
+ log_warn("WARNING: adding device %s with idname %s which is already used for %s.",
|
||||
+ dev_name(dev), id->idname, dev_name(du_devid->dev));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/*
|
||||
* If one of the existing entries (du_dev, du_pvid, du_devid, du_devname)
|
||||
@@ -1112,29 +1149,6 @@ id_done:
|
||||
dm_list_del(&update_du->list);
|
||||
update_matching_kind = "device";
|
||||
update_matching_name = dev_name(dev);
|
||||
-
|
||||
- if (du_devid && (du_devid != du_dev)) {
|
||||
- log_warn("WARNING: device %s (%s) and %s (%s) have duplicate device ID.",
|
||||
- dev_name(dev), id->idname,
|
||||
- (du_pvid && du_pvid->dev) ? dev_name(du_pvid->dev) : "none",
|
||||
- du_pvid ? du_pvid->idname : "");
|
||||
- }
|
||||
-
|
||||
- if (du_pvid && (du_pvid != du_dev)) {
|
||||
- log_warn("WARNING: device %s (%s) and %s (%s) have duplicate PVID %s",
|
||||
- dev_name(dev), id->idname,
|
||||
- du_pvid->dev ? dev_name(du_pvid->dev) : "none", du_pvid->idname,
|
||||
- pvid);
|
||||
- }
|
||||
-
|
||||
- if (du_devname && (du_devname != du_dev)) {
|
||||
- /* clear devname in another entry with our devname */
|
||||
- log_warn("Devices file PVID %s clearing wrong DEVNAME %s.",
|
||||
- du_devname->pvid, du_devname->devname);
|
||||
- free(du_devname->devname);
|
||||
- du_devname->devname = NULL;
|
||||
- }
|
||||
-
|
||||
} else if (du_pvid) {
|
||||
/*
|
||||
* If the device_id of the existing entry for PVID is the same
|
||||
@@ -1154,11 +1168,6 @@ id_done:
|
||||
update_matching_kind = "PVID";
|
||||
update_matching_name = pvid;
|
||||
} else {
|
||||
- log_warn("WARNING: device %s (%s) and %s (%s) have duplicate PVID %s",
|
||||
- dev_name(dev), id->idname,
|
||||
- du_pvid->dev ? dev_name(du_pvid->dev) : "none", du_pvid->idname,
|
||||
- pvid);
|
||||
-
|
||||
if (!cmd->current_settings.yes &&
|
||||
yes_no_prompt("Add device with duplicate PV to devices file?") == 'n') {
|
||||
log_print("Device not added.");
|
||||
@@ -1166,21 +1175,6 @@ id_done:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
-
|
||||
- if (du_devid && (du_devid != du_pvid)) {
|
||||
- /* warn about another entry using the same device_id */
|
||||
- log_warn("WARNING: duplicate device_id %s for PVIDs %s %s",
|
||||
- du_devid->idname, du_devid->pvid, du_pvid->pvid);
|
||||
- }
|
||||
-
|
||||
- if (du_devname && (du_devname != du_pvid)) {
|
||||
- /* clear devname in another entry with our devname */
|
||||
- log_warn("Devices file PVID %s clearing wrong DEVNAME %s.",
|
||||
- du_devname->pvid, du_devname->devname);
|
||||
- free(du_devname->devname);
|
||||
- du_devname->devname = NULL;
|
||||
- }
|
||||
-
|
||||
} else if (du_devid) {
|
||||
/*
|
||||
* Do we create a new du or update the existing du?
|
||||
@@ -1195,64 +1189,13 @@ id_done:
|
||||
* the same device_id (create a new du for dev.)
|
||||
* If not, then update the existing du_devid.
|
||||
*/
|
||||
-
|
||||
- if (du_devid->dev != dev)
|
||||
- check_idname = device_id_system_read(cmd, du_devid->dev, id->idtype);
|
||||
-
|
||||
- if (check_idname && !strcmp(check_idname, id->idname)) {
|
||||
- int ret1, ret2;
|
||||
- dev_t devt1, devt2;
|
||||
-
|
||||
- /*
|
||||
- * two different devices have the same device_id,
|
||||
- * create a new du for the device being added
|
||||
- */
|
||||
-
|
||||
- /* dev_is_partitioned() the dev open to read it. */
|
||||
- if (!label_scan_open(du_devid->dev))
|
||||
- log_warn("Cannot open %s", dev_name(du_devid->dev));
|
||||
-
|
||||
- if (dev_is_partitioned(cmd, du_devid->dev)) {
|
||||
- /* Check if existing entry is whole device and new entry is a partition of it. */
|
||||
- ret1 = dev_get_primary_dev(cmd->dev_types, dev, &devt1);
|
||||
- if ((ret1 == 2) && (devt1 == du_devid->dev->dev))
|
||||
- log_warn("Remove partitioned device %s from devices file.", dev_name(du_devid->dev));
|
||||
- } else {
|
||||
- /* Check if both entries are partitions of the same device. */
|
||||
- ret1 = dev_get_primary_dev(cmd->dev_types, dev, &devt1);
|
||||
- ret2 = dev_get_primary_dev(cmd->dev_types, du_devid->dev, &devt2);
|
||||
-
|
||||
- if ((ret1 == 2) && (ret2 == 2) && (devt1 == devt2)) {
|
||||
- log_warn("Partitions %s %s have same device_id %s",
|
||||
- dev_name(dev), dev_name(du_devid->dev), id->idname);
|
||||
- } else {
|
||||
- log_warn("Duplicate device_id %s %s for %s and %s",
|
||||
- idtype_to_str(id->idtype), check_idname,
|
||||
- dev_name(dev), dev_name(du_devid->dev));
|
||||
- }
|
||||
- }
|
||||
- } else {
|
||||
+ if (du_devid->dev == dev) {
|
||||
/* update the existing entry with matching devid */
|
||||
update_du = du_devid;
|
||||
dm_list_del(&update_du->list);
|
||||
update_matching_kind = "device_id";
|
||||
update_matching_name = id->idname;
|
||||
}
|
||||
-
|
||||
- if (du_devname && (du_devname != du_devid)) {
|
||||
- /* clear devname in another entry with our devname */
|
||||
- log_warn("Devices file PVID %s clearing wrong DEVNAME %s",
|
||||
- du_devname->pvid, du_devname->devname);
|
||||
- free(du_devname->devname);
|
||||
- du_devname->devname = NULL;
|
||||
- }
|
||||
-
|
||||
- } else if (du_devname) {
|
||||
- /* clear devname in another entry with our devname */
|
||||
- log_warn("Devices file PVID %s clearing wrong DEVNAME %s",
|
||||
- du_devname->pvid, du_devname->devname);
|
||||
- free(du_devname->devname);
|
||||
- du_devname->devname = NULL;
|
||||
}
|
||||
|
||||
free((void *)check_idname);
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
From 940d475e612a8ae2e3fe48213e7ed2a5c2a40705 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Mon, 30 Jun 2025 14:11:16 +0200
|
||||
Subject: [PATCH 31/47] cov: check for potential empty registry list
|
||||
|
||||
Check early for empty thread_registry list and return EINVAL
|
||||
instead of doing zero length allocation.
|
||||
|
||||
(cherry picked from commit bf580fcc2f17a0c7c732b929ed08acaf9dd831d7)
|
||||
---
|
||||
daemons/dmeventd/dmeventd.c | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
|
||||
index b823a0476..2224ba23e 100644
|
||||
--- a/daemons/dmeventd/dmeventd.c
|
||||
+++ b/daemons/dmeventd/dmeventd.c
|
||||
@@ -680,7 +680,12 @@ static int _get_status(struct message_data *message_data)
|
||||
return -EINVAL;
|
||||
|
||||
_lock_mutex();
|
||||
- count = dm_list_size(&_thread_registry);
|
||||
+ if (!(count = dm_list_size(&_thread_registry))) {
|
||||
+ _unlock_mutex();
|
||||
+ ret = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
buffers = alloca(sizeof(char*) * count);
|
||||
dm_list_iterate_items(thread, &_thread_registry) {
|
||||
if ((current = dm_asprintf(buffers + i, "0:%d %s %s %u %" PRIu32 ";",
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,106 +0,0 @@
|
||||
From df2b1555aff71452cde156badec70117065c9e2c Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Thu, 3 Feb 2022 16:56:03 -0600
|
||||
Subject: [PATCH 31/54] lvmdevices: make deldev work for missing device
|
||||
|
||||
---
|
||||
lib/device/device_id.c | 6 +++---
|
||||
lib/device/device_id.h | 1 +
|
||||
tools/lvmdevices.c | 33 ++++++++++++++++-----------------
|
||||
3 files changed, 20 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index ccc5f43a1..aeaa1ffc6 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -894,7 +894,7 @@ struct dev_use *get_du_for_pvid(struct cmd_context *cmd, const char *pvid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static struct dev_use *_get_du_for_devname(struct cmd_context *cmd, const char *devname)
|
||||
+struct dev_use *get_du_for_devname(struct cmd_context *cmd, const char *devname)
|
||||
{
|
||||
struct dev_use *du;
|
||||
|
||||
@@ -1093,7 +1093,7 @@ id_done:
|
||||
du_pvid = get_du_for_pvid(cmd, pvid);
|
||||
|
||||
/* Is there already an entry using this device's name? */
|
||||
- du_devname = _get_du_for_devname(cmd, dev_name(dev));
|
||||
+ du_devname = get_du_for_devname(cmd, dev_name(dev));
|
||||
|
||||
/* Is there already an entry using the device_id for this device? */
|
||||
du_devid = _get_du_for_device_id(cmd, id->idtype, id->idname);
|
||||
@@ -1514,7 +1514,7 @@ int device_ids_match_dev(struct cmd_context *cmd, struct device *dev)
|
||||
struct dev_use *du;
|
||||
|
||||
/* First check the du entry with matching devname since it's likely correct. */
|
||||
- if ((du = _get_du_for_devname(cmd, dev_name(dev)))) {
|
||||
+ if ((du = get_du_for_devname(cmd, dev_name(dev)))) {
|
||||
if (_match_du_to_dev(cmd, du, dev))
|
||||
return 1;
|
||||
}
|
||||
diff --git a/lib/device/device_id.h b/lib/device/device_id.h
|
||||
index 4cf1374c8..2cd2fd7c6 100644
|
||||
--- a/lib/device/device_id.h
|
||||
+++ b/lib/device/device_id.h
|
||||
@@ -40,6 +40,7 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg,
|
||||
|
||||
struct dev_use *get_du_for_dev(struct cmd_context *cmd, struct device *dev);
|
||||
struct dev_use *get_du_for_pvid(struct cmd_context *cmd, const char *pvid);
|
||||
+struct dev_use *get_du_for_devname(struct cmd_context *cmd, const char *devname);
|
||||
|
||||
char *devices_file_version(void);
|
||||
int devices_file_exists(struct cmd_context *cmd);
|
||||
diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c
|
||||
index c50c09f90..662b35f9a 100644
|
||||
--- a/tools/lvmdevices.c
|
||||
+++ b/tools/lvmdevices.c
|
||||
@@ -383,28 +383,27 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
* No filter because we always want to allow removing a device
|
||||
* by name from the devices file.
|
||||
*/
|
||||
- if (!(dev = dev_cache_get(cmd, devname, NULL))) {
|
||||
- log_error("No device found for %s.", devname);
|
||||
- goto bad;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * dev_cache_scan uses sysfs to check if an LV is using each dev
|
||||
- * and sets this flag is so.
|
||||
- */
|
||||
- if (dev_is_used_by_active_lv(cmd, dev, NULL, NULL, NULL, NULL)) {
|
||||
- if (!arg_count(cmd, yes_ARG) &&
|
||||
- yes_no_prompt("Device %s is used by an active LV, continue to remove? ", devname) == 'n') {
|
||||
- log_error("Device not removed.");
|
||||
- goto bad;
|
||||
+ if ((dev = dev_cache_get(cmd, devname, NULL))) {
|
||||
+ /*
|
||||
+ * dev_cache_scan uses sysfs to check if an LV is using each dev
|
||||
+ * and sets this flag is so.
|
||||
+ */
|
||||
+ if (dev_is_used_by_active_lv(cmd, dev, NULL, NULL, NULL, NULL)) {
|
||||
+ if (!arg_count(cmd, yes_ARG) &&
|
||||
+ yes_no_prompt("Device %s is used by an active LV, continue to remove? ", devname) == 'n') {
|
||||
+ log_error("Device not removed.");
|
||||
+ goto bad;
|
||||
+ }
|
||||
}
|
||||
+ if ((du = get_du_for_dev(cmd, dev)))
|
||||
+ goto dev_del;
|
||||
}
|
||||
|
||||
- if (!(du = get_du_for_dev(cmd, dev))) {
|
||||
- log_error("Device not found in devices file.");
|
||||
+ if (!(du = get_du_for_devname(cmd, devname))) {
|
||||
+ log_error("No devices file entry for %s.", devname);
|
||||
goto bad;
|
||||
}
|
||||
-
|
||||
+ dev_del:
|
||||
dm_list_del(&du->list);
|
||||
free_du(du);
|
||||
device_ids_write(cmd);
|
||||
--
|
||||
2.34.3
|
||||
|
||||
54
SOURCES/0032-cov-check-for-potential-empty-row-list.patch
Normal file
54
SOURCES/0032-cov-check-for-potential-empty-row-list.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From ceb2cbb8a9252222e24d919977b149a5f455c11c Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Mon, 30 Jun 2025 14:14:01 +0200
|
||||
Subject: [PATCH 32/47] cov: check for potential empty row list
|
||||
|
||||
Skip potential 0 length allocation and return early for empty list.
|
||||
|
||||
(cherry picked from commit 9fcc66316cd5f4b78b78ab1e0d50fafad362d499)
|
||||
---
|
||||
device_mapper/libdm-report.c | 7 +++++--
|
||||
libdm/libdm-report.c | 7 +++++--
|
||||
2 files changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/device_mapper/libdm-report.c b/device_mapper/libdm-report.c
|
||||
index 4c3f3266a..343a7edbc 100644
|
||||
--- a/device_mapper/libdm-report.c
|
||||
+++ b/device_mapper/libdm-report.c
|
||||
@@ -4668,9 +4668,12 @@ static int _sort_rows(struct dm_report *rh)
|
||||
struct row *(*rows)[];
|
||||
uint32_t count = 0;
|
||||
struct row *row;
|
||||
+ size_t cnt_rows;
|
||||
|
||||
- if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) *
|
||||
- dm_list_size(&rh->rows)))) {
|
||||
+ if (!(cnt_rows = dm_list_size(&rh->rows)))
|
||||
+ return 1; /* nothing to sort */
|
||||
+
|
||||
+ if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) * cnt_rows))) {
|
||||
log_error("dm_report: sort array allocation failed");
|
||||
return 0;
|
||||
}
|
||||
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
|
||||
index 36d99f7d7..87c588c3c 100644
|
||||
--- a/libdm/libdm-report.c
|
||||
+++ b/libdm/libdm-report.c
|
||||
@@ -4665,9 +4665,12 @@ static int _sort_rows(struct dm_report *rh)
|
||||
struct row *(*rows)[];
|
||||
uint32_t count = 0;
|
||||
struct row *row;
|
||||
+ size_t cnt_rows;
|
||||
|
||||
- if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) *
|
||||
- dm_list_size(&rh->rows)))) {
|
||||
+ if (!(cnt_rows = dm_list_size(&rh->rows)))
|
||||
+ return 1; /* nothing to sort */
|
||||
+
|
||||
+ if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) * cnt_rows))) {
|
||||
log_error("dm_report: sort array allocation failed");
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,144 +0,0 @@
|
||||
From 08a5619a1d7a5a8dd6e0df6e4dedec47ce2533b7 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Thu, 10 Feb 2022 14:00:25 -0600
|
||||
Subject: [PATCH 32/54] devices file: do not clear PVID of unread devices
|
||||
|
||||
In a certain disconnected state, a block device is present on
|
||||
the system, can be opened, reports a valid size, reports the
|
||||
correct device id (wwid), and matches a devices file entry.
|
||||
But, reading the device can still fail. In this case,
|
||||
device_ids_validate() was misinterpreting the read error as
|
||||
the device having no data/label on it (and no PVID).
|
||||
The validate function would then clear the PVID from the
|
||||
devices file entry for the device, thinking that it was
|
||||
fixing the devices file (making it consistent with the on disk
|
||||
state.) Fix this by not attempting to check and correct a
|
||||
devices file entry that cannot be read. Also make this case
|
||||
explicit in the hints validation code (which was doing the
|
||||
right thing but indirectly.)
|
||||
---
|
||||
lib/device/device.h | 1 +
|
||||
lib/device/device_id.c | 14 ++++++++++++++
|
||||
lib/label/hints.c | 14 ++++++++++++++
|
||||
lib/label/label.c | 8 ++++++++
|
||||
4 files changed, 37 insertions(+)
|
||||
|
||||
diff --git a/lib/device/device.h b/lib/device/device.h
|
||||
index 9e471a9b5..8c3a8c30e 100644
|
||||
--- a/lib/device/device.h
|
||||
+++ b/lib/device/device.h
|
||||
@@ -40,6 +40,7 @@
|
||||
#define DEV_IS_NVME 0x00040000 /* set if dev is nvme */
|
||||
#define DEV_MATCHED_USE_ID 0x00080000 /* matched an entry from cmd->use_devices */
|
||||
#define DEV_SCAN_FOUND_NOLABEL 0x00100000 /* label_scan read, passed filters, but no lvm label */
|
||||
+#define DEV_SCAN_NOT_READ 0x00200000 /* label_scan not able to read dev */
|
||||
|
||||
/*
|
||||
* Support for external device info.
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index aeaa1ffc6..7fe581571 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -1724,6 +1724,13 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
|
||||
if (scanned_devs && !dev_in_device_list(dev, scanned_devs))
|
||||
continue;
|
||||
|
||||
+ /*
|
||||
+ * The matched device could not be read so we do not have
|
||||
+ * the PVID from disk and cannot verify the devices file entry.
|
||||
+ */
|
||||
+ if (dev->flags & DEV_SCAN_NOT_READ)
|
||||
+ continue;
|
||||
+
|
||||
/*
|
||||
* du and dev may have been matched, but the dev could still
|
||||
* have been excluded by other filters during label scan.
|
||||
@@ -1806,6 +1813,13 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
|
||||
if (scanned_devs && !dev_in_device_list(dev, scanned_devs))
|
||||
continue;
|
||||
|
||||
+ /*
|
||||
+ * The matched device could not be read so we do not have
|
||||
+ * the PVID from disk and cannot verify the devices file entry.
|
||||
+ */
|
||||
+ if (dev->flags & DEV_SCAN_NOT_READ)
|
||||
+ continue;
|
||||
+
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) {
|
||||
log_warn("Devices file %s is excluded by filter: %s.",
|
||||
dev_name(dev), dev_filtered_reason(dev));
|
||||
diff --git a/lib/label/hints.c b/lib/label/hints.c
|
||||
index 3ce9634f2..95d5d77b8 100644
|
||||
--- a/lib/label/hints.c
|
||||
+++ b/lib/label/hints.c
|
||||
@@ -234,6 +234,7 @@ static int _touch_newhints(void)
|
||||
return_0;
|
||||
if (fclose(fp))
|
||||
stack;
|
||||
+ log_debug("newhints created");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -504,6 +505,19 @@ int validate_hints(struct cmd_context *cmd, struct dm_list *hints)
|
||||
if (!hint->chosen)
|
||||
continue;
|
||||
|
||||
+ /*
|
||||
+ * label_scan was unable to read the dev so we don't know its pvid.
|
||||
+ * Since we are unable to verify the hint is correct, it's possible
|
||||
+ * that the PVID is actually found on a different device, so don't
|
||||
+ * depend on hints. (This would also fail the following pvid check.)
|
||||
+ */
|
||||
+ if (dev->flags & DEV_SCAN_NOT_READ) {
|
||||
+ log_debug("Uncertain hint for unread device %d:%d %s",
|
||||
+ major(hint->devt), minor(hint->devt), dev_name(dev));
|
||||
+ ret = 0;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
if (strcmp(dev->pvid, hint->pvid)) {
|
||||
log_debug("Invalid hint device %d:%d %s pvid %s had hint pvid %s",
|
||||
major(hint->devt), minor(hint->devt), dev_name(dev),
|
||||
diff --git a/lib/label/label.c b/lib/label/label.c
|
||||
index 9fac3e464..354ab35e2 100644
|
||||
--- a/lib/label/label.c
|
||||
+++ b/lib/label/label.c
|
||||
@@ -686,6 +686,8 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, devs) {
|
||||
|
||||
+ devl->dev->flags &= ~DEV_SCAN_NOT_READ;
|
||||
+
|
||||
/*
|
||||
* If we prefetch more devs than blocks in the cache, then the
|
||||
* cache will wait for earlier reads to complete, toss the
|
||||
@@ -701,6 +703,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
log_debug_devs("Scan failed to open %s.", dev_name(devl->dev));
|
||||
dm_list_del(&devl->list);
|
||||
dm_list_add(&reopen_devs, &devl->list);
|
||||
+ devl->dev->flags |= DEV_SCAN_NOT_READ;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -724,6 +727,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
log_debug_devs("Scan failed to read %s.", dev_name(devl->dev));
|
||||
scan_read_errors++;
|
||||
scan_failed_count++;
|
||||
+ devl->dev->flags |= DEV_SCAN_NOT_READ;
|
||||
lvmcache_del_dev(devl->dev);
|
||||
if (bb)
|
||||
bcache_put(bb);
|
||||
@@ -1113,6 +1117,10 @@ int label_scan(struct cmd_context *cmd)
|
||||
* filter", and this result needs to be cleared (wiped) so that the
|
||||
* complete set of filters (including those that require data) can be
|
||||
* checked in _process_block, where headers have been read.
|
||||
+ *
|
||||
+ * FIXME: devs that are filtered with data in _process_block
|
||||
+ * are not moved to the filtered_devs list like devs filtered
|
||||
+ * here without data. Does that have any effect?
|
||||
*/
|
||||
log_debug_devs("Filtering devices to scan (nodata)");
|
||||
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
From 659e03ed04eff50f12d56baff949d1e7e7b3168b Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Sun, 29 Jun 2025 16:45:49 +0200
|
||||
Subject: [PATCH 33/47] gcc: for C90 don't mix declaration and code
|
||||
|
||||
This commit fixes C90 compatibility issues by ensuring variable declarations
|
||||
are placed at the beginning of code blocks before any executable statements.
|
||||
|
||||
(cherry picked from commit 0be635934c9cb4ac56e53d95adc7d7800d15e11f)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockctl.c | 9 ++++++---
|
||||
tools/reporter.c | 3 ++-
|
||||
2 files changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockctl.c b/daemons/lvmlockd/lvmlockctl.c
|
||||
index 4623e349d..e36293260 100644
|
||||
--- a/daemons/lvmlockd/lvmlockctl.c
|
||||
+++ b/daemons/lvmlockd/lvmlockctl.c
|
||||
@@ -87,12 +87,15 @@ do { \
|
||||
static int szscanf(const char *input, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
- va_start(args, format);
|
||||
- const char *fm = format;
|
||||
- const char *in = input;
|
||||
+ const char *fm;
|
||||
+ const char *in;
|
||||
int matched = 0;
|
||||
int n;
|
||||
|
||||
+ va_start(args, format);
|
||||
+ fm = format;
|
||||
+ in = input;
|
||||
+
|
||||
while (*fm != '\0') {
|
||||
|
||||
/*
|
||||
diff --git a/tools/reporter.c b/tools/reporter.c
|
||||
index 5cc6a2487..e88b8fa72 100644
|
||||
--- a/tools/reporter.c
|
||||
+++ b/tools/reporter.c
|
||||
@@ -1498,6 +1498,7 @@ int report_format_init(struct cmd_context *cmd)
|
||||
struct single_report_args *single_args;
|
||||
struct dm_report_group *new_report_group;
|
||||
struct dm_report *tmp_log_rh = NULL;
|
||||
+ const char * radixchar;
|
||||
|
||||
args.log_only = arg_is_set(cmd, logonly_ARG);
|
||||
report_command_log = args.log_only || find_config_tree_bool(cmd, log_report_command_log_CFG, NULL);
|
||||
@@ -1522,7 +1523,7 @@ int report_format_init(struct cmd_context *cmd)
|
||||
cmd->report_strict_type_mode = 1;
|
||||
|
||||
/* For json_std, the radix character must be '.'. */
|
||||
- const char * radixchar = nl_langinfo(RADIXCHAR);
|
||||
+ radixchar = nl_langinfo(RADIXCHAR);
|
||||
if (radixchar && strcmp(radixchar, ".")) {
|
||||
log_debug("Radix character for current locale is '%s', json_std requires '.', "
|
||||
"overriding LC_NUMERIC locale to 'C'", radixchar);
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
From cdefd8635de24200b55822fa0b6bc23a638fb87a Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Mon, 21 Feb 2022 11:35:58 -0600
|
||||
Subject: [PATCH 33/54] man lvmcache: mention writecache memory usage
|
||||
|
||||
---
|
||||
man/lvmcache.7_main | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/man/lvmcache.7_main b/man/lvmcache.7_main
|
||||
index 48cf7b492..73680235b 100644
|
||||
--- a/man/lvmcache.7_main
|
||||
+++ b/man/lvmcache.7_main
|
||||
@@ -240,6 +240,18 @@ The writecache block size should be chosen to match the xfs sectsz value.
|
||||
It is also possible to specify a sector size of 4096 to mkfs.xfs when
|
||||
creating the file system. In this case the writecache block size of 4096
|
||||
can be used.
|
||||
+.P
|
||||
+.SS dm-writecache memory usage
|
||||
+.P
|
||||
+The amount of main system memory used by dm-writecache can be a factor
|
||||
+when selecting the writecache cachevol size and the writecache block size.
|
||||
+.P
|
||||
+.IP \[bu] 2
|
||||
+writecache block size 4096: each 100 GiB of writecache cachevol uses
|
||||
+slighly over 2 GiB of system memory.
|
||||
+.IP \[bu] 2
|
||||
+writecache block size 512: each 100 GiB of writecache cachevol uses
|
||||
+a little over 16 GiB of system memory.
|
||||
.
|
||||
.SS dm-writecache settings
|
||||
.
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
From 6596b120d33f33286f37ba8b2f486fa01978b82e Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Thu, 10 Jul 2025 15:11:30 +0200
|
||||
Subject: [PATCH 34/47] sanlock: fix struct copy to avoid aliasing issues
|
||||
|
||||
Replace direct structure assignment with explicit copying to prevent
|
||||
potential undefined behavior from structure aliasing. This ensures
|
||||
proper memory handling when working with sanlock structures.
|
||||
|
||||
This possibly fixes regression introduced with commit: e9640e5178769
|
||||
as unintended side effect.
|
||||
|
||||
(cherry picked from commit b86b1da80acfa97ee6cc18e3d3a44809d4083a1b)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockd-sanlock.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
index 6ef59b591..93cb3ab17 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
@@ -2420,8 +2420,8 @@ static int release_rename(struct lockspace *ls, struct resource *r)
|
||||
if (!res_args)
|
||||
return -ENOMEM;
|
||||
|
||||
- memcpy(&rd1, &rds->rs, sizeof(struct rd_sanlock));
|
||||
- memcpy(&rd2, &rds->rs, sizeof(struct rd_sanlock));
|
||||
+ rd1.rs = rds->rs;
|
||||
+ rd2.rs = rds->rs;
|
||||
|
||||
res1 = &rd1.rs;
|
||||
res2 = &rd2.rs;
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,102 +0,0 @@
|
||||
From c047ff61f68d1b853569b153251f8bc5f88e23cd Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Mon, 21 Feb 2022 16:09:57 -0600
|
||||
Subject: [PATCH 34/54] writecache: display block size from lvs
|
||||
|
||||
lvs was missing the ability to display writecache block size.
|
||||
now possible with lvs -o writecache_block_size
|
||||
---
|
||||
lib/report/columns.h | 1 +
|
||||
lib/report/properties.c | 2 ++
|
||||
lib/report/report.c | 20 ++++++++++++++++++++
|
||||
man/lvmcache.7_main | 4 ++++
|
||||
test/shell/writecache-cache-blocksize.sh | 2 ++
|
||||
5 files changed, 29 insertions(+)
|
||||
|
||||
diff --git a/lib/report/columns.h b/lib/report/columns.h
|
||||
index 12b78b766..7e450dace 100644
|
||||
--- a/lib/report/columns.h
|
||||
+++ b/lib/report/columns.h
|
||||
@@ -108,6 +108,7 @@ FIELD(LVS, lv, TIM, "RTime", lvid, 26, lvtimeremoved, lv_time_removed, "Removal
|
||||
FIELD(LVS, lv, STR, "Host", lvid, 10, lvhost, lv_host, "Creation host of the LV, if known.", 0)
|
||||
FIELD(LVS, lv, STR_LIST, "Modules", lvid, 0, modules, lv_modules, "Kernel device-mapper modules required for this LV.", 0)
|
||||
FIELD(LVS, lv, BIN, "Historical", lvid, 0, lvhistorical, lv_historical, "Set if the LV is historical.", 0)
|
||||
+FIELD(LVS, lv, NUM, "WCacheBlkSize", lvid, 0, writecache_block_size, writecache_block_size, "The writecache block size", 0)
|
||||
/*
|
||||
* End of LVS type fields
|
||||
*/
|
||||
diff --git a/lib/report/properties.c b/lib/report/properties.c
|
||||
index 12ea890f4..6f302360f 100644
|
||||
--- a/lib/report/properties.c
|
||||
+++ b/lib/report/properties.c
|
||||
@@ -353,6 +353,8 @@ GET_PV_STR_PROPERTY_FN(pv_device_id_type, pv->device_id_type)
|
||||
#define _writecache_writeback_blocks_get prop_not_implemented_get
|
||||
#define _writecache_error_set prop_not_implemented_set
|
||||
#define _writecache_error_get prop_not_implemented_get
|
||||
+#define _writecache_block_size_set prop_not_implemented_set
|
||||
+#define _writecache_block_size_get prop_not_implemented_get
|
||||
|
||||
#define _vdo_operating_mode_set prop_not_implemented_set
|
||||
#define _vdo_operating_mode_get prop_not_implemented_get
|
||||
diff --git a/lib/report/report.c b/lib/report/report.c
|
||||
index 60df417a4..c06b22674 100644
|
||||
--- a/lib/report/report.c
|
||||
+++ b/lib/report/report.c
|
||||
@@ -3346,6 +3346,26 @@ static int _integritymismatches_disp(struct dm_report *rh __attribute__((unused)
|
||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||
}
|
||||
|
||||
+static int _writecache_block_size_disp(struct dm_report *rh __attribute__((unused)),
|
||||
+ struct dm_pool *mem,
|
||||
+ struct dm_report_field *field,
|
||||
+ const void *data,
|
||||
+ void *private __attribute__((unused)))
|
||||
+{
|
||||
+ struct logical_volume *lv = (struct logical_volume *) data;
|
||||
+ uint32_t bs = 0;
|
||||
+
|
||||
+ if (lv_is_writecache(lv)) {
|
||||
+ struct lv_segment *seg = first_seg(lv);
|
||||
+ bs = seg->writecache_block_size;
|
||||
+ }
|
||||
+
|
||||
+ if (!bs)
|
||||
+ return dm_report_field_int32(rh, field, &GET_TYPE_RESERVED_VALUE(num_undef_32));
|
||||
+
|
||||
+ return dm_report_field_uint32(rh, field, &bs);
|
||||
+}
|
||||
+
|
||||
static int _datapercent_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
diff --git a/man/lvmcache.7_main b/man/lvmcache.7_main
|
||||
index 73680235b..519e352cb 100644
|
||||
--- a/man/lvmcache.7_main
|
||||
+++ b/man/lvmcache.7_main
|
||||
@@ -241,6 +241,10 @@ It is also possible to specify a sector size of 4096 to mkfs.xfs when
|
||||
creating the file system. In this case the writecache block size of 4096
|
||||
can be used.
|
||||
.P
|
||||
+The writecache block size is displayed by the command:
|
||||
+.br
|
||||
+lvs -o writecacheblocksize VG/LV
|
||||
+.P
|
||||
.SS dm-writecache memory usage
|
||||
.P
|
||||
The amount of main system memory used by dm-writecache can be a factor
|
||||
diff --git a/test/shell/writecache-cache-blocksize.sh b/test/shell/writecache-cache-blocksize.sh
|
||||
index 2579ef7b7..4e17effe5 100644
|
||||
--- a/test/shell/writecache-cache-blocksize.sh
|
||||
+++ b/test/shell/writecache-cache-blocksize.sh
|
||||
@@ -222,6 +222,8 @@ vgextend $vg "$dev2"
|
||||
lvcreate -n $lv1 -l 8 -an $vg "$dev1"
|
||||
lvcreate -n $lv2 -l 4 -an $vg "$dev2"
|
||||
lvconvert --yes --type writecache --cachevol $lv2 --cachesettings "block_size=4096" $vg/$lv1
|
||||
+lvs -o writecacheblocksize $vg/$lv1 |tee out
|
||||
+grep 4096 out
|
||||
lvchange -ay $vg/$lv1
|
||||
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" |tee out
|
||||
grep "sectsz=4096" out
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -1,148 +0,0 @@
|
||||
From 8552290efae4905fd1a942be8e752842b11f1881 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Thu, 24 Feb 2022 15:57:29 -0600
|
||||
Subject: [PATCH 35/54] devices: simplify dev_cache_get_by_devt
|
||||
|
||||
remove unused args, and no callers need or want a
|
||||
repeated dev_cache_scan if there is no dev from the
|
||||
lookup.
|
||||
---
|
||||
lib/device/dev-cache.c | 60 ++++--------------------------------------
|
||||
lib/device/dev-cache.h | 2 +-
|
||||
lib/label/label.c | 2 +-
|
||||
tools/pvscan.c | 6 ++---
|
||||
4 files changed, 10 insertions(+), 60 deletions(-)
|
||||
|
||||
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
|
||||
index c6e5f68cf..cc1af7c7a 100644
|
||||
--- a/lib/device/dev-cache.c
|
||||
+++ b/lib/device/dev-cache.c
|
||||
@@ -1577,63 +1577,13 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
return dev;
|
||||
}
|
||||
|
||||
-struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct dev_filter *f, int *filtered)
|
||||
+struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt)
|
||||
{
|
||||
- char path[PATH_MAX];
|
||||
- const char *sysfs_dir;
|
||||
- struct stat info;
|
||||
- struct device *d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev);
|
||||
- int ret;
|
||||
-
|
||||
- if (filtered)
|
||||
- *filtered = 0;
|
||||
-
|
||||
- if (!d) {
|
||||
- sysfs_dir = dm_sysfs_dir();
|
||||
- if (sysfs_dir && *sysfs_dir) {
|
||||
- /* First check if dev is sysfs to avoid useless scan */
|
||||
- if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d",
|
||||
- sysfs_dir, (int)MAJOR(dev), (int)MINOR(dev)) < 0) {
|
||||
- log_error("dm_snprintf partition failed.");
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- if (lstat(path, &info)) {
|
||||
- log_debug("No sysfs entry for %d:%d errno %d at %s.",
|
||||
- (int)MAJOR(dev), (int)MINOR(dev), errno, path);
|
||||
- return NULL;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- log_debug_devs("Device num not found in dev_cache repeat dev_cache_scan for %d:%d",
|
||||
- (int)MAJOR(dev), (int)MINOR(dev));
|
||||
- dev_cache_scan(cmd);
|
||||
- d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev);
|
||||
-
|
||||
- if (!d)
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- if (d->flags & DEV_REGULAR)
|
||||
- return d;
|
||||
-
|
||||
- if (!f)
|
||||
- return d;
|
||||
-
|
||||
- ret = f->passes_filter(cmd, f, d, NULL);
|
||||
-
|
||||
- if (ret == -EAGAIN) {
|
||||
- log_debug_devs("get device by number defer filter %s", dev_name(d));
|
||||
- d->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
- ret = 1;
|
||||
- }
|
||||
-
|
||||
- if (ret)
|
||||
- return d;
|
||||
-
|
||||
- if (filtered)
|
||||
- *filtered = 1;
|
||||
+ struct device *dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devt);
|
||||
|
||||
+ if (dev)
|
||||
+ return dev;
|
||||
+ log_debug_devs("No devno %d:%d in dev cache.", (int)MAJOR(devt), (int)MINOR(devt));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
|
||||
index 635dc4fc9..7305eeb0e 100644
|
||||
--- a/lib/device/dev-cache.h
|
||||
+++ b/lib/device/dev-cache.h
|
||||
@@ -54,7 +54,7 @@ int dev_cache_has_scanned(void);
|
||||
int dev_cache_add_dir(const char *path);
|
||||
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f);
|
||||
|
||||
-struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t device, struct dev_filter *f, int *filtered);
|
||||
+struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt);
|
||||
|
||||
struct device *dev_hash_get(const char *name);
|
||||
|
||||
diff --git a/lib/label/label.c b/lib/label/label.c
|
||||
index 354ab35e2..ffe925254 100644
|
||||
--- a/lib/label/label.c
|
||||
+++ b/lib/label/label.c
|
||||
@@ -1443,7 +1443,7 @@ void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv
|
||||
if (lv_info(cmd, lv, 0, &lvinfo, 0, 0) && lvinfo.exists) {
|
||||
/* FIXME: Still unclear what is it supposed to find */
|
||||
devt = MKDEV(lvinfo.major, lvinfo.minor);
|
||||
- if ((dev = dev_cache_get_by_devt(cmd, devt, NULL, NULL)))
|
||||
+ if ((dev = dev_cache_get_by_devt(cmd, devt)))
|
||||
label_scan_invalidate(dev);
|
||||
}
|
||||
}
|
||||
diff --git a/tools/pvscan.c b/tools/pvscan.c
|
||||
index f60c4a2ca..160a2c9a0 100644
|
||||
--- a/tools/pvscan.c
|
||||
+++ b/tools/pvscan.c
|
||||
@@ -857,7 +857,7 @@ static int _get_devs_from_saved_vg(struct cmd_context *cmd, const char *vgname,
|
||||
|
||||
devno = MKDEV(file_major, file_minor);
|
||||
|
||||
- if (!(dev = dev_cache_get_by_devt(cmd, devno, NULL, NULL))) {
|
||||
+ if (!(dev = dev_cache_get_by_devt(cmd, devno))) {
|
||||
log_error_pvscan(cmd, "No device found for %d:%d PVID %s", file_major, file_minor, pvid);
|
||||
goto bad;
|
||||
}
|
||||
@@ -1195,7 +1195,7 @@ static int _get_args_devs(struct cmd_context *cmd, struct dm_list *pvscan_args,
|
||||
if (arg->devname)
|
||||
arg->dev = dev_cache_get(cmd, arg->devname, NULL);
|
||||
else if (arg->devno)
|
||||
- arg->dev = dev_cache_get_by_devt(cmd, arg->devno, NULL, NULL);
|
||||
+ arg->dev = dev_cache_get_by_devt(cmd, arg->devno);
|
||||
else
|
||||
return_0;
|
||||
}
|
||||
@@ -1257,7 +1257,7 @@ static void _set_pv_devices_online(struct cmd_context *cmd, struct volume_group
|
||||
|
||||
devno = MKDEV(major, minor);
|
||||
|
||||
- if (!(dev = dev_cache_get_by_devt(cmd, devno, NULL, NULL))) {
|
||||
+ if (!(dev = dev_cache_get_by_devt(cmd, devno))) {
|
||||
log_print_pvscan(cmd, "VG %s PV %s no device found for %d:%d",
|
||||
vg->name, pvid, major, minor);
|
||||
pvl->pv->status |= MISSING_PV;
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
From e10a604ae404ff6a87eced54743d5a539a06a030 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Thu, 10 Jul 2025 15:13:18 +0200
|
||||
Subject: [PATCH 35/47] sanlock: fix file descriptor leak in error path
|
||||
|
||||
Add proper cleanup of file descriptor in the error handling path
|
||||
to prevent resource leaks when sanlock operations fail.
|
||||
|
||||
(cherry picked from commit f82c46e6735ce123da27fb576371e660697b0bb7)
|
||||
---
|
||||
daemons/lvmlockd/lvmlockd-sanlock.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
index 93cb3ab17..17820b91d 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
@@ -320,8 +320,11 @@ static int read_host_id_file(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
- _fclose(file, (char *)daemon_host_id_file);
|
||||
+
|
||||
out:
|
||||
+ if (file)
|
||||
+ _fclose(file, (char *)daemon_host_id_file);
|
||||
+
|
||||
log_debug("host_id %d from %s", host_id, daemon_host_id_file);
|
||||
return host_id;
|
||||
}
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
From bf48c1541291aeda537520b664f59249fc85f95b Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Fri, 11 Jul 2025 14:29:41 +0200
|
||||
Subject: [PATCH 36/47] command-lines: fix typo in configurable name
|
||||
|
||||
Fix type in lvm.conf option name used for lvcreate
|
||||
and replace global/mirror_segfault_default with correct
|
||||
name global/mirror_segtype_default.
|
||||
|
||||
(cherry picked from commit 0b7b6ccd79929611131549a70bcb339f0c67530e)
|
||||
---
|
||||
tools/command-lines.in | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/command-lines.in b/tools/command-lines.in
|
||||
index d85df7bbd..3d38b1ce7 100644
|
||||
--- a/tools/command-lines.in
|
||||
+++ b/tools/command-lines.in
|
||||
@@ -973,7 +973,7 @@ OP: PV ...
|
||||
IO: --stripes 1
|
||||
ID: lvcreate_mirror_or_raid1
|
||||
DESC: Create a raid1 or mirror LV.
|
||||
-DESC: Implicit type is defined by lvm.conf global/mirror_segfault_default.
|
||||
+DESC: Implicit type is defined by lvm.conf global/mirror_segtype_default.
|
||||
AUTOTYPE: raid1
|
||||
AUTOTYPE: mirror
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,467 +0,0 @@
|
||||
From 8ba6259b24cd4b99e061f2610c5cd0bcde890039 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Thu, 24 Feb 2022 16:03:21 -0600
|
||||
Subject: [PATCH 36/54] devices: drop incorrect paths from aliases list
|
||||
|
||||
along with some basic checks for cases when a device
|
||||
has no aliases.
|
||||
|
||||
lvm itself creates many situations where a struct device
|
||||
has no valid paths, when it activates and opens an LV,
|
||||
does something with it, e.g. zeroing, and then closes
|
||||
and deactivates it. (dev-cache is intended for PVs, and
|
||||
the use of LVs should be moved out of dev-cache in a
|
||||
future patch.)
|
||||
---
|
||||
lib/device/dev-cache.c | 223 ++++++++++++++++++++++++++---------------
|
||||
lib/device/dev-cache.h | 2 +-
|
||||
lib/device/dev-io.c | 34 ++++---
|
||||
lib/device/device.h | 3 -
|
||||
4 files changed, 164 insertions(+), 98 deletions(-)
|
||||
|
||||
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
|
||||
index cc1af7c7a..58e67e130 100644
|
||||
--- a/lib/device/dev-cache.c
|
||||
+++ b/lib/device/dev-cache.c
|
||||
@@ -351,7 +351,7 @@ static int _add_alias(struct device *dev, const char *path, enum add_hash hash)
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (!(path = dm_pool_strdup(_cache.mem, path)) ||
|
||||
+ if (!(path = _strdup(path)) ||
|
||||
!(sl = _zalloc(sizeof(*sl)))) {
|
||||
log_error("Failed to add allias to dev cache.");
|
||||
return 0;
|
||||
@@ -1162,6 +1162,17 @@ static int _insert(const char *path, const struct stat *info,
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static void _drop_all_aliases(struct device *dev)
|
||||
+{
|
||||
+ struct dm_str_list *strl, *strl2;
|
||||
+
|
||||
+ dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
|
||||
+ log_debug("Drop alias for %d:%d %s.", (int)MAJOR(dev->dev), (int)MINOR(dev->dev), strl->str);
|
||||
+ dm_hash_remove(_cache.names, strl->str);
|
||||
+ dm_list_del(&strl->list);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void dev_cache_scan(struct cmd_context *cmd)
|
||||
{
|
||||
log_debug_devs("Creating list of system devices.");
|
||||
@@ -1371,59 +1382,6 @@ int dev_cache_add_dir(const char *path)
|
||||
return 1;
|
||||
}
|
||||
|
||||
-/* Check cached device name is still valid before returning it */
|
||||
-/* This should be a rare occurrence */
|
||||
-/* set quiet if the cache is expected to be out-of-date */
|
||||
-/* FIXME Make rest of code pass/cache struct device instead of dev_name */
|
||||
-const char *dev_name_confirmed(struct device *dev, int quiet)
|
||||
-{
|
||||
- struct stat buf;
|
||||
- const char *name;
|
||||
- int r;
|
||||
-
|
||||
- if ((dev->flags & DEV_REGULAR))
|
||||
- return dev_name(dev);
|
||||
-
|
||||
- while ((r = stat(name = dm_list_item(dev->aliases.n,
|
||||
- struct dm_str_list)->str, &buf)) ||
|
||||
- (buf.st_rdev != dev->dev)) {
|
||||
- if (r < 0) {
|
||||
- if (quiet)
|
||||
- log_sys_debug("stat", name);
|
||||
- else
|
||||
- log_sys_error("stat", name);
|
||||
- }
|
||||
- if (quiet)
|
||||
- log_debug_devs("Path %s no longer valid for device(%d,%d)",
|
||||
- name, (int) MAJOR(dev->dev),
|
||||
- (int) MINOR(dev->dev));
|
||||
- else
|
||||
- log_warn("Path %s no longer valid for device(%d,%d)",
|
||||
- name, (int) MAJOR(dev->dev),
|
||||
- (int) MINOR(dev->dev));
|
||||
-
|
||||
- /* Remove the incorrect hash entry */
|
||||
- dm_hash_remove(_cache.names, name);
|
||||
-
|
||||
- /* Leave list alone if there isn't an alternative name */
|
||||
- /* so dev_name will always find something to return. */
|
||||
- /* Otherwise add the name to the correct device. */
|
||||
- if (dm_list_size(&dev->aliases) > 1) {
|
||||
- dm_list_del(dev->aliases.n);
|
||||
- if (!r)
|
||||
- _insert(name, &buf, 0, obtain_device_list_from_udev());
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- /* Scanning issues this inappropriately sometimes. */
|
||||
- log_debug_devs("Aborting - please provide new pathname for what "
|
||||
- "used to be %s", name);
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- return dev_name(dev);
|
||||
-}
|
||||
-
|
||||
struct device *dev_hash_get(const char *name)
|
||||
{
|
||||
return (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
@@ -1452,26 +1410,23 @@ static void _remove_alias(struct device *dev, const char *name)
|
||||
* deactivated LV. Those old paths are all invalid and are dropped here.
|
||||
*/
|
||||
|
||||
-static void _verify_aliases(struct device *dev, const char *newname)
|
||||
+static void _verify_aliases(struct device *dev)
|
||||
{
|
||||
struct dm_str_list *strl, *strl2;
|
||||
struct stat st;
|
||||
|
||||
dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
|
||||
- /* newname was just stat'd and added by caller */
|
||||
- if (newname && !strcmp(strl->str, newname))
|
||||
- continue;
|
||||
-
|
||||
if (stat(strl->str, &st) || (st.st_rdev != dev->dev)) {
|
||||
- log_debug("Drop invalid path %s for %d:%d (new path %s).",
|
||||
- strl->str, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), newname ?: "");
|
||||
+ log_debug("Drop alias for %d:%d invalid path %s %d:%d.",
|
||||
+ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), strl->str,
|
||||
+ (int)MAJOR(st.st_rdev), (int)MINOR(st.st_rdev));
|
||||
dm_hash_remove(_cache.names, strl->str);
|
||||
dm_list_del(&strl->list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f)
|
||||
+static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f, int existing)
|
||||
{
|
||||
struct device *dev = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
struct stat st;
|
||||
@@ -1485,13 +1440,18 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
if (dev && (dev->flags & DEV_REGULAR))
|
||||
return dev;
|
||||
|
||||
+ if (dev && dm_list_empty(&dev->aliases)) {
|
||||
+ /* shouldn't happen */
|
||||
+ log_warn("Ignoring dev with no valid paths for %s.", name);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
- * The requested path is invalid, remove any dev-cache
|
||||
- * info for it.
|
||||
+ * The requested path is invalid, remove any dev-cache info for it.
|
||||
*/
|
||||
if (stat(name, &st)) {
|
||||
if (dev) {
|
||||
- log_print("Device path %s is invalid for %d:%d %s.",
|
||||
+ log_debug("Device path %s is invalid for %d:%d %s.",
|
||||
name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
|
||||
|
||||
dm_hash_remove(_cache.names, name);
|
||||
@@ -1499,11 +1459,17 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
_remove_alias(dev, name);
|
||||
|
||||
/* Remove any other names in dev->aliases that are incorrect. */
|
||||
- _verify_aliases(dev, NULL);
|
||||
+ _verify_aliases(dev);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ if (dev && dm_list_empty(&dev->aliases)) {
|
||||
+ /* shouldn't happen */
|
||||
+ log_warn("Ignoring dev with no valid paths for %s.", name);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
if (!S_ISBLK(st.st_mode)) {
|
||||
log_debug("Not a block device %s.", name);
|
||||
return NULL;
|
||||
@@ -1514,26 +1480,110 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
* Remove incorrect info and then add new dev-cache entry.
|
||||
*/
|
||||
if (dev && (st.st_rdev != dev->dev)) {
|
||||
- log_debug("Device path %s does not match %d:%d %s.",
|
||||
- name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
|
||||
+ struct device *dev_by_devt = (struct device *) btree_lookup(_cache.devices, (uint32_t) st.st_rdev);
|
||||
+
|
||||
+ /*
|
||||
+ * lvm commands create this condition when they
|
||||
+ * activate/deactivate LVs combined with creating new LVs.
|
||||
+ * The command does not purge dev structs when deactivating
|
||||
+ * an LV (which it probably should do), but the better
|
||||
+ * approach would be not using dev-cache at all for LVs.
|
||||
+ */
|
||||
|
||||
- dm_hash_remove(_cache.names, name);
|
||||
+ log_debug("Dropping aliases for device entry %d:%d %s for new device %d:%d %s.",
|
||||
+ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev),
|
||||
+ (int)MAJOR(st.st_rdev), (int)MINOR(st.st_rdev), name);
|
||||
|
||||
- _remove_alias(dev, name);
|
||||
+ _drop_all_aliases(dev);
|
||||
|
||||
- /* Remove any other names in dev->aliases that are incorrect. */
|
||||
- _verify_aliases(dev, NULL);
|
||||
+ if (dev_by_devt) {
|
||||
+ log_debug("Dropping aliases for device entry %d:%d %s for new device %d:%d %s.",
|
||||
+ (int)MAJOR(dev_by_devt->dev), (int)MINOR(dev_by_devt->dev), dev_name(dev_by_devt),
|
||||
+ (int)MAJOR(st.st_rdev), (int)MINOR(st.st_rdev), name);
|
||||
|
||||
- /* Add new dev-cache entry next. */
|
||||
- dev = NULL;
|
||||
+ _drop_all_aliases(dev_by_devt);
|
||||
+ }
|
||||
+
|
||||
+#if 0
|
||||
+ /*
|
||||
+ * I think only lvm's own dm devs should be added here, so use
|
||||
+ * a warning to look for any other unknown cases.
|
||||
+ */
|
||||
+ if (MAJOR(st.st_rdev) != cmd->dev_types->device_mapper_major) {
|
||||
+ log_warn("WARNING: new device appeared %d:%d %s",
|
||||
+ (int)MAJOR(st.st_rdev), (int)(MINOR(st.st_rdev)), name);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ if (!_insert_dev(name, st.st_rdev))
|
||||
+ return_NULL;
|
||||
+
|
||||
+ /* Get the struct dev that was just added. */
|
||||
+ dev = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
+
|
||||
+ if (!dev) {
|
||||
+ log_error("Failed to get device %s", name);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
+ if (dev && dm_list_empty(&dev->aliases)) {
|
||||
+ /* shouldn't happen */
|
||||
+ log_warn("Ignoring dev with no valid paths for %s.", name);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (!dev && existing)
|
||||
+ return_NULL;
|
||||
+
|
||||
/*
|
||||
- * Either add a new struct dev for st_rdev and name,
|
||||
- * or add name as a new alias for an existing struct dev
|
||||
- * for st_rdev.
|
||||
+ * This case should never be hit for a PV. It should only
|
||||
+ * happen when the command is opening a new LV it has created.
|
||||
+ * Add an arg to all callers indicating when the arg should be
|
||||
+ * new (for an LV) and not existing.
|
||||
+ * FIXME: fix this further by not using dev-cache struct devs
|
||||
+ * at all for new dm devs (LVs) that lvm uses. Make the
|
||||
+ * dev-cache contain only devs for PVs.
|
||||
+ * Places to fix that use a dev for LVs include:
|
||||
+ * . lv_resize opening lv to discard
|
||||
+ * . wipe_lv opening lv to zero it
|
||||
+ * . _extend_sanlock_lv opening lv to extend it
|
||||
+ * . _write_log_header opening lv to write header
|
||||
+ * Also, io to LVs should not go through bcache.
|
||||
+ * bcache should contain only labels and metadata
|
||||
+ * scanned from PVs.
|
||||
*/
|
||||
if (!dev) {
|
||||
+ /*
|
||||
+ * This case should only be used for new devices created by this
|
||||
+ * command (opening LVs it's created), so if a dev exists for the
|
||||
+ * dev_t referenced by the name, then drop all aliases for before
|
||||
+ * _insert_dev adds the new name. lvm commands actually hit this
|
||||
+ * fairly often when it uses some LV, deactivates the LV, then
|
||||
+ * creates some new LV which ends up with the same major:minor.
|
||||
+ * Without dropping the aliases, it's plausible that lvm commands
|
||||
+ * could end up using the wrong dm device.
|
||||
+ */
|
||||
+ struct device *dev_by_devt = (struct device *) btree_lookup(_cache.devices, (uint32_t) st.st_rdev);
|
||||
+ if (dev_by_devt) {
|
||||
+ log_debug("Dropping aliases for %d:%d before adding new path %s.",
|
||||
+ (int)MAJOR(st.st_rdev), (int)(MINOR(st.st_rdev)), name);
|
||||
+ _drop_all_aliases(dev_by_devt);
|
||||
+ }
|
||||
+
|
||||
+#if 0
|
||||
+ /*
|
||||
+ * I think only lvm's own dm devs should be added here, so use
|
||||
+ * a warning to look for any other unknown cases.
|
||||
+ */
|
||||
+ if (MAJOR(st.st_rdev) != cmd->dev_types->device_mapper_major) {
|
||||
+ log_warn("WARNING: new device appeared %d:%d %s",
|
||||
+ (int)MAJOR(st.st_rdev), (int)(MINOR(st.st_rdev)), name);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
if (!_insert_dev(name, st.st_rdev))
|
||||
return_NULL;
|
||||
|
||||
@@ -1544,10 +1594,9 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
log_error("Failed to get device %s", name);
|
||||
return NULL;
|
||||
}
|
||||
-
|
||||
- _verify_aliases(dev, name);
|
||||
}
|
||||
|
||||
+ out:
|
||||
/*
|
||||
* The caller passed a filter if they only want the dev if it
|
||||
* passes filters.
|
||||
@@ -1577,6 +1626,16 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
return dev;
|
||||
}
|
||||
|
||||
+struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f)
|
||||
+{
|
||||
+ return _dev_cache_get(cmd, name, f, 1);
|
||||
+}
|
||||
+
|
||||
+struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f)
|
||||
+{
|
||||
+ return _dev_cache_get(cmd, name, f, 0);
|
||||
+}
|
||||
+
|
||||
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt)
|
||||
{
|
||||
struct device *dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devt);
|
||||
@@ -1653,8 +1712,10 @@ int dev_fd(struct device *dev)
|
||||
|
||||
const char *dev_name(const struct device *dev)
|
||||
{
|
||||
- return (dev && dev->aliases.n) ? dm_list_item(dev->aliases.n, struct dm_str_list)->str :
|
||||
- unknown_device_name();
|
||||
+ if (dev && dev->aliases.n && !dm_list_empty(&dev->aliases))
|
||||
+ return dm_list_item(dev->aliases.n, struct dm_str_list)->str;
|
||||
+ else
|
||||
+ return unknown_device_name();
|
||||
}
|
||||
|
||||
bool dev_cache_has_md_with_end_superblock(struct dev_types *dt)
|
||||
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
|
||||
index 7305eeb0e..51c3fc6c3 100644
|
||||
--- a/lib/device/dev-cache.h
|
||||
+++ b/lib/device/dev-cache.h
|
||||
@@ -53,7 +53,7 @@ int dev_cache_has_scanned(void);
|
||||
|
||||
int dev_cache_add_dir(const char *path);
|
||||
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f);
|
||||
-
|
||||
+struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f);
|
||||
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt);
|
||||
|
||||
struct device *dev_hash_get(const char *name);
|
||||
diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c
|
||||
index b4f1930b1..811ad8978 100644
|
||||
--- a/lib/device/dev-io.c
|
||||
+++ b/lib/device/dev-io.c
|
||||
@@ -58,6 +58,9 @@ static int _dev_get_size_file(struct device *dev, uint64_t *size)
|
||||
const char *name = dev_name(dev);
|
||||
struct stat info;
|
||||
|
||||
+ if (dm_list_empty(&dev->aliases))
|
||||
+ return_0;
|
||||
+
|
||||
if (dev->size_seqno == _dev_size_seqno) {
|
||||
log_very_verbose("%s: using cached size %" PRIu64 " sectors",
|
||||
name, dev->size);
|
||||
@@ -87,7 +90,7 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
|
||||
int do_close = 0;
|
||||
|
||||
if (dm_list_empty(&dev->aliases))
|
||||
- return 0;
|
||||
+ return_0;
|
||||
|
||||
if (dev->size_seqno == _dev_size_seqno) {
|
||||
log_very_verbose("%s: using cached size %" PRIu64 " sectors",
|
||||
@@ -305,6 +308,13 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
if ((flags & O_EXCL))
|
||||
need_excl = 1;
|
||||
|
||||
+ if (dm_list_empty(&dev->aliases)) {
|
||||
+ /* shouldn't happen */
|
||||
+ log_print("Cannot open device %d:%d with no valid paths.", (int)MAJOR(dev->dev), (int)MINOR(dev->dev));
|
||||
+ return 0;
|
||||
+ }
|
||||
+ name = dev_name(dev);
|
||||
+
|
||||
if (dev->fd >= 0) {
|
||||
if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
|
||||
((dev->flags & DEV_OPENED_EXCL) || !need_excl)) {
|
||||
@@ -314,7 +324,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
|
||||
if (dev->open_count && !need_excl)
|
||||
log_debug_devs("%s: Already opened read-only. Upgrading "
|
||||
- "to read-write.", dev_name(dev));
|
||||
+ "to read-write.", name);
|
||||
|
||||
/* dev_close_immediate will decrement this */
|
||||
dev->open_count++;
|
||||
@@ -327,11 +337,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
|
||||
if (critical_section())
|
||||
/* FIXME Make this log_error */
|
||||
- log_verbose("dev_open(%s) called while suspended",
|
||||
- dev_name(dev));
|
||||
-
|
||||
- if (!(name = dev_name_confirmed(dev, quiet)))
|
||||
- return_0;
|
||||
+ log_verbose("dev_open(%s) called while suspended", name);
|
||||
|
||||
#ifdef O_DIRECT_SUPPORT
|
||||
if (direct) {
|
||||
@@ -372,9 +378,9 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
}
|
||||
#endif
|
||||
if (quiet)
|
||||
- log_sys_debug("open", name);
|
||||
+ log_debug("Failed to open device path %s (%d).", name, errno);
|
||||
else
|
||||
- log_sys_error("open", name);
|
||||
+ log_error("Failed to open device path %s (%d).", name, errno);
|
||||
|
||||
dev->flags |= DEV_OPEN_FAILURE;
|
||||
return 0;
|
||||
@@ -415,10 +421,12 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
if ((flags & O_CREAT) && !(flags & O_TRUNC))
|
||||
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
|
||||
|
||||
- log_debug_devs("Opened %s %s%s%s", dev_name(dev),
|
||||
- dev->flags & DEV_OPENED_RW ? "RW" : "RO",
|
||||
- dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
|
||||
- dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
|
||||
+ if (!quiet) {
|
||||
+ log_debug_devs("Opened %s %s%s%s", name,
|
||||
+ dev->flags & DEV_OPENED_RW ? "RW" : "RO",
|
||||
+ dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
|
||||
+ dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
|
||||
+ }
|
||||
|
||||
dev->flags &= ~DEV_OPEN_FAILURE;
|
||||
return 1;
|
||||
diff --git a/lib/device/device.h b/lib/device/device.h
|
||||
index 8c3a8c30e..572994bb9 100644
|
||||
--- a/lib/device/device.h
|
||||
+++ b/lib/device/device.h
|
||||
@@ -204,9 +204,6 @@ struct device *dev_create_file(const char *filename, struct device *dev,
|
||||
struct dm_str_list *alias, int use_malloc);
|
||||
void dev_destroy_file(struct device *dev);
|
||||
|
||||
-/* Return a valid device name from the alias list; NULL otherwise */
|
||||
-const char *dev_name_confirmed(struct device *dev, int quiet);
|
||||
-
|
||||
int dev_mpath_init(const char *config_wwids_file);
|
||||
void dev_mpath_exit(void);
|
||||
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
From 7dc7ab8e99005da29aba22df2bb67e58e19a50f0 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Thu, 24 Feb 2022 16:10:37 -0600
|
||||
Subject: [PATCH 37/54] devices: initial use of existing option
|
||||
|
||||
Use dev_cache_get_existing() in a few common, high level
|
||||
locations where it's obvious that only existing dev-cache
|
||||
entries are wanted. This can be expanded and used in more
|
||||
locations (or dev_cache_get can stop creating new entries.)
|
||||
---
|
||||
lib/device/device_id.c | 4 ++--
|
||||
tools/toollib.c | 6 +++---
|
||||
2 files changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index 7fe581571..bcb2e6bcf 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -1565,7 +1565,7 @@ void device_ids_match(struct cmd_context *cmd)
|
||||
dm_list_iterate_items(du, &cmd->use_devices) {
|
||||
if (du->dev)
|
||||
continue;
|
||||
- if (!(du->dev = dev_cache_get(cmd, du->devname, NULL))) {
|
||||
+ if (!(du->dev = dev_cache_get_existing(cmd, du->devname, NULL))) {
|
||||
log_warn("Device not found for %s.", du->devname);
|
||||
} else {
|
||||
/* Should we set dev->id? Which idtype? Use --deviceidtype? */
|
||||
@@ -1603,7 +1603,7 @@ void device_ids_match(struct cmd_context *cmd)
|
||||
* the du/dev pairs in preparation for using the filters.
|
||||
*/
|
||||
if (du->devname &&
|
||||
- (dev = dev_cache_get(cmd, du->devname, NULL))) {
|
||||
+ (dev = dev_cache_get_existing(cmd, du->devname, NULL))) {
|
||||
/* On successful match, du, dev, and id are linked. */
|
||||
if (_match_du_to_dev(cmd, du, dev))
|
||||
continue;
|
||||
diff --git a/tools/toollib.c b/tools/toollib.c
|
||||
index d6f48aad2..16be336d4 100644
|
||||
--- a/tools/toollib.c
|
||||
+++ b/tools/toollib.c
|
||||
@@ -1434,7 +1434,7 @@ int process_each_label(struct cmd_context *cmd, int argc, char **argv,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (!(dev = dev_cache_get(cmd, argv[opt], cmd->filter))) {
|
||||
+ if (!(dev = dev_cache_get_existing(cmd, argv[opt], cmd->filter))) {
|
||||
log_error("Failed to find device "
|
||||
"\"%s\".", argv[opt]);
|
||||
ret_max = ECMD_FAILED;
|
||||
@@ -3870,7 +3870,7 @@ static int _get_arg_devices(struct cmd_context *cmd,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
- if (!(dil->dev = dev_cache_get(cmd, sl->str, cmd->filter))) {
|
||||
+ if (!(dil->dev = dev_cache_get_existing(cmd, sl->str, cmd->filter))) {
|
||||
log_error("Cannot use %s: %s", sl->str, devname_error_reason(sl->str));
|
||||
ret_max = EINIT_FAILED;
|
||||
} else {
|
||||
@@ -5206,7 +5206,7 @@ int pvcreate_each_device(struct cmd_context *cmd,
|
||||
struct device *dev;
|
||||
|
||||
/* No filter used here */
|
||||
- if (!(dev = dev_cache_get(cmd, pd->name, NULL))) {
|
||||
+ if (!(dev = dev_cache_get_existing(cmd, pd->name, NULL))) {
|
||||
log_error("No device found for %s.", pd->name);
|
||||
dm_list_del(&pd->list);
|
||||
dm_list_add(&pp->arg_fail, &pd->list);
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
From 7f5a4a9de4aab40f2c243f0f657008da839cb75f Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Thu, 10 Jul 2025 21:40:14 +0200
|
||||
Subject: [PATCH 37/47] tools: simplify LVM_DID_EXEC environment variable
|
||||
|
||||
Set LVM_DID_EXEC to "1" instead of using the command name string,
|
||||
avoiding potential issues with unusual command names and improving
|
||||
consistency in environment variable handling.
|
||||
|
||||
(cherry picked from commit 5d16b1d7348aad816424b2a8e95fd31a59c3e2e2)
|
||||
---
|
||||
tools/lvmcmdline.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
|
||||
index ebb1b87c9..2ecdbd164 100644
|
||||
--- a/tools/lvmcmdline.c
|
||||
+++ b/tools/lvmcmdline.c
|
||||
@@ -3608,7 +3608,7 @@ int lvm2_main(int argc, char **argv)
|
||||
if (is_static() && strcmp(base, "lvm.static") &&
|
||||
path_exists(LVM_PATH) &&
|
||||
!getenv("LVM_DID_EXEC")) {
|
||||
- if (setenv("LVM_DID_EXEC", base, 1))
|
||||
+ if (setenv("LVM_DID_EXEC", "1", 1))
|
||||
log_sys_error("setenv", "LVM_DID_EXEC");
|
||||
if (execvp(LVM_PATH, argv) == -1)
|
||||
log_sys_error("execvp", LVM_PATH);
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,270 +0,0 @@
|
||||
From 591b5f006fca7e06bfbf0d5512da3ae5b0f6bbdd Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Tue, 22 Feb 2022 15:03:11 -0600
|
||||
Subject: [PATCH 38/54] devices: fix dev_name assumptions
|
||||
|
||||
dev_name(dev) returns "[unknown]" if there are no names
|
||||
on dev->aliases. It's meant mainly for log messages.
|
||||
|
||||
Many places assume a valid path name is returned, and
|
||||
use it directly. A caller that wants to use the path
|
||||
from dev_name() must first check if the dev has any
|
||||
paths with dm_list_empty(&dev->aliases).
|
||||
---
|
||||
lib/activate/dev_manager.c | 9 ++++++++-
|
||||
lib/device/dev-type.c | 3 +++
|
||||
lib/device/device_id.c | 13 +++++++++++--
|
||||
lib/label/hints.c | 2 ++
|
||||
lib/label/label.c | 16 +++++++++++++++-
|
||||
lib/locking/lvmlockd.c | 4 ++++
|
||||
lib/metadata/mirror.c | 17 +++++++++++++----
|
||||
lib/metadata/pv_list.c | 5 +++++
|
||||
lib/metadata/vg.c | 5 +++++
|
||||
test/shell/losetup-partscan.sh | 2 ++
|
||||
10 files changed, 68 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
|
||||
index a73a556b2..284254d68 100644
|
||||
--- a/lib/activate/dev_manager.c
|
||||
+++ b/lib/activate/dev_manager.c
|
||||
@@ -2875,6 +2875,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
|
||||
/* FIXME Avoid repeating identical stat in dm_tree_node_add_target_area */
|
||||
for (s = start_area; s < areas; s++) {
|
||||
+
|
||||
+ /* FIXME: dev_name() does not return NULL! It needs to check if dm_list_empty(&dev->aliases)
|
||||
+ but this knot of logic is too complex to pull apart without careful deconstruction. */
|
||||
+
|
||||
if ((seg_type(seg, s) == AREA_PV &&
|
||||
(!seg_pvseg(seg, s) || !seg_pv(seg, s) || !seg_dev(seg, s) ||
|
||||
!(name = dev_name(seg_dev(seg, s))) || !*name ||
|
||||
@@ -2893,7 +2897,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
return_0;
|
||||
num_error_areas++;
|
||||
} else if (seg_type(seg, s) == AREA_PV) {
|
||||
- if (!dm_tree_node_add_target_area(node, dev_name(seg_dev(seg, s)), NULL,
|
||||
+ struct device *dev = seg_dev(seg, s);
|
||||
+ name = dm_list_empty(&dev->aliases) ? NULL : dev_name(dev);
|
||||
+
|
||||
+ if (!dm_tree_node_add_target_area(node, name, NULL,
|
||||
(seg_pv(seg, s)->pe_start + (extent_size * seg_pe(seg, s)))))
|
||||
return_0;
|
||||
num_existing_areas++;
|
||||
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
|
||||
index 0e77a009d..c67a86fa3 100644
|
||||
--- a/lib/device/dev-type.c
|
||||
+++ b/lib/device/dev-type.c
|
||||
@@ -966,6 +966,9 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
|
||||
|
||||
/* TODO: Should we check for valid dev - _dev_is_valid(dev)? */
|
||||
|
||||
+ if (dm_list_empty(&dev->aliases))
|
||||
+ goto_out;
|
||||
+
|
||||
if (!(probe = blkid_new_probe_from_filename(dev_name(dev)))) {
|
||||
log_error("Failed to create a new blkid probe for device %s.", dev_name(dev));
|
||||
goto out;
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index bcb2e6bcf..82db6e4a5 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -347,6 +347,8 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
|
||||
}
|
||||
|
||||
else if (idtype == DEV_ID_TYPE_DEVNAME) {
|
||||
+ if (dm_list_empty(&dev->aliases))
|
||||
+ goto_bad;
|
||||
if (!(idname = strdup(dev_name(dev))))
|
||||
goto_bad;
|
||||
return idname;
|
||||
@@ -940,6 +942,10 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
|
||||
if (!dev_get_partition_number(dev, &part))
|
||||
return_0;
|
||||
|
||||
+ /* Ensure valid dev_name(dev) below. */
|
||||
+ if (dm_list_empty(&dev->aliases))
|
||||
+ return_0;
|
||||
+
|
||||
/*
|
||||
* When enable_devices_file=0 and pending_devices_file=1 we let
|
||||
* pvcreate/vgcreate add new du's to cmd->use_devices. These du's may
|
||||
@@ -1820,6 +1826,9 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
|
||||
if (dev->flags & DEV_SCAN_NOT_READ)
|
||||
continue;
|
||||
|
||||
+ if (dm_list_empty(&dev->aliases))
|
||||
+ continue;
|
||||
+
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) {
|
||||
log_warn("Devices file %s is excluded by filter: %s.",
|
||||
dev_name(dev), dev_filtered_reason(dev));
|
||||
@@ -2197,14 +2206,14 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l
|
||||
dm_list_iterate_items(dil, &search_pvids) {
|
||||
char *dup_devname1, *dup_devname2, *dup_devname3;
|
||||
|
||||
- if (!dil->dev) {
|
||||
+ if (!dil->dev || dm_list_empty(&dil->dev->aliases)) {
|
||||
not_found++;
|
||||
continue;
|
||||
}
|
||||
- found++;
|
||||
|
||||
dev = dil->dev;
|
||||
devname = dev_name(dev);
|
||||
+ found++;
|
||||
|
||||
if (!(du = get_du_for_pvid(cmd, dil->pvid))) {
|
||||
/* shouldn't happen */
|
||||
diff --git a/lib/label/hints.c b/lib/label/hints.c
|
||||
index 95d5d77b8..2a7b3dca7 100644
|
||||
--- a/lib/label/hints.c
|
||||
+++ b/lib/label/hints.c
|
||||
@@ -498,6 +498,8 @@ int validate_hints(struct cmd_context *cmd, struct dm_list *hints)
|
||||
if (!(iter = dev_iter_create(NULL, 0)))
|
||||
return 0;
|
||||
while ((dev = dev_iter_get(cmd, iter))) {
|
||||
+ if (dm_list_empty(&dev->aliases))
|
||||
+ continue;
|
||||
if (!(hint = _find_hint_name(hints, dev_name(dev))))
|
||||
continue;
|
||||
|
||||
diff --git a/lib/label/label.c b/lib/label/label.c
|
||||
index ffe925254..cf707f7a3 100644
|
||||
--- a/lib/label/label.c
|
||||
+++ b/lib/label/label.c
|
||||
@@ -1565,10 +1565,24 @@ int label_scan_open_rw(struct device *dev)
|
||||
|
||||
int label_scan_reopen_rw(struct device *dev)
|
||||
{
|
||||
+ const char *name;
|
||||
int flags = 0;
|
||||
int prev_fd = dev->bcache_fd;
|
||||
int fd;
|
||||
|
||||
+ if (dm_list_empty(&dev->aliases)) {
|
||||
+ log_error("Cannot reopen rw device %d:%d with no valid paths di %d fd %d.",
|
||||
+ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev->bcache_di, dev->bcache_fd);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ name = dev_name(dev);
|
||||
+ if (!name || name[0] != '/') {
|
||||
+ log_error("Cannot reopen rw device %d:%d with no valid name di %d fd %d.",
|
||||
+ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev->bcache_di, dev->bcache_fd);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
if (!(dev->flags & DEV_IN_BCACHE)) {
|
||||
if ((dev->bcache_fd != -1) || (dev->bcache_di != -1)) {
|
||||
/* shouldn't happen */
|
||||
@@ -1598,7 +1612,7 @@ int label_scan_reopen_rw(struct device *dev)
|
||||
flags |= O_NOATIME;
|
||||
flags |= O_RDWR;
|
||||
|
||||
- fd = open(dev_name(dev), flags, 0777);
|
||||
+ fd = open(name, flags, 0777);
|
||||
if (fd < 0) {
|
||||
log_error("Failed to open rw %s errno %d di %d fd %d.",
|
||||
dev_name(dev), errno, dev->bcache_di, dev->bcache_fd);
|
||||
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
|
||||
index b598df3d6..60c80f1b1 100644
|
||||
--- a/lib/locking/lvmlockd.c
|
||||
+++ b/lib/locking/lvmlockd.c
|
||||
@@ -272,6 +272,8 @@ static void _lockd_retrive_vg_pv_list(struct volume_group *vg,
|
||||
|
||||
i = 0;
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
+ if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases))
|
||||
+ continue;
|
||||
lock_pvs->path[i] = strdup(pv_dev_name(pvl->pv));
|
||||
if (!lock_pvs->path[i]) {
|
||||
log_error("Fail to allocate PV path for VG %s", vg->name);
|
||||
@@ -341,6 +343,8 @@ static void _lockd_retrive_lv_pv_list(struct volume_group *vg,
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (lv_is_on_pv(lv, pvl->pv)) {
|
||||
+ if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases))
|
||||
+ continue;
|
||||
lock_pvs->path[i] = strdup(pv_dev_name(pvl->pv));
|
||||
if (!lock_pvs->path[i]) {
|
||||
log_error("Fail to allocate PV path for LV %s/%s",
|
||||
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
|
||||
index e2bf191a1..46da57948 100644
|
||||
--- a/lib/metadata/mirror.c
|
||||
+++ b/lib/metadata/mirror.c
|
||||
@@ -1231,14 +1231,23 @@ int remove_mirrors_from_segments(struct logical_volume *lv,
|
||||
const char *get_pvmove_pvname_from_lv_mirr(const struct logical_volume *lv_mirr)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
+ struct device *dev;
|
||||
|
||||
dm_list_iterate_items(seg, &lv_mirr->segments) {
|
||||
if (!seg_is_mirrored(seg))
|
||||
continue;
|
||||
- if (seg_type(seg, 0) == AREA_PV)
|
||||
- return dev_name(seg_dev(seg, 0));
|
||||
- if (seg_type(seg, 0) == AREA_LV)
|
||||
- return dev_name(seg_dev(first_seg(seg_lv(seg, 0)), 0));
|
||||
+ if (seg_type(seg, 0) == AREA_PV) {
|
||||
+ dev = seg_dev(seg, 0);
|
||||
+ if (!dev || dm_list_empty(&dev->aliases))
|
||||
+ return NULL;
|
||||
+ return dev_name(dev);
|
||||
+ }
|
||||
+ if (seg_type(seg, 0) == AREA_LV) {
|
||||
+ dev = seg_dev(first_seg(seg_lv(seg, 0)), 0);
|
||||
+ if (!dev || dm_list_empty(&dev->aliases))
|
||||
+ return NULL;
|
||||
+ return dev_name(dev);
|
||||
+ }
|
||||
}
|
||||
|
||||
return NULL;
|
||||
diff --git a/lib/metadata/pv_list.c b/lib/metadata/pv_list.c
|
||||
index 813e8e525..fc3667db0 100644
|
||||
--- a/lib/metadata/pv_list.c
|
||||
+++ b/lib/metadata/pv_list.c
|
||||
@@ -152,6 +152,11 @@ static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
|
||||
struct pv_list *new_pvl = NULL, *pvl2;
|
||||
struct dm_list *pe_ranges;
|
||||
|
||||
+ if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases)) {
|
||||
+ log_error("Failed to create PV entry for missing device.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
pvname = pv_dev_name(pvl->pv);
|
||||
if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) {
|
||||
log_warn("WARNING: Physical volume %s not allocatable.", pvname);
|
||||
diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c
|
||||
index 85482552a..adc954bab 100644
|
||||
--- a/lib/metadata/vg.c
|
||||
+++ b/lib/metadata/vg.c
|
||||
@@ -679,6 +679,11 @@ int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return r;
|
||||
}
|
||||
|
||||
+ if (!pv->dev || dm_list_empty(&pv->dev->aliases)) {
|
||||
+ log_error("No device found for PV.");
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
log_debug("vgreduce_single VG %s PV %s", vg->name, pv_dev_name(pv));
|
||||
|
||||
if (pv_pe_alloc_count(pv)) {
|
||||
diff --git a/test/shell/losetup-partscan.sh b/test/shell/losetup-partscan.sh
|
||||
index 99f552ad1..670568945 100644
|
||||
--- a/test/shell/losetup-partscan.sh
|
||||
+++ b/test/shell/losetup-partscan.sh
|
||||
@@ -33,6 +33,8 @@ aux udev_wait
|
||||
ls -la "${LOOP}"*
|
||||
test -e "${LOOP}p1"
|
||||
|
||||
+aux lvmconf 'devices/scan = "/dev"'
|
||||
+
|
||||
aux extend_filter "a|$LOOP|"
|
||||
aux extend_devices "$LOOP"
|
||||
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
From 89300351f254ce1fe499f6bae609c16a0b1ef60a Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Wed, 9 Jul 2025 23:26:03 +0200
|
||||
Subject: [PATCH 38/47] gcc: ensure pointer is properly initialized
|
||||
|
||||
Fix gcc warning by ensuring pointers are properly defined and
|
||||
initialized before use in man-generator code to prevent potential
|
||||
undefined behavior.
|
||||
|
||||
(cherry picked from commit a23ef8e26f5468c37d676da15d0125bff6de7095)
|
||||
---
|
||||
tools/man-generator.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tools/man-generator.c b/tools/man-generator.c
|
||||
index bd161796a..7a60d4327 100644
|
||||
--- a/tools/man-generator.c
|
||||
+++ b/tools/man-generator.c
|
||||
@@ -1219,7 +1219,7 @@ static void _print_cmd_usage_option(const struct command_name *cname,
|
||||
static int _print_man(char *name, char *des_file, int secondary)
|
||||
{
|
||||
const struct command_name *cname;
|
||||
- const struct command_name_args *cna;
|
||||
+ const struct command_name_args *cna = NULL;
|
||||
struct command *cmd, *prev_cmd = NULL;
|
||||
char *lvmname = name;
|
||||
int i, sep = 0;
|
||||
@@ -1363,7 +1363,7 @@ static int _print_man(char *name, char *des_file, int secondary)
|
||||
if (cname && (i == (COMMAND_COUNT - 1))) {
|
||||
_print_cmd_usage_option(cname, cmd);
|
||||
} else {
|
||||
- if (cna->variants > 1)
|
||||
+ if (cna && cna->variants > 1)
|
||||
sep = 1;
|
||||
}
|
||||
}
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,272 +0,0 @@
|
||||
From 932b9720bb074e49ac920642b3fe9c3d84019787 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Mon, 28 Feb 2022 17:37:12 -0600
|
||||
Subject: [PATCH 39/54] devices: use dev-cache aliases handling from label scan
|
||||
functions
|
||||
|
||||
The label scan functions where doing some device alias validation
|
||||
which is now better handled by the dev-cache layer, so just use
|
||||
that.
|
||||
---
|
||||
lib/device/dev-cache.c | 4 +-
|
||||
lib/device/dev-cache.h | 1 +
|
||||
lib/label/label.c | 143 ++++++++++-------------------------------
|
||||
3 files changed, 36 insertions(+), 112 deletions(-)
|
||||
|
||||
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
|
||||
index 58e67e130..b0759b06c 100644
|
||||
--- a/lib/device/dev-cache.c
|
||||
+++ b/lib/device/dev-cache.c
|
||||
@@ -1410,7 +1410,7 @@ static void _remove_alias(struct device *dev, const char *name)
|
||||
* deactivated LV. Those old paths are all invalid and are dropped here.
|
||||
*/
|
||||
|
||||
-static void _verify_aliases(struct device *dev)
|
||||
+void dev_cache_verify_aliases(struct device *dev)
|
||||
{
|
||||
struct dm_str_list *strl, *strl2;
|
||||
struct stat st;
|
||||
@@ -1459,7 +1459,7 @@ static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name,
|
||||
_remove_alias(dev, name);
|
||||
|
||||
/* Remove any other names in dev->aliases that are incorrect. */
|
||||
- _verify_aliases(dev);
|
||||
+ dev_cache_verify_aliases(dev);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
|
||||
index 51c3fc6c3..321a56d7b 100644
|
||||
--- a/lib/device/dev-cache.h
|
||||
+++ b/lib/device/dev-cache.h
|
||||
@@ -55,6 +55,7 @@ int dev_cache_add_dir(const char *path);
|
||||
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f);
|
||||
struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f);
|
||||
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt);
|
||||
+void dev_cache_verify_aliases(struct device *dev);
|
||||
|
||||
struct device *dev_hash_get(const char *name);
|
||||
|
||||
diff --git a/lib/label/label.c b/lib/label/label.c
|
||||
index cf707f7a3..06958b502 100644
|
||||
--- a/lib/label/label.c
|
||||
+++ b/lib/label/label.c
|
||||
@@ -458,7 +458,6 @@ static int _scan_dev_open(struct device *dev)
|
||||
const char *name;
|
||||
const char *modestr;
|
||||
struct stat sbuf;
|
||||
- int retried = 0;
|
||||
int flags = 0;
|
||||
int fd, di;
|
||||
|
||||
@@ -478,14 +477,23 @@ static int _scan_dev_open(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ next_name:
|
||||
/*
|
||||
* All the names for this device (major:minor) are kept on
|
||||
* dev->aliases, the first one is the primary/preferred name.
|
||||
+ *
|
||||
+ * The default name preferences in dev-cache mean that the first
|
||||
+ * name in dev->aliases is not a symlink for scsi devices, but is
|
||||
+ * the /dev/mapper/ symlink for mpath devices.
|
||||
+ *
|
||||
+ * If preferred names are set to symlinks, should this
|
||||
+ * first attempt to open using a non-symlink?
|
||||
+ *
|
||||
+ * dm_list_first() returns NULL if the list is empty.
|
||||
*/
|
||||
if (!(name_list = dm_list_first(&dev->aliases))) {
|
||||
- /* Shouldn't happen */
|
||||
- log_error("Device open %s %d:%d has no path names.",
|
||||
- dev_name(dev), (int)MAJOR(dev->dev), (int)MINOR(dev->dev));
|
||||
+ log_error("Device open %d:%d has no path names.",
|
||||
+ (int)MAJOR(dev->dev), (int)MINOR(dev->dev));
|
||||
return 0;
|
||||
}
|
||||
name_sl = dm_list_item(name_list, struct dm_str_list);
|
||||
@@ -513,50 +521,34 @@ static int _scan_dev_open(struct device *dev)
|
||||
modestr = "ro";
|
||||
}
|
||||
|
||||
-retry_open:
|
||||
-
|
||||
fd = open(name, flags, 0777);
|
||||
-
|
||||
if (fd < 0) {
|
||||
if ((errno == EBUSY) && (flags & O_EXCL)) {
|
||||
log_error("Can't open %s exclusively. Mounted filesystem?",
|
||||
dev_name(dev));
|
||||
+ return 0;
|
||||
} else {
|
||||
- int major, minor;
|
||||
-
|
||||
/*
|
||||
- * Shouldn't happen, if it does, print stat info to help figure
|
||||
- * out what's wrong.
|
||||
+ * drop name from dev->aliases and use verify_aliases to
|
||||
+ * drop any other invalid aliases before retrying open with
|
||||
+ * any remaining valid paths.
|
||||
*/
|
||||
-
|
||||
- major = (int)MAJOR(dev->dev);
|
||||
- minor = (int)MINOR(dev->dev);
|
||||
-
|
||||
- log_error("Device open %s %d:%d failed errno %d", name, major, minor, errno);
|
||||
-
|
||||
- if (stat(name, &sbuf)) {
|
||||
- log_debug_devs("Device open %s %d:%d stat failed errno %d",
|
||||
- name, major, minor, errno);
|
||||
- } else if (sbuf.st_rdev != dev->dev) {
|
||||
- log_debug_devs("Device open %s %d:%d stat %d:%d does not match.",
|
||||
- name, major, minor,
|
||||
- (int)MAJOR(sbuf.st_rdev), (int)MINOR(sbuf.st_rdev));
|
||||
- }
|
||||
-
|
||||
- if (!retried) {
|
||||
- /*
|
||||
- * FIXME: remove this, the theory for this retry is that
|
||||
- * there may be a udev race that we can sometimes mask by
|
||||
- * retrying. This is here until we can figure out if it's
|
||||
- * needed and if so fix the real problem.
|
||||
- */
|
||||
- usleep(5000);
|
||||
- log_debug_devs("Device open %s retry", dev_name(dev));
|
||||
- retried = 1;
|
||||
- goto retry_open;
|
||||
- }
|
||||
+ log_debug("Drop alias for %d:%d failed open %s (%d)",
|
||||
+ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), name, errno);
|
||||
+ dev_cache_failed_path(dev, name);
|
||||
+ dev_cache_verify_aliases(dev);
|
||||
+ goto next_name;
|
||||
}
|
||||
- return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Verify that major:minor from the path still match dev. */
|
||||
+ if ((fstat(fd, &sbuf) < 0) || (sbuf.st_rdev != dev->dev)) {
|
||||
+ log_warn("Invalid path %s for device %d:%d, trying different path.",
|
||||
+ name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev));
|
||||
+ (void)close(fd);
|
||||
+ dev_cache_failed_path(dev, name);
|
||||
+ dev_cache_verify_aliases(dev);
|
||||
+ goto next_name;
|
||||
}
|
||||
|
||||
dev->flags |= DEV_IN_BCACHE;
|
||||
@@ -604,37 +596,6 @@ static int _scan_dev_close(struct device *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static void _drop_bad_aliases(struct device *dev)
|
||||
-{
|
||||
- struct dm_str_list *strl, *strl2;
|
||||
- const char *name;
|
||||
- struct stat sbuf;
|
||||
- int major = (int)MAJOR(dev->dev);
|
||||
- int minor = (int)MINOR(dev->dev);
|
||||
- int bad;
|
||||
-
|
||||
- dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
|
||||
- name = strl->str;
|
||||
- bad = 0;
|
||||
-
|
||||
- if (stat(name, &sbuf)) {
|
||||
- bad = 1;
|
||||
- log_debug_devs("Device path check %d:%d %s stat failed errno %d",
|
||||
- major, minor, name, errno);
|
||||
- } else if (sbuf.st_rdev != dev->dev) {
|
||||
- bad = 1;
|
||||
- log_debug_devs("Device path check %d:%d %s stat %d:%d does not match.",
|
||||
- major, minor, name,
|
||||
- (int)MAJOR(sbuf.st_rdev), (int)MINOR(sbuf.st_rdev));
|
||||
- }
|
||||
-
|
||||
- if (bad) {
|
||||
- log_debug_devs("Device path check %d:%d dropping path %s.", major, minor, name);
|
||||
- dev_cache_failed_path(dev, name);
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
// Like bcache_invalidate, only it throws any dirty data away if the
|
||||
// write fails.
|
||||
static void _invalidate_di(struct bcache *cache, int di)
|
||||
@@ -662,10 +623,8 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
char headers_buf[HEADERS_BUF_SIZE];
|
||||
struct dm_list wait_devs;
|
||||
struct dm_list done_devs;
|
||||
- struct dm_list reopen_devs;
|
||||
struct device_list *devl, *devl2;
|
||||
struct block *bb;
|
||||
- int retried_open = 0;
|
||||
int scan_read_errors = 0;
|
||||
int scan_process_errors = 0;
|
||||
int scan_failed_count = 0;
|
||||
@@ -676,7 +635,6 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
|
||||
dm_list_init(&wait_devs);
|
||||
dm_list_init(&done_devs);
|
||||
- dm_list_init(&reopen_devs);
|
||||
|
||||
log_debug_devs("Scanning %d devices for VG info", dm_list_size(devs));
|
||||
|
||||
@@ -700,9 +658,9 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
|
||||
if (!_in_bcache(devl->dev)) {
|
||||
if (!_scan_dev_open(devl->dev)) {
|
||||
- log_debug_devs("Scan failed to open %s.", dev_name(devl->dev));
|
||||
+ log_debug_devs("Scan failed to open %d:%d %s.",
|
||||
+ (int)MAJOR(devl->dev->dev), (int)MINOR(devl->dev->dev), dev_name(devl->dev));
|
||||
dm_list_del(&devl->list);
|
||||
- dm_list_add(&reopen_devs, &devl->list);
|
||||
devl->dev->flags |= DEV_SCAN_NOT_READ;
|
||||
continue;
|
||||
}
|
||||
@@ -786,41 +744,6 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
if (!dm_list_empty(devs))
|
||||
goto scan_more;
|
||||
|
||||
- /*
|
||||
- * We're done scanning all the devs. If we failed to open any of them
|
||||
- * the first time through, refresh device paths and retry. We failed
|
||||
- * to open the devs on the reopen_devs list.
|
||||
- *
|
||||
- * FIXME: it's not clear if or why this helps.
|
||||
- */
|
||||
- if (!dm_list_empty(&reopen_devs)) {
|
||||
- if (retried_open) {
|
||||
- /* Don't try again. */
|
||||
- scan_failed_count += dm_list_size(&reopen_devs);
|
||||
- dm_list_splice(&done_devs, &reopen_devs);
|
||||
- goto out;
|
||||
- }
|
||||
- retried_open = 1;
|
||||
-
|
||||
- dm_list_iterate_items_safe(devl, devl2, &reopen_devs) {
|
||||
- _drop_bad_aliases(devl->dev);
|
||||
-
|
||||
- if (dm_list_empty(&devl->dev->aliases)) {
|
||||
- log_warn("WARNING: Scan ignoring device %d:%d with no paths.",
|
||||
- (int)MAJOR(devl->dev->dev),
|
||||
- (int)MINOR(devl->dev->dev));
|
||||
-
|
||||
- dm_list_del(&devl->list);
|
||||
- lvmcache_del_dev(devl->dev);
|
||||
- scan_failed_count++;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* Put devs that failed to open back on the original list to retry. */
|
||||
- dm_list_splice(devs, &reopen_devs);
|
||||
- goto scan_more;
|
||||
- }
|
||||
-out:
|
||||
log_debug_devs("Scanned devices: read errors %d process errors %d failed %d",
|
||||
scan_read_errors, scan_process_errors, scan_failed_count);
|
||||
|
||||
--
|
||||
2.34.3
|
||||
|
||||
40
SOURCES/0039-dmeventd-check-device-exists.patch
Normal file
40
SOURCES/0039-dmeventd-check-device-exists.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From 4ed321be7a9dcd3df99f3175f03bc45d65989c98 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Tue, 22 Jul 2025 20:34:38 +0200
|
||||
Subject: [PATCH 39/47] dmeventd: check device exists
|
||||
|
||||
Check first whether the monitored device actually really exists,
|
||||
before resolving its device name.
|
||||
|
||||
In the case device is not present in DM table, fail _fill_device_data().
|
||||
|
||||
(cherry picked from commit 175a80157a2116a64f72e912c04b4a45a03c50f6)
|
||||
---
|
||||
daemons/dmeventd/dmeventd.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
|
||||
index 2224ba23e..93dfb9bc0 100644
|
||||
--- a/daemons/dmeventd/dmeventd.c
|
||||
+++ b/daemons/dmeventd/dmeventd.c
|
||||
@@ -606,11 +606,14 @@ static int _fill_device_data(struct thread_status *ts)
|
||||
if (!dm_task_run(dmt))
|
||||
goto fail;
|
||||
|
||||
- free(ts->device.name);
|
||||
- if (!(ts->device.name = strdup(dm_task_get_name(dmt))))
|
||||
+ if (!dm_task_get_info(dmt, &dmi))
|
||||
goto fail;
|
||||
|
||||
- if (!dm_task_get_info(dmt, &dmi))
|
||||
+ if (!dmi.exists)
|
||||
+ goto fail;
|
||||
+
|
||||
+ free(ts->device.name);
|
||||
+ if (!(ts->device.name = strdup(dm_task_get_name(dmt))))
|
||||
goto fail;
|
||||
|
||||
ts->device.major = dmi.major;
|
||||
--
|
||||
2.51.0
|
||||
|
||||
53
SOURCES/0040-dmeventd-add-device-existence-check.patch
Normal file
53
SOURCES/0040-dmeventd-add-device-existence-check.patch
Normal file
@ -0,0 +1,53 @@
|
||||
From a7c707334f3b2d571f8fa80db75e631b11e4b09b Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Tue, 22 Jul 2025 20:35:24 +0200
|
||||
Subject: [PATCH 40/47] dmeventd: add device existence check
|
||||
|
||||
Add device existence check after successful wait ioctl to prevent
|
||||
processing events on removed devices.
|
||||
|
||||
When dm_task_run() succeeds on a WAITEVENT ioctl, the success might
|
||||
actually indicate that the device was removed rather than a genuine
|
||||
device event. Without this check, dmeventd would attempt to process
|
||||
ERROR events on non-existent devices, leading to unnecessary error
|
||||
commands and log noise.
|
||||
|
||||
This fix adds a _fill_device_data() call immediately after successful
|
||||
wait completion to verify the device still exists. If the device is
|
||||
gone, execution jumps to the existing ENXIO error path which properly
|
||||
handles device disappearance.
|
||||
|
||||
Note: Future kernel versions may return ENXIO directly from the wait
|
||||
ioctl when devices are removed, making this workaround unnecessary.
|
||||
Until then, this extra INFO ioctl provides the needed verification.
|
||||
|
||||
(cherry picked from commit fa2ec32c4eaab7f6c7e85dd71fba455a0022dc38)
|
||||
---
|
||||
daemons/dmeventd/dmeventd.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
|
||||
index 93dfb9bc0..b696cc77a 100644
|
||||
--- a/daemons/dmeventd/dmeventd.c
|
||||
+++ b/daemons/dmeventd/dmeventd.c
|
||||
@@ -902,6 +902,9 @@ static int _event_wait(struct thread_status *thread)
|
||||
}
|
||||
|
||||
if (dm_task_run(thread->wait_task)) {
|
||||
+ /* Recheck device info whether is still exists */
|
||||
+ if (!_fill_device_data(thread))
|
||||
+ goto disappeared; /* device is gone... */
|
||||
thread->current_events |= DM_EVENT_DEVICE_ERROR;
|
||||
ret = DM_WAIT_INTR;
|
||||
/* Update event_nr */
|
||||
@@ -910,6 +913,7 @@ static int _event_wait(struct thread_status *thread)
|
||||
} else {
|
||||
switch (dm_task_get_errno(thread->wait_task)) {
|
||||
case ENXIO:
|
||||
+disappeared:
|
||||
log_error("%s disappeared, detaching.",
|
||||
thread->device.name);
|
||||
ret = DM_WAIT_FATAL;
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,101 +0,0 @@
|
||||
From 10a598075a0fdf6d93cc2fefa73fc4a5f1d0de48 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Tue, 1 Mar 2022 14:31:39 -0600
|
||||
Subject: [PATCH 40/54] writecache: check memory usage
|
||||
|
||||
warn if writecache neds > 50% of system memory, and
|
||||
confirm if writecache needs > 90% of system memory.
|
||||
---
|
||||
tools/lvconvert.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 69 insertions(+)
|
||||
|
||||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
|
||||
index 34b82ea02..a90946173 100644
|
||||
--- a/tools/lvconvert.c
|
||||
+++ b/tools/lvconvert.c
|
||||
@@ -6072,6 +6072,69 @@ bad:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int _check_writecache_memory(struct cmd_context *cmd, struct logical_volume *lv_fast,
|
||||
+ uint32_t block_size_sectors)
|
||||
+{
|
||||
+ char line[128];
|
||||
+ FILE *fp;
|
||||
+ uint64_t cachevol_size_bytes = lv_fast->size * SECTOR_SIZE;
|
||||
+ uint64_t need_mem_bytes = 0;
|
||||
+ uint64_t proc_mem_bytes = 0;
|
||||
+ uint64_t need_mem_gb;
|
||||
+ uint64_t proc_mem_gb;
|
||||
+ unsigned long long proc_mem_kb = 0;
|
||||
+
|
||||
+ if (!(fp = fopen("/proc/meminfo", "r")))
|
||||
+ goto skip_proc;
|
||||
+
|
||||
+ while (fgets(line, sizeof(line), fp)) {
|
||||
+ if (strncmp(line, "MemTotal:", 9))
|
||||
+ continue;
|
||||
+ if (sscanf(line, "%*s%llu%*s", &proc_mem_kb) != 1)
|
||||
+ break;
|
||||
+ break;
|
||||
+ }
|
||||
+ (void)fclose(fp);
|
||||
+
|
||||
+ proc_mem_bytes = proc_mem_kb * 1024;
|
||||
+
|
||||
+ skip_proc:
|
||||
+ /* dm-writecache memory consumption per block is 88 bytes */
|
||||
+ if (block_size_sectors == 8) {
|
||||
+ need_mem_bytes = cachevol_size_bytes * 88 / 4096;
|
||||
+ } else if (block_size_sectors == 1) {
|
||||
+ need_mem_bytes = cachevol_size_bytes * 88 / 512;
|
||||
+ } else {
|
||||
+ /* shouldn't happen */
|
||||
+ log_warn("Unknown memory usage for unknown writecache block_size_sectors %u", block_size_sectors);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ need_mem_gb = need_mem_bytes / 1073741824;
|
||||
+ proc_mem_gb = proc_mem_bytes / 1073741824;
|
||||
+
|
||||
+ /*
|
||||
+ * warn if writecache needs > 50% of main memory, and
|
||||
+ * confirm if writecache needs > 90% of main memory.
|
||||
+ */
|
||||
+ if (need_mem_bytes >= (proc_mem_bytes / 2)) {
|
||||
+ log_warn("WARNING: writecache size %s will use %llu GiB of system memory (%llu GiB).",
|
||||
+ display_size(cmd, lv_fast->size),
|
||||
+ (unsigned long long)need_mem_gb,
|
||||
+ (unsigned long long)proc_mem_gb);
|
||||
+
|
||||
+ if (need_mem_gb >= (proc_mem_gb * 9 / 10)) {
|
||||
+ if (!arg_is_set(cmd, yes_ARG) &&
|
||||
+ yes_no_prompt("Continue adding writecache? [y/n]: ") == 'n') {
|
||||
+ log_error("Conversion aborted.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
int lvconvert_writecache_attach_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct processing_handle *handle)
|
||||
@@ -6160,6 +6223,12 @@ int lvconvert_writecache_attach_single(struct cmd_context *cmd,
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
+ if (!_check_writecache_memory(cmd, lv_fast, block_size_sectors)) {
|
||||
+ if (!is_active && !deactivate_lv(cmd, lv))
|
||||
+ stack;
|
||||
+ goto_bad;
|
||||
+ }
|
||||
+
|
||||
if (!is_active) {
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_error("Failed to deactivate LV after checking block size %s", display_lvname(lv));
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -1,108 +0,0 @@
|
||||
From 090dc0c320f0abee8ab79f4eaea6561c195b5009 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Thu, 31 Mar 2022 11:38:08 -0500
|
||||
Subject: [PATCH 41/54] change messages about filtered devices
|
||||
|
||||
Change messages that refer to devices being "excluded by filters"
|
||||
to say just "excluded". This will avoid mistaking the word
|
||||
"filters" with the lvm.conf filter setting.
|
||||
---
|
||||
lib/device/device_id.c | 6 +++---
|
||||
tools/lvmdevices.c | 4 ++--
|
||||
tools/pvscan.c | 4 ++--
|
||||
tools/vgimportclone.c | 4 ++--
|
||||
4 files changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index 82db6e4a5..6133e700a 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -1744,7 +1744,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
|
||||
* probably wants to do something about it.
|
||||
*/
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) {
|
||||
- log_warn("Devices file %s is excluded by filter: %s.",
|
||||
+ log_warn("Devices file %s is excluded: %s.",
|
||||
dev_name(dev), dev_filtered_reason(dev));
|
||||
continue;
|
||||
}
|
||||
@@ -1830,7 +1830,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
|
||||
continue;
|
||||
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) {
|
||||
- log_warn("Devices file %s is excluded by filter: %s.",
|
||||
+ log_warn("Devices file %s is excluded: %s.",
|
||||
dev_name(dev), dev_filtered_reason(dev));
|
||||
/* FIXME: what if this dev is wrongly matched and should be checked below? */
|
||||
continue;
|
||||
@@ -2266,7 +2266,7 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l
|
||||
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) {
|
||||
/* I don't think this would happen */
|
||||
- log_warn("WARNING: new device %s for PVID %s does not pass filter %s.",
|
||||
+ log_warn("WARNING: new device %s for PVID %s is excluded: %s.",
|
||||
dev_name(dev), dil->pvid, dev_filtered_reason(dev));
|
||||
if (du) /* Should not happen 'du' is NULL */
|
||||
du->dev = NULL;
|
||||
diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c
|
||||
index 662b35f9a..8521b89ea 100644
|
||||
--- a/tools/lvmdevices.c
|
||||
+++ b/tools/lvmdevices.c
|
||||
@@ -112,7 +112,7 @@ static void _search_devs_for_pvids(struct cmd_context *cmd, struct dm_list *sear
|
||||
dev = devl->dev;
|
||||
cmd->filter->wipe(cmd, cmd->filter, dev, NULL);
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) {
|
||||
- log_warn("WARNING: PVID %s found on %s which is excluded by filter: %s",
|
||||
+ log_warn("WARNING: PVID %s found on %s which is excluded: %s",
|
||||
dev->pvid, dev_name(dev), dev_filtered_reason(dev));
|
||||
dm_list_del(&devl->list);
|
||||
}
|
||||
@@ -310,7 +310,7 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
cmd->filter_deviceid_skip = 1;
|
||||
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) {
|
||||
- log_warn("WARNING: adding device %s that is excluded by filter: %s.",
|
||||
+ log_warn("WARNING: adding device %s that is excluded: %s.",
|
||||
dev_name(dev), dev_filtered_reason(dev));
|
||||
}
|
||||
|
||||
diff --git a/tools/pvscan.c b/tools/pvscan.c
|
||||
index 160a2c9a0..50d46051a 100644
|
||||
--- a/tools/pvscan.c
|
||||
+++ b/tools/pvscan.c
|
||||
@@ -1756,7 +1756,7 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv,
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, &pvscan_devs) {
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, NULL)) {
|
||||
- log_print_pvscan(cmd, "%s excluded by filters: %s.",
|
||||
+ log_print_pvscan(cmd, "%s excluded: %s.",
|
||||
dev_name(devl->dev), dev_filtered_reason(devl->dev));
|
||||
dm_list_del(&devl->list);
|
||||
}
|
||||
@@ -1813,7 +1813,7 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv,
|
||||
|
||||
/* Applies all filters, including those that need data from dev. */
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, NULL)) {
|
||||
- log_print_pvscan(cmd, "%s excluded by filters: %s.",
|
||||
+ log_print_pvscan(cmd, "%s excluded: %s.",
|
||||
dev_name(devl->dev), dev_filtered_reason(devl->dev));
|
||||
dm_list_del(&devl->list);
|
||||
}
|
||||
diff --git a/tools/vgimportclone.c b/tools/vgimportclone.c
|
||||
index 23bb6271f..cab501619 100644
|
||||
--- a/tools/vgimportclone.c
|
||||
+++ b/tools/vgimportclone.c
|
||||
@@ -311,8 +311,8 @@ int vgimportclone(struct cmd_context *cmd, int argc, char **argv)
|
||||
*/
|
||||
dm_list_iterate_items(devl, &vp.new_devs) {
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, "persistent")) {
|
||||
- /* FIXME: print which filter */
|
||||
- log_error("Device %s was excluded by filters.", dev_name(devl->dev));
|
||||
+ log_error("Device %s is excluded: %s.",
|
||||
+ dev_name(devl->dev), dev_filtered_reason(devl->dev));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
From d825680fd9fae523f166a1ff1a833e5157ccce79 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Tue, 29 Jul 2025 16:00:39 +0200
|
||||
Subject: [PATCH 41/47] dmeventd: _get_status returns success for non
|
||||
monitoring
|
||||
|
||||
No longer returning EINVAL when the dmeventd is not monitoring
|
||||
any device (there are no registered devices).
|
||||
|
||||
This makes usable i.e. 'dmeventd -R' for the case, the dmeventd
|
||||
was not monnitoring anything during this call.
|
||||
|
||||
Previously this actually cause refuse of 'restart' - since
|
||||
restarting 'dmeventd' has seen failing resutl of a call:
|
||||
DM_EVENT_CMD_GET_STATUS
|
||||
|
||||
(cherry picked from commit 6a31246bdd50ee8619d58704d83e4e916e0608d8)
|
||||
---
|
||||
daemons/dmeventd/dmeventd.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
|
||||
index b696cc77a..22a713b9a 100644
|
||||
--- a/daemons/dmeventd/dmeventd.c
|
||||
+++ b/daemons/dmeventd/dmeventd.c
|
||||
@@ -685,7 +685,7 @@ static int _get_status(struct message_data *message_data)
|
||||
_lock_mutex();
|
||||
if (!(count = dm_list_size(&_thread_registry))) {
|
||||
_unlock_mutex();
|
||||
- ret = -EINVAL;
|
||||
+ ret = 0; /* no monitored devices */
|
||||
goto out;
|
||||
}
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
From 4aa92f3e18cb49470ee9b5d928abe6b4c86f3074 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Wed, 6 Apr 2022 12:20:26 -0500
|
||||
Subject: [PATCH 42/54] vgimportdevices: fix incorrect deviceidtype usage
|
||||
|
||||
When a VG has PVs with different device id types,
|
||||
it would try to use the idtype of the previous PV
|
||||
in the loop. This would produce an unncessary warning,
|
||||
or could lead to using the devname idtype when a better
|
||||
idtype is available.
|
||||
---
|
||||
tools/vgimportdevices.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tools/vgimportdevices.c b/tools/vgimportdevices.c
|
||||
index 2580613c4..ea205d941 100644
|
||||
--- a/tools/vgimportdevices.c
|
||||
+++ b/tools/vgimportdevices.c
|
||||
@@ -57,8 +57,7 @@ static int _vgimportdevices_single(struct cmd_context *cmd,
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
pv = pvl->pv;
|
||||
|
||||
- if (!idtypestr && pv->device_id_type)
|
||||
- idtypestr = pv->device_id_type;
|
||||
+ idtypestr = pv->device_id_type;
|
||||
|
||||
memcpy(pvid, &pvl->pv->id.uuid, ID_LEN);
|
||||
device_id_add(cmd, pv->dev, pvid, idtypestr, NULL);
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
From 5af9f7beca2c30815707c412dcbe31a109fd0d62 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Fri, 25 Jul 2025 10:45:07 +0200
|
||||
Subject: [PATCH 42/47] vgsplit: fix check for not splitting an LV between two
|
||||
VGs
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Fix check for not splitting an LV between two VGs in case
|
||||
where the LVs contains an internal layer.
|
||||
|
||||
For example, integrity layer for RAIDs and splitting a PV that
|
||||
is not part of the RAID LV at all (sdc here):
|
||||
|
||||
❯ vgcreate vg /dev/sda /dev/sdb /dev/sdc
|
||||
Volume group "vg" successfully created
|
||||
|
||||
❯ lvcreate -l1 -m1 --type raid1 --raidintegrity y vg /dev/sda /dev/sdb
|
||||
Logical volume "lvol0" created.
|
||||
|
||||
Before this patch:
|
||||
|
||||
❯ vgsplit vg vg2 /dev/sdc
|
||||
Logical volume vg/lvol0_rimage_0 (part of lvol0) must be inactive.
|
||||
|
||||
❯ vgchange -an vg
|
||||
0 logical volume(s) in volume group "vg" now active
|
||||
|
||||
❯ vgsplit vg vg2 /dev/sdc
|
||||
Can't split LV lvol0_rimage_0 between two Volume Groups
|
||||
|
||||
With this patch applied:
|
||||
|
||||
❯ vgsplit vg vg2 /dev/sdc
|
||||
New volume group "vg2" successfully split from "vg"
|
||||
|
||||
(cherry picked from commit 185455659347722a5eab26f1cc9f189076847e45)
|
||||
---
|
||||
tools/vgsplit.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
|
||||
index e79195019..aa89835d3 100644
|
||||
--- a/tools/vgsplit.c
|
||||
+++ b/tools/vgsplit.c
|
||||
@@ -170,7 +170,7 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
|
||||
|
||||
}
|
||||
|
||||
- if (vg_with == vg_from)
|
||||
+ if (!vg_with || vg_with == vg_from)
|
||||
continue;
|
||||
|
||||
/* Move this LV */
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
From 6de2a6a378a7673168fad34aebe8ddcb564a5911 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Fri, 8 Apr 2022 11:28:53 -0500
|
||||
Subject: [PATCH 43/54] lvmlockd: return error from vgcreate init_vg_sanlock
|
||||
|
||||
in vgcreate for shared sanlock vg, if sanlock_write_resource
|
||||
returns an unexpected error, then make init_vg_sanlock fail
|
||||
which will cause the vgcreate to fail.
|
||||
---
|
||||
daemons/lvmlockd/lvmlockd-sanlock.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
index e595eeffd..d87d1093b 100644
|
||||
--- a/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
+++ b/daemons/lvmlockd/lvmlockd-sanlock.c
|
||||
@@ -684,10 +684,10 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
||||
break;
|
||||
}
|
||||
|
||||
- if (rv) {
|
||||
+ if (rv < 0) {
|
||||
log_error("clear lv resource area %llu error %d",
|
||||
(unsigned long long)offset, rv);
|
||||
- break;
|
||||
+ return rv;
|
||||
}
|
||||
offset += align_size;
|
||||
}
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
From 147d05c177c39d298f02fc6f786e476308413133 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Tue, 12 Aug 2025 11:32:18 +0200
|
||||
Subject: [PATCH 43/47] vgsplit: fix check for not splitting an LV between two
|
||||
VGs for cachevol
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When cachevol was used for the cache LV, the check for not splitting an
|
||||
LV between two VGs was incorrect, not allowing to split the VG in cases
|
||||
it should have been possible.
|
||||
|
||||
For example, splitting a VG which contains the cache LV with cachevol
|
||||
only on two devices (sda and sdb here) and leaving third device completely
|
||||
unused (sdc here) should clearly allow us to split it into a new VG:
|
||||
|
||||
❯ vgcreate vg /dev/sd{a..c}
|
||||
Physical volume "/dev/sda" successfully created.
|
||||
Physical volume "/dev/sdb" successfully created.
|
||||
Physical volume "/dev/sdc" successfully created.
|
||||
Volume group "vg" successfully created
|
||||
|
||||
❯ lvcreate -l2 -n main vg /dev/sda
|
||||
Logical volume "main" created.
|
||||
|
||||
❯ lvcreate -l2 -n fast vg /dev/sdb
|
||||
Logical volume "fast" created.
|
||||
|
||||
❯ lvconvert -y --type cache --cachevol fast vg/main
|
||||
Logical volume vg/main is now cached.
|
||||
|
||||
❯ lvs -a -o name,devices vg
|
||||
lv_name devices
|
||||
[fast_cvol] /dev/sdb(0)
|
||||
main main_corig(0)
|
||||
[main_corig] /dev/sda(0)
|
||||
|
||||
❯ lsblk -o name /dev/sd{a..c}
|
||||
NAME
|
||||
sda
|
||||
└─vg-main_corig
|
||||
└─vg-main
|
||||
sdb
|
||||
└─vg-fast_cvol
|
||||
├─vg-fast_cvol-cdata
|
||||
│ └─vg-main
|
||||
└─vg-fast_cvol-cmeta
|
||||
└─vg-main
|
||||
sdc
|
||||
|
||||
Before this patch:
|
||||
|
||||
❯ vgsplit vg vg2 /dev/sdc
|
||||
Logical volume vg/main must be inactive.
|
||||
|
||||
❯ vgchange -an vg
|
||||
0 logical volume(s) in volume group "vg" now active
|
||||
|
||||
❯ vgsplit vg vg2 /dev/sdc
|
||||
Can't split LV main between two Volume Groups
|
||||
|
||||
With this patch applied:
|
||||
|
||||
❯ vgsplit vg vg2 /dev/sdc
|
||||
New volume group "vg2" successfully split from "vg"
|
||||
|
||||
(cherry picked from commit 3fe57cc892fc984c30fb14c866a109ef17772ed4)
|
||||
---
|
||||
tools/vgsplit.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
|
||||
index aa89835d3..5d6c0a06c 100644
|
||||
--- a/tools/vgsplit.c
|
||||
+++ b/tools/vgsplit.c
|
||||
@@ -450,6 +450,8 @@ static int _move_cache(struct volume_group *vg_from,
|
||||
|
||||
if (lv_is_cache_vol(lv)) {
|
||||
fast = lv;
|
||||
+ } else if (lv_is_cache_vol(seg->lv)) {
|
||||
+ fast = seg->lv;
|
||||
} else {
|
||||
data = seg_lv(seg, 0);
|
||||
meta = seg->metadata_lv;
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
From d96432835532fbcd8c72694c6ed68fca3ce98d5c Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Wed, 13 Apr 2022 12:16:57 -0500
|
||||
Subject: [PATCH 44/54] devices file: remove extraneous unlock in vgchange -u
|
||||
|
||||
vgchange -u exit path was unlocking the devices file in cases
|
||||
when it wasn't needed, which produced an warning.
|
||||
---
|
||||
lib/device/device_id.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||||
index 6133e700a..20901ab90 100644
|
||||
--- a/lib/device/device_id.c
|
||||
+++ b/lib/device/device_id.c
|
||||
@@ -1272,15 +1272,15 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg,
|
||||
int update = 0;
|
||||
|
||||
if (!cmd->enable_devices_file)
|
||||
- goto out;
|
||||
+ return;
|
||||
|
||||
/* Without this setting there is no stacking LVs on PVs. */
|
||||
if (!cmd->scan_lvs)
|
||||
- goto out;
|
||||
+ return;
|
||||
|
||||
/* Check if any devices file entries are stacked on LVs. */
|
||||
if (!_device_ids_use_lvmlv(cmd))
|
||||
- goto out;
|
||||
+ return;
|
||||
|
||||
memcpy(old_vgid, old_vg_id, ID_LEN);
|
||||
memcpy(new_vgid, &vg->id, ID_LEN);
|
||||
@@ -1310,7 +1310,6 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg,
|
||||
if (update &&
|
||||
!device_ids_write(cmd))
|
||||
stack;
|
||||
- out:
|
||||
unlock_devices_file(cmd);
|
||||
}
|
||||
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
From c370fe563dd095a09f6e070afb8a5c8e4915ec47 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Fri, 8 Aug 2025 12:36:11 -0500
|
||||
Subject: [PATCH 44/47] lvmdevices: do not create system.devices when deleting
|
||||
entries
|
||||
|
||||
When using "lvmdevices --deldev" or "lvmdevices --delpvid" and no
|
||||
system.devices file exists, the commands should not create the file.
|
||||
|
||||
(cherry picked from commit e61aab70498a887557c133fcba21fcc41345d272)
|
||||
---
|
||||
test/shell/devicesfile-edit.sh | 7 +++++++
|
||||
tools/lvmdevices.c | 4 ++++
|
||||
2 files changed, 11 insertions(+)
|
||||
|
||||
diff --git a/test/shell/devicesfile-edit.sh b/test/shell/devicesfile-edit.sh
|
||||
index 5f8eb90ee..4b8f9c008 100644
|
||||
--- a/test/shell/devicesfile-edit.sh
|
||||
+++ b/test/shell/devicesfile-edit.sh
|
||||
@@ -249,6 +249,13 @@ lvmdevices --update --delnotfound
|
||||
not grep PVID=aaa $DF
|
||||
not grep PVID=bbb $DF
|
||||
|
||||
+# test that deldev does not create devices file when it doesn't exist
|
||||
+rm -f $DF
|
||||
+test ! -e $DF
|
||||
+not lvmdevices --deldev "$LOOP1"
|
||||
+test ! -e $DF
|
||||
+not lvmdevices --delpvid "$PVID1"
|
||||
+test ! -e $DF
|
||||
|
||||
# TODO: add/rem of partitions of same device
|
||||
|
||||
diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c
|
||||
index 7f10038d4..65399c96c 100644
|
||||
--- a/tools/lvmdevices.c
|
||||
+++ b/tools/lvmdevices.c
|
||||
@@ -590,6 +590,10 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
if (!devices_file_exists(cmd)) {
|
||||
+ if (arg_is_set(cmd, deldev_ARG) || arg_is_set(cmd, delpvid_ARG) || arg_is_set(cmd, update_ARG)) {
|
||||
+ log_error("Devices file does not exist.");
|
||||
+ return ECMD_FAILED;
|
||||
+ }
|
||||
if (!devices_file_touch(cmd)) {
|
||||
log_error("Failed to create the devices file.");
|
||||
return ECMD_FAILED;
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,458 +0,0 @@
|
||||
From 5d40b91bd4aa8580ee1f40d467b848f7847f39e3 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Thu, 21 Apr 2022 13:45:01 -0500
|
||||
Subject: [PATCH 45/54] filter-mpath: use multipath blacklist
|
||||
|
||||
Explicit wwid's from these sections control whether the
|
||||
same wwid in /etc/multipath/wwids is recognized as a
|
||||
multipath component. Other non-wwid keywords are not
|
||||
used, and may require disabling the use of the multipath
|
||||
wwids file in lvm.conf.
|
||||
---
|
||||
lib/device/dev-mpath.c | 181 ++++++++++++++++++++++++--
|
||||
test/shell/duplicate-pvs-multipath.sh | 2 +-
|
||||
test/shell/multipath-config.sh | 171 ++++++++++++++++++++++++
|
||||
3 files changed, 342 insertions(+), 12 deletions(-)
|
||||
create mode 100644 test/shell/multipath-config.sh
|
||||
|
||||
diff --git a/lib/device/dev-mpath.c b/lib/device/dev-mpath.c
|
||||
index cbbad9dc9..6eed03c5b 100644
|
||||
--- a/lib/device/dev-mpath.c
|
||||
+++ b/lib/device/dev-mpath.c
|
||||
@@ -17,12 +17,14 @@
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/device/device_id.h"
|
||||
+#include "lib/datastruct/str_list.h"
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
#include <libudev.h>
|
||||
#include "lib/device/dev-ext-udev-constants.h"
|
||||
#endif
|
||||
|
||||
#include <dirent.h>
|
||||
+#include <ctype.h>
|
||||
|
||||
#define MPATH_PREFIX "mpath-"
|
||||
|
||||
@@ -35,15 +37,167 @@
|
||||
* If dm-3 is not an mpath device, then the constant "1" is stored in
|
||||
* the hash table with the key of the dm minor number.
|
||||
*/
|
||||
-static struct dm_pool *_hash_mem;
|
||||
+static struct dm_pool *_wwid_mem;
|
||||
static struct dm_hash_table *_minor_hash_tab;
|
||||
static struct dm_hash_table *_wwid_hash_tab;
|
||||
+static struct dm_list _ignored;
|
||||
+static struct dm_list _ignored_exceptions;
|
||||
|
||||
#define MAX_WWID_LINE 512
|
||||
|
||||
-/*
|
||||
- * do we need to check the multipath.conf blacklist?
|
||||
- */
|
||||
+static void _read_blacklist_file(const char *path)
|
||||
+{
|
||||
+ FILE *fp;
|
||||
+ char line[MAX_WWID_LINE];
|
||||
+ char wwid[MAX_WWID_LINE];
|
||||
+ char *word, *p;
|
||||
+ int section_black = 0;
|
||||
+ int section_exceptions = 0;
|
||||
+ int found_quote;
|
||||
+ int found_three;
|
||||
+ int i, j;
|
||||
+
|
||||
+ if (!(fp = fopen(path, "r")))
|
||||
+ return;
|
||||
+
|
||||
+ while (fgets(line, sizeof(line), fp)) {
|
||||
+ word = NULL;
|
||||
+
|
||||
+ /* skip initial white space on the line */
|
||||
+ for (i = 0; i < MAX_WWID_LINE; i++) {
|
||||
+ if ((line[i] == '\n') || (line[i] == '\0'))
|
||||
+ break;
|
||||
+ if (isspace(line[i]))
|
||||
+ continue;
|
||||
+ word = &line[i];
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!word || word[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ /* identify the start of the section we want to read */
|
||||
+ if (strchr(word, '{')) {
|
||||
+ if (!strncmp(word, "blacklist_exceptions", 20))
|
||||
+ section_exceptions = 1;
|
||||
+ else if (!strncmp(word, "blacklist", 9))
|
||||
+ section_black = 1;
|
||||
+ continue;
|
||||
+ }
|
||||
+ /* identify the end of the section we've been reading */
|
||||
+ if (strchr(word, '}')) {
|
||||
+ section_exceptions = 0;
|
||||
+ section_black = 0;
|
||||
+ continue;
|
||||
+ }
|
||||
+ /* skip lines that are not in a section we want */
|
||||
+ if (!section_black && !section_exceptions)
|
||||
+ continue;
|
||||
+
|
||||
+ /*
|
||||
+ * read a wwid from the blacklist{_exceptions} section.
|
||||
+ * does not recognize other non-wwid entries in the
|
||||
+ * section, and skips those (should the entire mp
|
||||
+ * config filtering be disabled if non-wwids are seen?
|
||||
+ */
|
||||
+ if (!(p = strstr(word, "wwid")))
|
||||
+ continue;
|
||||
+
|
||||
+ i += 4; /* skip "wwid" */
|
||||
+
|
||||
+ /*
|
||||
+ * copy wwid value from the line.
|
||||
+ * the wwids copied here need to match the
|
||||
+ * wwids read from /etc/multipath/wwids,
|
||||
+ * which are matched to wwids from sysfs.
|
||||
+ */
|
||||
+
|
||||
+ memset(wwid, 0, sizeof(wwid));
|
||||
+ found_quote = 0;
|
||||
+ found_three = 0;
|
||||
+ j = 0;
|
||||
+
|
||||
+ for (; i < MAX_WWID_LINE; i++) {
|
||||
+ if ((line[i] == '\n') || (line[i] == '\0'))
|
||||
+ break;
|
||||
+ if (!j && isspace(line[i]))
|
||||
+ continue;
|
||||
+ if (isspace(line[i]))
|
||||
+ break;
|
||||
+ /* quotes around wwid are optional */
|
||||
+ if ((line[i] == '"') && !found_quote) {
|
||||
+ found_quote = 1;
|
||||
+ continue;
|
||||
+ }
|
||||
+ /* second quote is end of wwid */
|
||||
+ if ((line[i] == '"') && found_quote)
|
||||
+ break;
|
||||
+ /* ignore first "3" in wwid */
|
||||
+ if ((line[i] == '3') && !found_three) {
|
||||
+ found_three = 1;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ wwid[j] = line[i];
|
||||
+ j++;
|
||||
+ }
|
||||
+
|
||||
+ if (j < 8)
|
||||
+ continue;
|
||||
+
|
||||
+ log_debug("multipath wwid %s in %s %s",
|
||||
+ wwid, section_exceptions ? "blacklist_exceptions" : "blacklist", path);
|
||||
+
|
||||
+ if (section_exceptions) {
|
||||
+ if (!str_list_add(_wwid_mem, &_ignored_exceptions, dm_pool_strdup(_wwid_mem, wwid)))
|
||||
+ stack;
|
||||
+ } else {
|
||||
+ if (!str_list_add(_wwid_mem, &_ignored, dm_pool_strdup(_wwid_mem, wwid)))
|
||||
+ stack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (fclose(fp))
|
||||
+ stack;
|
||||
+}
|
||||
+
|
||||
+static void _read_wwid_exclusions(void)
|
||||
+{
|
||||
+ char path[PATH_MAX] = { 0 };
|
||||
+ DIR *dir;
|
||||
+ struct dirent *de;
|
||||
+ struct dm_str_list *sl, *sl2;
|
||||
+ int rem_count = 0;
|
||||
+
|
||||
+ _read_blacklist_file("/etc/multipath.conf");
|
||||
+
|
||||
+ if ((dir = opendir("/etc/multipath/conf.d"))) {
|
||||
+ while ((de = readdir(dir))) {
|
||||
+ if (de->d_name[0] == '.')
|
||||
+ continue;
|
||||
+ snprintf(path, PATH_MAX-1, "/etc/multipath/conf.d/%s", de->d_name);
|
||||
+ _read_blacklist_file(path);
|
||||
+ }
|
||||
+ closedir(dir);
|
||||
+ }
|
||||
+
|
||||
+ /* for each wwid in ignored_exceptions, remove it from ignored */
|
||||
+
|
||||
+ dm_list_iterate_items_safe(sl, sl2, &_ignored) {
|
||||
+ if (str_list_match_item(&_ignored_exceptions, sl->str))
|
||||
+ str_list_del(&_ignored, sl->str);
|
||||
+ }
|
||||
+
|
||||
+ /* for each wwid in ignored, remove it from wwid_hash */
|
||||
+
|
||||
+ dm_list_iterate_items(sl, &_ignored) {
|
||||
+ dm_hash_remove_binary(_wwid_hash_tab, sl->str, strlen(sl->str));
|
||||
+ rem_count++;
|
||||
+ }
|
||||
+
|
||||
+ if (rem_count)
|
||||
+ log_debug("multipath config ignored %d wwids", rem_count);
|
||||
+}
|
||||
|
||||
static void _read_wwid_file(const char *config_wwids_file)
|
||||
{
|
||||
@@ -93,6 +247,9 @@ int dev_mpath_init(const char *config_wwids_file)
|
||||
struct dm_hash_table *minor_tab;
|
||||
struct dm_hash_table *wwid_tab;
|
||||
|
||||
+ dm_list_init(&_ignored);
|
||||
+ dm_list_init(&_ignored_exceptions);
|
||||
+
|
||||
if (!(mem = dm_pool_create("mpath", 256))) {
|
||||
log_error("mpath pool creation failed.");
|
||||
return 0;
|
||||
@@ -104,7 +261,7 @@ int dev_mpath_init(const char *config_wwids_file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- _hash_mem = mem;
|
||||
+ _wwid_mem = mem;
|
||||
_minor_hash_tab = minor_tab;
|
||||
|
||||
/* multipath_wwids_file="" disables the use of the file */
|
||||
@@ -116,16 +273,18 @@ int dev_mpath_init(const char *config_wwids_file)
|
||||
if (!(wwid_tab = dm_hash_create(110))) {
|
||||
log_error("mpath hash table creation failed.");
|
||||
dm_hash_destroy(_minor_hash_tab);
|
||||
- dm_pool_destroy(_hash_mem);
|
||||
+ dm_pool_destroy(_wwid_mem);
|
||||
_minor_hash_tab = NULL;
|
||||
- _hash_mem = NULL;
|
||||
+ _wwid_mem = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_wwid_hash_tab = wwid_tab;
|
||||
|
||||
- if (config_wwids_file)
|
||||
+ if (config_wwids_file) {
|
||||
_read_wwid_file(config_wwids_file);
|
||||
+ _read_wwid_exclusions();
|
||||
+ }
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -136,12 +295,12 @@ void dev_mpath_exit(void)
|
||||
dm_hash_destroy(_minor_hash_tab);
|
||||
if (_wwid_hash_tab)
|
||||
dm_hash_destroy(_wwid_hash_tab);
|
||||
- if (_hash_mem)
|
||||
- dm_pool_destroy(_hash_mem);
|
||||
+ if (_wwid_mem)
|
||||
+ dm_pool_destroy(_wwid_mem);
|
||||
|
||||
_minor_hash_tab = NULL;
|
||||
_wwid_hash_tab = NULL;
|
||||
- _hash_mem = NULL;
|
||||
+ _wwid_mem = NULL;
|
||||
}
|
||||
|
||||
|
||||
diff --git a/test/shell/duplicate-pvs-multipath.sh b/test/shell/duplicate-pvs-multipath.sh
|
||||
index a145e4afb..59c15b0d4 100644
|
||||
--- a/test/shell/duplicate-pvs-multipath.sh
|
||||
+++ b/test/shell/duplicate-pvs-multipath.sh
|
||||
@@ -10,7 +10,7 @@
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-test_description='udev rule and systemd unit run vgchange'
|
||||
+test_description='duplicate pv detection of mpath components using wwid'
|
||||
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
SKIP_WITH_LVMLOCKD=1
|
||||
diff --git a/test/shell/multipath-config.sh b/test/shell/multipath-config.sh
|
||||
new file mode 100644
|
||||
index 000000000..ffb7d632a
|
||||
--- /dev/null
|
||||
+++ b/test/shell/multipath-config.sh
|
||||
@@ -0,0 +1,171 @@
|
||||
+#!/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='using multipath blacklist'
|
||||
+
|
||||
+SKIP_WITH_LVMPOLLD=1
|
||||
+SKIP_WITH_LVMLOCKD=1
|
||||
+
|
||||
+. lib/inittest
|
||||
+
|
||||
+# FIXME: don't run this test by default because it destroys the
|
||||
+# local multipath config, the timing of multipath/dm/lvm interactions
|
||||
+# is fragile, and there's insufficient cleanup after a test fails.
|
||||
+skip
|
||||
+
|
||||
+systemctl stop multipathd
|
||||
+multipath -F || true
|
||||
+rm /etc/multipath/wwids || true
|
||||
+rmmod scsi_debug || true
|
||||
+rm /etc/multipath/conf.d/lvmtest.conf || true
|
||||
+
|
||||
+modprobe --dry-run scsi_debug || skip
|
||||
+multipath -l || skip
|
||||
+multipath -l | grep scsi_debug && skip
|
||||
+ls /etc/multipath/wwids && skip
|
||||
+
|
||||
+# Need to use /dev/mapper/mpath
|
||||
+aux lvmconf 'devices/dir = "/dev"'
|
||||
+aux lvmconf 'devices/scan = "/dev"'
|
||||
+# Could set filter to $MP and the component /dev/sd devs
|
||||
+aux lvmconf "devices/filter = [ \"a|.*|\" ]"
|
||||
+aux lvmconf "devices/global_filter = [ \"a|.*|\" ]"
|
||||
+
|
||||
+modprobe scsi_debug dev_size_mb=16 num_tgts=1
|
||||
+sleep 2
|
||||
+
|
||||
+# Get scsi device name created by scsi_debug.
|
||||
+# SD = sdh
|
||||
+# SD_DEV = /dev/sdh
|
||||
+
|
||||
+SD=$(grep -H scsi_debug /sys/block/sd*/device/model | cut -f4 -d /);
|
||||
+echo $SD
|
||||
+SD_DEV=/dev/$SD
|
||||
+echo $SD_DEV
|
||||
+
|
||||
+# if multipath claimed SD, then io will fail
|
||||
+#dd if=$SD_DEV of=/dev/null bs=4k count=1 iflag=direct
|
||||
+#dd if=/dev/zero of=$SD_DEV bs=4k count=1 oflag=direct
|
||||
+
|
||||
+# check if multipathd claimed the scsi dev when it appears and create mp dm device
|
||||
+sleep 2
|
||||
+multipath -l
|
||||
+# create the mp dm device
|
||||
+multipath $SD_DEV
|
||||
+
|
||||
+# Get mpath device name created by multipath.
|
||||
+# MP = mpatha
|
||||
+# MP_DEV = /dev/maper/mpatha
|
||||
+
|
||||
+MP=$(multipath -l | grep scsi_debug | cut -f1 -d ' ')
|
||||
+echo $MP
|
||||
+MP_DEV=/dev/mapper/$MP
|
||||
+echo $MP_DEV
|
||||
+
|
||||
+dd if=$MP_DEV of=/dev/null bs=4k count=1 iflag=direct
|
||||
+dd if=/dev/zero of=$MP_DEV bs=4k count=1 oflag=direct
|
||||
+
|
||||
+# Get wwid for the mp and sd dev.
|
||||
+WWID=$(multipath -l $MP_DEV | head -1 | awk '{print $2}' | tr -d ')' | tr -d '(')
|
||||
+echo $WWID
|
||||
+
|
||||
+grep $WWID /etc/multipath/wwids
|
||||
+
|
||||
+pvcreate $MP_DEV
|
||||
+vgcreate $vg1 $MP_DEV
|
||||
+
|
||||
+not pvs $SD_DEV
|
||||
+pvs $MP_DEV
|
||||
+
|
||||
+# remove mpath dm device then check that SD_DEV is
|
||||
+# filtered based on /etc/multipath/wwids instead of
|
||||
+# based on sysfs holder
|
||||
+multipath -f $MP
|
||||
+sleep 2
|
||||
+not pvs $SD_DEV
|
||||
+multipath $SD_DEV
|
||||
+sleep 2
|
||||
+multipath -l | grep $SD
|
||||
+
|
||||
+#
|
||||
+# Add the wwid to the blacklist, then restart multipath
|
||||
+# so the sd dev should no longer be used by multipath,
|
||||
+# but the sd dev wwid is still in /etc/multipath/wwids.
|
||||
+#
|
||||
+
|
||||
+mkdir /etc/multipath/conf.d/ || true
|
||||
+rm -f /etc/multipath/conf.d/lvmtest.conf
|
||||
+
|
||||
+cat <<EOF > "/etc/multipath/conf.d/lvmtest.conf"
|
||||
+blacklist {
|
||||
+ wwid $WWID
|
||||
+}
|
||||
+EOF
|
||||
+
|
||||
+cat /etc/multipath/conf.d/lvmtest.conf
|
||||
+
|
||||
+multipath -r
|
||||
+sleep 2
|
||||
+
|
||||
+grep $WWID /etc/multipath/wwids
|
||||
+
|
||||
+multipath -l |tee out
|
||||
+not grep $SD out
|
||||
+not grep $MP out
|
||||
+not grep $WWID out
|
||||
+
|
||||
+not pvs $MP_DEV
|
||||
+pvs $SD_DEV
|
||||
+vgs $vg1
|
||||
+
|
||||
+#
|
||||
+# Add the wwid to the blacklist_exceptions, in addition
|
||||
+# to the blacklist, then restart multipath so the
|
||||
+# sd dev should again be used by multipath.
|
||||
+#
|
||||
+
|
||||
+rm -f /etc/multipath/conf.d/lvmtest.conf
|
||||
+
|
||||
+cat <<EOF > "/etc/multipath/conf.d/lvmtest.conf"
|
||||
+blacklist {
|
||||
+wwid $WWID
|
||||
+}
|
||||
+blacklist_exceptions {
|
||||
+wwid $WWID
|
||||
+}
|
||||
+EOF
|
||||
+
|
||||
+cat /etc/multipath/conf.d/lvmtest.conf
|
||||
+
|
||||
+multipath -r
|
||||
+sleep 2
|
||||
+
|
||||
+grep $WWID /etc/multipath/wwids
|
||||
+
|
||||
+multipath -l |tee out
|
||||
+grep $SD out
|
||||
+grep $MP out
|
||||
+grep $WWID out
|
||||
+
|
||||
+pvs $MP_DEV
|
||||
+not pvs $SD_DEV
|
||||
+vgs $vg1
|
||||
+lvs $vg1
|
||||
+
|
||||
+sleep 2
|
||||
+vgremove -ff $vg1
|
||||
+sleep 2
|
||||
+multipath -f $MP
|
||||
+rm /etc/multipath/conf.d/lvmtest.conf
|
||||
+rm /etc/multipath/wwids
|
||||
+sleep 1
|
||||
+rmmod scsi_debug
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
From 85a712e95a5c0127d27ca3bbbe7019d54393cc33 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Fri, 29 Aug 2025 13:43:20 +0200
|
||||
Subject: [PATCH 45/47] tools: pvchange: unlock devices file at the end of cmd
|
||||
processing
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Unlock devices file at the end of cmd processing, after all the PVs are
|
||||
processed, not after the first processed PV.
|
||||
|
||||
Before this patch:
|
||||
|
||||
❯ pvchange -u /dev/sda /dev/sdb
|
||||
Physical volume "/dev/sda" changed
|
||||
WARNING: Devices file unlock no fd.
|
||||
Physical volume "/dev/sdb" changed
|
||||
2 physical volumes changed / 0 physical volumes not changed
|
||||
|
||||
With this patch applied:
|
||||
|
||||
❯ pvchange -u /dev/sda /dev/sdb
|
||||
Physical volume "/dev/sda" changed
|
||||
Physical volume "/dev/sdb" changed
|
||||
2 physical volumes changed / 0 physical volumes not changed
|
||||
|
||||
The lvm_run_command/devices_file_exit/unlock_devices_file will
|
||||
do the unlock at the very end of cmd processing.
|
||||
|
||||
(cherry picked from commit 16d3195a69fbe15d9fad4a16cceec468ea542e5a)
|
||||
---
|
||||
tools/pvchange.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/pvchange.c b/tools/pvchange.c
|
||||
index 339d990ca..d7376c499 100644
|
||||
--- a/tools/pvchange.c
|
||||
+++ b/tools/pvchange.c
|
||||
@@ -194,7 +194,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
|
||||
log_error("Failed to set pvid for devices file.");
|
||||
if (!device_ids_write(cmd))
|
||||
log_warn("Failed to update devices file.");
|
||||
- unlock_devices_file(cmd);
|
||||
+ //unlock_devices_file(cmd);
|
||||
}
|
||||
|
||||
log_print_unless_silent("Physical volume \"%s\" changed", pv_name);
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
From e027f4da9bc7b4ed9b225af75089e3443595bf81 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Mon, 2 May 2022 09:46:28 -0500
|
||||
Subject: [PATCH 46/54] improve description of devices option
|
||||
|
||||
---
|
||||
tools/args.h | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tools/args.h b/tools/args.h
|
||||
index 9a7bf81b2..00a2ec817 100644
|
||||
--- a/tools/args.h
|
||||
+++ b/tools/args.h
|
||||
@@ -235,8 +235,9 @@ arg(deviceidtype_ARG, '\0', "deviceidtype", string_VAL, 0, 0,
|
||||
"then it will override the default type that lvm would use.\n")
|
||||
|
||||
arg(devices_ARG, '\0', "devices", pv_VAL, ARG_GROUPABLE, 0,
|
||||
- "Devices that the command can use. This option can be repeated\n"
|
||||
- "or accepts a comma separated list of devices. This overrides\n"
|
||||
+ "Restricts the devices that are visible and accessible to the command.\n"
|
||||
+ "Devices not listed will appear to be missing. This option can be\n"
|
||||
+ "repeated, or accepts a comma separated list of devices. This overrides\n"
|
||||
"the devices file.\n")
|
||||
|
||||
arg(devicesfile_ARG, '\0', "devicesfile", string_VAL, 0, 0,
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
From dcae883b382f03a58a04d72f6a3bb446e4814ae9 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Fri, 29 Aug 2025 13:50:20 +0200
|
||||
Subject: [PATCH 46/47] tools: pvchange: unlock devices file at the end of cmd
|
||||
processing
|
||||
|
||||
Remove the line, not just comment out.
|
||||
|
||||
(cherry picked from commit d89869f17ec217ee758918047b7edba6c9aa017a)
|
||||
---
|
||||
tools/pvchange.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/tools/pvchange.c b/tools/pvchange.c
|
||||
index d7376c499..1b43b0154 100644
|
||||
--- a/tools/pvchange.c
|
||||
+++ b/tools/pvchange.c
|
||||
@@ -194,7 +194,6 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
|
||||
log_error("Failed to set pvid for devices file.");
|
||||
if (!device_ids_write(cmd))
|
||||
log_warn("Failed to update devices file.");
|
||||
- //unlock_devices_file(cmd);
|
||||
}
|
||||
|
||||
log_print_unless_silent("Physical volume \"%s\" changed", pv_name);
|
||||
--
|
||||
2.51.0
|
||||
|
||||
162
SOURCES/0047-make-generate.patch
Normal file
162
SOURCES/0047-make-generate.patch
Normal file
@ -0,0 +1,162 @@
|
||||
From 3a6c6366c0605fbb7b0001d920da6bd801bff689 Mon Sep 17 00:00:00 2001
|
||||
From: Marian Csontos <mcsontos@redhat.com>
|
||||
Date: Mon, 29 Sep 2025 15:44:24 +0200
|
||||
Subject: [PATCH 47/47] make: generate
|
||||
|
||||
---
|
||||
man/lvchange.8_pregen | 6 +++---
|
||||
man/lvconvert.8_pregen | 8 ++++----
|
||||
man/lvcreate.8_pregen | 10 +++++-----
|
||||
man/lvextend.8_pregen | 2 +-
|
||||
man/lvresize.8_pregen | 2 +-
|
||||
5 files changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/man/lvchange.8_pregen b/man/lvchange.8_pregen
|
||||
index f45d8001c..1e87db1b8 100644
|
||||
--- a/man/lvchange.8_pregen
|
||||
+++ b/man/lvchange.8_pregen
|
||||
@@ -891,7 +891,7 @@ See \fBvgcfgbackup\fP(8) for more information.
|
||||
Specifies when writes to a cache LV should be considered complete.
|
||||
\fBwriteback\fP considers a write complete as soon as it is
|
||||
stored in the cache pool.
|
||||
-\fBwritethough\fP considers a write complete only when it has
|
||||
+\fBwritethrough\fP considers a write complete only when it has
|
||||
been stored in both the cache pool and on the origin LV.
|
||||
While writethrough may be slower for writes, it is more
|
||||
resilient if something should happen to a device associated with the
|
||||
@@ -923,7 +923,7 @@ See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.
|
||||
.TP
|
||||
.O_compression
|
||||
-Controls whether compression is enabled or disable for VDO volume.
|
||||
+Controls whether compression is enabled or disabled for VDO volume.
|
||||
See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.
|
||||
.TP
|
||||
@@ -948,7 +948,7 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.
|
||||
.TP
|
||||
.O_deduplication
|
||||
-Controls whether deduplication is enabled or disable for VDO volume.
|
||||
+Controls whether deduplication is enabled or disabled for VDO volume.
|
||||
See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.
|
||||
.TP
|
||||
diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen
|
||||
index 7ff0d1d79..d5173a651 100644
|
||||
--- a/man/lvconvert.8_pregen
|
||||
+++ b/man/lvconvert.8_pregen
|
||||
@@ -1750,7 +1750,7 @@ Specifies the cache metadata format used by cache target.
|
||||
Specifies when writes to a cache LV should be considered complete.
|
||||
\fBwriteback\fP considers a write complete as soon as it is
|
||||
stored in the cache pool.
|
||||
-\fBwritethough\fP considers a write complete only when it has
|
||||
+\fBwritethrough\fP considers a write complete only when it has
|
||||
been stored in both the cache pool and on the origin LV.
|
||||
While writethrough may be slower for writes, it is more
|
||||
resilient if something should happen to a device associated with the
|
||||
@@ -1807,7 +1807,7 @@ See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.
|
||||
.TP
|
||||
.O_compression
|
||||
-Controls whether compression is enabled or disable for VDO volume.
|
||||
+Controls whether compression is enabled or disabled for VDO volume.
|
||||
See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.
|
||||
.TP
|
||||
@@ -1824,7 +1824,7 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.
|
||||
.TP
|
||||
.O_deduplication
|
||||
-Controls whether deduplication is enabled or disable for VDO volume.
|
||||
+Controls whether deduplication is enabled or disabled for VDO volume.
|
||||
See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.
|
||||
.TP
|
||||
@@ -2009,7 +2009,7 @@ Use VDO type volume for pool data volume.
|
||||
.
|
||||
.TP
|
||||
.O_poolmetadata
|
||||
-The name of a an LV to use for storing pool metadata.
|
||||
+The name of an LV to use for storing pool metadata.
|
||||
.
|
||||
.TP
|
||||
.O_poolmetadatasize
|
||||
diff --git a/man/lvcreate.8_pregen b/man/lvcreate.8_pregen
|
||||
index 5a8c9cc2e..8fc5b34d2 100644
|
||||
--- a/man/lvcreate.8_pregen
|
||||
+++ b/man/lvcreate.8_pregen
|
||||
@@ -633,7 +633,7 @@ Create a striped LV.
|
||||
.P
|
||||
.
|
||||
Create a raid1 or mirror LV.
|
||||
-Implicit type is defined by lvm.conf global/mirror_segfault_default.
|
||||
+Implicit type is defined by lvm.conf global/mirror_segtype_default.
|
||||
.P
|
||||
.B lvcreate
|
||||
.O_mirrors
|
||||
@@ -1575,7 +1575,7 @@ Specifies the cache metadata format used by cache target.
|
||||
Specifies when writes to a cache LV should be considered complete.
|
||||
\fBwriteback\fP considers a write complete as soon as it is
|
||||
stored in the cache pool.
|
||||
-\fBwritethough\fP considers a write complete only when it has
|
||||
+\fBwritethrough\fP considers a write complete only when it has
|
||||
been stored in both the cache pool and on the origin LV.
|
||||
While writethrough may be slower for writes, it is more
|
||||
resilient if something should happen to a device associated with the
|
||||
@@ -1632,7 +1632,7 @@ See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.
|
||||
.TP
|
||||
.O_compression
|
||||
-Controls whether compression is enabled or disable for VDO volume.
|
||||
+Controls whether compression is enabled or disabled for VDO volume.
|
||||
See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.
|
||||
.TP
|
||||
@@ -1657,7 +1657,7 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.
|
||||
.TP
|
||||
.O_deduplication
|
||||
-Controls whether deduplication is enabled or disable for VDO volume.
|
||||
+Controls whether deduplication is enabled or disabled for VDO volume.
|
||||
See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.
|
||||
.TP
|
||||
@@ -1847,7 +1847,7 @@ This is useful for skipping a potentially long and resource intensive initial
|
||||
sync of an empty mirror/raid1/raid4/raid5 and raid10 LV.
|
||||
This option is not valid for raid6, because raid6 relies on proper parity
|
||||
(P and Q Syndromes) being created during initial synchronization in order
|
||||
-to reconstruct proper user date in case of device failures.
|
||||
+to reconstruct proper user data in case of device failures.
|
||||
raid0 and raid0_meta do not provide any data copies or parity support
|
||||
and thus do not support initial synchronization.
|
||||
.
|
||||
diff --git a/man/lvextend.8_pregen b/man/lvextend.8_pregen
|
||||
index e52d46fd4..2729d6eda 100644
|
||||
--- a/man/lvextend.8_pregen
|
||||
+++ b/man/lvextend.8_pregen
|
||||
@@ -713,7 +713,7 @@ This is useful for skipping a potentially long and resource intensive initial
|
||||
sync of an empty mirror/raid1/raid4/raid5 and raid10 LV.
|
||||
This option is not valid for raid6, because raid6 relies on proper parity
|
||||
(P and Q Syndromes) being created during initial synchronization in order
|
||||
-to reconstruct proper user date in case of device failures.
|
||||
+to reconstruct proper user data in case of device failures.
|
||||
raid0 and raid0_meta do not provide any data copies or parity support
|
||||
and thus do not support initial synchronization.
|
||||
.
|
||||
diff --git a/man/lvresize.8_pregen b/man/lvresize.8_pregen
|
||||
index a1f127a1e..8c1ff4dfd 100644
|
||||
--- a/man/lvresize.8_pregen
|
||||
+++ b/man/lvresize.8_pregen
|
||||
@@ -639,7 +639,7 @@ This is useful for skipping a potentially long and resource intensive initial
|
||||
sync of an empty mirror/raid1/raid4/raid5 and raid10 LV.
|
||||
This option is not valid for raid6, because raid6 relies on proper parity
|
||||
(P and Q Syndromes) being created during initial synchronization in order
|
||||
-to reconstruct proper user date in case of device failures.
|
||||
+to reconstruct proper user data in case of device failures.
|
||||
raid0 and raid0_meta do not provide any data copies or parity support
|
||||
and thus do not support initial synchronization.
|
||||
.
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -1,576 +0,0 @@
|
||||
From 9c6954bc61b22ca03df8897d88eb9618e65fc3c6 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Wed, 13 Apr 2022 15:09:08 +0200
|
||||
Subject: [PATCH 47/54] vdo: support --vdosettings
|
||||
|
||||
Allow to use --vdosettings with lvcreate,lvconvert,lvchange.
|
||||
Support settings currenly only configurable via lvm.conf.
|
||||
With lvchange we require inactivate LV for changes to be applied.
|
||||
|
||||
Settings block_map_era_length has supported alias block_map_period.
|
||||
---
|
||||
device_mapper/vdo/target.h | 6 +-
|
||||
man/lvmvdo.7_main | 39 ++++++--
|
||||
test/shell/lvchange-vdo.sh | 8 ++
|
||||
test/shell/lvconvert-vdo.sh | 8 +-
|
||||
test/shell/lvcreate-vdo.sh | 6 +-
|
||||
tools/args.h | 9 ++
|
||||
tools/command-lines.in | 6 +-
|
||||
tools/lvchange.c | 43 ++++++++-
|
||||
tools/lvconvert.c | 9 +-
|
||||
tools/lvcreate.c | 34 ++++---
|
||||
tools/toollib.c | 177 ++++++++++++++++++++++++++++++++++++
|
||||
tools/toollib.h | 6 ++
|
||||
12 files changed, 312 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/device_mapper/vdo/target.h b/device_mapper/vdo/target.h
|
||||
index 51dde3f4d..60c5bff56 100644
|
||||
--- a/device_mapper/vdo/target.h
|
||||
+++ b/device_mapper/vdo/target.h
|
||||
@@ -77,8 +77,10 @@ enum dm_vdo_write_policy {
|
||||
struct dm_vdo_target_params {
|
||||
uint32_t minimum_io_size; // in sectors
|
||||
uint32_t block_map_cache_size_mb;
|
||||
- uint32_t block_map_era_length; // format period
|
||||
-
|
||||
+ union {
|
||||
+ uint32_t block_map_era_length; // format period
|
||||
+ uint32_t block_map_period; // supported alias
|
||||
+ };
|
||||
uint32_t check_point_frequency;
|
||||
uint32_t index_memory_size_mb; // format
|
||||
|
||||
diff --git a/man/lvmvdo.7_main b/man/lvmvdo.7_main
|
||||
index 3b77173c4..14bd640b5 100644
|
||||
--- a/man/lvmvdo.7_main
|
||||
+++ b/man/lvmvdo.7_main
|
||||
@@ -132,6 +132,19 @@ that can keep 100% incompressible data there.
|
||||
# lvconvert --type vdo-pool -n vdo0 -V10G vg/ExistingLV
|
||||
.fi
|
||||
.
|
||||
+.SS \n+[step]. Change the compression and deduplication of a VDOPoolLV
|
||||
+.
|
||||
+Disable or enable the compression and deduplication for VDOPoolLV
|
||||
+(the volume that maintains all VDO LV(s) associated with it).
|
||||
+.P
|
||||
+.B lvchange --compression y|n --deduplication y|n VG/VDOPoolLV
|
||||
+.P
|
||||
+.I Example
|
||||
+.nf
|
||||
+# lvchange --compression n vg/vdopool0
|
||||
+# lvchange --deduplication y vg/vdopool1
|
||||
+.fi
|
||||
+.
|
||||
.SS \n+[step]. Change the default settings used for creating a VDOPoolLV
|
||||
.
|
||||
VDO allows to set a large variety of options. Lots of these settings
|
||||
@@ -173,17 +186,27 @@ EOF
|
||||
# lvcreate --vdo -L10G --config 'allocation/vdo_cpu_threads=4' vg/vdopool1
|
||||
.fi
|
||||
.
|
||||
-.SS \n+[step]. Change the compression and deduplication of a VDOPoolLV
|
||||
-.
|
||||
-Disable or enable the compression and deduplication for VDOPoolLV
|
||||
-(the volume that maintains all VDO LV(s) associated with it).
|
||||
-.P
|
||||
-.B lvchange --compression y|n --deduplication y|n VG/VDOPoolLV
|
||||
+.SS \n+[step]. Set or change VDO settings with option --vdosettings
|
||||
+.
|
||||
+Use the form 'option=value' or 'option1=value option2=value',
|
||||
+or repeat --vdosettings for each option being set.
|
||||
+Options are listed in the Example section above, for the full description see
|
||||
+.BR lvm.conf (5).
|
||||
+Options can omit 'vdo_' and 'vdo_use_' prefixes and all its underscores.
|
||||
+So i.e. vdo_use_metadata_hints=1 and metadatahints=1 are equivalent.
|
||||
+To change the option for an already existing VDOPoolLV use
|
||||
+.BR lvchange (8)
|
||||
+command. However not all option can be changed.
|
||||
+Only compression and deduplication options can be also changed for an active VDO LV.
|
||||
+Lowest priority options are specified with configuration file,
|
||||
+then with --vdosettings and highest are expliction option --compression
|
||||
+and --deduplication.
|
||||
.P
|
||||
.I Example
|
||||
+.P
|
||||
.nf
|
||||
-# lvchange --compression n vg/vdopool0
|
||||
-# lvchange --deduplication y vg/vdopool1
|
||||
+# lvcreate --vdo -L10G --vdosettings 'ack_threads=1 hash_zone_threads=2' vg/vdopool0
|
||||
+# lvchange --vdosettings 'bio_threads=2 deduplication=1' vg/vdopool0
|
||||
.fi
|
||||
.
|
||||
.SS \n+[step]. Checking the usage of VDOPoolLV
|
||||
diff --git a/test/shell/lvchange-vdo.sh b/test/shell/lvchange-vdo.sh
|
||||
index 461b7821f..7cc44d6bc 100644
|
||||
--- a/test/shell/lvchange-vdo.sh
|
||||
+++ b/test/shell/lvchange-vdo.sh
|
||||
@@ -48,9 +48,17 @@ check grep_dmsetup status $vg-vdopool-vpool " online online "
|
||||
lvchange --compression n --deduplication n $vg/vdopool
|
||||
check grep_dmsetup status $vg-vdopool-vpool " offline offline "
|
||||
|
||||
+# --vdosettings needs inactive LV
|
||||
+not lvchange --vdosettings 'ack_threads=8' $vg/vdopool
|
||||
|
||||
lvchange -an $vg/$lv1
|
||||
|
||||
+# With inactive vdo-pool changes are applied
|
||||
+# explicit option --compression has highest priority
|
||||
+lvchange --vdosettings 'ack_threads=5 compression=0' --compression y $vg/vdopool
|
||||
+check lv_field $vg/$lv1 vdo_ack_threads "5"
|
||||
+check lv_field $vg/$lv1 vdo_compression "enabled"
|
||||
+
|
||||
# Test activation
|
||||
lvchange -aly $vg/$lv1
|
||||
check active $vg $lv1
|
||||
diff --git a/test/shell/lvconvert-vdo.sh b/test/shell/lvconvert-vdo.sh
|
||||
index 529f325bd..c42d8f25a 100644
|
||||
--- a/test/shell/lvconvert-vdo.sh
|
||||
+++ b/test/shell/lvconvert-vdo.sh
|
||||
@@ -28,12 +28,12 @@ lvcreate -L5G -n $lv1 $vg
|
||||
not lvconvert --type vdo-pool $vg/$lv1 |& tee out
|
||||
grep "WARNING" out
|
||||
|
||||
-
|
||||
-lvconvert -y --type vdo-pool $vg/$lv1
|
||||
+# Check --vdosettings is also applied to converted vdo-pool
|
||||
+lvconvert -y --type vdo-pool --vdosettings 'ack_threads=5' $vg/$lv1
|
||||
+check lv_field $vg/$lv1 vdo_ack_threads "5"
|
||||
lvremove -f $vg
|
||||
|
||||
-
|
||||
-#
|
||||
+#
|
||||
lvcreate -L5G -n $lv1 $vg
|
||||
lvconvert -y --vdopool $vg/$lv1
|
||||
lvremove -f $vg
|
||||
diff --git a/test/shell/lvcreate-vdo.sh b/test/shell/lvcreate-vdo.sh
|
||||
index 44f8bf094..3e807ac94 100644
|
||||
--- a/test/shell/lvcreate-vdo.sh
|
||||
+++ b/test/shell/lvcreate-vdo.sh
|
||||
@@ -79,8 +79,12 @@ not fsck -n "$DM_DEV_DIR/mapper/$vg-${lv2}"
|
||||
|
||||
lvremove -ff $vg
|
||||
|
||||
+# Unknown settings does not pass
|
||||
+# TODO: try to catch this in parser and 'fail'
|
||||
+not lvcreate --type vdo --vdosettings 'ack_Xthreads=4' -L10G -V1T -ky -n $lv1 $vg
|
||||
|
||||
-lvcreate --type vdo -L10G -V1T -ky -n $lv1 $vg
|
||||
+lvcreate --type vdo --vdosettings 'ack_threads=4' -L10G -V1T -ky -n $lv1 $vg
|
||||
+check lv_field $vg/$lv1 vdo_ack_threads "4"
|
||||
lvs -a $vg
|
||||
lvremove -ff $vg
|
||||
|
||||
diff --git a/tools/args.h b/tools/args.h
|
||||
index 00a2ec817..bfd848ce9 100644
|
||||
--- a/tools/args.h
|
||||
+++ b/tools/args.h
|
||||
@@ -900,6 +900,15 @@ arg(vdopool_ARG, '\0', "vdopool", lv_VAL, 0, 0,
|
||||
"The name of a VDO pool LV.\n"
|
||||
"See \\fBlvmvdo\\fP(7) for more information about VDO usage.\n")
|
||||
|
||||
+arg(vdosettings_ARG, '\0', "vdosettings", string_VAL, ARG_GROUPABLE, 0,
|
||||
+ "Specifies tunable VDO options for VDO LVs.\n"
|
||||
+ "Use the form 'option=value' or 'option1=value option2=value', or\n"
|
||||
+ "repeat --vdosettings for each option being set.\n"
|
||||
+ "These settings override the default VDO behaviors.\n"
|
||||
+ "To remove vdosettings and revert to the default\n"
|
||||
+ "VDO behaviors, use --vdosettings 'default'.\n"
|
||||
+ "See \\fBlvmvdo\\fP(7) for more information.\n")
|
||||
+
|
||||
arg(version_ARG, '\0', "version", 0, 0, 0,
|
||||
"Display version information.\n")
|
||||
|
||||
diff --git a/tools/command-lines.in b/tools/command-lines.in
|
||||
index 00ac08934..08302b34f 100644
|
||||
--- a/tools/command-lines.in
|
||||
+++ b/tools/command-lines.in
|
||||
@@ -243,6 +243,7 @@ OO_LVCHANGE_META: --addtag Tag, --deltag Tag,
|
||||
--setautoactivation Bool, --errorwhenfull Bool, --discards Discards, --zero Bool,
|
||||
--cachemode CacheMode, --cachepolicy String, --cachesettings String,
|
||||
--minrecoveryrate SizeKB, --maxrecoveryrate SizeKB,
|
||||
+--vdosettings String,
|
||||
--writebehind Number, --writemostly WriteMostlyPV, --persistent n
|
||||
|
||||
# It's unfortunate that activate needs to be optionally allowed here;
|
||||
@@ -341,7 +342,8 @@ OO_LVCONVERT_CACHE: --cachemetadataformat CacheMetadataFormat,
|
||||
--cachesettings String, --zero Bool
|
||||
|
||||
OO_LVCONVERT_VDO: --metadataprofile String, --readahead Readahead,
|
||||
---compression Bool, --deduplication Bool, --zero Bool
|
||||
+--compression Bool, --deduplication Bool, --vdosettings String,
|
||||
+--zero Bool
|
||||
|
||||
OO_LVCONVERT: --alloc Alloc, --background, --force, --noudevsync
|
||||
|
||||
@@ -839,7 +841,7 @@ OO_LVCREATE_POOL: --poolmetadatasize SizeMB, --poolmetadataspare Bool, --chunksi
|
||||
|
||||
OO_LVCREATE_THINPOOL: --discards Discards, --errorwhenfull Bool
|
||||
|
||||
-OO_LVCREATE_VDO: --compression Bool, --deduplication Bool
|
||||
+OO_LVCREATE_VDO: --compression Bool, --deduplication Bool, --vdosettings String
|
||||
---
|
||||
|
||||
lvcreate --type error --size SizeMB VG
|
||||
diff --git a/tools/lvchange.c b/tools/lvchange.c
|
||||
index 0525bc53c..dc51786d7 100644
|
||||
--- a/tools/lvchange.c
|
||||
+++ b/tools/lvchange.c
|
||||
@@ -755,6 +755,43 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
+static int _lvchange_vdo(struct cmd_context *cmd,
|
||||
+ struct logical_volume *lv,
|
||||
+ uint32_t *mr)
|
||||
+{
|
||||
+ struct lv_segment *seg;
|
||||
+ int updated = 0;
|
||||
+
|
||||
+ seg = first_seg(lv);
|
||||
+
|
||||
+ // With VDO LV given flip to VDO pool
|
||||
+ if (seg_is_vdo(seg))
|
||||
+ seg = first_seg(seg_lv(seg, 0));
|
||||
+
|
||||
+ if (!get_vdo_settings(cmd, &seg->vdo_params, &updated))
|
||||
+ return_0;
|
||||
+
|
||||
+ if ((updated & VDO_CHANGE_OFFLINE) &&
|
||||
+ lv_info(cmd, seg->lv, 1, NULL, 0, 0)) {
|
||||
+ log_error("Cannot change VDO settings for active VDO pool %s.",
|
||||
+ display_lvname(seg->lv));
|
||||
+ // TODO maybe add --force support with prompt here
|
||||
+ log_print_unless_silent("VDO pool %s with all its LVs needs to be deactivated.",
|
||||
+ display_lvname(seg->lv));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (updated) {
|
||||
+ if (!dm_vdo_validate_target_params(&seg->vdo_params, 0 /* vdo_size */))
|
||||
+ return_0;
|
||||
+
|
||||
+ /* Request caller to commit and reload metadata */
|
||||
+ *mr |= MR_RELOAD;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int _lvchange_tag(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int arg, uint32_t *mr)
|
||||
{
|
||||
@@ -1154,6 +1191,7 @@ static int _option_requires_direct_commit(int opt_enum)
|
||||
cachemode_ARG,
|
||||
cachepolicy_ARG,
|
||||
cachesettings_ARG,
|
||||
+ vdosettings_ARG,
|
||||
-1
|
||||
};
|
||||
|
||||
@@ -1354,7 +1392,10 @@ static int _lvchange_properties_single(struct cmd_context *cmd,
|
||||
docmds++;
|
||||
doit += _lvchange_cache(cmd, lv, &mr);
|
||||
break;
|
||||
-
|
||||
+ case vdosettings_ARG:
|
||||
+ docmds++;
|
||||
+ doit += _lvchange_vdo(cmd, lv, &mr);
|
||||
+ break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "Failed to check for option %s",
|
||||
arg_long_option_name(i));
|
||||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
|
||||
index a90946173..3d4b24fe3 100644
|
||||
--- a/tools/lvconvert.c
|
||||
+++ b/tools/lvconvert.c
|
||||
@@ -5456,13 +5456,8 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
|
||||
if (!fill_vdo_target_params(cmd, &vdo_params, &vdo_pool_header_size, vg->profile))
|
||||
goto_out;
|
||||
|
||||
- if (arg_is_set(cmd, compression_ARG))
|
||||
- vdo_params.use_compression =
|
||||
- arg_int_value(cmd, compression_ARG, 0);
|
||||
-
|
||||
- if (arg_is_set(cmd, deduplication_ARG))
|
||||
- vdo_params.use_deduplication =
|
||||
- arg_int_value(cmd, deduplication_ARG, 0);
|
||||
+ if (!get_vdo_settings(cmd, &vdo_params, NULL))
|
||||
+ return_0;
|
||||
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
log_error("Cannot activate %s.", display_lvname(lv));
|
||||
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
|
||||
index 79af42685..8de6f3408 100644
|
||||
--- a/tools/lvcreate.c
|
||||
+++ b/tools/lvcreate.c
|
||||
@@ -698,6 +698,23 @@ static int _read_cache_params(struct cmd_context *cmd,
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int _read_vdo_params(struct cmd_context *cmd,
|
||||
+ struct lvcreate_params *lp)
|
||||
+{
|
||||
+ if (!seg_is_vdo(lp))
|
||||
+ return 1;
|
||||
+
|
||||
+ // prefiling settings here
|
||||
+ if (!fill_vdo_target_params(cmd, &lp->vdo_params, &lp->vdo_pool_header_size, NULL))
|
||||
+ return_0;
|
||||
+
|
||||
+ // override with optional vdo settings
|
||||
+ if (!get_vdo_settings(cmd, &lp->vdo_params, NULL))
|
||||
+ return_0;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int _read_activation_params(struct cmd_context *cmd,
|
||||
struct volume_group *vg,
|
||||
struct lvcreate_params *lp)
|
||||
@@ -888,7 +905,8 @@ static int _lvcreate_params(struct cmd_context *cmd,
|
||||
#define VDO_POOL_ARGS \
|
||||
vdopool_ARG,\
|
||||
compression_ARG,\
|
||||
- deduplication_ARG
|
||||
+ deduplication_ARG,\
|
||||
+ vdosettings_ARG
|
||||
|
||||
/* Cache and cache-pool segment type */
|
||||
if (seg_is_cache(lp)) {
|
||||
@@ -1098,19 +1116,6 @@ static int _lvcreate_params(struct cmd_context *cmd,
|
||||
zero_ARG,
|
||||
-1))
|
||||
return_0;
|
||||
-
|
||||
- // FIXME: prefiling here - this is wrong place
|
||||
- // but will work for this moment
|
||||
- if (!fill_vdo_target_params(cmd, &lp->vdo_params, &lp->vdo_pool_header_size, NULL))
|
||||
- return_0;
|
||||
-
|
||||
- if (arg_is_set(cmd, compression_ARG))
|
||||
- lp->vdo_params.use_compression =
|
||||
- arg_int_value(cmd, compression_ARG, 0);
|
||||
-
|
||||
- if (arg_is_set(cmd, deduplication_ARG))
|
||||
- lp->vdo_params.use_deduplication =
|
||||
- arg_int_value(cmd, deduplication_ARG, 0);
|
||||
}
|
||||
|
||||
/* Check options shared between more segment types */
|
||||
@@ -1198,6 +1203,7 @@ static int _lvcreate_params(struct cmd_context *cmd,
|
||||
&lp->pool_metadata_size, &lp->pool_metadata_spare,
|
||||
&lp->chunk_size, &lp->discards, &lp->zero_new_blocks)) ||
|
||||
!_read_cache_params(cmd, lp) ||
|
||||
+ !_read_vdo_params(cmd, lp) ||
|
||||
!_read_mirror_and_raid_params(cmd, lp))
|
||||
return_0;
|
||||
|
||||
diff --git a/tools/toollib.c b/tools/toollib.c
|
||||
index 16be336d4..697baee82 100644
|
||||
--- a/tools/toollib.c
|
||||
+++ b/tools/toollib.c
|
||||
@@ -1192,6 +1192,183 @@ out:
|
||||
return ok;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Compare VDO option name, skip any '_' in name
|
||||
+ * and also allow to use it without vdo_[use_] prefix
|
||||
+ */
|
||||
+static int _compare_vdo_option(const char *b1, const char *b2)
|
||||
+{
|
||||
+ if (strncasecmp(b1, "vdo", 3) == 0) // skip vdo prefix
|
||||
+ b1 += 3;
|
||||
+
|
||||
+ if ((tolower(*b1) != tolower(*b2)) &&
|
||||
+ (strncmp(b2, "use_", 4) == 0))
|
||||
+ b2 += 4; // try again with skipped prefix 'use_'
|
||||
+
|
||||
+ while (*b1 && *b2) {
|
||||
+ if (tolower(*b1) == tolower(*b2)) {
|
||||
+ ++b1;
|
||||
+ ++b2;
|
||||
+ continue; // matching char
|
||||
+ }
|
||||
+
|
||||
+ if (*b1 == '_')
|
||||
+ ++b1; // skip to next char
|
||||
+ else if (*b2 == '_')
|
||||
+ ++b2; // skip to next char
|
||||
+ else
|
||||
+ break; // mismatch
|
||||
+ }
|
||||
+
|
||||
+ return (*b1 || *b2) ? 0 : 1;
|
||||
+}
|
||||
+
|
||||
+#define CHECK_AND_SET(var, onoff) \
|
||||
+ option = #var;\
|
||||
+ if (_compare_vdo_option(cn->key, option)) {\
|
||||
+ if (is_lvchange || !cn->v || (cn->v->type != DM_CFG_INT))\
|
||||
+ goto err;\
|
||||
+ if (vtp->var != cn->v->v.i) {\
|
||||
+ vtp->var = cn->v->v.i;\
|
||||
+ u |= onoff;\
|
||||
+ }\
|
||||
+ continue;\
|
||||
+ }
|
||||
+
|
||||
+#define DO_OFFLINE(var) \
|
||||
+ CHECK_AND_SET(var, VDO_CHANGE_OFFLINE)
|
||||
+
|
||||
+#define DO_ONLINE(var) \
|
||||
+ CHECK_AND_SET(var, VDO_CHANGE_ONLINE)
|
||||
+
|
||||
+int get_vdo_settings(struct cmd_context *cmd,
|
||||
+ struct dm_vdo_target_params *vtp,
|
||||
+ int *updated)
|
||||
+{
|
||||
+ const char *str, *option = NULL;
|
||||
+ struct arg_value_group_list *group;
|
||||
+ struct dm_config_tree *result = NULL, *prev = NULL, *current = NULL;
|
||||
+ struct dm_config_node *cn;
|
||||
+ int r = 0, u = 0, is_lvchange;
|
||||
+ int use_compression = vtp->use_compression;
|
||||
+ int use_deduplication = vtp->use_deduplication;
|
||||
+ int checked_lvchange;
|
||||
+
|
||||
+ if (updated)
|
||||
+ *updated = 0;
|
||||
+
|
||||
+ // Group all --vdosettings
|
||||
+ dm_list_iterate_items(group, &cmd->arg_value_groups) {
|
||||
+ if (!grouped_arg_is_set(group->arg_values, vdosettings_ARG))
|
||||
+ continue;
|
||||
+
|
||||
+ if (!(current = dm_config_create()))
|
||||
+ goto_out;
|
||||
+ if (prev)
|
||||
+ current->cascade = prev;
|
||||
+ prev = current;
|
||||
+
|
||||
+ if (!(str = grouped_arg_str_value(group->arg_values,
|
||||
+ vdosettings_ARG,
|
||||
+ NULL)))
|
||||
+ goto_out;
|
||||
+
|
||||
+ if (!dm_config_parse_without_dup_node_check(current, str, str + strlen(str)))
|
||||
+ goto_out;
|
||||
+ }
|
||||
+
|
||||
+ if (current) {
|
||||
+ if (!(result = dm_config_flatten(current)))
|
||||
+ goto_out;
|
||||
+
|
||||
+ checked_lvchange = !strcmp(cmd->name, "lvchange");
|
||||
+
|
||||
+ /* Use all acceptable VDO options */
|
||||
+ for (cn = result->root; cn; cn = cn->sib) {
|
||||
+ is_lvchange = 0;
|
||||
+ DO_OFFLINE(ack_threads);
|
||||
+ DO_OFFLINE(bio_rotation);
|
||||
+ DO_OFFLINE(bio_threads);
|
||||
+ DO_OFFLINE(block_map_cache_size_mb);
|
||||
+ DO_OFFLINE(block_map_era_length);
|
||||
+ DO_OFFLINE(block_map_period); // alias for block_map_era_length
|
||||
+ DO_OFFLINE(cpu_threads);
|
||||
+ DO_OFFLINE(hash_zone_threads);
|
||||
+ DO_OFFLINE(logical_threads);
|
||||
+ DO_OFFLINE(max_discard);
|
||||
+ DO_OFFLINE(physical_threads);
|
||||
+
|
||||
+ // Support also these - even when we have regular opts for them
|
||||
+ DO_ONLINE(use_compression);
|
||||
+ DO_ONLINE(use_deduplication);
|
||||
+
|
||||
+ // Settings bellow cannot be changed with lvchange command
|
||||
+ is_lvchange = checked_lvchange;
|
||||
+
|
||||
+ DO_OFFLINE(check_point_frequency);
|
||||
+ DO_OFFLINE(index_memory_size_mb);
|
||||
+ DO_OFFLINE(minimum_io_size);
|
||||
+ DO_OFFLINE(slab_size_mb);
|
||||
+ DO_OFFLINE(use_metadata_hints);
|
||||
+ DO_OFFLINE(use_sparse_index);
|
||||
+
|
||||
+ option = "write_policy";
|
||||
+ if (_compare_vdo_option(cn->key, option)) {
|
||||
+ if (is_lvchange || !cn->v || (cn->v->type != DM_CFG_STRING))
|
||||
+ goto err;
|
||||
+ if (!set_vdo_write_policy(&vtp->write_policy, cn->v->v.str))
|
||||
+ goto_out;
|
||||
+ u |= VDO_CHANGE_OFFLINE;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ log_error("Unknown VDO setting \"%s\".", cn->key);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (arg_is_set(cmd, compression_ARG)) {
|
||||
+ vtp->use_compression = arg_int_value(cmd, compression_ARG, 0);
|
||||
+ if (vtp->use_compression != use_compression)
|
||||
+ u |= VDO_CHANGE_ONLINE;
|
||||
+ }
|
||||
+
|
||||
+ if (arg_is_set(cmd, deduplication_ARG)) {
|
||||
+ vtp->use_deduplication = arg_int_value(cmd, deduplication_ARG, 0);
|
||||
+ if (vtp->use_deduplication != use_deduplication)
|
||||
+ u |= VDO_CHANGE_ONLINE;
|
||||
+ }
|
||||
+
|
||||
+ if (updated) {
|
||||
+ // validation of updated VDO option
|
||||
+ if (!dm_vdo_validate_target_params(vtp, 0 /* vdo_size */)) {
|
||||
+err:
|
||||
+ if (is_lvchange)
|
||||
+ log_error("Cannot change VDO setting \"vdo_%s\" in existing VDO pool.",
|
||||
+ option);
|
||||
+ else
|
||||
+ log_error("Invalid argument for VDO setting \"vdo_%s\".",
|
||||
+ option);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ *updated = u;
|
||||
+ }
|
||||
+
|
||||
+ r = 1;
|
||||
+out:
|
||||
+ if (result)
|
||||
+ dm_config_destroy(result);
|
||||
+
|
||||
+ while (prev) {
|
||||
+ current = prev->cascade;
|
||||
+ dm_config_destroy(prev);
|
||||
+ prev = current;
|
||||
+ }
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
static int _get_one_writecache_setting(struct cmd_context *cmd, struct writecache_settings *settings,
|
||||
char *key, char *val, uint32_t *block_size_sectors)
|
||||
{
|
||||
diff --git a/tools/toollib.h b/tools/toollib.h
|
||||
index f3a60fbc4..2b38e4e4f 100644
|
||||
--- a/tools/toollib.h
|
||||
+++ b/tools/toollib.h
|
||||
@@ -217,6 +217,12 @@ int get_cache_params(struct cmd_context *cmd,
|
||||
const char **name,
|
||||
struct dm_config_tree **settings);
|
||||
|
||||
+#define VDO_CHANGE_ONLINE 1
|
||||
+#define VDO_CHANGE_OFFLINE 2
|
||||
+int get_vdo_settings(struct cmd_context *cmd,
|
||||
+ struct dm_vdo_target_params *vtp,
|
||||
+ int *updated);
|
||||
+
|
||||
int get_writecache_settings(struct cmd_context *cmd, struct writecache_settings *settings,
|
||||
uint32_t *block_size_sectors);
|
||||
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
From 52efa6f5a1a5a9057130d0b3c8acfdb8feff2e22 Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Mon, 27 Oct 2025 11:01:16 -0500
|
||||
Subject: [PATCH] activating raid LV with partial snapshot is an error
|
||||
|
||||
Detect and report this error early in the command, with
|
||||
a clear message, including a possible remedy. Previously,
|
||||
the command failed at a lower level, where the message is
|
||||
confusing or even misleading.
|
||||
|
||||
Old error message:
|
||||
"Aborting. LV vg/snap1 is incomplete and --activationmode partial was not specified."
|
||||
|
||||
New error message:
|
||||
"Activating raid LV vg/main requires the removal of partial snapshot vg/snap1."
|
||||
|
||||
(cherry picked from commit 2760e804630a36bab2c3938ce9ac0b08c5e75395)
|
||||
---
|
||||
tools/toollib.c | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/tools/toollib.c b/tools/toollib.c
|
||||
index a7384dd60..b9fa67446 100644
|
||||
--- a/tools/toollib.c
|
||||
+++ b/tools/toollib.c
|
||||
@@ -781,6 +781,19 @@ int lv_change_activate(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (lv_is_raid(lv) && lv_is_origin(lv) && lv_is_partial(lv)) {
|
||||
+ struct lv_list *lvl;
|
||||
+ dm_list_iterate_items(lvl, &lv->vg->lvs) {
|
||||
+ if (lv_is_cow(lvl->lv) &&
|
||||
+ (lv_origin_lv(lvl->lv) == lv) &&
|
||||
+ lv_is_partial(lvl->lv)) {
|
||||
+ log_error("Activating raid LV %s requires the removal of partial snapshot %s.",
|
||||
+ display_lvname(lv), display_lvname(lvl->lv));
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (is_change_activating(activate) &&
|
||||
lvmcache_has_duplicate_devs() &&
|
||||
vg_has_duplicate_pvs(lv->vg) &&
|
||||
--
|
||||
2.51.1
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
From 45a2ccfa3bdf4c5b3f8b9e0cc5330fca345b0d26 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Rajnoha <prajnoha@redhat.com>
|
||||
Date: Thu, 5 May 2022 11:02:32 +0200
|
||||
Subject: [PATCH 48/54] toollib: fix segfault when handling selection with
|
||||
historical LVs
|
||||
|
||||
When processing historical LVs inside process_each_lv_in_vg for
|
||||
selection, we need to use dummy "_historical_lv" for select_match_lv.
|
||||
|
||||
This is because a historical LV is not an actual LV, but only a tiny
|
||||
representation with subset of original properties that we recorded
|
||||
(name, uuid...).
|
||||
|
||||
To use the same processing functions we use for full-fledged non-historical
|
||||
LVs, we need to use the prefilled "_historical_lv" structure which has all
|
||||
the other missing properties hard-coded.
|
||||
---
|
||||
tools/toollib.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tools/toollib.c b/tools/toollib.c
|
||||
index 697baee82..01ba03658 100644
|
||||
--- a/tools/toollib.c
|
||||
+++ b/tools/toollib.c
|
||||
@@ -3392,13 +3392,14 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
process_lv = 1;
|
||||
}
|
||||
|
||||
- process_lv = process_lv && select_match_lv(cmd, handle, vg, lvl->lv) && _select_matches(handle);
|
||||
+ _historical_lv.this_glv = glvl->glv;
|
||||
+ _historical_lv.name = glvl->glv->historical->name;
|
||||
+
|
||||
+ process_lv = process_lv && select_match_lv(cmd, handle, vg, &_historical_lv) && _select_matches(handle);
|
||||
|
||||
if (!process_lv)
|
||||
continue;
|
||||
|
||||
- _historical_lv.this_glv = glvl->glv;
|
||||
- _historical_lv.name = glvl->glv->historical->name;
|
||||
log_very_verbose("Processing historical LV %s in VG %s.", glvl->glv->historical->name, vg->name);
|
||||
|
||||
ret = process_single_lv(cmd, &_historical_lv, handle);
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
From eda98e4b9418568d6793d2c853aaa54db051cc9f Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Fri, 27 May 2022 12:38:43 -0500
|
||||
Subject: [PATCH 49/54] devices file: move clean up after command is run
|
||||
|
||||
devices_file_exit wasn't being called between lvm_shell
|
||||
commands, so the file lock wouldn't be released.
|
||||
---
|
||||
lib/commands/toolcontext.c | 1 -
|
||||
tools/lvmcmdline.c | 1 +
|
||||
2 files changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
|
||||
index a0c78ddd6..7db5e11a1 100644
|
||||
--- a/lib/commands/toolcontext.c
|
||||
+++ b/lib/commands/toolcontext.c
|
||||
@@ -1912,7 +1912,6 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(cmd, &cmd->formats);
|
||||
|
||||
- devices_file_exit(cmd);
|
||||
if (!dev_cache_exit())
|
||||
stack;
|
||||
_destroy_dev_types(cmd);
|
||||
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
|
||||
index 1727ba089..eb63fd9b5 100644
|
||||
--- a/tools/lvmcmdline.c
|
||||
+++ b/tools/lvmcmdline.c
|
||||
@@ -3306,6 +3306,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
|
||||
hints_exit(cmd);
|
||||
lvmcache_destroy(cmd, 1, 1);
|
||||
label_scan_destroy(cmd);
|
||||
+ devices_file_exit(cmd);
|
||||
|
||||
if ((config_string_cft = remove_config_tree_by_source(cmd, CONFIG_STRING)))
|
||||
dm_config_destroy(config_string_cft);
|
||||
--
|
||||
2.34.3
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
From a71342640ddf81b73625e55149f1077245ee7412 Mon Sep 17 00:00:00 2001
|
||||
From: Heinz Mauelshagen <heinzm@redhat.com>
|
||||
Date: Mon, 27 Oct 2025 17:37:09 +0100
|
||||
Subject: [PATCH 49/51] lv_manip: show a warning during classic snapshot
|
||||
creation on a RaidLV.
|
||||
|
||||
The RaidLV will fail to activate in case of the loss of any of its snapshots.
|
||||
Once created, commit 2760e804630a36bab2c3938ce9ac0b08c5e75395 will
|
||||
catch any loss of such snapshots and provide remedy information.
|
||||
|
||||
(cherry picked from commit ae81b41811ede78b77f6badf0c65c88fa56cc951)
|
||||
---
|
||||
lib/metadata/lv_manip.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
|
||||
index 577ffd0b3..e7405f1dc 100644
|
||||
--- a/lib/metadata/lv_manip.c
|
||||
+++ b/lib/metadata/lv_manip.c
|
||||
@@ -9654,6 +9654,11 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
goto revert_new_lv;
|
||||
}
|
||||
|
||||
+ if (lp->snapshot && origin_lv && lv_is_raid(origin_lv)) {
|
||||
+ log_warn("WARNING: Loss of snapshot %s will cause the activation of the %s LV %s to fail!",
|
||||
+ lp->lv_name, lvseg_name(first_seg(origin_lv)), display_lvname(origin_lv));
|
||||
+ }
|
||||
+
|
||||
/* Do not scan this LV until properly zeroed/wiped. */
|
||||
if (_should_wipe_lv(lp, lv, 0))
|
||||
lv->status |= LV_NOSCAN;
|
||||
--
|
||||
2.51.1
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
From bf0b3962088fb18f4a2aba00f38955e1fc6e31fe Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@redhat.com>
|
||||
Date: Fri, 27 May 2022 14:27:03 -0500
|
||||
Subject: [PATCH 50/54] devices file: fail if --devicesfile filename doesn't
|
||||
exist
|
||||
|
||||
A typo of the filename after --devicesfile should result in a
|
||||
command error rather than the command falling back to using no
|
||||
devices file at all. Exception is vgcreate|pvcreate which
|
||||
create a new devices file if the file name doesn't exist.
|
||||
---
|
||||
lib/device/dev-cache.c | 9 +++++++++
|
||||
test/shell/devicesfile-basic.sh | 4 ++++
|
||||
2 files changed, 13 insertions(+)
|
||||
|
||||
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
|
||||
index b0759b06c..0eb2568b5 100644
|
||||
--- a/lib/device/dev-cache.c
|
||||
+++ b/lib/device/dev-cache.c
|
||||
@@ -1882,6 +1882,15 @@ static int _setup_devices(struct cmd_context *cmd, int no_file_match)
|
||||
|
||||
file_exists = devices_file_exists(cmd);
|
||||
|
||||
+ /*
|
||||
+ * Fail if user specifies a file name that doesn't exist and
|
||||
+ * the command is not creating a new devices file.
|
||||
+ */
|
||||
+ if (!file_exists && !cmd->create_edit_devices_file && cmd->devicesfile && strlen(cmd->devicesfile)) {
|
||||
+ log_error("Devices file not found: %s", cmd->devices_file_path);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Removing the devices file is another way of disabling the use of
|
||||
* a devices file, unless the command creates the devices file.
|
||||
diff --git a/test/shell/devicesfile-basic.sh b/test/shell/devicesfile-basic.sh
|
||||
index 7ba9e2c7f..d1cfb6a35 100644
|
||||
--- a/test/shell/devicesfile-basic.sh
|
||||
+++ b/test/shell/devicesfile-basic.sh
|
||||
@@ -104,6 +104,10 @@ not ls "$DFDIR/system.devices"
|
||||
vgs --devicesfile test.devices $vg1
|
||||
not vgs --devicesfile test.devices $vg2
|
||||
|
||||
+# misspelled override name fails
|
||||
+not vgs --devicesfile doesnotexist $vg1
|
||||
+not vgs --devicesfile doesnotexist $vg2
|
||||
+
|
||||
# devicesfile and devices cannot be used together
|
||||
not vgs --devicesfile test.devices --devices "$dev1","$dev1" $vg1
|
||||
|
||||
--
|
||||
2.34.3
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user