Commit 73d7e283 authored by Pavel Emelyanov's avatar Pavel Emelyanov

show: Filter -D output with --pid option

Show only image info relevant to given pid. Also reuse
the introduced --pid argument for exec action.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 6241a057
......@@ -261,11 +261,28 @@ void show_creds(int fd, struct cr_options *o)
pb_show_vertical(fd, PB_CREDS);
}
static int pstree_item_from_pb(PstreeEntry *e, struct pstree_item *item)
{
int i;
item->pid.virt = e->pid;
item->nr_threads = e->n_threads;
item->threads = xzalloc(sizeof(struct pid) * e->n_threads);
if (!item->threads) {
xfree(item);
return -1;
}
for (i = 0; i < item->nr_threads; i++)
item->threads[i].virt = e->threads[i];
return 0;
}
static void pstree_handler(int fd, void *obj, int collect)
{
PstreeEntry *e = obj;
struct pstree_item *item = NULL;
int i;
if (!collect)
return;
......@@ -274,17 +291,11 @@ static void pstree_handler(int fd, void *obj, int collect)
if (!item)
return;
item->pid.virt = e->pid;
item->nr_threads = e->n_threads;
item->threads = xzalloc(sizeof(struct pid) * e->n_threads);
if (!item->threads) {
if (pstree_item_from_pb(e, item)) {
xfree(item);
return;
}
for (i = 0; i < item->nr_threads; i++)
item->threads[i].virt = e->threads[i];
list_add_tail(&item->sibling, &pstree_list);
}
......@@ -428,10 +439,92 @@ err:
return ret;
}
static int cr_show_pstree_item(struct cr_options *opts, struct pstree_item *item)
{
int ret = -1, i;
struct cr_fdset *cr_fdset = NULL;
cr_fdset = cr_task_fdset_open(item->pid.virt, O_SHOW);
if (!cr_fdset)
goto out;
pr_msg("Task %d:\n", item->pid.virt);
pr_msg("----------------------------------------\n");
show_core(fdset_fd(cr_fdset, CR_FD_CORE), opts);
if (item->nr_threads > 1) {
int fd_th;
for (i = 0; i < item->nr_threads; i++) {
if (item->threads[i].virt == item->pid.virt)
continue;
fd_th = open_image_ro(CR_FD_CORE, item->threads[i].virt);
if (fd_th < 0)
goto outc;
pr_msg("Thread %d.%d:\n", item->pid.virt, item->threads[i].virt);
pr_msg("----------------------------------------\n");
show_core(fd_th, opts);
close_safe(&fd_th);
}
}
pr_msg("Resources for %d:\n", item->pid.virt);
pr_msg("----------------------------------------\n");
for (i = _CR_FD_TASK_FROM + 1; i < _CR_FD_TASK_TO; i++)
if (i != CR_FD_CORE && fdset_template[i].show) {
pr_msg("* ");
pr_msg(fdset_template[i].fmt, item->pid.virt);
pr_msg(":\n");
fdset_template[i].show(fdset_fd(cr_fdset, i), opts);
}
pr_msg("---[ end of task %d ]---\n", item->pid.virt);
ret = 0;
outc:
close_cr_fdset(&cr_fdset);
out:
return ret;
}
static int cr_show_pid(struct cr_options *opts, int pid)
{
int fd, ret;
struct pstree_item item;
fd = open_image_ro(CR_FD_PSTREE);
if (fd < 0)
return -1;
while (1) {
PstreeEntry *pe;
ret = pb_read_one_eof(fd, &pe, PB_PSTREE);
if (ret <= 0)
return ret;
if (pe->pid == pid) {
pstree_item_from_pb(pe, &item);
pstree_entry__free_unpacked(pe, NULL);
break;
}
pstree_entry__free_unpacked(pe, NULL);
}
close(fd);
return cr_show_pstree_item(opts, &item);
}
static int cr_show_all(struct cr_options *opts)
{
struct pstree_item *item = NULL, *tmp;
int i, ret = -1, fd, pid;
int ret = -1, fd, pid;
fd = open_image_ro(CR_FD_PSTREE);
if (fd < 0)
......@@ -451,51 +544,9 @@ static int cr_show_all(struct cr_options *opts)
if (ret)
goto out;
list_for_each_entry(item, &pstree_list, sibling) {
struct cr_fdset *cr_fdset = NULL;
cr_fdset = cr_task_fdset_open(item->pid.virt, O_SHOW);
if (!cr_fdset)
goto out;
pr_msg("Task %d:\n", item->pid.virt);
pr_msg("----------------------------------------\n");
show_core(fdset_fd(cr_fdset, CR_FD_CORE), opts);
if (item->nr_threads > 1) {
int fd_th;
for (i = 0; i < item->nr_threads; i++) {
if (item->threads[i].virt == item->pid.virt)
continue;
fd_th = open_image_ro(CR_FD_CORE, item->threads[i].virt);
if (fd_th < 0)
goto out;
pr_msg("Thread %d.%d:\n", item->pid.virt, item->threads[i].virt);
pr_msg("----------------------------------------\n");
show_core(fd_th, opts);
close_safe(&fd_th);
}
}
pr_msg("Resources for %d:\n", item->pid.virt);
pr_msg("----------------------------------------\n");
for (i = _CR_FD_TASK_FROM + 1; i < _CR_FD_TASK_TO; i++)
if (i != CR_FD_CORE && fdset_template[i].show) {
pr_msg("* ");
pr_msg(fdset_template[i].fmt, item->pid.virt);
pr_msg(":\n");
fdset_template[i].show(fdset_fd(cr_fdset, i), opts);
}
pr_msg("---[ end of task %d ]---\n", item->pid.virt);
close_cr_fdset(&cr_fdset);
}
list_for_each_entry(item, &pstree_list, sibling)
if (cr_show_pstree_item(opts, item))
break;
out:
list_for_each_entry_safe(item, tmp, &pstree_list, sibling) {
......@@ -506,10 +557,13 @@ out:
return ret;
}
int cr_show(struct cr_options *opts)
int cr_show(struct cr_options *opts, int pid)
{
if (opts->show_dump_file)
return cr_parse_file(opts);
if (pid)
return cr_show_pid(opts, pid);
return cr_show_all(opts);
}
......@@ -62,13 +62,13 @@ bad_ns:
int main(int argc, char *argv[])
{
pid_t pid = 0;
pid_t pid = 0, tree_id = 0;
int ret = -1;
int opt, idx;
int log_inited = 0;
int log_level = 0;
static const char short_opts[] = "dsf:t:hcD:o:n:vxVr:jl";
static const char short_opts[] = "dsf:t:p:hcD:o:n:vxVr:jl";
BUILD_BUG_ON(PAGE_SIZE != PAGE_IMAGE_SIZE);
......@@ -88,6 +88,7 @@ int main(int argc, char *argv[])
while (1) {
static struct option long_opts[] = {
{ "tree", required_argument, 0, 't' },
{ "pid", required_argument, 0, 'p' },
{ "leave-stopped", no_argument, 0, 's' },
{ "restore-detached", no_argument, 0, 'd' },
{ "contents", no_argument, 0, 'c' },
......@@ -126,9 +127,12 @@ int main(int argc, char *argv[])
case 'x':
opts.ext_unix_sk = true;
break;
case 't':
case 'p':
pid = atoi(optarg);
break;
case 't':
tree_id = atoi(optarg);
break;
case 'c':
opts.show_pages_content = true;
break;
......@@ -292,22 +296,24 @@ int main(int argc, char *argv[])
switch (argv[optind][0]) {
case 'd':
if (!pid)
if (!tree_id)
goto opt_pid_missing;
ret = cr_dump_tasks(pid, &opts);
ret = cr_dump_tasks(tree_id, &opts);
break;
case 'r':
if (!pid)
if (!tree_id)
goto opt_pid_missing;
ret = cr_restore_tasks(pid, &opts);
ret = cr_restore_tasks(tree_id, &opts);
break;
case 's':
ret = cr_show(&opts);
ret = cr_show(&opts, pid);
break;
case 'c':
ret = cr_check();
break;
case 'e':
if (!pid)
pid = tree_id; /* old usage */
if (!pid)
goto opt_pid_missing;
ret = cr_exec(pid, argv + optind + 1);
......@@ -328,7 +334,7 @@ usage:
pr_msg(" %s restore -t pid [<options>]\n", argv[0]);
pr_msg(" %s show (-D dir)|(-f file) [<options>]\n", argv[0]);
pr_msg(" %s check\n", argv[0]);
pr_msg(" %s exec -t pid <syscall-string>\n", argv[0]);
pr_msg(" %s exec -p pid <syscall-string>\n", argv[0]);
pr_msg("\nCommands:\n");
pr_msg(" dump checkpoint a process/tree identified by pid\n");
......@@ -390,6 +396,7 @@ usage:
pr_msg(" -f|--file show contents of a checkpoint file\n");
pr_msg(" -D|--images-dir directory where to get images from\n");
pr_msg(" -c|--contents show contents of pages dumped in hexdump format\n");
pr_msg(" -p|--pid <pid> show files relevant to pid (filter -D flood)\n");
pr_msg("\nOther options:\n");
pr_msg(" -h|--help show this text\n");
......
......@@ -217,7 +217,7 @@ extern struct cr_options opts;
int cr_dump_tasks(pid_t pid, const struct cr_options *opts);
int cr_restore_tasks(pid_t pid, struct cr_options *opts);
int cr_show(struct cr_options *opts);
int cr_show(struct cr_options *opts, int pid);
int convert_to_elf(char *elf_path, int fd_core);
int cr_check(void);
int cr_exec(int pid, char **opts);
......
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