mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-01 14:55:39 +00:00
dump: Dump threads params as well
We only need registers at the moment Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
This commit is contained in:
7
TODO
7
TODO
@@ -12,3 +12,10 @@ Some things which are to be done
|
||||
- 'crtools show' should support showing only a subset of resources dumped such as
|
||||
pipes/vma/ and etc...
|
||||
- add bash completion file
|
||||
|
||||
Some notes on code
|
||||
------------------
|
||||
|
||||
- need to handle out cr_fdset(s), they are getting used more frequently
|
||||
than I initially thought, including the usage only of a few file descriptors
|
||||
while the whole set is always allocated
|
||||
|
128
cr-dump.c
128
cr-dump.c
@@ -67,7 +67,6 @@ static FILE *fopen_proc(char *fmt, char *mode, ...)
|
||||
}
|
||||
|
||||
static char big_buffer[PATH_MAX];
|
||||
static struct parasite_ctl *parasite_ctl;
|
||||
|
||||
static char loc_buf[PAGE_SIZE];
|
||||
|
||||
@@ -619,28 +618,14 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
|
||||
static int get_task_regs(pid_t pid, struct core_entry *core)
|
||||
{
|
||||
struct core_entry *core = xzalloc(sizeof(*core));
|
||||
user_fpregs_struct_t fpregs = {-1};
|
||||
user_regs_struct_t regs = {-1};
|
||||
int fd_core = cr_fdset->desc[CR_FD_CORE].fd;
|
||||
int ret = -1;
|
||||
unsigned long brk;
|
||||
int ret = -1;
|
||||
|
||||
pr_info("\n");
|
||||
pr_info("Dumping core (pid: %d)\n", pid);
|
||||
pr_info("----------------------------------------\n");
|
||||
|
||||
if (!core)
|
||||
goto err;
|
||||
|
||||
lseek(fd_core, MAGIC_OFFSET, SEEK_SET);
|
||||
|
||||
jerr(ptrace(PTRACE_GETREGS, pid, NULL, ®s), err_free);
|
||||
jerr(ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs), err_free);
|
||||
|
||||
pr_info("Dumping GP/FPU registers ... ");
|
||||
jerr(ptrace(PTRACE_GETREGS, pid, NULL, ®s), err);
|
||||
jerr(ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs), err);
|
||||
|
||||
assign_reg(core->u.arch.gpregs, regs, r15);
|
||||
assign_reg(core->u.arch.gpregs, regs, r14);
|
||||
@@ -684,6 +669,33 @@ static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
|
||||
assign_array(core->u.arch.fpregs, fpregs, padding);
|
||||
|
||||
pr_info("OK\n");
|
||||
ret = 0;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
|
||||
{
|
||||
struct core_entry *core = xzalloc(sizeof(*core));
|
||||
int fd_core = cr_fdset->desc[CR_FD_CORE].fd;
|
||||
int ret = -1;
|
||||
unsigned long brk;
|
||||
|
||||
pr_info("\n");
|
||||
pr_info("Dumping core (pid: %d)\n", pid);
|
||||
pr_info("----------------------------------------\n");
|
||||
|
||||
if (!core)
|
||||
goto err;
|
||||
|
||||
lseek(fd_core, MAGIC_OFFSET, SEEK_SET);
|
||||
|
||||
pr_info("Dumping GP/FPU registers ... ");
|
||||
ret = get_task_regs(pid, core);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
pr_info("OK\n");
|
||||
|
||||
pr_info("Obtainting TLS ... ");
|
||||
ret = dump_task_tls(pid, core->u.arch.tls_array, ARRAY_SIZE(core->u.arch.tls_array));
|
||||
@@ -907,6 +919,7 @@ static int dump_pstree(pid_t pid, struct list_head *pstree_list, struct cr_fdset
|
||||
|
||||
e.pid = item->pid;
|
||||
e.nr_children = item->nr_children;
|
||||
e.nr_threads = item->nr_threads;
|
||||
|
||||
write_ptr_safe(cr_fdset->desc[CR_FD_PSTREE].fd, &e, err);
|
||||
|
||||
@@ -917,6 +930,14 @@ static int dump_pstree(pid_t pid, struct list_head *pstree_list, struct cr_fdset
|
||||
&item->children[i], err);
|
||||
}
|
||||
pr_info("\n");
|
||||
|
||||
pr_info("Threads:\n");
|
||||
for (i = 0; i < item->nr_threads; i++) {
|
||||
pr_info(" %d", item->threads[i]);
|
||||
write_ptr_safe(cr_fdset->desc[CR_FD_PSTREE].fd,
|
||||
&item->threads[i], err);
|
||||
}
|
||||
pr_info("\n");
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
@@ -1056,6 +1077,58 @@ err_strno:
|
||||
goto err;
|
||||
}
|
||||
|
||||
static int dump_task_thread(pid_t pid, struct cr_fdset *cr_fdset)
|
||||
{
|
||||
struct core_entry *core = xzalloc(sizeof(*core));
|
||||
int fd_core = cr_fdset->desc[CR_FD_CORE].fd;
|
||||
int ret = -1;
|
||||
|
||||
pr_info("\n");
|
||||
pr_info("Dumping core for thread (pid: %d)\n", pid);
|
||||
pr_info("----------------------------------------\n");
|
||||
|
||||
if (!core)
|
||||
goto err;
|
||||
|
||||
lseek(fd_core, MAGIC_OFFSET, SEEK_SET);
|
||||
|
||||
ret = seize_task(pid);
|
||||
if (ret) {
|
||||
pr_err("Failed to seize thread (pid: %d) with %d\n",
|
||||
pid, ret);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
pr_info("Dumping GP/FPU registers ... ");
|
||||
ret = get_task_regs(pid, core);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
pr_info("OK\n");
|
||||
|
||||
ret = unseize_task(pid);
|
||||
if (ret) {
|
||||
pr_err("Can't unsieze thread (pid: %d)\n", pid);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
pr_info("Dumping header ... ");
|
||||
core->header.version = HEADER_VERSION;
|
||||
core->header.arch = HEADER_ARCH_X86_64;
|
||||
core->header.flags = 0;
|
||||
|
||||
write_ptr_safe(fd_core, core, err_free);
|
||||
|
||||
pr_info("OK\n");
|
||||
ret = 0;
|
||||
|
||||
err_free:
|
||||
free(core);
|
||||
err:
|
||||
pr_info("----------------------------------------\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dump_one_task(pid_t pid, struct cr_fdset *cr_fdset)
|
||||
{
|
||||
LIST_HEAD(vma_area_list);
|
||||
@@ -1138,7 +1211,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts)
|
||||
LIST_HEAD(pstree_list);
|
||||
struct cr_fdset *cr_fdset = NULL;
|
||||
struct pstree_item *item;
|
||||
int ret = -1;
|
||||
int i, ret = -1;
|
||||
|
||||
pr_info("========================================\n");
|
||||
if (!opts->leader_only)
|
||||
@@ -1184,6 +1257,21 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts)
|
||||
close_cr_fdset(cr_fdset);
|
||||
free_cr_fdset(&cr_fdset);
|
||||
|
||||
if (item->nr_threads > 1) {
|
||||
for (i = 0; i < item->nr_threads; i++) {
|
||||
/* Leader is already dumped */
|
||||
if (item->pid == item->threads[i])
|
||||
continue;
|
||||
cr_fdset = alloc_cr_fdset(item->threads[i]);
|
||||
if (!cr_fdset)
|
||||
goto err;
|
||||
if (prep_cr_fdset_for_dump(cr_fdset, CR_FD_DESC_CORE))
|
||||
goto err;
|
||||
if (dump_task_thread(item->threads[i], cr_fdset))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts->leader_only)
|
||||
break;
|
||||
}
|
||||
|
@@ -58,7 +58,8 @@ struct cr_fdset {
|
||||
};
|
||||
|
||||
#define CR_FD_DESC_USE(type) ((1 << (type)))
|
||||
#define CR_FD_DESC_ALL ((1 << CR_FD_MAX) - 1)
|
||||
#define CR_FD_DESC_ALL (CR_FD_DESC_USE(CR_FD_MAX) - 1)
|
||||
#define CR_FD_DESC_CORE CR_FD_DESC_USE(CR_FD_CORE)
|
||||
#define CR_FD_DESC_NOPSTREE (CR_FD_DESC_ALL & ~(CR_FD_DESC_USE(CR_FD_PSTREE)))
|
||||
#define CR_FD_DESC_NONE (0)
|
||||
|
||||
|
@@ -36,7 +36,10 @@ struct shmem_entry {
|
||||
struct pstree_entry {
|
||||
u32 pid;
|
||||
u32 nr_children;
|
||||
u32 nr_threads;
|
||||
|
||||
u32 children[0];
|
||||
u32 threads[0];
|
||||
} __packed;
|
||||
|
||||
struct pipe_entry {
|
||||
|
Reference in New Issue
Block a user