#include #include #include #include #include #include #include /* copied from kpageflags_read() */ #define KPF_LOCKED 0 #define KPF_ERROR 1 #define KPF_REFERENCED 2 #define KPF_UPTODATE 3 #define KPF_DIRTY 4 #define KPF_LRU 5 #define KPF_ACTIVE 6 #define KPF_SLAB 7 #define KPF_WRITEBACK 8 #define KPF_RECLAIM 9 #define KPF_BUDDY 10 #define KPF_RESERVED 11 #define KPF_SWAPCACHE 12 #define KPF_SWAPBACKED 13 #define KPF_NUM 14 #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", }; 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, char *buf) { int i; for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) buf[i] = (flags & (1 << i)) ? page_flag_names[i][0] : '_'; return buf; } static unsigned long pages2mb(unsigned long pages) { return (pages * getpagesize()) >> 20; } int main(int argc, char *argv[]) { static char kpageflags_name[] = "/proc/kpageflags"; static char buf[64]; unsigned long i; uint64_t flags; int fd; fd = open(kpageflags_name, O_RDONLY); if (fd < 0) { fprintf(stderr, "%s: cannot open `%s': %s\n", argv[0], kpageflags_name, strerror(errno)); exit(1); } nr_pages = read(fd, kpageflags, sizeof(kpageflags)); if (nr_pages <= 0) { fprintf(stderr, "%s: cannot read `%s': %s\n", argv[0], kpageflags_name, strerror(errno)); 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; for (i = 0; i < nr_pages; i++) { flags = kpageflags[i]; if (flags == 0x40000) flags = ARRAY_SIZE(page_count) - 1; if (flags >= ARRAY_SIZE(page_count)) { fprintf(stderr, "%s: flags overflow: 0x%lx > 0x%lx\n", argv[0], flags, ARRAY_SIZE(page_count)); exit(4); } page_count[flags]++; } for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) { printf("%s ", page_flag_names[i]); } printf("\n\n flags\t symbolic-flags\tpage-count\t MB\n"); for (i = 0; i < ARRAY_SIZE(page_count); i++) { if (page_count[i]) printf("0x%04lx\t%20s\t%10lu\t%8lu\n", i, page_flag_name(i, buf), page_count[i], pages2mb(page_count[i])); } printf("\n total\t\t\t\t%10lu\t%8lu\n", nr_pages, pages2mb(nr_pages)); return 0; }