From 27eac01bb4e9de3b851d4b4477156e24a8ca864a Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Sun, 29 Aug 2010 13:21:38 +0300 Subject: [PATCH] Parser: Read kpageflags and kpagecount Read the /proc/kpageflags and /proc/kpagecount data for every page frame. Signed-off-by: Timo Kokkonen --- main.c | 2 ++ pagemap.h | 2 ++ parse.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ parse.h | 1 + 4 files changed, 84 insertions(+) diff --git a/main.c b/main.c index c28ed2a..9fc6d71 100644 --- a/main.c +++ b/main.c @@ -130,6 +130,8 @@ int main(int argc, char *argv[]) if (scan_all_pids(&pf, &process_list, &opts)) return 1; + update_kpageflags(&pf); + if (opts.parse_mask & PARSE_DUMP) dump_process_maps(&pf, &process_list, &opts); else diff --git a/pagemap.h b/pagemap.h index 0eb280c..ffc55ef 100644 --- a/pagemap.h +++ b/pagemap.h @@ -26,6 +26,8 @@ struct pageframe { struct list_head ml; /* List of mappings which refer to this pfn */ unsigned long long pf; /* page frame entry from /proc/pid/pagemap */ + unsigned long long kpageflags; + unsigned long long kpagecount; int refcount; }; diff --git a/parse.c b/parse.c index e21935f..67fc0f7 100644 --- a/parse.c +++ b/parse.c @@ -1,7 +1,11 @@ +#include +#include #include #include #include #include +#include +#include #include "parse.h" #include "pagemap.h" @@ -385,3 +389,78 @@ int scan_all_pids(struct pageframe *pf, struct process *process_list, return 0; } + +struct kpageflag_data { + struct bintree_ops ops; + + int kpageflags_fd; + int kpagecount_fd; +}; + +#define bintree_ops_to_kpfd(bintree_ops) \ + container_of((bintree_ops), struct kpageflag_data, ops) + +static void _update_kpageflags(struct bintree *bt, struct bintree_ops *ops) +{ + struct pageframe *pf = tree_to_pageframe(bt); + struct kpageflag_data *kpfd = bintree_ops_to_kpfd(ops); + int ret, error; + long int pfnn = pfn(pf) * sizeof(pf->kpageflags); + + ret = lseek(kpfd->kpageflags_fd, pfnn, SEEK_SET); + if (ret < 0) { + error = errno; + fprintf(stderr, "Error seeking to %lx: %s\n", + pfnn, strerror(error)); + return; + } + + ret = read(kpfd->kpageflags_fd, &pf->kpageflags, + sizeof(pf->kpageflags)); + if (ret < 0) { + error = errno; + fprintf(stderr, "Error reading from %llx: %s\n", + pf->pf * sizeof(pf->kpageflags), + strerror(error)); + return; + } + + ret = lseek(kpfd->kpagecount_fd, pfnn, SEEK_SET); + if (ret < 0) { + error = errno; + fprintf(stderr, "Error seeking to %lx: %s\n", + pfnn, strerror(error)); + return; + } + + ret = read(kpfd->kpagecount_fd, &pf->kpagecount, + sizeof(pf->kpagecount)); + if (ret < 0) { + error = errno; + fprintf(stderr, "Error reading from %llx: %s\n", + pf->pf * sizeof(pf->kpagecount), + strerror(error)); + return; + } +} + +int update_kpageflags(struct pageframe *pf) +{ + struct kpageflag_data kpfd = { + .ops = { + .callback = _update_kpageflags, + }, + .kpageflags_fd = open("/proc/kpageflags", O_RDONLY), + .kpagecount_fd = open("/proc/kpagecount", O_RDONLY), + }; + + if (kpfd.kpageflags_fd == -1 || kpfd.kpagecount_fd == -1) + return -1; + + bintree_walk(&pf->tree, &kpfd.ops); + + close(kpfd.kpageflags_fd); + close(kpfd.kpagecount_fd); + + return 0; +} diff --git a/parse.h b/parse.h index 83d0bcd..d915ce3 100644 --- a/parse.h +++ b/parse.h @@ -5,5 +5,6 @@ int scan_all_pids(struct pageframe *pf, struct process *process_list, struct parse_opts *opts); +int update_kpageflags(struct pageframe *pf); #endif -- 2.45.0