diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2011-02-24 17:33:14 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2011-02-24 17:33:14 -0500 |
| commit | 5ce919cbbb30c8d5a5b3b924cb889dfc729fdbda (patch) | |
| tree | ef4574f2941bbde5d6e8513e369b60d37fb2e01a /trace-input.c | |
| parent | 3b2c0ffbb1e601c61739e694f52e478f066aaf56 (diff) | |
trace-cmd: Add tracecmd_read_page_record()
Add new function tracecmd_read_page_record() that can parse records from
a page without the need of a tracecmd_input handle. It requires a pevent,
a page read from the ring buffer, the size of the page and the last_record.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'trace-input.c')
| -rw-r--r-- | trace-input.c | 133 |
1 files changed, 120 insertions, 13 deletions
diff --git a/trace-input.c b/trace-input.c index a8fa871..f3dff08 100644 --- a/trace-input.c +++ b/trace-input.c | |||
| @@ -740,6 +740,28 @@ static void free_next(struct tracecmd_input *handle, int cpu) | |||
| 740 | free_record(record); | 740 | free_record(record); |
| 741 | } | 741 | } |
| 742 | 742 | ||
| 743 | static int read_page_flags(struct pevent *pevent, void **ptr) | ||
| 744 | { | ||
| 745 | unsigned int flags; | ||
| 746 | |||
| 747 | *ptr += 8; | ||
| 748 | switch (pevent->header_page_size_size) { | ||
| 749 | case 4: | ||
| 750 | flags = data2host4(pevent, *ptr); | ||
| 751 | *ptr += 4; | ||
| 752 | break; | ||
| 753 | case 8: | ||
| 754 | flags = (unsigned int)data2host8(pevent, *ptr); | ||
| 755 | *ptr += 8; | ||
| 756 | break; | ||
| 757 | default: | ||
| 758 | warning("bad long size"); | ||
| 759 | return -1; | ||
| 760 | } | ||
| 761 | |||
| 762 | return flags; | ||
| 763 | } | ||
| 764 | |||
| 743 | /* | 765 | /* |
| 744 | * Page is mapped, now read in the page header info. | 766 | * Page is mapped, now read in the page header info. |
| 745 | */ | 767 | */ |
| @@ -756,20 +778,9 @@ static int update_page_info(struct tracecmd_input *handle, int cpu) | |||
| 756 | } | 778 | } |
| 757 | 779 | ||
| 758 | handle->cpu_data[cpu].timestamp = data2host8(pevent, ptr); | 780 | handle->cpu_data[cpu].timestamp = data2host8(pevent, ptr); |
| 759 | ptr += 8; | 781 | flags = read_page_flags(pevent, &ptr); |
| 760 | switch (pevent->header_page_size_size) { | 782 | if (flags == -1U) |
| 761 | case 4: | ||
| 762 | flags = data2host4(pevent, ptr); | ||
| 763 | ptr += 4; | ||
| 764 | break; | ||
| 765 | case 8: | ||
| 766 | flags = (unsigned int)data2host8(pevent, ptr); | ||
| 767 | ptr += 8; | ||
| 768 | break; | ||
| 769 | default: | ||
| 770 | warning("bad long size"); | ||
| 771 | return -1; | 783 | return -1; |
| 772 | } | ||
| 773 | 784 | ||
| 774 | handle->cpu_data[cpu].page_size = flags & COMMIT_MASK; | 785 | handle->cpu_data[cpu].page_size = flags & COMMIT_MASK; |
| 775 | 786 | ||
| @@ -1506,6 +1517,102 @@ tracecmd_translate_data(struct tracecmd_input *handle, | |||
| 1506 | } | 1517 | } |
| 1507 | 1518 | ||
| 1508 | /** | 1519 | /** |
| 1520 | * tracecmd_read_page_record - read a record off of a page | ||
| 1521 | * @pevent: pevent used to parse the page | ||
| 1522 | * @page: the page to read | ||
| 1523 | * @size: the size of the page | ||
| 1524 | * @last_record: last record read from this page. | ||
| 1525 | * | ||
| 1526 | * If a ring buffer page is available, and the need to parse it | ||
| 1527 | * without having a handle, then this function can be used. | ||
| 1528 | * | ||
| 1529 | * The @pevent needs to be initialized to have the page header information | ||
| 1530 | * already available. | ||
| 1531 | * | ||
| 1532 | * The @last_record is used to know where to read the next record from. | ||
| 1533 | * If @last_record is NULL, the first record on the page will be read. | ||
| 1534 | * | ||
| 1535 | * Returns: | ||
| 1536 | * A newly allocated record that must be freed with free_record() if | ||
| 1537 | * a record is found. Otherwise NULL is returned if the record is bad | ||
| 1538 | * or no more records exist. | ||
| 1539 | */ | ||
| 1540 | struct record * | ||
| 1541 | tracecmd_read_page_record(struct pevent *pevent, void *page, int size, | ||
| 1542 | struct record *last_record) | ||
| 1543 | { | ||
| 1544 | unsigned long long extend; | ||
| 1545 | unsigned long long ts; | ||
| 1546 | unsigned int type_len; | ||
| 1547 | unsigned int flags; | ||
| 1548 | struct record *record; | ||
| 1549 | int page_size; | ||
| 1550 | int length; | ||
| 1551 | void *ptr; | ||
| 1552 | |||
| 1553 | if (!last_record) { | ||
| 1554 | ptr = page; | ||
| 1555 | flags = read_page_flags(pevent, &ptr); | ||
| 1556 | if (flags == -1U) | ||
| 1557 | return NULL; | ||
| 1558 | page_size = flags & COMMIT_MASK; | ||
| 1559 | if (page_size > size) { | ||
| 1560 | warning("tracecmd_read_page_record: page_size > size"); | ||
| 1561 | return NULL; | ||
| 1562 | } | ||
| 1563 | ptr = page + pevent->header_page_data_offset; | ||
| 1564 | ts = data2host8(pevent, page); | ||
| 1565 | } else { | ||
| 1566 | if (last_record->data < page || last_record->data >= (page + size)) { | ||
| 1567 | warning("tracecmd_read_page_record: bad last record (size=%u)", | ||
| 1568 | last_record->size); | ||
| 1569 | return NULL; | ||
| 1570 | } | ||
| 1571 | ptr = last_record->data + last_record->size; | ||
| 1572 | ts = last_record->ts; | ||
| 1573 | } | ||
| 1574 | |||
| 1575 | if (ptr >= page + size) | ||
| 1576 | return NULL; | ||
| 1577 | |||
| 1578 | read_again: | ||
| 1579 | type_len = translate_data(pevent, &ptr, &extend, &length); | ||
| 1580 | |||
| 1581 | switch (type_len) { | ||
| 1582 | case RINGBUF_TYPE_PADDING: | ||
| 1583 | return NULL; | ||
| 1584 | case RINGBUF_TYPE_TIME_EXTEND: | ||
| 1585 | ts += extend; | ||
| 1586 | /* fall through */ | ||
| 1587 | case RINGBUF_TYPE_TIME_STAMP: | ||
| 1588 | goto read_again; | ||
| 1589 | default: | ||
| 1590 | break; | ||
| 1591 | } | ||
| 1592 | |||
| 1593 | if (length < 0 || ptr + length > page + size) { | ||
| 1594 | warning("tracecmd_read_page_record: bad record (size=%u)", | ||
| 1595 | length); | ||
| 1596 | return NULL; | ||
| 1597 | } | ||
| 1598 | |||
| 1599 | ts += extend; | ||
| 1600 | |||
| 1601 | record = malloc(sizeof(*record)); | ||
| 1602 | if (!record) | ||
| 1603 | return NULL; | ||
| 1604 | memset(record, 0, sizeof(*record)); | ||
| 1605 | |||
| 1606 | record->ts = ts; | ||
| 1607 | record->size = length; | ||
| 1608 | record->cpu = 0; | ||
| 1609 | record->data = ptr; | ||
| 1610 | record->ref_count = 1; | ||
| 1611 | |||
| 1612 | return record; | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | /** | ||
| 1509 | * tracecmd_peek_data - return the record at the current location. | 1616 | * tracecmd_peek_data - return the record at the current location. |
| 1510 | * @handle: input handle for the trace.dat file | 1617 | * @handle: input handle for the trace.dat file |
| 1511 | * @cpu: the CPU to pull from | 1618 | * @cpu: the CPU to pull from |
