diff options
author | Chuck Lever <cel@netapp.com> | 2005-08-25 19:25:52 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-09-23 12:38:41 -0400 |
commit | 46c0ee8bc4ad3743de05e8b8b20201df44dcb6d3 (patch) | |
tree | 6b2993ff1cefb69cc3cc40c3605d088ea2af3c98 | |
parent | 49e9a89086b3cae784a4868ca852863e4f4ea3fe (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.h | 2 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 45 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 12 |
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); | |||
257 | void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status); | 258 | void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status); |
258 | void xprt_wait_for_buffer_space(struct rpc_task *task); | 259 | void xprt_wait_for_buffer_space(struct rpc_task *task); |
259 | void xprt_write_space(struct rpc_xprt *xprt); | 260 | void xprt_write_space(struct rpc_xprt *xprt); |
261 | void xprt_adjust_cwnd(struct rpc_task *task, int result); | ||
260 | struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid); | 262 | struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid); |
261 | void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied); | 263 | void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied); |
262 | void xprt_disconnect(struct rpc_xprt *xprt); | 264 | void 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 | */ |
296 | static void | 299 | void xprt_adjust_cwnd(struct rpc_task *task, int result) |
297 | xprt_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 | /* | 646 | static void xprt_timer(struct rpc_task *task) |
644 | * RPC receive timeout handler. | ||
645 | */ | ||
646 | static void | ||
647 | xprt_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); |
663 | out: | 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 | */ | ||
869 | static void xs_udp_timer(struct rpc_task *task) | ||
870 | { | ||
871 | xprt_adjust_cwnd(task, -ETIMEDOUT); | ||
872 | } | ||
873 | |||
863 | static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) | 874 | static 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 | }; |