File 0313-90mdraid-Use-stock-MD-rules-to-assemble-RAID-arrays.patch of Package dracut.12460

From 91ab88b0bda124816724dcea4c532259add83e41 Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Fri, 14 Oct 2016 11:01:57 +0200
Subject: [PATCH] 90mdraid: Use stock MD rules to assemble RAID arrays

We cannot call 'mdadm' from a RUN udev event key or use the
initqueue, as 'mdadm -I' will remove the partitions before
assembling the array. This is only safe to be called directly
from the udev rule (eg by the IMPORT or PROGRAM key), as then
udev will prevent any events for the partition devices to
be processed.
If 'mdadm -I' is called _after_ the event is processed it will
race with udev processing the events for the partitions devices,
and induce random boot failures.

References: bsc#998860

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 modules.d/90mdraid/62-md-dracut-cmdline.rules   | 16 +++++++++
 modules.d/90mdraid/65-md-incremental-imsm.rules | 44 -------------------------
 modules.d/90mdraid/mdraid_start.sh              | 34 -------------------
 modules.d/90mdraid/module-setup.sh              | 14 +-------
 modules.d/90mdraid/parse-md.sh                  | 34 +++++++++----------
 5 files changed, 32 insertions(+), 110 deletions(-)
 create mode 100644 modules.d/90mdraid/62-md-dracut-cmdline.rules
 delete mode 100644 modules.d/90mdraid/65-md-incremental-imsm.rules
 delete mode 100755 modules.d/90mdraid/mdraid_start.sh

diff --git a/modules.d/90mdraid/62-md-dracut-cmdline.rules b/modules.d/90mdraid/62-md-dracut-cmdline.rules
new file mode 100644
index 0000000..c30636f
--- /dev/null
+++ b/modules.d/90mdraid/62-md-dracut-cmdline.rules
@@ -0,0 +1,16 @@
+# Interpret dracut-specific commandline arguments which inhibit
+# mdadm from starting
+# See udev(8) for syntax
+
+ACTION!="add|change", GOTO="md_end"
+SUBSYSTEM!="block", GOTO="md_end"
+
+# Disable MD assembly if rd_NO_MD is given
+ENV{rd_NO_MD}=="?*", ENV{ID_FS_TYPE}=="ddf_raid_member|isw_raid_member|linux_raid_member", ENV{ID_FS_TYPE}="unknown"
+
+# Disable ISW / IMSM RAID assembly if rd_NO_MDIMSM is given
+ENV{ID_FS_TYPE}=="isw_raid_member", ENV{rd_NO_MDIMSM}=="?*", ENV{ID_FS_TYPE}="unknown"
+# Disable DDF RAID assembly if rd_NO_MDDDF is given
+ENV{ID_FS_TYPE}=="ddf_raid_member", ENV{rd_NO_MDDDF}=="?*", ENV{ID_FS_TYPE}="unknown"
+
+LABEL="md_end"
diff --git a/modules.d/90mdraid/65-md-incremental-imsm.rules b/modules.d/90mdraid/65-md-incremental-imsm.rules
deleted file mode 100644
index d66dd01..0000000
--- a/modules.d/90mdraid/65-md-incremental-imsm.rules
+++ /dev/null
@@ -1,44 +0,0 @@
-# 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}=="?*", 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 $env{rd_MD_OFFROOT} -I $env{DEVNAME}"
-
-LABEL="md_end"
diff --git a/modules.d/90mdraid/mdraid_start.sh b/modules.d/90mdraid/mdraid_start.sh
deleted file mode 100755
index 400ab5d..0000000
--- a/modules.d/90mdraid/mdraid_start.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/sh
-
-type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh
-_md_force_run() {
-    local _udevinfo
-    local _path_s
-    local _path_d
-    local _offroot
-    _offroot=$(strstr "$(mdadm --help-options 2>&1)" offroot && echo --offroot)
-    # try to force-run anything not running yet
-    for md in /dev/md[0-9_]*; do
-        [ -b "$md" ] || continue
-        _udevinfo="$(udevadm info --query=env --name="$md")"
-        strstr "$_udevinfo" "MD_LEVEL=container" && continue
-        strstr "$_udevinfo" "DEVTYPE=partition" && continue
-
-        _path_s="/sys/$(udevadm info -q path -n "$md")/md/array_state"
-        [ ! -r "$_path_s" ] && continue
-
-        # inactive ?
-        [ "$(cat "$_path_s")" != "inactive" ] && continue
-
-        mdadm $_offroot -R "$md" 2>&1 | vinfo
-
-        # still inactive ?
-        [ "$(cat "$_path_s")" = "inactive" ] && continue
-
-        _path_d="${_path_s%/*}/degraded"
-        [ ! -r "$_path_d" ] && continue
-        > $hookdir/initqueue/work
-    done
-}
-
-_md_force_run
diff --git a/modules.d/90mdraid/module-setup.sh b/modules.d/90mdraid/module-setup.sh
index d865fca..13ef9fe 100755
--- a/modules.d/90mdraid/module-setup.sh
+++ b/modules.d/90mdraid/module-setup.sh
@@ -79,18 +79,8 @@ install() {
     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}"
-        [ -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/62-md-dracut-cmdline.rules"
 
     inst_rules "$moddir/59-persistent-storage-md.rules"
     prepare_udev_rules 59-persistent-storage-md.rules
@@ -125,12 +115,10 @@ install() {
     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 $systemdsystemunitdir/mdmon@.service ]; then
             inst_simple $systemdsystemunitdir/mdmon@.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
index 8582f59..c187a91 100755
--- a/modules.d/90mdraid/parse-md.sh
+++ b/modules.d/90mdraid/parse-md.sh
@@ -1,31 +1,27 @@
 #!/bin/sh
 
 MD_UUID=$(getargs rd.md.uuid -d rd_MD_UUID=)
+MD_RULES=/etc/udev/62-md-dracut-uuid.rules
 
 if ( ! [ -n "$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
+    # Create md rule 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 line || [ -n "$line" ]; do
-                if [ "${line%%UUID CHECK}" != "$line" ]; then
-                    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' $uuid
-                        printf 'ENV{ID_FS_UUID}=="%s", GOTO="md_uuid_ok"\n' $uuid
-                    done;
-                    printf 'GOTO="md_end"\n'
-                    printf 'LABEL="md_uuid_ok"\n'
-                    printf 'ENV{IMSM_NO_PLATFORM}="1"'
-                else
-                    echo "$line"
-                fi
-            done < "${f}" > "${f}.new"
-            mv "${f}.new" "$f"
-        done
+        printf 'ACTION!="add|change", GOTO="md_uuid_end"\n' > $MD_RULES
+        printf 'SUBSYSTEM!="block", GOTO="md_uuid_end"\n' >> $MD_RULES
+        printf 'ENV{ID_FS_TYPE}!="ddf_raid_member", ENV{ID_FS_TYPE}!="isw_raid_member", ENV{ID_FS_TYPE}!="linux_raid_member", GOTO="md_uuid_end"\n' >> $MD_RULES
+
+        for uuid in $MD_UUID; do
+            printf 'ENV{MD_UUID}=="%s", GOTO="md_uuid_ok"\n' $uuid >> $MD_RULES
+            printf 'ENV{ID_FS_UUID}=="%s", GOTO="md_uuid_ok"\n' $uuid >> $MD_RULES
+        done;
+        printf 'ENV{ID_FS_TYPE}="unknown"\n' >> $MD_RULES
+        printf 'GOTO="md_uuid_end"\n' >> $MD_RULES
+        printf 'LABEL="md_uuid_ok"\n' >> $MD_RULES
+        printf 'ENV{IMSM_NO_PLATFORM}="1"' >> $MD_RULES
+        printf 'LABEL="md_uuid_end"\n' >> $MD_RULES
     fi
 fi
 
-- 
2.6.6