From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Date: 2016-01-13 15:23:58
A softirq on -RT can be preempted. That means one task is in
__dev_queue_xmit(), gets preempted and another task may enter
__dev_queue_xmit() aw well. netperf together with a bridge device
will then trigger the `recursion alert` because each task increments
the xmit_recursion variable which is per-CPU.
A virtual device like br0 is required to trigger this warning.
This patch moves the counter to per task instead per-CPU so it counts
the recursion properly on -RT.
Cc: stable-rt@vger.kernel.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
include/linux/netdevice.h | 9 +++++++++
include/linux/sched.h | 3 +++
net/core/dev.c | 41 ++++++++++++++++++++++++++++++++++++++---
3 files changed, 50 insertions(+), 3 deletions(-)
@@ -1851,6 +1851,9 @@ struct task_struct {#ifdef CONFIG_DEBUG_ATOMIC_SLEEPunsignedlongtask_state_change;#endif+#ifdef CONFIG_PREEMPT_RT_FULL+intxmit_recursion;+#endifintpagefault_disabled;/* CPU-specific state of this task */structthread_structthread;---a/net/core/dev.c+++b/net/core/dev.c
From: Hannes Frederic Sowa <hidden> Date: 2016-01-14 22:02:16
On 14.01.2016 15:50, Sebastian Andrzej Siewior wrote:
* Thomas Gleixner | 2016-01-13 18:31:46 [+0100]:
quoted
On Wed, 13 Jan 2016, Sebastian Andrzej Siewior wrote:
quoted
+#ifdef CONFIG_PREEMPT_RT_FULL
+static inline int dev_recursion_level(void)
+{
+ return atomic_read(¤t->xmit_recursion);
Why would you need an atomic here. current does hardly race against itself.
right.
We are just adding a second recursion limit solely to openvswitch which
has the same problem:
https://patchwork.ozlabs.org/patch/566769/
This time also we depend on rcu_read_lock marking the section being
nonpreemptible. Nice would be a more generic solution here which doesn't
need to always add something to *current.
Thanks,
Hannes
From: Eric Dumazet <hidden> Date: 2016-01-14 22:20:09
On Thu, 2016-01-14 at 23:02 +0100, Hannes Frederic Sowa wrote:
We are just adding a second recursion limit solely to openvswitch which
has the same problem:
https://patchwork.ozlabs.org/patch/566769/
This time also we depend on rcu_read_lock marking the section being
nonpreemptible. Nice would be a more generic solution here which doesn't
need to always add something to *current.
Note that rcu_read_lock() does not imply that preemption is disabled.
From: Hannes Frederic Sowa <hidden> Date: 2016-01-14 23:00:44
On 14.01.2016 23:20, Eric Dumazet wrote:
On Thu, 2016-01-14 at 23:02 +0100, Hannes Frederic Sowa wrote:
quoted
We are just adding a second recursion limit solely to openvswitch which
has the same problem:
https://patchwork.ozlabs.org/patch/566769/
This time also we depend on rcu_read_lock marking the section being
nonpreemptible. Nice would be a more generic solution here which doesn't
need to always add something to *current.
Note that rcu_read_lock() does not imply that preemption is disabled.
Exactly, it is conditional on CONFIG_PREEMPT_CPU/CONFIG_PREMPT_COUNT but
haven't thought about exactly that in this moment.
I will resend this patch with better protection.
Thanks Eric!
From: Thomas Gleixner <hidden> Date: 2016-01-15 08:22:28
On Fri, 15 Jan 2016, Hannes Frederic Sowa wrote:
On 14.01.2016 23:20, Eric Dumazet wrote:
quoted
On Thu, 2016-01-14 at 23:02 +0100, Hannes Frederic Sowa wrote:
quoted
We are just adding a second recursion limit solely to openvswitch which
has the same problem:
https://patchwork.ozlabs.org/patch/566769/
This time also we depend on rcu_read_lock marking the section being
nonpreemptible. Nice would be a more generic solution here which doesn't
need to always add something to *current.
Note that rcu_read_lock() does not imply that preemption is disabled.
Exactly, it is conditional on CONFIG_PREEMPT_CPU/CONFIG_PREMPT_COUNT but
haven't thought about exactly that in this moment.
Wrong. CONFIG_PREEMPT_RCU makes RCU preemptible.
If that is not set then it fiddles with preempt_count when
CONFIG_PREEMPT_COUNT=y. If CONFIG_PREEMPT_COUNT=n then you have a non
preemptible system anyway.
So you cannot assume that rcu_read_lock() disables preemption.
Thanks,
tglx
From: Hannes Frederic Sowa <hidden> Date: 2016-01-15 09:34:39
On 15.01.2016 09:21, Thomas Gleixner wrote:
On Fri, 15 Jan 2016, Hannes Frederic Sowa wrote:
quoted
On 14.01.2016 23:20, Eric Dumazet wrote:
quoted
On Thu, 2016-01-14 at 23:02 +0100, Hannes Frederic Sowa wrote:
quoted
We are just adding a second recursion limit solely to openvswitch which
has the same problem:
https://patchwork.ozlabs.org/patch/566769/
This time also we depend on rcu_read_lock marking the section being
nonpreemptible. Nice would be a more generic solution here which doesn't
need to always add something to *current.
Note that rcu_read_lock() does not imply that preemption is disabled.
Exactly, it is conditional on CONFIG_PREEMPT_CPU/CONFIG_PREMPT_COUNT but
haven't thought about exactly that in this moment.
Wrong. CONFIG_PREEMPT_RCU makes RCU preemptible.
If that is not set then it fiddles with preempt_count when
CONFIG_PREEMPT_COUNT=y. If CONFIG_PREEMPT_COUNT=n then you have a non
preemptible system anyway.
So you cannot assume that rcu_read_lock() disables preemption.
Sorry for maybe writing it misleading but that is exactly what I wanted
to say here. Yes, I agree, I didn't really check because of _bh and
rcu_read_lock. This was a mistake. ;)
I already send out an updated patch with added preemption guards.
Thanks,
Hannes