aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2014-07-24 23:59:32 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-07-29 16:10:19 -0400
commitc7fb3f0631b8d66b90e0642a95b948febb3f3cee (patch)
tree799554628d9375a2d0f45925ac58984de07080f5 /net
parent0971374e2818eef6ebdbd7a37acf6ab7e98ac06c (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.c39
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
449static 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
449static void svc_tcp_write_space(struct sock *sk) 466static 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
1201static 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
1218static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, 1221static 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,