Commit 97a1d8bb authored by Pavel Emelyanov's avatar Pavel Emelyanov

mm: Dump vmas into separate image file

The core image now contains only core per-task stuff.
The new file resurrects Tula magic number removed earlier.
Acked-by: 's avatarAndrey Vagin <avagin@parallels.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 309b2c18
...@@ -490,16 +490,19 @@ static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list, ...@@ -490,16 +490,19 @@ static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list,
const struct cr_fdset *cr_fdset) const struct cr_fdset *cr_fdset)
{ {
struct vma_area *vma_area; struct vma_area *vma_area;
int ret = -1; int ret = -1, fd = cr_fdset->fds[CR_FD_VMAS];
pr_info("\n"); pr_info("\n");
pr_info("Dumping mappings (pid: %d)\n", pid); pr_info("Dumping mappings (pid: %d)\n", pid);
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
list_for_each_entry(vma_area, vma_area_list, list) { list_for_each_entry(vma_area, vma_area_list, list) {
struct vma_entry *vma = &vma_area->vma; struct vma_entry *vma = &vma_area->vma;
ret = write_img(fd, vma);
if (ret < 0)
goto err;
if (!vma_entry_is(vma, VMA_AREA_REGULAR)) if (!vma_entry_is(vma, VMA_AREA_REGULAR))
continue; continue;
if (vma_entry_is(vma, VMA_AREA_SYSVIPC)) if (vma_entry_is(vma, VMA_AREA_SYSVIPC))
...@@ -512,15 +515,15 @@ static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list, ...@@ -512,15 +515,15 @@ static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list,
else if (vma_entry_is(vma, VMA_FILE_PRIVATE) || else if (vma_entry_is(vma, VMA_FILE_PRIVATE) ||
vma_entry_is(vma, VMA_FILE_SHARED)) vma_entry_is(vma, VMA_FILE_SHARED))
ret = dump_filemap(pid, vma, vma_area->vm_file_fd, cr_fdset); ret = dump_filemap(pid, vma, vma_area->vm_file_fd, cr_fdset);
else
ret = 0;
if (ret) if (ret)
goto err; goto err;
} }
ret = 0; ret = 0;
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
err: err:
return ret; return ret;
} }
...@@ -1185,53 +1188,6 @@ static struct vma_area *find_vma_by_addr(const struct list_head *vma_area_list, ...@@ -1185,53 +1188,6 @@ static struct vma_area *find_vma_by_addr(const struct list_head *vma_area_list,
return NULL; return NULL;
} }
/* kernel expects a special format in core file */
static int finalize_core(pid_t pid, const struct list_head *vma_area_list,
const struct cr_fdset *cr_fdset)
{
int fd_core;
unsigned long num;
struct vma_area *vma_area;
struct vma_entry ve;
ssize_t bytes;
pr_info("\n");
pr_info("Finalizing core (pid: %d)\n", pid);
pr_info("----------------------------------------\n");
fd_core = cr_fdset->fds[CR_FD_CORE];
lseek(fd_core, GET_FILE_OFF_AFTER(struct core_entry), SEEK_SET);
num = 0;
pr_info("Appending VMAs ... ");
/* All VMAs first */
list_for_each_entry(vma_area, vma_area_list, list) {
bytes = write(fd_core, &vma_area->vma, sizeof(vma_area->vma));
if (bytes != sizeof(vma_area->vma)) {
pr_perror("\nUnable to write vma entry (%li written)", num);
goto err;
}
num++;
}
/* Ending marker */
memzero_p(&ve);
if (write_img(fd_core, &ve))
goto err;
pr_info("OK (%li written)\n", num);
pr_info("----------------------------------------\n");
return 0;
err:
pr_perror("Error catched");
return -1;
}
static int dump_task_thread(struct parasite_ctl *parasite_ctl, static int dump_task_thread(struct parasite_ctl *parasite_ctl,
pid_t pid, const struct cr_fdset *cr_fdset) pid_t pid, const struct cr_fdset *cr_fdset)
{ {
...@@ -1281,7 +1237,6 @@ static int dump_one_zombie(const struct pstree_item *item, ...@@ -1281,7 +1237,6 @@ static int dump_one_zombie(const struct pstree_item *item,
{ {
struct core_entry *core; struct core_entry *core;
int ret; int ret;
LIST_HEAD(vma_area_list);
cr_fdset = cr_dump_fdset_open(item->pid, CR_FD_DESC_CORE, cr_fdset); cr_fdset = cr_dump_fdset_open(item->pid, CR_FD_DESC_CORE, cr_fdset);
if (cr_fdset == NULL) if (cr_fdset == NULL)
...@@ -1294,10 +1249,7 @@ static int dump_one_zombie(const struct pstree_item *item, ...@@ -1294,10 +1249,7 @@ static int dump_one_zombie(const struct pstree_item *item,
core->tc.task_state = TASK_DEAD; core->tc.task_state = TASK_DEAD;
core->tc.exit_code = pps->exit_code; core->tc.exit_code = pps->exit_code;
if (dump_task_core(core, cr_fdset) < 0) return dump_task_core(core, cr_fdset);
return -1;
return finalize_core(item->pid, &vma_area_list, cr_fdset);
} }
static struct proc_pid_stat pps_buf; static struct proc_pid_stat pps_buf;
...@@ -1442,12 +1394,6 @@ static int dump_one_task(const struct pstree_item *item, struct cr_fdset *cr_fds ...@@ -1442,12 +1394,6 @@ static int dump_one_task(const struct pstree_item *item, struct cr_fdset *cr_fds
goto err; goto err;
} }
ret = finalize_core(pid, &vma_area_list, cr_fdset);
if (ret) {
pr_err("Finalizing core (pid: %d) failed with %d\n", pid, ret);
goto err;
}
free_mappings(&vma_area_list); free_mappings(&vma_area_list);
err: err:
......
...@@ -226,24 +226,21 @@ static int prepare_shmem_pid(int pid) ...@@ -226,24 +226,21 @@ static int prepare_shmem_pid(int pid)
struct task_core_entry tc; struct task_core_entry tc;
struct image_header hdr; struct image_header hdr;
fd = open_image_ro(CR_FD_CORE, pid); fd = open_image_ro(CR_FD_VMAS, pid);
if (fd < 0) if (fd < 0) {
return -1; if (errno == ENOENT)
return 0;
lseek(fd, GET_FILE_OFF_AFTER(struct core_entry), SEEK_SET); else
return -1;
}
while (1) { while (1) {
ret = read_img(fd, &vi); ret = read_img_eof(fd, &vi);
if (ret < 0) { if (ret <= 0)
pr_perror("%d: Can't read vma_entry", pid); break;
goto out;
}
pr_info("%d: vma %lx %lx\n", pid, vi.start, vi.end); pr_info("%d: vma %lx %lx\n", pid, vi.start, vi.end);
if (final_vma_entry(&vi))
break;
if (!vma_entry_is(&vi, VMA_ANON_SHARED)) if (!vma_entry_is(&vi, VMA_ANON_SHARED))
continue; continue;
...@@ -565,26 +562,25 @@ write_fd: ...@@ -565,26 +562,25 @@ write_fd:
static int fixup_vma_fds(int pid, int fd) static int fixup_vma_fds(int pid, int fd)
{ {
int offset = GET_FILE_OFF_AFTER(struct core_entry);
lseek(fd, offset, SEEK_SET);
while (1) { while (1) {
struct vma_entry vi; struct vma_entry vi;
int ret = 0; int ret = 0;
ret = read(fd, &vi, sizeof(vi)); ret = read(fd, &vi, sizeof(vi));
if (ret == 0)
return 0;
if (ret < 0) { if (ret < 0) {
pr_perror("%d: Can't read vma_entry", pid); pr_perror("%d: Can't read vma_entry", pid);
} else if (ret != sizeof(vi)) { return -1;
}
if (ret != sizeof(vi)) {
pr_err("%d: Incomplete vma_entry (%d != %ld)\n", pr_err("%d: Incomplete vma_entry (%d != %ld)\n",
pid, ret, sizeof(vi)); pid, ret, sizeof(vi));
return -1; return -1;
} }
if (final_vma_entry(&vi))
return 0;
if (!(vma_entry_is(&vi, VMA_AREA_REGULAR))) if (!(vma_entry_is(&vi, VMA_AREA_REGULAR)))
continue; continue;
...@@ -626,7 +622,7 @@ static int prepare_and_sigreturn(int pid) ...@@ -626,7 +622,7 @@ static int prepare_and_sigreturn(int pid)
int fd = -1, err = -1; int fd = -1, err = -1;
struct stat buf; struct stat buf;
fd = open_image(CR_FD_CORE, O_RDWR, pid); fd = open_image(CR_FD_VMAS, O_RDWR, pid);
if (fd < 0) if (fd < 0)
return -1; return -1;
...@@ -1377,13 +1373,12 @@ static long restorer_get_vma_hint(pid_t pid, struct list_head *self_vma_list, lo ...@@ -1377,13 +1373,12 @@ static long restorer_get_vma_hint(pid_t pid, struct list_head *self_vma_list, lo
* better to stick with it. * better to stick with it.
*/ */
fd = open_image_ro_nocheck(FMT_FNAME_CORE, pid); fd = open_image_ro_nocheck(FMT_FNAME_VMAS, pid);
if (fd < 0) if (fd < 0)
return -1; return -1;
prev_vma_end = 0; prev_vma_end = 0;
lseek(fd, MAGIC_OFFSET, SEEK_SET);
lseek(fd, GET_FILE_OFF_AFTER(struct core_entry), SEEK_SET);
while (1) { while (1) {
ret = read(fd, &vma, sizeof(vma)); ret = read(fd, &vma, sizeof(vma));
...@@ -1533,6 +1528,7 @@ static void sigreturn_restore(pid_t pid) ...@@ -1533,6 +1528,7 @@ static void sigreturn_restore(pid_t pid)
int fd_fdinfo = -1; int fd_fdinfo = -1;
int fd_core = -1; int fd_core = -1;
int fd_pages = -1; int fd_pages = -1;
int fd_vmas = -1;
int i; int i;
int *fd_core_threads; int *fd_core_threads;
...@@ -1575,6 +1571,12 @@ static void sigreturn_restore(pid_t pid) ...@@ -1575,6 +1571,12 @@ static void sigreturn_restore(pid_t pid)
goto err; goto err;
} }
fd_vmas = open_image_ro(CR_FD_VMAS, pid);
if (fd_vmas < 0) {
pr_perror("Can't open vmas-%d", pid);
goto err;
}
restore_code_len = sizeof(restorer_blob); restore_code_len = sizeof(restorer_blob);
restore_code_len = round_up(restore_code_len, 16); restore_code_len = round_up(restore_code_len, 16);
...@@ -1692,6 +1694,7 @@ static void sigreturn_restore(pid_t pid) ...@@ -1692,6 +1694,7 @@ static void sigreturn_restore(pid_t pid)
*/ */
task_args->pid = pid; task_args->pid = pid;
task_args->fd_core = fd_core; task_args->fd_core = fd_core;
task_args->fd_vmas = fd_vmas;
task_args->logfd = log_get_fd(); task_args->logfd = log_get_fd();
task_args->sigchld_act = sigchld_act; task_args->sigchld_act = sigchld_act;
task_args->fd_fdinfo = fd_fdinfo; task_args->fd_fdinfo = fd_fdinfo;
......
...@@ -111,23 +111,26 @@ out: ...@@ -111,23 +111,26 @@ out:
pr_img_tail(CR_FD_PIPES); pr_img_tail(CR_FD_PIPES);
} }
static void show_vma(int fd_vma) static void show_vmas(int fd_vma)
{ {
struct vma_area vma_area = {}; struct vma_area vma_area = {};
struct vma_entry ve; struct vma_entry ve;
pr_msg("\n\t---[VMA areas]---\n"); pr_img_head(CR_FD_VMAS);
while (1) { while (1) {
if (read_img(fd_vma, &ve) < 0) int ret;
break;
if (final_vma_entry(&ve)) ret = read_img_eof(fd_vma, &ve);
if (ret <= 0)
break; break;
/* Simply in a sake of fancy printing */ /* Simply in a sake of fancy printing */
vma_area.vma = ve; vma_area.vma = ve;
pr_msg_vma(&vma_area); pr_msg_vma(&vma_area);
} }
pr_img_tail(CR_FD_VMAS);
} }
void print_data(unsigned long addr, unsigned char *data, size_t size) void print_data(unsigned long addr, unsigned char *data, size_t size)
...@@ -431,18 +434,6 @@ static void show_core(int fd_core, bool show_content) ...@@ -431,18 +434,6 @@ static void show_core(int fd_core, bool show_content)
show_core_regs(fd_core); show_core_regs(fd_core);
show_core_rest(fd_core); show_core_rest(fd_core);
if (is_thread)
goto out;
lseek(fd_core, GET_FILE_OFF_AFTER(struct core_entry), SEEK_SET);
/*
* If this is thread code -- we should jump out once
* we reach EOF.
*/
if (is_thread)
goto out;
show_vma(fd_core);
out: out:
pr_img_tail(CR_FD_CORE); pr_img_tail(CR_FD_CORE);
} }
...@@ -472,6 +463,9 @@ static int cr_parse_file(struct cr_options *opts) ...@@ -472,6 +463,9 @@ static int cr_parse_file(struct cr_options *opts)
case CORE_MAGIC: case CORE_MAGIC:
show_core(fd, opts->show_pages_content); show_core(fd, opts->show_pages_content);
break; break;
case VMAS_MAGIC:
show_vmas(fd);
break;
case PSTREE_MAGIC: case PSTREE_MAGIC:
show_pstree(fd, NULL); show_pstree(fd, NULL);
break; break;
...@@ -580,6 +574,8 @@ static int cr_show_all(unsigned long pid, struct cr_options *opts) ...@@ -580,6 +574,8 @@ static int cr_show_all(unsigned long pid, struct cr_options *opts)
} }
} }
show_vmas(cr_fdset->fds[CR_FD_VMAS]);
show_pipes(cr_fdset->fds[CR_FD_PIPES]); show_pipes(cr_fdset->fds[CR_FD_PIPES]);
show_files(cr_fdset->fds[CR_FD_FDINFO]); show_files(cr_fdset->fds[CR_FD_FDINFO]);
......
...@@ -57,6 +57,11 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = { ...@@ -57,6 +57,11 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
.magic = CORE_MAGIC, .magic = CORE_MAGIC,
}, },
[CR_FD_VMAS] = {
.fmt = FMT_FNAME_VMAS,
.magic = VMAS_MAGIC,
},
/* info about pipes - fds, pipe id and pipe data */ /* info about pipes - fds, pipe id and pipe data */
[CR_FD_PIPES] = { [CR_FD_PIPES] = {
.fmt = FMT_FNAME_PIPES, .fmt = FMT_FNAME_PIPES,
......
...@@ -22,6 +22,7 @@ enum { ...@@ -22,6 +22,7 @@ enum {
CR_FD_FDINFO, CR_FD_FDINFO,
CR_FD_PAGES, CR_FD_PAGES,
CR_FD_CORE, CR_FD_CORE,
CR_FD_VMAS,
CR_FD_PIPES, CR_FD_PIPES,
CR_FD_SIGACT, CR_FD_SIGACT,
CR_FD_UNIXSK, CR_FD_UNIXSK,
...@@ -77,6 +78,7 @@ extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX]; ...@@ -77,6 +78,7 @@ extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX];
#define FMT_FNAME_PAGES "pages-%d.img" #define FMT_FNAME_PAGES "pages-%d.img"
#define FMT_FNAME_SHMEM_PAGES "pages-shmem-%ld.img" #define FMT_FNAME_SHMEM_PAGES "pages-shmem-%ld.img"
#define FMT_FNAME_CORE "core-%d.img" #define FMT_FNAME_CORE "core-%d.img"
#define FMT_FNAME_VMAS "vmas-%d.img"
#define FMT_FNAME_PIPES "pipes-%d.img" #define FMT_FNAME_PIPES "pipes-%d.img"
#define FMT_FNAME_PSTREE "pstree-%d.img" #define FMT_FNAME_PSTREE "pstree-%d.img"
#define FMT_FNAME_SIGACTS "sigacts-%d.img" #define FMT_FNAME_SIGACTS "sigacts-%d.img"
...@@ -118,6 +120,7 @@ struct cr_fdset { ...@@ -118,6 +120,7 @@ struct cr_fdset {
CR_FD_DESC_USE(CR_FD_FDINFO) |\ CR_FD_DESC_USE(CR_FD_FDINFO) |\
CR_FD_DESC_USE(CR_FD_PAGES) |\ CR_FD_DESC_USE(CR_FD_PAGES) |\
CR_FD_DESC_USE(CR_FD_CORE) |\ CR_FD_DESC_USE(CR_FD_CORE) |\
CR_FD_DESC_USE(CR_FD_VMAS) |\
CR_FD_DESC_USE(CR_FD_PIPES) |\ CR_FD_DESC_USE(CR_FD_PIPES) |\
CR_FD_DESC_USE(CR_FD_SIGACT) |\ CR_FD_DESC_USE(CR_FD_SIGACT) |\
CR_FD_DESC_USE(CR_FD_UNIXSK) |\ CR_FD_DESC_USE(CR_FD_UNIXSK) |\
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#define FDINFO_MAGIC 0x56213732 /* Dmitrov */ #define FDINFO_MAGIC 0x56213732 /* Dmitrov */
#define PAGES_MAGIC 0x56084025 /* Vladimir */ #define PAGES_MAGIC 0x56084025 /* Vladimir */
#define CORE_MAGIC 0x55053847 /* Kolomna */ #define CORE_MAGIC 0x55053847 /* Kolomna */
#define VMAS_MAGIC 0x54123737 /* Tula */
#define PIPES_MAGIC 0x56513555 /* Tver */ #define PIPES_MAGIC 0x56513555 /* Tver */
#define SIGACT_MAGIC 0x55344201 /* Murom */ #define SIGACT_MAGIC 0x55344201 /* Murom */
#define UNIXSK_MAGIC 0x54373943 /* Ryazan */ #define UNIXSK_MAGIC 0x54373943 /* Ryazan */
...@@ -180,7 +181,6 @@ struct ipc_sem_entry { ...@@ -180,7 +181,6 @@ struct ipc_sem_entry {
#define vma_entry_is(vma, s) (((vma)->status & (s)) == (s)) #define vma_entry_is(vma, s) (((vma)->status & (s)) == (s))
#define vma_entry_len(vma) ((vma)->end - (vma)->start) #define vma_entry_len(vma) ((vma)->end - (vma)->start)
#define final_vma_entry(vma) ((vma)->start == 0 && (vma)->end == 0)
struct page_entry { struct page_entry {
u64 va; u64 va;
......
...@@ -65,6 +65,7 @@ struct task_restore_core_args { ...@@ -65,6 +65,7 @@ struct task_restore_core_args {
int pid; /* task pid */ int pid; /* task pid */
int fd_core; /* opened core file */ int fd_core; /* opened core file */
int fd_vmas; /* opened vmas file */
int fd_fdinfo; /* opened files dump file */ int fd_fdinfo; /* opened files dump file */
int fd_pages; /* opened pages dump file */ int fd_pages; /* opened pages dump file */
int logfd; int logfd;
......
...@@ -398,9 +398,8 @@ long restore_task(struct task_restore_core_args *args) ...@@ -398,9 +398,8 @@ long restore_task(struct task_restore_core_args *args)
* OK, lets try to map new one. * OK, lets try to map new one.
*/ */
vma_entry = next_on_heap(vma_entry, core_entry); vma_entry = next_on_heap(vma_entry, core_entry);
sys_lseek(args->fd_core, GET_FILE_OFF_AFTER(struct core_entry), SEEK_SET);
while (1) { while (1) {
ret = sys_read(args->fd_core, vma_entry, sizeof(*vma_entry)); ret = sys_read(args->fd_vmas, vma_entry, sizeof(*vma_entry));
if (!ret) if (!ret)
break; break;
if (ret != sizeof(*vma_entry)) { if (ret != sizeof(*vma_entry)) {
...@@ -409,9 +408,6 @@ long restore_task(struct task_restore_core_args *args) ...@@ -409,9 +408,6 @@ long restore_task(struct task_restore_core_args *args)
goto core_restore_end; goto core_restore_end;
} }
if (final_vma_entry(vma_entry))
break;
if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
continue; continue;
...@@ -459,9 +455,9 @@ long restore_task(struct task_restore_core_args *args) ...@@ -459,9 +455,9 @@ long restore_task(struct task_restore_core_args *args)
* Walk though all VMAs again to drop PROT_WRITE * Walk though all VMAs again to drop PROT_WRITE
* if it was not there. * if it was not there.
*/ */
sys_lseek(args->fd_core, GET_FILE_OFF_AFTER(struct core_entry), SEEK_SET); sys_lseek(args->fd_vmas, MAGIC_OFFSET, SEEK_SET);
while (1) { while (1) {
ret = sys_read(args->fd_core, vma_entry, sizeof(*vma_entry)); ret = sys_read(args->fd_vmas, vma_entry, sizeof(*vma_entry));
if (!ret) if (!ret)
break; break;
if (ret != sizeof(*vma_entry)) { if (ret != sizeof(*vma_entry)) {
...@@ -470,9 +466,6 @@ long restore_task(struct task_restore_core_args *args) ...@@ -470,9 +466,6 @@ long restore_task(struct task_restore_core_args *args)
goto core_restore_end; goto core_restore_end;
} }
if (final_vma_entry(vma_entry))
break;
if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR))) if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR)))
continue; continue;
...@@ -494,6 +487,7 @@ long restore_task(struct task_restore_core_args *args) ...@@ -494,6 +487,7 @@ long restore_task(struct task_restore_core_args *args)
vma_entry->prot); vma_entry->prot);
} }
sys_close(args->fd_vmas);
sys_close(args->fd_core); sys_close(args->fd_core);
ret = sys_munmap(args->shmems, SHMEMS_SIZE); ret = sys_munmap(args->shmems, SHMEMS_SIZE);
......
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