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

Reply via email to