Commit e3fec3af authored by Mike Rapoport's avatar Mike Rapoport Committed by Andrei Vagin

criu: page_pipe_buf: add PPB_LAZY flag

for buffers that contain potentially lazy pages
Signed-off-by: 's avatarMike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 3df6627e
......@@ -95,6 +95,8 @@ struct page_pipe_buf {
unsigned int pipe_size; /* how many pages can be fit into pipe */
unsigned int pages_in; /* how many pages are there */
unsigned int nr_segs; /* how many iov-s are busy */
#define PPB_LAZY (1 << 0)
unsigned int flags;
struct iovec *iov; /* vaddr:len map */
struct list_head l; /* links into page_pipe->bufs */
};
......@@ -120,7 +122,8 @@ struct page_pipe {
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 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,
unsigned int flags);
extern int page_pipe_add_hole(struct page_pipe *p, unsigned long addr);
extern void debug_show_page_pipe(struct page_pipe *pp);
......
......@@ -146,6 +146,7 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
for (pfn = 0; pfn < nr_to_scan; pfn++) {
unsigned long vaddr;
unsigned int ppb_flags = 0;
int ret;
if (!should_dump_page(vma->e, at[pfn]))
......@@ -153,6 +154,9 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
vaddr = vma->e->start + *off + pfn * PAGE_SIZE;
if (vma_entry_can_be_lazy(vma->e))
ppb_flags |= PPB_LAZY;
/*
* If we're doing incremental dump (parent images
* specified) and page is not soft-dirty -- we dump
......@@ -164,7 +168,7 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
ret = page_pipe_add_hole(pp, vaddr);
pages[0]++;
} else {
ret = page_pipe_add_page(pp, vaddr);
ret = page_pipe_add_page(pp, vaddr, ppb_flags);
pages[1]++;
}
......
......@@ -57,10 +57,12 @@ static void ppb_destroy(struct page_pipe_buf *ppb)
}
static void ppb_init(struct page_pipe_buf *ppb, unsigned int pages_in,
unsigned int nr_segs, struct iovec *iov)
unsigned int nr_segs, unsigned int flags,
struct iovec *iov)
{
ppb->pages_in = pages_in;
ppb->nr_segs = nr_segs;
ppb->flags = flags;
ppb->iov = iov;
}
......@@ -81,7 +83,7 @@ static int ppb_resize_pipe(struct page_pipe_buf *ppb, unsigned long new_size)
return 0;
}
static int page_pipe_grow(struct page_pipe *pp)
static int page_pipe_grow(struct page_pipe *pp, unsigned int flags)
{
struct page_pipe_buf *ppb;
struct iovec *free_iov;
......@@ -103,7 +105,7 @@ static int page_pipe_grow(struct page_pipe *pp)
out:
free_iov = &pp->iovs[pp->free_iov];
ppb_init(ppb, 0, 0, free_iov);
ppb_init(ppb, 0, 0, flags, free_iov);
return 0;
}
......@@ -139,7 +141,7 @@ struct page_pipe *create_page_pipe(unsigned int nr_segs, struct iovec *iovs, uns
pp->free_hole = 0;
pp->holes = NULL;
if (page_pipe_grow(pp))
if (page_pipe_grow(pp, 0))
goto err_free_iovs;
return pp;
......@@ -180,13 +182,16 @@ void page_pipe_reinit(struct page_pipe *pp)
pp->free_hole = 0;
if (page_pipe_grow(pp))
if (page_pipe_grow(pp, 0))
BUG(); /* It can't fail, because ppb is in free_bufs */
}
static inline int try_add_page_to(struct page_pipe *pp, struct page_pipe_buf *ppb,
unsigned long addr)
unsigned long addr, unsigned int flags)
{
if (ppb->flags != flags)
return 1;
if (ppb->pages_in == ppb->pipe_size) {
unsigned long new_size = ppb->pipe_size << 1;
int ret;
......@@ -218,25 +223,27 @@ out:
return 0;
}
static inline int try_add_page(struct page_pipe *pp, unsigned long addr)
static inline int try_add_page(struct page_pipe *pp, unsigned long addr,
unsigned int flags)
{
BUG_ON(list_empty(&pp->bufs));
return try_add_page_to(pp, list_entry(pp->bufs.prev, struct page_pipe_buf, l), addr);
return try_add_page_to(pp, list_entry(pp->bufs.prev, struct page_pipe_buf, l), addr, flags);
}
int page_pipe_add_page(struct page_pipe *pp, unsigned long addr)
int page_pipe_add_page(struct page_pipe *pp, unsigned long addr,
unsigned int flags)
{
int ret;
ret = try_add_page(pp, addr);
ret = try_add_page(pp, addr, flags);
if (ret <= 0)
return ret;
ret = page_pipe_grow(pp);
ret = page_pipe_grow(pp, flags);
if (ret < 0)
return ret;
ret = try_add_page(pp, addr);
ret = try_add_page(pp, addr, flags);
BUG_ON(ret > 0);
return ret;
}
......@@ -277,8 +284,8 @@ void debug_show_page_pipe(struct page_pipe *pp)
pr_debug("* %u pipes %u/%u iovs:\n",
pp->nr_pipes, pp->free_iov, pp->nr_iovs);
list_for_each_entry(ppb, &pp->bufs, l) {
pr_debug("\tbuf %u pages, %u iovs:\n",
ppb->pages_in, ppb->nr_segs);
pr_debug("\tbuf %u pages, %u iovs, flags: %x :\n",
ppb->pages_in, ppb->nr_segs, ppb->flags);
for (i = 0; i < ppb->nr_segs; i++) {
iov = &ppb->iov[i];
pr_debug("\t\t%p %lu\n", iov->iov_base,
......
......@@ -713,7 +713,7 @@ again:
else if (xfer.parent && page_in_parent(pgstate == PST_DIRTY))
ret = page_pipe_add_hole(pp, pgaddr);
else
ret = page_pipe_add_page(pp, pgaddr);
ret = page_pipe_add_page(pp, pgaddr, 0);
if (ret == -EAGAIN) {
ret = dump_pages(pp, &xfer, addr);
......
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