[CRIU] [PATCH 10/39] crtools: restore nested mount namespaces (v2)

Andrey Vagin avagin at openvz.org
Mon Apr 21 07:23:20 PDT 2014


Known issue:
* currently only namespaces with the same root is supported
* nested namespaces can be dumped and restored only if the root task
  has own mount namespace.

All nested namespaces are restored in a root namespace in temporary
directories. All mount points restored in one tree and then they are
divided into namesaces.
The task with minimal pid for each namespaces unshared mntns and
then it makes pivot_root in a proper temporary directory. All other
tasks makes setns to enter into a mount namespace of the task with
minimal pid.

v2: clean up

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-restore.c         | 12 ++++++++++++
 include/mount.h      |  2 ++
 include/namespaces.h |  1 +
 mount.c              | 37 +++++++++++++++++++++++++++++++++++++
 namespaces.c         |  1 +
 5 files changed, 53 insertions(+)

diff --git a/cr-restore.c b/cr-restore.c
index 4c4e459..ac4c79b 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1286,6 +1286,18 @@ static int restore_task_with_children(void *_arg)
 	if (create_children_and_session())
 		goto err;
 
+	if (current->ids && current->ids->has_mnt_ns_id) {
+		struct ns_id *nsid;
+
+		nsid = lookup_ns_by_id(current->ids->mnt_ns_id, &mnt_ns_desc);
+		if (nsid == NULL) {
+			pr_err("Can't find mount namespace %d\n", current->ids->mnt_ns_id);
+			goto err;
+		}
+		if (restore_task_mnt_ns(nsid, current->pid.real))
+			goto err;
+	}
+
 	if (unmap_guard_pages())
 		goto err;
 
diff --git a/include/mount.h b/include/mount.h
index 4fd10e3..86836ea 100644
--- a/include/mount.h
+++ b/include/mount.h
@@ -24,6 +24,8 @@ extern struct ns_desc mnt_ns_desc;
 extern dev_t phys_stat_resolve_dev(dev_t st_dev, const char *path);
 extern bool phys_stat_dev_match(dev_t st_dev, dev_t phys_dev, const char *path);
 
+struct ns_id;
+extern int restore_task_mnt_ns(struct ns_id *nsid, pid_t pid);
 extern int fini_mnt_ns(void);
 
 #endif /* __CR_MOUNT_H__ */
diff --git a/include/namespaces.h b/include/namespaces.h
index ec410e2..a1fc714 100644
--- a/include/namespaces.h
+++ b/include/namespaces.h
@@ -15,6 +15,7 @@ struct ns_id {
 	pid_t pid;
 	struct ns_desc *nd;
 	struct ns_id *next;
+	futex_t created; /* boolean */
 };
 extern struct ns_id *ns_ids;
 
diff --git a/mount.c b/mount.c
index 5262b08..26a0100 100644
--- a/mount.c
+++ b/mount.c
@@ -1528,6 +1528,43 @@ err:
 	return NULL;
 }
 
+int restore_task_mnt_ns(struct ns_id *nsid, pid_t pid)
+{
+	char path[PATH_MAX];
+
+	if (root_item->ids->mnt_ns_id == nsid->id)
+		return 0;
+
+	if (nsid->pid != getpid()) {
+		int fd;
+
+		futex_wait_while_eq(&nsid->created, 0);
+		fd = open_proc(nsid->pid, "ns/mnt");
+		if (fd < 0)
+			return -1;
+
+		if (setns(fd, CLONE_NEWNS)) {
+			pr_perror("Unable to change mount namespace");
+			return -1;
+		}
+		return 0;
+	}
+
+	if (unshare(CLONE_NEWNS)) {
+		pr_perror("Unable to unshare mount namespace");
+		return -1;
+	}
+
+	snprintf(path, sizeof(path), "%s/%d/", mnt_roots, nsid->id);
+
+	if (cr_pivot_root(path))
+		return -1;
+
+	futex_set_and_wake(&nsid->created, 1);
+
+	return 0;
+}
+
 /*
  * All nested mount namespaces are restore as sub-trees of the root namespace.
  */
diff --git a/namespaces.c b/namespaces.c
index 7613049..bcb9ddf 100644
--- a/namespaces.c
+++ b/namespaces.c
@@ -136,6 +136,7 @@ int rst_add_ns_id(unsigned int id, pid_t pid, struct ns_desc *nd)
 	nsid->nd = nd;
 	nsid->id = id;
 	nsid->pid = pid;
+	futex_set(&nsid->created, 0);
 
 	nsid->next = ns_ids;
 	ns_ids = nsid;
-- 
1.8.5.3



More information about the CRIU mailing list