1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4 *
5 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdbool.h>
10
11 #include <sys/utsname.h>
12
13 #include "kbuffer.h"
14
15 #define MISSING_EVENTS (1UL << 31)
16 #define MISSING_STORED (1UL << 30)
17
18 #define COMMIT_MASK ((1 << 27) - 1)
19
20 /* Absolute time stamps do not have the 5 MSB, take from the real time stamp */
21 #define TS_MSB (0xf8ULL << 56)
22
23 enum {
24 KBUFFER_FL_HOST_BIG_ENDIAN = (1<<0),
25 KBUFFER_FL_BIG_ENDIAN = (1<<1),
26 KBUFFER_FL_LONG_8 = (1<<2),
27 KBUFFER_FL_OLD_FORMAT = (1<<3),
28 };
29
30 #define ENDIAN_MASK (KBUFFER_FL_HOST_BIG_ENDIAN | KBUFFER_FL_BIG_ENDIAN)
31
32 /** kbuffer
33 * @timestamp - timestamp of current event
34 * @lost_events - # of lost events between this subbuffer and previous
35 * @flags - special flags of the kbuffer
36 * @subbuffer - pointer to the sub-buffer page
37 * @data - pointer to the start of data on the sub-buffer page
38 * @index - index from @data to the @curr event data
39 * @curr - offset from @data to the start of current event
40 * (includes metadata)
41 * @next - offset from @data to the start of next event
42 * @size - The size of data on @data
43 * @start - The offset from @subbuffer where @data lives
44 * @first - The offset from @subbuffer where the first non time stamp event lives
45 *
46 * @read_4 - Function to read 4 raw bytes (may swap)
47 * @read_8 - Function to read 8 raw bytes (may swap)
48 * @read_long - Function to read a long word (4 or 8 bytes with needed swap)
49 */
50 struct kbuffer {
51 unsigned long long timestamp;
52 long long lost_events;
53 unsigned long flags;
54 void *subbuffer;
55 void *data;
56 unsigned int index;
57 unsigned int curr;
58 unsigned int next;
59 unsigned int size;
60 unsigned int start;
61 unsigned int first;
62
63 unsigned int (*read_4)(void *ptr);
64 unsigned long long (*read_8)(void *ptr);
65 unsigned long long (*read_long)(struct kbuffer *kbuf, void *ptr);
66 int (*next_event)(struct kbuffer *kbuf);
67 };
68
zmalloc(size_t size)69 static void *zmalloc(size_t size)
70 {
71 return calloc(1, size);
72 }
73
host_is_bigendian(void)74 static int host_is_bigendian(void)
75 {
76 unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
77 unsigned int *ptr;
78
79 ptr = (unsigned int *)str;
80 return *ptr == 0x01020304;
81 }
82
do_swap(struct kbuffer * kbuf)83 static int do_swap(struct kbuffer *kbuf)
84 {
85 return ((kbuf->flags & KBUFFER_FL_HOST_BIG_ENDIAN) + kbuf->flags) &
86 ENDIAN_MASK;
87 }
88
__read_8(void * ptr)89 static unsigned long long __read_8(void *ptr)
90 {
91 unsigned long long data = *(unsigned long long *)ptr;
92
93 return data;
94 }
95
__read_8_sw(void * ptr)96 static unsigned long long __read_8_sw(void *ptr)
97 {
98 unsigned long long data = *(unsigned long long *)ptr;
99 unsigned long long swap;
100
101 swap = ((data & 0xffULL) << 56) |
102 ((data & (0xffULL << 8)) << 40) |
103 ((data & (0xffULL << 16)) << 24) |
104 ((data & (0xffULL << 24)) << 8) |
105 ((data & (0xffULL << 32)) >> 8) |
106 ((data & (0xffULL << 40)) >> 24) |
107 ((data & (0xffULL << 48)) >> 40) |
108 ((data & (0xffULL << 56)) >> 56);
109
110 return swap;
111 }
112
__read_4(void * ptr)113 static unsigned int __read_4(void *ptr)
114 {
115 unsigned int data = *(unsigned int *)ptr;
116
117 return data;
118 }
119
__read_4_sw(void * ptr)120 static unsigned int __read_4_sw(void *ptr)
121 {
122 unsigned int data = *(unsigned int *)ptr;
123 unsigned int swap;
124
125 swap = ((data & 0xffULL) << 24) |
126 ((data & (0xffULL << 8)) << 8) |
127 ((data & (0xffULL << 16)) >> 8) |
128 ((data & (0xffULL << 24)) >> 24);
129
130 return swap;
131 }
132
read_8(struct kbuffer * kbuf,void * ptr)133 static unsigned long long read_8(struct kbuffer *kbuf, void *ptr)
134 {
135 return kbuf->read_8(ptr);
136 }
137
read_4(struct kbuffer * kbuf,void * ptr)138 static unsigned int read_4(struct kbuffer *kbuf, void *ptr)
139 {
140 return kbuf->read_4(ptr);
141 }
142
__read_long_8(struct kbuffer * kbuf,void * ptr)143 static unsigned long long __read_long_8(struct kbuffer *kbuf, void *ptr)
144 {
145 return kbuf->read_8(ptr);
146 }
147
__read_long_4(struct kbuffer * kbuf,void * ptr)148 static unsigned long long __read_long_4(struct kbuffer *kbuf, void *ptr)
149 {
150 return kbuf->read_4(ptr);
151 }
152
read_long(struct kbuffer * kbuf,void * ptr)153 static unsigned long long read_long(struct kbuffer *kbuf, void *ptr)
154 {
155 return kbuf->read_long(kbuf, ptr);
156 }
157
calc_index(struct kbuffer * kbuf,void * ptr)158 static int calc_index(struct kbuffer *kbuf, void *ptr)
159 {
160 return (unsigned long)ptr - (unsigned long)kbuf->data;
161 }
162
163 static int __next_event(struct kbuffer *kbuf);
164
165 /*
166 * Just because sizeof(long) is 4 bytes, doesn't mean the OS isn't
167 * 64bits
168 */
host_is_32bit(void)169 static bool host_is_32bit(void)
170 {
171 struct utsname buf;
172 int ret;
173
174 ret = uname(&buf);
175 if (ret < 0) {
176 /* Oh well, just assume it is 32 bit */
177 return true;
178 }
179 /* If the uname machine value contains 64, assume the kernel is 64 bit */
180 return strstr(buf.machine, "64") == NULL;
181 }
182
183 /**
184 * kbuffer_alloc - allocat a new kbuffer
185 * @size; enum to denote size of word
186 * @endian: enum to denote endianness
187 *
188 * Allocates and returns a new kbuffer.
189 */
190 struct kbuffer *
kbuffer_alloc(enum kbuffer_long_size size,enum kbuffer_endian endian)191 kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian)
192 {
193 struct kbuffer *kbuf;
194 int flags = 0;
195
196 switch (size) {
197 case KBUFFER_LSIZE_4:
198 break;
199 case KBUFFER_LSIZE_SAME_AS_HOST:
200 if (sizeof(long) != 8 && host_is_32bit())
201 break;
202 /* fallthrough */
203 case KBUFFER_LSIZE_8:
204 flags |= KBUFFER_FL_LONG_8;
205 break;
206 default:
207 return NULL;
208 }
209
210 switch (endian) {
211 case KBUFFER_ENDIAN_LITTLE:
212 case KBUFFER_ENDIAN_SAME_AS_HOST:
213 break;
214 case KBUFFER_ENDIAN_BIG:
215 flags |= KBUFFER_FL_BIG_ENDIAN;
216 break;
217 default:
218 return NULL;
219 }
220
221 kbuf = zmalloc(sizeof(*kbuf));
222 if (!kbuf)
223 return NULL;
224
225 kbuf->flags = flags;
226
227 if (host_is_bigendian()) {
228 if (endian == KBUFFER_ENDIAN_SAME_AS_HOST)
229 flags |= KBUFFER_FL_BIG_ENDIAN;
230 kbuf->flags |= KBUFFER_FL_HOST_BIG_ENDIAN;
231 }
232
233 if (do_swap(kbuf)) {
234 kbuf->read_8 = __read_8_sw;
235 kbuf->read_4 = __read_4_sw;
236 } else {
237 kbuf->read_8 = __read_8;
238 kbuf->read_4 = __read_4;
239 }
240
241 if (kbuf->flags & KBUFFER_FL_LONG_8)
242 kbuf->read_long = __read_long_8;
243 else
244 kbuf->read_long = __read_long_4;
245
246 /* May be changed by kbuffer_set_old_format() */
247 kbuf->next_event = __next_event;
248
249 return kbuf;
250 }
251
252 /** kbuffer_free - free an allocated kbuffer
253 * @kbuf: The kbuffer to free
254 *
255 * Can take NULL as a parameter.
256 */
kbuffer_free(struct kbuffer * kbuf)257 void kbuffer_free(struct kbuffer *kbuf)
258 {
259 free(kbuf);
260 }
261
type4host(struct kbuffer * kbuf,unsigned int type_len_ts)262 static unsigned int type4host(struct kbuffer *kbuf,
263 unsigned int type_len_ts)
264 {
265 if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
266 return (type_len_ts >> 29) & 3;
267 else
268 return type_len_ts & 3;
269 }
270
len4host(struct kbuffer * kbuf,unsigned int type_len_ts)271 static unsigned int len4host(struct kbuffer *kbuf,
272 unsigned int type_len_ts)
273 {
274 if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
275 return (type_len_ts >> 27) & 7;
276 else
277 return (type_len_ts >> 2) & 7;
278 }
279
type_len4host(struct kbuffer * kbuf,unsigned int type_len_ts)280 static unsigned int type_len4host(struct kbuffer *kbuf,
281 unsigned int type_len_ts)
282 {
283 if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
284 return (type_len_ts >> 27) & ((1 << 5) - 1);
285 else
286 return type_len_ts & ((1 << 5) - 1);
287 }
288
ts4host(struct kbuffer * kbuf,unsigned int type_len_ts)289 static unsigned int ts4host(struct kbuffer *kbuf,
290 unsigned int type_len_ts)
291 {
292 if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
293 return type_len_ts & ((1 << 27) - 1);
294 else
295 return type_len_ts >> 5;
296 }
297
298 /*
299 * Linux 2.6.30 and earlier (not much ealier) had a different
300 * ring buffer format. It should be obsolete, but we handle it anyway.
301 */
302 enum old_ring_buffer_type {
303 OLD_RINGBUF_TYPE_PADDING,
304 OLD_RINGBUF_TYPE_TIME_EXTEND,
305 OLD_RINGBUF_TYPE_TIME_STAMP,
306 OLD_RINGBUF_TYPE_DATA,
307 };
308
old_update_pointers(struct kbuffer * kbuf)309 static unsigned int old_update_pointers(struct kbuffer *kbuf)
310 {
311 unsigned long long extend;
312 unsigned int type_len_ts;
313 unsigned int type;
314 unsigned int len;
315 unsigned int delta;
316 unsigned int length;
317 void *ptr = kbuf->data + kbuf->curr;
318
319 type_len_ts = read_4(kbuf, ptr);
320 ptr += 4;
321
322 type = type4host(kbuf, type_len_ts);
323 len = len4host(kbuf, type_len_ts);
324 delta = ts4host(kbuf, type_len_ts);
325
326 switch (type) {
327 case OLD_RINGBUF_TYPE_PADDING:
328 kbuf->next = kbuf->size;
329 return 0;
330
331 case OLD_RINGBUF_TYPE_TIME_EXTEND:
332 extend = read_4(kbuf, ptr);
333 extend <<= TS_SHIFT;
334 extend += delta;
335 delta = extend;
336 ptr += 4;
337 length = 0;
338 break;
339
340 case OLD_RINGBUF_TYPE_TIME_STAMP:
341 /* should never happen! */
342 kbuf->curr = kbuf->size;
343 kbuf->next = kbuf->size;
344 kbuf->index = kbuf->size;
345 return -1;
346 default:
347 if (len)
348 length = len * 4;
349 else {
350 length = read_4(kbuf, ptr);
351 length -= 4;
352 ptr += 4;
353 }
354 break;
355 }
356
357 kbuf->timestamp += delta;
358 kbuf->index = calc_index(kbuf, ptr);
359 kbuf->next = kbuf->index + length;
360
361 return type;
362 }
363
__old_next_event(struct kbuffer * kbuf)364 static int __old_next_event(struct kbuffer *kbuf)
365 {
366 int type;
367
368 do {
369 kbuf->curr = kbuf->next;
370 if (kbuf->next >= kbuf->size)
371 return -1;
372 type = old_update_pointers(kbuf);
373 } while (type == OLD_RINGBUF_TYPE_TIME_EXTEND || type == OLD_RINGBUF_TYPE_PADDING);
374
375 return 0;
376 }
377
378 static unsigned int
translate_data(struct kbuffer * kbuf,void * data,void ** rptr,unsigned long long * delta,int * length)379 translate_data(struct kbuffer *kbuf, void *data, void **rptr,
380 unsigned long long *delta, int *length)
381 {
382 unsigned long long extend, msb = 0;
383 unsigned int type_len_ts;
384 unsigned int type_len;
385
386 type_len_ts = read_4(kbuf, data);
387 data += 4;
388
389 type_len = type_len4host(kbuf, type_len_ts);
390 *delta = ts4host(kbuf, type_len_ts);
391
392 switch (type_len) {
393 case KBUFFER_TYPE_PADDING:
394 *length = read_4(kbuf, data);
395 break;
396
397 case KBUFFER_TYPE_TIME_STAMP:
398 msb = kbuf->timestamp & TS_MSB;
399 /* fall through */
400 case KBUFFER_TYPE_TIME_EXTEND:
401 extend = read_4(kbuf, data);
402 data += 4;
403 extend <<= TS_SHIFT;
404 extend += *delta;
405 *delta = extend | msb;
406 *length = 0;
407 break;
408
409 case 0:
410 *length = read_4(kbuf, data) - 4;
411 *length = (*length + 3) & ~3;
412 data += 4;
413 break;
414 default:
415 *length = type_len * 4;
416 break;
417 }
418
419 *rptr = data;
420
421 return type_len;
422 }
423
update_pointers(struct kbuffer * kbuf)424 static unsigned int update_pointers(struct kbuffer *kbuf)
425 {
426 unsigned long long delta;
427 unsigned int type_len;
428 int length;
429 void *ptr = kbuf->data + kbuf->curr;
430
431 type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
432
433 if (type_len == KBUFFER_TYPE_TIME_STAMP)
434 kbuf->timestamp = delta;
435 else
436 kbuf->timestamp += delta;
437
438 kbuf->index = calc_index(kbuf, ptr);
439 kbuf->next = kbuf->index + length;
440
441 return type_len;
442 }
443
444 /**
445 * kbuffer_translate_data - read raw data to get a record
446 * @swap: Set to 1 if bytes in words need to be swapped when read
447 * @data: The raw data to read
448 * @size: Address to store the size of the event data.
449 *
450 * Returns a pointer to the event data. To determine the entire
451 * record size (record metadata + data) just add the difference between
452 * @data and the returned value to @size.
453 */
kbuffer_translate_data(int swap,void * data,unsigned int * size)454 void *kbuffer_translate_data(int swap, void *data, unsigned int *size)
455 {
456 unsigned long long delta;
457 struct kbuffer kbuf;
458 int type_len;
459 int length;
460 void *ptr;
461
462 if (swap) {
463 kbuf.read_8 = __read_8_sw;
464 kbuf.read_4 = __read_4_sw;
465 kbuf.flags = host_is_bigendian() ? 0 : KBUFFER_FL_BIG_ENDIAN;
466 } else {
467 kbuf.read_8 = __read_8;
468 kbuf.read_4 = __read_4;
469 kbuf.flags = host_is_bigendian() ? KBUFFER_FL_BIG_ENDIAN: 0;
470 }
471
472 type_len = translate_data(&kbuf, data, &ptr, &delta, &length);
473 switch (type_len) {
474 case KBUFFER_TYPE_PADDING:
475 case KBUFFER_TYPE_TIME_EXTEND:
476 case KBUFFER_TYPE_TIME_STAMP:
477 return NULL;
478 }
479
480 *size = length;
481
482 return ptr;
483 }
484
__next_event(struct kbuffer * kbuf)485 static int __next_event(struct kbuffer *kbuf)
486 {
487 int type;
488
489 do {
490 kbuf->curr = kbuf->next;
491 if (kbuf->next >= kbuf->size)
492 return -1;
493 type = update_pointers(kbuf);
494 } while (type == KBUFFER_TYPE_TIME_EXTEND ||
495 type == KBUFFER_TYPE_TIME_STAMP ||
496 type == KBUFFER_TYPE_PADDING);
497
498 return 0;
499 }
500
next_event(struct kbuffer * kbuf)501 static int next_event(struct kbuffer *kbuf)
502 {
503 return kbuf->next_event(kbuf);
504 }
505
506 /**
507 * kbuffer_next_event - increment the current pointer
508 * @kbuf: The kbuffer to read
509 * @ts: Address to store the next record's timestamp (may be NULL to ignore)
510 *
511 * Increments the pointers into the subbuffer of the kbuffer to point to the
512 * next event so that the next kbuffer_read_event() will return a
513 * new event.
514 *
515 * Returns the data of the next event if a new event exists on the subbuffer,
516 * NULL otherwise.
517 */
kbuffer_next_event(struct kbuffer * kbuf,unsigned long long * ts)518 void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts)
519 {
520 int ret;
521
522 if (!kbuf || !kbuf->subbuffer)
523 return NULL;
524
525 ret = next_event(kbuf);
526 if (ret < 0)
527 return NULL;
528
529 if (ts)
530 *ts = kbuf->timestamp;
531
532 return kbuf->data + kbuf->index;
533 }
534
535 /**
536 * kbuffer_load_subbuffer - load a new subbuffer into the kbuffer
537 * @kbuf: The kbuffer to load
538 * @subbuffer: The subbuffer to load into @kbuf.
539 *
540 * Load a new subbuffer (page) into @kbuf. This will reset all
541 * the pointers and update the @kbuf timestamp. The next read will
542 * return the first event on @subbuffer.
543 *
544 * Returns 0 on succes, -1 otherwise.
545 */
kbuffer_load_subbuffer(struct kbuffer * kbuf,void * subbuffer)546 int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer)
547 {
548 unsigned long long flags;
549 void *ptr = subbuffer;
550
551 if (!kbuf || !subbuffer)
552 return -1;
553
554 kbuf->subbuffer = subbuffer;
555
556 kbuf->timestamp = read_8(kbuf, ptr);
557 ptr += 8;
558
559 kbuf->curr = 0;
560
561 if (kbuf->flags & KBUFFER_FL_LONG_8)
562 kbuf->start = 16;
563 else
564 kbuf->start = 12;
565
566 kbuf->data = subbuffer + kbuf->start;
567
568 flags = read_long(kbuf, ptr);
569 kbuf->size = (unsigned int)flags & COMMIT_MASK;
570
571 if (flags & MISSING_EVENTS) {
572 if (flags & MISSING_STORED) {
573 ptr = kbuf->data + kbuf->size;
574 kbuf->lost_events = read_long(kbuf, ptr);
575 } else
576 kbuf->lost_events = -1;
577 } else
578 kbuf->lost_events = 0;
579
580 kbuf->index = 0;
581 kbuf->next = 0;
582
583 next_event(kbuf);
584
585 /* save the first record from the page */
586 kbuf->first = kbuf->curr;
587
588 return 0;
589 }
590
591 /**
592 * kbuffer_subbuf_timestamp - read the timestamp from a sub buffer
593 * @kbuf: The kbuffer to load
594 * @subbuf: The subbuffer to read from.
595 *
596 * Return the timestamp from a subbuffer.
597 */
kbuffer_subbuf_timestamp(struct kbuffer * kbuf,void * subbuf)598 unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf)
599 {
600 return kbuf->read_8(subbuf);
601 }
602
603 /**
604 * kbuffer_ptr_delta - read the delta field from a record
605 * @kbuf: The kbuffer to load
606 * @ptr: The record in the buffe.
607 *
608 * Return the timestamp delta from a record
609 */
kbuffer_ptr_delta(struct kbuffer * kbuf,void * ptr)610 unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr)
611 {
612 unsigned int type_len_ts;
613
614 type_len_ts = read_4(kbuf, ptr);
615 return ts4host(kbuf, type_len_ts);
616 }
617
618
619 /**
620 * kbuffer_read_event - read the next event in the kbuffer subbuffer
621 * @kbuf: The kbuffer to read from
622 * @ts: The address to store the timestamp of the event (may be NULL to ignore)
623 *
624 * Returns a pointer to the data part of the current event.
625 * NULL if no event is left on the subbuffer.
626 */
kbuffer_read_event(struct kbuffer * kbuf,unsigned long long * ts)627 void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts)
628 {
629 if (!kbuf || !kbuf->subbuffer)
630 return NULL;
631
632 if (kbuf->curr >= kbuf->size)
633 return NULL;
634
635 if (ts)
636 *ts = kbuf->timestamp;
637 return kbuf->data + kbuf->index;
638 }
639
640 /**
641 * kbuffer_timestamp - Return the timestamp of the current event
642 * @kbuf: The kbuffer to read from
643 *
644 * Returns the timestamp of the current (next) event.
645 */
kbuffer_timestamp(struct kbuffer * kbuf)646 unsigned long long kbuffer_timestamp(struct kbuffer *kbuf)
647 {
648 return kbuf->timestamp;
649 }
650
651 /**
652 * kbuffer_read_at_offset - read the event that is at offset
653 * @kbuf: The kbuffer to read from
654 * @offset: The offset into the subbuffer
655 * @ts: The address to store the timestamp of the event (may be NULL to ignore)
656 *
657 * The @offset must be an index from the @kbuf subbuffer beginning.
658 * If @offset is bigger than the stored subbuffer, NULL will be returned.
659 *
660 * Returns the data of the record that is at @offset. Note, @offset does
661 * not need to be the start of the record, the offset just needs to be
662 * in the record (or beginning of it).
663 *
664 * Note, the kbuf timestamp and pointers are updated to the
665 * returned record. That is, kbuffer_read_event() will return the same
666 * data and timestamp, and kbuffer_next_event() will increment from
667 * this record.
668 */
kbuffer_read_at_offset(struct kbuffer * kbuf,int offset,unsigned long long * ts)669 void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset,
670 unsigned long long *ts)
671 {
672 void *data;
673
674 if (offset < kbuf->start)
675 offset = 0;
676 else
677 offset -= kbuf->start;
678
679 /* Reset the buffer */
680 kbuffer_load_subbuffer(kbuf, kbuf->subbuffer);
681 data = kbuffer_read_event(kbuf, ts);
682
683 while (kbuf->curr < offset) {
684 data = kbuffer_next_event(kbuf, ts);
685 if (!data)
686 break;
687 }
688
689 return data;
690 }
691
692 /**
693 * kbuffer_subbuffer_size - the size of the loaded subbuffer
694 * @kbuf: The kbuffer to read from
695 *
696 * Returns the size of the subbuffer. Note, this size is
697 * where the last event resides. The stored subbuffer may actually be
698 * bigger due to padding and such.
699 */
kbuffer_subbuffer_size(struct kbuffer * kbuf)700 int kbuffer_subbuffer_size(struct kbuffer *kbuf)
701 {
702 return kbuf->size;
703 }
704
705 /**
706 * kbuffer_curr_index - Return the index of the record
707 * @kbuf: The kbuffer to read from
708 *
709 * Returns the index from the start of the data part of
710 * the subbuffer to the current location. Note this is not
711 * from the start of the subbuffer. An index of zero will
712 * point to the first record. Use kbuffer_curr_offset() for
713 * the actually offset (that can be used by kbuffer_read_at_offset())
714 */
kbuffer_curr_index(struct kbuffer * kbuf)715 int kbuffer_curr_index(struct kbuffer *kbuf)
716 {
717 return kbuf->curr;
718 }
719
720 /**
721 * kbuffer_curr_offset - Return the offset of the record
722 * @kbuf: The kbuffer to read from
723 *
724 * Returns the offset from the start of the subbuffer to the
725 * current location.
726 */
kbuffer_curr_offset(struct kbuffer * kbuf)727 int kbuffer_curr_offset(struct kbuffer *kbuf)
728 {
729 return kbuf->curr + kbuf->start;
730 }
731
732 /**
733 * kbuffer_event_size - return the size of the event data
734 * @kbuf: The kbuffer to read
735 *
736 * Returns the size of the event data (the payload not counting
737 * the meta data of the record) of the current event.
738 */
kbuffer_event_size(struct kbuffer * kbuf)739 int kbuffer_event_size(struct kbuffer *kbuf)
740 {
741 return kbuf->next - kbuf->index;
742 }
743
744 /**
745 * kbuffer_curr_size - return the size of the entire record
746 * @kbuf: The kbuffer to read
747 *
748 * Returns the size of the entire record (meta data and payload)
749 * of the current event.
750 */
kbuffer_curr_size(struct kbuffer * kbuf)751 int kbuffer_curr_size(struct kbuffer *kbuf)
752 {
753 return kbuf->next - kbuf->curr;
754 }
755
756 /**
757 * kbuffer_missed_events - return the # of missed events from last event.
758 * @kbuf: The kbuffer to read from
759 *
760 * Returns the # of missed events (if recorded) before the current
761 * event. Note, only events on the beginning of a subbuffer can
762 * have missed events, all other events within the buffer will be
763 * zero.
764 */
kbuffer_missed_events(struct kbuffer * kbuf)765 int kbuffer_missed_events(struct kbuffer *kbuf)
766 {
767 /* Only the first event can have missed events */
768 if (kbuf->curr)
769 return 0;
770
771 return kbuf->lost_events;
772 }
773
774 /**
775 * kbuffer_set_old_forma - set the kbuffer to use the old format parsing
776 * @kbuf: The kbuffer to set
777 *
778 * This is obsolete (or should be). The first kernels to use the
779 * new ring buffer had a slightly different ring buffer format
780 * (2.6.30 and earlier). It is still somewhat supported by kbuffer,
781 * but should not be counted on in the future.
782 */
kbuffer_set_old_format(struct kbuffer * kbuf)783 void kbuffer_set_old_format(struct kbuffer *kbuf)
784 {
785 kbuf->flags |= KBUFFER_FL_OLD_FORMAT;
786
787 kbuf->next_event = __old_next_event;
788 }
789
790 /**
791 * kbuffer_start_of_data - return offset of where data starts on subbuffer
792 * @kbuf: The kbuffer
793 *
794 * Returns the location on the subbuffer where the data starts.
795 */
kbuffer_start_of_data(struct kbuffer * kbuf)796 int kbuffer_start_of_data(struct kbuffer *kbuf)
797 {
798 return kbuf->first + kbuf->start;
799 }
800
801 /**
802 * kbuffer_raw_get - get raw buffer info
803 * @kbuf: The kbuffer
804 * @subbuf: Start of mapped subbuffer
805 * @info: Info descriptor to fill in
806 *
807 * For debugging. This can return internals of the ring buffer.
808 * Expects to have info->next set to what it will read.
809 * The type, length and timestamp delta will be filled in, and
810 * @info->next will be updated to the next element.
811 * The @subbuf is used to know if the info is passed the end of
812 * data and NULL will be returned if it is.
813 */
814 struct kbuffer_raw_info *
kbuffer_raw_get(struct kbuffer * kbuf,void * subbuf,struct kbuffer_raw_info * info)815 kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, struct kbuffer_raw_info *info)
816 {
817 unsigned long long flags;
818 unsigned long long delta;
819 unsigned int type_len;
820 unsigned int size;
821 int start;
822 int length;
823 void *ptr = info->next;
824
825 if (!kbuf || !subbuf)
826 return NULL;
827
828 if (kbuf->flags & KBUFFER_FL_LONG_8)
829 start = 16;
830 else
831 start = 12;
832
833 flags = read_long(kbuf, subbuf + 8);
834 size = (unsigned int)flags & COMMIT_MASK;
835
836 if (ptr < subbuf || ptr >= subbuf + start + size)
837 return NULL;
838
839 type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
840
841 info->next = ptr + length;
842
843 info->type = type_len;
844 info->delta = delta;
845 info->length = length;
846
847 return info;
848 }
849