mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-28 16:53:49 +00:00
4835f747d3
Implement support for storing page allocation tag references directly in the page flags instead of page extensions. sysctl.vm.mem_profiling boot parameter it extended to provide a way for a user to request this mode. Enabling compression eliminates memory overhead caused by page_ext and results in better performance for page allocations. However this mode will not work if the number of available page flag bits is insufficient to address all kernel allocations. Such condition can happen during boot or when loading a module. If this condition is detected, memory allocation profiling gets disabled with an appropriate warning. By default compression mode is disabled. Link: https://lkml.kernel.org/r/20241023170759.999909-7-surenb@google.com Signed-off-by: Suren Baghdasaryan <surenb@google.com> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com> Cc: Ard Biesheuvel <ardb@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Borislav Petkov (AMD) <bp@alien8.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: Daniel Gomez <da.gomez@samsung.com> Cc: David Hildenbrand <david@redhat.com> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: David Rientjes <rientjes@google.com> Cc: Dennis Zhou <dennis@kernel.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: John Hubbard <jhubbard@nvidia.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Kalesh Singh <kaleshsingh@google.com> Cc: Kees Cook <keescook@chromium.org> Cc: Kent Overstreet <kent.overstreet@linux.dev> Cc: Liam R. Howlett <Liam.Howlett@Oracle.com> Cc: Luis Chamberlain <mcgrof@kernel.org> Cc: Matthew Wilcox <willy@infradead.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Minchan Kim <minchan@google.com> Cc: Paul E. McKenney <paulmck@kernel.org> Cc: Petr Pavlu <petr.pavlu@suse.com> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Sami Tolvanen <samitolvanen@google.com> Cc: Sourav Panda <souravpanda@google.com> Cc: Steven Rostedt (Google) <rostedt@goodmis.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Thomas Huth <thuth@redhat.com> Cc: Uladzislau Rezki (Sony) <urezki@gmail.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Xiongwei Song <xiongwei.song@windriver.com> Cc: Yu Zhao <yuzhao@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
105 lines
4.2 KiB
ReStructuredText
105 lines
4.2 KiB
ReStructuredText
.. SPDX-License-Identifier: GPL-2.0
|
|
|
|
===========================
|
|
MEMORY ALLOCATION PROFILING
|
|
===========================
|
|
|
|
Low overhead (suitable for production) accounting of all memory allocations,
|
|
tracked by file and line number.
|
|
|
|
Usage:
|
|
kconfig options:
|
|
- CONFIG_MEM_ALLOC_PROFILING
|
|
|
|
- CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT
|
|
|
|
- CONFIG_MEM_ALLOC_PROFILING_DEBUG
|
|
adds warnings for allocations that weren't accounted because of a
|
|
missing annotation
|
|
|
|
Boot parameter:
|
|
sysctl.vm.mem_profiling={0|1|never}[,compressed]
|
|
|
|
When set to "never", memory allocation profiling overhead is minimized and it
|
|
cannot be enabled at runtime (sysctl becomes read-only).
|
|
When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=y, default value is "1".
|
|
When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=n, default value is "never".
|
|
"compressed" optional parameter will try to store page tag references in a
|
|
compact format, avoiding page extensions. This results in improved performance
|
|
and memory consumption, however it might fail depending on system configuration.
|
|
If compression fails, a warning is issued and memory allocation profiling gets
|
|
disabled.
|
|
|
|
sysctl:
|
|
/proc/sys/vm/mem_profiling
|
|
|
|
Runtime info:
|
|
/proc/allocinfo
|
|
|
|
Example output::
|
|
|
|
root@moria-kvm:~# sort -g /proc/allocinfo|tail|numfmt --to=iec
|
|
2.8M 22648 fs/kernfs/dir.c:615 func:__kernfs_new_node
|
|
3.8M 953 mm/memory.c:4214 func:alloc_anon_folio
|
|
4.0M 1010 drivers/staging/ctagmod/ctagmod.c:20 [ctagmod] func:ctagmod_start
|
|
4.1M 4 net/netfilter/nf_conntrack_core.c:2567 func:nf_ct_alloc_hashtable
|
|
6.0M 1532 mm/filemap.c:1919 func:__filemap_get_folio
|
|
8.8M 2785 kernel/fork.c:307 func:alloc_thread_stack_node
|
|
13M 234 block/blk-mq.c:3421 func:blk_mq_alloc_rqs
|
|
14M 3520 mm/mm_init.c:2530 func:alloc_large_system_hash
|
|
15M 3656 mm/readahead.c:247 func:page_cache_ra_unbounded
|
|
55M 4887 mm/slub.c:2259 func:alloc_slab_page
|
|
122M 31168 mm/page_ext.c:270 func:alloc_page_ext
|
|
|
|
Theory of operation
|
|
===================
|
|
|
|
Memory allocation profiling builds off of code tagging, which is a library for
|
|
declaring static structs (that typically describe a file and line number in
|
|
some way, hence code tagging) and then finding and operating on them at runtime,
|
|
- i.e. iterating over them to print them in debugfs/procfs.
|
|
|
|
To add accounting for an allocation call, we replace it with a macro
|
|
invocation, alloc_hooks(), that
|
|
- declares a code tag
|
|
- stashes a pointer to it in task_struct
|
|
- calls the real allocation function
|
|
- and finally, restores the task_struct alloc tag pointer to its previous value.
|
|
|
|
This allows for alloc_hooks() calls to be nested, with the most recent one
|
|
taking effect. This is important for allocations internal to the mm/ code that
|
|
do not properly belong to the outer allocation context and should be counted
|
|
separately: for example, slab object extension vectors, or when the slab
|
|
allocates pages from the page allocator.
|
|
|
|
Thus, proper usage requires determining which function in an allocation call
|
|
stack should be tagged. There are many helper functions that essentially wrap
|
|
e.g. kmalloc() and do a little more work, then are called in multiple places;
|
|
we'll generally want the accounting to happen in the callers of these helpers,
|
|
not in the helpers themselves.
|
|
|
|
To fix up a given helper, for example foo(), do the following:
|
|
- switch its allocation call to the _noprof() version, e.g. kmalloc_noprof()
|
|
|
|
- rename it to foo_noprof()
|
|
|
|
- define a macro version of foo() like so:
|
|
|
|
#define foo(...) alloc_hooks(foo_noprof(__VA_ARGS__))
|
|
|
|
It's also possible to stash a pointer to an alloc tag in your own data structures.
|
|
|
|
Do this when you're implementing a generic data structure that does allocations
|
|
"on behalf of" some other code - for example, the rhashtable code. This way,
|
|
instead of seeing a large line in /proc/allocinfo for rhashtable.c, we can
|
|
break it out by rhashtable type.
|
|
|
|
To do so:
|
|
- Hook your data structure's init function, like any other allocation function.
|
|
|
|
- Within your init function, use the convenience macro alloc_tag_record() to
|
|
record alloc tag in your data structure.
|
|
|
|
- Then, use the following form for your allocations:
|
|
alloc_hooks_tag(ht->your_saved_tag, kmalloc_noprof(...))
|