Commit a9a973da authored by Mike Rapoport's avatar Mike Rapoport Committed by Andrei Vagin

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: 's avatarMike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent a1ed9e09
...@@ -1483,7 +1483,7 @@ static int cr_pre_dump_finish(int ret) ...@@ -1483,7 +1483,7 @@ static int cr_pre_dump_finish(int ret)
goto err; goto err;
mem_pp = dmpi(item)->mem_pp; 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); xfer.close(&xfer);
......
...@@ -38,7 +38,7 @@ struct page_xfer { ...@@ -38,7 +38,7 @@ struct page_xfer {
extern int open_page_xfer(struct page_xfer *xfer, int fd_type, long id); extern int open_page_xfer(struct page_xfer *xfer, int fd_type, long id);
struct page_pipe; struct page_pipe;
extern int page_xfer_dump_pages(struct page_xfer *, 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 connect_to_page_server(void);
extern int disconnect_from_page_server(void); extern int disconnect_from_page_server(void);
......
...@@ -26,6 +26,7 @@ enum { ...@@ -26,6 +26,7 @@ enum {
CNT_PAGES_SKIPPED_PARENT, CNT_PAGES_SKIPPED_PARENT,
CNT_PAGES_WRITTEN, CNT_PAGES_WRITTEN,
CNT_PAGES_ZERO, CNT_PAGES_ZERO,
CNT_PAGES_LAZY,
DUMP_CNT_NR_STATS, DUMP_CNT_NR_STATS,
}; };
......
...@@ -143,7 +143,7 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u ...@@ -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)]; u64 *at = &map[PAGE_PFN(*off)];
unsigned long pfn, nr_to_scan; unsigned long pfn, nr_to_scan;
unsigned long pages[3] = {}; unsigned long pages[4] = {};
nr_to_scan = (vma_area_len(vma) - *off) / PAGE_SIZE; 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 ...@@ -175,7 +175,10 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
pages[1]++; pages[1]++;
} else { } else {
ret = page_pipe_add_page(pp, vaddr, ppb_flags); ret = page_pipe_add_page(pp, vaddr, ppb_flags);
pages[2]++; if (ppb_flags & PPB_LAZY)
pages[2]++;
else
pages[3]++;
} }
if (ret) { if (ret) {
...@@ -189,10 +192,11 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u ...@@ -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_SCANNED, nr_to_scan);
cnt_add(CNT_PAGES_ZERO, pages[0]); cnt_add(CNT_PAGES_ZERO, pages[0]);
cnt_add(CNT_PAGES_SKIPPED_PARENT, pages[1]); 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", pr_info("Pagemap generated: %lu pages (%lu lazy) %lu holes %lu zeros\n",
pages[2], pages[1], pages[0]); pages[3] + pages[2], pages[2], pages[1], pages[0]);
return 0; return 0;
} }
...@@ -272,7 +276,7 @@ static int xfer_pages(struct page_pipe *pp, struct page_xfer *xfer) ...@@ -272,7 +276,7 @@ static int xfer_pages(struct page_pipe *pp, struct page_xfer *xfer)
* pre-dump action (see pre_dump_one_task) * pre-dump action (see pre_dump_one_task)
*/ */
timing_start(TIME_MEMWRITE); 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); timing_stop(TIME_MEMWRITE);
return ret; return ret;
......
...@@ -39,6 +39,7 @@ static void psi2iovec(struct page_server_iov *ps, struct iovec *iov) ...@@ -39,6 +39,7 @@ static void psi2iovec(struct page_server_iov *ps, struct iovec *iov)
#define PS_IOV_OPEN2 4 #define PS_IOV_OPEN2 4
#define PS_IOV_PARENT 5 #define PS_IOV_PARENT 5
#define PS_IOV_ZERO 6 #define PS_IOV_ZERO 6
#define PS_IOV_LAZY 7
#define PS_IOV_FLUSH 0x1023 #define PS_IOV_FLUSH 0x1023
#define PS_IOV_FLUSH_N_CLOSE 0x1024 #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) ...@@ -305,6 +306,10 @@ static int write_hole_loc(struct page_xfer *xfer, struct iovec *iov, int type)
pe.has_zero = true; pe.has_zero = true;
pe.zero = true; pe.zero = true;
break; break;
case PS_IOV_LAZY:
pe.has_lazy = true;
pe.lazy = true;
break;
default: default:
return -1; return -1;
} }
...@@ -439,7 +444,7 @@ static int dump_holes(struct page_xfer *xfer, struct page_pipe *pp, ...@@ -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, 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; struct page_pipe_buf *ppb;
unsigned int cur_hole = 0; unsigned int cur_hole = 0;
...@@ -464,6 +469,12 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp, ...@@ -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, pr_debug("\tp %p [%u]\n", iov.iov_base,
(unsigned int)(iov.iov_len / PAGE_SIZE)); (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)) if (xfer->write_pagemap(xfer, &iov))
return -1; return -1;
if (xfer->write_pages(xfer, ppb->p[0], iov.iov_len)) if (xfer->write_pages(xfer, ppb->p[0], iov.iov_len))
...@@ -740,6 +751,7 @@ static int page_server_serve(int sk) ...@@ -740,6 +751,7 @@ static int page_server_serve(int sk)
break; break;
case PS_IOV_HOLE: case PS_IOV_HOLE:
case PS_IOV_ZERO: case PS_IOV_ZERO:
case PS_IOV_LAZY:
ret = page_server_hole(sk, &pi); ret = page_server_hole(sk, &pi);
break; break;
case PS_IOV_FLUSH: case PS_IOV_FLUSH:
......
...@@ -144,7 +144,7 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len) ...@@ -144,7 +144,7 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
if (!len) if (!len)
return; 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->pi_off += len;
pr->cvaddr += len; pr->cvaddr += len;
} }
......
...@@ -640,7 +640,7 @@ static int dump_pages(struct page_pipe *pp, struct page_xfer *xfer, void *addr) ...@@ -640,7 +640,7 @@ static int dump_pages(struct page_pipe *pp, struct page_xfer *xfer, void *addr)
return -1; 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, static int next_data_segment(int fd, unsigned long pfn,
......
...@@ -158,6 +158,7 @@ void write_stats(int what) ...@@ -158,6 +158,7 @@ void write_stats(int what)
ds_entry.pages_skipped_parent = dstats->counts[CNT_PAGES_SKIPPED_PARENT]; ds_entry.pages_skipped_parent = dstats->counts[CNT_PAGES_SKIPPED_PARENT];
ds_entry.pages_written = dstats->counts[CNT_PAGES_WRITTEN]; ds_entry.pages_written = dstats->counts[CNT_PAGES_WRITTEN];
ds_entry.pages_zero = dstats->counts[CNT_PAGES_ZERO]; ds_entry.pages_zero = dstats->counts[CNT_PAGES_ZERO];
ds_entry.pages_lazy = dstats->counts[CNT_PAGES_LAZY];
name = "dump"; name = "dump";
} else if (what == RESTORE_STATS) { } else if (what == RESTORE_STATS) {
......
...@@ -11,4 +11,5 @@ message pagemap_entry { ...@@ -11,4 +11,5 @@ message pagemap_entry {
required uint32 nr_pages = 2; required uint32 nr_pages = 2;
optional bool in_parent = 3; optional bool in_parent = 3;
optional bool zero = 4; optional bool zero = 4;
optional bool lazy = 5;
} }
...@@ -14,6 +14,7 @@ message dump_stats_entry { ...@@ -14,6 +14,7 @@ message dump_stats_entry {
optional uint32 irmap_resolve = 8; optional uint32 irmap_resolve = 8;
required uint64 pages_zero = 9; required uint64 pages_zero = 9;
required uint64 pages_lazy = 10;
} }
message restore_stats_entry { message restore_stats_entry {
......
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