aboutsummaryrefslogtreecommitdiffstats
path: root/trace-input.c
diff options
context:
space:
mode:
Diffstat (limited to 'trace-input.c')
-rw-r--r--trace-input.c133
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
743static 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 */
1540struct record *
1541tracecmd_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