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 <[email protected]>
---
 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


Reply via email to