@@ -58,7 +58,7 @@ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
5858
5959 spin_lock (& ses -> chan_lock );
6060 for (i = 0 ; i < ses -> chan_count ; i ++ ) {
61- if (is_server_using_iface ( ses -> chans [i ].server , iface ) ) {
61+ if (ses -> chans [i ].iface == iface ) {
6262 spin_unlock (& ses -> chan_lock );
6363 return true;
6464 }
@@ -151,11 +151,9 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
151151{
152152 int old_chan_count , new_chan_count ;
153153 int left ;
154- int i = 0 ;
155154 int rc = 0 ;
156155 int tries = 0 ;
157- struct cifs_server_iface * ifaces = NULL ;
158- size_t iface_count ;
156+ struct cifs_server_iface * iface = NULL , * niface = NULL ;
159157
160158 spin_lock (& ses -> chan_lock );
161159
@@ -184,33 +182,17 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
184182 }
185183 spin_unlock (& ses -> chan_lock );
186184
187- /*
188- * Make a copy of the iface list at the time and use that
189- * instead so as to not hold the iface spinlock for opening
190- * channels
191- */
192- spin_lock (& ses -> iface_lock );
193- iface_count = ses -> iface_count ;
194- if (iface_count <= 0 ) {
195- spin_unlock (& ses -> iface_lock );
196- cifs_dbg (VFS , "no iface list available to open channels\n" );
197- return 0 ;
198- }
199- ifaces = kmemdup (ses -> iface_list , iface_count * sizeof (* ifaces ),
200- GFP_ATOMIC );
201- if (!ifaces ) {
202- spin_unlock (& ses -> iface_lock );
203- return 0 ;
204- }
205- spin_unlock (& ses -> iface_lock );
206-
207185 /*
208186 * Keep connecting to same, fastest, iface for all channels as
209187 * long as its RSS. Try next fastest one if not RSS or channel
210188 * creation fails.
211189 */
190+ spin_lock (& ses -> iface_lock );
191+ iface = list_first_entry (& ses -> iface_list , struct cifs_server_iface ,
192+ iface_head );
193+ spin_unlock (& ses -> iface_lock );
194+
212195 while (left > 0 ) {
213- struct cifs_server_iface * iface ;
214196
215197 tries ++ ;
216198 if (tries > 3 * ses -> chan_max ) {
@@ -219,27 +201,46 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
219201 break ;
220202 }
221203
222- iface = & ifaces [ i ] ;
223- if (is_ses_using_iface ( ses , iface ) && ! iface -> rss_capable ) {
224- i = ( i + 1 ) % iface_count ;
225- continue ;
204+ spin_lock ( & ses -> iface_lock ) ;
205+ if (! ses -> iface_count ) {
206+ spin_unlock ( & ses -> iface_lock ) ;
207+ break ;
226208 }
227209
228- rc = cifs_ses_add_channel (cifs_sb , ses , iface );
229- if (rc ) {
230- cifs_dbg (FYI , "failed to open extra channel on iface#%d rc=%d\n" ,
231- i , rc );
232- i = (i + 1 ) % iface_count ;
233- continue ;
210+ list_for_each_entry_safe_from (iface , niface , & ses -> iface_list ,
211+ iface_head ) {
212+ /* skip ifaces that are unusable */
213+ if (!iface -> is_active ||
214+ (is_ses_using_iface (ses , iface ) &&
215+ !iface -> rss_capable )) {
216+ continue ;
217+ }
218+
219+ /* take ref before unlock */
220+ kref_get (& iface -> refcount );
221+
222+ spin_unlock (& ses -> iface_lock );
223+ rc = cifs_ses_add_channel (cifs_sb , ses , iface );
224+ spin_lock (& ses -> iface_lock );
225+
226+ if (rc ) {
227+ cifs_dbg (VFS , "failed to open extra channel on iface:%pIS rc=%d\n" ,
228+ & iface -> sockaddr ,
229+ rc );
230+ kref_put (& iface -> refcount , release_iface );
231+ continue ;
232+ }
233+
234+ cifs_dbg (FYI , "successfully opened new channel on iface:%pIS\n" ,
235+ & iface -> sockaddr );
236+ break ;
234237 }
238+ spin_unlock (& ses -> iface_lock );
235239
236- cifs_dbg (FYI , "successfully opened new channel on iface#%d\n" ,
237- i );
238240 left -- ;
239241 new_chan_count ++ ;
240242 }
241243
242- kfree (ifaces );
243244 return new_chan_count - old_chan_count ;
244245}
245246
@@ -355,6 +356,7 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
355356 spin_unlock (& ses -> chan_lock );
356357 goto out ;
357358 }
359+ chan -> iface = iface ;
358360 ses -> chan_count ++ ;
359361 atomic_set (& ses -> chan_seq , 0 );
360362
0 commit comments