lkml.org 
[lkml]   [2009]   [Apr]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [RFC][PATCH] proc: export more page flags in /proc/kpageflags
On Tue, Apr 14, 2009 at 12:22:31PM +0800, Wu Fengguang wrote:
> Export the following page flags in /proc/kpageflags,
> just in case they will be useful to someone:
>
> - PG_swapcache
> - PG_swapbacked
> - PG_mappedtodisk
> - PG_reserved
> - PG_private
> - PG_private_2
> - PG_owner_priv_1
>
> - PG_head
> - PG_tail
> - PG_compound
>
> - PG_unevictable
> - PG_mlocked
>
> - PG_poison
>
> Also add the following two pseudo page flags:
>
> - PG_MMAP: whether the page is memory mapped
> - PG_NOPAGE: whether the page is present
>
> This increases the total number of exported page flags to 25.

And here are two simple tools utilizing the exported page flags:

# ./page-types
flags page-count MB symbolic-flags long-symbolic-flags
0x000000 472521 1845 _________________________
0x000020 1 0 _____l___________________ lru
0x000028 2516 9 ___U_l___________________ uptodate,lru
0x00002c 5209 20 __RU_l___________________ referenced,uptodate,lru
0x000068 234 0 ___U_lA__________________ uptodate,lru,active
0x00006c 981 3 __RU_lA__________________ referenced,uptodate,lru,active
0x000228 49 0 ___U_l___x_______________ uptodate,lru,reclaim
0x000400 547 2 __________B______________ buddy
0x000804 1 0 __R________m_____________ referenced,mmap
0x000828 1073 4 ___U_l_____m_____________ uptodate,lru,mmap
0x00082c 318 1 __RU_l_____m_____________ referenced,uptodate,lru,mmap
0x000868 235 0 ___U_lA____m_____________ uptodate,lru,active,mmap
0x00086c 822 3 __RU_lA____m_____________ referenced,uptodate,lru,active,mmap
0x000880 1510 5 _______S___m_____________ slab,mmap
0x0008c0 49 0 ______AS___m_____________ active,slab,mmap
0x002078 1 0 ___UDlA______b___________ uptodate,dirty,lru,active,swapbacked
0x00207c 17 0 __RUDlA______b___________ referenced,uptodate,dirty,lru,active,swapbacked
0x002808 10 0 ___U_______m_b___________ uptodate,mmap,swapbacked
0x002868 3296 12 ___U_lA____m_b___________ uptodate,lru,active,mmap,swapbacked
0x00286c 25 0 __RU_lA____m_b___________ referenced,uptodate,lru,active,mmap,swapbacked
0x002878 2 0 ___UDlA____m_b___________ uptodate,dirty,lru,active,mmap,swapbacked
0x008000 19247 75 _______________r_________ reserved
0x080000 15 0 ___________________H_____ head
0x080014 1 0 __R_D______________H_____ referenced,dirty,head
0x080880 915 3 _______S___m_______H_____ slab,mmap,head
0x0808c0 60 0 ______AS___m_______H_____ active,slab,mmap,head
0x100000 4309 16 ____________________T____ tail
0x100014 4 0 __R_D_______________T____ referenced,dirty,tail
total 513968 2007

To show the compound tail pages:
# ./page-areas 0x100000
offset len KB
3089 3 12KB
487441 7 28KB
487449 7 28KB
487457 7 28KB
487465 7 28KB
487473 7 28KB
487481 7 28KB
487489 7 28KB
487497 7 28KB
487505 7 28KB
487513 7 28KB
487521 7 28KB
487529 7 28KB
487537 7 28KB
487545 7 28KB
487553 7 28KB
487561 7 28KB
487569 7 28KB
487577 7 28KB
487585 7 28KB
487593 7 28KB
487617 7 28KB
487627 1 4KB
487629 1 4KB
487633 7 28KB
487641 7 28KB
487649 7 28KB
487657 7 28KB
487665 7 28KB
487673 7 28KB
487681 7 28KB
487689 7 28KB
487697 7 28KB
487705 7 28KB
487713 7 28KB
487721 7 28KB
487729 7 28KB
487737 7 28KB
487745 7 28KB
487753 7 28KB
487761 7 28KB
487769 7 28KB
487777 7 28KB
487785 7 28KB
487793 7 28KB
487801 7 28KB
487809 7 28KB
487817 7 28KB
487825 7 28KB
487853 3 12KB
487865 7 28KB
487873 3 12KB
487893 3 12KB
487897 3 12KB
487901 3 12KB
487905 3 12KB
487909 3 12KB
487929 7 28KB
487937 7 28KB
487945 7 28KB
493569 3 12KB
493573 1 4KB
493575 1 4KB
493585 7 28KB
493593 3 12KB
493597 3 12KB
493601 7 28KB
493609 7 28KB
493617 7 28KB
493625 1 4KB
493633 7 28KB
493641 3 12KB
493645 3 12KB
[snip]

Thanks,
Fengguang

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/fcntl.h>

#include "pagemap.h"

int main(int argc, char *argv[])
{
static char kpageflags_name[] = "/proc/kpageflags";
unsigned long i;
uint64_t flags;
int fd;

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;

for (i = 0; i < nr_pages; i++) {
flags = kpageflags[i];

if (flags >= ARRAY_SIZE(page_count)) {
static int warned = 0;

if (!warned) {
warned = 1;
fprintf(stderr, "%s: flags overflow: 0x%lx >= 0x%lx\n",
argv[0], flags, ARRAY_SIZE(page_count));
fprintf(stderr, "Either the kernel is buggy(<=2.6.28), "
"or I'm too old to recognize new flags.\n\n");
}

flags = ARRAY_SIZE(page_count) - 1;
}
page_count[flags]++;
}

#if 0
for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) {
printf("%s ", page_flag_names[i]);
}
#endif

printf(" flags\tpage-count MB symbolic-flags long-symbolic-flags\n");
for (i = 0; i < ARRAY_SIZE(page_count); i++) {
if (page_count[i])
printf("0x%06lx\t%10lu %8lu %s %s\n",
i,
page_count[i],
pages2mb(page_count[i]),
page_flag_name(i),
page_flag_longname(i));
}

printf(" total\t%10lu %8lu\n",
nr_pages, pages2mb(nr_pages));

return 0;
}

#define KPF_BYTES 8

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

/* 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_MMAP, /* 11 */
KPF_SWAPCACHE, /* 12 */
KPF_SWAPBACKED, /* 13 */
KPF_MAPPEDTODISK, /* 14 */
KPF_RESERVED, /* 15 */
KPF_PRIVATE, /* 16 */
KPF_PRIVATE2, /* 17 */
KPF_OWNER_PRIVATE, /* 18 */
KPF_COMPOUND_HEAD, /* 19 */
KPF_COMPOUND_TAIL, /* 20 */
KPF_UNEVICTABLE, /* 21 */
KPF_MLOCKED, /* 22 */
KPF_POISON, /* 23 */
KPF_NOPAGE, /* 24 */
KPF_NUM
};

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_SWAPCACHE] = "c:swapcache",
[KPF_SWAPBACKED] = "b:swapbacked",
[KPF_MAPPEDTODISK] = "d:mappedtodisk",
[KPF_PRIVATE] = "P:private",
[KPF_PRIVATE2] = "p:private_2",
[KPF_OWNER_PRIVATE] = "O:owner_private",
[KPF_COMPOUND_HEAD] = "H:head",
[KPF_COMPOUND_TAIL] = "T:tail",
[KPF_UNEVICTABLE] = "u:unevictable",
[KPF_MLOCKED] = "M:mlocked",
[KPF_MMAP] = "m:mmap",
[KPF_POISON] = "X:poison",
[KPF_NOPAGE] = "n:nopage",
};

static unsigned long page_count[(1 << KPF_NUM)];
static unsigned long nr_pages;
static uint64_t kpageflags[KPF_BYTES * (16<<20)]; /* 64GB */

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<<i))
n += snprintf(buf + n, sizeof(buf) - n, "%s,",
page_flag_names[i] + 2);
if (n)
n--;
buf[n] = '\0';

return buf;
}

static unsigned long pages2kb(unsigned long pages)
{
return (pages * getpagesize()) >> 10;
}

static unsigned long pages2mb(unsigned long pages)
{
return (pages * getpagesize()) >> 20;
}

BINS = page-types page-areas

all: $(BINS)

page-types: page-types.c pagemap.h
gcc -g -o $@ $<

page-areas: page-areas.c pagemap.h
gcc -g -o $@ $<

clean:
rm $(BINS)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/fcntl.h>

#include "pagemap.h"

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;
}
\
 
 \ /
  Last update: 2009-04-14 06:39    [W:1.629 / U:0.112 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site