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 { ...@@ -95,6 +95,8 @@ struct page_pipe_buf {
unsigned int pipe_size; /* how many pages can be fit into pipe */ unsigned int pipe_size; /* how many pages can be fit into pipe */
unsigned int pages_in; /* how many pages are there */ unsigned int pages_in; /* how many pages are there */
unsigned int nr_segs; /* how many iov-s are busy */ 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 iovec *iov; /* vaddr:len map */
struct list_head l; /* links into page_pipe->bufs */ struct list_head l; /* links into page_pipe->bufs */
}; };
...@@ -120,7 +122,8 @@ struct page_pipe { ...@@ -120,7 +122,8 @@ struct page_pipe {
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,
unsigned int flags);
extern int page_pipe_add_hole(struct page_pipe *p, unsigned long addr); extern int page_pipe_add_hole(struct page_pipe *p, unsigned long addr);
extern void debug_show_page_pipe(struct page_pipe *pp); 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 ...@@ -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++) { for (pfn = 0; pfn < nr_to_scan; pfn++) {
unsigned long vaddr; unsigned long vaddr;
unsigned int ppb_flags = 0;
int ret; int ret;
if (!should_dump_page(vma->e, at[pfn])) 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 ...@@ -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; 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 * If we're doing incremental dump (parent images
* specified) and page is not soft-dirty -- we dump * 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 ...@@ -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); ret = page_pipe_add_hole(pp, vaddr);
pages[0]++; pages[0]++;
} else { } else {
ret = page_pipe_add_page(pp, vaddr); ret = page_pipe_add_page(pp, vaddr, ppb_flags);
pages[1]++; pages[1]++;
} }
......
...@@ -57,10 +57,12 @@ static void ppb_destroy(struct page_pipe_buf *ppb) ...@@ -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, 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->pages_in = pages_in;
ppb->nr_segs = nr_segs; ppb->nr_segs = nr_segs;
ppb->flags = flags;
ppb->iov = iov; ppb->iov = iov;
} }
...@@ -81,7 +83,7 @@ static int ppb_resize_pipe(struct page_pipe_buf *ppb, unsigned long new_size) ...@@ -81,7 +83,7 @@ static int ppb_resize_pipe(struct page_pipe_buf *ppb, unsigned long new_size)
return 0; 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 page_pipe_buf *ppb;
struct iovec *free_iov; struct iovec *free_iov;
...@@ -103,7 +105,7 @@ static int page_pipe_grow(struct page_pipe *pp) ...@@ -103,7 +105,7 @@ static int page_pipe_grow(struct page_pipe *pp)
out: out:
free_iov = &pp->iovs[pp->free_iov]; free_iov = &pp->iovs[pp->free_iov];
ppb_init(ppb, 0, 0, free_iov); ppb_init(ppb, 0, 0, flags, free_iov);
return 0; return 0;
} }
...@@ -139,7 +141,7 @@ struct page_pipe *create_page_pipe(unsigned int nr_segs, struct iovec *iovs, uns ...@@ -139,7 +141,7 @@ struct page_pipe *create_page_pipe(unsigned int nr_segs, struct iovec *iovs, uns
pp->free_hole = 0; pp->free_hole = 0;
pp->holes = NULL; pp->holes = NULL;
if (page_pipe_grow(pp)) if (page_pipe_grow(pp, 0))
goto err_free_iovs; goto err_free_iovs;
return pp; return pp;
...@@ -180,13 +182,16 @@ void page_pipe_reinit(struct page_pipe *pp) ...@@ -180,13 +182,16 @@ void page_pipe_reinit(struct page_pipe *pp)
pp->free_hole = 0; 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 */ 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, 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) { if (ppb->pages_in == ppb->pipe_size) {
unsigned long new_size = ppb->pipe_size << 1; unsigned long new_size = ppb->pipe_size << 1;
int ret; int ret;
...@@ -218,25 +223,27 @@ out: ...@@ -218,25 +223,27 @@ out:
return 0; 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)); 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; int ret;
ret = try_add_page(pp, addr); ret = try_add_page(pp, addr, flags);
if (ret <= 0) if (ret <= 0)
return ret; return ret;
ret = page_pipe_grow(pp); ret = page_pipe_grow(pp, flags);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = try_add_page(pp, addr); ret = try_add_page(pp, addr, flags);
BUG_ON(ret > 0); BUG_ON(ret > 0);
return ret; return ret;
} }
...@@ -277,8 +284,8 @@ void debug_show_page_pipe(struct page_pipe *pp) ...@@ -277,8 +284,8 @@ void debug_show_page_pipe(struct page_pipe *pp)
pr_debug("* %u pipes %u/%u iovs:\n", pr_debug("* %u pipes %u/%u iovs:\n",
pp->nr_pipes, pp->free_iov, pp->nr_iovs); pp->nr_pipes, pp->free_iov, pp->nr_iovs);
list_for_each_entry(ppb, &pp->bufs, l) { list_for_each_entry(ppb, &pp->bufs, l) {
pr_debug("\tbuf %u pages, %u iovs:\n", pr_debug("\tbuf %u pages, %u iovs, flags: %x :\n",
ppb->pages_in, ppb->nr_segs); ppb->pages_in, ppb->nr_segs, ppb->flags);
for (i = 0; i < ppb->nr_segs; i++) { for (i = 0; i < ppb->nr_segs; i++) {
iov = &ppb->iov[i]; iov = &ppb->iov[i];
pr_debug("\t\t%p %lu\n", iov->iov_base, pr_debug("\t\t%p %lu\n", iov->iov_base,
......
...@@ -713,7 +713,7 @@ again: ...@@ -713,7 +713,7 @@ again:
else if (xfer.parent && page_in_parent(pgstate == PST_DIRTY)) else if (xfer.parent && page_in_parent(pgstate == PST_DIRTY))
ret = page_pipe_add_hole(pp, pgaddr); ret = page_pipe_add_hole(pp, pgaddr);
else else
ret = page_pipe_add_page(pp, pgaddr); ret = page_pipe_add_page(pp, pgaddr, 0);
if (ret == -EAGAIN) { if (ret == -EAGAIN) {
ret = dump_pages(pp, &xfer, addr); 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