提交 ca384b2b 编写于 作者: T Trond Myklebust 提交者: Zheng Zengkai

SUNRPC: Fix socket waits for write buffer space

stable inclusion
from stable-v5.10.111
commit 7a506fabcfe1a58bcdf6dd18fa3fca42635235f0
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I5GL1Z

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7a506fabcfe1a58bcdf6dd18fa3fca42635235f0

--------------------------------

[ Upstream commit 7496b59f ]

The socket layer requires that we use the socket lock to protect changes
to the sock->sk_write_pending field and others.
Reported-by: NChuck Lever <chuck.lever@oracle.com>
Signed-off-by: NTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: NSasha Levin <sashal@kernel.org>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: NWei Li <liwei391@huawei.com>
上级 220864b7
...@@ -754,12 +754,12 @@ xs_stream_start_connect(struct sock_xprt *transport) ...@@ -754,12 +754,12 @@ xs_stream_start_connect(struct sock_xprt *transport)
/** /**
* xs_nospace - handle transmit was incomplete * xs_nospace - handle transmit was incomplete
* @req: pointer to RPC request * @req: pointer to RPC request
* @transport: pointer to struct sock_xprt
* *
*/ */
static int xs_nospace(struct rpc_rqst *req) static int xs_nospace(struct rpc_rqst *req, struct sock_xprt *transport)
{ {
struct rpc_xprt *xprt = req->rq_xprt; struct rpc_xprt *xprt = &transport->xprt;
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
struct sock *sk = transport->inet; struct sock *sk = transport->inet;
int ret = -EAGAIN; int ret = -EAGAIN;
...@@ -770,25 +770,49 @@ static int xs_nospace(struct rpc_rqst *req) ...@@ -770,25 +770,49 @@ static int xs_nospace(struct rpc_rqst *req)
/* Don't race with disconnect */ /* Don't race with disconnect */
if (xprt_connected(xprt)) { if (xprt_connected(xprt)) {
struct socket_wq *wq;
rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
set_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags);
rcu_read_unlock();
/* wait for more buffer space */ /* wait for more buffer space */
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
sk->sk_write_pending++; sk->sk_write_pending++;
xprt_wait_for_buffer_space(xprt); xprt_wait_for_buffer_space(xprt);
} else } else
ret = -ENOTCONN; ret = -ENOTCONN;
spin_unlock(&xprt->transport_lock); spin_unlock(&xprt->transport_lock);
return ret;
}
/* Race breaker in case memory is freed before above code is called */ static int xs_sock_nospace(struct rpc_rqst *req)
if (ret == -EAGAIN) { {
struct socket_wq *wq; struct sock_xprt *transport =
container_of(req->rq_xprt, struct sock_xprt, xprt);
struct sock *sk = transport->inet;
int ret = -EAGAIN;
rcu_read_lock(); lock_sock(sk);
wq = rcu_dereference(sk->sk_wq); if (!sock_writeable(sk))
set_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags); ret = xs_nospace(req, transport);
rcu_read_unlock(); release_sock(sk);
return ret;
}
sk->sk_write_space(sk); static int xs_stream_nospace(struct rpc_rqst *req)
} {
struct sock_xprt *transport =
container_of(req->rq_xprt, struct sock_xprt, xprt);
struct sock *sk = transport->inet;
int ret = -EAGAIN;
lock_sock(sk);
if (!sk_stream_memory_free(sk))
ret = xs_nospace(req, transport);
release_sock(sk);
return ret; return ret;
} }
...@@ -878,7 +902,7 @@ static int xs_local_send_request(struct rpc_rqst *req) ...@@ -878,7 +902,7 @@ static int xs_local_send_request(struct rpc_rqst *req)
case -ENOBUFS: case -ENOBUFS:
break; break;
case -EAGAIN: case -EAGAIN:
status = xs_nospace(req); status = xs_stream_nospace(req);
break; break;
default: default:
dprintk("RPC: sendmsg returned unrecognized error %d\n", dprintk("RPC: sendmsg returned unrecognized error %d\n",
...@@ -954,7 +978,7 @@ static int xs_udp_send_request(struct rpc_rqst *req) ...@@ -954,7 +978,7 @@ static int xs_udp_send_request(struct rpc_rqst *req)
/* Should we call xs_close() here? */ /* Should we call xs_close() here? */
break; break;
case -EAGAIN: case -EAGAIN:
status = xs_nospace(req); status = xs_sock_nospace(req);
break; break;
case -ENETUNREACH: case -ENETUNREACH:
case -ENOBUFS: case -ENOBUFS:
...@@ -1069,7 +1093,7 @@ static int xs_tcp_send_request(struct rpc_rqst *req) ...@@ -1069,7 +1093,7 @@ static int xs_tcp_send_request(struct rpc_rqst *req)
/* Should we call xs_close() here? */ /* Should we call xs_close() here? */
break; break;
case -EAGAIN: case -EAGAIN:
status = xs_nospace(req); status = xs_stream_nospace(req);
break; break;
case -ECONNRESET: case -ECONNRESET:
case -ECONNREFUSED: case -ECONNREFUSED:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册