diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-05-29 00:42:03 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-06-13 12:35:51 -0400 |
commit | 9ffadfbc092fc25d9639a019fb3079cf352ef978 (patch) | |
tree | b2aa602f609bc2ef9aa11029269927dab517b5e1 /net/sunrpc/xprtsock.c | |
parent | f1dc237c60a5fdecc83062a28a702193f881cb19 (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.c | 31 |
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: |