mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-24 01:09:38 -05:00
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>
This commit is contained in:
parent
a6d8fb54a5
commit
fa1d0508bd
2 changed files with 34 additions and 0 deletions
|
@ -303,6 +303,7 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
|
|||
struct cifs_server_iface *iface = NULL;
|
||||
struct cifs_server_iface *old_iface = NULL;
|
||||
struct cifs_server_iface *last_iface = NULL;
|
||||
struct sockaddr_storage ss;
|
||||
int rc = 0;
|
||||
|
||||
spin_lock(&ses->chan_lock);
|
||||
|
@ -321,6 +322,10 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
|
|||
}
|
||||
spin_unlock(&ses->chan_lock);
|
||||
|
||||
spin_lock(&server->srv_lock);
|
||||
ss = server->dstaddr;
|
||||
spin_unlock(&server->srv_lock);
|
||||
|
||||
spin_lock(&ses->iface_lock);
|
||||
if (!ses->iface_count) {
|
||||
spin_unlock(&ses->iface_lock);
|
||||
|
@ -334,6 +339,16 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
|
|||
|
||||
/* then look for a new one */
|
||||
list_for_each_entry(iface, &ses->iface_list, iface_head) {
|
||||
if (!chan_index) {
|
||||
/* if we're trying to get the updated iface for primary channel */
|
||||
if (!cifs_match_ipaddr((struct sockaddr *) &ss,
|
||||
(struct sockaddr *) &iface->sockaddr))
|
||||
continue;
|
||||
|
||||
kref_get(&iface->refcount);
|
||||
break;
|
||||
}
|
||||
|
||||
/* do not mix rdma and non-rdma interfaces */
|
||||
if (iface->rdma_capable != server->rdma)
|
||||
continue;
|
||||
|
@ -360,6 +375,13 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
|
|||
cifs_dbg(FYI, "unable to find a suitable iface\n");
|
||||
}
|
||||
|
||||
if (!chan_index && !iface) {
|
||||
cifs_dbg(FYI, "unable to get the interface matching: %pIS\n",
|
||||
&ss);
|
||||
spin_unlock(&ses->iface_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* now drop the ref to the current iface */
|
||||
if (old_iface && iface) {
|
||||
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)
|
|||
old_iface->weight_fulfilled--;
|
||||
|
||||
kref_put(&old_iface->refcount, release_iface);
|
||||
} else if (!chan_index) {
|
||||
/* special case: update interface for primary channel */
|
||||
cifs_dbg(FYI, "referencing primary channel iface: %pIS\n",
|
||||
&iface->sockaddr);
|
||||
iface->num_channels++;
|
||||
iface->weight_fulfilled++;
|
||||
} else {
|
||||
WARN_ON(!iface);
|
||||
cifs_dbg(FYI, "adding new iface: %pIS\n", &iface->sockaddr);
|
||||
|
|
|
@ -756,6 +756,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_
|
|||
unsigned int ret_data_len = 0;
|
||||
struct network_interface_info_ioctl_rsp *out_buf = NULL;
|
||||
struct cifs_ses *ses = tcon->ses;
|
||||
struct TCP_Server_Info *pserver;
|
||||
|
||||
/* do not query too frequently */
|
||||
if (ses->iface_last_update &&
|
||||
|
@ -780,6 +781,11 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_
|
|||
if (rc)
|
||||
goto out;
|
||||
|
||||
/* check if iface is still active */
|
||||
pserver = ses->chans[0].server;
|
||||
if (pserver && !cifs_chan_is_iface_active(ses, pserver))
|
||||
cifs_chan_update_iface(ses, pserver);
|
||||
|
||||
out:
|
||||
kfree(out_buf);
|
||||
return rc;
|
||||
|
|
Loading…
Add table
Reference in a new issue