diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/debug.c | 2 | ||||
-rw-r--r-- | mm/page_alloc.c | 1 | ||||
-rw-r--r-- | mm/page_owner.c | 25 |
3 files changed, 28 insertions, 0 deletions
diff --git a/mm/debug.c b/mm/debug.c index 78dc54877075..61b1f1bb328e 100644 --- a/mm/debug.c +++ b/mm/debug.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/memcontrol.h> | 11 | #include <linux/memcontrol.h> |
12 | #include <trace/events/mmflags.h> | 12 | #include <trace/events/mmflags.h> |
13 | #include <linux/migrate.h> | 13 | #include <linux/migrate.h> |
14 | #include <linux/page_owner.h> | ||
14 | 15 | ||
15 | #include "internal.h" | 16 | #include "internal.h" |
16 | 17 | ||
@@ -67,6 +68,7 @@ void dump_page_badflags(struct page *page, const char *reason, | |||
67 | void dump_page(struct page *page, const char *reason) | 68 | void dump_page(struct page *page, const char *reason) |
68 | { | 69 | { |
69 | dump_page_badflags(page, reason, 0); | 70 | dump_page_badflags(page, reason, 0); |
71 | dump_page_owner(page); | ||
70 | } | 72 | } |
71 | EXPORT_SYMBOL(dump_page); | 73 | EXPORT_SYMBOL(dump_page); |
72 | 74 | ||
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 030fafccaa6b..d98672d33752 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -443,6 +443,7 @@ static void bad_page(struct page *page, const char *reason, | |||
443 | printk(KERN_ALERT "BUG: Bad page state in process %s pfn:%05lx\n", | 443 | printk(KERN_ALERT "BUG: Bad page state in process %s pfn:%05lx\n", |
444 | current->comm, page_to_pfn(page)); | 444 | current->comm, page_to_pfn(page)); |
445 | dump_page_badflags(page, reason, bad_flags); | 445 | dump_page_badflags(page, reason, bad_flags); |
446 | dump_page_owner(page); | ||
446 | 447 | ||
447 | print_modules(); | 448 | print_modules(); |
448 | dump_stack(); | 449 | dump_stack(); |
diff --git a/mm/page_owner.c b/mm/page_owner.c index a57068cfe52f..44ad1f00c4e1 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c | |||
@@ -183,6 +183,31 @@ err: | |||
183 | return -ENOMEM; | 183 | return -ENOMEM; |
184 | } | 184 | } |
185 | 185 | ||
186 | void __dump_page_owner(struct page *page) | ||
187 | { | ||
188 | struct page_ext *page_ext = lookup_page_ext(page); | ||
189 | struct stack_trace trace = { | ||
190 | .nr_entries = page_ext->nr_entries, | ||
191 | .entries = &page_ext->trace_entries[0], | ||
192 | }; | ||
193 | gfp_t gfp_mask = page_ext->gfp_mask; | ||
194 | int mt = gfpflags_to_migratetype(gfp_mask); | ||
195 | |||
196 | if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags)) { | ||
197 | pr_alert("page_owner info is not active (free page?)\n"); | ||
198 | return; | ||
199 | } | ||
200 | |||
201 | pr_alert("page allocated via order %u, migratetype %s, " | ||
202 | "gfp_mask %#x(%pGg)\n", page_ext->order, | ||
203 | migratetype_names[mt], gfp_mask, &gfp_mask); | ||
204 | print_stack_trace(&trace, 0); | ||
205 | |||
206 | if (page_ext->last_migrate_reason != -1) | ||
207 | pr_alert("page has been migrated, last migrate reason: %s\n", | ||
208 | migrate_reason_names[page_ext->last_migrate_reason]); | ||
209 | } | ||
210 | |||
186 | static ssize_t | 211 | static ssize_t |
187 | read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 212 | read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos) |
188 | { | 213 | { |