From a9a973da77dab9ad6f3741fd8a2cfd7ea614186e Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Thu, 14 Jul 2016 15:49:34 +0300 Subject: [PATCH] criu: add ability to skip writing lazy pages 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 Signed-off-by: Pavel Emelyanov --- 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 f9ff0f468..7a5eecee8 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -1483,7 +1483,7 @@ static int cr_pre_dump_finish(int ret) goto err; mem_pp = dmpi(item)->mem_pp; - ret = page_xfer_dump_pages(&xfer, mem_pp, 0); + ret = page_xfer_dump_pages(&xfer, mem_pp, 0, true); xfer.close(&xfer); diff --git a/criu/include/page-xfer.h b/criu/include/page-xfer.h index 3ba61ed74..f92d357b7 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 c0effa7a1..5d7177815 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 afdce7352..49e58cbd8 100644 --- a/criu/mem.c +++ b/criu/mem.c @@ -143,7 +143,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; @@ -175,7 +175,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) { @@ -189,10 +192,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; } @@ -272,7 +276,7 @@ static int xfer_pages(struct page_pipe *pp, struct page_xfer *xfer) * pre-dump action (see pre_dump_one_task) */ 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); return ret; diff --git a/criu/page-xfer.c b/criu/page-xfer.c index 23e00853b..c77b2d0e8 100644 --- a/criu/page-xfer.c +++ b/criu/page-xfer.c @@ -39,6 +39,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 @@ -305,6 +306,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; } @@ -439,7 +444,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; @@ -464,6 +469,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)) @@ -740,6 +751,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 a2c07de3c..206fcd376 100644 --- a/criu/pagemap.c +++ b/criu/pagemap.c @@ -144,7 +144,7 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len) if (!len) return; - 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 6facf0621..e8aeee867 100644 --- a/criu/shmem.c +++ b/criu/shmem.c @@ -640,7 +640,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 next_data_segment(int fd, unsigned long pfn, diff --git a/criu/stats.c b/criu/stats.c index 7caabf18c..3fef9c472 100644 --- a/criu/stats.c +++ b/criu/stats.c @@ -158,6 +158,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 00081620c..8b0092f72 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 c099eb1e9..f926a5a89 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 {