Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: prevent deadlocks when enabling NAPIs with mixed kthread config

The following order of calls currently deadlocks if:
- device has threaded=1; and
- NAPI has persistent config with threaded=0.

netif_napi_add_weight_config()
dev->threaded == 1
napi_kthread_create()

napi_enable()
napi_restore_config()
napi_set_threaded(0)
napi_stop_kthread()
while (NAPIF_STATE_SCHED)
msleep(20)

We deadlock because disabled NAPI has STATE_SCHED set.
Creating a thread in netif_napi_add() just to destroy it in
napi_disable() is fairly ugly in the first place. Let's read
both the device config and the NAPI config in netif_napi_add().

Fixes: e6d76268813d ("net: Update threaded state in napi config in netif_set_threaded")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20250809001205.1147153-4-kuba@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Jakub Kicinski and committed by
Paolo Abeni
b3fc08ab ccba9f6b

+11 -2
+3 -2
net/core/dev.c
··· 7357 7357 * Clear dev->threaded if kthread creation failed so that 7358 7358 * threaded mode will not be enabled in napi_enable(). 7359 7359 */ 7360 - if (dev->threaded && napi_kthread_create(napi)) 7361 - dev->threaded = NETDEV_NAPI_THREADED_DISABLED; 7360 + if (napi_get_threaded_config(dev, napi)) 7361 + if (napi_kthread_create(napi)) 7362 + dev->threaded = NETDEV_NAPI_THREADED_DISABLED; 7362 7363 netif_napi_set_irq_locked(napi, -1); 7363 7364 } 7364 7365 EXPORT_SYMBOL(netif_napi_add_weight_locked);
+8
net/core/dev.h
··· 323 323 return NETDEV_NAPI_THREADED_DISABLED; 324 324 } 325 325 326 + static inline enum netdev_napi_threaded 327 + napi_get_threaded_config(struct net_device *dev, struct napi_struct *n) 328 + { 329 + if (n->config) 330 + return n->config->threaded; 331 + return dev->threaded; 332 + } 333 + 326 334 int napi_set_threaded(struct napi_struct *n, 327 335 enum netdev_napi_threaded threaded); 328 336