cifs: do not use tcpStatus after negotiate completes
Recent changes to multichannel to allow channel reconnects to work in parallel and independent of each other did so by making use of tcpStatus for the connection, and status for the session. However, this did not take into account the multiuser scenario, where same connection is used by multiple connections. However, tcpStatus should be tracked only till the end of negotiate exchange, and not used for session setup. This change fixes this. Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
52832252dd
commit
1a6a41d4ce
@ -3973,7 +3973,7 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
|
||||
if (rc == 0) {
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsInNegotiate)
|
||||
server->tcpStatus = CifsNeedSessSetup;
|
||||
server->tcpStatus = CifsGood;
|
||||
else
|
||||
rc = -EHOSTDOWN;
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
@ -3996,19 +3996,18 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
||||
bool is_binding = false;
|
||||
|
||||
/* only send once per connect */
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if ((server->tcpStatus != CifsNeedSessSetup) &&
|
||||
(ses->status == CifsGood)) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return 0;
|
||||
}
|
||||
server->tcpStatus = CifsInSessSetup;
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
spin_lock(&ses->chan_lock);
|
||||
is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
||||
spin_unlock(&ses->chan_lock);
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (ses->status == CifsExiting) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return 0;
|
||||
}
|
||||
ses->status = CifsInSessSetup;
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
if (!is_binding) {
|
||||
ses->capabilities = server->capabilities;
|
||||
if (!linuxExtEnabled)
|
||||
@ -4032,13 +4031,13 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
||||
if (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;
|
||||
if (ses->status == CifsInSessSetup)
|
||||
ses->status = CifsNeedSessSetup;
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
} else {
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsInSessSetup)
|
||||
server->tcpStatus = CifsGood;
|
||||
if (ses->status == CifsInSessSetup)
|
||||
ses->status = CifsGood;
|
||||
/* Even if one channel is active, session is in good state */
|
||||
ses->status = CifsGood;
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
@ -3899,7 +3899,8 @@ SMB2_echo(struct TCP_Server_Info *server)
|
||||
cifs_dbg(FYI, "In echo request for conn_id %lld\n", server->conn_id);
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsNeedNegotiate) {
|
||||
if (server->ops->need_neg &&
|
||||
server->ops->need_neg(server)) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
/* No need to send echo on newly established connections */
|
||||
mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
|
||||
|
@ -641,7 +641,8 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
if (!is_signed)
|
||||
return 0;
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsNeedNegotiate) {
|
||||
if (server->ops->need_neg &&
|
||||
server->ops->need_neg(server)) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user