diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 13:54:25 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 13:54:25 +0000 |
commit | 9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a (patch) | |
tree | 2efb72864cc69e174c9c5ee33efb88a5f1553b48 /modules.d/90lvm/lvm_scan.sh | |
parent | Initial commit. (diff) | |
download | dracut-9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a.tar.xz dracut-9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a.zip |
Adding upstream version 060+5.upstream/060+5
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules.d/90lvm/lvm_scan.sh')
-rwxr-xr-x | modules.d/90lvm/lvm_scan.sh | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/modules.d/90lvm/lvm_scan.sh b/modules.d/90lvm/lvm_scan.sh new file mode 100755 index 0000000..980e449 --- /dev/null +++ b/modules.d/90lvm/lvm_scan.sh @@ -0,0 +1,176 @@ +#!/bin/sh + +# run lvm scan if udev has settled + +extraargs="$*" +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=) + +# 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 + [ -e "$f" ] || continue + printf '%s' "${f##/tmp/.lvm_scan-} " + done +) + +check_lvm_ver() { + maj=$1 + min=$2 + ver=$3 + # --poll is supported since 2.2.57 + [ "$4" -lt "$maj" ] && return 1 + [ "$4" -gt "$maj" ] && return 0 + [ "$5" -lt "$min" ] && return 1 + [ "$5" -gt "$min" ] && return 0 + [ "$6" -ge "$ver" ] && return 0 + 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 2> /dev/null | grep "$filter=") + if [ -n "$filter" ]; then + printf '%s\n' "$filter" > /run/lvm/initrd_filter + return 1 + fi + + global_filter=$(lvm config devices/global_filter 2> /dev/null | 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 +IFS=. +# shellcheck disable=SC2046 +set -- $(lvm version 2> /dev/null) +IFS=$OLDIFS +maj=${1##*:} +min=$2 +sub=${3%% *} +sub=${sub%%\(*} + +# For lvchange and vgchange use --sysinit which: +# disables polling (--poll n) +# ignores monitoring (--ignoremonitoring) +# ignores locking failures (--ignorelockingfailure) +# disables hints (--nohints) +# +# For lvs and vgscan: +# disable locking (--nolocking) +# disable hints (--nohints) + +activate_args="--sysinit $extraargs" +unset extraargs + +export LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES=1 + +scan_args="--nolocking" + +check_lvm_ver 2 3 14 "$maj" "$min" "$sub" \ + && scan_args="$scan_args --nohints" + +if [ -n "$LVS" ]; then + info "Scanning devices $lvmdevs for LVM logical volumes $LVS" + # shellcheck disable=SC2086 + LVSLIST=$(lvm lvs $scan_args --noheading -o lv_full_name,segtype $LVS) + info "$LVSLIST" + + # Only attempt to activate an LV if it appears in the lvs output. + for LV in $LVS; do + if strstr "$LVSLIST" "$LV"; then + # This lvchange is expected to fail if all PVs used by + # the LV are not yet present. Premature/failed lvchange + # could be avoided by reporting if an LV is complete + # from the lvs command above and skipping this lvchange + # if the LV is not lised as complete. + # shellcheck disable=SC2086 + lvm lvchange --yes -K -ay $activate_args "$LV" 2>&1 | vinfo + fi + done +fi + +if [ -z "$LVS" ] || [ -n "$VGS" ]; then + info "Scanning devices $lvmdevs for LVM volume groups $VGS" + # shellcheck disable=SC2086 + lvm vgscan $scan_args 2>&1 | vinfo + # shellcheck disable=SC2086 + lvm vgchange -ay $activate_args $VGS 2>&1 | vinfo +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 + +need_shutdown |