diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-07-24 23:59:32 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-07-29 16:10:19 -0400 |
commit | c7fb3f0631b8d66b90e0642a95b948febb3f3cee (patch) | |
tree | 799554628d9375a2d0f45925ac58984de07080f5 /net | |
parent | 0971374e2818eef6ebdbd7a37acf6ab7e98ac06c (diff) |
SUNRPC: svc_tcp_write_space: don't clear SOCK_NOSPACE prematurely
If requests are queued in the socket inbuffer waiting for an
svc_tcp_has_wspace() requirement to be satisfied, then we do not want
to clear the SOCK_NOSPACE flag until we've satisfied that requirement.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svcsock.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index b2437ee93657..88db211d4264 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -446,11 +446,31 @@ static void svc_write_space(struct sock *sk) | |||
446 | } | 446 | } |
447 | } | 447 | } |
448 | 448 | ||
449 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) | ||
450 | { | ||
451 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
452 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | ||
453 | int required; | ||
454 | |||
455 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) | ||
456 | return 1; | ||
457 | required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg; | ||
458 | if (sk_stream_wspace(svsk->sk_sk) >= required || | ||
459 | (sk_stream_min_wspace(svsk->sk_sk) == 0 && | ||
460 | atomic_read(&xprt->xpt_reserved) == 0)) | ||
461 | return 1; | ||
462 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
449 | static void svc_tcp_write_space(struct sock *sk) | 466 | static void svc_tcp_write_space(struct sock *sk) |
450 | { | 467 | { |
468 | struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data); | ||
451 | struct socket *sock = sk->sk_socket; | 469 | struct socket *sock = sk->sk_socket; |
452 | 470 | ||
453 | if (sk_stream_is_writeable(sk) && sock) | 471 | if (!sk_stream_is_writeable(sk) || !sock) |
472 | return; | ||
473 | if (!svsk || svc_tcp_has_wspace(&svsk->sk_xprt)) | ||
454 | clear_bit(SOCK_NOSPACE, &sock->flags); | 474 | clear_bit(SOCK_NOSPACE, &sock->flags); |
455 | svc_write_space(sk); | 475 | svc_write_space(sk); |
456 | } | 476 | } |
@@ -1198,23 +1218,6 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) | |||
1198 | svc_putnl(resv, 0); | 1218 | svc_putnl(resv, 0); |
1199 | } | 1219 | } |
1200 | 1220 | ||
1201 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) | ||
1202 | { | ||
1203 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
1204 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | ||
1205 | int required; | ||
1206 | |||
1207 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) | ||
1208 | return 1; | ||
1209 | required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg; | ||
1210 | if (sk_stream_wspace(svsk->sk_sk) >= required || | ||
1211 | (sk_stream_min_wspace(svsk->sk_sk) == 0 && | ||
1212 | atomic_read(&xprt->xpt_reserved) == 0)) | ||
1213 | return 1; | ||
1214 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
1215 | return 0; | ||
1216 | } | ||
1217 | |||
1218 | static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, | 1221 | static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, |
1219 | struct net *net, | 1222 | struct net *net, |
1220 | struct sockaddr *sa, int salen, | 1223 | struct sockaddr *sa, int salen, |