[CRIU] [PATCH v6 7/9] criu: add ability to skip writing lazy pages
Mike Rapoport
rppt at linux.vnet.ibm.com
Thu Jul 14 05:49:34 PDT 2016
When appropriate, the lazy pages will no be written to the destination.
Instead, a pagemap entry for range of such pages will be marked with 'lazy'
flag.
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
criu/cr-dump.c | 2 +-
criu/include/page-xfer.h | 2 +-
criu/include/stats.h | 1 +
criu/mem.c | 16 ++++++++++------
criu/page-xfer.c | 14 +++++++++++++-
criu/pagemap.c | 2 +-
criu/shmem.c | 2 +-
criu/stats.c | 1 +
images/pagemap.proto | 1 +
images/stats.proto | 1 +
10 files changed, 31 insertions(+), 11 deletions(-)
diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 2c0aacb..e7d7847 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -1458,7 +1458,7 @@ static int cr_pre_dump_finish(int ret)
if (ret < 0)
goto err;
- ret = page_xfer_dump_pages(&xfer, ctl->mem_pp, 0);
+ ret = page_xfer_dump_pages(&xfer, ctl->mem_pp, 0, true);
xfer.close(&xfer);
diff --git a/criu/include/page-xfer.h b/criu/include/page-xfer.h
index 3ba61ed..f92d357 100644
--- a/criu/include/page-xfer.h
+++ b/criu/include/page-xfer.h
@@ -38,7 +38,7 @@ struct page_xfer {
extern int open_page_xfer(struct page_xfer *xfer, int fd_type, long id);
struct page_pipe;
extern int page_xfer_dump_pages(struct page_xfer *, struct page_pipe *,
- unsigned long off);
+ unsigned long off, bool dump_lazy);
extern int connect_to_page_server(void);
extern int disconnect_from_page_server(void);
diff --git a/criu/include/stats.h b/criu/include/stats.h
index c0effa7..5d71778 100644
--- a/criu/include/stats.h
+++ b/criu/include/stats.h
@@ -26,6 +26,7 @@ enum {
CNT_PAGES_SKIPPED_PARENT,
CNT_PAGES_WRITTEN,
CNT_PAGES_ZERO,
+ CNT_PAGES_LAZY,
DUMP_CNT_NR_STATS,
};
diff --git a/criu/mem.c b/criu/mem.c
index 455d75f..da85280 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -141,7 +141,7 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
{
u64 *at = &map[PAGE_PFN(*off)];
unsigned long pfn, nr_to_scan;
- unsigned long pages[3] = {};
+ unsigned long pages[4] = {};
nr_to_scan = (vma_area_len(vma) - *off) / PAGE_SIZE;
@@ -173,7 +173,10 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
pages[1]++;
} else {
ret = page_pipe_add_page(pp, vaddr, ppb_flags);
- pages[2]++;
+ if (ppb_flags & PPB_LAZY)
+ pages[2]++;
+ else
+ pages[3]++;
}
if (ret) {
@@ -187,10 +190,11 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
cnt_add(CNT_PAGES_SCANNED, nr_to_scan);
cnt_add(CNT_PAGES_ZERO, pages[0]);
cnt_add(CNT_PAGES_SKIPPED_PARENT, pages[1]);
- cnt_add(CNT_PAGES_WRITTEN, pages[2]);
+ cnt_add(CNT_PAGES_LAZY, pages[2]);
+ cnt_add(CNT_PAGES_WRITTEN, pages[3]);
- pr_info("Pagemap generated: %lu pages %lu holes %lu zeros\n",
- pages[2], pages[1], pages[0]);
+ pr_info("Pagemap generated: %lu pages (%lu lazy) %lu holes %lu zeros\n",
+ pages[3] + pages[2], pages[2], pages[1], pages[0]);
return 0;
}
@@ -264,7 +268,7 @@ static int dump_pages(struct page_pipe *pp, struct parasite_ctl *ctl,
*/
if (xfer) {
timing_start(TIME_MEMWRITE);
- ret = page_xfer_dump_pages(xfer, pp, 0);
+ ret = page_xfer_dump_pages(xfer, pp, 0, true);
timing_stop(TIME_MEMWRITE);
}
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index 5b61a3f..b4408c7 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -38,6 +38,7 @@ static void psi2iovec(struct page_server_iov *ps, struct iovec *iov)
#define PS_IOV_OPEN2 4
#define PS_IOV_PARENT 5
#define PS_IOV_ZERO 6
+#define PS_IOV_LAZY 7
#define PS_IOV_FLUSH 0x1023
#define PS_IOV_FLUSH_N_CLOSE 0x1024
@@ -251,6 +252,10 @@ static int write_hole_loc(struct page_xfer *xfer, struct iovec *iov, int type)
pe.has_zero = true;
pe.zero = true;
break;
+ case PS_IOV_LAZY:
+ pe.has_lazy = true;
+ pe.lazy = true;
+ break;
default:
return -1;
}
@@ -398,7 +403,7 @@ static int dump_holes(struct page_xfer *xfer, struct page_pipe *pp,
}
int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
- unsigned long off)
+ unsigned long off, bool dump_lazy)
{
struct page_pipe_buf *ppb;
unsigned int cur_hole = 0;
@@ -423,6 +428,12 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
pr_debug("\tp %p [%u]\n", iov.iov_base,
(unsigned int)(iov.iov_len / PAGE_SIZE));
+ if (!dump_lazy && ppb->flags & PPB_LAZY) {
+ if (xfer->write_hole(xfer, &iov, PS_IOV_LAZY))
+ return -1;
+ continue;
+ }
+
if (xfer->write_pagemap(xfer, &iov))
return -1;
if (xfer->write_pages(xfer, ppb->p[0], iov.iov_len))
@@ -674,6 +685,7 @@ static int page_server_serve(int sk)
break;
case PS_IOV_HOLE:
case PS_IOV_ZERO:
+ case PS_IOV_LAZY:
ret = page_server_hole(sk, &pi);
break;
case PS_IOV_FLUSH:
diff --git a/criu/pagemap.c b/criu/pagemap.c
index 2416259..0b9d95b 100644
--- a/criu/pagemap.c
+++ b/criu/pagemap.c
@@ -160,7 +160,7 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
return;
pr_debug("\tpr%u Skip %lu bytes from page-dump\n", pr->id, len);
- if (!pr->pe->in_parent && !pr->pe->zero)
+ if (!pr->pe->in_parent && !pr->pe->zero && !pr->pe->lazy)
pr->pi_off += len;
pr->cvaddr += len;
}
diff --git a/criu/shmem.c b/criu/shmem.c
index c4a58e5..67e32a4 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -522,7 +522,7 @@ static int dump_pages(struct page_pipe *pp, struct page_xfer *xfer, void *addr)
return -1;
}
- return page_xfer_dump_pages(xfer, pp, (unsigned long)addr);
+ return page_xfer_dump_pages(xfer, pp, (unsigned long)addr, true);
}
static int dump_one_shmem(struct shmem_info *si)
diff --git a/criu/stats.c b/criu/stats.c
index c01e010..a575e77 100644
--- a/criu/stats.c
+++ b/criu/stats.c
@@ -123,6 +123,7 @@ void write_stats(int what)
ds_entry.pages_skipped_parent = dstats->counts[CNT_PAGES_SKIPPED_PARENT];
ds_entry.pages_written = dstats->counts[CNT_PAGES_WRITTEN];
ds_entry.pages_zero = dstats->counts[CNT_PAGES_ZERO];
+ ds_entry.pages_lazy = dstats->counts[CNT_PAGES_LAZY];
name = "dump";
} else if (what == RESTORE_STATS) {
diff --git a/images/pagemap.proto b/images/pagemap.proto
index 0008162..8b0092f 100644
--- a/images/pagemap.proto
+++ b/images/pagemap.proto
@@ -11,4 +11,5 @@ message pagemap_entry {
required uint32 nr_pages = 2;
optional bool in_parent = 3;
optional bool zero = 4;
+ optional bool lazy = 5;
}
diff --git a/images/stats.proto b/images/stats.proto
index c099eb1..f926a5a 100644
--- a/images/stats.proto
+++ b/images/stats.proto
@@ -14,6 +14,7 @@ message dump_stats_entry {
optional uint32 irmap_resolve = 8;
required uint64 pages_zero = 9;
+ required uint64 pages_lazy = 10;
}
message restore_stats_entry {
--
1.9.1
More information about the CRIU
mailing list