sched/debug: Make the "Preemption disabled at ..." message more useful
This message is currently really useless since it always prints a value that comes from the printk() we just did, e.g.: BUG: sleeping function called from invalid context at mm/slab.h:388 in_atomic(): 0, irqs_disabled(): 0, pid: 31996, name: trinity-c1 Preemption disabled at:[<ffffffff8119db33>] down_trylock+0x13/0x80 BUG: sleeping function called from invalid context at include/linux/freezer.h:56 in_atomic(): 0, irqs_disabled(): 0, pid: 31996, name: trinity-c1 Preemption disabled at:[<ffffffff811aaa37>] console_unlock+0x2f7/0x930 Here, both down_trylock() and console_unlock() is somewhere in the printk() path. We should save the value before calling printk() and use the saved value instead. That immediately reveals the offending callsite: BUG: sleeping function called from invalid context at mm/slab.h:388 in_atomic(): 0, irqs_disabled(): 0, pid: 14971, name: trinity-c2 Preemption disabled at:[<ffffffff819bcd46>] rhashtable_walk_start+0x46/0x150 Bug report: http://marc.info/?l=linux-netdev&m=146925979821849&w=2 Change-Id: I5b08294385a2ac625dbf28d1f18ffd164aedabe0 Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rusty Russel <rusty@rustcorp.com.au> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org> [mkhaja@codeaurora.org: Fix trivial merge conflict] Git-commit: d1c6d149cf04d6c7c3c3ebf4b66c82500cbcf6e1 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Mohammed Khajapasha <mkhaja@codeaurora.org>
This commit is contained in:
parent
6f55033ecf
commit
4748cf2bde
2 changed files with 22 additions and 8 deletions
|
@ -3246,6 +3246,15 @@ static inline void cond_resched_rcu(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned long get_preempt_disable_ip(struct task_struct *p)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_PREEMPT
|
||||
return p->preempt_disable_ip;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Does a critical section need to be broken due to another
|
||||
* task waiting?: (technically does not depend on CONFIG_PREEMPT,
|
||||
|
|
|
@ -3362,6 +3362,9 @@ NOKPROBE_SYMBOL(preempt_count_sub);
|
|||
*/
|
||||
static noinline void __schedule_bug(struct task_struct *prev)
|
||||
{
|
||||
/* Save this before calling printk(), since that will clobber it */
|
||||
unsigned long preempt_disable_ip = get_preempt_disable_ip(current);
|
||||
|
||||
if (oops_in_progress)
|
||||
return;
|
||||
|
||||
|
@ -3372,13 +3375,12 @@ static noinline void __schedule_bug(struct task_struct *prev)
|
|||
print_modules();
|
||||
if (irqs_disabled())
|
||||
print_irqtrace_events(prev);
|
||||
#ifdef CONFIG_DEBUG_PREEMPT
|
||||
if (in_atomic_preempt_off()) {
|
||||
if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)
|
||||
&& in_atomic_preempt_off()) {
|
||||
pr_err("Preemption disabled at:");
|
||||
print_ip_sym(current->preempt_disable_ip);
|
||||
print_ip_sym(preempt_disable_ip);
|
||||
pr_cont("\n");
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_PANIC_ON_SCHED_BUG
|
||||
BUG();
|
||||
#endif
|
||||
|
@ -8511,6 +8513,7 @@ EXPORT_SYMBOL(__might_sleep);
|
|||
void ___might_sleep(const char *file, int line, int preempt_offset)
|
||||
{
|
||||
static unsigned long prev_jiffy; /* ratelimiting */
|
||||
unsigned long preempt_disable_ip;
|
||||
|
||||
rcu_sleep_check(); /* WARN_ON_ONCE() by default, no rate limit reqd. */
|
||||
if ((preempt_count_equals(preempt_offset) && !irqs_disabled() &&
|
||||
|
@ -8523,6 +8526,9 @@ void ___might_sleep(const char *file, int line, int preempt_offset)
|
|||
return;
|
||||
prev_jiffy = jiffies;
|
||||
|
||||
/* Save this before calling printk(), since that will clobber it */
|
||||
preempt_disable_ip = get_preempt_disable_ip(current);
|
||||
|
||||
printk(KERN_ERR
|
||||
"BUG: sleeping function called from invalid context at %s:%d\n",
|
||||
file, line);
|
||||
|
@ -8537,13 +8543,12 @@ void ___might_sleep(const char *file, int line, int preempt_offset)
|
|||
debug_show_held_locks(current);
|
||||
if (irqs_disabled())
|
||||
print_irqtrace_events(current);
|
||||
#ifdef CONFIG_DEBUG_PREEMPT
|
||||
if (!preempt_count_equals(preempt_offset)) {
|
||||
if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)
|
||||
&& !preempt_count_equals(preempt_offset)) {
|
||||
pr_err("Preemption disabled at:");
|
||||
print_ip_sym(current->preempt_disable_ip);
|
||||
print_ip_sym(preempt_disable_ip);
|
||||
pr_cont("\n");
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_PANIC_ON_SCHED_BUG
|
||||
BUG();
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue