@@ -146,6 +146,16 @@ cifs_chan_needs_reconnect(struct cifs_ses *ses,
146
146
return CIFS_CHAN_NEEDS_RECONNECT (ses , chan_index );
147
147
}
148
148
149
+ bool
150
+ cifs_chan_is_iface_active (struct cifs_ses * ses ,
151
+ struct TCP_Server_Info * server )
152
+ {
153
+ unsigned int chan_index = cifs_ses_get_chan_index (ses , server );
154
+
155
+ return ses -> chans [chan_index ].iface &&
156
+ ses -> chans [chan_index ].iface -> is_active ;
157
+ }
158
+
149
159
/* returns number of channels added */
150
160
int cifs_try_adding_channels (struct cifs_sb_info * cifs_sb , struct cifs_ses * ses )
151
161
{
@@ -244,6 +254,75 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
244
254
return new_chan_count - old_chan_count ;
245
255
}
246
256
257
+ /*
258
+ * update the iface for the channel if necessary.
259
+ * will return 0 when iface is updated. 1 otherwise
260
+ * Must be called with chan_lock held.
261
+ */
262
+ int
263
+ cifs_chan_update_iface (struct cifs_ses * ses , struct TCP_Server_Info * server )
264
+ {
265
+ unsigned int chan_index = cifs_ses_get_chan_index (ses , server );
266
+ struct cifs_server_iface * iface = NULL ;
267
+ struct cifs_server_iface * old_iface = NULL ;
268
+ int rc = 0 ;
269
+
270
+ /* primary channel. This can never go away */
271
+ if (!chan_index )
272
+ return 0 ;
273
+
274
+ if (ses -> chans [chan_index ].iface ) {
275
+ old_iface = ses -> chans [chan_index ].iface ;
276
+ if (old_iface -> is_active )
277
+ return 1 ;
278
+ }
279
+
280
+ spin_lock (& ses -> iface_lock );
281
+
282
+ /* then look for a new one */
283
+ list_for_each_entry (iface , & ses -> iface_list , iface_head ) {
284
+ if (!iface -> is_active ||
285
+ (is_ses_using_iface (ses , iface ) &&
286
+ !iface -> rss_capable )) {
287
+ continue ;
288
+ }
289
+ kref_get (& iface -> refcount );
290
+ }
291
+
292
+ if (!list_entry_is_head (iface , & ses -> iface_list , iface_head )) {
293
+ rc = 1 ;
294
+ iface = NULL ;
295
+ cifs_dbg (FYI , "unable to find a suitable iface\n" );
296
+ }
297
+
298
+ ses -> chans [chan_index ].iface = iface ;
299
+
300
+ /* now drop the ref to the current iface */
301
+ if (old_iface && iface ) {
302
+ kref_put (& old_iface -> refcount , release_iface );
303
+ cifs_dbg (FYI , "replacing iface: %pIS with %pIS\n" ,
304
+ & old_iface -> sockaddr ,
305
+ & iface -> sockaddr );
306
+ } else if (old_iface ) {
307
+ kref_put (& old_iface -> refcount , release_iface );
308
+ cifs_dbg (FYI , "releasing ref to iface: %pIS\n" ,
309
+ & old_iface -> sockaddr );
310
+ } else {
311
+ WARN_ON (!iface );
312
+ cifs_dbg (FYI , "adding new iface: %pIS\n" , & iface -> sockaddr );
313
+ }
314
+
315
+ spin_unlock (& ses -> iface_lock );
316
+
317
+ /* No iface is found. if secondary chan, drop connection */
318
+ if (!iface && CIFS_SERVER_IS_CHAN (server )) {
319
+ cifs_put_tcp_session (server , false);
320
+ ses -> chans [chan_index ].server = NULL ;
321
+ }
322
+
323
+ return rc ;
324
+ }
325
+
247
326
/*
248
327
* If server is a channel of ses, return the corresponding enclosing
249
328
* cifs_chan otherwise return NULL.
0 commit comments