[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