initrd: Detect filesystem type before doing fsck/mount

BusyBox doesn't handle the "auto" filesystem type very well: fsck will
just ignore such filesystems, and mount will only work properly if the
required kernel module is already loaded.  Therefore, use blkid to
determine the filesystem type.

Also generate an /etc/fstab in the initrd rootfs on the fly.  This is
useful if you're dropped into an emergency shell since it allows you
to say "fsck /dev/sda1" or "mount /dev/sda" and have the right thing
happen.
This commit is contained in:
Eelco Dolstra 2012-06-28 10:55:44 -04:00
parent 7acfd8ec20
commit 76c74cd7c7
2 changed files with 30 additions and 12 deletions

View file

@ -205,7 +205,9 @@ in
else
[ config.boot.kernelPackages.aufs ];
boot.initrd.kernelModules = [ "aufs" "squashfs" "iso9660" "loop" ];
boot.initrd.availableKernelModules = [ "aufs" "squashfs" "iso9660" ];
boot.initrd.kernelModules = [ "loop" ];
boot.kernelModules = pkgs.stdenv.lib.optional config.isoImage.makeEfiBootable "efivars";

View file

@ -184,21 +184,28 @@ onACPower() {
# Check the specified file system, if appropriate.
checkFS() {
local device="$1"
local fsType="$2"
# Only check block devices.
if ! test -b "$device"; then return 0; fi
FSTYPE=$(blkid -o value -s TYPE "$device" || true)
if [ ! -b "$device" ]; then return 0; fi
# Don't check ROM filesystems.
if test "$FSTYPE" = iso9660 -o "$FSTYPE" = udf; then return 0; fi
if [ "$fsType" = iso9660 -o "$fsType" = udf ]; then return 0; fi
# If we couldn't figure out the FS type, then skip fsck.
if [ "$fsType" = auto ]; then
echo 'cannot check filesystem with type "auto"!'
return 0
fi
# Optionally, skip fsck on journaling filesystems. This option is
# a hack - it's mostly because e2fsck on ext3 takes much longer to
# recover the journal than the ext3 implementation in the kernel
# does (minutes versus seconds).
if test -z "@checkJournalingFS@" -a \
\( "$FSTYPE" = ext3 -o "$FSTYPE" = ext4 -o "$FSTYPE" = reiserfs \
-o "$FSTYPE" = xfs -o "$FSTYPE" = jfs \)
\( "$fsType" = ext3 -o "$fsType" = ext4 -o "$fsType" = reiserfs \
-o "$fsType" = xfs -o "$fsType" = jfs \)
then
return 0
fi
@ -210,7 +217,9 @@ checkFS() {
return 0
fi
FSTAB_FILE="/etc/mtab" fsck -V -C -a "$device"
echo "checking $device..."
fsck -V -a "$device"
fsckResult=$?
if test $(($fsckResult | 2)) = $fsckResult; then
@ -240,7 +249,16 @@ mountFS() {
local options="$3"
local fsType="$4"
checkFS "$device"
if [ "$fsType" = auto ]; then
fsType=$(blkid -o value -s TYPE "$device")
if [ -z "$fsType" ]; then fsType=auto; fi
fi
echo "$device /mnt-root$mountPoint $fsType $options" >> /etc/fstab
checkFS "$device" "$fsType"
echo "mounting $device on $mountPoint..."
mkdir -p "/mnt-root$mountPoint" || true
@ -250,7 +268,7 @@ mountFS() {
if [ "$fsType" = "nfs" ]; then
nfsmount "$device" "/mnt-root$mountPoint" && break
else
mount -t "$fsType" -o "$options" "$device" "/mnt-root$mountPoint" && break
mount "/mnt-root$mountPoint" && break
fi
if [ "$fsType" != cifs -o "$n" -ge 10 ]; then fail; break; fi
echo "retrying..."
@ -311,8 +329,6 @@ while read -u 3 mountPoint; do
# doing something with $device right now.
udevadm settle || true
echo "mounting $device on $mountPoint..."
mountFS "$device" "$mountPoint" "$options" "$fsType"
done