| From bafce987010469cea098ccae0989d4ab4fd67f95 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 30 Mar 2022 09:22:20 +0000 |
| Subject: cifs: do not use tcpStatus after negotiate completes |
| |
| From: Shyam Prasad N <sprasad@microsoft.com> |
| |
| [ Upstream commit 1a6a41d4cedd9b302e2200e6f0e3c44dbbe13689 ] |
| |
| 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> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/cifs/connect.c | 23 +++++++++++------------ |
| fs/cifs/smb2pdu.c | 3 ++- |
| fs/cifs/smb2transport.c | 3 ++- |
| 3 files changed, 15 insertions(+), 14 deletions(-) |
| |
| diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c |
| index b28b1ff39fed..aa2d4c49e2a5 100644 |
| --- a/fs/cifs/connect.c |
| +++ b/fs/cifs/connect.c |
| @@ -3956,7 +3956,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); |
| @@ -3979,19 +3979,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) |
| @@ -4015,13 +4014,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); |
| diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c |
| index 1b7ad0c09566..f5321a3500f3 100644 |
| --- a/fs/cifs/smb2pdu.c |
| +++ b/fs/cifs/smb2pdu.c |
| @@ -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); |
| diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c |
| index 2af79093b78b..01b732641edb 100644 |
| --- a/fs/cifs/smb2transport.c |
| +++ b/fs/cifs/smb2transport.c |
| @@ -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; |
| } |
| -- |
| 2.35.1 |
| |