From: Waiman Long <[email protected]> Sent: Sunday, August 30, 2026 4:41 PM > > There is a retry loop in init_vp_index() where the CPUs from a certain > node are stripped out if they have already been in the allocated cpumask > or not in HK_TYPE_MANAGED_IRQ housekeeping cpumask. If there is no > CPU left, the allocated cpumask is ignored and the process is retried > again. However, if the HK_TYPE_MANAGED_IRQ housekeeping cpumask turns > out not to contain any CPU in that particular node, that will become an > infinite retry loop. This particular problem was reported by sashiko > [1]. This should rarely happen, but we still need to guard against this. > > Fix this infinite loop problem by also skipping NUMA node that has no > housekeeping CPU in the inner while loop of init_vp_index(). Also update > the early abort check to check for the absence of online housekeeping > CPUs instead of just the emptiness of the cpumask. As the outer for > loop will only be reached if the housekeeping cpumask has at least one > online CPU, a NUMA node with housekeeping CPUs will eventually be found. > > Link: > https://sashiko.dev/#/message/20260422030903.E1BFCC2BCB0%40smtp.kernel.org [1] > Fixes: 6640b5df1a38 ("Drivers: hv: vmbus: Don't assign VMbus channel > interrupts to isolated CPUs") > Signed-off-by: Waiman Long <[email protected]> > --- > drivers/hv/channel_mgmt.c | 12 +++++++++--- > 1 file changed, 9 insertions(+), 3 deletions(-) > > diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c > index 89d214dda360..28b8ff9aea6e 100644 > --- a/drivers/hv/channel_mgmt.c > +++ b/drivers/hv/channel_mgmt.c > @@ -752,13 +752,14 @@ static void init_vp_index(struct vmbus_channel *channel) > u32 i, ncpu = num_online_cpus(); > cpumask_var_t available_mask; > struct cpumask *allocated_mask; > + const struct cpumask *node_mask; > const struct cpumask *hk_mask = > housekeeping_cpumask(HK_TYPE_MANAGED_IRQ); > u32 target_cpu; > int numa_node; > > if (!perf_chn || > !alloc_cpumask_var(&available_mask, GFP_KERNEL) || > - cpumask_empty(hk_mask)) { > + !cpumask_intersects(hk_mask, cpu_online_mask)) { > /* > * If the channel is not a performance critical > * channel, bind it to VMBUS_CONNECT_CPU. > @@ -780,14 +781,19 @@ static void init_vp_index(struct vmbus_channel *channel) > next_numa_node_id = 0; > continue; > } > - if (cpumask_empty(cpumask_of_node(numa_node))) > + /* > + * Try next NUMA node if current NUMA node has no CPU > + * or doesn't contain any housekeeping CPU. > + */ > + node_mask = cpumask_of_node(numa_node); > + if (!cpumask_intersects(node_mask, hk_mask)) > continue; > break; > } > allocated_mask = &hv_context.hv_numa_map[numa_node]; > > retry: > - cpumask_xor(available_mask, allocated_mask, > cpumask_of_node(numa_node)); > + cpumask_xor(available_mask, allocated_mask, node_mask); > cpumask_and(available_mask, available_mask, hk_mask); > > if (cpumask_empty(available_mask)) { > -- > 2.55.0 >
Looks good. Reviewed-by: Michael Kelley <[email protected]>

