[CRIU] [PATCH 3/3] shmem: use chunk mode for dumping shared memory

Andrey Vagin avagin at openvz.org
Mon Feb 3 03:19:37 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 | 53 ++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 38 insertions(+), 15 deletions(-)

diff --git a/shmem.c b/shmem.c
index 1b753a4..96ede63 100644
--- a/shmem.c
+++ b/shmem.c
@@ -309,16 +309,42 @@ int add_shmem_area(pid_t pid, VmaEntry *vma)
 	return 0;
 }
 
+struct pp_mem_batch_args
+{
+	struct page_xfer *xfer;
+	void *addr;
+};
+
+static int fill_pages(struct page_pipe *pp, void *_args)
+{
+	struct pp_mem_batch_args *pp_args = _args;
+	struct page_pipe_buf *ppb;
+	int ret;
+
+	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;
+		}
+
+	ret = page_xfer_dump_pages(pp_args->xfer, pp, (unsigned long)pp_args->addr);
+	page_pipe_cleanup(pp);
+
+	return ret;
+}
+
 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;
 	void *addr = NULL;
 	unsigned long pfn, nrpages;
+	struct pp_mem_batch_args pp_args;
 
 	pr_info("Dumping shared memory %ld\n", si->shmid);
 
@@ -358,28 +384,25 @@ static int dump_one_shmem(struct shmem_info_dump *si)
 	if (!pp)
 		goto err_iovs;
 
+	err = open_page_xfer(&xfer, CR_FD_SHMEM_PAGEMAP, si->shmid);
+	if (err)
+		goto err_pp;
+
+	pp_args.addr = addr;
+	pp_args.xfer = &xfer;
+	page_pipe_start_chunk(pp, fill_pages, &pp_args);
+
 	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;
+			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 = page_pipe_complete_chunk(pp);
 
+err_xfer:
 	xfer.close(&xfer);
 err_pp:
 	destroy_page_pipe(pp);
-- 
1.8.5.3



More information about the CRIU mailing list