[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