summaryrefslogtreecommitdiff
path: root/fs/smb/client/sess.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/smb/client/sess.c')
-rw-r--r--fs/smb/client/sess.c48
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;