summaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtsock.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-05-29 00:42:03 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-06-13 12:35:51 -0400
commit9ffadfbc092fc25d9639a019fb3079cf352ef978 (patch)
treeb2aa602f609bc2ef9aa11029269927dab517b5e1 /net/sunrpc/xprtsock.c
parentf1dc237c60a5fdecc83062a28a702193f881cb19 (diff)
SUNRPC: Fix suspicious enobufs issues.
The current test is racy when dealing with fast NICs. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r--net/sunrpc/xprtsock.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 646170d0cb86..6b3efeb3edc5 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -642,6 +642,7 @@ static int xs_tcp_send_request(struct rpc_task *task)
642 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); 642 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
643 struct xdr_buf *xdr = &req->rq_snd_buf; 643 struct xdr_buf *xdr = &req->rq_snd_buf;
644 bool zerocopy = true; 644 bool zerocopy = true;
645 bool vm_wait = false;
645 int status; 646 int status;
646 int sent; 647 int sent;
647 648
@@ -677,15 +678,33 @@ static int xs_tcp_send_request(struct rpc_task *task)
677 return 0; 678 return 0;
678 } 679 }
679 680
681 WARN_ON_ONCE(sent == 0 && status == 0);
682
683 if (status == -EAGAIN ) {
684 /*
685 * Return EAGAIN if we're sure we're hitting the
686 * socket send buffer limits.
687 */
688 if (test_bit(SOCK_NOSPACE, &transport->sock->flags))
689 break;
690 /*
691 * Did we hit a memory allocation failure?
692 */
693 if (sent == 0) {
694 status = -ENOBUFS;
695 if (vm_wait)
696 break;
697 /* Retry, knowing now that we're below the
698 * socket send buffer limit
699 */
700 vm_wait = true;
701 }
702 continue;
703 }
680 if (status < 0) 704 if (status < 0)
681 break; 705 break;
682 if (sent == 0) { 706 vm_wait = false;
683 status = -EAGAIN;
684 break;
685 }
686 } 707 }
687 if (status == -EAGAIN && sk_stream_is_writeable(transport->inet))
688 status = -ENOBUFS;
689 708
690 switch (status) { 709 switch (status) {
691 case -ENOTSOCK: 710 case -ENOTSOCK: