[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