[CRIU] [PATCH] mem: Rework vma open

Pavel Emelyanov xemul at virtuozzo.com
Fri May 20 04:15:02 PDT 2016


We now have two places where we if/elseif/elseif/else a vma
and take actions -- the prepare_mm_pid and open_vmas. I propose
to make this if/... onlce once (while preparing) and set up
a callback on vma to be called later (while opening).

This requires my patch that doesn't set -1 in alloc_vma or
Andrey's patch that does the same.

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/cr-dump.c           |  2 +-
 criu/cr-restore.c        | 28 +++++++------------------
 criu/files-reg.c         | 23 +++++++++++++++++++--
 criu/include/files-reg.h |  1 +
 criu/include/files.h     |  1 -
 criu/include/shmem.h     |  6 +++---
 criu/include/sk-packet.h |  3 ++-
 criu/include/vma.h       |  1 +
 criu/mem.c               | 20 +++++-------------
 criu/pie/restorer.c      |  2 +-
 criu/shmem.c             | 53 +++++++++++++++++++++++++++++++++++-------------
 criu/sk-packet.c         | 12 +++++++++--
 12 files changed, 91 insertions(+), 61 deletions(-)

diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 8ef46a4..3507aee 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -394,7 +394,7 @@ static int dump_filemap(pid_t pid, struct vma_area *vma_area,
 		p.link = &aufs_link;
 	}
 
-	/* Flags will be set during restore in get_filemap_fd() */
+	/* Flags will be set during restore in open_filmap() */
 
 	if (fd_id_generate_special(&p, &id))
 		ret = dump_one_reg_file(vma_area->vm_file_fd, id, &p);
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index ceb40fb..cb25982 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -293,12 +293,13 @@ static int map_private_vma(struct vma_area *vma, void **tgt_addr,
 	struct vma_area *p = *pvma;
 
 	if (vma_area_is(vma, VMA_FILE_PRIVATE)) {
-		ret = get_filemap_fd(vma);
+		ret = vma->vm_open(current->pid.virt, vma);
 		if (ret < 0) {
 			pr_err("Can't fixup VMA's fd\n");
 			return -1;
 		}
-		vma->e->fd = ret;
+
+		vma->vm_open = NULL; /* prevent from 2nd open in open_vmas */
 	}
 
 	nr_pages = vma_entry_len(vma->e) / PAGE_SIZE;
@@ -689,7 +690,6 @@ static int unmap_guard_pages()
 static int open_vmas(int pid)
 {
 	struct vma_area *vma;
-	int ret = 0;
 	struct list_head *vmas = &rsti(current)->vmas.h;
 
 	list_for_each_entry(vma, vmas, list) {
@@ -700,27 +700,13 @@ static int open_vmas(int pid)
 				vma->e->start, vma->e->end,
 				vma->e->pgoff, vma->e->status);
 
-		if (vma_area_is(vma, VMA_AREA_SYSVIPC))
-			ret = get_sysv_shmem_fd(vma->e);
-		else if (vma_area_is(vma, VMA_ANON_SHARED))
-			ret = get_shmem_fd(pid, vma->e);
-		else if (vma_area_is(vma, VMA_FILE_SHARED))
-			ret = get_filemap_fd(vma);
-		else if (vma_area_is(vma, VMA_AREA_SOCKET))
-			ret = get_socket_fd(pid, vma->e);
-		else
-			continue;
-
-		if (ret < 0) {
-			pr_err("Can't fixup fd\n");
-			break;
+		if (vma->vm_open && vma->vm_open(pid, vma)) {
+			pr_err("`- Can't open vma\n");
+			return -1;
 		}
-
-		pr_info("\t`- setting %d as mapping fd\n", ret);
-		vma->e->fd = ret;
 	}
 
-	return ret < 0 ? -1 : 0;
+	return 0;
 }
 
 static rt_sigaction_t sigchld_act;
diff --git a/criu/files-reg.c b/criu/files-reg.c
index fd36ae9..5bf0f5c 100644
--- a/criu/files-reg.c
+++ b/criu/files-reg.c
@@ -1572,9 +1572,10 @@ int open_reg_by_id(u32 id)
 	return open_reg_fd(fd);
 }
 
-int get_filemap_fd(struct vma_area *vma)
+static int open_filemap(int pid, struct vma_area *vma)
 {
 	u32 flags;
+	int ret;
 
 	/*
 	 * Thevma->fd should have been assigned in collect_filemap
@@ -1591,7 +1592,25 @@ int get_filemap_fd(struct vma_area *vma)
 	else
 		flags = O_RDONLY;
 
-	return open_path(vma->vmfd, do_open_reg_noseek_flags, &flags);
+	ret = open_path(vma->vmfd, do_open_reg_noseek_flags, &flags);
+	if (ret < 0)
+		return ret;
+
+	vma->e->fd = ret;
+	return 0;
+}
+
+int collect_filemap(struct vma_area *vma)
+{
+	struct file_desc *fd;
+
+	fd = collect_special_file(vma->e->shmid);
+	if (!fd)
+		return -1;
+
+	vma->vmfd = fd;
+	vma->vm_open = open_filemap;
+	return 0;
 }
 
 static void remap_get(struct file_desc *fdesc, char typ)
diff --git a/criu/include/files-reg.h b/criu/include/files-reg.h
index 9e5944d..4bf5cd5 100644
--- a/criu/include/files-reg.h
+++ b/criu/include/files-reg.h
@@ -45,6 +45,7 @@ extern void remap_put(struct file_remap *remap);
 
 extern struct file_desc *try_collect_special_file(u32 id, int optional);
 #define collect_special_file(id)	try_collect_special_file(id, 0)
+extern int collect_filemap(struct vma_area *);
 
 extern int collect_remaps_and_regfiles(void);
 
diff --git a/criu/include/files.h b/criu/include/files.h
index 1894f09..65b7d51 100644
--- a/criu/include/files.h
+++ b/criu/include/files.h
@@ -184,7 +184,6 @@ extern int prepare_fds(struct pstree_item *me);
 extern int prepare_fd_pid(struct pstree_item *me);
 extern int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id);
 extern int prepare_shared_fdinfo(void);
-extern int get_filemap_fd(struct vma_area *);
 extern int restore_fs(struct pstree_item *);
 extern int prepare_fs_pid(struct pstree_item *);
 extern int set_fd_flags(int fd, int flags);
diff --git a/criu/include/shmem.h b/criu/include/shmem.h
index 217394c..e07db1f 100644
--- a/criu/include/shmem.h
+++ b/criu/include/shmem.h
@@ -5,11 +5,11 @@
 #include "images/vma.pb-c.h"
 
 struct _VmaEntry;
-extern int collect_shmem(int pid, struct _VmaEntry *vi);
+struct vma_area;
+
+extern int collect_shmem(int pid, struct vma_area *vma);
 extern int collect_sysv_shmem(unsigned long shmid, unsigned long size);
 extern void show_saved_shmems(void);
-extern int get_shmem_fd(int pid, VmaEntry *vi);
-extern int get_sysv_shmem_fd(struct _VmaEntry *vi);
 extern int cr_dump_shmem(void);
 extern int add_shmem_area(pid_t pid, VmaEntry *vma);
 extern int fixup_sysv_shmems(void);
diff --git a/criu/include/sk-packet.h b/criu/include/sk-packet.h
index 6c4398c..fda471f 100644
--- a/criu/include/sk-packet.h
+++ b/criu/include/sk-packet.h
@@ -12,8 +12,9 @@ struct vma_area;
 extern struct collect_image_info packet_sk_cinfo;
 
 extern int dump_socket_map(struct vma_area *vma);
-extern int get_socket_fd(int pid, VmaEntry *vma);
+extern int collect_socket_map(struct vma_area *);
 
+struct nlmsghdr;
 extern int packet_receive_one(struct nlmsghdr *h, void *arg);
 
 #ifndef PACKET_VNET_HDR
diff --git a/criu/include/vma.h b/criu/include/vma.h
index d69f5f0..44b3fdb 100644
--- a/criu/include/vma.h
+++ b/criu/include/vma.h
@@ -63,6 +63,7 @@ struct vma_area {
 		};
 
 		struct /* for restore */ {
+			int (*vm_open)(int pid, struct vma_area *vma);
 			struct file_desc *vmfd;
 			unsigned long	*page_bitmap;	/* existent pages */
 			unsigned long	*ppage_bitmap;	/* parent's existent pages */
diff --git a/criu/mem.c b/criu/mem.c
index 4d11a8d..e05dbc1 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -18,6 +18,7 @@
 #include "shmem.h"
 #include "pstree.h"
 #include "restorer.h"
+#include "sk-packet.h"
 #include "files-reg.h"
 #include "pagemap-cache.h"
 #include "fault-injection.h"
@@ -405,18 +406,6 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl,
 	return ret;
 }
 
-static inline int collect_filemap(struct vma_area *vma)
-{
-	struct file_desc *fd;
-
-	fd = collect_special_file(vma->e->shmid);
-	if (!fd)
-		return -1;
-
-	vma->vmfd = fd;
-	return 0;
-}
-
 int prepare_mm_pid(struct pstree_item *i)
 {
 	pid_t pid = i->pid.virt;
@@ -478,12 +467,13 @@ int prepare_mm_pid(struct pstree_item *i)
 
 		pr_info("vma 0x%"PRIx64" 0x%"PRIx64"\n", vma->e->start, vma->e->end);
 
-		if (vma_area_is(vma, VMA_ANON_SHARED) &&
-				!vma_area_is(vma, VMA_AREA_SYSVIPC))
-			ret = collect_shmem(pid, vma->e);
+		if (vma_area_is(vma, VMA_ANON_SHARED))
+			ret = collect_shmem(pid, vma);
 		else if (vma_area_is(vma, VMA_FILE_PRIVATE) ||
 				vma_area_is(vma, VMA_FILE_SHARED))
 			ret = collect_filemap(vma);
+		else if (vma_area_is(vma, VMA_AREA_SOCKET))
+			ret = collect_socket_map(vma);
 		else
 			ret = 0;
 		if (ret)
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index 2c439a9..4515222 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -524,7 +524,7 @@ static unsigned long restore_mapping(const VmaEntry *vma_entry)
 
 	if (vma_entry_is(vma_entry, VMA_AREA_SYSVIPC)) {
 		/*
-		 * See comment in get_sysv_shmem_fd() for what SYSV_SHMEM_SKIP_FD
+		 * See comment in open_shmem_sysv() for what SYSV_SHMEM_SKIP_FD
 		 * means and why we check for PROT_EXEC few lines below.
 		 */
 		if (vma_entry->fd == SYSV_SHMEM_SKIP_FD)
diff --git a/criu/shmem.c b/criu/shmem.c
index 49fa88a..99cd78c 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -136,7 +136,7 @@ int fixup_sysv_shmems(void)
 
 		list_for_each_entry(att, &si->att, l) {
 			/*
-			 * Same thing is checked in get_sysv_shmem_fd() for
+			 * Same thing is checked in open_shmem_sysv() for
 			 * intermediate holes.
 			 */
 			if (att->first->start + si->size != att->prev_end) {
@@ -145,7 +145,7 @@ int fixup_sysv_shmems(void)
 			}
 
 			/*
-			 * See comment in get_shmem_fd() about this PROT_EXEC 
+			 * See comment in open_shmem_sysv() about this PROT_EXEC 
 			 */
 			if (si->want_write)
 				att->first->prot |= PROT_EXEC;
@@ -155,11 +155,12 @@ int fixup_sysv_shmems(void)
 	return 0;
 }
 
-int get_sysv_shmem_fd(VmaEntry *vme)
+static int open_shmem_sysv(int pid, struct vma_area *vma)
 {
+	VmaEntry *vme = vma->e;
 	struct shmem_sysv_info *si;
 	struct shmem_sysv_att *att;
-	int ret_fd;
+	uint64_t ret_fd;
 
 	si = (struct shmem_sysv_info *)find_shmem_by_id(vme->shmid);
 	if (!si) {
@@ -242,14 +243,25 @@ int get_sysv_shmem_fd(VmaEntry *vme)
 		 */
 		si->want_write = 1;
 
-	return ret_fd;
+	vme->fd = ret_fd;
+	return 0;
 }
 
-int collect_shmem(int pid, VmaEntry *vi)
+static int open_shmem(int pid, struct vma_area *vma);
+
+int collect_shmem(int pid, struct vma_area *vma)
 {
+	VmaEntry *vi = vma->e;
 	unsigned long size = vi->pgoff + vi->end - vi->start;
 	struct shmem_info *si;
 
+	if (vma_entry_is(vi, VMA_AREA_SYSVIPC)) {
+		vma->vm_open = open_shmem_sysv;
+		return 0;
+	}
+
+	vma->vm_open = open_shmem;
+
 	si = find_shmem_by_id(vi->shmid);
 	if (si) {
 		if (si->pid == SYSVIPC_SHMEM_PID) {
@@ -299,7 +311,7 @@ int collect_shmem(int pid, VmaEntry *vi)
 	return 0;
 }
 
-static int shmem_wait_and_open(int pid, struct shmem_info *si)
+static int shmem_wait_and_open(int pid, struct shmem_info *si, VmaEntry *vi)
 {
 	char path[128];
 	int ret;
@@ -316,7 +328,11 @@ static int shmem_wait_and_open(int pid, struct shmem_info *si)
 		pr_perror("     %d: Can't stat shmem at %s",
 				si->pid, path);
 	futex_inc_and_wake(&si->lock);
-	return ret;
+	if (ret < 0)
+		return -1;
+
+	vi->fd = ret;
+	return 0;
 }
 
 static int restore_shmem_content(void *addr, struct shmem_info *si)
@@ -368,8 +384,9 @@ static int restore_shmem_content(void *addr, struct shmem_info *si)
 	return ret;
 }
 
-int get_shmem_fd(int pid, VmaEntry *vi)
+static int open_shmem(int pid, struct vma_area *vma)
 {
+	VmaEntry *vi = vma->e;
 	struct shmem_info *si;
 	void *addr = MAP_FAILED;
 	int f = -1;
@@ -385,10 +402,17 @@ int get_shmem_fd(int pid, VmaEntry *vi)
 	BUG_ON(si->pid == SYSVIPC_SHMEM_PID);
 
 	if (si->pid != pid)
-		return shmem_wait_and_open(pid, si);
+		return shmem_wait_and_open(pid, si, vi);
 
-	if (si->fd != -1)
-		return dup(si->fd);
+	if (si->fd != -1) {
+		f = dup(si->fd);
+		if (f < 0) {
+			pr_perror("Can't dup shmem fd");
+			return -1;
+		}
+
+		goto out;
+	}
 
 	flags = MAP_SHARED;
 #ifdef CONFIG_HAS_MEMFD
@@ -445,8 +469,9 @@ int get_shmem_fd(int pid, VmaEntry *vi)
 	 * the file descriptor, so we don't wait them.
 	 */
 	futex_wait_until(&si->lock, si->count - si->self_count + 1);
-
-	return f;
+out:
+	vi->fd = f;
+	return 0;
 err:
 	if (addr != MAP_FAILED)
 		munmap(addr, si->size);
diff --git a/criu/sk-packet.c b/criu/sk-packet.c
index 73d9c7b..d82268e 100644
--- a/criu/sk-packet.c
+++ b/criu/sk-packet.c
@@ -302,8 +302,9 @@ err:
 	return -1;
 }
 
-int get_socket_fd(int pid, VmaEntry *vma)
+static int open_socket_map(int pid, struct vma_area *vm)
 {
+	VmaEntry *vma = vm->e;
 	struct file_desc *fd;
 	struct fdinfo_list_entry *le;
 
@@ -329,13 +330,20 @@ int get_socket_fd(int pid, VmaEntry *vma)
 				return -1;
 			}
 
-			return fd;
+			vma->fd = fd;
+			return 0;
 		}
 
 	pr_err("No open packet socket %x by %d\n", (int)vma->shmid, pid);
 	return -1;
 }
 
+int collect_socket_map(struct vma_area *vma)
+{
+	vma->vm_open = open_socket_map;
+	return 0;
+}
+
 static int restore_mreqs(int sk, PacketSockEntry *pse)
 {
 	int i;
-- 
2.5.0


More information about the CRIU mailing list