From 6859d1f2902c600f6b1c587c91408a91e05cdc02 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 31 Jul 2023 16:48:28 +1000 Subject: SUNRPC: make rqst_should_sleep() idempotent() Based on its name you would think that rqst_should_sleep() would be read-only, not changing anything. But in fact it will clear SP_TASK_PENDING if that was set. This is surprising, and it blurs the line between "check for work to do" and "dequeue work to do". So change the "test_and_clear" to simple "test" and clear the bit once the thread has decided to wake up and return to the caller. With this, it makes sense to *always* set SP_TASK_PENDING when asked, rather than to set it only if no thread could be woken up. [ cel: Previously TASK_PENDING indicated there is work waiting but no idle threads were found to pick up that work. After this patch, it acts as an XPT_BUSY flag for wake-ups that have no associated xprt. ] Signed-off-by: NeilBrown Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- net/sunrpc/svc_xprt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index d3280ae70e36..4cfe9640df48 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -581,8 +581,8 @@ void svc_wake_up(struct svc_serv *serv) { struct svc_pool *pool = &serv->sv_pools[0]; - if (!svc_pool_wake_idle_thread(pool)) - set_bit(SP_TASK_PENDING, &pool->sp_flags); + set_bit(SP_TASK_PENDING, &pool->sp_flags); + svc_pool_wake_idle_thread(pool); } EXPORT_SYMBOL_GPL(svc_wake_up); @@ -704,7 +704,7 @@ rqst_should_sleep(struct svc_rqst *rqstp) struct svc_pool *pool = rqstp->rq_pool; /* did someone call svc_wake_up? */ - if (test_and_clear_bit(SP_TASK_PENDING, &pool->sp_flags)) + if (test_bit(SP_TASK_PENDING, &pool->sp_flags)) return false; /* was a socket queued? */ @@ -748,6 +748,7 @@ static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp) set_bit(RQ_BUSY, &rqstp->rq_flags); smp_mb__after_atomic(); + clear_bit(SP_TASK_PENDING, &pool->sp_flags); rqstp->rq_xprt = svc_xprt_dequeue(pool); if (rqstp->rq_xprt) goto out_found; @@ -756,6 +757,7 @@ static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp) return NULL; return NULL; out_found: + clear_bit(SP_TASK_PENDING, &pool->sp_flags); /* Normally we will wait up to 5 seconds for any required * cache information to be provided. */ -- cgit v1.2.3