[v5,2/3] mm, page_owner: Add page_owner_stacks file to print out only stacks and their counte

Message ID 20230516182537.3139-3-osalvador@suse.de
State New
Headers
Series page_owner: print stacks and their counter |

Commit Message

Oscar Salvador May 16, 2023, 6:25 p.m. UTC
  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.

Signed-off-by: Oscar Salvador <osalvador@suse.de>
---
 include/linux/stackdepot.h |  6 ++++
 lib/stackdepot.c           | 72 ++++++++++++++++++++++++++++++++++++++
 mm/page_owner.c            | 27 ++++++++++++++
 3 files changed, 105 insertions(+)
  

Comments

kernel test robot May 17, 2023, 12:59 a.m. UTC | #1
Hi Oscar,

kernel test robot noticed the following build errors:

[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on linus/master v6.4-rc2 next-20230516]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Oscar-Salvador/lib-stackdepot-Add-a-refcount-field-in-stack_record/20230517-022632
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20230516182537.3139-3-osalvador%40suse.de
patch subject: [PATCH v5 2/3] mm, page_owner: Add page_owner_stacks file to print out only stacks and their counte
config: hexagon-randconfig-r041-20230515
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project b0fb98227c90adf2536c9ad644a74d5e92961111)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/8e924bbbd702591f6d8502cfac0bda27e1f67e1b
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Oscar-Salvador/lib-stackdepot-Add-a-refcount-field-in-stack_record/20230517-022632
        git checkout 8e924bbbd702591f6d8502cfac0bda27e1f67e1b
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash kernel/trace/ lib/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202305170804.ZRfW9CRd-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

   In file included from lib/buildid.c:7:
   In file included from include/linux/pagemap.h:8:
   In file included from include/linux/mm.h:22:
   In file included from include/linux/page_ext.h:7:
>> include/linux/stackdepot.h:116:26: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   void *stack_start(struct seq_file *m, loff_t *ppos);
                            ^
   include/linux/stackdepot.h:117:25: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   void *stack_next(struct seq_file *m, void *v, loff_t *ppos);
                           ^
   include/linux/stackdepot.h:118:24: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   int stack_print(struct seq_file *m, void *v);
                          ^
   In file included from lib/buildid.c:7:
   In file included from include/linux/pagemap.h:11:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __raw_readb(PCI_IOBASE + addr);
                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from lib/buildid.c:7:
   In file included from include/linux/pagemap.h:11:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from lib/buildid.c:7:
   In file included from include/linux/pagemap.h:11:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writeb(value, PCI_IOBASE + addr);
                               ~~~~~~~~~~ ^
   include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   9 warnings generated.
--
   In file included from lib/show_mem.c:8:
   In file included from include/linux/mm.h:22:
   In file included from include/linux/page_ext.h:7:
>> include/linux/stackdepot.h:116:26: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   void *stack_start(struct seq_file *m, loff_t *ppos);
                            ^
   include/linux/stackdepot.h:117:25: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   void *stack_next(struct seq_file *m, void *v, loff_t *ppos);
                           ^
   include/linux/stackdepot.h:118:24: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   int stack_print(struct seq_file *m, void *v);
                          ^
   3 warnings generated.
--
   In file included from lib/stackdepot.c:21:
   In file included from include/linux/mm.h:22:
   In file included from include/linux/page_ext.h:7:
>> include/linux/stackdepot.h:116:26: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   void *stack_start(struct seq_file *m, loff_t *ppos);
                            ^
   include/linux/stackdepot.h:117:25: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   void *stack_next(struct seq_file *m, void *v, loff_t *ppos);
                           ^
   include/linux/stackdepot.h:118:24: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   int stack_print(struct seq_file *m, void *v);
                          ^
   In file included from lib/stackdepot.c:30:
   In file included from include/linux/memblock.h:13:
   In file included from arch/hexagon/include/asm/dma.h:9:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __raw_readb(PCI_IOBASE + addr);
                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from lib/stackdepot.c:30:
   In file included from include/linux/memblock.h:13:
   In file included from arch/hexagon/include/asm/dma.h:9:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from lib/stackdepot.c:30:
   In file included from include/linux/memblock.h:13:
   In file included from arch/hexagon/include/asm/dma.h:9:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writeb(value, PCI_IOBASE + addr);
                               ~~~~~~~~~~ ^
   include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
>> lib/stackdepot.c:491:7: error: conflicting types for 'stack_start'
   void *stack_start(struct seq_file *m, loff_t *ppos)
         ^
   include/linux/stackdepot.h:116:7: note: previous declaration is here
   void *stack_start(struct seq_file *m, loff_t *ppos);
         ^
>> lib/stackdepot.c:509:7: error: conflicting types for 'stack_next'
   void *stack_next(struct seq_file *m, void *v, loff_t *ppos)
         ^
   include/linux/stackdepot.h:117:7: note: previous declaration is here
   void *stack_next(struct seq_file *m, void *v, loff_t *ppos);
         ^
>> lib/stackdepot.c:538:5: error: conflicting types for 'stack_print'
   int stack_print(struct seq_file *m, void *v)
       ^
   include/linux/stackdepot.h:118:5: note: previous declaration is here
   int stack_print(struct seq_file *m, void *v);
       ^
   9 warnings and 3 errors generated.
--
   In file included from kernel/trace/trace_irqsoff.c:13:
   In file included from include/linux/kallsyms.h:13:
   In file included from include/linux/mm.h:22:
   In file included from include/linux/page_ext.h:7:
>> include/linux/stackdepot.h:116:26: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   void *stack_start(struct seq_file *m, loff_t *ppos);
                            ^
   include/linux/stackdepot.h:117:25: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   void *stack_next(struct seq_file *m, void *v, loff_t *ppos);
                           ^
   include/linux/stackdepot.h:118:24: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   int stack_print(struct seq_file *m, void *v);
                          ^
   In file included from kernel/trace/trace_irqsoff.c:16:
   In file included from include/linux/ftrace.h:10:
   In file included from include/linux/trace_recursion.h:5:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __raw_readb(PCI_IOBASE + addr);
                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from kernel/trace/trace_irqsoff.c:16:
   In file included from include/linux/ftrace.h:10:
   In file included from include/linux/trace_recursion.h:5:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from kernel/trace/trace_irqsoff.c:16:
   In file included from include/linux/ftrace.h:10:
   In file included from include/linux/trace_recursion.h:5:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writeb(value, PCI_IOBASE + addr);
                               ~~~~~~~~~~ ^
   include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   kernel/trace/trace_irqsoff.c:68:19: warning: unused function 'irqsoff_display_graph' [-Wunused-function]
   static inline int irqsoff_display_graph(struct trace_array *tr, int set)
                     ^
   10 warnings generated.
--
   In file included from kernel/trace/trace_branch.c:7:
   In file included from include/linux/kallsyms.h:13:
   In file included from include/linux/mm.h:22:
   In file included from include/linux/page_ext.h:7:
>> include/linux/stackdepot.h:116:26: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   void *stack_start(struct seq_file *m, loff_t *ppos);
                            ^
   include/linux/stackdepot.h:117:25: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   void *stack_next(struct seq_file *m, void *v, loff_t *ppos);
                           ^
   include/linux/stackdepot.h:118:24: warning: declaration of 'struct seq_file' will not be visible outside of this function [-Wvisibility]
   int stack_print(struct seq_file *m, void *v);
                          ^
   In file included from kernel/trace/trace_branch.c:13:
   In file included from include/linux/ftrace.h:10:
   In file included from include/linux/trace_recursion.h:5:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __raw_readb(PCI_IOBASE + addr);
                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from kernel/trace/trace_branch.c:13:
   In file included from include/linux/ftrace.h:10:
   In file included from include/linux/trace_recursion.h:5:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from kernel/trace/trace_branch.c:13:
   In file included from include/linux/ftrace.h:10:
   In file included from include/linux/trace_recursion.h:5:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writeb(value, PCI_IOBASE + addr);
                               ~~~~~~~~~~ ^
   include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   kernel/trace/trace_branch.c:205:6: warning: no previous prototype for function 'ftrace_likely_update' [-Wmissing-prototypes]
   void ftrace_likely_update(struct ftrace_likely_data *f, int val,
        ^
   kernel/trace/trace_branch.c:205:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void ftrace_likely_update(struct ftrace_likely_data *f, int val,
   ^
   static 
   10 warnings generated.


vim +/stack_start +491 lib/stackdepot.c

   489	
   490	#ifdef CONFIG_PAGE_OWNER
 > 491	void *stack_start(struct seq_file *m, loff_t *ppos)
   492	{
   493		unsigned long *table = m->private;
   494		struct stack_record **stacks, *stack;
   495	
   496		/* First time */
   497		if (*ppos == 0)
   498			*table = 0;
   499	
   500		if (*ppos == -1UL)
   501			return NULL;
   502	
   503		stacks = &stack_table[*table];
   504		stack = (struct stack_record *)stacks;
   505	
   506		return stack;
   507	}
   508	
 > 509	void *stack_next(struct seq_file *m, void *v, loff_t *ppos)
   510	{
   511		unsigned long *table = m->private;
   512		unsigned long nr_table = *table;
   513		struct stack_record *next = NULL, *stack = v, **stacks;
   514		unsigned long stack_table_entries = stack_hash_mask + 1;
   515	
   516		if (!stack) {
   517	new_table:
   518			/* New table */
   519			nr_table++;
   520			if (nr_table >= stack_table_entries)
   521				goto out;
   522			stacks = &stack_table[nr_table];
   523			stack = (struct stack_record *)stacks;
   524			next = stack;
   525		} else {
   526			next = stack->next;
   527		}
   528	
   529		if (!next)
   530			goto new_table;
   531	
   532	out:
   533		*table = nr_table;
   534		*ppos = (nr_table >= stack_table_entries) ? -1UL : *ppos + 1;
   535		return next;
   536	}
   537	
 > 538	int stack_print(struct seq_file *m, void *v)
   539	{
   540		char *buf;
   541		int ret = 0;
   542		struct stack_record *stack = v;
   543	
   544		if (!stack->size || stack->size < 0 ||
   545		    stack->size > PAGE_SIZE || stack->handle.valid != 1 ||
   546		    refcount_read(&stack->count) < 1)
   547			return 0;
   548	
   549		buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
   550		ret += stack_trace_snprint(buf, PAGE_SIZE, stack->entries, stack->size, 0);
   551		scnprintf(buf + ret, PAGE_SIZE - ret, "stack count: %d\n\n",
   552			  refcount_read(&stack->count));
   553		seq_printf(m, buf);
   554		seq_puts(m, "\n\n");
   555		kfree(buf);
   556	
   557		return 0;
   558	}
   559	#endif
   560
  
Alexander Potapenko May 22, 2023, 8:27 a.m. UTC | #2
On Tue, May 16, 2023 at 8:25 PM Oscar Salvador <osalvador@suse.de> wrote:

I am still hesitant about adding this functionality to stackdepot,
because page_owner is the only user of the stack counters that look
orthogonal to the rest of stackdepot.
One indicator of that is the fact that you keep adding dependencies on
page_owner to stackdepot code.

> 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

"cating"?

> +#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

Code depending on CONFIG_PAGE_OWNER should not belong here.
It is fine to have generic iterators to traverse the stack depot in
stackdepot.h without #ifdefs.
Perhaps they don't need to implement the whole interface of seq_file.


> @@ -486,6 +487,77 @@ static struct stack_record *stack_depot_getstack(depot_stack_handle_t handle)
>         return stack;
>  }
>
> +#ifdef CONFIG_PAGE_OWNER

Ditto - no CONFIG_PAGE_OWNER, please


> +
> +int stack_print(struct seq_file *m, void *v)
> +{
> +       char *buf;
> +       int ret = 0;
> +       struct stack_record *stack = v;
> +
> +       if (!stack->size || 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;
> +}

Maybe stack_print() should be in mm/page_owner.c instead?
  

Patch

diff --git a/include/linux/stackdepot.h b/include/linux/stackdepot.h
index 6ba4fcdb0c5f..7e9d0e9ec66b 100644
--- a/include/linux/stackdepot.h
+++ b/include/linux/stackdepot.h
@@ -112,6 +112,12 @@  void stack_depot_dec_count(depot_stack_handle_t handle);
 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
  *
diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index bc4a9cd25834..c4af2e946500 100644
--- a/lib/stackdepot.c
+++ b/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,77 @@  static struct stack_record *stack_depot_getstack(depot_stack_handle_t handle)
 	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 || 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)
 {
diff --git a/mm/page_owner.c b/mm/page_owner.c
index 2d5d07013e4e..2d97f6b34ea6 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -719,6 +719,30 @@  static const struct file_operations proc_page_owner_operations = {
 	.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)