@@ -54,41 +54,53 @@ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
5454{
5555 int i ;
5656
57+ spin_lock (& ses -> chan_lock );
5758 for (i = 0 ; i < ses -> chan_count ; i ++ ) {
58- if (is_server_using_iface (ses -> chans [i ].server , iface ))
59+ if (is_server_using_iface (ses -> chans [i ].server , iface )) {
60+ spin_unlock (& ses -> chan_lock );
5961 return true;
62+ }
6063 }
64+ spin_unlock (& ses -> chan_lock );
6165 return false;
6266}
6367
6468/* returns number of channels added */
6569int cifs_try_adding_channels (struct cifs_sb_info * cifs_sb , struct cifs_ses * ses )
6670{
67- int old_chan_count = ses -> chan_count ;
68- int left = ses -> chan_max - ses -> chan_count ;
71+ int old_chan_count , new_chan_count ;
72+ int left ;
6973 int i = 0 ;
7074 int rc = 0 ;
7175 int tries = 0 ;
7276 struct cifs_server_iface * ifaces = NULL ;
7377 size_t iface_count ;
7478
79+ if (ses -> server -> dialect < SMB30_PROT_ID ) {
80+ cifs_dbg (VFS , "multichannel is not supported on this protocol version, use 3.0 or above\n" );
81+ return 0 ;
82+ }
83+
84+ spin_lock (& ses -> chan_lock );
85+
86+ new_chan_count = old_chan_count = ses -> chan_count ;
87+ left = ses -> chan_max - ses -> chan_count ;
88+
7589 if (left <= 0 ) {
7690 cifs_dbg (FYI ,
7791 "ses already at max_channels (%zu), nothing to open\n" ,
7892 ses -> chan_max );
79- return 0 ;
80- }
81-
82- if (ses -> server -> dialect < SMB30_PROT_ID ) {
83- cifs_dbg (VFS , "multichannel is not supported on this protocol version, use 3.0 or above\n" );
93+ spin_unlock (& ses -> chan_lock );
8494 return 0 ;
8595 }
8696
8797 if (!(ses -> server -> capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL )) {
8898 cifs_dbg (VFS , "server %s does not support multichannel\n" , ses -> server -> hostname );
8999 ses -> chan_max = 1 ;
100+ spin_unlock (& ses -> chan_lock );
90101 return 0 ;
91102 }
103+ spin_unlock (& ses -> chan_lock );
92104
93105 /*
94106 * Make a copy of the iface list at the time and use that
@@ -142,10 +154,11 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
142154 cifs_dbg (FYI , "successfully opened new channel on iface#%d\n" ,
143155 i );
144156 left -- ;
157+ new_chan_count ++ ;
145158 }
146159
147160 kfree (ifaces );
148- return ses -> chan_count - old_chan_count ;
161+ return new_chan_count - old_chan_count ;
149162}
150163
151164/*
@@ -157,17 +170,22 @@ cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server)
157170{
158171 int i ;
159172
173+ spin_lock (& ses -> chan_lock );
160174 for (i = 0 ; i < ses -> chan_count ; i ++ ) {
161- if (ses -> chans [i ].server == server )
175+ if (ses -> chans [i ].server == server ) {
176+ spin_unlock (& ses -> chan_lock );
162177 return & ses -> chans [i ];
178+ }
163179 }
180+ spin_unlock (& ses -> chan_lock );
164181 return NULL ;
165182}
166183
167184static int
168185cifs_ses_add_channel (struct cifs_sb_info * cifs_sb , struct cifs_ses * ses ,
169186 struct cifs_server_iface * iface )
170187{
188+ struct TCP_Server_Info * chan_server ;
171189 struct cifs_chan * chan ;
172190 struct smb3_fs_context ctx = {NULL };
173191 static const char unc_fmt [] = "\\%s\\foo" ;
@@ -240,15 +258,20 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
240258 SMB2_CLIENT_GUID_SIZE );
241259 ctx .use_client_guid = true;
242260
243- mutex_lock ( & ses -> session_mutex );
261+ chan_server = cifs_get_tcp_session ( & ctx );
244262
263+ mutex_lock (& ses -> session_mutex );
264+ spin_lock (& ses -> chan_lock );
245265 chan = ses -> binding_chan = & ses -> chans [ses -> chan_count ];
246- chan -> server = cifs_get_tcp_session ( & ctx ) ;
266+ chan -> server = chan_server ;
247267 if (IS_ERR (chan -> server )) {
248268 rc = PTR_ERR (chan -> server );
249269 chan -> server = NULL ;
270+ spin_unlock (& ses -> chan_lock );
250271 goto out ;
251272 }
273+ spin_unlock (& ses -> chan_lock );
274+
252275 spin_lock (& cifs_tcp_ses_lock );
253276 chan -> server -> is_channel = true;
254277 spin_unlock (& cifs_tcp_ses_lock );
@@ -283,8 +306,11 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
283306 * ses to the new server.
284307 */
285308
309+ spin_lock (& ses -> chan_lock );
286310 ses -> chan_count ++ ;
287311 atomic_set (& ses -> chan_seq , 0 );
312+ spin_unlock (& ses -> chan_lock );
313+
288314out :
289315 ses -> binding = false;
290316 ses -> binding_chan = NULL ;
0 commit comments