Unmount everything under /mnt before zpool export, not just the chroot dirs
Check NixOS configurations / eval-hosts (pull_request) Successful in 10m28s

The previous fix (#42) only unmounted /mnt/{dev,proc,sys,run}, but disko
also mounts the ESP at /mnt/boot (modules/disko/baremetal.nix) -- another
nested mount blocking ZFS from unmounting its own root dataset at /mnt
the same way. Confirmed live: zpool export still failed with "cannot
unmount '/mnt': pool or dataset busy" after the chroot-only fix.

Replace the manual dev/proc/sys/run list with a single recursive
`umount -R /mnt`, which clears everything nested under /mnt -- current
and future mountpoints alike -- rather than needing to keep enumerating
whatever nixos-install/disko happen to leave mounted.
This commit is contained in:
2026-07-22 04:23:42 +00:00
parent 400af07154
commit 619324589a
+16 -13
View File
@@ -180,19 +180,22 @@ nixos-install \
# if the chosen host has no ZFS root, e.g. proxmox-*/linode-*) clears # if the chosen host has no ZFS root, e.g. proxmox-*/linode-*) clears
# that in-use state so the next import, from any hostid, succeeds. # that in-use state so the next import, from any hostid, succeeds.
# #
# nixos-install bind-mounts /dev, /proc, /sys (and usually /run) into # Anything still mounted under /mnt -- nixos-install's own leftover
# /mnt to run the target's activation script (switch-to-configuration # chroot bind mounts for running the target's activation script
# boot) in a chroot, and doesn't unmount them again once it's done. # (/mnt/dev, /mnt/proc, /mnt/sys, /mnt/run), and disko's own /mnt/boot
# Left in place, those nested mounts make ZFS refuse to unmount its own # ESP mount (modules/disko/baremetal.nix) -- blocks ZFS from unmounting
# root dataset at /mnt -- confirmed live: zpool export failed with # its root dataset at /mnt, the same way any nested mount blocks
# "cannot unmount '/mnt': pool or dataset busy", and because of this # unmounting its parent. Confirmed live: zpool export failed with
# script's `set -e`, that killed the script before it ever reached # "cannot unmount '/mnt': pool or dataset busy" even after handling the
# reboot, silently defeating the whole point of exporting first. # chroot mounts alone, because /mnt/boot was still mounted too. Because
for chroot_mount in dev proc sys run; do # of this script's `set -e`, that killed the script before it ever
if mountpoint -q "/mnt/${chroot_mount}"; then # reached reboot, silently defeating the whole point of exporting first.
umount -R "/mnt/${chroot_mount}" # Unmounting everything under /mnt up front (recursively, so nested
fi # mounts like /mnt/dev/pts come along for free) sidesteps needing to
done # enumerate every mount disko/nixos-install might leave behind.
if mountpoint -q /mnt; then
umount -R /mnt
fi
if [[ -n "$(zpool list -H -o name 2>/dev/null)" ]]; then if [[ -n "$(zpool list -H -o name 2>/dev/null)" ]]; then
echo "Exporting ZFS pool(s) before reboot..." echo "Exporting ZFS pool(s) before reboot..."