@@ -688,6 +688,7 @@ struct netdev_queue {
/* Subordinate device that the queue has been assigned to */
struct net_device *sb_dev;
#ifdef CONFIG_XDP_SOCKETS
+ /* "ops protected", see comment about net_device::lock */
struct xsk_buff_pool *pool;
#endif
@@ -20,12 +20,12 @@ struct netdev_rx_queue {
struct net_device *dev;
netdevice_tracker dev_tracker;
+ /* All fields below are "ops protected",
+ * see comment about net_device::lock
+ */
#ifdef CONFIG_XDP_SOCKETS
struct xsk_buff_pool *pool;
#endif
- /* NAPI instance for the queue
- * "ops protected", see comment about net_device::lock
- */
struct napi_struct *napi;
struct pp_memory_provider_params mp_params;
} ____cacheline_aligned_in_smp;
@@ -279,9 +279,14 @@ static void xp_release_deferred(struct work_struct *work)
{
struct xsk_buff_pool *pool = container_of(work, struct xsk_buff_pool,
work);
+ struct net_device *netdev = pool->netdev;
rtnl_lock();
- xp_clear_dev(pool);
+ if (netdev) {
+ netdev_lock_ops(netdev);
+ xp_clear_dev(pool);
+ netdev_unlock_ops(netdev);
+ }
rtnl_unlock();
if (pool->fq) {
Read accesses go via xsk_get_pool_from_qid(), the call coming from the core and gve look safe (other "ops locked" drivers don't support XSK). Write accesses go via xsk_reg_pool_at_qid() and xsk_clear_pool_at_qid(). Former is already under the ops lock, latter needs to be locked when coming from the workqueue via xp_clear_dev(). Signed-off-by: Jakub Kicinski <kuba@kernel.org> --- v2: - only clear if netdev still set v1: https://lore.kernel.org/20250312223507.805719-10-kuba@kernel.org --- include/linux/netdevice.h | 1 + include/net/netdev_rx_queue.h | 6 +++--- net/xdp/xsk_buff_pool.c | 7 ++++++- 3 files changed, 10 insertions(+), 4 deletions(-)