Open vSwitch internal ports currently use RTNL as their ops compatibility
lock. Opt them in to netdev instance locking so eligible control operations
can be serialized per device instead of contending on the global RTNL lock.

The internal port ethtool operations implement get_drvinfo and get_link.
The latter uses ethtool_op_get_link(), which synchronizes linkwatch state
and requires RTNL. Allow get_drvinfo to run under the instance lock, but
set ETHTOOL_OP_NEEDS_RTNL_GLINK to retain RTNL for get_link.

Feature synchronization can acquire a lower device's ops lock while holding
an internal port's lock. Assign these software upper devices a distinct
lockdep class to describe the nesting.

Signed-off-by: Wang Zhan <[email protected]>
---
 net/openvswitch/vport-internal_dev.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/net/openvswitch/vport-internal_dev.c 
b/net/openvswitch/vport-internal_dev.c
index 125d310871e93..eb2e83a3e16f1 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -11,6 +11,7 @@
 #include <linux/skbuff.h>
 
 #include <net/dst.h>
+#include <net/netdev_lock.h>
 #include <net/xfrm.h>
 #include <net/rtnetlink.h>
 
@@ -29,6 +30,12 @@ static struct internal_dev *internal_dev_priv(struct 
net_device *netdev)
        return netdev_priv(netdev);
 }
 
+static int internal_dev_init(struct net_device *netdev)
+{
+       netdev_lockdep_set_classes(netdev);
+       return 0;
+}
+
 /* Called with rcu_read_lock_bh. */
 static netdev_tx_t
 internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
@@ -69,6 +76,7 @@ static void internal_dev_getinfo(struct net_device *netdev,
 }
 
 static const struct ethtool_ops internal_dev_ethtool_ops = {
+       .op_needs_rtnl  = ETHTOOL_OP_NEEDS_RTNL_GLINK,
        .get_drvinfo    = internal_dev_getinfo,
        .get_link       = ethtool_op_get_link,
 };
@@ -81,6 +89,7 @@ static void internal_dev_destructor(struct net_device *dev)
 }
 
 static const struct net_device_ops internal_dev_netdev_ops = {
+       .ndo_init = internal_dev_init,
        .ndo_open = internal_dev_open,
        .ndo_stop = internal_dev_stop,
        .ndo_start_xmit = internal_dev_xmit,
@@ -106,6 +115,7 @@ static void do_setup(struct net_device *netdev)
        netdev->needs_free_netdev = true;
        netdev->priv_destructor = NULL;
        netdev->ethtool_ops = &internal_dev_ethtool_ops;
+       netdev->request_ops_lock = true;
        netdev->rtnl_link_ops = &internal_dev_link_ops;
 
        netdev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |

base-commit: ac155a26750a595703e7dadff84735456d75a479
-- 
2.47.3

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to