NFS client bugfixes for Linux 4.20
Bugfixes: - 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() -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJcGnQMAAoJEA4mA3inWBJc3OIP/iRGQeEKuJrGxarssdzIXrqZ ID6t6XuYxuh6nknS3PAvn1TpAPGFRcTya5MIjvMEMCknH4tQVmD7S2v2vOlx395E 5Cg5Q6FX1dj3i2/flzS1YcByQonUrkJuuMZ36bRJ5uCGjXdryhgC1YNcsq3HXAiA G/O4W+BpvxLC9z3KGwWz2+v5K4gnIh9sypSye8qsQdrgDlFDo88jWH57gtxQTVjv 13vke64pv/bm97EfZ8gfZprcwLegQ3JJsmcoOfwnh2jRd2i5j4S/xmCLaTjOn9Fg 8fgev7klAzO/39gNV+syGKXVwgOh6mKk5PifDYv986ghvzamPmVT+chIpjgXKSJp KOpGXY/547KFHWwMQVsmNI+5RPC7FTwDkTwXuOVcmtVyNiJgpveX45pQS8kwRYxq kZXk/t1T1lXbsBPd0S+1KDjUUPd9DjSm3T3CZKvvfJBbH+ITV2gol2eqneizgxDo JLBdNFRVTPnud7IEdXiXgjMzl8aFAZsPkXfUmqWPEMtiTn5izSUbXxa04KYgHQpI GAAMVAZttl6cYoRkPIVIbQLbpY4LsBxA9iTTR39SGINLYiFQBFUNkP02OR+HaD4l bzY8n5Li1/WekxHagq6RFt+ajBgXSPeCXS3WqigEMc0Xw58u/3Td+0DuRIABmhhr IJDorHWizxgh2VseZkUB =+M4X -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
8c9dff1ebd
|
@ -1952,6 +1952,7 @@ call_connect_status(struct rpc_task *task)
|
|||
/* retry with existing socket, after a delay */
|
||||
rpc_delay(task, 3*HZ);
|
||||
/* fall through */
|
||||
case -ENOTCONN:
|
||||
case -EAGAIN:
|
||||
/* Check for timeouts before looping back to call_bind */
|
||||
case -ETIMEDOUT:
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
*/
|
||||
static void xprt_init(struct rpc_xprt *xprt, struct net *net);
|
||||
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 DEFINE_SPINLOCK(xprt_list_lock);
|
||||
|
@ -680,7 +679,9 @@ void xprt_force_disconnect(struct rpc_xprt *xprt)
|
|||
/* Try to schedule an autoclose RPC call */
|
||||
if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
|
||||
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);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xprt_force_disconnect);
|
||||
|
@ -820,7 +821,7 @@ void xprt_connect(struct rpc_task *task)
|
|||
if (!xprt_connected(xprt)) {
|
||||
task->tk_timeout = task->tk_rqstp->rq_timeout;
|
||||
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))
|
||||
return;
|
||||
|
@ -839,34 +840,6 @@ void xprt_connect(struct rpc_task *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 {
|
||||
XID_RB_EQUAL,
|
||||
XID_RB_LEFT,
|
||||
|
|
|
@ -1217,6 +1217,8 @@ static void xs_reset_transport(struct sock_xprt *transport)
|
|||
|
||||
trace_rpc_socket_close(xprt, sock);
|
||||
sock_release(sock);
|
||||
|
||||
xprt_disconnect_done(xprt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1237,8 +1239,6 @@ static void xs_close(struct rpc_xprt *xprt)
|
|||
|
||||
xs_reset_transport(transport);
|
||||
xprt->reestablish_timeout = 0;
|
||||
|
||||
xprt_disconnect_done(xprt);
|
||||
}
|
||||
|
||||
static void xs_inject_disconnect(struct rpc_xprt *xprt)
|
||||
|
@ -1489,8 +1489,6 @@ static void xs_tcp_state_change(struct sock *sk)
|
|||
&transport->sock_state))
|
||||
xprt_clear_connecting(xprt);
|
||||
clear_bit(XPRT_CLOSING, &xprt->state);
|
||||
if (sk->sk_err)
|
||||
xprt_wake_pending_tasks(xprt, -sk->sk_err);
|
||||
/* Trigger the socket release */
|
||||
xs_tcp_force_close(xprt);
|
||||
}
|
||||
|
@ -2092,8 +2090,8 @@ static void xs_udp_setup_socket(struct work_struct *work)
|
|||
trace_rpc_socket_connect(xprt, sock, 0);
|
||||
status = 0;
|
||||
out:
|
||||
xprt_unlock_connect(xprt, transport);
|
||||
xprt_clear_connecting(xprt);
|
||||
xprt_unlock_connect(xprt, transport);
|
||||
xprt_wake_pending_tasks(xprt, status);
|
||||
}
|
||||
|
||||
|
@ -2329,8 +2327,8 @@ static void xs_tcp_setup_socket(struct work_struct *work)
|
|||
}
|
||||
status = -EAGAIN;
|
||||
out:
|
||||
xprt_unlock_connect(xprt, transport);
|
||||
xprt_clear_connecting(xprt);
|
||||
xprt_unlock_connect(xprt, transport);
|
||||
xprt_wake_pending_tasks(xprt, status);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue