On Thu, 1 Apr 2021 00:46:18 +0200 Paolo Abeni wrote: > I hit an hangup on napi_disable(), when the threaded > mode is enabled and the napi is under heavy traffic. > > If the relevant napi has been scheduled and the napi_disable() > kicks in before the next napi_threaded_wait() completes - so > that the latter quits due to the napi_disable_pending() condition, > the existing code leaves the NAPI_STATE_SCHED bit set and the > napi_disable() loop waiting for such bit will hang. > > Address the issue explicitly clearing the SCHED_BIT on napi_thread > termination, if the thread is owns the napi. > > Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support") > Signed-off-by: Paolo Abeni <pab...@redhat.com> > --- > net/core/dev.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/net/core/dev.c b/net/core/dev.c > index b4c67a5be606d..e2e716ba027b8 100644 > --- a/net/core/dev.c > +++ b/net/core/dev.c > @@ -7059,6 +7059,14 @@ static int napi_thread_wait(struct napi_struct *napi) > set_current_state(TASK_INTERRUPTIBLE); > } > __set_current_state(TASK_RUNNING); > + > + /* if the thread owns this napi, and the napi itself has been disabled > + * in-between napi_schedule() and the above napi_disable_pending() > + * check, we need to clear the SCHED bit here, or napi_disable > + * will hang waiting for such bit being cleared > + */ > + if (test_bit(NAPI_STATE_SCHED_THREADED, &napi->state) || woken) > + clear_bit(NAPI_STATE_SCHED, &napi->state);
Not sure this covers 100% of the cases. We depend on the ability to go through schedule() "unnecessarily" when the napi gets scheduled after we go into TASK_INTERRUPTIBLE. If we just check woken outside of the loop it may be false even though we got a "wake event". Looking closer now I don't really understand where we ended up with disable handling :S Seems like the thread exits on napi_disable(), but is reaped by netif_napi_del(). Some drivers (*cough* nfp) will go napi_disable() -> napi_enable()... and that will break. Am I missing something? Should we not stay in the wait loop on napi_disable()?