[CRIU] [PATCH cr 5/8] pid: restore pid namespace

Andrey Vagin avagin at openvz.org
Wed May 16 04:32:38 EDT 2012


Each process has two pids
real_pid - the pid of a process in crtools's pid namespace.
pid - the pid of a process in its pid namespace.
      This pid is get for help parasite and it should be saved after restore.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-dump.c                  |   76 +++++++++++++++++++++++++++----------------
 cr-restore.c               |    9 +++--
 include/crtools.h          |    2 -
 include/namespaces.h       |    5 ++-
 include/parasite-syscall.h |    2 +-
 include/parasite.h         |    7 +++-
 namespaces.c               |   12 +++---
 parasite-syscall.c         |    3 +-
 parasite.c                 |    6 +++
 9 files changed, 79 insertions(+), 43 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index 93fb84f..25679d6 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -999,6 +999,7 @@ static int parse_threads(const struct pstree_item *item, struct pid **_t, int *_
 		}
 		t = tmp;
 		t[nr - 1].real_pid = atoi(de->d_name);
+		t[nr - 1].pid = -1;
 		nr++;
 	}
 
@@ -1225,6 +1226,7 @@ static struct pstree_item *collect_task(pid_t pid, struct pstree_item *parent,
 		goto err;
 
 	item->pid.real_pid = pid;
+	item->pid.pid = -1;
 	item->parent = parent;
 
 	ret = seize_task(pid, item_ppid(item), &item->pgid, &item->sid);
@@ -1309,9 +1311,9 @@ static int collect_subtree(pid_t pid, struct pstree_item *parent,
 	return 0;
 }
 
-static int dump_pstree(pid_t pid, const struct list_head *pstree_list);
+static int dump_pstree(const struct list_head *pstree_list);
 
-static int collect_dump_pstree(pid_t pid, struct list_head *pstree_list,
+static int collect_pstree(pid_t pid, struct list_head *pstree_list,
 			  const struct cr_options *opts)
 {
 	int ret, attempts = 5;
@@ -1372,13 +1374,10 @@ try_again:
 	if (!ret)
 		ret = check_xids(pstree_list);
 
-	if (ret)
-		return ret;
-
-	return dump_pstree(pid, pstree_list);
+	return ret;
 }
 
-static int dump_pstree(pid_t pid, const struct list_head *pstree_list)
+static int dump_pstree(const struct list_head *pstree_list)
 {
 	const struct pstree_item *item;
 	struct pstree_entry e;
@@ -1387,7 +1386,7 @@ static int dump_pstree(pid_t pid, const struct list_head *pstree_list)
 	int pstree_fd;
 
 	pr_info("\n");
-	pr_info("Dumping pstree (pid: %d)\n", pid);
+	pr_info("Dumping pstree\n");
 	pr_info("----------------------------------------\n");
 
 	pstree_fd = open_image(CR_FD_PSTREE, O_DUMP);
@@ -1447,7 +1446,7 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl, struct pid *tid)
 	if (ret)
 		goto err_free;
 
-	ret = parasite_dump_tid_addr_seized(parasite_ctl, pid, &taddr);
+	ret = parasite_dump_tid_addr_seized(parasite_ctl, pid, &taddr, &tid->pid);
 	if (ret) {
 		pr_err("Can't dump tid address for pid %d", pid);
 		goto err_free;
@@ -1461,7 +1460,7 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl, struct pid *tid)
 	core->tc.task_state = TASK_ALIVE;
 	core->tc.exit_code = 0;
 
-	fd_core = open_image(CR_FD_CORE, O_DUMP, pid);
+	fd_core = open_image(CR_FD_CORE, O_DUMP, tid->pid);
 	if (fd_core < 0)
 		goto err_free;
 
@@ -1554,11 +1553,6 @@ static int dump_one_task(struct pstree_item *item)
 	if (item->state == TASK_DEAD)
 		return dump_one_zombie(item, &pps_buf);
 
-	ret = -1;
-	cr_fdset = cr_task_fdset_open(item->pid.pid, O_DUMP);
-	if (!cr_fdset)
-		goto err;
-
 	ret = collect_mappings(pid, &vma_area_list);
 	if (ret) {
 		pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
@@ -1578,6 +1572,32 @@ static int dump_one_task(struct pstree_item *item)
 		goto err;
 	}
 
+	ret = parasite_dump_misc_seized(parasite_ctl, &misc);
+	if (ret) {
+		pr_err("Can't dump misc (pid: %d)\n", pid);
+		goto err_cure_fdset;
+	}
+
+	item->pid.pid = misc.pid;
+	item->sid = misc.sid;
+	item->pgid = misc.pgid;
+
+	if (item->parent) {
+		int i;
+		for (i = 0; i < item->parent->nr_children; i++)
+			if (item->parent->children[i].real_pid == item->pid.real_pid) {
+				item->parent->children[i].pid = item->pid.pid;
+				break;
+			}
+
+		BUG_ON(i == item->parent->nr_children);
+	}
+
+	ret = -1;
+	cr_fdset = cr_task_fdset_open(item->pid.pid, O_DUMP);
+	if (!cr_fdset)
+		goto err_cure;
+
 	ret = dump_task_files_seized(parasite_ctl, cr_fdset, fds, nr_fds);
 	if (ret) {
 		pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
@@ -1602,12 +1622,6 @@ static int dump_one_task(struct pstree_item *item)
 		goto err_cure;
 	}
 
-	ret = parasite_dump_misc_seized(parasite_ctl, &misc);
-	if (ret) {
-		pr_err("Can't dump misc (pid: %d)\n", pid);
-		goto err_cure;
-	}
-
 	ret = dump_task_core_all(pid, &pps_buf, &misc, parasite_ctl, cr_fdset);
 	if (ret) {
 		pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
@@ -1644,8 +1658,8 @@ static int dump_one_task(struct pstree_item *item)
 		goto err;
 	}
 
-err:
 	close_cr_fdset(&cr_fdset);
+err:
 	close_pid_proc();
 err_free:
 	free_mappings(&vma_area_list);
@@ -1653,6 +1667,8 @@ err_free:
 	return ret;
 
 err_cure:
+	close_cr_fdset(&cr_fdset);
+err_cure_fdset:
 	parasite_cure_seized(parasite_ctl);
 	goto err;
 }
@@ -1667,14 +1683,9 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
 	pr_info("Dumping process %s(pid: %d)\n", !opts->leader_only ? "group " : "", pid);
 	pr_info("========================================\n");
 
-	if (collect_dump_pstree(pid, &pstree_list, opts))
+	if (collect_pstree(pid, &pstree_list, opts))
 		goto err;
 
-	if (opts->namespaces_flags) {
-		if (dump_namespaces(pid, opts->namespaces_flags) < 0)
-			goto err;
-	}
-
 	/*
 	 * Ignore collection errors by now since we may not want
 	 * to dump the missed sockets. But later, when we will start
@@ -1702,6 +1713,15 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
 			break;
 	}
 
+	if (dump_pstree(&pstree_list))
+		goto err;
+
+	if (opts->namespaces_flags) {
+		item = list_first_entry(&pstree_list, struct pstree_item, list);
+		if (dump_namespaces(&item->pid, opts->namespaces_flags) < 0)
+			goto err;
+	}
+
 	ret = cr_dump_shmem();
 	if (ret)
 		goto err;
diff --git a/cr-restore.c b/cr-restore.c
index eb644f6..a257925 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -506,11 +506,14 @@ static inline int fork_with_pid(int pid, unsigned long ns_clone_flags)
 		goto err_close;
 	}
 
-	if (write_img_buf(ca.fd, buf, strlen(buf)))
-		goto err_unlock;
+	if (pid == 1) {
+		ca.clone_flags |= CLONE_NEWPID;
+	} else
+		if (write_img_buf(ca.fd, buf, strlen(buf)))
+			goto err_unlock;
 
 	ret = clone(restore_task_with_children, stack + STACK_SIZE,
-			ns_clone_flags | SIGCHLD, &ca);
+			ca.clone_flags | SIGCHLD, &ca);
 
 	if (ret < 0)
 		pr_perror("Can't fork for %d", pid);
diff --git a/include/crtools.h b/include/crtools.h
index 652d1ea..e639633 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -208,10 +208,8 @@ struct rst_info {
 
 struct pid
 {
-	union {
 	u32 real_pid;
 	u32 pid;
-	};
 };
 
 struct pstree_item {
diff --git a/include/namespaces.h b/include/namespaces.h
index 80c67af..eed805c 100644
--- a/include/namespaces.h
+++ b/include/namespaces.h
@@ -1,6 +1,9 @@
 #ifndef __CR_NS_H__
 #define __CR_NS_H__
-int dump_namespaces(int pid, unsigned int ns_flags);
+
+#include "crtools.h"
+
+int dump_namespaces(struct pid *pid, unsigned int ns_flags);
 int prepare_namespace(int pid, unsigned long clone_flags);
 struct cr_options;
 int try_show_namespaces(int pid, struct cr_options *);
diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index d8e1259..8c0d5d1 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -39,7 +39,7 @@ extern int parasite_dump_pages_seized(struct parasite_ctl *ctl,
 				      struct cr_fdset *cr_fdset);
 struct parasite_dump_tid_addr;
 extern int parasite_dump_tid_addr_seized(struct parasite_ctl *ctl,
-					 pid_t pid, unsigned int **tid_add);
+					 pid_t pid, unsigned int **tid_add, u32 *tid);
 
 extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds, char *flags);
 
diff --git a/include/parasite.h b/include/parasite.h
index 23773d1..2c98858 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -76,12 +76,17 @@ struct parasite_dump_misc {
 	unsigned int		secbits;
 	unsigned long		brk;
 	k_rtsigset_t		blocked;
+
+	u32 pid;
+	u32 sid;
+	u32 pgid;
 };
 
 struct parasite_dump_tid_addr {
 	parasite_status_t	status;
 
-	unsigned int *tid_addr;
+	unsigned int		*tid_addr;
+	int			tid;
 };
 
 #define PARASITE_MAX_FDS	(PAGE_SIZE / sizeof(int))
diff --git a/namespaces.c b/namespaces.c
index 7079564..5ac3b7f 100644
--- a/namespaces.c
+++ b/namespaces.c
@@ -29,24 +29,24 @@ out:
 	return ret;
 }
 
-static int do_dump_namespaces(int ns_pid, unsigned int ns_flags)
+static int do_dump_namespaces(struct pid *ns_pid, unsigned int ns_flags)
 {
 	struct cr_fdset *fdset;
 	int ret = 0;
 
-	fdset = cr_ns_fdset_open(ns_pid, O_DUMP);
+	fdset = cr_ns_fdset_open(ns_pid->pid, O_DUMP);
 	if (fdset == NULL)
 		return -1;
 
 	if (ns_flags & CLONE_NEWUTS) {
 		pr_info("Dump UTS namespace\n");
-		ret = dump_uts_ns(ns_pid, fdset);
+		ret = dump_uts_ns(ns_pid->real_pid, fdset);
 		if (ret < 0)
 			goto err;
 	}
 	if (ns_flags & CLONE_NEWIPC) {
 		pr_info("Dump IPC namespace\n");
-		ret = dump_ipc_ns(ns_pid, fdset);
+		ret = dump_ipc_ns(ns_pid->real_pid, fdset);
 		if (ret < 0)
 			goto err;
 	}
@@ -56,7 +56,7 @@ err:
 
 }
 
-int dump_namespaces(int ns_pid, unsigned int ns_flags)
+int dump_namespaces(struct pid *ns_pid, unsigned int ns_flags)
 {
 	int pid, status;
 	int ret = 0;
@@ -72,7 +72,7 @@ int dump_namespaces(int ns_pid, unsigned int ns_flags)
 	 * net namesapce with this is still open
 	 */
 
-	pr_info("Dumping %d's namespaces\n", ns_pid);
+	pr_info("Dumping %d(%d)'s namespaces\n", ns_pid->pid, ns_pid->real_pid);
 
 	pid = fork();
 	if (pid < 0) {
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 68fd383..3817b5b 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -429,7 +429,7 @@ static int parasite_set_logfd(struct parasite_ctl *ctl, pid_t pid)
 	return 0;
 }
 
-int parasite_dump_tid_addr_seized(struct parasite_ctl *ctl, pid_t pid, unsigned int **tid_addr)
+int parasite_dump_tid_addr_seized(struct parasite_ctl *ctl, pid_t pid, unsigned int **tid_addr, u32 *tid)
 {
 	struct parasite_dump_tid_addr args = { };
 	int ret;
@@ -438,6 +438,7 @@ int parasite_dump_tid_addr_seized(struct parasite_ctl *ctl, pid_t pid, unsigned
 			(parasite_status_t *)&args, sizeof(args));
 
 	*tid_addr = args.tid_addr;
+	*tid = args.tid;
 
 	return ret;
 }
diff --git a/parasite.c b/parasite.c
index 07d9b53..6242913 100644
--- a/parasite.c
+++ b/parasite.c
@@ -370,6 +370,10 @@ static int dump_misc(struct parasite_dump_misc *args)
 	args->brk = sys_brk(0);
 	args->blocked = old_blocked;
 
+	args->pid = sys_getpid();
+	args->sid = sys_getsid();
+	args->pgid = sys_getpgid();
+
 	return 0;
 }
 
@@ -384,6 +388,8 @@ static int dump_tid_addr(struct parasite_dump_tid_addr *args)
 		return ret;
 	}
 
+	args->tid = sys_gettid();
+
 	return 0;
 }
 
-- 
1.7.1



More information about the CRIU mailing list