SUNRPC: svc_tcp_write_space: don't clear SOCK_NOSPACE prematurely
authorTrond Myklebust <trond.myklebust@primarydata.com>
Fri, 25 Jul 2014 03:59:32 +0000 (23:59 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Tue, 29 Jul 2014 20:10:19 +0000 (16:10 -0400)
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>
net/sunrpc/svcsock.c

index b2437ee936572eaeac619a836c5483474fbd27a6..88db211d4264788249b08c991a7eed835e5aafc6 100644 (file)
@@ -446,11 +446,31 @@ static void svc_write_space(struct sock *sk)
        }
 }
 
+static int svc_tcp_has_wspace(struct svc_xprt *xprt)
+{
+       struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
+       struct svc_serv *serv = svsk->sk_xprt.xpt_server;
+       int required;
+
+       if (test_bit(XPT_LISTENER, &xprt->xpt_flags))
+               return 1;
+       required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg;
+       if (sk_stream_wspace(svsk->sk_sk) >= required ||
+           (sk_stream_min_wspace(svsk->sk_sk) == 0 &&
+            atomic_read(&xprt->xpt_reserved) == 0))
+               return 1;
+       set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
+       return 0;
+}
+
 static void svc_tcp_write_space(struct sock *sk)
 {
+       struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data);
        struct socket *sock = sk->sk_socket;
 
-       if (sk_stream_is_writeable(sk) && sock)
+       if (!sk_stream_is_writeable(sk) || !sock)
+               return;
+       if (!svsk || svc_tcp_has_wspace(&svsk->sk_xprt))
                clear_bit(SOCK_NOSPACE, &sock->flags);
        svc_write_space(sk);
 }
@@ -1198,23 +1218,6 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
        svc_putnl(resv, 0);
 }
 
-static int svc_tcp_has_wspace(struct svc_xprt *xprt)
-{
-       struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
-       struct svc_serv *serv = svsk->sk_xprt.xpt_server;
-       int required;
-
-       if (test_bit(XPT_LISTENER, &xprt->xpt_flags))
-               return 1;
-       required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg;
-       if (sk_stream_wspace(svsk->sk_sk) >= required ||
-           (sk_stream_min_wspace(svsk->sk_sk) == 0 &&
-            atomic_read(&xprt->xpt_reserved) == 0))
-               return 1;
-       set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
-       return 0;
-}
-
 static struct svc_xprt *svc_tcp_create(struct svc_serv *serv,
                                       struct net *net,
                                       struct sockaddr *sa, int salen,
This page took 0.026748 seconds and 5 git commands to generate.