[CRIU] [RFC PATCH 04/16] criu: lazy-pages: handle remaining pages based on IOVs rather than pages
Pavel Emelyanov
xemul at virtuozzo.com
Wed Oct 5 06:07:43 PDT 2016
On 09/27/2016 04:42 PM, Mike Rapoport wrote:
> Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
> ---
> criu/uffd.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++-----------
> 1 file changed, 70 insertions(+), 14 deletions(-)
>
> diff --git a/criu/uffd.c b/criu/uffd.c
> index 063ce4f..3f25b86 100644
> --- a/criu/uffd.c
> +++ b/criu/uffd.c
> @@ -325,6 +325,56 @@ out:
>
> static int find_vmas(struct lazy_pages_info *lpi);
>
> +static int update_lazy_iovecs(struct lazy_pages_info *lpi, unsigned long addr,
> + int len)
> +{
> + struct lazy_iovec *lazy_iov, *n;
> +
> + list_for_each_entry_safe(lazy_iov, n, &lpi->iovs, l) {
> + unsigned long start = (unsigned long)lazy_iov->iov.iov_base;
> + unsigned long end = start + lazy_iov->iov.iov_len;
> +
> + if (len <= 0)
> + break;
> +
> + if (addr < start || addr >= end)
> + continue;
> +
> + if (addr + len < end) {
> + if (addr == start) {
> + lazy_iov->iov.iov_base += len;
> + lazy_iov->iov.iov_len -= len;
> + } else {
> + struct lazy_iovec *new;
> +
> + lazy_iov->iov.iov_len -= (end - addr);
> +
> + new = xzalloc(sizeof(*new));
> + if (!new)
> + return -1;
> +
> + new->iov.iov_base = (void *)(addr + len);
> + new->iov.iov_len = end - (addr + len);
> +
> + list_add(&new->l, &lazy_iov->l);
> + }
> + break;
> + }
> +
> + if (addr == start) {
> + list_del(&lazy_iov->l);
> + xfree(lazy_iov);
> + } else {
> + lazy_iov->iov.iov_len -= (end - addr);
> + }
> +
> + len -= (end - addr);
> + addr = end;
> + }
> +
> + return 0;
> +}
> +
> static int collect_lazy_iovecs(struct lazy_pages_info *lpi)
> {
> struct page_read *pr = &lpi->pr;
> @@ -585,28 +635,30 @@ static int collect_uffd_pages(struct page_read *pr, struct lazy_pages_info *lpi)
>
> static int handle_remaining_pages(struct lazy_pages_info *lpi, void *dest)
> {
> - struct uffd_pages_struct *uffd_pages;
> - int rc;
> + struct lazy_iovec *lazy_iov;
> + int nr_pages, i, err;
> + unsigned long base, addr;
>
> - list_for_each_entry(uffd_pages, &lpi->pages, list) {
The lpi->pages list is not longer in use after this, is it?
> - pr_debug("Checking remaining pages 0x%lx (flags 0x%x)\n",
> - uffd_pages->addr, uffd_pages->flags);
> - if (uffd_pages->flags & UFFD_FLAG_SENT)
> - continue;
> + lpi->pr.reset(&lpi->pr);
>
> - rc = uffd_handle_page(lpi, uffd_pages->addr, dest);
> - if (rc < 0) {
> - pr_err("Error during UFFD copy\n");
> - return -1;
> - }
> + list_for_each_entry(lazy_iov, &lpi->iovs, l) {
> + nr_pages = lazy_iov->iov.iov_len / PAGE_SIZE;
> + base = (unsigned long)lazy_iov->iov.iov_base;
>
> - uffd_pages->flags |= UFFD_FLAG_SENT;
> + for (i = 0; i < nr_pages; i++) {
> + addr = base + i * PAGE_SIZE;
> +
> + err = uffd_handle_page(lpi, addr, dest);
> + if (err < 0) {
> + pr_err("Error during UFFD copy\n");
> + return -1;
> + }
> + }
> }
>
> return 0;
> }
>
> -
> static int handle_regular_pages(struct lazy_pages_info *lpi, void *dest,
> __u64 address)
> {
> @@ -628,6 +680,10 @@ static int handle_regular_pages(struct lazy_pages_info *lpi, void *dest,
> uffd_pages->flags |= UFFD_FLAG_SENT;
> }
>
> + rc = update_lazy_iovecs(lpi, address, PAGE_SIZE);
Ugh, why second scan for lpi->iovs? Can we update them right in the
place where we handle them?
> + if (rc < 0)
> + return -1;
> +
> return 0;
> }
>
>
More information about the CRIU
mailing list