[CRIU] [PATCH 6/7] page-read: Callback on io completion

Pavel Emelyanov xemul at virtuozzo.com
Wed Nov 16 01:39:48 PST 2016


This one is called by PR once IO is complete (right now
for sync cases only, more work is required here) and
lets us unify local and remote PF code in uffd.

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/include/pagemap.h |  1 +
 criu/pagemap.c         | 11 ++++++++++-
 criu/uffd.c            | 19 ++++++++++++++-----
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/criu/include/pagemap.h b/criu/include/pagemap.h
index fbe8ca0..50829ae 100644
--- a/criu/include/pagemap.h
+++ b/criu/include/pagemap.h
@@ -58,6 +58,7 @@ struct page_read {
 	void (*reset)(struct page_read *pr);
 	int (*sync)(struct page_read *pr);
 
+	int (*io_complete)(struct page_read *, unsigned long vaddr, int nr);
 	int (*maybe_read_page)(struct page_read *pr, unsigned long vaddr,
 			int nr, void *buf, unsigned flags);
 
diff --git a/criu/pagemap.c b/criu/pagemap.c
index a9c37d7..f4439ec 100644
--- a/criu/pagemap.c
+++ b/criu/pagemap.c
@@ -392,8 +392,11 @@ static int maybe_read_page_local(struct page_read *pr, unsigned long vaddr,
 	 */
 	if ((flags & (PR_ASYNC|PR_ASAP)) == PR_ASYNC)
 		ret = enqueue_async_page(pr, vaddr, len, buf);
-	else
+	else {
 		ret = read_local_page(pr, vaddr, len, buf);
+		if (ret == 0 && pr->io_complete)
+			ret = pr->io_complete(pr, vaddr, nr);
+	}
 
 	pr->pi_off += len;
 
@@ -418,6 +421,9 @@ static int maybe_read_page_remote(struct page_read *pr, unsigned long vaddr,
 	if (ret == 0)
 		ret = receive_remote_pages(nr * PAGE_SIZE, buf);
 
+	if (ret == 0 && pr->io_complete)
+		ret = pr->io_complete(pr, vaddr, nr);
+
 	return ret;
 }
 
@@ -471,6 +477,8 @@ static int process_async_reads(struct page_read *pr)
 		if (opts.auto_dedup && punch_hole(pr, piov->from, ret, false))
 			return -1;
 
+		BUG_ON(pr->io_complete); /* FIXME -- implement once needed */
+
 		list_del(&piov->l);
 		xfree(piov->to);
 		xfree(piov);
@@ -700,6 +708,7 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
 	pr->seek_page = seek_pagemap_page;
 	pr->reset = reset_pagemap;
 	pr->sync = process_async_reads;
+	pr->io_complete = NULL; /* set up by the client if needed */
 	pr->id = ids++;
 	pr->pid = pid;
 
diff --git a/criu/uffd.c b/criu/uffd.c
index 93cdee7..2464588 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -476,6 +476,8 @@ free_mm:
 	return ret;
 }
 
+static int uffd_io_complete(struct page_read *pr, unsigned long vaddr, int nr);
+
 static int ud_open(int client, struct lazy_pages_info **_lpi)
 {
 	struct lazy_pages_info *lpi;
@@ -523,6 +525,8 @@ static int ud_open(int client, struct lazy_pages_info **_lpi)
 		goto out;
 	}
 
+	lpi->pr.io_complete = uffd_io_complete;
+
 	/*
 	 * Find the memory pages belonging to the restored process
 	 * so that it is trackable when all pages have been transferred.
@@ -587,6 +591,14 @@ static int complete_page_fault(struct lazy_pages_info *lpi, unsigned long vaddr,
 	return update_lazy_iovecs(lpi, vaddr, nr * PAGE_SIZE);
 }
 
+static int uffd_io_complete(struct page_read *pr, unsigned long vaddr, int nr)
+{
+	struct lazy_pages_info *lpi;
+
+	lpi = container_of(pr, struct lazy_pages_info, pr);
+	return complete_page_fault(lpi, vaddr, nr);
+}
+
 static int uffd_zero(struct lazy_pages_info *lpi, __u64 address, int nr_pages)
 {
 	struct uffdio_zeropage uffdio_zeropage;
@@ -655,7 +667,7 @@ static int uffd_handle_pages(struct lazy_pages_info *lpi, __u64 address, int nr)
 		return ret;
 	}
 
-	return complete_page_fault(lpi, address, nr);
+	return 0;
 }
 
 static int handle_remaining_pages(struct lazy_pages_info *lpi)
@@ -700,10 +712,7 @@ static int page_fault_common(struct lazy_pages_info *lpi, __u64 address, int nr,
 
 static int page_fault_local(struct lazy_pages_info *lpi, __u64 address, int nr)
 {
-	if (page_fault_common(lpi, address, nr, PR_ASYNC | PR_ASAP))
-		return -1;
-
-	return complete_page_fault(lpi, address, nr);
+	return page_fault_common(lpi, address, nr, PR_ASYNC | PR_ASAP);
 }
 
 static int page_fault_remote(struct lazy_pages_info *lpi, __u64 address, int nr)
-- 
2.5.0



More information about the CRIU mailing list