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