mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 13:58:34 +00:00
mem: use chunk mode for dumping anonymous memory
Before this patch, criu splices all data in pipes and then saves these data in a image file. Here is a problem, becase creating pipes with big buffers fails too often, because a kernel tries to allocate a big linear chunks of memory. Now memory are dumped for a few iterations, where the size of pipe buffers is restricted. TODO: need to rework pre-dump, because currently dumping data from pipes are postponed. We are going to use sys_process_vm_readv for this. Signed-off-by: Andrey Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
4e395c5c8d
commit
b5dff62e3b
34
mem.c
34
mem.c
@@ -105,14 +105,15 @@ static inline bool page_in_parent(u64 pme)
|
|||||||
* the memory contents is present in the pagent image set.
|
* the memory contents is present in the pagent image set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int generate_iovs(struct vma_area *vma, int pagemap, struct page_pipe *pp, u64 *map)
|
static int generate_iovs(struct vma_area *vma, int pagemap,
|
||||||
|
struct page_pipe *pp, u64 *map, u64 *off)
|
||||||
{
|
{
|
||||||
unsigned long pfn, nr_to_scan;
|
unsigned long pfn, nr_to_scan;
|
||||||
unsigned long pages[2] = {};
|
unsigned long pages[2] = {};
|
||||||
u64 from, len;
|
u64 from, len;
|
||||||
|
|
||||||
nr_to_scan = vma_area_len(vma) / PAGE_SIZE;
|
nr_to_scan = (vma_area_len(vma) - *off) / PAGE_SIZE;
|
||||||
from = vma->e->start / PAGE_SIZE * sizeof(*map);
|
from = (vma->e->start + *off) / PAGE_SIZE * sizeof(*map);
|
||||||
len = nr_to_scan * sizeof(*map);
|
len = nr_to_scan * sizeof(*map);
|
||||||
if (pread(pagemap, map, len, from) != len) {
|
if (pread(pagemap, map, len, from) != len) {
|
||||||
pr_perror("Can't read pagemap file");
|
pr_perror("Can't read pagemap file");
|
||||||
@@ -126,7 +127,7 @@ static int generate_iovs(struct vma_area *vma, int pagemap, struct page_pipe *pp
|
|||||||
if (!should_dump_page(vma->e, map[pfn]))
|
if (!should_dump_page(vma->e, map[pfn]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
vaddr = vma->e->start + pfn * PAGE_SIZE;
|
vaddr = vma->e->start + *off + pfn * PAGE_SIZE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're doing incremental dump (parent images
|
* If we're doing incremental dump (parent images
|
||||||
@@ -143,10 +144,14 @@ static int generate_iovs(struct vma_area *vma, int pagemap, struct page_pipe *pp
|
|||||||
pages[1]++;
|
pages[1]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret)
|
if (ret) {
|
||||||
return -1;
|
*off += (pfn - 1) * PAGE_SIZE;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*off += pfn * PAGE_SIZE;
|
||||||
|
|
||||||
cnt_add(CNT_PAGES_SCANNED, nr_to_scan);
|
cnt_add(CNT_PAGES_SCANNED, nr_to_scan);
|
||||||
cnt_add(CNT_PAGES_SKIPPED_PARENT, pages[0]);
|
cnt_add(CNT_PAGES_SKIPPED_PARENT, pages[0]);
|
||||||
cnt_add(CNT_PAGES_WRITTEN, pages[1]);
|
cnt_add(CNT_PAGES_WRITTEN, pages[1]);
|
||||||
@@ -262,7 +267,8 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
|
|||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
pp = create_page_pipe(vma_area_list->priv_size / 2, pargs_iovs(args), false);
|
pp = create_page_pipe(vma_area_list->priv_size / 2,
|
||||||
|
pargs_iovs(args), pp_ret == NULL);
|
||||||
if (!pp)
|
if (!pp)
|
||||||
goto out_close;
|
goto out_close;
|
||||||
|
|
||||||
@@ -270,7 +276,6 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
|
|||||||
ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, ctl->pid.virt);
|
ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, ctl->pid.virt);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_pp;
|
goto out_pp;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -278,10 +283,21 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
|
|||||||
*/
|
*/
|
||||||
args->off = 0;
|
args->off = 0;
|
||||||
list_for_each_entry(vma_area, &vma_area_list->h, list) {
|
list_for_each_entry(vma_area, &vma_area_list->h, list) {
|
||||||
|
u64 off = 0;
|
||||||
|
|
||||||
if (!privately_dump_vma(vma_area))
|
if (!privately_dump_vma(vma_area))
|
||||||
continue;
|
continue;
|
||||||
|
again:
|
||||||
|
ret = generate_iovs(vma_area, pagemap, pp, map, &off);
|
||||||
|
if (ret == -EAGAIN) {
|
||||||
|
BUG_ON(pp_ret);
|
||||||
|
|
||||||
ret = generate_iovs(vma_area, pagemap, pp, map);
|
ret = fill_pages(pp, ctl, args, &xfer);
|
||||||
|
if (ret)
|
||||||
|
goto out_xfer;
|
||||||
|
page_pipe_reinit(pp);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_xfer;
|
goto out_xfer;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user