From dbadf6e9c20bacb54a8d3df442f4e0069224a111 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 4 Jun 2010 14:22:11 +0000 Subject: [PATCH] =?UTF-8?q?*=20Use=20mountall=20to=20mount=20all=20filesys?= =?UTF-8?q?tems=20and=20activate=20all=20swap=20devices=20=20=20during=20b?= =?UTF-8?q?oot.=20=20Mountall=20ensures=20that=20these=20are=20done=20in?= =?UTF-8?q?=20the=20right=20=20=20order.=20=20It's=20informed=20by=20udev?= =?UTF-8?q?=20about=20devices=20becoming=20available.=20=20It=20=20=20emit?= =?UTF-8?q?s=20some=20Upstart=20events=20upon=20reaching=20certain=20state?= =?UTF-8?q?s,=20in=20=20=20particular=20=E2=80=98local-filesystems?= =?UTF-8?q?=E2=80=99=20after=20all=20local=20filesystems=20have=20been=20?= =?UTF-8?q?=20=20mounted=20successfully,=20=E2=80=98remote-filesystems?= =?UTF-8?q?=E2=80=99=20after=20all=20network=20=20=20filesystems=20have=20?= =?UTF-8?q?been=20mounted,=20and=20=E2=80=98filesystem=E2=80=99=20(sic)=20?= =?UTF-8?q?when=20all=20=20=20filesystems=20have=20been=20mounted.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, if a filesystem fails to mount or doesn't exist, then the mingettys won't start and the boot will appear to hang. This is because mountall doesn't emit an event for failing filesystems and waits indefinitely for the filesystems to become available. * The ‘filesystems’ and ‘swap’ Upstart jobs are gone. (Support for encrypted swap devices is temporarily gone.) * Generate a proper /etc/fstab from the ‘fileSystems’ and ‘swapDevices’ options. svn path=/nixos/branches/boot-order/; revision=22148 --- modules/services/ttys/mingetty.nix | 2 +- modules/tasks/filesystems.nix | 142 ++++++++--------------------- modules/tasks/swap.nix | 75 ++------------- 3 files changed, 45 insertions(+), 174 deletions(-) diff --git a/modules/services/ttys/mingetty.nix b/modules/services/ttys/mingetty.nix index 445fdcd78ed7..8299580a8cf9 100644 --- a/modules/services/ttys/mingetty.nix +++ b/modules/services/ttys/mingetty.nix @@ -55,7 +55,7 @@ with pkgs.lib; # Generate a separate job for each tty. jobs = listToAttrs (map (tty: nameValuePair tty { - startOn = "started udev"; + startOn = "started udev and local-filesystems"; exec = "${pkgs.mingetty}/sbin/mingetty --loginprog=${pkgs.shadow}/bin/login --noclear ${tty}"; diff --git a/modules/tasks/filesystems.nix b/modules/tasks/filesystems.nix index d42a4449edc7..791ecccf4c88 100644 --- a/modules/tasks/filesystems.nix +++ b/modules/tasks/filesystems.nix @@ -2,108 +2,6 @@ with pkgs.lib; -let - - fileSystems = config.fileSystems; - mount = config.system.sbin.mount; - - task = - '' - PATH=${pkgs.e2fsprogs}/sbin:${pkgs.utillinuxng}/sbin:$PATH - - newDevices=1 - - # If we mount any file system, we repeat this loop, because new - # mount opportunities may have become available (such as images - # for loopback mounts). - - while test -n "$newDevices"; do - newDevices= - - ${flip concatMapStrings fileSystems (fs: '' - for dummy in x; do # make `continue' work - mountPoint='${fs.mountPoint}' - device='${if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}"}' - fsType='${fs.fsType}' - - # A device is a pseudo-device (i.e. not an actual device - # node) if it's not an absolute path (e.g. an NFS server - # such as machine:/path), if it starts with // (a CIFS FS), - # a known pseudo filesystem (such as tmpfs), or the device - # is a directory (e.g. a bind mount). - isPseudo= - test "''${device:0:1}" != / -o "''${device:0:2}" = // -o "$fsType" = "tmpfs" \ - -o -d "$device" && isPseudo=1 - - if ! test -n "$isPseudo" -o -e "$device"; then - echo "skipping $device, doesn't exist (yet)" - continue - fi - - # !!! quick hack: if the mount point is already mounted, try - # a remount to change the options but nothing else. - if cat /proc/mounts | grep -F -q " $mountPoint "; then - if test "''${device:0:2}" != //; then - echo "remounting $device on $mountPoint" - ${mount}/bin/mount -t "$fsType" \ - -o remount,"${fs.options}" \ - "$device" "$mountPoint" || true - fi - continue - fi - - # If $device is already mounted somewhere else, unmount it first. - # !!! Note: we use /etc/mtab, not /proc/mounts, because mtab - # contains more accurate info when using loop devices. - - if test -z "$isPseudo"; then - - device=$(readlink -f "$device") - - prevMountPoint=$( - cat /etc/mtab \ - | grep "^$device " \ - | sed 's|^[^ ]\+ \+\([^ ]\+\).*|\1|' \ - ) - - if test "$prevMountPoint" = "$mountPoint"; then - echo "remounting $device on $mountPoint" - ${mount}/bin/mount -t "$fsType" \ - -o remount,"${fs.options}" \ - "$device" "$mountPoint" || true - continue - fi - - if test -n "$prevMountPoint"; then - echo "unmount $device from $prevMountPoint" - ${mount}/bin/umount "$prevMountPoint" || true - fi - - fi - - echo "mounting $device on $mountPoint" - - # !!! should do something with the result; also prevent repeated fscks. - if test -z "$isPseudo"; then - fsck -a "$device" || true - fi - - ${optionalString fs.autocreate - '' - mkdir -p "$mountPoint" - '' - } - - if ${mount}/bin/mount -t "$fsType" -o "${fs.options}" "$device" "$mountPoint"; then - newDevices=1 - fi - done - '')} - done - ''; - -in - { ###### interface @@ -221,12 +119,44 @@ in config = { # Add the mount helpers to the system path so that `mount' can find them. - environment.systemPackages = [pkgs.ntfs3g pkgs.cifs_utils pkgs.nfsUtils]; + environment.systemPackages = [ pkgs.ntfs3g pkgs.cifs_utils pkgs.nfsUtils pkgs.mountall ]; - jobs.filesystems = - { startOn = [ "new-devices" "ip-up" ]; + environment.etc = singleton + { source = pkgs.writeText "fstab" + '' + # This is a generated file. Do not edit! - script = task; + # Filesystems. + ${flip concatMapStrings config.fileSystems (fs: + (if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") + + " " + fs.mountPoint + + " " + fs.fsType + + " " + fs.options + + " 0" + + " " + (if fs.mountPoint == "/" then "1" else "2") + + "\n" + )} + + # Swap devices. + ${flip concatMapStrings config.swapDevices (sw: + "${sw.device} none swap\n" + )} + ''; + target = "fstab"; + }; + + jobs.mountall = + { startOn = "started udev"; + + script = + '' + exec > /dev/console 2>&1 + export PATH=${config.system.sbin.mount}/bin:${pkgs.utillinux}/sbin:$PATH + ${pkgs.mountall}/sbin/mountall --verbose --debug + echo DONE + ''; + + extraConfig = "console owner"; task = true; }; diff --git a/modules/tasks/swap.nix b/modules/tasks/swap.nix index ab81185532ea..a3f241fc8c55 100644 --- a/modules/tasks/swap.nix +++ b/modules/tasks/swap.nix @@ -2,12 +2,6 @@ with pkgs.lib; -let - - inherit (pkgs) cryptsetup utillinux; - -in - { ###### interface @@ -36,37 +30,31 @@ in options = {config, options, ...}: { options = { + device = mkOption { example = "/dev/sda3"; type = types.string; - description = '' - Path of the device. - ''; + description = "Path of the device."; }; label = mkOption { example = "swap"; type = types.string; - description = " + description = '' Label of the device. Can be used instead of device. - "; + ''; }; cipher = mkOption { default = false; example = true; type = types.bool; - description = " - Cipher the swap device to protect swapped data. This option + description = '' + Encrypt the swap device to protect swapped data. This option does not work with labels. - "; + ''; }; - command = mkOption { - description = " - Command used to activate the swap device. - "; - }; }; config = { @@ -75,59 +63,12 @@ in "/dev/disk/by-label/${config.label}" else mkNotdef; - - command = '' - if test -e "${config.device}"; then - ${if config.cipher then '' - plainDevice="${config.device}" - name="crypt$(echo "$plainDevice" | sed -e 's,/,.,g')" - device="/dev/mapper/$name" - if ! test -e "$device"; then - ${cryptsetup}/sbin/cryptsetup -c aes -s 128 -d /dev/urandom create "$name" "$plainDevice" - ${utillinux}/sbin/mkswap -f "$device" || true - fi - '' - else '' - device="${config.device}" - '' - } - device=$(readlink -f "$device") - # Add new swap devices. - if echo $unused | grep -q "^$device\$"; then - unused="$(echo $unused | grep -v "^$device\$" || true)" - else - ${utillinux}/sbin/swapon "$device" || true - fi - fi - ''; }; - + }; }; }; - ###### implementation - - config = { - - jobs.swap = - { task = true; - - startOn = ["startup" "new-devices"]; - - script = - '' - unused="$(sed '1d; s/ .*//' /proc/swaps)" - - ${toString (map (x: x.command) config.swapDevices)} - - # Remove remaining swap devices. - test -n "$unused" && ${utillinux}/sbin/swapoff $unused || true - ''; - }; - - }; - }