From e5ead2d5c76a46c9a7cc27594692cd37ef56039a Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 18 Mar 2013 14:33:28 +0100 Subject: [PATCH] --- yaml --- r: 362517 b: refs/heads/master c: dd9c086d9f507d02d5ba4d7c5eef4bb9518088b8 h: refs/heads/master i: 362515: d823c33956144b07c48792ed6186962a8505f709 v: v3 --- [refs] | 2 +- trunk/kernel/events/internal.h | 2 +- trunk/kernel/events/ring_buffer.c | 22 ++++++++++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index d6e4e663a958..9761533740ae 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0e48026ae7abf871e51eaa9183c81ab5bef4c267 +refs/heads/master: dd9c086d9f507d02d5ba4d7c5eef4bb9518088b8 diff --git a/trunk/kernel/events/internal.h b/trunk/kernel/events/internal.h index d56a64c99a8b..eb675c4d59df 100644 --- a/trunk/kernel/events/internal.h +++ b/trunk/kernel/events/internal.h @@ -16,7 +16,7 @@ struct ring_buffer { int page_order; /* allocation order */ #endif int nr_pages; /* nr of data pages */ - int writable; /* are we writable */ + int overwrite; /* can overwrite itself */ atomic_t poll; /* POLL_ for wakeups */ diff --git a/trunk/kernel/events/ring_buffer.c b/trunk/kernel/events/ring_buffer.c index 23cb34ff3973..97fddb09762b 100644 --- a/trunk/kernel/events/ring_buffer.c +++ b/trunk/kernel/events/ring_buffer.c @@ -18,12 +18,24 @@ static bool perf_output_space(struct ring_buffer *rb, unsigned long tail, unsigned long offset, unsigned long head) { - unsigned long mask; + unsigned long sz = perf_data_size(rb); + unsigned long mask = sz - 1; - if (!rb->writable) + /* + * check if user-writable + * overwrite : over-write its own tail + * !overwrite: buffer possibly drops events. + */ + if (rb->overwrite) return true; - mask = perf_data_size(rb) - 1; + /* + * verify that payload is not bigger than buffer + * otherwise masking logic may fail to detect + * the "not enough space" condition + */ + if ((head - offset) > sz) + return false; offset = (offset - tail) & mask; head = (head - tail) & mask; @@ -212,7 +224,9 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) rb->watermark = max_size / 2; if (flags & RING_BUFFER_WRITABLE) - rb->writable = 1; + rb->overwrite = 0; + else + rb->overwrite = 1; atomic_set(&rb->refcount, 1);