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"
|
|
|
|
|
+ " " + (if fs.fsType == "none" || fs.noCheck then "0" else
|
|
|
|
|
if fs.mountPoint == "/" then "1" else "2")
|
|
|
|
|
+ "\n"
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
# Swap devices.
|
|
|
|
|
${flip concatMapStrings config.swapDevices (sw:
|
|
|
|
|
"${sw.device} none swap\n"
|
|
|
|
|
)}
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2011-10-26 19:37:47 +00:00
|
|
|
|
type = types.nullOr (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
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
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-03-16 20:23:45 +00:00
|
|
|
|
{ startOn = "started udev";
|
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..."
|
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
|
|
|
|
|
|
|
|
|
|
stop tty1 || true
|
|
|
|
|
|
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
|
|
|
|
}
|