[CRIU] [RFC PATCH v2 05/23] lazy-pages: use lazy_iov'ecs to search for pages
Mike Rapoport
rppt at linux.vnet.ibm.com
Mon Feb 6 03:43:58 PST 2017
Currently we use pagemap to check if we should copy a page into process
address space or zero it. The lazy_iov'ecs can be used instead. If a
lazy_iov covers the faulting address, we should go ahead and read the page
and copy it. If there is not lazy_iov for the faulting address, just zero
it immediately.
Searching lazy_iov's rather than pagemap will also simplify upcoming
handling of UFFD_EVENT_REMAP.
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
criu/uffd.c | 32 +++++++++++++++++++++++++-------
1 file changed, 25 insertions(+), 7 deletions(-)
diff --git a/criu/uffd.c b/criu/uffd.c
index 9f257c3..c767475 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -309,6 +309,18 @@ static MmEntry *init_mm_entry(struct lazy_pages_info *lpi)
return mm;
}
+static struct lazy_iov *find_lazy_iov(struct lazy_pages_info *lpi,
+ unsigned long addr)
+{
+ struct lazy_iov *iov;
+
+ list_for_each_entry(iov, &lpi->iovs, l)
+ if (addr >= iov->base && addr < iov->base + iov->len)
+ return iov;
+
+ return NULL;
+}
+
/*
* Purge range (addr, addr + len) from lazy_iovs. The range may
* cover several continuous IOVs.
@@ -597,28 +609,29 @@ static int uffd_zero(struct lazy_pages_info *lpi, __u64 address, int nr_pages)
* Returns 0 for zero pages, 1 for "real" pages and negative value on
* error
*/
-static int uffd_seek_or_zero_pages(struct lazy_pages_info *lpi, __u64 address,
- int nr)
+static int uffd_seek_pages(struct lazy_pages_info *lpi, __u64 address, int nr)
{
int ret;
lpi->pr.reset(&lpi->pr);
ret = lpi->pr.seek_pagemap(&lpi->pr, address);
- if (!ret)
- return uffd_zero(lpi, address, nr);
+ if (!ret) {
+ pr_err("%d: no pagemap covers %llx\n", lpi->pid, address);
+ return ret;
+ }
lpi->pr.skip_pages(&lpi->pr, address - lpi->pr.pe->vaddr);
- return 1;
+ return 0;
}
static int uffd_handle_pages(struct lazy_pages_info *lpi, __u64 address, int nr, unsigned flags)
{
int ret;
- ret = uffd_seek_or_zero_pages(lpi, address, nr);
- if (ret <= 0)
+ ret = uffd_seek_pages(lpi, address, nr);
+ if (ret)
return ret;
ret = lpi->pr.read_pages(&lpi->pr, address, nr, lpi->buf, flags);
@@ -653,6 +666,7 @@ static int handle_remaining_pages(struct lazy_pages_info *lpi)
static int handle_page_fault(struct lazy_pages_info *lpi, struct uffd_msg *msg)
{
struct lp_req *req;
+ struct lazy_iov *iov;
__u64 address;
int ret;
@@ -664,6 +678,10 @@ static int handle_page_fault(struct lazy_pages_info *lpi, struct uffd_msg *msg)
if (req->addr == address)
return 0;
+ iov = find_lazy_iov(lpi, address);
+ if (!iov)
+ return uffd_zero(lpi, address, 1);
+
req = xzalloc(sizeof(*req));
if (!req)
return -1;
--
1.9.1
More information about the CRIU
mailing list