[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