@@ -1001,6 +1001,7 @@ void xprt_transmit(struct rpc_task *task)
1001
1001
{
1002
1002
struct rpc_rqst * req = task -> tk_rqstp ;
1003
1003
struct rpc_xprt * xprt = req -> rq_xprt ;
1004
+ unsigned int connect_cookie ;
1004
1005
int status , numreqs ;
1005
1006
1006
1007
dprintk ("RPC: %5u xprt_transmit(%u)\n" , task -> tk_pid , req -> rq_slen );
@@ -1024,6 +1025,7 @@ void xprt_transmit(struct rpc_task *task)
1024
1025
} else if (!req -> rq_bytes_sent )
1025
1026
return ;
1026
1027
1028
+ connect_cookie = xprt -> connect_cookie ;
1027
1029
req -> rq_xtime = ktime_get ();
1028
1030
status = xprt -> ops -> send_request (task );
1029
1031
trace_xprt_transmit (xprt , req -> rq_xid , status );
@@ -1047,20 +1049,28 @@ void xprt_transmit(struct rpc_task *task)
1047
1049
xprt -> stat .bklog_u += xprt -> backlog .qlen ;
1048
1050
xprt -> stat .sending_u += xprt -> sending .qlen ;
1049
1051
xprt -> stat .pending_u += xprt -> pending .qlen ;
1052
+ spin_unlock_bh (& xprt -> transport_lock );
1050
1053
1051
- /* Don't race with disconnect */
1052
- if (!xprt_connected (xprt ))
1053
- task -> tk_status = - ENOTCONN ;
1054
- else {
1054
+ req -> rq_connect_cookie = connect_cookie ;
1055
+ if (rpc_reply_expected (task ) && !READ_ONCE (req -> rq_reply_bytes_recvd )) {
1055
1056
/*
1056
- * Sleep on the pending queue since
1057
- * we're expecting a reply.
1057
+ * Sleep on the pending queue if we're expecting a reply.
1058
+ * The spinlock ensures atomicity between the test of
1059
+ * req->rq_reply_bytes_recvd, and the call to rpc_sleep_on().
1058
1060
*/
1059
- if (!req -> rq_reply_bytes_recvd && rpc_reply_expected (task ))
1061
+ spin_lock (& xprt -> recv_lock );
1062
+ if (!req -> rq_reply_bytes_recvd ) {
1060
1063
rpc_sleep_on (& xprt -> pending , task , xprt_timer );
1061
- req -> rq_connect_cookie = xprt -> connect_cookie ;
1064
+ /*
1065
+ * Send an extra queue wakeup call if the
1066
+ * connection was dropped in case the call to
1067
+ * rpc_sleep_on() raced.
1068
+ */
1069
+ if (!xprt_connected (xprt ))
1070
+ xprt_wake_pending_tasks (xprt , - ENOTCONN );
1071
+ }
1072
+ spin_unlock (& xprt -> recv_lock );
1062
1073
}
1063
- spin_unlock_bh (& xprt -> transport_lock );
1064
1074
}
1065
1075
1066
1076
static void xprt_add_backlog (struct rpc_xprt * xprt , struct rpc_task * task )
0 commit comments