[CRIU] [PATCH 27/32] tools: cpt2 -- Add "write" routines for virtual memory areas

Pavel Emelyanov xemul at parallels.com
Mon Apr 1 06:25:40 EDT 2013


On 03/31/2013 01:43 AM, Cyrill Gorcunov wrote:
> 
> Here we introduce writing of memory related stuff. In particular
> VMAs areas, memory map and pages.
> 
> Because shared VMAs are to be written separately we gather them
> into own hash.
> 
> Pages data read from openvz image file and wrote to page criu files,
> this is inefficient and better to teach criu to work with page data
> from openvz image file directly. But it's a target for further
> optimization, for a while lets stick with trivial approach.
> 
> Also we convert only regular pages, other type of pages (iterator)
> are to be converted someday latter.
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
>  tools/cpt2/src/include/mm.h |   5 +
>  tools/cpt2/src/mm.c         | 441 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 446 insertions(+)
> 


> +int write_vmas(context_t *ctx, pid_t pid, off_t cpt_mm)
> +{
> +	VmaEntry e = VMA_ENTRY__INIT;
> +	int fd_vmas = -1, ret = -1;
> +	struct vma_struct *vma;
> +	struct mm_struct *mm;
> +
> +	mm = obj_lookup_to(CPT_OBJ_MM, cpt_mm);
> +	if (!mm)
> +		return -1;
> +
> +	fd_vmas = open_image(ctx, CR_FD_VMAS, O_DUMP, pid);
> +	if (fd_vmas < 0)
> +		return -1;
> +
> +	list_for_each_entry(vma, &mm->vma_list, list) {
> +
> +		if (!vma_is(vma, VMA_AREA_REGULAR))
> +			continue;
> +
> +		if (vma_is(vma, VMA_AREA_SYSVIPC))
> +			continue;

Why?

> +

> +		if (vma_is_shared(vma))

This define is in patch #19 and ...

> +			e.flags = MAP_SHARED;
> +		else
> +			e.flags = MAP_PRIVATE;
> +
> +		if (vma_is(vma, VMA_ANON_SHARED | VMA_ANON_PRIVATE))

... looks exactly like this one. Such tricks do not improve code readability.

> +			e.flags |= MAP_ANONYMOUS;
> +

> +
> +#define write_socket_map(ctx, vma, pid)		0

WTF???

> +

> +static int write_vma_pages(context_t *ctx, int pagemap_fd, int page_fd,
> +			   struct vma_struct *vma)
> +{
> +	union {
> +		struct cpt_object_hdr	h;
> +		struct cpt_page_block	pb;
> +	} u;
> +
> +	u8 page[PAGE_SIZE];
> +
> +	unsigned long nr_pages, i;
> +	off_t start, end;
> +	PagemapEntry pe;
> +	int ret = -1;
> +
> +	start	= obj_of(vma)->o_pos + vma->vmai.cpt_hdrlen;
> +	end	= obj_of(vma)->o_pos + vma->vmai.cpt_next;
> +
> +	for (; start < end; start += u.h.cpt_next) {
> +		if (read_obj_cpt(ctx->fd, OBJ_ANY, &u.h, start)) {
> +			pr_err("Can't read page header at %li\n", (long)start);
> +			goto err;
> +		}
> +
> +		/*
> +		 * Skip any non regular pages.
> +		 */
> +		switch (u.h.cpt_object) {
> +		case CPT_OBJ_PAGES:
> +			break;
> +		case CPT_OBJ_REMAPPAGES:
> +		case CPT_OBJ_COPYPAGES:
> +		case CPT_OBJ_LAZYPAGES:
> +		case CPT_OBJ_ITERPAGES:
> +		case CPT_OBJ_ITERYOUNGPAGES:
> +			continue;

Bail out with error.

> +		default:
> +			pr_err("Unexpected object %d at %li\n",
> +			       u.h.cpt_object, (long)start);
> +			goto err;
> +		}
> +
> +		if (read_obj_cont(ctx->fd, &u.pb)) {
> +			pr_err("Can't read page at %li\n", (long)start);
> +			goto err;
> +		}
> +
> +		if (u.h.cpt_content != CPT_CONTENT_DATA) {
> +			pr_err("Unexpected object content %d at %li\n",
> +			       u.h.cpt_content, (long)start);
> +			goto err;
> +		}
> +
> +		/*
> +		 * Nothing to write.
> +		 */
> +		if (u.h.cpt_hdrlen == u.h.cpt_next)
> +			continue;
> +
> +		nr_pages = PAGES(u.h.cpt_next - u.h.cpt_hdrlen);
> +		i = PAGES(u.pb.cpt_end - u.pb.cpt_start);
> +		if (nr_pages != i) {
> +			pr_err("Broken pages count (%li/%li)at %li\n",
> +			       nr_pages, i, (long)start);
> +			goto err;
> +		}
> +
> +		pagemap_entry__init(&pe);
> +
> +		pe.vaddr	= u.pb.cpt_start;
> +		pe.nr_pages	= nr_pages;
> +
> +		if (pb_write_one(pagemap_fd, &pe, PB_PAGEMAP) < 0)
> +			goto err;
> +
> +		for (i = 0; i < nr_pages; i++) {
> +			if (__read(ctx->fd, page, sizeof(page))) {
> +				pr_err("Can't read page at %li\n",
> +				       (long)start);
> +					goto err;
> +				}
> +			if (__write(page_fd, page, sizeof(page))) {
> +				pr_err("Can't write page at %li\n",
> +				       (long)start);
> +				goto err;
> +			}

Plz, use sendfile for this.

> +		}
> +	}
> +	ret = 0;
> +err:
> +	return ret;
> +}



More information about the CRIU mailing list