[CRIU] [PATCH] filemap: Get vma mnt_id early

Pavel Emelyanov xemul at parallels.com
Tue Sep 23 09:32:50 PDT 2014


We have a, well, issue with how we calculate the vma's mnt_id.

Right now get one via criu side file descriptor that it got by
opening the /proc/pid/map_files/ link. The problem is that these
descriptors are 'merged' or 'borrowed' by adjacent vmas from
previous ones. Thus, getting the mnt_id value for each of them
makes no sense -- these files are the same.

So move this mnt_id getting earlier into vma parsing code. This
brings a potential problem -- if we have two adjacent vmas
mapping the same inode (dev:ino pair) but living in different
mount namespaces -- this check would produce wrong result. 
"Wrong" from the perspective that on restore correct file would
be opened from wrong namespace.

I propose to live with it, since this is not worse than the
--evasive-devices option, it's _very_ unlikely, but saves a lot
of openeings.

Note, that in case app switched mount namespace and then mapped
some new library (with dlopen) things would work correctly -- new
vmas will likely be not adjacent and for different dev:ino.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 cr-dump.c            | 15 +--------------
 include/proc_parse.h |  1 +
 include/vma.h        |  1 +
 proc_parse.c         | 23 +++++++++++++++++++++++
 4 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index 72eb94d..e873a38 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -247,17 +247,6 @@ static int collect_fds(pid_t pid, struct parasite_drain_fd *dfds)
 	return 0;
 }
 
-static int get_fd_mntid(int fd, int *mnt_id)
-{
-	struct fdinfo_common fdinfo = { .mnt_id = -1};
-
-	if (parse_fdinfo(fd, FD_TYPES__UND, NULL, &fdinfo))
-		return -1;
-
-	*mnt_id = fdinfo.mnt_id;
-	return 0;
-}
-
 static int fill_fd_params_special(int fd, struct fd_parms *p)
 {
 	*p = FD_PARMS_INIT;
@@ -371,6 +360,7 @@ static int dump_filemap(pid_t pid, struct vma_area *vma_area,
 
 	BUG_ON(!vma_area->vmst);
 	p.stat = *vma_area->vmst;
+	p.mnt_id = vma_area->mnt_id;
 
 	/*
 	 * AUFS support to compensate for the kernel bug
@@ -388,9 +378,6 @@ static int dump_filemap(pid_t pid, struct vma_area *vma_area,
 		p.link = &aufs_link;
 	}
 
-	if (get_fd_mntid(vma_area->vm_file_fd, &p.mnt_id))
-		return -1;
-
 	/* Flags will be set during restore in get_filemap_fd() */
 
 	if (fd_id_generate_special(&p, &id))
diff --git a/include/proc_parse.h b/include/proc_parse.h
index 7fade06..ab02f33 100644
--- a/include/proc_parse.h
+++ b/include/proc_parse.h
@@ -212,6 +212,7 @@ extern int parse_fdinfo_pid(int pid, int fd, int type,
 		int (*cb)(union fdinfo_entries *e, void *arg), void *arg);
 extern int parse_cpuinfo_features(int (*handler)(char *tok));
 extern int parse_file_locks(void);
+extern int get_fd_mntid(int fd, int *mnt_id);
 
 struct pid;
 extern int parse_threads(int pid, struct pid **_t, int *_n);
diff --git a/include/vma.h b/include/vma.h
index 0d7dcaf..d2ce80c 100644
--- a/include/vma.h
+++ b/include/vma.h
@@ -50,6 +50,7 @@ struct vma_area {
 			 */
 			bool		file_borrowed;
 			struct stat	*vmst;
+			int		mnt_id;
 		};
 
 		struct /* for restore */ {
diff --git a/proc_parse.c b/proc_parse.c
index 82af774..1ae2c52 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -214,6 +214,14 @@ static int vma_get_mapfile(struct vma_area *vma, DIR *mfd,
 		vma->vm_file_fd = prev->vm_file_fd;
 		if (prev->e->status & VMA_AREA_SOCKET)
 			vma->e->status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR;
+
+		/*
+		 * FIXME -- in theory there can be vmas that have
+		 * dev:ino match, but live in different mount
+		 * namespaces. However, we only borrow files for
+		 * subsequent vmas. These are _very_ likely to
+		 * have files from the same namespaces.
+		 */
 		vma->file_borrowed = true;
 
 		return 0;
@@ -453,6 +461,7 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_file
 			vma_area->e->status = prev->e->status;
 			vma_area->e->shmid = prev->e->shmid;
 			vma_area->vmst = prev->vmst;
+			vma_area->mnt_id = prev->mnt_id;
 		} else if (vma_area->vm_file_fd >= 0) {
 			struct stat *st_buf;
 
@@ -504,6 +513,9 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_file
 				else
 					vma_area->e->status |= VMA_FILE_SHARED;
 			}
+
+			if (get_fd_mntid(vma_area->vm_file_fd, &vma_area->mnt_id))
+				return -1;
 		} else {
 			/*
 			 * No file but mapping -- anonymous one.
@@ -1410,6 +1422,17 @@ int parse_fdinfo(int fd, int type,
 	return parse_fdinfo_pid_s(PROC_SELF, fd, type, cb, arg);
 }
 
+int get_fd_mntid(int fd, int *mnt_id)
+{
+	struct fdinfo_common fdinfo = { .mnt_id = -1};
+
+	if (parse_fdinfo(fd, FD_TYPES__UND, NULL, &fdinfo))
+		return -1;
+
+	*mnt_id = fdinfo.mnt_id;
+	return 0;
+}
+
 static int parse_file_lock_buf(char *buf, struct file_lock *fl,
 				bool is_blocked)
 {
-- 
1.8.4.2



More information about the CRIU mailing list