aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprt.c
diff options
context:
space:
mode:
authorChuck Lever <cel@netapp.com>2005-08-25 19:25:51 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-09-23 12:38:40 -0400
commit49e9a89086b3cae784a4868ca852863e4f4ea3fe (patch)
tree5ba197fc1767fee5590b892b2f19aeb3583494c4 /net/sunrpc/xprt.c
parent12a804698b29d040b7cdd92e8a44b0e75164dae9 (diff)
[PATCH] RPC: expose API for serializing access to RPC transports
The next method we abstract is the one that releases a transport, allowing another task to have access to the transport. Again, one generic version of this is provided for transports that don't need the RPC client to perform congestion control, and one version is for transports that can use the original Van Jacobson implementation in xprt.c. 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>
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r--net/sunrpc/xprt.c77
1 files changed, 63 insertions, 14 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 2d1e8b83dd68..e92ea99dd318 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -153,14 +153,42 @@ static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
153 return retval; 153 return retval;
154} 154}
155 155
156
157static void __xprt_lock_write_next(struct rpc_xprt *xprt) 156static void __xprt_lock_write_next(struct rpc_xprt *xprt)
158{ 157{
159 struct rpc_task *task; 158 struct rpc_task *task;
159 struct rpc_rqst *req;
160
161 if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
162 return;
163
164 task = rpc_wake_up_next(&xprt->resend);
165 if (!task) {
166 task = rpc_wake_up_next(&xprt->sending);
167 if (!task)
168 goto out_unlock;
169 }
170
171 req = task->tk_rqstp;
172 xprt->snd_task = task;
173 if (req) {
174 req->rq_bytes_sent = 0;
175 req->rq_ntrans++;
176 }
177 return;
178
179out_unlock:
180 smp_mb__before_clear_bit();
181 clear_bit(XPRT_LOCKED, &xprt->state);
182 smp_mb__after_clear_bit();
183}
184
185static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt)
186{
187 struct rpc_task *task;
160 188
161 if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) 189 if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
162 return; 190 return;
163 if (!xprt->nocong && RPCXPRT_CONGESTED(xprt)) 191 if (RPCXPRT_CONGESTED(xprt))
164 goto out_unlock; 192 goto out_unlock;
165 task = rpc_wake_up_next(&xprt->resend); 193 task = rpc_wake_up_next(&xprt->resend);
166 if (!task) { 194 if (!task) {
@@ -168,7 +196,7 @@ static void __xprt_lock_write_next(struct rpc_xprt *xprt)
168 if (!task) 196 if (!task)
169 goto out_unlock; 197 goto out_unlock;
170 } 198 }
171 if (xprt->nocong || __xprt_get_cong(xprt, task)) { 199 if (__xprt_get_cong(xprt, task)) {
172 struct rpc_rqst *req = task->tk_rqstp; 200 struct rpc_rqst *req = task->tk_rqstp;
173 xprt->snd_task = task; 201 xprt->snd_task = task;
174 if (req) { 202 if (req) {
@@ -183,11 +211,14 @@ out_unlock:
183 smp_mb__after_clear_bit(); 211 smp_mb__after_clear_bit();
184} 212}
185 213
186/* 214/**
187 * Releases the transport for use by other requests. 215 * xprt_release_xprt - allow other requests to use a transport
216 * @xprt: transport with other tasks potentially waiting
217 * @task: task that is releasing access to the transport
218 *
219 * Note that "task" can be NULL. No congestion control is provided.
188 */ 220 */
189static void 221void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
190__xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
191{ 222{
192 if (xprt->snd_task == task) { 223 if (xprt->snd_task == task) {
193 xprt->snd_task = NULL; 224 xprt->snd_task = NULL;
@@ -198,11 +229,29 @@ __xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
198 } 229 }
199} 230}
200 231
201static inline void 232/**
202xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task) 233 * xprt_release_xprt_cong - allow other requests to use a transport
234 * @xprt: transport with other tasks potentially waiting
235 * @task: task that is releasing access to the transport
236 *
237 * Note that "task" can be NULL. Another task is awoken to use the
238 * transport if the transport's congestion window allows it.
239 */
240void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
241{
242 if (xprt->snd_task == task) {
243 xprt->snd_task = NULL;
244 smp_mb__before_clear_bit();
245 clear_bit(XPRT_LOCKED, &xprt->state);
246 smp_mb__after_clear_bit();
247 __xprt_lock_write_next_cong(xprt);
248 }
249}
250
251static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
203{ 252{
204 spin_lock_bh(&xprt->transport_lock); 253 spin_lock_bh(&xprt->transport_lock);
205 __xprt_release_write(xprt, task); 254 xprt->ops->release_xprt(xprt, task);
206 spin_unlock_bh(&xprt->transport_lock); 255 spin_unlock_bh(&xprt->transport_lock);
207} 256}
208 257
@@ -237,7 +286,7 @@ __xprt_put_cong(struct rpc_xprt *xprt, struct rpc_rqst *req)
237 return; 286 return;
238 req->rq_cong = 0; 287 req->rq_cong = 0;
239 xprt->cong -= RPC_CWNDSCALE; 288 xprt->cong -= RPC_CWNDSCALE;
240 __xprt_lock_write_next(xprt); 289 __xprt_lock_write_next_cong(xprt);
241} 290}
242 291
243/* 292/*
@@ -256,7 +305,7 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
256 cwnd += (RPC_CWNDSCALE * RPC_CWNDSCALE + (cwnd >> 1)) / cwnd; 305 cwnd += (RPC_CWNDSCALE * RPC_CWNDSCALE + (cwnd >> 1)) / cwnd;
257 if (cwnd > RPC_MAXCWND(xprt)) 306 if (cwnd > RPC_MAXCWND(xprt))
258 cwnd = RPC_MAXCWND(xprt); 307 cwnd = RPC_MAXCWND(xprt);
259 __xprt_lock_write_next(xprt); 308 __xprt_lock_write_next_cong(xprt);
260 } else if (result == -ETIMEDOUT) { 309 } else if (result == -ETIMEDOUT) {
261 cwnd >>= 1; 310 cwnd >>= 1;
262 if (cwnd < RPC_CWNDSCALE) 311 if (cwnd < RPC_CWNDSCALE)
@@ -693,7 +742,7 @@ void xprt_transmit(struct rpc_task *task)
693 task->tk_status = -ENOTCONN; 742 task->tk_status = -ENOTCONN;
694 else if (!req->rq_received) 743 else if (!req->rq_received)
695 rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); 744 rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
696 __xprt_release_write(xprt, task); 745 xprt->ops->release_xprt(xprt, task);
697 spin_unlock_bh(&xprt->transport_lock); 746 spin_unlock_bh(&xprt->transport_lock);
698 return; 747 return;
699 } 748 }
@@ -792,7 +841,7 @@ void xprt_release(struct rpc_task *task)
792 if (!(req = task->tk_rqstp)) 841 if (!(req = task->tk_rqstp))
793 return; 842 return;
794 spin_lock_bh(&xprt->transport_lock); 843 spin_lock_bh(&xprt->transport_lock);
795 __xprt_release_write(xprt, task); 844 xprt->ops->release_xprt(xprt, task);
796 __xprt_put_cong(xprt, req); 845 __xprt_put_cong(xprt, req);
797 if (!list_empty(&req->rq_list)) 846 if (!list_empty(&req->rq_list))
798 list_del(&req->rq_list); 847 list_del(&req->rq_list);