[CRIU] [RFC PATCH 03/16] criu: lazy-pages: introduce collect_lazy_iovecs
Mike Rapoport
rppt at linux.vnet.ibm.com
Wed Oct 5 07:26:05 PDT 2016
On Wed, Oct 05, 2016 at 04:05:58PM +0300, Pavel Emelyanov wrote:
> On 09/27/2016 04:42 PM, Mike Rapoport wrote:
> > Instead of tracking memory handled by userfaultfd on the page basis we can
> > use IOVs for continious chunks. Start conversion by introducing
> > collect_lazy_iovecs function.
> >
> > Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
> > ---
> > criu/uffd.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 53 insertions(+)
> >
> > diff --git a/criu/uffd.c b/criu/uffd.c
> > index 81dc7ae..063ce4f 100644
> > --- a/criu/uffd.c
> > +++ b/criu/uffd.c
> > @@ -45,11 +45,17 @@
> >
> > static mutex_t *lazy_sock_mutex;
> >
> > +struct lazy_iovec {
> > + struct iovec iov;
> > + struct list_head l;
> > +};
> > +
> > struct lazy_pages_info {
> > int pid;
> > int uffd;
> >
> > struct list_head pages;
> > + struct list_head iovs;
> >
> > struct page_read pr;
> >
> > @@ -74,6 +80,7 @@ static struct lazy_pages_info *lpi_init(void)
> >
> > memset(lpi, 0, sizeof(*lpi));
> > INIT_LIST_HEAD(&lpi->pages);
> > + INIT_LIST_HEAD(&lpi->iovs);
> > INIT_HLIST_NODE(&lpi->hash);
> >
> > return lpi;
> > @@ -81,8 +88,12 @@ static struct lazy_pages_info *lpi_init(void)
> >
> > static void lpi_fini(struct lazy_pages_info *lpi)
> > {
> > + struct lazy_iovec *p, *n;
> > +
> > if (!lpi)
> > return;
> > + list_for_each_entry_safe(p, n, &lpi->iovs, l)
> > + xfree(p);
> > if (lpi->uffd > 0)
> > close(lpi->uffd);
> > if (lpi->pr.close)
> > @@ -314,6 +325,42 @@ out:
> >
> > static int find_vmas(struct lazy_pages_info *lpi);
> >
> > +static int collect_lazy_iovecs(struct lazy_pages_info *lpi)
> > +{
> > + struct page_read *pr = &lpi->pr;
> > + struct lazy_iovec *lazy_iov, *n;
> > + int nr_pages = 0;
> > +
> > + pr->reset(pr);
> > +
> > + while (pr->advance(pr)) {
>
> This place looks like it wanted to do pr->get_pagemap(), but for
> some reason it doesn't :) Why?
For future compatibility :) We will want to know about zero pagemaps here
as well and for that we'll need "raw" pagemap iterator. My intention is to
add 'zero' list to lazy_pages_info and use that for detecting when to
inject zero pages into process address space.
> > + PagemapEntry *pe = pr->pe;
> > +
> > + if (!pagemap_lazy(pe))
> > + continue;
> > +
> > + lazy_iov = xzalloc(sizeof(*lazy_iov));
> > + if (!lazy_iov) {
> > + pr_err("Out of memory\n");
> > + goto free_iovs;
> > + }
> > +
> > + pagemap2iovec(pe, &lazy_iov->iov);
> > + list_add_tail(&lazy_iov->l, &lpi->iovs);
> > + nr_pages += pe->nr_pages;
> > +
> > + pr_debug("adding IOV: %p:%lx (%d)\n", lazy_iov->iov.iov_base, lazy_iov->iov.iov_len, pe->nr_pages);
> > + }
> > +
> > + return nr_pages;
> > +
> > +free_iovs:
> > + list_for_each_entry_safe(lazy_iov, n, &lpi->iovs, l)
> > + xfree(lazy_iov);
> > +
> > + return -1;
> > +}
> > +
> > static struct lazy_pages_info *ud_open(int client)
> > {
> > struct lazy_pages_info *lpi;
> > @@ -353,6 +400,12 @@ static struct lazy_pages_info *ud_open(int client)
> >
> > hlist_add_head(&lpi->hash, &lpi_hash[lpi->uffd % LPI_HASH_SIZE]);
> >
> > + ret = collect_lazy_iovecs(lpi);
> > + if (ret != lpi->total_pages) {
> > + pr_err("collect_lazy_iovecs=%d\n", ret);
> > + goto out;
> > + }
> > +
> > return lpi;
> >
> > out:
> >
>
More information about the CRIU
mailing list