[PATCH net-next v2 1/4] net: protect queue -> napi linking with netdev_lock()
From: Joe Damato <hidden>
Date: 2025-01-16 05:53:26
Also in:
lkml
Subsystem:
networking drivers, networking [general], the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
From: Jakub Kicinski <kuba@kernel.org>
netdev netlink is the only reader of netdev_{,rx_}queue->napi,
and it already holds netdev->lock. Switch protection of the
writes to netdev->lock as well.
Add netif_queue_set_napi_locked() for API completeness,
but the expectation is that most current drivers won't have
to worry about locking any more. Today they jump thru hoops
to take rtnl_lock.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Joe Damato <redacted>
---
v2:
- Added in v2 from Jakub.
include/linux/netdevice.h | 9 +++++++--
include/net/netdev_rx_queue.h | 2 +-
net/core/dev.c | 16 +++++++++++++---
3 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 8308d9c75918..c7201642e9fb 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h@@ -690,7 +690,7 @@ struct netdev_queue { * slow- / control-path part */ /* NAPI instance for the queue - * Readers and writers must hold RTNL + * Readers and writers must hold netdev->lock */ struct napi_struct *napi;
@@ -2458,7 +2458,8 @@ struct net_device { * Partially protects (writers must hold both @lock and rtnl_lock): * @up * - * Also protects some fields in struct napi_struct. + * Also protects some fields in: + * struct napi_struct, struct netdev_queue, struct netdev_rx_queue * * Ordering: take after rtnl_lock. */
@@ -2685,6 +2686,10 @@ static inline void *netdev_priv(const struct net_device *dev) void netif_queue_set_napi(struct net_device *dev, unsigned int queue_index, enum netdev_queue_type type, struct napi_struct *napi); +void netif_queue_set_napi_locked(struct net_device *dev, + unsigned int queue_index, + enum netdev_queue_type type, + struct napi_struct *napi); static inline void netdev_lock(struct net_device *dev) {
diff --git a/include/net/netdev_rx_queue.h b/include/net/netdev_rx_queue.h
index 596836abf7bf..9fcac0b43b71 100644
--- a/include/net/netdev_rx_queue.h
+++ b/include/net/netdev_rx_queue.h@@ -23,7 +23,7 @@ struct netdev_rx_queue { struct xsk_buff_pool *pool; #endif /* NAPI instance for the queue - * Readers and writers must hold RTNL + * Readers and writers must hold netdev->lock */ struct napi_struct *napi; struct pp_memory_provider_params mp_params;
diff --git a/net/core/dev.c b/net/core/dev.c
index 782ae3ff3f8d..528478cd8615 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c@@ -6851,14 +6851,24 @@ EXPORT_SYMBOL(dev_set_threaded); */ void netif_queue_set_napi(struct net_device *dev, unsigned int queue_index, enum netdev_queue_type type, struct napi_struct *napi) +{ + netdev_lock(dev); + netif_queue_set_napi_locked(dev, queue_index, type, napi); + netdev_unlock(dev); +} +EXPORT_SYMBOL(netif_queue_set_napi); + +void netif_queue_set_napi_locked(struct net_device *dev, + unsigned int queue_index, + enum netdev_queue_type type, + struct napi_struct *napi) { struct netdev_rx_queue *rxq; struct netdev_queue *txq; if (WARN_ON_ONCE(napi && !napi->dev)) return; - if (dev->reg_state >= NETREG_REGISTERED) - ASSERT_RTNL(); + netdev_assert_locked_or_invisible(dev); switch (type) { case NETDEV_QUEUE_TYPE_RX:
@@ -6873,7 +6883,7 @@ void netif_queue_set_napi(struct net_device *dev, unsigned int queue_index, return; } } -EXPORT_SYMBOL(netif_queue_set_napi); +EXPORT_SYMBOL(netif_queue_set_napi_locked); static void napi_restore_config(struct napi_struct *n) {
--
2.25.1