@@ -208,10 +208,13 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
208208 if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT (ses ))
209209 goto next_session ;
210210
211+ ses -> status = CifsNeedReconnect ;
211212 num_sessions ++ ;
212213
213- list_for_each_entry (tcon , & ses -> tcon_list , tcon_list )
214+ list_for_each_entry (tcon , & ses -> tcon_list , tcon_list ) {
214215 tcon -> need_reconnect = true;
216+ tcon -> tidStatus = CifsNeedReconnect ;
217+ }
215218 if (ses -> tcon_ipc )
216219 ses -> tcon_ipc -> need_reconnect = true;
217220
@@ -2035,12 +2038,12 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
20352038 cifs_dbg (FYI , "Existing smb sess found (status=%d)\n" ,
20362039 ses -> status );
20372040
2038- mutex_lock (& ses -> session_mutex );
20392041 spin_lock (& ses -> chan_lock );
20402042 if (cifs_chan_needs_reconnect (ses , server )) {
20412043 spin_unlock (& ses -> chan_lock );
20422044 cifs_dbg (FYI , "Session needs reconnect\n" );
20432045
2046+ mutex_lock (& ses -> session_mutex );
20442047 rc = cifs_negotiate_protocol (xid , ses , server );
20452048 if (rc ) {
20462049 mutex_unlock (& ses -> session_mutex );
@@ -2059,10 +2062,11 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
20592062 free_xid (xid );
20602063 return ERR_PTR (rc );
20612064 }
2065+ mutex_unlock (& ses -> session_mutex );
2066+
20622067 spin_lock (& ses -> chan_lock );
20632068 }
20642069 spin_unlock (& ses -> chan_lock );
2065- mutex_unlock (& ses -> session_mutex );
20662070
20672071 /* existing SMB ses has a server reference already */
20682072 cifs_put_tcp_session (server , 0 );
@@ -2112,7 +2116,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
21122116
21132117 ses -> sectype = ctx -> sectype ;
21142118 ses -> sign = ctx -> sign ;
2115- mutex_lock (& ses -> session_mutex );
21162119
21172120 /* add server as first channel */
21182121 spin_lock (& ses -> chan_lock );
@@ -2122,15 +2125,16 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
21222125 ses -> chans_need_reconnect = 1 ;
21232126 spin_unlock (& ses -> chan_lock );
21242127
2128+ mutex_lock (& ses -> session_mutex );
21252129 rc = cifs_negotiate_protocol (xid , ses , server );
21262130 if (!rc )
21272131 rc = cifs_setup_session (xid , ses , server , ctx -> local_nls );
2132+ mutex_unlock (& ses -> session_mutex );
21282133
21292134 /* each channel uses a different signing key */
21302135 memcpy (ses -> chans [0 ].signkey , ses -> smb3signingkey ,
21312136 sizeof (ses -> smb3signingkey ));
21322137
2133- mutex_unlock (& ses -> session_mutex );
21342138 if (rc )
21352139 goto get_ses_fail ;
21362140
@@ -2347,10 +2351,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
23472351 }
23482352 }
23492353
2350- /*
2351- * BB Do we need to wrap session_mutex around this TCon call and Unix
2352- * SetFS as we do on SessSetup and reconnect?
2353- */
23542354 xid = get_xid ();
23552355 rc = ses -> server -> ops -> tree_connect (xid , ses , ctx -> UNC , tcon ,
23562356 ctx -> local_nls );
@@ -3870,14 +3870,20 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
38703870 return - ENOSYS ;
38713871
38723872 /* only send once per connect */
3873- if (!server -> ops -> need_neg (server ))
3873+ spin_lock (& cifs_tcp_ses_lock );
3874+ if (!server -> ops -> need_neg (server ) ||
3875+ server -> tcpStatus != CifsNeedNegotiate ) {
3876+ spin_unlock (& cifs_tcp_ses_lock );
38743877 return 0 ;
3878+ }
3879+ server -> tcpStatus = CifsInNegotiate ;
3880+ spin_unlock (& cifs_tcp_ses_lock );
38753881
38763882 rc = server -> ops -> negotiate (xid , ses , server );
38773883 if (rc == 0 ) {
38783884 spin_lock (& cifs_tcp_ses_lock );
3879- if (server -> tcpStatus == CifsNeedNegotiate )
3880- server -> tcpStatus = CifsGood ;
3885+ if (server -> tcpStatus == CifsInNegotiate )
3886+ server -> tcpStatus = CifsNeedSessSetup ;
38813887 else
38823888 rc = - EHOSTDOWN ;
38833889 spin_unlock (& cifs_tcp_ses_lock );
@@ -3894,6 +3900,15 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
38943900 int rc = - ENOSYS ;
38953901 bool is_binding = false;
38963902
3903+ /* only send once per connect */
3904+ spin_lock (& cifs_tcp_ses_lock );
3905+ if (server -> tcpStatus != CifsNeedSessSetup ) {
3906+ spin_unlock (& cifs_tcp_ses_lock );
3907+ return 0 ;
3908+ }
3909+ ses -> status = CifsInSessSetup ;
3910+ spin_unlock (& cifs_tcp_ses_lock );
3911+
38973912 spin_lock (& ses -> chan_lock );
38983913 is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT (ses );
38993914 spin_unlock (& ses -> chan_lock );
@@ -4264,6 +4279,17 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t
42644279 struct dfs_cache_tgt_iterator * tit ;
42654280 bool target_match ;
42664281
4282+ /* only send once per connect */
4283+ spin_lock (& cifs_tcp_ses_lock );
4284+ if (tcon -> ses -> status != CifsGood ||
4285+ (tcon -> tidStatus != CifsNew &&
4286+ tcon -> tidStatus != CifsNeedTcon )) {
4287+ spin_unlock (& cifs_tcp_ses_lock );
4288+ return 0 ;
4289+ }
4290+ tcon -> tidStatus = CifsInTcon ;
4291+ spin_unlock (& cifs_tcp_ses_lock );
4292+
42674293 extract_unc_hostname (server -> hostname , & tcp_host , & tcp_host_len );
42684294
42694295 tit = dfs_cache_get_tgt_iterator (tl );
@@ -4422,6 +4448,17 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
44224448{
44234449 const struct smb_version_operations * ops = tcon -> ses -> server -> ops ;
44244450
4451+ /* only send once per connect */
4452+ spin_lock (& cifs_tcp_ses_lock );
4453+ if (tcon -> ses -> status != CifsGood ||
4454+ (tcon -> tidStatus != CifsNew &&
4455+ tcon -> tidStatus != CifsNeedTcon )) {
4456+ spin_unlock (& cifs_tcp_ses_lock );
4457+ return 0 ;
4458+ }
4459+ tcon -> tidStatus = CifsInTcon ;
4460+ spin_unlock (& cifs_tcp_ses_lock );
4461+
44254462 return ops -> tree_connect (xid , tcon -> ses , tcon -> treeName , tcon , nlsc );
44264463}
44274464#endif
0 commit comments