aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorToke Høiland-Jørgensen <toke@redhat.com>2025-12-11 12:50:05 +0100
committerPaolo Abeni <pabeni@redhat.com>2025-12-22 12:25:11 +0100
commit5498227676303e3ffa9a3a46214af96bc3e81314 (patch)
treea9b42fb881d7278ab1a3067f17f8100a350b2fe3 /net
parent1e5a541420b8c6d87d88eb50b6b978cdeafee1c9 (diff)
net: openvswitch: Avoid needlessly taking the RTNL on vport destroy
The openvswitch teardown code will immediately call ovs_netdev_detach_dev() in response to a NETDEV_UNREGISTER notification. It will then start the dp_notify_work workqueue, which will later end up calling the vport destroy() callback. This callback takes the RTNL to do another ovs_netdev_detach_port(), which in this case is unnecessary. This causes extra pressure on the RTNL, in some cases leading to "unregister_netdevice: waiting for XX to become free" warnings on teardown. We can straight-forwardly avoid the extra RTNL lock acquisition by checking the device flags before taking the lock, and skip the locking altogether if the IFF_OVS_DATAPATH flag has already been unset. Fixes: b07c26511e94 ("openvswitch: fix vport-netdev unregister") Tested-by: Adrian Moreno <amorenoz@redhat.com> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com> Acked-by: Eelco Chaudron <echaudro@redhat.com> Acked-by: Aaron Conole <aconole@redhat.com> Link: https://patch.msgid.link/20251211115006.228876-1-toke@redhat.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'net')
-rw-r--r--net/openvswitch/vport-netdev.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 91a11067e458..6574f9bcdc02 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -160,10 +160,19 @@ void ovs_netdev_detach_dev(struct vport *vport)
static void netdev_destroy(struct vport *vport)
{
- rtnl_lock();
- if (netif_is_ovs_port(vport->dev))
- ovs_netdev_detach_dev(vport);
- rtnl_unlock();
+ /* When called from ovs_db_notify_wq() after a dp_device_event(), the
+ * port has already been detached, so we can avoid taking the RTNL by
+ * checking this first.
+ */
+ if (netif_is_ovs_port(vport->dev)) {
+ rtnl_lock();
+ /* Check again while holding the lock to ensure we don't race
+ * with the netdev notifier and detach twice.
+ */
+ if (netif_is_ovs_port(vport->dev))
+ ovs_netdev_detach_dev(vport);
+ rtnl_unlock();
+ }
call_rcu(&vport->rcu, vport_netdev_free);
}