Skip to content

Commit 12d1e30

Browse files
sprasad-microsoftsmfrench
authored andcommitted
cifs: do not let cifs_chan_update_iface deallocate channels
cifs_chan_update_iface is meant to check and update the server interface used for a channel when the existing server interface is no longer available. So far, this handler had the code to remove an interface entry even if a new candidate interface is not available. Allowing this leads to several corner cases to handle. This change makes the logic much simpler by not deallocating the current channel interface entry if a new interface is not found to replace it with. Signed-off-by: Shyam Prasad N <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent f30bbc3 commit 12d1e30

File tree

1 file changed

+19
-31
lines changed

1 file changed

+19
-31
lines changed

fs/smb/client/sess.c

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -439,15 +439,15 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
439439
cifs_dbg(FYI, "unable to find a suitable iface\n");
440440
}
441441

442-
if (!chan_index && !iface) {
442+
if (!iface) {
443443
cifs_dbg(FYI, "unable to get the interface matching: %pIS\n",
444444
&ss);
445445
spin_unlock(&ses->iface_lock);
446446
return 0;
447447
}
448448

449449
/* now drop the ref to the current iface */
450-
if (old_iface && iface) {
450+
if (old_iface) {
451451
cifs_dbg(FYI, "replacing iface: %pIS with %pIS\n",
452452
&old_iface->sockaddr,
453453
&iface->sockaddr);
@@ -460,44 +460,32 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
460460

461461
kref_put(&old_iface->refcount, release_iface);
462462
} else if (old_iface) {
463-
cifs_dbg(FYI, "releasing ref to iface: %pIS\n",
463+
/* if a new candidate is not found, keep things as is */
464+
cifs_dbg(FYI, "could not replace iface: %pIS\n",
464465
&old_iface->sockaddr);
465-
466-
old_iface->num_channels--;
467-
if (old_iface->weight_fulfilled)
468-
old_iface->weight_fulfilled--;
469-
470-
kref_put(&old_iface->refcount, release_iface);
471466
} else if (!chan_index) {
472467
/* special case: update interface for primary channel */
473-
cifs_dbg(FYI, "referencing primary channel iface: %pIS\n",
474-
&iface->sockaddr);
475-
iface->num_channels++;
476-
iface->weight_fulfilled++;
477-
} else {
478-
WARN_ON(!iface);
479-
cifs_dbg(FYI, "adding new iface: %pIS\n", &iface->sockaddr);
468+
if (iface) {
469+
cifs_dbg(FYI, "referencing primary channel iface: %pIS\n",
470+
&iface->sockaddr);
471+
iface->num_channels++;
472+
iface->weight_fulfilled++;
473+
}
480474
}
481475
spin_unlock(&ses->iface_lock);
482476

483-
spin_lock(&ses->chan_lock);
484-
chan_index = cifs_ses_get_chan_index(ses, server);
485-
if (chan_index == CIFS_INVAL_CHAN_INDEX) {
477+
if (iface) {
478+
spin_lock(&ses->chan_lock);
479+
chan_index = cifs_ses_get_chan_index(ses, server);
480+
if (chan_index == CIFS_INVAL_CHAN_INDEX) {
481+
spin_unlock(&ses->chan_lock);
482+
return 0;
483+
}
484+
485+
ses->chans[chan_index].iface = iface;
486486
spin_unlock(&ses->chan_lock);
487-
return 0;
488487
}
489488

490-
ses->chans[chan_index].iface = iface;
491-
492-
/* No iface is found. if secondary chan, drop connection */
493-
if (!iface && SERVER_IS_CHAN(server))
494-
ses->chans[chan_index].server = NULL;
495-
496-
spin_unlock(&ses->chan_lock);
497-
498-
if (!iface && SERVER_IS_CHAN(server))
499-
cifs_put_tcp_session(server, false);
500-
501489
return rc;
502490
}
503491

0 commit comments

Comments
 (0)