]> git.itanic.dy.fi Git - scan-pagemap/blobdiff - parse.c
Parser: Read kpageflags and kpagecount
[scan-pagemap] / parse.c
diff --git a/parse.c b/parse.c
index e21935f4543c753ce0b4194e4d9ffe61f8d60a95..67fc0f781dd0e2b284bdc598e872aba010d1e747 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -1,7 +1,11 @@
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #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;
+}