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)
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);
......
......@@ -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);
......
......@@ -26,6 +26,7 @@ enum {
CNT_PAGES_SKIPPED_PARENT,
CNT_PAGES_WRITTEN,
CNT_PAGES_ZERO,
CNT_PAGES_LAZY,
DUMP_CNT_NR_STATS,
};
......
......@@ -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;
......
......@@ -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:
......
......@@ -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;
}
......
......@@ -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,
......
......@@ -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) {
......
......@@ -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;
}
......@@ -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 {
......
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