Blame SOURCES/0008-add-dracut-files.patch

9db2f0
From 7dff68f6d02afb1174b13c36865d4000cf63aff7 Mon Sep 17 00:00:00 2001
9db2f0
From: David Teigland <teigland@redhat.com>
9db2f0
Date: Thu, 1 Apr 2021 12:08:58 -0500
9db2f0
Subject: [PATCH 08/11] add dracut files
9db2f0
9db2f0
pvscan-udev-initrd.sh is shell wrapper around the
9db2f0
pvscan command for use in the initrd lvm udev rule.
9db2f0
It finds the intersection of complete VG/LVs reported
9db2f0
by pvscan, and the VG/LVs specified on boot cmdline.
9db2f0
The resulting VG or LVs are printed as env-vars that
9db2f0
the udev rule can IMPORT, and pass to vgchange/lvchange.
9db2f0
9db2f0
64-lvm.rules calls pvscan-udev-initrd.sh/pvscan to scan
9db2f0
the PV to check if any VG or LVs are complete given the
9db2f0
new device.  The pvscan will only ever read the single
9db2f0
device triggering the uevent.  If any VG or LVs are
9db2f0
complete, the udev rule uses systemd-run to run a
9db2f0
vgchange or lvchange command to activate the complete
9db2f0
VG or LVs.  (Running vgchange or lvchange directly may
9db2f0
take longer than udev likes, so systemd-run --no-block
9db2f0
is used.)
9db2f0
---
9db2f0
 dracut/64-lvm.rules          |  44 +++++++++++++++++
9db2f0
 dracut/module-setup.sh       | 112 +++++++++++++++++++++++++++++++++++++++++++
9db2f0
 dracut/parse-lvm.sh          |  18 +++++++
9db2f0
 dracut/pvscan-udev-initrd.sh |  57 ++++++++++++++++++++++
9db2f0
 4 files changed, 231 insertions(+)
9db2f0
 create mode 100644 dracut/64-lvm.rules
9db2f0
 create mode 100755 dracut/module-setup.sh
9db2f0
 create mode 100755 dracut/parse-lvm.sh
9db2f0
 create mode 100755 dracut/pvscan-udev-initrd.sh
9db2f0
9db2f0
diff --git a/dracut/64-lvm.rules b/dracut/64-lvm.rules
9db2f0
new file mode 100644
9db2f0
index 0000000..174af1d
9db2f0
--- /dev/null
9db2f0
+++ b/dracut/64-lvm.rules
9db2f0
@@ -0,0 +1,44 @@
9db2f0
+# Copyright 2008,2021 Red Hat, Inc.
9db2f0
+#
9db2f0
+# Jeremy Katz <katzj@redhat.com>
9db2f0
+
9db2f0
+SUBSYSTEM!="block", GOTO="lvm_end"
9db2f0
+ACTION!="add|change", GOTO="lvm_end"
9db2f0
+# Also don't process disks that are slated to be a multipath device
9db2f0
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="lvm_end"
9db2f0
+KERNEL=="dm-[0-9]*", ACTION=="add", GOTO="lvm_end"
9db2f0
+ENV{ID_FS_TYPE}!="LVM2_member", GOTO="lvm_end"
9db2f0
+
9db2f0
+PROGRAM=="/bin/sh -c 'for i in $sys/$devpath/holders/dm-[0-9]*; do [ -e $$i ] && exit 0; done; exit 1;' ", \
9db2f0
+    GOTO="lvm_end"
9db2f0
+
9db2f0
+# pvscan-udev-initrd.sh is a wrapper that calls pvscan and prints
9db2f0
+# LVM_VG_NAME_COMPLETE='...'
9db2f0
+# LVM_LV_NAMES_COMPLETE='...'
9db2f0
+# if the given device completes a VG or LVs listed in
9db2f0
+# rd.lvm.vg or rd.lvm.lv
9db2f0
+#
9db2f0
+# If a VG or LVs are completed by the device, but are not
9db2f0
+# listed in rd.lvm.vg/lv, then they are not printed
9db2f0
+# (we don't want to activate VGs/LVs that are not specified.)
9db2f0
+#
9db2f0
+# If no VG or LVs are completed by the device, then
9db2f0
+# nothing is printed.
9db2f0
+#
9db2f0
+# LVs may be complete and activated before the VG is complete,
9db2f0
+# i.e. the entire VG is not necessary to activate LVs in it.
9db2f0
+#
9db2f0
+# If multiple LV names are completed from one device,
9db2f0
+# e.g. LVM_LV_NAMES_COMPLETE='vg/lv1 vg/lv2 vg/lv3'
9db2f0
+# they will be activated by one lvchange command.
9db2f0
+
9db2f0
+IMPORT{program}="pvscan-udev-initrd.sh $env{DEVNAME}"
9db2f0
+
9db2f0
+# systemd services are used to run vgchange/lvchange
9db2f0
+# because the lvm activation commands can run for longer
9db2f0
+# than udev will tolerate.
9db2f0
+
9db2f0
+ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/usr/bin/systemd-run --no-block --property DefaultDependencies=no /sbin/lvm vgchange -ay --yes --ignoremonitoring --poll n --sysinit $env{LVM_VG_NAME_COMPLETE}"
9db2f0
+ENV{LVM_LV_NAMES_COMPLETE}=="?*", RUN+="/usr/bin/systemd-run --no-block --property DefaultDependencies=no /sbin/lvm lvchange -ay --yes -K --ignoremonitoring --poll n --sysinit $env{LVM_LV_NAMES_COMPLETE}"
9db2f0
+
9db2f0
+LABEL="lvm_end"
9db2f0
diff --git a/dracut/module-setup.sh b/dracut/module-setup.sh
9db2f0
new file mode 100755
9db2f0
index 0000000..51d9cd3
9db2f0
--- /dev/null
9db2f0
+++ b/dracut/module-setup.sh
9db2f0
@@ -0,0 +1,112 @@
9db2f0
+#!/bin/bash
9db2f0
+
9db2f0
+# called by dracut
9db2f0
+check() {
9db2f0
+    # No point trying to support lvm if the binaries are missing
9db2f0
+    require_binaries lvm || return 1
9db2f0
+
9db2f0
+    [[ $hostonly ]] || [[ $mount_needs ]] && {
9db2f0
+        for fs in "${host_fs_types[@]}"; do
9db2f0
+            [[ $fs = LVM*_member ]] && return 0
9db2f0
+        done
9db2f0
+        return 255
9db2f0
+    }
9db2f0
+
9db2f0
+    return 0
9db2f0
+}
9db2f0
+
9db2f0
+# called by dracut
9db2f0
+depends() {
9db2f0
+    # We depend on dm_mod being loaded
9db2f0
+    echo rootfs-block dm
9db2f0
+    return 0
9db2f0
+}
9db2f0
+
9db2f0
+# called by dracut
9db2f0
+cmdline() {
9db2f0
+    local _activated
9db2f0
+    declare -A _activated
9db2f0
+
9db2f0
+    for dev in "${!host_fs_types[@]}"; do
9db2f0
+        [ -e /sys/block/${dev#/dev/}/dm/name ] || continue
9db2f0
+        [ -e /sys/block/${dev#/dev/}/dm/uuid ] || continue
9db2f0
+        uuid=$(
9db2f0
+        [[ "${uuid#LVM-}" == "$uuid" ]] && continue
9db2f0
+        dev=$(
9db2f0
+        eval $(dmsetup splitname --nameprefixes --noheadings --rows "$dev" 2>/dev/null)
9db2f0
+        [[ ${DM_VG_NAME} ]] && [[ ${DM_LV_NAME} ]] || return 1
9db2f0
+        if ! [[ ${_activated[${DM_VG_NAME}/${DM_LV_NAME}]} ]]; then
9db2f0
+            printf " rd.lvm.lv=%s " "${DM_VG_NAME}/${DM_LV_NAME} "
9db2f0
+            _activated["${DM_VG_NAME}/${DM_LV_NAME}"]=1
9db2f0
+        fi
9db2f0
+    done
9db2f0
+}
9db2f0
+
9db2f0
+installkernel() {
9db2f0
+    hostonly='' instmods dm-snapshot
9db2f0
+}
9db2f0
+
9db2f0
+# called by dracut
9db2f0
+install() {
9db2f0
+    local _i
9db2f0
+
9db2f0
+    inst lvm
9db2f0
+
9db2f0
+    if [[ $hostonly_cmdline == "yes" ]]; then
9db2f0
+        local _lvmconf=$(cmdline)
9db2f0
+        [[ $_lvmconf ]] && printf "%s\n" "$_lvmconf" >> "${initdir}/etc/cmdline.d/90lvm.conf"
9db2f0
+    fi
9db2f0
+
9db2f0
+    inst_rules "$moddir/64-lvm.rules"
9db2f0
+
9db2f0
+    if [[ $hostonly ]] || [[ $lvmconf = "yes" ]]; then
9db2f0
+        if [ -f $dracutsysrootdir/etc/lvm/lvm.conf ]; then
9db2f0
+            inst_simple -H /etc/lvm/lvm.conf
9db2f0
+        fi
9db2f0
+
9db2f0
+        export LVM_SUPPRESS_FD_WARNINGS=1
9db2f0
+        # Also install any files needed for LVM system id support.
9db2f0
+        if [ -f $dracutsysrootdir/etc/lvm/lvmlocal.conf ]; then
9db2f0
+            inst_simple -H /etc/lvm/lvmlocal.conf
9db2f0
+        fi
9db2f0
+        eval $(lvm dumpconfig global/system_id_source &>/dev/null)
9db2f0
+        if [ "$system_id_source" == "file" ]; then
9db2f0
+            eval $(lvm dumpconfig global/system_id_file)
9db2f0
+            if [ -f "$system_id_file" ]; then
9db2f0
+                inst_simple -H $system_id_file
9db2f0
+            fi
9db2f0
+        fi
9db2f0
+        unset LVM_SUPPRESS_FD_WARNINGS
9db2f0
+    fi
9db2f0
+
9db2f0
+    inst_rules 11-dm-lvm.rules
9db2f0
+
9db2f0
+    inst_script "$moddir/pvscan-udev-initrd.sh" /usr/lib/udev/pvscan-udev-initrd.sh
9db2f0
+    inst_hook cmdline 30 "$moddir/parse-lvm.sh"
9db2f0
+
9db2f0
+    inst_libdir_file "libdevmapper-event-lvm*.so"
9db2f0
+
9db2f0
+    if [[ $hostonly ]] && type -P lvs &>/dev/null; then
9db2f0
+        for dev in "${!host_fs_types[@]}"; do
9db2f0
+            [ -e /sys/block/${dev#/dev/}/dm/name ] || continue
9db2f0
+            dev=$(
9db2f0
+            eval $(dmsetup splitname --nameprefixes --noheadings --rows "$dev" 2>/dev/null)
9db2f0
+            [[ ${DM_VG_NAME} ]] && [[ ${DM_LV_NAME} ]] || continue
9db2f0
+            case "$(lvs --noheadings -o segtype ${DM_VG_NAME} 2>/dev/null)" in
9db2f0
+                *thin*|*cache*|*era*)
9db2f0
+                    inst_multiple -o thin_dump thin_restore thin_check thin_repair \
9db2f0
+                                  cache_dump cache_restore cache_check cache_repair \
9db2f0
+                                  era_check era_dump era_invalidate era_restore
9db2f0
+                    break;;
9db2f0
+            esac
9db2f0
+        done
9db2f0
+    fi
9db2f0
+
9db2f0
+    if ! [[ $hostonly ]]; then
9db2f0
+        inst_multiple -o thin_dump thin_restore thin_check thin_repair \
9db2f0
+                      cache_dump cache_restore cache_check cache_repair \
9db2f0
+                      era_check era_dump era_invalidate era_restore
9db2f0
+    fi
9db2f0
+
9db2f0
+    dracut_need_initqueue
9db2f0
+}
9db2f0
diff --git a/dracut/parse-lvm.sh b/dracut/parse-lvm.sh
9db2f0
new file mode 100755
9db2f0
index 0000000..8236050
9db2f0
--- /dev/null
9db2f0
+++ b/dracut/parse-lvm.sh
9db2f0
@@ -0,0 +1,18 @@
9db2f0
+#!/bin/sh
9db2f0
+
9db2f0
+if [ -e /etc/lvm/lvm.conf ] && ! getargbool 1 rd.lvm.conf -d -n rd_NO_LVMCONF; then
9db2f0
+    rm -f -- /etc/lvm/lvm.conf
9db2f0
+fi
9db2f0
+
9db2f0
+LV_DEVS="$(getargs rd.lvm.vg -d rd_LVM_VG=) $(getargs rd.lvm.lv -d rd_LVM_LV=)"
9db2f0
+
9db2f0
+if ! getargbool 1 rd.lvm -d -n rd_NO_LVM \
9db2f0
+    || ( [ -z "$LV_DEVS" ] && ! getargbool 0 rd.auto ); then
9db2f0
+    info "rd.lvm=0: removing LVM activation"
9db2f0
+    rm -f -- /etc/udev/rules.d/64-lvm*.rules
9db2f0
+else
9db2f0
+    for dev in $LV_DEVS; do
9db2f0
+        wait_for_dev -n "/dev/$dev"
9db2f0
+    done
9db2f0
+fi
9db2f0
+
9db2f0
diff --git a/dracut/pvscan-udev-initrd.sh b/dracut/pvscan-udev-initrd.sh
9db2f0
new file mode 100755
9db2f0
index 0000000..1743771
9db2f0
--- /dev/null
9db2f0
+++ b/dracut/pvscan-udev-initrd.sh
9db2f0
@@ -0,0 +1,57 @@
9db2f0
+#!/bin/sh
9db2f0
+
9db2f0
+# pvscan wrapper called by initrd lvm udev rule to find the
9db2f0
+# intersection of complete VGs/LVs found by pvscan and the
9db2f0
+# requested VGs/LVs from the cmdline.
9db2f0
+#
9db2f0
+# Used in 64-lvm.rules as:
9db2f0
+# IMPORT{program}="pvscan-udev-initrd.sh $env{DEVNAME}"
9db2f0
+#
9db2f0
+# See /usr/lib/dracut/modules.d/90lvm/64-lvm.rules
9db2f0
+
9db2f0
+dev=$1
9db2f0
+
9db2f0
+type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh
9db2f0
+
9db2f0
+
9db2f0
+VGS=$(getargs rd.lvm.vg -d rd_LVM_VG=)
9db2f0
+LVS=$(getargs rd.lvm.lv -d rd_LVM_LV=)
9db2f0
+
9db2f0
+IFS=' '
9db2f0
+
9db2f0
+# pvscan will produce a single VG line, and one or more LV lines.
9db2f0
+# VG <name> complete
9db2f0
+# VG <name> incomplete
9db2f0
+# LV <name> complete
9db2f0
+# LV <name> incomplete
9db2f0
+#
9db2f0
+# LV names are printed as vgname/lvname.
9db2f0
+# We only care about the complete items.
9db2f0
+# Each pvscan will produce a single VG line,
9db2f0
+# and may produce zero, one or more LV lines.
9db2f0
+
9db2f0
+PVSCAN=$(/sbin/lvm pvscan --cache --listlvs --checkcomplete --journal output --config 'global/event_activation=1' $dev)
9db2f0
+
9db2f0
+read -r -a VGSARRAY <<< "$VGS"
9db2f0
+
9db2f0
+for VG in "${VGSARRAY[@]}"
9db2f0
+do
9db2f0
+    if strstr "$PVSCAN" "VG $VG complete" ; then
9db2f0
+        echo LVM_VG_NAME_COMPLETE=\'"$VG"\'
9db2f0
+    fi
9db2f0
+done
9db2f0
+
9db2f0
+# Combine all matching LVs into a single print containing them all,
9db2f0
+# e.g. LVM_LV_NAMES_COMPLETE='vg/lv1 vg/lv2'
9db2f0
+
9db2f0
+read -r -a LVSARRAY <<< "$LVS"
9db2f0
+
9db2f0
+echo -n LVM_LV_NAMES_COMPLETE=\'
9db2f0
+for LV in "${LVSARRAY[@]}"
9db2f0
+do
9db2f0
+    if strstr "$PVSCAN" "LV $LV complete" ; then
9db2f0
+        echo -n "$LV "
9db2f0
+    fi
9db2f0
+done
9db2f0
+echo \'
9db2f0
+
9db2f0
-- 
9db2f0
1.8.3.1
9db2f0