[CRIU] [PATCH 10/11] vma: Mark cow roots

Pavel Emelyanov xemul at virtuozzo.com
Thu May 11 02:13:33 PDT 2017


Next patch will stop premapping some private vmas. In particular -- those,
that are not COW-ed with anyone. To make this work we need to distinguish
vmas that are not cowed with anyone from those cowed with children only.
Currently both have vma->parent pointer set to NULL, so for former let's
introduce the special mark.

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/include/vma.h |  2 ++
 criu/mem.c         | 16 ++++++++++++----
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/criu/include/vma.h b/criu/include/vma.h
index 7870966..3e1d9a1 100644
--- a/criu/include/vma.h
+++ b/criu/include/vma.h
@@ -73,6 +73,8 @@ struct vma_area {
 	};
 };
 
+#define VMA_COW_ROOT	((struct vma_area *)1)
+
 typedef int (*dump_filemap_t)(struct vma_area *vma_area, int fd);
 
 extern struct vma_area *alloc_vma_area(void);
diff --git a/criu/mem.c b/criu/mem.c
index ee48060..b4f9990 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -581,6 +581,11 @@ static inline bool check_cow_vmas(struct vma_area *vma, struct vma_area *pvma)
 	return true;
 }
 
+static inline bool vma_inherited(struct vma_area *vma)
+{
+	return (vma->pvma != NULL && vma->pvma != VMA_COW_ROOT);
+}
+
 static void prepare_cow_vmas_for(struct vm_area_list *vmas, struct vm_area_list *pvmas)
 {
 	struct vma_area *vma, *pvma;
@@ -589,8 +594,11 @@ static void prepare_cow_vmas_for(struct vm_area_list *vmas, struct vm_area_list
 	pvma = list_first_entry(&pvmas->h, struct vma_area, list);
 
 	while (1) {
-		if ((vma->e->start == pvma->e->start) && check_cow_vmas(vma, pvma))
+		if ((vma->e->start == pvma->e->start) && check_cow_vmas(vma, pvma)) {
 			vma->pvma = pvma;
+			if (pvma->pvma == NULL)
+				pvma->pvma = VMA_COW_ROOT;
+		}
 
 		/* <= here to shift from matching VMAs and ... */
 		while (vma->e->start <= pvma->e->start) {
@@ -661,7 +669,7 @@ static int premap_private_vma(struct pstree_item *t, struct vma_area *vma, void
 		vma->e->start -= PAGE_SIZE;
 
 	size = vma_entry_len(vma->e);
-	if (vma->pvma == NULL) {
+	if (!vma_inherited(vma)) {
 		int flag = 0;
 		/*
 		 * The respective memory area was NOT found in the parent.
@@ -836,7 +844,7 @@ static int restore_priv_vma_content(struct pstree_item *t, struct page_read *pr)
 					vma->premmaped_addr);
 
 			set_bit(off, vma->page_bitmap);
-			if (vma->pvma) { /* inherited vma */
+			if (vma_inherited(vma)) {
 				clear_bit(off, vma->pvma->page_bitmap);
 
 				ret = pr->read_pages(pr, va, 1, buf, 0);
@@ -894,7 +902,7 @@ err_read:
 		unsigned long size, i = 0;
 		void *addr = decode_pointer(vma->premmaped_addr);
 
-		if (vma->pvma == NULL)
+		if (!vma_inherited(vma))
 			continue;
 
 		size = vma_entry_len(vma->e) / PAGE_SIZE;
-- 
2.1.4



More information about the CRIU mailing list