On Wed 2025-07-09 14:53:29, Thomas Weißschuh wrote: > On Wed, Jul 09, 2025 at 01:36:14PM +0200, Petr Mladek wrote: > > On Tue 2025-07-08 16:48:47, Arnd Bergmann wrote: > > > On Tue, Jul 8, 2025, at 16:24, Petr Mladek wrote: > > > > On Wed 2025-07-02 13:28:35, Nathan Chancellor wrote: > > > >> On Wed, Jul 02, 2025 at 11:51:56AM +0200, Petr Mladek wrote: > > > > > > > > Thanks a lot for the nice report. > > > > > > > > The problem is how cpumask_var_t is defined in > > > > include/linux/cpumask_types.h: > > > > > > > > #ifdef CONFIG_CPUMASK_OFFSTACK > > > > typedef struct cpumask *cpumask_var_t; > > > > #else > > > > typedef struct cpumask cpumask_var_t[1]; > > > > #endif /* CONFIG_CPUMASK_OFFSTACK */ > > > > > > > > And KUNIT_DEFINE_ACTION_WRAPPER() expect that the 3rd parameter > > > > is a pointer. > > > > > > > > I am going to solve this by adding a wrapper over free_cpumask_var() > > > > which would work with a pointer to cpumask_var_t. > > > > > > I'm not familiar enough with the cleanup mechanism of kunit, > > > but can't you just move the mask allocation outside of > > > test_readerwriter()? > > > > The only solution would be global variable. > > When the cpumask is allocated on the stack, free_cpumask_var() is a no-op. > So while the stack address would be leaked to another thread, > it should be fine as nothing is ever done with it. > For more clarity it could also be gated explicitly: > > if (IS_ENABLED(CONFIG_CPUMASK_OFFSTACK)) { > err = kunit_add_action_or_reset(test, prbtest_cpumask_cleanup, > test_cpus); > KUNIT_ASSERT_EQ(test, err, 0); > }
It is likely a matter of taste but I like this idea. It looks better than passing an invalid pointer and hope nobody would do anything with it. The only problem is that if (IS_ENABLED(CONFIG_CPUMASK_OFFSTACK)) { did not prevented the compiler warning. I guess that the code was still compiled and later just optimized out. So, I am going to use #ifdef instead. I create a function: /* * A cast would be needed for the clean up action when the cpumask was on stack. * Also it would leak the stack address to the cleanup thread. * And alloc_cpu_mask() and free_cpumask_var() would do nothing anyway. */ #ifdef CONFIG_CPUMASK_OFFSTACK KUNIT_DEFINE_ACTION_WRAPPER(prbtest_cpumask_cleanup, free_cpumask_var, cpumask_var_t); static void prbtest_alloc_cpumask(struct kunit *test, cpumask_var_t *mask) { int err; KUNIT_ASSERT_TRUE(test, alloc_cpumask_var(mask, GFP_KERNEL)); err = kunit_add_action_or_reset(test, prbtest_cpumask_cleanup, *mask); KUNIT_ASSERT_EQ(test, err, 0); } #else static inline void prbtest_alloc_cpumask(struct kunit *test, cpumask_var_t *mask) {} #endif which will be called in test_readerwriter(). It seems to work, ..., sigh. I did not expect so many troubles with a tiny detail. Best Regards, Petr