Merge pull request #328221 from nikstur/fix-overlay-etc

nixos/etc: handle mountpoints on top of /etc when switching
This commit is contained in:
Jörg Thalheim 2024-07-18 21:59:30 +02:00 committed by GitHub
commit 054c2d71f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 62 additions and 2 deletions

View File

@ -247,6 +247,30 @@ in
--options lowerdir=$tmpMetadataMount::${config.system.build.etcBasedir},${etcOverlayOptions} \
$tmpEtcMount
# Before moving the new /etc overlay under the old /etc, we have to
# move mounts on top of /etc to the new /etc mountpoint.
findmnt /etc --submounts --list --noheading --kernel --output TARGET | while read -r mountPoint; do
if [[ "$mountPoint" = "/etc" ]]; then
continue
fi
tmpMountPoint="$tmpEtcMount/''${mountPoint:5}"
${if config.system.etc.overlay.mutable then ''
if [[ -f "$mountPoint" ]]; then
touch "$tmpMountPoint"
elif [[ -d "$mountPoint" ]]; then
mkdir -p "$tmpMountPoint"
fi
'' else ''
if [[ ! -e "$tmpMountPoint" ]]; then
echo "Skipping undeclared mountpoint in environment.etc: $mountPoint"
continue
fi
''
}
mount --bind "$mountPoint" "$tmpMountPoint"
done
# Move the new temporary /etc mount underneath the current /etc mount.
#
# This should eventually use util-linux to perform this move beneath,
@ -255,8 +279,7 @@ in
${pkgs.move-mount-beneath}/bin/move-mount --move --beneath $tmpEtcMount /etc
# Unmount the top /etc mount to atomically reveal the new mount.
umount /etc
umount --recursive /etc
fi
'' else ''
# Set up the statically computed bits of /etc.

View File

@ -15,6 +15,11 @@
boot.kernelPackages = pkgs.linuxPackages_latest;
time.timeZone = "Utc";
environment.etc = {
"mountpoint/.keep".text = "keep";
"filemount".text = "keep";
};
specialisation.new-generation.configuration = {
environment.etc."newgen".text = "newgen";
};
@ -33,8 +38,17 @@
with subtest("switching to a new generation"):
machine.fail("stat /etc/newgen")
machine.succeed("mount -t tmpfs tmpfs /etc/mountpoint")
machine.succeed("touch /etc/mountpoint/extra-file")
machine.succeed("mount --bind /dev/null /etc/filemount")
machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
assert machine.succeed("cat /etc/newgen") == "newgen"
print(machine.succeed("findmnt /etc/mountpoint"))
print(machine.succeed("ls /etc/mountpoint"))
print(machine.succeed("stat /etc/mountpoint/extra-file"))
print(machine.succeed("findmnt /etc/filemount"))
'';
}

View File

@ -28,9 +28,22 @@
machine.fail("stat /etc/newgen")
machine.succeed("echo -n 'mutable' > /etc/mutable")
# Directory
machine.succeed("mkdir /etc/mountpoint")
machine.succeed("mount -t tmpfs tmpfs /etc/mountpoint")
machine.succeed("touch /etc/mountpoint/extra-file")
# File
machine.succeed("touch /etc/filemount")
machine.succeed("mount --bind /dev/null /etc/filemount")
machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
assert machine.succeed("cat /etc/newgen") == "newgen"
assert machine.succeed("cat /etc/mutable") == "mutable"
print(machine.succeed("findmnt /etc/mountpoint"))
print(machine.succeed("stat /etc/mountpoint/extra-file"))
print(machine.succeed("findmnt /etc/filemount"))
'';
}

View File

@ -1,6 +1,7 @@
{ lib
, stdenv
, fetchFromGitHub
, fetchpatch
}:
stdenv.mkDerivation {
@ -20,6 +21,15 @@ stdenv.mkDerivation {
runHook postInstall
'';
patches = [
# Fix uninitialized variable in flags_attr, https://github.com/brauner/move-mount-beneath/pull/2
(fetchpatch {
name = "aarch64";
url = "https://github.com/brauner/move-mount-beneath/commit/0bd0b863f7b98608514d90d4f2a80a21ce2e6cd3.patch";
hash = "sha256-D3TttAT0aFqpYC8LuVnrkLwDcfVFOSeYzUDx6VqPu1Q=";
})
];
meta = {
description = "Toy binary to illustrate adding a mount beneath an existing mount";
mainProgram = "move-mount";