blob: beb33ab7a996acadfd8c56ac4a5177c81440fbc5 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Joonsoo Kim48c96a32014-12-12 16:56:01 -08002#include <linux/debugfs.h>
3#include <linux/mm.h>
4#include <linux/slab.h>
5#include <linux/uaccess.h>
Mike Rapoport57c8a662018-10-30 15:09:49 -07006#include <linux/memblock.h>
Joonsoo Kim48c96a32014-12-12 16:56:01 -08007#include <linux/stacktrace.h>
8#include <linux/page_owner.h>
Vlastimil Babka7dd80b82016-03-15 14:56:12 -07009#include <linux/jump_label.h>
Vlastimil Babka7cd12b42016-03-15 14:56:18 -070010#include <linux/migrate.h>
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070011#include <linux/stackdepot.h>
Joonsoo Kime2f612e2016-10-07 16:58:21 -070012#include <linux/seq_file.h>
Liam Markfd0328e2020-12-14 19:04:49 -080013#include <linux/sched/clock.h>
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070014
Joonsoo Kim48c96a32014-12-12 16:56:01 -080015#include "internal.h"
16
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070017/*
18 * TODO: teach PAGE_OWNER_STACK_DEPTH (__dump_page_owner and save_stack)
19 * to use off stack temporal storage
20 */
21#define PAGE_OWNER_STACK_DEPTH (16)
22
Joonsoo Kim9300d8d2016-10-07 16:58:30 -070023struct page_owner {
Ayush Mittal6b4c54e2017-11-15 17:34:30 -080024 unsigned short order;
25 short last_migrate_reason;
Joonsoo Kim9300d8d2016-10-07 16:58:30 -070026 gfp_t gfp_mask;
Joonsoo Kim9300d8d2016-10-07 16:58:30 -070027 depot_stack_handle_t handle;
Vlastimil Babka89745582019-09-23 15:34:42 -070028 depot_stack_handle_t free_handle;
Liam Markfd0328e2020-12-14 19:04:49 -080029 u64 ts_nsec;
30 pid_t pid;
Joonsoo Kim9300d8d2016-10-07 16:58:30 -070031};
32
Vlastimil Babka0fe9a442019-10-14 14:11:44 -070033static bool page_owner_enabled = false;
Vlastimil Babka7dd80b82016-03-15 14:56:12 -070034DEFINE_STATIC_KEY_FALSE(page_owner_inited);
Joonsoo Kim48c96a32014-12-12 16:56:01 -080035
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070036static depot_stack_handle_t dummy_handle;
37static depot_stack_handle_t failure_handle;
Vlastimil Babkadab4ead2017-09-06 16:20:44 -070038static depot_stack_handle_t early_handle;
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070039
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -080040static void init_early_allocated_pages(void);
41
Dou Liyang11731942018-04-05 16:23:49 -070042static int __init early_page_owner_param(char *buf)
Joonsoo Kim48c96a32014-12-12 16:56:01 -080043{
44 if (!buf)
45 return -EINVAL;
46
47 if (strcmp(buf, "on") == 0)
Vlastimil Babka0fe9a442019-10-14 14:11:44 -070048 page_owner_enabled = true;
Joonsoo Kim48c96a32014-12-12 16:56:01 -080049
50 return 0;
51}
52early_param("page_owner", early_page_owner_param);
53
54static bool need_page_owner(void)
55{
Vlastimil Babka0fe9a442019-10-14 14:11:44 -070056 return page_owner_enabled;
Joonsoo Kim48c96a32014-12-12 16:56:01 -080057}
58
Vlastimil Babkadab4ead2017-09-06 16:20:44 -070059static __always_inline depot_stack_handle_t create_dummy_stack(void)
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070060{
61 unsigned long entries[4];
Thomas Gleixneraf52bf62019-04-25 11:45:03 +020062 unsigned int nr_entries;
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070063
Thomas Gleixneraf52bf62019-04-25 11:45:03 +020064 nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 0);
65 return stack_depot_save(entries, nr_entries, GFP_KERNEL);
Vlastimil Babkadab4ead2017-09-06 16:20:44 -070066}
67
68static noinline void register_dummy_stack(void)
69{
70 dummy_handle = create_dummy_stack();
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070071}
72
73static noinline void register_failure_stack(void)
74{
Vlastimil Babkadab4ead2017-09-06 16:20:44 -070075 failure_handle = create_dummy_stack();
76}
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070077
Vlastimil Babkadab4ead2017-09-06 16:20:44 -070078static noinline void register_early_stack(void)
79{
80 early_handle = create_dummy_stack();
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070081}
82
Joonsoo Kim48c96a32014-12-12 16:56:01 -080083static void init_page_owner(void)
84{
Vlastimil Babka0fe9a442019-10-14 14:11:44 -070085 if (!page_owner_enabled)
Joonsoo Kim48c96a32014-12-12 16:56:01 -080086 return;
87
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -070088 register_dummy_stack();
89 register_failure_stack();
Vlastimil Babkadab4ead2017-09-06 16:20:44 -070090 register_early_stack();
Vlastimil Babka7dd80b82016-03-15 14:56:12 -070091 static_branch_enable(&page_owner_inited);
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -080092 init_early_allocated_pages();
Joonsoo Kim48c96a32014-12-12 16:56:01 -080093}
94
95struct page_ext_operations page_owner_ops = {
Joonsoo Kim9300d8d2016-10-07 16:58:30 -070096 .size = sizeof(struct page_owner),
Joonsoo Kim48c96a32014-12-12 16:56:01 -080097 .need = need_page_owner,
98 .init = init_page_owner,
99};
100
Vijayanand Jittab76264c2021-01-05 11:33:53 +0530101struct page_owner *get_page_owner(struct page_ext *page_ext)
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700102{
103 return (void *)page_ext + page_owner_ops.offset;
104}
Vijayanand Jittab76264c2021-01-05 11:33:53 +0530105EXPORT_SYMBOL_GPL(get_page_owner);
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700106
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200107static inline bool check_recursive_alloc(unsigned long *entries,
108 unsigned int nr_entries,
109 unsigned long ip)
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800110{
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200111 unsigned int i;
Yang Shif86e4272016-06-03 14:55:38 -0700112
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200113 for (i = 0; i < nr_entries; i++) {
114 if (entries[i] == ip)
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700115 return true;
116 }
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700117 return false;
118}
119
120static noinline depot_stack_handle_t save_stack(gfp_t flags)
121{
122 unsigned long entries[PAGE_OWNER_STACK_DEPTH];
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700123 depot_stack_handle_t handle;
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200124 unsigned int nr_entries;
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700125
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200126 nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 2);
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700127
128 /*
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200129 * We need to check recursion here because our request to
130 * stackdepot could trigger memory allocation to save new
131 * entry. New memory allocation would reach here and call
132 * stack_depot_save_entries() again if we don't catch it. There is
133 * still not enough memory in stackdepot so it would try to
134 * allocate memory again and loop forever.
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700135 */
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200136 if (check_recursive_alloc(entries, nr_entries, _RET_IP_))
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700137 return dummy_handle;
138
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200139 handle = stack_depot_save(entries, nr_entries, flags);
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700140 if (!handle)
141 handle = failure_handle;
142
143 return handle;
144}
145
Vlastimil Babka89745582019-09-23 15:34:42 -0700146void __reset_page_owner(struct page *page, unsigned int order)
147{
148 int i;
149 struct page_ext *page_ext;
Vlastimil Babka89745582019-09-23 15:34:42 -0700150 depot_stack_handle_t handle = 0;
151 struct page_owner *page_owner;
152
Vlastimil Babka0fe9a442019-10-14 14:11:44 -0700153 handle = save_stack(GFP_NOWAIT | __GFP_NOWARN);
Vlastimil Babka89745582019-09-23 15:34:42 -0700154
Vlastimil Babka5556cfe2019-10-14 14:11:40 -0700155 page_ext = lookup_page_ext(page);
156 if (unlikely(!page_ext))
157 return;
Vlastimil Babka89745582019-09-23 15:34:42 -0700158 for (i = 0; i < (1 << order); i++) {
Vlastimil Babkafdf3bf82019-10-14 14:11:47 -0700159 __clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
Vlastimil Babka0fe9a442019-10-14 14:11:44 -0700160 page_owner = get_page_owner(page_ext);
161 page_owner->free_handle = handle;
Vlastimil Babka5556cfe2019-10-14 14:11:40 -0700162 page_ext = page_ext_next(page_ext);
Vlastimil Babka89745582019-09-23 15:34:42 -0700163 }
164}
165
Vlastimil Babka7e2f2a02019-09-23 15:34:36 -0700166static inline void __set_page_owner_handle(struct page *page,
167 struct page_ext *page_ext, depot_stack_handle_t handle,
168 unsigned int order, gfp_t gfp_mask)
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700169{
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700170 struct page_owner *page_owner;
Vlastimil Babka7e2f2a02019-09-23 15:34:36 -0700171 int i;
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800172
Vlastimil Babka7e2f2a02019-09-23 15:34:36 -0700173 for (i = 0; i < (1 << order); i++) {
174 page_owner = get_page_owner(page_ext);
175 page_owner->handle = handle;
176 page_owner->order = order;
177 page_owner->gfp_mask = gfp_mask;
178 page_owner->last_migrate_reason = -1;
Liam Markfd0328e2020-12-14 19:04:49 -0800179 page_owner->pid = current->pid;
180 page_owner->ts_nsec = local_clock();
Vlastimil Babka7e2f2a02019-09-23 15:34:36 -0700181 __set_bit(PAGE_EXT_OWNER, &page_ext->flags);
Vlastimil Babkafdf3bf82019-10-14 14:11:47 -0700182 __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800183
Vlastimil Babka5556cfe2019-10-14 14:11:40 -0700184 page_ext = page_ext_next(page_ext);
Vlastimil Babka7e2f2a02019-09-23 15:34:36 -0700185 }
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800186}
187
Vlastimil Babkadab4ead2017-09-06 16:20:44 -0700188noinline void __set_page_owner(struct page *page, unsigned int order,
189 gfp_t gfp_mask)
190{
191 struct page_ext *page_ext = lookup_page_ext(page);
192 depot_stack_handle_t handle;
193
194 if (unlikely(!page_ext))
195 return;
196
197 handle = save_stack(gfp_mask);
Vlastimil Babka7e2f2a02019-09-23 15:34:36 -0700198 __set_page_owner_handle(page, page_ext, handle, order, gfp_mask);
Vlastimil Babkadab4ead2017-09-06 16:20:44 -0700199}
200
Vlastimil Babka7cd12b42016-03-15 14:56:18 -0700201void __set_page_owner_migrate_reason(struct page *page, int reason)
202{
203 struct page_ext *page_ext = lookup_page_ext(page);
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700204 struct page_owner *page_owner;
205
Yang Shif86e4272016-06-03 14:55:38 -0700206 if (unlikely(!page_ext))
207 return;
Vlastimil Babka7cd12b42016-03-15 14:56:18 -0700208
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700209 page_owner = get_page_owner(page_ext);
210 page_owner->last_migrate_reason = reason;
Vlastimil Babka7cd12b42016-03-15 14:56:18 -0700211}
212
Matthew Wilcox (Oracle)8fb156c2020-10-15 20:05:29 -0700213void __split_page_owner(struct page *page, unsigned int nr)
Joonsoo Kime2cfc912015-07-17 16:24:18 -0700214{
Joonsoo Kima9627bc2016-07-26 15:23:49 -0700215 int i;
Joonsoo Kime2cfc912015-07-17 16:24:18 -0700216 struct page_ext *page_ext = lookup_page_ext(page);
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700217 struct page_owner *page_owner;
Joonsoo Kime2cfc912015-07-17 16:24:18 -0700218
Joonsoo Kima9627bc2016-07-26 15:23:49 -0700219 if (unlikely(!page_ext))
220 return;
221
Matthew Wilcox (Oracle)8fb156c2020-10-15 20:05:29 -0700222 for (i = 0; i < nr; i++) {
Vlastimil Babka7e2f2a02019-09-23 15:34:36 -0700223 page_owner = get_page_owner(page_ext);
224 page_owner->order = 0;
Vlastimil Babka5556cfe2019-10-14 14:11:40 -0700225 page_ext = page_ext_next(page_ext);
Vlastimil Babka7e2f2a02019-09-23 15:34:36 -0700226 }
Joonsoo Kime2cfc912015-07-17 16:24:18 -0700227}
228
Vlastimil Babkad435edc2016-03-15 14:56:15 -0700229void __copy_page_owner(struct page *oldpage, struct page *newpage)
230{
231 struct page_ext *old_ext = lookup_page_ext(oldpage);
232 struct page_ext *new_ext = lookup_page_ext(newpage);
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700233 struct page_owner *old_page_owner, *new_page_owner;
Vlastimil Babkad435edc2016-03-15 14:56:15 -0700234
Yang Shif86e4272016-06-03 14:55:38 -0700235 if (unlikely(!old_ext || !new_ext))
236 return;
237
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700238 old_page_owner = get_page_owner(old_ext);
239 new_page_owner = get_page_owner(new_ext);
240 new_page_owner->order = old_page_owner->order;
241 new_page_owner->gfp_mask = old_page_owner->gfp_mask;
242 new_page_owner->last_migrate_reason =
243 old_page_owner->last_migrate_reason;
244 new_page_owner->handle = old_page_owner->handle;
Liam Markfd0328e2020-12-14 19:04:49 -0800245 new_page_owner->pid = old_page_owner->pid;
246 new_page_owner->ts_nsec = old_page_owner->ts_nsec;
Vlastimil Babkad435edc2016-03-15 14:56:15 -0700247
248 /*
249 * We don't clear the bit on the oldpage as it's going to be freed
250 * after migration. Until then, the info can be useful in case of
251 * a bug, and the overal stats will be off a bit only temporarily.
252 * Also, migrate_misplaced_transhuge_page() can still fail the
253 * migration and then we want the oldpage to retain the info. But
254 * in that case we also don't need to explicitly clear the info from
255 * the new page, which will be freed.
256 */
257 __set_bit(PAGE_EXT_OWNER, &new_ext->flags);
Vlastimil Babkafdf3bf82019-10-14 14:11:47 -0700258 __set_bit(PAGE_EXT_OWNER_ALLOCATED, &new_ext->flags);
Vlastimil Babkad435edc2016-03-15 14:56:15 -0700259}
260
Joonsoo Kime2f612e2016-10-07 16:58:21 -0700261void pagetypeinfo_showmixedcount_print(struct seq_file *m,
262 pg_data_t *pgdat, struct zone *zone)
263{
264 struct page *page;
265 struct page_ext *page_ext;
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700266 struct page_owner *page_owner;
Joonsoo Kime2f612e2016-10-07 16:58:21 -0700267 unsigned long pfn = zone->zone_start_pfn, block_end_pfn;
268 unsigned long end_pfn = pfn + zone->spanned_pages;
269 unsigned long count[MIGRATE_TYPES] = { 0, };
270 int pageblock_mt, page_mt;
271 int i;
272
273 /* Scan block by block. First and last block may be incomplete */
274 pfn = zone->zone_start_pfn;
275
276 /*
277 * Walk the zone in pageblock_nr_pages steps. If a page block spans
278 * a zone boundary, it will be double counted between zones. This does
279 * not matter as the mixed block count will still be correct
280 */
281 for (; pfn < end_pfn; ) {
Qian Caia26ee562019-10-18 20:19:29 -0700282 page = pfn_to_online_page(pfn);
283 if (!page) {
Joonsoo Kime2f612e2016-10-07 16:58:21 -0700284 pfn = ALIGN(pfn + 1, MAX_ORDER_NR_PAGES);
285 continue;
286 }
287
288 block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
289 block_end_pfn = min(block_end_pfn, end_pfn);
290
Joonsoo Kime2f612e2016-10-07 16:58:21 -0700291 pageblock_mt = get_pageblock_migratetype(page);
292
293 for (; pfn < block_end_pfn; pfn++) {
294 if (!pfn_valid_within(pfn))
295 continue;
296
Qian Caia26ee562019-10-18 20:19:29 -0700297 /* The pageblock is online, no need to recheck. */
Joonsoo Kime2f612e2016-10-07 16:58:21 -0700298 page = pfn_to_page(pfn);
299
300 if (page_zone(page) != zone)
301 continue;
302
303 if (PageBuddy(page)) {
Vinayak Menon727c0802017-07-10 15:49:17 -0700304 unsigned long freepage_order;
305
Matthew Wilcox (Oracle)ab130f912020-10-15 20:10:15 -0700306 freepage_order = buddy_order_unsafe(page);
Vinayak Menon727c0802017-07-10 15:49:17 -0700307 if (freepage_order < MAX_ORDER)
308 pfn += (1UL << freepage_order) - 1;
Joonsoo Kime2f612e2016-10-07 16:58:21 -0700309 continue;
310 }
311
312 if (PageReserved(page))
313 continue;
314
315 page_ext = lookup_page_ext(page);
316 if (unlikely(!page_ext))
317 continue;
318
Vlastimil Babkafdf3bf82019-10-14 14:11:47 -0700319 if (!test_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags))
Joonsoo Kime2f612e2016-10-07 16:58:21 -0700320 continue;
321
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700322 page_owner = get_page_owner(page_ext);
Wei Yang01c0bfe2020-06-03 15:59:08 -0700323 page_mt = gfp_migratetype(page_owner->gfp_mask);
Joonsoo Kime2f612e2016-10-07 16:58:21 -0700324 if (pageblock_mt != page_mt) {
325 if (is_migrate_cma(pageblock_mt))
326 count[MIGRATE_MOVABLE]++;
327 else
328 count[pageblock_mt]++;
329
330 pfn = block_end_pfn;
331 break;
332 }
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700333 pfn += (1UL << page_owner->order) - 1;
Joonsoo Kime2f612e2016-10-07 16:58:21 -0700334 }
335 }
336
337 /* Print counts */
338 seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name);
339 for (i = 0; i < MIGRATE_TYPES; i++)
340 seq_printf(m, "%12lu ", count[i]);
341 seq_putc(m, '\n');
342}
343
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800344static ssize_t
345print_page_owner(char __user *buf, size_t count, unsigned long pfn,
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700346 struct page *page, struct page_owner *page_owner,
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700347 depot_stack_handle_t handle)
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800348{
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200349 int ret, pageblock_mt, page_mt;
350 unsigned long *entries;
351 unsigned int nr_entries;
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800352 char *kbuf;
353
Miles Chenc8f61cf2018-12-28 00:33:21 -0800354 count = min_t(size_t, count, PAGE_SIZE);
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800355 kbuf = kmalloc(count, GFP_KERNEL);
356 if (!kbuf)
357 return -ENOMEM;
358
359 ret = snprintf(kbuf, count,
Liam Markfd0328e2020-12-14 19:04:49 -0800360 "Page allocated via order %u, mask %#x(%pGg), pid %d, ts %llu ns\n",
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700361 page_owner->order, page_owner->gfp_mask,
Liam Markfd0328e2020-12-14 19:04:49 -0800362 &page_owner->gfp_mask, page_owner->pid,
363 page_owner->ts_nsec);
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800364
365 if (ret >= count)
366 goto err;
367
368 /* Print information relevant to grouping pages by mobility */
Mel Gorman0b423ca2016-05-19 17:14:27 -0700369 pageblock_mt = get_pageblock_migratetype(page);
Wei Yang01c0bfe2020-06-03 15:59:08 -0700370 page_mt = gfp_migratetype(page_owner->gfp_mask);
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800371 ret += snprintf(kbuf + ret, count - ret,
Vlastimil Babka60f30352016-03-15 14:56:08 -0700372 "PFN %lu type %s Block %lu type %s Flags %#lx(%pGp)\n",
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800373 pfn,
Vlastimil Babka60f30352016-03-15 14:56:08 -0700374 migratetype_names[page_mt],
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800375 pfn >> pageblock_order,
Vlastimil Babka60f30352016-03-15 14:56:08 -0700376 migratetype_names[pageblock_mt],
377 page->flags, &page->flags);
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800378
379 if (ret >= count)
380 goto err;
381
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200382 nr_entries = stack_depot_fetch(handle, &entries);
383 ret += stack_trace_snprint(kbuf + ret, count - ret, entries, nr_entries, 0);
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800384 if (ret >= count)
385 goto err;
386
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700387 if (page_owner->last_migrate_reason != -1) {
Vlastimil Babka7cd12b42016-03-15 14:56:18 -0700388 ret += snprintf(kbuf + ret, count - ret,
389 "Page has been migrated, last migrate reason: %s\n",
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700390 migrate_reason_names[page_owner->last_migrate_reason]);
Vlastimil Babka7cd12b42016-03-15 14:56:18 -0700391 if (ret >= count)
392 goto err;
393 }
394
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800395 ret += snprintf(kbuf + ret, count - ret, "\n");
396 if (ret >= count)
397 goto err;
398
399 if (copy_to_user(buf, kbuf, ret))
400 ret = -EFAULT;
401
402 kfree(kbuf);
403 return ret;
404
405err:
406 kfree(kbuf);
407 return -ENOMEM;
408}
409
Vlastimil Babka4e462112016-03-15 14:56:21 -0700410void __dump_page_owner(struct page *page)
411{
412 struct page_ext *page_ext = lookup_page_ext(page);
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700413 struct page_owner *page_owner;
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700414 depot_stack_handle_t handle;
Thomas Gleixneraf52bf62019-04-25 11:45:03 +0200415 unsigned long *entries;
416 unsigned int nr_entries;
Sudip Mukherjee82850272016-06-24 14:50:24 -0700417 gfp_t gfp_mask;
418 int mt;
Vlastimil Babka4e462112016-03-15 14:56:21 -0700419
Yang Shif86e4272016-06-03 14:55:38 -0700420 if (unlikely(!page_ext)) {
421 pr_alert("There is not page extension available.\n");
422 return;
423 }
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700424
425 page_owner = get_page_owner(page_ext);
426 gfp_mask = page_owner->gfp_mask;
Wei Yang01c0bfe2020-06-03 15:59:08 -0700427 mt = gfp_migratetype(gfp_mask);
Yang Shif86e4272016-06-03 14:55:38 -0700428
Vlastimil Babka4e462112016-03-15 14:56:21 -0700429 if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags)) {
Vlastimil Babka373891672019-09-23 15:34:39 -0700430 pr_alert("page_owner info is not present (never set?)\n");
Vlastimil Babka4e462112016-03-15 14:56:21 -0700431 return;
432 }
433
Vlastimil Babkafdf3bf82019-10-14 14:11:47 -0700434 if (test_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags))
Vlastimil Babka373891672019-09-23 15:34:39 -0700435 pr_alert("page_owner tracks the page as allocated\n");
436 else
437 pr_alert("page_owner tracks the page as freed\n");
438
Liam Markfd0328e2020-12-14 19:04:49 -0800439 pr_alert("page last allocated via order %u, migratetype %s, gfp_mask %#x(%pGg), pid %d, ts %llu\n",
440 page_owner->order, migratetype_names[mt], gfp_mask, &gfp_mask,
441 page_owner->pid, page_owner->ts_nsec);
Vlastimil Babka373891672019-09-23 15:34:39 -0700442
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700443 handle = READ_ONCE(page_owner->handle);
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700444 if (!handle) {
Vlastimil Babka373891672019-09-23 15:34:39 -0700445 pr_alert("page_owner allocation stack trace missing\n");
446 } else {
447 nr_entries = stack_depot_fetch(handle, &entries);
448 stack_trace_print(entries, nr_entries, 0);
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700449 }
450
Vlastimil Babka89745582019-09-23 15:34:42 -0700451 handle = READ_ONCE(page_owner->free_handle);
452 if (!handle) {
453 pr_alert("page_owner free stack trace missing\n");
454 } else {
455 nr_entries = stack_depot_fetch(handle, &entries);
456 pr_alert("page last free stack trace:\n");
457 stack_trace_print(entries, nr_entries, 0);
458 }
Vlastimil Babka89745582019-09-23 15:34:42 -0700459
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700460 if (page_owner->last_migrate_reason != -1)
Vlastimil Babka4e462112016-03-15 14:56:21 -0700461 pr_alert("page has been migrated, last migrate reason: %s\n",
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700462 migrate_reason_names[page_owner->last_migrate_reason]);
Vlastimil Babka4e462112016-03-15 14:56:21 -0700463}
464
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800465static ssize_t
466read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
467{
468 unsigned long pfn;
469 struct page *page;
470 struct page_ext *page_ext;
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700471 struct page_owner *page_owner;
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700472 depot_stack_handle_t handle;
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800473
Vlastimil Babka7dd80b82016-03-15 14:56:12 -0700474 if (!static_branch_unlikely(&page_owner_inited))
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800475 return -EINVAL;
476
477 page = NULL;
478 pfn = min_low_pfn + *ppos;
479
480 /* Find a valid PFN or the start of a MAX_ORDER_NR_PAGES area */
481 while (!pfn_valid(pfn) && (pfn & (MAX_ORDER_NR_PAGES - 1)) != 0)
482 pfn++;
483
484 drain_all_pages(NULL);
485
486 /* Find an allocated page */
487 for (; pfn < max_pfn; pfn++) {
488 /*
489 * If the new page is in a new MAX_ORDER_NR_PAGES area,
490 * validate the area as existing, skip it if not
491 */
492 if ((pfn & (MAX_ORDER_NR_PAGES - 1)) == 0 && !pfn_valid(pfn)) {
493 pfn += MAX_ORDER_NR_PAGES - 1;
494 continue;
495 }
496
497 /* Check for holes within a MAX_ORDER area */
498 if (!pfn_valid_within(pfn))
499 continue;
500
501 page = pfn_to_page(pfn);
502 if (PageBuddy(page)) {
Matthew Wilcox (Oracle)ab130f912020-10-15 20:10:15 -0700503 unsigned long freepage_order = buddy_order_unsafe(page);
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800504
505 if (freepage_order < MAX_ORDER)
506 pfn += (1UL << freepage_order) - 1;
507 continue;
508 }
509
510 page_ext = lookup_page_ext(page);
Yang Shif86e4272016-06-03 14:55:38 -0700511 if (unlikely(!page_ext))
512 continue;
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800513
514 /*
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800515 * Some pages could be missed by concurrent allocation or free,
516 * because we don't hold the zone lock.
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800517 */
518 if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags))
519 continue;
520
Vlastimil Babka373891672019-09-23 15:34:39 -0700521 /*
522 * Although we do have the info about past allocation of free
523 * pages, it's not relevant for current memory usage.
524 */
Vlastimil Babkafdf3bf82019-10-14 14:11:47 -0700525 if (!test_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags))
Vlastimil Babka373891672019-09-23 15:34:39 -0700526 continue;
527
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700528 page_owner = get_page_owner(page_ext);
529
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700530 /*
Vlastimil Babka7e2f2a02019-09-23 15:34:36 -0700531 * Don't print "tail" pages of high-order allocations as that
532 * would inflate the stats.
533 */
534 if (!IS_ALIGNED(pfn, 1 << page_owner->order))
535 continue;
536
537 /*
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700538 * Access to page_ext->handle isn't synchronous so we should
539 * be careful to access it.
540 */
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700541 handle = READ_ONCE(page_owner->handle);
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700542 if (!handle)
543 continue;
544
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800545 /* Record the next PFN to read in the file offset */
546 *ppos = (pfn - min_low_pfn) + 1;
547
Joonsoo Kimf2ca0b52016-07-26 15:23:55 -0700548 return print_page_owner(buf, count, pfn, page,
Joonsoo Kim9300d8d2016-10-07 16:58:30 -0700549 page_owner, handle);
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800550 }
551
552 return 0;
553}
554
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800555static void init_pages_in_zone(pg_data_t *pgdat, struct zone *zone)
556{
Oscar Salvador6787c1d2018-01-31 16:20:11 -0800557 unsigned long pfn = zone->zone_start_pfn;
558 unsigned long end_pfn = zone_end_pfn(zone);
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800559 unsigned long count = 0;
560
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800561 /*
562 * Walk the zone in pageblock_nr_pages steps. If a page block spans
563 * a zone boundary, it will be double counted between zones. This does
564 * not matter as the mixed block count will still be correct
565 */
566 for (; pfn < end_pfn; ) {
Oscar Salvador6787c1d2018-01-31 16:20:11 -0800567 unsigned long block_end_pfn;
568
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800569 if (!pfn_valid(pfn)) {
570 pfn = ALIGN(pfn + 1, MAX_ORDER_NR_PAGES);
571 continue;
572 }
573
574 block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
575 block_end_pfn = min(block_end_pfn, end_pfn);
576
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800577 for (; pfn < block_end_pfn; pfn++) {
Oscar Salvador6787c1d2018-01-31 16:20:11 -0800578 struct page *page;
579 struct page_ext *page_ext;
580
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800581 if (!pfn_valid_within(pfn))
582 continue;
583
584 page = pfn_to_page(pfn);
585
Joonsoo Kim9d43f5a2016-05-19 17:12:13 -0700586 if (page_zone(page) != zone)
587 continue;
588
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800589 /*
Vlastimil Babka10903022017-09-06 16:20:51 -0700590 * To avoid having to grab zone->lock, be a little
591 * careful when reading buddy page order. The only
592 * danger is that we skip too much and potentially miss
593 * some early allocated pages, which is better than
594 * heavy lock contention.
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800595 */
596 if (PageBuddy(page)) {
Matthew Wilcox (Oracle)ab130f912020-10-15 20:10:15 -0700597 unsigned long order = buddy_order_unsafe(page);
Vlastimil Babka10903022017-09-06 16:20:51 -0700598
599 if (order > 0 && order < MAX_ORDER)
600 pfn += (1UL << order) - 1;
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800601 continue;
602 }
603
604 if (PageReserved(page))
605 continue;
606
607 page_ext = lookup_page_ext(page);
Yang Shif86e4272016-06-03 14:55:38 -0700608 if (unlikely(!page_ext))
609 continue;
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800610
Vlastimil Babkadab4ead2017-09-06 16:20:44 -0700611 /* Maybe overlapping zone */
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800612 if (test_bit(PAGE_EXT_OWNER, &page_ext->flags))
613 continue;
614
615 /* Found early allocated page */
Vlastimil Babka7e2f2a02019-09-23 15:34:36 -0700616 __set_page_owner_handle(page, page_ext, early_handle,
617 0, 0);
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800618 count++;
619 }
Vlastimil Babka10903022017-09-06 16:20:51 -0700620 cond_resched();
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800621 }
622
623 pr_info("Node %d, zone %8s: page owner found early allocated %lu pages\n",
624 pgdat->node_id, zone->name, count);
625}
626
627static void init_zones_in_node(pg_data_t *pgdat)
628{
629 struct zone *zone;
630 struct zone *node_zones = pgdat->node_zones;
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800631
632 for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
633 if (!populated_zone(zone))
634 continue;
635
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800636 init_pages_in_zone(pgdat, zone);
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800637 }
638}
639
640static void init_early_allocated_pages(void)
641{
642 pg_data_t *pgdat;
643
Joonsoo Kim61cf5fe2014-12-12 16:56:04 -0800644 for_each_online_pgdat(pgdat)
645 init_zones_in_node(pgdat);
646}
647
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800648static const struct file_operations proc_page_owner_operations = {
649 .read = read_page_owner,
650};
651
652static int __init pageowner_init(void)
653{
Vlastimil Babka7dd80b82016-03-15 14:56:12 -0700654 if (!static_branch_unlikely(&page_owner_inited)) {
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800655 pr_info("page_owner is disabled\n");
656 return 0;
657 }
658
Greg Kroah-Hartmand9f79792019-03-05 15:46:09 -0800659 debugfs_create_file("page_owner", 0400, NULL, NULL,
660 &proc_page_owner_operations);
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800661
Greg Kroah-Hartmand9f79792019-03-05 15:46:09 -0800662 return 0;
Joonsoo Kim48c96a32014-12-12 16:56:01 -0800663}
Paul Gortmaker44c5af92015-05-01 21:57:34 -0400664late_initcall(pageowner_init)