]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
cifs: reset iface weights when we cannot find a candidate
authorShyam Prasad N <sprasad@microsoft.com>
Thu, 17 Jul 2025 12:06:13 +0000 (17:36 +0530)
committerSteve French <stfrench@microsoft.com>
Sun, 27 Jul 2025 21:59:58 +0000 (16:59 -0500)
We now do a weighted selection of server interfaces when allocating
new channels. The weights are decided based on the speed advertised.
The fulfilled weight for an interface is a counter that is used to
track the interface selection. It should be reset back to zero once
all interfaces fulfilling their weight.

In cifs_chan_update_iface, this reset logic was missing. As a result
when the server interface list changes, the client may not be able
to find a new candidate for other channels after all interfaces have
been fulfilled.

Fixes: a6d8fb54a515 ("cifs: distribute channels across interfaces based on speed")
Cc: <stable@vger.kernel.org>
Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/sess.c

index 330bc3d25badd80d08cf52fb21a22c954fc51df7..0a8c2fcc9dedf1d75b247b7c738a682b371ddb70 100644 (file)
@@ -332,6 +332,7 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
        struct cifs_server_iface *old_iface = NULL;
        struct cifs_server_iface *last_iface = NULL;
        struct sockaddr_storage ss;
+       int retry = 0;
 
        spin_lock(&ses->chan_lock);
        chan_index = cifs_ses_get_chan_index(ses, server);
@@ -360,6 +361,7 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
                return;
        }
 
+try_again:
        last_iface = list_last_entry(&ses->iface_list, struct cifs_server_iface,
                                     iface_head);
        iface_min_speed = last_iface->speed;
@@ -397,6 +399,13 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
        }
 
        if (list_entry_is_head(iface, &ses->iface_list, iface_head)) {
+               list_for_each_entry(iface, &ses->iface_list, iface_head)
+                       iface->weight_fulfilled = 0;
+
+               /* see if it can be satisfied in second attempt */
+               if (!retry++)
+                       goto try_again;
+
                iface = NULL;
                cifs_dbg(FYI, "unable to find a suitable iface\n");
        }