[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#652459: initramfs-tools: [patch] Please support mounting of /usr in the initramfs



Package: initramfs-tools
Version: 0.99
Severity: normal
Tags: patch

Hi,

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.

This patch implements a generic solution into two parts
1) Generation of /etc/fstab in the initramfs, including the rootfs
   and all the filesystems desired to be mounted
2) In local mountroot(), rather than just mounting the rootfs, loop
   over all mountpoints in /etc/fstab and mount them.

Note that this can replace the ROOT= option with the fstab entry alone,
though if set, ROOT= supercedes the root entry.  If the host /etc/fstab
does not contain a root entry, a dummy one is generated to ensure that
the rootfs is always the first entry in the initramfs fstab.  This
also means that the rootfs may be mounted with the options in
/etc/fstab.

This isn't intended to apply directly--it's more of a proof of concept.
I've tested the fstab generator; I haven't yet tested local mountroot().
Not being totally familiar with the initramfs internals, it might also
need:

- inclusion of modules for the additional filesystems
- ability to NFS mount filesystems other than the rootfs, i.e.
  it might need nfsmount for local (not that this is a useful use
  case)

Also note that the initramfs mount option (patch sent upstream) is not
yet in mount(8), and it would need to be before the option could be
used.


Regards,
Roger
>From 77ff35762d8038a546c342e5c2fb46dca5977db1 Mon Sep 17 00:00:00 2001
From: Roger Leigh <Roger Leigh rleigh@debian.org>
Date: Sat, 17 Dec 2011 11:47:59 +0000
Subject: [PATCH 1/2] Create /etc/fstab in the initramfs

Known special mounts (/, /etc, /usr), and those marked with the
"initramfs" option are added to /etc/fstab in the initramfs.
This means that it becomes possible to mount filesystems in
addition to root in the initramfs.

The primary motivation for this change is to permit /usr to be
mounted early, thus guaranteeing the presence of programs and
libraries from /usr during early boot, solving a long-standing
problem of needing to move an increasing number of libraries
and other files to the root filesystem.  It additionally permits
mounting of /etc separately, thereby permitting it to be
encrypted and/or writable while the root filesystem is
unencrypted and/or read-only.

Note that mount(8) breaks due to the new initramfs option being
unrecognised.  A patch to add this option has been submitted
upstream.  The option is filtered out in the generated fstab to
avoid breaking mount in the initramfs.
---
 mkinitramfs       |    3 ++
 scripts/functions |   78 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/mkinitramfs b/mkinitramfs
index 039eb81..8196b58 100755
--- a/mkinitramfs
+++ b/mkinitramfs
@@ -268,6 +268,9 @@ if [ -n "${ROOT:-}" ]; then
 	echo "ROOT=${ROOT}" > ${DESTDIR}/conf/conf.d/root
 fi
 
+# fstab creation
+create_initramfs_fstab > ${DESTDIR}/etc/fstab
+
 if ! command -v ldd >/dev/null 2>&1 ; then
 	echo "WARNING: no ldd around - install libc-bin" >&2
 	exit 1
diff --git a/scripts/functions b/scripts/functions
index 765802f..43c6adf 100644
--- a/scripts/functions
+++ b/scripts/functions
@@ -295,6 +295,84 @@ parse_numeric() {
 	fi
 }
 
+# Search for filesystems needed for mounting in the initramfs.  These
+# may be required filesystems such as the rootfs, or have initramfs in
+# the options.  Strip initramfs option from the generated fstab, in
+# case the initramfs mount chokes on it.  If no root filesystem exists
+# in /etc/fstab, create a dummy entry (needed so that the local mount
+# can fill in the missing parts from the command-line etc.).
+# Echos fstab format to stdout
+parse_initramfs_fstab () {
+	local rootfound copy file MNT_FSNAME MNT_DIR MNT_TYPE MNT_OPTS MNT_FREQ MNT_PASS MNT_JUNK
+	rootfound="no"
+	for file in /etc/fstab /etc/fstab.d/*.fstab; do
+		if [ -f "${file}" ]; then
+			while read MNT_FSNAME MNT_DIR MNT_TYPE MNT_OPTS MNT_FREQ MNT_PASS MNT_JUNK
+			do
+				case "${MNT_FSNAME}" in
+				    ""|\#*)
+					continue;;
+				esac
+
+				copy="no"
+
+				case "${MNT_DIR}" in
+				    /)
+					copy="yes"
+					rootfound="yes"
+					;;
+				    /etc|/usr)
+					copy="yes"
+					;;
+				esac
+
+				case "${MNT_OPTS}" in
+				    initramfs)
+					copy="yes"
+					MNT_OPTS="defaults"
+					;;
+				    initramfs,*)
+					copy="yes"
+					MNT_OPTS="${MNT_OPTS#initramfs,}"
+					;;
+				    *,initramfs)
+					copy="yes"
+					MNT_OPTS="${MNT_OPTS%,initramfs}"
+;;
+				    *,initramfs,*)
+					copy="yes"
+					MNT_OPTS="${MNT_OPTS/,initramfs,/,}"
+					;;
+				esac
+
+				if [ "${copy}" != "yes" ]; then
+				    continue;
+				fi
+
+				echo "${MNT_FSNAME} ${MNT_DIR} ${MNT_TYPE} ${MNT_OPTS} ${MNT_FREQ} ${MNT_PASS}"
+		done < "${file}"
+	fi
+	done
+
+	if [ "${rootfound}" = "no" ]; then
+	    MNT_FSNAME="no_root_filesystem_set_in_fstab"
+	    MNT_DIR="/"
+	    MNT_TYPE="unknown"
+	    MNT_OPTS="defaults"
+	    MNT_FREQ="0"
+	    MNT_PASS="0"
+	    echo "${MNT_FSNAME} ${MNT_DIR} ${MNT_TYPE} ${MNT_OPTS} ${MNT_FREQ} ${MNT_PASS}"
+	fi
+}
+
+# Create fstab for filesystems needed for mounting in the initramfs.
+# The list is sorted on the mountpoint to ensure that the rootfs is
+# listed first.
+# Echos fstab format to stdout
+create_initramfs_fstab () {
+	parse_initramfs_fstab | sort -k 2,2
+}
+
 # Parameter: device node to check
 # Echos fstype to stdout
 # Return value: indicates if an fs could be recognized
-- 
1.7.7.3

>From 70c85db65a7d7194b20acafd697cdbd468cf3b05 Mon Sep 17 00:00:00 2001
From: Roger Leigh <Roger Leigh rleigh@debian.org>
Date: Sat, 17 Dec 2011 13:08:14 +0000
Subject: [PATCH 2/2] scripts/local: Make use of fstab file for mounting
 rootfs

Mount all filesystems in fstab in addition to the rootfs.
---
 scripts/local |   81 ++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 57 insertions(+), 24 deletions(-)

diff --git a/scripts/local b/scripts/local
index 521e69a..a049069 100644
--- a/scripts/local
+++ b/scripts/local
@@ -76,35 +76,68 @@ pre_mountroot()
 
 mountroot()
 {
-	pre_mountroot
+	while read MNT_FSNAME MNT_DIR MNT_TYPE MNT_OPTS MNT_FREQ MNT_PASS MNT_JUNK
+	do
+		# Skip comments
+		case "${MNT_FSNAME}" in
+		""|\#*)
+			continue;;
+		esac
 
-	# Get the root filesystem type if not set
-	if [ -z "${ROOTFSTYPE}" ]; then
-		FSTYPE=$(get_fstype "${ROOT}")
-	else
-		FSTYPE=${ROOTFSTYPE}
-	fi
+		# First fstab entry is guaranteed to be the rootfs
+		case "${MNT_DIR}" in
+		/)
+			# If ROOT is set, then override all fstab
+			# settings, otherwise set ROOT to the fstab
+			# value
+			if [ -n "${ROOT}" ]; then
+				MNT_FSNAME="${ROOT}"
+			else
+				ROOT="${MNT_FSNAME}"
+			fi
+			# Set mount options
+			if [ -n "${ROOTFLAGS}" ]; then
+				MNT_OPTS="${ROOTFLAGS},$MNT_OPTS"
+			else
+				MNT_OPTS="-o ${MNT_OPTS}"
+			fi
+			# Get the root filesystem type if not set
+			if [ -z "${ROOTMNT_TYPE}" ]; then
+				MNT_TYPE=$(get_fstype "${MNT_FSNAME}")
+			else
+				MNT_TYPE=${ROOTFSTYPE}
+			fi
 
-	[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-premount"
-	run_scripts /scripts/local-premount
-	[ "$quiet" != "y" ] && log_end_msg
+			pre_mountroot
 
-	if [ "${readonly}" = "y" ]; then
-		roflag=-r
-	else
-		roflag=-w
-	fi
+			[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-premount"
+			run_scripts /scripts/local-premount
+			[ "$quiet" != "y" ] && log_end_msg
+			;;
+		*)
+		    MNT_OPTS="-o ${MNT_OPTS}"
+		    ;;
+		esac
 
-	# FIXME This has no error checking
-	modprobe ${FSTYPE}
+		if [ "${MNT_TYPE}" != "unknown" ]; then
+			MNT_TYPE="-t ${MNT_TYPE}"
+		else
+			MNT_TYPE=""
+		fi
 
-	# FIXME This has no error checking
-	# Mount root
-	if [ "${FSTYPE}" != "unknown" ]; then
-		mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} ${rootmnt}
-	else
-		mount ${roflag} ${ROOTFLAGS} ${ROOT} ${rootmnt}
-	fi
+		if [ "${readonly}" = "y" ]; then
+			roflag=-r
+		else
+			roflag=-w
+		fi
+
+		# FIXME This has no error checking
+		modprobe ${MNT_TYPE}
+
+		# FIXME This has no error checking
+		# Mount filesystem
+		mount ${roflag} ${MNT_TYPE} ${MNT_OPTS} ${MNT_FSNAME} ${rootmnt}
+	done < "/etc/fstab"
 
 	[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-bottom"
 	run_scripts /scripts/local-bottom
-- 
1.7.7.3


Reply to: