[CRIU] [PATCH] restorer: rework unmaping old VMA-s
Andrey Vagin
avagin at openvz.org
Fri Sep 20 10:21:01 EDT 2013
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.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
cr-restore.c | 9 ++----
include/restorer.h | 1 -
pie/restorer.c | 92 ++++++++++++++++++++++--------------------------------
3 files changed, 40 insertions(+), 62 deletions(-)
diff --git a/cr-restore.c b/cr-restore.c
index b38a378..146224f 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -2240,7 +2240,7 @@ void __gcov_flush(void) {}
static int sigreturn_restore(pid_t pid, CoreEntry *core)
{
long restore_task_vma_len;
- long restore_thread_vma_len, self_vmas_len, vmas_len;
+ long restore_thread_vma_len, vmas_len;
void *mem = MAP_FAILED;
void *restore_thread_exec_start;
@@ -2284,7 +2284,6 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
if (rst_mem_init())
goto err;
- self_vmas_len = round_up((self_vmas.nr + 1) * sizeof(VmaEntry), PAGE_SIZE);
vmas_len = round_up((rst_vmas.nr + 1) * sizeof(VmaEntry), PAGE_SIZE);
/* pr_info_vma_list(&self_vma_list); */
@@ -2346,7 +2345,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
restore_task_vma_len +
restore_thread_vma_len +
SHMEMS_SIZE + TASK_ENTRIES_SIZE +
- self_vmas_len + vmas_len +
+ vmas_len +
rst_mem_len;
/*
@@ -2438,11 +2437,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
task_args->task_entries = mem;
mem += TASK_ENTRIES_SIZE;
- task_args->self_vmas = vma_list_remap(mem, self_vmas_len, &self_vmas);
- if (!task_args->self_vmas)
- goto err;
- mem += self_vmas_len;
task_args->nr_vmas = rst_vmas.nr;
task_args->tgt_vmas = vma_list_remap(mem, vmas_len, &rst_vmas);
task_args->premmapped_addr = (unsigned long) current->rst->premmapped_addr;
diff --git a/include/restorer.h b/include/restorer.h
index ae762d7..2dd2977 100644
--- a/include/restorer.h
+++ b/include/restorer.h
@@ -117,7 +117,6 @@ struct task_restore_core_args {
struct task_entries *task_entries;
void *rst_mem;
unsigned long rst_mem_size;
- VmaEntry *self_vmas;
VmaEntry *tgt_vmas;
siginfo_t *siginfo;
unsigned int siginfo_nr;
diff --git a/pie/restorer.c b/pie/restorer.c
index 3c88484..95bb63f 100644
--- a/pie/restorer.c
+++ b/pie/restorer.c
@@ -523,6 +523,37 @@ 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)
+{
+ void *p[6] = {NULL, 0, 0, 0, 0, (void *) TASK_SIZE};
+ int xchg, i;
+
+ /* Sorting vma-s */
+ xchg = premmapped_addr > bootstrap_start ? 2 : 0;
+
+ p[1 + xchg] = premmapped_addr;
+ p[2 + xchg] = premmapped_addr + premmapped_len;
+ p[3 - xchg] = bootstrap_start;
+ p[4 - xchg] = bootstrap_start + bootstrap_len;
+
+ for (i = 0; i < 6; i += 2) {
+ int ret;
+ ret = sys_munmap(p[i], p[i + 1] - p[i]);
+ if (ret) {
+ pr_err("Unable to unmap (%p-%p): %d\n",
+ p[i], p[i + 1], ret);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
* The main routine to restore task via sigreturn.
* This one is very special, we never return there
* but use sigreturn facility to restore core registers
@@ -534,7 +565,6 @@ long __export_restore_task(struct task_restore_core_args *args)
long ret = -1;
VmaEntry *vma_entry;
unsigned long va;
- unsigned long premmapped_end = args->premmapped_addr + args->premmapped_len;
struct rt_sigframe *rt_sigframe;
unsigned long new_sp;
@@ -559,60 +589,14 @@ long __export_restore_task(struct task_restore_core_args *args)
pr_info("Switched to the restorer %d\n", my_pid);
- for (vma_entry = args->self_vmas; vma_entry->start != 0; vma_entry++) {
- unsigned long addr = vma_entry->start;
- unsigned long len;
-
- if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
- continue;
-
- pr_debug("Examine %"PRIx64"-%"PRIx64"\n", vma_entry->start, vma_entry->end);
-
- /*
- * Park runtime vdso at safe place, thus we can access it
- * during restore of targets vma, it's quite important to
- * remap it instead of copying to save page frame number
- * associated with vdso, we will use it if there is subsequent
- * checkpoint done on previously restored program.
- */
- if (vma_entry_is(vma_entry, VMA_AREA_VDSO)) {
- BUG_ON(vma_entry->start != args->vdso_sym_rt.vma_start);
- BUG_ON(vma_entry_len(vma_entry) != vdso_vma_size(&args->vdso_sym_rt));
-
- if (vdso_remap("rt-vdso", vma_entry->start,
- args->vdso_rt_parked_at,
- vdso_vma_size(&args->vdso_sym_rt)))
- goto core_restore_end;
- continue;
- }
-
- if (addr < args->premmapped_addr) {
- if (vma_entry->end >= args->premmapped_addr)
- len = args->premmapped_addr - addr;
- else
- len = vma_entry->end - vma_entry->start;
- if (sys_munmap((void *) addr, len)) {
- pr_err("munmap fail for %lx - %lx\n", addr, addr + len);
- goto core_restore_end;
- }
- }
-
- if (vma_entry->end >= TASK_SIZE)
- continue;
-
- if (vma_entry->end > premmapped_end) {
- if (vma_entry->start < premmapped_end)
- addr = premmapped_end;
- len = vma_entry->end - addr;
- if (sys_munmap((void *) addr, len)) {
- pr_err("munmap fail for %lx - %lx\n", addr, addr + len);
- goto core_restore_end;
- }
- }
- }
+ if (vdso_remap("rt-vdso", args->vdso_sym_rt.vma_start,
+ args->vdso_rt_parked_at,
+ vdso_vma_size(&args->vdso_sym_rt)))
+ goto core_restore_end;
- sys_munmap(args->self_vmas,
- ((void *)(vma_entry + 1) - ((void *)args->self_vmas)));
+ if (unmap_old_vmas((void *)args->premmapped_addr, args->premmapped_len,
+ bootstrap_start, bootstrap_len))
+ goto core_restore_end;
/* Shift private vma-s to the left */
for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) {
--
1.8.3.1
More information about the CRIU
mailing list