Skip to content

Commit 4685aa8

Browse files
committed
Mount file-systems in the correct order
Use the `fsBefore` function from NixOS to sort the file-systems. The function originates from `nixpkgs/nixos/lib/utils.nix`, but the file is a lambda that requires more arguments than we have available.
1 parent 17d08c6 commit 4685aa8

File tree

1 file changed

+55
-2
lines changed

1 file changed

+55
-2
lines changed

lib/default.nix

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ let
166166
_path: lhs: rhs:
167167
!(isAttrs lhs && isAttrs rhs)
168168
) lhs rhs;
169-
170169
in
171170
recursiveMerge left right;
172171

@@ -357,6 +356,44 @@ let
357356
*/
358357
maybeStr = x: lib.optionalString (x != null) x;
359358

359+
/*
360+
Check whenever `b` depends on `a` as a fileSystem
361+
362+
Note: copied from nixpkgs/nixos/utils.nix @ 47718fe8858fa4642cd6a4f0b5a1173bad9ce8df
363+
because the file that exports it is not meant to be used standalone.
364+
*/
365+
fsBefore =
366+
a: b:
367+
with lib;
368+
let
369+
# normalisePath adds a slash at the end of the path if it didn't already
370+
# have one.
371+
#
372+
# The reason slashes are added at the end of each path is to prevent `b`
373+
# from accidentally depending on `a` in cases like
374+
# a = { mountPoint = "/aaa"; ... }
375+
# b = { device = "/aaaa"; ... }
376+
# Here a.mountPoint *is* a prefix of b.device even though a.mountPoint is
377+
# *not* a parent of b.device. If we add a slash at the end of each string,
378+
# though, this is not a problem: "/aaa/" is not a prefix of "/aaaa/".
379+
normalisePath = path: "${path}${optionalString (!(hasSuffix "/" path)) "/"}";
380+
normalise =
381+
mount:
382+
mount
383+
// {
384+
device = normalisePath (toString mount.device);
385+
mountPoint = normalisePath mount.mountPoint;
386+
depends = map normalisePath mount.depends;
387+
};
388+
389+
a' = normalise a;
390+
b' = normalise b;
391+
392+
in
393+
hasPrefix a'.mountPoint b'.device
394+
|| hasPrefix a'.mountPoint b'.mountPoint
395+
|| any (hasPrefix a'.mountPoint) b'.depends;
396+
360397
/*
361398
Takes a Submodules config and options argument and returns a serializable
362399
subset of config variables as a shell script snippet.
@@ -956,9 +993,25 @@ let
956993
default =
957994
with lib;
958995
let
996+
mountOrder = pipe cfg.config._config.fileSystems.contents [
997+
(foldl' recursiveUpdate { })
998+
(mapAttrsToList (
999+
mountPoint: value:
1000+
value
1001+
// {
1002+
mountPoint = value.mountPoint or mountPoint;
1003+
depends = [ ];
1004+
}
1005+
))
1006+
(toposort diskoLib.fsBefore)
1007+
(getAttr "result")
1008+
(map (getAttr "mountPoint"))
1009+
];
1010+
9591011
fsMounts = diskoLib.deepMergeMap (dev: dev._mount.fs or { }) (
9601012
flatten (map attrValues (attrValues devices))
9611013
);
1014+
9621015
sortedDeviceList = diskoLib.sortDevicesByDependencies (cfg.config._meta.deviceDependencies or { }
9631016
) devices;
9641017
in
@@ -968,7 +1021,7 @@ let
9681021
${concatMapStrings (dev: (attrByPath (dev ++ [ "_mount" ]) { } devices).dev or "") sortedDeviceList}
9691022
9701023
# and then mount the filesystems in alphabetical order
971-
${concatStrings (attrValues fsMounts)}
1024+
${concatStrings (attrVals mountOrder fsMounts)}
9721025
'';
9731026
};
9741027
_unmount = lib.mkOption {

0 commit comments

Comments
 (0)