Skip to content

Commit

Permalink
cifs: do not use tcpStatus after negotiate completes
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Steve French <[email protected]>
  • Loading branch information
sprasad-microsoft authored and Steve French committed May 24, 2022
1 parent 5283225 commit 1a6a41d
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 14 deletions.
23 changes: 11 additions & 12 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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(&ses->chan_lock);
is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
spin_unlock(&ses->chan_lock);

spin_lock(&cifs_tcp_ses_lock);
if ((server->tcpStatus != CifsNeedSessSetup) &&
(ses->status == CifsGood)) {
if (ses->status == CifsExiting) {
spin_unlock(&cifs_tcp_ses_lock);
return 0;
}
server->tcpStatus = CifsInSessSetup;
ses->status = 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);

if (!is_binding) {
ses->capabilities = server->capabilities;
if (!linuxExtEnabled)
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion fs/cifs/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion fs/cifs/smb2transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit 1a6a41d

Please sign in to comment.