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:43 -0400 |
commit | 1570c1e41eabf6b7031f3e4322a2cf1cbe319fee (patch) | |
tree | eee53757ac3e03d55b6c01bb0500996ba520a8bb | |
parent | 46c0ee8bc4ad3743de05e8b8b20201df44dcb6d3 (diff) |
[PATCH] RPC: add generic interface for adjusting the congestion window
A new interface that allows transports to adjust their congestion window
using the Van Jacobson implementation in xprt.c is provided.
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 | 3 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 66 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 13 |
3 files changed, 33 insertions, 49 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 443c3f984cf9..2e48752d55d9 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
@@ -258,9 +258,10 @@ void xprt_set_retrans_timeout_rtt(struct rpc_task *task); | |||
258 | void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status); | 258 | void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status); |
259 | void xprt_wait_for_buffer_space(struct rpc_task *task); | 259 | void xprt_wait_for_buffer_space(struct rpc_task *task); |
260 | void xprt_write_space(struct rpc_xprt *xprt); | 260 | void xprt_write_space(struct rpc_xprt *xprt); |
261 | void xprt_update_rtt(struct rpc_task *task); | ||
261 | void xprt_adjust_cwnd(struct rpc_task *task, int result); | 262 | void xprt_adjust_cwnd(struct rpc_task *task, int result); |
262 | struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid); | 263 | struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid); |
263 | void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied); | 264 | void xprt_complete_rqst(struct rpc_task *task, int copied); |
264 | void xprt_disconnect(struct rpc_xprt *xprt); | 265 | void xprt_disconnect(struct rpc_xprt *xprt); |
265 | 266 | ||
266 | /* | 267 | /* |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index ffc595592af3..707806fe1a23 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -592,55 +592,41 @@ struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid) | |||
592 | } | 592 | } |
593 | 593 | ||
594 | /** | 594 | /** |
595 | * xprt_update_rtt - update an RPC client's RTT state after receiving a reply | ||
596 | * @task: RPC request that recently completed | ||
597 | * | ||
598 | */ | ||
599 | void xprt_update_rtt(struct rpc_task *task) | ||
600 | { | ||
601 | struct rpc_rqst *req = task->tk_rqstp; | ||
602 | struct rpc_rtt *rtt = task->tk_client->cl_rtt; | ||
603 | unsigned timer = task->tk_msg.rpc_proc->p_timer; | ||
604 | |||
605 | if (timer) { | ||
606 | if (req->rq_ntrans == 1) | ||
607 | rpc_update_rtt(rtt, timer, | ||
608 | (long)jiffies - req->rq_xtime); | ||
609 | rpc_set_timeo(rtt, timer, req->rq_ntrans - 1); | ||
610 | } | ||
611 | } | ||
612 | |||
613 | /** | ||
595 | * xprt_complete_rqst - called when reply processing is complete | 614 | * xprt_complete_rqst - called when reply processing is complete |
596 | * @xprt: controlling transport | 615 | * @task: RPC request that recently completed |
597 | * @req: RPC request that just completed | ||
598 | * @copied: actual number of bytes received from the transport | 616 | * @copied: actual number of bytes received from the transport |
599 | * | 617 | * |
618 | * Caller holds transport lock. | ||
600 | */ | 619 | */ |
601 | void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied) | 620 | void xprt_complete_rqst(struct rpc_task *task, int copied) |
602 | { | 621 | { |
603 | struct rpc_task *task = req->rq_task; | 622 | struct rpc_rqst *req = task->tk_rqstp; |
604 | struct rpc_clnt *clnt = task->tk_client; | ||
605 | |||
606 | /* Adjust congestion window */ | ||
607 | if (!xprt->nocong) { | ||
608 | unsigned timer = task->tk_msg.rpc_proc->p_timer; | ||
609 | xprt_adjust_cwnd(task, copied); | ||
610 | if (timer) { | ||
611 | if (req->rq_ntrans == 1) | ||
612 | rpc_update_rtt(clnt->cl_rtt, timer, | ||
613 | (long)jiffies - req->rq_xtime); | ||
614 | rpc_set_timeo(clnt->cl_rtt, timer, req->rq_ntrans - 1); | ||
615 | } | ||
616 | } | ||
617 | 623 | ||
618 | #ifdef RPC_PROFILE | 624 | dprintk("RPC: %5u xid %08x complete (%d bytes received)\n", |
619 | /* Profile only reads for now */ | 625 | task->tk_pid, ntohl(req->rq_xid), copied); |
620 | if (copied > 1024) { | ||
621 | static unsigned long nextstat; | ||
622 | static unsigned long pkt_rtt, pkt_len, pkt_cnt; | ||
623 | |||
624 | pkt_cnt++; | ||
625 | pkt_len += req->rq_slen + copied; | ||
626 | pkt_rtt += jiffies - req->rq_xtime; | ||
627 | if (time_before(nextstat, jiffies)) { | ||
628 | printk("RPC: %lu %ld cwnd\n", jiffies, xprt->cwnd); | ||
629 | printk("RPC: %ld %ld %ld %ld stat\n", | ||
630 | jiffies, pkt_cnt, pkt_len, pkt_rtt); | ||
631 | pkt_rtt = pkt_len = pkt_cnt = 0; | ||
632 | nextstat = jiffies + 5 * HZ; | ||
633 | } | ||
634 | } | ||
635 | #endif | ||
636 | 626 | ||
637 | dprintk("RPC: %4d has input (%d bytes)\n", task->tk_pid, copied); | ||
638 | list_del_init(&req->rq_list); | 627 | list_del_init(&req->rq_list); |
639 | req->rq_received = req->rq_private_buf.len = copied; | 628 | req->rq_received = req->rq_private_buf.len = copied; |
640 | |||
641 | /* ... and wake up the process. */ | ||
642 | rpc_wake_up_task(task); | 629 | rpc_wake_up_task(task); |
643 | return; | ||
644 | } | 630 | } |
645 | 631 | ||
646 | static void xprt_timer(struct rpc_task *task) | 632 | static void xprt_timer(struct rpc_task *task) |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index c3658ff027a6..980f26504f48 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -460,8 +460,6 @@ static void xs_udp_data_ready(struct sock *sk, int len) | |||
460 | goto out_unlock; | 460 | goto out_unlock; |
461 | task = rovr->rq_task; | 461 | task = rovr->rq_task; |
462 | 462 | ||
463 | dprintk("RPC: %4d received reply\n", task->tk_pid); | ||
464 | |||
465 | if ((copied = rovr->rq_private_buf.buflen) > repsize) | 463 | if ((copied = rovr->rq_private_buf.buflen) > repsize) |
466 | copied = repsize; | 464 | copied = repsize; |
467 | 465 | ||
@@ -472,7 +470,9 @@ static void xs_udp_data_ready(struct sock *sk, int len) | |||
472 | /* Something worked... */ | 470 | /* Something worked... */ |
473 | dst_confirm(skb->dst); | 471 | dst_confirm(skb->dst); |
474 | 472 | ||
475 | xprt_complete_rqst(xprt, rovr, copied); | 473 | xprt_adjust_cwnd(task, copied); |
474 | xprt_update_rtt(task); | ||
475 | xprt_complete_rqst(task, copied); | ||
476 | 476 | ||
477 | out_unlock: | 477 | out_unlock: |
478 | spin_unlock(&xprt->transport_lock); | 478 | spin_unlock(&xprt->transport_lock); |
@@ -634,11 +634,8 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc | |||
634 | } | 634 | } |
635 | 635 | ||
636 | out: | 636 | out: |
637 | if (!(xprt->tcp_flags & XPRT_COPY_DATA)) { | 637 | if (!(xprt->tcp_flags & XPRT_COPY_DATA)) |
638 | dprintk("RPC: %4d received reply complete\n", | 638 | xprt_complete_rqst(req->rq_task, xprt->tcp_copied); |
639 | req->rq_task->tk_pid); | ||
640 | xprt_complete_rqst(xprt, req, xprt->tcp_copied); | ||
641 | } | ||
642 | spin_unlock(&xprt->transport_lock); | 639 | spin_unlock(&xprt->transport_lock); |
643 | xs_tcp_check_recm(xprt); | 640 | xs_tcp_check_recm(xprt); |
644 | } | 641 | } |