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 else
[ config.boot.kernelPackages.aufs ]; [ 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"; boot.kernelModules = pkgs.stdenv.lib.optional config.isoImage.makeEfiBootable "efivars";

View file

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