switch to initqueue handling of events
authorHarald Hoyer <harald@redhat.com>
Thu, 2 Jul 2009 09:42:35 +0000 (11:42 +0200)
committerHarald Hoyer <harald@redhat.com>
Thu, 2 Jul 2009 09:47:28 +0000 (11:47 +0200)
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.

modules.d/40network/net-genrules.sh
modules.d/50plymouth/63-luks.rules
modules.d/90crypt/70-luks.rules
modules.d/95nbd/nbdroot
modules.d/95rootfs-block/block-genrules.sh
modules.d/99base/init
modules.d/99base/initqueue [new file with mode: 0755]
modules.d/99base/install

index dbd04741f1fa81d025ed7dcafbf4c152e2363b63..f843c53fdffe975e4b5583f72a920d7df9e8c71f 100755 (executable)
@@ -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
index cfa619b719c868dcf15801790b7a93007b4b5ccf..c3c6627aba6ea638581f2d3c705bf30e092d6980 100644 (file)
@@ -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"
index cfa619b719c868dcf15801790b7a93007b4b5ccf..c3c6627aba6ea638581f2d3c705bf30e092d6980 100644 (file)
@@ -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"
index 90f6ef8c94b697d9d8d1670e2729c06832a1e777..ad2e9066bbd6d165258ab522fed9459e75c57526 100755 (executable)
@@ -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
index d6924c85a4e28e11213d7098125a56a3d6166b87..2706dbb9cb77842224283b67d3cb88bb5078e532 100644 (file)
@@ -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
index 868ca19cd460b3cdb679e28bc5d0df52768d9c33..0e29d7617f12e584f8daa1be45674f5d07d01f07 100755 (executable)
@@ -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 (executable)
index 0000000..0a760b7
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+echo "$@" > /tmp/$$.job
+mv /tmp/$$.job /initqueue/
+>> /initqueue/work
index b233f97172f60d74ca83bbd9ee6154af4a6b4af0..ff15200741e8caf46663238eb20e6f7d82e17b02 100755 (executable)
@@ -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