From: Alex Chiang <achiang@hp.com>
To: akpm@linux-foundation.org
Cc: Haicheng Li <haicheng.li@intel.com>,
Randy Dunlap <randy.dunlap@oracle.com>,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
Andi Kleen <andi@firstfloor.org>,
fengguang.wu@intel.com
Subject: [PATCH] page-types: kernel pageflags mode
Date: Fri, 04 Dec 2009 14:29:48 -0700 [thread overview]
Message-ID: <20091204212606.29258.98531.stgit@bob.kio> (raw)
An earlier commit taught page-types the -d|--describe argument, which
allows the user to describe page flags passed on the command line:
# ./Documentation/vm/page-types -d 0x4000
0x0000000000004000 ______________b___________________ swapbacked
In -d mode, page-types expects the page flag bits in the order generated
by the kernel function get_uflags().
However, those bits are rearranged compared to what is actually stored
in struct page->flags. A kernel developer dumping a page's flags
using printk, e.g., may get misleading results in -d mode.
Teach page-types the -k mode, which parses and describes the bits in
the internal kernel order:
# ./Documentation/vm/page-types -k 0x4000
0x0000000000004000 ______________H_________ compound_head
Note that the recommended way to build page-types is from the top-level
kernel source directory. This ensures that it will get the same CONFIG_*
defines used to build the kernel source.
# make Documentation/vm/
The implication is that attempting to use page-types -k on a kernel
with different CONFIG_* settings may lead to surprising and misleading
results. To retain sanity, always use the page-types built out of the
kernel tree you are actually testing.
Cc: fengguang.wu@intel.com
Cc: Haicheng Li <haicheng.li@intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: Alex Chiang <achiang@hp.com>
---
Applies on top of mmotm.
Documentation/vm/Makefile | 2 +
Documentation/vm/page-types.c | 117 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 113 insertions(+), 6 deletions(-)
diff --git a/Documentation/vm/Makefile b/Documentation/vm/Makefile
index 5bd269b..1bebc43 100644
--- a/Documentation/vm/Makefile
+++ b/Documentation/vm/Makefile
@@ -1,6 +1,8 @@
# kbuild trick to avoid linker error. Can be omitted if a module is built.
obj- := dummy.o
+HOSTCFLAGS_page-types.o += $(LINUXINCLUDE)
+
# List of programs to build
hostprogs-y := slabinfo page-types
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c
index 7a7d9ba..b0f129c 100644
--- a/Documentation/vm/page-types.c
+++ b/Documentation/vm/page-types.c
@@ -100,7 +100,7 @@
#define BIT(name) (1ULL << KPF_##name)
#define BITS_COMPOUND (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL))
-static const char *page_flag_names[] = {
+static const char *page_flag_names_proc[] = {
[KPF_LOCKED] = "L:locked",
[KPF_ERROR] = "E:error",
[KPF_REFERENCED] = "R:referenced",
@@ -140,6 +140,103 @@ static const char *page_flag_names[] = {
[KPF_SLUB_DEBUG] = "E:slub_debug",
};
+enum pageflags {
+ PG_locked, /* Page is locked. Don't touch. */
+ PG_error,
+ PG_referenced,
+ PG_uptodate,
+ PG_dirty,
+ PG_lru,
+ PG_active,
+ PG_slab,
+ PG_owner_priv_1, /* Owner use. If pagecache, fs may use*/
+ PG_arch_1,
+ PG_reserved,
+ PG_private, /* If pagecache, has fs-private data */
+ PG_private_2, /* If pagecache, has fs aux data */
+ PG_writeback, /* Page is under writeback */
+#ifdef CONFIG_PAGEFLAGS_EXTENDED
+ PG_head, /* A head page */
+ PG_tail, /* A tail page */
+#else
+ PG_compound, /* A compound page */
+#endif
+ PG_swapcache, /* Swap page: swp_entry_t in private */
+ PG_mappedtodisk, /* Has blocks allocated on-disk */
+ PG_reclaim, /* To be reclaimed asap */
+ PG_buddy, /* Page is free, on buddy lists */
+ PG_swapbacked, /* Page is backed by RAM/swap */
+ PG_unevictable, /* Page is "unevictable" */
+#ifdef CONFIG_MMU
+ PG_mlocked, /* Page is vma mlocked */
+#endif
+#ifdef CONFIG_ARCH_USES_PG_UNCACHED
+ PG_uncached, /* Page has been mapped as uncached */
+#endif
+#ifdef CONFIG_MEMORY_FAILURE
+ PG_hwpoison, /* hardware poisoned page. Don't touch */
+#endif
+ __NR_PAGEFLAGS,
+
+ /* Filesystems */
+ PG_checked = PG_owner_priv_1,
+
+ /* Two page bits are conscripted by FS-Cache to maintain local caching
+ * state. These bits are set on pages belonging to the netfs's inodes
+ * when those inodes are being locally cached.
+ */
+ PG_fscache = PG_private_2, /* page backed by cache */
+
+ /* XEN */
+ PG_pinned = PG_owner_priv_1,
+ PG_savepinned = PG_dirty,
+
+ /* SLOB */
+ PG_slob_free = PG_private,
+
+ /* SLUB */
+ PG_slub_frozen = PG_active,
+ PG_slub_debug = PG_error,
+};
+
+static const char *page_flag_names_kernel[] = {
+ [PG_locked] = "L:locked",
+ [PG_error] = "E:error",
+ [PG_referenced] = "R:referenced",
+ [PG_uptodate] = "U:uptodate",
+ [PG_dirty] = "D:dirty",
+ [PG_lru] = "l:lru",
+ [PG_active] = "A:active",
+ [PG_slab] = "S:slab",
+ [PG_owner_priv_1] = "O:owner_private",
+ [PG_arch_1] = "h:arch",
+ [PG_reserved] = "r:reserved",
+ [PG_private] = "P:private",
+ [PG_private_2] = "p:private_2",
+ [PG_writeback] = "W:writeback",
+#ifdef CONFIG_PAGEFLAGS_EXTENDED
+ [PG_head] = "H:compound_head",
+ [PG_tail] = "T:compound_tail",
+#else
+ [PG_compound] = "C:compound",
+#endif
+ [PG_swapcache] = "s:swapcache",
+ [PG_mappedtodisk] = "d:mappedtodisk",
+ [PG_reclaim] = "I:reclaim",
+ [PG_buddy] = "B:buddy",
+ [PG_swapbacked] = "b:swapbacked",
+ [PG_unevictable] = "u:unevictable",
+#ifdef CONFIG_MMU
+ [PG_mlocked] = "m:mlocked",
+#endif
+#ifdef CONFIG_ARCH_USES_PG_UNCACHED
+ [PG_uncached] = "c:uncached",
+#endif
+#ifdef CONFIG_MEMORY_FAILURE
+ [PG_hwpoison] = "X:hwpoison",
+#endif
+};
+
/*
* data structures
@@ -186,6 +283,8 @@ static unsigned long total_pages;
static unsigned long nr_pages[HASH_SIZE];
static uint64_t page_flags[HASH_SIZE];
+static char **page_flag_names = (char **)page_flag_names_proc;
+static int page_flag_nr = KPF_SLUB_DEBUG + 1;
/*
* helper functions
@@ -297,7 +396,7 @@ static char *page_flag_name(uint64_t flags)
int present;
int i, j;
- for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+ for (i = 0, j = 0; i < page_flag_nr; i++) {
present = (flags >> i) & 1;
if (!page_flag_names[i]) {
if (present)
@@ -315,7 +414,7 @@ static char *page_flag_longname(uint64_t flags)
static char buf[1024];
int i, n;
- for (i = 0, n = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+ for (i = 0, n = 0; i < page_flag_nr; i++) {
if (!page_flag_names[i])
continue;
if ((flags >> i) & 1)
@@ -675,6 +774,7 @@ static void usage(void)
"page-types [options]\n"
" -r|--raw Raw mode, for kernel developers\n"
" -d|--describe flags Describe flags\n"
+" -k|--kernel describe flags Describe flags, kernel internal order\n"
" -a|--addr addr-spec Walk a range of pages\n"
" -b|--bits bits-spec Walk pages with specified bits\n"
" -p|--pid pid Walk process address space\n"
@@ -705,7 +805,7 @@ static void usage(void)
"bit-names:\n"
);
- for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+ for (i = 0, j = 0; i < page_flag_nr; i++) {
if (!page_flag_names[i])
continue;
printf("%16s%s", page_flag_names[i] + 2,
@@ -836,7 +936,7 @@ static uint64_t parse_flag_name(const char *str, int len)
if (len <= 8 && !strncmp(str, "compound", len))
return BITS_COMPOUND;
- for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+ for (i = 0; i < page_flag_nr; i++) {
if (!page_flag_names[i])
continue;
if (!strncmp(str, page_flag_names[i] + 2, len))
@@ -906,6 +1006,7 @@ static const struct option opts[] = {
{ "addr" , 1, NULL, 'a' },
{ "bits" , 1, NULL, 'b' },
{ "describe" , 1, NULL, 'd' },
+ { "kernel" , 1, NULL, 'k' },
{ "list" , 0, NULL, 'l' },
{ "list-each" , 0, NULL, 'L' },
{ "no-summary", 0, NULL, 'N' },
@@ -922,7 +1023,7 @@ int main(int argc, char *argv[])
page_size = getpagesize();
while ((c = getopt_long(argc, argv,
- "rp:f:a:b:d:lLNXxh", opts, NULL)) != -1) {
+ "rp:f:a:b:d:k:lLNXxh", opts, NULL)) != -1) {
switch (c) {
case 'r':
opt_raw = 1;
@@ -939,6 +1040,10 @@ int main(int argc, char *argv[])
case 'b':
parse_bits_mask(optarg);
break;
+ case 'k':
+ /* Fall-through to case 'd' */
+ page_flag_names = (char **)page_flag_names_kernel;
+ page_flag_nr = __NR_PAGEFLAGS;
case 'd':
describe_flags(optarg);
exit(0);
WARNING: multiple messages have this Message-ID (diff)
From: Alex Chiang <achiang@hp.com>
To: akpm@linux-foundation.org
Cc: Haicheng Li <haicheng.li@intel.com>,
Randy Dunlap <randy.dunlap@oracle.com>,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
Andi Kleen <andi@firstfloor.org>,
fengguang.wu@intel.com
Subject: [PATCH] page-types: kernel pageflags mode
Date: Fri, 04 Dec 2009 14:29:48 -0700 [thread overview]
Message-ID: <20091204212606.29258.98531.stgit@bob.kio> (raw)
An earlier commit taught page-types the -d|--describe argument, which
allows the user to describe page flags passed on the command line:
# ./Documentation/vm/page-types -d 0x4000
0x0000000000004000 ______________b___________________ swapbacked
In -d mode, page-types expects the page flag bits in the order generated
by the kernel function get_uflags().
However, those bits are rearranged compared to what is actually stored
in struct page->flags. A kernel developer dumping a page's flags
using printk, e.g., may get misleading results in -d mode.
Teach page-types the -k mode, which parses and describes the bits in
the internal kernel order:
# ./Documentation/vm/page-types -k 0x4000
0x0000000000004000 ______________H_________ compound_head
Note that the recommended way to build page-types is from the top-level
kernel source directory. This ensures that it will get the same CONFIG_*
defines used to build the kernel source.
# make Documentation/vm/
The implication is that attempting to use page-types -k on a kernel
with different CONFIG_* settings may lead to surprising and misleading
results. To retain sanity, always use the page-types built out of the
kernel tree you are actually testing.
Cc: fengguang.wu@intel.com
Cc: Haicheng Li <haicheng.li@intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: Alex Chiang <achiang@hp.com>
---
Applies on top of mmotm.
Documentation/vm/Makefile | 2 +
Documentation/vm/page-types.c | 117 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 113 insertions(+), 6 deletions(-)
diff --git a/Documentation/vm/Makefile b/Documentation/vm/Makefile
index 5bd269b..1bebc43 100644
--- a/Documentation/vm/Makefile
+++ b/Documentation/vm/Makefile
@@ -1,6 +1,8 @@
# kbuild trick to avoid linker error. Can be omitted if a module is built.
obj- := dummy.o
+HOSTCFLAGS_page-types.o += $(LINUXINCLUDE)
+
# List of programs to build
hostprogs-y := slabinfo page-types
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c
index 7a7d9ba..b0f129c 100644
--- a/Documentation/vm/page-types.c
+++ b/Documentation/vm/page-types.c
@@ -100,7 +100,7 @@
#define BIT(name) (1ULL << KPF_##name)
#define BITS_COMPOUND (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL))
-static const char *page_flag_names[] = {
+static const char *page_flag_names_proc[] = {
[KPF_LOCKED] = "L:locked",
[KPF_ERROR] = "E:error",
[KPF_REFERENCED] = "R:referenced",
@@ -140,6 +140,103 @@ static const char *page_flag_names[] = {
[KPF_SLUB_DEBUG] = "E:slub_debug",
};
+enum pageflags {
+ PG_locked, /* Page is locked. Don't touch. */
+ PG_error,
+ PG_referenced,
+ PG_uptodate,
+ PG_dirty,
+ PG_lru,
+ PG_active,
+ PG_slab,
+ PG_owner_priv_1, /* Owner use. If pagecache, fs may use*/
+ PG_arch_1,
+ PG_reserved,
+ PG_private, /* If pagecache, has fs-private data */
+ PG_private_2, /* If pagecache, has fs aux data */
+ PG_writeback, /* Page is under writeback */
+#ifdef CONFIG_PAGEFLAGS_EXTENDED
+ PG_head, /* A head page */
+ PG_tail, /* A tail page */
+#else
+ PG_compound, /* A compound page */
+#endif
+ PG_swapcache, /* Swap page: swp_entry_t in private */
+ PG_mappedtodisk, /* Has blocks allocated on-disk */
+ PG_reclaim, /* To be reclaimed asap */
+ PG_buddy, /* Page is free, on buddy lists */
+ PG_swapbacked, /* Page is backed by RAM/swap */
+ PG_unevictable, /* Page is "unevictable" */
+#ifdef CONFIG_MMU
+ PG_mlocked, /* Page is vma mlocked */
+#endif
+#ifdef CONFIG_ARCH_USES_PG_UNCACHED
+ PG_uncached, /* Page has been mapped as uncached */
+#endif
+#ifdef CONFIG_MEMORY_FAILURE
+ PG_hwpoison, /* hardware poisoned page. Don't touch */
+#endif
+ __NR_PAGEFLAGS,
+
+ /* Filesystems */
+ PG_checked = PG_owner_priv_1,
+
+ /* Two page bits are conscripted by FS-Cache to maintain local caching
+ * state. These bits are set on pages belonging to the netfs's inodes
+ * when those inodes are being locally cached.
+ */
+ PG_fscache = PG_private_2, /* page backed by cache */
+
+ /* XEN */
+ PG_pinned = PG_owner_priv_1,
+ PG_savepinned = PG_dirty,
+
+ /* SLOB */
+ PG_slob_free = PG_private,
+
+ /* SLUB */
+ PG_slub_frozen = PG_active,
+ PG_slub_debug = PG_error,
+};
+
+static const char *page_flag_names_kernel[] = {
+ [PG_locked] = "L:locked",
+ [PG_error] = "E:error",
+ [PG_referenced] = "R:referenced",
+ [PG_uptodate] = "U:uptodate",
+ [PG_dirty] = "D:dirty",
+ [PG_lru] = "l:lru",
+ [PG_active] = "A:active",
+ [PG_slab] = "S:slab",
+ [PG_owner_priv_1] = "O:owner_private",
+ [PG_arch_1] = "h:arch",
+ [PG_reserved] = "r:reserved",
+ [PG_private] = "P:private",
+ [PG_private_2] = "p:private_2",
+ [PG_writeback] = "W:writeback",
+#ifdef CONFIG_PAGEFLAGS_EXTENDED
+ [PG_head] = "H:compound_head",
+ [PG_tail] = "T:compound_tail",
+#else
+ [PG_compound] = "C:compound",
+#endif
+ [PG_swapcache] = "s:swapcache",
+ [PG_mappedtodisk] = "d:mappedtodisk",
+ [PG_reclaim] = "I:reclaim",
+ [PG_buddy] = "B:buddy",
+ [PG_swapbacked] = "b:swapbacked",
+ [PG_unevictable] = "u:unevictable",
+#ifdef CONFIG_MMU
+ [PG_mlocked] = "m:mlocked",
+#endif
+#ifdef CONFIG_ARCH_USES_PG_UNCACHED
+ [PG_uncached] = "c:uncached",
+#endif
+#ifdef CONFIG_MEMORY_FAILURE
+ [PG_hwpoison] = "X:hwpoison",
+#endif
+};
+
/*
* data structures
@@ -186,6 +283,8 @@ static unsigned long total_pages;
static unsigned long nr_pages[HASH_SIZE];
static uint64_t page_flags[HASH_SIZE];
+static char **page_flag_names = (char **)page_flag_names_proc;
+static int page_flag_nr = KPF_SLUB_DEBUG + 1;
/*
* helper functions
@@ -297,7 +396,7 @@ static char *page_flag_name(uint64_t flags)
int present;
int i, j;
- for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+ for (i = 0, j = 0; i < page_flag_nr; i++) {
present = (flags >> i) & 1;
if (!page_flag_names[i]) {
if (present)
@@ -315,7 +414,7 @@ static char *page_flag_longname(uint64_t flags)
static char buf[1024];
int i, n;
- for (i = 0, n = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+ for (i = 0, n = 0; i < page_flag_nr; i++) {
if (!page_flag_names[i])
continue;
if ((flags >> i) & 1)
@@ -675,6 +774,7 @@ static void usage(void)
"page-types [options]\n"
" -r|--raw Raw mode, for kernel developers\n"
" -d|--describe flags Describe flags\n"
+" -k|--kernel describe flags Describe flags, kernel internal order\n"
" -a|--addr addr-spec Walk a range of pages\n"
" -b|--bits bits-spec Walk pages with specified bits\n"
" -p|--pid pid Walk process address space\n"
@@ -705,7 +805,7 @@ static void usage(void)
"bit-names:\n"
);
- for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+ for (i = 0, j = 0; i < page_flag_nr; i++) {
if (!page_flag_names[i])
continue;
printf("%16s%s", page_flag_names[i] + 2,
@@ -836,7 +936,7 @@ static uint64_t parse_flag_name(const char *str, int len)
if (len <= 8 && !strncmp(str, "compound", len))
return BITS_COMPOUND;
- for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+ for (i = 0; i < page_flag_nr; i++) {
if (!page_flag_names[i])
continue;
if (!strncmp(str, page_flag_names[i] + 2, len))
@@ -906,6 +1006,7 @@ static const struct option opts[] = {
{ "addr" , 1, NULL, 'a' },
{ "bits" , 1, NULL, 'b' },
{ "describe" , 1, NULL, 'd' },
+ { "kernel" , 1, NULL, 'k' },
{ "list" , 0, NULL, 'l' },
{ "list-each" , 0, NULL, 'L' },
{ "no-summary", 0, NULL, 'N' },
@@ -922,7 +1023,7 @@ int main(int argc, char *argv[])
page_size = getpagesize();
while ((c = getopt_long(argc, argv,
- "rp:f:a:b:d:lLNXxh", opts, NULL)) != -1) {
+ "rp:f:a:b:d:k:lLNXxh", opts, NULL)) != -1) {
switch (c) {
case 'r':
opt_raw = 1;
@@ -939,6 +1040,10 @@ int main(int argc, char *argv[])
case 'b':
parse_bits_mask(optarg);
break;
+ case 'k':
+ /* Fall-through to case 'd' */
+ page_flag_names = (char **)page_flag_names_kernel;
+ page_flag_nr = __NR_PAGEFLAGS;
case 'd':
describe_flags(optarg);
exit(0);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next reply other threads:[~2009-12-04 21:30 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-12-04 21:29 Alex Chiang [this message]
2009-12-04 21:29 ` [PATCH] page-types: kernel pageflags mode Alex Chiang
2009-12-04 22:17 ` Randy Dunlap
2009-12-04 22:17 ` Randy Dunlap
2009-12-06 3:46 ` [RFC] print symbolic page flag names in bad_page() Wu Fengguang
2009-12-06 3:46 ` Wu Fengguang
2009-12-06 23:00 ` Andi Kleen
2009-12-06 23:00 ` Andi Kleen
2009-12-07 2:01 ` Alex Chiang
2009-12-07 2:01 ` Alex Chiang
2009-12-07 2:02 ` Wu Fengguang
2009-12-07 2:02 ` Wu Fengguang
2009-12-07 5:38 ` Ingo Molnar
2009-12-07 5:38 ` Ingo Molnar
2009-12-07 9:30 ` Mel Gorman
2009-12-07 9:30 ` Mel Gorman
2009-12-16 12:14 ` Wu Fengguang
2009-12-16 12:14 ` Wu Fengguang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20091204212606.29258.98531.stgit@bob.kio \
--to=achiang@hp.com \
--cc=akpm@linux-foundation.org \
--cc=andi@firstfloor.org \
--cc=fengguang.wu@intel.com \
--cc=haicheng.li@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=randy.dunlap@oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.