diff options
author | Suren Baghdasaryan <surenb@google.com> | 2023-04-10 20:17:52 +0000 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-08-14 12:28:44 -0400 |
commit | fecd3fa3d1518f4e941be31ed5fd4662e7dd5146 (patch) | |
tree | 6377ed16d018ddc00233a3ca65f50b612db8ccb9 | |
parent | 43d7ecf0f764bf6cfeda17666a36899a560ccdfc (diff) |
lib: add memory allocations report in show_mem()
Include allocations in show_mem reports.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
-rw-r--r-- | include/linux/alloc_tag.h | 2 | ||||
-rw-r--r-- | lib/alloc_tag.c | 40 | ||||
-rw-r--r-- | mm/show_mem.c | 14 |
3 files changed, 56 insertions, 0 deletions
diff --git a/include/linux/alloc_tag.h b/include/linux/alloc_tag.h index 424df355008b..88073ebff268 100644 --- a/include/linux/alloc_tag.h +++ b/include/linux/alloc_tag.h @@ -24,6 +24,8 @@ struct alloc_tag { #ifdef CONFIG_MEM_ALLOC_PROFILING +void alloc_tags_show_mem_report(struct seq_buf *s); + static inline struct alloc_tag *ct_to_alloc_tag(struct codetag *ct) { return container_of(ct, struct alloc_tag, ct); diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c index 3be0c95842fe..63af296a5a87 100644 --- a/lib/alloc_tag.c +++ b/lib/alloc_tag.c @@ -5,6 +5,7 @@ #include <linux/module.h> #include <linux/page_ext.h> #include <linux/proc_fs.h> +#include <linux/seq_buf.h> #include <linux/seq_file.h> static struct codetag_type *alloc_tag_cttype; @@ -83,6 +84,45 @@ static const struct seq_operations allocinfo_seq_op = { .show = allocinfo_show, }; +void alloc_tags_show_mem_report(struct seq_buf *s) +{ + struct codetag_iterator iter; + struct codetag *ct; + struct { + struct codetag *tag; + size_t bytes; + } tags[10], n; + unsigned int i, nr = 0; + char buf[1024]; + + codetag_lock_module_list(alloc_tag_cttype, true); + iter = codetag_get_ct_iter(alloc_tag_cttype); + while ((ct = codetag_next_ct(&iter))) { + n.tag = ct; + n.bytes = alloc_tag_read(ct_to_alloc_tag(ct)); + + for (i = 0; i < nr; i++) + if (n.bytes > tags[i].bytes) + break; + + if (i < ARRAY_SIZE(tags)) { + nr -= nr == ARRAY_SIZE(tags); + memmove(&tags[i + 1], + &tags[i], + sizeof(tags[0]) * (nr - i)); + nr++; + tags[i] = n; + } + } + + for (i = 0; i < nr; i++) { + alloc_tag_to_text(buf, tags[i].tag); + seq_buf_printf(s, "%s\n", buf); + } + + codetag_lock_module_list(alloc_tag_cttype, false); +} + static void __init procfs_init(void) { proc_create_seq("allocinfo", 0444, NULL, &allocinfo_seq_op); diff --git a/mm/show_mem.c b/mm/show_mem.c index e7f05c87094a..de209c55d78a 100644 --- a/mm/show_mem.c +++ b/mm/show_mem.c @@ -57,4 +57,18 @@ void __show_mem(unsigned int filter, nodemask_t *nodemask, int max_zone_idx) kfree(buf); } +#ifdef CONFIG_MEM_ALLOC_PROFILING + { + struct seq_buf s; + char *buf = kmalloc(4096, GFP_ATOMIC); + + if (buf) { + printk("Memory allocations:\n"); + seq_buf_init(&s, buf, 4096); + alloc_tags_show_mem_report(&s); + printk("%s", buf); + kfree(buf); + } + } +#endif } |