2009-10-12 16:36:19 +00:00
|
|
|
|
{ config, pkgs, ... }:
|
|
|
|
|
|
|
|
|
|
with pkgs.lib;
|
2006-12-21 14:22:40 +00:00
|
|
|
|
|
2012-03-15 13:54:23 +00:00
|
|
|
|
let
|
|
|
|
|
|
|
|
|
|
fstab = pkgs.writeText "fstab"
|
|
|
|
|
''
|
|
|
|
|
# This is a generated file. Do not edit!
|
|
|
|
|
|
|
|
|
|
# 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"
|
2012-05-16 00:03:44 +00:00
|
|
|
|
+ " " + (if fs.fsType == "none" || fs.fsType == "btrfs" || fs.noCheck then "0" else
|
2012-03-15 13:54:23 +00:00
|
|
|
|
if fs.mountPoint == "/" then "1" else "2")
|
|
|
|
|
+ "\n"
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
# Swap devices.
|
|
|
|
|
${flip concatMapStrings config.swapDevices (sw:
|
2012-06-12 13:41:51 +00:00
|
|
|
|
"${sw.device} none swap\n"
|
2012-03-15 13:54:23 +00:00
|
|
|
|
)}
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
2009-10-12 16:36:19 +00:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
###### interface
|
2009-05-27 23:14:38 +00:00
|
|
|
|
|
|
|
|
|
options = {
|
|
|
|
|
|
2009-06-11 16:03:57 +00:00
|
|
|
|
fileSystems = mkOption {
|
2009-05-27 23:14:38 +00:00
|
|
|
|
example = [
|
|
|
|
|
{ mountPoint = "/";
|
|
|
|
|
device = "/dev/hda1";
|
|
|
|
|
}
|
|
|
|
|
{ mountPoint = "/data";
|
|
|
|
|
device = "/dev/hda2";
|
|
|
|
|
fsType = "ext3";
|
|
|
|
|
options = "data=journal";
|
|
|
|
|
}
|
|
|
|
|
{ mountPoint = "/bigdisk";
|
|
|
|
|
label = "bigdisk";
|
|
|
|
|
}
|
|
|
|
|
];
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2012-03-09 14:37:58 +00:00
|
|
|
|
description = ''
|
2009-05-27 23:14:38 +00:00
|
|
|
|
The file systems to be mounted. It must include an entry for
|
|
|
|
|
the root directory (<literal>mountPoint = \"/\"</literal>). Each
|
|
|
|
|
entry in the list is an attribute set with the following fields:
|
|
|
|
|
<literal>mountPoint</literal>, <literal>device</literal>,
|
|
|
|
|
<literal>fsType</literal> (a file system type recognised by
|
|
|
|
|
<command>mount</command>; defaults to
|
|
|
|
|
<literal>\"auto\"</literal>), and <literal>options</literal>
|
|
|
|
|
(the mount options passed to <command>mount</command> using the
|
|
|
|
|
<option>-o</option> flag; defaults to <literal>\"defaults\"</literal>).
|
|
|
|
|
|
|
|
|
|
Instead of specifying <literal>device</literal>, you can also
|
|
|
|
|
specify a volume label (<literal>label</literal>) for file
|
|
|
|
|
systems that support it, such as ext2/ext3 (see <command>mke2fs
|
|
|
|
|
-L</command>).
|
|
|
|
|
|
2011-09-14 18:20:50 +00:00
|
|
|
|
<literal>autocreate</literal> forces <literal>mountPoint</literal> to be created with
|
2009-05-27 23:14:38 +00:00
|
|
|
|
<command>mkdir -p</command> .
|
2012-03-09 14:37:58 +00:00
|
|
|
|
'';
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2012-05-14 01:33:11 +00:00
|
|
|
|
type = types.list types.optionSet;
|
2009-06-11 16:03:57 +00:00
|
|
|
|
|
2009-07-15 13:41:00 +00:00
|
|
|
|
options = {
|
2009-06-11 16:03:57 +00:00
|
|
|
|
|
|
|
|
|
mountPoint = mkOption {
|
|
|
|
|
example = "/mnt/usb";
|
|
|
|
|
type = types.uniq types.string;
|
2012-03-09 14:37:58 +00:00
|
|
|
|
description = "Location of the mounted the file system.";
|
2009-06-11 16:03:57 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
device = mkOption {
|
|
|
|
|
default = null;
|
|
|
|
|
example = "/dev/sda";
|
|
|
|
|
type = types.uniq (types.nullOr types.string);
|
2012-03-09 14:37:58 +00:00
|
|
|
|
description = "Location of the device.";
|
2009-06-11 16:03:57 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
label = mkOption {
|
|
|
|
|
default = null;
|
|
|
|
|
example = "root-partition";
|
|
|
|
|
type = types.uniq (types.nullOr types.string);
|
2012-03-09 14:37:58 +00:00
|
|
|
|
description = "Label of the device (if any).";
|
2009-06-11 16:03:57 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
fsType = mkOption {
|
|
|
|
|
default = "auto";
|
|
|
|
|
example = "ext3";
|
|
|
|
|
type = types.uniq types.string;
|
2012-03-09 14:37:58 +00:00
|
|
|
|
description = "Type of the file system.";
|
2009-06-11 16:03:57 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
options = mkOption {
|
2009-07-14 12:07:17 +00:00
|
|
|
|
default = "defaults,relatime";
|
2009-06-11 16:03:57 +00:00
|
|
|
|
example = "data=journal";
|
|
|
|
|
type = types.string;
|
|
|
|
|
merge = pkgs.lib.concatStringsSep ",";
|
2010-09-13 11:46:35 +00:00
|
|
|
|
description = "Options used to mount the file system.";
|
2009-06-11 16:03:57 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
autocreate = mkOption {
|
2009-06-14 11:07:44 +00:00
|
|
|
|
default = false;
|
|
|
|
|
type = types.bool;
|
2012-03-09 14:37:58 +00:00
|
|
|
|
description = ''
|
2009-06-11 16:03:57 +00:00
|
|
|
|
Automatically create the mount point defined in
|
|
|
|
|
<option>fileSystems.*.mountPoint</option>.
|
2012-03-09 14:37:58 +00:00
|
|
|
|
'';
|
2009-06-11 16:03:57 +00:00
|
|
|
|
};
|
2010-09-13 11:46:35 +00:00
|
|
|
|
|
2012-05-16 00:03:44 +00:00
|
|
|
|
autoFormat = mkOption {
|
|
|
|
|
default = false;
|
|
|
|
|
type = types.bool;
|
|
|
|
|
description = ''
|
|
|
|
|
If the device does not currently contain a filesystem (as
|
|
|
|
|
determined by <command>blkid</command>, then automatically
|
|
|
|
|
format it with the filesystem type specified in
|
|
|
|
|
<option>fsType</option>. Use with caution.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2010-09-13 11:46:35 +00:00
|
|
|
|
noCheck = mkOption {
|
|
|
|
|
default = false;
|
|
|
|
|
type = types.bool;
|
|
|
|
|
description = "Disable running fsck on this filesystem.";
|
|
|
|
|
};
|
2009-06-11 16:03:57 +00:00
|
|
|
|
};
|
2009-05-27 23:14:38 +00:00
|
|
|
|
};
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2012-03-09 14:37:58 +00:00
|
|
|
|
system.fsPackages = mkOption {
|
2009-05-27 23:14:38 +00:00
|
|
|
|
internal = true;
|
2012-03-09 14:37:58 +00:00
|
|
|
|
default = [ ];
|
|
|
|
|
description = "Packages supplying file system mounters and checkers.";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
boot.supportedFilesystems = mkOption {
|
|
|
|
|
default = [ ];
|
|
|
|
|
example = [ "btrfs" ];
|
|
|
|
|
type = types.list types.string;
|
|
|
|
|
description = "Names of supported filesystem types.";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
boot.initrd.supportedFilesystems = mkOption {
|
|
|
|
|
default = [ ];
|
|
|
|
|
example = [ "btrfs" ];
|
|
|
|
|
type = types.list types.string;
|
|
|
|
|
description = "Names of supported filesystem types in the initial ramdisk.";
|
2009-05-27 23:14:38 +00:00
|
|
|
|
};
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2012-09-23 22:14:43 +00:00
|
|
|
|
boot.ttyEmergency = mkOption {
|
|
|
|
|
default =
|
|
|
|
|
if pkgs.stdenv.isArm
|
|
|
|
|
then "ttyS0" # presumably an embedded platform such as a plug
|
|
|
|
|
else "tty1";
|
|
|
|
|
description = ''
|
|
|
|
|
The tty that will be stopped in case an emergency shell is spawned
|
|
|
|
|
at boot.
|
|
|
|
|
'';
|
|
|
|
|
};
|
2009-05-27 23:14:38 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2009-10-12 16:36:19 +00:00
|
|
|
|
###### implementation
|
2009-05-27 23:14:38 +00:00
|
|
|
|
|
2009-10-12 16:36:19 +00:00
|
|
|
|
config = {
|
2009-05-27 23:14:38 +00:00
|
|
|
|
|
2012-03-09 14:37:58 +00:00
|
|
|
|
boot.supportedFilesystems =
|
|
|
|
|
map (fs: fs.fsType) config.fileSystems;
|
|
|
|
|
|
|
|
|
|
boot.initrd.supportedFilesystems =
|
|
|
|
|
map (fs: fs.fsType)
|
|
|
|
|
(filter (fs: fs.mountPoint == "/" || fs.neededForBoot) config.fileSystems);
|
|
|
|
|
|
2009-10-12 16:36:19 +00:00
|
|
|
|
# Add the mount helpers to the system path so that `mount' can find them.
|
2012-03-09 14:37:58 +00:00
|
|
|
|
system.fsPackages = [ pkgs.dosfstools ];
|
|
|
|
|
|
2010-06-04 15:35:32 +00:00
|
|
|
|
environment.systemPackages =
|
2012-03-09 14:37:58 +00:00
|
|
|
|
[ pkgs.ntfs3g pkgs.cifs_utils pkgs.mountall ]
|
|
|
|
|
++ config.system.fsPackages;
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2010-06-04 14:22:11 +00:00
|
|
|
|
environment.etc = singleton
|
2012-03-15 13:54:23 +00:00
|
|
|
|
{ source = fstab;
|
2010-06-04 14:22:11 +00:00
|
|
|
|
target = "fstab";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
jobs.mountall =
|
2012-05-21 21:26:45 +00:00
|
|
|
|
{ startOn = "started udev or config-changed";
|
2010-06-04 14:22:11 +00:00
|
|
|
|
|
2010-06-07 12:15:55 +00:00
|
|
|
|
task = true;
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2012-03-16 20:23:45 +00:00
|
|
|
|
path = [ pkgs.utillinux pkgs.mountall ] ++ config.system.fsPackages;
|
2012-03-09 14:37:58 +00:00
|
|
|
|
|
2012-03-18 17:48:19 +00:00
|
|
|
|
console = "output";
|
|
|
|
|
|
|
|
|
|
preStart =
|
2010-06-04 14:22:11 +00:00
|
|
|
|
''
|
2012-03-15 13:54:23 +00:00
|
|
|
|
# Ensure that this job is restarted when fstab changed:
|
|
|
|
|
# ${fstab}
|
2010-06-07 12:15:55 +00:00
|
|
|
|
echo "mounting filesystems..."
|
2012-04-11 21:21:00 +00:00
|
|
|
|
|
2012-05-16 00:03:44 +00:00
|
|
|
|
# Format devices.
|
|
|
|
|
${flip concatMapStrings config.fileSystems (fs: optionalString fs.autoFormat ''
|
|
|
|
|
if [ -e "${fs.device}" ]; then
|
|
|
|
|
type=$(blkid -p -s TYPE -o value "${fs.device}" || true)
|
|
|
|
|
if [ -z "$type" ]; then
|
|
|
|
|
echo "creating ${fs.fsType} filesystem on ${fs.device}..."
|
|
|
|
|
mkfs.${fs.fsType} "${fs.device}"
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
'')}
|
|
|
|
|
|
2012-04-11 21:21:00 +00:00
|
|
|
|
# Create missing mount points. Note that this won't work
|
|
|
|
|
# if the mount point is under another mount point.
|
|
|
|
|
${flip concatMapStrings config.fileSystems (fs: optionalString fs.autocreate ''
|
|
|
|
|
mkdir -p -m 0755 '${fs.mountPoint}'
|
|
|
|
|
'')}
|
2012-06-12 13:41:51 +00:00
|
|
|
|
|
|
|
|
|
# Create missing swapfiles.
|
|
|
|
|
# FIXME: support changing the size of existing swapfiles.
|
|
|
|
|
${flip concatMapStrings config.swapDevices (sw: optionalString (sw.size != null) ''
|
|
|
|
|
if [ ! -e "${sw.device}" -a -e "$(dirname "${sw.device}")" ]; then
|
|
|
|
|
# FIXME: use ‘fallocate’ on filesystems that support it.
|
|
|
|
|
dd if=/dev/zero of="${sw.device}" bs=1M count=${toString sw.size}
|
|
|
|
|
mkswap ${sw.device}
|
|
|
|
|
fi
|
|
|
|
|
'')}
|
|
|
|
|
|
2010-06-04 14:22:11 +00:00
|
|
|
|
'';
|
2012-03-18 17:48:19 +00:00
|
|
|
|
|
|
|
|
|
daemonType = "daemon";
|
|
|
|
|
|
|
|
|
|
exec = "mountall --daemon";
|
2010-06-07 12:15:55 +00:00
|
|
|
|
};
|
2009-05-27 23:14:38 +00:00
|
|
|
|
|
2010-06-07 12:15:55 +00:00
|
|
|
|
# The `mount-failed' event is emitted synchronously, but we don't
|
|
|
|
|
# want `mountall' to wait for the emergency shell. So use this
|
|
|
|
|
# intermediate job to make the event asynchronous.
|
2012-03-16 20:41:49 +00:00
|
|
|
|
jobs."mount-failed" =
|
|
|
|
|
{ task = true;
|
2010-06-07 12:15:55 +00:00
|
|
|
|
startOn = "mount-failed";
|
2012-03-18 18:04:49 +00:00
|
|
|
|
restartIfChanged = false;
|
2010-06-07 12:15:55 +00:00
|
|
|
|
script =
|
|
|
|
|
''
|
2012-03-18 01:44:20 +00:00
|
|
|
|
# Don't start the emergency shell if the X server is
|
|
|
|
|
# running. The user won't see it, and the "console owner"
|
|
|
|
|
# stanza breaks VT switching and causes the X server to go
|
|
|
|
|
# to 100% CPU time.
|
|
|
|
|
status="$(status xserver || true)"
|
|
|
|
|
[[ "$status" =~ start/ ]] && exit 0
|
|
|
|
|
|
2012-09-23 22:14:43 +00:00
|
|
|
|
stop ${config.boot.ttyEmergency} || true
|
2012-03-18 01:44:20 +00:00
|
|
|
|
|
2010-06-07 12:15:55 +00:00
|
|
|
|
start --no-wait emergency-shell \
|
|
|
|
|
DEVICE="$DEVICE" MOUNTPOINT="$MOUNTPOINT"
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2010-07-12 16:07:26 +00:00
|
|
|
|
# On an `ip-up' event, notify mountall so that it retries mounting
|
|
|
|
|
# remote filesystems.
|
2012-03-16 20:41:49 +00:00
|
|
|
|
jobs."mountall-ip-up" =
|
2010-07-12 16:07:26 +00:00
|
|
|
|
{
|
|
|
|
|
task = true;
|
|
|
|
|
startOn = "ip-up";
|
2012-03-18 18:04:49 +00:00
|
|
|
|
restartIfChanged = false;
|
2010-07-12 16:07:26 +00:00
|
|
|
|
script =
|
|
|
|
|
''
|
2012-03-18 17:48:19 +00:00
|
|
|
|
# Send USR1 to the mountall process. Can't use "pkill
|
|
|
|
|
# mountall" here because that has a race condition: we may
|
|
|
|
|
# accidentally send USR1 to children of mountall (such as
|
|
|
|
|
# fsck) just before they do execve().
|
|
|
|
|
status="$(status mountall)"
|
|
|
|
|
if [[ "$status" =~ "start/running, process "([0-9]+) ]]; then
|
|
|
|
|
pid=''${BASH_REMATCH[1]}
|
|
|
|
|
echo "sending USR1 to $pid..."
|
|
|
|
|
kill -USR1 "$pid"
|
|
|
|
|
fi
|
2010-07-12 16:07:26 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2012-03-16 20:41:49 +00:00
|
|
|
|
jobs."emergency-shell" =
|
|
|
|
|
{ task = true;
|
2010-06-07 12:15:55 +00:00
|
|
|
|
|
2012-03-18 18:04:49 +00:00
|
|
|
|
restartIfChanged = false;
|
|
|
|
|
|
2012-03-18 17:48:19 +00:00
|
|
|
|
console = "owner";
|
2010-06-07 12:15:55 +00:00
|
|
|
|
|
|
|
|
|
script =
|
|
|
|
|
''
|
|
|
|
|
cat <<EOF
|
|
|
|
|
|
|
|
|
|
[1;31m<<< Emergency shell >>>[0m
|
|
|
|
|
|
|
|
|
|
The filesystem \`$DEVICE' could not be mounted on \`$MOUNTPOINT'.
|
|
|
|
|
|
|
|
|
|
Please do one of the following:
|
|
|
|
|
|
|
|
|
|
- Repair the filesystem (\`fsck $DEVICE') and exit the emergency
|
|
|
|
|
shell to resume booting.
|
|
|
|
|
|
|
|
|
|
- Ignore any failed filesystems and continue booting by running
|
|
|
|
|
\`initctl emit filesystem'.
|
|
|
|
|
|
|
|
|
|
- Remove the failed filesystem from the system configuration in
|
|
|
|
|
/etc/nixos/configuration.nix and run \`nixos-rebuild switch'.
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2010-06-07 12:15:55 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
${pkgs.shadow}/bin/login root || false
|
|
|
|
|
|
|
|
|
|
initctl start --no-wait mountall
|
|
|
|
|
'';
|
2009-10-12 16:36:19 +00:00
|
|
|
|
};
|
2006-12-21 14:22:40 +00:00
|
|
|
|
|
2009-03-06 12:27:33 +00:00
|
|
|
|
};
|
2009-08-11 21:10:33 +00:00
|
|
|
|
|
2006-12-21 14:22:40 +00:00
|
|
|
|
}
|