[CRIU] [PATCH 14/15] restorer: rework unmaping old VMA-s (v3)

Christopher Covington cov at codeaurora.org
Mon Oct 6 12:33:43 PDT 2014


Hi Andrey, Pavel,

On 09/23/2013 06:33 AM, Andrey Vagin wrote:
> All process VMA-s are in "premmaped area". All restorer stuff are in
> bootstap "area", so we have two areas.
> 
> So we don't need to unmap extra VMA-s one by one. We can call munmap
> three times for the region before the first area, for the hole between
> areas and for the region after the second area.
> 
> The old scheme didn't work, because the list of VMA-s can be changed
> after collecting. It can be due to memory allocations by libc or due to
> increased stack.

> diff --git a/pie/restorer.c b/pie/restorer.c
> index 8e43609..59b801f 100644
> --- a/pie/restorer.c
> +++ b/pie/restorer.c
> @@ -524,6 +524,51 @@ void __export_unmap(void)
>  }
>  
>  /*
> + * This function unmaps all VMAs, which don't belong to
> + * the restored process or the restorer
> + */
> +static int unmap_old_vmas(void *premmapped_addr, unsigned long premmapped_len,
> +		      void *bootstrap_start, unsigned long bootstrap_len)
> +{
> +	unsigned long s1, s2;
> +	void *p1, *p2;
> +	int ret;
> +
> +	if ((void *) premmapped_addr < bootstrap_start) {
> +		p1 = premmapped_addr;
> +		s1 = premmapped_len;
> +		p2 = bootstrap_start;
> +		s2 = bootstrap_len;
> +	} else {
> +		p2 = premmapped_addr;
> +		s2 = premmapped_len;
> +		p1 = bootstrap_start;
> +		s1 = bootstrap_len;
> +	}
> +
> +	ret = sys_munmap(NULL, p1 - NULL);
> +	if (ret) {
> +		pr_err("Unable to unmap (%p-%p): %d\n", NULL, p1, ret);
> +		return -1;
> +	}
> +
> +	ret = sys_munmap(p1 + s1, p2 - (p1 + s1));
> +	if (ret) {
> +		pr_err("Unable to unmap (%p-%p): %d\n", p1 + s1, p2, ret);
> +		return -1;
> +	}
> +
> +	ret = sys_munmap(p2 + s2, (void *) TASK_SIZE - (p2 + s2));

Experimenting with various kernel configurations on AArch64 such as 64K pages
(which change the default VA_BITS and therefore TASK_SIZE), it has become
apparent to me that TASK_SIZE as used here cannot be a compile-time constant
if we are to have one AArch64 CRIU binary that works regardless of the kernel
configuration it is paired with.

Currently, the shift for TASK_SIZE could be 39, 42, or 48. What do you all
think is the best way to handle this? Return -1 if unmapping up to bit 39
fails, but just give a debug print if unmapping between bits 39 and 42 or bits
42 and 48 fails? Is there an existing /proc entry or sysconf() or
prctl(PR_GET_MM, ...) to determine task size dynamically that I've overlooked?
If not, should I propose one? Should I try to probe the value with mmap calls
or similar?

> +	if (ret) {
> +		pr_err("Unable to unmap (%p-%p): %d\n",
> +				p2 + s2, (void *)TASK_SIZE, ret);
> +		return -1;
> +	}
> +
> +	return 0;
> +}

Thanks,
Christopher

-- 
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by the Linux Foundation.


More information about the CRIU mailing list