Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: LGPL-2.1
0002 /*
0003  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
0004  *
0005  */
0006 #include <stdio.h>
0007 #include <stdlib.h>
0008 #include <string.h>
0009 
0010 #include "kbuffer.h"
0011 
0012 #define MISSING_EVENTS (1UL << 31)
0013 #define MISSING_STORED (1UL << 30)
0014 
0015 #define COMMIT_MASK ((1 << 27) - 1)
0016 
0017 enum {
0018     KBUFFER_FL_HOST_BIG_ENDIAN  = (1<<0),
0019     KBUFFER_FL_BIG_ENDIAN       = (1<<1),
0020     KBUFFER_FL_LONG_8       = (1<<2),
0021     KBUFFER_FL_OLD_FORMAT       = (1<<3),
0022 };
0023 
0024 #define ENDIAN_MASK (KBUFFER_FL_HOST_BIG_ENDIAN | KBUFFER_FL_BIG_ENDIAN)
0025 
0026 /** kbuffer
0027  * @timestamp       - timestamp of current event
0028  * @lost_events     - # of lost events between this subbuffer and previous
0029  * @flags       - special flags of the kbuffer
0030  * @subbuffer       - pointer to the sub-buffer page
0031  * @data        - pointer to the start of data on the sub-buffer page
0032  * @index       - index from @data to the @curr event data
0033  * @curr        - offset from @data to the start of current event
0034  *             (includes metadata)
0035  * @next        - offset from @data to the start of next event
0036  * @size        - The size of data on @data
0037  * @start       - The offset from @subbuffer where @data lives
0038  *
0039  * @read_4      - Function to read 4 raw bytes (may swap)
0040  * @read_8      - Function to read 8 raw bytes (may swap)
0041  * @read_long       - Function to read a long word (4 or 8 bytes with needed swap)
0042  */
0043 struct kbuffer {
0044     unsigned long long  timestamp;
0045     long long       lost_events;
0046     unsigned long       flags;
0047     void            *subbuffer;
0048     void            *data;
0049     unsigned int        index;
0050     unsigned int        curr;
0051     unsigned int        next;
0052     unsigned int        size;
0053     unsigned int        start;
0054 
0055     unsigned int (*read_4)(void *ptr);
0056     unsigned long long (*read_8)(void *ptr);
0057     unsigned long long (*read_long)(struct kbuffer *kbuf, void *ptr);
0058     int (*next_event)(struct kbuffer *kbuf);
0059 };
0060 
0061 static void *zmalloc(size_t size)
0062 {
0063     return calloc(1, size);
0064 }
0065 
0066 static int host_is_bigendian(void)
0067 {
0068     unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
0069     unsigned int *ptr;
0070 
0071     ptr = (unsigned int *)str;
0072     return *ptr == 0x01020304;
0073 }
0074 
0075 static int do_swap(struct kbuffer *kbuf)
0076 {
0077     return ((kbuf->flags & KBUFFER_FL_HOST_BIG_ENDIAN) + kbuf->flags) &
0078         ENDIAN_MASK;
0079 }
0080 
0081 static unsigned long long __read_8(void *ptr)
0082 {
0083     unsigned long long data = *(unsigned long long *)ptr;
0084 
0085     return data;
0086 }
0087 
0088 static unsigned long long __read_8_sw(void *ptr)
0089 {
0090     unsigned long long data = *(unsigned long long *)ptr;
0091     unsigned long long swap;
0092 
0093     swap = ((data & 0xffULL) << 56) |
0094         ((data & (0xffULL << 8)) << 40) |
0095         ((data & (0xffULL << 16)) << 24) |
0096         ((data & (0xffULL << 24)) << 8) |
0097         ((data & (0xffULL << 32)) >> 8) |
0098         ((data & (0xffULL << 40)) >> 24) |
0099         ((data & (0xffULL << 48)) >> 40) |
0100         ((data & (0xffULL << 56)) >> 56);
0101 
0102     return swap;
0103 }
0104 
0105 static unsigned int __read_4(void *ptr)
0106 {
0107     unsigned int data = *(unsigned int *)ptr;
0108 
0109     return data;
0110 }
0111 
0112 static unsigned int __read_4_sw(void *ptr)
0113 {
0114     unsigned int data = *(unsigned int *)ptr;
0115     unsigned int swap;
0116 
0117     swap = ((data & 0xffULL) << 24) |
0118         ((data & (0xffULL << 8)) << 8) |
0119         ((data & (0xffULL << 16)) >> 8) |
0120         ((data & (0xffULL << 24)) >> 24);
0121 
0122     return swap;
0123 }
0124 
0125 static unsigned long long read_8(struct kbuffer *kbuf, void *ptr)
0126 {
0127     return kbuf->read_8(ptr);
0128 }
0129 
0130 static unsigned int read_4(struct kbuffer *kbuf, void *ptr)
0131 {
0132     return kbuf->read_4(ptr);
0133 }
0134 
0135 static unsigned long long __read_long_8(struct kbuffer *kbuf, void *ptr)
0136 {
0137     return kbuf->read_8(ptr);
0138 }
0139 
0140 static unsigned long long __read_long_4(struct kbuffer *kbuf, void *ptr)
0141 {
0142     return kbuf->read_4(ptr);
0143 }
0144 
0145 static unsigned long long read_long(struct kbuffer *kbuf, void *ptr)
0146 {
0147     return kbuf->read_long(kbuf, ptr);
0148 }
0149 
0150 static int calc_index(struct kbuffer *kbuf, void *ptr)
0151 {
0152     return (unsigned long)ptr - (unsigned long)kbuf->data;
0153 }
0154 
0155 static int __next_event(struct kbuffer *kbuf);
0156 
0157 /**
0158  * kbuffer_alloc - allocat a new kbuffer
0159  * @size;   enum to denote size of word
0160  * @endian: enum to denote endianness
0161  *
0162  * Allocates and returns a new kbuffer.
0163  */
0164 struct kbuffer *
0165 kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian)
0166 {
0167     struct kbuffer *kbuf;
0168     int flags = 0;
0169 
0170     switch (size) {
0171     case KBUFFER_LSIZE_4:
0172         break;
0173     case KBUFFER_LSIZE_8:
0174         flags |= KBUFFER_FL_LONG_8;
0175         break;
0176     default:
0177         return NULL;
0178     }
0179 
0180     switch (endian) {
0181     case KBUFFER_ENDIAN_LITTLE:
0182         break;
0183     case KBUFFER_ENDIAN_BIG:
0184         flags |= KBUFFER_FL_BIG_ENDIAN;
0185         break;
0186     default:
0187         return NULL;
0188     }
0189 
0190     kbuf = zmalloc(sizeof(*kbuf));
0191     if (!kbuf)
0192         return NULL;
0193 
0194     kbuf->flags = flags;
0195 
0196     if (host_is_bigendian())
0197         kbuf->flags |= KBUFFER_FL_HOST_BIG_ENDIAN;
0198 
0199     if (do_swap(kbuf)) {
0200         kbuf->read_8 = __read_8_sw;
0201         kbuf->read_4 = __read_4_sw;
0202     } else {
0203         kbuf->read_8 = __read_8;
0204         kbuf->read_4 = __read_4;
0205     }
0206 
0207     if (kbuf->flags & KBUFFER_FL_LONG_8)
0208         kbuf->read_long = __read_long_8;
0209     else
0210         kbuf->read_long = __read_long_4;
0211 
0212     /* May be changed by kbuffer_set_old_format() */
0213     kbuf->next_event = __next_event;
0214 
0215     return kbuf;
0216 }
0217 
0218 /** kbuffer_free - free an allocated kbuffer
0219  * @kbuf:   The kbuffer to free
0220  *
0221  * Can take NULL as a parameter.
0222  */
0223 void kbuffer_free(struct kbuffer *kbuf)
0224 {
0225     free(kbuf);
0226 }
0227 
0228 static unsigned int type4host(struct kbuffer *kbuf,
0229                   unsigned int type_len_ts)
0230 {
0231     if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
0232         return (type_len_ts >> 29) & 3;
0233     else
0234         return type_len_ts & 3;
0235 }
0236 
0237 static unsigned int len4host(struct kbuffer *kbuf,
0238                  unsigned int type_len_ts)
0239 {
0240     if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
0241         return (type_len_ts >> 27) & 7;
0242     else
0243         return (type_len_ts >> 2) & 7;
0244 }
0245 
0246 static unsigned int type_len4host(struct kbuffer *kbuf,
0247                   unsigned int type_len_ts)
0248 {
0249     if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
0250         return (type_len_ts >> 27) & ((1 << 5) - 1);
0251     else
0252         return type_len_ts & ((1 << 5) - 1);
0253 }
0254 
0255 static unsigned int ts4host(struct kbuffer *kbuf,
0256                 unsigned int type_len_ts)
0257 {
0258     if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
0259         return type_len_ts & ((1 << 27) - 1);
0260     else
0261         return type_len_ts >> 5;
0262 }
0263 
0264 /*
0265  * Linux 2.6.30 and earlier (not much ealier) had a different
0266  * ring buffer format. It should be obsolete, but we handle it anyway.
0267  */
0268 enum old_ring_buffer_type {
0269     OLD_RINGBUF_TYPE_PADDING,
0270     OLD_RINGBUF_TYPE_TIME_EXTEND,
0271     OLD_RINGBUF_TYPE_TIME_STAMP,
0272     OLD_RINGBUF_TYPE_DATA,
0273 };
0274 
0275 static unsigned int old_update_pointers(struct kbuffer *kbuf)
0276 {
0277     unsigned long long extend;
0278     unsigned int type_len_ts;
0279     unsigned int type;
0280     unsigned int len;
0281     unsigned int delta;
0282     unsigned int length;
0283     void *ptr = kbuf->data + kbuf->curr;
0284 
0285     type_len_ts = read_4(kbuf, ptr);
0286     ptr += 4;
0287 
0288     type = type4host(kbuf, type_len_ts);
0289     len = len4host(kbuf, type_len_ts);
0290     delta = ts4host(kbuf, type_len_ts);
0291 
0292     switch (type) {
0293     case OLD_RINGBUF_TYPE_PADDING:
0294         kbuf->next = kbuf->size;
0295         return 0;
0296 
0297     case OLD_RINGBUF_TYPE_TIME_EXTEND:
0298         extend = read_4(kbuf, ptr);
0299         extend <<= TS_SHIFT;
0300         extend += delta;
0301         delta = extend;
0302         ptr += 4;
0303         length = 0;
0304         break;
0305 
0306     case OLD_RINGBUF_TYPE_TIME_STAMP:
0307         /* should never happen! */
0308         kbuf->curr = kbuf->size;
0309         kbuf->next = kbuf->size;
0310         kbuf->index = kbuf->size;
0311         return -1;
0312     default:
0313         if (len)
0314             length = len * 4;
0315         else {
0316             length = read_4(kbuf, ptr);
0317             length -= 4;
0318             ptr += 4;
0319         }
0320         break;
0321     }
0322 
0323     kbuf->timestamp += delta;
0324     kbuf->index = calc_index(kbuf, ptr);
0325     kbuf->next = kbuf->index + length;
0326 
0327     return type;
0328 }
0329 
0330 static int __old_next_event(struct kbuffer *kbuf)
0331 {
0332     int type;
0333 
0334     do {
0335         kbuf->curr = kbuf->next;
0336         if (kbuf->next >= kbuf->size)
0337             return -1;
0338         type = old_update_pointers(kbuf);
0339     } while (type == OLD_RINGBUF_TYPE_TIME_EXTEND || type == OLD_RINGBUF_TYPE_PADDING);
0340 
0341     return 0;
0342 }
0343 
0344 static unsigned int
0345 translate_data(struct kbuffer *kbuf, void *data, void **rptr,
0346            unsigned long long *delta, int *length)
0347 {
0348     unsigned long long extend;
0349     unsigned int type_len_ts;
0350     unsigned int type_len;
0351 
0352     type_len_ts = read_4(kbuf, data);
0353     data += 4;
0354 
0355     type_len = type_len4host(kbuf, type_len_ts);
0356     *delta = ts4host(kbuf, type_len_ts);
0357 
0358     switch (type_len) {
0359     case KBUFFER_TYPE_PADDING:
0360         *length = read_4(kbuf, data);
0361         break;
0362 
0363     case KBUFFER_TYPE_TIME_EXTEND:
0364     case KBUFFER_TYPE_TIME_STAMP:
0365         extend = read_4(kbuf, data);
0366         data += 4;
0367         extend <<= TS_SHIFT;
0368         extend += *delta;
0369         *delta = extend;
0370         *length = 0;
0371         break;
0372 
0373     case 0:
0374         *length = read_4(kbuf, data) - 4;
0375         *length = (*length + 3) & ~3;
0376         data += 4;
0377         break;
0378     default:
0379         *length = type_len * 4;
0380         break;
0381     }
0382 
0383     *rptr = data;
0384 
0385     return type_len;
0386 }
0387 
0388 static unsigned int update_pointers(struct kbuffer *kbuf)
0389 {
0390     unsigned long long delta;
0391     unsigned int type_len;
0392     int length;
0393     void *ptr = kbuf->data + kbuf->curr;
0394 
0395     type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
0396 
0397     if (type_len == KBUFFER_TYPE_TIME_STAMP)
0398         kbuf->timestamp = delta;
0399     else
0400         kbuf->timestamp += delta;
0401 
0402     kbuf->index = calc_index(kbuf, ptr);
0403     kbuf->next = kbuf->index + length;
0404 
0405     return type_len;
0406 }
0407 
0408 /**
0409  * kbuffer_translate_data - read raw data to get a record
0410  * @swap:   Set to 1 if bytes in words need to be swapped when read
0411  * @data:   The raw data to read
0412  * @size:   Address to store the size of the event data.
0413  *
0414  * Returns a pointer to the event data. To determine the entire
0415  * record size (record metadata + data) just add the difference between
0416  * @data and the returned value to @size.
0417  */
0418 void *kbuffer_translate_data(int swap, void *data, unsigned int *size)
0419 {
0420     unsigned long long delta;
0421     struct kbuffer kbuf;
0422     int type_len;
0423     int length;
0424     void *ptr;
0425 
0426     if (swap) {
0427         kbuf.read_8 = __read_8_sw;
0428         kbuf.read_4 = __read_4_sw;
0429         kbuf.flags = host_is_bigendian() ? 0 : KBUFFER_FL_BIG_ENDIAN;
0430     } else {
0431         kbuf.read_8 = __read_8;
0432         kbuf.read_4 = __read_4;
0433         kbuf.flags = host_is_bigendian() ? KBUFFER_FL_BIG_ENDIAN: 0;
0434     }
0435 
0436     type_len = translate_data(&kbuf, data, &ptr, &delta, &length);
0437     switch (type_len) {
0438     case KBUFFER_TYPE_PADDING:
0439     case KBUFFER_TYPE_TIME_EXTEND:
0440     case KBUFFER_TYPE_TIME_STAMP:
0441         return NULL;
0442     }
0443 
0444     *size = length;
0445 
0446     return ptr;
0447 }
0448 
0449 static int __next_event(struct kbuffer *kbuf)
0450 {
0451     int type;
0452 
0453     do {
0454         kbuf->curr = kbuf->next;
0455         if (kbuf->next >= kbuf->size)
0456             return -1;
0457         type = update_pointers(kbuf);
0458     } while (type == KBUFFER_TYPE_TIME_EXTEND ||
0459          type == KBUFFER_TYPE_TIME_STAMP ||
0460          type == KBUFFER_TYPE_PADDING);
0461 
0462     return 0;
0463 }
0464 
0465 static int next_event(struct kbuffer *kbuf)
0466 {
0467     return kbuf->next_event(kbuf);
0468 }
0469 
0470 /**
0471  * kbuffer_next_event - increment the current pointer
0472  * @kbuf:   The kbuffer to read
0473  * @ts:     Address to store the next record's timestamp (may be NULL to ignore)
0474  *
0475  * Increments the pointers into the subbuffer of the kbuffer to point to the
0476  * next event so that the next kbuffer_read_event() will return a
0477  * new event.
0478  *
0479  * Returns the data of the next event if a new event exists on the subbuffer,
0480  * NULL otherwise.
0481  */
0482 void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts)
0483 {
0484     int ret;
0485 
0486     if (!kbuf || !kbuf->subbuffer)
0487         return NULL;
0488 
0489     ret = next_event(kbuf);
0490     if (ret < 0)
0491         return NULL;
0492 
0493     if (ts)
0494         *ts = kbuf->timestamp;
0495 
0496     return kbuf->data + kbuf->index;
0497 }
0498 
0499 /**
0500  * kbuffer_load_subbuffer - load a new subbuffer into the kbuffer
0501  * @kbuf:   The kbuffer to load
0502  * @subbuffer:  The subbuffer to load into @kbuf.
0503  *
0504  * Load a new subbuffer (page) into @kbuf. This will reset all
0505  * the pointers and update the @kbuf timestamp. The next read will
0506  * return the first event on @subbuffer.
0507  *
0508  * Returns 0 on succes, -1 otherwise.
0509  */
0510 int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer)
0511 {
0512     unsigned long long flags;
0513     void *ptr = subbuffer;
0514 
0515     if (!kbuf || !subbuffer)
0516         return -1;
0517 
0518     kbuf->subbuffer = subbuffer;
0519 
0520     kbuf->timestamp = read_8(kbuf, ptr);
0521     ptr += 8;
0522 
0523     kbuf->curr = 0;
0524 
0525     if (kbuf->flags & KBUFFER_FL_LONG_8)
0526         kbuf->start = 16;
0527     else
0528         kbuf->start = 12;
0529 
0530     kbuf->data = subbuffer + kbuf->start;
0531 
0532     flags = read_long(kbuf, ptr);
0533     kbuf->size = (unsigned int)flags & COMMIT_MASK;
0534 
0535     if (flags & MISSING_EVENTS) {
0536         if (flags & MISSING_STORED) {
0537             ptr = kbuf->data + kbuf->size;
0538             kbuf->lost_events = read_long(kbuf, ptr);
0539         } else
0540             kbuf->lost_events = -1;
0541     } else
0542         kbuf->lost_events = 0;
0543 
0544     kbuf->index = 0;
0545     kbuf->next = 0;
0546 
0547     next_event(kbuf);
0548 
0549     return 0;
0550 }
0551 
0552 /**
0553  * kbuffer_subbuf_timestamp - read the timestamp from a sub buffer
0554  * @kbuf:      The kbuffer to load
0555  * @subbuf:    The subbuffer to read from.
0556  *
0557  * Return the timestamp from a subbuffer.
0558  */
0559 unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf)
0560 {
0561     return kbuf->read_8(subbuf);
0562 }
0563 
0564 /**
0565  * kbuffer_ptr_delta - read the delta field from a record
0566  * @kbuf:      The kbuffer to load
0567  * @ptr:       The record in the buffe.
0568  *
0569  * Return the timestamp delta from a record
0570  */
0571 unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr)
0572 {
0573     unsigned int type_len_ts;
0574 
0575     type_len_ts = read_4(kbuf, ptr);
0576     return ts4host(kbuf, type_len_ts);
0577 }
0578 
0579 
0580 /**
0581  * kbuffer_read_event - read the next event in the kbuffer subbuffer
0582  * @kbuf:   The kbuffer to read from
0583  * @ts:     The address to store the timestamp of the event (may be NULL to ignore)
0584  *
0585  * Returns a pointer to the data part of the current event.
0586  * NULL if no event is left on the subbuffer.
0587  */
0588 void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts)
0589 {
0590     if (!kbuf || !kbuf->subbuffer)
0591         return NULL;
0592 
0593     if (kbuf->curr >= kbuf->size)
0594         return NULL;
0595 
0596     if (ts)
0597         *ts = kbuf->timestamp;
0598     return kbuf->data + kbuf->index;
0599 }
0600 
0601 /**
0602  * kbuffer_timestamp - Return the timestamp of the current event
0603  * @kbuf:   The kbuffer to read from
0604  *
0605  * Returns the timestamp of the current (next) event.
0606  */
0607 unsigned long long kbuffer_timestamp(struct kbuffer *kbuf)
0608 {
0609     return kbuf->timestamp;
0610 }
0611 
0612 /**
0613  * kbuffer_read_at_offset - read the event that is at offset
0614  * @kbuf:   The kbuffer to read from
0615  * @offset: The offset into the subbuffer
0616  * @ts:     The address to store the timestamp of the event (may be NULL to ignore)
0617  *
0618  * The @offset must be an index from the @kbuf subbuffer beginning.
0619  * If @offset is bigger than the stored subbuffer, NULL will be returned.
0620  *
0621  * Returns the data of the record that is at @offset. Note, @offset does
0622  * not need to be the start of the record, the offset just needs to be
0623  * in the record (or beginning of it).
0624  *
0625  * Note, the kbuf timestamp and pointers are updated to the
0626  * returned record. That is, kbuffer_read_event() will return the same
0627  * data and timestamp, and kbuffer_next_event() will increment from
0628  * this record.
0629  */
0630 void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset,
0631                  unsigned long long *ts)
0632 {
0633     void *data;
0634 
0635     if (offset < kbuf->start)
0636         offset = 0;
0637     else
0638         offset -= kbuf->start;
0639 
0640     /* Reset the buffer */
0641     kbuffer_load_subbuffer(kbuf, kbuf->subbuffer);
0642     data = kbuffer_read_event(kbuf, ts);
0643 
0644     while (kbuf->curr < offset) {
0645         data = kbuffer_next_event(kbuf, ts);
0646         if (!data)
0647             break;
0648     }
0649 
0650     return data;
0651 }
0652 
0653 /**
0654  * kbuffer_subbuffer_size - the size of the loaded subbuffer
0655  * @kbuf:   The kbuffer to read from
0656  *
0657  * Returns the size of the subbuffer. Note, this size is
0658  * where the last event resides. The stored subbuffer may actually be
0659  * bigger due to padding and such.
0660  */
0661 int kbuffer_subbuffer_size(struct kbuffer *kbuf)
0662 {
0663     return kbuf->size;
0664 }
0665 
0666 /**
0667  * kbuffer_curr_index - Return the index of the record
0668  * @kbuf:   The kbuffer to read from
0669  *
0670  * Returns the index from the start of the data part of
0671  * the subbuffer to the current location. Note this is not
0672  * from the start of the subbuffer. An index of zero will
0673  * point to the first record. Use kbuffer_curr_offset() for
0674  * the actually offset (that can be used by kbuffer_read_at_offset())
0675  */
0676 int kbuffer_curr_index(struct kbuffer *kbuf)
0677 {
0678     return kbuf->curr;
0679 }
0680 
0681 /**
0682  * kbuffer_curr_offset - Return the offset of the record
0683  * @kbuf:   The kbuffer to read from
0684  *
0685  * Returns the offset from the start of the subbuffer to the
0686  * current location.
0687  */
0688 int kbuffer_curr_offset(struct kbuffer *kbuf)
0689 {
0690     return kbuf->curr + kbuf->start;
0691 }
0692 
0693 /**
0694  * kbuffer_event_size - return the size of the event data
0695  * @kbuf:   The kbuffer to read
0696  *
0697  * Returns the size of the event data (the payload not counting
0698  * the meta data of the record) of the current event.
0699  */
0700 int kbuffer_event_size(struct kbuffer *kbuf)
0701 {
0702     return kbuf->next - kbuf->index;
0703 }
0704 
0705 /**
0706  * kbuffer_curr_size - return the size of the entire record
0707  * @kbuf:   The kbuffer to read
0708  *
0709  * Returns the size of the entire record (meta data and payload)
0710  * of the current event.
0711  */
0712 int kbuffer_curr_size(struct kbuffer *kbuf)
0713 {
0714     return kbuf->next - kbuf->curr;
0715 }
0716 
0717 /**
0718  * kbuffer_missed_events - return the # of missed events from last event.
0719  * @kbuf:   The kbuffer to read from
0720  *
0721  * Returns the # of missed events (if recorded) before the current
0722  * event. Note, only events on the beginning of a subbuffer can
0723  * have missed events, all other events within the buffer will be
0724  * zero.
0725  */
0726 int kbuffer_missed_events(struct kbuffer *kbuf)
0727 {
0728     /* Only the first event can have missed events */
0729     if (kbuf->curr)
0730         return 0;
0731 
0732     return kbuf->lost_events;
0733 }
0734 
0735 /**
0736  * kbuffer_set_old_forma - set the kbuffer to use the old format parsing
0737  * @kbuf:   The kbuffer to set
0738  *
0739  * This is obsolete (or should be). The first kernels to use the
0740  * new ring buffer had a slightly different ring buffer format
0741  * (2.6.30 and earlier). It is still somewhat supported by kbuffer,
0742  * but should not be counted on in the future.
0743  */
0744 void kbuffer_set_old_format(struct kbuffer *kbuf)
0745 {
0746     kbuf->flags |= KBUFFER_FL_OLD_FORMAT;
0747 
0748     kbuf->next_event = __old_next_event;
0749 }
0750 
0751 /**
0752  * kbuffer_start_of_data - return offset of where data starts on subbuffer
0753  * @kbuf:   The kbuffer
0754  *
0755  * Returns the location on the subbuffer where the data starts.
0756  */
0757 int kbuffer_start_of_data(struct kbuffer *kbuf)
0758 {
0759     return kbuf->start;
0760 }
0761 
0762 /**
0763  * kbuffer_raw_get - get raw buffer info
0764  * @kbuf:   The kbuffer
0765  * @subbuf: Start of mapped subbuffer
0766  * @info:   Info descriptor to fill in
0767  *
0768  * For debugging. This can return internals of the ring buffer.
0769  * Expects to have info->next set to what it will read.
0770  * The type, length and timestamp delta will be filled in, and
0771  * @info->next will be updated to the next element.
0772  * The @subbuf is used to know if the info is passed the end of
0773  * data and NULL will be returned if it is.
0774  */
0775 struct kbuffer_raw_info *
0776 kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, struct kbuffer_raw_info *info)
0777 {
0778     unsigned long long flags;
0779     unsigned long long delta;
0780     unsigned int type_len;
0781     unsigned int size;
0782     int start;
0783     int length;
0784     void *ptr = info->next;
0785 
0786     if (!kbuf || !subbuf)
0787         return NULL;
0788 
0789     if (kbuf->flags & KBUFFER_FL_LONG_8)
0790         start = 16;
0791     else
0792         start = 12;
0793 
0794     flags = read_long(kbuf, subbuf + 8);
0795     size = (unsigned int)flags & COMMIT_MASK;
0796 
0797     if (ptr < subbuf || ptr >= subbuf + start + size)
0798         return NULL;
0799 
0800     type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
0801 
0802     info->next = ptr + length;
0803 
0804     info->type = type_len;
0805     info->delta = delta;
0806     info->length = length;
0807 
0808     return info;
0809 }