[CRIU] [PATCH 05/21] parasite: use transparent thread indexes
Andrey Vagin
avagin at openvz.org
Fri May 24 08:20:08 EDT 2013
In this case we don't need to search thread_state in parasite.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
cr-dump.c | 18 +++++-----
cr-exec.c | 4 +--
include/parasite-syscall.h | 22 +++++++++----
include/parasite.h | 3 ++
include/pstree.h | 1 -
parasite-syscall.c | 82 +++++++++++++++++++++++++++++++---------------
pie/parasite.c | 53 +++++++++---------------------
pstree.c | 5 ++-
8 files changed, 104 insertions(+), 84 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index 10df8df..95be08e 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1077,9 +1077,11 @@ static int collect_file_locks(void)
}
static int dump_task_thread(struct parasite_ctl *parasite_ctl,
- struct pid *tid, CoreEntry *core)
+ const struct pstree_item *item, int id)
{
int ret = -1, fd_core;
+ struct pid *tid = &item->threads[id];
+ CoreEntry *core = item->core[id];
pid_t pid = tid->real;
pr_info("\n");
@@ -1090,7 +1092,7 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl,
if (ret)
goto err;
- ret = parasite_dump_thread_seized(parasite_ctl, tid, core);
+ ret = parasite_dump_thread_seized(parasite_ctl, id, tid, core);
if (ret) {
pr_err("Can't dump thread for pid %d\n", pid);
goto err;
@@ -1207,7 +1209,7 @@ static int dump_task_threads(struct parasite_ctl *parasite_ctl,
if (item->pid.real == item->threads[i].real)
item->threads[i].virt = item->pid.virt;
else {
- if (dump_task_thread(parasite_ctl, &item->threads[i], item->core[i]))
+ if (dump_task_thread(parasite_ctl, item, i))
return -1;
}
@@ -1348,7 +1350,7 @@ static int pre_dump_one_task(struct pstree_item *item, struct list_head *ctls)
if (ret)
goto err_cure;
- if (parasite_cure_remote(parasite_ctl, item))
+ if (parasite_cure_remote(parasite_ctl))
pr_err("Can't cure (pid: %d) from parasite\n", pid);
list_add_tail(¶site_ctl->pre_list, ctls);
err_free:
@@ -1357,7 +1359,7 @@ err:
return ret;
err_cure:
- if (parasite_cure_seized(parasite_ctl, item))
+ if (parasite_cure_seized(parasite_ctl))
pr_err("Can't cure (pid: %d) from parasite\n", pid);
goto err_free;
}
@@ -1507,7 +1509,7 @@ static int dump_one_task(struct pstree_item *item)
goto err_cure;
}
- ret = dump_task_core_all(parasite_ctl, item->this_core, &pps_buf, &misc, &vmas, cr_fdset);
+ ret = dump_task_core_all(parasite_ctl, item->core[0], &pps_buf, &misc, &vmas, cr_fdset);
if (ret) {
pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
goto err_cure;
@@ -1525,7 +1527,7 @@ static int dump_one_task(struct pstree_item *item)
goto err;
}
- ret = parasite_cure_seized(parasite_ctl, item);
+ ret = parasite_cure_seized(parasite_ctl);
if (ret) {
pr_err("Can't cure (pid: %d) from parasite\n", pid);
goto err;
@@ -1566,7 +1568,7 @@ err_free:
err_cure:
close_cr_fdset(&cr_fdset);
err_cure_fdset:
- parasite_cure_seized(parasite_ctl, item);
+ parasite_cure_seized(parasite_ctl);
goto err;
}
diff --git a/cr-exec.c b/cr-exec.c
index 1b73da0..c2e3bea 100644
--- a/cr-exec.c
+++ b/cr-exec.c
@@ -110,7 +110,7 @@ int cr_exec(int pid, char **opt)
goto out_unseize;
}
- ctl = parasite_prep_ctl(pid, &vmas);
+ ctl = parasite_prep_ctl(pid, &vmas, 1);
if (!ctl) {
pr_err("Can't prep ctl %d\n", pid);
goto out_unseize;
@@ -120,7 +120,7 @@ int cr_exec(int pid, char **opt)
if (ret < 0)
pr_err("Can't execute syscall remotely\n");
- parasite_cure_seized(ctl, NULL);
+ parasite_cure_seized(ctl);
out_unseize:
unseize_task(pid, prev_state);
out:
diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index e4a644f..ffffaf6 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -5,6 +5,11 @@
#include "pstree.h"
+struct parasite_thread_ctl
+{
+ pid_t tid;
+};
+
/* parasite control block */
struct parasite_ctl {
struct pid pid;
@@ -26,6 +31,9 @@ struct parasite_ctl {
struct list_head pre_list;
struct page_pipe *mem_pp;
+
+ int nr_threads;
+ struct parasite_thread_ctl threads[0];
};
struct cr_fdset;
@@ -46,8 +54,8 @@ extern int parasite_dump_creds(struct parasite_ctl *ctl, struct _CredsEntry *ce)
struct parasite_dump_thread;
struct pid;
struct _CoreEntry;
-extern int parasite_dump_thread_seized(struct parasite_ctl *ctl, struct pid *tid,
- struct _CoreEntry *core);
+extern int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
+ struct pid *tid, struct _CoreEntry *core);
struct parasite_drain_fd;
struct fd_opts;
@@ -57,21 +65,23 @@ extern int parasite_drain_fds_seized(struct parasite_ctl *ctl,
extern int parasite_get_proc_fd_seized(struct parasite_ctl *ctl);
struct pstree_item;
-extern int parasite_cure_remote(struct parasite_ctl *ctl, struct pstree_item *item);
+extern int parasite_cure_remote(struct parasite_ctl *ctl);
extern int parasite_cure_local(struct parasite_ctl *ctl);
-extern int parasite_cure_seized(struct parasite_ctl *ctl, struct pstree_item *item);
+extern int parasite_cure_seized(struct parasite_ctl *ctl);
extern struct parasite_ctl *parasite_infect_seized(pid_t pid,
struct pstree_item *item,
struct vm_area_list *vma_area_list,
struct parasite_drain_fd *dfds);
-extern struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_list);
+extern struct parasite_ctl *parasite_prep_ctl(pid_t pid,
+ struct vm_area_list *vma_area_list,
+ unsigned int nr_threads);
extern int parasite_map_exchange(struct parasite_ctl *ctl, unsigned long size);
extern struct parasite_tty_args *parasite_dump_tty(struct parasite_ctl *ctl, int fd);
struct pstree_item;
extern int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *item);
-extern int parasite_fini_threads_seized(struct parasite_ctl *ctl, struct pstree_item *item);
+extern int parasite_fini_threads_seized(struct parasite_ctl *ctl);
int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
unsigned long arg1,
diff --git a/include/parasite.h b/include/parasite.h
index 6d07cb3..9ad3161 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -63,6 +63,8 @@ struct ctl_msg {
(struct ctl_msg){ .id = _id, .cmd = _cmd, .ack = _cmd, .err = _err, }
struct parasite_init_args {
+ int id;
+
int h_addr_len;
struct sockaddr_un h_addr;
@@ -136,6 +138,7 @@ struct parasite_dump_creds {
};
struct parasite_dump_thread {
+ int id;
unsigned int *tid_addr;
pid_t tid;
k_rtsigset_t blocked;
diff --git a/include/pstree.h b/include/pstree.h
index b9b3c87..20bacb7 100644
--- a/include/pstree.h
+++ b/include/pstree.h
@@ -43,7 +43,6 @@ struct pstree_item {
struct pid *threads; /* array of threads */
CoreEntry **core;
TaskKobjIdsEntry *ids;
- CoreEntry *this_core; /* for fast access to a leader */
struct rst_info rst[0];
};
diff --git a/parasite-syscall.c b/parasite-syscall.c
index b7891fe..deca9cd 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -195,8 +195,10 @@ void *parasite_args_s(struct parasite_ctl *ctl, int args_size)
ctl->addr_args; \
})
-static int parasite_execute_trap_by_pid(unsigned int cmd, struct parasite_ctl *ctl, pid_t pid)
+static int parasite_execute_trap_by_id(unsigned int cmd, struct parasite_ctl *ctl, int id)
{
+ struct parasite_thread_ctl *thread = &ctl->threads[id];
+ pid_t pid = thread->tid;
int ret;
user_regs_struct_t regs_orig, regs;
@@ -232,7 +234,7 @@ static int parasite_execute_trap_by_pid(unsigned int cmd, struct parasite_ctl *c
int parasite_execute_trap(unsigned int cmd, struct parasite_ctl *ctl)
{
- return parasite_execute_trap_by_pid(cmd, ctl, ctl->pid.real);
+ return parasite_execute_trap_by_id(cmd, ctl, 0);
}
static int munmap_seized(struct parasite_ctl *ctl, void *addr, size_t length)
@@ -296,6 +298,7 @@ static int parasite_init(struct parasite_ctl *ctl, pid_t pid, int nr_threads)
args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid());
args->p_addr_len = gen_parasite_saddr(&args->p_addr, pid);
args->nr_threads = nr_threads;
+ args->id = 0;
if (sock == -1) {
int rst = -1;
@@ -354,15 +357,16 @@ err:
return -1;
}
-int parasite_dump_thread_seized(struct parasite_ctl *ctl, struct pid *tid,
- CoreEntry *core)
+int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
+ struct pid *tid, CoreEntry *core)
{
struct parasite_dump_thread *args;
int ret;
args = parasite_args(ctl, struct parasite_dump_thread);
+ args->id = id;
- ret = parasite_execute_trap_by_pid(PARASITE_CMD_DUMP_THREAD, ctl, tid->real);
+ ret = parasite_execute_trap_by_id(PARASITE_CMD_DUMP_THREAD, ctl, id);
memcpy(&core->thread_core->blk_sigset, &args->blocked, sizeof(args->blocked));
CORE_THREAD_ARCH_INFO(core)->clear_tid_addr = encode_pointer(args->tid_addr);
@@ -532,14 +536,21 @@ int parasite_get_proc_fd_seized(struct parasite_ctl *ctl)
int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *item)
{
+ struct parasite_init_args *args;
int ret = 0, i;
- for (i = 0; i < item->nr_threads; i++) {
- if (item->pid.real == item->threads[i].real)
- continue;
+ args = parasite_args(ctl, struct parasite_init_args);
+
+ for (i = 1; i < item->nr_threads; i++) {
+ pid_t tid = item->threads[i].real;
+
+ ctl->threads[i].tid = tid;
+ ctl->nr_threads++;
+
+ args->id = i;
- ret = parasite_execute_trap_by_pid(PARASITE_CMD_INIT_THREAD, ctl,
- item->threads[i].real);
+
+ ret = parasite_execute_trap_by_id(PARASITE_CMD_INIT_THREAD, ctl, i);
if (ret) {
pr_err("Can't init thread in parasite %d\n",
item->threads[i].real);
@@ -550,16 +561,18 @@ int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
return ret;
}
-int parasite_fini_threads_seized(struct parasite_ctl *ctl, struct pstree_item *item)
+int parasite_fini_threads_seized(struct parasite_ctl *ctl)
{
+ struct parasite_init_args *args;
int ret = 0, i;
- for (i = 0; i < item->nr_threads; i++) {
- if (item->pid.real == item->threads[i].real)
- continue;
+ args = parasite_args(ctl, struct parasite_init_args);
+
+ for (i = 1; i < ctl->nr_threads; i++) {
+ pid_t tid = ctl->threads[i].tid;
- ret = parasite_execute_trap_by_pid(PARASITE_CMD_FINI_THREAD, ctl,
- item->threads[i].real);
+ args->id = i;
+ ret = parasite_execute_trap_by_id(PARASITE_CMD_FINI_THREAD, ctl, i);
/*
* Note the thread's fini() can be called even when not
* all threads were init()'ed, say we're rolling back from
@@ -573,8 +586,7 @@ int parasite_fini_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
* would change the code logic.
*/
if (ret && ret != -ENOENT) {
- pr_err("Can't fini thread in parasite %d\n",
- item->threads[i].real);
+ pr_err("Can't fini thread in parasite %d\n", tid);
break;
}
}
@@ -582,7 +594,17 @@ int parasite_fini_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
return ret;
}
-int parasite_cure_remote(struct parasite_ctl *ctl, struct pstree_item *item)
+static int parasite_fini_seized(struct parasite_ctl *ctl)
+{
+ struct parasite_init_args *args;
+
+ args = parasite_args(ctl, struct parasite_init_args);
+ args->id = 0;
+
+ return parasite_execute_trap(PARASITE_CMD_FINI, ctl);
+}
+
+int parasite_cure_remote(struct parasite_ctl *ctl)
{
int ret = 0;
@@ -590,8 +612,8 @@ int parasite_cure_remote(struct parasite_ctl *ctl, struct pstree_item *item)
if (ctl->parasite_ip) {
ctl->signals_blocked = 0;
- parasite_fini_threads_seized(ctl, item);
- parasite_execute_trap(PARASITE_CMD_FINI, ctl);
+ parasite_fini_threads_seized(ctl);
+ parasite_fini_seized(ctl);
}
if (ctl->remote_map) {
@@ -630,35 +652,39 @@ int parasite_cure_local(struct parasite_ctl *ctl)
return ret;
}
-int parasite_cure_seized(struct parasite_ctl *ctl, struct pstree_item *item)
+int parasite_cure_seized(struct parasite_ctl *ctl)
{
int ret;
- ret = parasite_cure_remote(ctl, item);
+ ret = parasite_cure_remote(ctl);
if (!ret)
ret = parasite_cure_local(ctl);
return ret;
}
-struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_list)
+struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_list, unsigned int nr_threads)
{
struct parasite_ctl *ctl = NULL;
struct vma_area *vma_area;
+ BUG_ON(nr_threads == 0);
+
if (!arch_can_dump_task(pid))
goto err;
/*
* Control block early setup.
*/
- ctl = xzalloc(sizeof(*ctl));
+ ctl = xzalloc(sizeof(*ctl) + nr_threads * sizeof(ctl->threads[0]));
if (!ctl) {
pr_err("Parasite control block allocation failed (pid: %d)\n", pid);
goto err;
}
ctl->tsock = -1;
+ ctl->nr_threads = 1;
+ ctl->threads[0].tid = pid;
if (ptrace(PTRACE_GETREGS, pid, NULL, &ctl->regs_orig)) {
pr_err("Can't obtain registers (pid: %d)\n", pid);
@@ -743,7 +769,9 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
int ret;
struct parasite_ctl *ctl;
- ctl = parasite_prep_ctl(pid, vma_area_list);
+ BUG_ON(item->threads[0].real != pid);
+
+ ctl = parasite_prep_ctl(pid, vma_area_list, item->nr_threads);
if (!ctl)
return NULL;
@@ -788,7 +816,7 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
return ctl;
err_restore:
- parasite_cure_seized(ctl, item);
+ parasite_cure_seized(ctl);
return NULL;
}
diff --git a/pie/parasite.c b/pie/parasite.c
index e0a35a9..070a995 100644
--- a/pie/parasite.c
+++ b/pie/parasite.c
@@ -18,7 +18,7 @@
static int tsock = -1;
static struct tid_state_s {
- pid_t tid;
+ int id;
futex_t cmd;
int ret;
@@ -176,33 +176,12 @@ static int drain_fds(struct parasite_drain_fd *args)
return ret;
}
-static struct tid_state_s *find_thread_state(pid_t tid)
-{
- unsigned int i;
-
- /*
- * FIXME
- *
- * We need a hash here rather
- */
- for (i = 0; i < next_tid_state; i++) {
- if (tid_state[i].tid == tid)
- return &tid_state[i];
- }
-
- return NULL;
-}
-
static int dump_thread(struct parasite_dump_thread *args)
{
+ struct tid_state_s *s = &tid_state[args->id];
pid_t tid = sys_gettid();
- struct tid_state_s *s;
int ret;
- s = find_thread_state(tid);
- if (!s)
- return -ENOENT;
-
if (!s->use_sig_blocked)
return -EINVAL;
@@ -217,11 +196,14 @@ static int dump_thread(struct parasite_dump_thread *args)
return 0;
}
-static int init_thread(void)
+static int init_thread(struct parasite_init_args *args)
{
k_rtsigset_t to_block;
int ret;
+ if (args->id != next_tid_state)
+ return -EINVAL;
+
if (next_tid_state >= nr_tid_state)
return -ENOMEM;
@@ -231,7 +213,8 @@ static int init_thread(void)
sizeof(k_rtsigset_t));
if (ret >= 0)
tid_state[next_tid_state].use_sig_blocked = true;
- tid_state[next_tid_state].tid = sys_gettid();
+
+ tid_state[next_tid_state].id = next_tid_state;
futex_set(&tid_state[next_tid_state].cmd, PARASITE_CMD_IDLE);
@@ -240,13 +223,9 @@ static int init_thread(void)
return ret;
}
-static int fini_thread(void)
+static int fini_thread(struct parasite_init_args *args)
{
- struct tid_state_s *s;
-
- s = find_thread_state(sys_gettid());
- if (!s)
- return -ENOENT;
+ struct tid_state_s *s = &tid_state[args->id];
if (s->use_sig_blocked)
return sys_sigprocmask(SIG_SETMASK, &s->sig_blocked,
@@ -271,7 +250,7 @@ static int init(struct parasite_init_args *args)
nr_tid_state = args->nr_threads;
- ret = init_thread();
+ ret = init_thread(args);
if (ret < 0)
return ret;
@@ -422,11 +401,11 @@ static int parasite_cfg_log(struct parasite_log_args *args)
return ret;
}
-static int fini(void)
+static int fini(struct parasite_init_args *args)
{
int ret;
- ret = fini_thread();
+ ret = fini_thread(args);
sys_munmap(tid_state, TID_STATE_SIZE(nr_tid_state));
log_set_fd(-1);
@@ -443,11 +422,11 @@ int __used parasite_service(unsigned int cmd, void *args)
case PARASITE_CMD_INIT:
return init(args);
case PARASITE_CMD_INIT_THREAD:
- return init_thread();
+ return init_thread(args);
case PARASITE_CMD_FINI:
- return fini();
+ return fini(args);
case PARASITE_CMD_FINI_THREAD:
- return fini_thread();
+ return fini_thread(args);
case PARASITE_CMD_CFG_LOG:
return parasite_cfg_log(args);
case PARASITE_CMD_DUMPPAGES:
diff --git a/pstree.c b/pstree.c
index 93ac707..1794a33 100644
--- a/pstree.c
+++ b/pstree.c
@@ -67,10 +67,9 @@ 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);
- item->this_core = item->core[i];
- } else
+ else
item->core[i] = core_entry_alloc(1, 0);
if (!item->core[i])
--
1.8.2
More information about the CRIU
mailing list