summaryrefslogtreecommitdiffstats
path: root/mm/page_owner.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/page_owner.c')
-rw-r--r--mm/page_owner.c123
1 files changed, 90 insertions, 33 deletions
diff --git a/mm/page_owner.c b/mm/page_owner.c
index addcbb2ae4e4..dee931184788 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -24,6 +24,9 @@ struct page_owner {
24 short last_migrate_reason; 24 short last_migrate_reason;
25 gfp_t gfp_mask; 25 gfp_t gfp_mask;
26 depot_stack_handle_t handle; 26 depot_stack_handle_t handle;
27#ifdef CONFIG_DEBUG_PAGEALLOC
28 depot_stack_handle_t free_handle;
29#endif
27}; 30};
28 31
29static bool page_owner_disabled = true; 32static bool page_owner_disabled = true;
@@ -102,19 +105,6 @@ static inline struct page_owner *get_page_owner(struct page_ext *page_ext)
102 return (void *)page_ext + page_owner_ops.offset; 105 return (void *)page_ext + page_owner_ops.offset;
103} 106}
104 107
105void __reset_page_owner(struct page *page, unsigned int order)
106{
107 int i;
108 struct page_ext *page_ext;
109
110 for (i = 0; i < (1 << order); i++) {
111 page_ext = lookup_page_ext(page + i);
112 if (unlikely(!page_ext))
113 continue;
114 __clear_bit(PAGE_EXT_OWNER, &page_ext->flags);
115 }
116}
117
118static inline bool check_recursive_alloc(unsigned long *entries, 108static inline bool check_recursive_alloc(unsigned long *entries,
119 unsigned int nr_entries, 109 unsigned int nr_entries,
120 unsigned long ip) 110 unsigned long ip)
@@ -154,18 +144,50 @@ static noinline depot_stack_handle_t save_stack(gfp_t flags)
154 return handle; 144 return handle;
155} 145}
156 146
157static inline void __set_page_owner_handle(struct page_ext *page_ext, 147void __reset_page_owner(struct page *page, unsigned int order)
158 depot_stack_handle_t handle, unsigned int order, gfp_t gfp_mask)
159{ 148{
149 int i;
150 struct page_ext *page_ext;
151#ifdef CONFIG_DEBUG_PAGEALLOC
152 depot_stack_handle_t handle = 0;
160 struct page_owner *page_owner; 153 struct page_owner *page_owner;
161 154
162 page_owner = get_page_owner(page_ext); 155 if (debug_pagealloc_enabled())
163 page_owner->handle = handle; 156 handle = save_stack(GFP_NOWAIT | __GFP_NOWARN);
164 page_owner->order = order; 157#endif
165 page_owner->gfp_mask = gfp_mask;
166 page_owner->last_migrate_reason = -1;
167 158
168 __set_bit(PAGE_EXT_OWNER, &page_ext->flags); 159 for (i = 0; i < (1 << order); i++) {
160 page_ext = lookup_page_ext(page + i);
161 if (unlikely(!page_ext))
162 continue;
163 __clear_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags);
164#ifdef CONFIG_DEBUG_PAGEALLOC
165 if (debug_pagealloc_enabled()) {
166 page_owner = get_page_owner(page_ext);
167 page_owner->free_handle = handle;
168 }
169#endif
170 }
171}
172
173static inline void __set_page_owner_handle(struct page *page,
174 struct page_ext *page_ext, depot_stack_handle_t handle,
175 unsigned int order, gfp_t gfp_mask)
176{
177 struct page_owner *page_owner;
178 int i;
179
180 for (i = 0; i < (1 << order); i++) {
181 page_owner = get_page_owner(page_ext);
182 page_owner->handle = handle;
183 page_owner->order = order;
184 page_owner->gfp_mask = gfp_mask;
185 page_owner->last_migrate_reason = -1;
186 __set_bit(PAGE_EXT_OWNER, &page_ext->flags);
187 __set_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags);
188
189 page_ext = lookup_page_ext(page + i);
190 }
169} 191}
170 192
171noinline void __set_page_owner(struct page *page, unsigned int order, 193noinline void __set_page_owner(struct page *page, unsigned int order,
@@ -178,7 +200,7 @@ noinline void __set_page_owner(struct page *page, unsigned int order,
178 return; 200 return;
179 201
180 handle = save_stack(gfp_mask); 202 handle = save_stack(gfp_mask);
181 __set_page_owner_handle(page_ext, handle, order, gfp_mask); 203 __set_page_owner_handle(page, page_ext, handle, order, gfp_mask);
182} 204}
183 205
184void __set_page_owner_migrate_reason(struct page *page, int reason) 206void __set_page_owner_migrate_reason(struct page *page, int reason)
@@ -204,8 +226,11 @@ void __split_page_owner(struct page *page, unsigned int order)
204 226
205 page_owner = get_page_owner(page_ext); 227 page_owner = get_page_owner(page_ext);
206 page_owner->order = 0; 228 page_owner->order = 0;
207 for (i = 1; i < (1 << order); i++) 229 for (i = 1; i < (1 << order); i++) {
208 __copy_page_owner(page, page + i); 230 page_ext = lookup_page_ext(page + i);
231 page_owner = get_page_owner(page_ext);
232 page_owner->order = 0;
233 }
209} 234}
210 235
211void __copy_page_owner(struct page *oldpage, struct page *newpage) 236void __copy_page_owner(struct page *oldpage, struct page *newpage)
@@ -235,6 +260,7 @@ void __copy_page_owner(struct page *oldpage, struct page *newpage)
235 * the new page, which will be freed. 260 * the new page, which will be freed.
236 */ 261 */
237 __set_bit(PAGE_EXT_OWNER, &new_ext->flags); 262 __set_bit(PAGE_EXT_OWNER, &new_ext->flags);
263 __set_bit(PAGE_EXT_OWNER_ACTIVE, &new_ext->flags);
238} 264}
239 265
240void pagetypeinfo_showmixedcount_print(struct seq_file *m, 266void pagetypeinfo_showmixedcount_print(struct seq_file *m,
@@ -294,7 +320,7 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m,
294 if (unlikely(!page_ext)) 320 if (unlikely(!page_ext))
295 continue; 321 continue;
296 322
297 if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags)) 323 if (!test_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags))
298 continue; 324 continue;
299 325
300 page_owner = get_page_owner(page_ext); 326 page_owner = get_page_owner(page_ext);
@@ -405,20 +431,36 @@ void __dump_page_owner(struct page *page)
405 mt = gfpflags_to_migratetype(gfp_mask); 431 mt = gfpflags_to_migratetype(gfp_mask);
406 432
407 if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags)) { 433 if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags)) {
408 pr_alert("page_owner info is not active (free page?)\n"); 434 pr_alert("page_owner info is not present (never set?)\n");
409 return; 435 return;
410 } 436 }
411 437
438 if (test_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags))
439 pr_alert("page_owner tracks the page as allocated\n");
440 else
441 pr_alert("page_owner tracks the page as freed\n");
442
443 pr_alert("page last allocated via order %u, migratetype %s, gfp_mask %#x(%pGg)\n",
444 page_owner->order, migratetype_names[mt], gfp_mask, &gfp_mask);
445
412 handle = READ_ONCE(page_owner->handle); 446 handle = READ_ONCE(page_owner->handle);
413 if (!handle) { 447 if (!handle) {
414 pr_alert("page_owner info is not active (free page?)\n"); 448 pr_alert("page_owner allocation stack trace missing\n");
415 return; 449 } else {
450 nr_entries = stack_depot_fetch(handle, &entries);
451 stack_trace_print(entries, nr_entries, 0);
416 } 452 }
417 453
418 nr_entries = stack_depot_fetch(handle, &entries); 454#ifdef CONFIG_DEBUG_PAGEALLOC
419 pr_alert("page allocated via order %u, migratetype %s, gfp_mask %#x(%pGg)\n", 455 handle = READ_ONCE(page_owner->free_handle);
420 page_owner->order, migratetype_names[mt], gfp_mask, &gfp_mask); 456 if (!handle) {
421 stack_trace_print(entries, nr_entries, 0); 457 pr_alert("page_owner free stack trace missing\n");
458 } else {
459 nr_entries = stack_depot_fetch(handle, &entries);
460 pr_alert("page last free stack trace:\n");
461 stack_trace_print(entries, nr_entries, 0);
462 }
463#endif
422 464
423 if (page_owner->last_migrate_reason != -1) 465 if (page_owner->last_migrate_reason != -1)
424 pr_alert("page has been migrated, last migrate reason: %s\n", 466 pr_alert("page has been migrated, last migrate reason: %s\n",
@@ -481,9 +523,23 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
481 if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags)) 523 if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags))
482 continue; 524 continue;
483 525
526 /*
527 * Although we do have the info about past allocation of free
528 * pages, it's not relevant for current memory usage.
529 */
530 if (!test_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags))
531 continue;
532
484 page_owner = get_page_owner(page_ext); 533 page_owner = get_page_owner(page_ext);
485 534
486 /* 535 /*
536 * Don't print "tail" pages of high-order allocations as that
537 * would inflate the stats.
538 */
539 if (!IS_ALIGNED(pfn, 1 << page_owner->order))
540 continue;
541
542 /*
487 * Access to page_ext->handle isn't synchronous so we should 543 * Access to page_ext->handle isn't synchronous so we should
488 * be careful to access it. 544 * be careful to access it.
489 */ 545 */
@@ -562,7 +618,8 @@ static void init_pages_in_zone(pg_data_t *pgdat, struct zone *zone)
562 continue; 618 continue;
563 619
564 /* Found early allocated page */ 620 /* Found early allocated page */
565 __set_page_owner_handle(page_ext, early_handle, 0, 0); 621 __set_page_owner_handle(page, page_ext, early_handle,
622 0, 0);
566 count++; 623 count++;
567 } 624 }
568 cond_resched(); 625 cond_resched();