mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-17 13:58:46 +00:00
Drivers: hv: vmbus: Use a round-robin algorithm for picking the outgoing channel
The current algorithm for picking an outgoing channel was not distributing the load well. Implement a simple round-robin scheme to ensure good distribution of the outgoing traffic. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Reviewed-by: Long Li <longli@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
96c1d0581d
commit
a13e8bbe85
@ -350,6 +350,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
newchannel->state = CHANNEL_OPEN_STATE;
|
newchannel->state = CHANNEL_OPEN_STATE;
|
||||||
|
channel->num_sc++;
|
||||||
if (channel->sc_creation_callback != NULL)
|
if (channel->sc_creation_callback != NULL)
|
||||||
/*
|
/*
|
||||||
* We need to invoke the sub-channel creation
|
* We need to invoke the sub-channel creation
|
||||||
@ -862,9 +863,8 @@ cleanup:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Retrieve the (sub) channel on which to send an outgoing request.
|
* Retrieve the (sub) channel on which to send an outgoing request.
|
||||||
* When a primary channel has multiple sub-channels, we choose a
|
* When a primary channel has multiple sub-channels, we try to
|
||||||
* channel whose VCPU binding is closest to the VCPU on which
|
* distribute the load equally amongst all available channels.
|
||||||
* this call is being made.
|
|
||||||
*/
|
*/
|
||||||
struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
|
struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
|
||||||
{
|
{
|
||||||
@ -872,11 +872,19 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
|
|||||||
int cur_cpu;
|
int cur_cpu;
|
||||||
struct vmbus_channel *cur_channel;
|
struct vmbus_channel *cur_channel;
|
||||||
struct vmbus_channel *outgoing_channel = primary;
|
struct vmbus_channel *outgoing_channel = primary;
|
||||||
int cpu_distance, new_cpu_distance;
|
int next_channel;
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
if (list_empty(&primary->sc_list))
|
if (list_empty(&primary->sc_list))
|
||||||
return outgoing_channel;
|
return outgoing_channel;
|
||||||
|
|
||||||
|
next_channel = primary->next_oc++;
|
||||||
|
|
||||||
|
if (next_channel > (primary->num_sc)) {
|
||||||
|
primary->next_oc = 0;
|
||||||
|
return outgoing_channel;
|
||||||
|
}
|
||||||
|
|
||||||
cur_cpu = hv_context.vp_index[get_cpu()];
|
cur_cpu = hv_context.vp_index[get_cpu()];
|
||||||
put_cpu();
|
put_cpu();
|
||||||
list_for_each_safe(cur, tmp, &primary->sc_list) {
|
list_for_each_safe(cur, tmp, &primary->sc_list) {
|
||||||
@ -887,18 +895,10 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
|
|||||||
if (cur_channel->target_vp == cur_cpu)
|
if (cur_channel->target_vp == cur_cpu)
|
||||||
return cur_channel;
|
return cur_channel;
|
||||||
|
|
||||||
cpu_distance = ((outgoing_channel->target_vp > cur_cpu) ?
|
if (i == next_channel)
|
||||||
(outgoing_channel->target_vp - cur_cpu) :
|
return cur_channel;
|
||||||
(cur_cpu - outgoing_channel->target_vp));
|
|
||||||
|
|
||||||
new_cpu_distance = ((cur_channel->target_vp > cur_cpu) ?
|
i++;
|
||||||
(cur_channel->target_vp - cur_cpu) :
|
|
||||||
(cur_cpu - cur_channel->target_vp));
|
|
||||||
|
|
||||||
if (cpu_distance < new_cpu_distance)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
outgoing_channel = cur_channel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return outgoing_channel;
|
return outgoing_channel;
|
||||||
|
@ -761,6 +761,9 @@ struct vmbus_channel {
|
|||||||
* link up channels based on their CPU affinity.
|
* link up channels based on their CPU affinity.
|
||||||
*/
|
*/
|
||||||
struct list_head percpu_list;
|
struct list_head percpu_list;
|
||||||
|
|
||||||
|
int num_sc;
|
||||||
|
int next_oc;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
|
static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user