diff options
-rw-r--r-- | include/linux/ring_buffer.h | 11 | ||||
-rw-r--r-- | kernel/trace/ring_buffer.c | 117 |
2 files changed, 105 insertions, 23 deletions
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index 9e6052bd1a1c..e1b7b2173885 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h | |||
@@ -18,10 +18,13 @@ struct ring_buffer_event { | |||
18 | /** | 18 | /** |
19 | * enum ring_buffer_type - internal ring buffer types | 19 | * enum ring_buffer_type - internal ring buffer types |
20 | * | 20 | * |
21 | * @RINGBUF_TYPE_PADDING: Left over page padding | 21 | * @RINGBUF_TYPE_PADDING: Left over page padding or discarded event |
22 | * array is ignored | 22 | * If time_delta is 0: |
23 | * size is variable depending on how much | 23 | * array is ignored |
24 | * size is variable depending on how much | ||
24 | * padding is needed | 25 | * padding is needed |
26 | * If time_delta is non zero: | ||
27 | * everything else same as RINGBUF_TYPE_DATA | ||
25 | * | 28 | * |
26 | * @RINGBUF_TYPE_TIME_EXTEND: Extend the time delta | 29 | * @RINGBUF_TYPE_TIME_EXTEND: Extend the time delta |
27 | * array[0] = time delta (28 .. 59) | 30 | * array[0] = time delta (28 .. 59) |
@@ -65,6 +68,8 @@ ring_buffer_event_time_delta(struct ring_buffer_event *event) | |||
65 | return event->time_delta; | 68 | return event->time_delta; |
66 | } | 69 | } |
67 | 70 | ||
71 | void ring_buffer_event_discard(struct ring_buffer_event *event); | ||
72 | |||
68 | /* | 73 | /* |
69 | * size is in bytes for each per CPU buffer. | 74 | * size is in bytes for each per CPU buffer. |
70 | */ | 75 | */ |
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); |