forked from mirrors/nixpkgs
nixos: apply toposort to fileSystems to support bind and move mounts
And use new `config.system.build.fileSystems` property everywhere.
This commit is contained in:
parent
2c8ca0d1bd
commit
65d26c4dc1
|
@ -2,6 +2,11 @@ pkgs: with pkgs.lib;
|
|||
|
||||
rec {
|
||||
|
||||
# Check whenever `b` depends on `a` as a fileSystem
|
||||
# FIXME: it's incorrect to simply use hasPrefix here: "/dev/a" is not a parent of "/dev/ab"
|
||||
fsBefore = a: b: ((any (x: elem x [ "bind" "move" ]) b.options) && (a.mountPoint == b.device))
|
||||
|| (hasPrefix a.mountPoint b.mountPoint);
|
||||
|
||||
# Escape a path according to the systemd rules, e.g. /dev/xyzzy
|
||||
# becomes dev-xyzzy. FIXME: slow.
|
||||
escapeSystemdPath = s:
|
||||
|
|
|
@ -12,7 +12,7 @@ let
|
|||
(fs: (fs.neededForBoot
|
||||
|| elem fs.mountPoint [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ])
|
||||
&& fs.fsType == "zfs")
|
||||
(attrValues config.fileSystems) != [];
|
||||
config.system.build.fileSystems != [];
|
||||
|
||||
# Ascertain whether NixOS container support is required
|
||||
containerSupportRequired =
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# the modules necessary to mount the root file system, then calls the
|
||||
# init in the root file system to start the second boot stage.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, utils, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -23,6 +23,14 @@ let
|
|||
};
|
||||
|
||||
|
||||
# The initrd only has to mount `/` or any FS marked as necessary for
|
||||
# booting (such as the FS containing `/nix/store`, or an FS needed for
|
||||
# mounting `/`, like `/` on a loopback).
|
||||
fileSystems = filter
|
||||
(fs: fs.neededForBoot || elem fs.mountPoint [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ])
|
||||
config.system.build.fileSystems;
|
||||
|
||||
|
||||
# Some additional utilities needed in stage 1, like mount, lvm, fsck
|
||||
# etc. We don't want to bring in all of those packages, so we just
|
||||
# copy what we need. Instead of using statically linked binaries,
|
||||
|
@ -71,7 +79,7 @@ let
|
|||
ln -sf kmod $out/bin/modprobe
|
||||
|
||||
# Copy resize2fs if needed.
|
||||
${optionalString (any (fs: fs.autoResize) (attrValues config.fileSystems)) ''
|
||||
${optionalString (any (fs: fs.autoResize) config.system.build.fileSystems) ''
|
||||
# We need mke2fs in the initrd.
|
||||
copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/resize2fs
|
||||
''}
|
||||
|
@ -128,14 +136,6 @@ let
|
|||
''; # */
|
||||
|
||||
|
||||
# The initrd only has to mount / or any FS marked as necessary for
|
||||
# booting (such as the FS containing /nix/store, or an FS needed for
|
||||
# mounting /, like / on a loopback).
|
||||
fileSystems = filter
|
||||
(fs: fs.neededForBoot || elem fs.mountPoint [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ])
|
||||
(attrValues config.fileSystems);
|
||||
|
||||
|
||||
udevRules = pkgs.stdenv.mkDerivation {
|
||||
name = "udev-rules";
|
||||
allowedReferences = [ extraUtils ];
|
||||
|
@ -398,9 +398,8 @@ in
|
|||
};
|
||||
|
||||
config = mkIf (!config.boot.isContainer) {
|
||||
|
||||
assertions = [
|
||||
{ assertion = any (fs: fs.mountPoint == "/") (attrValues config.fileSystems);
|
||||
{ assertion = any (fs: fs.mountPoint == "/") fileSystems;
|
||||
message = "The ‘fileSystems’ option does not specify your root file system.";
|
||||
}
|
||||
{ assertion = let inherit (config.boot) resumeDevice; in
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
with lib;
|
||||
|
||||
let
|
||||
fileSystems = attrValues config.fileSystems ++ config.swapDevices;
|
||||
fileSystems = config.system.build.fileSystems ++ config.swapDevices;
|
||||
encDevs = filter (dev: dev.encrypted.enable) fileSystems;
|
||||
keyedEncDevs = filter (dev: dev.encrypted.keyFile != null) encDevs;
|
||||
keylessEncDevs = filter (dev: dev.encrypted.keyFile == null) encDevs;
|
||||
|
|
|
@ -5,7 +5,16 @@ with utils;
|
|||
|
||||
let
|
||||
|
||||
fileSystems = attrValues config.fileSystems;
|
||||
fileSystems' = toposort fsBefore (attrValues config.fileSystems);
|
||||
|
||||
fileSystems = if fileSystems' ? "result"
|
||||
then # use topologically sorted fileSystems everywhere
|
||||
fileSystems'.result
|
||||
else # the assertion below will catch this,
|
||||
# but we fall back to the original order
|
||||
# anyway so that other modules could check
|
||||
# their assertions too
|
||||
(attrValues config.fileSystems);
|
||||
|
||||
prioOption = prio: optionalString (prio != null) " pri=${toString prio}";
|
||||
|
||||
|
@ -162,6 +171,17 @@ in
|
|||
|
||||
config = {
|
||||
|
||||
assertions = let
|
||||
ls = sep: concatMapStringsSep sep (x: x.mountPoint);
|
||||
in [
|
||||
{ assertion = ! (fileSystems' ? "cycle");
|
||||
message = "The ‘fileSystems’ option can't be topologically sorted: mountpoint dependency path ${ls " -> " fileSystems'.cycle} loops to ${ls ", " fileSystems'.loops}";
|
||||
}
|
||||
];
|
||||
|
||||
# Export for use in other modules
|
||||
system.build.fileSystems = fileSystems;
|
||||
|
||||
boot.supportedFilesystems = map (fs: fs.fsType) fileSystems;
|
||||
|
||||
# Add the mount helpers to the system path so that `mount' can find them.
|
||||
|
@ -177,7 +197,7 @@ in
|
|||
# This is a generated file. Do not edit!
|
||||
|
||||
# Filesystems.
|
||||
${flip concatMapStrings fileSystems (fs:
|
||||
${concatMapStrings (fs:
|
||||
(if fs.device != null then fs.device
|
||||
else if fs.label != null then "/dev/disk/by-label/${fs.label}"
|
||||
else throw "No device specified for mount point ‘${fs.mountPoint}’.")
|
||||
|
@ -188,7 +208,7 @@ in
|
|||
+ " " + (if skipCheck fs then "0" else
|
||||
if fs.mountPoint == "/" then "1" else "2")
|
||||
+ "\n"
|
||||
)}
|
||||
) fileSystems}
|
||||
|
||||
# Swap devices.
|
||||
${flip concatMapStrings config.swapDevices (sw:
|
||||
|
|
|
@ -36,7 +36,7 @@ let
|
|||
|
||||
fsToPool = fs: datasetToPool fs.device;
|
||||
|
||||
zfsFilesystems = filter (x: x.fsType == "zfs") (attrValues config.fileSystems);
|
||||
zfsFilesystems = filter (x: x.fsType == "zfs") config.system.build.fileSystems;
|
||||
|
||||
isRoot = fs: fs.neededForBoot || elem fs.mountPoint [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ];
|
||||
|
||||
|
@ -277,7 +277,7 @@ in
|
|||
|
||||
systemd.services = let
|
||||
getPoolFilesystems = pool:
|
||||
filter (x: x.fsType == "zfs" && (fsToPool x) == pool) (attrValues config.fileSystems);
|
||||
filter (x: x.fsType == "zfs" && (fsToPool x) == pool) config.system.build.fileSystems;
|
||||
|
||||
getPoolMounts = pool:
|
||||
let
|
||||
|
|
Loading…
Reference in a new issue