Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46c0ee8b authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust
Browse files

[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: default avatarChuck Lever <cel@netapp.com>
 Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 49e9a890
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -137,6 +137,7 @@ struct rpc_xprt_ops {
	void		(*connect)(struct rpc_task *task);
	void		(*connect)(struct rpc_task *task);
	int		(*send_request)(struct rpc_task *task);
	int		(*send_request)(struct rpc_task *task);
	void		(*set_retrans_timeout)(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		(*close)(struct rpc_xprt *xprt);
	void		(*destroy)(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_wake_pending_tasks(struct rpc_xprt *xprt, int status);
void			xprt_wait_for_buffer_space(struct rpc_task *task);
void			xprt_wait_for_buffer_space(struct rpc_task *task);
void			xprt_write_space(struct rpc_xprt *xprt);
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);
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_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied);
void			xprt_disconnect(struct rpc_xprt *xprt);
void			xprt_disconnect(struct rpc_xprt *xprt);
+20 −25
Original line number Original line Diff line number Diff line
@@ -289,16 +289,19 @@ __xprt_put_cong(struct rpc_xprt *xprt, struct rpc_rqst *req)
	__xprt_lock_write_next_cong(xprt);
	__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.
 * We use a time-smoothed congestion estimator to avoid heavy oscillation.
 */
 */
static void
void xprt_adjust_cwnd(struct rpc_task *task, int result)
xprt_adjust_cwnd(struct rpc_xprt *xprt, 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) {
	if (result >= 0 && cwnd <= xprt->cong) {
		/* The (cwnd >> 1) term makes sure
		/* The (cwnd >> 1) term makes sure
		 * the result gets rounded properly. */
		 * 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",
	dprintk("RPC:      cong %ld, cwnd was %ld, now %ld\n",
			xprt->cong, xprt->cwnd, cwnd);
			xprt->cong, xprt->cwnd, cwnd);
	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 */
	/* Adjust congestion window */
	if (!xprt->nocong) {
	if (!xprt->nocong) {
		unsigned timer = task->tk_msg.rpc_proc->p_timer;
		unsigned timer = task->tk_msg.rpc_proc->p_timer;
		xprt_adjust_cwnd(xprt, copied);
		xprt_adjust_cwnd(task, copied);
		__xprt_put_cong(xprt, req);
		if (timer) {
		if (timer) {
			if (req->rq_ntrans == 1)
			if (req->rq_ntrans == 1)
				rpc_update_rtt(clnt->cl_rtt, timer,
				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;
	return;
}
}


/*
static void xprt_timer(struct rpc_task *task)
 * RPC receive timeout handler.
 */
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;
	struct rpc_xprt *xprt = req->rq_xprt;


	spin_lock(&xprt->transport_lock);
	dprintk("RPC: %4d xprt_timer\n", task->tk_pid);
	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");


	spin_lock(&xprt->transport_lock);
	if (!req->rq_received) {
		if (xprt->ops->timer)
			xprt->ops->timer(task);
		task->tk_status = -ETIMEDOUT;
		task->tk_status = -ETIMEDOUT;
out:
	}
	task->tk_timeout = 0;
	task->tk_timeout = 0;
	rpc_wake_up_task(task);
	rpc_wake_up_task(task);
	spin_unlock(&xprt->transport_lock);
	spin_unlock(&xprt->transport_lock);
+12 −0
Original line number Original line Diff line number Diff line
@@ -860,6 +860,17 @@ static void xs_tcp_set_buffer_size(struct rpc_xprt *xprt)
	return;
	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)
static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
{
{
	struct sockaddr_in myaddr = {
	struct sockaddr_in myaddr = {
@@ -1050,6 +1061,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
	.connect		= xs_connect,
	.connect		= xs_connect,
	.send_request		= xs_udp_send_request,
	.send_request		= xs_udp_send_request,
	.set_retrans_timeout	= xprt_set_retrans_timeout_rtt,
	.set_retrans_timeout	= xprt_set_retrans_timeout_rtt,
	.timer			= xs_udp_timer,
	.close			= xs_close,
	.close			= xs_close,
	.destroy		= xs_destroy,
	.destroy		= xs_destroy,
};
};