[CRIU] [PATCH] mem: Don't do unneeded mprotects

Andrei Vagin avagin at virtuozzo.com
Wed May 17 17:40:30 PDT 2017


Applied, thanks
On Mon, May 15, 2017 at 05:14:31PM +0300, Pavel Emelyanov wrote:
> When a vma we restore doesn't have any pages in pagemaps there's
> not need to enforce PROT_WRITE bit on it.
> 
> This only applies to non-premmaped vmas.
> 
> Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
> ---
>  criu/include/image.h |  1 +
>  criu/mem.c           | 27 ++++++++++++++++++++++++++-
>  criu/pie/restorer.c  |  6 ++++--
>  3 files changed, 31 insertions(+), 3 deletions(-)
> 
> diff --git a/criu/include/image.h b/criu/include/image.h
> index 24fb828..1dcd18c 100644
> --- a/criu/include/image.h
> +++ b/criu/include/image.h
> @@ -89,6 +89,7 @@
>  #define VMA_AREA_VVAR		(1 <<  12)
>  #define VMA_AREA_AIORING	(1 <<  13)
>  
> +#define VMA_NO_PROT_WRITE	(1 <<  29)
>  #define VMA_PREMMAPED		(1 <<  30)
>  #define VMA_UNSUPP		(1 <<  31)
>  
> diff --git a/criu/mem.c b/criu/mem.c
> index 942d5d9..db7279a 100644
> --- a/criu/mem.c
> +++ b/criu/mem.c
> @@ -690,6 +690,13 @@ static int premap_private_vma(struct pstree_item *t, struct vma_area *vma, void
>  			}
>  		}
>  
> +		/*
> +		 * All mappings here get PROT_WRITE regardless of whether we
> +		 * put any data into it or not, because this area will get
> +		 * mremap()-ed (branch below) so we MIGHT need to have WRITE 
> +		 * bits there. Ideally we'd check for the whole COW-chain
> +		 * having any data in.
> +		 */
>  		addr = mmap(*tgt_addr, size,
>  				vma->e->prot | PROT_WRITE,
>  				vma->e->flags | MAP_FIXED | flag,
> @@ -786,14 +793,26 @@ static int premap_priv_vmas(struct pstree_item *t, struct vm_area_list *vmas,
>  		if (!vma_area_is_private(vma, kdat.task_size))
>  			continue;
>  
> -		if (vma->pvma == NULL && pr->pieok && !vma_force_premap(vma, &vmas->h))
> +		if (vma->pvma == NULL && pr->pieok && !vma_force_premap(vma, &vmas->h)) {
>  			/*
>  			 * VMA in question is not shared with anyone. We'll
>  			 * restore it with its contents in restorer.
> +			 * Now let's check whether we need to map it with
> +			 * PROT_WRITE or not.
>  			 */
> +			do {
> +				if (pr->pe->vaddr + pr->pe->nr_pages * PAGE_SIZE <= vma->e->start)
> +					continue;
> +				if (pr->pe->vaddr > vma->e->end)
> +					vma->e->status |= VMA_NO_PROT_WRITE;
> +				break;
> +			} while (pr->advance(pr));
> +
>  			continue;
> +		}
>  
>  		ret = premap_private_vma(t, vma, at);
> +
>  		if (ret < 0)
>  			break;
>  	}
> @@ -879,6 +898,12 @@ static int restore_priv_vma_content(struct pstree_item *t, struct page_read *pr)
>  						(nr_pages - i) * PAGE_SIZE,
>  						vma->e->end - va);
>  
> +				if (vma->e->status & VMA_NO_PROT_WRITE) {
> +					pr_debug("VMA 0x%"PRIx64":0x%"PRIx64" RO %#lx:%lu IO\n",
> +							vma->e->start, vma->e->end, va, nr_pages);
> +					BUG();
> +				}
> +
>  				if (pagemap_enqueue_iovec(pr, (void *)va, len, vma_io))
>  					return -1;
>  
> diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
> index 98c81f3..1758883 100644
> --- a/criu/pie/restorer.c
> +++ b/criu/pie/restorer.c
> @@ -621,7 +621,8 @@ static unsigned long restore_mapping(VmaEntry *vma_entry)
>  		flags |= MAP_ANONYMOUS;
>  
>  	/* A mapping of file with MAP_SHARED is up to date */
> -	if (vma_entry->fd == -1 || !(vma_entry->flags & MAP_SHARED))
> +	if ((vma_entry->fd == -1 || !(vma_entry->flags & MAP_SHARED)) &&
> +			!(vma_entry->status & VMA_NO_PROT_WRITE))
>  		prot |= PROT_WRITE;
>  
>  	pr_debug("\tmmap(%"PRIx64" -> %"PRIx64", %x %x %d)\n",
> @@ -1348,7 +1349,8 @@ long __export_restore_task(struct task_restore_args *args)
>  		if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR)))
>  			continue;
>  
> -		if (vma_entry->prot & PROT_WRITE)
> +		if ((vma_entry->prot & PROT_WRITE) ||
> +				(vma_entry->status & VMA_NO_PROT_WRITE))
>  			continue;
>  
>  		sys_mprotect(decode_pointer(vma_entry->start),
> -- 
> 2.1.4
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu


More information about the CRIU mailing list