linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups
@ 2015-11-15 19:32 Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 1/8] stop_machine: cpu_stopper_thread() must check done != NULL Oleg Nesterov
                   ` (8 more replies)
  0 siblings, 9 replies; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-15 19:32 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Milos Vyletel, Prarit Bhargava, Tejun Heo, Thomas Gleixner, linux-kernel

Hello,

I tried to backport the recent stop_machine fixes and recalled that
I forgot to make the fix and cleanups I promised during the previous
discussion.

Please review.

I am also going to rediff/resend my old patch which removes lglock
from stop_machine.c, but it probably needs more discussion so I'll
send it separately.

Oleg.

 include/linux/stop_machine.h |    2 +-
 kernel/stop_machine.c        |   84 ++++++++++++++++++++---------------------
 2 files changed, 42 insertions(+), 44 deletions(-)


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/8] stop_machine: cpu_stopper_thread() must check done != NULL
  2015-11-15 19:32 [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Oleg Nesterov
@ 2015-11-15 19:33 ` Oleg Nesterov
  2015-11-16 18:52   ` Tejun Heo
  2015-11-23 16:21   ` [tip:sched/core] stop_machine: Fix possible cpu_stopper_thread() crash tip-bot for Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 2/8] stop_machine: don't disable preemption in stop_two_cpus() Oleg Nesterov
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-15 19:33 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Milos Vyletel, Prarit Bhargava, Tejun Heo, Thomas Gleixner, linux-kernel

stop_one_cpu_nowait(fn) will crash the kernel if the callback returns
nonzero, work->done == NULL in this case.

This needs more cleanups, cpu_stop_signal_done() is called right after
we check done != NULL and it does the same check.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/stop_machine.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 867bc20..1a66a95 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -454,7 +454,7 @@ repeat:
 		preempt_disable();
 
 		ret = fn(arg);
-		if (ret)
+		if (ret && done)
 			done->ret = ret;
 
 		/* restore preemption and check it's still balanced */
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/8] stop_machine: don't disable preemption in stop_two_cpus()
  2015-11-15 19:32 [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 1/8] stop_machine: cpu_stopper_thread() must check done != NULL Oleg Nesterov
@ 2015-11-15 19:33 ` Oleg Nesterov
  2015-11-23 16:21   ` [tip:sched/core] stop_machine: Don' t " tip-bot for Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 3/8] stop_machine: make cpu_stop_queue_work() and stop_one_cpu_nowait() return bool Oleg Nesterov
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-15 19:33 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Milos Vyletel, Prarit Bhargava, Tejun Heo, Thomas Gleixner, linux-kernel

Now that stop_two_cpus() path does not check cpu_active() we can remove
preempt_disable(), it was only needed to ensure that stop_machine() can
not be called after we observe cpu_active() == T and before we queue the
new work.

Also, turn the pointless and confusing ->executed check into WARN_ON().
We know that both works must be executed, otherwise we have a bug. And
in fact I think that done->executed should die, see the next changes.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/stop_machine.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 1a66a95..17f01a9 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -258,7 +258,6 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
 	struct cpu_stop_work work1, work2;
 	struct multi_stop_data msdata;
 
-	preempt_disable();
 	msdata = (struct multi_stop_data){
 		.fn = fn,
 		.data = arg,
@@ -277,16 +276,12 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
 
 	if (cpu1 > cpu2)
 		swap(cpu1, cpu2);
-	if (cpu_stop_queue_two_works(cpu1, &work1, cpu2, &work2)) {
-		preempt_enable();
+	if (cpu_stop_queue_two_works(cpu1, &work1, cpu2, &work2))
 		return -ENOENT;
-	}
-
-	preempt_enable();
 
 	wait_for_completion(&done.completion);
-
-	return done.executed ? done.ret : -ENOENT;
+	WARN_ON(!done.executed);
+	return done.ret;
 }
 
 /**
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 3/8] stop_machine: make cpu_stop_queue_work() and stop_one_cpu_nowait() return bool
  2015-11-15 19:32 [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 1/8] stop_machine: cpu_stopper_thread() must check done != NULL Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 2/8] stop_machine: don't disable preemption in stop_two_cpus() Oleg Nesterov
@ 2015-11-15 19:33 ` Oleg Nesterov
  2015-11-17 17:05   ` [PATCH v2 " Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 4/8] stop_machine: change stop_one_cpu() to rely on cpu_stop_queue_work() Oleg Nesterov
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-15 19:33 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Milos Vyletel, Prarit Bhargava, Tejun Heo, Thomas Gleixner, linux-kernel

Change cpu_stop_queue_work() to return true if the work was queued and
change stop_one_cpu_nowait() to return the result of cpu_stop_queue_work().
This makes it more useful, for example now you can alloc cpu_stop_work for
stop_one_cpu_nowait() and free it in the callback or if stop_one_cpu_nowait()
fails, currently this is impossible because you can't know if @fn will be
called or not.

Also, this allows to kill cpu_stop_done->executed, see the next changes.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 include/linux/stop_machine.h |    2 +-
 kernel/stop_machine.c        |   16 ++++++++++++----
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 0adedca..40b239a 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -29,7 +29,7 @@ struct cpu_stop_work {
 
 int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
 int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *arg);
-void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
+bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 			 struct cpu_stop_work *work_buf);
 int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
 int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 17f01a9..0ec1f16 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -81,17 +81,21 @@ static void __cpu_stop_queue_work(struct cpu_stopper *stopper,
 }
 
 /* queue @work to @stopper.  if offline, @work is completed immediately */
-static void cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
+static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
 {
 	struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
 	unsigned long flags;
+	bool enabled;
 
 	spin_lock_irqsave(&stopper->lock, flags);
-	if (stopper->enabled)
+	enabled = stopper->enabled;
+	if (enabled)
 		__cpu_stop_queue_work(stopper, work);
 	else
 		cpu_stop_signal_done(work->done, false);
 	spin_unlock_irqrestore(&stopper->lock, flags);
+
+	return enabled;
 }
 
 /**
@@ -297,12 +301,16 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
  *
  * CONTEXT:
  * Don't care.
+ *
+ * RETURNS:
+ * true if cpu_stop_work was queued successfully and @fn will be called,
+ * false otherwise.
  */
-void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
+bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 			struct cpu_stop_work *work_buf)
 {
 	*work_buf = (struct cpu_stop_work){ .fn = fn, .arg = arg, };
-	cpu_stop_queue_work(cpu, work_buf);
+	return cpu_stop_queue_work(cpu, work_buf);
 }
 
 /* static data for stop_cpus */
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 4/8] stop_machine: change stop_one_cpu() to rely on cpu_stop_queue_work()
  2015-11-15 19:32 [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Oleg Nesterov
                   ` (2 preceding siblings ...)
  2015-11-15 19:33 ` [PATCH 3/8] stop_machine: make cpu_stop_queue_work() and stop_one_cpu_nowait() return bool Oleg Nesterov
@ 2015-11-15 19:33 ` Oleg Nesterov
  2015-11-23 16:22   ` [tip:sched/core] stop_machine: Change " tip-bot for Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 5/8] stop_machine: change __stop_cpus() " Oleg Nesterov
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-15 19:33 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Milos Vyletel, Prarit Bhargava, Tejun Heo, Thomas Gleixner, linux-kernel

Change stop_one_cpu() to return -ENOENT if cpu_stop_queue_work() fails.
Otherwise we know that ->executed must be true after wait_for_completion()
so we can just return done.ret.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/stop_machine.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 0ec1f16..68b73c4 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -128,9 +128,11 @@ int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg)
 	struct cpu_stop_work work = { .fn = fn, .arg = arg, .done = &done };
 
 	cpu_stop_init_done(&done, 1);
-	cpu_stop_queue_work(cpu, &work);
+	if (!cpu_stop_queue_work(cpu, &work))
+		return -ENOENT;
 	wait_for_completion(&done.completion);
-	return done.executed ? done.ret : -ENOENT;
+	WARN_ON(!done.executed);
+	return done.ret;
 }
 
 /* This controls the threads on each CPU. */
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 5/8] stop_machine: change __stop_cpus() to rely on cpu_stop_queue_work()
  2015-11-15 19:32 [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Oleg Nesterov
                   ` (3 preceding siblings ...)
  2015-11-15 19:33 ` [PATCH 4/8] stop_machine: change stop_one_cpu() to rely on cpu_stop_queue_work() Oleg Nesterov
@ 2015-11-15 19:33 ` Oleg Nesterov
  2015-11-23 16:22   ` [tip:sched/core] stop_machine: Change " tip-bot for Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 6/8] stop_machine: kill cpu_stop_done->executed Oleg Nesterov
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-15 19:33 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Milos Vyletel, Prarit Bhargava, Tejun Heo, Thomas Gleixner, linux-kernel

Change queue_stop_cpus_work() to return true if it queues at least one
work, this means that the caller should wait.

__stop_cpus() can check the value returned by queue_stop_cpus_work() and
avoid done.executed, just like stop_one_cpu() does.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/stop_machine.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 68b73c4..ed2019a 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -318,12 +318,13 @@ bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 /* static data for stop_cpus */
 static DEFINE_MUTEX(stop_cpus_mutex);
 
-static void queue_stop_cpus_work(const struct cpumask *cpumask,
+static bool queue_stop_cpus_work(const struct cpumask *cpumask,
 				 cpu_stop_fn_t fn, void *arg,
 				 struct cpu_stop_done *done)
 {
 	struct cpu_stop_work *work;
 	unsigned int cpu;
+	bool queued = false;
 
 	/*
 	 * Disable preemption while queueing to avoid getting
@@ -336,9 +337,12 @@ static void queue_stop_cpus_work(const struct cpumask *cpumask,
 		work->fn = fn;
 		work->arg = arg;
 		work->done = done;
-		cpu_stop_queue_work(cpu, work);
+		if (cpu_stop_queue_work(cpu, work))
+			queued = true;
 	}
 	lg_global_unlock(&stop_cpus_lock);
+
+	return queued;
 }
 
 static int __stop_cpus(const struct cpumask *cpumask,
@@ -347,9 +351,11 @@ static int __stop_cpus(const struct cpumask *cpumask,
 	struct cpu_stop_done done;
 
 	cpu_stop_init_done(&done, cpumask_weight(cpumask));
-	queue_stop_cpus_work(cpumask, fn, arg, &done);
+	if (!queue_stop_cpus_work(cpumask, fn, arg, &done))
+		return -ENOENT;
 	wait_for_completion(&done.completion);
-	return done.executed ? done.ret : -ENOENT;
+	WARN_ON(!done.executed);
+	return done.ret;
 }
 
 /**
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 6/8] stop_machine: kill cpu_stop_done->executed
  2015-11-15 19:32 [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Oleg Nesterov
                   ` (4 preceding siblings ...)
  2015-11-15 19:33 ` [PATCH 5/8] stop_machine: change __stop_cpus() " Oleg Nesterov
@ 2015-11-15 19:33 ` Oleg Nesterov
  2015-11-23 16:23   ` [tip:sched/core] stop_machine: Kill cpu_stop_done->executed tip-bot for Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 7/8] stop_machine: shift the done != NULL check from cpu_stop_signal_done() to callers Oleg Nesterov
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-15 19:33 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Milos Vyletel, Prarit Bhargava, Tejun Heo, Thomas Gleixner, linux-kernel

Now that cpu_stop_done->executed becomes write-only (ignoring WARN_ON()
checks) we can remove it.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/stop_machine.c |   12 +++---------
 1 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index ed2019a..09eb83f 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -28,7 +28,6 @@
  */
 struct cpu_stop_done {
 	atomic_t		nr_todo;	/* nr left to execute */
-	bool			executed;	/* actually executed? */
 	int			ret;		/* collected return value */
 	struct completion	completion;	/* fired if nr_todo reaches 0 */
 };
@@ -63,11 +62,9 @@ static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo)
 }
 
 /* signal completion unless @done is NULL */
-static void cpu_stop_signal_done(struct cpu_stop_done *done, bool executed)
+static void cpu_stop_signal_done(struct cpu_stop_done *done)
 {
 	if (done) {
-		if (executed)
-			done->executed = true;
 		if (atomic_dec_and_test(&done->nr_todo))
 			complete(&done->completion);
 	}
@@ -92,7 +89,7 @@ static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
 	if (enabled)
 		__cpu_stop_queue_work(stopper, work);
 	else
-		cpu_stop_signal_done(work->done, false);
+		cpu_stop_signal_done(work->done);
 	spin_unlock_irqrestore(&stopper->lock, flags);
 
 	return enabled;
@@ -131,7 +128,6 @@ int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg)
 	if (!cpu_stop_queue_work(cpu, &work))
 		return -ENOENT;
 	wait_for_completion(&done.completion);
-	WARN_ON(!done.executed);
 	return done.ret;
 }
 
@@ -286,7 +282,6 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
 		return -ENOENT;
 
 	wait_for_completion(&done.completion);
-	WARN_ON(!done.executed);
 	return done.ret;
 }
 
@@ -354,7 +349,6 @@ static int __stop_cpus(const struct cpumask *cpumask,
 	if (!queue_stop_cpus_work(cpumask, fn, arg, &done))
 		return -ENOENT;
 	wait_for_completion(&done.completion);
-	WARN_ON(!done.executed);
 	return done.ret;
 }
 
@@ -467,6 +461,7 @@ repeat:
 		ret = fn(arg);
 		if (ret && done)
 			done->ret = ret;
+		cpu_stop_signal_done(done);
 
 		/* restore preemption and check it's still balanced */
 		preempt_enable();
@@ -475,7 +470,6 @@ repeat:
 			  kallsyms_lookup((unsigned long)fn, NULL, NULL, NULL,
 					  ksym_buf), arg);
 
-		cpu_stop_signal_done(done, true);
 		goto repeat;
 	}
 }
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 7/8] stop_machine: shift the done != NULL check from cpu_stop_signal_done() to callers
  2015-11-15 19:32 [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Oleg Nesterov
                   ` (5 preceding siblings ...)
  2015-11-15 19:33 ` [PATCH 6/8] stop_machine: kill cpu_stop_done->executed Oleg Nesterov
@ 2015-11-15 19:33 ` Oleg Nesterov
  2015-11-23 16:23   ` [tip:sched/core] stop_machine: Shift the 'done != NULL' " tip-bot for Oleg Nesterov
  2015-11-15 19:33 ` [PATCH 8/8] stop_machine: cleanup the usage of preemption counter in cpu_stopper_thread() Oleg Nesterov
  2015-11-16  9:43 ` [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Peter Zijlstra
  8 siblings, 1 reply; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-15 19:33 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Milos Vyletel, Prarit Bhargava, Tejun Heo, Thomas Gleixner, linux-kernel

Change cpu_stop_queue_work() and cpu_stopper_thread() to check done != NULL
before cpu_stop_signal_done(done). This makes the code more clean imo, note
that cpu_stopper_thread() has to do this check anyway.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/stop_machine.c |   18 ++++++++----------
 1 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 09eb83f..7ff7ace 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -64,10 +64,8 @@ static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo)
 /* signal completion unless @done is NULL */
 static void cpu_stop_signal_done(struct cpu_stop_done *done)
 {
-	if (done) {
-		if (atomic_dec_and_test(&done->nr_todo))
-			complete(&done->completion);
-	}
+	if (atomic_dec_and_test(&done->nr_todo))
+		complete(&done->completion);
 }
 
 static void __cpu_stop_queue_work(struct cpu_stopper *stopper,
@@ -88,7 +86,7 @@ static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
 	enabled = stopper->enabled;
 	if (enabled)
 		__cpu_stop_queue_work(stopper, work);
-	else
+	else if (work->done)
 		cpu_stop_signal_done(work->done);
 	spin_unlock_irqrestore(&stopper->lock, flags);
 
@@ -457,12 +455,12 @@ repeat:
 
 		/* cpu stop callbacks are not allowed to sleep */
 		preempt_disable();
-
 		ret = fn(arg);
-		if (ret && done)
-			done->ret = ret;
-		cpu_stop_signal_done(done);
-
+		if (done) {
+			if (ret)
+				done->ret = ret;
+			cpu_stop_signal_done(done);
+		}
 		/* restore preemption and check it's still balanced */
 		preempt_enable();
 		WARN_ONCE(preempt_count(),
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 8/8] stop_machine: cleanup the usage of preemption counter in cpu_stopper_thread()
  2015-11-15 19:32 [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Oleg Nesterov
                   ` (6 preceding siblings ...)
  2015-11-15 19:33 ` [PATCH 7/8] stop_machine: shift the done != NULL check from cpu_stop_signal_done() to callers Oleg Nesterov
@ 2015-11-15 19:33 ` Oleg Nesterov
  2015-11-16 19:10   ` Tejun Heo
  2015-11-23 16:23   ` [tip:sched/core] stop_machine: Clean up the usage of the " tip-bot for Oleg Nesterov
  2015-11-16  9:43 ` [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Peter Zijlstra
  8 siblings, 2 replies; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-15 19:33 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Milos Vyletel, Prarit Bhargava, Tejun Heo, Thomas Gleixner, linux-kernel

1. Change this code to use preempt_count_inc/preempt_count_dec; this way
   it works even if CONFIG_PREEMPT_COUNT=n, and we avoid the unnecessary
   __preempt_schedule() check (stop_sched_class is not preemptible).

   And this makes clear that we only want to make preempt_count() != 0
   for __might_sleep() / schedule_debug().

2. Change WARN_ONCE() to use %pf to print the function name and remove
   kallsyms_lookup/ksym_buf.

3. Move "int ret" into the "if (work)" block, this looks more consistent.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/stop_machine.c |   15 +++++----------
 1 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 7ff7ace..6110119 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -435,7 +435,6 @@ static void cpu_stopper_thread(unsigned int cpu)
 {
 	struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
 	struct cpu_stop_work *work;
-	int ret;
 
 repeat:
 	work = NULL;
@@ -451,23 +450,19 @@ repeat:
 		cpu_stop_fn_t fn = work->fn;
 		void *arg = work->arg;
 		struct cpu_stop_done *done = work->done;
-		char ksym_buf[KSYM_NAME_LEN] __maybe_unused;
+		int ret;
 
-		/* cpu stop callbacks are not allowed to sleep */
-		preempt_disable();
+		/* cpu stop callbacks must not sleep, make in_atomic() == T */
+		preempt_count_inc();
 		ret = fn(arg);
 		if (done) {
 			if (ret)
 				done->ret = ret;
 			cpu_stop_signal_done(done);
 		}
-		/* restore preemption and check it's still balanced */
-		preempt_enable();
+		preempt_count_dec();
 		WARN_ONCE(preempt_count(),
-			  "cpu_stop: %s(%p) leaked preempt count\n",
-			  kallsyms_lookup((unsigned long)fn, NULL, NULL, NULL,
-					  ksym_buf), arg);
-
+			  "cpu_stop: %pf(%p) leaked preempt count\n", fn, arg);
 		goto repeat;
 	}
 }
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups
  2015-11-15 19:32 [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Oleg Nesterov
                   ` (7 preceding siblings ...)
  2015-11-15 19:33 ` [PATCH 8/8] stop_machine: cleanup the usage of preemption counter in cpu_stopper_thread() Oleg Nesterov
@ 2015-11-16  9:43 ` Peter Zijlstra
  8 siblings, 0 replies; 23+ messages in thread
From: Peter Zijlstra @ 2015-11-16  9:43 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Milos Vyletel, Prarit Bhargava, Tejun Heo,
	Thomas Gleixner, linux-kernel

On Sun, Nov 15, 2015 at 08:32:54PM +0100, Oleg Nesterov wrote:
> Hello,
> 
> I tried to backport the recent stop_machine fixes and recalled that
> I forgot to make the fix and cleanups I promised during the previous
> discussion.
> 
> Please review.
> 

Thanks!

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] stop_machine: cpu_stopper_thread() must check done != NULL
  2015-11-15 19:33 ` [PATCH 1/8] stop_machine: cpu_stopper_thread() must check done != NULL Oleg Nesterov
@ 2015-11-16 18:52   ` Tejun Heo
  2015-11-17 17:53     ` Oleg Nesterov
  2015-11-23 16:21   ` [tip:sched/core] stop_machine: Fix possible cpu_stopper_thread() crash tip-bot for Oleg Nesterov
  1 sibling, 1 reply; 23+ messages in thread
From: Tejun Heo @ 2015-11-16 18:52 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Milos Vyletel, Prarit Bhargava,
	Thomas Gleixner, linux-kernel

On Sun, Nov 15, 2015 at 08:33:11PM +0100, Oleg Nesterov wrote:
> stop_one_cpu_nowait(fn) will crash the kernel if the callback returns
> nonzero, work->done == NULL in this case.
> 
> This needs more cleanups, cpu_stop_signal_done() is called right after
> we check done != NULL and it does the same check.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>

Acked-by: Tejun Heo <tj@kernel.org>

cc stable?

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 8/8] stop_machine: cleanup the usage of preemption counter in cpu_stopper_thread()
  2015-11-15 19:33 ` [PATCH 8/8] stop_machine: cleanup the usage of preemption counter in cpu_stopper_thread() Oleg Nesterov
@ 2015-11-16 19:10   ` Tejun Heo
  2015-11-23 16:23   ` [tip:sched/core] stop_machine: Clean up the usage of the " tip-bot for Oleg Nesterov
  1 sibling, 0 replies; 23+ messages in thread
From: Tejun Heo @ 2015-11-16 19:10 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Milos Vyletel, Prarit Bhargava,
	Thomas Gleixner, linux-kernel

On Sun, Nov 15, 2015 at 08:33:32PM +0100, Oleg Nesterov wrote:
> 1. Change this code to use preempt_count_inc/preempt_count_dec; this way
>    it works even if CONFIG_PREEMPT_COUNT=n, and we avoid the unnecessary
>    __preempt_schedule() check (stop_sched_class is not preemptible).
> 
>    And this makes clear that we only want to make preempt_count() != 0
>    for __might_sleep() / schedule_debug().
> 
> 2. Change WARN_ONCE() to use %pf to print the function name and remove
>    kallsyms_lookup/ksym_buf.
> 
> 3. Move "int ret" into the "if (work)" block, this looks more consistent.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>

The entire series looks good to me.  Please feel free to add

Acked-by: Tejun Heo <tj@kernel.org>

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v2 3/8] stop_machine: make cpu_stop_queue_work() and stop_one_cpu_nowait() return bool
  2015-11-15 19:33 ` [PATCH 3/8] stop_machine: make cpu_stop_queue_work() and stop_one_cpu_nowait() return bool Oleg Nesterov
@ 2015-11-17 17:05   ` Oleg Nesterov
  2015-11-17 18:05     ` Peter Zijlstra
  2015-11-23 16:22     ` [tip:sched/core] stop_machine: Make " tip-bot for Oleg Nesterov
  0 siblings, 2 replies; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-17 17:05 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Milos Vyletel, Prarit Bhargava, Tejun Heo, Thomas Gleixner, linux-kernel

On 11/15, Oleg Nesterov wrote:
>
> --- a/include/linux/stop_machine.h
> +++ b/include/linux/stop_machine.h
> @@ -29,7 +29,7 @@ struct cpu_stop_work {
>  
>  int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
>  int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *arg);
> -void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
> +bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
>  			 struct cpu_stop_work *work_buf);

Peter, sorry!!!

I forgot to update the !CONFIG_SMP version of stop_one_cpu_nowait(). Please
see V2 below.

Or please tell me if I should send the incremental patch:

	--- a/include/linux/stop_machine.h
	+++ b/include/linux/stop_machine.h
	@@ -65,7 +65,7 @@ static void stop_one_cpu_nowait_workfn(struct work_struct *work)
		preempt_enable();
	 }
	 
	-static inline void stop_one_cpu_nowait(unsigned int cpu,
	+static inline bool stop_one_cpu_nowait(unsigned int cpu,
					       cpu_stop_fn_t fn, void *arg,
					       struct cpu_stop_work *work_buf)
	 {
	@@ -74,7 +74,10 @@ static inline void stop_one_cpu_nowait(unsigned int cpu,
			work_buf->fn = fn;
			work_buf->arg = arg;
			schedule_work(&work_buf->work);
	+		return true;
		}
	+
	+	return false;
	 }


-------------------------------------------------------------------------------
>From d5710e2dca493046257f97ed18699eed4c36a880 Mon Sep 17 00:00:00 2001
From: Oleg Nesterov <oleg@redhat.com>
Date: Sat, 14 Nov 2015 19:37:01 +0100
Subject: [PATCH v2 3/8] stop_machine: make cpu_stop_queue_work() and stop_one_cpu_nowait() return bool

Change cpu_stop_queue_work() to return true if the work was queued and
change stop_one_cpu_nowait() to return the result of cpu_stop_queue_work().
This makes it more useful, for example now you can alloc cpu_stop_work for
stop_one_cpu_nowait() and free it in the callback or if stop_one_cpu_nowait()
fails, currently this is impossible because you can't know if @fn will be
called or not.

Also, this allows to kill cpu_stop_done->executed, see the next changes.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 include/linux/stop_machine.h |    7 +++++--
 kernel/stop_machine.c        |   16 ++++++++++++----
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 0adedca..9ef42e1 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -29,7 +29,7 @@ struct cpu_stop_work {
 
 int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
 int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *arg);
-void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
+bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 			 struct cpu_stop_work *work_buf);
 int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
 int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
@@ -65,7 +65,7 @@ static void stop_one_cpu_nowait_workfn(struct work_struct *work)
 	preempt_enable();
 }
 
-static inline void stop_one_cpu_nowait(unsigned int cpu,
+static inline bool stop_one_cpu_nowait(unsigned int cpu,
 				       cpu_stop_fn_t fn, void *arg,
 				       struct cpu_stop_work *work_buf)
 {
@@ -74,7 +74,10 @@ static inline void stop_one_cpu_nowait(unsigned int cpu,
 		work_buf->fn = fn;
 		work_buf->arg = arg;
 		schedule_work(&work_buf->work);
+		return true;
 	}
+
+	return false;
 }
 
 static inline int stop_cpus(const struct cpumask *cpumask,
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 17f01a9..0ec1f16 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -81,17 +81,21 @@ static void __cpu_stop_queue_work(struct cpu_stopper *stopper,
 }
 
 /* queue @work to @stopper.  if offline, @work is completed immediately */
-static void cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
+static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
 {
 	struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
 	unsigned long flags;
+	bool enabled;
 
 	spin_lock_irqsave(&stopper->lock, flags);
-	if (stopper->enabled)
+	enabled = stopper->enabled;
+	if (enabled)
 		__cpu_stop_queue_work(stopper, work);
 	else
 		cpu_stop_signal_done(work->done, false);
 	spin_unlock_irqrestore(&stopper->lock, flags);
+
+	return enabled;
 }
 
 /**
@@ -297,12 +301,16 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
  *
  * CONTEXT:
  * Don't care.
+ *
+ * RETURNS:
+ * true if cpu_stop_work was queued successfully and @fn will be called,
+ * false otherwise.
  */
-void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
+bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 			struct cpu_stop_work *work_buf)
 {
 	*work_buf = (struct cpu_stop_work){ .fn = fn, .arg = arg, };
-	cpu_stop_queue_work(cpu, work_buf);
+	return cpu_stop_queue_work(cpu, work_buf);
 }
 
 /* static data for stop_cpus */
-- 
1.5.5.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] stop_machine: cpu_stopper_thread() must check done != NULL
  2015-11-16 18:52   ` Tejun Heo
@ 2015-11-17 17:53     ` Oleg Nesterov
  0 siblings, 0 replies; 23+ messages in thread
From: Oleg Nesterov @ 2015-11-17 17:53 UTC (permalink / raw)
  To: Tejun Heo
  Cc: Ingo Molnar, Peter Zijlstra, Milos Vyletel, Prarit Bhargava,
	Thomas Gleixner, linux-kernel

On 11/16, Tejun Heo wrote:
>
> On Sun, Nov 15, 2015 at 08:33:11PM +0100, Oleg Nesterov wrote:
> > stop_one_cpu_nowait(fn) will crash the kernel if the callback returns
> > nonzero, work->done == NULL in this case.
> >
> > This needs more cleanups, cpu_stop_signal_done() is called right after
> > we check done != NULL and it does the same check.
> >
> > Signed-off-by: Oleg Nesterov <oleg@redhat.com>
>
> Acked-by: Tejun Heo <tj@kernel.org>

Thanks!

> cc stable?

Yes, I was going to add -stable initially. And perhaps this makes sense
anyway, the patch is really trivial.

OTOH I have checked the history, none of cpu_stop_signal_done's callbacks
ever returned non-zero, so I decided to not spam -stable.

Oleg.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 3/8] stop_machine: make cpu_stop_queue_work() and stop_one_cpu_nowait() return bool
  2015-11-17 17:05   ` [PATCH v2 " Oleg Nesterov
@ 2015-11-17 18:05     ` Peter Zijlstra
  2015-11-23 16:22     ` [tip:sched/core] stop_machine: Make " tip-bot for Oleg Nesterov
  1 sibling, 0 replies; 23+ messages in thread
From: Peter Zijlstra @ 2015-11-17 18:05 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Milos Vyletel, Prarit Bhargava, Tejun Heo,
	Thomas Gleixner, linux-kernel

On Tue, Nov 17, 2015 at 06:05:23PM +0100, Oleg Nesterov wrote:
> On 11/15, Oleg Nesterov wrote:
> >
> > --- a/include/linux/stop_machine.h
> > +++ b/include/linux/stop_machine.h
> > @@ -29,7 +29,7 @@ struct cpu_stop_work {
> >  
> >  int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
> >  int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *arg);
> > -void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
> > +bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
> >  			 struct cpu_stop_work *work_buf);
> 
> Peter, sorry!!!
> 
> I forgot to update the !CONFIG_SMP version of stop_one_cpu_nowait(). Please
> see V2 below.

No problem, updated the patch.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [tip:sched/core] stop_machine: Fix possible cpu_stopper_thread() crash
  2015-11-15 19:33 ` [PATCH 1/8] stop_machine: cpu_stopper_thread() must check done != NULL Oleg Nesterov
  2015-11-16 18:52   ` Tejun Heo
@ 2015-11-23 16:21   ` tip-bot for Oleg Nesterov
  1 sibling, 0 replies; 23+ messages in thread
From: tip-bot for Oleg Nesterov @ 2015-11-23 16:21 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: efault, peterz, tglx, linux-kernel, torvalds, prarit, tj, hpa,
	milos, oleg, mingo

Commit-ID:  64038f292a1b33c7d46bd11f62f7798101152c00
Gitweb:     http://git.kernel.org/tip/64038f292a1b33c7d46bd11f62f7798101152c00
Author:     Oleg Nesterov <oleg@redhat.com>
AuthorDate: Sun, 15 Nov 2015 20:33:11 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 23 Nov 2015 09:48:17 +0100

stop_machine: Fix possible cpu_stopper_thread() crash

stop_one_cpu_nowait(fn) will crash the kernel if the callback returns
nonzero, work->done == NULL in this case.

This needs more cleanups, cpu_stop_signal_done() is called right after
we check done != NULL and it does the same check.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Milos Vyletel <milos@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151115193311.GA8242@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/stop_machine.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 867bc20..1a66a95 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -454,7 +454,7 @@ repeat:
 		preempt_disable();
 
 		ret = fn(arg);
-		if (ret)
+		if (ret && done)
 			done->ret = ret;
 
 		/* restore preemption and check it's still balanced */

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip:sched/core] stop_machine: Don' t disable preemption in stop_two_cpus()
  2015-11-15 19:33 ` [PATCH 2/8] stop_machine: don't disable preemption in stop_two_cpus() Oleg Nesterov
@ 2015-11-23 16:21   ` tip-bot for Oleg Nesterov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot for Oleg Nesterov @ 2015-11-23 16:21 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tj, tglx, efault, peterz, prarit, oleg, milos, linux-kernel,
	torvalds, mingo, hpa

Commit-ID:  6a19005157c464b47b2082f2617d12bc11198a0d
Gitweb:     http://git.kernel.org/tip/6a19005157c464b47b2082f2617d12bc11198a0d
Author:     Oleg Nesterov <oleg@redhat.com>
AuthorDate: Sun, 15 Nov 2015 20:33:14 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 23 Nov 2015 09:48:18 +0100

stop_machine: Don't disable preemption in stop_two_cpus()

Now that stop_two_cpus() path does not check cpu_active() we can remove
preempt_disable(), it was only needed to ensure that stop_machine() can
not be called after we observe cpu_active() == T and before we queue the
new work.

Also, turn the pointless and confusing ->executed check into WARN_ON().
We know that both works must be executed, otherwise we have a bug. And
in fact I think that done->executed should die, see the next changes.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Milos Vyletel <milos@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151115193314.GA8249@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/stop_machine.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 1a66a95..17f01a9 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -258,7 +258,6 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
 	struct cpu_stop_work work1, work2;
 	struct multi_stop_data msdata;
 
-	preempt_disable();
 	msdata = (struct multi_stop_data){
 		.fn = fn,
 		.data = arg,
@@ -277,16 +276,12 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
 
 	if (cpu1 > cpu2)
 		swap(cpu1, cpu2);
-	if (cpu_stop_queue_two_works(cpu1, &work1, cpu2, &work2)) {
-		preempt_enable();
+	if (cpu_stop_queue_two_works(cpu1, &work1, cpu2, &work2))
 		return -ENOENT;
-	}
-
-	preempt_enable();
 
 	wait_for_completion(&done.completion);
-
-	return done.executed ? done.ret : -ENOENT;
+	WARN_ON(!done.executed);
+	return done.ret;
 }
 
 /**

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip:sched/core] stop_machine: Make cpu_stop_queue_work() and stop_one_cpu_nowait() return bool
  2015-11-17 17:05   ` [PATCH v2 " Oleg Nesterov
  2015-11-17 18:05     ` Peter Zijlstra
@ 2015-11-23 16:22     ` tip-bot for Oleg Nesterov
  1 sibling, 0 replies; 23+ messages in thread
From: tip-bot for Oleg Nesterov @ 2015-11-23 16:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tj, milos, tglx, torvalds, prarit, efault, mingo, linux-kernel,
	oleg, hpa, peterz

Commit-ID:  1b034bd989aa4a396c13d305759c376c52595a97
Gitweb:     http://git.kernel.org/tip/1b034bd989aa4a396c13d305759c376c52595a97
Author:     Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 17 Nov 2015 18:05:23 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 23 Nov 2015 09:48:18 +0100

stop_machine: Make cpu_stop_queue_work() and stop_one_cpu_nowait() return bool

Change cpu_stop_queue_work() to return true if the work was queued and
change stop_one_cpu_nowait() to return the result of cpu_stop_queue_work().
This makes it more useful, for example now you can alloc cpu_stop_work for
stop_one_cpu_nowait() and free it in the callback or if stop_one_cpu_nowait()
fails, currently this is impossible because you can't know if @fn will be
called or not.

Also, this allows to kill cpu_stop_done->executed, see the next changes.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Milos Vyletel <milos@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151117170523.GA13955@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 include/linux/stop_machine.h |  7 +++++--
 kernel/stop_machine.c        | 16 ++++++++++++----
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 0adedca..9ef42e1 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -29,7 +29,7 @@ struct cpu_stop_work {
 
 int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
 int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *arg);
-void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
+bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 			 struct cpu_stop_work *work_buf);
 int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
 int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
@@ -65,7 +65,7 @@ static void stop_one_cpu_nowait_workfn(struct work_struct *work)
 	preempt_enable();
 }
 
-static inline void stop_one_cpu_nowait(unsigned int cpu,
+static inline bool stop_one_cpu_nowait(unsigned int cpu,
 				       cpu_stop_fn_t fn, void *arg,
 				       struct cpu_stop_work *work_buf)
 {
@@ -74,7 +74,10 @@ static inline void stop_one_cpu_nowait(unsigned int cpu,
 		work_buf->fn = fn;
 		work_buf->arg = arg;
 		schedule_work(&work_buf->work);
+		return true;
 	}
+
+	return false;
 }
 
 static inline int stop_cpus(const struct cpumask *cpumask,
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 17f01a9..0ec1f16 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -81,17 +81,21 @@ static void __cpu_stop_queue_work(struct cpu_stopper *stopper,
 }
 
 /* queue @work to @stopper.  if offline, @work is completed immediately */
-static void cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
+static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
 {
 	struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
 	unsigned long flags;
+	bool enabled;
 
 	spin_lock_irqsave(&stopper->lock, flags);
-	if (stopper->enabled)
+	enabled = stopper->enabled;
+	if (enabled)
 		__cpu_stop_queue_work(stopper, work);
 	else
 		cpu_stop_signal_done(work->done, false);
 	spin_unlock_irqrestore(&stopper->lock, flags);
+
+	return enabled;
 }
 
 /**
@@ -297,12 +301,16 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
  *
  * CONTEXT:
  * Don't care.
+ *
+ * RETURNS:
+ * true if cpu_stop_work was queued successfully and @fn will be called,
+ * false otherwise.
  */
-void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
+bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 			struct cpu_stop_work *work_buf)
 {
 	*work_buf = (struct cpu_stop_work){ .fn = fn, .arg = arg, };
-	cpu_stop_queue_work(cpu, work_buf);
+	return cpu_stop_queue_work(cpu, work_buf);
 }
 
 /* static data for stop_cpus */

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip:sched/core] stop_machine: Change stop_one_cpu() to rely on cpu_stop_queue_work()
  2015-11-15 19:33 ` [PATCH 4/8] stop_machine: change stop_one_cpu() to rely on cpu_stop_queue_work() Oleg Nesterov
@ 2015-11-23 16:22   ` tip-bot for Oleg Nesterov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot for Oleg Nesterov @ 2015-11-23 16:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: oleg, linux-kernel, tglx, tj, hpa, mingo, peterz, efault, milos,
	prarit, torvalds

Commit-ID:  958c5f848e17e216df138cc2161b07b7120e2d15
Gitweb:     http://git.kernel.org/tip/958c5f848e17e216df138cc2161b07b7120e2d15
Author:     Oleg Nesterov <oleg@redhat.com>
AuthorDate: Sun, 15 Nov 2015 20:33:20 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 23 Nov 2015 09:48:18 +0100

stop_machine: Change stop_one_cpu() to rely on cpu_stop_queue_work()

Change stop_one_cpu() to return -ENOENT if cpu_stop_queue_work() fails.
Otherwise we know that ->executed must be true after wait_for_completion()
so we can just return done.ret.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Milos Vyletel <milos@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151115193320.GA8259@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/stop_machine.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 0ec1f16..68b73c4 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -128,9 +128,11 @@ int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg)
 	struct cpu_stop_work work = { .fn = fn, .arg = arg, .done = &done };
 
 	cpu_stop_init_done(&done, 1);
-	cpu_stop_queue_work(cpu, &work);
+	if (!cpu_stop_queue_work(cpu, &work))
+		return -ENOENT;
 	wait_for_completion(&done.completion);
-	return done.executed ? done.ret : -ENOENT;
+	WARN_ON(!done.executed);
+	return done.ret;
 }
 
 /* This controls the threads on each CPU. */

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip:sched/core] stop_machine: Change __stop_cpus() to rely on cpu_stop_queue_work()
  2015-11-15 19:33 ` [PATCH 5/8] stop_machine: change __stop_cpus() " Oleg Nesterov
@ 2015-11-23 16:22   ` tip-bot for Oleg Nesterov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot for Oleg Nesterov @ 2015-11-23 16:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: oleg, mingo, linux-kernel, hpa, milos, tj, efault, prarit, tglx,
	torvalds, peterz

Commit-ID:  4aff1ca6970afbf9cd916c34a9c442c8ccba905e
Gitweb:     http://git.kernel.org/tip/4aff1ca6970afbf9cd916c34a9c442c8ccba905e
Author:     Oleg Nesterov <oleg@redhat.com>
AuthorDate: Sun, 15 Nov 2015 20:33:23 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 23 Nov 2015 09:48:19 +0100

stop_machine: Change __stop_cpus() to rely on cpu_stop_queue_work()

Change queue_stop_cpus_work() to return true if it queues at least one
work, this means that the caller should wait.

__stop_cpus() can check the value returned by queue_stop_cpus_work() and
avoid done.executed, just like stop_one_cpu() does.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Milos Vyletel <milos@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151115193323.GA8262@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/stop_machine.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 68b73c4..ed2019a 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -318,12 +318,13 @@ bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 /* static data for stop_cpus */
 static DEFINE_MUTEX(stop_cpus_mutex);
 
-static void queue_stop_cpus_work(const struct cpumask *cpumask,
+static bool queue_stop_cpus_work(const struct cpumask *cpumask,
 				 cpu_stop_fn_t fn, void *arg,
 				 struct cpu_stop_done *done)
 {
 	struct cpu_stop_work *work;
 	unsigned int cpu;
+	bool queued = false;
 
 	/*
 	 * Disable preemption while queueing to avoid getting
@@ -336,9 +337,12 @@ static void queue_stop_cpus_work(const struct cpumask *cpumask,
 		work->fn = fn;
 		work->arg = arg;
 		work->done = done;
-		cpu_stop_queue_work(cpu, work);
+		if (cpu_stop_queue_work(cpu, work))
+			queued = true;
 	}
 	lg_global_unlock(&stop_cpus_lock);
+
+	return queued;
 }
 
 static int __stop_cpus(const struct cpumask *cpumask,
@@ -347,9 +351,11 @@ static int __stop_cpus(const struct cpumask *cpumask,
 	struct cpu_stop_done done;
 
 	cpu_stop_init_done(&done, cpumask_weight(cpumask));
-	queue_stop_cpus_work(cpumask, fn, arg, &done);
+	if (!queue_stop_cpus_work(cpumask, fn, arg, &done))
+		return -ENOENT;
 	wait_for_completion(&done.completion);
-	return done.executed ? done.ret : -ENOENT;
+	WARN_ON(!done.executed);
+	return done.ret;
 }
 
 /**

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip:sched/core] stop_machine: Kill cpu_stop_done->executed
  2015-11-15 19:33 ` [PATCH 6/8] stop_machine: kill cpu_stop_done->executed Oleg Nesterov
@ 2015-11-23 16:23   ` tip-bot for Oleg Nesterov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot for Oleg Nesterov @ 2015-11-23 16:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: oleg, tglx, mingo, torvalds, prarit, linux-kernel, tj, hpa,
	efault, milos, peterz

Commit-ID:  6fa3b826bcb3309157166e6e523a4be236fe267a
Gitweb:     http://git.kernel.org/tip/6fa3b826bcb3309157166e6e523a4be236fe267a
Author:     Oleg Nesterov <oleg@redhat.com>
AuthorDate: Sun, 15 Nov 2015 20:33:26 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 23 Nov 2015 09:48:19 +0100

stop_machine: Kill cpu_stop_done->executed

Now that cpu_stop_done->executed becomes write-only (ignoring WARN_ON()
checks) we can remove it.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Milos Vyletel <milos@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151115193326.GA8269@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/stop_machine.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index ed2019a..09eb83f 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -28,7 +28,6 @@
  */
 struct cpu_stop_done {
 	atomic_t		nr_todo;	/* nr left to execute */
-	bool			executed;	/* actually executed? */
 	int			ret;		/* collected return value */
 	struct completion	completion;	/* fired if nr_todo reaches 0 */
 };
@@ -63,11 +62,9 @@ static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo)
 }
 
 /* signal completion unless @done is NULL */
-static void cpu_stop_signal_done(struct cpu_stop_done *done, bool executed)
+static void cpu_stop_signal_done(struct cpu_stop_done *done)
 {
 	if (done) {
-		if (executed)
-			done->executed = true;
 		if (atomic_dec_and_test(&done->nr_todo))
 			complete(&done->completion);
 	}
@@ -92,7 +89,7 @@ static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
 	if (enabled)
 		__cpu_stop_queue_work(stopper, work);
 	else
-		cpu_stop_signal_done(work->done, false);
+		cpu_stop_signal_done(work->done);
 	spin_unlock_irqrestore(&stopper->lock, flags);
 
 	return enabled;
@@ -131,7 +128,6 @@ int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg)
 	if (!cpu_stop_queue_work(cpu, &work))
 		return -ENOENT;
 	wait_for_completion(&done.completion);
-	WARN_ON(!done.executed);
 	return done.ret;
 }
 
@@ -286,7 +282,6 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
 		return -ENOENT;
 
 	wait_for_completion(&done.completion);
-	WARN_ON(!done.executed);
 	return done.ret;
 }
 
@@ -354,7 +349,6 @@ static int __stop_cpus(const struct cpumask *cpumask,
 	if (!queue_stop_cpus_work(cpumask, fn, arg, &done))
 		return -ENOENT;
 	wait_for_completion(&done.completion);
-	WARN_ON(!done.executed);
 	return done.ret;
 }
 
@@ -467,6 +461,7 @@ repeat:
 		ret = fn(arg);
 		if (ret && done)
 			done->ret = ret;
+		cpu_stop_signal_done(done);
 
 		/* restore preemption and check it's still balanced */
 		preempt_enable();
@@ -475,7 +470,6 @@ repeat:
 			  kallsyms_lookup((unsigned long)fn, NULL, NULL, NULL,
 					  ksym_buf), arg);
 
-		cpu_stop_signal_done(done, true);
 		goto repeat;
 	}
 }

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip:sched/core] stop_machine: Shift the 'done != NULL' check from cpu_stop_signal_done() to callers
  2015-11-15 19:33 ` [PATCH 7/8] stop_machine: shift the done != NULL check from cpu_stop_signal_done() to callers Oleg Nesterov
@ 2015-11-23 16:23   ` tip-bot for Oleg Nesterov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot for Oleg Nesterov @ 2015-11-23 16:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tj, tglx, peterz, mingo, torvalds, milos, efault, hpa, oleg,
	prarit, linux-kernel

Commit-ID:  dd2e3121e3cb16d03a6e3f2db48f260f046f39c2
Gitweb:     http://git.kernel.org/tip/dd2e3121e3cb16d03a6e3f2db48f260f046f39c2
Author:     Oleg Nesterov <oleg@redhat.com>
AuthorDate: Sun, 15 Nov 2015 20:33:29 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 23 Nov 2015 09:48:19 +0100

stop_machine: Shift the 'done != NULL' check from cpu_stop_signal_done() to callers

Change cpu_stop_queue_work() and cpu_stopper_thread() to check done != NULL
before cpu_stop_signal_done(done). This makes the code more clean imo, note
that cpu_stopper_thread() has to do this check anyway.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Milos Vyletel <milos@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151115193329.GA8274@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/stop_machine.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 09eb83f..7ff7ace 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -64,10 +64,8 @@ static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo)
 /* signal completion unless @done is NULL */
 static void cpu_stop_signal_done(struct cpu_stop_done *done)
 {
-	if (done) {
-		if (atomic_dec_and_test(&done->nr_todo))
-			complete(&done->completion);
-	}
+	if (atomic_dec_and_test(&done->nr_todo))
+		complete(&done->completion);
 }
 
 static void __cpu_stop_queue_work(struct cpu_stopper *stopper,
@@ -88,7 +86,7 @@ static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
 	enabled = stopper->enabled;
 	if (enabled)
 		__cpu_stop_queue_work(stopper, work);
-	else
+	else if (work->done)
 		cpu_stop_signal_done(work->done);
 	spin_unlock_irqrestore(&stopper->lock, flags);
 
@@ -457,12 +455,12 @@ repeat:
 
 		/* cpu stop callbacks are not allowed to sleep */
 		preempt_disable();
-
 		ret = fn(arg);
-		if (ret && done)
-			done->ret = ret;
-		cpu_stop_signal_done(done);
-
+		if (done) {
+			if (ret)
+				done->ret = ret;
+			cpu_stop_signal_done(done);
+		}
 		/* restore preemption and check it's still balanced */
 		preempt_enable();
 		WARN_ONCE(preempt_count(),

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip:sched/core] stop_machine: Clean up the usage of the preemption counter in cpu_stopper_thread()
  2015-11-15 19:33 ` [PATCH 8/8] stop_machine: cleanup the usage of preemption counter in cpu_stopper_thread() Oleg Nesterov
  2015-11-16 19:10   ` Tejun Heo
@ 2015-11-23 16:23   ` tip-bot for Oleg Nesterov
  1 sibling, 0 replies; 23+ messages in thread
From: tip-bot for Oleg Nesterov @ 2015-11-23 16:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, efault, milos, linux-kernel, tj, peterz, hpa, torvalds,
	oleg, mingo, prarit

Commit-ID:  accaf6ea3db6f5fb997f096b6eefd5431d03f7e5
Gitweb:     http://git.kernel.org/tip/accaf6ea3db6f5fb997f096b6eefd5431d03f7e5
Author:     Oleg Nesterov <oleg@redhat.com>
AuthorDate: Sun, 15 Nov 2015 20:33:32 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 23 Nov 2015 09:48:20 +0100

stop_machine: Clean up the usage of the preemption counter in cpu_stopper_thread()

1. Change this code to use preempt_count_inc/preempt_count_dec; this way
   it works even if CONFIG_PREEMPT_COUNT=n, and we avoid the unnecessary
   __preempt_schedule() check (stop_sched_class is not preemptible).

   And this makes clear that we only want to make preempt_count() != 0
   for __might_sleep() / schedule_debug().

2. Change WARN_ONCE() to use %pf to print the function name and remove
   kallsyms_lookup/ksym_buf.

3. Move "int ret" into the "if (work)" block, this looks more consistent.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Milos Vyletel <milos@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151115193332.GA8281@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/stop_machine.c | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 7ff7ace..6110119 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -435,7 +435,6 @@ static void cpu_stopper_thread(unsigned int cpu)
 {
 	struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
 	struct cpu_stop_work *work;
-	int ret;
 
 repeat:
 	work = NULL;
@@ -451,23 +450,19 @@ repeat:
 		cpu_stop_fn_t fn = work->fn;
 		void *arg = work->arg;
 		struct cpu_stop_done *done = work->done;
-		char ksym_buf[KSYM_NAME_LEN] __maybe_unused;
+		int ret;
 
-		/* cpu stop callbacks are not allowed to sleep */
-		preempt_disable();
+		/* cpu stop callbacks must not sleep, make in_atomic() == T */
+		preempt_count_inc();
 		ret = fn(arg);
 		if (done) {
 			if (ret)
 				done->ret = ret;
 			cpu_stop_signal_done(done);
 		}
-		/* restore preemption and check it's still balanced */
-		preempt_enable();
+		preempt_count_dec();
 		WARN_ONCE(preempt_count(),
-			  "cpu_stop: %s(%p) leaked preempt count\n",
-			  kallsyms_lookup((unsigned long)fn, NULL, NULL, NULL,
-					  ksym_buf), arg);
-
+			  "cpu_stop: %pf(%p) leaked preempt count\n", fn, arg);
 		goto repeat;
 	}
 }

^ permalink raw reply related	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2015-11-23 16:24 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-15 19:32 [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Oleg Nesterov
2015-11-15 19:33 ` [PATCH 1/8] stop_machine: cpu_stopper_thread() must check done != NULL Oleg Nesterov
2015-11-16 18:52   ` Tejun Heo
2015-11-17 17:53     ` Oleg Nesterov
2015-11-23 16:21   ` [tip:sched/core] stop_machine: Fix possible cpu_stopper_thread() crash tip-bot for Oleg Nesterov
2015-11-15 19:33 ` [PATCH 2/8] stop_machine: don't disable preemption in stop_two_cpus() Oleg Nesterov
2015-11-23 16:21   ` [tip:sched/core] stop_machine: Don' t " tip-bot for Oleg Nesterov
2015-11-15 19:33 ` [PATCH 3/8] stop_machine: make cpu_stop_queue_work() and stop_one_cpu_nowait() return bool Oleg Nesterov
2015-11-17 17:05   ` [PATCH v2 " Oleg Nesterov
2015-11-17 18:05     ` Peter Zijlstra
2015-11-23 16:22     ` [tip:sched/core] stop_machine: Make " tip-bot for Oleg Nesterov
2015-11-15 19:33 ` [PATCH 4/8] stop_machine: change stop_one_cpu() to rely on cpu_stop_queue_work() Oleg Nesterov
2015-11-23 16:22   ` [tip:sched/core] stop_machine: Change " tip-bot for Oleg Nesterov
2015-11-15 19:33 ` [PATCH 5/8] stop_machine: change __stop_cpus() " Oleg Nesterov
2015-11-23 16:22   ` [tip:sched/core] stop_machine: Change " tip-bot for Oleg Nesterov
2015-11-15 19:33 ` [PATCH 6/8] stop_machine: kill cpu_stop_done->executed Oleg Nesterov
2015-11-23 16:23   ` [tip:sched/core] stop_machine: Kill cpu_stop_done->executed tip-bot for Oleg Nesterov
2015-11-15 19:33 ` [PATCH 7/8] stop_machine: shift the done != NULL check from cpu_stop_signal_done() to callers Oleg Nesterov
2015-11-23 16:23   ` [tip:sched/core] stop_machine: Shift the 'done != NULL' " tip-bot for Oleg Nesterov
2015-11-15 19:33 ` [PATCH 8/8] stop_machine: cleanup the usage of preemption counter in cpu_stopper_thread() Oleg Nesterov
2015-11-16 19:10   ` Tejun Heo
2015-11-23 16:23   ` [tip:sched/core] stop_machine: Clean up the usage of the " tip-bot for Oleg Nesterov
2015-11-16  9:43 ` [PATCH 0/8] stop_machine: stop_one_cpu_nowait() fix, misc cleanups Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).