aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <cel@netapp.com>2005-08-25 19:25:52 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-09-23 12:38:41 -0400
commit46c0ee8bc4ad3743de05e8b8b20201df44dcb6d3 (patch)
tree6b2993ff1cefb69cc3cc40c3605d088ea2af3c98
parent49e9a89086b3cae784a4868ca852863e4f4ea3fe (diff)
[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>
-rw-r--r--include/linux/sunrpc/xprt.h2
-rw-r--r--net/sunrpc/xprt.c45
-rw-r--r--net/sunrpc/xprtsock.c12
3 files changed, 34 insertions, 25 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 86833b725bb5..443c3f984cf9 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -137,6 +137,7 @@ struct rpc_xprt_ops {
137 void (*connect)(struct rpc_task *task); 137 void (*connect)(struct rpc_task *task);
138 int (*send_request)(struct rpc_task *task); 138 int (*send_request)(struct rpc_task *task);
139 void (*set_retrans_timeout)(struct rpc_task *task); 139 void (*set_retrans_timeout)(struct rpc_task *task);
140 void (*timer)(struct rpc_task *task);
140 void (*close)(struct rpc_xprt *xprt); 141 void (*close)(struct rpc_xprt *xprt);
141 void (*destroy)(struct rpc_xprt *xprt); 142 void (*destroy)(struct rpc_xprt *xprt);
142}; 143};
@@ -257,6 +258,7 @@ void xprt_set_retrans_timeout_rtt(struct rpc_task *task);
257void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status); 258void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
258void xprt_wait_for_buffer_space(struct rpc_task *task); 259void xprt_wait_for_buffer_space(struct rpc_task *task);
259void xprt_write_space(struct rpc_xprt *xprt); 260void xprt_write_space(struct rpc_xprt *xprt);
261void xprt_adjust_cwnd(struct rpc_task *task, int result);
260struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid); 262struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
261void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied); 263void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied);
262void xprt_disconnect(struct rpc_xprt *xprt); 264void xprt_disconnect(struct rpc_xprt *xprt);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index e92ea99dd318..ffc595592af3 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -289,16 +289,19 @@ __xprt_put_cong(struct rpc_xprt *xprt, struct rpc_rqst *req)
289 __xprt_lock_write_next_cong(xprt); 289 __xprt_lock_write_next_cong(xprt);
290} 290}
291 291
292/* 292/**
293 * Adjust RPC congestion window 293 * xprt_adjust_cwnd - adjust transport congestion window
294 * @task: recently completed RPC request used to adjust window
295 * @result: result code of completed RPC request
296 *
294 * We use a time-smoothed congestion estimator to avoid heavy oscillation. 297 * We use a time-smoothed congestion estimator to avoid heavy oscillation.
295 */ 298 */
296static void 299void xprt_adjust_cwnd(struct rpc_task *task, int result)
297xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
298{ 300{
299 unsigned long cwnd; 301 struct rpc_rqst *req = task->tk_rqstp;
302 struct rpc_xprt *xprt = task->tk_xprt;
303 unsigned long cwnd = xprt->cwnd;
300 304
301 cwnd = xprt->cwnd;
302 if (result >= 0 && cwnd <= xprt->cong) { 305 if (result >= 0 && cwnd <= xprt->cong) {
303 /* The (cwnd >> 1) term makes sure 306 /* The (cwnd >> 1) term makes sure
304 * the result gets rounded properly. */ 307 * the result gets rounded properly. */
@@ -314,6 +317,7 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
314 dprintk("RPC: cong %ld, cwnd was %ld, now %ld\n", 317 dprintk("RPC: cong %ld, cwnd was %ld, now %ld\n",
315 xprt->cong, xprt->cwnd, cwnd); 318 xprt->cong, xprt->cwnd, cwnd);
316 xprt->cwnd = cwnd; 319 xprt->cwnd = cwnd;
320 __xprt_put_cong(xprt, req);
317} 321}
318 322
319/** 323/**
@@ -602,8 +606,7 @@ void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
602 /* Adjust congestion window */ 606 /* Adjust congestion window */
603 if (!xprt->nocong) { 607 if (!xprt->nocong) {
604 unsigned timer = task->tk_msg.rpc_proc->p_timer; 608 unsigned timer = task->tk_msg.rpc_proc->p_timer;
605 xprt_adjust_cwnd(xprt, copied); 609 xprt_adjust_cwnd(task, copied);
606 __xprt_put_cong(xprt, req);
607 if (timer) { 610 if (timer) {
608 if (req->rq_ntrans == 1) 611 if (req->rq_ntrans == 1)
609 rpc_update_rtt(clnt->cl_rtt, timer, 612 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)
640 return; 643 return;
641} 644}
642 645
643/* 646static void xprt_timer(struct rpc_task *task)
644 * RPC receive timeout handler.
645 */
646static void
647xprt_timer(struct rpc_task *task)
648{ 647{
649 struct rpc_rqst *req = task->tk_rqstp; 648 struct rpc_rqst *req = task->tk_rqstp;
650 struct rpc_xprt *xprt = req->rq_xprt; 649 struct rpc_xprt *xprt = req->rq_xprt;
651 650
652 spin_lock(&xprt->transport_lock); 651 dprintk("RPC: %4d xprt_timer\n", task->tk_pid);
653 if (req->rq_received)
654 goto out;
655
656 xprt_adjust_cwnd(req->rq_xprt, -ETIMEDOUT);
657 __xprt_put_cong(xprt, req);
658 652
659 dprintk("RPC: %4d xprt_timer (%s request)\n", 653 spin_lock(&xprt->transport_lock);
660 task->tk_pid, req ? "pending" : "backlogged"); 654 if (!req->rq_received) {
661 655 if (xprt->ops->timer)
662 task->tk_status = -ETIMEDOUT; 656 xprt->ops->timer(task);
663out: 657 task->tk_status = -ETIMEDOUT;
658 }
664 task->tk_timeout = 0; 659 task->tk_timeout = 0;
665 rpc_wake_up_task(task); 660 rpc_wake_up_task(task);
666 spin_unlock(&xprt->transport_lock); 661 spin_unlock(&xprt->transport_lock);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 8589c1ad55e3..c3658ff027a6 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -860,6 +860,17 @@ static void xs_tcp_set_buffer_size(struct rpc_xprt *xprt)
860 return; 860 return;
861} 861}
862 862
863/**
864 * xs_udp_timer - called when a retransmit timeout occurs on a UDP transport
865 * @task: task that timed out
866 *
867 * Adjust the congestion window after a retransmit timeout has occurred.
868 */
869static void xs_udp_timer(struct rpc_task *task)
870{
871 xprt_adjust_cwnd(task, -ETIMEDOUT);
872}
873
863static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) 874static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
864{ 875{
865 struct sockaddr_in myaddr = { 876 struct sockaddr_in myaddr = {
@@ -1050,6 +1061,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
1050 .connect = xs_connect, 1061 .connect = xs_connect,
1051 .send_request = xs_udp_send_request, 1062 .send_request = xs_udp_send_request,
1052 .set_retrans_timeout = xprt_set_retrans_timeout_rtt, 1063 .set_retrans_timeout = xprt_set_retrans_timeout_rtt,
1064 .timer = xs_udp_timer,
1053 .close = xs_close, 1065 .close = xs_close,
1054 .destroy = xs_destroy, 1066 .destroy = xs_destroy,
1055}; 1067};