]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
cifs: do not use tcpStatus after negotiate completes
authorShyam Prasad N <sprasad@microsoft.com>
Wed, 30 Mar 2022 09:22:20 +0000 (09:22 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jun 2022 08:29:52 +0000 (10:29 +0200)
[ 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
fs/cifs/smb2pdu.c
fs/cifs/smb2transport.c

index b28b1ff39fed3e1a91a999a011fdf39bf08fb4c5..aa2d4c49e2a5b53fc0c9b63684cf9ee488b0c7e0 100644 (file)
@@ -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);
index 1b7ad0c09566876185216446aa88f0b8f96fcd28..f5321a3500f3812fbc8a6714be8bff09877bf163 100644 (file)
@@ -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);
index 2af79093b78bcc2f7a7c60a4df0fb5c1fff83bc1..01b732641edb2255a87026c451104bfa83b3f59d 100644 (file)
@@ -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;
        }