summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorHenrique Carvalho2026-02-21 01:59:44 -0300
committerSasha Levin2026-03-12 07:09:42 -0400
commit0786f9422cbf727011544a127a22131a554b466c (patch)
tree4eb0126c7e2a75194f52401145f965bd9544d2e4 /fs
parent5a34959a2ab1883981e7bf7ad64898f4e596a72a (diff)
smb: client: fix cifs_pick_channel when channels are equally loaded
commit 663c28469d3274d6456f206a6671c91493d85ff1 upstream. cifs_pick_channel uses (start % chan_count) when channels are equally loaded, but that can return a channel that failed the eligibility checks. Drop the fallback and return the scan-selected channel instead. If none is eligible, keep the existing behavior of using the primary channel. Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com> Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Acked-by: Meetakshi Setiya <msetiya@microsoft.com> Reviewed-by: Shyam Prasad N <sprasad@microsoft.com> Cc: stable@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/smb/client/transport.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
index 915cedde5d66..2d7140767dc4 100644
--- a/fs/smb/client/transport.c
+++ b/fs/smb/client/transport.c
@@ -806,16 +806,21 @@ cifs_cancelled_callback(struct mid_q_entry *mid)
}
/*
- * Return a channel (master if none) of @ses that can be used to send
- * regular requests.
+ * cifs_pick_channel - pick an eligible channel for network operations
*
- * If we are currently binding a new channel (negprot/sess.setup),
- * return the new incomplete channel.
+ * @ses: session reference
+ *
+ * Select an eligible channel (not terminating and not marked as needing
+ * reconnect), preferring the least loaded one. If no eligible channel is
+ * found, fall back to the primary channel (index 0).
+ *
+ * Return: TCP_Server_Info pointer for the chosen channel, or NULL if @ses is
+ * NULL.
*/
struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
{
uint index = 0;
- unsigned int min_in_flight = UINT_MAX, max_in_flight = 0;
+ unsigned int min_in_flight = UINT_MAX;
struct TCP_Server_Info *server = NULL;
int i, start, cur;
@@ -845,14 +850,8 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
min_in_flight = server->in_flight;
index = cur;
}
- if (server->in_flight > max_in_flight)
- max_in_flight = server->in_flight;
}
- /* if all channels are equally loaded, fall back to round-robin */
- if (min_in_flight == max_in_flight)
- index = (uint)start % ses->chan_count;
-
server = ses->chans[index].server;
spin_unlock(&ses->chan_lock);