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

Cyrill Gorcunov gorcunov at openvz.org
Thu May 10 13:07:04 EDT 2012


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         |   54 +++++++++++++++++++++++++++++++++++++++----------
 5 files changed, 51 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..358c2d5 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,28 @@ 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)) {
+				BUG_ON(!vma_area);
+				pr_err("Nonlinear mapping found %016lx-%016lx\n",
+				       vma_area->vma.start, vma_area->vma.end);
+				/*
+				 * 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 +97,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 +209,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