[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(&parasite_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