Jobs are no longer handled inside the udev events.
/sbin/initqueue is called with the commands to queue.
init will work on these jobs sequentially, so that we prevent jobs
from being killed by udev timeouts.
This serialization also prevents some problems introduced by
the udev event parallelization.
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
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"
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"
# 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
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
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"
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
# 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.
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
[ -d "$NEWROOT/proc" ] && break;
for f in /mount/*.sh; do
- [ -x "$f" ] && . "$f";
+ [ -f "$f" ] && . "$f"
+ do_initqueue
[ "$ROOTFS_MOUNTED" ] && break;
done
--- /dev/null
+#!/bin/sh
+
+echo "$@" > /tmp/$$.job
+mv /tmp/$$.job /initqueue/
+>> /initqueue/work
#!/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