[CRIU] [PATCH 3/3] pstree: Make pstree_item::pid pointer and move virt and node to array

Kirill Tkhai ktkhai at virtuozzo.com
Wed Jan 25 07:29:04 PST 2017


So, after the patch struct pid will look as:

struct pid {
        struct pstree_item *item;
        pid_t real;
        int state;
        struct {
                pid_t virt;
                struct rb_node node;
        } ns[1];
};

Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 criu/action-scripts.c   |    2 -
 criu/autofs.c           |   12 ++---
 criu/cgroup.c           |    2 -
 criu/cr-check.c         |    2 -
 criu/cr-dump.c          |   77 ++++++++++++++++---------------
 criu/cr-restore.c       |  116 ++++++++++++++++++++++++-----------------------
 criu/cr-service.c       |    4 +-
 criu/file-lock.c        |    4 +-
 criu/files-reg.c        |   14 +++---
 criu/files.c            |   28 ++++++-----
 criu/filesystems.c      |    2 -
 criu/image.c            |    7 ++-
 criu/include/pid.h      |   11 ++--
 criu/include/pstree.h   |    4 +-
 criu/irmap.c            |    4 +-
 criu/mem.c              |   20 ++++----
 criu/mount.c            |    8 ++-
 criu/namespaces.c       |   26 +++++------
 criu/net.c              |    4 +-
 criu/page-xfer.c        |    4 +-
 criu/parasite-syscall.c |    2 -
 criu/proc_parse.c       |    2 -
 criu/pstree.c           |  116 ++++++++++++++++++++++++-----------------------
 criu/seccomp.c          |    4 +-
 criu/seize.c            |   36 +++++++--------
 criu/tty.c              |    8 ++-
 26 files changed, 262 insertions(+), 257 deletions(-)

diff --git a/criu/action-scripts.c b/criu/action-scripts.c
index bfa1f827a..e67edb834 100644
--- a/criu/action-scripts.c
+++ b/criu/action-scripts.c
@@ -69,7 +69,7 @@ static int run_shell_scripts(const char *action)
 		int pid;
 		char root_item_pid[16];
 
-		pid = root_item->pid.real;
+		pid = root_item->pid->real;
 		if (pid != -1) {
 			snprintf(root_item_pid, sizeof(root_item_pid), "%d", pid);
 			if (setenv("CRTOOLS_INIT_PID", root_item_pid, 1)) {
diff --git a/criu/autofs.c b/criu/autofs.c
index 3ce84af2a..1875fe799 100644
--- a/criu/autofs.c
+++ b/criu/autofs.c
@@ -579,12 +579,12 @@ static int autofs_dup_pipe(struct pstree_item *task,
 
 	if (dup_fle(task, ple, new_fd, flags) < 0) {
 		pr_err("Failed to add fd %d to process %d\n",
-				new_fd, task->pid.virt);
+				new_fd, task->pid->ns[0].virt);
 		return -1;
 	}
 
 	pr_info("autofs: added pipe fd %d, flags %#x to %d\n",
-			new_fd, flags, task->pid.virt);
+			new_fd, flags, task->pid->ns[0].virt);
 	return new_fd;
 }
 
@@ -851,12 +851,12 @@ static struct fdinfo_list_entry *autofs_pipe_le(struct pstree_item *master,
 	ple = find_fle_by_fd(&rsti(master)->used, pipe_fd);
 	if (!ple) {
 		pr_err("Failed to find pipe fd %d in process %d\n",
-				pipe_fd, master->pid.virt);
+				pipe_fd, master->pid->ns[0].virt);
 		return NULL;
 	}
 	if (ple->fe->type != FD_TYPES__PIPE) {
 		pr_err("Fd %d in process %d is not a pipe: %d\n", pipe_fd,
-				master->pid.virt, ple->fe->type);
+				master->pid->ns[0].virt, ple->fe->type);
 		return NULL;
 	}
 	return ple;
@@ -873,7 +873,7 @@ static int autofs_create_fle(struct pstree_item *task, FdinfoEntry *fe,
 		return -1;
 	le = (void *)ALIGN((long)le, sizeof(int));
 
-	fle_init(le, task->pid.virt, fe);
+	fle_init(le, task->pid->ns[0].virt, fe);
 
 	collect_task_fd(le, rst_info);
 
@@ -967,7 +967,7 @@ static int autofs_add_mount_info(void *data)
 		entry->fd = autofs_dup_pipe(master, ple, entry->fd);
 		if (entry->fd < 0) {
 			pr_err("Failed to find free fd in process %d\n",
-					master->pid.virt);
+					master->pid->ns[0].virt);
 			return -1;
 		}
 	}
diff --git a/criu/cgroup.c b/criu/cgroup.c
index 48850573f..5036be430 100644
--- a/criu/cgroup.c
+++ b/criu/cgroup.c
@@ -640,7 +640,7 @@ int dump_task_cgroup(struct pstree_item *item, u32 *cg_id, struct parasite_dump_
 	struct cg_set *cs;
 
 	if (item)
-		pid = item->pid.real;
+		pid = item->pid->real;
 	else
 		pid = getpid();
 
diff --git a/criu/cr-check.c b/criu/cr-check.c
index 57cab6ff9..431a9986b 100644
--- a/criu/cr-check.c
+++ b/criu/cr-check.c
@@ -1122,7 +1122,7 @@ int cr_check(void)
 	if (root_item == NULL)
 		return -1;
 
-	root_item->pid.real = getpid();
+	root_item->pid->real = getpid();
 
 	if (collect_pstree_ids())
 		return -1;
diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 555814b23..0130893d6 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -591,7 +591,7 @@ static int dump_task_kobj_ids(struct pstree_item *item)
 {
 	int new;
 	struct kid_elem elem;
-	int pid = item->pid.real;
+	int pid = item->pid->real;
 	TaskKobjIdsEntry *ids = item->ids;
 
 	elem.pid = pid;
@@ -639,7 +639,7 @@ int get_task_ids(struct pstree_item *item)
 
 	task_kobj_ids_entry__init(item->ids);
 
-	if (item->pid.state != TASK_DEAD) {
+	if (item->pid->state != TASK_DEAD) {
 		ret = dump_task_kobj_ids(item);
 		if (ret)
 			goto err_free;
@@ -696,7 +696,7 @@ static int dump_task_core_all(struct parasite_ctl *ctl,
 {
 	struct cr_img *img;
 	CoreEntry *core = item->core[0];
-	pid_t pid = item->pid.real;
+	pid_t pid = item->pid->real;
 	int ret = -1;
 	struct proc_status_creds *creds;
 	struct parasite_dump_cgroup_args cgroup_args, *info = NULL;
@@ -713,7 +713,7 @@ static int dump_task_core_all(struct parasite_ctl *ctl,
 
 	creds = dmpi(item)->pi_creds;
 	if (creds->s.seccomp_mode != SECCOMP_MODE_DISABLED) {
-		pr_info("got seccomp mode %d for %d\n", creds->s.seccomp_mode, item->pid.virt);
+		pr_info("got seccomp mode %d for %d\n", creds->s.seccomp_mode, item->pid->ns[0].virt);
 		core->tc->has_seccomp_mode = true;
 		core->tc->seccomp_mode = creds->s.seccomp_mode;
 
@@ -725,7 +725,7 @@ static int dump_task_core_all(struct parasite_ctl *ctl,
 
 	strlcpy((char *)core->tc->comm, stat->comm, TASK_COMM_LEN);
 	core->tc->flags = stat->flags;
-	core->tc->task_state = item->pid.state;
+	core->tc->task_state = item->pid->state;
 	core->tc->exit_code = 0;
 
 	ret = parasite_dump_thread_leader_seized(ctl, pid, core);
@@ -770,24 +770,25 @@ static int dump_task_core_all(struct parasite_ctl *ctl,
 static int collect_pstree_ids_predump(void)
 {
 	struct pstree_item *item;
+	struct pid pid;
 	struct {
 		struct pstree_item i;
 		struct dmp_info d;
-	} crt = { };
+	} crt = { .i.pid = &pid, };
 
 	/*
 	 * This thing is normally done inside
 	 * write_img_inventory().
 	 */
 
-	crt.i.pid.state = TASK_ALIVE;
-	crt.i.pid.real = getpid();
+	crt.i.pid->state = TASK_ALIVE;
+	crt.i.pid->real = getpid();
 
 	if (predump_task_ns_ids(&crt.i))
 		return -1;
 
 	for_each_pstree_item(item) {
-		if (item->pid.state == TASK_DEAD)
+		if (item->pid->state == TASK_DEAD)
 			continue;
 
 		if (predump_task_ns_ids(item))
@@ -831,9 +832,9 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl,
 		pr_err("Can't dump thread for pid %d\n", pid);
 		goto err;
 	}
-	pstree_insert_pid(tid->virt, tid);
+	pstree_insert_pid(tid->ns[0].virt, tid);
 
-	img = open_image(CR_FD_CORE, O_DUMP, tid->virt);
+	img = open_image(CR_FD_CORE, O_DUMP, tid->ns[0].virt);
 	if (!img)
 		goto err;
 
@@ -860,7 +861,7 @@ static int dump_one_zombie(const struct pstree_item *item,
 	core->tc->task_state = TASK_DEAD;
 	core->tc->exit_code = pps->exit_code;
 
-	img = open_image(CR_FD_CORE, O_DUMP, item->pid.virt);
+	img = open_image(CR_FD_CORE, O_DUMP, item->pid->ns[0].virt);
 	if (!img)
 		goto err;
 
@@ -984,8 +985,8 @@ static int dump_task_threads(struct parasite_ctl *parasite_ctl,
 
 	for (i = 0; i < item->nr_threads; i++) {
 		/* Leader is already dumped */
-		if (item->pid.real == item->threads[i].real) {
-			item->threads[i].virt = item->pid.virt;
+		if (item->pid->real == item->threads[i].real) {
+			item->threads[i].ns[0].virt = item->pid->ns[0].virt;
 			continue;
 		}
 		if (dump_task_thread(parasite_ctl, item, i))
@@ -1015,17 +1016,17 @@ static int fill_zombies_pids(struct pstree_item *item)
 	 * Pids read here are virtual -- caller has set up
 	 * the proc of target pid namespace.
 	 */
-	if (parse_children(item->pid.virt, &ch, &nr) < 0)
+	if (parse_children(item->pid->ns[0].virt, &ch, &nr) < 0)
 		return -1;
 
 	/*
 	 * Step 1 -- filter our ch's pid of alive tasks
 	 */
 	list_for_each_entry(child, &item->children, sibling) {
-		if (child->pid.virt < 0)
+		if (child->pid->ns[0].virt < 0)
 			continue;
 		for (i = 0; i < nr; i++) {
-			if (ch[i] == child->pid.virt) {
+			if (ch[i] == child->pid->ns[0].virt) {
 				ch[i] = -1;
 				break;
 			}
@@ -1040,12 +1041,12 @@ static int fill_zombies_pids(struct pstree_item *item)
 	 */
 	i = 0;
 	list_for_each_entry(child, &item->children, sibling) {
-		if (child->pid.virt > 0)
+		if (child->pid->ns[0].virt > 0)
 			continue;
 		for (; i < nr; i++) {
 			if (ch[i] < 0)
 				continue;
-			child->pid.virt = ch[i];
+			child->pid->ns[0].virt = ch[i];
 			ch[i] = -1;
 			break;
 		}
@@ -1073,12 +1074,12 @@ static int dump_zombies(void)
 	 */
 
 	for_each_pstree_item(item) {
-		if (item->pid.state != TASK_DEAD)
+		if (item->pid->state != TASK_DEAD)
 			continue;
 
-		if (item->pid.virt < 0) {
+		if (item->pid->ns[0].virt < 0) {
 			if (!pidns)
-				item->pid.virt = item->pid.real;
+				item->pid->ns[0].virt = item->pid->real;
 			else if (root_item == item) {
 				pr_err("A root task is dead\n");
 				goto err;
@@ -1087,7 +1088,7 @@ static int dump_zombies(void)
 		}
 
 		pr_info("Obtaining zombie stat ... \n");
-		if (parse_pid_stat(item->pid.virt, &pps_buf) < 0)
+		if (parse_pid_stat(item->pid->ns[0].virt, &pps_buf) < 0)
 			goto err;
 
 		item->sid = pps_buf.sid;
@@ -1108,7 +1109,7 @@ static int dump_zombies(void)
 
 static int pre_dump_one_task(struct pstree_item *item)
 {
-	pid_t pid = item->pid.real;
+	pid_t pid = item->pid->real;
 	struct vm_area_list vmas;
 	struct parasite_ctl *parasite_ctl;
 	int ret = -1;
@@ -1122,12 +1123,12 @@ static int pre_dump_one_task(struct pstree_item *item)
 	pr_info("Pre-dumping task (pid: %d)\n", pid);
 	pr_info("========================================\n");
 
-	if (item->pid.state == TASK_STOPPED) {
+	if (item->pid->state == TASK_STOPPED) {
 		pr_warn("Stopped tasks are not supported\n");
 		return 0;
 	}
 
-	if (item->pid.state == TASK_DEAD)
+	if (item->pid->state == TASK_DEAD)
 		return 0;
 
 	ret = collect_mappings(pid, &vmas, NULL);
@@ -1161,7 +1162,7 @@ static int pre_dump_one_task(struct pstree_item *item)
 		goto err_cure;
 	}
 
-	item->pid.virt = misc.pid;
+	item->pid->ns[0].virt = misc.pid;
 
 	mdc.pre_dump = true;
 	mdc.lazy = false;
@@ -1185,7 +1186,7 @@ static int pre_dump_one_task(struct pstree_item *item)
 
 static int dump_one_task(struct pstree_item *item)
 {
-	pid_t pid = item->pid.real;
+	pid_t pid = item->pid->real;
 	struct vm_area_list vmas;
 	struct parasite_ctl *parasite_ctl;
 	int ret, exit_code = -1;
@@ -1202,7 +1203,7 @@ static int dump_one_task(struct pstree_item *item)
 	pr_info("Dumping task (pid: %d)\n", pid);
 	pr_info("========================================\n");
 
-	if (item->pid.state == TASK_DEAD)
+	if (item->pid->state == TASK_DEAD)
 		/*
 		 * zombies are dumped separately in dump_zombies()
 		 */
@@ -1291,21 +1292,21 @@ static int dump_one_task(struct pstree_item *item)
 		goto err_cure_imgset;
 	}
 
-	item->pid.virt = misc.pid;
-	pstree_insert_pid(item->pid.virt, &item->pid);
+	item->pid->ns[0].virt = misc.pid;
+	pstree_insert_pid(item->pid->ns[0].virt, item->pid);
 	item->sid = misc.sid;
 	item->pgid = misc.pgid;
 
 	pr_info("sid=%d pgid=%d pid=%d\n",
-		item->sid, item->pgid, item->pid.virt);
+		item->sid, item->pgid, item->pid->ns[0].virt);
 
 	if (item->sid == 0) {
 		pr_err("A session leader of %d(%d) is outside of its pid namespace\n",
-			item->pid.real, item->pid.virt);
+			item->pid->real, item->pid->ns[0].virt);
 		goto err_cure;
 	}
 
-	cr_imgset = cr_task_imgset_open(item->pid.virt, O_DUMP);
+	cr_imgset = cr_task_imgset_open(item->pid->ns[0].virt, O_DUMP);
 	if (!cr_imgset)
 		goto err_cure;
 
@@ -1458,9 +1459,9 @@ static int cr_pre_dump_finish(int ret)
 		if (!ctl)
 			continue;
 
-		pr_info("\tPre-dumping %d\n", item->pid.virt);
+		pr_info("\tPre-dumping %d\n", item->pid->ns[0].virt);
 		timing_start(TIME_MEMWRITE);
-		ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, item->pid.virt);
+		ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, item->pid->ns[0].virt);
 		if (ret < 0)
 			goto err;
 
@@ -1509,7 +1510,7 @@ int cr_pre_dump_tasks(pid_t pid)
 	root_item = alloc_pstree_item();
 	if (!root_item)
 		goto err;
-	root_item->pid.real = pid;
+	root_item->pid->real = pid;
 
 	if (!opts.track_mem) {
 		pr_info("Enforcing memory tracking for pre-dump.\n");
@@ -1689,7 +1690,7 @@ int cr_dump_tasks(pid_t pid)
 	root_item = alloc_pstree_item();
 	if (!root_item)
 		goto err;
-	root_item->pid.real = pid;
+	root_item->pid->real = pid;
 
 	pre_dump_ret = run_scripts(ACT_PRE_DUMP);
 	if (pre_dump_ret != 0) {
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index fb5fa74a8..f8a337cc0 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -245,7 +245,7 @@ static int root_prepare_shared(void)
 	}
 
 	for_each_pstree_item(pi) {
-		if (pi->pid.state == TASK_HELPER)
+		if (pi->pid->state == TASK_HELPER)
 			continue;
 
 		ret = prepare_mm_pid(pi);
@@ -453,7 +453,7 @@ static int restore_one_sigaction(int sig, struct cr_img *img, int pid)
 
 static int prepare_sigactions(void)
 {
-	int pid = current->pid.virt;
+	int pid = current->pid->ns[0].virt;
 	struct cr_img *img;
 	int sig, rst = 0;
 	int ret = 0;
@@ -496,7 +496,7 @@ static int __collect_child_pids(struct pstree_item *p, int state, unsigned int *
 	list_for_each_entry(pi, &p->children, sibling) {
 		pid_t *child;
 
-		if (pi->pid.state != state)
+		if (pi->pid->state != state)
 			continue;
 
 		child = rst_mem_alloc(sizeof(*child), RM_PRIVATE);
@@ -504,7 +504,7 @@ static int __collect_child_pids(struct pstree_item *p, int state, unsigned int *
 			return -1;
 
 		(*n)++;
-		*child = pi->pid.virt;
+		*child = pi->pid->ns[0].virt;
 	}
 
 	return 0;
@@ -523,8 +523,8 @@ static int collect_child_pids(int state, unsigned int *n)
 
 	if (current == root_item) {
 		for_each_pstree_item(pi) {
-			if (pi->pid.state != TASK_HELPER &&
-			    pi->pid.state != TASK_DEAD)
+			if (pi->pid->state != TASK_HELPER &&
+			    pi->pid->state != TASK_DEAD)
 				continue;
 			if (__collect_child_pids(pi, state, n))
 				return -1;
@@ -573,7 +573,7 @@ static int open_cores(int pid, CoreEntry *leader_core)
 		goto err;
 
 	for (i = 0; i < current->nr_threads; i++) {
-		tpid = current->threads[i].virt;
+		tpid = current->threads[i].ns[0].virt;
 
 		if (tpid == pid)
 			cores[i] = leader_core;
@@ -776,10 +776,10 @@ static int wait_on_helpers_zombies(void)
 	struct pstree_item *pi;
 
 	list_for_each_entry(pi, &current->children, sibling) {
-		pid_t pid = pi->pid.virt;
+		pid_t pid = pi->pid->ns[0].virt;
 		int status;
 
-		switch (pi->pid.state) {
+		switch (pi->pid->state) {
 		case TASK_DEAD:
 			if (waitid(P_PID, pid, NULL, WNOWAIT | WEXITED) < 0) {
 				pr_perror("Wait on %d zombie failed", pid);
@@ -807,7 +807,7 @@ static int restore_one_zombie(CoreEntry *core)
 	if (inherit_fd_fini() < 0)
 		return -1;
 
-	if (lazy_pages_setup_zombie(current->pid.virt))
+	if (lazy_pages_setup_zombie(current->pid->ns[0].virt))
 		return -1;
 
 	prctl(PR_SET_NAME, (long)(void *)core->tc->comm, 0, 0, 0);
@@ -830,7 +830,7 @@ static int restore_one_zombie(CoreEntry *core)
 			signr = SIGABRT;
 		}
 
-		if (kill(current->pid.virt, signr) < 0)
+		if (kill(current->pid->ns[0].virt, signr) < 0)
 			pr_perror("Can't kill myself, will just exit");
 
 		exit_code = 0;
@@ -882,9 +882,9 @@ static int restore_one_task(int pid, CoreEntry *core)
 
 	if (task_alive(current))
 		ret = restore_one_alive_task(pid, core);
-	else if (current->pid.state == TASK_DEAD)
+	else if (current->pid->state == TASK_DEAD)
 		ret = restore_one_zombie(core);
-	else if (current->pid.state == TASK_HELPER) {
+	else if (current->pid->state == TASK_HELPER) {
 		sigset_t blockmask, oldmask;
 
 		sigemptyset(&blockmask);
@@ -967,22 +967,22 @@ static inline int fork_with_pid(struct pstree_item *item)
 {
 	struct cr_clone_arg ca;
 	int ret = -1;
-	pid_t pid = item->pid.virt;
+	pid_t pid = item->pid->ns[0].virt;
 
-	if (item->pid.state != TASK_HELPER) {
+	if (item->pid->state != TASK_HELPER) {
 		if (open_core(pid, &ca.core))
 			return -1;
 
 		if (check_core(ca.core, item))
 			return -1;
 
-		item->pid.state = ca.core->tc->task_state;
+		item->pid->state = ca.core->tc->task_state;
 		rsti(item)->cg_set = ca.core->tc->cg_set;
 
 		rsti(item)->has_seccomp = ca.core->tc->seccomp_mode != SECCOMP_MODE_DISABLED;
 
-		if (item->pid.state != TASK_DEAD && !task_alive(item)) {
-			pr_err("Unknown task state %d\n", item->pid.state);
+		if (item->pid->state != TASK_DEAD && !task_alive(item)) {
+			pr_err("Unknown task state %d\n", item->pid->state);
 			return -1;
 		}
 
@@ -1052,9 +1052,9 @@ static inline int fork_with_pid(struct pstree_item *item)
 
 
 	if (item == root_item) {
-		item->pid.real = ret;
+		item->pid->real = ret;
 		pr_debug("PID: real %d virt %d\n",
-				item->pid.real, item->pid.virt);
+				item->pid->real, item->pid->ns[0].virt);
 	}
 
 err_unlock:
@@ -1081,8 +1081,8 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
 	status = siginfo->si_status;
 
 	/* skip scripts */
-	if (!current && root_item->pid.real != pid) {
-		pid = waitpid(root_item->pid.real, &status, WNOHANG);
+	if (!current && root_item->pid->real != pid) {
+		pid = waitpid(root_item->pid->real, &status, WNOHANG);
 		if (pid <= 0)
 			return;
 		exit = WIFEXITED(status);
@@ -1111,11 +1111,11 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
 
 		/* Exited (with zero code) helpers are OK */
 		list_for_each_entry(pi, &current->children, sibling)
-			if (pi->pid.virt == siginfo->si_pid)
+			if (pi->pid->ns[0].virt == siginfo->si_pid)
 				break;
 
 		BUG_ON(&pi->sibling == &current->children);
-		if (pi->pid.state != TASK_HELPER)
+		if (pi->pid->state != TASK_HELPER)
 			break;
 	}
 
@@ -1189,8 +1189,8 @@ static void restore_sid(void)
 	 * we can call setpgid() on custom values.
 	 */
 
-	if (current->pid.virt == current->sid) {
-		pr_info("Restoring %d to %d sid\n", current->pid.virt, current->sid);
+	if (current->pid->ns[0].virt == current->sid) {
+		pr_info("Restoring %d to %d sid\n", current->pid->ns[0].virt, current->sid);
 		sid = setsid();
 		if (sid != current->sid) {
 			pr_perror("Can't restore sid (%d)", sid);
@@ -1200,7 +1200,7 @@ static void restore_sid(void)
 		sid = getsid(getpid());
 		if (sid != current->sid) {
 			/* Skip the root task if it's not init */
-			if (current == root_item && root_item->pid.virt != INIT_PID)
+			if (current == root_item && root_item->pid->ns[0].virt != INIT_PID)
 				return;
 			pr_err("Requested sid %d doesn't match inherited %d\n",
 					current->sid, sid);
@@ -1223,13 +1223,13 @@ static void restore_pgid(void)
 
 	pid_t pgid, my_pgid = current->pgid;
 
-	pr_info("Restoring %d to %d pgid\n", current->pid.virt, my_pgid);
+	pr_info("Restoring %d to %d pgid\n", current->pid->ns[0].virt, my_pgid);
 
 	pgid = getpgrp();
 	if (my_pgid == pgid)
 		return;
 
-	if (my_pgid != current->pid.virt) {
+	if (my_pgid != current->pid->ns[0].virt) {
 		struct pstree_item *leader;
 
 		/*
@@ -1240,18 +1240,18 @@ static void restore_pgid(void)
 
 		leader = rsti(current)->pgrp_leader;
 		if (leader) {
-			BUG_ON(my_pgid != leader->pid.virt);
+			BUG_ON(my_pgid != leader->pid->ns[0].virt);
 			futex_wait_until(&rsti(leader)->pgrp_set, 1);
 		}
 	}
 
 	pr_info("\twill call setpgid, mine pgid is %d\n", pgid);
 	if (setpgid(0, my_pgid) != 0) {
-		pr_perror("Can't restore pgid (%d/%d->%d)", current->pid.virt, pgid, current->pgid);
+		pr_perror("Can't restore pgid (%d/%d->%d)", current->pid->ns[0].virt, pgid, current->pgid);
 		exit(1);
 	}
 
-	if (my_pgid == current->pid.virt)
+	if (my_pgid == current->pid->ns[0].virt)
 		futex_set_and_wake(&rsti(current)->pgrp_set, 1);
 }
 
@@ -1344,23 +1344,23 @@ static int restore_task_with_children(void *_arg)
 		}
 		buf[ret] = '\0';
 
-		current->pid.real = atoi(buf);
+		current->pid->real = atoi(buf);
 		pr_debug("PID: real %d virt %d\n",
-				current->pid.real, current->pid.virt);
+				current->pid->real, current->pid->ns[0].virt);
 	}
 
 	if ( !(ca->clone_flags & CLONE_FILES))
 		close_safe(&ca->fd);
 
-	if (current->pid.state != TASK_HELPER) {
+	if (current->pid->state != TASK_HELPER) {
 		ret = clone_service_fd(rsti(current)->service_fd_id);
 		if (ret)
 			goto err;
 	}
 
 	pid = getpid();
-	if (current->pid.virt != pid) {
-		pr_err("Pid %d do not match expected %d\n", pid, current->pid.virt);
+	if (current->pid->ns[0].virt != pid) {
+		pr_err("Pid %d do not match expected %d\n", pid, current->pid->ns[0].virt);
 		set_task_cr_err(EEXIST);
 		goto err;
 	}
@@ -1464,7 +1464,7 @@ static int restore_task_with_children(void *_arg)
 	if (restore_finish_stage(task_entries, CR_STATE_FORKING) < 0)
 		goto err;
 
-	if (restore_one_task(current->pid.virt, ca->core))
+	if (restore_one_task(current->pid->ns[0].virt, ca->core))
 		goto err;
 
 	return 0;
@@ -1535,7 +1535,7 @@ static int attach_to_tasks(bool root_seized)
 		if (!task_alive(item))
 			continue;
 
-		if (parse_threads(item->pid.real, &item->threads, &item->nr_threads))
+		if (parse_threads(item->pid->real, &item->threads, &item->nr_threads))
 			return -1;
 
 		for (i = 0; i < item->nr_threads; i++) {
@@ -1588,7 +1588,7 @@ static int catch_tasks(bool root_seized, enum trace_flags *flag)
 		if (!task_alive(item))
 			continue;
 
-		if (parse_threads(item->pid.real, &item->threads, &item->nr_threads))
+		if (parse_threads(item->pid->real, &item->threads, &item->nr_threads))
 			return -1;
 
 		for (i = 0; i < item->nr_threads; i++) {
@@ -1637,7 +1637,7 @@ static void finalize_restore(void)
 	struct pstree_item *item;
 
 	for_each_pstree_item(item) {
-		pid_t pid = item->pid.real;
+		pid_t pid = item->pid->real;
 		struct parasite_ctl *ctl;
 
 		if (!task_alive(item))
@@ -1652,9 +1652,9 @@ static void finalize_restore(void)
 
 		xfree(ctl);
 
-		if ((item->pid.state == TASK_STOPPED) ||
+		if ((item->pid->state == TASK_STOPPED) ||
 				(opts.final_state == TASK_STOPPED))
-			kill(item->pid.real, SIGSTOP);
+			kill(item->pid->real, SIGSTOP);
 	}
 }
 
@@ -1733,7 +1733,7 @@ static int write_restored_pid(void)
 	if (!opts.pidfile)
 		return 0;
 
-	pid = root_item->pid.real;
+	pid = root_item->pid->real;
 
 	if (write_pidfile(pid) < 0) {
 		pr_perror("Can't write pidfile");
@@ -1774,7 +1774,7 @@ static int restore_root_task(struct pstree_item *init)
 	 * this later.
 	 */
 
-	if (init->pid.virt == INIT_PID) {
+	if (init->pid->ns[0].virt == INIT_PID) {
 		if (!(root_ns_mask & CLONE_NEWPID)) {
 			pr_err("This process tree can only be restored "
 				"in a new pid namespace.\n"
@@ -1819,7 +1819,7 @@ static int restore_root_task(struct pstree_item *init)
 		act.sa_flags &= ~SA_NOCLDSTOP;
 		sigaction(SIGCHLD, &act, NULL);
 
-		if (ptrace(PTRACE_SEIZE, init->pid.real, 0, 0)) {
+		if (ptrace(PTRACE_SEIZE, init->pid->real, 0, 0)) {
 			pr_perror("Can't attach to init");
 			goto out_kill;
 		}
@@ -1838,7 +1838,7 @@ static int restore_root_task(struct pstree_item *init)
 		goto out_kill;
 
 	if (root_ns_mask & CLONE_NEWNS) {
-		mnt_ns_fd = open_proc(init->pid.real, "ns/mnt");
+		mnt_ns_fd = open_proc(init->pid->real, "ns/mnt");
 		if (mnt_ns_fd < 0)
 			goto out_kill;
 	}
@@ -1881,7 +1881,7 @@ static int restore_root_task(struct pstree_item *init)
 
 	/* Zombies die after CR_STATE_RESTORE */
 	for_each_pstree_item(item) {
-		if (item->pid.state == TASK_DEAD)
+		if (item->pid->state == TASK_DEAD)
 			task_entries->nr_threads--;
 	}
 
@@ -1992,18 +1992,18 @@ static int restore_root_task(struct pstree_item *init)
 		int status;
 
 		/* Kill init */
-		if (root_item->pid.real > 0)
-			kill(root_item->pid.real, SIGKILL);
+		if (root_item->pid->real > 0)
+			kill(root_item->pid->real, SIGKILL);
 
-		if (waitpid(root_item->pid.real, &status, 0) < 0)
+		if (waitpid(root_item->pid->real, &status, 0) < 0)
 			pr_warn("Unable to wait %d: %s",
-				root_item->pid.real, strerror(errno));
+				root_item->pid->real, strerror(errno));
 	} else {
 		struct pstree_item *pi;
 
 		for_each_pstree_item(pi)
-			if (pi->pid.virt > 0)
-				kill(pi->pid.virt, SIGKILL);
+			if (pi->pid->ns[0].virt > 0)
+				kill(pi->pid->ns[0].virt, SIGKILL);
 	}
 
 out:
@@ -2037,10 +2037,10 @@ int prepare_dummy_task_state(struct pstree_item *pi)
 {
 	CoreEntry *core;
 
-	if (open_core(pi->pid.virt, &core))
+	if (open_core(pi->pid->ns[0].virt, &core))
 		return -1;
 
-	pi->pid.state = core->tc->task_state;
+	pi->pid->state = core->tc->task_state;
 	core_entry__free_unpacked(core, NULL);
 
 	return 0;
@@ -2674,7 +2674,7 @@ static int prepare_signals(int pid, struct task_restore_args *ta, CoreEntry *lea
 	for (i = 0; i < current->nr_threads; i++) {
 		if (!current->core[i]->thread_core->signals_p)/*backward compatibility*/
 			ret = open_signal_image(CR_FD_PSIGNAL,
-					current->threads[i].virt, &siginfo_priv_nr[i]);
+					current->threads[i].ns[0].virt, &siginfo_priv_nr[i]);
 		else
 			ret = prepare_one_signal_queue(current->core[i]->thread_core->signals_p,
 										&siginfo_priv_nr[i]);
@@ -3093,7 +3093,7 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
 		struct rt_sigframe *sigframe;
 		k_rtsigset_t *blkset = NULL;
 
-		thread_args[i].pid = current->threads[i].virt;
+		thread_args[i].pid = current->threads[i].ns[0].virt;
 		thread_args[i].siginfo_n = siginfo_priv_nr[i];
 		thread_args[i].siginfo = task_args->siginfo;
 		thread_args[i].siginfo += siginfo_n;
diff --git a/criu/cr-service.c b/criu/cr-service.c
index 7dd139882..4bac50d06 100644
--- a/criu/cr-service.c
+++ b/criu/cr-service.c
@@ -195,7 +195,7 @@ int send_criu_rpc_script(enum script_actions act, char *name, int fd)
 		 * checking this.
 		 */
 		cn.has_pid = true;
-		cn.pid = root_item->pid.real;
+		cn.pid = root_item->pid->real;
 		break;
 	default:
 		break;
@@ -575,7 +575,7 @@ static int restore_using_req(int sk, CriuOpts *req)
 	success = true;
 exit:
 	if (send_criu_restore_resp(sk, success,
-				   root_item ? root_item->pid.real : -1) == -1) {
+				   root_item ? root_item->pid->real : -1) == -1) {
 		pr_perror("Can't send response");
 		success = false;
 	}
diff --git a/criu/file-lock.c b/criu/file-lock.c
index d9bda19e0..2d4036c75 100644
--- a/criu/file-lock.c
+++ b/criu/file-lock.c
@@ -318,11 +318,11 @@ int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
 				continue;
 		}
 
-		fl->real_owner = pid->virt;
+		fl->real_owner = pid->ns[0].virt;
 		fl->owners_fd = fd;
 
 		pr_info("Found lock entry %d.%d %d vs %d\n",
-				pid->real, pid->virt, fd,
+				pid->real, pid->ns[0].virt, fd,
 				fl->fl_owner);
 	}
 
diff --git a/criu/files-reg.c b/criu/files-reg.c
index 79a811e1f..951d6760f 100644
--- a/criu/files-reg.c
+++ b/criu/files-reg.c
@@ -382,7 +382,7 @@ static int open_remap_dead_process(struct reg_file_info *rfi,
 	if (!helper)
 		return -1;
 
-	if (helper->pid.state != TASK_UNDEF) {
+	if (helper->pid->state != TASK_UNDEF) {
 		pr_info("Skipping helper for restoring /proc/%d; pid exists\n", rfe->remap_id);
 		return 0;
 	}
@@ -391,11 +391,11 @@ static int open_remap_dead_process(struct reg_file_info *rfi,
 
 	helper->sid = root_item->sid;
 	helper->pgid = root_item->pgid;
-	helper->pid.virt = rfe->remap_id;
+	helper->pid->ns[0].virt = rfe->remap_id;
 	helper->parent = root_item;
 	list_add_tail(&helper->sibling, &root_item->children);
 
-	pr_info("Added a helper for restoring /proc/%d\n", helper->pid.virt);
+	pr_info("Added a helper for restoring /proc/%d\n", helper->pid->ns[0].virt);
 
 	return 0;
 }
@@ -821,14 +821,14 @@ int dead_pid_conflict(void)
 			 * If the dead PID was given to a main thread of another
 			 * process, this is handled during restore.
 			 */
-			item = container_of(node, struct pstree_item, pid);
-			if (item->pid.real == item->threads[i].real ||
-			    item->threads[i].virt != pid)
+			item = node->item;
+			if (item->pid->real == item->threads[i].real ||
+			    item->threads[i].ns[0].virt != pid)
 				continue;
 		}
 
 		pr_err("Conflict with a dead task with the same PID as of this thread (virt %d, real %d).\n",
-			node->virt, node->real);
+			node->ns[0].virt, node->real);
 		return -1;
 	}
 
diff --git a/criu/files.c b/criu/files.c
index 3869ab118..babd96548 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -326,7 +326,7 @@ static int fill_fd_params(struct pid *owner_pid, int fd, int lfd,
 {
 	int ret;
 	struct statfs fsbuf;
-	struct fdinfo_common fdinfo = { .mnt_id = -1, .owner = owner_pid->virt };
+	struct fdinfo_common fdinfo = { .mnt_id = -1, .owner = owner_pid->ns[0].virt };
 
 	if (fstat(lfd, &p->stat) < 0) {
 		pr_perror("Can't stat fd %d", lfd);
@@ -533,7 +533,7 @@ int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
 	int off, nr_fds = min((int) PARASITE_MAX_FDS, dfds->nr_fds);
 
 	pr_info("\n");
-	pr_info("Dumping opened files (pid: %d)\n", item->pid.real);
+	pr_info("Dumping opened files (pid: %d)\n", item->pid->real);
 	pr_info("----------------------------------------\n");
 
 	lfds = xmalloc(nr_fds * sizeof(int));
@@ -559,7 +559,7 @@ int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
 			goto err;
 
 		for (i = 0; i < nr_fds; i++) {
-			ret = dump_one_file(&item->pid, dfds->fds[i + off],
+			ret = dump_one_file(item->pid, dfds->fds[i + off],
 						lfds[i], opts + i, img, ctl);
 			close(lfds[i]);
 			if (ret)
@@ -747,7 +747,7 @@ int dup_fle(struct pstree_item *task, struct fdinfo_list_entry *ple,
 	if (!e)
 		return -1;
 
-	return collect_fd(task->pid.virt, e, rsti(task));
+	return collect_fd(task->pid->ns[0].virt, e, rsti(task));
 }
 
 int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id)
@@ -781,7 +781,7 @@ int prepare_fd_pid(struct pstree_item *item)
 {
 	int ret = 0;
 	struct cr_img *img;
-	pid_t pid = item->pid.virt;
+	pid_t pid = item->pid->ns[0].virt;
 	struct rst_info *rst_info = rsti(item);
 
 	INIT_LIST_HEAD(&rst_info->used);
@@ -790,7 +790,7 @@ int prepare_fd_pid(struct pstree_item *item)
 	if (item->ids == NULL) /* zombie */
 		return 0;
 
-	if (rsti(item)->fdt && rsti(item)->fdt->pid != item->pid.virt)
+	if (rsti(item)->fdt && rsti(item)->fdt->pid != item->pid->ns[0].virt)
 		return 0;
 
 	img = open_image(CR_FD_FDINFO, O_RSTR, item->ids->files_id);
@@ -907,8 +907,8 @@ int recv_fd_from_peer(struct fdinfo_list_entry *fle)
 
 	if (tmp != fle) {
 		pr_info("Further fle=%p, pid=%d\n", tmp, fle->pid);
-		if (!task_fle(current, fle)) {
-			pr_err("Unexpected fle %p, pid=%d\n", fle, current->pid.virt);
+		if (!task_fle(current, tmp)) {
+			pr_err("Unexpected fle %p, pid=%d\n", tmp, current->pid->ns[0].virt);
 			return -1;
 		}
 		if (keep_fd_for_future(tmp, fd))
@@ -1181,7 +1181,7 @@ int prepare_fds(struct pstree_item *me)
 		futex_inc_and_wake(&fdt->fdt_lock);
 		futex_wait_while_lt(&fdt->fdt_lock, fdt->nr);
 
-		if (fdt->pid != me->pid.virt) {
+		if (fdt->pid != me->pid->ns[0].virt) {
 			pr_info("File descriptor table is shared with %d\n", fdt->pid);
 			futex_wait_until(&fdt->fdt_lock, fdt->nr + 1);
 			goto out;
@@ -1271,7 +1271,7 @@ int restore_fs(struct pstree_item *me)
 
 int prepare_fs_pid(struct pstree_item *item)
 {
-	pid_t pid = item->pid.virt;
+	pid_t pid = item->pid->ns[0].virt;
 	struct rst_info *ri = rsti(item);
 	struct cr_img *img;
 	FsEntry *fe;
@@ -1322,15 +1322,15 @@ int shared_fdt_prepare(struct pstree_item *item)
 
 		futex_init(&fdt->fdt_lock);
 		fdt->nr = 1;
-		fdt->pid = parent->pid.virt;
+		fdt->pid = parent->pid->ns[0].virt;
 	} else
 		fdt = rsti(parent)->fdt;
 
 	rsti(item)->fdt = fdt;
 	rsti(item)->service_fd_id = fdt->nr;
 	fdt->nr++;
-	if (pid_rst_prio(item->pid.virt, fdt->pid))
-		fdt->pid = item->pid.virt;
+	if (pid_rst_prio(item->pid->ns[0].virt, fdt->pid))
+		fdt->pid = item->pid->ns[0].virt;
 
 	return 0;
 }
@@ -1628,7 +1628,7 @@ int inherit_fd_fini()
 int open_transport_socket(void)
 {
 	struct fdt *fdt = rsti(current)->fdt;
-	pid_t pid = current->pid.virt;
+	pid_t pid = current->pid->ns[0].virt;
 	struct sockaddr_un saddr;
 	int sock, slen;
 
diff --git a/criu/filesystems.c b/criu/filesystems.c
index 554b76776..7fc4c2622 100644
--- a/criu/filesystems.c
+++ b/criu/filesystems.c
@@ -407,7 +407,7 @@ static int tmpfs_dump(struct mount_info *pm)
 	sprintf(tmpfs_path, "/proc/self/fd/%d", fd);
 
 	if (root_ns_mask & CLONE_NEWUSER)
-		userns_pid = root_item->pid.real;
+		userns_pid = root_item->pid->real;
 
 	ret = cr_system_userns(-1, img_raw_fd(img), -1, "tar", (char *[])
 			{ "tar", "--create",
diff --git a/criu/image.c b/criu/image.c
index 5d3b56e43..898a580ab 100644
--- a/criu/image.c
+++ b/criu/image.c
@@ -113,10 +113,11 @@ int write_img_inventory(InventoryEntry *he)
 
 int prepare_inventory(InventoryEntry *he)
 {
+	struct pid pid;
 	struct {
 		struct pstree_item i;
 		struct dmp_info d;
-	} crt = { };
+	} crt = { .i.pid = &pid };
 
 	pr_info("Perparing image inventory (version %u)\n", CRTOOLS_IMAGES_V1);
 
@@ -132,8 +133,8 @@ int prepare_inventory(InventoryEntry *he)
 		he->check_only = true;
 	}
 
-	crt.i.pid.state = TASK_ALIVE;
-	crt.i.pid.real = getpid();
+	crt.i.pid->state = TASK_ALIVE;
+	crt.i.pid->real = getpid();
 	if (get_task_ids(&crt.i))
 		return -1;
 
diff --git a/criu/include/pid.h b/criu/include/pid.h
index 772508f96..9ac583ffb 100644
--- a/criu/include/pid.h
+++ b/criu/include/pid.h
@@ -13,16 +13,17 @@ struct pid {
 	 */
 	pid_t real;
 
+	int state;	/* TASK_XXX constants */
+
 	/*
 	 * The @virt pid is one which used in the image itself and keeps
 	 * the pid value to be restored. This pid fetched from the
 	 * dumpee context, because the dumpee might have own pid namespace.
 	 */
-	pid_t virt;
-
-	int state;	/* TASK_XXX constants */
-
-	struct rb_node node;
+	struct {
+		pid_t virt;
+		struct rb_node node;
+	} ns[1]; /* Must be at the end of struct pid */
 };
 
 #define TASK_UNDEF		0x0
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index b4dc6b635..f441d5397 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -16,7 +16,7 @@ struct pstree_item {
 	struct list_head	children;	/* list of my children */
 	struct list_head	sibling;	/* linkage in my parent's children list */
 
-	struct pid		pid;
+	struct pid		*pid;
 	pid_t			pgid;
 	pid_t			sid;
 	pid_t			born_sid;
@@ -76,7 +76,7 @@ static inline bool is_alive_state(int state)
 
 static inline bool task_alive(struct pstree_item *i)
 {
-	return is_alive_state(i->pid.state);
+	return is_alive_state(i->pid->state);
 }
 
 extern void free_pstree(struct pstree_item *root_item);
diff --git a/criu/irmap.c b/criu/irmap.c
index a69776c9f..c27fdd720 100644
--- a/criu/irmap.c
+++ b/criu/irmap.c
@@ -237,7 +237,7 @@ char *irmap_lookup(unsigned int s_dev, unsigned long i_ino)
 	 * irmap_predump_prep, so we just go ahead and scan.
 	 */
 	if (!doing_predump &&
-			__mntns_get_root_fd(root_item->pid.real) < 0)
+			__mntns_get_root_fd(root_item->pid->real) < 0)
 		goto out;
 
 	timing_start(TIME_IRMAP_RESOLVE);
@@ -333,7 +333,7 @@ int irmap_predump_prep(void)
 	 */
 
 	doing_predump = true;
-	return __mntns_get_root_fd(root_item->pid.real) < 0 ? -1 : 0;
+	return __mntns_get_root_fd(root_item->pid->real) < 0 ? -1 : 0;
 }
 
 int irmap_predump_run(void)
diff --git a/criu/mem.c b/criu/mem.c
index 9f72e1f2a..0be32312d 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -306,7 +306,7 @@ static int __parasite_dump_pages_seized(struct pstree_item *item,
 		return 0;
 
 	pr_info("\n");
-	pr_info("Dumping pages (type: %d pid: %d)\n", CR_FD_PAGES, item->pid.real);
+	pr_info("Dumping pages (type: %d pid: %d)\n", CR_FD_PAGES, item->pid->real);
 	pr_info("----------------------------------------\n");
 
 	timing_start(TIME_MEMDUMP);
@@ -320,7 +320,7 @@ static int __parasite_dump_pages_seized(struct pstree_item *item,
 
 	pmc_size = max(vma_area_list->priv_longest,
 		vma_area_list->shared_longest);
-	if (pmc_init(&pmc, item->pid.real, &vma_area_list->h,
+	if (pmc_init(&pmc, item->pid->real, &vma_area_list->h,
 			 pmc_size * PAGE_SIZE))
 		return -1;
 
@@ -344,11 +344,11 @@ static int __parasite_dump_pages_seized(struct pstree_item *item,
 		 * right here. For pre-dumps the pp will be taken by the
 		 * caller and handled later.
 		 */
-		ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, item->pid.virt);
+		ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, item->pid->ns[0].virt);
 		if (ret < 0)
 			goto out_pp;
 	} else {
-		ret = check_parent_page_xfer(CR_FD_PAGEMAP, item->pid.virt);
+		ret = check_parent_page_xfer(CR_FD_PAGEMAP, item->pid->ns[0].virt);
 		if (ret < 0)
 			goto out_pp;
 
@@ -378,7 +378,7 @@ static int __parasite_dump_pages_seized(struct pstree_item *item,
 		if (!map)
 			goto out_xfer;
 		if (vma_area_is(vma_area, VMA_ANON_SHARED))
-			ret = add_shmem_area(item->pid.real, vma_area->e, map);
+			ret = add_shmem_area(item->pid->real, vma_area->e, map);
 		else {
 again:
 			ret = generate_iovs(vma_area, pp, map, &off,
@@ -414,7 +414,7 @@ static int __parasite_dump_pages_seized(struct pstree_item *item,
 	 * Step 4 -- clean up
 	 */
 
-	ret = task_reset_dirty_track(item->pid.real);
+	ret = task_reset_dirty_track(item->pid->real);
 out_xfer:
 	if (!mdc->pre_dump)
 		xfer.close(&xfer);
@@ -477,7 +477,7 @@ int parasite_dump_pages_seized(struct pstree_item *item,
 
 int prepare_mm_pid(struct pstree_item *i)
 {
-	pid_t pid = i->pid.virt;
+	pid_t pid = i->pid->ns[0].virt;
 	int ret = -1, vn = 0;
 	struct cr_img *img;
 	struct rst_info *ri = rsti(i);
@@ -563,7 +563,7 @@ static int map_private_vma(struct pstree_item *t,
 	struct vma_area *p = *pvma;
 
 	if (vma_area_is(vma, VMA_FILE_PRIVATE)) {
-		ret = vma->vm_open(t->pid.virt, vma);
+		ret = vma->vm_open(t->pid->ns[0].virt, vma);
 		if (ret < 0) {
 			pr_err("Can't fixup VMA's fd\n");
 			return -1;
@@ -731,7 +731,7 @@ static int restore_priv_vma_content(struct pstree_item *t)
 
 	vma = list_first_entry(vmas, struct vma_area, list);
 
-	ret = open_page_read(t->pid.virt, &pr, PR_TASK);
+	ret = open_page_read(t->pid->ns[0].virt, &pr, PR_TASK);
 	if (ret <= 0)
 		return -1;
 
@@ -961,7 +961,7 @@ int unmap_guard_pages(struct pstree_item *t)
 
 int open_vmas(struct pstree_item *t)
 {
-	int pid = t->pid.virt;
+	int pid = t->pid->ns[0].virt;
 	struct vma_area *vma;
 	struct vm_area_list *vmas = &rsti(t)->vmas;
 
diff --git a/criu/mount.c b/criu/mount.c
index d03dab4aa..d8de26480 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -150,9 +150,9 @@ static struct mount_info *__lookup_overlayfs(struct mount_info *list, char *rpat
 		 * to make sure we stat the correct file
 		 */
 		if (mntns_root == -1) {
-			mntns_root = __mntns_get_root_fd(root_item->pid.real);
+			mntns_root = __mntns_get_root_fd(root_item->pid->real);
 			if (mntns_root < 0) {
-				pr_err("Unable to get the root file descriptor of pid %d\n", root_item->pid.real);
+				pr_err("Unable to get the root file descriptor of pid %d\n", root_item->pid->real);
 				return ERR_PTR(-ENOENT);
 			}
 		}
@@ -2679,7 +2679,7 @@ static int do_restore_task_mnt_ns(struct ns_id *nsid, struct pstree_item *curren
 {
 	int fd;
 
-	fd = open_proc(root_item->pid.virt, "fd/%d", nsid->mnt.ns_fd);
+	fd = open_proc(root_item->pid->ns[0].virt, "fd/%d", nsid->mnt.ns_fd);
 	if (fd < 0)
 		return -1;
 
@@ -3196,7 +3196,7 @@ int mntns_get_root_fd(struct ns_id *mntns)
 	if (!mntns->ns_populated) {
 		int fd;
 
-		fd = open_proc(root_item->pid.virt, "fd/%d", mntns->mnt.root_fd);
+		fd = open_proc(root_item->pid->ns[0].virt, "fd/%d", mntns->mnt.root_fd);
 		if (fd < 0)
 			return -1;
 
diff --git a/criu/namespaces.c b/criu/namespaces.c
index b954f9796..f655c164e 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -309,7 +309,7 @@ struct ns_id *rst_new_ns_id(unsigned int id, pid_t pid,
 
 int rst_add_ns_id(unsigned int id, struct pstree_item *i, struct ns_desc *nd)
 {
-	pid_t pid = i->pid.virt;
+	pid_t pid = i->pid->ns[0].virt;
 	struct ns_id *nsid;
 
 	nsid = lookup_ns_by_id(id, nd);
@@ -401,7 +401,7 @@ static unsigned int generate_ns_id(int pid, unsigned int kid, struct ns_desc *nd
 
 	if (pid != getpid()) {
 		type = NS_OTHER;
-		if (pid == root_item->pid.real) {
+		if (pid == root_item->pid->real) {
 			BUG_ON(root_ns_mask & nd->cflag);
 			pr_info("Will take %s namespace in the image\n", nd->str);
 			root_ns_mask |= nd->cflag;
@@ -549,7 +549,7 @@ static int open_ns_fd(struct file_desc *d, int *new_fd)
 		return -1;
 	}
 
-	snprintf(path, sizeof(path) - 1, "/proc/%d/ns/%s", item->pid.virt, nd->str);
+	snprintf(path, sizeof(path) - 1, "/proc/%d/ns/%s", item->pid->ns[0].virt, nd->str);
 	path[sizeof(path) - 1] = '\0';
 
 	fd = open(path, nfi->nfe->flags);
@@ -594,7 +594,7 @@ struct collect_image_info nsfile_cinfo = {
 
 int predump_task_ns_ids(struct pstree_item *item)
 {
-	int pid = item->pid.real;
+	int pid = item->pid->real;
 
 	if (!__get_ns_id(pid, &net_ns_desc, NULL, &dmpi(item)->netns))
 		return -1;
@@ -607,7 +607,7 @@ int predump_task_ns_ids(struct pstree_item *item)
 
 int dump_task_ns_ids(struct pstree_item *item)
 {
-	int pid = item->pid.real;
+	int pid = item->pid->real;
 	TaskKobjIdsEntry *ids = item->ids;
 
 	ids->has_pid_ns_id = true;
@@ -791,7 +791,7 @@ int collect_user_ns(struct ns_id *ns, void *oarg)
 	 * mappings, which are used for convirting local id-s to
 	 * userns id-s (userns_uid(), userns_gid())
 	 */
-	if (dump_user_ns(root_item->pid.real, root_item->ids->user_ns_id))
+	if (dump_user_ns(root_item->pid->real, root_item->ids->user_ns_id))
 		return -1;
 
 	return 0;
@@ -995,7 +995,7 @@ static int do_dump_namespaces(struct ns_id *ns)
 
 int dump_namespaces(struct pstree_item *item, unsigned int ns_flags)
 {
-	struct pid *ns_pid = &item->pid;
+	struct pid *ns_pid = item->pid;
 	struct ns_id *ns;
 	int pid, nr = 0;
 	int ret = 0;
@@ -1011,9 +1011,9 @@ int dump_namespaces(struct pstree_item *item, unsigned int ns_flags)
 	 * net namespace with this is still open
 	 */
 
-	pr_info("Dumping %d(%d)'s namespaces\n", ns_pid->virt, ns_pid->real);
+	pr_info("Dumping %d(%d)'s namespaces\n", ns_pid->ns[0].virt, ns_pid->real);
 
-	if ((ns_flags & CLONE_NEWPID) && ns_pid->virt != 1) {
+	if ((ns_flags & CLONE_NEWPID) && ns_pid->ns[0].virt != 1) {
 		pr_err("Can't dump a pid namespace without the process init\n");
 		return -1;
 	}
@@ -1473,10 +1473,10 @@ int prepare_userns(struct pstree_item *item)
 	if (ret < 0)
 		return -1;
 
-	if (write_id_map(item->pid.real, e->uid_map, e->n_uid_map, "uid_map"))
+	if (write_id_map(item->pid->real, e->uid_map, e->n_uid_map, "uid_map"))
 		return -1;
 
-	if (write_id_map(item->pid.real, e->gid_map, e->n_gid_map, "gid_map"))
+	if (write_id_map(item->pid->real, e->gid_map, e->n_gid_map, "gid_map"))
 		return -1;
 
 	return 0;
@@ -1645,11 +1645,11 @@ int join_namespaces(void)
 
 int prepare_namespace(struct pstree_item *item, unsigned long clone_flags)
 {
-	pid_t pid = item->pid.virt;
+	pid_t pid = item->pid->ns[0].virt;
 	int id;
 
 	pr_info("Restoring namespaces %d flags 0x%lx\n",
-			item->pid.virt, clone_flags);
+			item->pid->ns[0].virt, clone_flags);
 
 	if ((clone_flags & CLONE_NEWUSER) && prepare_userns_creds())
 		return -1;
diff --git a/criu/net.c b/criu/net.c
index 69658ff0c..4f62d76c7 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -1774,7 +1774,7 @@ int network_lock_internal()
 				"COMMIT\n";
 	int ret = 0, nsret;
 
-	if (switch_ns(root_item->pid.real, &net_ns_desc, &nsret))
+	if (switch_ns(root_item->pid->real, &net_ns_desc, &nsret))
 		return -1;
 
 
@@ -1798,7 +1798,7 @@ static int network_unlock_internal()
 			"COMMIT\n";
 	int ret = 0, nsret;
 
-	if (switch_ns(root_item->pid.real, &net_ns_desc, &nsret))
+	if (switch_ns(root_item->pid->real, &net_ns_desc, &nsret))
 		return -1;
 
 
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index c7ea433e4..1f0102e65 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -889,8 +889,8 @@ static int page_server_init_send(void)
 		if (!task_alive(pi))
 			continue;
 
-		if (page_pipe_from_pagemap(&pp, pi->pid.virt)) {
-			pr_err("%d: failed to open page-read\n", pi->pid.virt);
+		if (page_pipe_from_pagemap(&pp, pi->pid->ns[0].virt)) {
+			pr_err("%d: failed to open page-read\n", pi->pid->ns[0].virt);
 			return -1;
 		}
 
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index a5253241b..a7a26adf4 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -208,7 +208,7 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
 
 	compel_release_thread(tctl);
 
-	tid->virt = args->tid;
+	tid->ns[0].virt = args->tid;
 	return dump_thread_core(pid, core, args);
 
 err_rth:
diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index 1e23685a9..b52135ea5 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -2221,7 +2221,7 @@ int parse_threads(int pid, struct pid **_t, int *_n)
 				return -1;
 			}
 			t = tmp;
-			t[nr - 1].virt = -1;
+			t[nr - 1].ns[0].virt = -1;
 		}
 		t[nr - 1].real = atoi(de->d_name);
 		t[nr - 1].state = TASK_THREAD;
diff --git a/criu/pstree.c b/criu/pstree.c
index af298b831..833b3d0ee 100644
--- a/criu/pstree.c
+++ b/criu/pstree.c
@@ -144,7 +144,7 @@ int pstree_alloc_cores(struct pstree_item *item)
 		return -1;
 
 	for (i = 0; i < item->nr_threads; i++) {
-		if (item->threads[i].real == item->pid.real)
+		if (item->threads[i].real == item->pid->real)
 			item->core[i] = core_entry_alloc(1, 1);
 		else
 			item->core[i] = core_entry_alloc(1, 0);
@@ -197,35 +197,37 @@ struct pstree_item *__alloc_pstree_item(bool rst)
 	int sz;
 
 	if (!rst) {
-		sz = sizeof(*item) + sizeof(struct dmp_info);
+		sz = sizeof(*item) + sizeof(struct dmp_info) + sizeof(struct pid);
 		item = xzalloc(sz);
 		if (!item)
 			return NULL;
+		item->pid = (void *)item + sizeof(*item) + sizeof(struct dmp_info);
 	} else {
-		sz = sizeof(*item) + sizeof(struct rst_info);
+		sz = sizeof(*item) + sizeof(struct rst_info) + sizeof(struct pid);
 		item = shmalloc(sz);
 		if (!item)
 			return NULL;
 
 		memset(item, 0, sz);
 		vm_area_list_init(&rsti(item)->vmas);
+		item->pid = (void *)item + sizeof(*item) + sizeof(struct rst_info);
 	}
 
 	INIT_LIST_HEAD(&item->children);
 	INIT_LIST_HEAD(&item->sibling);
 
-	item->pid.virt = -1;
-	item->pid.real = -1;
+	item->pid->ns[0].virt = -1;
+	item->pid->real = -1;
 	item->born_sid = -1;
 	futex_init(&item->task_st);
-	item->pid.item = item;
+	item->pid->item = item;
 
 	return item;
 }
 
 void init_pstree_helper(struct pstree_item *ret)
 {
-	ret->pid.state = TASK_HELPER;
+	ret->pid->state = TASK_HELPER;
 	rsti(ret)->clone_flags = CLONE_FILES | CLONE_FS;
 	task_entries->nr_helpers++;
 }
@@ -269,7 +271,7 @@ int dump_pstree(struct pstree_item *root_item)
 	struct cr_img *img;
 
 	pr_info("\n");
-	pr_info("Dumping pstree (pid: %d)\n", root_item->pid.real);
+	pr_info("Dumping pstree (pid: %d)\n", root_item->pid->real);
 	pr_info("----------------------------------------\n");
 
 	/*
@@ -281,10 +283,10 @@ int dump_pstree(struct pstree_item *root_item)
 	 * deeper in process tree, thus top-level checking for
 	 * leader is enough.
 	 */
-	if (root_item->pid.virt != root_item->sid) {
+	if (root_item->pid->ns[0].virt != root_item->sid) {
 		if (!opts.shell_job) {
 			pr_err("The root process %d is not a session leader. "
-			       "Consider using --" OPT_SHELL_JOB " option\n", item->pid.virt);
+			       "Consider using --" OPT_SHELL_JOB " option\n", item->pid->ns[0].virt);
 			return -1;
 		}
 	}
@@ -294,10 +296,10 @@ int dump_pstree(struct pstree_item *root_item)
 		return -1;
 
 	for_each_pstree_item(item) {
-		pr_info("Process: %d(%d)\n", item->pid.virt, item->pid.real);
+		pr_info("Process: %d(%d)\n", item->pid->ns[0].virt, item->pid->real);
 
-		e.pid		= item->pid.virt;
-		e.ppid		= item->parent ? item->parent->pid.virt : 0;
+		e.pid		= item->pid->ns[0].virt;
+		e.ppid		= item->parent ? item->parent->pid->ns[0].virt : 0;
 		e.pgid		= item->pgid;
 		e.sid		= item->sid;
 		e.n_threads	= item->nr_threads;
@@ -307,7 +309,7 @@ int dump_pstree(struct pstree_item *root_item)
 			goto err;
 
 		for (i = 0; i < item->nr_threads; i++)
-			e.threads[i] = item->threads[i].virt;
+			e.threads[i] = item->threads[i].ns[0].virt;
 
 		ret = pb_write_one(img, &e, PB_PSTREE);
 		xfree(e.threads);
@@ -336,7 +338,7 @@ static int prepare_pstree_for_shell_job(void)
 	if (!opts.shell_job)
 		return 0;
 
-	if (root_item->sid == root_item->pid.virt)
+	if (root_item->sid == root_item->pid->ns[0].virt)
 		return 0;
 
 	/*
@@ -389,12 +391,12 @@ static struct pid *lookup_create_pid(pid_t pid, struct pid *pid_node)
 	struct rb_node *parent = NULL;
 
 	while (node) {
-		struct pid *this = rb_entry(node, struct pid, node);
+		struct pid *this = rb_entry(node, struct pid, ns[0].node);
 
 		parent = *new;
-		if (pid < this->virt)
+		if (pid < this->ns[0].virt)
 			node = node->rb_left, new = &((*new)->rb_left);
-		else if (pid > this->virt)
+		else if (pid > this->ns[0].virt)
 			node = node->rb_right, new = &((*new)->rb_right);
 		else
 			return this;
@@ -407,10 +409,10 @@ static struct pid *lookup_create_pid(pid_t pid, struct pid *pid_node)
 		if (item == NULL)
 			return NULL;
 
-		item->pid.virt = pid;
-		pid_node = &item->pid;
+		item->pid->ns[0].virt = pid;
+		pid_node = item->pid;
 	}
-	rb_link_and_balance(&pid_root_rb, &pid_node->node, parent, new);
+	rb_link_and_balance(&pid_root_rb, &pid_node->ns[0].node, parent, new);
 	return pid_node;
 }
 
@@ -432,7 +434,7 @@ struct pstree_item *lookup_create_item(pid_t pid)
 		return NULL;
 	BUG_ON(node->state == TASK_THREAD);
 
-	return container_of(node, struct pstree_item, pid);
+	return node->item;
 }
 
 struct pid *pstree_pid_by_virt(pid_t pid)
@@ -440,11 +442,11 @@ struct pid *pstree_pid_by_virt(pid_t pid)
 	struct rb_node *node = pid_root_rb.rb_node;
 
 	while (node) {
-		struct pid *this = rb_entry(node, struct pid, node);
+		struct pid *this = rb_entry(node, struct pid, ns[0].node);
 
-		if (pid < this->virt)
+		if (pid < this->ns[0].virt)
 			node = node->rb_left;
-		else if (pid > this->virt)
+		else if (pid > this->ns[0].virt)
 			node = node->rb_right;
 		else
 			return this;
@@ -457,7 +459,7 @@ static int read_pstree_ids(struct pstree_item *pi)
 	int ret;
 	struct cr_img *img;
 
-	img = open_image(CR_FD_IDS, O_RSTR, pi->pid.virt);
+	img = open_image(CR_FD_IDS, O_RSTR, pi->pid->ns[0].virt);
 	if (!img)
 		return -1;
 
@@ -498,7 +500,7 @@ static int read_pstree_image(pid_t *pid_max)
 		pi = lookup_create_item(e->pid);
 		if (pi == NULL)
 			break;
-		BUG_ON(pi->pid.state != TASK_UNDEF);
+		BUG_ON(pi->pid->state != TASK_UNDEF);
 
 		/*
 		 * All pids should be added in the tree to be able to find
@@ -511,7 +513,7 @@ static int read_pstree_image(pid_t *pid_max)
 		if (lookup_create_item(e->sid) == NULL)
 			break;
 
-		pi->pid.virt = e->pid;
+		pi->pid->ns[0].virt = e->pid;
 		if (e->pid > *pid_max)
 			*pid_max = e->pid;
 		pi->pgid = e->pgid;
@@ -520,7 +522,7 @@ static int read_pstree_image(pid_t *pid_max)
 		pi->sid = e->sid;
 		if (e->sid > *pid_max)
 			*pid_max = e->sid;
-		pi->pid.state = TASK_ALIVE;
+		pi->pid->state = TASK_ALIVE;
 
 		if (e->ppid == 0) {
 			if (root_item) {
@@ -536,13 +538,13 @@ static int read_pstree_image(pid_t *pid_max)
 
 			pid = pstree_pid_by_virt(e->ppid);
 			if (!pid || pid->state == TASK_UNDEF || pid->state == TASK_THREAD) {
-				pr_err("Can't find a parent for %d\n", pi->pid.virt);
+				pr_err("Can't find a parent for %d\n", pi->pid->ns[0].virt);
 				pstree_entry__free_unpacked(e, NULL);
 				xfree(pi);
 				goto err;
 			}
 
-			parent = container_of(pid, struct pstree_item, pid);
+			parent = pid->item;
 			pi->parent = parent;
 			list_add(&pi->sibling, &parent->children);
 		}
@@ -555,12 +557,12 @@ static int read_pstree_image(pid_t *pid_max)
 		for (i = 0; i < e->n_threads; i++) {
 			struct pid *node;
 			pi->threads[i].real = -1;
-			pi->threads[i].virt = e->threads[i];
+			pi->threads[i].ns[0].virt = e->threads[i];
 			pi->threads[i].state = TASK_THREAD;
 			pi->threads[i].item = NULL;
 			if (i == 0)
 				continue; /* A thread leader is in a tree already */
-			node = lookup_create_pid(pi->threads[i].virt, &pi->threads[i]);
+			node = lookup_create_pid(pi->threads[i].ns[0].virt, &pi->threads[i]);
 
 			BUG_ON(node == NULL);
 			if (node != &pi->threads[i]) {
@@ -590,20 +592,20 @@ static int get_free_pid()
 	static struct pid *prev, *next;
 
 	if (prev == NULL)
-		prev = rb_entry(rb_first(&pid_root_rb), struct pid, node);
+		prev = rb_entry(rb_first(&pid_root_rb), struct pid, ns[0].node);
 
 	while (1) {
 		struct rb_node *node;
 		pid_t pid;
 
-		pid = prev->virt + 1;
+		pid = prev->ns[0].virt + 1;
 		pid = pid < RESERVED_PIDS ? RESERVED_PIDS + 1 : pid;
 
-		node = rb_next(&prev->node);
+		node = rb_next(&prev->ns[0].node);
 		if (node == NULL)
 			return pid;
-		next = rb_entry(node, struct pid, node);
-		if (next->virt > pid)
+		next = rb_entry(node, struct pid, ns[0].node);
+		if (next->ns[0].virt > pid)
 			return pid;
 		prev = next;
 	}
@@ -632,12 +634,12 @@ static int prepare_pstree_ids(void)
 		 * a session leader himself -- this is a simple case, we
 		 * just proceed in a normal way.
 		 */
-		if (item->sid == root_item->sid || item->sid == item->pid.virt)
+		if (item->sid == root_item->sid || item->sid == item->pid->ns[0].virt)
 			continue;
 
 		leader = pstree_item_by_virt(item->sid);
 		BUG_ON(leader == NULL);
-		if (leader->pid.state != TASK_UNDEF) {
+		if (leader->pid->state != TASK_UNDEF) {
 			pid_t pid;
 
 			pid = get_free_pid();
@@ -656,7 +658,7 @@ static int prepare_pstree_ids(void)
 			list_add(&helper->sibling, &leader->children);
 
 			pr_info("Attach %d to the task %d\n",
-					helper->pid.virt, leader->pid.virt);
+					helper->pid->ns[0].virt, leader->pid->ns[0].virt);
 		} else {
 			helper = leader;
 			helper->sid = item->sid;
@@ -668,7 +670,7 @@ static int prepare_pstree_ids(void)
 		init_pstree_helper(helper);
 
 		pr_info("Add a helper %d for restoring SID %d\n",
-				helper->pid.virt, helper->sid);
+				helper->pid->ns[0].virt, helper->sid);
 
 		child = list_entry(item->sibling.prev, struct pstree_item, sibling);
 		item = child;
@@ -679,11 +681,11 @@ static int prepare_pstree_ids(void)
 		list_for_each_entry_safe_continue(child, tmp, &root_item->children, sibling) {
 			if (child->sid != helper->sid)
 				continue;
-			if (child->sid == child->pid.virt)
+			if (child->sid == child->pid->ns[0].virt)
 				continue;
 
 			pr_info("Attach %d to the temporary task %d\n",
-					child->pid.virt, helper->pid.virt);
+					child->pid->ns[0].virt, helper->pid->ns[0].virt);
 
 			child->parent = helper;
 			list_move(&child->sibling, &helper->children);
@@ -695,10 +697,10 @@ static int prepare_pstree_ids(void)
 		if (!item->parent) /* skip the root task */
 			continue;
 
-		if (item->pid.state == TASK_HELPER)
+		if (item->pid->state == TASK_HELPER)
 			continue;
 
-		if (item->sid != item->pid.virt) {
+		if (item->sid != item->pid->ns[0].virt) {
 			struct pstree_item *parent;
 
 			if (item->parent->sid == item->sid)
@@ -706,15 +708,15 @@ static int prepare_pstree_ids(void)
 
 			/* the task could fork a child before and after setsid() */
 			parent = item->parent;
-			while (parent && parent->pid.virt != item->sid) {
+			while (parent && parent->pid->ns[0].virt != item->sid) {
 				if (parent->born_sid != -1 && parent->born_sid != item->sid) {
 					pr_err("Can't determinate with which sid (%d or %d)"
 						"the process %d was born\n",
-						parent->born_sid, item->sid, parent->pid.virt);
+						parent->born_sid, item->sid, parent->pid->ns[0].virt);
 					return -1;
 				}
 				parent->born_sid = item->sid;
-				pr_info("%d was born with sid %d\n", parent->pid.virt, item->sid);
+				pr_info("%d was born with sid %d\n", parent->pid->ns[0].virt, item->sid);
 				parent = parent->parent;
 			}
 
@@ -734,13 +736,13 @@ static int prepare_pstree_ids(void)
 	for_each_pstree_item(item) {
 		struct pid *pid;
 
-		if (!item->pgid || item->pid.virt == item->pgid)
+		if (!item->pgid || item->pid->ns[0].virt == item->pgid)
 			continue;
 
 		pid = pstree_pid_by_virt(item->pgid);
 		if (pid->state != TASK_UNDEF) {
 			BUG_ON(pid->state == TASK_THREAD);
-			rsti(item)->pgrp_leader = container_of(pid, struct pstree_item, pid);
+			rsti(item)->pgrp_leader = pid->item;
 			continue;
 		}
 
@@ -752,19 +754,19 @@ static int prepare_pstree_ids(void)
 		if (current_pgid == item->pgid)
 			continue;
 
-		helper = container_of(pid, struct pstree_item, pid);
+		helper = pid->item;
 		init_pstree_helper(helper);
 
 		helper->sid = item->sid;
 		helper->pgid = item->pgid;
-		helper->pid.virt = item->pgid;
+		helper->pid->ns[0].virt = item->pgid;
 		helper->parent = item;
 		helper->ids = item->ids;
 		list_add(&helper->sibling, &item->children);
 		rsti(item)->pgrp_leader = helper;
 
 		pr_info("Add a helper %d for restoring PGID %d\n",
-				helper->pid.virt, helper->pgid);
+				helper->pid->ns[0].virt, helper->pgid);
 	}
 
 	return 0;
@@ -982,7 +984,7 @@ struct pstree_item *pstree_item_by_virt(pid_t virt)
 		return NULL;
 	BUG_ON(pid->state == TASK_THREAD);
 
-	return container_of(pid, struct pstree_item, pid);
+	return pid->item;
 }
 
 struct pstree_item *pstree_item_by_real(pid_t real)
@@ -990,7 +992,7 @@ struct pstree_item *pstree_item_by_real(pid_t real)
 	struct pstree_item *item;
 
 	for_each_pstree_item(item) {
-		if (item->pid.real == real)
+		if (item->pid->real == real)
 			return item;
 	}
 	return NULL;
@@ -1002,6 +1004,6 @@ int pid_to_virt(pid_t real)
 
 	item = pstree_item_by_real(real);
 	if (item)
-		return item->pid.virt;
+		return item->pid->ns[0].virt;
 	return 0;
 }
diff --git a/criu/seccomp.c b/criu/seccomp.c
index 099997be4..c5e7a7d93 100644
--- a/criu/seccomp.c
+++ b/criu/seccomp.c
@@ -49,7 +49,7 @@ static int collect_filter_for_pstree(struct pstree_item *item)
 	struct sock_filter buf[BPF_MAXINSNS];
 	void *m;
 
-	if (item->pid.state == TASK_DEAD ||
+	if (item->pid->state == TASK_DEAD ||
 	    dmpi(item)->pi_creds->s.seccomp_mode != SECCOMP_MODE_FILTER)
 		return 0;
 
@@ -57,7 +57,7 @@ static int collect_filter_for_pstree(struct pstree_item *item)
 		int len;
 		struct seccomp_info *info, *inherited = NULL;
 
-		len = ptrace(PTRACE_SECCOMP_GET_FILTER, item->pid.real, i, buf);
+		len = ptrace(PTRACE_SECCOMP_GET_FILTER, item->pid->real, i, buf);
 		if (len < 0) {
 			if (errno == ENOENT) {
 				/* end of the search */
diff --git a/criu/seize.c b/criu/seize.c
index 21821f51f..d5079ca6c 100644
--- a/criu/seize.c
+++ b/criu/seize.c
@@ -439,7 +439,7 @@ static inline bool child_collected(struct pstree_item *i, pid_t pid)
 	struct pstree_item *c;
 
 	list_for_each_entry(c, &i->children, sibling)
-		if (c->pid.real == pid)
+		if (c->pid->real == pid)
 			return true;
 
 	return false;
@@ -451,7 +451,7 @@ static int collect_children(struct pstree_item *item)
 	pid_t *ch;
 	int ret, i, nr_children, nr_inprogress;
 
-	ret = parse_children(item->pid.real, &ch, &nr_children);
+	ret = parse_children(item->pid->real, &ch, &nr_children);
 	if (ret < 0)
 		return ret;
 
@@ -490,7 +490,7 @@ static int collect_children(struct pstree_item *item)
 			goto free;
 		}
 
-		ret = compel_wait_task(pid, item->pid.real, parse_pid_status, &creds->s);
+		ret = compel_wait_task(pid, item->pid->real, parse_pid_status, &creds->s);
 		if (ret < 0) {
 			/*
 			 * Here is a race window between parse_children() and seize(),
@@ -511,9 +511,9 @@ static int collect_children(struct pstree_item *item)
 			processes_to_wait--;
 
 		dmpi(c)->pi_creds = creds;
-		c->pid.real = pid;
+		c->pid->real = pid;
 		c->parent = item;
-		c->pid.state = ret;
+		c->pid->state = ret;
 		list_add_tail(&c->sibling, &item->children);
 
 		/* Here is a recursive call (Depth-first search) */
@@ -530,7 +530,7 @@ static void unseize_task_and_threads(const struct pstree_item *item, int st)
 {
 	int i;
 
-	if (item->pid.state == TASK_DEAD)
+	if (item->pid->state == TASK_DEAD)
 		return;
 
 	/*
@@ -538,7 +538,7 @@ static void unseize_task_and_threads(const struct pstree_item *item, int st)
 	 * the item->state is the state task was in when we seized one.
 	 */
 
-	compel_resume_task(item->pid.real, item->pid.state, st);
+	compel_resume_task(item->pid->real, item->pid->state, st);
 
 	if (st == TASK_DEAD)
 		return;
@@ -555,7 +555,7 @@ static void pstree_wait(struct pstree_item *root_item)
 
 	for_each_pstree_item(item) {
 
-		if (item->pid.state == TASK_DEAD)
+		if (item->pid->state == TASK_DEAD)
 			continue;
 
 		for (i = 0; i < item->nr_threads; i++) {
@@ -609,14 +609,14 @@ void pstree_switch_state(struct pstree_item *root_item, int st)
 static pid_t item_ppid(const struct pstree_item *item)
 {
 	item = item->parent;
-	return item ? item->pid.real : -1;
+	return item ? item->pid->real : -1;
 }
 
 static inline bool thread_collected(struct pstree_item *i, pid_t tid)
 {
 	int t;
 
-	if (i->pid.real == tid) /* thread leader is collected as task */
+	if (i->pid->real == tid) /* thread leader is collected as task */
 		return true;
 
 	for (t = 0; t < i->nr_threads; t++)
@@ -680,11 +680,11 @@ static int collect_threads(struct pstree_item *item)
 	struct pid *threads = NULL;
 	int nr_threads = 0, i = 0, ret, nr_inprogress, nr_stopped = 0;
 
-	ret = parse_threads(item->pid.real, &threads, &nr_threads);
+	ret = parse_threads(item->pid->real, &threads, &nr_threads);
 	if (ret < 0)
 		goto err;
 
-	if ((item->pid.state == TASK_DEAD) && (nr_threads > 1)) {
+	if ((item->pid->state == TASK_DEAD) && (nr_threads > 1)) {
 		pr_err("Zombies with threads are not supported\n");
 		goto err;
 	}
@@ -695,7 +695,7 @@ static int collect_threads(struct pstree_item *item)
 		return -1;
 
 	if (item->nr_threads == 0) {
-		item->threads[0].real = item->pid.real;
+		item->threads[0].real = item->pid->real;
 		item->nr_threads = 1;
 		item->threads[0].item = NULL;
 	}
@@ -711,7 +711,7 @@ static int collect_threads(struct pstree_item *item)
 		nr_inprogress++;
 
 		pr_info("\tSeizing %d's %d thread\n",
-				item->pid.real, pid);
+				item->pid->real, pid);
 
 		if (!opts.freeze_cgroup && compel_interrupt_task(pid))
 			continue;
@@ -812,7 +812,7 @@ static int collect_task(struct pstree_item *item)
 	if (ret < 0)
 		goto err_close;
 
-	if ((item->pid.state == TASK_DEAD) && !list_empty(&item->children)) {
+	if ((item->pid->state == TASK_DEAD) && !list_empty(&item->children)) {
 		pr_err("Zombie with children?! O_o Run, run, run!\n");
 		goto err_close;
 	}
@@ -820,7 +820,7 @@ static int collect_task(struct pstree_item *item)
 	if (pstree_alloc_cores(item))
 		goto err_close;
 
-	pr_info("Collected %d in %d state\n", item->pid.real, item->pid.state);
+	pr_info("Collected %d in %d state\n", item->pid->real, item->pid->state);
 	return 0;
 
 err_close:
@@ -830,7 +830,7 @@ static int collect_task(struct pstree_item *item)
 
 int collect_pstree(void)
 {
-	pid_t pid = root_item->pid.real;
+	pid_t pid = root_item->pid->real;
 	int ret = -1;
 	struct proc_status_creds *creds;
 
@@ -865,7 +865,7 @@ int collect_pstree(void)
 		processes_to_wait--;
 
 	pr_info("Seized task %d, state %d\n", pid, ret);
-	root_item->pid.state = ret;
+	root_item->pid->state = ret;
 	dmpi(root_item)->pi_creds = creds;
 
 	ret = collect_task(root_item);
diff --git a/criu/tty.c b/criu/tty.c
index d225b0307..30a29092e 100644
--- a/criu/tty.c
+++ b/criu/tty.c
@@ -1002,7 +1002,7 @@ static int pty_open_unpaired_slave(struct file_desc *d, struct tty_info *slave)
 		 * checkpoint complete process tree together with
 		 * the process which keeps the master peer.
 		 */
-		if (root_item->sid != root_item->pid.virt) {
+		if (root_item->sid != root_item->pid->ns[0].virt) {
 			pr_debug("Restore inherited group %d\n",
 				 getpgid(getppid()));
 			if (tty_set_prgp(fd, getpgid(getppid())))
@@ -1251,10 +1251,10 @@ static int tty_find_restoring_task(struct tty_info *info)
 		 * for us.
 		 */
 		item = find_first_sid(info->tie->sid);
-		if (item && item->pid.virt == item->sid) {
+		if (item && item->pid->ns[0].virt == item->sid) {
 			pr_info("Set a control terminal %x to %d\n",
 				info->tfe->id, info->tie->sid);
-			return prepare_ctl_tty(item->pid.virt,
+			return prepare_ctl_tty(item->pid->ns[0].virt,
 					       rsti(item),
 					       info->tfe->id);
 		}
@@ -1659,7 +1659,7 @@ int dump_verify_tty_sids(void)
 		if (!ret && dinfo->sid) {
 			struct pstree_item *item = find_first_sid(dinfo->sid);
 
-			if (!item || item->pid.virt != dinfo->sid) {
+			if (!item || item->pid->ns[0].virt != dinfo->sid) {
 				if (!opts.shell_job) {
 					pr_err("Found dangling tty with sid %d pgid %d (%s) on peer fd %d.\n",
 					       dinfo->sid, dinfo->pgrp,



More information about the CRIU mailing list