All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] sched: Use RCU read lock on all calls to dl_bw_of()
@ 2014-09-29 15:19 Sasha Levin
  2014-09-29 16:43 ` Kirill Tkhai
  0 siblings, 1 reply; 7+ messages in thread
From: Sasha Levin @ 2014-09-29 15:19 UTC (permalink / raw)
  To: mingo; +Cc: torvalds, paulmck, peterz, ktkhai, linux-kernel, Sasha Levin

Commit "sched: Use dl_bw_of() under RCU read lock" has missed a call
to dl_bw_of(), which has now started showing warnings:

[  820.960972] ===============================
[  820.961663] [ INFO: suspicious RCU usage. ]
[  820.962344] 3.17.0-rc6-next-20140926-sasha-00051-g9253dff-dirty #1242 Not tainted
[  820.963670] -------------------------------
[  820.964454] kernel/sched/core.c:2008 sched RCU must be held!
[  820.975556]
[  820.975556] other info that might help us debug this:
[  820.975556]
[  820.987512] rcu_scheduler_active = 1, debug_locks = 1
[  820.988546] 9 locks held by trinity-c157/26236:
[  820.989274] #0: (&f->f_pos_lock){+.+.+.}, at: __fdget_pos (fs/file.c:718)
[  820.994630] #1: (sb_writers#5){.+.+.+}, at: do_readv_writev (include/linux/fs.h:2270 fs/read_write.c:832)
[  820.996170] #2: (&of->mutex){+.+.+.}, at: kernfs_fop_write (fs/kernfs/file.c:296)
[  821.001816] #3: (s_active#23){.+.+.+}, at: kernfs_fop_write (fs/kernfs/file.c:296)
[  821.003235] #4: (device_hotplug_lock){+.+.+.}, at: lock_device_hotplug_sysfs (drivers/base/core.c:66)
[  821.004842] #5: (&dev->mutex){......}, at: device_offline (include/linux/device.h:900 drivers/base/core.c:1423)
[  821.010610] #6: (cpu_add_remove_lock){+.+.+.}, at: cpu_down (kernel/cpu.c:426)
[  821.011859] #7: (cpu_hotplug.lock){++++++}, at: cpu_hotplug_begin (kernel/cpu.c:152)
[  821.013208] #8: (cpu_hotplug.lock#2){+.+.+.}, at: cpu_hotplug_begin (kernel/cpu.c:158)
[  821.027101]
[  821.027101] stack backtrace:
[  821.027903] CPU: 17 PID: 26236 Comm: trinity-c157 Not tainted 3.17.0-rc6-next-20140926-sasha-00051-g9253dff-dirty #1242
[  821.030246]  0000000000000001 0000000000000000 0000000000000001 ffff880803363a98
[  821.038543]  ffffffffb5f0070f 0000000000000011 ffff8808271eb000 ffff880803363ac8
[  821.039967]  ffffffffb124e8ed 0000000000000000 ffff880803363bbc 0000000000000013
[  821.041455] Call Trace:
[  821.042038] dump_stack (lib/dump_stack.c:52)
[  821.043005] lockdep_rcu_suspicious (kernel/locking/lockdep.c:4265)
[  821.044169] sched_cpu_inactive (kernel/sched/core.c:2008 kernel/sched/core.c:5271)
[  821.050486] notifier_call_chain (kernel/notifier.c:93)
[  821.051594] __raw_notifier_call_chain (kernel/notifier.c:395)
[  821.052766] _cpu_down (include/linux/notifier.h:179 kernel/cpu.c:219 kernel/cpu.c:356)
[  821.053809] ? cpu_down (kernel/cpu.c:426)
[  821.054770] cpu_down (kernel/cpu.c:431)
[  821.062497] cpu_subsys_offline (drivers/base/cpu.c:69)
[  821.063500] device_offline (drivers/base/core.c:1428)
[  821.064428] ? cpu_device_release (drivers/base/cpu.c:67)
[  821.065429] online_store (drivers/base/core.c:451 (discriminator 2))
[  821.066390] dev_attr_store (drivers/base/core.c:138)
[  821.067328] ? dev_driver_string (drivers/base/core.c:130)
[  821.073698] sysfs_kf_write (fs/sysfs/file.c:116)
[  821.074496] ? sysfs_file_ops (fs/sysfs/file.c:108)
[  821.075312] kernfs_fop_write (fs/kernfs/file.c:308)
[  821.076135] ? do_readv_writev (include/linux/fs.h:2270 fs/read_write.c:832)
[  821.076999] do_loop_readv_writev (fs/read_write.c:710)
[  821.078066] ? kernfs_vma_page_mkwrite (fs/kernfs/file.c:267)
[  821.079252] do_readv_writev (fs/read_write.c:842)
[  821.080495] ? kernfs_vma_page_mkwrite (fs/kernfs/file.c:267)
[  821.081644] ? mutex_lock_nested (./arch/x86/include/asm/preempt.h:98 kernel/locking/mutex.c:599 kernel/locking/mutex.c:616)
[  821.086535] ? __fdget_pos (fs/file.c:718)
[  821.087447] ? __fdget_pos (fs/file.c:718)
[  821.088363] ? rcu_read_lock_held (kernel/rcu/update.c:169)
[  821.089425] vfs_writev (fs/read_write.c:881)
[  821.090486] SyS_writev (fs/read_write.c:913 fs/read_write.c:905)
[  821.091382] tracesys_phase2 (arch/x86/kernel/entry_64.S:529)

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
 kernel/sched/core.c |   15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index e6cfd9b..91bfbbb 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5261,6 +5261,9 @@ static int sched_cpu_inactive(struct notifier_block *nfb,
 {
 	unsigned long flags;
 	long cpu = (long)hcpu;
+	int ret;
+
+	rcu_read_lock();
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_DOWN_PREPARE:
@@ -5277,13 +5280,19 @@ static int sched_cpu_inactive(struct notifier_block *nfb,
 			overflow = __dl_overflow(dl_b, cpus, 0, 0);
 			raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 
+			ret = notifier_from_errno(-EBUSY);
 			if (overflow)
-				return notifier_from_errno(-EBUSY);
+				goto done;
 		}
-		return NOTIFY_OK;
+		ret = NOTIFY_OK;
+		goto done;
 	}
 
-	return NOTIFY_DONE;
+	ret = NOTIFY_DONE;
+
+done:
+	rcu_read_unlock();
+	return ret;
 }
 
 static int __init migration_init(void)
-- 
1.7.10.4


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

* Re: [PATCH] sched: Use RCU read lock on all calls to dl_bw_of()
  2014-09-29 15:19 [PATCH] sched: Use RCU read lock on all calls to dl_bw_of() Sasha Levin
@ 2014-09-29 16:43 ` Kirill Tkhai
  2014-09-29 16:54   ` Peter Zijlstra
  0 siblings, 1 reply; 7+ messages in thread
From: Kirill Tkhai @ 2014-09-29 16:43 UTC (permalink / raw)
  To: Sasha Levin; +Cc: mingo, torvalds, paulmck, peterz, linux-kernel

Hi, Sasha,

В Пн, 29/09/2014 в 11:19 -0400, Sasha Levin пишет:
> Commit "sched: Use dl_bw_of() under RCU read lock" has missed a call
> to dl_bw_of(), which has now started showing warnings:
> 
> [  820.960972] ===============================
> [  820.961663] [ INFO: suspicious RCU usage. ]
> [  820.962344] 3.17.0-rc6-next-20140926-sasha-00051-g9253dff-dirty #1242 Not tainted
> [  820.963670] -------------------------------
> [  820.964454] kernel/sched/core.c:2008 sched RCU must be held!
> [  820.975556]
> [  820.975556] other info that might help us debug this:
> [  820.975556]
> [  820.987512] rcu_scheduler_active = 1, debug_locks = 1
> [  820.988546] 9 locks held by trinity-c157/26236:
> [  820.989274] #0: (&f->f_pos_lock){+.+.+.}, at: __fdget_pos (fs/file.c:718)
> [  820.994630] #1: (sb_writers#5){.+.+.+}, at: do_readv_writev (include/linux/fs.h:2270 fs/read_write.c:832)
> [  820.996170] #2: (&of->mutex){+.+.+.}, at: kernfs_fop_write (fs/kernfs/file.c:296)
> [  821.001816] #3: (s_active#23){.+.+.+}, at: kernfs_fop_write (fs/kernfs/file.c:296)
> [  821.003235] #4: (device_hotplug_lock){+.+.+.}, at: lock_device_hotplug_sysfs (drivers/base/core.c:66)
> [  821.004842] #5: (&dev->mutex){......}, at: device_offline (include/linux/device.h:900 drivers/base/core.c:1423)
> [  821.010610] #6: (cpu_add_remove_lock){+.+.+.}, at: cpu_down (kernel/cpu.c:426)
> [  821.011859] #7: (cpu_hotplug.lock){++++++}, at: cpu_hotplug_begin (kernel/cpu.c:152)
> [  821.013208] #8: (cpu_hotplug.lock#2){+.+.+.}, at: cpu_hotplug_begin (kernel/cpu.c:158)
> [  821.027101]
> [  821.027101] stack backtrace:
> [  821.027903] CPU: 17 PID: 26236 Comm: trinity-c157 Not tainted 3.17.0-rc6-next-20140926-sasha-00051-g9253dff-dirty #1242
> [  821.030246]  0000000000000001 0000000000000000 0000000000000001 ffff880803363a98
> [  821.038543]  ffffffffb5f0070f 0000000000000011 ffff8808271eb000 ffff880803363ac8
> [  821.039967]  ffffffffb124e8ed 0000000000000000 ffff880803363bbc 0000000000000013
> [  821.041455] Call Trace:
> [  821.042038] dump_stack (lib/dump_stack.c:52)
> [  821.043005] lockdep_rcu_suspicious (kernel/locking/lockdep.c:4265)
> [  821.044169] sched_cpu_inactive (kernel/sched/core.c:2008 kernel/sched/core.c:5271)
> [  821.050486] notifier_call_chain (kernel/notifier.c:93)
> [  821.051594] __raw_notifier_call_chain (kernel/notifier.c:395)
> [  821.052766] _cpu_down (include/linux/notifier.h:179 kernel/cpu.c:219 kernel/cpu.c:356)
> [  821.053809] ? cpu_down (kernel/cpu.c:426)
> [  821.054770] cpu_down (kernel/cpu.c:431)
> [  821.062497] cpu_subsys_offline (drivers/base/cpu.c:69)
> [  821.063500] device_offline (drivers/base/core.c:1428)
> [  821.064428] ? cpu_device_release (drivers/base/cpu.c:67)
> [  821.065429] online_store (drivers/base/core.c:451 (discriminator 2))
> [  821.066390] dev_attr_store (drivers/base/core.c:138)
> [  821.067328] ? dev_driver_string (drivers/base/core.c:130)
> [  821.073698] sysfs_kf_write (fs/sysfs/file.c:116)
> [  821.074496] ? sysfs_file_ops (fs/sysfs/file.c:108)
> [  821.075312] kernfs_fop_write (fs/kernfs/file.c:308)
> [  821.076135] ? do_readv_writev (include/linux/fs.h:2270 fs/read_write.c:832)
> [  821.076999] do_loop_readv_writev (fs/read_write.c:710)
> [  821.078066] ? kernfs_vma_page_mkwrite (fs/kernfs/file.c:267)
> [  821.079252] do_readv_writev (fs/read_write.c:842)
> [  821.080495] ? kernfs_vma_page_mkwrite (fs/kernfs/file.c:267)
> [  821.081644] ? mutex_lock_nested (./arch/x86/include/asm/preempt.h:98 kernel/locking/mutex.c:599 kernel/locking/mutex.c:616)
> [  821.086535] ? __fdget_pos (fs/file.c:718)
> [  821.087447] ? __fdget_pos (fs/file.c:718)
> [  821.088363] ? rcu_read_lock_held (kernel/rcu/update.c:169)
> [  821.089425] vfs_writev (fs/read_write.c:881)
> [  821.090486] SyS_writev (fs/read_write.c:913 fs/read_write.c:905)
> [  821.091382] tracesys_phase2 (arch/x86/kernel/entry_64.S:529)
> 
> Signed-off-by: Sasha Levin <sasha.levin@oracle.com>

Thanks for your report. It looks like your fix is not enough, because
we check for rcu_read_lock_sched_held() in dl_bw_of(). It still warns
even if rcu_read_lock() is held.

I used rcu_read_lock_sched_held() because we free root_domain using
call_rcu_sched(). So, it's necessary to held rcu_read_lock_sched(),
and my initial commit has this problem too.

It looks like we should fix it in a way like this:

[PATCH]sched: Use dl_bw_of() under rcu_read_lock_sched()

rq->rd is freed using call_rcu_sched(), and it's accessed with preemption
disabled in the most cases.

So in other places we should use rcu_read_lock_sched() to access it to fit
the scheme:

rcu_read_lock_sched() or preempt_disable() <==> call_rcu_sched().

Signed-off-by: Kirill Tkhai <ktkhai@parallels.com
Fixes 66339c31bc39 "sched: Use dl_bw_of() under RCU read lock"
Reported-by: Sasha Levin <sasha.levin@oracle.com>
---
 kernel/sched/core.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 25e4513..3a0a62d 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5248,6 +5248,9 @@ static int sched_cpu_inactive(struct notifier_block *nfb,
 {
 	unsigned long flags;
 	long cpu = (long)hcpu;
+	int ret;
+
+	rcu_read_lock_sched();
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_DOWN_PREPARE:
@@ -5264,13 +5267,19 @@ static int sched_cpu_inactive(struct notifier_block *nfb,
 			overflow = __dl_overflow(dl_b, cpus, 0, 0);
 			raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 
+			ret = notifier_from_errno(-EBUSY);
 			if (overflow)
-				return notifier_from_errno(-EBUSY);
+				goto done;
 		}
-		return NOTIFY_OK;
+		ret = NOTIFY_OK;
+		goto done;
 	}
 
-	return NOTIFY_DONE;
+	ret = NOTIFY_DONE;
+
+done:
+	rcu_read_unlock_sched();
+	return ret;
 }
 
 static int __init migration_init(void)
@@ -7634,7 +7643,7 @@ static int sched_dl_global_constraints(void)
 	int cpu, ret = 0;
 	unsigned long flags;
 
-	rcu_read_lock();
+	rcu_read_lock_sched();
 
 	/*
 	 * Here we want to check the bandwidth not being set to some
@@ -7657,7 +7666,7 @@ static int sched_dl_global_constraints(void)
 			break;
 	}
 
-	rcu_read_unlock();
+	rcu_read_unlock_sched();
 
 	return ret;
 }
@@ -7674,7 +7683,7 @@ static void sched_dl_do_global(void)
 	if (global_rt_runtime() != RUNTIME_INF)
 		new_bw = to_ratio(global_rt_period(), global_rt_runtime());
 
-	rcu_read_lock();
+	rcu_read_lock_sched();
 	/*
 	 * FIXME: As above...
 	 */
@@ -7685,7 +7694,7 @@ static void sched_dl_do_global(void)
 		dl_b->bw = new_bw;
 		raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 	}
-	rcu_read_unlock();
+	rcu_read_unlock_sched();
 }
 
 static int sched_rt_global_validate(void)



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

* Re: [PATCH] sched: Use RCU read lock on all calls to dl_bw_of()
  2014-09-29 16:43 ` Kirill Tkhai
@ 2014-09-29 16:54   ` Peter Zijlstra
  2014-09-29 17:00     ` Peter Zijlstra
  0 siblings, 1 reply; 7+ messages in thread
From: Peter Zijlstra @ 2014-09-29 16:54 UTC (permalink / raw)
  To: Kirill Tkhai; +Cc: Sasha Levin, mingo, torvalds, paulmck, linux-kernel

On Mon, Sep 29, 2014 at 08:43:47PM +0400, Kirill Tkhai wrote:
> Thanks for your report. It looks like your fix is not enough, because
> we check for rcu_read_lock_sched_held() in dl_bw_of(). It still warns
> even if rcu_read_lock() is held.
> 
> I used rcu_read_lock_sched_held() because we free root_domain using
> call_rcu_sched(). So, it's necessary to held rcu_read_lock_sched(),
> and my initial commit has this problem too.
> 
> It looks like we should fix it in a way like this:
> 
> [PATCH]sched: Use dl_bw_of() under rcu_read_lock_sched()
> 
> rq->rd is freed using call_rcu_sched(), and it's accessed with preemption
> disabled in the most cases.
> 
> So in other places we should use rcu_read_lock_sched() to access it to fit
> the scheme:
> 
> rcu_read_lock_sched() or preempt_disable() <==> call_rcu_sched().

Hmm, sad that. I cannot remember why that is rcu_sched, I suspect
because we rely on it someplace but I cannot remember where.

We could of course do a double take on that and use call_rcu after
call_rcu_sched(), such that either or both are sufficient.

I would very much prefer not to add extra preempt_disable()s if
possible.

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

* Re: [PATCH] sched: Use RCU read lock on all calls to dl_bw_of()
  2014-09-29 16:54   ` Peter Zijlstra
@ 2014-09-29 17:00     ` Peter Zijlstra
  2014-09-30  8:23       ` Kirill Tkhai
  0 siblings, 1 reply; 7+ messages in thread
From: Peter Zijlstra @ 2014-09-29 17:00 UTC (permalink / raw)
  To: Kirill Tkhai; +Cc: Sasha Levin, mingo, torvalds, paulmck, linux-kernel

On Mon, Sep 29, 2014 at 06:54:18PM +0200, Peter Zijlstra wrote:
> On Mon, Sep 29, 2014 at 08:43:47PM +0400, Kirill Tkhai wrote:
> > Thanks for your report. It looks like your fix is not enough, because
> > we check for rcu_read_lock_sched_held() in dl_bw_of(). It still warns
> > even if rcu_read_lock() is held.
> > 
> > I used rcu_read_lock_sched_held() because we free root_domain using
> > call_rcu_sched(). So, it's necessary to held rcu_read_lock_sched(),
> > and my initial commit has this problem too.
> > 
> > It looks like we should fix it in a way like this:
> > 
> > [PATCH]sched: Use dl_bw_of() under rcu_read_lock_sched()
> > 
> > rq->rd is freed using call_rcu_sched(), and it's accessed with preemption
> > disabled in the most cases.
> > 
> > So in other places we should use rcu_read_lock_sched() to access it to fit
> > the scheme:
> > 
> > rcu_read_lock_sched() or preempt_disable() <==> call_rcu_sched().
> 
> Hmm, sad that. I cannot remember why that is rcu_sched, I suspect
> because we rely on it someplace but I cannot remember where.
> 
> We could of course do a double take on that and use call_rcu after
> call_rcu_sched(), such that either or both are sufficient.
> 
> I would very much prefer not to add extra preempt_disable()s if
> possible.

Ah wait, if we simply move that preempt_disable() inside the
for_each_cpu() loop there's no harm done. Having them outside is painful
though.

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

* Re: [PATCH] sched: Use RCU read lock on all calls to dl_bw_of()
  2014-09-29 17:00     ` Peter Zijlstra
@ 2014-09-30  8:23       ` Kirill Tkhai
  2014-10-02  9:24         ` Peter Zijlstra
  2014-10-03  5:28         ` [tip:sched/core] sched/dl: Use dl_bw_of() under rcu_read_lock_sched() tip-bot for Kirill Tkhai
  0 siblings, 2 replies; 7+ messages in thread
From: Kirill Tkhai @ 2014-09-30  8:23 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: Sasha Levin, mingo, torvalds, paulmck, linux-kernel

В Пн, 29/09/2014 в 19:00 +0200, Peter Zijlstra пишет:
> On Mon, Sep 29, 2014 at 06:54:18PM +0200, Peter Zijlstra wrote:
> > On Mon, Sep 29, 2014 at 08:43:47PM +0400, Kirill Tkhai wrote:
> > > Thanks for your report. It looks like your fix is not enough, because
> > > we check for rcu_read_lock_sched_held() in dl_bw_of(). It still warns
> > > even if rcu_read_lock() is held.
> > > 
> > > I used rcu_read_lock_sched_held() because we free root_domain using
> > > call_rcu_sched(). So, it's necessary to held rcu_read_lock_sched(),
> > > and my initial commit has this problem too.
> > > 
> > > It looks like we should fix it in a way like this:
> > > 
> > > [PATCH]sched: Use dl_bw_of() under rcu_read_lock_sched()
> > > 
> > > rq->rd is freed using call_rcu_sched(), and it's accessed with preemption
> > > disabled in the most cases.
> > > 
> > > So in other places we should use rcu_read_lock_sched() to access it to fit
> > > the scheme:
> > > 
> > > rcu_read_lock_sched() or preempt_disable() <==> call_rcu_sched().
> > 
> > Hmm, sad that. I cannot remember why that is rcu_sched, I suspect
> > because we rely on it someplace but I cannot remember where.
> > 
> > We could of course do a double take on that and use call_rcu after
> > call_rcu_sched(), such that either or both are sufficient.
> > 
> > I would very much prefer not to add extra preempt_disable()s if
> > possible.
> 
> Ah wait, if we simply move that preempt_disable() inside the
> for_each_cpu() loop there's no harm done. Having them outside is painful
> though.

[PATCH]sched: Use dl_bw_of() under preempt_disable()

rq->rd is freed using call_rcu_sched(), so rcu_read_lock() to access it
is not enough. We should use either rcu_read_lock_sched() or preempt_disable().

We choose preempt_disable()/preempt_enable() like in other places
where rq->rd is used.

Signed-off-by: Kirill Tkhai <ktkhai@parallels.com
Fixes 66339c31bc39 "sched: Use dl_bw_of() under RCU read lock"
Reported-by: Sasha Levin <sasha.levin@oracle.com>
Suggested-by: Peter Zijlstra <peterz@infradead.org>
---
 kernel/sched/core.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 25e4513..e1a4d76 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5248,6 +5248,7 @@ static int sched_cpu_inactive(struct notifier_block *nfb,
 {
 	unsigned long flags;
 	long cpu = (long)hcpu;
+	struct dl_bw *dl_b;
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_DOWN_PREPARE:
@@ -5255,15 +5256,19 @@ static int sched_cpu_inactive(struct notifier_block *nfb,
 
 		/* explicitly allow suspend */
 		if (!(action & CPU_TASKS_FROZEN)) {
-			struct dl_bw *dl_b = dl_bw_of(cpu);
 			bool overflow;
 			int cpus;
 
+			preempt_disable();
+			dl_b = dl_bw_of(cpu);
+
 			raw_spin_lock_irqsave(&dl_b->lock, flags);
 			cpus = dl_bw_cpus(cpu);
 			overflow = __dl_overflow(dl_b, cpus, 0, 0);
 			raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 
+			preempt_enable();
+
 			if (overflow)
 				return notifier_from_errno(-EBUSY);
 		}
@@ -7631,11 +7636,10 @@ static int sched_dl_global_constraints(void)
 	u64 runtime = global_rt_runtime();
 	u64 period = global_rt_period();
 	u64 new_bw = to_ratio(period, runtime);
+	struct dl_bw *dl_b;
 	int cpu, ret = 0;
 	unsigned long flags;
 
-	rcu_read_lock();
-
 	/*
 	 * Here we want to check the bandwidth not being set to some
 	 * value smaller than the currently allocated bandwidth in
@@ -7646,25 +7650,27 @@ static int sched_dl_global_constraints(void)
 	 * solutions is welcome!
 	 */
 	for_each_possible_cpu(cpu) {
-		struct dl_bw *dl_b = dl_bw_of(cpu);
+		preempt_disable();
+		dl_b = dl_bw_of(cpu);
 
 		raw_spin_lock_irqsave(&dl_b->lock, flags);
 		if (new_bw < dl_b->total_bw)
 			ret = -EBUSY;
 		raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 
+		preempt_enable();
+
 		if (ret)
 			break;
 	}
 
-	rcu_read_unlock();
-
 	return ret;
 }
 
 static void sched_dl_do_global(void)
 {
 	u64 new_bw = -1;
+	struct dl_bw *dl_b;
 	int cpu;
 	unsigned long flags;
 
@@ -7674,18 +7680,19 @@ static void sched_dl_do_global(void)
 	if (global_rt_runtime() != RUNTIME_INF)
 		new_bw = to_ratio(global_rt_period(), global_rt_runtime());
 
-	rcu_read_lock();
 	/*
 	 * FIXME: As above...
 	 */
 	for_each_possible_cpu(cpu) {
-		struct dl_bw *dl_b = dl_bw_of(cpu);
+		preempt_disable();
+		dl_b = dl_bw_of(cpu);
 
 		raw_spin_lock_irqsave(&dl_b->lock, flags);
 		dl_b->bw = new_bw;
 		raw_spin_unlock_irqrestore(&dl_b->lock, flags);
+
+		preempt_enable();
 	}
-	rcu_read_unlock();
 }
 
 static int sched_rt_global_validate(void)



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

* Re: [PATCH] sched: Use RCU read lock on all calls to dl_bw_of()
  2014-09-30  8:23       ` Kirill Tkhai
@ 2014-10-02  9:24         ` Peter Zijlstra
  2014-10-03  5:28         ` [tip:sched/core] sched/dl: Use dl_bw_of() under rcu_read_lock_sched() tip-bot for Kirill Tkhai
  1 sibling, 0 replies; 7+ messages in thread
From: Peter Zijlstra @ 2014-10-02  9:24 UTC (permalink / raw)
  To: Kirill Tkhai; +Cc: Sasha Levin, mingo, torvalds, paulmck, linux-kernel

On Tue, Sep 30, 2014 at 12:23:37PM +0400, Kirill Tkhai wrote:
> [PATCH]sched: Use dl_bw_of() under preempt_disable()
> 
> rq->rd is freed using call_rcu_sched(), so rcu_read_lock() to access it
> is not enough. We should use either rcu_read_lock_sched() or preempt_disable().
> 
> We choose preempt_disable()/preempt_enable() like in other places
> where rq->rd is used.

I changed it to rcu_read_lock_sched(), but no biggie, thanks!

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

* [tip:sched/core] sched/dl: Use dl_bw_of() under rcu_read_lock_sched()
  2014-09-30  8:23       ` Kirill Tkhai
  2014-10-02  9:24         ` Peter Zijlstra
@ 2014-10-03  5:28         ` tip-bot for Kirill Tkhai
  1 sibling, 0 replies; 7+ messages in thread
From: tip-bot for Kirill Tkhai @ 2014-10-03  5:28 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, sasha.levin, ktkhai, hpa, mingo, peterz, tglx

Commit-ID:  f10e00f4bf360c36edbe6bf18a6c75b171cbe012
Gitweb:     http://git.kernel.org/tip/f10e00f4bf360c36edbe6bf18a6c75b171cbe012
Author:     Kirill Tkhai <ktkhai@parallels.com>
AuthorDate: Tue, 30 Sep 2014 12:23:37 +0400
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Fri, 3 Oct 2014 05:46:58 +0200

sched/dl: Use dl_bw_of() under rcu_read_lock_sched()

rq->rd is freed using call_rcu_sched(), so rcu_read_lock() to access it
is not enough. We should use either rcu_read_lock_sched() or preempt_disable().

Reported-by: Sasha Levin <sasha.levin@oracle.com>
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Kirill Tkhai <ktkhai@parallels.com
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Fixes: 66339c31bc39 "sched: Use dl_bw_of() under RCU read lock"
Link: http://lkml.kernel.org/r/1412065417.20287.24.camel@tkhai
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/sched/core.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index b5349fe..c84bdc0 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5264,6 +5264,7 @@ static int sched_cpu_inactive(struct notifier_block *nfb,
 {
 	unsigned long flags;
 	long cpu = (long)hcpu;
+	struct dl_bw *dl_b;
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_DOWN_PREPARE:
@@ -5271,15 +5272,19 @@ static int sched_cpu_inactive(struct notifier_block *nfb,
 
 		/* explicitly allow suspend */
 		if (!(action & CPU_TASKS_FROZEN)) {
-			struct dl_bw *dl_b = dl_bw_of(cpu);
 			bool overflow;
 			int cpus;
 
+			rcu_read_lock_sched();
+			dl_b = dl_bw_of(cpu);
+
 			raw_spin_lock_irqsave(&dl_b->lock, flags);
 			cpus = dl_bw_cpus(cpu);
 			overflow = __dl_overflow(dl_b, cpus, 0, 0);
 			raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 
+			rcu_read_unlock_sched();
+
 			if (overflow)
 				return notifier_from_errno(-EBUSY);
 		}
@@ -7647,11 +7652,10 @@ static int sched_dl_global_constraints(void)
 	u64 runtime = global_rt_runtime();
 	u64 period = global_rt_period();
 	u64 new_bw = to_ratio(period, runtime);
+	struct dl_bw *dl_b;
 	int cpu, ret = 0;
 	unsigned long flags;
 
-	rcu_read_lock();
-
 	/*
 	 * Here we want to check the bandwidth not being set to some
 	 * value smaller than the currently allocated bandwidth in
@@ -7662,25 +7666,27 @@ static int sched_dl_global_constraints(void)
 	 * solutions is welcome!
 	 */
 	for_each_possible_cpu(cpu) {
-		struct dl_bw *dl_b = dl_bw_of(cpu);
+		rcu_read_lock_sched();
+		dl_b = dl_bw_of(cpu);
 
 		raw_spin_lock_irqsave(&dl_b->lock, flags);
 		if (new_bw < dl_b->total_bw)
 			ret = -EBUSY;
 		raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 
+		rcu_read_unlock_sched();
+
 		if (ret)
 			break;
 	}
 
-	rcu_read_unlock();
-
 	return ret;
 }
 
 static void sched_dl_do_global(void)
 {
 	u64 new_bw = -1;
+	struct dl_bw *dl_b;
 	int cpu;
 	unsigned long flags;
 
@@ -7690,18 +7696,19 @@ static void sched_dl_do_global(void)
 	if (global_rt_runtime() != RUNTIME_INF)
 		new_bw = to_ratio(global_rt_period(), global_rt_runtime());
 
-	rcu_read_lock();
 	/*
 	 * FIXME: As above...
 	 */
 	for_each_possible_cpu(cpu) {
-		struct dl_bw *dl_b = dl_bw_of(cpu);
+		rcu_read_lock_sched();
+		dl_b = dl_bw_of(cpu);
 
 		raw_spin_lock_irqsave(&dl_b->lock, flags);
 		dl_b->bw = new_bw;
 		raw_spin_unlock_irqrestore(&dl_b->lock, flags);
+
+		rcu_read_unlock_sched();
 	}
-	rcu_read_unlock();
 }
 
 static int sched_rt_global_validate(void)

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

end of thread, other threads:[~2014-10-03  5:29 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-29 15:19 [PATCH] sched: Use RCU read lock on all calls to dl_bw_of() Sasha Levin
2014-09-29 16:43 ` Kirill Tkhai
2014-09-29 16:54   ` Peter Zijlstra
2014-09-29 17:00     ` Peter Zijlstra
2014-09-30  8:23       ` Kirill Tkhai
2014-10-02  9:24         ` Peter Zijlstra
2014-10-03  5:28         ` [tip:sched/core] sched/dl: Use dl_bw_of() under rcu_read_lock_sched() tip-bot for Kirill Tkhai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.