diff options
| author | Tom Zanussi <tzanussi@gmail.com> | 2009-03-22 04:30:49 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-03-22 13:38:25 -0400 |
| commit | 2d622719f1572ef31e0616444a515eba3094d050 (patch) | |
| tree | f9bffcdca6289f141fb53a38dd9f32af8c71efad /kernel/trace/ring_buffer.c | |
| parent | cf027f645e6aee4f0ca6197a6b6a57f327fdb13f (diff) | |
tracing: add ring_buffer_event_discard() to ring buffer
This patch overloads RINGBUF_TYPE_PADDING to provide a way to discard
events from the ring buffer, for the event-filtering mechanism
introduced in a subsequent patch.
I did the initial version but thanks to Steven Rostedt for adding
the parts that actually made it work. ;-)
Signed-off-by: Tom Zanussi <tzanussi@gmail.com>
Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/ring_buffer.c')
| -rw-r--r-- | kernel/trace/ring_buffer.c | 117 |
1 files changed, 97 insertions, 20 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 384ca5d9d729..a09027ec1714 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
| @@ -189,16 +189,65 @@ enum { | |||
| 189 | RB_LEN_TIME_STAMP = 16, | 189 | RB_LEN_TIME_STAMP = 16, |
| 190 | }; | 190 | }; |
| 191 | 191 | ||
| 192 | /* inline for ring buffer fast paths */ | 192 | static inline int rb_null_event(struct ring_buffer_event *event) |
| 193 | { | ||
| 194 | return event->type == RINGBUF_TYPE_PADDING && event->time_delta == 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | static inline int rb_discarded_event(struct ring_buffer_event *event) | ||
| 198 | { | ||
| 199 | return event->type == RINGBUF_TYPE_PADDING && event->time_delta; | ||
| 200 | } | ||
| 201 | |||
| 202 | static void rb_event_set_padding(struct ring_buffer_event *event) | ||
| 203 | { | ||
| 204 | event->type = RINGBUF_TYPE_PADDING; | ||
| 205 | event->time_delta = 0; | ||
| 206 | } | ||
| 207 | |||
| 208 | /** | ||
| 209 | * ring_buffer_event_discard - discard an event in the ring buffer | ||
| 210 | * @buffer: the ring buffer | ||
| 211 | * @event: the event to discard | ||
| 212 | * | ||
| 213 | * Sometimes a event that is in the ring buffer needs to be ignored. | ||
| 214 | * This function lets the user discard an event in the ring buffer | ||
| 215 | * and then that event will not be read later. | ||
| 216 | * | ||
| 217 | * Note, it is up to the user to be careful with this, and protect | ||
| 218 | * against races. If the user discards an event that has been consumed | ||
| 219 | * it is possible that it could corrupt the ring buffer. | ||
| 220 | */ | ||
| 221 | void ring_buffer_event_discard(struct ring_buffer_event *event) | ||
| 222 | { | ||
| 223 | event->type = RINGBUF_TYPE_PADDING; | ||
| 224 | /* time delta must be non zero */ | ||
| 225 | if (!event->time_delta) | ||
| 226 | event->time_delta = 1; | ||
| 227 | } | ||
| 228 | |||
| 193 | static unsigned | 229 | static unsigned |
| 194 | rb_event_length(struct ring_buffer_event *event) | 230 | rb_event_data_length(struct ring_buffer_event *event) |
| 195 | { | 231 | { |
| 196 | unsigned length; | 232 | unsigned length; |
| 197 | 233 | ||
| 234 | if (event->len) | ||
| 235 | length = event->len * RB_ALIGNMENT; | ||
| 236 | else | ||
| 237 | length = event->array[0]; | ||
| 238 | return length + RB_EVNT_HDR_SIZE; | ||
| 239 | } | ||
| 240 | |||
| 241 | /* inline for ring buffer fast paths */ | ||
| 242 | static unsigned | ||
| 243 | rb_event_length(struct ring_buffer_event *event) | ||
| 244 | { | ||
| 198 | switch (event->type) { | 245 | switch (event->type) { |
| 199 | case RINGBUF_TYPE_PADDING: | 246 | case RINGBUF_TYPE_PADDING: |
| 200 | /* undefined */ | 247 | if (rb_null_event(event)) |
| 201 | return -1; | 248 | /* undefined */ |
| 249 | return -1; | ||
| 250 | return rb_event_data_length(event); | ||
| 202 | 251 | ||
| 203 | case RINGBUF_TYPE_TIME_EXTEND: | 252 | case RINGBUF_TYPE_TIME_EXTEND: |
| 204 | return RB_LEN_TIME_EXTEND; | 253 | return RB_LEN_TIME_EXTEND; |
| @@ -207,11 +256,7 @@ rb_event_length(struct ring_buffer_event *event) | |||
| 207 | return RB_LEN_TIME_STAMP; | 256 | return RB_LEN_TIME_STAMP; |
| 208 | 257 | ||
| 209 | case RINGBUF_TYPE_DATA: | 258 | case RINGBUF_TYPE_DATA: |
| 210 | if (event->len) | 259 | return rb_event_data_length(event); |
| 211 | length = event->len * RB_ALIGNMENT; | ||
| 212 | else | ||
| 213 | length = event->array[0]; | ||
| 214 | return length + RB_EVNT_HDR_SIZE; | ||
| 215 | default: | 260 | default: |
| 216 | BUG(); | 261 | BUG(); |
| 217 | } | 262 | } |
| @@ -845,11 +890,6 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) | |||
| 845 | } | 890 | } |
| 846 | EXPORT_SYMBOL_GPL(ring_buffer_resize); | 891 | EXPORT_SYMBOL_GPL(ring_buffer_resize); |
| 847 | 892 | ||
| 848 | static inline int rb_null_event(struct ring_buffer_event *event) | ||
| 849 | { | ||
| 850 | return event->type == RINGBUF_TYPE_PADDING; | ||
| 851 | } | ||
| 852 | |||
| 853 | static inline void * | 893 | static inline void * |
| 854 | __rb_data_page_index(struct buffer_data_page *bpage, unsigned index) | 894 | __rb_data_page_index(struct buffer_data_page *bpage, unsigned index) |
| 855 | { | 895 | { |
| @@ -1219,7 +1259,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, | |||
| 1219 | if (tail < BUF_PAGE_SIZE) { | 1259 | if (tail < BUF_PAGE_SIZE) { |
| 1220 | /* Mark the rest of the page with padding */ | 1260 | /* Mark the rest of the page with padding */ |
| 1221 | event = __rb_page_index(tail_page, tail); | 1261 | event = __rb_page_index(tail_page, tail); |
| 1222 | event->type = RINGBUF_TYPE_PADDING; | 1262 | rb_event_set_padding(event); |
| 1223 | } | 1263 | } |
| 1224 | 1264 | ||
| 1225 | if (tail <= BUF_PAGE_SIZE) | 1265 | if (tail <= BUF_PAGE_SIZE) |
| @@ -1969,7 +2009,7 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer) | |||
| 1969 | 2009 | ||
| 1970 | event = rb_reader_event(cpu_buffer); | 2010 | event = rb_reader_event(cpu_buffer); |
| 1971 | 2011 | ||
| 1972 | if (event->type == RINGBUF_TYPE_DATA) | 2012 | if (event->type == RINGBUF_TYPE_DATA || rb_discarded_event(event)) |
| 1973 | cpu_buffer->entries--; | 2013 | cpu_buffer->entries--; |
| 1974 | 2014 | ||
| 1975 | rb_update_read_stamp(cpu_buffer, event); | 2015 | rb_update_read_stamp(cpu_buffer, event); |
| @@ -2052,9 +2092,18 @@ rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
| 2052 | 2092 | ||
| 2053 | switch (event->type) { | 2093 | switch (event->type) { |
| 2054 | case RINGBUF_TYPE_PADDING: | 2094 | case RINGBUF_TYPE_PADDING: |
| 2055 | RB_WARN_ON(cpu_buffer, 1); | 2095 | if (rb_null_event(event)) |
| 2096 | RB_WARN_ON(cpu_buffer, 1); | ||
| 2097 | /* | ||
| 2098 | * Because the writer could be discarding every | ||
| 2099 | * event it creates (which would probably be bad) | ||
| 2100 | * if we were to go back to "again" then we may never | ||
| 2101 | * catch up, and will trigger the warn on, or lock | ||
| 2102 | * the box. Return the padding, and we will release | ||
| 2103 | * the current locks, and try again. | ||
| 2104 | */ | ||
| 2056 | rb_advance_reader(cpu_buffer); | 2105 | rb_advance_reader(cpu_buffer); |
| 2057 | return NULL; | 2106 | return event; |
| 2058 | 2107 | ||
| 2059 | case RINGBUF_TYPE_TIME_EXTEND: | 2108 | case RINGBUF_TYPE_TIME_EXTEND: |
| 2060 | /* Internal data, OK to advance */ | 2109 | /* Internal data, OK to advance */ |
| @@ -2115,8 +2164,12 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
| 2115 | 2164 | ||
| 2116 | switch (event->type) { | 2165 | switch (event->type) { |
| 2117 | case RINGBUF_TYPE_PADDING: | 2166 | case RINGBUF_TYPE_PADDING: |
| 2118 | rb_inc_iter(iter); | 2167 | if (rb_null_event(event)) { |
| 2119 | goto again; | 2168 | rb_inc_iter(iter); |
| 2169 | goto again; | ||
| 2170 | } | ||
| 2171 | rb_advance_iter(iter); | ||
| 2172 | return event; | ||
| 2120 | 2173 | ||
| 2121 | case RINGBUF_TYPE_TIME_EXTEND: | 2174 | case RINGBUF_TYPE_TIME_EXTEND: |
| 2122 | /* Internal data, OK to advance */ | 2175 | /* Internal data, OK to advance */ |
| @@ -2163,10 +2216,16 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
| 2163 | if (!cpumask_test_cpu(cpu, buffer->cpumask)) | 2216 | if (!cpumask_test_cpu(cpu, buffer->cpumask)) |
| 2164 | return NULL; | 2217 | return NULL; |
| 2165 | 2218 | ||
| 2219 | again: | ||
| 2166 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); | 2220 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); |
| 2167 | event = rb_buffer_peek(buffer, cpu, ts); | 2221 | event = rb_buffer_peek(buffer, cpu, ts); |
| 2168 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | 2222 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |
| 2169 | 2223 | ||
| 2224 | if (event && event->type == RINGBUF_TYPE_PADDING) { | ||
| 2225 | cpu_relax(); | ||
| 2226 | goto again; | ||
| 2227 | } | ||
| 2228 | |||
| 2170 | return event; | 2229 | return event; |
| 2171 | } | 2230 | } |
| 2172 | 2231 | ||
| @@ -2185,10 +2244,16 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
| 2185 | struct ring_buffer_event *event; | 2244 | struct ring_buffer_event *event; |
| 2186 | unsigned long flags; | 2245 | unsigned long flags; |
| 2187 | 2246 | ||
| 2247 | again: | ||
| 2188 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); | 2248 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); |
| 2189 | event = rb_iter_peek(iter, ts); | 2249 | event = rb_iter_peek(iter, ts); |
| 2190 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | 2250 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |
| 2191 | 2251 | ||
| 2252 | if (event && event->type == RINGBUF_TYPE_PADDING) { | ||
| 2253 | cpu_relax(); | ||
| 2254 | goto again; | ||
| 2255 | } | ||
| 2256 | |||
| 2192 | return event; | 2257 | return event; |
| 2193 | } | 2258 | } |
| 2194 | 2259 | ||
| @@ -2207,6 +2272,7 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
| 2207 | struct ring_buffer_event *event = NULL; | 2272 | struct ring_buffer_event *event = NULL; |
| 2208 | unsigned long flags; | 2273 | unsigned long flags; |
| 2209 | 2274 | ||
| 2275 | again: | ||
| 2210 | /* might be called in atomic */ | 2276 | /* might be called in atomic */ |
| 2211 | preempt_disable(); | 2277 | preempt_disable(); |
| 2212 | 2278 | ||
| @@ -2228,6 +2294,11 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
| 2228 | out: | 2294 | out: |
| 2229 | preempt_enable(); | 2295 | preempt_enable(); |
| 2230 | 2296 | ||
| 2297 | if (event && event->type == RINGBUF_TYPE_PADDING) { | ||
| 2298 | cpu_relax(); | ||
| 2299 | goto again; | ||
| 2300 | } | ||
| 2301 | |||
| 2231 | return event; | 2302 | return event; |
| 2232 | } | 2303 | } |
| 2233 | EXPORT_SYMBOL_GPL(ring_buffer_consume); | 2304 | EXPORT_SYMBOL_GPL(ring_buffer_consume); |
| @@ -2306,6 +2377,7 @@ ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts) | |||
| 2306 | struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; | 2377 | struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; |
| 2307 | unsigned long flags; | 2378 | unsigned long flags; |
| 2308 | 2379 | ||
| 2380 | again: | ||
| 2309 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); | 2381 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); |
| 2310 | event = rb_iter_peek(iter, ts); | 2382 | event = rb_iter_peek(iter, ts); |
| 2311 | if (!event) | 2383 | if (!event) |
| @@ -2315,6 +2387,11 @@ ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts) | |||
| 2315 | out: | 2387 | out: |
| 2316 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | 2388 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |
| 2317 | 2389 | ||
| 2390 | if (event && event->type == RINGBUF_TYPE_PADDING) { | ||
| 2391 | cpu_relax(); | ||
| 2392 | goto again; | ||
| 2393 | } | ||
| 2394 | |||
| 2318 | return event; | 2395 | return event; |
| 2319 | } | 2396 | } |
| 2320 | EXPORT_SYMBOL_GPL(ring_buffer_read); | 2397 | EXPORT_SYMBOL_GPL(ring_buffer_read); |
