Commit 3c09c15d authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Andrei Vagin

page-xfer: dump compatible iovec

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@openvz.org>
Signed-off-by: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent aefed47f
...@@ -119,6 +119,12 @@ struct page_pipe { ...@@ -119,6 +119,12 @@ struct page_pipe {
#define PP_COMPAT 0x2 /* Use compatible iovs (struct compat_iovec) */ #define PP_COMPAT 0x2 /* Use compatible iovs (struct compat_iovec) */
#define PP_OWN_IOVS 0x4 /* create_page_pipe allocated IOVs memory */ #define PP_OWN_IOVS 0x4 /* create_page_pipe allocated IOVs memory */
/* XXX: move to arch-depended file, when non-x86 add support for compat mode */
struct iovec_compat {
u32 iov_base;
u32 iov_len;
};
struct page_pipe *create_page_pipe(unsigned int nr_segs, struct iovec *iovs, unsigned flags); struct page_pipe *create_page_pipe(unsigned int nr_segs, struct iovec *iovs, unsigned flags);
extern void destroy_page_pipe(struct page_pipe *p); extern void destroy_page_pipe(struct page_pipe *p);
extern int page_pipe_add_page(struct page_pipe *p, unsigned long addr); extern int page_pipe_add_page(struct page_pipe *p, unsigned long addr);
......
...@@ -81,12 +81,6 @@ static int ppb_resize_pipe(struct page_pipe_buf *ppb, unsigned long new_size) ...@@ -81,12 +81,6 @@ static int ppb_resize_pipe(struct page_pipe_buf *ppb, unsigned long new_size)
return 0; return 0;
} }
/* 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) static inline void iov_init_compat(struct iovec_compat *iov, unsigned long addr)
{ {
iov->iov_base = (u32)addr; iov->iov_base = (u32)addr;
......
...@@ -341,9 +341,19 @@ static int page_xfer_dump_hole(struct page_xfer *xfer, ...@@ -341,9 +341,19 @@ static int page_xfer_dump_hole(struct page_xfer *xfer,
return 0; return 0;
} }
static struct iovec get_iov(struct iovec *iovs, unsigned int n) static struct iovec get_iov(struct iovec *iovs, unsigned int n, bool compat)
{ {
if (likely(!compat)) {
return iovs[n]; 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;
}
} }
static int dump_holes(struct page_xfer *xfer, struct page_pipe *pp, static int dump_holes(struct page_xfer *xfer, struct page_pipe *pp,
...@@ -352,7 +362,8 @@ static int dump_holes(struct page_xfer *xfer, struct page_pipe *pp, ...@@ -352,7 +362,8 @@ static int dump_holes(struct page_xfer *xfer, struct page_pipe *pp,
int ret; int ret;
for (; *cur_hole < pp->free_hole ; (*cur_hole)++) { for (; *cur_hole < pp->free_hole ; (*cur_hole)++) {
struct iovec hole = get_iov(pp->holes, *cur_hole); struct iovec hole = get_iov(pp->holes, *cur_hole,
pp->flags & PP_COMPAT);
if (limit && hole.iov_base >= limit) if (limit && hole.iov_base >= limit)
break; break;
...@@ -380,7 +391,7 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp, ...@@ -380,7 +391,7 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
pr_debug("\tbuf %d/%d\n", ppb->pages_in, ppb->nr_segs); pr_debug("\tbuf %d/%d\n", ppb->pages_in, ppb->nr_segs);
for (i = 0; i < ppb->nr_segs; i++) { for (i = 0; i < ppb->nr_segs; i++) {
struct iovec iov = get_iov(ppb->iov, i); struct iovec iov = get_iov(ppb->iov, i, pp->flags & PP_COMPAT);
ret = dump_holes(xfer, pp, &cur_hole, iov.iov_base, off); ret = dump_holes(xfer, pp, &cur_hole, iov.iov_base, off);
if (ret) if (ret)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment