* Allow multiple file systems to be mounted in stage 1 (i.e., from the

initrd).  This is useful if /nix (which is necessary for stage 2) is
  on a different file system than /.

svn path=/nixos/trunk/; revision=7862
This commit is contained in:
Eelco Dolstra 2007-02-06 16:53:36 +00:00
parent 923348b490
commit 8cf1eceb0a
3 changed files with 99 additions and 37 deletions

View File

@ -3,6 +3,7 @@
fail() {
# If starting stage 2 failed, start an interactive shell.
echo "Stage 2 failed, starting emergency shell..."
echo "(Stage 1 init script is $stage2Init)"
exec @staticShell@
}
@ -67,12 +68,55 @@ udevtrigger
udevsettle
# Function for mounting a file system.
mountFS() {
local device="$1"
local mountPoint="$2"
local options="$3"
# Check the root device, if .
mustCheck=
if test -b "$device"; then
mustCheck=1
else
case $device in
LABEL=*)
mustCheck=1
;;
esac
fi
if test -n "$mustCheck"; then
fsck -C -a "$device"
fsckResult=$?
if test $(($fsckResult | 2)) = $fsckResult; then
echo "fsck finished, rebooting..."
sleep 3
# reboot -f -d !!! don't have reboot yet
fail
fi
if test $(($fsckResult | 4)) = $fsckResult; then
echo "$device has unrepaired errors, please fix them manually."
fail
fi
if test $fsckResult -ge 8; then
echo "fsck on $device failed."
fail
fi
fi
# Mount read-writable.
mount -n -o "$options" "$device" /mnt/root$mountPoint || fail
}
# Try to find and mount the root device.
mkdir /mnt
mkdir /mnt/root
echo "mounting the root device..."
if test -n "@autoDetectRootDevice@"; then
# Look for the root device by label.
@ -109,33 +153,37 @@ if test -n "@autoDetectRootDevice@"; then
else
# Hard-coded root device.
rootDevice="@rootDevice@"
# Hard-coded root device(s).
mountPoints=(@mountPoints@)
devices=(@devices@)
fsTypes=(@fsTypes@)
optionss=(@optionss@)
# Check the root device.
fsck -C -a "$rootDevice"
fsckResult=$?
for ((n = 0; n < ${#mountPoints[*]}; n++)); do
mountPoint=${mountPoints[$n]}
device=${devices[$n]}
fsType=${fsTypes[$n]}
options=${optionss[$n]}
if test $(($fsckResult | 2)) = $fsckResult; then
echo "fsck finished, rebooting..."
sleep 3
# reboot -f -d !!! don't have reboot yet
fail
fi
# !!! Really quick hack to support bind mounts, i.e., where
# the "device" should be taken relative to /mnt/root, not /.
# Assume that every device that doesn't start with /dev or
# LABEL= is a bind mount.
case $device in
/dev/*)
;;
LABEL=*)
;;
*)
device=/mnt/root$device
;;
esac
if test $(($fsckResult | 4)) = $fsckResult; then
echo "$rootDevice has unrepaired errors, please fix them manually."
fail
fi
if test $fsckResult -ge 8; then
echo "fsck on $rootDevice failed."
fail
fi
# Mount read-writable.
mount -n -o rw "$rootDevice" /mnt/root || fail
echo "mounting $device on $mountPoint..."
mountFS "$device" "$mountPoint" "$options"
done
fi
@ -148,8 +196,6 @@ mount --move . /
umount /proc # cleanup
umount /sys
echo "INIT = $stage2Init"
if test -z "$stage2Init"; then fail; fi
exec chroot . $stage2Init

View File

@ -10,8 +10,15 @@
, # Whether to find root device automatically using its label.
autoDetectRootDevice
, # If not scanning, the root must be specified explicitly.
rootDevice
, # If not scanning, the root must be specified explicitly. Actually,
# stage 1 can mount multiple file systems. This is necessary if,
# for instance, /nix (necessary for stage 2) is on a different file
# system than /.
#
# This is a list of {mountPoint, device|label} attribute sets, i.e.,
# the format used by the fileSystems configuration option. There
# must at least be a file system for the / mount point in this list.
fileSystems ? []
# If scanning, we need a disk label.
, rootLabel
@ -21,12 +28,23 @@
stage2Init ? "/init"
}:
let
# !!! use XML; copy&pasted from upstart-jobs/filesystems.nix.
mountPoints = map (fs: fs.mountPoint) fileSystems;
devices = map (fs: if fs ? device then fs.device else "LABEL=" + fs.label) fileSystems;
fsTypes = map (fs: if fs ? fsType then fs.fsType else "auto") fileSystems;
optionss = map (fs: if fs ? options then fs.options else "defaults") fileSystems;
in
assert autoDetectRootDevice -> mountPoints != [];
substituteAll {
src = ./boot-stage-1-init.sh;
isExecutable = true;
inherit staticShell modules modulesDir;
inherit autoDetectRootDevice;
rootDevice = if !autoDetectRootDevice then rootDevice else "";
inherit autoDetectRootDevice mountPoints devices fsTypes optionss;
rootLabel = if autoDetectRootDevice then rootLabel else "";
path = [
staticTools

View File

@ -68,12 +68,10 @@ rec {
inherit (pkgsDiet) module_init_tools;
inherit extraUtils;
autoDetectRootDevice = config.get ["boot" "autoDetectRootDevice"];
rootDevice =
let rootFS =
(pkgs.library.findSingle (fs: fs.mountPoint == "/")
(abort "No root mount point declared.")
(config.get ["fileSystems"]));
in if rootFS ? device then rootFS.device else "LABEL=" + rootFS.label;
fileSystems =
pkgs.lib.filter
(fs: fs.mountPoint == "/" || (fs ? neededForBoot && fs.neededForBoot))
(config.get ["fileSystems"]);
rootLabel = config.get ["boot" "rootLabel"];
inherit stage2Init;
modulesDir = modulesClosure;