diff -Nru curtin-21.2-942-gc6cc8412/curtin/util.py curtin-21.2-943-g1f663e51/curtin/util.py --- curtin-21.2-942-gc6cc8412/curtin/util.py 2021-07-15 16:32:09.000000000 +0000 +++ curtin-21.2-943-g1f663e51/curtin/util.py 2021-07-16 16:32:58.000000000 +0000 @@ -695,7 +695,26 @@ 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). + # + # Related bug reports: + # https://bugs.launchpad.net/maas/+bug/1928839 + # https://bugs.launchpad.net/subiquity/+bug/1934775 + 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: diff -Nru curtin-21.2-942-gc6cc8412/debian/changelog curtin-21.2-943-g1f663e51/debian/changelog --- curtin-21.2-942-gc6cc8412/debian/changelog 2021-07-15 16:32:12.000000000 +0000 +++ curtin-21.2-943-g1f663e51/debian/changelog 2021-07-16 16:33:00.000000000 +0000 @@ -1,8 +1,8 @@ -curtin (21.2-942-gc6cc8412-0ubuntu1+307~trunk~ubuntu20.10.1) groovy; urgency=low +curtin (21.2-943-g1f663e51-0ubuntu1+307~trunk~ubuntu20.10.1) groovy; urgency=low * Auto build. - -- curtin developers Thu, 15 Jul 2021 16:32:12 +0000 + -- curtin developers Fri, 16 Jul 2021 16:33:00 +0000 curtin (20.2-0ubuntu1) groovy; urgency=medium diff -Nru curtin-21.2-942-gc6cc8412/debian/git-build-recipe.manifest curtin-21.2-943-g1f663e51/debian/git-build-recipe.manifest --- curtin-21.2-942-gc6cc8412/debian/git-build-recipe.manifest 2021-07-15 16:32:12.000000000 +0000 +++ curtin-21.2-943-g1f663e51/debian/git-build-recipe.manifest 2021-07-16 16:33:00.000000000 +0000 @@ -1,3 +1,3 @@ -# git-build-recipe format 0.4 deb-version 21.2-942-gc6cc8412-0ubuntu1+307~trunk -lp:curtin git-commit:c6cc84128292cd21becbd3e16a536526006b7d6f +# git-build-recipe format 0.4 deb-version 21.2-943-g1f663e51-0ubuntu1+307~trunk +lp:curtin git-commit:1f663e5104bbd3304c215a2b5f32a9f8103cba80 merge ubuntu-pkg lp:curtin git-commit:e46e3c216e47c1801001ba390580b784300e961e diff -Nru curtin-21.2-942-gc6cc8412/tests/unittests/test_curthooks.py curtin-21.2-943-g1f663e51/tests/unittests/test_curthooks.py --- curtin-21.2-942-gc6cc8412/tests/unittests/test_curthooks.py 2021-07-15 16:32:09.000000000 +0000 +++ curtin-21.2-943-g1f663e51/tests/unittests/test_curthooks.py 2021-07-16 16:32:58.000000000 +0000 @@ -109,7 +109,7 @@ def test_disable_changes_binary_name_write_dummy_binary(self): self.mock_which.return_value = self.update_initramfs - self.mock_subp.side_effect = iter([('', '')] * 10) + self.mock_subp.side_effect = iter([('', '')] * 15) curthooks.disable_update_initramfs({}, self.target) self.assertIn( call(['dpkg-divert', '--add', '--rename', '--divert', @@ -215,18 +215,25 @@ target = os.path.join(self.target, point) return call(['mount', '--bind', '/%s' % point, target]) + def _rpriv_call(self, point): + target = os.path.join(self.target, point) + return call(['mount', '--make-rprivate', target]) + def _side_eff(self, cmd_out=None, cmd_err=None): if cmd_out is None: cmd_out = '' if cmd_err is None: cmd_err = '' effects = ([('mount', '')] * len(self.mounts) + - [(cmd_out, cmd_err)] + [('settle', '')]) + [(cmd_out, cmd_err)] + + [('settle', '')] + + [('mount', '')]*len(self.mounts)) return effects def _subp_calls(self, mycall): pre = [self._mnt_call(point) for point in self.mounts] - post = [call(['udevadm', 'settle'])] + post = [call(['udevadm', 'settle'])] + [ + self._rpriv_call(point) for point in reversed(self.mounts)] return pre + [mycall] + post def test_does_nothing_if_binary_diverted(self): @@ -243,7 +250,7 @@ target=self.target) calls = self._subp_calls(dcall) self.mock_subp.assert_has_calls(calls) - self.assertEqual(6, self.mock_subp.call_count) + self.assertEqual(10, self.mock_subp.call_count) def test_mounts_and_runs(self): # in_chroot calls to dpkg-divert, update-initramfs @@ -256,7 +263,7 @@ call(['update-initramfs', '-c', '-k', self.kversion], target=self.target)) self.mock_subp.assert_has_calls(subp_calls) - self.assertEqual(12, self.mock_subp.call_count) + self.assertEqual(20, self.mock_subp.call_count) def test_mounts_and_runs_for_all_kernels(self): kversion2 = '5.4.0-generic' @@ -280,7 +287,7 @@ call(['update-initramfs', '-c', '-k', kversion2], target=self.target)) self.mock_subp.assert_has_calls(subp_calls) - self.assertEqual(24, self.mock_subp.call_count) + self.assertEqual(40, self.mock_subp.call_count) def test_calls_update_if_initrd_exists_else_create(self): kversion2 = '5.2.0-generic' @@ -290,7 +297,7 @@ with open(os.path.join(self.boot, 'initrd.img-' + kversion2), 'w'): pass - effects = self._side_eff() * 3 + effects = self._side_eff() * 4 self.mock_subp.side_effect = iter(effects) curthooks.update_initramfs(self.target, True) subp_calls = self._subp_calls( @@ -302,7 +309,7 @@ call(['update-initramfs', '-c', '-k', self.kversion], target=self.target)) self.mock_subp.assert_has_calls(subp_calls) - self.assertEqual(18, self.mock_subp.call_count) + self.assertEqual(30, self.mock_subp.call_count) class TestSetupKernelImgConf(CiTestCase):