mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 06:34:12 +08:00
cifs: avoid races in parallel reconnects in smb1
Prevent multiple threads of doing negotiate, session setup and tree connect by holding @ses->session_mutex in cifs_reconnect_tcon() while reconnecting session and tcon. Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com> Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
179a88a855
commit
6cc041e90c
@ -71,7 +71,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
|
||||
int rc;
|
||||
struct cifs_ses *ses;
|
||||
struct TCP_Server_Info *server;
|
||||
struct nls_table *nls_codepage;
|
||||
struct nls_table *nls_codepage = NULL;
|
||||
|
||||
/*
|
||||
* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
|
||||
@ -99,6 +99,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
|
||||
}
|
||||
spin_unlock(&tcon->tc_lock);
|
||||
|
||||
again:
|
||||
rc = cifs_wait_for_server_reconnect(server, tcon->retry);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -110,8 +111,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
|
||||
}
|
||||
spin_unlock(&ses->chan_lock);
|
||||
|
||||
nls_codepage = load_nls_default();
|
||||
|
||||
mutex_lock(&ses->session_mutex);
|
||||
/*
|
||||
* Recheck after acquire mutex. If another thread is negotiating
|
||||
* and the server never sends an answer the socket will be closed
|
||||
@ -120,29 +120,38 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
|
||||
spin_lock(&server->srv_lock);
|
||||
if (server->tcpStatus == CifsNeedReconnect) {
|
||||
spin_unlock(&server->srv_lock);
|
||||
mutex_lock(&ses->session_mutex);
|
||||
|
||||
if (tcon->retry)
|
||||
goto again;
|
||||
rc = -EHOSTDOWN;
|
||||
goto out;
|
||||
}
|
||||
spin_unlock(&server->srv_lock);
|
||||
|
||||
nls_codepage = load_nls_default();
|
||||
|
||||
/*
|
||||
* need to prevent multiple threads trying to simultaneously
|
||||
* reconnect the same SMB session
|
||||
*/
|
||||
spin_lock(&ses->ses_lock);
|
||||
spin_lock(&ses->chan_lock);
|
||||
if (!cifs_chan_needs_reconnect(ses, server)) {
|
||||
if (!cifs_chan_needs_reconnect(ses, server) &&
|
||||
ses->ses_status == SES_GOOD) {
|
||||
spin_unlock(&ses->chan_lock);
|
||||
spin_unlock(&ses->ses_lock);
|
||||
|
||||
/* this means that we only need to tree connect */
|
||||
if (tcon->need_reconnect)
|
||||
goto skip_sess_setup;
|
||||
|
||||
rc = -EHOSTDOWN;
|
||||
mutex_unlock(&ses->session_mutex);
|
||||
goto out;
|
||||
}
|
||||
spin_unlock(&ses->chan_lock);
|
||||
spin_unlock(&ses->ses_lock);
|
||||
|
||||
mutex_lock(&ses->session_mutex);
|
||||
rc = cifs_negotiate_protocol(0, ses, server);
|
||||
if (!rc)
|
||||
rc = cifs_setup_session(0, ses, server, nls_codepage);
|
||||
|
Loading…
Reference in New Issue
Block a user