diff --git a/modules.d/40network/net-genrules.sh b/modules.d/40network/net-genrules.sh index dbd04741..f843c53f 100755 --- a/modules.d/40network/net-genrules.sh +++ b/modules.d/40network/net-genrules.sh @@ -19,20 +19,20 @@ fix_bootif() { BOOTIF=$(getarg 'BOOTIF=') if [ -n "$BOOTIF" ] ; then BOOTIF=$(fix_bootif "$BOOTIF") - printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$BOOTIF" + printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/initqueue /sbin/ifup $env{INTERFACE}"\n' "$BOOTIF" # If we have to handle multiple interfaces, handle only them. elif [ -n "$IFACES" ] ; then for iface in $IFACES ; do - printf 'ACTION=="add", SUBSYSTEM=="net", KERNEL=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$iface" + printf 'ACTION=="add", SUBSYSTEM=="net", KERNEL=="%s", RUN+="/sbin/initqueue /sbin/ifup $env{INTERFACE}"\n' "$iface" done # Default: We don't know the interface to use, handle all else - printf 'ACTION=="add", SUBSYSTEM=="net", RUN+="/sbin/ifup $env{INTERFACE}"\n' + printf 'ACTION=="add", SUBSYSTEM=="net", RUN+="/sbin/initqueue /sbin/ifup $env{INTERFACE}"\n' fi # Udev event 'online' only gets fired from ifup/dhclient-script. # No special rules required - printf 'ACTION=="online", SUBSYSTEM=="net", RUN+="/sbin/netroot $env{INTERFACE}"\n' + printf 'ACTION=="online", SUBSYSTEM=="net", RUN+="/sbin/initqueue /sbin/netroot $env{INTERFACE}"\n' } > /etc/udev/rules.d/60-net.rules diff --git a/modules.d/50plymouth/63-luks.rules b/modules.d/50plymouth/63-luks.rules index cfa619b7..c3c6627a 100644 --- a/modules.d/50plymouth/63-luks.rules +++ b/modules.d/50plymouth/63-luks.rules @@ -7,6 +7,6 @@ SUBSYSTEM!="block", GOTO="luks_end" ACTION!="add|change", GOTO="luks_end" -ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}" +ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue /sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}" LABEL="luks_end" diff --git a/modules.d/90crypt/70-luks.rules b/modules.d/90crypt/70-luks.rules index cfa619b7..c3c6627a 100644 --- a/modules.d/90crypt/70-luks.rules +++ b/modules.d/90crypt/70-luks.rules @@ -7,6 +7,6 @@ SUBSYSTEM!="block", GOTO="luks_end" ACTION!="add|change", GOTO="luks_end" -ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}" +ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue /sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}" LABEL="luks_end" diff --git a/modules.d/95nbd/nbdroot b/modules.d/95nbd/nbdroot index 90f6ef8c..ad2e9066 100755 --- a/modules.d/95nbd/nbdroot +++ b/modules.d/95nbd/nbdroot @@ -93,7 +93,7 @@ done # If we didn't get a root= on the command line, then we need to # add the udev rules for mounting the nbd0 device if [ ! -e /etc/udev/rules.d/99-mount.rules ]; then - printf 'KERNEL=="%s", RUN+="/bin/mount -t %s -o %s %s %s"\n' \ + printf 'KERNEL=="%s", RUN+="/sbin/initqueue /bin/mount -t %s -o %s %s %s"\n' \ nbd0 "$nbdfstype" "$fsopts" /dev/nbd0 "$NEWROOT" \ > /etc/udev/rules.d/99-mount.rules fi diff --git a/modules.d/95rootfs-block/block-genrules.sh b/modules.d/95rootfs-block/block-genrules.sh index d6924c85..2706dbb9 100644 --- a/modules.d/95rootfs-block/block-genrules.sh +++ b/modules.d/95rootfs-block/block-genrules.sh @@ -1,8 +1,8 @@ if [ "${root%%:*}" = "block" ]; then ( - printf 'KERNEL=="%s", RUN+="/bin/mount -t %s -o %s %s %s"\n' \ + printf 'KERNEL=="%s", RUN+="/sbin/initqueue /bin/mount -t %s -o %s %s %s"\n' \ ${root#block:/dev/} "$fstype" "$rflags" "${root#block:}" "$NEWROOT" - printf 'SYMLINK=="%s", RUN+="/bin/mount -t %s -o %s %s %s"\n' \ + printf 'SYMLINK=="%s", RUN+="/sbin/initqueue /bin/mount -t %s -o %s %s %s"\n' \ ${root#block:/dev/} "$fstype" "$rflags" "${root#block:}" "$NEWROOT" ) >> /etc/udev/rules.d/99-mount.rules fi diff --git a/modules.d/99base/init b/modules.d/99base/init index 868ca19c..0e29d761 100755 --- a/modules.d/99base/init +++ b/modules.d/99base/init @@ -14,6 +14,29 @@ emergency_shell() sh -i } +do_initqueue() +{ + while :; do + # bail out, if we have mounted the root filesystem + [ -d "$NEWROOT/proc" ] && break; + + if [ $UDEVVERSION -ge 143 ]; then + udevadm settle --exit-if-exists=/initqueue/work + else + udevadm settle --timeout=30 + fi + [ -f /initqueue/work ] || break + rm /initqueue/work + + for job in /initqueue/*.job; do + . $job + rm -f $job + # bail out, if we have mounted the root filesystem + [ -d "$NEWROOT/proc" ] && break; + done + done +} + export PATH=/sbin:/bin:/usr/sbin:/usr/bin export TERM=linux NEWROOT="/sysroot" @@ -45,6 +68,8 @@ mkdir /dev/shm mkdir /dev/pts mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts >/dev/null 2>&1 +UDEVVERSION=$(udevadm --version) + # run scriptlets to parse the command line getarg 'rdbreak=cmdline' && emergency_shell source_all cmdline @@ -75,7 +100,8 @@ source_all pre-trigger # then the rest udevadm trigger $udevtriggeropts >/dev/null 2>&1 -udevadm settle --timeout=30 >/dev/null 2>&1 + +do_initqueue # pre-mount happens before we try to mount the root filesystem, # and happens once. @@ -83,6 +109,8 @@ getarg 'rdbreak=pre-mount' && emergency_shell source_all pre-mount getarg 'rdbreak=mount' && emergency_shell +do_initqueue + # mount scripts actually try to mount the root filesystem, and may # be sourced any number of times. As soon as one suceeds, no more are sourced. i=0 @@ -90,7 +118,8 @@ while :; do [ -d "$NEWROOT/proc" ] && break; for f in /mount/*.sh; do - [ -x "$f" ] && . "$f"; + [ -f "$f" ] && . "$f" + do_initqueue [ "$ROOTFS_MOUNTED" ] && break; done diff --git a/modules.d/99base/initqueue b/modules.d/99base/initqueue new file mode 100755 index 00000000..0a760b72 --- /dev/null +++ b/modules.d/99base/initqueue @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "$@" > /tmp/$$.job +mv /tmp/$$.job /initqueue/ +>> /initqueue/work diff --git a/modules.d/99base/install b/modules.d/99base/install index b233f971..ff152007 100755 --- a/modules.d/99base/install +++ b/modules.d/99base/install @@ -1,11 +1,14 @@ #!/bin/bash -dracut_install mount mknod mkdir modprobe pidof sleep chroot sed ls flock cp +dracut_install mount mknod mkdir modprobe pidof sleep chroot sed ls flock cp mv if [ ! -e "${initdir}/bin/sh" ]; then dracut_install bash (ln -s bash "${initdir}/bin/sh" || :) fi # install our scripts and hooks inst "$moddir/init" "/init" +inst "$moddir/initqueue" "/sbin/initqueue" +mkdir -p ${initdir}/initqueue +mkdir -p ${initdir}/tmp # Bail out if switch_root does not exist if which switch_root >/dev/null 2>&1; then dracut_install switch_root