[CRIU] [PATCH] restore: restore mntns before creating private vma-s (v3)

Andrey Vagin avagin at openvz.org
Fri Nov 13 09:55:52 PST 2015


From: Andrew Vagin <avagin at virtuozzo.com>

We need to open a file to restore a file mapping and this file
can be from a current mntns.

v2: All namespaces are resotred from the root task and then
other tasks calls setns() to set a proper mntns.

v3: fix comments from Pavel
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 cr-restore.c         | 19 ++++++-------
 include/namespaces.h |  1 +
 mount.c              | 76 +++++++++++++++++++++++++++++++++-------------------
 3 files changed, 57 insertions(+), 39 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index 0350a23..c132588 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1520,9 +1520,6 @@ static int restore_task_with_children(void *_arg)
 		if (mount_proc())
 			goto err_fini_mnt;
 
-		if (close_old_fds(current))
-			goto err_fini_mnt;
-
 		if (root_prepare_shared())
 			goto err_fini_mnt;
 
@@ -1530,14 +1527,11 @@ static int restore_task_with_children(void *_arg)
 			goto err_fini_mnt;
 	}
 
-	if (prepare_mappings())
+	if (restore_task_mnt_ns(current))
 		goto err_fini_mnt;
 
-	if (!(ca->clone_flags & CLONE_FILES)) {
-		ret = close_old_fds(current);
-		if (ret)
-			goto err_fini_mnt;
-	}
+	if (prepare_mappings())
+		goto err_fini_mnt;
 
 	/*
 	 * Call this _before_ forking to optimize cgroups
@@ -1559,8 +1553,11 @@ static int restore_task_with_children(void *_arg)
 	if (create_children_and_session())
 		goto err_fini_mnt;
 
-	if (restore_task_mnt_ns(current))
-		goto err_fini_mnt;
+	if (!(ca->clone_flags & CLONE_FILES)) {
+		ret = close_old_fds(current);
+		if (ret)
+			goto err_fini_mnt;
+	}
 
 	if (unmap_guard_pages())
 		goto err_fini_mnt;
diff --git a/include/namespaces.h b/include/namespaces.h
index f511290..9b7dca3 100644
--- a/include/namespaces.h
+++ b/include/namespaces.h
@@ -37,6 +37,7 @@ struct ns_id {
 		struct {
 			struct mount_info *mntinfo_list;
 			struct mount_info *mntinfo_tree;
+			int ns_fd;
 		} mnt;
 
 		struct {
diff --git a/mount.c b/mount.c
index 5a5b90a..960cb5d 100644
--- a/mount.c
+++ b/mount.c
@@ -2590,36 +2590,13 @@ int mntns_maybe_create_roots(void)
 
 static int do_restore_task_mnt_ns(struct ns_id *nsid, struct pstree_item *current)
 {
-	char path[PATH_MAX];
-
-	if (nsid->ns_pid != current->pid.virt) {
-		int fd;
-
-		futex_wait_while_eq(&nsid->ns_created, 0);
-		fd = open_proc(nsid->ns_pid, "ns/mnt");
-		if (fd < 0)
-			return -1;
-
-		if (setns(fd, CLONE_NEWNS)) {
-			pr_perror("Unable to change mount namespace");
-			return -1;
-		}
-
-		close(fd);
-		return 0;
-	}
-
-	if (unshare(CLONE_NEWNS)) {
-		pr_perror("Unable to unshare mount namespace");
+	if (setns(nsid->mnt.ns_fd, CLONE_NEWNS)) {
+		pr_perror("Can't restore mntns");
 		return -1;
 	}
 
-	path[0] = '/';
-	print_ns_root(nsid, path + 1, sizeof(path) - 1);
-	if (cr_pivot_root(path))
-		return -1;
-
-	futex_set_and_wake(&nsid->ns_created, 1);
+	if (nsid->ns_pid == current->pid.virt)
+		futex_set_and_wake(&nsid->ns_created, 1);
 
 	return 0;
 }
@@ -2642,6 +2619,9 @@ int restore_task_mnt_ns(struct pstree_item *current)
 		if (root_item->ids->mnt_ns_id == id)
 			return 0;
 
+		if (!current->parent && id == current->parent->ids->mnt_ns_id)
+			return 0;
+
 		nsid = lookup_ns_by_id(id, &mnt_ns_desc);
 		if (nsid == NULL) {
 			pr_err("Can't find mount namespace %d\n", id);
@@ -2762,9 +2742,10 @@ void cleanup_mnt_ns(void)
 
 int prepare_mnt_ns(void)
 {
-	int ret = -1;
+	int ret = -1, rst = -1;
 	struct mount_info *old;
 	struct ns_id ns = { .type = NS_CRIU, .ns_pid = PROC_SELF, .nd = &mnt_ns_desc };
+	struct ns_id *nsid;
 
 	if (!(root_ns_mask & CLONE_NEWNS))
 		return rst_collect_local_mntns();
@@ -2842,7 +2823,46 @@ int prepare_mnt_ns(void)
 	if (!ret && opts.root)
 		ret = cr_pivot_root(NULL);
 
+	rst = open_proc(PROC_SELF, "ns/mnt");
+	if (rst < 0)
+		return -1;
+
+	/* resotre non-root namespaces */
+	for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) {
+		char path[PATH_MAX];
+
+		if (nsid->nd != &mnt_ns_desc)
+			continue;
+		if (root_item->ids->mnt_ns_id == nsid->id)
+			continue;
+
+		if (unshare(CLONE_NEWNS)) {
+			pr_perror("Unable to create a new mntns");
+			goto err;
+		}
+
+		path[0] = '/';
+		print_ns_root(nsid, path + 1, sizeof(path) - 1);
+		if (cr_pivot_root(path))
+			goto err;
+
+		nsid->mnt.ns_fd = open_proc(PROC_SELF, "ns/mnt");
+		if (nsid->mnt.ns_fd < 0)
+			goto err;
+
+		/* return back to get access to the roots yard */
+		if (setns(rst, CLONE_NEWNS)) {
+			pr_perror("Can't restore mntns back");
+			goto err;
+		}
+	}
+	close(rst);
+
 	return ret;
+err:
+	if (rst)
+		restore_ns(rst, &mnt_ns_desc);
+	return -1;
 }
 
 int __mntns_get_root_fd(pid_t pid)
-- 
2.4.3



More information about the CRIU mailing list