[PATCH 15/23] Drivers: hv: Use RCU to protect access of HK_TYPE_MANAGED_IRQ cpumask

Waiman Long
2026-04-21T03:06:52Z

As HK_TYPE_MANAGED_IRQ cpumask is going to be changeable at run time,
use RCU to protect access to the cpumask. The memory allocation
alloc_cpumask_var() call is done before taking the rcu_read_lock()
as this call can be sleepable.

Signed-off-by: Waiman Long <longman@redhat.com>
---
drivers/hv/channel_mgmt.c | 15 +++++++++------
drivers/hv/vmbus_drv.c | 7 +++++--
2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 84eb0a6a0b54..44441dafed90 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -752,13 +752,16 @@ 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 *hk_mask = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ);
+ const struct cpumask *hk_mask;
u32 target_cpu;
int numa_node;
+ bool alloc_ok;

- if (!perf_chn ||
- !alloc_cpumask_var(&available_mask, GFP_KERNEL) ||
- cpumask_empty(hk_mask)) {
+ alloc_ok = alloc_cpumask_var(&available_mask, GFP_KERNEL);
+ guard(rcu)();
+ hk_mask = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ);
+
+ if (!perf_chn || !alloc_ok || cpumask_empty(hk_mask)) {
/*
* If the channel is not a performance critical
* channel, bind it to VMBUS_CONNECT_CPU.
@@ -770,7 +773,7 @@ static void init_vp_index(struct vmbus_channel *channel)
channel->target_cpu = VMBUS_CONNECT_CPU;
if (perf_chn)
hv_set_allocated_cpu(VMBUS_CONNECT_CPU);
- return;
+ goto out_free;
}

for (i = 1; i <= ncpu + 1; i++) {
@@ -808,7 +811,7 @@ static void init_vp_index(struct vmbus_channel *channel)
}

channel->target_cpu = target_cpu;
-
+out_free:
free_cpumask_var(available_mask);
}

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 3faa74e49a6b..60c7a5ac15c0 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1763,8 +1763,11 @@ int vmbus_channel_set_cpu(struct vmbus_channel *channel, u32 target_cpu)
if (target_cpu >= nr_cpumask_bits)
return -EINVAL;

- if (!cpumask_test_cpu(target_cpu, housekeeping_cpumask(HK_TYPE_MANAGED_IRQ)))
- return -EINVAL;
+ scoped_guard(rcu) {
+ if (!cpumask_test_cpu(target_cpu,
+ housekeeping_cpumask(HK_TYPE_MANAGED_IRQ)))
+ return -EINVAL;
+ }

if (!cpu_online(target_cpu))
return -EINVAL;
--
2.53.0