xref: /linux/Documentation/mm/page_owner.rst (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1==================================================
2page owner: Tracking about who allocated each page
3==================================================
4
5Introduction
6============
7
8page owner is for the tracking about who allocated each page.
9It can be used to debug memory leak or to find a memory hogger.
10When allocation happens, information about allocation such as call stack
11and order of pages is stored into certain storage for each page.
12When we need to know about status of all pages, we can get and analyze
13this information.
14
15Although we already have tracepoint for tracing page allocation/free,
16using it for analyzing who allocate each page is rather complex. We need
17to enlarge the trace buffer for preventing overlapping until userspace
18program launched. And, launched program continually dump out the trace
19buffer for later analysis and it would change system behaviour with more
20possibility rather than just keeping it in memory, so bad for debugging.
21
22page owner can also be used for various purposes. For example, accurate
23fragmentation statistics can be obtained through gfp flag information of
24each page. It is already implemented and activated if page owner is
25enabled. Other usages are more than welcome.
26
27It can also be used to show all the stacks and their current number of
28allocated base pages, which gives us a quick overview of where the memory
29is going without the need to screen through all the pages and match the
30allocation and free operation. It's also possible to show only a numeric
31identifier of all the stacks (without stack traces) and their number of
32allocated base pages (faster to read and parse, eg, for monitoring) that
33can be matched with stacks later (show_handles and show_stacks_handles).
34
35page owner is disabled by default. So, if you'd like to use it, you need
36to add "page_owner=on" to your boot cmdline. If the kernel is built
37with page owner and page owner is disabled in runtime due to not enabling
38boot option, runtime overhead is marginal. If disabled in runtime, it
39doesn't require memory to store owner information, so there is no runtime
40memory overhead. And, page owner inserts just two unlikely branches into
41the page allocator hotpath and if not enabled, then allocation is done
42like as the kernel without page owner. These two unlikely branches should
43not affect to allocation performance, especially if the static keys jump
44label patching functionality is available. Following is the kernel's code
45size change due to this facility.
46
47Although enabling page owner increases kernel size by several kilobytes,
48most of this code is outside page allocator and its hot path. Building
49the kernel with page owner and turning it on if needed would be great
50option to debug kernel memory problem.
51
52There is one notice that is caused by implementation detail. page owner
53stores information into the memory from struct page extension. This memory
54is initialized some time later than that page allocator starts in sparse
55memory system, so, until initialization, many pages can be allocated and
56they would have no owner information. To fix it up, these early allocated
57pages are investigated and marked as allocated in initialization phase.
58Although it doesn't mean that they have the right owner information,
59at least, we can tell whether the page is allocated or not,
60more accurately. On 2GB memory x86-64 VM box, 13343 early allocated pages
61are caught and marked, although they are mostly allocated from struct
62page extension feature. Anyway, after that, no page is left in
63un-tracking state.
64
65Usage
66=====
67
681) Build user-space helpers:
69::
70
71   To filter page_owner output:
72
73	cd tools/mm
74	make page_owner_filter
75
76   To sort and analyze page_owner output:
77
78	cd tools/mm
79	make page_owner_sort
80
812) Enable page owner: add "page_owner=on" to boot cmdline.
82
833) Do the job that you want to debug.
84
854) (Optional) Filter page_owner output::
86
87	./page_owner_filter -m handle -n 0,1,2 > filtered_page_owner.txt
88
895) Analyze information from page owner::
90
91	cat /sys/kernel/debug/page_owner_stacks/show_stacks > stacks.txt
92	cat stacks.txt
93	 post_alloc_hook+0x177/0x1a0
94	 get_page_from_freelist+0xd01/0xd80
95	 __alloc_pages+0x39e/0x7e0
96	 allocate_slab+0xbc/0x3f0
97	 ___slab_alloc+0x528/0x8a0
98	 kmem_cache_alloc+0x224/0x3b0
99	 sk_prot_alloc+0x58/0x1a0
100	 sk_alloc+0x32/0x4f0
101	 inet_create+0x427/0xb50
102	 __sock_create+0x2e4/0x650
103	 inet_ctl_sock_create+0x30/0x180
104	 igmp_net_init+0xc1/0x130
105	 ops_init+0x167/0x410
106	 setup_net+0x304/0xa60
107	 copy_net_ns+0x29b/0x4a0
108	 create_new_namespaces+0x4a1/0x820
109	nr_base_pages: 16
110	...
111	...
112	echo 7000 > /sys/kernel/debug/page_owner_stacks/count_threshold
113	cat /sys/kernel/debug/page_owner_stacks/show_stacks> stacks_7000.txt
114	cat stacks_7000.txt
115	 post_alloc_hook+0x177/0x1a0
116	 get_page_from_freelist+0xd01/0xd80
117	 __alloc_pages+0x39e/0x7e0
118	 alloc_pages_mpol+0x22e/0x490
119	 folio_alloc+0xd5/0x110
120	 filemap_alloc_folio+0x78/0x230
121	 page_cache_ra_order+0x287/0x6f0
122	 filemap_get_pages+0x517/0x1160
123	 filemap_read+0x304/0x9f0
124	 xfs_file_buffered_read+0xe6/0x1d0 [xfs]
125	 xfs_file_read_iter+0x1f0/0x380 [xfs]
126	 __kernel_read+0x3b9/0x730
127	 kernel_read_file+0x309/0x4d0
128	 __do_sys_finit_module+0x381/0x730
129	 do_syscall_64+0x8d/0x150
130	 entry_SYSCALL_64_after_hwframe+0x62/0x6a
131	nr_base_pages: 20824
132	...
133
134	cat /sys/kernel/debug/page_owner_stacks/show_handles > handles_7000.txt
135	cat handles_7000.txt
136	handle: 42
137	nr_base_pages: 20824
138	...
139
140	cat /sys/kernel/debug/page_owner_stacks/show_stacks_handles > stacks_handles.txt
141	cat stacks_handles.txt
142	 post_alloc_hook+0x177/0x1a0
143	 get_page_from_freelist+0xd01/0xd80
144	 __alloc_pages+0x39e/0x7e0
145	 alloc_pages_mpol+0x22e/0x490
146	 folio_alloc+0xd5/0x110
147	 filemap_alloc_folio+0x78/0x230
148	 page_cache_ra_order+0x287/0x6f0
149	 filemap_get_pages+0x517/0x1160
150	 filemap_read+0x304/0x9f0
151	 xfs_file_buffered_read+0xe6/0x1d0 [xfs]
152	 xfs_file_read_iter+0x1f0/0x380 [xfs]
153	 __kernel_read+0x3b9/0x730
154	 kernel_read_file+0x309/0x4d0
155	 __do_sys_finit_module+0x381/0x730
156	 do_syscall_64+0x8d/0x150
157	 entry_SYSCALL_64_after_hwframe+0x62/0x6a
158	handle: 42
159	...
160
161	cat /sys/kernel/debug/page_owner > page_owner_full.txt
162	./page_owner_sort page_owner_full.txt sorted_page_owner.txt
163
164   The general output of ``page_owner_full.txt`` is as follows::
165
166	Page allocated via order XXX, ...
167	PFN XXX ...
168	// Detailed stack
169
170	Page allocated via order XXX, ...
171	PFN XXX ...
172	// Detailed stack
173    By default, it will do full pfn dump, to start with a given pfn,
174    page_owner supports fseek.
175
176    FILE *fp = fopen("/sys/kernel/debug/page_owner", "r");
177    fseek(fp, pfn_start, SEEK_SET);
178
179   The ``page_owner_sort`` tool ignores ``PFN`` rows, puts the remaining rows
180   in buf, uses regexp to extract the page order value, counts the times
181   and pages of buf, and finally sorts them according to the parameter(s).
182
183   See the result about who allocated each page
184   in the ``sorted_page_owner.txt``. General output::
185
186	XXX times, XXX pages:
187	Page allocated via order XXX, ...
188	// Detailed stack
189
190   By default, ``page_owner_sort`` is sorted according to the times of buf.
191   If you want to sort by the page nums of buf, use the ``-m`` parameter.
192   The detailed parameters are:
193
194   fundamental function::
195
196	Sort:
197		-a		Sort by memory allocation time.
198		-m		Sort by total memory.
199		-p		Sort by pid.
200		-P		Sort by tgid.
201		-n		Sort by task command name.
202		-r		Sort by memory release time.
203		-s		Sort by stack trace.
204		-t		Sort by times (default).
205		--sort <order>	Specify sorting order.  Sorting syntax is [+|-]key[,[+|-]key[,...]].
206				Choose a key from the **STANDARD FORMAT SPECIFIERS** section. The "+" is
207				optional since default direction is increasing numerical or lexicographic
208				order. Mixed use of abbreviated and complete-form of keys is allowed.
209
210		Examples:
211				./page_owner_sort <input> <output> --sort=n,+pid,-tgid
212				./page_owner_sort <input> <output> --sort=at
213
214   additional function::
215
216	Cull:
217		--cull <rules>
218				Specify culling rules.Culling syntax is key[,key[,...]].Choose a
219				multi-letter key from the **STANDARD FORMAT SPECIFIERS** section.
220
221		<rules> is a single argument in the form of a comma-separated list,
222		which offers a way to specify individual culling rules.  The recognized
223		keywords are described in the **STANDARD FORMAT SPECIFIERS** section below.
224		<rules> can be specified by the sequence of keys k1,k2, ..., as described in
225		the STANDARD SORT KEYS section below. Mixed use of abbreviated and
226		complete-form of keys is allowed.
227
228		Examples:
229				./page_owner_sort <input> <output> --cull=stacktrace
230				./page_owner_sort <input> <output> --cull=st,pid,name
231				./page_owner_sort <input> <output> --cull=n,f
232
233	Filter:
234		-f		Filter out the information of blocks whose memory has been released.
235
236	Select:
237		--pid <pidlist>		Select by pid. This selects the blocks whose process ID
238					numbers appear in <pidlist>.
239		--tgid <tgidlist>	Select by tgid. This selects the blocks whose thread
240					group ID numbers appear in <tgidlist>.
241		--name <cmdlist>	Select by task command name. This selects the blocks whose
242					task command name appear in <cmdlist>.
243
244		<pidlist>, <tgidlist>, <cmdlist> are single arguments in the form of a comma-separated list,
245		which offers a way to specify individual selecting rules.
246
247
248		Examples:
249				./page_owner_sort <input> <output> --pid=1
250				./page_owner_sort <input> <output> --tgid=1,2,3
251				./page_owner_sort <input> <output> --name name1,name2
252
253STANDARD FORMAT SPECIFIERS
254==========================
255::
256
257  For --sort option:
258
259	KEY		LONG		DESCRIPTION
260	p		pid		process ID
261	tg		tgid		thread group ID
262	n		name		task command name
263	st		stacktrace	stack trace of the page allocation
264	T		txt		full text of block
265	ft		free_ts		timestamp of the page when it was released
266	at		alloc_ts	timestamp of the page when it was allocated
267	ator		allocator	memory allocator for pages
268
269  For --cull option:
270
271	KEY		LONG		DESCRIPTION
272	p		pid		process ID
273	tg		tgid		thread group ID
274	n		name		task command name
275	f		free		whether the page has been released or not
276	st		stacktrace	stack trace of the page allocation
277	ator		allocator	memory allocator for pages
278
279Filtering page_owner output
280============================
281
282page_owner supports filtering output at the kernel level before reading,
283which reduces the amount of data that needs to be processed in userspace.
284
285The page_owner_filter tool provides a convenient interface for this filtering
286capability. It supports two types of filters:
287
2881. **print_mode filter**: Control what information is printed for each page
289	- ``stack``: Print full stack traces (default, compatible with existing usage)
290	- ``handle``: Print only stack handle numbers (much faster, smaller output)
291	- ``stack_handle``: Print both stack traces and handle numbers
292
293	The ``handle`` mode uses numeric identifiers instead of full stack traces.
294	The mapping from handles to actual stack traces can be obtained via the
295	show_stacks_handles interface.
296
2972. **NUMA node filter**: Filter pages by NUMA node ID
298	- Supports single node: ``-n 0``
299	- Multiple nodes: ``-n 0,1,2``
300	- Ranges: ``-n 0-3``
301	- Mixed format: ``-n 0,2-3,5``
302
303Usage examples::
304
305	# Filter by print mode
306	./page_owner_filter -m handle
307	./page_owner_filter -m stack_handle
308
309	# Filter by NUMA node
310	./page_owner_filter -n 0
311	./page_owner_filter -n 0-3
312
313	# Combined filters
314	./page_owner_filter -m stack -n 0,1,2
315	./page_owner_filter -m handle -n 0,2-3
316
317	# Save to file
318	./page_owner_filter -m handle -o filtered_output.txt
319
320The handle mode is particularly useful for monitoring and performance-critical
321scenarios as it dramatically reduces output size. Testing shows handle mode can
322reduce output size by ~66% (84MB vs 244MB) and improve read performance by ~4.4x
323compared to full stack output.
324
325The NUMA node filter is useful for NUMA-aware memory allocation analysis and debugging.
326
327Behind the scenes, page_owner_filter opens /sys/kernel/debug/page_owner and
328writes filter commands before reading the filtered output. The filtering uses
329per-file-descriptor state, allowing each open() to have independent filter settings.
330
331Each file descriptor maintains its own filter state, so you can have multiple
332independent filtering operations running concurrently. For example, in different
333terminals you can run different filters simultaneously::
334
335	# Terminal 1: Filter node 0
336	./page_owner_filter -n 0 > node0_output.txt
337
338	# Terminal 2: Filter node 1 (runs concurrently)
339	./page_owner_filter -n 1 > node1_output.txt
340