[CRIU] [PATCH 13/15] cr-restore: remove unshared pages from inherited private mappings

Andrew Vagin avagin at parallels.com
Tue Nov 13 16:25:07 EST 2012


On Mon, Nov 12, 2012 at 03:44:54PM +0400, Pavel Emelyanov wrote:
> On 11/02/2012 05:32 PM, Andrey Vagin wrote:
> > A parent process can change a few pages after forking a child and
> > all this pages should not be avaliable from the child.
> > 
> > Each vma has a bitmap of existent pages. Parent's and child's bitmaps
> > can be compared and all pages which are not present in a child bitmap
> > are dropped.
> > 
> > Signed-off-by: Andrey Vagin <avagin at openvz.org>
> > ---
> >  cr-restore.c      | 42 +++++++++++++++++++++++++++++++++++++++++-
> >  include/crtools.h |  2 ++
> >  2 files changed, 43 insertions(+), 1 deletion(-)
> > 
> > diff --git a/cr-restore.c b/cr-restore.c
> > index 9749634..eb759cb 100644
> > --- a/cr-restore.c
> > +++ b/cr-restore.c
> >  
> > @@ -283,6 +291,12 @@ static int restore_priv_vma_content(pid_t pid)
> >  			vma = list_entry(vma->list.next, struct vma_area, list);
> >  		}
> >  
> > +		page_offset = (va - vma->vma.start) / PAGE_SIZE;
> > +		if (vma->page_bitmap)
> > +			set_bit(page_offset, vma->page_bitmap);
> 
> Can page_bitmap be NULL?

Currently it can't be. I will fix this place.

> 
> > +		if (vma->ppage_bitmap)
> > +			clear_bit(page_offset, vma->ppage_bitmap);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
> 
> 
> > +
> >  		ret = read(fd, buf, PAGE_SIZE);
> >  		if (ret != PAGE_SIZE) {
> >  			pr_err("Can'r read mapping page %d\n", ret);
> > @@ -298,6 +312,32 @@ static int restore_priv_vma_content(pid_t pid)
> >  	}
> >  	close(fd);
> >  
> > +	/* Remove pages, which were not shared with a child */
> > +	list_for_each_entry(vma, &rst_vma_list, list) {
> > +		unsigned long size, i = 0;
> > +		void *addr = (void *) vma_premmaped_start(&vma->vma);
> > +
> > +		if (vma->ppage_bitmap == NULL)
> > +			continue;
> > +
> > +		size = vma_entry_len(&vma->vma) / PAGE_SIZE;
> > +		while (1) {
> > +			/* Find all pages, which avaliable only for a parent */
> > +			i = find_next_bit(vma->ppage_bitmap, size, i);
> 
> This code means "find all pages available for a parent", w/o only.

All pages which shared with this child were dropped from this bitmap.
Look at 30 lines above.

May be this one is better:

Find all parent's pages, which are not shared with this child.
> 
> > +
> > +			if ( i >= size)
> > +				break;
> > +
> > +			ret = madvise(addr + PAGE_SIZE * i,
> > +						PAGE_SIZE, MADV_DONTNEED);
> > +			if (ret < 0) {
> > +				pr_perror("madvise failed\n");
> > +				return -1;
> > +			}
> > +			i++;
> > +		}
> > +	}
> > +
> >  	return 0;
> >  }
> >  
> > diff --git a/include/crtools.h b/include/crtools.h
> > index 37e50ca..ec76ec1 100644
> > --- a/include/crtools.h
> > +++ b/include/crtools.h
> > @@ -215,6 +215,8 @@ struct vma_area {
> >  	struct list_head	list;
> >  	VmaEntry		vma;
> >  	int			vm_file_fd;
> > +	unsigned long		*page_bitmap;  /* existent pages */
> 
> Not used anywhere for read, this is set-only field.
Yes. So?
> 
> > +	unsigned long		*ppage_bitmap; /* parent's existent pages */
> >  };
> >  
> >  #define vma_area_is(vma_area, s)	vma_entry_is(&((vma_area)->vma), s)
> > 
> 
> 


More information about the CRIU mailing list