From ded4448ba98305b6f0c58cdd67a8b0de9a3db0d3 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 8 Dec 2021 15:16:03 -0600 Subject: [PATCH] feat(lvm): use generated filter when none is set Previously, the lvm device filter generated by dracut would not be used if any lvm.conf file existed in the initrd. Change this so that the generated filter will be used when the included lvm.conf has no filter set. (cherry picked from commit 7ffc5e388bcce20785803825bdd260c3c854b34f) Resolves: #2037955 --- modules.d/90lvm/lvm_scan.sh | 91 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 16 deletions(-) diff --git a/modules.d/90lvm/lvm_scan.sh b/modules.d/90lvm/lvm_scan.sh index 00143bff..bda265f6 100755 --- a/modules.d/90lvm/lvm_scan.sh +++ b/modules.d/90lvm/lvm_scan.sh @@ -10,6 +10,7 @@ LVS=$(getargs rd.lvm.lv -d rd_LVM_LV=) # shellcheck disable=SC2174 [ -d /etc/lvm ] || mkdir -m 0755 -p /etc/lvm +[ -d /run/lvm ] || mkdir -m 0755 -p /run/lvm # build a list of devices to scan lvmdevs=$( for f in /tmp/.lvm_scan-*; do @@ -18,22 +19,6 @@ lvmdevs=$( done ) -if [ ! -e /etc/lvm/lvm.conf ]; then - { - echo 'devices {' - printf ' filter = [ ' - for dev in $lvmdevs; do - printf '"a|^/dev/%s$|", ' "$dev" - done - echo '"r/.*/" ]' - echo '}' - - echo 'global {' - echo '}' - } > /etc/lvm/lvm.conf - lvmwritten=1 -fi - check_lvm_ver() { maj=$1 min=$2 @@ -47,6 +32,75 @@ check_lvm_ver() { return 1 } +no_lvm_conf_filter() { + if [ ! -e /etc/lvm/lvm.conf ]; then + return 0 + fi + + if [ -e /run/lvm/initrd_no_filter ]; then + return 0 + fi + + if [ -e /run/lvm/initrd_filter ]; then + return 1 + fi + + if [ -e /run/lvm/initrd_global_filter ]; then + return 1 + fi + + # Save lvm config results in /run to avoid running + # lvm config commands for every PV that's scanned. + + filter=$(lvm config devices/filter | grep "$filter=") + if [ -n "$filter" ]; then + printf '%s\n' "$filter" > /run/lvm/initrd_filter + return 1 + fi + + global_filter=$(lvm config devices/global_filter | grep "$global_filter=") + if [ -n "$global_filter" ]; then + printf '%s\n' "$global_filter" > /run/lvm/initrd_global_filter + return 1 + fi + + # /etc/lvm/lvm.conf exists with no filter setting + true > /run/lvm/initrd_no_filter + return 0 +} + +# If no lvm.conf exists, create a basic one with a global section. +if [ ! -e /etc/lvm/lvm.conf ]; then + { + echo 'global {' + echo '}' + } > /etc/lvm/lvm.conf + lvmwritten=1 +fi + +# Save the original lvm.conf before appending a filter setting. +if [ ! -e /etc/lvm/lvm.conf.orig ]; then + cp /etc/lvm/lvm.conf /etc/lvm/lvm.conf.orig +fi + +# If the original lvm.conf does not contain a filter setting, +# then generate a filter and append it to the original lvm.conf. +# The filter is generated from the list PVs that have been seen +# so far (each has been processed by the lvm udev rule.) +if no_lvm_conf_filter; then + { + echo 'devices {' + printf ' filter = [ ' + for dev in $lvmdevs; do + printf '"a|^/dev/%s$|", ' "$dev" + done + echo '"r/.*/" ]' + echo '}' + } > /etc/lvm/lvm.conf.filter + lvmfilter=1 + cat /etc/lvm/lvm.conf.orig /etc/lvm/lvm.conf.filter > /etc/lvm/lvm.conf +fi + # hopefully this output format will never change, e.g.: # LVM version: 2.02.53(1) (2009-09-25) OLDIFS=$IFS @@ -99,8 +153,13 @@ fi if [ "$lvmwritten" ]; then rm -f -- /etc/lvm/lvm.conf +elif [ "$lvmfilter" ]; then + # revert filter that was appended to existing lvm.conf + cp /etc/lvm/lvm.conf.orig /etc/lvm/lvm.conf + rm -f -- /etc/lvm/lvm.conf.filter fi unset lvmwritten +unset lvmfilter udevadm settle