Commit a05885ce authored by Shyam Prasad N's avatar Shyam Prasad N Committed by Steve French

cifs: fix the connection state transitions with multichannel

Recent changes to multichannel required some adjustments in
the way connection states transitioned during/after reconnect.

Also some minor fixes:
1. A pending switch of GlobalMid_Lock to cifs_tcp_ses_lock
2. Relocations of the code that logs reconnect
3. Changed some code in allocate_mid to suit the new scheme
Signed-off-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 3663c904
...@@ -181,17 +181,16 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server, ...@@ -181,17 +181,16 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
server->maxBuf = 0; server->maxBuf = 0;
server->max_read = 0; server->max_read = 0;
cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
trace_smb3_reconnect(server->CurrentMid, server->conn_id, server->hostname);
/* /*
* before reconnecting the tcp session, mark the smb session (uid) and the tid bad so they * before reconnecting the tcp session, mark the smb session (uid) and the tid bad so they
* are not used until reconnected. * are not used until reconnected.
*/ */
cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n", __func__); cifs_dbg(FYI, "%s: marking necessary sessions and tcons for reconnect\n", __func__);
/* If server is a channel, select the primary channel */ /* If server is a channel, select the primary channel */
pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server; pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
spin_lock(&ses->chan_lock); spin_lock(&ses->chan_lock);
...@@ -218,13 +217,8 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server, ...@@ -218,13 +217,8 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
} }
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
/*
* before reconnecting the tcp session, mark the smb session (uid)
* and the tid bad so they are not used until reconnected
*/
cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect and tearing down socket\n",
__func__);
/* do not want to be sending data on a socket we are freeing */ /* do not want to be sending data on a socket we are freeing */
cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
mutex_lock(&server->srv_mutex); mutex_lock(&server->srv_mutex);
if (server->ssocket) { if (server->ssocket) {
cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", server->ssocket->state, cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", server->ssocket->state,
...@@ -280,7 +274,12 @@ static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num ...@@ -280,7 +274,12 @@ static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num
wake_up(&server->response_q); wake_up(&server->response_q);
return false; return false;
} }
cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
trace_smb3_reconnect(server->CurrentMid, server->conn_id,
server->hostname);
server->tcpStatus = CifsNeedReconnect; server->tcpStatus = CifsNeedReconnect;
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
return true; return true;
} }
...@@ -634,7 +633,6 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg) ...@@ -634,7 +633,6 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
if (server->tcpStatus == CifsNeedReconnect) { if (server->tcpStatus == CifsNeedReconnect) {
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
cifs_reconnect(server, false);
return -ECONNABORTED; return -ECONNABORTED;
} }
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
...@@ -3885,6 +3883,11 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses, ...@@ -3885,6 +3883,11 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
else else
rc = -EHOSTDOWN; rc = -EHOSTDOWN;
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
} else {
spin_lock(&cifs_tcp_ses_lock);
if (server->tcpStatus == CifsInNegotiate)
server->tcpStatus = CifsNeedNegotiate;
spin_unlock(&cifs_tcp_ses_lock);
} }
return rc; return rc;
...@@ -3931,8 +3934,18 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, ...@@ -3931,8 +3934,18 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
if (server->ops->sess_setup) if (server->ops->sess_setup)
rc = server->ops->sess_setup(xid, ses, server, nls_info); rc = server->ops->sess_setup(xid, ses, server, nls_info);
if (rc) if (rc) {
cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
spin_lock(&cifs_tcp_ses_lock);
if (server->tcpStatus == CifsInSessSetup)
server->tcpStatus = CifsNeedSessSetup;
spin_unlock(&cifs_tcp_ses_lock);
} else {
spin_lock(&cifs_tcp_ses_lock);
if (server->tcpStatus == CifsInSessSetup)
server->tcpStatus = CifsGood;
spin_unlock(&cifs_tcp_ses_lock);
}
return rc; return rc;
} }
...@@ -4279,9 +4292,8 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t ...@@ -4279,9 +4292,8 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t
/* only send once per connect */ /* only send once per connect */
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
if (tcon->ses->status != CifsGood || if (tcon->tidStatus != CifsNew &&
(tcon->tidStatus != CifsNew && tcon->tidStatus != CifsNeedTcon) {
tcon->tidStatus != CifsNeedTcon)) {
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
return 0; return 0;
} }
......
...@@ -1054,7 +1054,6 @@ sess_establish_session(struct sess_data *sess_data) ...@@ -1054,7 +1054,6 @@ sess_establish_session(struct sess_data *sess_data)
/* Even if one channel is active, session is in good state */ /* Even if one channel is active, session is in good state */
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
server->tcpStatus = CifsGood;
ses->status = CifsGood; ses->status = CifsGood;
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
......
...@@ -1393,7 +1393,6 @@ SMB2_sess_establish_session(struct SMB2_sess_data *sess_data) ...@@ -1393,7 +1393,6 @@ SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
/* Even if one channel is active, session is in good state */ /* Even if one channel is active, session is in good state */
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
server->tcpStatus = CifsGood;
ses->status = CifsGood; ses->status = CifsGood;
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
......
...@@ -431,7 +431,8 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, ...@@ -431,7 +431,8 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
* socket so the server throws away the partial SMB * socket so the server throws away the partial SMB
*/ */
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
server->tcpStatus = CifsNeedReconnect; if (server->tcpStatus != CifsExiting)
server->tcpStatus = CifsNeedReconnect;
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
trace_smb3_partial_send_reconnect(server->CurrentMid, trace_smb3_partial_send_reconnect(server->CurrentMid,
server->conn_id, server->hostname); server->conn_id, server->hostname);
...@@ -729,17 +730,6 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, ...@@ -729,17 +730,6 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
struct mid_q_entry **ppmidQ) struct mid_q_entry **ppmidQ)
{ {
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
if (ses->server->tcpStatus == CifsExiting) {
spin_unlock(&cifs_tcp_ses_lock);
return -ENOENT;
}
if (ses->server->tcpStatus == CifsNeedReconnect) {
spin_unlock(&cifs_tcp_ses_lock);
cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
return -EAGAIN;
}
if (ses->status == CifsNew) { if (ses->status == CifsNew) {
if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
(in_buf->Command != SMB_COM_NEGOTIATE)) { (in_buf->Command != SMB_COM_NEGOTIATE)) {
......
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