[10/11] vma: Mark cow roots

Submitted by Pavel Emelianov on May 5, 2017, 4:04 p.m.

Details

Message ID 80d9b089-bb11-1bbd-90d3-e8e0d317ab1b@virtuozzo.com
State New
Series "Do not remap vmas when not needed"
Headers show

Commit Message

Pavel Emelianov May 5, 2017, 4:04 p.m.
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@virtuozzo.com>
---
 criu/include/vma.h |  2 ++
 criu/mem.c         | 16 ++++++++++++----
 2 files changed, 14 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/include/vma.h b/criu/include/vma.h
index de8b411..c941890 100644
--- a/criu/include/vma.h
+++ b/criu/include/vma.h
@@ -72,6 +72,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 e8ca093..fe62b41 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) {
@@ -659,7 +667,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.
@@ -834,7 +842,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);
@@ -892,7 +900,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;