+
+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;
+}