1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-27 05:44:18 +03:00

Compare commits

..

3 Commits

Author SHA1 Message Date
David Teigland
cc0fb42015 tests: add udev-pvscan-vgchange
uses real devices, tests udev rule and systemd unit
2021-04-07 17:19:51 -05:00
David Teigland
2ed8f23ae3 add pvscan-udev-initrd.sh
pvscan wrapper for use in the initrd lvm udev rule.
Finds the intersection of complete VG/LVs reported
by pvscan, and the VG/LVs specified on boot cmdline.
The resulting VG or LVs are printed as env-vars that
the udev rule can IMPORT, and pass to vgchange/lvchange.
2021-04-01 13:17:07 -05:00
David Teigland
84607d93b6 new udev and systemd autoactivation
new udev rule: 69-dm-lvm.rules

. calls pvscan directly on the added device
. pvscan output indicates if a complete VG can be
  activated
. the complete VG name to activate is set in env var
  LVM_VG_NAME_COMPLETE
. this replaces 69-dm-lvm-meta.rules

new unit file: lvm-vgchange@.service

. udev rule above starts this using systemctl start
  if LVM_VG_NAME_COMPLETE is set
. the service runs vgchange -aay on the vg
. this replaces lvm2-pvscan@.service
2021-04-01 09:28:31 -05:00
8 changed files with 293 additions and 7 deletions

View File

@@ -1935,6 +1935,7 @@ libdm/libdevmapper.pc
man/Makefile
po/Makefile
scripts/lvm2-pvscan.service
scripts/lvm-vgchange.service
scripts/blkdeactivate.sh
scripts/blk_availability_init_red_hat
scripts/blk_availability_systemd_red_hat.service

View File

@@ -88,7 +88,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
$(Q) $(INSTALL_DATA) lvm-vgchange.service $(systemd_unit_dir)/lvm-vgchange@.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
@@ -139,6 +139,7 @@ DISTCLEAN_TARGETS += \
dm_event_systemd_red_hat.socket \
lvmdump.sh \
lvm2-pvscan.service \
lvm-vgchange.service \
lvm2_cluster_activation_red_hat.sh \
lvm2_cluster_activation_systemd_red_hat.service \
lvm2_clvmd_systemd_red_hat.service \

View File

@@ -9,4 +9,4 @@ Conflicts=shutdown.target
[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=@SBINDIR@/lvm vgchange -aay %i
ExecStart=@SBINDIR@/lvm vgchange -aay --config log/prefix=\"\" %i

View File

@@ -300,6 +300,9 @@ if (( sysreport )); then
for unit in $("$GREP" lvm2-pvscan "$sysreport_dir/systemd_unit_list" | cut -d " " -f 1); do
log "$SYSTEMCTL status -l --no-pager -n $log_lines -o short-precise $unit >> \"$sysreport_dir/systemd_lvm2_pvscan_service_status\""
done
for unit in $("$GREP" lvm-vgchange "$sysreport_dir/systemd_unit_list" | cut -d " " -f 1); do
log "$SYSTEMCTL status -l --no-pager -n $log_lines -o short-precise $unit >> \"$sysreport_dir/systemd_lvm_vgchange_service_status\""
done
fi
fi

View File

@@ -0,0 +1,221 @@
#!/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'
. lib/inittest
#
# To use this test, add two or more devices with real device ids,
# e.g. wwids, to a file, e.g.
# $ 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
}
wipe_all
touch $DF
for dev in "${REAL_DEVICES[@]}"; do
pvcreate $dev
done
test $num_devs -gt 2 || skip
# 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}')
BDEV1=$(basename "$dev1")
_clear_online_files
udevadm trigger --settle -c add /sys/block/$BDEV1
ls "$RUNDIR/lvm/pvs_online/$PVID1"
ls "$RUNDIR/lvm/vgs_online/$vg1"
systemctl status lvm-vgchange@$vg1 | tee out || true
grep Started 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}')
BDEV1=$(basename "$dev1")
BDEV2=$(basename "$dev2")
_clear_online_files
udevadm trigger --settle -c add /sys/block/$BDEV1
ls "$RUNDIR/lvm/pvs_online/$PVID1"
not ls "$RUNDIR/lvm/vgs_online/$vg2"
systemctl status lvm-vgchange@$vg2 | tee out || true
not grep Started 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"
systemctl status lvm-vgchange@$vg2 | tee out || true
grep Started 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}')
BDEV1=$(basename "$dev1")
BDEV2=$(basename "$dev2")
BDEV3=$(basename "$dev3")
_clear_online_files
udevadm trigger -c add /sys/block/$BDEV1 &
udevadm trigger -c add /sys/block/$BDEV2 &
udevadm trigger -c add /sys/block/$BDEV3
sleep 5
aux udev_wait
ls "$RUNDIR/lvm/pvs_online/$PVID1"
ls "$RUNDIR/lvm/pvs_online/$PVID2"
ls "$RUNDIR/lvm/pvs_online/$PVID3"
ls "$RUNDIR/lvm/vgs_online/$vg3"
systemctl status lvm-vgchange@$vg3 | tee out || true
grep Started 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}')
BDEV1=$(basename "$dev1")
BDEV2=$(basename "$dev2")
BDEV3=$(basename "$dev3")
_clear_online_files
udevadm trigger -c add /sys/block/$BDEV1 &
udevadm trigger -c add /sys/block/$BDEV2 &
udevadm trigger -c add /sys/block/$BDEV3
sleep 5
aux udev_wait
ls "$RUNDIR/lvm/pvs_online/$PVID1"
ls "$RUNDIR/lvm/pvs_online/$PVID2"
ls "$RUNDIR/lvm/pvs_online/$PVID3"
ls "$RUNDIR/lvm/vgs_online/$vg4"
systemctl status lvm-vgchange@$vg4 | tee out || true
grep Started 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

View File

@@ -1,13 +1,12 @@
# Copyright (C) 2012,2021 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
# Udev rules for LVM.
# 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"
@@ -69,8 +68,12 @@ ENV{SYSTEMD_READY}="1"
# 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.
IMPORT{program}="/usr/sbin/lvm pvscan --cache --listvg --checkcomplete --vgonline --udevoutput --journal=output $env{DEVNAME}"
IMPORT{program}="(LVM_EXEC)/lvm pvscan --cache --listvg --checkcomplete --vgonline --udevoutput --journal=output $env{DEVNAME}"
ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/usr/bin/systemctl start lvm-vgchange@$env{LVM_VG_NAME_COMPLETE}.service"
GOTO="lvm_end"

View File

@@ -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-metad.rules
LVM_RULES=11-dm-lvm.rules 69-dm-lvm.rules
DM_DIR=$(shell $(GREP) "\#define DM_DIR" $(top_srcdir)/libdm/misc/dm-ioctl.h | $(AWK) '{print $$3}')

View File

@@ -0,0 +1,57 @@
# pvscan wrapper called by initrd lvm udev rule to find the
# intersection of complete VGs/LVs found by pvscan and the
# requested VGs/LVs from the cmdline.
#
# Used in 64-lvm.rules as:
# IMPORT{program}="pvscan-udev-initrd.sh $env{DEVNAME}"
#
# See /usr/lib/dracut/modules.d/90lvm/64-lvm.rules
#!/bin/sh
dev=$1
type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh
VGS=$(getargs rd.lvm.vg -d rd_LVM_VG=)
LVS=$(getargs rd.lvm.lv -d rd_LVM_LV=)
IFS=' '
# pvscan will produce a single VG line, and one or more LV lines.
# VG <name> complete
# VG <name> incomplete
# LV <name> complete
# LV <name> incomplete
#
# LV names are printed as vgname/lvname.
# We only care about the complete items.
# Each pvscan will produce a single VG line,
# and may produce zero, one or more LV lines.
PVSCAN=$(/usr/sbin/lvm pvscan --cache --listlvs --checkcomplete --journal output --config 'global/event_activation=1' $dev)
read -r -a VGSARRAY <<< "$VGS"
for VG in "${VGSARRAY[@]}"
do
if strstr "$PVSCAN" "VG $VG complete" ; then
echo LVM_VG_NAME_COMPLETE=\'"$VG"\'
fi
done
# Combine all matching LVs into a single print containing them all,
# e.g. LVM_LV_NAMES_COMPLETE='vg/lv1 vg/lv2'
read -r -a LVSARRAY <<< "$LVS"
echo -n LVM_LV_NAMES_COMPLETE=\'
for LV in "${LVSARRAY[@]}"
do
if strstr "$PVSCAN" "LV $LV complete" ; then
echo -n "$LV "
fi
done
echo \'