Skip to content

Commit 7bd2e6b

Browse files
committed
Merge branch 'net-skip-taking-rtnl_lock-for-queue-get'
Jakub Kicinski says: ==================== net: skip taking rtnl_lock for queue GET (prep) Skip taking rtnl_lock for queue GET ops on devices which opt into running all ops under the instance lock. In preparating for performing queue ops without rtnl lock clarify the protection of queue-related fields. v1: https://lore.kernel.org/[email protected] ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 5106876 + b524586 commit 7bd2e6b

File tree

9 files changed

+65
-35
lines changed

9 files changed

+65
-35
lines changed

include/linux/netdevice.h

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ struct netdev_queue {
710710
* slow- / control-path part
711711
*/
712712
/* NAPI instance for the queue
713-
* Readers and writers must hold RTNL
713+
* "ops protected", see comment about net_device::lock
714714
*/
715715
struct napi_struct *napi;
716716

@@ -2496,18 +2496,38 @@ struct net_device {
24962496
* Should always be taken using netdev_lock() / netdev_unlock() helpers.
24972497
* Drivers are free to use it for other protection.
24982498
*
2499-
* Protects:
2499+
* For the drivers that implement shaper or queue API, the scope
2500+
* of this lock is expanded to cover most ndo/queue/ethtool/sysfs
2501+
* operations. Drivers may opt-in to this behavior by setting
2502+
* @request_ops_lock.
2503+
*
2504+
* @lock protection mixes with rtnl_lock in multiple ways, fields are
2505+
* either:
2506+
*
2507+
* - simply protected by the instance @lock;
2508+
*
2509+
* - double protected - writers hold both locks, readers hold either;
2510+
*
2511+
* - ops protected - protected by the lock held around the NDOs
2512+
* and other callbacks, that is the instance lock on devices for
2513+
* which netdev_need_ops_lock() returns true, otherwise by rtnl_lock;
2514+
*
2515+
* - double ops protected - always protected by rtnl_lock but for
2516+
* devices for which netdev_need_ops_lock() returns true - also
2517+
* the instance lock.
2518+
*
2519+
* Simply protects:
25002520
* @gro_flush_timeout, @napi_defer_hard_irqs, @napi_list,
25012521
* @net_shaper_hierarchy, @reg_state, @threaded
25022522
*
2503-
* Partially protects (writers must hold both @lock and rtnl_lock):
2523+
* Double protects:
25042524
* @up
25052525
*
2506-
* Also protects some fields in struct napi_struct.
2526+
* Double ops protects:
2527+
* @real_num_rx_queues, @real_num_tx_queues
25072528
*
2508-
* For the drivers that implement shaper or queue API, the scope
2509-
* of this lock is expanded to cover most ndo/queue/ethtool/sysfs
2510-
* operations.
2529+
* Also protects some fields in:
2530+
* struct napi_struct, struct netdev_queue, struct netdev_rx_queue
25112531
*
25122532
* Ordering: take after rtnl_lock.
25132533
*/
@@ -4062,17 +4082,7 @@ static inline bool netif_is_multiqueue(const struct net_device *dev)
40624082
}
40634083

40644084
int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq);
4065-
4066-
#ifdef CONFIG_SYSFS
40674085
int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq);
4068-
#else
4069-
static inline int netif_set_real_num_rx_queues(struct net_device *dev,
4070-
unsigned int rxqs)
4071-
{
4072-
dev->real_num_rx_queues = rxqs;
4073-
return 0;
4074-
}
4075-
#endif
40764086
int netif_set_real_num_queues(struct net_device *dev,
40774087
unsigned int txq, unsigned int rxq);
40784088

include/net/netdev_lock.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,27 @@
55

66
#include <linux/lockdep.h>
77
#include <linux/netdevice.h>
8+
#include <linux/rtnetlink.h>
89

910
static inline bool netdev_trylock(struct net_device *dev)
1011
{
1112
return mutex_trylock(&dev->lock);
1213
}
1314

14-
static inline void netdev_assert_locked(struct net_device *dev)
15+
static inline void netdev_assert_locked(const struct net_device *dev)
1516
{
1617
lockdep_assert_held(&dev->lock);
1718
}
1819

19-
static inline void netdev_assert_locked_or_invisible(struct net_device *dev)
20+
static inline void
21+
netdev_assert_locked_or_invisible(const struct net_device *dev)
2022
{
2123
if (dev->reg_state == NETREG_REGISTERED ||
2224
dev->reg_state == NETREG_UNREGISTERING)
2325
netdev_assert_locked(dev);
2426
}
2527

26-
static inline bool netdev_need_ops_lock(struct net_device *dev)
28+
static inline bool netdev_need_ops_lock(const struct net_device *dev)
2729
{
2830
bool ret = dev->request_ops_lock || !!dev->queue_mgmt_ops;
2931

@@ -46,10 +48,20 @@ static inline void netdev_unlock_ops(struct net_device *dev)
4648
netdev_unlock(dev);
4749
}
4850

49-
static inline void netdev_ops_assert_locked(struct net_device *dev)
51+
static inline void netdev_ops_assert_locked(const struct net_device *dev)
5052
{
5153
if (netdev_need_ops_lock(dev))
5254
lockdep_assert_held(&dev->lock);
55+
else
56+
ASSERT_RTNL();
57+
}
58+
59+
static inline void
60+
netdev_ops_assert_locked_or_invisible(const struct net_device *dev)
61+
{
62+
if (dev->reg_state == NETREG_REGISTERED ||
63+
dev->reg_state == NETREG_UNREGISTERING)
64+
netdev_ops_assert_locked(dev);
5365
}
5466

5567
static inline int netdev_lock_cmp_fn(const struct lockdep_map *a,

include/net/netdev_rx_queue.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ struct netdev_rx_queue {
2424
struct xsk_buff_pool *pool;
2525
#endif
2626
/* NAPI instance for the queue
27-
* Readers and writers must hold RTNL
27+
* "ops protected", see comment about net_device::lock
2828
*/
2929
struct napi_struct *napi;
3030
struct pp_memory_provider_params mp_params;

net/core/dev.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,6 +3130,7 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
31303130
if (dev->reg_state == NETREG_REGISTERED ||
31313131
dev->reg_state == NETREG_UNREGISTERING) {
31323132
ASSERT_RTNL();
3133+
netdev_ops_assert_locked(dev);
31333134

31343135
rc = netdev_queue_update_kobjects(dev, dev->real_num_tx_queues,
31353136
txq);
@@ -3160,7 +3161,6 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
31603161
}
31613162
EXPORT_SYMBOL(netif_set_real_num_tx_queues);
31623163

3163-
#ifdef CONFIG_SYSFS
31643164
/**
31653165
* netif_set_real_num_rx_queues - set actual number of RX queues used
31663166
* @dev: Network device
@@ -3180,6 +3180,7 @@ int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq)
31803180

31813181
if (dev->reg_state == NETREG_REGISTERED) {
31823182
ASSERT_RTNL();
3183+
netdev_ops_assert_locked(dev);
31833184

31843185
rc = net_rx_queue_update_kobjects(dev, dev->real_num_rx_queues,
31853186
rxq);
@@ -3191,7 +3192,6 @@ int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq)
31913192
return 0;
31923193
}
31933194
EXPORT_SYMBOL(netif_set_real_num_rx_queues);
3194-
#endif
31953195

31963196
/**
31973197
* netif_set_real_num_queues - set actual number of RX and TX queues used
@@ -6901,8 +6901,7 @@ void netif_queue_set_napi(struct net_device *dev, unsigned int queue_index,
69016901

69026902
if (WARN_ON_ONCE(napi && !napi->dev))
69036903
return;
6904-
if (dev->reg_state >= NETREG_REGISTERED)
6905-
ASSERT_RTNL();
6904+
netdev_ops_assert_locked_or_invisible(dev);
69066905

69076906
switch (type) {
69086907
case NETDEV_QUEUE_TYPE_RX:
@@ -10359,7 +10358,7 @@ u32 dev_get_min_mp_channel_count(const struct net_device *dev)
1035910358
{
1036010359
int i;
1036110360

10362-
ASSERT_RTNL();
10361+
netdev_ops_assert_locked(dev);
1036310362

1036410363
for (i = dev->real_num_rx_queues - 1; i >= 0; i--)
1036510364
if (dev->_rx[i].mp_params.mp_priv)
@@ -11963,9 +11962,9 @@ void unregister_netdevice_many_notify(struct list_head *head,
1196311962
dev_tcx_uninstall(dev);
1196411963
netdev_lock_ops(dev);
1196511964
dev_xdp_uninstall(dev);
11965+
dev_memory_provider_uninstall(dev);
1196611966
netdev_unlock_ops(dev);
1196711967
bpf_dev_bound_netdev_unregister(dev);
11968-
dev_memory_provider_uninstall(dev);
1196911968

1197011969
netdev_offload_xstats_disable_all(dev);
1197111970

net/core/devmem.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,10 @@ void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding)
128128
rxq->mp_params.mp_priv = NULL;
129129
rxq->mp_params.mp_ops = NULL;
130130

131-
netdev_lock(binding->dev);
132131
rxq_idx = get_netdev_rx_queue_index(rxq);
133132

134133
err = netdev_rx_queue_restart(binding->dev, rxq_idx);
135134
WARN_ON(err && err != -ENETDOWN);
136-
netdev_unlock(binding->dev);
137135
}
138136

139137
xa_erase(&net_devmem_dmabuf_bindings, binding->id);

net/core/net-sysfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2148,8 +2148,10 @@ static void remove_queue_kobjects(struct net_device *dev)
21482148
net_rx_queue_update_kobjects(dev, real_rx, 0);
21492149
netdev_queue_update_kobjects(dev, real_tx, 0);
21502150

2151+
netdev_lock_ops(dev);
21512152
dev->real_num_rx_queues = 0;
21522153
dev->real_num_tx_queues = 0;
2154+
netdev_unlock_ops(dev);
21532155
#ifdef CONFIG_SYSFS
21542156
kset_unregister(dev->queues_kset);
21552157
#endif

net/core/netdev-genl.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,13 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
867867
goto err_unlock_sock;
868868
}
869869

870+
if (!netdev_need_ops_lock(netdev)) {
871+
err = -EOPNOTSUPP;
872+
NL_SET_BAD_ATTR(info->extack,
873+
info->attrs[NETDEV_A_DEV_IFINDEX]);
874+
goto err_unlock;
875+
}
876+
870877
if (dev_xdp_prog_count(netdev)) {
871878
NL_SET_ERR_MSG(info->extack, "unable to bind dmabuf to device with XDP program attached");
872879
err = -EEXIST;
@@ -947,7 +954,9 @@ void netdev_nl_sock_priv_destroy(struct netdev_nl_sock *priv)
947954

948955
mutex_lock(&priv->lock);
949956
list_for_each_entry_safe(binding, temp, &priv->bindings, list) {
957+
netdev_lock(binding->dev);
950958
net_devmem_unbind_dmabuf(binding);
959+
netdev_unlock(binding->dev);
951960
}
952961
mutex_unlock(&priv->lock);
953962
}

net/core/netdev_rx_queue.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
9292
struct netdev_rx_queue *rxq;
9393
int ret;
9494

95+
if (!netdev_need_ops_lock(dev))
96+
return -EOPNOTSUPP;
97+
9598
if (ifq_idx >= dev->real_num_rx_queues)
9699
return -EINVAL;
97100
ifq_idx = array_index_nospec(ifq_idx, dev->real_num_rx_queues);

net/core/page_pool.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/slab.h>
1212
#include <linux/device.h>
1313

14+
#include <net/netdev_lock.h>
1415
#include <net/netdev_rx_queue.h>
1516
#include <net/page_pool/helpers.h>
1617
#include <net/page_pool/memory_provider.h>
@@ -279,11 +280,7 @@ static int page_pool_init(struct page_pool *pool,
279280
get_device(pool->p.dev);
280281

281282
if (pool->slow.flags & PP_FLAG_ALLOW_UNREADABLE_NETMEM) {
282-
/* We rely on rtnl_lock()ing to make sure netdev_rx_queue
283-
* configuration doesn't change while we're initializing
284-
* the page_pool.
285-
*/
286-
ASSERT_RTNL();
283+
netdev_assert_locked(pool->slow.netdev);
287284
rxq = __netif_get_rx_queue(pool->slow.netdev,
288285
pool->slow.queue_idx);
289286
pool->mp_priv = rxq->mp_params.mp_priv;

0 commit comments

Comments
 (0)