diff options
author | Wu Fengguang <fengguang.wu@intel.com> | 2010-03-10 18:20:43 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-12 18:52:28 -0500 |
commit | 718a38211bf4375c0a1efad3afbc5dbaef5d33f9 (patch) | |
tree | ade6815c619705f0342f98cc8bb39fa3309c81a6 | |
parent | 9b3a6549b2602ca30f58715a0071e29f9898cae9 (diff) |
mm: introduce dump_page() and print symbolic flag names
- introduce dump_page() to print the page info for debugging some error
condition.
- convert three mm users: bad_page(), print_bad_pte() and memory offline
failure.
- print an extra field: the symbolic names of page->flags
Example dump_page() output:
[ 157.521694] page:ffffea0000a7cba8 count:2 mapcount:1 mapping:ffff88001c901791 index:0x147
[ 157.525570] page flags: 0x100000000100068(uptodate|lru|active|swapbacked)
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Alex Chiang <achiang@hp.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Mel Gorman <mel@linux.vnet.ibm.com>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/mm.h | 2 | ||||
-rw-r--r-- | mm/memory.c | 8 | ||||
-rw-r--r-- | mm/memory_hotplug.c | 6 | ||||
-rw-r--r-- | mm/page_alloc.c | 83 |
4 files changed, 86 insertions, 13 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index 7f693b272c4a..e70f21beb4b4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1465,5 +1465,7 @@ extern void shake_page(struct page *p, int access); | |||
1465 | extern atomic_long_t mce_bad_pages; | 1465 | extern atomic_long_t mce_bad_pages; |
1466 | extern int soft_offline_page(struct page *page, int flags); | 1466 | extern int soft_offline_page(struct page *page, int flags); |
1467 | 1467 | ||
1468 | extern void dump_page(struct page *page); | ||
1469 | |||
1468 | #endif /* __KERNEL__ */ | 1470 | #endif /* __KERNEL__ */ |
1469 | #endif /* _LINUX_MM_H */ | 1471 | #endif /* _LINUX_MM_H */ |
diff --git a/mm/memory.c b/mm/memory.c index 3d9130bd95d0..5b7f2002e54b 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -509,12 +509,8 @@ static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr, | |||
509 | "BUG: Bad page map in process %s pte:%08llx pmd:%08llx\n", | 509 | "BUG: Bad page map in process %s pte:%08llx pmd:%08llx\n", |
510 | current->comm, | 510 | current->comm, |
511 | (long long)pte_val(pte), (long long)pmd_val(*pmd)); | 511 | (long long)pte_val(pte), (long long)pmd_val(*pmd)); |
512 | if (page) { | 512 | if (page) |
513 | printk(KERN_ALERT | 513 | dump_page(page); |
514 | "page:%p flags:%p count:%d mapcount:%d mapping:%p index:%lx\n", | ||
515 | page, (void *)page->flags, page_count(page), | ||
516 | page_mapcount(page), page->mapping, page->index); | ||
517 | } | ||
518 | printk(KERN_ALERT | 514 | printk(KERN_ALERT |
519 | "addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n", | 515 | "addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n", |
520 | (void *)addr, vma->vm_flags, vma->anon_vma, mapping, index); | 516 | (void *)addr, vma->vm_flags, vma->anon_vma, mapping, index); |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 78e34e63c7b8..be211a582930 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -688,9 +688,9 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) | |||
688 | if (page_count(page)) | 688 | if (page_count(page)) |
689 | not_managed++; | 689 | not_managed++; |
690 | #ifdef CONFIG_DEBUG_VM | 690 | #ifdef CONFIG_DEBUG_VM |
691 | printk(KERN_INFO "removing from LRU failed" | 691 | printk(KERN_ALERT "removing pfn %lx from LRU failed\n", |
692 | " %lx/%d/%lx\n", | 692 | pfn); |
693 | pfn, page_count(page), page->flags); | 693 | dump_page(page); |
694 | #endif | 694 | #endif |
695 | } | 695 | } |
696 | } | 696 | } |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 78ce90dd671f..d03c946d5566 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/kmemleak.h> | 50 | #include <linux/kmemleak.h> |
51 | #include <linux/memory.h> | 51 | #include <linux/memory.h> |
52 | #include <trace/events/kmem.h> | 52 | #include <trace/events/kmem.h> |
53 | #include <linux/ftrace_event.h> | ||
53 | 54 | ||
54 | #include <asm/tlbflush.h> | 55 | #include <asm/tlbflush.h> |
55 | #include <asm/div64.h> | 56 | #include <asm/div64.h> |
@@ -288,10 +289,7 @@ static void bad_page(struct page *page) | |||
288 | 289 | ||
289 | printk(KERN_ALERT "BUG: Bad page state in process %s pfn:%05lx\n", | 290 | printk(KERN_ALERT "BUG: Bad page state in process %s pfn:%05lx\n", |
290 | current->comm, page_to_pfn(page)); | 291 | current->comm, page_to_pfn(page)); |
291 | printk(KERN_ALERT | 292 | dump_page(page); |
292 | "page:%p flags:%p count:%d mapcount:%d mapping:%p index:%lx\n", | ||
293 | page, (void *)page->flags, page_count(page), | ||
294 | page_mapcount(page), page->mapping, page->index); | ||
295 | 293 | ||
296 | dump_stack(); | 294 | dump_stack(); |
297 | out: | 295 | out: |
@@ -5183,3 +5181,80 @@ bool is_free_buddy_page(struct page *page) | |||
5183 | return order < MAX_ORDER; | 5181 | return order < MAX_ORDER; |
5184 | } | 5182 | } |
5185 | #endif | 5183 | #endif |
5184 | |||
5185 | static struct trace_print_flags pageflag_names[] = { | ||
5186 | {1UL << PG_locked, "locked" }, | ||
5187 | {1UL << PG_error, "error" }, | ||
5188 | {1UL << PG_referenced, "referenced" }, | ||
5189 | {1UL << PG_uptodate, "uptodate" }, | ||
5190 | {1UL << PG_dirty, "dirty" }, | ||
5191 | {1UL << PG_lru, "lru" }, | ||
5192 | {1UL << PG_active, "active" }, | ||
5193 | {1UL << PG_slab, "slab" }, | ||
5194 | {1UL << PG_owner_priv_1, "owner_priv_1" }, | ||
5195 | {1UL << PG_arch_1, "arch_1" }, | ||
5196 | {1UL << PG_reserved, "reserved" }, | ||
5197 | {1UL << PG_private, "private" }, | ||
5198 | {1UL << PG_private_2, "private_2" }, | ||
5199 | {1UL << PG_writeback, "writeback" }, | ||
5200 | #ifdef CONFIG_PAGEFLAGS_EXTENDED | ||
5201 | {1UL << PG_head, "head" }, | ||
5202 | {1UL << PG_tail, "tail" }, | ||
5203 | #else | ||
5204 | {1UL << PG_compound, "compound" }, | ||
5205 | #endif | ||
5206 | {1UL << PG_swapcache, "swapcache" }, | ||
5207 | {1UL << PG_mappedtodisk, "mappedtodisk" }, | ||
5208 | {1UL << PG_reclaim, "reclaim" }, | ||
5209 | {1UL << PG_buddy, "buddy" }, | ||
5210 | {1UL << PG_swapbacked, "swapbacked" }, | ||
5211 | {1UL << PG_unevictable, "unevictable" }, | ||
5212 | #ifdef CONFIG_MMU | ||
5213 | {1UL << PG_mlocked, "mlocked" }, | ||
5214 | #endif | ||
5215 | #ifdef CONFIG_ARCH_USES_PG_UNCACHED | ||
5216 | {1UL << PG_uncached, "uncached" }, | ||
5217 | #endif | ||
5218 | #ifdef CONFIG_MEMORY_FAILURE | ||
5219 | {1UL << PG_hwpoison, "hwpoison" }, | ||
5220 | #endif | ||
5221 | {-1UL, NULL }, | ||
5222 | }; | ||
5223 | |||
5224 | static void dump_page_flags(unsigned long flags) | ||
5225 | { | ||
5226 | const char *delim = ""; | ||
5227 | unsigned long mask; | ||
5228 | int i; | ||
5229 | |||
5230 | printk(KERN_ALERT "page flags: %#lx(", flags); | ||
5231 | |||
5232 | /* remove zone id */ | ||
5233 | flags &= (1UL << NR_PAGEFLAGS) - 1; | ||
5234 | |||
5235 | for (i = 0; pageflag_names[i].name && flags; i++) { | ||
5236 | |||
5237 | mask = pageflag_names[i].mask; | ||
5238 | if ((flags & mask) != mask) | ||
5239 | continue; | ||
5240 | |||
5241 | flags &= ~mask; | ||
5242 | printk("%s%s", delim, pageflag_names[i].name); | ||
5243 | delim = "|"; | ||
5244 | } | ||
5245 | |||
5246 | /* check for left over flags */ | ||
5247 | if (flags) | ||
5248 | printk("%s%#lx", delim, flags); | ||
5249 | |||
5250 | printk(")\n"); | ||
5251 | } | ||
5252 | |||
5253 | void dump_page(struct page *page) | ||
5254 | { | ||
5255 | printk(KERN_ALERT | ||
5256 | "page:%p count:%d mapcount:%d mapping:%p index:%#lx\n", | ||
5257 | page, page_count(page), page_mapcount(page), | ||
5258 | page->mapping, page->index); | ||
5259 | dump_page_flags(page->flags); | ||
5260 | } | ||