Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 06ea0bfe authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: Fix races in xs_nospace()

When a send failure occurs due to the socket being out of buffer space,
we call xs_nospace() in order to have the RPC task wait until the
socket has drained enough to make it worth while trying again.
The current patch fixes a race in which the socket is drained before
we get round to setting up the machinery in xs_nospace(), and which
is reported to cause hangs.

Link: http://lkml.kernel.org/r/20140210170315.33dfc621@notabene.brown


Fixes: a9a6b52e (SUNRPC: Don't start the retransmission timer...)
Reported-by: default avatarNeil Brown <neilb@suse.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent a699d65e
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -510,6 +510,7 @@ static int xs_nospace(struct rpc_task *task)
	struct rpc_rqst *req = task->tk_rqstp;
	struct rpc_xprt *xprt = req->rq_xprt;
	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
	struct sock *sk = transport->inet;
	int ret = -EAGAIN;

	dprintk("RPC: %5u xmit incomplete (%u left of %u)\n",
@@ -527,7 +528,7 @@ static int xs_nospace(struct rpc_task *task)
			 * window size
			 */
			set_bit(SOCK_NOSPACE, &transport->sock->flags);
			transport->inet->sk_write_pending++;
			sk->sk_write_pending++;
			/* ...and wait for more buffer space */
			xprt_wait_for_buffer_space(task, xs_nospace_callback);
		}
@@ -537,6 +538,9 @@ static int xs_nospace(struct rpc_task *task)
	}

	spin_unlock_bh(&xprt->transport_lock);

	/* Race breaker in case memory is freed before above code is called */
	sk->sk_write_space(sk);
	return ret;
}