[PATCH] pstree: Bind CoreEntry to pstree and fill it early

Cyrill Gorcunov gorcunov at openvz.org
Fri Feb 22 14:56:13 EST 2013


When parasite daemon mode will be implemented we get
deprived of ability to fetch registers at the late
moment of dumping, thus just bind CoreEntry to pstree
item and allocate CoreEntry'ies for every thread found
once process tree is in seized state. Then immediately
fill CoreEntry with registers state.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 cr-dump.c        | 128 +++++++++++++++++++++++--------------------------------
 include/pstree.h |   5 ++-
 pstree.c         |  72 ++++++++++++++++++++++++++++++-
 3 files changed, 129 insertions(+), 76 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index 4c3d064..a1e16c9 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -540,39 +540,6 @@ static int dump_task_kobj_ids(struct pstree_item *item)
 	return 0;
 }
 
-static CoreEntry *core_entry_alloc(int alloc_thread_info,
-				   int alloc_tc)
-{
-	CoreEntry *core;
-	TaskCoreEntry *tc;
-
-	core = xmalloc(sizeof(*core));
-	if (!core)
-		return NULL;
-	core_entry__init(core);
-
-	core->mtype = CORE_ENTRY__MARCH;
-
-	if (alloc_thread_info) {
-		if (arch_alloc_thread_info(core))
-			goto err;
-	}
-
-	if (alloc_tc) {
-		tc = xzalloc(sizeof(*tc) + TASK_COMM_LEN);
-		if (!tc)
-			goto err;
-		task_core_entry__init(tc);
-		tc->comm = (void *)tc + sizeof(*tc);
-		core->tc = tc;
-	}
-
-	return core;
-err:
-	core_entry_free(core);
-	return NULL;
-}
-
 int get_task_ids(struct pstree_item *item)
 {
 	int ret;
@@ -607,40 +574,31 @@ static int dump_task_ids(struct pstree_item *item, const struct cr_fdset *cr_fds
 	return pb_write_one(fdset_fd(cr_fdset, CR_FD_IDS), item->ids, PB_IDS);
 }
 
-static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
+static int dump_task_core_all(pid_t pid, CoreEntry *core, const struct proc_pid_stat *stat,
 		const struct parasite_dump_misc *misc, const struct parasite_ctl *ctl,
 		const struct cr_fdset *cr_fdset,
 		struct list_head *vma_area_list)
 {
 	int fd_core = fdset_fd(cr_fdset, CR_FD_CORE);
-	CoreEntry *core;
 	int ret = -1;
 
-	core = core_entry_alloc(1, 1);
-	if (!core)
-		return -1;
-
 	pr_info("\n");
 	pr_info("Dumping core (pid: %d)\n", pid);
 	pr_info("----------------------------------------\n");
 
 	ret = dump_task_mm(pid, stat, misc, cr_fdset);
 	if (ret)
-		goto err_free;
-
-	ret = get_task_regs(pid, core, ctl);
-	if (ret)
-		goto err_free;
+		goto err;
 
 	mark_stack_vma(CORE_THREAD_ARCH_INFO(core)->gpregs->sp, vma_area_list);
 
 	ret = get_task_futex_robust_list(pid, core->thread_core);
 	if (ret)
-		goto err_free;
+		goto err;
 
 	ret = get_task_personality(pid, &core->tc->personality);
 	if (ret)
-		goto err_free;
+		goto err;
 
 	strncpy((char *)core->tc->comm, stat->comm, TASK_COMM_LEN);
 	core->tc->flags = stat->flags;
@@ -652,16 +610,15 @@ static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
 
 	ret = dump_sched_info(pid, core->thread_core);
 	if (ret)
-		goto err_free;
+		goto err;
 
 	core_put_tls(core, misc->tls);
 
 	ret = pb_write_one(fd_core, core, PB_CORE);
 	if (ret < 0)
-		goto err_free;
+		goto err;
 
-err_free:
-	core_entry_free(core);
+err:
 	pr_info("----------------------------------------\n");
 
 	return ret;
@@ -983,6 +940,39 @@ static int collect_pstree_ids(void)
 	return 0;
 }
 
+static int collect_regs_seized(struct pstree_item *item)
+{
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < item->nr_threads; i++) {
+		pid_t pid = item->threads[i].real;
+		ret = get_task_regs(pid, item->core[i], NULL);
+		if (ret) {
+			pr_err("Can't obtain regs for thread %d\n", pid);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int collect_pstree_cores(void)
+{
+	struct pstree_item *item;
+
+	for_each_pstree_item(item) {
+		if (pstree_alloc_cores(item))
+			return -1;
+		if (item->state == TASK_DEAD)
+			continue;
+		if (collect_regs_seized(item))
+			return -1;
+	}
+
+	return 0;
+}
+
 static int collect_pstree(pid_t pid, const struct cr_options *opts)
 {
 	int ret, attempts = 5;
@@ -1060,9 +1050,9 @@ static int collect_file_locks(const struct cr_options *opts)
 
 }
 
-static int dump_task_thread(struct parasite_ctl *parasite_ctl, struct pid *tid)
+static int dump_task_thread(struct parasite_ctl *parasite_ctl,
+			    struct pid *tid, CoreEntry *core)
 {
-	CoreEntry *core;
 	int ret = -1, fd_core;
 	pid_t pid = tid->real;
 
@@ -1070,39 +1060,29 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl, struct pid *tid)
 	pr_info("Dumping core for thread (pid: %d)\n", pid);
 	pr_info("----------------------------------------\n");
 
-	core = core_entry_alloc(1, 0);
-	if (!core)
-		goto err;
-
-	ret = get_task_regs(pid, core, NULL);
-	if (ret)
-		goto err_free;
-
 	ret = get_task_futex_robust_list(pid, core->thread_core);
 	if (ret)
-		goto err_free;
+		goto err;
 
 	ret = parasite_dump_thread_seized(parasite_ctl, tid, core);
 	if (ret) {
 		pr_err("Can't dump thread for pid %d\n", pid);
-		goto err_free;
+		goto err;
 	}
 
 	core->thread_core->has_blk_sigset = true;
 
 	ret = dump_sched_info(pid, core->thread_core);
 	if (ret)
-		goto err_free;
+		goto err;
 
 	fd_core = open_image(CR_FD_CORE, O_DUMP, tid->virt);
 	if (fd_core < 0)
-		goto err_free;
+		goto err;
 
 	ret = pb_write_one(fd_core, core, PB_CORE);
 
 	close(fd_core);
-err_free:
-	core_entry_free(core);
 err:
 	pr_info("----------------------------------------\n");
 	return ret;
@@ -1114,21 +1094,17 @@ static int dump_one_zombie(const struct pstree_item *item,
 	CoreEntry *core;
 	int ret = -1, fd_core;
 
-	core = core_entry_alloc(0, 1);
-	if (core == NULL)
-		goto err;
+	core = item->core[0];
 
 	core->tc->task_state = TASK_DEAD;
 	core->tc->exit_code = pps->exit_code;
 
 	fd_core = open_image(CR_FD_CORE, O_DUMP, item->pid.virt);
 	if (fd_core < 0)
-		goto err_free;
+		goto err;
 
 	ret = pb_write_one(fd_core, core, PB_CORE);
 	close(fd_core);
-err_free:
-	core_entry_free(core);
 err:
 	return ret;
 }
@@ -1147,7 +1123,8 @@ static int dump_task_threads(struct parasite_ctl *parasite_ctl,
 			continue;
 		}
 
-		if (dump_task_thread(parasite_ctl, &item->threads[i]))
+		if (dump_task_thread(parasite_ctl, &item->threads[i],
+				     item->core[i]))
 			return -1;
 	}
 
@@ -1354,7 +1331,7 @@ static int dump_one_task(struct pstree_item *item)
 		goto err_cure;
 	}
 
-	ret = dump_task_core_all(pid, &pps_buf, &misc,
+	ret = dump_task_core_all(pid, item->this_core, &pps_buf, &misc,
 					parasite_ctl, cr_fdset, &vma_area_list);
 	if (ret) {
 		pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
@@ -1430,6 +1407,9 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
 	if (collect_pstree(pid, opts))
 		goto err;
 
+	if (collect_pstree_cores())
+		goto err;
+
 	if (network_lock())
 		goto err;
 
diff --git a/include/pstree.h b/include/pstree.h
index ed6495c..d548973 100644
--- a/include/pstree.h
+++ b/include/pstree.h
@@ -41,7 +41,9 @@ struct pstree_item {
 
 	int			nr_threads;	/* number of threads */
 	struct pid		*threads;	/* array of threads */
+	CoreEntry		**core;
 	TaskKobjIdsEntry	*ids;
+	CoreEntry		*this_core;	/* for fast access to a leader */
 
 	struct rst_info		rst[0];
 };
@@ -76,6 +78,7 @@ extern struct task_entries *task_entries;
 int get_task_ids(struct pstree_item *);
 extern struct _TaskKobjIdsEntry *root_ids;
 
-extern void core_entry_free(CoreEntry *core);
+extern int pstree_alloc_cores(struct pstree_item *item);
+extern void pstree_free_cores(struct pstree_item *item);
 
 #endif /* __CR_PSTREE_H__ */
diff --git a/pstree.c b/pstree.c
index 5bfcbdc..0cba604 100644
--- a/pstree.c
+++ b/pstree.c
@@ -16,7 +16,7 @@
 
 struct pstree_item *root_item;
 
-void core_entry_free(CoreEntry *core)
+static void core_entry_free(CoreEntry *core)
 {
 	if (core) {
 		arch_free_thread_info(core);
@@ -26,6 +26,75 @@ void core_entry_free(CoreEntry *core)
 	}
 }
 
+static CoreEntry *core_entry_alloc(int alloc_thread_info, int alloc_tc)
+{
+	CoreEntry *core;
+	TaskCoreEntry *tc;
+
+	core = xmalloc(sizeof(*core));
+	if (!core)
+		return NULL;
+	core_entry__init(core);
+
+	core->mtype = CORE_ENTRY__MARCH;
+
+	if (alloc_thread_info) {
+		if (arch_alloc_thread_info(core))
+			goto err;
+	}
+
+	if (alloc_tc) {
+		tc = xzalloc(sizeof(*tc) + TASK_COMM_LEN);
+		if (!tc)
+			goto err;
+		task_core_entry__init(tc);
+		tc->comm = (void *)tc + sizeof(*tc);
+		core->tc = tc;
+	}
+
+	return core;
+err:
+	core_entry_free(core);
+	return NULL;
+}
+
+int pstree_alloc_cores(struct pstree_item *item)
+{
+	unsigned int i;
+
+	item->core = xzalloc(sizeof(*item->core) * item->nr_threads);
+	if (!item->core)
+		return -1;
+
+	for (i = 0; i < item->nr_threads; i++) {
+		int is_leader = (item->threads[i].real == item->pid.real);
+
+		item->core[i] = core_entry_alloc(item->state != TASK_DEAD, is_leader);
+		if (!item->core[i])
+			goto err;
+
+		if (is_leader)
+			item->this_core = item->core[i];
+	}
+
+	return 0;
+err:
+	pstree_free_cores(item);
+	return -1;
+}
+
+void pstree_free_cores(struct pstree_item *item)
+{
+	unsigned int i;
+
+	if (item->core) {
+		for (i = 1; i < item->nr_threads; i++)
+			core_entry_free(item->core[i]);
+		xfree(item->core);
+		item->core = NULL;
+	}
+}
+
 void free_pstree(struct pstree_item *root_item)
 {
 	struct pstree_item *item = root_item, *parent;
@@ -38,6 +107,7 @@ void free_pstree(struct pstree_item *root_item)
 
 		parent = item->parent;
 		list_del(&item->sibling);
+		pstree_free_cores(item);
 		xfree(item->threads);
 		xfree(item);
 		item = parent;
-- 
1.8.1.2


--+QahgC5+KEYLbs62--


More information about the CRIU mailing list