diff options
Diffstat (limited to 'kernel/trace/ring_buffer.c')
-rw-r--r-- | kernel/trace/ring_buffer.c | 118 |
1 files changed, 97 insertions, 21 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 808b14bbf076..960cbf44c844 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 | } |
@@ -518,7 +563,6 @@ static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer) | |||
518 | struct list_head *head = &cpu_buffer->pages; | 563 | struct list_head *head = &cpu_buffer->pages; |
519 | struct buffer_page *bpage, *tmp; | 564 | struct buffer_page *bpage, *tmp; |
520 | 565 | ||
521 | list_del_init(&cpu_buffer->reader_page->list); | ||
522 | free_buffer_page(cpu_buffer->reader_page); | 566 | free_buffer_page(cpu_buffer->reader_page); |
523 | 567 | ||
524 | list_for_each_entry_safe(bpage, tmp, head, list) { | 568 | list_for_each_entry_safe(bpage, tmp, head, list) { |
@@ -845,11 +889,6 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) | |||
845 | } | 889 | } |
846 | EXPORT_SYMBOL_GPL(ring_buffer_resize); | 890 | EXPORT_SYMBOL_GPL(ring_buffer_resize); |
847 | 891 | ||
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 * | 892 | static inline void * |
854 | __rb_data_page_index(struct buffer_data_page *bpage, unsigned index) | 893 | __rb_data_page_index(struct buffer_data_page *bpage, unsigned index) |
855 | { | 894 | { |
@@ -1219,7 +1258,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, | |||
1219 | if (tail < BUF_PAGE_SIZE) { | 1258 | if (tail < BUF_PAGE_SIZE) { |
1220 | /* Mark the rest of the page with padding */ | 1259 | /* Mark the rest of the page with padding */ |
1221 | event = __rb_page_index(tail_page, tail); | 1260 | event = __rb_page_index(tail_page, tail); |
1222 | event->type = RINGBUF_TYPE_PADDING; | 1261 | rb_event_set_padding(event); |
1223 | } | 1262 | } |
1224 | 1263 | ||
1225 | if (tail <= BUF_PAGE_SIZE) | 1264 | if (tail <= BUF_PAGE_SIZE) |
@@ -1969,7 +2008,7 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer) | |||
1969 | 2008 | ||
1970 | event = rb_reader_event(cpu_buffer); | 2009 | event = rb_reader_event(cpu_buffer); |
1971 | 2010 | ||
1972 | if (event->type == RINGBUF_TYPE_DATA) | 2011 | if (event->type == RINGBUF_TYPE_DATA || rb_discarded_event(event)) |
1973 | cpu_buffer->entries--; | 2012 | cpu_buffer->entries--; |
1974 | 2013 | ||
1975 | rb_update_read_stamp(cpu_buffer, event); | 2014 | rb_update_read_stamp(cpu_buffer, event); |
@@ -2052,9 +2091,18 @@ rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
2052 | 2091 | ||
2053 | switch (event->type) { | 2092 | switch (event->type) { |
2054 | case RINGBUF_TYPE_PADDING: | 2093 | case RINGBUF_TYPE_PADDING: |
2055 | RB_WARN_ON(cpu_buffer, 1); | 2094 | if (rb_null_event(event)) |
2095 | RB_WARN_ON(cpu_buffer, 1); | ||
2096 | /* | ||
2097 | * Because the writer could be discarding every | ||
2098 | * event it creates (which would probably be bad) | ||
2099 | * if we were to go back to "again" then we may never | ||
2100 | * catch up, and will trigger the warn on, or lock | ||
2101 | * the box. Return the padding, and we will release | ||
2102 | * the current locks, and try again. | ||
2103 | */ | ||
2056 | rb_advance_reader(cpu_buffer); | 2104 | rb_advance_reader(cpu_buffer); |
2057 | return NULL; | 2105 | return event; |
2058 | 2106 | ||
2059 | case RINGBUF_TYPE_TIME_EXTEND: | 2107 | case RINGBUF_TYPE_TIME_EXTEND: |
2060 | /* Internal data, OK to advance */ | 2108 | /* Internal data, OK to advance */ |
@@ -2115,8 +2163,12 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
2115 | 2163 | ||
2116 | switch (event->type) { | 2164 | switch (event->type) { |
2117 | case RINGBUF_TYPE_PADDING: | 2165 | case RINGBUF_TYPE_PADDING: |
2118 | rb_inc_iter(iter); | 2166 | if (rb_null_event(event)) { |
2119 | goto again; | 2167 | rb_inc_iter(iter); |
2168 | goto again; | ||
2169 | } | ||
2170 | rb_advance_iter(iter); | ||
2171 | return event; | ||
2120 | 2172 | ||
2121 | case RINGBUF_TYPE_TIME_EXTEND: | 2173 | case RINGBUF_TYPE_TIME_EXTEND: |
2122 | /* Internal data, OK to advance */ | 2174 | /* Internal data, OK to advance */ |
@@ -2163,10 +2215,16 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
2163 | if (!cpumask_test_cpu(cpu, buffer->cpumask)) | 2215 | if (!cpumask_test_cpu(cpu, buffer->cpumask)) |
2164 | return NULL; | 2216 | return NULL; |
2165 | 2217 | ||
2218 | again: | ||
2166 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); | 2219 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); |
2167 | event = rb_buffer_peek(buffer, cpu, ts); | 2220 | event = rb_buffer_peek(buffer, cpu, ts); |
2168 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | 2221 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |
2169 | 2222 | ||
2223 | if (event && event->type == RINGBUF_TYPE_PADDING) { | ||
2224 | cpu_relax(); | ||
2225 | goto again; | ||
2226 | } | ||
2227 | |||
2170 | return event; | 2228 | return event; |
2171 | } | 2229 | } |
2172 | 2230 | ||
@@ -2185,10 +2243,16 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
2185 | struct ring_buffer_event *event; | 2243 | struct ring_buffer_event *event; |
2186 | unsigned long flags; | 2244 | unsigned long flags; |
2187 | 2245 | ||
2246 | again: | ||
2188 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); | 2247 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); |
2189 | event = rb_iter_peek(iter, ts); | 2248 | event = rb_iter_peek(iter, ts); |
2190 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | 2249 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |
2191 | 2250 | ||
2251 | if (event && event->type == RINGBUF_TYPE_PADDING) { | ||
2252 | cpu_relax(); | ||
2253 | goto again; | ||
2254 | } | ||
2255 | |||
2192 | return event; | 2256 | return event; |
2193 | } | 2257 | } |
2194 | 2258 | ||
@@ -2207,6 +2271,7 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
2207 | struct ring_buffer_event *event = NULL; | 2271 | struct ring_buffer_event *event = NULL; |
2208 | unsigned long flags; | 2272 | unsigned long flags; |
2209 | 2273 | ||
2274 | again: | ||
2210 | /* might be called in atomic */ | 2275 | /* might be called in atomic */ |
2211 | preempt_disable(); | 2276 | preempt_disable(); |
2212 | 2277 | ||
@@ -2228,6 +2293,11 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
2228 | out: | 2293 | out: |
2229 | preempt_enable(); | 2294 | preempt_enable(); |
2230 | 2295 | ||
2296 | if (event && event->type == RINGBUF_TYPE_PADDING) { | ||
2297 | cpu_relax(); | ||
2298 | goto again; | ||
2299 | } | ||
2300 | |||
2231 | return event; | 2301 | return event; |
2232 | } | 2302 | } |
2233 | EXPORT_SYMBOL_GPL(ring_buffer_consume); | 2303 | EXPORT_SYMBOL_GPL(ring_buffer_consume); |
@@ -2306,6 +2376,7 @@ ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts) | |||
2306 | struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; | 2376 | struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; |
2307 | unsigned long flags; | 2377 | unsigned long flags; |
2308 | 2378 | ||
2379 | again: | ||
2309 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); | 2380 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); |
2310 | event = rb_iter_peek(iter, ts); | 2381 | event = rb_iter_peek(iter, ts); |
2311 | if (!event) | 2382 | if (!event) |
@@ -2315,6 +2386,11 @@ ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts) | |||
2315 | out: | 2386 | out: |
2316 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | 2387 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |
2317 | 2388 | ||
2389 | if (event && event->type == RINGBUF_TYPE_PADDING) { | ||
2390 | cpu_relax(); | ||
2391 | goto again; | ||
2392 | } | ||
2393 | |||
2318 | return event; | 2394 | return event; |
2319 | } | 2395 | } |
2320 | EXPORT_SYMBOL_GPL(ring_buffer_read); | 2396 | EXPORT_SYMBOL_GPL(ring_buffer_read); |