Commit 663c2846 authored by Henrique Carvalho's avatar Henrique Carvalho Committed by Steve French
Browse files

smb: client: fix cifs_pick_channel when channels are equally loaded



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: default avatarHenrique Carvalho <henrique.carvalho@suse.com>
Acked-by: default avatarPaulo Alcantara (Red Hat) <pc@manguebit.org>
Acked-by: default avatarMeetakshi Setiya <msetiya@microsoft.com>
Reviewed-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 6de23f81
Loading
Loading
Loading
Loading
+10 −11
Original line number Diff line number Diff line
@@ -807,16 +807,21 @@ cifs_cancelled_callback(struct TCP_Server_Info *server, 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;

@@ -846,14 +851,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);