[CRIU] Re: [PATCH cr 05/11] restore: map private vma-s before forking children

Andrew Vagin avagin at parallels.com
Mon Oct 15 14:01:50 EDT 2012


On Mon, Oct 15, 2012 at 08:23:49PM +0400, Pavel Emelyanov wrote:
> On 10/15/2012 07:32 PM, Andrey Vagin wrote:
> > In this case private vma-s will be inherited by children,
> > it allows to restore copy-on-write reqions.
> > 
> > This code compares child and parent vma lists. If it found
> > two vma-s with the same start and end addresses, it decides
> > that the child inherites this vmas from the parent.
> > 
> > Each anon vma is mapped only once. An address for vma is allocated
> > by kernel, then it will be remapped in restorer.
> > 
> > Signed-off-by: Andrey Vagin <avagin at openvz.org>
> > ---
> >  cr-restore.c |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 files changed, 65 insertions(+), 2 deletions(-)
> > 
> > diff --git a/cr-restore.c b/cr-restore.c
> > index 21d6f97..020b489 100644
> > --- a/cr-restore.c
> > +++ b/cr-restore.c
> > @@ -173,20 +173,71 @@ err:
> >  	return ret;
> >  }
> >  
> > +/* Map a private vma, if it is not mapped by a parrent yet */
> > +static int map_private_vma(pid_t pid, struct vma_area *vma,
> > +			struct vma_area **pvma, struct list_head *pvma_list)
> > +{
> > +	struct vma_area *p = *pvma;
> > +
> > +	if (!vma_priv(&vma->vma))
> > +		return 0;
> > +
> > +	list_for_each_entry_continue(p, pvma_list, list) {
> > +		if (p->vma.start > vma->vma.start)
> > +			 break;
> > +
> > +		if (p->vma.end == vma->vma.end &&
> > +		    p->vma.start == vma->vma.start) {
> > +			pr_info("COW 0x%016lx-0x%016lx 0x%016lx vma\n",
> > +				vma->vma.start, vma->vma.end, vma->vma.pgoff);
> > +			vma->vma.shmid = p->vma.shmid;
> 
> Two vmas, one in parent the other one in child with equal starts and ends
> are not necessarily shared.

It's not a big deal. A child compares pages contents and if they are
differ, the content is restored. If two vmas are not shared, this method can
makebenefit even in this case if they have two equal pages;).

> 
> > +		}
> > +
> > +	}
> > +
> > +	*pvma = list_entry(p->list.prev, struct vma_area, list);
> > +
> > +	if (!vma->vma.shmid) {
> > +		void *addr;
> > +
> > +		pr_info("Map 0x%016lx-0x%016lx 0x%016lx vma\n",
> > +			vma->vma.start, vma->vma.end, vma->vma.pgoff);
> > +
> > +		addr = mmap(NULL, vma_entry_len(&vma->vma),
> > +				vma->vma.prot | PROT_WRITE, vma->vma.flags,
> > +				vma->vma.fd, vma->vma.pgoff);
> > +
> > +		if (addr == MAP_FAILED) {
> > +			pr_err("Unable to map ANON_VMA");
> > +			return -1;
> > +		}
> > +		vma->vma.shmid = (unsigned long) addr;
> > +	}
> > +
> > +	if (vma_entry_is(&vma->vma, VMA_FILE_PRIVATE))
> > +		close(vma->vma.fd);
> > +
> > +	return 0;
> > +}
> > +
> >  static int read_vmas(int pid)
> >  {
> >  	int fd, ret = 0;
> > +	LIST_HEAD(old);
> > +	struct vma_area *pvma, *vma;
> >  
> > +	list_replace_init(&vma_list, &old);
> >  	INIT_LIST_HEAD(&vma_list);
> >  
> > +	pvma = list_first_entry(&old, struct vma_area, list);
> > +
> >  	/* Skip errors, because a zombie doesn't have an image of vmas */
> >  	fd = open_image_ro(CR_FD_VMAS, pid);
> >  	if (fd < 0)
> > -		return ret;
> > +		goto out;
> >  
> >  	nr_vmas = 0;
> >  	while (1) {
> > -		struct vma_area *vma;
> >  		VmaEntry *e;
> >  
> >  		ret = -1;
> > @@ -209,9 +260,21 @@ static int read_vmas(int pid)
> >  
> >  		vma->vma = *e;
> >  		vma_entry__free_unpacked(e, NULL);
> > +
> > +		ret = map_private_vma(pid, vma, &pvma, &old);
> > +		if (ret < 0)
> > +			break;
> >  	}
> >  
> >  	close(fd);
> > +
> > +out:
> > +	while (!list_empty(&old)) {
> > +		vma = list_first_entry(&old, struct vma_area, list);
> > +		list_del(&vma->list);
> > +		xfree(vma);
> > +	}
> > +
> >  	return ret;
> >  }
> >  
> > 
> 
> 


More information about the CRIU mailing list