softirq/preempt: add missing current->preempt_disable_ip update
PATCH 1/1 softirq/preempt: add missing current->preempt_disable_ip update
While debugging some "sleeping function called from invalid context" bug I realized that the debug message "Preemption disabled at:" pointed to an incorrect function.
In particular if the function/action that disabled preemption was spin_lock_bh() then current->preempt_disable_ip won't be updated.
The reason for this is that __local_bh_disable_ip() will increase preempt_count manually instead of calling preempt_count_add(), which would handle the update correctly.
It look like the manual handling was done to work around some lockdep issue.
So add the missing update of current->preempt_disable_ip to __local_bh_disable_ip() as well.
--- kernel/softirq.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
kernel/softirq.c +7 -2
@@ -114,8 +114,13 @@ void __local_bh_disable_ip(unsigned long ip, unsigned int cnt)trace_softirqs_off (ip);raw_local_irq_restore (flags); -if (preempt_count () == cnt) - trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); +if (preempt_count () == cnt) { +unsigned long ip =get_parent_ip (CALLER_ADDR1 ); +#ifdef CONFIG_DEBUG_PREEMPT + current->preempt_disable_ip = ip; +#endif +trace_preempt_off (CALLER_ADDR0 , ip); + } }EXPORT_SYMBOL (__local_bh_disable_ip);#endif /* CONFIG_TRACE_IRQFLAGS */
Signature · 1 line
1.8.5.5
Quoted 29 lines · Heiko Carstens
While debugging some "sleeping function called from invalid context" bug I realized that the debug message "Preemption disabled at:" pointed to an incorrect function.
In particular if the function/action that disabled preemption wasspin_lock_bh()thencurrent->preempt_disable_ipwon't be updated.The reason for this is that
__local_bh_disable_ip()will increasepreempt_countmanually instead of callingpreempt_count_add(), which would handle the update correctly.
It look like the manual handling was done to work around some lockdep issue.So add the missing update of
current->preempt_disable_ipto__local_bh_disable_ip()as well.Signed-off-by Heiko Carstens <[email protected]>--- kernel/softirq.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)kernel/softirq.c +0
-2@@ -114,8 +114,13 @@ void __local_bh_disable_ip(unsigned long ip, unsigned int cnt)trace_softirqs_off (ip);raw_local_irq_restore (flags); -if (preempt_count () == cnt) -trace_preempt_off (CALLER_ADDR0 ,get_parent_ip (CALLER_ADDR1 ));
kernel/softirq.c void __local_bh_disable_ip(unsigned long ip, unsigned int cnt) · line 126
Quoted 10 lines
kernel/softirq.c +7
-0+if (preempt_count () == cnt) { +unsigned long ip =get_parent_ip (CALLER_ADDR1 ); +#ifdef CONFIG_DEBUG_PREEMPT + current->preempt_disable_ip = ip; +#endif +trace_preempt_off (CALLER_ADDR0 , ip); + } }EXPORT_SYMBOL (__local_bh_disable_ip);#endif /* CONFIG_TRACE_IRQFLAGS */
*ping*