--- Begin Message ---
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
--- End Message ---