aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-04-17 18:52:19 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-04-19 16:52:44 -0400
commitb6ddf64ffe9d59577a9176856bb6fe69a539f573 (patch)
treedd12c31555cf9449dd6094428d377186b3c4c373 /net
parent24b74bf0c9e08cbda74d3c64af69ad402ed54e04 (diff)
SUNRPC: Fix up xprt_write_space()
The rest of the networking layer uses SOCK_ASYNC_NOSPACE to signal whether or not we have someone waiting for buffer memory. Convert the SUNRPC layer to use the same idiom. Remove the unlikely()s in xs_udp_write_space and xs_tcp_write_space. In fact, the most common case will be that there is nobody waiting for buffer space. SOCK_NOSPACE is there to tell the TCP layer whether or not the cwnd was limited by the application window. Ensure that we follow the same idiom as the rest of the networking layer here too. Finally, ensure that we clear SOCK_ASYNC_NOSPACE once we wake up, so that write_space() doesn't keep waking things up on xprt->pending. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/xprt.c4
-rw-r--r--net/sunrpc/xprtsock.c61
2 files changed, 43 insertions, 22 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 85199c647022..3ba64f9f84ba 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -447,13 +447,13 @@ EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks);
447 * @task: task to be put to sleep 447 * @task: task to be put to sleep
448 * 448 *
449 */ 449 */
450void xprt_wait_for_buffer_space(struct rpc_task *task) 450void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action)
451{ 451{
452 struct rpc_rqst *req = task->tk_rqstp; 452 struct rpc_rqst *req = task->tk_rqstp;
453 struct rpc_xprt *xprt = req->rq_xprt; 453 struct rpc_xprt *xprt = req->rq_xprt;
454 454
455 task->tk_timeout = req->rq_timeout; 455 task->tk_timeout = req->rq_timeout;
456 rpc_sleep_on(&xprt->pending, task, NULL); 456 rpc_sleep_on(&xprt->pending, task, action);
457} 457}
458EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space); 458EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space);
459 459
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 8bd3b0f73ac0..4c2462e2f2b2 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -516,6 +516,14 @@ out:
516 return sent; 516 return sent;
517} 517}
518 518
519static void xs_nospace_callback(struct rpc_task *task)
520{
521 struct sock_xprt *transport = container_of(task->tk_rqstp->rq_xprt, struct sock_xprt, xprt);
522
523 transport->inet->sk_write_pending--;
524 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
525}
526
519/** 527/**
520 * xs_nospace - place task on wait queue if transmit was incomplete 528 * xs_nospace - place task on wait queue if transmit was incomplete
521 * @task: task to put to sleep 529 * @task: task to put to sleep
@@ -531,20 +539,27 @@ static void xs_nospace(struct rpc_task *task)
531 task->tk_pid, req->rq_slen - req->rq_bytes_sent, 539 task->tk_pid, req->rq_slen - req->rq_bytes_sent,
532 req->rq_slen); 540 req->rq_slen);
533 541
534 if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) { 542 /* Protect against races with write_space */
535 /* Protect against races with write_space */ 543 spin_lock_bh(&xprt->transport_lock);
536 spin_lock_bh(&xprt->transport_lock); 544
537 545 /* Don't race with disconnect */
538 /* Don't race with disconnect */ 546 if (xprt_connected(xprt)) {
539 if (!xprt_connected(xprt)) 547 if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
540 task->tk_status = -ENOTCONN; 548 /*
541 else if (test_bit(SOCK_NOSPACE, &transport->sock->flags)) 549 * Notify TCP that we're limited by the application
542 xprt_wait_for_buffer_space(task); 550 * window size
551 */
552 set_bit(SOCK_NOSPACE, &transport->sock->flags);
553 transport->inet->sk_write_pending++;
554 /* ...and wait for more buffer space */
555 xprt_wait_for_buffer_space(task, xs_nospace_callback);
556 }
557 } else {
558 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
559 task->tk_status = -ENOTCONN;
560 }
543 561
544 spin_unlock_bh(&xprt->transport_lock); 562 spin_unlock_bh(&xprt->transport_lock);
545 } else
546 /* Keep holding the socket if it is blocked */
547 rpc_delay(task, HZ>>4);
548} 563}
549 564
550/** 565/**
@@ -588,19 +603,20 @@ static int xs_udp_send_request(struct rpc_task *task)
588 } 603 }
589 604
590 switch (status) { 605 switch (status) {
606 case -EAGAIN:
607 xs_nospace(task);
608 break;
591 case -ENETUNREACH: 609 case -ENETUNREACH:
592 case -EPIPE: 610 case -EPIPE:
593 case -ECONNREFUSED: 611 case -ECONNREFUSED:
594 /* When the server has died, an ICMP port unreachable message 612 /* When the server has died, an ICMP port unreachable message
595 * prompts ECONNREFUSED. */ 613 * prompts ECONNREFUSED. */
596 break; 614 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
597 case -EAGAIN:
598 xs_nospace(task);
599 break; 615 break;
600 default: 616 default:
617 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
601 dprintk("RPC: sendmsg returned unrecognized error %d\n", 618 dprintk("RPC: sendmsg returned unrecognized error %d\n",
602 -status); 619 -status);
603 break;
604 } 620 }
605 621
606 return status; 622 return status;
@@ -695,12 +711,13 @@ static int xs_tcp_send_request(struct rpc_task *task)
695 case -ENOTCONN: 711 case -ENOTCONN:
696 case -EPIPE: 712 case -EPIPE:
697 status = -ENOTCONN; 713 status = -ENOTCONN;
714 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
698 break; 715 break;
699 default: 716 default:
700 dprintk("RPC: sendmsg returned unrecognized error %d\n", 717 dprintk("RPC: sendmsg returned unrecognized error %d\n",
701 -status); 718 -status);
719 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
702 xs_tcp_shutdown(xprt); 720 xs_tcp_shutdown(xprt);
703 break;
704 } 721 }
705 722
706 return status; 723 return status;
@@ -1189,9 +1206,11 @@ static void xs_udp_write_space(struct sock *sk)
1189 1206
1190 if (unlikely(!(sock = sk->sk_socket))) 1207 if (unlikely(!(sock = sk->sk_socket)))
1191 goto out; 1208 goto out;
1209 clear_bit(SOCK_NOSPACE, &sock->flags);
1210
1192 if (unlikely(!(xprt = xprt_from_sock(sk)))) 1211 if (unlikely(!(xprt = xprt_from_sock(sk))))
1193 goto out; 1212 goto out;
1194 if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))) 1213 if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0)
1195 goto out; 1214 goto out;
1196 1215
1197 xprt_write_space(xprt); 1216 xprt_write_space(xprt);
@@ -1222,9 +1241,11 @@ static void xs_tcp_write_space(struct sock *sk)
1222 1241
1223 if (unlikely(!(sock = sk->sk_socket))) 1242 if (unlikely(!(sock = sk->sk_socket)))
1224 goto out; 1243 goto out;
1244 clear_bit(SOCK_NOSPACE, &sock->flags);
1245
1225 if (unlikely(!(xprt = xprt_from_sock(sk)))) 1246 if (unlikely(!(xprt = xprt_from_sock(sk))))
1226 goto out; 1247 goto out;
1227 if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))) 1248 if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0)
1228 goto out; 1249 goto out;
1229 1250
1230 xprt_write_space(xprt); 1251 xprt_write_space(xprt);