[CRIU] [PATCH] shmem: use chunk mode for dumping shared memory
Andrey Vagin
avagin at openvz.org
Wed Feb 12 13:36:15 PST 2014
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.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
shmem.c | 50 ++++++++++++++++++++++++++++++++------------------
1 file changed, 32 insertions(+), 18 deletions(-)
diff --git a/shmem.c b/shmem.c
index 0c1a97f..2f8e7e9 100644
--- a/shmem.c
+++ b/shmem.c
@@ -272,11 +272,25 @@ int add_shmem_area(pid_t pid, VmaEntry *vma)
return 0;
}
+static int dump_pages(struct page_pipe *pp, struct page_xfer *xfer, void *addr)
+{
+ struct page_pipe_buf *ppb;
+
+ list_for_each_entry(ppb, &pp->bufs, l)
+ if (vmsplice(ppb->p[1], ppb->iov, ppb->nr_segs,
+ SPLICE_F_GIFT | SPLICE_F_NONBLOCK) !=
+ ppb->pages_in * PAGE_SIZE) {
+ pr_perror("Can't get shmem into page-pipe");
+ return -1;
+ }
+
+ return page_xfer_dump_pages(xfer, pp, (unsigned long)addr);
+}
+
static int dump_one_shmem(struct shmem_info_dump *si)
{
struct iovec *iovs;
struct page_pipe *pp;
- struct page_pipe_buf *ppb;
struct page_xfer xfer;
int err, ret = -1, fd;
unsigned char *map = NULL;
@@ -317,32 +331,32 @@ static int dump_one_shmem(struct shmem_info_dump *si)
if (!iovs)
goto err_unmap;
- pp = create_page_pipe((nrpages + 1) / 2, iovs, false);
+ pp = create_page_pipe((nrpages + 1) / 2, iovs, true);
if (!pp)
goto err_iovs;
+ err = open_page_xfer(&xfer, CR_FD_SHMEM_PAGEMAP, si->shmid);
+ if (err)
+ goto err_pp;
+
for (pfn = 0; pfn < nrpages; pfn++) {
if (!(map[pfn] & PAGE_RSS))
continue;
-
- if (page_pipe_add_page(pp, (unsigned long)addr + pfn * PAGE_SIZE))
- goto err_pp;
+again:
+ ret = page_pipe_add_page(pp, (unsigned long)addr + pfn * PAGE_SIZE);
+ if (ret == -EAGAIN) {
+ ret = dump_pages(pp, &xfer, addr);
+ if (ret)
+ goto err_xfer;
+ page_pipe_reinit(pp);
+ goto again;
+ } else if (ret)
+ goto err_xfer;
}
- list_for_each_entry(ppb, &pp->bufs, l)
- if (vmsplice(ppb->p[1], ppb->iov, ppb->nr_segs,
- SPLICE_F_GIFT | SPLICE_F_NONBLOCK) !=
- ppb->pages_in * PAGE_SIZE) {
- pr_perror("Can't get shmem into page-pipe");
- goto err_pp;
- }
-
- err = open_page_xfer(&xfer, CR_FD_SHMEM_PAGEMAP, si->shmid);
- if (err)
- goto err_pp;
-
- ret = page_xfer_dump_pages(&xfer, pp, (unsigned long)addr);
+ ret = dump_pages(pp, &xfer, addr);
+err_xfer:
xfer.close(&xfer);
err_pp:
destroy_page_pipe(pp);
--
1.8.5.3
More information about the CRIU
mailing list