diff options
Diffstat (limited to 'fs/smb/client/sess.c')
-rw-r--r-- | fs/smb/client/sess.c | 48 |
1 files changed, 23 insertions, 25 deletions
diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c index 3ba123d95958..fd68f1d1ebd2 100644 --- a/fs/smb/client/sess.c +++ b/fs/smb/client/sess.c @@ -149,17 +149,23 @@ cifs_chan_is_iface_active(struct cifs_ses *ses, * >0: number of channels remaining to be opened * <0: error from cifs_ses_add_channel() */ -static int try_adding_channels(struct cifs_ses *ses) +static int try_adding_channels(struct cifs_ses *ses, struct list_head *ifaces) { - size_t iface_weight = 0, iface_min_speed = 0; - struct cifs_server_iface *iface = NULL, *niface = NULL; - struct cifs_server_iface *last_iface = NULL; + size_t weight = 0, min_speed = 0; + struct cifs_server_iface *iface = NULL, *niface = NULL, *last; int rc = 0, left = ses->chan_max - ses->chan_count; - last_iface = list_last_entry(&ses->iface_list, struct cifs_server_iface, iface_head); - iface_min_speed = last_iface->speed; + if (list_empty(ifaces)) + return 0; - list_for_each_entry_safe(iface, niface, &ses->iface_list, iface_head) { + last = list_last_entry(ifaces, struct cifs_server_iface, iface_head); + min_speed = last->speed; + if (!list_empty(&ses->iface_list)) { + last = list_last_entry(&ses->iface_list, struct cifs_server_iface, iface_head); + min_speed = min_t(size_t, min_speed, last->speed); + } + + list_for_each_entry_safe(iface, niface, ifaces, iface_head) { rc = 0; /* do not mix rdma and non-rdma interfaces */ @@ -167,40 +173,32 @@ static int try_adding_channels(struct cifs_ses *ses) continue; /* skip ifaces that are unusable */ - if (!iface->is_active || (is_ses_using_iface(ses, iface) && !iface->rss_capable)) + if (!iface->is_active || !iface->rss_capable) continue; spin_lock(&ses->iface_lock); - if (!ses->iface_count) { - spin_unlock(&ses->iface_lock); - cifs_dbg(ONCE, "server %s does not advertise interfaces\n", - ses->server->hostname); - break; - } - /* check if we already allocated enough channels */ - iface_weight = iface->speed / iface_min_speed; - if (iface->weight_fulfilled >= iface_weight) { + weight = iface->speed / min_speed; + if (iface->weight_fulfilled >= weight) { spin_unlock(&ses->iface_lock); continue; } - - /* take ref before unlock */ - kref_get(&iface->refcount); - spin_unlock(&ses->iface_lock); + rc = cifs_ses_add_channel(ses, iface); - spin_lock(&ses->iface_lock); + spin_lock(&ses->iface_lock); if (!rc) { cifs_info("successfully opened new channel on iface:%pIS\n", &iface->sockaddr); + list_move(&iface->iface_head, &ses->iface_list); + ses->iface_count++; + iface->is_active = 1; iface->num_channels++; iface->weight_fulfilled++; left--; } else { cifs_dbg(VFS, "failed to open extra channel on iface:%pIS rc=%d\n", &iface->sockaddr, rc); - kref_put(&iface->refcount, release_iface); iface->weight_fulfilled++; if (rc != -EAGAIN) { spin_unlock(&ses->iface_lock); @@ -213,7 +211,7 @@ static int try_adding_channels(struct cifs_ses *ses) return rc ?: left; } -int cifs_try_adding_channels(struct cifs_ses *ses) +int cifs_try_adding_channels(struct cifs_ses *ses, struct list_head *ifaces) { int rc, retries = 0; @@ -226,7 +224,7 @@ try_again: } spin_unlock(&ses->chan_lock); - rc = try_adding_channels(ses); + rc = try_adding_channels(ses, ifaces); if (!rc) return 0; |