about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorKim Lindberger <kim.lindberger@gmail.com>2021-06-14 10:50:07 +0200
committerGitHub <noreply@github.com>2021-06-14 10:50:07 +0200
commit26706834a58daa0c6f699c18f05e0a8b62ed3b7f (patch)
treeff3cfcfc92318122dfb82d170e9a688b3f8fc4a4 /nixos
parent86752e44440dfcd17f53d08fc117bd96c8bac144 (diff)
parentea34fe21e18f87dc8b333672f23edf2bcee98cd7 (diff)
downloadnixlib-26706834a58daa0c6f699c18f05e0a8b62ed3b7f.tar
nixlib-26706834a58daa0c6f699c18f05e0a8b62ed3b7f.tar.gz
nixlib-26706834a58daa0c6f699c18f05e0a8b62ed3b7f.tar.bz2
nixlib-26706834a58daa0c6f699c18f05e0a8b62ed3b7f.tar.lz
nixlib-26706834a58daa0c6f699c18f05e0a8b62ed3b7f.tar.xz
nixlib-26706834a58daa0c6f699c18f05e0a8b62ed3b7f.tar.zst
nixlib-26706834a58daa0c6f699c18f05e0a8b62ed3b7f.zip
Merge pull request #86967 from jakobrs/more-general-fsbefore
nixos/lib/utils: Add `fileSystems.<name>.depends` option and generalise fsBefore (fixes #86955)
Diffstat (limited to 'nixos')
-rw-r--r--nixos/lib/utils.nix26
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix6
-rw-r--r--nixos/modules/installer/netboot/netboot.nix6
-rw-r--r--nixos/modules/tasks/filesystems.nix20
4 files changed, 54 insertions, 4 deletions
diff --git a/nixos/lib/utils.nix b/nixos/lib/utils.nix
index c9dfdbed99a3..1a51b149e56e 100644
--- a/nixos/lib/utils.nix
+++ b/nixos/lib/utils.nix
@@ -14,8 +14,30 @@ rec {
   fsNeededForBoot = fs: fs.neededForBoot || elem fs.mountPoint pathsNeededForBoot;
 
   # Check whenever `b` depends on `a` as a fileSystem
-  fsBefore = a: b: a.mountPoint == b.device
-                || hasPrefix "${a.mountPoint}${optionalString (!(hasSuffix "/" a.mountPoint)) "/"}" b.mountPoint;
+  fsBefore = a: b:
+    let
+      # normalisePath adds a slash at the end of the path if it didn't already
+      # have one.
+      #
+      # The reason slashes are added at the end of each path is to prevent `b`
+      # from accidentally depending on `a` in cases like
+      #    a = { mountPoint = "/aaa"; ... }
+      #    b = { device     = "/aaaa"; ... }
+      # Here a.mountPoint *is* a prefix of b.device even though a.mountPoint is
+      # *not* a parent of b.device. If we add a slash at the end of each string,
+      # though, this is not a problem: "/aaa/" is not a prefix of "/aaaa/".
+      normalisePath = path: "${path}${optionalString (!(hasSuffix "/" path)) "/"}";
+      normalise = mount: mount // { device = normalisePath mount.device;
+                                    mountPoint = normalisePath mount.mountPoint;
+                                    depends = map normalisePath mount.depends;
+                                  };
+
+      a' = normalise a;
+      b' = normalise b;
+
+    in hasPrefix a'.mountPoint b'.device
+    || hasPrefix a'.mountPoint b'.mountPoint
+    || any (hasPrefix a'.mountPoint) b'.depends;
 
   # Escape a path according to the systemd rules, e.g. /dev/xyzzy
   # becomes dev-xyzzy.  FIXME: slow.
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index c2836b5a9a1b..4e5d888c4bbd 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -680,6 +680,12 @@ in
           "upperdir=/nix/.rw-store/store"
           "workdir=/nix/.rw-store/work"
         ];
+
+        depends = [
+          "/nix/.ro-store"
+          "/nix/.rw-store/store"
+          "/nix/.rw-store/work"
+        ];
       };
 
     boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" "overlay" ];
diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix
index fa074fdfcc6e..238ab6d0617b 100644
--- a/nixos/modules/installer/netboot/netboot.nix
+++ b/nixos/modules/installer/netboot/netboot.nix
@@ -57,6 +57,12 @@ with lib;
           "upperdir=/nix/.rw-store/store"
           "workdir=/nix/.rw-store/work"
         ];
+
+        depends = [
+          "/nix/.ro-store"
+          "/nix/.rw-store/store"
+          "/nix/.rw-store/work"
+        ];
       };
 
     boot.initrd.availableKernelModules = [ "squashfs" "overlay" ];
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index 065d6cc95d18..2949c82df8fe 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -24,13 +24,15 @@ let
 
   specialFSTypes = [ "proc" "sysfs" "tmpfs" "ramfs" "devtmpfs" "devpts" ];
 
+  nonEmptyWithoutTrailingSlash = addCheckDesc "non-empty without trailing slash" types.str
+    (s: isNonEmpty s && (builtins.match ".+/" s) == null);
+
   coreFileSystemOpts = { name, config, ... }: {
 
     options = {
       mountPoint = mkOption {
         example = "/mnt/usb";
-        type = addCheckDesc "non-empty without trailing slash" types.str
-          (s: isNonEmpty s && (builtins.match ".+/" s) == null);
+        type = nonEmptyWithoutTrailingSlash;
         description = "Location of the mounted the file system.";
       };
 
@@ -55,6 +57,20 @@ let
         type = types.listOf nonEmptyStr;
       };
 
+      depends = mkOption {
+        default = [ ];
+        example = [ "/persist" ];
+        type = types.listOf nonEmptyWithoutTrailingSlash;
+        description = ''
+          List of paths that should be mounted before this one. This filesystem's
+          <option>device</option> and <option>mountPoint</option> are always
+          checked and do not need to be included explicitly. If a path is added
+          to this list, any other filesystem whose mount point is a parent of
+          the path will be mounted before this filesystem. The paths do not need
+          to actually be the <option>mountPoint</option> of some other filesystem.
+        '';
+      };
+
     };
 
     config = {