Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/checkpoint-restore/criu.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/criu
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@gmail.com>2022-04-27 06:56:37 +0300
committerAndrei Vagin <avagin@google.com>2022-05-13 09:07:35 +0300
commit6d879d570d011a281f7c39e224810aca1351f127 (patch)
treeba1bf030ee6326ad798a8ff30570ae9ac156efa3 /criu
parentd84e2e4e94ca933f511644731ba55531eb75b0ce (diff)
page-xfer: adjust a buffer to a pipe size
Due to side effects of F_SETPIPE_SZ, the actual pipe size can be greater than PIPE_MAX_SIZE. Signed-off-by: Andrei Vagin <avagin@gmail.com>
Diffstat (limited to 'criu')
-rw-r--r--criu/include/page-xfer.h2
-rw-r--r--criu/page-xfer.c63
2 files changed, 40 insertions, 25 deletions
diff --git a/criu/include/page-xfer.h b/criu/include/page-xfer.h
index 1bcd4ff20..36fe67092 100644
--- a/criu/include/page-xfer.h
+++ b/criu/include/page-xfer.h
@@ -10,7 +10,7 @@ struct ps_info {
extern int cr_page_server(bool daemon_mode, bool lazy_dump, int cfd);
/* User buffer for read-mode pre-dump*/
-#define BUFFER_SIZE (PIPE_MAX_SIZE << PAGE_SHIFT)
+#define PIPE_MAX_BUFFER_SIZE (PIPE_MAX_SIZE << PAGE_SHIFT)
/*
* page_xfer -- transfer pages into image file.
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index 6599e29cf..3d29fbf78 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -777,31 +777,48 @@ int page_xfer_predump_pages(int pid, struct page_xfer *xfer, struct page_pipe *p
struct page_pipe_buf *ppb;
unsigned int cur_hole = 0, i;
unsigned long ret, bytes_read;
+ unsigned long userbuf_len;
struct iovec bufvec;
- struct iovec aux_iov[PIPE_MAX_SIZE];
+ struct iovec *aux_iov;
unsigned long aux_len;
+ void *userbuf;
- char *userbuf = mmap(NULL, BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
+ userbuf_len = PIPE_MAX_BUFFER_SIZE;
+ userbuf = mmap(NULL, userbuf_len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (userbuf == MAP_FAILED) {
pr_perror("Unable to mmap a buffer");
return -1;
}
+ aux_iov = xmalloc(userbuf_len / PAGE_SIZE * sizeof(aux_iov[0]));
+ if (!aux_iov)
+ goto err;
list_for_each_entry(ppb, &pp->bufs, l) {
+ if (ppb->pipe_size * PAGE_SIZE > userbuf_len) {
+ void *addr;
+
+ addr = mremap(userbuf, userbuf_len, ppb->pipe_size * PAGE_SIZE, MREMAP_MAYMOVE);
+ if (addr == MAP_FAILED) {
+ pr_perror("Unable to mmap a buffer");
+ goto err;
+ }
+ userbuf_len = ppb->pipe_size * PAGE_SIZE;
+ userbuf = addr;
+ addr = xrealloc(aux_iov, ppb->pipe_size * sizeof(aux_iov[0]));
+ if (!addr)
+ goto err;
+ aux_iov = addr;
+ }
timing_start(TIME_MEMDUMP);
aux_len = 0;
- bufvec.iov_len = BUFFER_SIZE;
+ bufvec.iov_len = userbuf_len;
bufvec.iov_base = userbuf;
bytes_read = fill_userbuf(pid, ppb, &bufvec, aux_iov, &aux_len);
-
- if (bytes_read == -ESRCH) {
- munmap(userbuf, BUFFER_SIZE);
- return -1;
- }
+ if (bytes_read == -ESRCH)
+ goto err;
bufvec.iov_base = userbuf;
bufvec.iov_len = bytes_read;
@@ -809,8 +826,7 @@ int page_xfer_predump_pages(int pid, struct page_xfer *xfer, struct page_pipe *p
if (ret == -1 || ret != bytes_read) {
pr_err("vmsplice: Failed to splice user buffer to pipe %ld\n", ret);
- munmap(userbuf, BUFFER_SIZE);
- return -1;
+ goto err;
}
timing_stop(TIME_MEMDUMP);
@@ -822,10 +838,8 @@ int page_xfer_predump_pages(int pid, struct page_xfer *xfer, struct page_pipe *p
u32 flags;
ret = dump_holes(xfer, pp, &cur_hole, iov.iov_base);
- if (ret) {
- munmap(userbuf, BUFFER_SIZE);
- return ret;
- }
+ if (ret)
+ goto err;
BUG_ON(iov.iov_base < (void *)xfer->offset);
iov.iov_base -= xfer->offset;
@@ -833,24 +847,25 @@ int page_xfer_predump_pages(int pid, struct page_xfer *xfer, struct page_pipe *p
flags = ppb_xfer_flags(xfer, ppb);
- if (xfer->write_pagemap(xfer, &iov, flags)) {
- munmap(userbuf, BUFFER_SIZE);
- return -1;
- }
+ if (xfer->write_pagemap(xfer, &iov, flags))
+ goto err;
- if (xfer->write_pages(xfer, ppb->p[0], iov.iov_len)) {
- munmap(userbuf, BUFFER_SIZE);
- return -1;
- }
+ if (xfer->write_pages(xfer, ppb->p[0], iov.iov_len))
+ goto err;
}
timing_stop(TIME_MEMWRITE);
}
- munmap(userbuf, BUFFER_SIZE);
+ munmap(userbuf, userbuf_len);
+ xfree(aux_iov);
timing_start(TIME_MEMWRITE);
return dump_holes(xfer, pp, &cur_hole, NULL);
+err:
+ munmap(userbuf, userbuf_len);
+ xfree(aux_iov);
+ return -1;
}
int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp)