cifs: account for primary channel in the interface list
[ Upstream commit fa1d0508bdd4a68c5e40f85f635712af8c12f180 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
548893404c
commit
b24d42b52b
@ -288,6 +288,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);
|
||||
@ -306,6 +307,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);
|
||||
@ -319,6 +324,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;
|
||||
@ -345,6 +360,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",
|
||||
@ -367,6 +389,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);
|
||||
|
@ -752,6 +752,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 &&
|
||||
@ -776,6 +777,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…
Reference in New Issue
Block a user