On Mon, 18 Jan 2016 09:58:12 +0900 Byungchul Park <byungchul.p...@lge.com> wrote:
> It causes an infinite recursive cycle when using CONFIG_DEBUG_SPINLOCK, > in the spin_dump(). Backtrace prints printk() -> console_trylock() -> > do_raw_spin_lock() -> spint_bug() -> spin_dump() -> printk()... > infinitely. > > If the spin_bug() is called from a function like printk() which is > trying to obtain the console lock, we should prevent the debug spinlock > code from calling printk() again in that context. > lol. Excellent. > --- a/kernel/locking/spinlock_debug.c > +++ b/kernel/locking/spinlock_debug.c > @@ -67,11 +67,22 @@ static void spin_dump(raw_spinlock_t *lock, const char > *msg) > dump_stack(); > } > > +extern int is_console_lock(raw_spinlock_t *lock); > + > static void spin_bug(raw_spinlock_t *lock, const char *msg) > { > if (!debug_locks_off()) > return; > > + /* > + * If this function is called from a function like printk() > + * which is trying to obtain the console lock, then we should > + * not call printk() any more. Or it will cause an infinite > + * recursive cycle! > + */ > + if (unlikely(is_console_lock(lock))) > + return; > + > spin_dump(lock, msg); > } > > diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c > index 2ce8826..50ea552 100644 > --- a/kernel/printk/printk.c > +++ b/kernel/printk/printk.c > @@ -119,6 +119,11 @@ static int __down_trylock_console_sem(unsigned long ip) > up(&console_sem);\ > } while (0) > > +int is_console_lock(raw_spinlock_t *lock) > +{ > + return &console_sem.lock == lock; > +} > + > /* > * This is used for debugging the mess that is the VT code by > * keeping track if we have the console semaphore held. It's I can't immediately think of anything better than this. It's a hack, but it's a small and quite clear hack.