Signed-off-by: Daniel Lezcano <redacted>
---
include/linux/smpboot.h | 4 ++++
kernel/smpboot.c | 17 +++++++++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/include/linux/smpboot.h b/include/linux/smpboot.h
index 9d1bc65d226c..98c072eeaf24 100644
--- a/include/linux/smpboot.h
+++ b/include/linux/smpboot.h
#include <linux/types.h>
struct task_struct;
+struct cpumask;
/* Cookie handed to the thread_fn*/
struct smpboot_thread_data;
@@ -27,6 +28,8 @@ struct smpboot_thread_data;
* unparked (cpu online)
* @selfparking: Thread is not parked by the park function.
* @thread_comm: The base name of the thread
+ * @cpumask: Optional mask of CPUs on which to create threads. Must remain
+ * valid and unchanged until the descriptor is unregistered.
*/
struct smp_hotplug_thread {
struct task_struct * __percpu *store;@@ -40,6 +43,7 @@ struct smp_hotplug_thread { void (*unpark)(unsigned int cpu);
bool selfparking;
const char *thread_comm;
+ const struct cpumask *cpumask;
};
int smpboot_register_percpu_thread(struct smp_hotplug_thread
*plug_thread);
diff --git a/kernel/smpboot.c b/kernel/smpboot.c
index 4503b60ce9bd..07857523a465 100644
--- a/kernel/smpboot.c
+++ b/kernel/smpboot.c
@@ -168,6 +168,9 @@ __smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu)
struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu);
struct smpboot_thread_data *td;
+ if (ht->cpumask && !cpumask_test_cpu(cpu, ht->cpumask))
+ return 0;
+
if (tsk)
return 0;
@@ -225,6 +228,9 @@ static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cp
{
struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu);
+ if (ht->cpumask && !cpumask_test_cpu(cpu, ht->cpumask))
+ return;
+
if (!ht->selfparking)
kthread_unpark(tsk);
}@@ -244,6 +250,9 @@ static void smpboot_park_thread(struct smp_hotplug_thread *ht, unsigned int cpu)
{
struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu);
+ if (ht->cpumask && !cpumask_test_cpu(cpu, ht->cpumask))
+ return;
+
if (tsk && !ht->selfparking)
kthread_park(tsk);
}@@ -267,6 +276,9 @@ static void smpboot_destroy_threads(struct smp_hotplug_thread *ht)
for_each_possible_cpu(cpu) {
struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu);
+ if (ht->cpumask && !cpumask_test_cpu(cpu, ht->cpumask))
+ continue;
+
if (tsk) {
kthread_stop_put(tsk);
*per_cpu_ptr(ht->store, cpu) = NULL;@@ -279,7 +291,8 @@ static void smpboot_destroy_threads(struct smp_hotplug_thread *ht)
* to hotplug
* @plug_thread: Hotplug thread descriptor
*
- * Creates and starts the threads on all online cpus.
+ * Creates and starts the threads on online CPUs selected by the descriptor's
+ * cpumask, or all online CPUs if no mask is specified.
*/
int smpboot_register_percpu_thread(struct smp_hotplug_thread
*plug_thread)
{@@ -308,7 +321,7 @@ EXPORT_SYMBOL_GPL(smpboot_register_percpu_thread);
* smpboot_unregister_percpu_thread - Unregister a per_cpu thread related to hotplug
* @plug_thread: Hotplug thread descriptor
*
- * Stops all threads on all possible cpus.
+ * Stops all threads associated with the descriptor, including offline CPUs.
*/
void smpboot_unregister_percpu_thread(struct smp_hotplug_thread
*plug_thread)
{