Skip to content

Commit fa1d050

Browse files
sprasad-microsoftSteve French
authored andcommitted
cifs: account for primary channel in the interface list
The refcounting of server interfaces should account for the primary channel too. Although this is not strictly necessary, doing so will account for the primary channel in DebugData. Cc: stable@vger.kernel.org Reviewed-by: Paulo Alcantara (SUSE) <pc@manguebit.com> Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent a6d8fb5 commit fa1d050

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

fs/smb/client/sess.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
303303
struct cifs_server_iface *iface = NULL;
304304
struct cifs_server_iface *old_iface = NULL;
305305
struct cifs_server_iface *last_iface = NULL;
306+
struct sockaddr_storage ss;
306307
int rc = 0;
307308

308309
spin_lock(&ses->chan_lock);
@@ -321,6 +322,10 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
321322
}
322323
spin_unlock(&ses->chan_lock);
323324

325+
spin_lock(&server->srv_lock);
326+
ss = server->dstaddr;
327+
spin_unlock(&server->srv_lock);
328+
324329
spin_lock(&ses->iface_lock);
325330
if (!ses->iface_count) {
326331
spin_unlock(&ses->iface_lock);
@@ -334,6 +339,16 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
334339

335340
/* then look for a new one */
336341
list_for_each_entry(iface, &ses->iface_list, iface_head) {
342+
if (!chan_index) {
343+
/* if we're trying to get the updated iface for primary channel */
344+
if (!cifs_match_ipaddr((struct sockaddr *) &ss,
345+
(struct sockaddr *) &iface->sockaddr))
346+
continue;
347+
348+
kref_get(&iface->refcount);
349+
break;
350+
}
351+
337352
/* do not mix rdma and non-rdma interfaces */
338353
if (iface->rdma_capable != server->rdma)
339354
continue;
@@ -360,6 +375,13 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
360375
cifs_dbg(FYI, "unable to find a suitable iface\n");
361376
}
362377

378+
if (!chan_index && !iface) {
379+
cifs_dbg(FYI, "unable to get the interface matching: %pIS\n",
380+
&ss);
381+
spin_unlock(&ses->iface_lock);
382+
return 0;
383+
}
384+
363385
/* now drop the ref to the current iface */
364386
if (old_iface && iface) {
365387
cifs_dbg(FYI, "replacing iface: %pIS with %pIS\n",
@@ -382,6 +404,12 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
382404
old_iface->weight_fulfilled--;
383405

384406
kref_put(&old_iface->refcount, release_iface);
407+
} else if (!chan_index) {
408+
/* special case: update interface for primary channel */
409+
cifs_dbg(FYI, "referencing primary channel iface: %pIS\n",
410+
&iface->sockaddr);
411+
iface->num_channels++;
412+
iface->weight_fulfilled++;
385413
} else {
386414
WARN_ON(!iface);
387415
cifs_dbg(FYI, "adding new iface: %pIS\n", &iface->sockaddr);

fs/smb/client/smb2ops.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_
756756
unsigned int ret_data_len = 0;
757757
struct network_interface_info_ioctl_rsp *out_buf = NULL;
758758
struct cifs_ses *ses = tcon->ses;
759+
struct TCP_Server_Info *pserver;
759760

760761
/* do not query too frequently */
761762
if (ses->iface_last_update &&
@@ -780,6 +781,11 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_
780781
if (rc)
781782
goto out;
782783

784+
/* check if iface is still active */
785+
pserver = ses->chans[0].server;
786+
if (pserver && !cifs_chan_is_iface_active(ses, pserver))
787+
cifs_chan_update_iface(ses, pserver);
788+
783789
out:
784790
kfree(out_buf);
785791
return rc;

0 commit comments

Comments
 (0)