Skip to content

Commit 463378c

Browse files
Sebastian Andrzej Siewiorl1k
authored andcommitted
kernel/stop_machine: partly revert "stop_machine: Use raw spinlocks"
With completion using swait and so rawlocks we don't need this anymore. Further, bisect thinks this patch is responsible for: |BUG: unable to handle kernel NULL pointer dereference at (null) |IP: [<ffffffff81082123>] sched_cpu_active+0x53/0x70 |PGD 0 |Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC |Dumping ftrace buffer: | (ftrace buffer empty) |Modules linked in: |CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.4.1+ torvalds#330 |Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS Debian-1.8.2-1 04/01/2014 |task: ffff88013ae64b00 ti: ffff88013ae74000 task.ti: ffff88013ae74000 |RIP: 0010:[<ffffffff81082123>] [<ffffffff81082123>] sched_cpu_active+0x53/0x70 |RSP: 0000:ffff88013ae77eb8 EFLAGS: 00010082 |RAX: 0000000000000001 RBX: ffffffff81c2cf20 RCX: 0000001050fb52fb |RDX: 0000001050fb52fb RSI: 000000105117ca1e RDI: 00000000001c7723 |RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000001 |R10: 0000000000000000 R11: 0000000000000001 R12: 00000000ffffffff |R13: ffffffff81c2cee0 R14: 0000000000000000 R15: 0000000000000001 |FS: 0000000000000000(0000) GS:ffff88013b200000(0000) knlGS:0000000000000000 |CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b |CR2: 0000000000000000 CR3: 0000000001c09000 CR4: 00000000000006e0 |Stack: | ffffffff810c446d ffff88013ae77f00 ffffffff8107d8dd 000000000000000a | 0000000000000001 0000000000000000 0000000000000000 0000000000000000 | 0000000000000000 ffff88013ae77f10 ffffffff8107d90e ffff88013ae77f20 |Call Trace: | [<ffffffff810c446d>] ? debug_lockdep_rcu_enabled+0x1d/0x20 | [<ffffffff8107d8dd>] ? notifier_call_chain+0x5d/0x80 | [<ffffffff8107d90e>] ? __raw_notifier_call_chain+0xe/0x10 | [<ffffffff810598a3>] ? cpu_notify+0x23/0x40 | [<ffffffff8105a7b8>] ? notify_cpu_starting+0x28/0x30 during hotplug. The rawlocks need to remain however. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
1 parent e489f49 commit 463378c

File tree

1 file changed

+8
-32
lines changed

1 file changed

+8
-32
lines changed

kernel/stop_machine.c

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ struct cpu_stop_done {
3030
atomic_t nr_todo; /* nr left to execute */
3131
bool executed; /* actually executed? */
3232
int ret; /* collected return value */
33-
struct task_struct *waiter; /* woken when nr_todo reaches 0 */
33+
struct completion completion; /* fired if nr_todo reaches 0 */
3434
};
3535

3636
/* the actual stopper, one per every possible cpu, enabled on online cpus */
@@ -59,7 +59,7 @@ static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo)
5959
{
6060
memset(done, 0, sizeof(*done));
6161
atomic_set(&done->nr_todo, nr_todo);
62-
done->waiter = current;
62+
init_completion(&done->completion);
6363
}
6464

6565
/* signal completion unless @done is NULL */
@@ -68,10 +68,8 @@ static void cpu_stop_signal_done(struct cpu_stop_done *done, bool executed)
6868
if (done) {
6969
if (executed)
7070
done->executed = true;
71-
if (atomic_dec_and_test(&done->nr_todo)) {
72-
wake_up_process(done->waiter);
73-
done->waiter = NULL;
74-
}
71+
if (atomic_dec_and_test(&done->nr_todo))
72+
complete(&done->completion);
7573
}
7674
}
7775

@@ -96,22 +94,6 @@ static void cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
9694
raw_spin_unlock_irqrestore(&stopper->lock, flags);
9795
}
9896

99-
static void wait_for_stop_done(struct cpu_stop_done *done)
100-
{
101-
set_current_state(TASK_UNINTERRUPTIBLE);
102-
while (atomic_read(&done->nr_todo)) {
103-
schedule();
104-
set_current_state(TASK_UNINTERRUPTIBLE);
105-
}
106-
/*
107-
* We need to wait until cpu_stop_signal_done() has cleared
108-
* done->waiter.
109-
*/
110-
while (done->waiter)
111-
cpu_relax();
112-
set_current_state(TASK_RUNNING);
113-
}
114-
11597
/**
11698
* stop_one_cpu - stop a cpu
11799
* @cpu: cpu to stop
@@ -143,7 +125,7 @@ int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg)
143125

144126
cpu_stop_init_done(&done, 1);
145127
cpu_stop_queue_work(cpu, &work);
146-
wait_for_stop_done(&done);
128+
wait_for_completion(&done.completion);
147129
return done.executed ? done.ret : -ENOENT;
148130
}
149131

@@ -302,7 +284,7 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
302284

303285
preempt_enable_nort();
304286

305-
wait_for_stop_done(&done);
287+
wait_for_completion(&done.completion);
306288

307289
return done.executed ? done.ret : -ENOENT;
308290
}
@@ -364,7 +346,7 @@ static int __stop_cpus(const struct cpumask *cpumask,
364346

365347
cpu_stop_init_done(&done, cpumask_weight(cpumask));
366348
queue_stop_cpus_work(cpumask, fn, arg, &done, false);
367-
wait_for_stop_done(&done);
349+
wait_for_completion(&done.completion);
368350
return done.executed ? done.ret : -ENOENT;
369351
}
370352

@@ -495,13 +477,7 @@ static void cpu_stopper_thread(unsigned int cpu)
495477
kallsyms_lookup((unsigned long)fn, NULL, NULL, NULL,
496478
ksym_buf), arg);
497479

498-
/*
499-
* Make sure that the wakeup and setting done->waiter
500-
* to NULL is atomic.
501-
*/
502-
local_irq_disable();
503480
cpu_stop_signal_done(done, true);
504-
local_irq_enable();
505481
goto repeat;
506482
}
507483
}
@@ -663,7 +639,7 @@ int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
663639
ret = multi_cpu_stop(&msdata);
664640

665641
/* Busy wait for completion. */
666-
while (atomic_read(&done.nr_todo))
642+
while (!completion_done(&done.completion))
667643
cpu_relax();
668644

669645
mutex_unlock(&stop_cpus_mutex);

0 commit comments

Comments
 (0)