Commit 3f48f35b authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

parasite: use transparent thread indexes

We have three arrays for thread related data: item->threads,
parasite_ctl->thread and tid_state in parasite.

With this patch a thread will have the same index in all arrays.
The zero index is used for a thread leader.

In this case we don't need to search thread_state in parasite.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 0772e475
......@@ -1078,9 +1078,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");
......@@ -1091,7 +1093,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;
......@@ -1208,7 +1210,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;
}
......@@ -1349,7 +1351,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(&parasite_ctl->pre_list, ctls);
err_free:
......@@ -1358,7 +1360,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;
}
......@@ -1514,7 +1516,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;
......@@ -1532,7 +1534,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;
......@@ -1573,7 +1575,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;
}
......
......@@ -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:
......
......@@ -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,
......
......@@ -41,6 +41,8 @@ enum {
};
struct parasite_init_args {
int id;
int h_addr_len;
struct sockaddr_un h_addr;
......@@ -121,6 +123,7 @@ struct parasite_dump_creds {
};
struct parasite_dump_thread {
int id;
unsigned int *tid_addr;
pid_t tid;
k_rtsigset_t blocked;
......
......@@ -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];
};
......
......@@ -197,8 +197,10 @@ void *parasite_args_s(struct parasite_ctl *ctl, int args_size)
ctl->addr_args; \
})
static int parasite_execute_by_pid(unsigned int cmd, struct parasite_ctl *ctl, pid_t pid)
static int parasite_execute_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;
......@@ -234,7 +236,7 @@ static int parasite_execute_by_pid(unsigned int cmd, struct parasite_ctl *ctl, p
int parasite_execute(unsigned int cmd, struct parasite_ctl *ctl)
{
return parasite_execute_by_pid(cmd, ctl, ctl->pid.real);
return parasite_execute_by_id(cmd, ctl, 0);
}
static int munmap_seized(struct parasite_ctl *ctl, void *addr, size_t length)
......@@ -298,6 +300,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;
......@@ -356,15 +359,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_by_pid(PARASITE_CMD_DUMP_THREAD, ctl, tid->real);
ret = parasite_execute_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);
......@@ -653,14 +657,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);
ret = parasite_execute_by_pid(PARASITE_CMD_INIT_THREAD, ctl,
item->threads[i].real);
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_by_id(PARASITE_CMD_INIT_THREAD, ctl, i);
if (ret) {
pr_err("Can't init thread in parasite %d\n",
item->threads[i].real);
......@@ -671,16 +682,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);
ret = parasite_execute_by_pid(PARASITE_CMD_FINI_THREAD, ctl,
item->threads[i].real);
for (i = 1; i < ctl->nr_threads; i++) {
pid_t tid = ctl->threads[i].tid;
args->id = i;
ret = parasite_execute_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
......@@ -694,8 +707,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;
}
}
......@@ -703,7 +715,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(PARASITE_CMD_FINI, ctl);
}
int parasite_cure_remote(struct parasite_ctl *ctl)
{
int ret = 0;
......@@ -711,8 +733,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(PARASITE_CMD_FINI, ctl);
parasite_fini_threads_seized(ctl);
parasite_fini_seized(ctl);
}
if (ctl->remote_map) {
......@@ -751,35 +773,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);
......@@ -864,7 +890,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;
......@@ -909,7 +937,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;
}
......@@ -18,7 +18,7 @@
static int tsock = -1;
static struct tid_state_s {
pid_t tid;
int id;
bool use_sig_blocked;
k_rtsigset_t sig_blocked;
} *tid_state;
......@@ -172,33 +172,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;
......@@ -213,11 +192,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;
......@@ -227,20 +209,17 @@ 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;
next_tid_state++;
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,
......@@ -265,7 +244,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;
......@@ -431,11 +410,11 @@ static int parasite_check_vdso_mark(struct parasite_vdso_vma_entry *args)
return 0;
}
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);
......@@ -452,11 +431,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:
......
......@@ -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])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment