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

Submitted by Pavel Emelianov on Nov. 16, 2016, 9:39 a.m.

Details

Message ID 582C2964.4040804@virtuozzo.com
State Superseded
Headers show

Commit Message

Pavel Emelianov Nov. 16, 2016, 9:39 a.m.
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@virtuozzo.com>
---
 criu/include/pagemap.h |  1 +
 criu/pagemap.c         | 11 ++++++++++-
 criu/uffd.c            | 19 ++++++++++++++-----
 3 files changed, 25 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

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)

Comments

Mike Rapoport Nov. 16, 2016, 10:55 a.m.
On Wed, Nov 16, 2016 at 11:39 AM, Pavel Emelyanov <xemul@virtuozzo.com> wrote:
> 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@virtuozzo.com>
> ---

Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.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
>