[CRIU] [PATCH 1/2] vm: don't overwrite vma->shmid for private mappings

Andrey Vagin avagin at openvz.org
Fri Nov 22 06:12:45 PST 2013


shmid contains a file id for file mappings. It's required to determine,
which VMA-s are cowed. The parent maps a VMA and saves premmaped
address. Then  child trys to determing, which VMA-s must be inhereted
from parent, for that it compares addresses, flags and file id.

We don't want to transfer vma_area-s in restorer, so when a VMA entry is
copied in restorer memory, the premmaped address is save in shmid.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-restore.c  | 17 +++++++++--------
 include/vma.h | 11 ++++++++++-
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index 27169e7..218b9ae 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -223,8 +223,6 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr,
 			return -1;
 		}
 		vma->vma.fd = ret;
-		/* shmid will be used for a temporary address */
-		vma->vma.shmid = 0;
 	}
 
 	nr_pages = vma_entry_len(&vma->vma) / PAGE_SIZE;
@@ -240,7 +238,7 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr,
 		    p->vma.start == vma->vma.start) {
 			pr_info("COW 0x%016"PRIx64"-0x%016"PRIx64" 0x%016"PRIx64" vma\n",
 				vma->vma.start, vma->vma.end, vma->vma.pgoff);
-			paddr = decode_pointer(vma_premmaped_start(&p->vma));
+			paddr = decode_pointer(vma->premmaped_addr);
 			break;
 		}
 
@@ -292,13 +290,13 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr,
 
 	}
 
-	vma_premmaped_start(&(vma->vma)) = (unsigned long) addr;
+	vma->premmaped_addr = (unsigned long) addr;
 	pr_debug("\tpremap 0x%016"PRIx64"-0x%016"PRIx64" -> %016lx\n",
 		vma->vma.start, vma->vma.end, (unsigned long)addr);
 
 	if (vma->vma.flags & MAP_GROWSDOWN) { /* Skip gurad page */
 		vma->vma.start += PAGE_SIZE;
-		vma_premmaped_start(&vma->vma) += PAGE_SIZE;
+		vma->premmaped_addr += PAGE_SIZE;
 	}
 
 	if (vma_entry_is(&vma->vma, VMA_FILE_PRIVATE))
@@ -366,7 +364,7 @@ static int restore_priv_vma_content(pid_t pid)
 
 			off = (va - vma->vma.start) / PAGE_SIZE;
 			p = decode_pointer((off) * PAGE_SIZE +
-					vma_premmaped_start(&vma->vma));
+					vma->premmaped_addr);
 
 			set_bit(off, vma->page_bitmap);
 			if (vma->ppage_bitmap) { /* inherited vma */
@@ -404,7 +402,7 @@ static int restore_priv_vma_content(pid_t pid)
 	/* Remove pages, which were not shared with a child */
 	list_for_each_entry(vma, &rst_vmas.h, list) {
 		unsigned long size, i = 0;
-		void *addr = decode_pointer(vma_premmaped_start(&vma->vma));
+		void *addr = decode_pointer(vma->premmaped_addr);
 
 		if (vma->ppage_bitmap == NULL)
 			continue;
@@ -574,7 +572,7 @@ static int unmap_guard_pages()
 			continue;
 
 		if (vma->vma.flags & MAP_GROWSDOWN) {
-			void *addr = decode_pointer(vma_premmaped_start(&vma->vma));
+			void *addr = decode_pointer(vma->premmaped_addr);
 
 			if (munmap(addr - PAGE_SIZE, PAGE_SIZE)) {
 				pr_perror("Can't unmap guard page\n");
@@ -2220,6 +2218,9 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
 			goto err_nv;
 
 		*vme = vma->vma;
+
+		if (vma_priv(&vma->vma))
+			vma_premmaped_start(vme) = vma->premmaped_addr;
 	}
 
 	/*
diff --git a/include/vma.h b/include/vma.h
index 47c8635..481b690 100644
--- a/include/vma.h
+++ b/include/vma.h
@@ -23,6 +23,8 @@ struct vma_area {
 	};
 	unsigned long		*page_bitmap;  /* existent pages */
 	unsigned long		*ppage_bitmap; /* parent's existent pages */
+
+	unsigned long		premmaped_addr;
 };
 
 extern int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list);
@@ -31,10 +33,17 @@ extern bool privately_dump_vma(struct vma_area *vma);
 
 #define vma_area_is(vma_area, s)	vma_entry_is(&((vma_area)->vma), s)
 #define vma_area_len(vma_area)		vma_entry_len(&((vma_area)->vma))
-#define vma_premmaped_start(vma)	((vma)->shmid)
 #define vma_entry_is(vma, s)		(((vma)->status & (s)) == (s))
 #define vma_entry_len(vma)		((vma)->end - (vma)->start)
 
+/*
+ * vma_premmaped_start() can be used only in restorer.
+ * In other cases vma_area->premmaped_addr must be used.
+ * This hack is required, because vma_area isn't tranfered in restorer and
+ * shmid is used to determing which vma-s are cowed.
+ */
+#define vma_premmaped_start(vma)	((vma)->shmid)
+
 static inline int in_vma_area(struct vma_area *vma, unsigned long addr)
 {
 	return addr >= (unsigned long)vma->vma.start &&
-- 
1.8.3.1



More information about the CRIU mailing list