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 | }; |
