From 91ab88b0bda124816724dcea4c532259add83e41 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke 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 --- 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