[v2,38/57] ns: Reserve pid_ns helpers

Submitted by Kirill Tkhai on March 28, 2017, 3:39 p.m.

Details

Message ID 149071558986.12770.838412186779354579.stgit@localhost.localdomain
State New
Series "Nested pid namespaces support"
Headers show

Commit Message

Kirill Tkhai March 28, 2017, 3:39 p.m.
Task is able to set "/proc/sys/kernel/ns_last_pid" only for
its active pid_ns. So, if we create a multi-level pid task,
we need helpers, which allow to set pids in whole pid hierarhy.

This patch reserves a helper for every pid_ns from free pids
of this ns.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/include/namespaces.h |    1 +
 criu/namespaces.c         |   37 +++++++++++++++++++++++++++++++++++++
 criu/pstree.c             |    2 ++
 3 files changed, 40 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index 8764a898..8934e5f5 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -264,5 +264,6 @@  static inline int pid_ns_root_off(void)
 		return 1;
 	return 0;
 }
+extern int reserve_pid_ns_helpers(void);
 
 #endif /* __CR_NS_H__ */
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 9d517815..9c815c34 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -2428,5 +2428,42 @@  int set_user_ns(u32 id)
 	return __set_user_ns(ns);
 }
 
+static int do_reserve_pid_ns_helpers(struct ns_id *ns, void *oarg)
+{
+	struct pstree_item *helper;
+	struct ns_id *iter = ns;
+	pid_t pid[MAX_NS_NESTING], *p;
+	int i, level;
+
+	for (i = MAX_NS_NESTING-1; iter && i >= 0; i--, iter = iter->parent) {
+		pid[i] = get_free_pid(iter);
+		if (pid[i] < 0) {
+			pr_err("Can't find free pid\n");
+			return -1;
+		}
+	}
+
+	if (iter) {
+		pr_err("Too many pids levels\n");
+		return -1;
+	}
+
+	p = &pid[++i];
+	level = MAX_NS_NESTING - i;
+	helper = lookup_create_item(p, level, ns->id);
+	if (helper == NULL)
+		return -1;
+	ns->ns_pid = pid[MAX_NS_NESTING-1];
+	return 0;
+}
+
+int reserve_pid_ns_helpers(void)
+{
+	if (!(root_ns_mask & CLONE_NEWPID))
+		return 0;
+
+	return walk_namespaces(&pid_ns_desc, do_reserve_pid_ns_helpers, NULL);
+}
+
 struct ns_desc pid_ns_desc = NS_DESC_ENTRY(CLONE_NEWPID, "pid");
 struct ns_desc user_ns_desc = NS_DESC_ENTRY(CLONE_NEWUSER, "user");
diff --git a/criu/pstree.c b/criu/pstree.c
index ecc46761..19e8acdc 100644
--- a/criu/pstree.c
+++ b/criu/pstree.c
@@ -1191,6 +1191,8 @@  int prepare_pstree(void)
 		 * pstree with properly injected helper tasks.
 		 */
 		ret = prepare_pstree_ids();
+	if (!ret)
+		ret = reserve_pid_ns_helpers();
 
 	return ret;
 }