[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