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

Pavel Emelyanov xemul at parallels.com
Mon Oct 15 12:23:49 EDT 2012


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.

> +		}
> +
> +	}
> +
> +	*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