[CRIU] [PATCH 4/7] pagemap: replace seek_page with seek_pagemap method
Mike Rapoport
rppt at linux.vnet.ibm.com
Sun Nov 20 01:50:03 PST 2016
The only external users of ->seek_page method are page-xfer and uffd and
both of them are anyway interested in the entire pagemap rather than a
particular page.
The added 'skip_zero' parameter allows proper detection of zero pagemaps by
uffd.
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
criu/include/pagemap.h | 3 ++-
criu/page-xfer.c | 2 +-
criu/pagemap.c | 23 ++++++++++++++++++-----
criu/uffd.c | 11 +++++------
4 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/criu/include/pagemap.h b/criu/include/pagemap.h
index 54c147a..ea106ec 100644
--- a/criu/include/pagemap.h
+++ b/criu/include/pagemap.h
@@ -54,7 +54,8 @@ struct page_read {
int (*advance)(struct page_read *pr);
void (*close)(struct page_read *);
void (*skip_pages)(struct page_read *, unsigned long len);
- int (*seek_page)(struct page_read *pr, unsigned long vaddr);
+ int (*seek_pagemap)(struct page_read *pr, unsigned long vaddr,
+ bool skip_zero);
void (*reset)(struct page_read *pr);
int (*sync)(struct page_read *pr);
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index f308972..79008ad 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -208,7 +208,7 @@ static int check_pagehole_in_parent(struct page_read *p, struct iovec *iov)
struct iovec piov;
unsigned long pend;
- ret = p->seek_page(p, off);
+ ret = p->seek_pagemap(p, off, true);
if (ret <= 0 || !p->pe) {
pr_err("Missing %lx in parent pagemap\n", off);
return -1;
diff --git a/criu/pagemap.c b/criu/pagemap.c
index 3c2fc5c..2521e57 100644
--- a/criu/pagemap.c
+++ b/criu/pagemap.c
@@ -83,6 +83,8 @@ static int punch_hole(struct page_read *pr, unsigned long off,
return 0;
}
+static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr);
+
int dedup_one_iovec(struct page_read *pr, struct iovec *iov)
{
unsigned long off;
@@ -97,7 +99,7 @@ int dedup_one_iovec(struct page_read *pr, struct iovec *iov)
struct iovec tiov;
struct page_read * prp;
- ret = pr->seek_page(pr, off);
+ ret = seek_pagemap_page(pr, off);
if (ret == 0) {
pr_err("Missing %lx in parent pagemap\n", off);
if (off < pr->cvaddr && pr->cvaddr < iov_end)
@@ -177,7 +179,8 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
pr->cvaddr += len;
}
-static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr)
+static int seek_pagemap(struct page_read *pr, unsigned long vaddr,
+ bool skip_zero)
{
if (!pr->pe)
advance(pr);
@@ -187,14 +190,14 @@ static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr)
unsigned long len = pr->pe->nr_pages * PAGE_SIZE;
unsigned long end = start + len;
- if (pagemap_zero(pr->pe))
+ if (skip_zero && pagemap_zero(pr->pe))
continue;
if (vaddr < pr->cvaddr)
break;
if (vaddr >= start && vaddr < end) {
- skip_pagemap_pages(pr, vaddr - pr->cvaddr);
+ skip_pagemap_pages(pr, start - pr->cvaddr);
return 1;
}
@@ -205,6 +208,16 @@ static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr)
return 0;
}
+static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr)
+{
+ if (seek_pagemap(pr, vaddr, true)) {
+ skip_pagemap_pages(pr, vaddr - pr->cvaddr);
+ return 1;
+ }
+
+ return 0;
+}
+
static inline void pagemap_bound_check(PagemapEntry *pe, unsigned long vaddr, int nr)
{
if (vaddr < pe->vaddr || (vaddr - pe->vaddr) / PAGE_SIZE + nr > pe->nr_pages) {
@@ -720,7 +733,7 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
pr->advance = advance;
pr->close = close_page_read;
pr->skip_pages = skip_pagemap_pages;
- pr->seek_page = seek_pagemap_page;
+ pr->seek_pagemap = seek_pagemap;
pr->reset = reset_pagemap;
pr->sync = process_async_reads;
pr->io_complete = NULL; /* set up by the client if needed */
diff --git a/criu/uffd.c b/criu/uffd.c
index 71fed07..3e3f320 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -618,12 +618,11 @@ static int uffd_seek_or_zero_pages(struct lazy_pages_info *lpi, __u64 address,
lpi->pr.reset(&lpi->pr);
- /*
- * FIXME: rework zeroes handling so we won't need to rely on
- * seek_page return value here
- */
- ret = lpi->pr.seek_page(&lpi->pr, address);
- if (ret == 0 || pagemap_zero(lpi->pr.pe))
+ ret = lpi->pr.seek_pagemap(&lpi->pr, address, false);
+ if (!ret)
+ return 0;
+
+ if (pagemap_zero(lpi->pr.pe))
return uffd_zero(lpi, address, nr);
return 1;
--
1.9.1
More information about the CRIU
mailing list