From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757468AbcAaMcs (ORCPT ); Sun, 31 Jan 2016 07:32:48 -0500 Received: from mail-pf0-f195.google.com ([209.85.192.195]:35304 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757278AbcAaMcp (ORCPT ); Sun, 31 Jan 2016 07:32:45 -0500 From: Sergey Senozhatsky X-Google-Original-From: Sergey Senozhatsky To: Peter Hurley Cc: Byungchul Park , akpm@linux-foundation.org, mingo@kernel.org, linux-kernel@vger.kernel.org, akinobu.mita@gmail.com, jack@suse.cz, torvalds@linux-foundation.org, Sergey Senozhatsky , Sergey Senozhatsky Subject: [PATCH 3/3] spinlock_debug: panic on recursive lock spin_dump() Date: Sun, 31 Jan 2016 21:33:43 +0900 Message-Id: <1454243623-15109-3-git-send-email-sergey.senozhatsky@gmail.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1454243623-15109-1-git-send-email-sergey.senozhatsky@gmail.com> References: <20160131123041.GA1306@swordfish> <1454243623-15109-1-git-send-email-sergey.senozhatsky@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org spin_dump() calls printk() which can attempt to reacquire the 'buggy' lock (one of printk's lock, or console device driver lock, etc.) and thus spin_dump() will recursive into itself. Steal most significant bit of spin_lock->owner_cpu to keep there a mark that spin_dump() is in progress for that particular spin_lock. spin_dump() will now set SPIN_DUMP_IN_PROGRESS bit at the beginning of spin_dump() and clear it at the end, so it's possible to detect recursive spin_dump() calls by checking if lock's owner_cpu already has SPIN_DUMP_IN_PROGRESS bit already set. panic() the system when spin_dump() recursion occurs. Not-Yet-Signed-off-by: Sergey Senozhatsky --- kernel/locking/spinlock_debug.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/kernel/locking/spinlock_debug.c b/kernel/locking/spinlock_debug.c index 0374a59..1a4a864 100644 --- a/kernel/locking/spinlock_debug.c +++ b/kernel/locking/spinlock_debug.c @@ -13,6 +13,9 @@ #include #include +#define SPIN_DUMP_IN_PROGRESS (1 << 31) +#define DEFAULT_OWNER_CPU (INT_MAX >> 1) + void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name, struct lock_class_key *key) { @@ -26,7 +29,7 @@ void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name, lock->raw_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; lock->magic = SPINLOCK_MAGIC; lock->owner = SPINLOCK_OWNER_INIT; - lock->owner_cpu = -1; + lock->owner_cpu = DEFAULT_OWNER_CPU; } EXPORT_SYMBOL(__raw_spin_lock_init); @@ -44,7 +47,7 @@ void __rwlock_init(rwlock_t *lock, const char *name, lock->raw_lock = (arch_rwlock_t) __ARCH_RW_LOCK_UNLOCKED; lock->magic = RWLOCK_MAGIC; lock->owner = SPINLOCK_OWNER_INIT; - lock->owner_cpu = -1; + lock->owner_cpu = DEFAULT_OWNER_CPU; } EXPORT_SYMBOL(__rwlock_init); @@ -53,6 +56,13 @@ static void spin_dump(raw_spinlock_t *lock, const char *msg) { struct task_struct *owner = NULL; + if (lock->owner_cpu & SPIN_DUMP_IN_PROGRESS) + panic("BUG: lock: %pS spin dump recursion on CPU#%d, %s/%d\n", + lock, raw_smp_processor_id(), + current->comm, task_pid_nr(current)); + + lock->owner_cpu |= SPIN_DUMP_IN_PROGRESS; + if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT) owner = lock->owner; printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n", @@ -63,8 +73,10 @@ static void spin_dump(raw_spinlock_t *lock, const char *msg) lock, lock->magic, owner ? owner->comm : "", owner ? task_pid_nr(owner) : -1, - lock->owner_cpu); + lock->owner_cpu == DEFAULT_OWNER_CPU ? -1 : lock->owner_cpu); dump_stack(); + + lock->owner_cpu &= ~SPIN_DUMP_IN_PROGRESS; } static void spin_bug(raw_spinlock_t *lock, const char *msg) @@ -100,7 +112,7 @@ static inline void debug_spin_unlock(raw_spinlock_t *lock) SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), lock, "wrong CPU"); lock->owner = SPINLOCK_OWNER_INIT; - lock->owner_cpu = -1; + lock->owner_cpu = DEFAULT_OWNER_CPU; } static void __spin_lock_debug(raw_spinlock_t *lock) @@ -244,7 +256,7 @@ static inline void debug_write_unlock(rwlock_t *lock) RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), lock, "wrong CPU"); lock->owner = SPINLOCK_OWNER_INIT; - lock->owner_cpu = -1; + lock->owner_cpu = DEFAULT_OWNER_CPU; } #if 0 /* This can cause lockups */ -- 2.7.0