]> git.itanic.dy.fi Git - scan-pagemap/blobdiff - parse.c
parser: Do not scan processes twice
[scan-pagemap] / parse.c
diff --git a/parse.c b/parse.c
index 3934fff77ee58b6e160756d0adeed1d1b45e506b..7f62748a8468c51fbec1c1277c62b77f00829978 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -165,25 +165,51 @@ static char *get_name_by_pid(int pid)
        return bname;
 }
 
-static int check_parse_opts(struct parse_opts *opts, struct pageframe *pf,
-               struct maps *map)
+static int should_scan_process(struct parse_opts *opts, struct process *process)
 {
+       int match = 0;
+       char *name;
+
+       if (opts->parse_mask & PARSE_PROCESS_NAME) {
+               name = get_name_by_pid(process->pid);
+               if (!strcmp(opts->name, name ? name : ""))
+                       match = 1;
+       }
+
        if (opts->parse_mask & PARSE_PID) {
-               if (opts->pid == map->pid)
-                       return 1;
+               if (opts->pid == process->pid)
+                       match = 1;
        }
 
+       if (opts->parse_mask & PARSE_NOADD_TREE)
+               match = !match;
+
+       return match;
+}
+
+static int should_scan_mapping(struct parse_opts *opts, struct maps *map)
+{
+       int match = 0;
+
        if (opts->parse_mask & PARSE_MAP_NAME) {
                if (!strcmp(opts->name, map->name))
-                       return 1;
-       }
+                       match = 1;
 
-       if (opts->parse_mask & PARSE_PROCESS_NAME) {
-               if (!strcmp(opts->name, get_name_by_pid(map->pid)))
-                       return 1;
-       }
+               if (opts->parse_mask & PARSE_NOADD_TREE)
+                       match = !match;
+       } else
+               match = 1;
 
-       return 0;
+       return match;
+}
+
+static int should_add_to_tree(struct parse_opts *opts, struct pageframe *pf,
+               struct maps *map)
+{
+       if (opts->parse_mask & PARSE_NOADD_TREE)
+               return 0;
+
+       return 1;
 }
 
 /* Read data from the /proc/pid/pagemap file */
@@ -205,6 +231,9 @@ static int parse_pageframe(FILE *file, struct pageframe *pf_tree,
                start = map->start >> (PAGE_SHIFT - 3);
                len = map->size >> (PAGE_SHIFT);
 
+               if (!should_scan_mapping(opts, map))
+                       continue;
+
                ret = fseek(file, start, SEEK_SET);
                if (ret) {
                        error = errno;
@@ -237,7 +266,7 @@ static int parse_pageframe(FILE *file, struct pageframe *pf_tree,
                                        pageframe->page_present))
                                continue;
 
-                       if (check_parse_opts(opts, pageframe, map)) {
+                       if (should_add_to_tree(opts, pageframe, map)) {
                                match = tree_to_pageframe(
                                        bintree_add(&pf_tree->tree,
                                                &pageframe->tree,
@@ -297,6 +326,8 @@ static int read_pageframe(int pid, int tid, struct pageframe *pageframe,
        process->pid = pid;
        process->tid = tid;
 
+       if (!should_scan_process(opts, process))
+               goto free;
 
        snprintf(path, sizeof(path), "/proc/%d/task/%d/maps", pid, tid);
        file = fopen(path, "rb");
@@ -480,6 +511,9 @@ int scan_all_pids(struct pageframe *pf, struct process **process_list,
        if (opts->parse_mask & PARSE_DUMP)
                return 0;
 
+       /* Do not add new pages in the tree after the initial scan */
+       opts->parse_mask |= PARSE_NOADD_TREE;
+
        while (1) {
                pid = get_next_pid(&dir);
                if (pid <= 0)