Commit 8c9dff1e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfs-for-4.20-6' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes from Trond Myklebust:

 - Fix TCP socket disconnection races by ensuring we always call
   xprt_disconnect_done() after releasing the socket.

 - Fix a race when clearing both XPRT_CONNECTING and XPRT_LOCKED

 - Remove xprt_connect_status() so it does not mask errors that should
   be handled by call_connect_status()

* tag 'nfs-for-4.20-6' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  SUNRPC: Remove xprt_connect_status()
  SUNRPC: Fix a race with XPRT_CONNECTING
  SUNRPC: Fix disconnection races
parents fe112793 abc13275
...@@ -1952,6 +1952,7 @@ call_connect_status(struct rpc_task *task) ...@@ -1952,6 +1952,7 @@ call_connect_status(struct rpc_task *task)
/* retry with existing socket, after a delay */ /* retry with existing socket, after a delay */
rpc_delay(task, 3*HZ); rpc_delay(task, 3*HZ);
/* fall through */ /* fall through */
case -ENOTCONN:
case -EAGAIN: case -EAGAIN:
/* Check for timeouts before looping back to call_bind */ /* Check for timeouts before looping back to call_bind */
case -ETIMEDOUT: case -ETIMEDOUT:
......
...@@ -67,7 +67,6 @@ ...@@ -67,7 +67,6 @@
*/ */
static void xprt_init(struct rpc_xprt *xprt, struct net *net); static void xprt_init(struct rpc_xprt *xprt, struct net *net);
static __be32 xprt_alloc_xid(struct rpc_xprt *xprt); static __be32 xprt_alloc_xid(struct rpc_xprt *xprt);
static void xprt_connect_status(struct rpc_task *task);
static void xprt_destroy(struct rpc_xprt *xprt); static void xprt_destroy(struct rpc_xprt *xprt);
static DEFINE_SPINLOCK(xprt_list_lock); static DEFINE_SPINLOCK(xprt_list_lock);
...@@ -680,7 +679,9 @@ void xprt_force_disconnect(struct rpc_xprt *xprt) ...@@ -680,7 +679,9 @@ void xprt_force_disconnect(struct rpc_xprt *xprt)
/* Try to schedule an autoclose RPC call */ /* Try to schedule an autoclose RPC call */
if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
queue_work(xprtiod_workqueue, &xprt->task_cleanup); queue_work(xprtiod_workqueue, &xprt->task_cleanup);
xprt_wake_pending_tasks(xprt, -EAGAIN); else if (xprt->snd_task)
rpc_wake_up_queued_task_set_status(&xprt->pending,
xprt->snd_task, -ENOTCONN);
spin_unlock_bh(&xprt->transport_lock); spin_unlock_bh(&xprt->transport_lock);
} }
EXPORT_SYMBOL_GPL(xprt_force_disconnect); EXPORT_SYMBOL_GPL(xprt_force_disconnect);
...@@ -820,7 +821,7 @@ void xprt_connect(struct rpc_task *task) ...@@ -820,7 +821,7 @@ void xprt_connect(struct rpc_task *task)
if (!xprt_connected(xprt)) { if (!xprt_connected(xprt)) {
task->tk_timeout = task->tk_rqstp->rq_timeout; task->tk_timeout = task->tk_rqstp->rq_timeout;
task->tk_rqstp->rq_connect_cookie = xprt->connect_cookie; task->tk_rqstp->rq_connect_cookie = xprt->connect_cookie;
rpc_sleep_on(&xprt->pending, task, xprt_connect_status); rpc_sleep_on(&xprt->pending, task, NULL);
if (test_bit(XPRT_CLOSING, &xprt->state)) if (test_bit(XPRT_CLOSING, &xprt->state))
return; return;
...@@ -839,34 +840,6 @@ void xprt_connect(struct rpc_task *task) ...@@ -839,34 +840,6 @@ void xprt_connect(struct rpc_task *task)
xprt_release_write(xprt, task); xprt_release_write(xprt, task);
} }
static void xprt_connect_status(struct rpc_task *task)
{
switch (task->tk_status) {
case 0:
dprintk("RPC: %5u xprt_connect_status: connection established\n",
task->tk_pid);
break;
case -ECONNREFUSED:
case -ECONNRESET:
case -ECONNABORTED:
case -ENETUNREACH:
case -EHOSTUNREACH:
case -EPIPE:
case -EAGAIN:
dprintk("RPC: %5u xprt_connect_status: retrying\n", task->tk_pid);
break;
case -ETIMEDOUT:
dprintk("RPC: %5u xprt_connect_status: connect attempt timed "
"out\n", task->tk_pid);
break;
default:
dprintk("RPC: %5u xprt_connect_status: error %d connecting to "
"server %s\n", task->tk_pid, -task->tk_status,
task->tk_rqstp->rq_xprt->servername);
task->tk_status = -EIO;
}
}
enum xprt_xid_rb_cmp { enum xprt_xid_rb_cmp {
XID_RB_EQUAL, XID_RB_EQUAL,
XID_RB_LEFT, XID_RB_LEFT,
......
...@@ -1217,6 +1217,8 @@ static void xs_reset_transport(struct sock_xprt *transport) ...@@ -1217,6 +1217,8 @@ static void xs_reset_transport(struct sock_xprt *transport)
trace_rpc_socket_close(xprt, sock); trace_rpc_socket_close(xprt, sock);
sock_release(sock); sock_release(sock);
xprt_disconnect_done(xprt);
} }
/** /**
...@@ -1237,8 +1239,6 @@ static void xs_close(struct rpc_xprt *xprt) ...@@ -1237,8 +1239,6 @@ static void xs_close(struct rpc_xprt *xprt)
xs_reset_transport(transport); xs_reset_transport(transport);
xprt->reestablish_timeout = 0; xprt->reestablish_timeout = 0;
xprt_disconnect_done(xprt);
} }
static void xs_inject_disconnect(struct rpc_xprt *xprt) static void xs_inject_disconnect(struct rpc_xprt *xprt)
...@@ -1489,8 +1489,6 @@ static void xs_tcp_state_change(struct sock *sk) ...@@ -1489,8 +1489,6 @@ static void xs_tcp_state_change(struct sock *sk)
&transport->sock_state)) &transport->sock_state))
xprt_clear_connecting(xprt); xprt_clear_connecting(xprt);
clear_bit(XPRT_CLOSING, &xprt->state); clear_bit(XPRT_CLOSING, &xprt->state);
if (sk->sk_err)
xprt_wake_pending_tasks(xprt, -sk->sk_err);
/* Trigger the socket release */ /* Trigger the socket release */
xs_tcp_force_close(xprt); xs_tcp_force_close(xprt);
} }
...@@ -2092,8 +2090,8 @@ static void xs_udp_setup_socket(struct work_struct *work) ...@@ -2092,8 +2090,8 @@ static void xs_udp_setup_socket(struct work_struct *work)
trace_rpc_socket_connect(xprt, sock, 0); trace_rpc_socket_connect(xprt, sock, 0);
status = 0; status = 0;
out: out:
xprt_unlock_connect(xprt, transport);
xprt_clear_connecting(xprt); xprt_clear_connecting(xprt);
xprt_unlock_connect(xprt, transport);
xprt_wake_pending_tasks(xprt, status); xprt_wake_pending_tasks(xprt, status);
} }
...@@ -2329,8 +2327,8 @@ static void xs_tcp_setup_socket(struct work_struct *work) ...@@ -2329,8 +2327,8 @@ static void xs_tcp_setup_socket(struct work_struct *work)
} }
status = -EAGAIN; status = -EAGAIN;
out: out:
xprt_unlock_connect(xprt, transport);
xprt_clear_connecting(xprt); xprt_clear_connecting(xprt);
xprt_unlock_connect(xprt, transport);
xprt_wake_pending_tasks(xprt, status); xprt_wake_pending_tasks(xprt, status);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment