[v3,30/55] pid: Use collect_pid_status() to populate item's pids

Submitted by Kirill Tkhai on April 10, 2017, 8:20 a.m.

Details

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

Commit Message

Kirill Tkhai April 10, 2017, 8:20 a.m.
If there are several pid namespaces, then collect pids
in all pid hierarhy.

v2: Check for kdat.has_nspid instead of top_pid_ns->children,
because top_pid_ns may be not set at the moment.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/cr-dump.c |   39 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index dd6884e7b..89e617a6b 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -586,11 +586,21 @@  static int get_task_personality(pid_t pid, u32 *personality)
 	return ret;
 }
 
+static void add_ns_pid(struct pid *pid, uint32_t *nspid, int nr)
+{
+	pid->level = nr;
+	while (nr-- > 0)
+		pid->ns[nr].virt = nspid[nr];
+}
+
 static int populate_ns_pids(pid_t real_pid, pid_t real_tid,
 			    struct pid **pid, struct pid **sid, struct pid **pgid,
 			    pid_t parasite_pid, pid_t parasite_sid, pid_t parasite_pgid)
 {
-	if (1) {
+	struct proc_pid_status st;
+	unsigned nr, sz;
+
+	if (!kdat.has_nspid) {
 		(*pid)->ns[0].virt = parasite_pid;
 		if (real_tid < 0) {
 			(*sid)->ns[0].virt = parasite_sid;
@@ -598,6 +608,33 @@  static int populate_ns_pids(pid_t real_pid, pid_t real_tid,
 		}
 		return 0;
 	}
+
+	if (collect_pid_status(real_pid, real_tid, pid_ns_root_off(), &st) < 0) {
+		pr_err("Can't parse /proc/%d/status\n", (*pid)->real);
+		return -1;
+	}
+	nr = st.n_levels;
+	BUG_ON(st.nspid[nr-1] != parasite_pid ||
+	      (real_tid < 0 && (st.nssid[nr-1] != parasite_sid || st.nspgid[nr-1] != parasite_pgid)));
+
+	if (nr > 1) {
+		sz = (sizeof(struct pid) + (nr - 1) * sizeof((*pid)->ns[0]));
+		*pid = xrealloc(*pid, sz);
+		if (real_tid < 0) {
+			*sid = xrealloc(*sid, sz);
+			*pgid = xrealloc(*pgid, sz);
+		}
+		if (!*pid || (real_tid < 0 && (!*sid || !*pgid)))
+			return -1;
+	}
+
+	add_ns_pid(*pid, st.nspid, nr);
+	if (real_tid < 0) {
+		add_ns_pid(*sid, st.nssid, nr);
+		add_ns_pid(*pgid, st.nspgid, nr);
+	}
+	free_pid_status(&st);
+
 	return 0;
 }