aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorChuck Lever <cel@citi.umich.edu>2005-08-11 16:25:50 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-09-23 12:38:28 -0400
commitc7b2cae8a634015b72941ba2fc6c4bc9b8d3a129 (patch)
tree95f561877d67eed80a823daa6ef0c00ad1c060eb /net/sunrpc
parent55aa4f58aa43dc9a51fb80010630d94b96053a2e (diff)
[PATCH] RPC: separate TCP and UDP write space callbacks
Split the socket write space callback function into a TCP version and UDP version, eliminating one dependence on the "xprt->stream" variable. Keep the common pieces of this path in xprt.c so other transports can use it too. Test-plan: Write-intensive workload on a single mount point. Version: Thu, 11 Aug 2005 16:07:51 -0400 Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/xprt.c34
-rw-r--r--net/sunrpc/xprtsock.c84
2 files changed, 87 insertions, 31 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 247fa1ec870c..31ef7dc7eed6 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -241,6 +241,40 @@ void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status)
241 rpc_wake_up(&xprt->pending); 241 rpc_wake_up(&xprt->pending);
242} 242}
243 243
244/**
245 * xprt_wait_for_buffer_space - wait for transport output buffer to clear
246 * @task: task to be put to sleep
247 *
248 */
249void xprt_wait_for_buffer_space(struct rpc_task *task)
250{
251 struct rpc_rqst *req = task->tk_rqstp;
252 struct rpc_xprt *xprt = req->rq_xprt;
253
254 task->tk_timeout = req->rq_timeout;
255 rpc_sleep_on(&xprt->pending, task, NULL, NULL);
256}
257
258/**
259 * xprt_write_space - wake the task waiting for transport output buffer space
260 * @xprt: transport with waiting tasks
261 *
262 * Can be called in a soft IRQ context, so xprt_write_space never sleeps.
263 */
264void xprt_write_space(struct rpc_xprt *xprt)
265{
266 if (unlikely(xprt->shutdown))
267 return;
268
269 spin_lock_bh(&xprt->transport_lock);
270 if (xprt->snd_task) {
271 dprintk("RPC: write space: waking waiting task on xprt %p\n",
272 xprt);
273 rpc_wake_up_task(xprt->snd_task);
274 }
275 spin_unlock_bh(&xprt->transport_lock);
276}
277
244static void xprt_reset_majortimeo(struct rpc_rqst *req) 278static void xprt_reset_majortimeo(struct rpc_rqst *req)
245{ 279{
246 struct rpc_timeout *to = &req->rq_xprt->timeout; 280 struct rpc_timeout *to = &req->rq_xprt->timeout;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 7f0b9f7f167b..70a772d7a796 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -308,15 +308,13 @@ static int xs_send_request(struct rpc_task *task)
308 308
309 if (status == -EAGAIN) { 309 if (status == -EAGAIN) {
310 if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) { 310 if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
311 /* Protect against races with xs_write_space */ 311 /* Protect against races with write_space */
312 spin_lock_bh(&xprt->transport_lock); 312 spin_lock_bh(&xprt->transport_lock);
313 /* Don't race with disconnect */ 313 /* Don't race with disconnect */
314 if (!xprt_connected(xprt)) 314 if (!xprt_connected(xprt))
315 task->tk_status = -ENOTCONN; 315 task->tk_status = -ENOTCONN;
316 else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) { 316 else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
317 task->tk_timeout = req->rq_timeout; 317 xprt_wait_for_buffer_space(task);
318 rpc_sleep_on(&xprt->pending, task, NULL, NULL);
319 }
320 spin_unlock_bh(&xprt->transport_lock); 318 spin_unlock_bh(&xprt->transport_lock);
321 return status; 319 return status;
322 } 320 }
@@ -721,45 +719,68 @@ static void xs_tcp_state_change(struct sock *sk)
721} 719}
722 720
723/** 721/**
724 * xs_write_space - callback invoked when socket buffer space becomes 722 * xs_udp_write_space - callback invoked when socket buffer space
725 * available 723 * becomes available
726 * @sk: socket whose state has changed 724 * @sk: socket whose state has changed
727 * 725 *
728 * Called when more output buffer space is available for this socket. 726 * Called when more output buffer space is available for this socket.
729 * We try not to wake our writers until they can make "significant" 727 * We try not to wake our writers until they can make "significant"
730 * progress, otherwise we'll waste resources thrashing sock_sendmsg 728 * progress, otherwise we'll waste resources thrashing kernel_sendmsg
731 * with a bunch of small requests. 729 * with a bunch of small requests.
732 */ 730 */
733static void xs_write_space(struct sock *sk) 731static void xs_udp_write_space(struct sock *sk)
734{ 732{
735 struct rpc_xprt *xprt;
736 struct socket *sock;
737
738 read_lock(&sk->sk_callback_lock); 733 read_lock(&sk->sk_callback_lock);
739 if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->sk_socket))
740 goto out;
741 if (xprt->shutdown)
742 goto out;
743 734
744 /* Wait until we have enough socket memory */ 735 /* from net/core/sock.c:sock_def_write_space */
745 if (xprt->stream) { 736 if (sock_writeable(sk)) {
746 /* from net/core/stream.c:sk_stream_write_space */ 737 struct socket *sock;
747 if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk)) 738 struct rpc_xprt *xprt;
739
740 if (unlikely(!(sock = sk->sk_socket)))
748 goto out; 741 goto out;
749 } else { 742 if (unlikely(!(xprt = xprt_from_sock(sk))))
750 /* from net/core/sock.c:sock_def_write_space */ 743 goto out;
751 if (!sock_writeable(sk)) 744 if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
752 goto out; 745 goto out;
746
747 xprt_write_space(xprt);
753 } 748 }
754 749
755 if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)) 750 out:
756 goto out; 751 read_unlock(&sk->sk_callback_lock);
752}
757 753
758 spin_lock_bh(&xprt->transport_lock); 754/**
759 if (xprt->snd_task) 755 * xs_tcp_write_space - callback invoked when socket buffer space
760 rpc_wake_up_task(xprt->snd_task); 756 * becomes available
761 spin_unlock_bh(&xprt->transport_lock); 757 * @sk: socket whose state has changed
762out: 758 *
759 * Called when more output buffer space is available for this socket.
760 * We try not to wake our writers until they can make "significant"
761 * progress, otherwise we'll waste resources thrashing kernel_sendmsg
762 * with a bunch of small requests.
763 */
764static void xs_tcp_write_space(struct sock *sk)
765{
766 read_lock(&sk->sk_callback_lock);
767
768 /* from net/core/stream.c:sk_stream_write_space */
769 if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
770 struct socket *sock;
771 struct rpc_xprt *xprt;
772
773 if (unlikely(!(sock = sk->sk_socket)))
774 goto out;
775 if (unlikely(!(xprt = xprt_from_sock(sk))))
776 goto out;
777 if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
778 goto out;
779
780 xprt_write_space(xprt);
781 }
782
783 out:
763 read_unlock(&sk->sk_callback_lock); 784 read_unlock(&sk->sk_callback_lock);
764} 785}
765 786
@@ -855,15 +876,16 @@ static void xs_bind(struct rpc_xprt *xprt, struct socket *sock)
855 xprt->old_write_space = sk->sk_write_space; 876 xprt->old_write_space = sk->sk_write_space;
856 if (xprt->prot == IPPROTO_UDP) { 877 if (xprt->prot == IPPROTO_UDP) {
857 sk->sk_data_ready = xs_udp_data_ready; 878 sk->sk_data_ready = xs_udp_data_ready;
879 sk->sk_write_space = xs_udp_write_space;
858 sk->sk_no_check = UDP_CSUM_NORCV; 880 sk->sk_no_check = UDP_CSUM_NORCV;
859 xprt_set_connected(xprt); 881 xprt_set_connected(xprt);
860 } else { 882 } else {
861 tcp_sk(sk)->nonagle = 1; /* disable Nagle's algorithm */ 883 tcp_sk(sk)->nonagle = 1; /* disable Nagle's algorithm */
862 sk->sk_data_ready = xs_tcp_data_ready; 884 sk->sk_data_ready = xs_tcp_data_ready;
863 sk->sk_state_change = xs_tcp_state_change; 885 sk->sk_state_change = xs_tcp_state_change;
886 sk->sk_write_space = xs_tcp_write_space;
864 xprt_clear_connected(xprt); 887 xprt_clear_connected(xprt);
865 } 888 }
866 sk->sk_write_space = xs_write_space;
867 889
868 /* Reset to new socket */ 890 /* Reset to new socket */
869 xprt->sock = sock; 891 xprt->sock = sock;