aboutsummaryrefslogtreecommitdiff
path: root/src/property/mount.lisp
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2021-04-30 15:20:50 -0700
committerSean Whitton <spwhitton@spwhitton.name>2021-04-30 17:56:41 -0700
commit9f0ba8d603de49e52f7ed75cecb092ad0d0d0771 (patch)
treeb25b7e54c1c5479c94d4a177f226b932edb4ba73 /src/property/mount.lisp
parent691c81810e647ef7d780f4f3546ee8856f777b07 (diff)
downloadconsfigurator-9f0ba8d603de49e52f7ed75cecb092ad0d0d0771.tar.gz
MOUNT:UNMOUNTED-BELOW: stop calling 'mount --make-rslave'
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
Diffstat (limited to 'src/property/mount.lisp')
-rw-r--r--src/property/mount.lisp38
1 files changed, 31 insertions, 7 deletions
diff --git a/src/property/mount.lisp b/src/property/mount.lisp
index fe805ad..72eb8d7 100644
--- a/src/property/mount.lisp
+++ b/src/property/mount.lisp
@@ -19,14 +19,42 @@
(named-readtables:in-readtable :consfigurator)
(defprop unmounted-below :posix (dir)
- "Unmount anything mounted at or below DIR."
+ "Unmount anything mounted at or below DIR.
+
+Not aware of shared subtrees, so you might need to use the --make-rslave
+option to mount(1) first. For example, if you did 'mount --rbind /dev
+chroot/dev' then unless you also execute 'mount --make-rslave chroot/dev',
+this property will empty /dev, breaking all kinds of things."
(:desc #?"${dir} unmounted")
(:hostattrs
- (declare (ignore dir))
- ;; findmnt(1) & arguments to mount(1)/umount(1) we use are from util-linux
+ ;; findmnt(1) & --recursive argument to umount(1) are from util-linux
(os:required 'os:linux))
(:apply
(with-change-if-changes-file-content ("/proc/mounts")
+ ;; We used to call --make-rslave as we worked through, but for mounts
+ ;; which were *not* made using the --rbind option to mount(1) or similar,
+ ;; doing that can can get us into a state where we can unmount everything
+ ;; we can see under DIR but the kernel will still consider the block
+ ;; device to be in use. That's a bit much for this property to deal
+ ;; with, so we require that the caller call --make-rslave as appropriate.
+ ;;
+ ;; In addition to that problem, we would also require multiple unmount
+ ;; passes; for example if we
+ ;;
+ ;; % mount --bind chroot chroot
+ ;; % mount proc chroot/proc -t proc
+ ;; % mount --make-rslave chroot
+ ;;
+ ;; then we would need
+ ;;
+ ;; % umount chroot/proc
+ ;; % umount chroot
+ ;; % umount chroot/proc
+ ;;
+ ;; because the --make-rslave leaves us with two independent mounts of
+ ;; /proc, and the second can't be removed until the bind mount is
+ ;; removed. (This situation arises because :CHROOT.FORK connections bind
+ ;; mount the chroot on itself if it is not already a mount point.)
(let* ((dir (ensure-directory-pathname dir))
(all-mounts
(mapcar #'ensure-directory-pathname
@@ -36,10 +64,6 @@
(loop as next = (pop sorted)
while next
do (loop while (subpathp (car sorted) next) do (pop sorted))
- ;; If any of the mounts were made with --rbind then unmounting
- ;; will unmount the source filesystems too (e.g. things
- ;; mounted under /dev), so use --make-rslave to prevent that.
- (mrun "mount" "--make-rslave" next)
(mrun "umount" "--recursive" next))))))
(defproplist unmounted-below-and-removed :posix (dir)