ring-buffer: pass in lockdep class key for reader_lock
On Sun, 7 Jun 2009, Ingo Molnar wrote: > Testing tracer sched_switch: <6>Starting ring buffer hammer > PASSED > Testing tracer sysprof: PASSED > Testing tracer function: PASSED > Testing tracer irqsoff: > ============================================= > PASSED > Testing tracer preemptoff: PASSED > Testing tracer preemptirqsoff: [ INFO: possible recursive locking detected ] > PASSED > Testing tracer branch: 2.6.30-rc8-tip-01972-ge5b9078-dirty #5760 > --------------------------------------------- > rb_consumer/431 is trying to acquire lock: > (&cpu_buffer->reader_lock){......}, at: [<c109eef7>] ring_buffer_reset_cpu+0x37/0x70 > > but task is already holding lock: > (&cpu_buffer->reader_lock){......}, at: [<c10a019e>] ring_buffer_consume+0x7e/0xc0 > > other info that might help us debug this: > 1 lock held by rb_consumer/431: > #0: (&cpu_buffer->reader_lock){......}, at: [<c10a019e>] ring_buffer_consume+0x7e/0xc0 The ring buffer is a generic structure, and can be used outside of ftrace. If ftrace traces within the use of the ring buffer, it can produce false positives with lockdep. This patch passes in a static lock key into the allocation of the ring buffer, so that different ring buffers will have their own lock class. Reported-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <1244477919.13761.9042.camel@twins> [ store key in ring buffer descriptor ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
918143e8b7
commit
1f8a6a10fb
|
@ -105,7 +105,19 @@ void ring_buffer_discard_commit(struct ring_buffer *buffer,
|
|||
* size is in bytes for each per CPU buffer.
|
||||
*/
|
||||
struct ring_buffer *
|
||||
ring_buffer_alloc(unsigned long size, unsigned flags);
|
||||
__ring_buffer_alloc(unsigned long size, unsigned flags, struct lock_class_key *key);
|
||||
|
||||
/*
|
||||
* Because the ring buffer is generic, if other users of the ring buffer get
|
||||
* traced by ftrace, it can produce lockdep warnings. We need to keep each
|
||||
* ring buffer's lock class separate.
|
||||
*/
|
||||
#define ring_buffer_alloc(size, flags) \
|
||||
({ \
|
||||
static struct lock_class_key __key; \
|
||||
__ring_buffer_alloc((size), (flags), &__key); \
|
||||
})
|
||||
|
||||
void ring_buffer_free(struct ring_buffer *buffer);
|
||||
|
||||
int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size);
|
||||
|
|
|
@ -426,6 +426,8 @@ struct ring_buffer {
|
|||
atomic_t record_disabled;
|
||||
cpumask_var_t cpumask;
|
||||
|
||||
struct lock_class_key *reader_lock_key;
|
||||
|
||||
struct mutex mutex;
|
||||
|
||||
struct ring_buffer_per_cpu **buffers;
|
||||
|
@ -565,6 +567,7 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu)
|
|||
cpu_buffer->cpu = cpu;
|
||||
cpu_buffer->buffer = buffer;
|
||||
spin_lock_init(&cpu_buffer->reader_lock);
|
||||
lockdep_set_class(&cpu_buffer->reader_lock, buffer->reader_lock_key);
|
||||
cpu_buffer->lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
|
||||
INIT_LIST_HEAD(&cpu_buffer->pages);
|
||||
|
||||
|
@ -635,7 +638,8 @@ static int rb_cpu_notify(struct notifier_block *self,
|
|||
* when the buffer wraps. If this flag is not set, the buffer will
|
||||
* drop data when the tail hits the head.
|
||||
*/
|
||||
struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags)
|
||||
struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
|
||||
struct lock_class_key *key)
|
||||
{
|
||||
struct ring_buffer *buffer;
|
||||
int bsize;
|
||||
|
@ -658,6 +662,7 @@ struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags)
|
|||
buffer->pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
|
||||
buffer->flags = flags;
|
||||
buffer->clock = trace_clock_local;
|
||||
buffer->reader_lock_key = key;
|
||||
|
||||
/* need at least two pages */
|
||||
if (buffer->pages == 1)
|
||||
|
@ -715,7 +720,7 @@ struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags)
|
|||
kfree(buffer);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ring_buffer_alloc);
|
||||
EXPORT_SYMBOL_GPL(__ring_buffer_alloc);
|
||||
|
||||
/**
|
||||
* ring_buffer_free - free a ring buffer.
|
||||
|
|
Loading…
Reference in New Issue