← Back to team overview

curtin-dev team mailing list archive

[Merge] ~mwhudson/curtin:lp-1928839 into curtin:master

 

Michael Hudson-Doyle has proposed merging ~mwhudson/curtin:lp-1928839 into curtin:master.

Commit message:
fix tearing down ChrootableTarget when mounts appear while it is set up

There are several bug reports that boil down to
ChrootableTarget.__exit__ failing to unmount bind mounts with "target is
busy". For example, ssh-ing in while running tends to do this, because
that creates a mount in /run and then umounting /target/run fails
because of the sub mount. Fix this by marking the mountpoints
recursively private and then unmounting them recursively.

LP: #1928839
LP: #1934775


Requested reviews:
  Server Team CI bot (server-team-bot): continuous-integration
  curtin developers (curtin-dev)
Related bugs:
  Bug #1928839 in curtin: "MaaS/Curtin fail to unmount /target/run way too often"
  https://bugs.launchpad.net/curtin/+bug/1928839
  Bug #1934775 in curtin: "Installer crash when trying to unmount target"
  https://bugs.launchpad.net/curtin/+bug/1934775

For more details, see:
https://code.launchpad.net/~mwhudson/curtin/+git/curtin/+merge/405670

Hopefully this fixes a problem that's always niggled at me.
-- 
Your team curtin developers is requested to review the proposed merge of ~mwhudson/curtin:lp-1928839 into curtin:master.
diff --git a/curtin/util.py b/curtin/util.py
index be063d7..7be3033 100644
--- a/curtin/util.py
+++ b/curtin/util.py
@@ -695,7 +695,22 @@ class ChrootableTarget(object):
             log_call(subp, ['udevadm', 'settle'])
 
         for p in reversed(self.umounts):
-            do_umount(p)
+            # Consider the following sequence:
+            #
+            # mkdir a a/b c
+            # mount --bind a c
+            # mount -t sysfs sysfs a/b
+            # umount c
+            #
+            # This umount fails with "mountpoint is busy", because of
+            # the mountpoint at c/b. But if we unmount c recursively,
+            # a/b ends up getting unmounted. What we need to do is to
+            # make the mountpoints c and c/b "private" so that
+            # unmounting them does not propagate to the mount tree c
+            # was cloned from (See "Shared subtree operations" in
+            # mount(8) for more on this).
+            subp(['mount', '--make-rprivate', p])
+            do_umount(p, recursive=True)
 
         rconf = paths.target_path(self.target, "/etc/resolv.conf")
         if self.sys_resolvconf and self.rconf_d: