[CRIU] [PATCH] Rework fixup_aufs_vma_fd() for non-AUFS links

Saied Kazemi saied at google.com
Wed Jan 21 15:22:16 PST 2015


This patch reworks fixup_aufs_vma_fd() to let symbolic links in
/proc/<pid>/map_files that are not pointing to AUFS branch names follow
the non-AUFS applcation logic.

The use case that prompted this commit was an application mapping
/dev/zero as shared and writeable which shows up in map_files as:

lrw------- ... 7fc5c5a5f000-7fc5c5a60000 -> /dev/zero (deleted)

If the AUFS support code reads the link, it will have to strip off the
" (deleted)" string added by the kernel but core CRIU code already
does this.

Signed-off-by: Saied Kazemi <saied at google.com>
---
 proc_parse.c  | 25 +++++++++++++++++--------
 sysfs_parse.c | 37 ++++++++++++++-----------------------
 2 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/proc_parse.c b/proc_parse.c
index 3da1d9e..76fe0da 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -275,15 +275,24 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
 	if (!vma->vmst)
 		return -1;
 
-	if (opts.aufs)
-		/*
-		 * For AUFS support, we cannot fstat() a file descriptor that
-		 * is a symbolic link to a branch (it would return different
-		 * dev/ino than the real file).  Instead, we stat() using the
-		 * full pathname that we saved before.
-		 */
+	/*
+	 * For AUFS support, we need to check if the symbolic link
+	 * points to a branch.  If it does, we cannot fstat() its file
+	 * descriptor because it would return a different dev/ino than
+	 * the real file.  If fixup_aufs_vma_fd() returns positive,
+	 * it means that it has stat()'ed using the full pathname.
+	 * Zero return means that the symbolic link does not point to
+	 * a branch and we can do fstat() below.
+	 */
+	if (opts.aufs) {
+		int ret;
 
-		return fixup_aufs_vma_fd(vma);
+		ret = fixup_aufs_vma_fd(vma);
+		if (ret < 0)
+			return -1;
+		if (ret > 0)
+			return 0;
+	}
 
 	if (fstat(vma->vm_file_fd, vma->vmst) < 0) {
 		pr_perror("Failed fstat on map %"PRIx64"", vma->e->start);
diff --git a/sysfs_parse.c b/sysfs_parse.c
index 8e236e9..743f92a 100644
--- a/sysfs_parse.c
+++ b/sysfs_parse.c
@@ -282,32 +282,23 @@ int fixup_aufs_vma_fd(struct vma_area *vma)
 		return -1;
 
 	len = fixup_aufs_path(&path[1], sizeof path - 1);
-	if (len < 0)
+	if (len <= 0)
+		return len;
+
+	vma->aufs_rpath = xmalloc(len + 2);
+	if (!vma->aufs_rpath)
 		return -1;
 
-	if (len == 0) {
-		/*
-		 * The vma is associated with a map_files entry
-		 * that does not expose the branch pathname
-		 * (e.g., /dev/zero).  In this case, we can use
-		 * the path.
-		 */
-		file = &path[1];
-	} else {
-		vma->aufs_rpath = xmalloc(len + 2);
-		if (!vma->aufs_rpath)
+	strcpy(vma->aufs_rpath, path);
+	if (opts.root) {
+		vma->aufs_fpath = xmalloc(strlen(opts.root) + 1 + len + 1);
+		if (!vma->aufs_fpath)
 			return -1;
-		strcpy(vma->aufs_rpath, path);
-		if (opts.root) {
-			vma->aufs_fpath = xmalloc(strlen(opts.root) + 1 + len + 1);
-			if (!vma->aufs_fpath)
-				return -1;
-			/* skip ./ in path */
-			sprintf(vma->aufs_fpath, "%s/%s", opts.root, &path[2]);
-		}
-		pr_debug("Saved AUFS paths %s and %s\n", vma->aufs_rpath, vma->aufs_fpath);
-		file = vma->aufs_fpath;
+		/* skip ./ in path */
+		sprintf(vma->aufs_fpath, "%s/%s", opts.root, &path[2]);
 	}
+	pr_debug("Saved AUFS paths %s and %s\n", vma->aufs_rpath, vma->aufs_fpath);
+	file = vma->aufs_fpath;
 
 	if (stat(file, vma->vmst) < 0) {
 		pr_perror("Failed stat on map %"PRIx64" (%s)",
@@ -315,7 +306,7 @@ int fixup_aufs_vma_fd(struct vma_area *vma)
 		return -1;
 	}
 
-	return 0;
+	return len;
 }
 
 void free_aufs_branches(void)
-- 
2.2.0.rc0.207.ga3a616c



More information about the CRIU mailing list