[Debian-eeepc-devel] Using a pre-populated /dev for faster boot
Phil Endecott
spam_from_debian_eee at chezphil.org
Thu Oct 16 23:42:52 UTC 2008
Hi everyone,
It's clear that it's possible to save a few seconds of boot time by
using a pre-populated /dev, rather than letting udev populate it
dynamically. This would be simple in a "locked down" system where
upgrades were impossible or monolithic, but it's harder to do neatly in
Debian. What I've done is not perfect, but it's a start and I thought
I ought to write it up.
The existing code is in /etc/init.d/udev, which basically
- starts udevd
- runs udevadm trigger
- runs udevadm settle
The last two steps implement "coldplugging" - they generate hotplug
events for the devices that were already attached when you started up,
which mostly means things that are physically built in. It's this
coldplugging that takes the time; I still start udev and it looks after
any genuinely hotplugged devices. Also, I still use coldplugging for
removeable devices that are already connected at boot - i.e. usb
devices. I do this by adding the option "--subsystem-match=usb" to the
udevadm trigger call. It's only the coldplugging for built-in devices
that I've removed.
In order to pre-populate /dev with entries for the coldplugged devices,
I have hacked /etc/init.d/udev to check for and untar a file called
/etc/init-devs.tar. If it doesn't find it, it falls back to the old
behaviour. If it does exist, after untarring it does coldplugging for
only usb devices as described above.
More code in the same script generates the tar file if a sentinel file
has been created asking it to do so. The tar file should be generated
early on as other steps in the boot process may change permissions on
things in /dev.
It's important to remember that udev can be configured to carry out
arbitrary actions. So simply recording what /dev entries it created
may not be sufficient in some cases. The other thing that it commonly
does is to load modules, but I've already bypassed that by building the
drivers needed by built-in devices into the kernel.
Net devices are one class of things that do more than just create /dev
nodes, so they need to be properly coldplugged. But I've chosen to do
that in a separate init script that runs much later, concurrent with X
starting up.
Wireless networking causes further complications because this is the
one thing that I have in a module. I have currently hacked this based
on its PCI ID to run during the later network coldplugging.
So in summary I have the following in /etc/init.d/udev; I hope it's
obvious where it goes:
log_daemon_msg "Starting the hotplug events dispatcher" "udevd"
if udevd --daemon; then
log_end_msg $?
else
log_end_msg $?
fi
mkdir -p /dev/.udev/queue/ /dev/.udev/rules.d/
create_dev_root_rule /dev/.udev/
# Pre-populate /dev if this file exists. If you remove this
# file you'll get the old behaviour.
if [ -r /etc/init-devs.tar ]
then
echo "Installing initial devices"
tar -x -C / -f /etc/init-devs.tar
trigger_rules="--subsystem-match=usb"
else
trigger_rules="--subsystem-nomatch=net --attr-nomatch=vendor=0x1814"
fi
log_action_begin_msg "Synthesizing the initial hotplug events"
if udevadm trigger $trigger_rules ; then
log_action_end_msg $?
else
log_action_end_msg $?
fi
create_dev_makedev
# wait for the udevd childs to finish
log_action_begin_msg "Waiting for /dev to be fully populated"
if udevadm settle; then
log_action_end_msg 0
else
log_action_end_msg 0 'timeout'
fi
if [ -f /etc/create-init-devs ]
then
tar cf /dev/init-devs.tar /dev
# /etc is read-only or something I think
fi
and I have this in /etc/init.d/coldplug_networking:
echo "Coldplugging network devices..."
udevadm trigger --attr-match=vendor=0x1814
udevadm trigger --subsystem-match=net
udevadm settle
echo "Coldplugging network done."
To use it, I touch /etc/create-init-devs, reboot, mv /dev/init-devs.tar
/etc; rm /etc/create-init-devs. If for some reason I want to
regenerate the files (after a kernel upgrade perhaps?) I rm
/etc/init-devs.tar and do it again.
I haven't used this much yet so if anyone can see any flaws please let
me know.
The main time saving comes from doing the network startup concurrently
with the X startup; I forget exactly what that saves because I did it a
while ago, but it's perhaps 3 seconds (in part due to a sleep in
net.agent). The main /dev pre-population saves about 2 seconds.
I don't think I'm going to spend much more time on this fast boot
exercise, but there are two things that still bother me:
- I want to get the kernel's 2 second probing of the touchpad off the
critical path.
- Setting the clock takes up to a second. But I don't think it would
if we didn't have to use --directisa. So can someone remind me why we
do that?
I also look forward to improved X startup time using kernel mode
setting, but I think I'll wait until someone else implements it.
Cheers, Phil.
More information about the Debian-eeepc-devel
mailing list