Message ID | 20211202032139.3156411-3-eric.dumazet@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | net: add preliminary netdev refcount tracking | expand |
On Wed, Dec 1, 2021 at 7:21 PM Eric Dumazet <eric.dumazet@gmail.com> wrote: > > From: Eric Dumazet <edumazet@google.com> > > This module uses reference tracker, forcing two issues. > > 1) Double free of a tracker > > 2) leak of two trackers, one being allocated from softirq context. > > "modprobe test_ref_tracker" would emit the following traces. > (Use scripts/decode_stacktrace.sh if necessary) > > [ > Signed-off-by: Eric Dumazet <edumazet@google.com> > --- > lib/Kconfig.debug | 10 ++++ > lib/Makefile | 2 +- > lib/test_ref_tracker.c | 116 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 127 insertions(+), 1 deletion(-) > create mode 100644 lib/test_ref_tracker.c > > diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug > index 5c12bde10996cf97b5f075d318089b1be73f71d7..d005f555872147e15d3e0a65d2a03e1a5c44f5f0 100644 > --- a/lib/Kconfig.debug > +++ b/lib/Kconfig.debug > @@ -2106,6 +2106,16 @@ config BACKTRACE_SELF_TEST > > Say N if you are unsure. > > +config TEST_REF_TRACKER > + tristate "Self test for reference tracker" > + depends on DEBUG_KERNEL > + select REF_TRACKER > + help > + This option provides a kernel module performing tests > + using reference tracker infrastructure. > + > + Say N if you are unsure. > + > config RBTREE_TEST > tristate "Red-Black tree test" > depends on DEBUG_KERNEL > diff --git a/lib/Makefile b/lib/Makefile > index c1fd9243ddb9cc1ac5252d7eb8009f9290782c4a..b213a7bbf3fda2eb9f234fb7473b8f1b617bed6b 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -101,7 +101,7 @@ obj-$(CONFIG_TEST_LOCKUP) += test_lockup.o > obj-$(CONFIG_TEST_HMM) += test_hmm.o > obj-$(CONFIG_TEST_FREE_PAGES) += test_free_pages.o > obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o > - > +obj-$(CONFIG_TEST_REF_TRACKER) += test_ref_tracker.o > # > # CFLAGS for compiling floating point code inside the kernel. x86/Makefile turns > # off the generation of FPU/SSE* instructions for kernel proper but FPU_FLAGS > diff --git a/lib/test_ref_tracker.c b/lib/test_ref_tracker.c > new file mode 100644 > index 0000000000000000000000000000000000000000..73bf9255e03790fa50491fe8e5cd411d54827c45 > --- /dev/null > +++ b/lib/test_ref_tracker.c > @@ -0,0 +1,116 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Referrence tracker self test. > + * > + * Copyright (c) 2021 Eric Dumazet <edumazet@google.com> > + */ > +#include <linux/init.h> > +#include <linux/module.h> > +#include <linux/delay.h> > +#include <linux/ref_tracker.h> > +#include <linux/slab.h> > +#include <linux/timer.h> > + > +static struct ref_tracker_dir ref_dir; > +static struct ref_tracker *tracker[20]; > + > +#define TRT_ALLOC(X) static noinline void \ > + alloctest_ref_tracker_alloc##X(struct ref_tracker_dir *dir, \ > + struct ref_tracker **trackerp) \ > + { \ > + ref_tracker_alloc(dir, trackerp, GFP_KERNEL); \ > + } > + > +TRT_ALLOC(0) > +TRT_ALLOC(1) > +TRT_ALLOC(2) > +TRT_ALLOC(3) > +TRT_ALLOC(4) > +TRT_ALLOC(5) > +TRT_ALLOC(6) > +TRT_ALLOC(7) > +TRT_ALLOC(8) > +TRT_ALLOC(9) > +TRT_ALLOC(10) > +TRT_ALLOC(11) > +TRT_ALLOC(12) > +TRT_ALLOC(13) > +TRT_ALLOC(14) > +TRT_ALLOC(15) > +TRT_ALLOC(16) > +TRT_ALLOC(17) > +TRT_ALLOC(18) > +TRT_ALLOC(19) > + > +#undef TRT_ALLOC > + > +static noinline void > +alloctest_ref_tracker_free(struct ref_tracker_dir *dir, > + struct ref_tracker **trackerp) > +{ > + ref_tracker_free(dir, trackerp); > +} > + > + > +static struct timer_list test_ref_tracker_timer; > +static atomic_t test_ref_timer_done = ATOMIC_INIT(0); > + > +static void test_ref_tracker_timer_func(struct timer_list *t) > +{ > + alloctest_ref_tracker_alloc0(&ref_dir, &tracker[0]); This will be changed to use GFP_ATOMIC instead of GFP_KERNEL ref_tracker_alloc(&ref_dir, ..., GFP_ATOMIC); > + atomic_set(&test_ref_timer_done, 1); > +} > + >
Hi Eric, I love your patch! Yet something to improve: [auto build test ERROR on net-next/master] url: https://github.com/0day-ci/linux/commits/Eric-Dumazet/net-add-preliminary-netdev-refcount-tracking/20211202-112353 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 8057cbb8335cf6d419866737504473833e1d128a config: sparc-buildonly-randconfig-r005-20211202 (https://download.01.org/0day-ci/archive/20211202/202112021600.8HBrwOX4-lkp@intel.com/config) compiler: sparc-linux-gcc (GCC) 11.2.0 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/0day-ci/linux/commit/5da0cdb1848fae9fb2d9d749bb94e568e2493df8 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Eric-Dumazet/net-add-preliminary-netdev-refcount-tracking/20211202-112353 git checkout 5da0cdb1848fae9fb2d9d749bb94e568e2493df8 # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=sparc SHELL=/bin/bash arch/sparc/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): In file included from arch/sparc/kernel/stacktrace.c:11: arch/sparc/kernel/kstack.h: In function 'kstack_valid': >> arch/sparc/kernel/kstack.h:23:13: error: 'hardirq_stack' undeclared (first use in this function) 23 | if (hardirq_stack[tp->cpu]) { | ^~~~~~~~~~~~~ arch/sparc/kernel/kstack.h:23:13: note: each undeclared identifier is reported only once for each function it appears in >> arch/sparc/kernel/kstack.h:28:40: error: 'softirq_stack' undeclared (first use in this function) 28 | base = (unsigned long) softirq_stack[tp->cpu]; | ^~~~~~~~~~~~~ arch/sparc/kernel/kstack.h: In function 'kstack_is_trap_frame': arch/sparc/kernel/kstack.h:46:13: error: 'hardirq_stack' undeclared (first use in this function) 46 | if (hardirq_stack[tp->cpu]) { | ^~~~~~~~~~~~~ arch/sparc/kernel/kstack.h:51:40: error: 'softirq_stack' undeclared (first use in this function) 51 | base = (unsigned long) softirq_stack[tp->cpu]; | ^~~~~~~~~~~~~ >> arch/sparc/kernel/kstack.h:59:18: error: 'struct pt_regs' has no member named 'magic' 59 | if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) | ^~ >> arch/sparc/kernel/kstack.h:59:39: error: 'PT_REGS_MAGIC' undeclared (first use in this function); did you mean 'PT_V9_MAGIC'? 59 | if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) | ^~~~~~~~~~~~~ | PT_V9_MAGIC arch/sparc/kernel/kstack.h: In function 'set_hardirq_stack': arch/sparc/kernel/kstack.h:67:30: error: 'hardirq_stack' undeclared (first use in this function); did you mean 'set_hardirq_stack'? 67 | void *orig_sp, *sp = hardirq_stack[smp_processor_id()]; | ^~~~~~~~~~~~~ | set_hardirq_stack arch/sparc/kernel/stacktrace.c: In function '__save_stack_trace': >> arch/sparc/kernel/stacktrace.c:46:35: error: 'struct pt_regs' has no member named 'tstate' 46 | if (!(regs->tstate & TSTATE_PRIV)) | ^~ >> arch/sparc/kernel/stacktrace.c:46:46: error: 'TSTATE_PRIV' undeclared (first use in this function) 46 | if (!(regs->tstate & TSTATE_PRIV)) | ^~~~~~~~~~~ >> arch/sparc/kernel/stacktrace.c:48:36: error: 'struct pt_regs' has no member named 'tpc'; did you mean 'pc'? 48 | pc = regs->tpc; | ^~~ | pc Kconfig warnings: (for reference only) WARNING: unmet direct dependencies detected for STACKTRACE Depends on STACKTRACE_SUPPORT Selected by - STACKDEPOT vim +/hardirq_stack +23 arch/sparc/kernel/kstack.h 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 9 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 10 /* SP must be STACK_BIAS adjusted already. */ 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 11 static inline bool kstack_valid(struct thread_info *tp, unsigned long sp) 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 12 { 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 13 unsigned long base = (unsigned long) tp; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 14 232486e1e9f348 arch/sparc/kernel/kstack.h David S. Miller 2010-02-12 15 /* Stack pointer must be 16-byte aligned. */ 232486e1e9f348 arch/sparc/kernel/kstack.h David S. Miller 2010-02-12 16 if (sp & (16UL - 1)) 232486e1e9f348 arch/sparc/kernel/kstack.h David S. Miller 2010-02-12 17 return false; 232486e1e9f348 arch/sparc/kernel/kstack.h David S. Miller 2010-02-12 18 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 19 if (sp >= (base + sizeof(struct thread_info)) && 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 20 sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 21 return true; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 22 6f63e781eaf6a7 arch/sparc64/kernel/kstack.h David S. Miller 2008-08-13 @23 if (hardirq_stack[tp->cpu]) { 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 24 base = (unsigned long) hardirq_stack[tp->cpu]; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 25 if (sp >= base && 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 26 sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 27 return true; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 @28 base = (unsigned long) softirq_stack[tp->cpu]; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 29 if (sp >= base && 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 30 sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 31 return true; 6f63e781eaf6a7 arch/sparc64/kernel/kstack.h David S. Miller 2008-08-13 32 } 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 33 return false; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 34 } 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 35 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 36 /* Does "regs" point to a valid pt_regs trap frame? */ 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 37 static inline bool kstack_is_trap_frame(struct thread_info *tp, struct pt_regs *regs) 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 38 { 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 39 unsigned long base = (unsigned long) tp; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 40 unsigned long addr = (unsigned long) regs; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 41 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 42 if (addr >= base && 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 43 addr <= (base + THREAD_SIZE - sizeof(*regs))) 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 44 goto check_magic; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 45 6f63e781eaf6a7 arch/sparc64/kernel/kstack.h David S. Miller 2008-08-13 46 if (hardirq_stack[tp->cpu]) { 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 47 base = (unsigned long) hardirq_stack[tp->cpu]; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 48 if (addr >= base && 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 49 addr <= (base + THREAD_SIZE - sizeof(*regs))) 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 50 goto check_magic; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 51 base = (unsigned long) softirq_stack[tp->cpu]; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 52 if (addr >= base && 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 53 addr <= (base + THREAD_SIZE - sizeof(*regs))) 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 54 goto check_magic; 6f63e781eaf6a7 arch/sparc64/kernel/kstack.h David S. Miller 2008-08-13 55 } 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 56 return false; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 57 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 58 check_magic: 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 @59 if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 60 return true; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 61 return false; 4f70f7a91bffdc arch/sparc64/kernel/kstack.h David S. Miller 2008-08-12 62 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hi Eric,
I love your patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/0day-ci/linux/commits/Eric-Dumazet/net-add-preliminary-netdev-refcount-tracking/20211202-112353
base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 8057cbb8335cf6d419866737504473833e1d128a
config: nios2-allyesconfig (https://download.01.org/0day-ci/archive/20211203/202112030323.z9IhC2B3-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 11.2.0
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/0day-ci/linux/commit/5da0cdb1848fae9fb2d9d749bb94e568e2493df8
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Eric-Dumazet/net-add-preliminary-netdev-refcount-tracking/20211202-112353
git checkout 5da0cdb1848fae9fb2d9d749bb94e568e2493df8
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=nios2 SHELL=/bin/bash
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
nios2-linux-ld: kernel/stacktrace.o: in function `stack_trace_save':
>> (.text+0x2e4): undefined reference to `save_stack_trace'
(.text+0x2e4): relocation truncated to fit: R_NIOS2_CALL26 against `save_stack_trace'
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for STACKTRACE
Depends on STACKTRACE_SUPPORT
Selected by
- STACKDEPOT
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
On Thu, Dec 2, 2021 at 11:25 AM kernel test robot <lkp@intel.com> wrote: > > Hi Eric, > > I love your patch! Yet something to improve: > > [auto build test ERROR on net-next/master] > > url: https://github.com/0day-ci/linux/commits/Eric-Dumazet/net-add-preliminary-netdev-refcount-tracking/20211202-112353 > base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 8057cbb8335cf6d419866737504473833e1d128a > config: nios2-allyesconfig (https://download.01.org/0day-ci/archive/20211203/202112030323.z9IhC2B3-lkp@intel.com/config) > compiler: nios2-linux-gcc (GCC) 11.2.0 > 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/0day-ci/linux/commit/5da0cdb1848fae9fb2d9d749bb94e568e2493df8 > git remote add linux-review https://github.com/0day-ci/linux > git fetch --no-tags linux-review Eric-Dumazet/net-add-preliminary-netdev-refcount-tracking/20211202-112353 > git checkout 5da0cdb1848fae9fb2d9d749bb94e568e2493df8 > # save the config file to linux build tree > mkdir build_dir > COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=nios2 SHELL=/bin/bash > > If you fix the issue, kindly add following tag as appropriate > Reported-by: kernel test robot <lkp@intel.com> > > All errors (new ones prefixed by >>): > > nios2-linux-ld: kernel/stacktrace.o: in function `stack_trace_save': > >> (.text+0x2e4): undefined reference to `save_stack_trace' > (.text+0x2e4): relocation truncated to fit: R_NIOS2_CALL26 against `save_stack_trace' > > Kconfig warnings: (for reference only) > WARNING: unmet direct dependencies detected for STACKTRACE > Depends on STACKTRACE_SUPPORT > Selected by > - STACKDEPOT > I am not sure I understand this. Dmitry, do I need to add a depends on STACKTRACE_SUPPORT. Thanks !
On Thu, 2 Dec 2021 at 20:46, Eric Dumazet <edumazet@google.com> wrote: > > On Thu, Dec 2, 2021 at 11:25 AM kernel test robot <lkp@intel.com> wrote: > > > > Hi Eric, > > > > I love your patch! Yet something to improve: > > > > [auto build test ERROR on net-next/master] > > > > url: https://github.com/0day-ci/linux/commits/Eric-Dumazet/net-add-preliminary-netdev-refcount-tracking/20211202-112353 > > base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 8057cbb8335cf6d419866737504473833e1d128a > > config: nios2-allyesconfig (https://download.01.org/0day-ci/archive/20211203/202112030323.z9IhC2B3-lkp@intel.com/config) > > compiler: nios2-linux-gcc (GCC) 11.2.0 > > 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/0day-ci/linux/commit/5da0cdb1848fae9fb2d9d749bb94e568e2493df8 > > git remote add linux-review https://github.com/0day-ci/linux > > git fetch --no-tags linux-review Eric-Dumazet/net-add-preliminary-netdev-refcount-tracking/20211202-112353 > > git checkout 5da0cdb1848fae9fb2d9d749bb94e568e2493df8 > > # save the config file to linux build tree > > mkdir build_dir > > COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=nios2 SHELL=/bin/bash > > > > If you fix the issue, kindly add following tag as appropriate > > Reported-by: kernel test robot <lkp@intel.com> > > > > All errors (new ones prefixed by >>): > > > > nios2-linux-ld: kernel/stacktrace.o: in function `stack_trace_save': > > >> (.text+0x2e4): undefined reference to `save_stack_trace' > > (.text+0x2e4): relocation truncated to fit: R_NIOS2_CALL26 against `save_stack_trace' > > > > Kconfig warnings: (for reference only) > > WARNING: unmet direct dependencies detected for STACKTRACE > > Depends on STACKTRACE_SUPPORT > > Selected by > > - STACKDEPOT > > > > I am not sure I understand this. > > Dmitry, do I need to add a depends on STACKTRACE_SUPPORT. Humm... There is something strange about nios2 arch. KASAN depends on ARCH_HAVE_KASAN which is not selected for nios2, so it implicitly avoids this issue. But I see PAGE_OWNER that also uses STACKDEPOT has "Depends on STACKTRACE_SUPPORT". So I guess yes. I am not sure how Kconfig will reach if we make STACKDEPOT depend on STACKTRACE_SUPPORT and your config says "select STACKDEPOT"...
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 5c12bde10996cf97b5f075d318089b1be73f71d7..d005f555872147e15d3e0a65d2a03e1a5c44f5f0 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2106,6 +2106,16 @@ config BACKTRACE_SELF_TEST Say N if you are unsure. +config TEST_REF_TRACKER + tristate "Self test for reference tracker" + depends on DEBUG_KERNEL + select REF_TRACKER + help + This option provides a kernel module performing tests + using reference tracker infrastructure. + + Say N if you are unsure. + config RBTREE_TEST tristate "Red-Black tree test" depends on DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index c1fd9243ddb9cc1ac5252d7eb8009f9290782c4a..b213a7bbf3fda2eb9f234fb7473b8f1b617bed6b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -101,7 +101,7 @@ obj-$(CONFIG_TEST_LOCKUP) += test_lockup.o obj-$(CONFIG_TEST_HMM) += test_hmm.o obj-$(CONFIG_TEST_FREE_PAGES) += test_free_pages.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o - +obj-$(CONFIG_TEST_REF_TRACKER) += test_ref_tracker.o # # CFLAGS for compiling floating point code inside the kernel. x86/Makefile turns # off the generation of FPU/SSE* instructions for kernel proper but FPU_FLAGS diff --git a/lib/test_ref_tracker.c b/lib/test_ref_tracker.c new file mode 100644 index 0000000000000000000000000000000000000000..73bf9255e03790fa50491fe8e5cd411d54827c45 --- /dev/null +++ b/lib/test_ref_tracker.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Referrence tracker self test. + * + * Copyright (c) 2021 Eric Dumazet <edumazet@google.com> + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/ref_tracker.h> +#include <linux/slab.h> +#include <linux/timer.h> + +static struct ref_tracker_dir ref_dir; +static struct ref_tracker *tracker[20]; + +#define TRT_ALLOC(X) static noinline void \ + alloctest_ref_tracker_alloc##X(struct ref_tracker_dir *dir, \ + struct ref_tracker **trackerp) \ + { \ + ref_tracker_alloc(dir, trackerp, GFP_KERNEL); \ + } + +TRT_ALLOC(0) +TRT_ALLOC(1) +TRT_ALLOC(2) +TRT_ALLOC(3) +TRT_ALLOC(4) +TRT_ALLOC(5) +TRT_ALLOC(6) +TRT_ALLOC(7) +TRT_ALLOC(8) +TRT_ALLOC(9) +TRT_ALLOC(10) +TRT_ALLOC(11) +TRT_ALLOC(12) +TRT_ALLOC(13) +TRT_ALLOC(14) +TRT_ALLOC(15) +TRT_ALLOC(16) +TRT_ALLOC(17) +TRT_ALLOC(18) +TRT_ALLOC(19) + +#undef TRT_ALLOC + +static noinline void +alloctest_ref_tracker_free(struct ref_tracker_dir *dir, + struct ref_tracker **trackerp) +{ + ref_tracker_free(dir, trackerp); +} + + +static struct timer_list test_ref_tracker_timer; +static atomic_t test_ref_timer_done = ATOMIC_INIT(0); + +static void test_ref_tracker_timer_func(struct timer_list *t) +{ + alloctest_ref_tracker_alloc0(&ref_dir, &tracker[0]); + atomic_set(&test_ref_timer_done, 1); +} + +static int __init test_ref_tracker_init(void) +{ + int i; + + ref_tracker_dir_init(&ref_dir, 100); + + timer_setup(&test_ref_tracker_timer, test_ref_tracker_timer_func, 0); + mod_timer(&test_ref_tracker_timer, jiffies + 1); + + alloctest_ref_tracker_alloc1(&ref_dir, &tracker[1]); + alloctest_ref_tracker_alloc2(&ref_dir, &tracker[2]); + alloctest_ref_tracker_alloc3(&ref_dir, &tracker[3]); + alloctest_ref_tracker_alloc4(&ref_dir, &tracker[4]); + alloctest_ref_tracker_alloc5(&ref_dir, &tracker[5]); + alloctest_ref_tracker_alloc6(&ref_dir, &tracker[6]); + alloctest_ref_tracker_alloc7(&ref_dir, &tracker[7]); + alloctest_ref_tracker_alloc8(&ref_dir, &tracker[8]); + alloctest_ref_tracker_alloc9(&ref_dir, &tracker[9]); + alloctest_ref_tracker_alloc10(&ref_dir, &tracker[10]); + alloctest_ref_tracker_alloc11(&ref_dir, &tracker[11]); + alloctest_ref_tracker_alloc12(&ref_dir, &tracker[12]); + alloctest_ref_tracker_alloc13(&ref_dir, &tracker[13]); + alloctest_ref_tracker_alloc14(&ref_dir, &tracker[14]); + alloctest_ref_tracker_alloc15(&ref_dir, &tracker[15]); + alloctest_ref_tracker_alloc16(&ref_dir, &tracker[16]); + alloctest_ref_tracker_alloc17(&ref_dir, &tracker[17]); + alloctest_ref_tracker_alloc18(&ref_dir, &tracker[18]); + alloctest_ref_tracker_alloc19(&ref_dir, &tracker[19]); + + /* free all trackers but first 0 and 1. */ + for (i = 2; i < ARRAY_SIZE(tracker); i++) + alloctest_ref_tracker_free(&ref_dir, &tracker[i]); + + /* Attempt to free an already freed tracker. */ + alloctest_ref_tracker_free(&ref_dir, &tracker[2]); + + while (!atomic_read(&test_ref_timer_done)) + msleep(1); + + /* This should warn about tracker[0] & tracker[1] being not freed. */ + ref_tracker_dir_exit(&ref_dir); + + return 0; +} + +static void __exit test_ref_tracker_exit(void) +{ +} + +module_init(test_ref_tracker_init); +module_exit(test_ref_tracker_exit); + +MODULE_LICENSE("GPL v2");