There are no more (known) nested calls to get_online_cpus() so it'spossible to remove the nested call magic and convert the mutex to apercpu-rwsem, which speeds up get/put_online_cpus() significantly for theuncontended case.

The contended case (write locked for hotplug operations) is slow anyway, sothe slightly more expensive down_write of the percpu rwsem does not matter.

-/* If set, cpu_up and cpu_down will return -EBUSY and do nothing.+/*+ * If set, cpu_up and cpu_down will return -EBUSY and do nothing. * Should always be manipulated under cpu_add_remove_lock */ static int cpu_hotplug_disabled;

-/*- * This ensures that the hotplug operation can begin only when the- * refcount goes to zero.- *- * Note that during a cpu-hotplug operation, the new readers, if any,- * will be blocked by the cpu_hotplug.lock- *- * Since cpu_hotplug_begin() is always called after invoking- * cpu_maps_update_begin(), we can be sure that only one writer is active.- *- * Note that theoretically, there is a possibility of a livelock:- * - Refcount goes to zero, last reader wakes up the sleeping- * writer.- * - Last reader unlocks the cpu_hotplug.lock.- * - A new reader arrives at this moment, bumps up the refcount.- * - The writer acquires the cpu_hotplug.lock finds the refcount- * non zero and goes to sleep again.- *- * However, this is very difficult to achieve in practice since- * get_online_cpus() not an api which is called all that often.- *- */ void cpu_hotplug_begin(void) {- DEFINE_WAIT(wait);-- cpu_hotplug.active_writer = current;- cpuhp_lock_acquire();-- for (;;) {- mutex_lock(&cpu_hotplug.lock);- prepare_to_wait(&cpu_hotplug.wq, &wait, TASK_UNINTERRUPTIBLE);- if (likely(!atomic_read(&cpu_hotplug.refcount)))- break;- mutex_unlock(&cpu_hotplug.lock);- schedule();- }- finish_wait(&cpu_hotplug.wq, &wait);+ percpu_down_write(&cpu_hotplug_lock); }