summaryrefslogtreecommitdiffstats
path: root/modules.d/90lvm
diff options
context:
space:
mode:
Diffstat (limited to 'modules.d/90lvm')
-rw-r--r--modules.d/90lvm/64-lvm.rules29
-rwxr-xr-xmodules.d/90lvm/lvm_scan.sh176
-rwxr-xr-xmodules.d/90lvm/module-setup.sh117
-rwxr-xr-xmodules.d/90lvm/parse-lvm.sh17
4 files changed, 339 insertions, 0 deletions
diff --git a/modules.d/90lvm/64-lvm.rules b/modules.d/90lvm/64-lvm.rules
new file mode 100644
index 0000000..1ad4911
--- /dev/null
+++ b/modules.d/90lvm/64-lvm.rules
@@ -0,0 +1,29 @@
+# hacky rules to try to activate lvm when we get new block devs...
+#
+# Copyright 2008, Red Hat, Inc.
+# Jeremy Katz <katzj@redhat.com>
+
+
+SUBSYSTEM!="block", GOTO="lvm_end"
+ACTION!="add|change", GOTO="lvm_end"
+
+# If the md device is active (indicated by array_state), then set the flag
+# LVM_MD_PV_ACTIVATED=1 indicating that the md device for the PV is ready
+# to be used. The lvm udev rule running in root will check that this flag
+# is set before it will process the md device (it wants to avoid
+# processing an md device that exists but is not yet ready to be used.)
+KERNEL=="md[0-9]*", ACTION=="change", ENV{ID_FS_TYPE}=="LVM2_member", ENV{LVM_MD_PV_ACTIVATED}!="1", TEST=="md/array_state", ENV{LVM_MD_PV_ACTIVATED}="1"
+
+# Also don't process disks that are slated to be a multipath device
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="lvm_end"
+KERNEL=="dm-[0-9]*", ACTION=="add", GOTO="lvm_end"
+ENV{ID_FS_TYPE}!="LVM?_member", GOTO="lvm_end"
+
+PROGRAM=="/bin/sh -c 'for i in $sys/$devpath/holders/dm-[0-9]*; do [ -e $$i ] && exit 0; done; exit 1;' ", \
+ GOTO="lvm_end"
+
+RUN+="/sbin/initqueue --settled --onetime --unique /sbin/lvm_scan"
+RUN+="/sbin/initqueue --timeout --name 51-lvm_scan --onetime --unique /sbin/lvm_scan --activationmode degraded"
+RUN+="/bin/sh -c '>/tmp/.lvm_scan-%k;'"
+
+LABEL="lvm_end"
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
diff --git a/modules.d/90lvm/module-setup.sh b/modules.d/90lvm/module-setup.sh
new file mode 100755
index 0000000..7ba4c69
--- /dev/null
+++ b/modules.d/90lvm/module-setup.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # No point trying to support lvm if the binaries are missing
+ require_binaries lvm grep || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for fs in "${host_fs_types[@]}"; do
+ [[ $fs == LVM*_member ]] && return 0
+ done
+ return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ # We depend on dm_mod being loaded
+ echo rootfs-block dm
+ return 0
+}
+
+# called by dracut
+cmdline() {
+ local _activated
+ declare -A _activated
+
+ for dev in "${!host_fs_types[@]}"; do
+ [[ -e /sys/block/${dev#/dev/}/dm/name ]] || continue
+ [[ -e /sys/block/${dev#/dev/}/dm/uuid ]] || continue
+ uuid=$(< "/sys/block/${dev#/dev/}/dm/uuid")
+ [[ ${uuid#LVM-} == "$uuid" ]] && continue
+ dev=$(< "/sys/block/${dev#/dev/}/dm/name")
+ eval "$(dmsetup splitname --nameprefixes --noheadings --rows "$dev" 2> /dev/null)"
+ [[ ${DM_VG_NAME} ]] && [[ ${DM_LV_NAME} ]] || return 1
+ if ! [[ ${_activated[DM_VG_NAME / DM_LV_NAME]} ]]; then
+ printf " rd.lvm.lv=%s " "${DM_VG_NAME}/${DM_LV_NAME} "
+ _activated["${DM_VG_NAME}/${DM_LV_NAME}"]=1
+ fi
+ done
+}
+
+installkernel() {
+ hostonly='' dracut_instmods -o -P ".*/(bcache/|md-cluster).*" "=drivers/md"
+}
+
+# called by dracut
+install() {
+ inst_multiple lvm grep
+
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _lvmconf
+ _lvmconf=$(cmdline)
+ [[ $_lvmconf ]] && printf "%s\n" "$_lvmconf" >> "${initdir}/etc/cmdline.d/90lvm.conf"
+ fi
+
+ inst_rules "$moddir/64-lvm.rules"
+
+ if [[ $hostonly ]] || [[ $lvmconf == "yes" ]]; then
+ if [[ -f $dracutsysrootdir/etc/lvm/lvm.conf ]]; then
+ inst_simple -H /etc/lvm/lvm.conf
+ fi
+
+ export LVM_SUPPRESS_FD_WARNINGS=1
+ # Also install any files needed for LVM system id support.
+ if [[ -f $dracutsysrootdir/etc/lvm/lvmlocal.conf ]]; then
+ inst_simple -H /etc/lvm/lvmlocal.conf
+ fi
+ eval "$(lvm dumpconfig global/system_id_source &> /dev/null)"
+ if [ "$system_id_source" == "file" ]; then
+ eval "$(lvm dumpconfig global/system_id_file)"
+ if [ -f "$system_id_file" ]; then
+ inst_simple -H "$system_id_file"
+ fi
+ fi
+ unset LVM_SUPPRESS_FD_WARNINGS
+ fi
+
+ inst_rules 11-dm-lvm.rules
+
+ # Gentoo ebuild for LVM2 prior to 2.02.63-r1 doesn't install above rules
+ # files, but provides the one below:
+ inst_rules 64-device-mapper.rules
+ # debian udev rules
+ inst_rules 56-lvm.rules 60-persistent-storage-lvm.rules
+
+ inst_script "$moddir/lvm_scan.sh" /sbin/lvm_scan
+ inst_hook cmdline 30 "$moddir/parse-lvm.sh"
+
+ if [[ $hostonly ]] && find_binary lvs &> /dev/null; then
+ for dev in "${!host_fs_types[@]}"; do
+ [[ -e /sys/block/${dev#/dev/}/dm/name ]] || continue
+ dev=$(< "/sys/block/${dev#/dev/}/dm/name")
+ eval "$(dmsetup splitname --nameprefixes --noheadings --rows "$dev" 2> /dev/null)"
+ # shellcheck disable=SC2015
+ [[ ${DM_VG_NAME} ]] && [[ ${DM_LV_NAME} ]] || continue
+ case "$(lvs --noheadings -o segtype "${DM_VG_NAME}" 2> /dev/null)" in
+ *thin* | *cache* | *era*)
+ inst_multiple -o thin_dump thin_restore thin_check thin_repair \
+ cache_dump cache_restore cache_check cache_repair \
+ era_check era_dump era_invalidate era_restore
+ break
+ ;;
+ esac
+ done
+ fi
+
+ if ! [[ $hostonly ]]; then
+ inst_multiple -o thin_dump thin_restore thin_check thin_repair \
+ cache_dump cache_restore cache_check cache_repair \
+ era_check era_dump era_invalidate era_restore
+ fi
+
+ dracut_need_initqueue
+}
diff --git a/modules.d/90lvm/parse-lvm.sh b/modules.d/90lvm/parse-lvm.sh
new file mode 100755
index 0000000..d774882
--- /dev/null
+++ b/modules.d/90lvm/parse-lvm.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+if [ -e /etc/lvm/lvm.conf ] && ! getargbool 1 rd.lvm.conf -d -n rd_NO_LVMCONF; then
+ rm -f -- /etc/lvm/lvm.conf
+fi
+
+LV_DEVS="$(getargs rd.lvm.vg -d rd_LVM_VG=) $(getargs rd.lvm.lv -d rd_LVM_LV=)"
+
+if ! getargbool 1 rd.lvm -d -n rd_NO_LVM \
+ || { [ -z "$LV_DEVS" ] && ! getargbool 0 rd.auto; }; then
+ info "rd.lvm=0: removing LVM activation"
+ rm -f -- /etc/udev/rules.d/64-lvm*.rules
+else
+ for dev in $LV_DEVS; do
+ wait_for_dev -n "/dev/$dev"
+ done
+fi