From 28b96fd89f7d746fc2b6c68682527214a55463f9 Mon Sep 17 00:00:00 2001 From: Shyam Prasad N Date: Mon, 19 Dec 2022 05:40:44 +0000 Subject: [PATCH] cifs: use the least loaded channel for sending requests Till now, we've used a simple round robin approach to distribute the requests between the channels. This does not work well if the channels consume the requests at different speeds, even if the advertised speeds are the same. This change will allow the client to pick the channel with least number of requests currently in-flight. This will disregard the link speed, and select a channel based on the current load of the channels. To allow developers to still switch to round-robin approach when needed, we'll now have a new kernel config option CONFIG_CIFS_MCHAN_LEAST_LOADED. This option will default to y. By disabling this option, one can run the SMB client with round-robin strategy to pick channels. Signed-off-by: Shyam Prasad N --- fs/cifs/Kconfig | 15 +++++++++++++++ fs/cifs/transport.c | 19 ++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 3b7e3b9e4fd2e..957cbddd385a9 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -67,6 +67,21 @@ config CIFS_STATS2 If unsure, say Y. +config CIFS_MCHAN_LEAST_LOADED + bool "Select the least loaded channel for send" + depends on CIFS + default y + help + Enabling this option will ensure that the channel with the least number of + in-flight requests will be used to send the requests. This will take effect + only when multichannel is in use. For non-multichannel mounts, this is + redundant. + + If this option is disabled, the client will fallback to using a round-robin + approach to distributing the requests among channels. + + If unsure, say Y. + config CIFS_ALLOW_INSECURE_LEGACY bool "Support legacy servers which use less secure dialects" depends on CIFS diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 575fa8f583422..53220995853a4 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -1034,15 +1034,28 @@ cifs_cancelled_callback(struct mid_q_entry *mid) struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses) { uint index = 0; +#ifdef CONFIG_CIFS_MCHAN_LEAST_LOADED + unsigned int min_in_flight = -1; + struct TCP_Server_Info *server = NULL; + int i; +#endif if (!ses) return NULL; - /* round robin */ - index = (uint)atomic_inc_return(&ses->chan_seq); - spin_lock(&ses->chan_lock); +#ifdef CONFIG_CIFS_MCHAN_LEAST_LOADED + for (i = 0; i < ses->chan_count; i++) { + server = ses->chans[i].server; + if (server && server->in_flight < min_in_flight) { + min_in_flight = server->in_flight; + index = i; + } + } +#else + index = (uint)atomic_inc_return(&ses->chan_seq); index %= ses->chan_count; +#endif spin_unlock(&ses->chan_lock); return ses->chans[index].server;