diff options
author | Oleg Nesterov <oleg@redhat.com> | 2010-03-15 05:10:03 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-04-02 14:12:01 -0400 |
commit | 897f0b3c3ff40b443c84e271bef19bd6ae885195 (patch) | |
tree | 6b969149bb59591a1c9485de405639db6c4208d6 /kernel/cpuset.c | |
parent | 25c2d55c00c6097e6792ebf21e31342f23b9b768 (diff) |
sched: Kill the broken and deadlockable cpuset_lock/cpuset_cpus_allowed_locked code
This patch just states the fact the cpusets/cpuhotplug interaction is
broken and removes the deadlockable code which only pretends to work.
- cpuset_lock() doesn't really work. It is needed for
cpuset_cpus_allowed_locked() but we can't take this lock in
try_to_wake_up()->select_fallback_rq() path.
- cpuset_lock() is deadlockable. Suppose that a task T bound to CPU takes
callback_mutex. If cpu_down(CPU) happens before T drops callback_mutex
stop_machine() preempts T, then migration_call(CPU_DEAD) tries to take
cpuset_lock() and hangs forever because CPU is already dead and thus
T can't be scheduled.
- cpuset_cpus_allowed_locked() is deadlockable too. It takes task_lock()
which is not irq-safe, but try_to_wake_up() can be called from irq.
Kill them, and change select_fallback_rq() to use cpu_possible_mask, like
we currently do without CONFIG_CPUSETS.
Also, with or without this patch, with or without CONFIG_CPUSETS, the
callers of select_fallback_rq() can race with each other or with
set_cpus_allowed() pathes.
The subsequent patches try to to fix these problems.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20100315091003.GA9123@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/cpuset.c')
-rw-r--r-- | kernel/cpuset.c | 27 |
1 files changed, 1 insertions, 26 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index d10946748ec2..9a747f56d58c 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -2182,19 +2182,10 @@ void __init cpuset_init_smp(void) | |||
2182 | void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask) | 2182 | void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask) |
2183 | { | 2183 | { |
2184 | mutex_lock(&callback_mutex); | 2184 | mutex_lock(&callback_mutex); |
2185 | cpuset_cpus_allowed_locked(tsk, pmask); | ||
2186 | mutex_unlock(&callback_mutex); | ||
2187 | } | ||
2188 | |||
2189 | /** | ||
2190 | * cpuset_cpus_allowed_locked - return cpus_allowed mask from a tasks cpuset. | ||
2191 | * Must be called with callback_mutex held. | ||
2192 | **/ | ||
2193 | void cpuset_cpus_allowed_locked(struct task_struct *tsk, struct cpumask *pmask) | ||
2194 | { | ||
2195 | task_lock(tsk); | 2185 | task_lock(tsk); |
2196 | guarantee_online_cpus(task_cs(tsk), pmask); | 2186 | guarantee_online_cpus(task_cs(tsk), pmask); |
2197 | task_unlock(tsk); | 2187 | task_unlock(tsk); |
2188 | mutex_unlock(&callback_mutex); | ||
2198 | } | 2189 | } |
2199 | 2190 | ||
2200 | void cpuset_init_current_mems_allowed(void) | 2191 | void cpuset_init_current_mems_allowed(void) |
@@ -2383,22 +2374,6 @@ int __cpuset_node_allowed_hardwall(int node, gfp_t gfp_mask) | |||
2383 | } | 2374 | } |
2384 | 2375 | ||
2385 | /** | 2376 | /** |
2386 | * cpuset_lock - lock out any changes to cpuset structures | ||
2387 | * | ||
2388 | * The out of memory (oom) code needs to mutex_lock cpusets | ||
2389 | * from being changed while it scans the tasklist looking for a | ||
2390 | * task in an overlapping cpuset. Expose callback_mutex via this | ||
2391 | * cpuset_lock() routine, so the oom code can lock it, before | ||
2392 | * locking the task list. The tasklist_lock is a spinlock, so | ||
2393 | * must be taken inside callback_mutex. | ||
2394 | */ | ||
2395 | |||
2396 | void cpuset_lock(void) | ||
2397 | { | ||
2398 | mutex_lock(&callback_mutex); | ||
2399 | } | ||
2400 | |||
2401 | /** | ||
2402 | * cpuset_unlock - release lock on cpuset changes | 2377 | * cpuset_unlock - release lock on cpuset changes |
2403 | * | 2378 | * |
2404 | * Undo the lock taken in a previous cpuset_lock() call. | 2379 | * Undo the lock taken in a previous cpuset_lock() call. |