Commit e5e53795 authored by Pavel Emelyanov's avatar Pavel Emelyanov

page-pipe: Support holes in page-pipe iov map

Holes are regions, that don't have pages in them (i.e. -- no
pages in pipes). These holes are in separate iovs array since
we should have straight arrays of iovs for non-holes, which is
in turd required to push it into vmsplice in _one_ chunk.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 6ff0edad
...@@ -18,9 +18,14 @@ struct page_pipe { ...@@ -18,9 +18,14 @@ struct page_pipe {
unsigned int nr_iovs; unsigned int nr_iovs;
unsigned int free_iov; unsigned int free_iov;
struct iovec *iovs; struct iovec *iovs;
unsigned int nr_holes;
unsigned int free_hole;
struct iovec *holes;
}; };
struct page_pipe *create_page_pipe(unsigned int nr, struct iovec *); struct page_pipe *create_page_pipe(unsigned int nr, struct iovec *);
void destroy_page_pipe(struct page_pipe *p); void destroy_page_pipe(struct page_pipe *p);
int page_pipe_add_page(struct page_pipe *p, unsigned long addr); int page_pipe_add_page(struct page_pipe *p, unsigned long addr);
int page_pipe_add_hole(struct page_pipe *p, unsigned long addr);
#endif #endif
...@@ -47,6 +47,10 @@ struct page_pipe *create_page_pipe(unsigned int nr_segs, struct iovec *iovs) ...@@ -47,6 +47,10 @@ struct page_pipe *create_page_pipe(unsigned int nr_segs, struct iovec *iovs)
pp->iovs = iovs; pp->iovs = iovs;
pp->free_iov = 0; pp->free_iov = 0;
pp->nr_holes = 0;
pp->free_hole = 0;
pp->holes = NULL;
if (page_pipe_grow(pp)) if (page_pipe_grow(pp))
return NULL; return NULL;
} }
...@@ -137,3 +141,34 @@ int page_pipe_add_page(struct page_pipe *pp, unsigned long addr) ...@@ -137,3 +141,34 @@ int page_pipe_add_page(struct page_pipe *pp, unsigned long addr)
BUG_ON(ret > 0); BUG_ON(ret > 0);
return ret; return ret;
} }
#define PP_HOLES_BATCH 32
int page_pipe_add_hole(struct page_pipe *pp, unsigned long addr)
{
struct iovec *iov;
if (pp->free_hole >= pp->nr_holes) {
pp->holes = xrealloc(pp->holes,
(pp->nr_holes + PP_HOLES_BATCH) * sizeof(struct iovec));
if (!pp->holes)
return -1;
pp->nr_holes += PP_HOLES_BATCH;
}
if (pp->free_hole) {
iov = &pp->holes[pp->free_hole - 1];
if ((unsigned long)iov->iov_base + iov->iov_len == addr) {
iov->iov_len += PAGE_SIZE;
goto out;
}
}
iov = &pp->holes[pp->free_hole];
iov->iov_base = (void *)addr;
iov->iov_len = PAGE_SIZE;
pp->free_hole++;
out:
return 0;
}
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