Commit a38568a0 authored by Suren Baghdasaryan's avatar Suren Baghdasaryan Committed by Andrew Morton

lib: add version into /proc/allocinfo output

Add version string and a header at the beginning of /proc/allocinfo to
allow later format changes.  Example output:

> head /proc/allocinfo
allocinfo - version: 1.0
#     <size>  <calls> <tag info>
           0        0 init/main.c:1314 func:do_initcalls
           0        0 init/do_mounts.c:353 func:mount_nodev_root
           0        0 init/do_mounts.c:187 func:mount_root_generic
           0        0 init/do_mounts.c:158 func:do_mount_root
           0        0 init/initramfs.c:493 func:unpack_to_rootfs
           0        0 init/initramfs.c:492 func:unpack_to_rootfs
           0        0 init/initramfs.c:491 func:unpack_to_rootfs
         512        1 arch/x86/events/rapl.c:681 func:init_rapl_pmus
         128        1 arch/x86/events/rapl.c:571 func:rapl_cpu_online

[akpm@linux-foundation.org: remove stray newline from struct allocinfo_private]
Link: https://lkml.kernel.org/r/20240514163128.3662251-1-surenb@google.comSigned-off-by: default avatarSuren Baghdasaryan <surenb@google.com>
Reviewed-by: default avatarPasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Cc: Kent Overstreet <kent.overstreet@linux.dev>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 8e0545c8
...@@ -961,13 +961,14 @@ Provides information about memory allocations at all locations in the code ...@@ -961,13 +961,14 @@ Provides information about memory allocations at all locations in the code
base. Each allocation in the code is identified by its source file, line base. Each allocation in the code is identified by its source file, line
number, module (if originates from a loadable module) and the function calling number, module (if originates from a loadable module) and the function calling
the allocation. The number of bytes allocated and number of calls at each the allocation. The number of bytes allocated and number of calls at each
location are reported. location are reported. The first line indicates the version of the file, the
second line is the header listing fields in the file.
Example output. Example output.
:: ::
> sort -rn /proc/allocinfo > tail -n +3 /proc/allocinfo | sort -rn
127664128 31168 mm/page_ext.c:270 func:alloc_page_ext 127664128 31168 mm/page_ext.c:270 func:alloc_page_ext
56373248 4737 mm/slub.c:2259 func:alloc_slab_page 56373248 4737 mm/slub.c:2259 func:alloc_slab_page
14880768 3633 mm/readahead.c:247 func:page_cache_ra_unbounded 14880768 3633 mm/readahead.c:247 func:page_cache_ra_unbounded
......
...@@ -16,47 +16,60 @@ EXPORT_SYMBOL(_shared_alloc_tag); ...@@ -16,47 +16,60 @@ EXPORT_SYMBOL(_shared_alloc_tag);
DEFINE_STATIC_KEY_MAYBE(CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT, DEFINE_STATIC_KEY_MAYBE(CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT,
mem_alloc_profiling_key); mem_alloc_profiling_key);
struct allocinfo_private {
struct codetag_iterator iter;
bool print_header;
};
static void *allocinfo_start(struct seq_file *m, loff_t *pos) static void *allocinfo_start(struct seq_file *m, loff_t *pos)
{ {
struct codetag_iterator *iter; struct allocinfo_private *priv;
struct codetag *ct; struct codetag *ct;
loff_t node = *pos; loff_t node = *pos;
iter = kzalloc(sizeof(*iter), GFP_KERNEL); priv = kzalloc(sizeof(*priv), GFP_KERNEL);
m->private = iter; m->private = priv;
if (!iter) if (!priv)
return NULL; return NULL;
priv->print_header = (node == 0);
codetag_lock_module_list(alloc_tag_cttype, true); codetag_lock_module_list(alloc_tag_cttype, true);
*iter = codetag_get_ct_iter(alloc_tag_cttype); priv->iter = codetag_get_ct_iter(alloc_tag_cttype);
while ((ct = codetag_next_ct(iter)) != NULL && node) while ((ct = codetag_next_ct(&priv->iter)) != NULL && node)
node--; node--;
return ct ? iter : NULL; return ct ? priv : NULL;
} }
static void *allocinfo_next(struct seq_file *m, void *arg, loff_t *pos) static void *allocinfo_next(struct seq_file *m, void *arg, loff_t *pos)
{ {
struct codetag_iterator *iter = (struct codetag_iterator *)arg; struct allocinfo_private *priv = (struct allocinfo_private *)arg;
struct codetag *ct = codetag_next_ct(iter); struct codetag *ct = codetag_next_ct(&priv->iter);
(*pos)++; (*pos)++;
if (!ct) if (!ct)
return NULL; return NULL;
return iter; return priv;
} }
static void allocinfo_stop(struct seq_file *m, void *arg) static void allocinfo_stop(struct seq_file *m, void *arg)
{ {
struct codetag_iterator *iter = (struct codetag_iterator *)m->private; struct allocinfo_private *priv = (struct allocinfo_private *)m->private;
if (iter) { if (priv) {
codetag_lock_module_list(alloc_tag_cttype, false); codetag_lock_module_list(alloc_tag_cttype, false);
kfree(iter); kfree(priv);
} }
} }
static void print_allocinfo_header(struct seq_buf *buf)
{
/* Output format version, so we can change it. */
seq_buf_printf(buf, "allocinfo - version: 1.0\n");
seq_buf_printf(buf, "# <size> <calls> <tag info>\n");
}
static void alloc_tag_to_text(struct seq_buf *out, struct codetag *ct) static void alloc_tag_to_text(struct seq_buf *out, struct codetag *ct)
{ {
struct alloc_tag *tag = ct_to_alloc_tag(ct); struct alloc_tag *tag = ct_to_alloc_tag(ct);
...@@ -71,13 +84,17 @@ static void alloc_tag_to_text(struct seq_buf *out, struct codetag *ct) ...@@ -71,13 +84,17 @@ static void alloc_tag_to_text(struct seq_buf *out, struct codetag *ct)
static int allocinfo_show(struct seq_file *m, void *arg) static int allocinfo_show(struct seq_file *m, void *arg)
{ {
struct codetag_iterator *iter = (struct codetag_iterator *)arg; struct allocinfo_private *priv = (struct allocinfo_private *)arg;
char *bufp; char *bufp;
size_t n = seq_get_buf(m, &bufp); size_t n = seq_get_buf(m, &bufp);
struct seq_buf buf; struct seq_buf buf;
seq_buf_init(&buf, bufp, n); seq_buf_init(&buf, bufp, n);
alloc_tag_to_text(&buf, iter->ct); if (priv->print_header) {
print_allocinfo_header(&buf);
priv->print_header = false;
}
alloc_tag_to_text(&buf, priv->iter.ct);
seq_commit(m, seq_buf_used(&buf)); seq_commit(m, seq_buf_used(&buf));
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment