summaryrefslogtreecommitdiffstats
path: root/modules.d/90mdraid
diff options
context:
space:
mode:
Diffstat (limited to 'modules.d/90mdraid')
-rw-r--r--modules.d/90mdraid/59-persistent-storage-md.rules24
-rw-r--r--modules.d/90mdraid/65-md-incremental-imsm.rules44
-rwxr-xr-xmodules.d/90mdraid/md-shutdown.sh23
-rwxr-xr-xmodules.d/90mdraid/mdmon-pre-shutdown.sh13
-rwxr-xr-xmodules.d/90mdraid/mdmon-pre-udev.sh4
-rwxr-xr-xmodules.d/90mdraid/mdraid-cleanup.sh21
-rwxr-xr-xmodules.d/90mdraid/mdraid-needshutdown.sh9
-rwxr-xr-xmodules.d/90mdraid/mdraid-waitclean.sh24
-rwxr-xr-xmodules.d/90mdraid/mdraid_start.sh70
-rwxr-xr-xmodules.d/90mdraid/module-setup.sh139
-rwxr-xr-xmodules.d/90mdraid/parse-md.sh64
11 files changed, 435 insertions, 0 deletions
diff --git a/modules.d/90mdraid/59-persistent-storage-md.rules b/modules.d/90mdraid/59-persistent-storage-md.rules
new file mode 100644
index 0000000..0d745cc
--- /dev/null
+++ b/modules.d/90mdraid/59-persistent-storage-md.rules
@@ -0,0 +1,24 @@
+SUBSYSTEM!="block", GOTO="md_end"
+ACTION!="add|change", GOTO="md_end"
+# Also don't process disks that are slated to be a multipath device
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="md_end"
+
+KERNEL!="md[0-9]*|md_d[0-9]*|md/*", KERNEL!="md*", GOTO="md_end"
+
+# partitions have no md/{array_state,metadata_version}
+ENV{DEVTYPE}=="partition", GOTO="md_ignore_state"
+
+# container devices have a metadata version of e.g. 'external:ddf' and
+# never leave state 'inactive'
+ATTR{md/metadata_version}=="external:[A-Za-z]*", ATTR{md/array_state}=="inactive", GOTO="md_ignore_state"
+TEST!="md/array_state", GOTO="md_end"
+ATTR{md/array_state}=="|clear|inactive", GOTO="md_end"
+
+LABEL="md_ignore_state"
+
+IMPORT{program}="/sbin/mdadm --detail --export $tempnode"
+IMPORT{builtin}="blkid"
+OPTIONS+="link_priority=100"
+OPTIONS+="watch"
+OPTIONS+="db_persist"
+LABEL="md_end"
diff --git a/modules.d/90mdraid/65-md-incremental-imsm.rules b/modules.d/90mdraid/65-md-incremental-imsm.rules
new file mode 100644
index 0000000..6697f15
--- /dev/null
+++ b/modules.d/90mdraid/65-md-incremental-imsm.rules
@@ -0,0 +1,44 @@
+# This file causes block devices with Linux RAID (mdadm) signatures to
+# automatically cause mdadm to be run.
+# See udev(8) for syntax
+
+ACTION!="add|change", GOTO="md_end"
+SUBSYSTEM!="block", GOTO="md_end"
+ENV{rd_NO_MD}=="?*", GOTO="md_end"
+KERNEL=="md*", ENV{ID_FS_TYPE}!="linux_raid_member", GOTO="md_end"
+KERNEL=="md*", ACTION!="change", GOTO="md_end"
+
+# Also don't process disks that are slated to be a multipath device
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="md_end"
+
+ENV{ID_FS_TYPE}=="ddf_raid_member|isw_raid_member|linux_raid_member", GOTO="md_try"
+GOTO="md_end"
+
+LABEL="md_try"
+ENV{ID_FS_TYPE}=="isw_raid_member", ENV{rd_NO_MDIMSM}=="?*", GOTO="md_end"
+ENV{ID_FS_TYPE}=="ddf_raid_member", ENV{rd_NO_MDDDF}=="?*", GOTO="md_end"
+
+# already done ?
+PROGRAM="/bin/sh -c 'for i in $sys/$devpath/holders/md[0-9_]*; do [ -e $$i ] && exit 0; done; exit 1;' ", \
+ GOTO="md_end"
+
+# for native arrays - array's uuid has to be specified
+# for containers - container's uuid has to be specified
+# TODO : how to get embedded array's uuid having container's component ?
+#
+# UUID CHECK
+
+ENV{DEVTYPE}!="partition", \
+ RUN+="/sbin/partx -d --nr 1-1024 $env{DEVNAME}"
+
+RUN+="/sbin/initqueue --timeout --name 50-mdraid_start --onetime --unique /sbin/mdraid_start"
+
+#
+# Incrementally build the md array; this will automatically assemble
+# any eventual containers as well (imsm, ddf)
+#
+LABEL="md_incremental"
+
+RUN+="/sbin/mdadm -I $env{DEVNAME}"
+
+LABEL="md_end"
diff --git a/modules.d/90mdraid/md-shutdown.sh b/modules.d/90mdraid/md-shutdown.sh
new file mode 100755
index 0000000..ca768a9
--- /dev/null
+++ b/modules.d/90mdraid/md-shutdown.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+_do_md_shutdown() {
+ local ret
+ local final="$1"
+ info "Waiting for mdraid devices to be clean."
+ mdadm -vv --wait-clean --scan | vinfo
+ ret=$?
+ info "Disassembling mdraid devices."
+ mdadm -vv --stop --scan | vinfo
+ ret=$((ret + $?))
+ if [ "x$final" != "x" ]; then
+ info "/proc/mdstat:"
+ vinfo < /proc/mdstat
+ fi
+ return $ret
+}
+
+if command -v mdadm > /dev/null; then
+ _do_md_shutdown "$1"
+else
+ :
+fi
diff --git a/modules.d/90mdraid/mdmon-pre-shutdown.sh b/modules.d/90mdraid/mdmon-pre-shutdown.sh
new file mode 100755
index 0000000..a5cd850
--- /dev/null
+++ b/modules.d/90mdraid/mdmon-pre-shutdown.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+_do_mdmon_takeover() {
+ local ret
+ mdmon --takeover --all
+ ret=$?
+ [ $ret -eq 0 ] && info "Taking over mdmon processes."
+ return $ret
+}
+
+if command -v mdmon > /dev/null; then
+ _do_mdmon_takeover "$1"
+fi
diff --git a/modules.d/90mdraid/mdmon-pre-udev.sh b/modules.d/90mdraid/mdmon-pre-udev.sh
new file mode 100755
index 0000000..b15cca8
--- /dev/null
+++ b/modules.d/90mdraid/mdmon-pre-udev.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# save state dir for mdmon/mdadm for the real root
+[ -d /run/mdadm ] || mkdir -m 0755 -p /run/mdadm
+# backward compat link
diff --git a/modules.d/90mdraid/mdraid-cleanup.sh b/modules.d/90mdraid/mdraid-cleanup.sh
new file mode 100755
index 0000000..ce50733
--- /dev/null
+++ b/modules.d/90mdraid/mdraid-cleanup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+containers=""
+for md in /dev/md[0-9_]*; do
+ [ -b "$md" ] || continue
+ udevinfo="$(udevadm info --query=property --name="$md")"
+ strstr "$udevinfo" "DEVTYPE=partition" && continue
+ if strstr "$udevinfo" "MD_LEVEL=container"; then
+ containers="$containers $md"
+ continue
+ fi
+ mdadm -S "$md" > /dev/null 2>&1
+done
+
+for md in $containers; do
+ mdadm -S "$md" > /dev/null 2>&1
+done
+
+unset containers udevinfo
diff --git a/modules.d/90mdraid/mdraid-needshutdown.sh b/modules.d/90mdraid/mdraid-needshutdown.sh
new file mode 100755
index 0000000..f248c4b
--- /dev/null
+++ b/modules.d/90mdraid/mdraid-needshutdown.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+for md in /dev/md[0-9_]*; do
+ [ -b "$md" ] || continue
+ need_shutdown
+ break
+done
diff --git a/modules.d/90mdraid/mdraid-waitclean.sh b/modules.d/90mdraid/mdraid-waitclean.sh
new file mode 100755
index 0000000..9317962
--- /dev/null
+++ b/modules.d/90mdraid/mdraid-waitclean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+if getargbool 0 rd.md.waitclean; then
+ type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+ containers=""
+ for md in /dev/md[0-9_]*; do
+ [ -b "$md" ] || continue
+ udevinfo="$(udevadm info --query=property --name="$md")"
+ strstr "$udevinfo" "DEVTYPE=partition" && continue
+ if strstr "$udevinfo" "MD_LEVEL=container"; then
+ containers="$containers $md"
+ continue
+ fi
+ info "Waiting for $md to become clean"
+ mdadm -W "$md" > /dev/null 2>&1
+ done
+
+ for md in $containers; do
+ info "Waiting for $md to become clean"
+ mdadm -W "$md" > /dev/null 2>&1
+ done
+
+ unset containers udevinfo
+fi
diff --git a/modules.d/90mdraid/mdraid_start.sh b/modules.d/90mdraid/mdraid_start.sh
new file mode 100755
index 0000000..d8c5de2
--- /dev/null
+++ b/modules.d/90mdraid/mdraid_start.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+type getargs > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+_md_start() {
+ local _udevinfo
+ local _path_s
+ local _path_d
+ local _md="$1"
+
+ _udevinfo="$(udevadm info --query=property --name="${_md}")"
+ strstr "$_udevinfo" "MD_LEVEL=container" && return 0
+ strstr "$_udevinfo" "DEVTYPE=partition" && return 0
+
+ _path_s="/sys/$(udevadm info -q path -n "${_md}")/md/array_state"
+ [ ! -r "$_path_s" ] && return 0
+
+ # inactive ?
+ [ "$(cat "$_path_s")" != "inactive" ] && return 0
+
+ mdadm -R "${_md}" 2>&1 | vinfo
+
+ # still inactive ?
+ [ "$(cat "$_path_s")" = "inactive" ] && return 0
+
+ _path_d="${_path_s%/*}/degraded"
+ [ ! -r "$_path_d" ] && return 0
+ : > "$hookdir"/initqueue/work
+}
+
+_md_force_run() {
+ local _md
+ local _UUID
+ local _MD_UUID
+
+ _MD_UUID=$(getargs rd.md.uuid -d rd_MD_UUID=)
+ [ -n "$_MD_UUID" ] || getargbool 0 rd.auto || return
+
+ if [ -n "$_MD_UUID" ]; then
+ _MD_UUID=$(str_replace "$_MD_UUID" "-" "")
+ _MD_UUID=$(str_replace "$_MD_UUID" ":" "")
+
+ for _md in /dev/md[0-9_]*; do
+ [ -b "$_md" ] || continue
+ _UUID=$(
+ /sbin/mdadm -D --export "$_md" \
+ | while read -r line || [ -n "$line" ]; do
+ str_starts "$line" "MD_UUID=" || continue
+ printf "%s" "${line#MD_UUID=}"
+ done
+ )
+
+ [ -z "$_UUID" ] && continue
+ _UUID=$(str_replace "$_UUID" ":" "")
+
+ # check if we should handle this device
+ strstr "$_MD_UUID" "$_UUID" || continue
+
+ _md_start "${_md}"
+ done
+ else
+ # try to force-run anything not running yet
+ for _md in /dev/md[0-9_]*; do
+ [ -b "$_md" ] || continue
+ _md_start "${_md}"
+ done
+ fi
+}
+
+_md_force_run
diff --git a/modules.d/90mdraid/module-setup.sh b/modules.d/90mdraid/module-setup.sh
new file mode 100755
index 0000000..6179a98
--- /dev/null
+++ b/modules.d/90mdraid/module-setup.sh
@@ -0,0 +1,139 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ local dev holder
+
+ # No mdadm? No mdraid support.
+ require_binaries mdadm expr || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for dev in "${!host_fs_types[@]}"; do
+ [[ ${host_fs_types[$dev]} != *_raid_member ]] && continue
+
+ DEVPATH=$(get_devpath_block "$dev")
+
+ for holder in "$DEVPATH"/holders/*; do
+ [[ -e $holder ]] || continue
+ [[ -e "$holder/md" ]] && return 0
+ break
+ done
+
+ done
+ return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo rootfs-block
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods '=drivers/md'
+}
+
+# called by dracut
+cmdline() {
+ local _activated dev line UUID
+ declare -A _activated
+
+ for dev in "${!host_fs_types[@]}"; do
+ [[ ${host_fs_types[$dev]} != *_raid_member ]] && continue
+
+ UUID=$(
+ /sbin/mdadm --examine --export "$dev" \
+ | while read -r line || [[ "$line" ]]; do
+ [[ ${line#MD_UUID=} == "$line" ]] && continue
+ printf "%s" "${line#MD_UUID=} "
+ done
+ )
+
+ [[ -z $UUID ]] && continue
+
+ if ! [[ ${_activated[${UUID}]} ]]; then
+ printf "%s" " rd.md.uuid=${UUID}"
+ _activated["${UUID}"]=1
+ fi
+
+ done
+}
+
+# called by dracut
+install() {
+ local rule rule_path
+ inst_multiple cat expr
+ inst_multiple -o mdmon
+ inst "$(command -v partx)" /sbin/partx
+ inst "$(command -v mdadm)" /sbin/mdadm
+
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _raidconf
+ _raidconf=$(cmdline)
+ [[ $_raidconf ]] && printf "%s\n" "$_raidconf" >> "${initdir}/etc/cmdline.d/90mdraid.conf"
+ fi
+
+ # <mdadm-3.3 udev rule
+ inst_rules 64-md-raid.rules
+ # >=mdadm-3.3 udev rules
+ inst_rules 63-md-raid-arrays.rules 64-md-raid-assembly.rules
+ # remove incremental assembly from stock rules, so they don't shadow
+ # 65-md-inc*.rules and its fine-grained controls, or cause other problems
+ # when we explicitly don't want certain components to be incrementally
+ # assembled
+ for rule in 64-md-raid.rules 64-md-raid-assembly.rules; do
+ rule_path="${initdir}${udevdir}/rules.d/${rule}"
+ # shellcheck disable=SC2016
+ [ -f "${rule_path}" ] && sed -i -r \
+ -e '/(RUN|IMPORT\{program\})\+?="[[:alpha:]/]*mdadm[[:blank:]]+(--incremental|-I)[[:blank:]]+(--export )?(\$env\{DEVNAME\}|\$tempnode|\$devnode)/d' \
+ "${rule_path}"
+ done
+
+ inst_rules "$moddir/65-md-incremental-imsm.rules"
+
+ inst_rules "$moddir/59-persistent-storage-md.rules"
+
+ if [[ $hostonly ]] || [[ $mdadmconf == "yes" ]]; then
+ if [[ -f $dracutsysrootdir/etc/mdadm.conf ]]; then
+ inst -H /etc/mdadm.conf
+ else
+ [[ -f $dracutsysrootdir/etc/mdadm/mdadm.conf ]] && inst -H /etc/mdadm/mdadm.conf /etc/mdadm.conf
+ fi
+ if [[ -d $dracutsysrootdir/etc/mdadm.conf.d ]]; then
+ local f
+ inst_dir /etc/mdadm.conf.d
+ for f in /etc/mdadm.conf.d/*.conf; do
+ [[ -f "$dracutsysrootdir$f" ]] || continue
+ inst -H "$f"
+ done
+ fi
+ fi
+
+ inst_hook pre-udev 30 "$moddir/mdmon-pre-udev.sh"
+ inst_hook pre-trigger 30 "$moddir/parse-md.sh"
+ inst_hook pre-mount 10 "$moddir/mdraid-waitclean.sh"
+ inst_hook cleanup 99 "$moddir/mdraid-needshutdown.sh"
+ inst_hook shutdown 30 "$moddir/md-shutdown.sh"
+ inst_script "$moddir/mdraid-cleanup.sh" /sbin/mdraid-cleanup
+ inst_script "$moddir/mdraid_start.sh" /sbin/mdraid_start
+ if dracut_module_included "systemd"; then
+ if [[ -e $dracutsysrootdir$systemdsystemunitdir/mdmon@.service ]]; then
+ inst_simple "$systemdsystemunitdir"/mdmon@.service
+ fi
+ if [[ -e $dracutsysrootdir$systemdsystemunitdir/mdadm-last-resort@.service ]]; then
+ inst_simple "$systemdsystemunitdir"/mdadm-last-resort@.service
+ fi
+ if [[ -e $dracutsysrootdir$systemdsystemunitdir/mdadm-last-resort@.timer ]]; then
+ inst_simple "$systemdsystemunitdir"/mdadm-last-resort@.timer
+ fi
+ if [[ -e $dracutsysrootdir$systemdsystemunitdir/mdadm-grow-continue@.service ]]; then
+ inst_simple "$systemdsystemunitdir"/mdadm-grow-continue@.service
+ fi
+ fi
+ inst_hook pre-shutdown 30 "$moddir/mdmon-pre-shutdown.sh"
+ dracut_need_initqueue
+}
diff --git a/modules.d/90mdraid/parse-md.sh b/modules.d/90mdraid/parse-md.sh
new file mode 100755
index 0000000..4d3a6b2
--- /dev/null
+++ b/modules.d/90mdraid/parse-md.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+# we really need to use `expr substr` with dash
+# shellcheck disable=SC2003 disable=SC2308
+
+MD_UUID=$(getargs rd.md.uuid -d rd_MD_UUID=)
+# normalize the uuid
+MD_UUID=$(str_replace "$MD_UUID" "-" "")
+MD_UUID=$(str_replace "$MD_UUID" ":" "")
+
+if { [ -z "$MD_UUID" ] && ! getargbool 0 rd.auto; } || ! getargbool 1 rd.md -d -n rd_NO_MD; then
+ info "rd.md=0: removing MD RAID activation"
+ udevproperty rd_NO_MD=1
+else
+ # rewrite the md rules to only process the specified raid array
+ if [ -n "$MD_UUID" ]; then
+ for f in /etc/udev/rules.d/65-md-incremental*.rules; do
+ [ -e "$f" ] || continue
+ while read -r line || [ -n "$line" ]; do
+ if [ "${line%%UUID CHECK}" != "$line" ]; then
+ for uuid in $MD_UUID; do
+ printf 'ENV{ID_FS_UUID}=="%s", GOTO="md_uuid_ok"\n' "$(expr substr "$uuid" 1 8)-$(expr substr "$uuid" 9 4)-$(expr substr "$uuid" 13 4)-$(expr substr "$uuid" 17 4)-$(expr substr "$uuid" 21 12)"
+ done
+ # shellcheck disable=SC2016
+ printf 'IMPORT{program}="/sbin/mdadm --examine --export $tempnode"\n'
+ for uuid in $MD_UUID; do
+ printf 'ENV{MD_UUID}=="%s", GOTO="md_uuid_ok"\n' "$(expr substr "$uuid" 1 8):$(expr substr "$uuid" 9 8):$(expr substr "$uuid" 17 8):$(expr substr "$uuid" 25 8)"
+ done
+ printf 'GOTO="md_end"\n'
+ printf 'LABEL="md_uuid_ok"\n'
+ else
+ echo "$line"
+ fi
+ done < "${f}" > "${f}.new"
+ mv "${f}.new" "$f"
+ done
+ for uuid in $MD_UUID; do
+ uuid="$(expr substr "$uuid" 1 8):$(expr substr "$uuid" 9 8):$(expr substr "$uuid" 17 8):$(expr substr "$uuid" 25 8)"
+ wait_for_dev "/dev/disk/by-id/md-uuid-${uuid}"
+ done
+ fi
+fi
+
+if [ -e /etc/mdadm.conf ] && getargbool 1 rd.md.conf -d -n rd_NO_MDADMCONF; then
+ udevproperty rd_MDADMCONF=1
+ rm -f -- "$hookdir"/pre-pivot/*mdraid-cleanup.sh
+fi
+
+if ! getargbool 1 rd.md.conf -d -n rd_NO_MDADMCONF; then
+ rm -f -- /etc/mdadm/mdadm.conf /etc/mdadm.conf
+ ln -s "$(command -v mdraid-cleanup)" "$hookdir"/pre-pivot/31-mdraid-cleanup.sh 2> /dev/null
+fi
+
+# noiswmd nodmraid for anaconda / rc.sysinit compatibility
+# note nodmraid really means nobiosraid, so we don't want MDIMSM then either
+if ! getargbool 1 rd.md.imsm -d -n rd_NO_MDIMSM -n noiswmd -n nodmraid; then
+ info "no MD RAID for imsm/isw raids"
+ udevproperty rd_NO_MDIMSM=1
+fi
+
+# same thing with ddf containers
+if ! getargbool 1 rd.md.ddf -n rd_NO_MDDDF -n noddfmd -n nodmraid; then
+ info "no MD RAID for SNIA ddf raids"
+ udevproperty rd_NO_MDDDF=1
+fi