The issue is present on machines such as this using lilo as the bootloader.
It can also be reproduced on the same hardware by installing the etch.5 kernel onto a clean etch install. The issue seems to be that the initramfs init script is passed the device number for the disk by lilo as the root= argument and creates a node in /dev (/dev/root) based on this. It then proceeds to attempt to mount this device as /root. Since the kernel has not yet finished detecting all devices this fails. The kernel then finishes detecting all devices and detects the root device. When using a clean install of lenny on the machine, the machine successfully boots, since the race condition is avoided by the default lilo.conf containing the argument append="rootdelay=10" which delays the attempt to mount the root device. A more preferable work around is to specify in the lilo config append="root=/dev/sda1" which overrides the lilo supplied root= argument, and causes a different path to be followed though the init script, this path detects that the /dev/sda1 device has not yet been created by udev and waits for that to happen, before then successfully mounting the root device and continuing to boot. Since this behaviour is explicitly more stable as it removes the race condition by waiting for the device to be created, I have created a patch to the init scripts provided by initramfs-tools which emulates the above behaviour but supporting the lilo root=<device_number> argument type. The patch waits for a device to be created which matches the device number passed in by lilo when the device is created, it sets the root device to the device it has detected to allow that to be mounted. Further should the device not be created within the specified delay it will create the device and allow the mount to be attempted on that.
diff -u -r ifst/usr/share/initramfs-tools/init changed/usr/share/initramfs-tools/init --- ifst/usr/share/initramfs-tools/init 2008-08-13 14:23:44.000000000 +0100 +++ changed/usr/share/initramfs-tools/init 2008-10-25 20:47:49.000000000 +0100 @@ -169,6 +169,8 @@ maybe_break mount log_begin_msg "Mounting root file system" . /scripts/${BOOT} +export dev_major= +export dev_minor= parse_numeric ${ROOT} maybe_break mountroot mountroot diff -u -r ifst/usr/share/initramfs-tools/scripts/functions changed/usr/share/initramfs-tools/scripts/functions --- ifst/usr/share/initramfs-tools/scripts/functions 2008-09-02 09:10:56.000000000 +0100 +++ changed/usr/share/initramfs-tools/scripts/functions 2008-10-25 20:47:49.000000000 +0100 @@ -251,8 +251,9 @@ return ;; esac - - mknod -m 600 /dev/root b ${major} ${minor} + dev_major=${major} + dev_minor=${minor} + #mknod -m 600 /dev/root b ${major} ${minor} ROOT=/dev/root } diff -u -r ifst/usr/share/initramfs-tools/scripts/local changed/usr/share/initramfs-tools/scripts/local --- ifst/usr/share/initramfs-tools/scripts/local 2008-08-13 14:23:44.000000000 +0100 +++ changed/usr/share/initramfs-tools/scripts/local 2008-10-25 20:47:49.000000000 +0100 @@ -52,10 +52,19 @@ while [ ! -e "${ROOT}" ] \ || ! $(get_fstype "${ROOT}" >/dev/null); do /bin/sleep 0.1 + if [ "${ROOT}" = "/dev/root" ]; then + export dev_major + export dev_minor + for d in /dev/*; do + dev_inf=$(ls -Ll $d | awk '{if ($5 < 64) printf("%d:%d\n", $5,$6); else printf("%d:%d\n", $5,$6)}') + if [ "${dev_inf}" = "${dev_major}:${dev_minor}" ]; then + ROOT=$d + fi + done + fi slumber=$(( ${slumber} - 1 )) [ ${slumber} -gt 0 ] || break done - if [ ${slumber} -gt 0 ]; then log_end_msg 0 else @@ -66,6 +75,12 @@ fi fi + if [ "${ROOT}" = "/dev/root" ]; then + log_begin_msg "failed to detect udev generated root, creating" + mknod -m 600 /dev/root b ${dev_major} ${dev_minor} + log_end_msg 0 + fi + # We've given up, but we'll let the user fix matters if they can while [ ! -e "${ROOT}" ]; do # give hint about renamed root