From: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
To: Peter Hurley <peter@hurleysoftware.com>
Cc: Byungchul Park <byungchul.park@lge.com>,
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@gmail.com>,
Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Subject: Re: [PATCH 3/3] spinlock_debug: panic on recursive lock spin_dump()
Date: Tue, 2 Feb 2016 01:14:58 +0900 [thread overview]
Message-ID: <20160201161458.GA609@swordfish> (raw)
In-Reply-To: <1454243623-15109-3-git-send-email-sergey.senozhatsky@gmail.com>
On (01/31/16 21:33), Sergey Senozhatsky wrote:
> 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 recurse into itself.
how about splitting ->owner_cpu 4 bytes as:
| |
1 byte spin bug recursion | 1 byte spin_dump recursion counter | 2 bytes owner cpu
| |
?
so we have 2 bytes to store the lock owner's smp_processor_id().
(I just don't want to extend spin lock with another 4 bytes to
fix the recursion.)
spin_dump() will increment lock's spin_dump recursion counter and decrement it
upon the exit from spin_dump(). if lock's recursion counter is equal to
U8_MAX -- panic() the system, we have recursed spin_dump() into spin_dump()
enough... (U8_MAX recursive printk->spin_dump->printk calls look big enough).
for spin_bug() recursion we don't have to maintain any counter: set
SPIN_BUG_RECURSION bit at the beginning of spin_bug() and clear it at
the end. if the lock already has SPIN_BUG_RECURSION bit set -- panic()
the system.
compile tested only.
will test it tomorrow.
---
kernel/locking/spinlock_debug.c | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/kernel/locking/spinlock_debug.c b/kernel/locking/spinlock_debug.c
index 0374a59..54bcc3b 100644
--- a/kernel/locking/spinlock_debug.c
+++ b/kernel/locking/spinlock_debug.c
@@ -13,6 +13,9 @@
#include <linux/delay.h>
#include <linux/export.h>
+#define SPIN_DUMP_RECURSION (1 << 16)
+#define SPIN_BUG_RECURSION (1 << 31)
+
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 = USHRT_MAX;
}
EXPORT_SYMBOL(__raw_spin_lock_init);
@@ -44,14 +47,26 @@ 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 = USHRT_MAX;
}
EXPORT_SYMBOL(__rwlock_init);
+static void spin_recursion_panic(raw_spinlock_t *lock, const char *msg)
+{
+ panic("BUG: lock: %pS %s recursion on CPU#%d, %s/%d\n",
+ lock, msg, raw_smp_processor_id(),
+ current->comm, task_pid_nr(current));
+}
+
static void spin_dump(raw_spinlock_t *lock, const char *msg)
{
struct task_struct *owner = NULL;
+ u8 recursion_counter = (u8)(lock->owner_cpu >> 16);
+
+ lock->owner_cpu += SPIN_DUMP_RECURSION;
+ if ((recursion_counter + 1) == U8_MAX)
+ spin_recursion_panic(lock, "spin_dump()");
if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
owner = lock->owner;
@@ -63,8 +78,10 @@ static void spin_dump(raw_spinlock_t *lock, const char *msg)
lock, lock->magic,
owner ? owner->comm : "<none>",
owner ? task_pid_nr(owner) : -1,
- lock->owner_cpu);
+ lock->owner_cpu == USHRT_MAX ? -1 : lock->owner_cpu);
dump_stack();
+
+ lock->owner_cpu -= SPIN_DUMP_RECURSION;
}
static void spin_bug(raw_spinlock_t *lock, const char *msg)
@@ -72,7 +89,12 @@ static void spin_bug(raw_spinlock_t *lock, const char *msg)
if (!debug_locks_off())
return;
+ if (lock->owner_cpu & SPIN_BUG_RECURSION)
+ spin_recursion_panic(lock, "spin_bug()");
+
+ lock->owner_cpu |= SPIN_BUG_RECURSION;
spin_dump(lock, msg);
+ lock->owner_cpu &= ~SPIN_BUG_RECURSION;
}
#define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg)
@@ -100,7 +122,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 = USHRT_MAX;
}
static void __spin_lock_debug(raw_spinlock_t *lock)
@@ -244,7 +266,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 = USHRT_MAX;
}
#if 0 /* This can cause lockups */
--
2.7.0.75.g3ee1e0f
next prev parent reply other threads:[~2016-02-01 16:16 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-27 12:01 [PATCH v4] lib/spinlock_debug.c: prevent a recursive cycle in the debug code Byungchul Park
2016-01-27 22:49 ` Peter Hurley
2016-01-28 7:15 ` Byungchul Park
2016-01-29 8:19 ` Byungchul Park
2016-01-28 1:42 ` Byungchul Park
2016-01-28 2:37 ` Sergey Senozhatsky
2016-01-28 4:36 ` byungchul.park
2016-01-28 6:05 ` Sergey Senozhatsky
2016-01-28 8:13 ` Byungchul Park
2016-01-28 10:41 ` Sergey Senozhatsky
2016-01-28 10:53 ` Sergey Senozhatsky
2016-01-28 15:42 ` Sergey Senozhatsky
2016-01-28 23:08 ` Peter Hurley
2016-01-28 23:54 ` Byungchul Park
2016-01-29 0:54 ` Sergey Senozhatsky
2016-01-29 3:00 ` Byungchul Park
2016-01-29 4:05 ` Sergey Senozhatsky
2016-01-29 12:15 ` Byungchul Park
2016-01-29 0:27 ` Sergey Senozhatsky
2016-01-29 4:32 ` Peter Hurley
2016-01-29 5:28 ` Sergey Senozhatsky
2016-01-29 5:48 ` Peter Hurley
2016-01-29 6:16 ` Sergey Senozhatsky
2016-01-29 6:37 ` Sergey Senozhatsky
2016-01-31 12:30 ` Sergey Senozhatsky
2016-01-31 12:33 ` [PATCH 1/3] printk: introduce console_reset_on_panic() function Sergey Senozhatsky
2016-01-31 12:33 ` [PATCH 2/3] printk: introduce reset_console_drivers() Sergey Senozhatsky
2016-01-31 12:47 ` kbuild test robot
2016-01-31 12:33 ` [PATCH 3/3] spinlock_debug: panic on recursive lock spin_dump() Sergey Senozhatsky
2016-02-01 16:14 ` Sergey Senozhatsky [this message]
2016-02-02 7:59 ` Sergey Senozhatsky
2016-01-31 12:42 ` [PATCH 1/3] printk: introduce console_reset_on_panic() function kbuild test robot
2016-01-29 6:54 ` [PATCH v4] lib/spinlock_debug.c: prevent a recursive cycle in the debug code Byungchul Park
2016-01-29 7:13 ` Sergey Senozhatsky
2016-01-29 8:13 ` Byungchul Park
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160201161458.GA609@swordfish \
--to=sergey.senozhatsky@gmail.com \
--cc=akinobu.mita@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=byungchul.park@lge.com \
--cc=jack@suse.cz \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=peter@hurleysoftware.com \
--cc=sergey.senozhatsky.work@gmail.com \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.