aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2008-12-23 23:24:13 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-29 06:46:12 -0500
commitf633cef0200bbaec539e2dbb0bc4bed7f022f98b (patch)
tree725d0b181b8e417303e27fa9e62d06b780fe4934 /kernel/trace/trace.c
parentf0868d1e23a8efec33beb3aa688aab7fdb1ae093 (diff)
ftrace: change trace.c to use registered events
Impact: rework trace.c to use new event register API Almost every ftrace event has to implement its output display in trace.c through a different function. Some events did not handle all the formats (trace, latency-trace, raw, hex, binary), and this method does not scale well. This patch converts the format functions to use the event API to find the event and and print its format. Currently, we have a print function for trace, latency_trace, raw, hex and binary. A trace_nop_print is available if the event wants to avoid output on a particular format. Perhaps other tracers could use this in the future (like mmiotrace and function_graph). Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c402
1 files changed, 38 insertions, 364 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 90ce0c1d437b..3f0317586cfd 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1483,15 +1483,6 @@ lat_print_timestamp(struct trace_seq *s, u64 abs_usecs,
1483 trace_seq_puts(s, " : "); 1483 trace_seq_puts(s, " : ");
1484} 1484}
1485 1485
1486static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
1487
1488static int task_state_char(unsigned long state)
1489{
1490 int bit = state ? __ffs(state) + 1 : 0;
1491
1492 return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?';
1493}
1494
1495static void test_cpu_buff_start(struct trace_iterator *iter) 1486static void test_cpu_buff_start(struct trace_iterator *iter)
1496{ 1487{
1497 struct trace_seq *s = &iter->seq; 1488 struct trace_seq *s = &iter->seq;
@@ -1515,14 +1506,14 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1515 struct trace_seq *s = &iter->seq; 1506 struct trace_seq *s = &iter->seq;
1516 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); 1507 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
1517 struct trace_entry *next_entry; 1508 struct trace_entry *next_entry;
1509 struct trace_event *event;
1518 unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE); 1510 unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);
1519 struct trace_entry *entry = iter->ent; 1511 struct trace_entry *entry = iter->ent;
1520 unsigned long abs_usecs; 1512 unsigned long abs_usecs;
1521 unsigned long rel_usecs; 1513 unsigned long rel_usecs;
1522 u64 next_ts; 1514 u64 next_ts;
1523 char *comm; 1515 char *comm;
1524 int S, T; 1516 int ret;
1525 int i;
1526 1517
1527 test_cpu_buff_start(iter); 1518 test_cpu_buff_start(iter);
1528 1519
@@ -1547,94 +1538,16 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1547 lat_print_generic(s, entry, cpu); 1538 lat_print_generic(s, entry, cpu);
1548 lat_print_timestamp(s, abs_usecs, rel_usecs); 1539 lat_print_timestamp(s, abs_usecs, rel_usecs);
1549 } 1540 }
1550 switch (entry->type) {
1551 case TRACE_FN: {
1552 struct ftrace_entry *field;
1553
1554 trace_assign_type(field, entry);
1555
1556 seq_print_ip_sym(s, field->ip, sym_flags);
1557 trace_seq_puts(s, " (");
1558 seq_print_ip_sym(s, field->parent_ip, sym_flags);
1559 trace_seq_puts(s, ")\n");
1560 break;
1561 }
1562 case TRACE_CTX:
1563 case TRACE_WAKE: {
1564 struct ctx_switch_entry *field;
1565
1566 trace_assign_type(field, entry);
1567
1568 T = task_state_char(field->next_state);
1569 S = task_state_char(field->prev_state);
1570 comm = trace_find_cmdline(field->next_pid);
1571 trace_seq_printf(s, " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
1572 field->prev_pid,
1573 field->prev_prio,
1574 S, entry->type == TRACE_CTX ? "==>" : " +",
1575 field->next_cpu,
1576 field->next_pid,
1577 field->next_prio,
1578 T, comm);
1579 break;
1580 }
1581 case TRACE_SPECIAL: {
1582 struct special_entry *field;
1583
1584 trace_assign_type(field, entry);
1585
1586 trace_seq_printf(s, "# %ld %ld %ld\n",
1587 field->arg1,
1588 field->arg2,
1589 field->arg3);
1590 break;
1591 }
1592 case TRACE_STACK: {
1593 struct stack_entry *field;
1594
1595 trace_assign_type(field, entry);
1596
1597 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
1598 if (i)
1599 trace_seq_puts(s, " <= ");
1600 seq_print_ip_sym(s, field->caller[i], sym_flags);
1601 }
1602 trace_seq_puts(s, "\n");
1603 break;
1604 }
1605 case TRACE_PRINT: {
1606 struct print_entry *field;
1607
1608 trace_assign_type(field, entry);
1609 1541
1610 seq_print_ip_sym(s, field->ip, sym_flags); 1542 event = ftrace_find_event(entry->type);
1611 trace_seq_printf(s, ": %s", field->buf); 1543 if (event && event->latency_trace) {
1612 break; 1544 ret = event->latency_trace(s, entry, sym_flags);
1613 } 1545 if (ret)
1614 case TRACE_BRANCH: { 1546 return ret;
1615 struct trace_branch *field; 1547 return TRACE_TYPE_HANDLED;
1616
1617 trace_assign_type(field, entry);
1618
1619 trace_seq_printf(s, "[%s] %s:%s:%d\n",
1620 field->correct ? " ok " : " MISS ",
1621 field->func,
1622 field->file,
1623 field->line);
1624 break;
1625 } 1548 }
1626 case TRACE_USER_STACK: {
1627 struct userstack_entry *field;
1628 1549
1629 trace_assign_type(field, entry); 1550 trace_seq_printf(s, "Unknown type %d\n", entry->type);
1630
1631 seq_print_userip_objs(field, s, sym_flags);
1632 trace_seq_putc(s, '\n');
1633 break;
1634 }
1635 default:
1636 trace_seq_printf(s, "Unknown type %d\n", entry->type);
1637 }
1638 return TRACE_TYPE_HANDLED; 1551 return TRACE_TYPE_HANDLED;
1639} 1552}
1640 1553
@@ -1643,13 +1556,12 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
1643 struct trace_seq *s = &iter->seq; 1556 struct trace_seq *s = &iter->seq;
1644 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); 1557 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
1645 struct trace_entry *entry; 1558 struct trace_entry *entry;
1559 struct trace_event *event;
1646 unsigned long usec_rem; 1560 unsigned long usec_rem;
1647 unsigned long long t; 1561 unsigned long long t;
1648 unsigned long secs; 1562 unsigned long secs;
1649 char *comm; 1563 char *comm;
1650 int ret; 1564 int ret;
1651 int S, T;
1652 int i;
1653 1565
1654 entry = iter->ent; 1566 entry = iter->ent;
1655 1567
@@ -1671,127 +1583,17 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
1671 if (!ret) 1583 if (!ret)
1672 return TRACE_TYPE_PARTIAL_LINE; 1584 return TRACE_TYPE_PARTIAL_LINE;
1673 1585
1674 switch (entry->type) { 1586 event = ftrace_find_event(entry->type);
1675 case TRACE_FN: { 1587 if (event && event->trace) {
1676 struct ftrace_entry *field; 1588 ret = event->trace(s, entry, sym_flags);
1677 1589 if (ret)
1678 trace_assign_type(field, entry); 1590 return ret;
1679 1591 return TRACE_TYPE_HANDLED;
1680 ret = seq_print_ip_sym(s, field->ip, sym_flags);
1681 if (!ret)
1682 return TRACE_TYPE_PARTIAL_LINE;
1683 if ((sym_flags & TRACE_ITER_PRINT_PARENT) &&
1684 field->parent_ip) {
1685 ret = trace_seq_printf(s, " <-");
1686 if (!ret)
1687 return TRACE_TYPE_PARTIAL_LINE;
1688 ret = seq_print_ip_sym(s,
1689 field->parent_ip,
1690 sym_flags);
1691 if (!ret)
1692 return TRACE_TYPE_PARTIAL_LINE;
1693 }
1694 ret = trace_seq_printf(s, "\n");
1695 if (!ret)
1696 return TRACE_TYPE_PARTIAL_LINE;
1697 break;
1698 }
1699 case TRACE_CTX:
1700 case TRACE_WAKE: {
1701 struct ctx_switch_entry *field;
1702
1703 trace_assign_type(field, entry);
1704
1705 T = task_state_char(field->next_state);
1706 S = task_state_char(field->prev_state);
1707 ret = trace_seq_printf(s, " %5d:%3d:%c %s [%03d] %5d:%3d:%c\n",
1708 field->prev_pid,
1709 field->prev_prio,
1710 S,
1711 entry->type == TRACE_CTX ? "==>" : " +",
1712 field->next_cpu,
1713 field->next_pid,
1714 field->next_prio,
1715 T);
1716 if (!ret)
1717 return TRACE_TYPE_PARTIAL_LINE;
1718 break;
1719 }
1720 case TRACE_SPECIAL: {
1721 struct special_entry *field;
1722
1723 trace_assign_type(field, entry);
1724
1725 ret = trace_seq_printf(s, "# %ld %ld %ld\n",
1726 field->arg1,
1727 field->arg2,
1728 field->arg3);
1729 if (!ret)
1730 return TRACE_TYPE_PARTIAL_LINE;
1731 break;
1732 }
1733 case TRACE_STACK: {
1734 struct stack_entry *field;
1735
1736 trace_assign_type(field, entry);
1737
1738 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
1739 if (i) {
1740 ret = trace_seq_puts(s, " <= ");
1741 if (!ret)
1742 return TRACE_TYPE_PARTIAL_LINE;
1743 }
1744 ret = seq_print_ip_sym(s, field->caller[i],
1745 sym_flags);
1746 if (!ret)
1747 return TRACE_TYPE_PARTIAL_LINE;
1748 }
1749 ret = trace_seq_puts(s, "\n");
1750 if (!ret)
1751 return TRACE_TYPE_PARTIAL_LINE;
1752 break;
1753 }
1754 case TRACE_PRINT: {
1755 struct print_entry *field;
1756
1757 trace_assign_type(field, entry);
1758
1759 seq_print_ip_sym(s, field->ip, sym_flags);
1760 trace_seq_printf(s, ": %s", field->buf);
1761 break;
1762 }
1763 case TRACE_GRAPH_RET: {
1764 return print_graph_function(iter);
1765 }
1766 case TRACE_GRAPH_ENT: {
1767 return print_graph_function(iter);
1768 }
1769 case TRACE_BRANCH: {
1770 struct trace_branch *field;
1771
1772 trace_assign_type(field, entry);
1773
1774 trace_seq_printf(s, "[%s] %s:%s:%d\n",
1775 field->correct ? " ok " : " MISS ",
1776 field->func,
1777 field->file,
1778 field->line);
1779 break;
1780 } 1592 }
1781 case TRACE_USER_STACK: { 1593 ret = trace_seq_printf(s, "Unknown type %d\n", entry->type);
1782 struct userstack_entry *field; 1594 if (!ret)
1783 1595 return TRACE_TYPE_PARTIAL_LINE;
1784 trace_assign_type(field, entry);
1785 1596
1786 ret = seq_print_userip_objs(field, s, sym_flags);
1787 if (!ret)
1788 return TRACE_TYPE_PARTIAL_LINE;
1789 ret = trace_seq_putc(s, '\n');
1790 if (!ret)
1791 return TRACE_TYPE_PARTIAL_LINE;
1792 break;
1793 }
1794 }
1795 return TRACE_TYPE_HANDLED; 1597 return TRACE_TYPE_HANDLED;
1796} 1598}
1797 1599
@@ -1799,8 +1601,8 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
1799{ 1601{
1800 struct trace_seq *s = &iter->seq; 1602 struct trace_seq *s = &iter->seq;
1801 struct trace_entry *entry; 1603 struct trace_entry *entry;
1604 struct trace_event *event;
1802 int ret; 1605 int ret;
1803 int S, T;
1804 1606
1805 entry = iter->ent; 1607 entry = iter->ent;
1806 1608
@@ -1809,86 +1611,26 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
1809 if (!ret) 1611 if (!ret)
1810 return TRACE_TYPE_PARTIAL_LINE; 1612 return TRACE_TYPE_PARTIAL_LINE;
1811 1613
1812 switch (entry->type) { 1614 event = ftrace_find_event(entry->type);
1813 case TRACE_FN: { 1615 if (event && event->raw) {
1814 struct ftrace_entry *field; 1616 ret = event->raw(s, entry, 0);
1815 1617 if (ret)
1816 trace_assign_type(field, entry); 1618 return ret;
1817 1619 return TRACE_TYPE_HANDLED;
1818 ret = trace_seq_printf(s, "%x %x\n",
1819 field->ip,
1820 field->parent_ip);
1821 if (!ret)
1822 return TRACE_TYPE_PARTIAL_LINE;
1823 break;
1824 }
1825 case TRACE_CTX:
1826 case TRACE_WAKE: {
1827 struct ctx_switch_entry *field;
1828
1829 trace_assign_type(field, entry);
1830
1831 T = task_state_char(field->next_state);
1832 S = entry->type == TRACE_WAKE ? '+' :
1833 task_state_char(field->prev_state);
1834 ret = trace_seq_printf(s, "%d %d %c %d %d %d %c\n",
1835 field->prev_pid,
1836 field->prev_prio,
1837 S,
1838 field->next_cpu,
1839 field->next_pid,
1840 field->next_prio,
1841 T);
1842 if (!ret)
1843 return TRACE_TYPE_PARTIAL_LINE;
1844 break;
1845 }
1846 case TRACE_SPECIAL:
1847 case TRACE_USER_STACK:
1848 case TRACE_STACK: {
1849 struct special_entry *field;
1850
1851 trace_assign_type(field, entry);
1852
1853 ret = trace_seq_printf(s, "# %ld %ld %ld\n",
1854 field->arg1,
1855 field->arg2,
1856 field->arg3);
1857 if (!ret)
1858 return TRACE_TYPE_PARTIAL_LINE;
1859 break;
1860 } 1620 }
1861 case TRACE_PRINT: { 1621 ret = trace_seq_printf(s, "%d ?\n", entry->type);
1862 struct print_entry *field; 1622 if (!ret)
1863 1623 return TRACE_TYPE_PARTIAL_LINE;
1864 trace_assign_type(field, entry);
1865 1624
1866 trace_seq_printf(s, "# %lx %s", field->ip, field->buf);
1867 break;
1868 }
1869 }
1870 return TRACE_TYPE_HANDLED; 1625 return TRACE_TYPE_HANDLED;
1871} 1626}
1872 1627
1873#define SEQ_PUT_FIELD_RET(s, x) \
1874do { \
1875 if (!trace_seq_putmem(s, &(x), sizeof(x))) \
1876 return 0; \
1877} while (0)
1878
1879#define SEQ_PUT_HEX_FIELD_RET(s, x) \
1880do { \
1881 BUILD_BUG_ON(sizeof(x) > MAX_MEMHEX_BYTES); \
1882 if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \
1883 return 0; \
1884} while (0)
1885
1886static enum print_line_t print_hex_fmt(struct trace_iterator *iter) 1628static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
1887{ 1629{
1888 struct trace_seq *s = &iter->seq; 1630 struct trace_seq *s = &iter->seq;
1889 unsigned char newline = '\n'; 1631 unsigned char newline = '\n';
1890 struct trace_entry *entry; 1632 struct trace_entry *entry;
1891 int S, T; 1633 struct trace_event *event;
1892 1634
1893 entry = iter->ent; 1635 entry = iter->ent;
1894 1636
@@ -1896,47 +1638,10 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
1896 SEQ_PUT_HEX_FIELD_RET(s, iter->cpu); 1638 SEQ_PUT_HEX_FIELD_RET(s, iter->cpu);
1897 SEQ_PUT_HEX_FIELD_RET(s, iter->ts); 1639 SEQ_PUT_HEX_FIELD_RET(s, iter->ts);
1898 1640
1899 switch (entry->type) { 1641 event = ftrace_find_event(entry->type);
1900 case TRACE_FN: { 1642 if (event && event->hex)
1901 struct ftrace_entry *field; 1643 event->hex(s, entry, 0);
1902
1903 trace_assign_type(field, entry);
1904
1905 SEQ_PUT_HEX_FIELD_RET(s, field->ip);
1906 SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip);
1907 break;
1908 }
1909 case TRACE_CTX:
1910 case TRACE_WAKE: {
1911 struct ctx_switch_entry *field;
1912
1913 trace_assign_type(field, entry);
1914
1915 T = task_state_char(field->next_state);
1916 S = entry->type == TRACE_WAKE ? '+' :
1917 task_state_char(field->prev_state);
1918 SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid);
1919 SEQ_PUT_HEX_FIELD_RET(s, field->prev_prio);
1920 SEQ_PUT_HEX_FIELD_RET(s, S);
1921 SEQ_PUT_HEX_FIELD_RET(s, field->next_cpu);
1922 SEQ_PUT_HEX_FIELD_RET(s, field->next_pid);
1923 SEQ_PUT_HEX_FIELD_RET(s, field->next_prio);
1924 SEQ_PUT_HEX_FIELD_RET(s, T);
1925 break;
1926 }
1927 case TRACE_SPECIAL:
1928 case TRACE_USER_STACK:
1929 case TRACE_STACK: {
1930 struct special_entry *field;
1931
1932 trace_assign_type(field, entry);
1933 1644
1934 SEQ_PUT_HEX_FIELD_RET(s, field->arg1);
1935 SEQ_PUT_HEX_FIELD_RET(s, field->arg2);
1936 SEQ_PUT_HEX_FIELD_RET(s, field->arg3);
1937 break;
1938 }
1939 }
1940 SEQ_PUT_FIELD_RET(s, newline); 1645 SEQ_PUT_FIELD_RET(s, newline);
1941 1646
1942 return TRACE_TYPE_HANDLED; 1647 return TRACE_TYPE_HANDLED;
@@ -1962,6 +1667,7 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
1962{ 1667{
1963 struct trace_seq *s = &iter->seq; 1668 struct trace_seq *s = &iter->seq;
1964 struct trace_entry *entry; 1669 struct trace_entry *entry;
1670 struct trace_event *event;
1965 1671
1966 entry = iter->ent; 1672 entry = iter->ent;
1967 1673
@@ -1969,43 +1675,11 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
1969 SEQ_PUT_FIELD_RET(s, entry->cpu); 1675 SEQ_PUT_FIELD_RET(s, entry->cpu);
1970 SEQ_PUT_FIELD_RET(s, iter->ts); 1676 SEQ_PUT_FIELD_RET(s, iter->ts);
1971 1677
1972 switch (entry->type) { 1678 event = ftrace_find_event(entry->type);
1973 case TRACE_FN: { 1679 if (event && event->binary)
1974 struct ftrace_entry *field; 1680 event->binary(s, entry, 0);
1975
1976 trace_assign_type(field, entry);
1977 1681
1978 SEQ_PUT_FIELD_RET(s, field->ip); 1682 return TRACE_TYPE_HANDLED;
1979 SEQ_PUT_FIELD_RET(s, field->parent_ip);
1980 break;
1981 }
1982 case TRACE_CTX: {
1983 struct ctx_switch_entry *field;
1984
1985 trace_assign_type(field, entry);
1986
1987 SEQ_PUT_FIELD_RET(s, field->prev_pid);
1988 SEQ_PUT_FIELD_RET(s, field->prev_prio);
1989 SEQ_PUT_FIELD_RET(s, field->prev_state);
1990 SEQ_PUT_FIELD_RET(s, field->next_pid);
1991 SEQ_PUT_FIELD_RET(s, field->next_prio);
1992 SEQ_PUT_FIELD_RET(s, field->next_state);
1993 break;
1994 }
1995 case TRACE_SPECIAL:
1996 case TRACE_USER_STACK:
1997 case TRACE_STACK: {
1998 struct special_entry *field;
1999
2000 trace_assign_type(field, entry);
2001
2002 SEQ_PUT_FIELD_RET(s, field->arg1);
2003 SEQ_PUT_FIELD_RET(s, field->arg2);
2004 SEQ_PUT_FIELD_RET(s, field->arg3);
2005 break;
2006 }
2007 }
2008 return 1;
2009} 1683}
2010 1684
2011static int trace_empty(struct trace_iterator *iter) 1685static int trace_empty(struct trace_iterator *iter)