[CRIU] [PATCH] Use /proc/pid/smaps for VMA parsing

Cyrill Gorcunov gorcunov at openvz.org
Thu May 10 09:51:28 EDT 2012


Pavel, I suspect you meant something like below?
-------------- next part --------------
>From 8fe814537b7e1f87d5e0541b9a3c78077ccd8bd0 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Thu, 10 May 2012 17:50:14 +0400
Subject: [PATCH] Use /proc/pid/smaps for VMA parsing

This allows us to detect nonlinear mappings.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 cr-dump.c            |    2 +-
 cr-restore.c         |    2 +-
 include/proc_parse.h |    2 +-
 include/util.h       |    5 ++++
 proc_parse.c         |   56 ++++++++++++++++++++++++++++++++++++++++---------
 5 files changed, 53 insertions(+), 14 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index cbe4b22..aa8ce88 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -82,7 +82,7 @@ static int collect_mappings(pid_t pid, struct list_head *vma_area_list)
 	pr_info("Collecting mappings (pid: %d)\n", pid);
 	pr_info("----------------------------------------\n");
 
-	ret = parse_maps(pid, vma_area_list, true);
+	ret = parse_smaps(pid, vma_area_list, true);
 	if (ret < 0)
 		goto err;
 
diff --git a/cr-restore.c b/cr-restore.c
index 19233e7..984c15d 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -965,7 +965,7 @@ static int sigreturn_restore(pid_t pid, struct list_head *tgt_vmas, int nr_vmas)
 	restore_task_vma_len	= 0;
 	restore_thread_vma_len	= 0;
 
-	ret = parse_maps(pid, &self_vma_list, false);
+	ret = parse_smaps(pid, &self_vma_list, false);
 	close_pid_proc();
 	if (ret < 0)
 		goto err;
diff --git a/include/proc_parse.h b/include/proc_parse.h
index 3356cbd..f5b2bc1 100644
--- a/include/proc_parse.h
+++ b/include/proc_parse.h
@@ -95,7 +95,7 @@ struct proc_mountinfo {
 extern int parse_mountinfo(pid_t pid, struct proc_mountinfo *mi, int nr_elems);
 extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
 extern int parse_pid_stat_small(pid_t pid, struct proc_pid_stat_small *s);
-extern int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files);
+extern int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files);
 extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
 
 #endif /* PROC_PARSE_H__ */
diff --git a/include/util.h b/include/util.h
index 5172a88..714bfdd 100644
--- a/include/util.h
+++ b/include/util.h
@@ -281,4 +281,9 @@ int copy_file(int fd_in, int fd_out, size_t bytes);
 bool is_anon_inode(struct statfs *statfs);
 int is_anon_link_type(int lfd, char *type);
 
+#define is_hex_digit(c)				\
+	(((c) >= '0' && (c) <= '9')	||	\
+	 ((c) >= 'a' && (c) <= 'f')	||	\
+	 ((c) >= 'A' && (c) <= 'F'))
+
 #endif /* UTIL_H_ */
diff --git a/proc_parse.c b/proc_parse.c
index aceb4f5..6da5468 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -25,7 +25,25 @@ static char *buf = __buf.buf;
 
 #define BUF_SIZE sizeof(__buf.buf)
 
-int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
+/* check the @line starts with "%lx-%lx" format */
+bool is_vma_range_fmt(char *line)
+{
+	while (*line && is_hex_digit(*line))
+		line++;
+
+	if (*line++ != '-')
+		return false;
+
+	while (*line && is_hex_digit(*line))
+		line++;
+
+	if (*line++ != ' ')
+		return false;
+
+	return true;
+}
+
+int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
 {
 	struct vma_area *vma_area = NULL;
 	u64 start, end, pgoff;
@@ -35,10 +53,10 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
 	int ret = -1, nr = 0;
 
 	DIR *map_files_dir = NULL;
-	FILE *maps = NULL;
+	FILE *smaps = NULL;
 
-	maps = fopen_proc(pid, "maps");
-	if (!maps)
+	smaps = fopen_proc(pid, "smaps");
+	if (!smaps)
 		goto err;
 
 	if (use_map_files) {
@@ -47,10 +65,30 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
 			goto err;
 	}
 
-	while (fgets(buf, BUF_SIZE, maps)) {
+	while (fgets(buf, BUF_SIZE, smaps)) {
 		int num;
 		char file_path[6];
 
+		if (!is_vma_range_fmt(buf)) {
+			if (!strncmp(buf, "Nonlinear", 9)) {
+				pr_err("Unsupported nonlinear mapping found");
+				if (vma_area)
+					pr_err("at start %016lx end %016lx",
+					       vma_area->vma.start, vma_area->vma.end);
+				pr_err("\n");
+				/*
+				 * VMA is already on list and will be
+				 * freed later as list get destroyed.
+				 */
+				vma_area = NULL;
+				goto err;
+			} else
+				continue;
+		}
+
+		vma_area = alloc_vma_area();
+		if (!vma_area)
+			goto err;
 
 		memset(file_path, 0, 6);
 		num = sscanf(buf, "%lx-%lx %c%c%c%c %lx %02x:%02x %lu %5s",
@@ -61,10 +99,6 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
 			goto err;
 		}
 
-		vma_area = alloc_vma_area();
-		if (!vma_area)
-			goto err;
-
 		if (map_files_dir) {
 			char path[32];
 
@@ -177,8 +211,8 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
 	ret = nr;
 
 err:
-	if (maps)
-		fclose(maps);
+	if (smaps)
+		fclose(smaps);
 
 	if (map_files_dir)
 		closedir(map_files_dir);
-- 
1.7.7.6



More information about the CRIU mailing list