@@ -179,7 +179,9 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
179
179
int left ;
180
180
int rc = 0 ;
181
181
int tries = 0 ;
182
+ size_t iface_weight = 0 , iface_min_speed = 0 ;
182
183
struct cifs_server_iface * iface = NULL , * niface = NULL ;
184
+ struct cifs_server_iface * last_iface = NULL ;
183
185
184
186
spin_lock (& ses -> chan_lock );
185
187
@@ -207,39 +209,47 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
207
209
}
208
210
spin_unlock (& ses -> chan_lock );
209
211
210
- /*
211
- * Keep connecting to same, fastest, iface for all channels as
212
- * long as its RSS. Try next fastest one if not RSS or channel
213
- * creation fails.
214
- */
215
- spin_lock (& ses -> iface_lock );
216
- iface = list_first_entry (& ses -> iface_list , struct cifs_server_iface ,
217
- iface_head );
218
- spin_unlock (& ses -> iface_lock );
219
-
220
212
while (left > 0 ) {
221
213
222
214
tries ++ ;
223
215
if (tries > 3 * ses -> chan_max ) {
224
- cifs_dbg (FYI , "too many channel open attempts (%d channels left to open)\n" ,
216
+ cifs_dbg (VFS , "too many channel open attempts (%d channels left to open)\n" ,
225
217
left );
226
218
break ;
227
219
}
228
220
229
221
spin_lock (& ses -> iface_lock );
230
222
if (!ses -> iface_count ) {
231
223
spin_unlock (& ses -> iface_lock );
224
+ cifs_dbg (VFS , "server %s does not advertise interfaces\n" ,
225
+ ses -> server -> hostname );
232
226
break ;
233
227
}
234
228
229
+ if (!iface )
230
+ iface = list_first_entry (& ses -> iface_list , struct cifs_server_iface ,
231
+ iface_head );
232
+ last_iface = list_last_entry (& ses -> iface_list , struct cifs_server_iface ,
233
+ iface_head );
234
+ iface_min_speed = last_iface -> speed ;
235
+
235
236
list_for_each_entry_safe_from (iface , niface , & ses -> iface_list ,
236
237
iface_head ) {
238
+ /* do not mix rdma and non-rdma interfaces */
239
+ if (iface -> rdma_capable != ses -> server -> rdma )
240
+ continue ;
241
+
237
242
/* skip ifaces that are unusable */
238
243
if (!iface -> is_active ||
239
244
(is_ses_using_iface (ses , iface ) &&
240
- !iface -> rss_capable )) {
245
+ !iface -> rss_capable ))
246
+ continue ;
247
+
248
+ /* check if we already allocated enough channels */
249
+ iface_weight = iface -> speed / iface_min_speed ;
250
+
251
+ if (iface -> weight_fulfilled >= iface_weight )
241
252
continue ;
242
- }
243
253
244
254
/* take ref before unlock */
245
255
kref_get (& iface -> refcount );
@@ -256,10 +266,21 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
256
266
continue ;
257
267
}
258
268
259
- cifs_dbg (FYI , "successfully opened new channel on iface:%pIS\n" ,
269
+ iface -> num_channels ++ ;
270
+ iface -> weight_fulfilled ++ ;
271
+ cifs_dbg (VFS , "successfully opened new channel on iface:%pIS\n" ,
260
272
& iface -> sockaddr );
261
273
break ;
262
274
}
275
+
276
+ /* reached end of list. reset weight_fulfilled and start over */
277
+ if (list_entry_is_head (iface , & ses -> iface_list , iface_head )) {
278
+ list_for_each_entry (iface , & ses -> iface_list , iface_head )
279
+ iface -> weight_fulfilled = 0 ;
280
+ spin_unlock (& ses -> iface_lock );
281
+ iface = NULL ;
282
+ continue ;
283
+ }
263
284
spin_unlock (& ses -> iface_lock );
264
285
265
286
left -- ;
278
299
cifs_chan_update_iface (struct cifs_ses * ses , struct TCP_Server_Info * server )
279
300
{
280
301
unsigned int chan_index ;
302
+ size_t iface_weight = 0 , iface_min_speed = 0 ;
281
303
struct cifs_server_iface * iface = NULL ;
282
304
struct cifs_server_iface * old_iface = NULL ;
305
+ struct cifs_server_iface * last_iface = NULL ;
283
306
int rc = 0 ;
284
307
285
308
spin_lock (& ses -> chan_lock );
@@ -299,13 +322,34 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
299
322
spin_unlock (& ses -> chan_lock );
300
323
301
324
spin_lock (& ses -> iface_lock );
325
+ if (!ses -> iface_count ) {
326
+ spin_unlock (& ses -> iface_lock );
327
+ cifs_dbg (VFS , "server %s does not advertise interfaces\n" , ses -> server -> hostname );
328
+ return 0 ;
329
+ }
330
+
331
+ last_iface = list_last_entry (& ses -> iface_list , struct cifs_server_iface ,
332
+ iface_head );
333
+ iface_min_speed = last_iface -> speed ;
334
+
302
335
/* then look for a new one */
303
336
list_for_each_entry (iface , & ses -> iface_list , iface_head ) {
337
+ /* do not mix rdma and non-rdma interfaces */
338
+ if (iface -> rdma_capable != server -> rdma )
339
+ continue ;
340
+
304
341
if (!iface -> is_active ||
305
342
(is_ses_using_iface (ses , iface ) &&
306
343
!iface -> rss_capable )) {
307
344
continue ;
308
345
}
346
+
347
+ /* check if we already allocated enough channels */
348
+ iface_weight = iface -> speed / iface_min_speed ;
349
+
350
+ if (iface -> weight_fulfilled >= iface_weight )
351
+ continue ;
352
+
309
353
kref_get (& iface -> refcount );
310
354
break ;
311
355
}
@@ -321,10 +365,22 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
321
365
cifs_dbg (FYI , "replacing iface: %pIS with %pIS\n" ,
322
366
& old_iface -> sockaddr ,
323
367
& iface -> sockaddr );
368
+
369
+ old_iface -> num_channels -- ;
370
+ if (old_iface -> weight_fulfilled )
371
+ old_iface -> weight_fulfilled -- ;
372
+ iface -> num_channels ++ ;
373
+ iface -> weight_fulfilled ++ ;
374
+
324
375
kref_put (& old_iface -> refcount , release_iface );
325
376
} else if (old_iface ) {
326
377
cifs_dbg (FYI , "releasing ref to iface: %pIS\n" ,
327
378
& old_iface -> sockaddr );
379
+
380
+ old_iface -> num_channels -- ;
381
+ if (old_iface -> weight_fulfilled )
382
+ old_iface -> weight_fulfilled -- ;
383
+
328
384
kref_put (& old_iface -> refcount , release_iface );
329
385
} else {
330
386
WARN_ON (!iface );
0 commit comments