Package: initscripts Version: 2.88dsf-53.2 Severity: normal Tags: patch User: [email protected] Usertags: usrinitramfs Control: block 652459 by -1
In #652459, Roger Leigh wrote: > In order to make the libraries and binaries in /usr available during > early boot, it would be desirable to be able to mount /usr in addition > to the rootfs inside the initramfs. ... > I should also mention that this can't go into unstable until some > prerequisite changes are made to util-linux and initscripts: > - initscripts needs to fsck /usr (and /etc) in checkroot.sh since > like the rootfs it's mounted read-only in the initramfs > - initscripts needs to remount /usr (and /etc) read-write as for > the rootfs This bug tracks those changes to initscripts. rleigh's proposed patch is at <http://anonscm.debian.org/gitweb/?p=users/rleigh/sysvinit.git;a=commitdiff;h=d406626ecad8988198542f270b663f3503f0b7ae> and I attach it here for your convenience. S
>From d406626ecad8988198542f270b663f3503f0b7ae Mon Sep 17 00:00:00 2001 From: Roger Leigh <[email protected]> Date: Sat, 18 May 2013 21:08:16 +0100 Subject: [PATCH] Handle mounting /usr in the initramfs --- debian/changelog | 6 + debian/src/initscripts/etc/init.d/checkroot.sh | 225 +++++++++++---------- debian/src/initscripts/lib/init/mount-functions.sh | 94 ++++++--- 3 files changed, 190 insertions(+), 135 deletions(-) diff --git a/debian/changelog b/debian/changelog index 40013dd..4f5a5a8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +sysvinit (2.88dsf-42+usrmount1) UNRELEASED; urgency=low + + * Add special handling for /usr and /etc in checkroot.sh. + + -- Roger Leigh <[email protected]> Sun, 12 May 2013 17:32:14 +0100 + sysvinit (2.88dsf-42) unstable; urgency=low [ Roger Leigh ] diff --git a/debian/src/initscripts/etc/init.d/checkroot.sh b/debian/src/initscripts/etc/init.d/checkroot.sh index 3bf506b..2910dd9 100755 --- a/debian/src/initscripts/etc/init.d/checkroot.sh +++ b/debian/src/initscripts/etc/init.d/checkroot.sh @@ -22,86 +22,38 @@ FSCK_LOGFILE=/var/log/fsck/checkroot . /lib/lsb/init-functions . /lib/init/mount-functions.sh -do_start () { - # Trap SIGINT so that we can handle user interrupt of fsck. - trap "" INT +checkfs() { + fs="$1" - # - # Set SULOGIN in /etc/default/rcS to yes if you want a sulogin to - # be spawned from this script *before anything else* with a timeout, - # like sysv does. - # - [ "$SULOGIN" = yes ] && sulogin -t 30 $CONSOLE - - KERNEL="$(uname -s)" - MACHINE="$(uname -m)" + read_fstab_entry "$fs" - read_fstab - - # - # Activate the swap device(s) in /etc/fstab. This needs to be done - # before fsck, since fsck can be quite memory-hungry. - # - ENABLE_SWAP=no - case "$KERNEL" in - Linux) - if [ "$NOSWAP" = yes ] - then - [ "$VERBOSE" = no ] || log_warning_msg "Not activating swap as requested via bootoption noswap." - ENABLE_SWAP=no - else - if [ "$swap_on_lv" = yes ] - then - [ "$VERBOSE" = no ] || log_warning_msg "Not activating swap on logical volume." - elif [ "$swap_on_file" = yes ] - then - [ "$VERBOSE" = no ] || log_warning_msg "Not activating swap on swapfile." - else - ENABLE_SWAP=yes - fi - fi - ;; - *) - ENABLE_SWAP=yes - ;; - esac - if [ "$ENABLE_SWAP" = yes ] - then - if [ "$VERBOSE" = no ] - then - log_action_begin_msg "Activating swap" - swapon -a -e >/dev/null 2>&1 - log_action_end_msg $? - else - log_daemon_msg "Activating swap" - swapon -a -v - log_end_msg $? - fi + if [ "$fs" = "/" ] ; then + fs="root" + else + MNT_CHECK="no" fi - # - # Does the root device in /etc/fstab match with the actual device ? - # If not we try to use the /dev/root alias device, and if that - # fails we create a temporary node in /run. - # - if [ "$rootcheck" = yes ] + # Does the device in /etc/fstab match with the actual device ? + # If not we try to use the /dev/root alias device (for /), and + # if that fails we create a temporary node in /run. + if [ "$MNT_CHECK" = yes ] then - ddev="$(mountpoint -qx $rootdev)" - rdev="$(mountpoint -d /)" + ddev="$(mountpoint -qx $MNT_DEV)" + rdev="$(mountpoint -d $MNT_DIR)" if [ "$ddev" != "$rdev" ] && [ "$ddev" != "4:0" ] then if [ "$(mountpoint -qx /dev/root)" = "4:0" ] then - rootdev=/dev/root + MNT_DEV=/dev/root else if \ - rm -f /run/rootdev \ - && mknod -m 600 /run/rootdev b ${rdev%:*} ${rdev#*:} \ - && [ -e /run/rootdev ] + rm -f /run/fsckdev \ + && mknod -m 600 /run/fsckdev b ${rdev%:*} ${rdev#*:} \ + && [ -e /run/fsckdev ] then - rootdev=/run/rootdev + MNT_DEV=/run/fsckdev else - rootfatal=yes + dev_fatal=yes fi fi fi @@ -110,9 +62,9 @@ do_start () { # # Bother, said Pooh. # - if [ "$rootfatal" = yes ] + if [ "$dev_fatal" = yes ] then - log_failure_msg "The device node $rootdev for the root filesystem is missing or incorrect + log_failure_msg "The device node $MNT_DEV for the $fs filesystem is missing or incorrect or there is no entry for the root filesystem listed in /etc/fstab. The system is also unable to create a temporary node in /run. This means you have to fix the problem manually." @@ -129,18 +81,18 @@ Will restart in 5 seconds." reboot -f fi - # See if we're on AC Power. If not, we're not gonna run our + # See if we're on AC Power. If not, we're not going to run our # check. If on_ac_power (in /usr/) is unavailable, behave as # before and check all file systems needing it. # Disabled AC power check until fsck can be told to only check the # file system if it is corrupt when running on battery. (bug #526398) -# if which on_ac_power >/dev/null 2>&1 && [ "$rootcheck" = yes ] +# if which on_ac_power >/dev/null 2>&1 && [ "$MNT_CHECK" = yes ] # then # on_ac_power >/dev/null 2>&1 # if [ "$?" -eq 1 ] # then # log_warning_msg "On battery power, so skipping file system check." -# rootcheck=no +# MNT_CHECK=no # fi # fi @@ -150,39 +102,39 @@ Will restart in 5 seconds." FSCKCODE=0 if [ -f /fastboot ] || grep -s -w -i "fastboot" /proc/cmdline then - [ "$rootcheck" = yes ] && log_warning_msg "Fast boot enabled, so skipping root file system check." - rootcheck=no + [ "$MNT_CHECK" = yes ] && log_warning_msg "Fast boot enabled, so skipping $fs file system check." + MNT_CHECK=no fi - if [ "$rootcheck" = yes ] + if [ "$MNT_CHECK" = yes ] then # - # Ensure that root is quiescent and read-only before fsck'ing. + # Ensure that fs is quiescent and read-only before fsck'ing. # - # mount -n -o remount,ro / would be the correct syntax but + # mount -n -o remount,ro $MNT_DIR would be the correct syntax but # mount can get confused when there is a "bind" mount defined - # in fstab that bind-mounts "/" somewhere else. + # in fstab that bind-mounts "$MNT_DIR" somewhere else. # - # So we use mount -n -o remount,ro $rootdev / but that can + # So we use mount -n -o remount,ro $MNT_DEV $MNT_DIR but that can # fail on older kernels on sparc64/alpha architectures due # to a bug in sys_mount(). # # As a compromise we try both. # if \ - ! mount -n -o remount,ro $rootdev / \ - && ! mount -n -o remount,ro -t dummytype $rootdev / 2>/dev/null \ - && ! mount -n -o remount,ro / 2>/dev/null + ! mount -n -o remount,ro $MNT_DEV $MNT_DIR \ + && ! mount -n -o remount,ro -t dummytype $MNT_DEV $MNT_DIR 2>/dev/null \ + && ! mount -n -o remount,ro $MNT_DIR 2>/dev/null then - log_failure_msg "Cannot check root file system because it is not mounted read-only." - rootcheck=no + log_failure_msg "Cannot check $fs file system because it is not mounted read-only." + MNT_CHECK=no fi fi # # The actual checking is done here. # - if [ "$rootcheck" = yes ] + if [ "$MNT_CHECK" = yes ] then if [ -f /forcefsck ] || grep -s -w -i "forcefsck" /proc/cmdline then @@ -208,11 +160,11 @@ Will restart in 5 seconds." then spinner="" fi - + if [ "$VERBOSE" = no ] then - log_action_begin_msg "Checking root file system" - logsave -s $FSCK_LOGFILE fsck $spinner $force $fix -t $roottype $rootdev + log_action_begin_msg "Checking $fs file system" + logsave -s $FSCK_LOGFILE fsck $spinner $force $fix -t $MNT_TYPE $MNT_DEV FSCKCODE=$? if [ "$FSCKCODE" = 0 ] then @@ -221,13 +173,16 @@ Will restart in 5 seconds." log_action_end_msg 1 "code $FSCKCODE" fi else - log_daemon_msg "Will now check root file system" - logsave -s $FSCK_LOGFILE fsck $spinner $force $fix -V -t $roottype $rootdev + log_daemon_msg "Will now check $fs file system" + logsave -s $FSCK_LOGFILE fsck $spinner $force $fix -V -t $MNT_TYPE $MNT_DEV FSCKCODE=$? log_end_msg $FSCKCODE fi fi + # Remove /run/fsckdev if we created it. + rm -f /run/fsckdev + # # If there was a failure, drop into single-user mode. # @@ -242,12 +197,12 @@ Will restart in 5 seconds." elif [ "$FSCKCODE" -gt 3 ] then # Surprise! Re-directing from a HERE document (as in "cat << EOF") - # does not work because the root is currently read-only. - log_failure_msg "An automatic file system check (fsck) of the root filesystem failed. + # does not work because the fs is currently read-only. + log_failure_msg "An automatic file system check (fsck) of the $fs filesystem failed. A manual fsck must be performed, then the system restarted. The fsck should be performed in maintenance mode with the -root filesystem mounted in read-only mode." - log_warning_msg "The root filesystem is currently mounted in read-only mode. +$fs filesystem mounted in read-only mode." + log_warning_msg "The $fs filesystem is currently mounted in read-only mode. A maintenance shell will now be started. After performing system maintenance, press CONTROL-D to terminate the maintenance shell and restart the system." @@ -262,7 +217,7 @@ Will restart in 5 seconds." reboot -f elif [ "$FSCKCODE" -gt 1 ] then - log_failure_msg "The file system check corrected errors on the root partition + log_failure_msg "The file system check corrected errors on the $fs partition but requested that the system be restarted." log_warning_msg "The system will be restarted in 5 seconds." sleep 5 @@ -271,20 +226,87 @@ but requested that the system be restarted." fi # - # Remount root to final mode (rw or ro). + # Remount fs to final mode (rw or ro). # # See the comments above at the previous "mount -o remount" # for an explanation why we try this twice. # - if ! mount -n -o remount,$rootopts,$rootmode $fstabroot / 2>/dev/null + if ! mount -n -o remount,$MNT_OPTS,$MNT_MODE $MNT_DEV $MNT_DIR 2>/dev/null + then + mount -n -o remount,$MNT_OPTS,$MNT_MODE $MNT_DIR + fi +} + +do_start () { + # Trap SIGINT so that we can handle user interrupt of fsck. + trap "" INT + + # + # Set SULOGIN in /etc/default/rcS to yes if you want a sulogin to + # be spawned from this script *before anything else* with a timeout, + # like sysv does. + # + [ "$SULOGIN" = yes ] && sulogin -t 30 $CONSOLE + + KERNEL="$(uname -s)" + MACHINE="$(uname -m)" + + read_fstab_swap + + # + # Activate the swap device(s) in /etc/fstab. This needs to be done + # before fsck, since fsck can be quite memory-hungry. + # + ENABLE_SWAP=no + case "$KERNEL" in + Linux) + if [ "$NOSWAP" = yes ] + then + [ "$VERBOSE" = no ] || log_warning_msg "Not activating swap as requested via bootoption noswap." + ENABLE_SWAP=no + else + if [ "$swap_on_lv" = yes ] + then + [ "$VERBOSE" = no ] || log_warning_msg "Not activating swap on logical volume." + elif [ "$swap_on_file" = yes ] + then + [ "$VERBOSE" = no ] || log_warning_msg "Not activating swap on swapfile." + else + ENABLE_SWAP=yes + fi + fi + ;; + *) + ENABLE_SWAP=yes + ;; + esac + if [ "$ENABLE_SWAP" = yes ] then - mount -n -o remount,$rootopts,$rootmode / + if [ "$VERBOSE" = no ] + then + log_action_begin_msg "Activating swap" + swapon -a -e >/dev/null 2>&1 + log_action_end_msg $? + else + log_daemon_msg "Activating swap" + swapon -a -v + log_end_msg $? + fi fi + + # fsck and remount filesystems + for fs in / /etc /usr; do + if mountpoint -q "$fs"; then + checkfs "$fs" + fi + done + # If possible, migrate /etc/mtab to be a symlink to # /proc/mounts. Note that not all systems e.g. Hurd currently # support this. - if [ "$rootmode" != "ro" ]; then + read_fstab_entry / + if [ "$MNT_MODE" != "ro" ]; then mtab_migrate fi @@ -293,11 +315,6 @@ but requested that the system be restarted." restorecon /etc/mtab fi - # - # Remove /run/rootdev if we created it. - # - rm -f /run/rootdev - # Update mount options for mounts created in early boot # S01mountkernfs.sh /etc/init.d/mountkernfs.sh reload diff --git a/debian/src/initscripts/lib/init/mount-functions.sh b/debian/src/initscripts/lib/init/mount-functions.sh index 345fdb6..81dd510 100644 --- a/debian/src/initscripts/lib/init/mount-functions.sh +++ b/debian/src/initscripts/lib/init/mount-functions.sh @@ -13,6 +13,48 @@ fstab_files() fi } +# Resolve device node from a name. This expands any LABEL or UUID. +# $1=name +# Resolved name is echoed. +resolve_device() { + 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='/' + newroot= + for s in $DEV; do + newroot="${newroot:+${newroot}\\x2f}${s}" + done + unset IFS + DEV="${newroot}" + fi + esac + DEV="/dev/disk/by-label/${DEV}" + ;; + UUID=*) + DEV="/dev/disk/by-uuid/${DEV#UUID=}" + ;; + esac + # Only canonicalise if a valid file, in case $DEV isn't a filename + [ -e "$DEV" ] && DEV=$(readlink -f "$DEV") + echo "$DEV" +} + # $1: directory is_empty_dir() { for FILE in $1/* $1/.* @@ -36,13 +78,7 @@ selinux_enabled () { # device node, # 2) Swap that is on a md device or a file that may be on a md # device, -_read_fstab () { - echo "fstabroot=/dev/root" - echo "rootdev=none" - echo "roottype=none" - echo "rootopts=defaults" - echo "rootmode=rw" - echo "rootcheck=no" +_read_fstab_swap () { echo "swap_on_lv=no" echo "swap_on_file=no" @@ -70,31 +106,17 @@ _read_fstab () { *) ;; esac - [ "$MTPT" != "/" ] && continue - echo rootdev=\"$DEV\" - echo fstabroot=\"$DEV\" - echo rootopts=\"$OPTS\" - echo roottype=\"$FSTYPE\" - ( [ "$PASS" != 0 ] && [ "$PASS" != "" ] ) && echo rootcheck=yes - ( [ "$FSTYPE" = "nfs" ] || [ "$FSTYPE" = "nfs4" ] ) && echo rootcheck=no - case "$OPTS" in - ro|ro,*|*,ro|*,ro,*) - echo rootmode=ro - ;; - esac done < "$file" fi done } # Read /etc/fstab, looking for: -# 1) The root filesystem, resolving LABEL=*|UUID=* entries to the -# device node, -# 2) Swap that is on a md device or a file that may be on a md +# 1) Swap that is on a md device or a file that may be on a md # device, -read_fstab () { - eval "$(_read_fstab)" +read_fstab_swap () { + eval "$(_read_fstab_swap)" } # Find a specific fstab entry @@ -103,11 +125,14 @@ read_fstab () { _read_fstab_entry () { # Not found by default. echo "MNT_FSNAME=" + echo "MNT_DEV=" echo "MNT_DIR=" echo "MNT_TYPE=" echo "MNT_OPTS=" echo "MNT_FREQ=" echo "MNT_PASS=" + echo "MNT_CHECK=no" + echo "MNT_MODE=rw" fstab_files | while read file; do if [ -f "$file" ]; then @@ -122,11 +147,19 @@ _read_fstab_entry () { [ "$MNT_TYPE" = "$2" ] || continue; fi echo "MNT_FSNAME=$MNT_FSNAME" + echo "MNT_DEV=$(resolve_device "$MNT_FSNAME")" echo "MNT_DIR=$MNT_DIR" echo "MNT_TYPE=$MNT_TYPE" echo "MNT_OPTS=$MNT_OPTS" echo "MNT_FREQ=$MNT_FREQ" echo "MNT_PASS=$MNT_PASS" + ( [ "$MNT_PASS" != 0 ] && [ "$MNT_PASS" != "" ] ) && echo "MNT_CHECK=yes" + ( [ "$MNT_TYPE" = "nfs" ] || [ "$MNT_TYPE" = "nfs4" ] ) && echo "MNT_CHECK=no" + case "$MNT_OPTS" in + ro|ro,*|*,ro|*,ro,*) + echo "MNT_MODE=ro" + ;; + esac break 2 fi MNT_DIR="" @@ -468,9 +501,6 @@ mount_run () { MNTMODE="$1" - # Needed to determine if root is being mounted read-only. - read_fstab - # # Get some writable area available before the root is checked # and remounted. Note that /run may be handed over from the @@ -598,7 +628,7 @@ mount_shm () # mount_tmp () { - MNTMODE="$1" + TMP_MODE="$1" # If /tmp is a symlink, make sure the linked-to directory exists. if [ -L /tmp ] && [ ! -d /tmp ]; then @@ -616,7 +646,9 @@ mount_tmp () # If root is read only, default to mounting a tmpfs on /tmp, # unless one is due to be mounted from fstab. - if [ "$RAMTMP" != "yes" ] && [ rw != "$rootmode" ]; then + # Needed to determine if root is being mounted read-only. + read_fstab_entry / + if [ "$RAMTMP" != "yes" ] && [ rw != "$MNT_MODE" ]; then # If there's an entry in fstab for /tmp (any # filesystem type, not just tmpfs), then we don't need # a tmpfs on /tmp by default. @@ -658,12 +690,12 @@ mount_tmp () # Mount /tmp as tmpfs if enabled. if [ yes = "$RAMTMP" ]; then - domount "$MNTMODE" tmpfs shmfs /tmp tmpfs "-o${NODEV}nosuid$TMP_OPT" + domount "$TMP_MODE" tmpfs shmfs /tmp tmpfs "-o${NODEV}nosuid$TMP_OPT" # Make sure we don't get cleaned touch /tmp/.tmpfs else # When root is still read only, this will fail. - if [ mount_noupdate != "$MNTMODE" ] && [ rw = "$rootmode" ]; then + if [ mount_noupdate != "$TMP_MODE" ] && [ rw = "$MNT_MODE" ]; then chmod "$TMP_MODE" /tmp fi fi -- 2.0.1
_______________________________________________ Pkg-sysvinit-devel mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-sysvinit-devel

