Package: initramfs-tools Version: 0.106 Severity: wishlist Tags: patch Hi,
the attached patch adds an event based loop for block devices to the init script. New blockdevices are recorded in /run/initramfs/block-events by an udev rule as they appear. The init script repeadately waits for that and then calls /scripts/local-block/* with a list of new devices storedin NEWDEVS until $ROOT and $resume (if set) exists or a timeout is reached. This fixes the problem that USB devices take too long to be discovered and crypto, raid, lvm or multipath can't be started on them. It also adds support for arbitrary nestings of them, e.g. raid5 over raid1. For the event loop I needed the $resume device translated to the device node earlier. This was previously done in scripts/local-premount/resume. It was essentially the same code used to translate the $ROOT so I created a new function translate_device() in script/functions and used that for both $ROOT and $resume. Note: hooks/block-event and scripts/block-event are executable, not represented in the patch. MfG Goswin -- System Information: Debian Release: wheezy/sid APT prefers unstable APT policy: (500, 'unstable') Architecture: amd64 (x86_64) Kernel: Linux 3.2.0-2-amd64 (SMP w/4 CPU cores) Locale: LANG=C, LC_CTYPE=de_DE (charmap=ISO-8859-1) Shell: /bin/sh linked to /bin/dash Versions of packages initramfs-tools depends on: ii cpio 2.11-7 ii klibc-utils 2.0~rc3-1 ii module-init-tools 3.16-1 ii udev 175-3.1 Versions of packages initramfs-tools recommends: ii busybox 1:1.19.3-5 Versions of packages initramfs-tools suggests: ii bash-completion 1:1.99-3 -- no debconf information
Description: event based loop This patch adds an event based loop for block devices to the init script. New blockdevices are recorded in /run/initramfs/block-events by an udev rule as they appear. The init script repeadately waits for that and then calls /scripts/local-block/* with a list of new devices storedin NEWDEVS until $ROOT and $resume (if set) exists or a timeout is reached. . This fixes the problem that USB devices take too long to be discovered and crypto, raid, lvm or multipath can't be started on them. It also adds support for arbitrary nestings of them, e.g. raid5 over raid1. . For the event loop I needed the $resume device translated to the device node earlier. This was previously done in scripts/local-premount/resume. It was essentially the same code used to translate the $ROOT so I created a new function translate_device() in script/functions and used that for both $ROOT and $resume. . Note: hooks/block-event and scripts/block-event are executable, not represented in the patch. Author: Goswin von Brederlow Last-Update: 2012-06-23 -- diff -Nru initramfs-tools-0.106/hooks/block-event initramfs-tools-0.106a0mrvn1/hooks/block-event --- initramfs-tools-0.106/hooks/block-event 1970-01-01 01:00:00.000000000 +0100 +++ initramfs-tools-0.106a0mrvn1/hooks/block-event 2012-06-23 18:52:54.000000000 +0200 @@ -0,0 +1,13 @@ +#!/bin/sh + +mkdir -p $DESTDIR/etc/udev/rules.d + +cat > $DESTDIR/etc/udev/rules.d/99-block-event.rules << EOF +# we are only interested in add and change actions for block devices +ACTION=="remove", GOTO="block_event_end" +SUBSYSTEM!="block", GOTO="block_event_end" + +RUN+="/scripts/block-event $name" + +LABEL="block_event_end" +EOF diff -Nru initramfs-tools-0.106/init initramfs-tools-0.106a0mrvn1/init --- initramfs-tools-0.106/init 2012-06-06 15:04:52.000000000 +0200 +++ initramfs-tools-0.106a0mrvn1/init 2012-06-23 21:14:40.000000000 +0200 @@ -69,41 +69,10 @@ init=${x#init=} ;; root=*) - ROOT=${x#root=} - case $ROOT in - LABEL=*) - ROOT="${ROOT#LABEL=}" - - # support any / in LABEL= path (escape to \x2f) - case "${ROOT}" in - */*) - if command -v sed >/dev/null 2>&1; then - ROOT="$(echo ${ROOT} | sed 's,/,\\x2f,g')" - else - if [ "${ROOT}" != "${ROOT#/}" ]; then - ROOT="\x2f${ROOT#/}" - fi - if [ "${ROOT}" != "${ROOT%/}" ]; then - ROOT="${ROOT%/}\x2f" - fi - IFS='/' - newroot= - for s in $ROOT; do - newroot="${newroot:+${newroot}\\x2f}${s}" - done - unset IFS - ROOT="${newroot}" - fi - esac - ROOT="/dev/disk/by-label/${ROOT}" - ;; - UUID=*) - ROOT="/dev/disk/by-uuid/${ROOT#UUID=}" - ;; - /dev/nfs) + ROOT=$(translate_device ${x#root=}) + if [ $ROOT = "/dev/nfs" ]; then [ -z "${BOOT}" ] && BOOT=nfs - ;; - esac + fi ;; rootflags=*) ROOTFLAGS="-o ${x#rootflags=}" @@ -190,7 +159,7 @@ export noresume unset resume else - resume=${RESUME:-} + resume=$(translate_device ${RESUME:-}) fi maybe_break top @@ -205,6 +174,39 @@ [ -n "${netconsole}" ] && modprobe netconsole netconsole="${netconsole}" +maybe_break events +TIMEOUT=20 +COUNT=$TIMEOUT +echo "Waiting for $ROOT" +if [ -n "$resume" ]; then + echo "Waiting for $resume" +fi +# run at least once +touch /dev/.initramfs/block-events +while [ $COUNT -gt 0 ]; do + sleep 1 + COUNT=$((COUNT-1)) + echo -ne "Waiting ($COUNT) \r" + wait_for_udev + mv 2>/dev/null /run/initramfs/block-events /run/initramfs/block-events.processing && \ + { + echo "Found new block devices... " + COUNT=$TIMEOUT + export NEWDEVS=$(cat /run/initramfs/block-events.processing) + wait_for_udev + run_scripts /scripts/local-block + } + if [ -n "$resume" ]; then + if [ -e $ROOT ] && [ -e $resume ]; then + break + fi + else + if [ -e $ROOT ]; then + break; + fi + fi +done + maybe_break premount [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-premount" run_scripts /scripts/init-premount @@ -309,6 +311,10 @@ unset readonly unset resume unset resume_offset +unset COUNT +unset TIMEOUT +unset WAIT +unset NEWDEVS # Move virtual filesystems over to the real filesystem mount -n -o move /sys ${rootmnt}/sys diff -Nru initramfs-tools-0.106/scripts/block-event initramfs-tools-0.106a0mrvn1/scripts/block-event --- initramfs-tools-0.106/scripts/block-event 1970-01-01 01:00:00.000000000 +0100 +++ initramfs-tools-0.106a0mrvn1/scripts/block-event 2012-06-23 18:48:41.000000000 +0200 @@ -0,0 +1,3 @@ +#!/bin/sh + +echo >>/run/initramfs/block-events $1 diff -Nru initramfs-tools-0.106/scripts/functions initramfs-tools-0.106a0mrvn1/scripts/functions --- initramfs-tools-0.106/scripts/functions 2012-06-06 15:04:52.000000000 +0200 +++ initramfs-tools-0.106a0mrvn1/scripts/functions 2012-06-23 19:34:36.000000000 +0200 @@ -423,3 +423,47 @@ command -v udevadm >/dev/null 2>&1 || return 0 udevadm settle ${1:+--timeout=$1} } + +# Translate device name to device node +# Parameter: root or resume argument +# Echos path to device node to stdout +translate_device() +{ + local DEV newdev + DEV=$1 + case $DEV in + LABEL=*) + DEV="${DEV#LABEL=}" + + # support any / in LABEL= path (escape to \x2f) + case "${DEV}" in + */*) + if command -v sed >/dev/null 2>&1; then + DEV="$(echo ${DEV} | sed 's,/,\\x2f,g')" + else + if [ "${DEV}" != "${DEV#/}" ]; then + DEV="\x2f${DEV#/}" + fi + if [ "${DEV}" != "${DEV%/}" ]; then + DEV="${DEV%/}\x2f" + fi + IFS='/' + newdev= + for s in $DEV; do + newdev="${newdev:+${newdev}\\x2f}${s}" + done + unset IFS + DEV="${newdev}" + fi + esac + DEV="/dev/disk/by-label/${DEV}" + ;; + UUID=*) + DEV="/dev/disk/by-uuid/${DEV#UUID=}" + ;; + /dev/nfs) + DEV= + ;; + esac + echo $DEV +} diff -Nru initramfs-tools-0.106/scripts/local-premount/resume initramfs-tools-0.106a0mrvn1/scripts/local-premount/resume --- initramfs-tools-0.106/scripts/local-premount/resume 2010-06-17 14:15:13.000000000 +0200 +++ initramfs-tools-0.106a0mrvn1/scripts/local-premount/resume 2012-06-23 21:15:34.000000000 +0200 @@ -19,38 +19,6 @@ exit 0 fi -case $resume in -LABEL=*) - resume="${resume#LABEL=}" - - # support any / in LABEL= path (escape to \x2f) - case "${resume}" in - */*) - if command -v sed >/dev/null 2>&1; then - resume="$(echo ${resume} | sed 's,/,\\x2f,g')" - else - if [ "${resume}" != "${resume#/}" ]; then - resume="\x2f${resume#/}" - fi - if [ "${resume}" != "${resume%/}" ]; then - resume="${resume%/}\x2f" - fi - IFS='/' - newresume= - for s in $resume; do - newresume="${newresume:+${newresume}\\x2f}${s}" - done - unset IFS - resume="${newresume}" - fi - esac - resume="/dev/disk/by-label/${resume}" - ;; -UUID=*) - resume="/dev/disk/by-uuid/${resume#UUID=}" - ;; -esac - [ ! -e "${resume}" ] && exit 0 [ ! -e /sys/power/resume ] && exit 0