[CRIU] Re: [PATCH cr 08/16] restore: don't unmap premmapped private vma-s

Andrew Vagin avagin at parallels.com
Wed Oct 31 08:10:32 EDT 2012


On Tue, Oct 30, 2012 at 08:32:07PM +0400, Pavel Emelyanov wrote:
> > @@ -231,6 +233,23 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr,
> >  	return 0;
> >  }
> >  
> > +/* Prevent merging vma-s outside and inside the premmapped region */
> 
> Why? Besides, having two guard pages doesn't prevent vmas from being merged.
This guard pages will be unmapped, then cr-restore reads
/proc/self/maps.

        ret = parse_smaps(pid, &self_vma_list, false);

In self_vma_list will will have a separate vma for a private space

restorer.c:
        for (vma_entry = args->self_vmas; vma_entry->start != 0; vma_entry++) {
                if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
                        continue;

                if (args->premmapped_addr == vma_entry->start)
                        continue;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
we have only this line, if we use guard pages.

                if (sys_munmap((void *)vma_entry->start, vma_entry_len(vma_entry))) {
                        pr_err("Munmap fail for %lx\n", vma_entry->start);
                        goto core_restore_end;
                }
        }

Do you want this version or I should remove guards and handle merged vma-s.

The second variant will be faster and a bit more complex.

> 
> > +static int unmap_priv_guard_pages()
> > +{
> > +	if (munmap(premmapped_addr, PAGE_SIZE)) {
> > +		pr_perror("Could not unmap a guard page %p", premmapped_addr);
> > +		return -1;
> > +	}
> > +
> > +	if (munmap(premmapped_addr + premmapped_len - PAGE_SIZE, PAGE_SIZE)) {
> > +		pr_perror("Could not unmap a guard page %p",
> > +				premmapped_addr + premmapped_len);
> > +		return -1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static int read_vmas(int pid)
> >  {
> >  	int fd, ret = 0;
> > @@ -280,13 +299,26 @@ static int read_vmas(int pid)
> >  		priv_size += vma_area_len(vma);
> >  	}
> >  
> > -	/* Reserve a place for mapping private vma-s one by one */
> > -	addr = mmap(NULL, priv_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
> > +	/*
> > +	 * Reserve a place for mapping private vma-s one by one.
> > +	 *
> > +	 * Add two guard pages from both sides. This pages will be
> > +	 * unmaped before reading a current vmas for this process.
> > +	 * In this case we can be sure, that vmas outside and inside
> > +	 * of the premmapped region are not merged to each other.
> > +	 */
> > +	addr = mmap(NULL, priv_size + 2 * PAGE_SIZE,
> > +			PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
> 
> If we DO need guard pages then implement this in separate patch with proper description.
> 
> >  	if (addr == MAP_FAILED) {
> >  		pr_perror("Unable to reserve memory");
> >  		return -1;
> >  	}
> >  
> > +	premmapped_addr = addr;
> > +	premmapped_len = priv_size + 2 * PAGE_SIZE;
> > +
> > +	addr += PAGE_SIZE;
> > +
> >  	list_for_each_entry(vma, &vma_list, list) {
> >  		if (!vma_priv(&vma->vma))
> >  			continue;
> > @@ -321,6 +321,10 @@ long __export_restore_task(struct task_restore_core_args *args)
> >  		if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
> >  			continue;
> >  
> > +		if (args->premmapped_addr <= vma_entry->start &&
> > +		    vma_entry->end <= args->premmapped_addr + args->premmapped_len)
> > +			continue;
> 
> Why so complex? Isn't it easier just to remove this are from self_vma_list in cr-restore?
> 
> > +
> >  		if (sys_munmap((void *)vma_entry->start, vma_entry_len(vma_entry))) {
> >  			pr_err("Munmap fail for %lx\n", vma_entry->start);
> >  			goto core_restore_end;
> > 
> 
> 


More information about the CRIU mailing list