The quilt patch titled Subject: mm, page_owner: add page_owner_stacks file to print out only stacks and their counts has been removed from the -mm tree. Its filename was mm-page_owner-add-page_owner_stacks-file-to-print-out-only-stacks-and-their-counte.patch This patch was dropped because an updated version will be merged ------------------------------------------------------ From: Oscar Salvador <osalvador@xxxxxxx> Subject: mm, page_owner: add page_owner_stacks file to print out only stacks and their counts Date: Tue, 16 May 2023 20:25:36 +0200 We might be only interested in knowing about stacks <-> count relationship, so instead of having to fiddle with page_owner output and screen through pfns, let us add a new file called 'page_owner_stacks' that does just that. By cating such file, we will get all the stacktraces followed by its counter, so we can have a more global view. [akpm@xxxxxxxxxxxxxxxxxxxx: build fix] [akpm@xxxxxxxxxxxxxxxxxxxx: suppress smatch "if (unsigned < 0)" warning] Link: https://lkml.kernel.org/r/20230516182537.3139-3-osalvador@xxxxxxx Signed-off-by: Oscar Salvador <osalvador@xxxxxxx> Cc: Alexander Potapenko <glider@xxxxxxxxxx> Cc: Andrey Konovalov <andreyknvl@xxxxxxxxx> Cc: Eric Dumazet <edumazet@xxxxxxxxxx> Cc: Marco Elver <elver@xxxxxxxxxx> Cc: Michal Hocko <mhocko@xxxxxxxx> Cc: Suren Baghdasaryan <surenb@xxxxxxxxxx> Cc: Vlastimil Babka <vbabka@xxxxxxx> Cc: Waiman Long <longman@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- include/linux/stackdepot.h | 7 +++ lib/stackdepot.c | 71 +++++++++++++++++++++++++++++++++++ mm/page_owner.c | 27 +++++++++++++ 3 files changed, 105 insertions(+) --- a/include/linux/stackdepot.h~mm-page_owner-add-page_owner_stacks-file-to-print-out-only-stacks-and-their-counte +++ a/include/linux/stackdepot.h @@ -25,6 +25,7 @@ #include <linux/gfp.h> typedef u32 depot_stack_handle_t; +struct seq_file; /* * Number of bits in the handle that stack depot doesn't use. Users may store @@ -112,6 +113,12 @@ void stack_depot_dec_count(depot_stack_h depot_stack_handle_t stack_depot_save(unsigned long *entries, unsigned int nr_entries, gfp_t gfp_flags); +#ifdef CONFIG_PAGE_OWNER +void *stack_start(struct seq_file *m, loff_t *ppos); +void *stack_next(struct seq_file *m, void *v, loff_t *ppos); +int stack_print(struct seq_file *m, void *v); +#endif + /** * stack_depot_fetch - Fetch a stack trace from stack depot * --- a/lib/stackdepot.c~mm-page_owner-add-page_owner_stacks-file-to-print-out-only-stacks-and-their-counte +++ a/lib/stackdepot.c @@ -29,6 +29,7 @@ #include <linux/types.h> #include <linux/memblock.h> #include <linux/kasan-enabled.h> +#include <linux/seq_file.h> #define DEPOT_HANDLE_BITS (sizeof(depot_stack_handle_t) * 8) @@ -486,6 +487,76 @@ static struct stack_record *stack_depot_ return stack; } +#ifdef CONFIG_PAGE_OWNER +void *stack_start(struct seq_file *m, loff_t *ppos) +{ + unsigned long *table = m->private; + struct stack_record **stacks, *stack; + + /* First time */ + if (*ppos == 0) + *table = 0; + + if (*ppos == -1UL) + return NULL; + + stacks = &stack_table[*table]; + stack = (struct stack_record *)stacks; + + return stack; +} + +void *stack_next(struct seq_file *m, void *v, loff_t *ppos) +{ + unsigned long *table = m->private; + unsigned long nr_table = *table; + struct stack_record *next = NULL, *stack = v, **stacks; + unsigned long stack_table_entries = stack_hash_mask + 1; + + if (!stack) { +new_table: + /* New table */ + nr_table++; + if (nr_table >= stack_table_entries) + goto out; + stacks = &stack_table[nr_table]; + stack = (struct stack_record *)stacks; + next = stack; + } else { + next = stack->next; + } + + if (!next) + goto new_table; + +out: + *table = nr_table; + *ppos = (nr_table >= stack_table_entries) ? -1UL : *ppos + 1; + return next; +} + +int stack_print(struct seq_file *m, void *v) +{ + char *buf; + int ret = 0; + struct stack_record *stack = v; + + if (stack->size <= 0 || stack->size > PAGE_SIZE || + stack->handle.valid != 1 || refcount_read(&stack->count) < 1) + return 0; + + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + ret += stack_trace_snprint(buf, PAGE_SIZE, stack->entries, stack->size, 0); + scnprintf(buf + ret, PAGE_SIZE - ret, "stack count: %d\n\n", + refcount_read(&stack->count)); + seq_printf(m, buf); + seq_puts(m, "\n\n"); + kfree(buf); + + return 0; +} +#endif + unsigned int stack_depot_fetch(depot_stack_handle_t handle, unsigned long **entries) { --- a/mm/page_owner.c~mm-page_owner-add-page_owner_stacks-file-to-print-out-only-stacks-and-their-counte +++ a/mm/page_owner.c @@ -719,6 +719,30 @@ static const struct file_operations proc .llseek = lseek_page_owner, }; +static void stack_stop(struct seq_file *m, void *v) +{ +} + +static const struct seq_operations page_owner_stack_op = { + .start = stack_start, + .next = stack_next, + .stop = stack_stop, + .show = stack_print +}; + +static int page_owner_stack_open(struct inode *inode, struct file *file) +{ + return seq_open_private(file, &page_owner_stack_op, + sizeof(unsigned long)); +} + +const struct file_operations page_owner_stack_operations = { + .open = page_owner_stack_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + static int __init pageowner_init(void) { if (!static_branch_unlikely(&page_owner_inited)) { @@ -729,6 +753,9 @@ static int __init pageowner_init(void) debugfs_create_file("page_owner", 0400, NULL, NULL, &proc_page_owner_operations); + debugfs_create_file("page_owner_stacks", 0400, NULL, NULL, + &page_owner_stack_operations); + return 0; } late_initcall(pageowner_init) _ Patches currently in -mm which might be from osalvador@xxxxxxx are mmpage_owner-filter-out-stacks-by-a-threshold-counter.patch