Message ID | 20240403131936.787234-7-linux@roeck-us.net (mailing list archive) |
---|---|
State | Not Applicable |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Add support for suppressing warning backtraces | expand |
On Wed, 3 Apr 2024 06:19:27 -0700 Guenter Roeck wrote: > dev_addr_lists_test generates lock warning noise at the end of tests > if lock debugging is enabled. There are two sets of warnings. > > WARNING: CPU: 0 PID: 689 at kernel/locking/mutex.c:923 __mutex_unlock_slowpath.constprop.0+0x13c/0x368 > DEBUG_LOCKS_WARN_ON(__owner_task(owner) != __get_current()) > > WARNING: kunit_try_catch/1336 still has locks held! > > KUnit test cleanup is not guaranteed to run in the same thread as the test > itself. For this test, this means that rtnl_lock() and rtnl_unlock() may > be called from different threads. This triggers the warnings. > Suppress the warnings because they are irrelevant for the test and just > confusing and distracting. > > The first warning can be suppressed by using START_SUPPRESSED_WARNING() > and END_SUPPRESSED_WARNING() around the call to rtnl_unlock(). To suppress > the second warning, it is necessary to set debug_locks_silent while the > rtnl lock is held. Is it okay if I move the locking into the tests, instead? It's only 4 lines more and no magic required, seems to work fine.
On Wed, Apr 03, 2024 at 06:34:12PM -0700, Jakub Kicinski wrote: > On Wed, 3 Apr 2024 06:19:27 -0700 Guenter Roeck wrote: > > dev_addr_lists_test generates lock warning noise at the end of tests > > if lock debugging is enabled. There are two sets of warnings. > > > > WARNING: CPU: 0 PID: 689 at kernel/locking/mutex.c:923 __mutex_unlock_slowpath.constprop.0+0x13c/0x368 > > DEBUG_LOCKS_WARN_ON(__owner_task(owner) != __get_current()) > > > > WARNING: kunit_try_catch/1336 still has locks held! > > > > KUnit test cleanup is not guaranteed to run in the same thread as the test > > itself. For this test, this means that rtnl_lock() and rtnl_unlock() may > > be called from different threads. This triggers the warnings. > > Suppress the warnings because they are irrelevant for the test and just > > confusing and distracting. > > > > The first warning can be suppressed by using START_SUPPRESSED_WARNING() > > and END_SUPPRESSED_WARNING() around the call to rtnl_unlock(). To suppress > > the second warning, it is necessary to set debug_locks_silent while the > > rtnl lock is held. > > Is it okay if I move the locking into the tests, instead? > It's only 4 lines more and no magic required, seems to work fine. I don't think it is that simple. Unit tests run in a kernel thread and exit immediately if a test fails. While the unit test code _looks_ sequential, that isn't really the case. Every instance of KUNIT_ASSERT_x or KUNIT_FAIL() results in immediate kernel thread termination. If that happens, any rtnl_unlock() in the failed function would not be executed. I am not aware of an equivalent of atexit() for kernel threads which would fix the problem. My understanding is that the kunit system doesn't support an equivalent either, but at least sometimes executes the exit function in a different thread context. Guenter
diff --git a/net/core/dev_addr_lists_test.c b/net/core/dev_addr_lists_test.c index 4dbd0dc6aea2..b427dd1a3c93 100644 --- a/net/core/dev_addr_lists_test.c +++ b/net/core/dev_addr_lists_test.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <kunit/test.h> +#include <linux/debug_locks.h> #include <linux/etherdevice.h> #include <linux/netdevice.h> #include <linux/rtnetlink.h> @@ -49,6 +50,7 @@ static int dev_addr_test_init(struct kunit *test) KUNIT_FAIL(test, "Can't register netdev %d", err); } + debug_locks_silent = 1; rtnl_lock(); return 0; } @@ -56,8 +58,12 @@ static int dev_addr_test_init(struct kunit *test) static void dev_addr_test_exit(struct kunit *test) { struct net_device *netdev = test->priv; + DEFINE_SUPPRESSED_WARNING(__mutex_unlock_slowpath); + START_SUPPRESSED_WARNING(__mutex_unlock_slowpath); rtnl_unlock(); + END_SUPPRESSED_WARNING(__mutex_unlock_slowpath); + debug_locks_silent = 0; unregister_netdev(netdev); free_netdev(netdev); }