Dismantle two netns holding a dummy and a netkit pair registered in opposite order. unregister_netdevice_many_notify() takes the instance locks of all the devices at once, nesting the two kinds of devices one way for the first netns and the other way for the second. With lockdep enabled this used to trigger a circular locking report. Acked-by: Stanislav Fomichev Reviewed-by: Eric Dumazet Signed-off-by: Jakub Kicinski --- tools/testing/selftests/net/Makefile | 1 + tools/testing/selftests/net/netdev_lock.py | 42 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100755 tools/testing/selftests/net/netdev_lock.py diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 3ee3378f8b26..d4ca82fec0b4 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -67,6 +67,7 @@ TEST_PROGS := \ nat6to4.sh \ ndisc_unsolicited_na_test.sh \ netdev-l2addr.sh \ + netdev_lock.py \ netdevice.sh \ netns-name.sh \ netns-sysctl.sh \ diff --git a/tools/testing/selftests/net/netdev_lock.py b/tools/testing/selftests/net/netdev_lock.py new file mode 100755 index 000000000000..0015b987eb9d --- /dev/null +++ b/tools/testing/selftests/net/netdev_lock.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +"""Tests for the netdev instance lock.""" + +from lib.py import ksft_run, ksft_exit +from lib.py import ip +from lib.py import NetNS + + +def test_unreg_order() -> None: + """Dismantle two netns holding the same two kinds of ops locked device, + registered in opposite order. + + unregister_netdevice_many_notify() takes the instance lock of every + device in the batch and holds them all at once, so the two kinds end up + nested one way round for the first netns and the other way round for + the second. + """ + with NetNS() as ns1, NetNS() as ns2: + net1, net2 = str(ns1), str(ns2) + + ip("link add du0 type dummy", ns=net1) + ip("link add nk0 type netkit peer name nk1", ns=net1) + + ip("link add nk0 type netkit peer name nk1", ns=net2) + ip("link add du0 type dummy", ns=net2) + + # only devices which are up get locked during unregister + for net in (net1, net2): + for dev in ("du0", "nk0", "nk1"): + ip(f"link set {dev} up", ns=net) + + +def main() -> None: + """Ksft boilerplate main.""" + ksft_run([test_unreg_order]) + ksft_exit() + + +if __name__ == "__main__": + main() -- 2.55.0