mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	[PATCH] RPC: separate xprt_timer implementations
Allow transports to hook the retransmit timer interrupt. Some transports calculate their congestion window here so that a retransmit timeout has immediate effect on the congestion window. Test-plan: Use WAN simulation to cause sporadic bursty packet loss. Look for significant regression in performance or client stability. Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
		
							parent
							
								
									49e9a89086
								
							
						
					
					
						commit
						46c0ee8bc4
					
				
					 3 changed files with 34 additions and 25 deletions
				
			
		| 
						 | 
				
			
			@ -137,6 +137,7 @@ struct rpc_xprt_ops {
 | 
			
		|||
	void		(*connect)(struct rpc_task *task);
 | 
			
		||||
	int		(*send_request)(struct rpc_task *task);
 | 
			
		||||
	void		(*set_retrans_timeout)(struct rpc_task *task);
 | 
			
		||||
	void		(*timer)(struct rpc_task *task);
 | 
			
		||||
	void		(*close)(struct rpc_xprt *xprt);
 | 
			
		||||
	void		(*destroy)(struct rpc_xprt *xprt);
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -257,6 +258,7 @@ void			xprt_set_retrans_timeout_rtt(struct rpc_task *task);
 | 
			
		|||
void			xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
 | 
			
		||||
void			xprt_wait_for_buffer_space(struct rpc_task *task);
 | 
			
		||||
void			xprt_write_space(struct rpc_xprt *xprt);
 | 
			
		||||
void			xprt_adjust_cwnd(struct rpc_task *task, int result);
 | 
			
		||||
struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
 | 
			
		||||
void			xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied);
 | 
			
		||||
void			xprt_disconnect(struct rpc_xprt *xprt);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -289,16 +289,19 @@ __xprt_put_cong(struct rpc_xprt *xprt, struct rpc_rqst *req)
 | 
			
		|||
	__xprt_lock_write_next_cong(xprt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Adjust RPC congestion window
 | 
			
		||||
/**
 | 
			
		||||
 * xprt_adjust_cwnd - adjust transport congestion window
 | 
			
		||||
 * @task: recently completed RPC request used to adjust window
 | 
			
		||||
 * @result: result code of completed RPC request
 | 
			
		||||
 *
 | 
			
		||||
 * We use a time-smoothed congestion estimator to avoid heavy oscillation.
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
 | 
			
		||||
void xprt_adjust_cwnd(struct rpc_task *task, int result)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long	cwnd;
 | 
			
		||||
	struct rpc_rqst *req = task->tk_rqstp;
 | 
			
		||||
	struct rpc_xprt *xprt = task->tk_xprt;
 | 
			
		||||
	unsigned long cwnd = xprt->cwnd;
 | 
			
		||||
 | 
			
		||||
	cwnd = xprt->cwnd;
 | 
			
		||||
	if (result >= 0 && cwnd <= xprt->cong) {
 | 
			
		||||
		/* The (cwnd >> 1) term makes sure
 | 
			
		||||
		 * the result gets rounded properly. */
 | 
			
		||||
| 
						 | 
				
			
			@ -314,6 +317,7 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
 | 
			
		|||
	dprintk("RPC:      cong %ld, cwnd was %ld, now %ld\n",
 | 
			
		||||
			xprt->cong, xprt->cwnd, cwnd);
 | 
			
		||||
	xprt->cwnd = cwnd;
 | 
			
		||||
	__xprt_put_cong(xprt, req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -602,8 +606,7 @@ void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
 | 
			
		|||
	/* Adjust congestion window */
 | 
			
		||||
	if (!xprt->nocong) {
 | 
			
		||||
		unsigned timer = task->tk_msg.rpc_proc->p_timer;
 | 
			
		||||
		xprt_adjust_cwnd(xprt, copied);
 | 
			
		||||
		__xprt_put_cong(xprt, req);
 | 
			
		||||
		xprt_adjust_cwnd(task, copied);
 | 
			
		||||
		if (timer) {
 | 
			
		||||
			if (req->rq_ntrans == 1)
 | 
			
		||||
				rpc_update_rtt(clnt->cl_rtt, timer,
 | 
			
		||||
| 
						 | 
				
			
			@ -640,27 +643,19 @@ void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
 | 
			
		|||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * RPC receive timeout handler.
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
xprt_timer(struct rpc_task *task)
 | 
			
		||||
static void xprt_timer(struct rpc_task *task)
 | 
			
		||||
{
 | 
			
		||||
	struct rpc_rqst	*req = task->tk_rqstp;
 | 
			
		||||
	struct rpc_rqst *req = task->tk_rqstp;
 | 
			
		||||
	struct rpc_xprt *xprt = req->rq_xprt;
 | 
			
		||||
 | 
			
		||||
	dprintk("RPC: %4d xprt_timer\n", task->tk_pid);
 | 
			
		||||
 | 
			
		||||
	spin_lock(&xprt->transport_lock);
 | 
			
		||||
	if (req->rq_received)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	xprt_adjust_cwnd(req->rq_xprt, -ETIMEDOUT);
 | 
			
		||||
	__xprt_put_cong(xprt, req);
 | 
			
		||||
 | 
			
		||||
	dprintk("RPC: %4d xprt_timer (%s request)\n",
 | 
			
		||||
		task->tk_pid, req ? "pending" : "backlogged");
 | 
			
		||||
 | 
			
		||||
	task->tk_status  = -ETIMEDOUT;
 | 
			
		||||
out:
 | 
			
		||||
	if (!req->rq_received) {
 | 
			
		||||
		if (xprt->ops->timer)
 | 
			
		||||
			xprt->ops->timer(task);
 | 
			
		||||
		task->tk_status = -ETIMEDOUT;
 | 
			
		||||
	}
 | 
			
		||||
	task->tk_timeout = 0;
 | 
			
		||||
	rpc_wake_up_task(task);
 | 
			
		||||
	spin_unlock(&xprt->transport_lock);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -860,6 +860,17 @@ static void xs_tcp_set_buffer_size(struct rpc_xprt *xprt)
 | 
			
		|||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * xs_udp_timer - called when a retransmit timeout occurs on a UDP transport
 | 
			
		||||
 * @task: task that timed out
 | 
			
		||||
 *
 | 
			
		||||
 * Adjust the congestion window after a retransmit timeout has occurred.
 | 
			
		||||
 */
 | 
			
		||||
static void xs_udp_timer(struct rpc_task *task)
 | 
			
		||||
{
 | 
			
		||||
	xprt_adjust_cwnd(task, -ETIMEDOUT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_in myaddr = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1050,6 +1061,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
 | 
			
		|||
	.connect		= xs_connect,
 | 
			
		||||
	.send_request		= xs_udp_send_request,
 | 
			
		||||
	.set_retrans_timeout	= xprt_set_retrans_timeout_rtt,
 | 
			
		||||
	.timer			= xs_udp_timer,
 | 
			
		||||
	.close			= xs_close,
 | 
			
		||||
	.destroy		= xs_destroy,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue