[CRIU] [PATCH RFC 2/8] criu: page_pipe_buf: add PPB_LAZY flag
Mike Rapoport
rppt at linux.vnet.ibm.com
Sat May 21 03:49:36 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 | 30 ++++++++++++++++++------------
criu/shmem.c | 2 +-
4 files changed, 28 insertions(+), 15 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 becbd6d..0497975 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -137,6 +137,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]))
@@ -144,6 +145,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
@@ -155,7 +159,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 db58f6a..78f8271 100644
--- a/criu/page-pipe.c
+++ b/criu/page-pipe.c
@@ -25,7 +25,7 @@ static inline void iov_init(struct iovec *iov, unsigned long addr)
iov->iov_len = PAGE_SIZE;
}
-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;
@@ -57,6 +57,7 @@ static int page_pipe_grow(struct page_pipe *pp)
out:
ppb->pages_in = 0;
ppb->nr_segs = 0;
+ ppb->flags = flags;
ppb->iov = &pp->iovs[pp->free_iov];
return 0;
@@ -84,7 +85,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;
}
@@ -120,13 +121,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;
@@ -164,25 +168,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;
}
@@ -222,8 +228,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 493477e..05458c7 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -405,7 +405,7 @@ static int dump_one_shmem(struct shmem_info_dump *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