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>
This commit is contained in:
Trond Myklebust 2009-05-18 17:47:56 -04:00 committed by J. Bruce Fields
parent ab52ae6db0
commit 47fcb03fef
1 changed files with 18 additions and 17 deletions

View File

@ -380,6 +380,7 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
sock->sk->sk_sndbuf = snd * 2; sock->sk->sk_sndbuf = snd * 2;
sock->sk->sk_rcvbuf = rcv * 2; sock->sk->sk_rcvbuf = rcv * 2;
sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK; sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK;
sock->sk->sk_write_space(sock->sk);
release_sock(sock->sk); release_sock(sock->sk);
#endif #endif
} }
@ -421,6 +422,15 @@ static void svc_write_space(struct sock *sk)
} }
} }
static void svc_tcp_write_space(struct sock *sk)
{
struct socket *sock = sk->sk_socket;
if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock)
clear_bit(SOCK_NOSPACE, &sock->flags);
svc_write_space(sk);
}
/* /*
* Copy the UDP datagram's destination address to the rqstp structure. * Copy the UDP datagram's destination address to the rqstp structure.
* The 'destination' address in this case is the address to which the * 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)
static int svc_tcp_has_wspace(struct svc_xprt *xprt) static int svc_tcp_has_wspace(struct svc_xprt *xprt)
{ {
struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
struct svc_serv *serv = svsk->sk_xprt.xpt_server; struct svc_serv *serv = svsk->sk_xprt.xpt_server;
int required; int required;
int wspace;
/* if (test_bit(XPT_LISTENER, &xprt->xpt_flags))
* Set the SOCK_NOSPACE flag before checking the available return 1;
* sock space. required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg;
*/ if (sk_stream_wspace(svsk->sk_sk) >= required)
return 1;
set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
required = atomic_read(&svsk->sk_xprt.xpt_reserved) + serv->sv_max_mesg; return 0;
wspace = sk_stream_wspace(svsk->sk_sk);
if (wspace < sk_stream_min_wspace(svsk->sk_sk))
return 0;
if (required * 2 > wspace)
return 0;
clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
return 1;
} }
static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, 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)
dprintk("setting up TCP socket for reading\n"); dprintk("setting up TCP socket for reading\n");
sk->sk_state_change = svc_tcp_state_change; sk->sk_state_change = svc_tcp_state_change;
sk->sk_data_ready = svc_tcp_data_ready; sk->sk_data_ready = svc_tcp_data_ready;
sk->sk_write_space = svc_write_space; sk->sk_write_space = svc_tcp_write_space;
svsk->sk_reclen = 0; svsk->sk_reclen = 0;
svsk->sk_tcplen = 0; svsk->sk_tcplen = 0;