Re: [PATCH 2/6] SUNRPC: rename and refactor svc_get_next_xprt()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Aug 02, 2023 at 05:34:39PM +1000, NeilBrown wrote:
> svc_get_next_xprt() does a lot more than just get an xprt.  It also
> decides if it needs to sleep, depending not only on the availability of
> xprts but also on the need to exit or handle external work.
> 
> So rename it to svc_rqst_wait_for_work() and only do the testing and
> waiting.  Move all the waiting-related code out of svc_recv() into the
> new svc_rqst_wait_for_work().
> 
> Move the dequeueing code out of svc_get_next_xprt() into svc_recv().
> 
> Previously svc_xprt_dequeue() would be called twice, once before waiting
> and possibly once after.  Now instead rqst_should_sleep() is called
> twice.  Once to decide if waiting is needed, and once to check against
> after setting the task state do see if we might have missed a wakeup.
> 
> signed-off-by: NeilBrown <neilb@xxxxxxx>

I've tested and applied this one and the previous one to the thread
scheduling branch, with a few minor fix-ups. Apologies for how long
this took, I'm wrestling with a SATA/block bug on the v6.6 test
system that is being very sassy and hard to nail down.

I need to dive into the backchannel patch next. I'm trying to think
of how I want to test that one.


> ---
>  net/sunrpc/svc_xprt.c | 91 ++++++++++++++++++++-----------------------
>  1 file changed, 43 insertions(+), 48 deletions(-)
> 
> diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
> index 60759647fee4..f1d64ded89fb 100644
> --- a/net/sunrpc/svc_xprt.c
> +++ b/net/sunrpc/svc_xprt.c
> @@ -722,51 +722,33 @@ rqst_should_sleep(struct svc_rqst *rqstp)
>  	return true;
>  }
>  
> -static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp)
> +static void svc_rqst_wait_for_work(struct svc_rqst *rqstp)
>  {
> -	struct svc_pool		*pool = rqstp->rq_pool;
> -
> -	/* rq_xprt should be clear on entry */
> -	WARN_ON_ONCE(rqstp->rq_xprt);
> +	struct svc_pool *pool = rqstp->rq_pool;
>  
> -	rqstp->rq_xprt = svc_xprt_dequeue(pool);
> -	if (rqstp->rq_xprt)
> -		goto out_found;
> -
> -	set_current_state(TASK_IDLE);
> -	smp_mb__before_atomic();
> -	clear_bit(SP_CONGESTED, &pool->sp_flags);
> -	clear_bit(RQ_BUSY, &rqstp->rq_flags);
> -	smp_mb__after_atomic();
> -
> -	if (likely(rqst_should_sleep(rqstp)))
> -		schedule();
> -	else
> -		__set_current_state(TASK_RUNNING);
> +	if (rqst_should_sleep(rqstp)) {
> +		set_current_state(TASK_IDLE);
> +		smp_mb__before_atomic();
> +		clear_bit(SP_CONGESTED, &pool->sp_flags);
> +		clear_bit(RQ_BUSY, &rqstp->rq_flags);
> +		smp_mb__after_atomic();
> +
> +		/* Need to check should_sleep() again after
> +		 * setting task state in case a wakeup happened
> +		 * between testing and setting.
> +		 */
> +		if (rqst_should_sleep(rqstp)) {
> +			schedule();
> +		} else {
> +			__set_current_state(TASK_RUNNING);
> +			cond_resched();
> +		}
>  
> +		set_bit(RQ_BUSY, &rqstp->rq_flags);
> +		smp_mb__after_atomic();
> +	} else
> +		cond_resched();
>  	try_to_freeze();
> -
> -	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;
> -
> -	if (kthread_should_stop())
> -		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.
> -	 */
> -	if (!test_bit(SP_CONGESTED, &pool->sp_flags))
> -		rqstp->rq_chandle.thread_wait = 5*HZ;
> -	else
> -		rqstp->rq_chandle.thread_wait = 1*HZ;
> -	trace_svc_xprt_dequeue(rqstp);
> -	return rqstp->rq_xprt;
>  }
>  
>  static void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt)
> @@ -858,20 +840,33 @@ static void svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
>   */
>  void svc_recv(struct svc_rqst *rqstp)
>  {
> -	struct svc_xprt		*xprt = NULL;
> +	struct svc_pool *pool = rqstp->rq_pool;
>  
>  	if (!svc_alloc_arg(rqstp))
>  		return;
>  
> -	try_to_freeze();
> -	cond_resched();
> +	svc_rqst_wait_for_work(rqstp);
> +
> +	clear_bit(SP_TASK_PENDING, &pool->sp_flags);
> +
>  	if (kthread_should_stop())
> -		goto out;
> +		return;
> +
> +	rqstp->rq_xprt = svc_xprt_dequeue(pool);
> +	if (rqstp->rq_xprt) {
> +		struct svc_xprt *xprt = rqstp->rq_xprt;
> +
> +		/* Normally we will wait up to 5 seconds for any required
> +		 * cache information to be provided.
> +		 */
> +		if (test_bit(SP_CONGESTED, &pool->sp_flags))
> +			rqstp->rq_chandle.thread_wait = 5 * HZ;
> +		else
> +			rqstp->rq_chandle.thread_wait = 1 * HZ;
>  
> -	xprt = svc_get_next_xprt(rqstp);
> -	if (xprt)
> +		trace_svc_xprt_dequeue(rqstp);
>  		svc_handle_xprt(rqstp, xprt);
> -out:
> +	}
>  }
>  EXPORT_SYMBOL_GPL(svc_recv);
>  
> -- 
> 2.40.1
> 

-- 
Chuck Lever



[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux