[CRIU] [PATCHv3 14/30] page-xfer: dump compatible iovec
Dmitry Safonov
dsafonov at virtuozzo.com
Tue Jun 28 12:24:07 PDT 2016
Change page_xfer_dump_pages the way it could handle compatible iovs.
Separated hole dumping in page_xfer_dump_hole and introduced
iterator function get_iov which will return native iovec,
converting compatible iovec if needed.
Fixes:
(00.009060) Fetched ack: 7 7 0
(00.009061) Transfering pages:
(00.009062) buf 16/16
(00.009063) p 0x100008048000 [32841]
(00.009101) Error (page-xfer.c:504): Only 65536 of 17592320561152 bytes have been spliced
(00.009253) page-pipe: Killing page pipe
(00.009263) ----------------------------------------
Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
criu/include/page-pipe.h | 6 ++++
criu/page-pipe.c | 6 ----
criu/page-xfer.c | 88 +++++++++++++++++++++++++++++-------------------
3 files changed, 60 insertions(+), 40 deletions(-)
diff --git a/criu/include/page-pipe.h b/criu/include/page-pipe.h
index 19e7a898e77f..474ffa004daa 100644
--- a/criu/include/page-pipe.h
+++ b/criu/include/page-pipe.h
@@ -98,6 +98,12 @@ struct page_pipe {
bool compat_iov; /* Use compatible iovs (struct compat_iovec) */
};
+/* XXX: move to arch-depended file, when non-x86 add support for compat mode */
+struct iovec_compat {
+ u32 iov_base;
+ u32 iov_len;
+};
+
extern struct page_pipe *create_page_pipe(unsigned int nr, struct iovec *,
bool chunk_mode, bool compat_iov);
extern void destroy_page_pipe(struct page_pipe *p);
diff --git a/criu/page-pipe.c b/criu/page-pipe.c
index c38b96e89407..db597b27f1e2 100644
--- a/criu/page-pipe.c
+++ b/criu/page-pipe.c
@@ -100,12 +100,6 @@ static struct page_pipe_buf *ppb_alloc_resize(struct page_pipe *pp, int size)
return ppb;
}
-/* XXX: move to arch-depended file, when non-x86 add support for compat mode */
-struct iovec_compat {
- u32 iov_base;
- u32 iov_len;
-};
-
static inline void iov_init_compat(struct iovec_compat *iov, unsigned long addr)
{
iov->iov_base = (u32)addr;
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index 3813712fefcf..8c2c799c0b0f 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -320,61 +320,81 @@ int open_page_xfer(struct page_xfer *xfer, int fd_type, long id)
return open_page_local_xfer(xfer, fd_type, id);
}
+static int page_xfer_dump_hole(struct page_xfer *xfer,
+ struct iovec *hole, unsigned long off)
+{
+ BUG_ON(hole->iov_base < (void *)off);
+ hole->iov_base -= off;
+ pr_debug("\th %p [%u]\n", hole->iov_base,
+ (unsigned int)(hole->iov_len / PAGE_SIZE));
+
+ if (xfer->write_hole(xfer, hole))
+ return -1;
+
+ return 0;
+}
+
+static struct iovec get_iov(struct iovec *iovs, unsigned int n, bool compat)
+{
+ if (likely(!compat)) {
+ return iovs[n];
+ } else {
+ struct iovec ret;
+ struct iovec_compat *tmp = (struct iovec_compat*)(void *)iovs;
+
+ tmp += n;
+ ret.iov_base = (void *)(uintptr_t)tmp->iov_base;
+ ret.iov_len = tmp->iov_len;
+ return ret;
+ }
+}
+
int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
unsigned long off)
{
struct page_pipe_buf *ppb;
- struct iovec *hole = NULL;
+ unsigned int cur_hole = 0;
+ int ret;
pr_debug("Transfering pages:\n");
- if (pp->free_hole)
- hole = &pp->holes[0];
-
list_for_each_entry(ppb, &pp->bufs, l) {
- int i;
+ unsigned int i;
pr_debug("\tbuf %d/%d\n", ppb->pages_in, ppb->nr_segs);
for (i = 0; i < ppb->nr_segs; i++) {
- struct iovec *iov = &ppb->iov[i];
-
- while (hole && (hole->iov_base < iov->iov_base)) {
- BUG_ON(hole->iov_base < (void *)off);
- hole->iov_base -= off;
- pr_debug("\th %p [%u]\n", hole->iov_base,
- (unsigned int)(hole->iov_len / PAGE_SIZE));
- if (xfer->write_hole(xfer, hole))
- return -1;
-
- hole++;
- if (hole >= &pp->holes[pp->free_hole])
- hole = NULL;
+ struct iovec iov = get_iov(ppb->iov, i, pp->compat_iov);
+
+ for (; cur_hole < pp->free_hole ; cur_hole++) {
+ struct iovec hole = get_iov(pp->holes, cur_hole,
+ pp->compat_iov);
+
+ if (hole.iov_base < iov.iov_base)
+ break;
+ ret = page_xfer_dump_hole(xfer, &hole, off);
+ if (ret)
+ return ret;
}
- BUG_ON(iov->iov_base < (void *)off);
- iov->iov_base -= off;
- pr_debug("\tp %p [%u]\n", iov->iov_base,
- (unsigned int)(iov->iov_len / PAGE_SIZE));
+ BUG_ON(iov.iov_base < (void *)off);
+ iov.iov_base -= off;
+ pr_debug("\tp %p [%u]\n", iov.iov_base,
+ (unsigned int)(iov.iov_len / PAGE_SIZE));
- if (xfer->write_pagemap(xfer, iov))
+ if (xfer->write_pagemap(xfer, &iov))
return -1;
- if (xfer->write_pages(xfer, ppb->p[0], iov->iov_len))
+ if (xfer->write_pages(xfer, ppb->p[0], iov.iov_len))
return -1;
}
}
- while (hole) {
- BUG_ON(hole->iov_base < (void *)off);
- hole->iov_base -= off;
- pr_debug("\th* %p [%u]\n", hole->iov_base,
- (unsigned int)(hole->iov_len / PAGE_SIZE));
- if (xfer->write_hole(xfer, hole))
- return -1;
+ for (; cur_hole < pp->free_hole ; cur_hole++) {
+ struct iovec hole = get_iov(pp->holes, cur_hole, pp->compat_iov);
- hole++;
- if (hole >= &pp->holes[pp->free_hole])
- hole = NULL;
+ ret = page_xfer_dump_hole(xfer, &hole, off);
+ if (ret)
+ return ret;
}
return 0;
--
2.9.0
More information about the CRIU
mailing list