From a2d4cea96ec766ef1df9484888f14e59576ec825 Mon Sep 17 00:00:00 2001 From: r-vdp Date: Thu, 5 Sep 2024 15:26:54 +0200 Subject: [PATCH 1/3] etc: rename the temporary dirs so that they are recognisable This makes it a lot easier to understand which dir is which --- nixos/modules/system/etc/etc.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/modules/system/etc/etc.nix b/nixos/modules/system/etc/etc.nix index 594b9aab61b7b..7547f4304709c 100644 --- a/nixos/modules/system/etc/etc.nix +++ b/nixos/modules/system/etc/etc.nix @@ -231,13 +231,13 @@ in if [[ ! $IN_NIXOS_SYSTEMD_STAGE1 ]] && [[ "${config.system.build.etc}/etc" != "$(readlink -f /run/current-system/etc)" ]]; then echo "remounting /etc..." - tmpMetadataMount=$(mktemp --directory) + tmpMetadataMount=$(mktemp --directory -t nixos-etc-metadata.XXXXXXXXXX) mount --type erofs ${config.system.build.etcMetadataImage} $tmpMetadataMount # Mount the new /etc overlay to a temporary private mount. # This needs the indirection via a private bind mount because you # cannot move shared mounts. - tmpEtcMount=$(mktemp --directory) + tmpEtcMount=$(mktemp --directory -t nixos-etc.XXXXXXXXXX) mount --bind --make-private $tmpEtcMount $tmpEtcMount mount --type overlay overlay \ --options lowerdir=$tmpMetadataMount::${config.system.build.etcBasedir},${etcOverlayOptions} \ From 0f786baf5db22e7eaa0e356b9ad595d9ee000eeb Mon Sep 17 00:00:00 2001 From: r-vdp Date: Thu, 5 Sep 2024 15:28:00 +0200 Subject: [PATCH 2/3] etc: remove unneeded temporary directions after putting in place the new etc --- nixos/modules/system/etc/etc.nix | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nixos/modules/system/etc/etc.nix b/nixos/modules/system/etc/etc.nix index 7547f4304709c..e8eeae03a360b 100644 --- a/nixos/modules/system/etc/etc.nix +++ b/nixos/modules/system/etc/etc.nix @@ -276,6 +276,22 @@ in # Unmount the top /etc mount to atomically reveal the new mount. umount --lazy --recursive /etc + + # Unmount the temporary mount + umount --lazy "$tmpEtcMount" + rmdir "$tmpEtcMount" + + # Unmount old metadata mounts + # For some reason, `findmnt /tmp --submounts` does not show the nested + # mounts. So we'll just find all mounts of type erofs and filter on the + # name of the mountpoint. + findmnt --type erofs --list --kernel --output TARGET | while read -r mountPoint; do + if [[ "$mountPoint" =~ ^/tmp/nixos-etc-metadata\..{10}$ && + "$mountPoint" != "$tmpMetadataMount" ]]; then + umount --lazy $mountPoint + rmdir "$mountPoint" + fi + done fi '' else '' # Set up the statically computed bits of /etc. From 65f375d172e1088c6f412ac009f550e4b0b188eb Mon Sep 17 00:00:00 2001 From: r-vdp Date: Thu, 5 Sep 2024 15:28:46 +0200 Subject: [PATCH 3/3] etc: extend tests to ensure that temporary dirs are cleaned up --- nixos/tests/activation/etc-overlay-immutable.nix | 15 ++++++++++++++- nixos/tests/activation/etc-overlay-mutable.nix | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/nixos/tests/activation/etc-overlay-immutable.nix b/nixos/tests/activation/etc-overlay-immutable.nix index 601ac77cbd846..882bc651841a6 100644 --- a/nixos/tests/activation/etc-overlay-immutable.nix +++ b/nixos/tests/activation/etc-overlay-immutable.nix @@ -27,9 +27,14 @@ specialisation.new-generation.configuration = { environment.etc."newgen".text = "newgen"; }; + specialisation.newer-generation.configuration = { + environment.etc."newergen".text = "newergen"; + }; }; - testScript = '' + testScript = /* python */ '' + newergen = machine.succeed("realpath /run/current-system/specialisation/newer-generation/bin/switch-to-configuration").rstrip() + with subtest("/run/etc-metadata/ is mounted"): print(machine.succeed("mountpoint /run/etc-metadata")) @@ -79,5 +84,13 @@ print(machine.succeed("ls /etc/mountpoint")) print(machine.succeed("stat /etc/mountpoint/extra-file")) print(machine.succeed("findmnt /etc/filemount")) + + machine.succeed(f"{newergen} switch") + + tmpMounts = machine.succeed("find /tmp -maxdepth 1 -type d -regex '/tmp/nixos-etc\\..*' | wc -l").rstrip() + metaMounts = machine.succeed("find /tmp -maxdepth 1 -type d -regex '/tmp/nixos-etc-metadata\\..*' | wc -l").rstrip() + + assert tmpMounts == "0", f"Found {tmpMounts} remaining tmpmounts" + assert metaMounts == "1", f"Found {metaMounts} remaining metamounts" ''; } diff --git a/nixos/tests/activation/etc-overlay-mutable.nix b/nixos/tests/activation/etc-overlay-mutable.nix index fe6165212470c..ef465e3616c35 100644 --- a/nixos/tests/activation/etc-overlay-mutable.nix +++ b/nixos/tests/activation/etc-overlay-mutable.nix @@ -15,9 +15,14 @@ specialisation.new-generation.configuration = { environment.etc."newgen".text = "newgen"; }; + specialisation.newer-generation.configuration = { + environment.etc."newergen".text = "newergen"; + }; }; - testScript = '' + testScript = /* python */ '' + newergen = machine.succeed("realpath /run/current-system/specialisation/newer-generation/bin/switch-to-configuration").rstrip() + with subtest("/run/etc-metadata/ is mounted"): print(machine.succeed("mountpoint /run/etc-metadata")) @@ -55,5 +60,14 @@ print(machine.succeed("findmnt /etc/mountpoint")) print(machine.succeed("stat /etc/mountpoint/extra-file")) print(machine.succeed("findmnt /etc/filemount")) + + machine.succeed(f"{newergen} switch") + assert machine.succeed("cat /etc/newergen") == "newergen" + + tmpMounts = machine.succeed("find /tmp -maxdepth 1 -type d -regex '/tmp/nixos-etc\\..*' | wc -l").rstrip() + metaMounts = machine.succeed("find /tmp -maxdepth 1 -type d -regex '/tmp/nixos-etc-metadata\\..*' | wc -l").rstrip() + + assert tmpMounts == "0", f"Found {tmpMounts} remaining tmpmounts" + assert metaMounts == "1", f"Found {metaMounts} remaining metamounts" ''; }