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