[CRIU] [PATCH 2/6] criu: pagemap: introduce advance() helper for pagemap iteration
Mike Rapoport
rppt at linux.vnet.ibm.com
Thu Sep 8 00:39:08 PDT 2016
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
criu/pagemap.c | 72 +++++++++++++++++++++++++---------------------------------
criu/uffd.c | 3 +++
2 files changed, 34 insertions(+), 41 deletions(-)
diff --git a/criu/pagemap.c b/criu/pagemap.c
index d8fe5b0..47c6788 100644
--- a/criu/pagemap.c
+++ b/criu/pagemap.c
@@ -121,31 +121,34 @@ int dedup_one_iovec(struct page_read *pr, struct iovec *iov)
return 0;
}
-static int get_pagemap(struct page_read *pr, struct iovec *iov)
+static int advance(struct page_read *pr)
{
- PagemapEntry *pe;
+ pr->curr_pme++;
+ if (pr->curr_pme >= pr->nr_pmes)
+ return 0;
- for (;;) {
- pr->curr_pme++;
- if (pr->curr_pme >= pr->nr_pmes)
- return 0;
+ pr->pe = pr->pmes[pr->curr_pme];
+ pr->cvaddr = pr->pe->vaddr;
- pe = pr->pmes[pr->curr_pme];
+ return 1;
+}
- if (!pe->zero)
+static int get_pagemap(struct page_read *pr, struct iovec *iov)
+{
+ for (;;) {
+ if (!advance(pr))
+ return 0;
+ if (!pr->pe->zero)
break;
}
- pagemap2iovec(pe, iov);
-
- pr->pe = pe;
- pr->cvaddr = (unsigned long)iov->iov_base;
-
- if (pe->in_parent && !pr->parent) {
+ if (pr->pe->in_parent && !pr->parent) {
pr_err("No parent for snapshot pagemap\n");
return -1;
}
+ pagemap2iovec(pr->pe, iov);
+
return 1;
}
@@ -163,38 +166,25 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr,
bool warn)
{
- int ret;
- struct iovec iov;
-
- if (pr->pe)
- pagemap2iovec(pr->pe, &iov);
- else
- goto new_pagemap;
+ pr->reset(pr);
- while (1) {
- unsigned long iov_end;
+ while (advance(pr)) {
+ unsigned long start = pr->pe->vaddr;
+ unsigned long len = pr->pe->nr_pages * PAGE_SIZE;
+ unsigned long end = start + len;
- if (vaddr < pr->cvaddr) {
- if (warn)
- pr_err("Missing %lx in parent pagemap, current iov: base=%lx,len=%zu\n",
- vaddr, (unsigned long)iov.iov_base, iov.iov_len);
- return 0;
+ if (vaddr >= start && vaddr < end) {
+ skip_pagemap_pages(pr, vaddr - pr->cvaddr);
+ return 1;
}
- iov_end = (unsigned long)iov.iov_base + iov.iov_len;
- if (iov_end <= vaddr) {
- skip_pagemap_pages(pr, iov_end - pr->cvaddr);
-new_pagemap:
- ret = get_pagemap(pr, &iov);
- if (ret <= 0)
- return ret;
-
- continue;
- }
-
- skip_pagemap_pages(pr, vaddr - pr->cvaddr);
- return 1;
+ if (end <= vaddr)
+ skip_pagemap_pages(pr, end - pr->cvaddr);
}
+
+ if (warn)
+ pr_err("Missing %lx in parent pagemap\n", vaddr);
+ return 0;
}
static inline void pagemap_bound_check(PagemapEntry *pe, unsigned long vaddr, int nr)
diff --git a/criu/uffd.c b/criu/uffd.c
index 97cacea..ebb0e8e 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -372,6 +372,9 @@ static int get_page(struct lazy_pages_info *lpi, unsigned long addr, void *dest)
if (ret <= 0)
return ret;
+ if (lpi->pr.pe->zero)
+ return 0;
+
ret = lpi->pr.read_pages(&lpi->pr, addr, 1, buf);
pr_debug("read_pages ret %d\n", ret);
if (ret <= 0)
--
1.9.1
More information about the CRIU
mailing list