Re: [Lxc-users] Can't start a 2nd container with 0.6.5
Daniel Lezcano
Sat, 23 Jan 2010 13:44:33 -0800

Brian K. White wrote:
> However, now when I go to make a 2nd container, I can't start it.
> I can create it, but not execute or start.
> [...] 
> Well I'm more boggled now.
> I stopped my first container nj12.
> lxc-ls shows nothing, screen -ls shows nothing, mount shows nothing extra, yet trying to start nj13 still fails, and trying to start nj12 still succeeds.
>
> I can't find anything functionally different between nj12 and nj13...
> What could I be missing???

Yep, there is a problem with the pivot root and the umount of the different mount point in the old rootfs. This problem appears with some configuration (I didn't figure out which one yet), I did a hot fix, which is more a workaround than a real fix, (I didnt't understand where is coming the real problem).

As soon as I find the culprit, I will release a 0.6.6 version to fix that as the 0.6.5 is bogus.

In the meantime, if you wish to test, I attached the patch to this email.

Thanks for reporting the problem.

 -- Daniel

---
 src/lxc/conf.c |   41 ++++++++++++++++++++++++++++++-----------
 1 file changed, 30 insertions(+), 11 deletions(-)

Index: lxc/src/lxc/conf.c
===================================================================
--- lxc.orig/src/lxc/conf.c
+++ lxc/src/lxc/conf.c
@@ -67,6 +67,10 @@ lxc_log_define(lxc_conf, lxc);
 #define MS_REC 16384
 #endif
 
+#ifndef MNT_DETACH
+#define MNT_DETACH 2
+#endif
+
 #ifndef CAP_SETFCAP
 #define CAP_SETFCAP 31
 #endif
@@ -532,6 +536,7 @@ static int setup_rootfs_pivot_root(const
 
 		lxc_list_for_each(iterator, &mountlist) {
 
+			/* umount normally */
 			if (!umount(iterator->elem)) {
 				DEBUG("umounted '%s'", (char *)iterator->elem);
 				lxc_list_del(iterator);
@@ -544,24 +549,38 @@ static int setup_rootfs_pivot_root(const
 	} while (still_mounted > 0 && still_mounted != last_still_mounted);
 
 
-	lxc_list_for_each(iterator, &mountlist)
+	lxc_list_for_each(iterator, &mountlist) {
+
+		/* let's try a lazy umount */
+		if (!umount2(iterator->elem, MNT_DETACH)) {
+			INFO("lazy unmount of '%s'", (char *)iterator->elem);
+			continue;
+		}
+
+		/* be more brutal (nfs) */
+		if (!umount2(iterator->elem, MNT_FORCE)) {
+			INFO("forced unmount of '%s'", (char *)iterator->elem);
+			continue;
+		}
+
 		WARN("failed to unmount '%s'", (char *)iterator->elem);
+	}
 
-	/* umount old root fs */
-	if (umount(pivotdir)) {
+	/* umount old root fs; if some other mount points are still
+	 * there, we won't be able to umount it, so we have to do
+	 * that in a lazy way otherwise the container will always
+	 * fail to start
+	 */
+	if (umount2(pivotdir, MNT_DETACH)) {
 		SYSERROR("could not unmount old rootfs");
 		return -1;
 	}
 	DEBUG("umounted '%s'", pivotdir);
 
-	/* remove temporary mount point */
-	if (pivotdir_is_temp) {
-		if (rmdir(pivotdir)) {
-			SYSERROR("can't remove temporary mountpoint");
-			return -1;
-		}
-
-	}
+	/* remove temporary mount point, we don't consider the removing
+	 * as fatal */
+	if (pivotdir_is_temp && rmdir(pivotdir))
+		WARN("can't remove temporary mountpoint: %m");
 
 	INFO("pivoted to '%s'", rootfs);
 	return 0;
