[CRIU] [PATCH cr 06/11] restore: mark all vma-s, which should not be unmapped in restorer

Andrey Vagin avagin at openvz.org
Mon Oct 15 11:32:19 EDT 2012


Private vma-s are mapped before forking children, then they are
remapped to corrected places in restorer.c.

In restorer all unneeded vma-s are unmaped, so crtools should
know which vma-s should remain, so crtools gets a current vma
list and then set a flag on vma-s which should not be unmaped.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-restore.c    |   93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/image.h |    2 +
 2 files changed, 95 insertions(+), 0 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index 020b489..6f465e9 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1275,6 +1275,8 @@ static VmaEntry *vma_list_remap(void *addr, unsigned long len, struct list_head
 	}
 
 	list_for_each_entry(vma_area, vmas, list) {
+		if (vma_entry_is(&vma_area->vma, VMA_AREA_DEST))
+			continue;
 		*vma = vma_area->vma;
 		vma++;
 	}
@@ -1359,6 +1361,94 @@ static int remap_restorer_blob(void *addr)
 	return 0;
 }
 
+static int mark_target_vmas(struct list_head *self_vma_list)
+{
+	LIST_HEAD(new_list);
+	struct vma_area *tmp, *vma, *new;
+	int len = 0;
+
+	vma = list_first_entry(self_vma_list, struct vma_area, list);
+
+	/* Some VMA may be merged, so they are should be splitted */
+	while (&vma->list != self_vma_list) {
+		struct vma_area *c, *n;
+
+		c = NULL;
+		len++;
+
+		/* Try to find a first target vma */
+		list_for_each_entry(n, &vma_list, list) {
+			unsigned long start = vma->vma.start;
+
+			if (!vma_anon(&n->vma))
+				continue;
+
+			if (n->vma.flags & MAP_GROWSDOWN)
+				start -= PAGE_SIZE; /* guard page */
+
+			if (n->vma.shmid >= start &&
+			    n->vma.shmid < vma->vma.end &&
+			    (c == NULL || c->vma.shmid > n->vma.shmid))
+				c = n;
+		}
+
+		if (c == NULL) {
+			tmp = list_entry(vma->list.next, struct vma_area, list);
+			list_move_tail(&vma->list, &new_list);
+			vma = tmp;
+			continue;
+		}
+
+		pr_debug("Mark VMA 0x%016lx-0x%016lx inside 0x%016lx-0x%016lx\n",
+				c->vma.shmid, c->vma.shmid + vma_area_len(c),
+				vma->vma.start, vma->vma.end);
+
+		/* A first part isn't a target VMA */
+		if (c->vma.shmid > vma->vma.start) {
+			BUG_ON(c->vma.flags & MAP_GROWSDOWN);
+			new = alloc_vma_area();
+			if (new == NULL)
+				return -1;
+			memcpy(new, vma, sizeof(*vma));
+
+			vma->vma.start = c->vma.shmid;
+
+			new->vma.end = c->vma.shmid;
+			list_add(&new->list, &new_list);
+			len++;
+		}
+
+		if (c->vma.flags & MAP_GROWSDOWN)
+			vma->vma.start -= PAGE_SIZE; /* guard page */
+
+		/* Split a target VMA and handle a remaining part again */
+		if (c->vma.shmid + vma_area_len(c) < vma->vma.end) {
+			new = alloc_vma_area();
+			if (new == NULL)
+				return -1;
+			memcpy(new, vma, sizeof(*vma));
+
+			new->vma.start = c->vma.shmid + vma_area_len(c);
+
+			vma->vma.end = c->vma.shmid + vma_area_len(c);
+			vma->vma.status |= VMA_AREA_DEST;
+			list_move_tail(&vma->list, &new_list);
+
+			vma = new;
+			continue;
+		}
+
+		tmp = list_entry(vma->list.next, struct vma_area, list);
+		vma->vma.status |= VMA_AREA_DEST;
+		list_move_tail(&vma->list, &new_list);
+		vma = tmp;
+	}
+
+	list_replace_init(&new_list, self_vma_list);
+
+	return len;
+}
+
 static int sigreturn_restore(pid_t pid, CoreEntry *core, struct list_head *tgt_vmas, int nr_vmas)
 {
 	long restore_task_vma_len;
@@ -1391,6 +1481,9 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core, struct list_head *tgt_v
 
 	/* required to unmap stack _with_ guard page */
 	mark_stack_vma((long) &self_vma_list, &self_vma_list);
+	ret = mark_target_vmas(&self_vma_list);
+	if (ret < 0)
+		goto err;
 
 	self_vmas_len = round_up((ret + 1) * sizeof(VmaEntry), PAGE_SIZE);
 	vmas_len = round_up((nr_vmas + 1) * sizeof(VmaEntry), PAGE_SIZE);
diff --git a/include/image.h b/include/image.h
index 9d67978..4fb4eab 100644
--- a/include/image.h
+++ b/include/image.h
@@ -93,6 +93,8 @@
 
 #define VMA_AREA_SYSVIPC	(1 <<  10)
 
+#define VMA_AREA_DEST		(1 <<  11)
+
 #define vma_entry_is(vma, s)	(((vma)->status & (s)) == (s))
 #define vma_entry_len(vma)	((vma)->end - (vma)->start)
 
-- 
1.7.1



More information about the CRIU mailing list