[CRIU] [PATCH 1/2] mount: restore mounts in the root mount namespace

Andrei Vagin avagin at openvz.org
Tue Feb 21 22:39:45 PST 2017


From: Andrei Vagin <avagin at virtuozzo.com>

Currently all mounts are restored in a one mount namespace, then
this namespace is cloned to restore other mount namespaces and
we need another copy of this namespace to clean link remap files.

Let's define terms:
A - the root mount namespace
B - the mount namespace where link remap files are destroyed

Currently we restore all mounts in the B namespace and then
clone it into the A namespace.

But it doesn't work in a case, when we have to open file
descriptores to restore mounts (e g to restore bind-mount
pty slaves), because a file descriptor has to be opened from
a specified mount (which is one of restore mount namespaces).

This patch reworks code so, that all mounts is restored in the A mount
namespace and then the B mount namespace is created. In this case
we can open files from the root mount namespace (A).

$ ./zdtm.py run -t zdtm/static/pty-console --iter 5

====================== Run zdtm/static/pty-console in ns =======================
Start test
Test is SUID
./pty-console --pidfile=pty-console.pid --outfile=pty-console.out
Run criu dump
Run criu restore
Run criu dump
=[log]=> dump/zdtm/static/pty-console/36/2/dump.log
------------------------ grep Error ------------------------
(00.106521) Error (criu/files-reg.c:1132): Can't lookup mount=563 for fd=4 path=/ptmx
(00.106585) Error (criu/cr-dump.c:1325): Dump files (pid: 70) failed with -1
(00.129041) Error (criu/cr-dump.c:1674): Dumping FAILED.
------------------------ ERROR OVER ------------------------

Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 criu/cr-restore.c       | 21 +++++++++++++++++----
 criu/include/restorer.h |  5 +++++
 criu/mount.c            | 32 +++++++++++++++++++++++++++-----
 3 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index b5e33c8..a358ca0 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1432,6 +1432,9 @@ static int restore_task_with_children(void *_arg)
 		if (prepare_namespace(current, ca->clone_flags))
 			goto err;
 
+		if (restore_finish_stage(task_entries, CR_STATE_POST_RESTORE_NS) < 0)
+			goto err;
+
 		if (root_prepare_shared())
 			goto err;
 
@@ -1495,6 +1498,7 @@ static inline int stage_participants(int next_stage)
 	case CR_STATE_FAIL:
 		return 0;
 	case CR_STATE_RESTORE_NS:
+	case CR_STATE_POST_RESTORE_NS:
 	case CR_STATE_RESTORE_SHARED:
 		return 1;
 	case CR_STATE_FORKING:
@@ -1883,16 +1887,25 @@ static int restore_root_task(struct pstree_item *init)
 	if (ret)
 		goto out_kill;
 
+	ret = run_scripts(ACT_SETUP_NS);
+	if (ret)
+		goto out_kill;
+
+	ret = restore_switch_stage(CR_STATE_POST_RESTORE_NS);
+	if (ret < 0)
+		goto out_kill;
+
+	pr_info("Wait until namespaces are created\n");
+	ret = restore_wait_inprogress_tasks();
+	if (ret)
+		goto out_kill;
+
 	if (root_ns_mask & CLONE_NEWNS) {
 		mnt_ns_fd = open_proc(init->pid->real, "ns/mnt");
 		if (mnt_ns_fd < 0)
 			goto out_kill;
 	}
 
-	ret = run_scripts(ACT_SETUP_NS);
-	if (ret)
-		goto out_kill;
-
 	if (opts.empty_ns & CLONE_NEWNET) {
 		/*
 		 * Local TCP connections were locked by network_lock_internal()
diff --git a/criu/include/restorer.h b/criu/include/restorer.h
index 715640d..9a392a8 100644
--- a/criu/include/restorer.h
+++ b/criu/include/restorer.h
@@ -206,6 +206,11 @@ static inline unsigned long restorer_stack(struct restore_mem_zone *mz)
 enum {
 	CR_STATE_FAIL		= -1,
 	CR_STATE_RESTORE_NS	= 0, /* is used for executing "setup-namespace" scripts */
+	/*
+	 * Need to wait a mount namespace which
+	 * will be used to clean up remap files.
+	 */
+	CR_STATE_POST_RESTORE_NS,
 	CR_STATE_RESTORE_SHARED,
 	CR_STATE_FORKING,
 	CR_STATE_RESTORE,
diff --git a/criu/mount.c b/criu/mount.c
index 37207da..5520b23 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -2948,17 +2948,39 @@ int prepare_mnt_ns(void)
 			goto err;
 		}
 
+		if (nsid->type == NS_ROOT) {
+			int fd;
+
+			/*
+			 * We need to create a mount namespace which will be
+			 * used to clean up remap files
+			 * (depopulate_roots_yard).  The namespace where mounts
+			 * was restored has to be restored as a root mount
+			 * namespace, because there are file descriptors
+			 * linked with it (e.g. to bind-mount slave pty-s).
+			 */
+			fd = open_proc(PROC_SELF, "ns/mnt");
+			if (fd < 0)
+				goto err;
+			if (setns(rst, CLONE_NEWNS)) {
+				pr_perror("Can't restore mntns back");
+				goto err;
+			}
+			nsid->mnt.ns_fd = rst;
+			rst = fd;
+		} else {
+			/* Pin one with a file descriptor */
+			nsid->mnt.ns_fd = open_proc(PROC_SELF, "ns/mnt");
+			if (nsid->mnt.ns_fd < 0)
+				goto err;
+		}
+
 		/* Set its root */
 		path[0] = '/';
 		print_ns_root(nsid, 0, path + 1, sizeof(path) - 1);
 		if (cr_pivot_root(path))
 			goto err;
 
-		/* Pin one with a file descriptor */
-		nsid->mnt.ns_fd = open_proc(PROC_SELF, "ns/mnt");
-		if (nsid->mnt.ns_fd < 0)
-			goto err;
-
 		/* root_fd is used to restore file mappings */
 		nsid->mnt.root_fd = open_proc(PROC_SELF, "root");
 		if (nsid->mnt.root_fd < 0)
-- 
2.7.4



More information about the CRIU mailing list