Commit e869c16d authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

mm: rework of dumping shared memory

vma_entry contains shmid and all shared memory are dumped in own files.
The most interesting thing is restore.
A maping is restored by process with the smallest pid. The mamping
is created before executing restorer.
We map a full mapping and restore it's conten, then we open a file from
/proc/pid/map_files and store a descriptor in vma_info. The mapping is
unmaped. Now we can map any region of this mapping in the restorer.

We use this trick, because a target process may have this mapping in
some places and the restorer has not function to open proc files.

v2: fix error hangling
xemul: Fixed static-s and args for cr_dump_shmem
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 31feef8a
...@@ -415,6 +415,31 @@ static int dump_task_files(pid_t pid, const struct cr_fdset *cr_fdset, ...@@ -415,6 +415,31 @@ static int dump_task_files(pid_t pid, const struct cr_fdset *cr_fdset,
return 0; return 0;
} }
struct shmem_info
{
unsigned long size;
unsigned long shmid;
unsigned long start;
unsigned long end;
int pid;
};
static int nr_shmems;
static struct shmem_info *shmems;
#define SHMEMS_SIZE 4096
static struct shmem_info* shmem_find(unsigned long shmid)
{
int i;
for (i = 0; i < nr_shmems; i++)
if (shmems[i].shmid == shmid)
return &shmems[i];
return NULL;
}
static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list, 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)
{ {
...@@ -431,21 +456,35 @@ static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list, ...@@ -431,21 +456,35 @@ static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list,
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))
continue;
pr_info_vma(vma_area); pr_info_vma(vma_area);
if (vma_entry_is(vma, VMA_ANON_SHARED)) { if (vma_entry_is(vma, VMA_ANON_SHARED)) {
struct shmem_entry e; struct shmem_info *si;
unsigned long size = vma->pgoff + (vma->end - vma->start);
si = shmem_find(vma_area->vma.shmid);
if (si) {
if (si->size < size)
si->size = size;
continue;
}
e.start = vma->start; nr_shmems++;
e.end = vma->end; if (nr_shmems * sizeof(*si) == SHMEMS_SIZE) {
e.shmid = vma_area->vma.shmid; pr_err("OOM storing shmems\n");
return -1;
}
pr_info("shmem: s: %16lx e: %16lx shmid: %16lx\n", si = &shmems[nr_shmems - 1];
e.start, e.end, e.shmid); si->size = size;
si->pid = pid;
si->start = vma->start;
si->end = vma->end;
si->shmid = vma_area->vma.shmid;
if (write_img(cr_fdset->fds[CR_FD_SHMEM], &e))
goto err;
} 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)) {
struct fd_parms p = { struct fd_parms p = {
...@@ -1230,6 +1269,8 @@ static int dump_one_zombie(const struct pstree_item *item, ...@@ -1230,6 +1269,8 @@ static int dump_one_zombie(const struct pstree_item *item,
struct cr_fdset *cr_fdset) struct cr_fdset *cr_fdset)
{ {
struct core_entry *core; struct core_entry *core;
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)
...@@ -1242,7 +1283,10 @@ static int dump_one_zombie(const struct pstree_item *item, ...@@ -1242,7 +1283,10 @@ 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;
return dump_task_core(core, cr_fdset); if (dump_task_core(core, cr_fdset) < 0)
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;
...@@ -1402,6 +1446,78 @@ err_free: ...@@ -1402,6 +1446,78 @@ err_free:
return ret; return ret;
} }
static int cr_dump_shmem(void)
{
int err, fd;
struct cr_fdset *cr_fdset = NULL;
unsigned char *map = NULL;
void *addr = NULL;
struct shmem_info *si;
unsigned long pfn, nrpages;
for (si = shmems; si < &shmems[nr_shmems]; si++) {
pr_info("Dumping shared memory %lx\n", si->shmid);
nrpages = (si->size + PAGE_SIZE -1) / PAGE_SIZE;
map = xmalloc(nrpages * sizeof(*map));
if (!map)
goto err;
fd = open_proc(si->pid, "map_files/%lx-%lx", si->start, si->end);
if (fd < 0)
goto err;
addr = mmap(NULL, si->size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
if (addr == MAP_FAILED) {
pr_err("Can't map shmem %lx (%lx-%lx)\n",
si->shmid, si->start, si->end);
goto err;
}
err = mincore(addr, si->size, map);
if (err)
goto err_unmap;
fd = open_image(CR_FD_SHMEM_PAGES, O_WRONLY | O_CREAT, si->shmid);
if (fd < 0)
goto err_unmap;
for (pfn = 0; pfn < nrpages; pfn++) {
u64 offset = pfn * PAGE_SIZE;
if (!(map[pfn] & PAGE_RSS))
continue;
if (write_img_buf(fd, &offset, sizeof(offset)))
break;
if (write_img_buf(fd, addr + offset, PAGE_SIZE))
break;
}
if (pfn != nrpages)
goto err_close;
err = write_img(fd, &zero_page_entry);
if (err < 0)
goto err_close;
close(fd);
munmap(addr, si->size);
xfree(map);
}
return 0;
err_close:
close(fd);
err_unmap:
munmap(addr, si->size);
err:
xfree(map);
return -1;
}
int cr_dump_tasks(pid_t pid, const struct cr_options *opts) int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
{ {
LIST_HEAD(pstree_list); LIST_HEAD(pstree_list);
...@@ -1440,6 +1556,11 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts) ...@@ -1440,6 +1556,11 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
goto err; goto err;
close_cr_fdset(&cr_fdset); close_cr_fdset(&cr_fdset);
nr_shmems = 0;
shmems = xmalloc(SHMEMS_SIZE);
if (!shmems)
goto err;
list_for_each_entry(item, &pstree_list, list) { list_for_each_entry(item, &pstree_list, list) {
cr_fdset = cr_dump_fdset_open(item->pid, CR_FD_DESC_NONE, NULL); cr_fdset = cr_dump_fdset_open(item->pid, CR_FD_DESC_NONE, NULL);
if (!cr_fdset) if (!cr_fdset)
...@@ -1463,8 +1584,9 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts) ...@@ -1463,8 +1584,9 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
if (opts->leader_only) if (opts->leader_only)
break; break;
} }
ret = 0;
ret = cr_dump_shmem();
xfree(shmems);
err: err:
pstree_switch_state(&pstree_list, opts); pstree_switch_state(&pstree_list, opts);
free_pstree(&pstree_list); free_pstree(&pstree_list);
......
...@@ -165,21 +165,19 @@ static int shmem_wait_and_open(int pid, struct shmem_info *si) ...@@ -165,21 +165,19 @@ static int shmem_wait_and_open(int pid, struct shmem_info *si)
return ret; return ret;
} }
static int collect_shmem(int pid, struct shmem_entry *e) static int collect_shmem(int pid, struct vma_entry *vi)
{ {
int i; int i;
struct shmem_info *entries = shmems->entries; struct shmem_info *entries = shmems->entries;
int nr_shmems = shmems->nr_shmems; int nr_shmems = shmems->nr_shmems;
unsigned long size = vi->pgoff + vi->end - vi->start;
struct shmem_info *si;
for (i = 0; i < nr_shmems; i++) { si = find_shmem(shmems, vi->shmid);
if (entries[i].start != e->start || if (si) {
entries[i].shmid != e->shmid)
continue;
if (entries[i].end != e->end) { if (si->size < size)
pr_err("Bogus shmem\n"); si->size = size;
return -1;
}
/* /*
* Only the shared mapping with a lowest * Only the shared mapping with a lowest
...@@ -187,8 +185,12 @@ static int collect_shmem(int pid, struct shmem_entry *e) ...@@ -187,8 +185,12 @@ static int collect_shmem(int pid, struct shmem_entry *e)
* will wait until the kernel propagate this mapping * will wait until the kernel propagate this mapping
* into /proc * into /proc
*/ */
if (entries[i].pid > pid) if (si->pid <= pid)
entries[i].pid = pid; return 0;
si->pid = pid;
si->start = vi->start;
si->end = vi->end;
return 0; return 0;
} }
...@@ -199,20 +201,66 @@ static int collect_shmem(int pid, struct shmem_entry *e) ...@@ -199,20 +201,66 @@ static int collect_shmem(int pid, struct shmem_entry *e)
return -1; return -1;
} }
memset(&shmems->entries[nr_shmems], 0, sizeof(shmems->entries[0])); pr_info("Add new shmem %lx (0x016%lx-0x016%lx)",
vi->shmid, vi->start, vi->end);
entries[nr_shmems].start = e->start; si = &shmems->entries[nr_shmems];
entries[nr_shmems].end = e->end; shmems->nr_shmems++;
entries[nr_shmems].shmid = e->shmid;
entries[nr_shmems].pid = pid;
cr_wait_init(&entries[nr_shmems].lock); si->start = vi->start;
si->end = vi->end;
si->shmid = vi->shmid;
si->pid = pid;
si->size = size;
si->fd = -1;
shmems->nr_shmems++; cr_wait_init(&si->lock);
return 0; return 0;
} }
static int prepare_shmem_pid(int pid)
{
int fd, ret = -1;
struct vma_entry vi;
struct task_core_entry tc;
struct image_header hdr;
fd = open_image_ro(CR_FD_CORE, pid);
if (fd < 0)
return -1;
lseek(fd, GET_FILE_OFF_AFTER(struct core_entry), SEEK_SET);
while (1) {
ret = read_img(fd, &vi);
if (ret < 0) {
pr_perror("%d: Can't read vma_entry", pid);
goto out;
}
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))
continue;
if (vma_entry_is(&vi, VMA_AREA_SYSVIPC))
continue;
ret = collect_shmem(pid, &vi);
if (ret)
break;
}
out:
close(fd);
return ret;
}
static int collect_pipe(int pid, struct pipe_entry *e, int p_fd) static int collect_pipe(int pid, struct pipe_entry *e, int p_fd)
{ {
int i; int i;
...@@ -281,34 +329,6 @@ static int collect_pipe(int pid, struct pipe_entry *e, int p_fd) ...@@ -281,34 +329,6 @@ static int collect_pipe(int pid, struct pipe_entry *e, int p_fd)
return 0; return 0;
} }
static int prepare_shmem_pid(int pid)
{
int sh_fd, ret = 0;
sh_fd = open_image_ro(CR_FD_SHMEM, pid);
if (sh_fd < 0) {
if (errno == ENOENT)
return 0;
else
return -1;
}
while (1) {
struct shmem_entry e;
ret = read_img_eof(sh_fd, &e);
if (ret <= 0)
break;
ret = collect_shmem(pid, &e);
if (ret)
break;
}
close(sh_fd);
return ret;
}
static int prepare_pipes_pid(int pid) static int prepare_pipes_pid(int pid)
{ {
int p_fd, ret = 0; int p_fd, ret = 0;
...@@ -428,90 +448,35 @@ static int prepare_shared(int ps_fd) ...@@ -428,90 +448,35 @@ static int prepare_shared(int ps_fd)
return ret; return ret;
} }
static struct shmem_id *find_shmem_id(unsigned long addr) static int restore_shmem_content(void *addr, struct shmem_info *si)
{
struct shmem_id *si;
for (si = shmem_ids; si; si = si->next)
if (si->addr <= addr && si->end >= addr)
return si;
return NULL;
}
static int save_shmem_id(struct shmem_entry *e)
{
struct shmem_id *si;
si = xmalloc(sizeof(*si));
if (!si)
return -1;
si->addr = e->start;
si->end = e->end;
si->shmid = e->shmid;
si->next = shmem_ids;
shmem_ids = si;
return 0;
}
static int prepare_shmem(int pid)
{ {
int sh_fd, ret = 0; u64 offset;
int fd, ret = 0;
sh_fd = open_image_ro(CR_FD_SHMEM, pid); fd = open_image_ro(CR_FD_SHMEM_PAGES, si->shmid);
if (sh_fd < 0) if (fd < 0) {
munmap(addr, si->size);
return -1; return -1;
}
while (1) { while (1) {
struct shmem_entry e; ret = read_img_buf(fd, &offset, sizeof(offset));
if (ret < 0)
ret = read_img_eof(sh_fd, &e);
if (ret <= 0)
break; break;
if ((ret = save_shmem_id(&e)) < 0) if (final_page_va(offset))
break; break;
}
close(sh_fd);
return ret;
}
static struct shmem_info *
find_shmem(struct shmems *shms, unsigned long start, unsigned long shmid)
{
struct shmem_info *si;
int i;
for (i = 0; i < shms->nr_shmems; i++) { if (offset + PAGE_SIZE > si->size)
si = &shms->entries[i]; break;
if (si->start == start &&
si->end > start &&
si->shmid == shmid)
return si;
}
return NULL;
}
static struct shmem_info *
find_shmem_page(struct shmems *shms, unsigned long addr, unsigned long shmid)
{
struct shmem_info *si;
int i;
for (i = 0; i < shms->nr_shmems; i++) { ret = read_img_buf(fd, addr + offset, PAGE_SIZE);
si = &shms->entries[i]; if (ret < 0)
if (si->start <= addr && break;
si->end > addr &&
si->shmid == shmid)
return si;
} }
return NULL; close(fd);
return ret;
} }
static int try_fixup_shared_map(int pid, struct vma_entry *vi, int fd) static int try_fixup_shared_map(int pid, struct vma_entry *vi, int fd)
...@@ -520,28 +485,23 @@ static int try_fixup_shared_map(int pid, struct vma_entry *vi, int fd) ...@@ -520,28 +485,23 @@ static int try_fixup_shared_map(int pid, struct vma_entry *vi, int fd)
struct shmem_id *shmid; struct shmem_id *shmid;
int sh_fd; int sh_fd;
shmid = find_shmem_id(vi->start);
if (!shmid)
return 0;
si = find_shmem(shmems, vi->start, shmid->shmid);
pr_info("%d: Search for %016lx shmem %p/%d\n", pid, vi->start, si, si ? si->pid : -1);
if (!si) {
pr_err("Can't find my shmem %016lx\n", vi->start);
return -1;
}
if (vma_entry_is(vi, VMA_AREA_SYSVIPC)) { if (vma_entry_is(vi, VMA_AREA_SYSVIPC)) {
/* /*
* SYSV IPC shared memory region was created already. We don't * SYSV IPC shared memory region was created already. We don't
* need to wait. But we have to pass shmid to restorer. Let's * need to wait. But we have to pass shmid to restorer. Let's
* use vma_entry->fd for it. * use vma_entry->fd for it.
*/ */
sh_fd = si->shmid; vi->fd = vi->shmid;
goto write_fd; goto write_fd;
} }
si = find_shmem(shmems, vi->shmid);
pr_info("%d: Search for %016lx shmem %lx %p/%d\n", pid, vi->start, vi->shmid, si, si ? si->pid : -1);
if (!si) {
pr_err("Can't find my shmem %016lx\n", vi->start);
return -1;
}
if (si->pid != pid) { if (si->pid != pid) {
sh_fd = shmem_wait_and_open(pid, si); sh_fd = shmem_wait_and_open(pid, si);
pr_info("%d: Fixing %lx vma to %lx/%d shmem -> %d\n", pr_info("%d: Fixing %lx vma to %lx/%d shmem -> %d\n",
...@@ -550,15 +510,54 @@ static int try_fixup_shared_map(int pid, struct vma_entry *vi, int fd) ...@@ -550,15 +510,54 @@ static int try_fixup_shared_map(int pid, struct vma_entry *vi, int fd)
pr_perror("%d: Can't open shmem", pid); pr_perror("%d: Can't open shmem", pid);
return -1; return -1;
} }
write_fd:
lseek(fd, -sizeof(*vi), SEEK_CUR);
vi->fd = sh_fd;
pr_info("%d: Fixed %lx vma %lx/%d shmem -> %d\n", pr_info("%d: Fixed %lx vma %lx/%d shmem -> %d\n",
pid, vi->start, si->shmid, si->pid, sh_fd); pid, vi->start, si->shmid, si->pid, sh_fd);
if (write(fd, vi, sizeof(*vi)) != sizeof(*vi)) { vi->fd = sh_fd;
pr_perror("%d: Can't write img", pid); } else {
return -1; void *addr;
} int f;
char path[128];
if (si->start == vi->start) {
/* The following hack solves problems:
* vi->pgoff may be not zero in a target process.
* This mapping may be mapped more then once.
* The restorer doesn't have snprintf.
* Here is a good place to restore content
*/
addr = mmap(NULL, si->size,
PROT_WRITE | PROT_READ,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (addr == MAP_FAILED) {
pr_err("Can't mmap shmid=0x%lx size=%ld\n",
vi->shmid, si->size);
return -1;
}
if (restore_shmem_content(addr, si) < 0) {
pr_err("Can't restore shmem content\n");
return -1;
}
f = open_proc_rw(getpid(), "map_files/%lx-%lx",
(unsigned long) addr,
(unsigned long) addr + si->size);
munmap(addr, si->size);
if (f < 0)
return -1;
vi->fd = si->fd = f;
} else
vi->fd = dup(si->fd);
}
write_fd:
lseek(fd, -sizeof(*vi), SEEK_CUR);
if (write(fd, vi, sizeof(*vi)) != sizeof(*vi)) {
pr_perror("%d: Can't write img", pid);
return -1;
} }
return 0; return 0;
...@@ -590,35 +589,23 @@ static int fixup_vma_fds(int pid, int fd) ...@@ -590,35 +589,23 @@ static int fixup_vma_fds(int pid, int fd)
continue; continue;
if (vma_entry_is(&vi, VMA_FILE_PRIVATE) || if (vma_entry_is(&vi, VMA_FILE_PRIVATE) ||
vma_entry_is(&vi, VMA_FILE_SHARED) || vma_entry_is(&vi, VMA_FILE_SHARED)) {
vma_entry_is(&vi, VMA_ANON_SHARED)) {
pr_info("%d: Fixing %016lx-%016lx %016lx vma\n", pr_info("%d: Fixing %016lx-%016lx %016lx vma\n",
pid, vi.start, vi.end, vi.pgoff); pid, vi.start, vi.end, vi.pgoff);
if (try_fixup_file_map(pid, &vi, fd)) if (try_fixup_file_map(pid, &vi, fd))
return -1; return -1;
}
if (vma_entry_is(&vi, VMA_ANON_SHARED)) {
pr_info("%d: Fixing %016lx-%016lx %016lx vma\n",
pid, vi.start, vi.end, vi.pgoff);
if (try_fixup_shared_map(pid, &vi, fd)) if (try_fixup_shared_map(pid, &vi, fd))
return -1; return -1;
} }
} }
}
static inline bool should_restore_page(int pid, unsigned long va)
{
struct shmem_info *si;
struct shmem_id *shmid;
/* return 0;
* If this is not a shmem virtual address
* we should restore such page.
*/
shmid = find_shmem_id(va);
if (!shmid)
return true;
si = find_shmem_page(shmems, va, shmid->shmid);
return si->pid == pid;
} }
/* /*
...@@ -646,30 +633,8 @@ static int fixup_pages_data(int pid, int fd) ...@@ -646,30 +633,8 @@ static int fixup_pages_data(int pid, int fd)
write(fd, &va, sizeof(va)); write(fd, &va, sizeof(va));
sendfile(fd, pgfd, NULL, PAGE_SIZE); sendfile(fd, pgfd, NULL, PAGE_SIZE);
} }
close_safe(&pgfd);
pgfd = open_image_ro(CR_FD_SHMEM_PAGES, pid);
if (pgfd < 0)
return -1;
while (1) {
if (read_img(pgfd, &va) < 0)
goto out;
if (final_page_va(va))
break;
if (!should_restore_page(pid, va)) {
lseek(pgfd, PAGE_SIZE, SEEK_CUR);
continue;
}
pr_info("%d: Restoring shared page: %16lx\n", pid, va);
write(fd, &va, sizeof(va));
sendfile(fd, pgfd, NULL, PAGE_SIZE);
}
ret = write_img(fd, &zero_page_entry); ret = 0;
out: out:
close_safe(&pgfd); close_safe(&pgfd);
return ret; return ret;
...@@ -685,6 +650,8 @@ static int prepare_image_maps(int fd, int pid) ...@@ -685,6 +650,8 @@ static int prepare_image_maps(int fd, int pid)
if (fixup_pages_data(pid, fd)) if (fixup_pages_data(pid, fd))
return -1; return -1;
pr_info("%d: Fixing maps\n", pid);
return 0; return 0;
} }
...@@ -1062,9 +1029,6 @@ static int restore_one_alive_task(int pid) ...@@ -1062,9 +1029,6 @@ static int restore_one_alive_task(int pid)
if (prepare_fds(pid)) if (prepare_fds(pid))
return -1; return -1;
if (prepare_shmem(pid))
return -1;
if (prepare_sigactions(pid)) if (prepare_sigactions(pid))
return -1; return -1;
...@@ -1413,6 +1377,7 @@ static int restore_root_task(int fd, struct cr_options *opts) ...@@ -1413,6 +1377,7 @@ static int restore_root_task(int fd, struct cr_options *opts)
pr_info("Wait until all tasks are restored\n"); pr_info("Wait until all tasks are restored\n");
ret = cr_wait_until_greater(&task_entries->nr_in_progress, 0); ret = cr_wait_until_greater(&task_entries->nr_in_progress, 0);
out:
if (ret < 0) { if (ret < 0) {
pr_err("Someone can't be restored\n"); pr_err("Someone can't be restored\n");
for (i = 0; i < task_pids->nr; i++) for (i = 0; i < task_pids->nr; i++)
......
...@@ -54,25 +54,6 @@ ...@@ -54,25 +54,6 @@
static char local_buf[PAGE_SIZE]; static char local_buf[PAGE_SIZE];
static LIST_HEAD(pstree_list); static LIST_HEAD(pstree_list);
static void show_shmem(int fd_shmem)
{
struct shmem_entry e;
pr_img_head(CR_FD_SHMEM);
while (1) {
int ret;
ret = read_img_eof(fd_shmem, &e);
if (ret <= 0)
goto out;
pr_msg("0x%lx-0x%lx id %lu\n", e.start, e.end, e.shmid);
}
out:
pr_img_tail(CR_FD_SHMEM);
}
static void show_files(int fd_files) static void show_files(int fd_files)
{ {
struct fdinfo_entry e; struct fdinfo_entry e;
...@@ -491,9 +472,6 @@ static int cr_parse_file(struct cr_options *opts) ...@@ -491,9 +472,6 @@ 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 SHMEM_MAGIC:
show_shmem(fd);
break;
case PSTREE_MAGIC: case PSTREE_MAGIC:
show_pstree(fd, NULL); show_pstree(fd, NULL);
break; break;
...@@ -606,8 +584,6 @@ static int cr_show_all(unsigned long pid, struct cr_options *opts) ...@@ -606,8 +584,6 @@ static int cr_show_all(unsigned long pid, struct cr_options *opts)
show_files(cr_fdset->fds[CR_FD_FDINFO]); show_files(cr_fdset->fds[CR_FD_FDINFO]);
show_shmem(cr_fdset->fds[CR_FD_SHMEM]);
show_sigacts(cr_fdset->fds[CR_FD_SIGACT]); show_sigacts(cr_fdset->fds[CR_FD_SIGACT]);
show_unixsk(cr_fdset->fds[CR_FD_UNIXSK]); show_unixsk(cr_fdset->fds[CR_FD_UNIXSK]);
......
...@@ -69,12 +69,6 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = { ...@@ -69,12 +69,6 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
.magic = PSTREE_MAGIC, .magic = PSTREE_MAGIC,
}, },
/* info about which memory areas are shared */
[CR_FD_SHMEM] = {
.fmt = FMT_FNAME_SHMEM,
.magic = SHMEM_MAGIC,
},
/* info about signal handlers */ /* info about signal handlers */
[CR_FD_SIGACT] = { [CR_FD_SIGACT] = {
.fmt = FMT_FNAME_SIGACTS, .fmt = FMT_FNAME_SIGACTS,
......
...@@ -21,10 +21,8 @@ enum { ...@@ -21,10 +21,8 @@ enum {
CR_FD_FDINFO, CR_FD_FDINFO,
CR_FD_PAGES, CR_FD_PAGES,
CR_FD_SHMEM_PAGES,
CR_FD_CORE, CR_FD_CORE,
CR_FD_PIPES, CR_FD_PIPES,
CR_FD_SHMEM,
CR_FD_SIGACT, CR_FD_SIGACT,
CR_FD_UNIXSK, CR_FD_UNIXSK,
CR_FD_INETSK, CR_FD_INETSK,
...@@ -46,6 +44,8 @@ enum { ...@@ -46,6 +44,8 @@ enum {
CR_FD_PID_MAX, /* fmt, pid */ CR_FD_PID_MAX, /* fmt, pid */
CR_FD_SHMEM_PAGES,
CR_FD_MAX CR_FD_MAX
}; };
...@@ -75,12 +75,11 @@ extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX]; ...@@ -75,12 +75,11 @@ extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX];
#define FMT_FNAME_FDINFO "fdinfo-%d.img" #define FMT_FNAME_FDINFO "fdinfo-%d.img"
#define FMT_FNAME_PAGES "pages-%d.img" #define FMT_FNAME_PAGES "pages-%d.img"
#define FMT_FNAME_SHMEM_PAGES "pages-shmem-%d.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_CORE_OUT "core-%d.img.out" #define FMT_FNAME_CORE_OUT "core-%d.img.out"
#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_SHMEM "shmem-%d.img"
#define FMT_FNAME_SIGACTS "sigacts-%d.img" #define FMT_FNAME_SIGACTS "sigacts-%d.img"
#define FMT_FNAME_UNIXSK "unixsk-%d.img" #define FMT_FNAME_UNIXSK "unixsk-%d.img"
#define FMT_FNAME_INETSK "inetsk-%d.img" #define FMT_FNAME_INETSK "inetsk-%d.img"
...@@ -119,10 +118,8 @@ struct cr_fdset { ...@@ -119,10 +118,8 @@ struct cr_fdset {
#define CR_FD_DESC_TASK (\ #define CR_FD_DESC_TASK (\
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_SHMEM_PAGES) |\
CR_FD_DESC_USE(CR_FD_CORE) |\ CR_FD_DESC_USE(CR_FD_CORE) |\
CR_FD_DESC_USE(CR_FD_PIPES) |\ CR_FD_DESC_USE(CR_FD_PIPES) |\
CR_FD_DESC_USE(CR_FD_SHMEM) |\
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) |\
CR_FD_DESC_USE(CR_FD_INETSK) |\ CR_FD_DESC_USE(CR_FD_INETSK) |\
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#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 SHMEM_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 */
...@@ -55,12 +54,6 @@ struct fdinfo_entry { ...@@ -55,12 +54,6 @@ struct fdinfo_entry {
((fe)->type == FDINFO_CWD) || \ ((fe)->type == FDINFO_CWD) || \
((fe)->type == FDINFO_EXE)) ((fe)->type == FDINFO_EXE))
struct shmem_entry {
u64 start;
u64 end;
u64 shmid;
} __packed;
struct pstree_entry { struct pstree_entry {
u32 pid; u32 pid;
u32 nr_children; u32 nr_children;
......
...@@ -182,11 +182,20 @@ struct rt_sigframe { ...@@ -182,11 +182,20 @@ struct rt_sigframe {
#define SHMEMS_SIZE 4096 #define SHMEMS_SIZE 4096
/*
* pid is a pid of a creater
* start, end are used for open mapping
* fd is a file discriptor, which is valid for creater,
* it's opened in cr-restor, because pgoff may be non zero
*/
struct shmem_info { struct shmem_info {
unsigned long shmid;
unsigned long start; unsigned long start;
unsigned long end; unsigned long end;
unsigned long shmid; unsigned long size;
int pid; int pid;
int fd;
u32 lock; /* futex */ u32 lock; /* futex */
}; };
...@@ -209,18 +218,15 @@ struct task_entries { ...@@ -209,18 +218,15 @@ struct task_entries {
u32 start; //futex u32 start; //futex
}; };
static always_inline struct shmem_info * static always_inline struct shmem_info *
find_shmem_by_pid(struct shmems *shmems, unsigned long start, int pid) find_shmem(struct shmems *shmems, unsigned long shmid)
{ {
struct shmem_info *si; struct shmem_info *si;
int i; int i;
for (i = 0; i < shmems->nr_shmems; i++) { for (i = 0; i < shmems->nr_shmems; i++) {
si = &shmems->entries[i]; si = &shmems->entries[i];
if (si->start == start && if (si->shmid == shmid)
si->end > start &&
si->pid == pid)
return si; return si;
} }
......
...@@ -538,10 +538,6 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a ...@@ -538,10 +538,6 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a
if (ret < 0) if (ret < 0)
goto out; goto out;
ret = parasite_prep_file(CR_FD_SHMEM_PAGES, ctl, cr_fdset);
if (ret < 0)
goto out;
ret = parasite_execute(PARASITE_CMD_DUMPPAGES_INIT, ctl, st, sizeof(*st)); ret = parasite_execute(PARASITE_CMD_DUMPPAGES_INIT, ctl, st, sizeof(*st));
if (ret < 0) { if (ret < 0) {
pr_err("Dumping pages failed with %li at %li\n", pr_err("Dumping pages failed with %li at %li\n",
...@@ -566,15 +562,16 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a ...@@ -566,15 +562,16 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a
if (vma_area->vma.status & VMA_AREA_SYSVIPC) if (vma_area->vma.status & VMA_AREA_SYSVIPC)
continue; continue;
if (vma_area_is(vma_area, VMA_ANON_SHARED))
continue;
pr_info_vma(vma_area); pr_info_vma(vma_area);
parasite_dumppages.vma_entry = vma_area->vma; parasite_dumppages.vma_entry = vma_area->vma;
if (vma_area_is(vma_area, VMA_ANON_PRIVATE) || if (vma_area_is(vma_area, VMA_ANON_PRIVATE) ||
vma_area_is(vma_area, VMA_FILE_PRIVATE)) vma_area_is(vma_area, VMA_FILE_PRIVATE)) {
parasite_dumppages.fd_type = PG_PRIV; parasite_dumppages.fd_type = PG_PRIV;
else if (vma_area_is(vma_area, VMA_ANON_SHARED)) } else {
parasite_dumppages.fd_type = PG_SHARED;
else {
pr_warn("Unexpected VMA area found\n"); pr_warn("Unexpected VMA area found\n");
continue; continue;
} }
...@@ -598,8 +595,6 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a ...@@ -598,8 +595,6 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a
if (write_img(cr_fdset->fds[CR_FD_PAGES], &zero_page_entry)) if (write_img(cr_fdset->fds[CR_FD_PAGES], &zero_page_entry))
goto out; goto out;
if (write_img(cr_fdset->fds[CR_FD_SHMEM_PAGES], &zero_page_entry))
goto out;
pr_info("\n"); pr_info("\n");
pr_info("Summary: %16li pages dumped\n", nrpages_dumped); pr_info("Summary: %16li pages dumped\n", nrpages_dumped);
...@@ -607,7 +602,6 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a ...@@ -607,7 +602,6 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a
out: out:
fchmod(cr_fdset->fds[CR_FD_PAGES], CR_FD_PERM); fchmod(cr_fdset->fds[CR_FD_PAGES], CR_FD_PERM);
fchmod(cr_fdset->fds[CR_FD_SHMEM_PAGES], CR_FD_PERM);
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
return ret; return ret;
......
...@@ -123,14 +123,8 @@ static int dump_pages_init(parasite_status_t *st) ...@@ -123,14 +123,8 @@ static int dump_pages_init(parasite_status_t *st)
if (ret < 0) if (ret < 0)
goto err; goto err;
ret = fd_pages[PG_SHARED] = recv_fd(tsock);
if (ret < 0)
goto err_s;
return 0; return 0;
err_s:
sys_close(fd_pages[PG_PRIV]);
err: err:
SET_PARASITE_RET(st, ret); SET_PARASITE_RET(st, ret);
return -1; return -1;
...@@ -246,7 +240,6 @@ err: ...@@ -246,7 +240,6 @@ err:
static int dump_pages_fini(void) static int dump_pages_fini(void)
{ {
sys_close(fd_pages[PG_PRIV]); sys_close(fd_pages[PG_PRIV]);
sys_close(fd_pages[PG_SHARED]);
return 0; return 0;
} }
......
...@@ -477,10 +477,10 @@ long restore_task(struct task_restore_core_args *args) ...@@ -477,10 +477,10 @@ long restore_task(struct task_restore_core_args *args)
if (vma_entry_is(vma_entry, VMA_ANON_SHARED)) { if (vma_entry_is(vma_entry, VMA_ANON_SHARED)) {
struct shmem_info *entry; struct shmem_info *entry;
entry = find_shmem_by_pid(args->shmems, entry = find_shmem(args->shmems,
vma_entry->start, vma_entry->shmid);
my_pid); if (entry && entry->pid == my_pid &&
if (entry) entry->start == vma_entry->start)
cr_wait_set(&entry->lock, 1); cr_wait_set(&entry->lock, 1);
} }
......
...@@ -63,7 +63,7 @@ void pr_vma(unsigned int loglevel, const struct vma_area *vma_area) ...@@ -63,7 +63,7 @@ void pr_vma(unsigned int loglevel, const struct vma_area *vma_area)
return; return;
print_on_level(loglevel, "s: %16lx e: %16lx l: %8liK p: %8x f: %8x pg: %8lx " print_on_level(loglevel, "s: %16lx e: %16lx l: %8liK p: %8x f: %8x pg: %8lx "
"vf: %s st: %s spc: %s\n", "vf: %s st: %s spc: %-8s shmid: %8lx\n",
vma_area->vma.start, vma_area->vma.end, vma_area->vma.start, vma_area->vma.end,
KBYTES(vma_area_len(vma_area)), KBYTES(vma_area_len(vma_area)),
vma_area->vma.prot, vma_area->vma.prot,
...@@ -79,7 +79,8 @@ void pr_vma(unsigned int loglevel, const struct vma_area *vma_area) ...@@ -79,7 +79,8 @@ void pr_vma(unsigned int loglevel, const struct vma_area *vma_area)
((vma_area->vma.status & VMA_AREA_STACK) ? "stack" : ((vma_area->vma.status & VMA_AREA_STACK) ? "stack" :
((vma_area->vma.status & VMA_AREA_HEAP) ? "heap" : ((vma_area->vma.status & VMA_AREA_HEAP) ? "heap" :
((vma_area->vma.status & VMA_AREA_VSYSCALL) ? "vsyscall" : ((vma_area->vma.status & VMA_AREA_VSYSCALL) ? "vsyscall" :
((vma_area->vma.status & VMA_AREA_VDSO) ? "vdso" : "n"))))); ((vma_area->vma.status & VMA_AREA_VDSO) ? "vdso" : "n")))),
vma_area->vma.shmid);
} }
int close_safe(int *fd) int close_safe(int *fd)
......
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