diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-05-18 17:47:56 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-06-18 22:58:51 -0400 |
commit | 47fcb03fefee2501e79176932a4184fc24d6f8ec (patch) | |
tree | cb8eb34c5e54ce278b54cb6f9c820f564c183574 /net/sunrpc/svcsock.c | |
parent | ab52ae6db035fa425f90146327ab7d2c5d3e5654 (diff) |
SUNRPC: Fix the TCP server's send buffer accounting
Currently, the sunrpc server is refusing to allow us to process new RPC
calls if the TCP send buffer is 2/3 full, even if we do actually have
enough free space to guarantee that we can send another request.
The following patch fixes svc_tcp_has_wspace() so that we only stop
processing requests if we know that the socket buffer cannot possibly fit
another reply.
It also fixes the tcp write_space() callback so that we only clear the
SOCK_NOSPACE flag when the TCP send buffer is less than 2/3 full.
This should ensure that the send window will grow as per the standard TCP
socket code.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r-- | net/sunrpc/svcsock.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 004a2f9dc432..b09c80c56ee3 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -380,6 +380,7 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd, | |||
380 | sock->sk->sk_sndbuf = snd * 2; | 380 | sock->sk->sk_sndbuf = snd * 2; |
381 | sock->sk->sk_rcvbuf = rcv * 2; | 381 | sock->sk->sk_rcvbuf = rcv * 2; |
382 | sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK; | 382 | sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK; |
383 | sock->sk->sk_write_space(sock->sk); | ||
383 | release_sock(sock->sk); | 384 | release_sock(sock->sk); |
384 | #endif | 385 | #endif |
385 | } | 386 | } |
@@ -421,6 +422,15 @@ static void svc_write_space(struct sock *sk) | |||
421 | } | 422 | } |
422 | } | 423 | } |
423 | 424 | ||
425 | static void svc_tcp_write_space(struct sock *sk) | ||
426 | { | ||
427 | struct socket *sock = sk->sk_socket; | ||
428 | |||
429 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) | ||
430 | clear_bit(SOCK_NOSPACE, &sock->flags); | ||
431 | svc_write_space(sk); | ||
432 | } | ||
433 | |||
424 | /* | 434 | /* |
425 | * Copy the UDP datagram's destination address to the rqstp structure. | 435 | * Copy the UDP datagram's destination address to the rqstp structure. |
426 | * The 'destination' address in this case is the address to which the | 436 | * The 'destination' address in this case is the address to which the |
@@ -1015,25 +1025,16 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) | |||
1015 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) | 1025 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) |
1016 | { | 1026 | { |
1017 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | 1027 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); |
1018 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | 1028 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
1019 | int required; | 1029 | int required; |
1020 | int wspace; | ||
1021 | 1030 | ||
1022 | /* | 1031 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) |
1023 | * Set the SOCK_NOSPACE flag before checking the available | 1032 | return 1; |
1024 | * sock space. | 1033 | required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg; |
1025 | */ | 1034 | if (sk_stream_wspace(svsk->sk_sk) >= required) |
1035 | return 1; | ||
1026 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | 1036 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); |
1027 | required = atomic_read(&svsk->sk_xprt.xpt_reserved) + serv->sv_max_mesg; | 1037 | return 0; |
1028 | wspace = sk_stream_wspace(svsk->sk_sk); | ||
1029 | |||
1030 | if (wspace < sk_stream_min_wspace(svsk->sk_sk)) | ||
1031 | return 0; | ||
1032 | if (required * 2 > wspace) | ||
1033 | return 0; | ||
1034 | |||
1035 | clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
1036 | return 1; | ||
1037 | } | 1038 | } |
1038 | 1039 | ||
1039 | static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, | 1040 | static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, |
@@ -1089,7 +1090,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
1089 | dprintk("setting up TCP socket for reading\n"); | 1090 | dprintk("setting up TCP socket for reading\n"); |
1090 | sk->sk_state_change = svc_tcp_state_change; | 1091 | sk->sk_state_change = svc_tcp_state_change; |
1091 | sk->sk_data_ready = svc_tcp_data_ready; | 1092 | sk->sk_data_ready = svc_tcp_data_ready; |
1092 | sk->sk_write_space = svc_write_space; | 1093 | sk->sk_write_space = svc_tcp_write_space; |
1093 | 1094 | ||
1094 | svsk->sk_reclen = 0; | 1095 | svsk->sk_reclen = 0; |
1095 | svsk->sk_tcplen = 0; | 1096 | svsk->sk_tcplen = 0; |