initqueue now loops until /dev/root exists or root is mounted

init now has the following points to inject scripts:

/cmdline/*.sh
   scripts for command line parsing

/pre-udev/*.sh
   scripts to run before udev is started

/pre-trigger/*.sh
   scripts to run before the main udev trigger is pulled

/initqueue/*.sh
   runs in parallel to the udev trigger
   Udev events can add scripts here with /sbin/initqueue.
   If /sbin/initqueue is called with the "--onetime" option, the script
   will be removed after it was run.
   If /initqueue/work is created and udev >= 143 then this loop can
   process the jobs in parallel to the udevtrigger.
   If the udev queue is empty and no root device is found or no root
   filesystem was mounted, the user will be dropped to a shell after
   a timeout.
   Scripts can remove themselves from the initqueue by "rm $job".

/pre-mount/*.sh
   scripts to run before the root filesystem is mounted
   NFS is an exception, because it has no device node to be created
   and mounts in the udev events

/mount/*.sh
   scripts to mount the root filesystem
   NFS is an exception, because it has no device node to be created
   and mounts in the udev events
   If the udev queue is empty and no root device is found or no root
   filesystem was mounted, the user will be dropped to a shell after
   a timeout.

/pre-pivot/*.sh
   scripts to run before the real init is executed and the initramfs
   disappears
   All processes started before should be killed here.

The behaviour of the dmraid module demonstrates how to use the new
mechanism. If it detects a device which is part of a raidmember from a
udev rule, it installs a job to scan for dmraid devices, if the udev
queue is empty. After a scan, it removes itsself from the queue.
master
Harald Hoyer 2009-07-03 17:44:10 +02:00
parent 5b2db7d177
commit 58dbb43eac
12 changed files with 84 additions and 48 deletions

View File

@ -7,6 +7,6 @@
SUBSYSTEM!="block", GOTO="luks_end"
ACTION!="add|change", GOTO="luks_end"

ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue /sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}"
ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue --onetime /sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}"

LABEL="luks_end"

View File

@ -7,6 +7,6 @@
SUBSYSTEM!="block", GOTO="luks_end"
ACTION!="add|change", GOTO="luks_end"

ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue /sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}"
ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue --onetime /sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}"

LABEL="luks_end"

View File

@ -0,0 +1,12 @@
# This file causes block devices with Linux RAID (mdadm) signatures to
# automatically cause mdadm to be run.
# See udev(8) for syntax

SUBSYSTEM!="block", GOTO="dm_end"
ACTION!="add|change", GOTO="dm_end"

ENV{ID_FS_TYPE}=="linux_raid_member", GOTO="dm_end"

ENV{ID_FS_TYPE}=="*_raid_member", RUN+="/sbin/initqueue /sbin/dmraid_scan \$0"

LABEL="dm_end"

9
modules.d/90dmraid/dmraid.sh Normal file → Executable file
View File

@ -1,3 +1,8 @@
dmraid -ay -Z
udevadm settle --timeout=30 >/dev/null 2>&1
#!/bin/sh

if udevadm settle --timeout=0 >/dev/null 2>&1; then
# run dmraid if udev has settled
dmraid -ay -Z
[ -e "$job" ] && rm -f "$job"
fi


View File

@ -1,4 +1,5 @@
#!/bin/bash
dracut_install dmraid
inst_hook pre-mount 10 "$moddir/dmraid.sh"
inst "$moddir/dmraid.sh" /sbin/dmraid_scan
inst_rules 64-md-raid.rules
inst_rules "$moddir/61-dmraid.rules"

View File

@ -5,4 +5,8 @@ if [ "${root%%:*}" = "block" ]; then
printf 'SYMLINK=="%s", SYMLINK+="root"\n' \
${root#block:/dev/}
) >> /etc/udev/rules.d/99-mount.rules
(
printf '[ -e "%s" ] && { ln -s "%s" /dev/root; rm "$job"; }\n' \
"${root#block:}" "${root#block:}"
) >> /initqueue/blocksymlink.sh
fi

View File

@ -1,4 +1,5 @@
#!/bin/sh
dracut_install ln
inst_hook cmdline 95 "$moddir/parse-block.sh"
inst_hook pre-udev 30 "$moddir/block-genrules.sh"
inst_hook mount 99 "$moddir/mount-root.sh"

View File

@ -16,36 +16,6 @@ emergency_shell()
sh -i
}

do_initqueue()
{
while :; do
# bail out, if we have mounted the root filesystem
[ -d "$NEWROOT/proc" ] && break;

# check if root can be mounted
[ -e /dev/root ] && break;

if [ $UDEVVERSION -ge 143 ]; then
udevadm settle --exit-if-exists=/initqueue/work --exit-if-exists=/dev/root
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;

# check if root can be mounted
[ -e /dev/root ] && break;
done
done
}

export PATH=/sbin:/bin:/usr/sbin:/usr/bin
export TERM=linux
NEWROOT="/sysroot"
@ -116,7 +86,47 @@ source_all pre-trigger
# then the rest
udevadm trigger $udevtriggeropts >/dev/null 2>&1

do_initqueue
i=0
while :; do
# bail out, if we have mounted the root filesystem
[ -d "$NEWROOT/proc" ] && break;

# check if root can be mounted
[ -e /dev/root ] && break;

if [ $UDEVVERSION -ge 143 ]; then
udevadm settle --exit-if-exists=/initqueue/work --exit-if-exists=/dev/root
else
udevadm settle --timeout=30
fi
unset queuetriggered
if [ -f /initqueue/work ]; then
rm /initqueue/work
queuetriggered="1"
fi
for job in /initqueue/*.sh; do
[ -e "$job" ] || break
job=$job . $job

# bail out, if we have mounted the root filesystem
[ -d "$NEWROOT/proc" ] && break;
# check if root can be mounted
[ -e /dev/root ] && break;
done

[ -n "$queuetriggered" ] && continue

if udevadm settle --timeout=0 >/dev/null 2>&1; then
# no more udev jobs
sleep 0.5
i=$(($i+1))
[ $i -gt 20 ] && getarg rdshell \
&& { flock -s 9 ; emergency_shell; } 9>/.console_lock
fi
done
unset job
unset queuetriggered

# pre-mount happens before we try to mount the root filesystem,
# and happens once.
@ -124,23 +134,19 @@ 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
while :; do
[ -d "$NEWROOT/proc" ] && break;

for f in /mount/*.sh; do
[ -f "$f" ] && . "$f"
do_initqueue
[ "$ROOTFS_MOUNTED" ] && break;
[ -d "$NEWROOT/proc" ] && break;
done

sleep 0.5
i=$(($i+1))
{ flock -s 9 ; [ $i -gt 20 ] && emergency_shell; } 9>/.console_lock
[ $i -gt 20 ] && getarg rdshell \
&& { flock -s 9 ; emergency_shell; } 9>/.console_lock
done

# pre pivot scripts are sourced just before we switch over to the new root.

View File

@ -1,5 +1,12 @@
#!/bin/sh

echo "$@" > /tmp/$$.job
mv /tmp/$$.job /initqueue/
if [ "$1" = "--onetime" ]; then
onetime="yes"
shift
fi
echo "$@" > /tmp/$$.sh
if [ -n "$onetime" ]; then
echo '[ -e "$job" ] && rm "$job"' >> /tmp/$$.sh
fi
mv /tmp/$$.sh /initqueue/
>> /initqueue/work

View File

@ -38,7 +38,7 @@ test_setup() {
initdir=overlay
. $basedir/dracut-functions
dracut_install sfdisk mke2fs poweroff cp umount
inst_simple ./create-root.sh /pre-mount/01create-root.sh
inst_simple ./create-root.sh /initqueue/01create-root.sh
)
# create an initramfs that will create the target root filesystem.

View File

@ -81,7 +81,7 @@ test_setup() {
initdir=overlay
. $basedir/dracut-functions
dracut_install sfdisk mke2fs poweroff cp umount
inst_simple ./create-root.sh /pre-mount/01create-root.sh
inst_simple ./create-root.sh /initqueue/01create-root.sh
)
# create an initramfs that will create the target root filesystem.

View File

@ -184,7 +184,7 @@ make_encrypted_root() {
initdir=overlay
. $basedir/dracut-functions
dracut_install mke2fs poweroff cp umount
inst_simple ./create-root.sh /pre-mount/01create-root.sh
inst_simple ./create-root.sh /initqueue/01create-root.sh
)

# create an initramfs that will create the target root filesystem.