From: Andrey Mirkin <major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
Andrey Mirkin <major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
Subject: [PATCH 9/9] Introduce functions to restore mm
Date: Wed, 3 Sep 2008 14:57:56 +0400 [thread overview]
Message-ID: <1220439476-16465-10-git-send-email-major@openvz.org> (raw)
In-Reply-To: <1220439476-16465-9-git-send-email-major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
Functions to restore mm, VMAs and mm context are added.
Signed-off-by: Andrey Mirkin <major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
---
cpt/Makefile | 2 +-
cpt/cpt.h | 1 +
cpt/cpt_image.h | 5 +
cpt/rst_mm.c | 320 +++++++++++++++++++++++++++++++++++++++++++++++++++++
cpt/rst_process.c | 3 +-
mm/mmap.c | 1 +
mm/mprotect.c | 2 +
8 files changed, 336 insertions(+), 2 deletions(-)
create mode 100644 cpt/rst_mm.c
diff --git a/cpt/Makefile b/cpt/Makefile
index 689a0eb..19ca732 100644
--- a/cpt/Makefile
+++ b/cpt/Makefile
@@ -3,4 +3,4 @@ obj-y += sys_core.o
obj-$(CONFIG_CHECKPOINT) += cptrst.o
cptrst-objs := sys.o checkpoint.o cpt_process.o cpt_mm.o restart.o \
- rst_process.o
+ rst_process.o rst_mm.o
diff --git a/cpt/cpt.h b/cpt/cpt.h
index d59255f..f2a1b28 100644
--- a/cpt/cpt.h
+++ b/cpt/cpt.h
@@ -62,3 +62,4 @@ int cpt_dump_mm(struct task_struct *tsk, struct cpt_context *ctx);
int restart_container(struct cpt_context *ctx);
int rst_get_object(int type, void *tmp, int size, struct cpt_context *ctx);
int rst_restart_process(struct cpt_context *ctx);
+int rst_restore_mm(struct cpt_context *ctx);
diff --git a/cpt/cpt_image.h b/cpt/cpt_image.h
index ae019e7..3b5b418 100644
--- a/cpt/cpt_image.h
+++ b/cpt/cpt_image.h
@@ -233,6 +233,11 @@ struct cpt_x86_regs
__u32 cpt_ss;
} __attribute__ ((aligned (8)));
+static inline void __user * cpt_ptr_import(__u64 ptr)
+{
+ return (void*)(unsigned long)ptr;
+}
+
static inline __u64 cpt_timespec_export(struct timespec *tv)
{
return (((u64)tv->tv_sec) << 32) + tv->tv_nsec;
diff --git a/cpt/rst_mm.c b/cpt/rst_mm.c
new file mode 100644
index 0000000..cccbff6
--- /dev/null
+++ b/cpt/rst_mm.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2008 Parallels, Inc.
+ *
+ * Author: Andrey Mirkin <major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/syscalls.h>
+
+#include "cpt.h"
+#include "cpt_image.h"
+
+static unsigned long make_prot(struct cpt_vma_image *vmai)
+{
+ unsigned long prot = 0;
+
+ if (vmai->cpt_flags & VM_READ)
+ prot |= PROT_READ;
+ if (vmai->cpt_flags & VM_WRITE)
+ prot |= PROT_WRITE;
+ if (vmai->cpt_flags & VM_EXEC)
+ prot |= PROT_EXEC;
+ if (vmai->cpt_flags & VM_GROWSDOWN)
+ prot |= PROT_GROWSDOWN;
+ if (vmai->cpt_flags & VM_GROWSUP)
+ prot |= PROT_GROWSUP;
+ return prot;
+}
+
+static unsigned long make_flags(struct cpt_vma_image *vmai)
+{
+ unsigned long flags = MAP_FIXED;
+
+ if (vmai->cpt_flags&(VM_SHARED|VM_MAYSHARE))
+ flags |= MAP_SHARED;
+ else
+ flags |= MAP_PRIVATE;
+
+ if (vmai->cpt_file == CPT_NULL)
+ flags |= MAP_ANONYMOUS;
+ if (vmai->cpt_flags & VM_GROWSDOWN)
+ flags |= MAP_GROWSDOWN;
+#ifdef MAP_GROWSUP
+ if (vmai->cpt_flags & VM_GROWSUP)
+ flags |= MAP_GROWSUP;
+#endif
+ if (vmai->cpt_flags & VM_DENYWRITE)
+ flags |= MAP_DENYWRITE;
+ if (vmai->cpt_flags & VM_EXECUTABLE)
+ flags |= MAP_EXECUTABLE;
+ if (!(vmai->cpt_flags & VM_ACCOUNT))
+ flags |= MAP_NORESERVE;
+ return flags;
+}
+
+static int rst_restore_one_vma(struct cpt_context *ctx)
+{
+ int err;
+ int i;
+ unsigned long addr;
+ struct mm_struct *mm = current->mm;
+ struct cpt_vma_image vmai;
+ struct vm_area_struct *vma;
+ struct file *file = NULL;
+ unsigned long prot;
+
+ err = rst_get_object(CPT_OBJ_VMA, &vmai, sizeof(vmai), ctx);
+ if (err)
+ return err;
+
+ prot = make_prot(&vmai);
+
+ if (vmai.cpt_vma_type == CPT_VMA_FILE) {
+ struct cpt_object_hdr h;
+ int len;
+ char *path;
+
+ err = rst_get_object(CPT_OBJ_NAME, &h, sizeof(h), ctx);
+ if (err)
+ goto out;
+ len = h.cpt_len - sizeof(h);
+ if (len < 0) {
+ err = -EINVAL;
+ goto out;
+ }
+ path = kmalloc(len, GFP_KERNEL);
+ if (!path) {
+ err = -ENOMEM;
+ goto out;
+ }
+ err = ctx->read(path, len, ctx);
+ if (err) {
+ kfree(path);
+ goto out;
+ }
+
+ /* Just open file
+ TODO: open with correct flags */
+ file = filp_open(path, O_RDONLY, 0);
+ kfree(path);
+ if (IS_ERR(file)) {
+ err = PTR_ERR(file);
+ goto out;
+ }
+ }
+
+ down_write(&mm->mmap_sem);
+ addr = do_mmap_pgoff(file, vmai.cpt_start,
+ vmai.cpt_end - vmai.cpt_start,
+ prot, make_flags(&vmai),
+ vmai.cpt_pgoff);
+
+ if (addr != vmai.cpt_start) {
+ up_write(&mm->mmap_sem);
+
+ err = -EINVAL;
+ if (IS_ERR((void*)addr))
+ err = addr;
+ goto out;
+ }
+
+ vma = find_vma(mm, vmai.cpt_start);
+ if (vma == NULL) {
+ up_write(&mm->mmap_sem);
+ eprintk("cannot find mmapped vma\n");
+ err = -ESRCH;
+ goto out;
+ }
+
+ /* do_mmap_pgoff() can merge new area to previous one (not to the next,
+ * we mmap in order, the rest of mm is still unmapped). This can happen
+ * f.e. if flags are to be adjusted later, or if we had different
+ * anon_vma on two adjacent regions. Split it by brute force. */
+ if (vma->vm_start != vmai.cpt_start) {
+ err = split_vma(mm, vma, (unsigned long)vmai.cpt_start, 0);
+ if (err) {
+ up_write(&mm->mmap_sem);
+ eprintk("cannot split vma\n");
+ goto out;
+ }
+ }
+ up_write(&mm->mmap_sem);
+
+ for (i = 0; i < vmai.cpt_page_num; i++) {
+ struct cpt_page_block pb;
+
+ err = rst_get_object(CPT_OBJ_PAGES, &pb, sizeof(pb), ctx);
+ if (err)
+ goto out;
+ if (!(vmai.cpt_flags & VM_ACCOUNT) && !(prot & PROT_WRITE)) {
+ /* I guess this is get_user_pages() messed things,
+ * this happens f.e. when gdb inserts breakpoints.
+ */
+ int j;
+ for (j = 0; j < (pb.cpt_end-pb.cpt_start)/PAGE_SIZE; j++) {
+ struct page *page;
+ void *maddr;
+ err = get_user_pages(current, current->mm,
+ (unsigned long)pb.cpt_start +
+ j * PAGE_SIZE,
+ 1, 1, 1, &page, NULL);
+ if (err == 0)
+ err = -EFAULT;
+ if (err < 0) {
+ eprintk("get_user_pages: %d\n", err);
+ goto out;
+ }
+ err = 0;
+ maddr = kmap(page);
+ if (pb.cpt_content == CPT_CONTENT_VOID) {
+ memset(maddr, 0, PAGE_SIZE);
+ } else if (pb.cpt_content == CPT_CONTENT_DATA) {
+ err = ctx->read(maddr, PAGE_SIZE, ctx);
+ if (err) {
+ kunmap(page);
+ goto out;
+ }
+ } else {
+ err = -EINVAL;
+ kunmap(page);
+ goto out;
+ }
+ set_page_dirty_lock(page);
+ kunmap(page);
+ page_cache_release(page);
+ }
+ } else {
+ if (!(prot & PROT_WRITE))
+ sys_mprotect(vmai.cpt_start,
+ vmai.cpt_end - vmai.cpt_start,
+ prot | PROT_WRITE);
+ if (pb.cpt_content == CPT_CONTENT_VOID) {
+ int j;
+ for (j=0; j<(pb.cpt_end-pb.cpt_start)/sizeof(unsigned long); j++) {
+ err = __put_user(0UL, ((unsigned long __user*)(unsigned long)pb.cpt_start) + j);
+ if (err) {
+ eprintk("__put_user 2 %d\n", err);
+ goto out;
+ }
+ }
+ } else if (pb.cpt_content == CPT_CONTENT_DATA) {
+ err = ctx->read(cpt_ptr_import(pb.cpt_start),
+ pb.cpt_end - pb.cpt_start,
+ ctx);
+ if (err)
+ goto out;
+ } else {
+ err = -EINVAL;
+ goto out;
+ }
+ if (!(prot & PROT_WRITE))
+ sys_mprotect(vmai.cpt_start,
+ vmai.cpt_end - vmai.cpt_start,
+ prot);
+ }
+ }
+
+out:
+ if (file)
+ fput(file);
+ return err;
+}
+
+static int rst_restore_mm_context(struct cpt_context *ctx)
+{
+ struct cpt_obj_bits b;
+ struct mm_struct *mm = current->mm;
+ int oldsize = mm->context.size;
+ int err;
+ void *oldldt;
+ void *newldt;
+
+ err = rst_get_object(CPT_OBJ_BITS, &b, sizeof(b), ctx);
+ if (err)
+ return err;
+
+ if (b.cpt_size > PAGE_SIZE)
+ newldt = vmalloc(b.cpt_size);
+ else
+ newldt = kmalloc(b.cpt_size, GFP_KERNEL);
+
+ if (!newldt)
+ return -ENOMEM;
+
+ err = ctx->read(newldt, b.cpt_size, ctx);
+ if (err)
+ return err;
+
+ oldldt = mm->context.ldt;
+ mm->context.ldt = newldt;
+ mm->context.size = b.cpt_size / LDT_ENTRY_SIZE;
+
+ load_LDT(&mm->context);
+
+ if (oldsize) {
+ if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
+ vfree(oldldt);
+ else
+ kfree(oldldt);
+ }
+
+ return 0;
+}
+
+int rst_restore_mm(struct cpt_context *ctx)
+{
+ int err;
+ int i;
+ struct mm_struct *mm = current->mm;
+ struct cpt_mm_image m;
+
+ err = rst_get_object(CPT_OBJ_MM, &m, sizeof(m), ctx);
+ if (err)
+ return err;
+
+ down_write(&mm->mmap_sem);
+ do_munmap(mm, 0, TASK_SIZE);
+
+ mm->start_code = m.cpt_start_code;
+ mm->end_code = m.cpt_end_code;
+ mm->start_data = m.cpt_start_data;
+ mm->end_data = m.cpt_end_data;
+ mm->start_brk = m.cpt_start_brk;
+ mm->brk = m.cpt_brk;
+ mm->start_stack = m.cpt_start_stack;
+ mm->arg_start = m.cpt_start_arg;
+ mm->arg_end = m.cpt_end_arg;
+ mm->env_start = m.cpt_start_env;
+ mm->env_end = m.cpt_end_env;
+ mm->def_flags = m.cpt_def_flags;
+ mm->flags = m.cpt_flags;
+
+ up_write(&mm->mmap_sem);
+
+ for (i = 0; i < m.cpt_map_count; i++) {
+ err = rst_restore_one_vma(ctx);
+ if (err < 0)
+ goto out;
+ }
+
+ err = rst_restore_mm_context(ctx);
+out:
+ return err;
+}
+
diff --git a/cpt/rst_process.c b/cpt/rst_process.c
index 6d47f3c..84be46e 100644
--- a/cpt/rst_process.c
+++ b/cpt/rst_process.c
@@ -210,7 +210,8 @@ static int restart_thread(void *arg)
err = rst_get_object(CPT_OBJ_TASK, ti, sizeof(*ti), ctx);
if (!err)
err = rst_restore_task_struct(current, ti, ctx);
- /* Restore mm here */
+ if (!err)
+ err = rst_restore_mm(ctx);
if (!err)
err = rst_restore_fpustate(current, ti, ctx);
if (!err)
diff --git a/mm/mmap.c b/mm/mmap.c
index 971d0ed..98d1ba9 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1858,6 +1858,7 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
return 0;
}
+EXPORT_SYMBOL(split_vma);
/* Munmap is split into 2 main parts -- this part which finds
* what needs doing, and the areas themselves, which do the
diff --git a/mm/mprotect.c b/mm/mprotect.c
index fded06f..47c7d75 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -22,6 +22,7 @@
#include <linux/swap.h>
#include <linux/swapops.h>
#include <linux/mmu_notifier.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
@@ -317,3 +318,4 @@ out:
up_write(¤t->mm->mmap_sem);
return error;
}
+EXPORT_SYMBOL(sys_mprotect);
--
1.5.6
WARNING: multiple messages have this Message-ID (diff)
From: Andrey Mirkin <major@openvz.org>
To: linux-kernel@vger.kernel.org
Cc: containers@lists.linux-foundation.org, Andrey Mirkin <major@openvz.org>
Subject: [PATCH 9/9] Introduce functions to restore mm
Date: Wed, 3 Sep 2008 14:57:56 +0400 [thread overview]
Message-ID: <1220439476-16465-10-git-send-email-major@openvz.org> (raw)
In-Reply-To: <1220439476-16465-9-git-send-email-major@openvz.org>
Functions to restore mm, VMAs and mm context are added.
Signed-off-by: Andrey Mirkin <major@openvz.org>
---
cpt/Makefile | 2 +-
cpt/cpt.h | 1 +
cpt/cpt_image.h | 5 +
cpt/rst_mm.c | 320 +++++++++++++++++++++++++++++++++++++++++++++++++++++
cpt/rst_process.c | 3 +-
mm/mmap.c | 1 +
mm/mprotect.c | 2 +
8 files changed, 336 insertions(+), 2 deletions(-)
create mode 100644 cpt/rst_mm.c
diff --git a/cpt/Makefile b/cpt/Makefile
index 689a0eb..19ca732 100644
--- a/cpt/Makefile
+++ b/cpt/Makefile
@@ -3,4 +3,4 @@ obj-y += sys_core.o
obj-$(CONFIG_CHECKPOINT) += cptrst.o
cptrst-objs := sys.o checkpoint.o cpt_process.o cpt_mm.o restart.o \
- rst_process.o
+ rst_process.o rst_mm.o
diff --git a/cpt/cpt.h b/cpt/cpt.h
index d59255f..f2a1b28 100644
--- a/cpt/cpt.h
+++ b/cpt/cpt.h
@@ -62,3 +62,4 @@ int cpt_dump_mm(struct task_struct *tsk, struct cpt_context *ctx);
int restart_container(struct cpt_context *ctx);
int rst_get_object(int type, void *tmp, int size, struct cpt_context *ctx);
int rst_restart_process(struct cpt_context *ctx);
+int rst_restore_mm(struct cpt_context *ctx);
diff --git a/cpt/cpt_image.h b/cpt/cpt_image.h
index ae019e7..3b5b418 100644
--- a/cpt/cpt_image.h
+++ b/cpt/cpt_image.h
@@ -233,6 +233,11 @@ struct cpt_x86_regs
__u32 cpt_ss;
} __attribute__ ((aligned (8)));
+static inline void __user * cpt_ptr_import(__u64 ptr)
+{
+ return (void*)(unsigned long)ptr;
+}
+
static inline __u64 cpt_timespec_export(struct timespec *tv)
{
return (((u64)tv->tv_sec) << 32) + tv->tv_nsec;
diff --git a/cpt/rst_mm.c b/cpt/rst_mm.c
new file mode 100644
index 0000000..cccbff6
--- /dev/null
+++ b/cpt/rst_mm.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2008 Parallels, Inc.
+ *
+ * Author: Andrey Mirkin <major@openvz.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/syscalls.h>
+
+#include "cpt.h"
+#include "cpt_image.h"
+
+static unsigned long make_prot(struct cpt_vma_image *vmai)
+{
+ unsigned long prot = 0;
+
+ if (vmai->cpt_flags & VM_READ)
+ prot |= PROT_READ;
+ if (vmai->cpt_flags & VM_WRITE)
+ prot |= PROT_WRITE;
+ if (vmai->cpt_flags & VM_EXEC)
+ prot |= PROT_EXEC;
+ if (vmai->cpt_flags & VM_GROWSDOWN)
+ prot |= PROT_GROWSDOWN;
+ if (vmai->cpt_flags & VM_GROWSUP)
+ prot |= PROT_GROWSUP;
+ return prot;
+}
+
+static unsigned long make_flags(struct cpt_vma_image *vmai)
+{
+ unsigned long flags = MAP_FIXED;
+
+ if (vmai->cpt_flags&(VM_SHARED|VM_MAYSHARE))
+ flags |= MAP_SHARED;
+ else
+ flags |= MAP_PRIVATE;
+
+ if (vmai->cpt_file == CPT_NULL)
+ flags |= MAP_ANONYMOUS;
+ if (vmai->cpt_flags & VM_GROWSDOWN)
+ flags |= MAP_GROWSDOWN;
+#ifdef MAP_GROWSUP
+ if (vmai->cpt_flags & VM_GROWSUP)
+ flags |= MAP_GROWSUP;
+#endif
+ if (vmai->cpt_flags & VM_DENYWRITE)
+ flags |= MAP_DENYWRITE;
+ if (vmai->cpt_flags & VM_EXECUTABLE)
+ flags |= MAP_EXECUTABLE;
+ if (!(vmai->cpt_flags & VM_ACCOUNT))
+ flags |= MAP_NORESERVE;
+ return flags;
+}
+
+static int rst_restore_one_vma(struct cpt_context *ctx)
+{
+ int err;
+ int i;
+ unsigned long addr;
+ struct mm_struct *mm = current->mm;
+ struct cpt_vma_image vmai;
+ struct vm_area_struct *vma;
+ struct file *file = NULL;
+ unsigned long prot;
+
+ err = rst_get_object(CPT_OBJ_VMA, &vmai, sizeof(vmai), ctx);
+ if (err)
+ return err;
+
+ prot = make_prot(&vmai);
+
+ if (vmai.cpt_vma_type == CPT_VMA_FILE) {
+ struct cpt_object_hdr h;
+ int len;
+ char *path;
+
+ err = rst_get_object(CPT_OBJ_NAME, &h, sizeof(h), ctx);
+ if (err)
+ goto out;
+ len = h.cpt_len - sizeof(h);
+ if (len < 0) {
+ err = -EINVAL;
+ goto out;
+ }
+ path = kmalloc(len, GFP_KERNEL);
+ if (!path) {
+ err = -ENOMEM;
+ goto out;
+ }
+ err = ctx->read(path, len, ctx);
+ if (err) {
+ kfree(path);
+ goto out;
+ }
+
+ /* Just open file
+ TODO: open with correct flags */
+ file = filp_open(path, O_RDONLY, 0);
+ kfree(path);
+ if (IS_ERR(file)) {
+ err = PTR_ERR(file);
+ goto out;
+ }
+ }
+
+ down_write(&mm->mmap_sem);
+ addr = do_mmap_pgoff(file, vmai.cpt_start,
+ vmai.cpt_end - vmai.cpt_start,
+ prot, make_flags(&vmai),
+ vmai.cpt_pgoff);
+
+ if (addr != vmai.cpt_start) {
+ up_write(&mm->mmap_sem);
+
+ err = -EINVAL;
+ if (IS_ERR((void*)addr))
+ err = addr;
+ goto out;
+ }
+
+ vma = find_vma(mm, vmai.cpt_start);
+ if (vma == NULL) {
+ up_write(&mm->mmap_sem);
+ eprintk("cannot find mmapped vma\n");
+ err = -ESRCH;
+ goto out;
+ }
+
+ /* do_mmap_pgoff() can merge new area to previous one (not to the next,
+ * we mmap in order, the rest of mm is still unmapped). This can happen
+ * f.e. if flags are to be adjusted later, or if we had different
+ * anon_vma on two adjacent regions. Split it by brute force. */
+ if (vma->vm_start != vmai.cpt_start) {
+ err = split_vma(mm, vma, (unsigned long)vmai.cpt_start, 0);
+ if (err) {
+ up_write(&mm->mmap_sem);
+ eprintk("cannot split vma\n");
+ goto out;
+ }
+ }
+ up_write(&mm->mmap_sem);
+
+ for (i = 0; i < vmai.cpt_page_num; i++) {
+ struct cpt_page_block pb;
+
+ err = rst_get_object(CPT_OBJ_PAGES, &pb, sizeof(pb), ctx);
+ if (err)
+ goto out;
+ if (!(vmai.cpt_flags & VM_ACCOUNT) && !(prot & PROT_WRITE)) {
+ /* I guess this is get_user_pages() messed things,
+ * this happens f.e. when gdb inserts breakpoints.
+ */
+ int j;
+ for (j = 0; j < (pb.cpt_end-pb.cpt_start)/PAGE_SIZE; j++) {
+ struct page *page;
+ void *maddr;
+ err = get_user_pages(current, current->mm,
+ (unsigned long)pb.cpt_start +
+ j * PAGE_SIZE,
+ 1, 1, 1, &page, NULL);
+ if (err == 0)
+ err = -EFAULT;
+ if (err < 0) {
+ eprintk("get_user_pages: %d\n", err);
+ goto out;
+ }
+ err = 0;
+ maddr = kmap(page);
+ if (pb.cpt_content == CPT_CONTENT_VOID) {
+ memset(maddr, 0, PAGE_SIZE);
+ } else if (pb.cpt_content == CPT_CONTENT_DATA) {
+ err = ctx->read(maddr, PAGE_SIZE, ctx);
+ if (err) {
+ kunmap(page);
+ goto out;
+ }
+ } else {
+ err = -EINVAL;
+ kunmap(page);
+ goto out;
+ }
+ set_page_dirty_lock(page);
+ kunmap(page);
+ page_cache_release(page);
+ }
+ } else {
+ if (!(prot & PROT_WRITE))
+ sys_mprotect(vmai.cpt_start,
+ vmai.cpt_end - vmai.cpt_start,
+ prot | PROT_WRITE);
+ if (pb.cpt_content == CPT_CONTENT_VOID) {
+ int j;
+ for (j=0; j<(pb.cpt_end-pb.cpt_start)/sizeof(unsigned long); j++) {
+ err = __put_user(0UL, ((unsigned long __user*)(unsigned long)pb.cpt_start) + j);
+ if (err) {
+ eprintk("__put_user 2 %d\n", err);
+ goto out;
+ }
+ }
+ } else if (pb.cpt_content == CPT_CONTENT_DATA) {
+ err = ctx->read(cpt_ptr_import(pb.cpt_start),
+ pb.cpt_end - pb.cpt_start,
+ ctx);
+ if (err)
+ goto out;
+ } else {
+ err = -EINVAL;
+ goto out;
+ }
+ if (!(prot & PROT_WRITE))
+ sys_mprotect(vmai.cpt_start,
+ vmai.cpt_end - vmai.cpt_start,
+ prot);
+ }
+ }
+
+out:
+ if (file)
+ fput(file);
+ return err;
+}
+
+static int rst_restore_mm_context(struct cpt_context *ctx)
+{
+ struct cpt_obj_bits b;
+ struct mm_struct *mm = current->mm;
+ int oldsize = mm->context.size;
+ int err;
+ void *oldldt;
+ void *newldt;
+
+ err = rst_get_object(CPT_OBJ_BITS, &b, sizeof(b), ctx);
+ if (err)
+ return err;
+
+ if (b.cpt_size > PAGE_SIZE)
+ newldt = vmalloc(b.cpt_size);
+ else
+ newldt = kmalloc(b.cpt_size, GFP_KERNEL);
+
+ if (!newldt)
+ return -ENOMEM;
+
+ err = ctx->read(newldt, b.cpt_size, ctx);
+ if (err)
+ return err;
+
+ oldldt = mm->context.ldt;
+ mm->context.ldt = newldt;
+ mm->context.size = b.cpt_size / LDT_ENTRY_SIZE;
+
+ load_LDT(&mm->context);
+
+ if (oldsize) {
+ if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
+ vfree(oldldt);
+ else
+ kfree(oldldt);
+ }
+
+ return 0;
+}
+
+int rst_restore_mm(struct cpt_context *ctx)
+{
+ int err;
+ int i;
+ struct mm_struct *mm = current->mm;
+ struct cpt_mm_image m;
+
+ err = rst_get_object(CPT_OBJ_MM, &m, sizeof(m), ctx);
+ if (err)
+ return err;
+
+ down_write(&mm->mmap_sem);
+ do_munmap(mm, 0, TASK_SIZE);
+
+ mm->start_code = m.cpt_start_code;
+ mm->end_code = m.cpt_end_code;
+ mm->start_data = m.cpt_start_data;
+ mm->end_data = m.cpt_end_data;
+ mm->start_brk = m.cpt_start_brk;
+ mm->brk = m.cpt_brk;
+ mm->start_stack = m.cpt_start_stack;
+ mm->arg_start = m.cpt_start_arg;
+ mm->arg_end = m.cpt_end_arg;
+ mm->env_start = m.cpt_start_env;
+ mm->env_end = m.cpt_end_env;
+ mm->def_flags = m.cpt_def_flags;
+ mm->flags = m.cpt_flags;
+
+ up_write(&mm->mmap_sem);
+
+ for (i = 0; i < m.cpt_map_count; i++) {
+ err = rst_restore_one_vma(ctx);
+ if (err < 0)
+ goto out;
+ }
+
+ err = rst_restore_mm_context(ctx);
+out:
+ return err;
+}
+
diff --git a/cpt/rst_process.c b/cpt/rst_process.c
index 6d47f3c..84be46e 100644
--- a/cpt/rst_process.c
+++ b/cpt/rst_process.c
@@ -210,7 +210,8 @@ static int restart_thread(void *arg)
err = rst_get_object(CPT_OBJ_TASK, ti, sizeof(*ti), ctx);
if (!err)
err = rst_restore_task_struct(current, ti, ctx);
- /* Restore mm here */
+ if (!err)
+ err = rst_restore_mm(ctx);
if (!err)
err = rst_restore_fpustate(current, ti, ctx);
if (!err)
diff --git a/mm/mmap.c b/mm/mmap.c
index 971d0ed..98d1ba9 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1858,6 +1858,7 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
return 0;
}
+EXPORT_SYMBOL(split_vma);
/* Munmap is split into 2 main parts -- this part which finds
* what needs doing, and the areas themselves, which do the
diff --git a/mm/mprotect.c b/mm/mprotect.c
index fded06f..47c7d75 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -22,6 +22,7 @@
#include <linux/swap.h>
#include <linux/swapops.h>
#include <linux/mmu_notifier.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
@@ -317,3 +318,4 @@ out:
up_write(¤t->mm->mmap_sem);
return error;
}
+EXPORT_SYMBOL(sys_mprotect);
--
1.5.6
next prev parent reply other threads:[~2008-09-03 10:57 UTC|newest]
Thread overview: 138+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-03 10:57 [PATCH 0/9] OpenVZ kernel based checkpointing/restart Andrey Mirkin
2008-09-03 10:57 ` Andrey Mirkin
2008-09-03 10:57 ` [PATCH 1/9] Introduce trivial sys_checkpoint and sys_restore system calls Andrey Mirkin
2008-09-03 10:57 ` [PATCH 2/9] Make checkpoint/restart functionality modular Andrey Mirkin
2008-09-03 10:57 ` [PATCH 3/9] Introduce context structure needed during checkpointing/restart Andrey Mirkin
2008-09-03 10:57 ` [PATCH 4/9] Introduce container dump function Andrey Mirkin
2008-09-03 14:23 ` Serge E. Hallyn
[not found] ` <20080903142308.GB13425-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-09-03 14:45 ` Andrey Mirkin
2008-09-03 14:45 ` Andrey Mirkin
[not found] ` <1220439476-16465-5-git-send-email-major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-09-03 10:57 ` [PATCH 5/9] Introduce function to dump process Andrey Mirkin
2008-09-03 10:57 ` Andrey Mirkin
[not found] ` <1220439476-16465-6-git-send-email-major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-09-03 10:57 ` [PATCH 6/9] Introduce functions to dump mm Andrey Mirkin
2008-09-03 10:57 ` Andrey Mirkin
[not found] ` <1220439476-16465-7-git-send-email-major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-09-03 10:57 ` [PATCH 7/9] Introduce function for restarting a container Andrey Mirkin
2008-09-03 10:57 ` Andrey Mirkin
[not found] ` <1220439476-16465-8-git-send-email-major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-09-03 10:57 ` [PATCH 8/9] Introduce functions to restart a process Andrey Mirkin
2008-09-03 10:57 ` Andrey Mirkin
[not found] ` <1220439476-16465-9-git-send-email-major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-09-03 10:57 ` Andrey Mirkin [this message]
2008-09-03 10:57 ` [PATCH 9/9] Introduce functions to restore mm Andrey Mirkin
2008-09-03 14:32 ` [PATCH 8/9] Introduce functions to restart a process Louis Rilling
2008-09-03 14:32 ` Louis Rilling
[not found] ` <20080903143248.GU14473-Hu8+6S1rdjywhHL9vcZdMVaTQe2KTcn/@public.gmane.org>
2008-09-13 17:34 ` Pavel Machek
2008-09-13 17:34 ` Pavel Machek
2008-09-03 14:17 ` [PATCH 6/9] Introduce functions to dump mm Louis Rilling
2008-09-03 14:17 ` Louis Rilling
2008-09-03 14:23 ` [PATCH 4/9] Introduce container dump function Serge E. Hallyn
[not found] ` <1220439476-16465-4-git-send-email-major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-09-03 10:57 ` Andrey Mirkin
2008-09-03 12:29 ` [PATCH 3/9] Introduce context structure needed during checkpointing/restart Matthieu Fertré
2008-09-03 12:29 ` Matthieu Fertré
[not found] ` <48BE8315.6030907-7Ky3UMAtGjA@public.gmane.org>
2008-09-03 14:11 ` Andrey Mirkin
2008-09-03 14:11 ` Andrey Mirkin
2008-09-03 13:56 ` Louis Rilling
2008-09-03 14:13 ` Cedric Le Goater
2008-09-03 13:56 ` Louis Rilling
[not found] ` <20080903135616.GR14473-Hu8+6S1rdjywhHL9vcZdMVaTQe2KTcn/@public.gmane.org>
2008-09-03 14:07 ` Andrey Mirkin
2008-09-03 14:07 ` Andrey Mirkin
2008-09-03 14:13 ` Cedric Le Goater
[not found] ` <48BE9B74.7010600-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
2008-09-03 14:29 ` Andrey Mirkin
2008-09-03 14:29 ` Andrey Mirkin
[not found] ` <1220439476-16465-3-git-send-email-major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-09-03 10:57 ` Andrey Mirkin
2008-09-03 14:27 ` [PATCH 2/9] Make checkpoint/restart functionality modular Serge E. Hallyn
2008-09-03 14:27 ` Serge E. Hallyn
[not found] ` <20080903142720.GC13425-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-09-03 14:51 ` Andrey Mirkin
2008-09-03 14:51 ` Andrey Mirkin
[not found] ` <1220439476-16465-2-git-send-email-major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-09-03 10:57 ` Andrey Mirkin
2008-09-03 11:44 ` [PATCH 1/9] Introduce trivial sys_checkpoint and sys_restore system calls Cedric Le Goater
2008-09-03 11:44 ` Cedric Le Goater
2008-09-03 13:05 ` [Devel] " Andrey Mirkin
[not found] ` <48BE7885.3070609-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
2008-09-03 13:05 ` Andrey Mirkin
2008-09-03 12:28 ` [PATCH 0/9] OpenVZ kernel based checkpointing/restart Cedric Le Goater
2008-09-03 13:59 ` [Devel] " Andrey Mirkin
2008-09-04 22:55 ` Dave Hansen
[not found] ` <200809031759.29132.major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-09-04 22:55 ` Dave Hansen
[not found] ` <48BE82F9.4020808-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
2008-09-03 13:59 ` Andrey Mirkin
2008-09-03 14:18 ` Serge E. Hallyn
2008-09-03 14:18 ` Serge E. Hallyn
[not found] ` <1220439476-16465-1-git-send-email-major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-09-03 10:57 ` [PATCH 1/9] Introduce trivial sys_checkpoint and sys_restore system calls Andrey Mirkin
2008-09-03 12:28 ` [PATCH 0/9] OpenVZ kernel based checkpointing/restart Cedric Le Goater
2008-09-03 13:49 ` Louis Rilling
2008-09-04 8:14 ` Oren Laadan
2008-09-04 14:05 ` Dave Hansen
2008-10-17 23:33 ` Dave Hansen
2008-09-03 13:49 ` Louis Rilling
2008-09-03 14:06 ` Louis Rilling
2008-09-03 14:19 ` Andrey Mirkin
2008-09-03 14:26 ` Cedric Le Goater
[not found] ` <48BE9E95.3020706-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
2008-09-03 14:53 ` Andrey Mirkin
2008-09-03 14:53 ` Andrey Mirkin
[not found] ` <20080903140636.GS14473-Hu8+6S1rdjywhHL9vcZdMVaTQe2KTcn/@public.gmane.org>
2008-09-03 14:19 ` Andrey Mirkin
2008-09-03 14:26 ` Cedric Le Goater
[not found] ` <20080903134951.GQ14473-Hu8+6S1rdjywhHL9vcZdMVaTQe2KTcn/@public.gmane.org>
2008-09-03 14:06 ` Louis Rilling
2008-09-04 8:14 ` Oren Laadan
2008-09-04 14:05 ` Dave Hansen
2008-10-17 23:33 ` Dave Hansen
2008-10-20 11:10 ` Louis Rilling
[not found] ` <20081020111002.GQ15171-Hu8+6S1rdjywhHL9vcZdMVaTQe2KTcn/@public.gmane.org>
2008-10-20 13:25 ` Daniel Lezcano
2008-10-20 16:36 ` Dave Hansen
2008-10-20 13:25 ` Daniel Lezcano
[not found] ` <48FC86B2.8000606-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
2008-10-20 13:48 ` Cedric Le Goater
2008-10-20 13:48 ` Cedric Le Goater
2008-10-20 13:49 ` Daniel Lezcano
[not found] ` <48FC8C30.6040409-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
2008-10-20 13:49 ` Daniel Lezcano
2008-10-20 15:53 ` Oren Laadan
2008-10-20 15:53 ` Oren Laadan
[not found] ` <48FCA97C.1040108-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2008-10-20 16:37 ` Daniel Lezcano
2008-10-20 16:37 ` Daniel Lezcano
[not found] ` <48FCB3CC.9030804-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
2008-10-20 17:23 ` Serge E. Hallyn
2008-10-20 17:23 ` Serge E. Hallyn
[not found] ` <20081020172358.GA29092-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-10-21 0:18 ` Oren Laadan
2008-10-21 0:18 ` Oren Laadan
2008-10-21 0:58 ` Serge E. Hallyn
2008-10-21 13:24 ` Daniel Lezcano
[not found] ` <48FD1FBC.5050408-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2008-10-21 0:58 ` Serge E. Hallyn
2008-10-21 13:24 ` Daniel Lezcano
2008-10-27 14:45 ` [Devel] " Andrey Mirkin
2008-10-27 14:45 ` Andrey Mirkin
2008-10-20 16:51 ` Serge E. Hallyn
2008-10-21 9:36 ` Cedric Le Goater
2008-10-20 16:51 ` Serge E. Hallyn
2008-10-21 9:36 ` Cedric Le Goater
2008-10-20 16:36 ` Dave Hansen
2008-10-20 11:10 ` Louis Rilling
2008-10-20 12:14 ` [Devel] " Andrey Mirkin
2008-10-20 15:55 ` Dave Hansen
2008-10-27 14:07 ` Andrey Mirkin
2008-10-27 14:39 ` Oren Laadan
[not found] ` <4905D2AD.1070309-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2008-10-30 6:02 ` Andrey Mirkin
2008-10-30 6:02 ` Andrey Mirkin
2008-10-30 11:47 ` Louis Rilling
2008-10-30 17:08 ` Dave Hansen
2008-10-30 18:01 ` Louis Rilling
2008-10-30 18:28 ` Oren Laadan
[not found] ` <20081030180133.GN15171-Hu8+6S1rdjywhHL9vcZdMVaTQe2KTcn/@public.gmane.org>
2008-10-30 18:28 ` Oren Laadan
2008-10-30 18:01 ` Louis Rilling
2008-10-30 17:45 ` Oren Laadan
[not found] ` <4909F2B5.7040907-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2008-10-30 18:14 ` Louis Rilling
2008-10-30 18:14 ` Louis Rilling
[not found] ` <20081030181418.GO15171-Hu8+6S1rdjywhHL9vcZdMVaTQe2KTcn/@public.gmane.org>
2008-10-30 18:32 ` Oren Laadan
2008-10-30 18:32 ` Oren Laadan
[not found] ` <4909FDD3.5090806-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2008-10-31 10:37 ` Louis Rilling
2008-10-31 10:37 ` Louis Rilling
[not found] ` <20081030114747.GL15171-Hu8+6S1rdjywhHL9vcZdMVaTQe2KTcn/@public.gmane.org>
2008-10-30 17:08 ` Dave Hansen
2008-10-30 17:45 ` Oren Laadan
[not found] ` <200810300902.47067.major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-10-30 11:47 ` Louis Rilling
2008-10-30 14:08 ` Serge E. Hallyn
2008-10-30 17:03 ` Dave Hansen
2008-10-30 17:03 ` Dave Hansen
2008-10-30 14:08 ` Serge E. Hallyn
[not found] ` <200810271707.13580.major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-10-27 14:39 ` Oren Laadan
2008-11-03 19:35 ` Oren Laadan
2008-11-03 19:35 ` Oren Laadan
2008-10-27 14:07 ` Andrey Mirkin
[not found] ` <200810201614.36911.major-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2008-10-20 15:55 ` Dave Hansen
2008-10-20 17:17 ` Oren Laadan
2008-10-20 17:17 ` Oren Laadan
[not found] ` <48FCBD24.7070902-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2008-10-27 14:38 ` Andrey Mirkin
2008-10-27 14:38 ` Andrey Mirkin
2008-10-20 12:14 ` Andrey Mirkin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1220439476-16465-10-git-send-email-major@openvz.org \
--to=major-gefaqzzx7r8dnm+yrofe0a@public.gmane.org \
--cc=containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.