#include #include #include #include #include #include #include /* copied from kpageflags_read() */ enum { KPF_LOCKED, /* 0 */ KPF_ERROR, /* 1 */ KPF_REFERENCED, /* 2 */ KPF_UPTODATE, /* 3 */ KPF_DIRTY, /* 4 */ KPF_LRU, /* 5 */ KPF_ACTIVE, /* 6 */ KPF_SLAB, /* 7 */ KPF_WRITEBACK, /* 8 */ KPF_RECLAIM, /* 9 */ KPF_BUDDY, /* 10 */ KPF_RESERVED, /* 11 */ KPF_SWAPCACHE, /* 12 */ KPF_SWAPBACKED, /* 13 */ KPF_PRIVATE, /* 14 */ KPF_PRIVATE2, /* 15 */ KPF_NOPAGE, /* 16 */ KPF_NOFLAGS, /* 17 */ KPF_NUM }; #define KPF_BYTES 8 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) static char *page_flag_names[] = { [KPF_LOCKED] = "L:locked", [KPF_ERROR] = "E:error", [KPF_REFERENCED] = "R:referenced", [KPF_UPTODATE] = "U:uptodate", [KPF_DIRTY] = "D:dirty", [KPF_LRU] = "l:lru", [KPF_ACTIVE] = "A:active", [KPF_SLAB] = "S:slab", [KPF_WRITEBACK] = "W:writeback", [KPF_RECLAIM] = "x:reclaim", [KPF_BUDDY] = "B:buddy", [KPF_RESERVED] = "r:reserved", [KPF_SWAPBACKED] = "b:swapbacked", [KPF_SWAPCACHE] = "c:swapcache", [KPF_PRIVATE] = "P:private", [KPF_PRIVATE2] = "p:private_2", [KPF_NOPAGE] = "N:nopage", [KPF_NOFLAGS] = "n:noflags", }; static unsigned long page_count[(1 << KPF_NUM)]; static unsigned long nr_pages; static uint64_t kpageflags[KPF_BYTES * (8<<20)]; char *page_flag_name(uint64_t flags) { int i; static char buf[64]; for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) buf[i] = (flags & (1 << i)) ? page_flag_names[i][0] : '_'; return buf; } char *page_flag_longname(uint64_t flags) { int i, n; static char buf[1024]; for (i = 0, n = 0; i < ARRAY_SIZE(page_flag_names); i++) if (flags & (1<> 10; } static void add_index(unsigned long index) { static unsigned long offset, len; if (index == offset + len) len++; else { if (len) printf("%10lu %8lu %8luKB\n", offset, len, pages2kb(len)); offset = index; len = 1; } } static void usage(const char *prog) { printf("Usage: %s page_flags\n", prog); } int main(int argc, char *argv[]) { static char kpageflags_name[] = "/proc/kpageflags"; unsigned long match_flags, match_exact; unsigned long i; char *p; int fd; if (argc < 2) { usage(argv[0]); exit(1); } match_exact = 0; p = argv[1]; if (p[0] == '=') { match_exact = 1; p++; } match_flags = strtol(p, 0, 16); fd = open(kpageflags_name, O_RDONLY); if (fd < 0) { perror(kpageflags_name); exit(1); } nr_pages = read(fd, kpageflags, sizeof(kpageflags)); if (nr_pages <= 0) { perror(kpageflags_name); exit(2); } if (nr_pages % KPF_BYTES != 0) { fprintf(stderr, "%s: partial read: %lu bytes\n", argv[0], nr_pages); exit(3); } nr_pages = nr_pages / KPF_BYTES; printf(" offset len KB\n"); for (i = 0; i < nr_pages; i++) { if (!match_exact && ((kpageflags[i] & match_flags) == match_flags) || (match_exact && kpageflags[i] == match_flags)) add_index(i); } add_index(0); return 0; }