[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