[CRIU] [PATCH v4 02/12] criu: page_pipe_buf: add PPB_LAZY flag
Mike Rapoport
rppt at linux.vnet.ibm.com
Sun Jun 5 23:27:35 PDT 2016
for buffers that contain potentially lazy pages
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
criu/include/page-pipe.h | 5 ++++-
criu/mem.c | 6 +++++-
criu/page-pipe.c | 35 +++++++++++++++++++++--------------
criu/shmem.c | 2 +-
4 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/criu/include/page-pipe.h b/criu/include/page-pipe.h
index a2dc268..031f145 100644
--- a/criu/include/page-pipe.h
+++ b/criu/include/page-pipe.h
@@ -74,6 +74,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 */
};
@@ -98,7 +100,8 @@ struct page_pipe {
extern struct page_pipe *create_page_pipe(unsigned int nr,
struct iovec *, bool chunk_mode);
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);
diff --git a/criu/mem.c b/criu/mem.c
index fbcc77d..a44ad69 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -142,6 +142,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]))
@@ -149,6 +150,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
@@ -160,7 +164,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]++;
}
diff --git a/criu/page-pipe.c b/criu/page-pipe.c
index aad5905..ccafea0 100644
--- a/criu/page-pipe.c
+++ b/criu/page-pipe.c
@@ -55,10 +55,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;
}
@@ -79,7 +81,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;
@@ -99,7 +101,7 @@ static int page_pipe_grow(struct page_pipe *pp)
return -1;
out:
- ppb_init(ppb, 0, 0, &pp->iovs[pp->free_iov]);
+ ppb_init(ppb, 0, 0, flags, &pp->iovs[pp->free_iov]);
return 0;
}
@@ -126,7 +128,7 @@ struct page_pipe *create_page_pipe(unsigned int nr_segs,
pp->chunk_mode = chunk_mode;
- if (page_pipe_grow(pp))
+ if (page_pipe_grow(pp, 0))
return NULL;
}
@@ -159,13 +161,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;
@@ -197,25 +202,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;
}
@@ -255,8 +262,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, iov->iov_len / PAGE_SIZE);
diff --git a/criu/shmem.c b/criu/shmem.c
index d3ad1a8..d9dd405 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -598,7 +598,7 @@ static int dump_one_shmem(struct shmem_info *si)
if (!(map[pfn] & PAGE_RSS))
continue;
again:
- ret = page_pipe_add_page(pp, (unsigned long)addr + pfn * PAGE_SIZE);
+ ret = page_pipe_add_page(pp, (unsigned long)addr + pfn * PAGE_SIZE, 0);
if (ret == -EAGAIN) {
ret = dump_pages(pp, &xfer, addr);
if (ret)
--
1.9.1
More information about the CRIU
mailing list