diff options
author | Namhyung Kim <namhyung@kernel.org> | 2013-12-12 02:36:15 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-12-13 08:30:22 -0500 |
commit | 41e12e580a7b0c151199f927193548b84d3e874c (patch) | |
tree | ae5fb86482f89da05d93de00a7f36f5fa46703ba /tools/lib | |
parent | 69c770a690422c6cdc4ea52d9edbba7c20cd1aff (diff) |
tools lib traceevent: Refactor pevent_filter_match() to get rid of die()
The test_filter() function is for testing given filter is matched to a
given record. However it doesn't handle error cases properly so add a
new argument err to save error info during the test and also pass it to
internal test functions.
The return value of pevent_filter_match() also converted to pevent_errno
to indicate an exact error case.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/1386833777-3790-13-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/traceevent/event-parse.h | 21 | ||||
-rw-r--r-- | tools/lib/traceevent/parse-filter.c | 135 |
2 files changed, 99 insertions, 57 deletions
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 089964e56ed4..3ad784f5f647 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h | |||
@@ -357,6 +357,8 @@ enum pevent_flag { | |||
357 | _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ | 357 | _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ |
358 | _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ | 358 | _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ |
359 | _PE(INVALID_ARG_TYPE, "invalid argument type"), \ | 359 | _PE(INVALID_ARG_TYPE, "invalid argument type"), \ |
360 | _PE(INVALID_EXP_TYPE, "invalid expression type"), \ | ||
361 | _PE(INVALID_OP_TYPE, "invalid operator type"), \ | ||
360 | _PE(INVALID_EVENT_NAME, "invalid event name"), \ | 362 | _PE(INVALID_EVENT_NAME, "invalid event name"), \ |
361 | _PE(EVENT_NOT_FOUND, "no event found"), \ | 363 | _PE(EVENT_NOT_FOUND, "no event found"), \ |
362 | _PE(SYNTAX_ERROR, "syntax error"), \ | 364 | _PE(SYNTAX_ERROR, "syntax error"), \ |
@@ -373,12 +375,16 @@ enum pevent_flag { | |||
373 | _PE(INVALID_PAREN, "open parenthesis cannot come here"), \ | 375 | _PE(INVALID_PAREN, "open parenthesis cannot come here"), \ |
374 | _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \ | 376 | _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \ |
375 | _PE(UNKNOWN_TOKEN, "unknown token"), \ | 377 | _PE(UNKNOWN_TOKEN, "unknown token"), \ |
376 | _PE(FILTER_NOT_FOUND, "no filter found") | 378 | _PE(FILTER_NOT_FOUND, "no filter found"), \ |
379 | _PE(NOT_A_NUMBER, "must have number field"), \ | ||
380 | _PE(NO_FILTER, "no filters exists"), \ | ||
381 | _PE(FILTER_MISS, "record does not match to filter") | ||
377 | 382 | ||
378 | #undef _PE | 383 | #undef _PE |
379 | #define _PE(__code, __str) PEVENT_ERRNO__ ## __code | 384 | #define _PE(__code, __str) PEVENT_ERRNO__ ## __code |
380 | enum pevent_errno { | 385 | enum pevent_errno { |
381 | PEVENT_ERRNO__SUCCESS = 0, | 386 | PEVENT_ERRNO__SUCCESS = 0, |
387 | PEVENT_ERRNO__FILTER_MATCH = PEVENT_ERRNO__SUCCESS, | ||
382 | 388 | ||
383 | /* | 389 | /* |
384 | * Choose an arbitrary negative big number not to clash with standard | 390 | * Choose an arbitrary negative big number not to clash with standard |
@@ -853,10 +859,11 @@ struct event_filter { | |||
853 | 859 | ||
854 | struct event_filter *pevent_filter_alloc(struct pevent *pevent); | 860 | struct event_filter *pevent_filter_alloc(struct pevent *pevent); |
855 | 861 | ||
856 | #define FILTER_NONE -2 | 862 | /* for backward compatibility */ |
857 | #define FILTER_NOEXIST -1 | 863 | #define FILTER_NONE PEVENT_ERRNO__FILTER_NOT_FOUND |
858 | #define FILTER_MISS 0 | 864 | #define FILTER_NOEXIST PEVENT_ERRNO__NO_FILTER |
859 | #define FILTER_MATCH 1 | 865 | #define FILTER_MISS PEVENT_ERRNO__FILTER_MISS |
866 | #define FILTER_MATCH PEVENT_ERRNO__FILTER_MATCH | ||
860 | 867 | ||
861 | enum filter_trivial_type { | 868 | enum filter_trivial_type { |
862 | FILTER_TRIVIAL_FALSE, | 869 | FILTER_TRIVIAL_FALSE, |
@@ -868,8 +875,8 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, | |||
868 | const char *filter_str); | 875 | const char *filter_str); |
869 | 876 | ||
870 | 877 | ||
871 | int pevent_filter_match(struct event_filter *filter, | 878 | enum pevent_errno pevent_filter_match(struct event_filter *filter, |
872 | struct pevent_record *record); | 879 | struct pevent_record *record); |
873 | 880 | ||
874 | int pevent_event_filtered(struct event_filter *filter, | 881 | int pevent_event_filtered(struct event_filter *filter, |
875 | int event_id); | 882 | int event_id); |
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 78440d73e0ad..9303c55128db 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c | |||
@@ -1678,8 +1678,8 @@ int pevent_filter_event_has_trivial(struct event_filter *filter, | |||
1678 | } | 1678 | } |
1679 | } | 1679 | } |
1680 | 1680 | ||
1681 | static int test_filter(struct event_format *event, | 1681 | static int test_filter(struct event_format *event, struct filter_arg *arg, |
1682 | struct filter_arg *arg, struct pevent_record *record); | 1682 | struct pevent_record *record, enum pevent_errno *err); |
1683 | 1683 | ||
1684 | static const char * | 1684 | static const char * |
1685 | get_comm(struct event_format *event, struct pevent_record *record) | 1685 | get_comm(struct event_format *event, struct pevent_record *record) |
@@ -1725,15 +1725,24 @@ get_value(struct event_format *event, | |||
1725 | } | 1725 | } |
1726 | 1726 | ||
1727 | static unsigned long long | 1727 | static unsigned long long |
1728 | get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record); | 1728 | get_arg_value(struct event_format *event, struct filter_arg *arg, |
1729 | struct pevent_record *record, enum pevent_errno *err); | ||
1729 | 1730 | ||
1730 | static unsigned long long | 1731 | static unsigned long long |
1731 | get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record) | 1732 | get_exp_value(struct event_format *event, struct filter_arg *arg, |
1733 | struct pevent_record *record, enum pevent_errno *err) | ||
1732 | { | 1734 | { |
1733 | unsigned long long lval, rval; | 1735 | unsigned long long lval, rval; |
1734 | 1736 | ||
1735 | lval = get_arg_value(event, arg->exp.left, record); | 1737 | lval = get_arg_value(event, arg->exp.left, record, err); |
1736 | rval = get_arg_value(event, arg->exp.right, record); | 1738 | rval = get_arg_value(event, arg->exp.right, record, err); |
1739 | |||
1740 | if (*err) { | ||
1741 | /* | ||
1742 | * There was an error, no need to process anymore. | ||
1743 | */ | ||
1744 | return 0; | ||
1745 | } | ||
1737 | 1746 | ||
1738 | switch (arg->exp.type) { | 1747 | switch (arg->exp.type) { |
1739 | case FILTER_EXP_ADD: | 1748 | case FILTER_EXP_ADD: |
@@ -1768,39 +1777,51 @@ get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_ | |||
1768 | 1777 | ||
1769 | case FILTER_EXP_NOT: | 1778 | case FILTER_EXP_NOT: |
1770 | default: | 1779 | default: |
1771 | die("error in exp"); | 1780 | if (!*err) |
1781 | *err = PEVENT_ERRNO__INVALID_EXP_TYPE; | ||
1772 | } | 1782 | } |
1773 | return 0; | 1783 | return 0; |
1774 | } | 1784 | } |
1775 | 1785 | ||
1776 | static unsigned long long | 1786 | static unsigned long long |
1777 | get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record) | 1787 | get_arg_value(struct event_format *event, struct filter_arg *arg, |
1788 | struct pevent_record *record, enum pevent_errno *err) | ||
1778 | { | 1789 | { |
1779 | switch (arg->type) { | 1790 | switch (arg->type) { |
1780 | case FILTER_ARG_FIELD: | 1791 | case FILTER_ARG_FIELD: |
1781 | return get_value(event, arg->field.field, record); | 1792 | return get_value(event, arg->field.field, record); |
1782 | 1793 | ||
1783 | case FILTER_ARG_VALUE: | 1794 | case FILTER_ARG_VALUE: |
1784 | if (arg->value.type != FILTER_NUMBER) | 1795 | if (arg->value.type != FILTER_NUMBER) { |
1785 | die("must have number field!"); | 1796 | if (!*err) |
1797 | *err = PEVENT_ERRNO__NOT_A_NUMBER; | ||
1798 | } | ||
1786 | return arg->value.val; | 1799 | return arg->value.val; |
1787 | 1800 | ||
1788 | case FILTER_ARG_EXP: | 1801 | case FILTER_ARG_EXP: |
1789 | return get_exp_value(event, arg, record); | 1802 | return get_exp_value(event, arg, record, err); |
1790 | 1803 | ||
1791 | default: | 1804 | default: |
1792 | die("oops in filter"); | 1805 | if (!*err) |
1806 | *err = PEVENT_ERRNO__INVALID_ARG_TYPE; | ||
1793 | } | 1807 | } |
1794 | return 0; | 1808 | return 0; |
1795 | } | 1809 | } |
1796 | 1810 | ||
1797 | static int test_num(struct event_format *event, | 1811 | static int test_num(struct event_format *event, struct filter_arg *arg, |
1798 | struct filter_arg *arg, struct pevent_record *record) | 1812 | struct pevent_record *record, enum pevent_errno *err) |
1799 | { | 1813 | { |
1800 | unsigned long long lval, rval; | 1814 | unsigned long long lval, rval; |
1801 | 1815 | ||
1802 | lval = get_arg_value(event, arg->num.left, record); | 1816 | lval = get_arg_value(event, arg->num.left, record, err); |
1803 | rval = get_arg_value(event, arg->num.right, record); | 1817 | rval = get_arg_value(event, arg->num.right, record, err); |
1818 | |||
1819 | if (*err) { | ||
1820 | /* | ||
1821 | * There was an error, no need to process anymore. | ||
1822 | */ | ||
1823 | return 0; | ||
1824 | } | ||
1804 | 1825 | ||
1805 | switch (arg->num.type) { | 1826 | switch (arg->num.type) { |
1806 | case FILTER_CMP_EQ: | 1827 | case FILTER_CMP_EQ: |
@@ -1822,7 +1843,8 @@ static int test_num(struct event_format *event, | |||
1822 | return lval <= rval; | 1843 | return lval <= rval; |
1823 | 1844 | ||
1824 | default: | 1845 | default: |
1825 | /* ?? */ | 1846 | if (!*err) |
1847 | *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP; | ||
1826 | return 0; | 1848 | return 0; |
1827 | } | 1849 | } |
1828 | } | 1850 | } |
@@ -1869,8 +1891,8 @@ static const char *get_field_str(struct filter_arg *arg, struct pevent_record *r | |||
1869 | return val; | 1891 | return val; |
1870 | } | 1892 | } |
1871 | 1893 | ||
1872 | static int test_str(struct event_format *event, | 1894 | static int test_str(struct event_format *event, struct filter_arg *arg, |
1873 | struct filter_arg *arg, struct pevent_record *record) | 1895 | struct pevent_record *record, enum pevent_errno *err) |
1874 | { | 1896 | { |
1875 | const char *val; | 1897 | const char *val; |
1876 | 1898 | ||
@@ -1894,48 +1916,57 @@ static int test_str(struct event_format *event, | |||
1894 | return regexec(&arg->str.reg, val, 0, NULL, 0); | 1916 | return regexec(&arg->str.reg, val, 0, NULL, 0); |
1895 | 1917 | ||
1896 | default: | 1918 | default: |
1897 | /* ?? */ | 1919 | if (!*err) |
1920 | *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP; | ||
1898 | return 0; | 1921 | return 0; |
1899 | } | 1922 | } |
1900 | } | 1923 | } |
1901 | 1924 | ||
1902 | static int test_op(struct event_format *event, | 1925 | static int test_op(struct event_format *event, struct filter_arg *arg, |
1903 | struct filter_arg *arg, struct pevent_record *record) | 1926 | struct pevent_record *record, enum pevent_errno *err) |
1904 | { | 1927 | { |
1905 | switch (arg->op.type) { | 1928 | switch (arg->op.type) { |
1906 | case FILTER_OP_AND: | 1929 | case FILTER_OP_AND: |
1907 | return test_filter(event, arg->op.left, record) && | 1930 | return test_filter(event, arg->op.left, record, err) && |
1908 | test_filter(event, arg->op.right, record); | 1931 | test_filter(event, arg->op.right, record, err); |
1909 | 1932 | ||
1910 | case FILTER_OP_OR: | 1933 | case FILTER_OP_OR: |
1911 | return test_filter(event, arg->op.left, record) || | 1934 | return test_filter(event, arg->op.left, record, err) || |
1912 | test_filter(event, arg->op.right, record); | 1935 | test_filter(event, arg->op.right, record, err); |
1913 | 1936 | ||
1914 | case FILTER_OP_NOT: | 1937 | case FILTER_OP_NOT: |
1915 | return !test_filter(event, arg->op.right, record); | 1938 | return !test_filter(event, arg->op.right, record, err); |
1916 | 1939 | ||
1917 | default: | 1940 | default: |
1918 | /* ?? */ | 1941 | if (!*err) |
1942 | *err = PEVENT_ERRNO__INVALID_OP_TYPE; | ||
1919 | return 0; | 1943 | return 0; |
1920 | } | 1944 | } |
1921 | } | 1945 | } |
1922 | 1946 | ||
1923 | static int test_filter(struct event_format *event, | 1947 | static int test_filter(struct event_format *event, struct filter_arg *arg, |
1924 | struct filter_arg *arg, struct pevent_record *record) | 1948 | struct pevent_record *record, enum pevent_errno *err) |
1925 | { | 1949 | { |
1950 | if (*err) { | ||
1951 | /* | ||
1952 | * There was an error, no need to process anymore. | ||
1953 | */ | ||
1954 | return 0; | ||
1955 | } | ||
1956 | |||
1926 | switch (arg->type) { | 1957 | switch (arg->type) { |
1927 | case FILTER_ARG_BOOLEAN: | 1958 | case FILTER_ARG_BOOLEAN: |
1928 | /* easy case */ | 1959 | /* easy case */ |
1929 | return arg->boolean.value; | 1960 | return arg->boolean.value; |
1930 | 1961 | ||
1931 | case FILTER_ARG_OP: | 1962 | case FILTER_ARG_OP: |
1932 | return test_op(event, arg, record); | 1963 | return test_op(event, arg, record, err); |
1933 | 1964 | ||
1934 | case FILTER_ARG_NUM: | 1965 | case FILTER_ARG_NUM: |
1935 | return test_num(event, arg, record); | 1966 | return test_num(event, arg, record, err); |
1936 | 1967 | ||
1937 | case FILTER_ARG_STR: | 1968 | case FILTER_ARG_STR: |
1938 | return test_str(event, arg, record); | 1969 | return test_str(event, arg, record, err); |
1939 | 1970 | ||
1940 | case FILTER_ARG_EXP: | 1971 | case FILTER_ARG_EXP: |
1941 | case FILTER_ARG_VALUE: | 1972 | case FILTER_ARG_VALUE: |
@@ -1944,11 +1975,11 @@ static int test_filter(struct event_format *event, | |||
1944 | * Expressions, fields and values evaluate | 1975 | * Expressions, fields and values evaluate |
1945 | * to true if they return non zero | 1976 | * to true if they return non zero |
1946 | */ | 1977 | */ |
1947 | return !!get_arg_value(event, arg, record); | 1978 | return !!get_arg_value(event, arg, record, err); |
1948 | 1979 | ||
1949 | default: | 1980 | default: |
1950 | die("oops!"); | 1981 | if (!*err) |
1951 | /* ?? */ | 1982 | *err = PEVENT_ERRNO__INVALID_ARG_TYPE; |
1952 | return 0; | 1983 | return 0; |
1953 | } | 1984 | } |
1954 | } | 1985 | } |
@@ -1961,8 +1992,7 @@ static int test_filter(struct event_format *event, | |||
1961 | * Returns 1 if filter found for @event_id | 1992 | * Returns 1 if filter found for @event_id |
1962 | * otherwise 0; | 1993 | * otherwise 0; |
1963 | */ | 1994 | */ |
1964 | int pevent_event_filtered(struct event_filter *filter, | 1995 | int pevent_event_filtered(struct event_filter *filter, int event_id) |
1965 | int event_id) | ||
1966 | { | 1996 | { |
1967 | struct filter_type *filter_type; | 1997 | struct filter_type *filter_type; |
1968 | 1998 | ||
@@ -1979,31 +2009,36 @@ int pevent_event_filtered(struct event_filter *filter, | |||
1979 | * @filter: filter struct with filter information | 2009 | * @filter: filter struct with filter information |
1980 | * @record: the record to test against the filter | 2010 | * @record: the record to test against the filter |
1981 | * | 2011 | * |
1982 | * Returns: | 2012 | * Returns: match result or error code (prefixed with PEVENT_ERRNO__) |
1983 | * 1 - filter found for event and @record matches | 2013 | * FILTER_MATCH - filter found for event and @record matches |
1984 | * 0 - filter found for event and @record does not match | 2014 | * FILTER_MISS - filter found for event and @record does not match |
1985 | * -1 - no filter found for @record's event | 2015 | * FILTER_NOT_FOUND - no filter found for @record's event |
1986 | * -2 - if no filters exist | 2016 | * NO_FILTER - if no filters exist |
2017 | * otherwise - error occurred during test | ||
1987 | */ | 2018 | */ |
1988 | int pevent_filter_match(struct event_filter *filter, | 2019 | enum pevent_errno pevent_filter_match(struct event_filter *filter, |
1989 | struct pevent_record *record) | 2020 | struct pevent_record *record) |
1990 | { | 2021 | { |
1991 | struct pevent *pevent = filter->pevent; | 2022 | struct pevent *pevent = filter->pevent; |
1992 | struct filter_type *filter_type; | 2023 | struct filter_type *filter_type; |
1993 | int event_id; | 2024 | int event_id; |
2025 | int ret; | ||
2026 | enum pevent_errno err = 0; | ||
1994 | 2027 | ||
1995 | if (!filter->filters) | 2028 | if (!filter->filters) |
1996 | return FILTER_NONE; | 2029 | return PEVENT_ERRNO__NO_FILTER; |
1997 | 2030 | ||
1998 | event_id = pevent_data_type(pevent, record); | 2031 | event_id = pevent_data_type(pevent, record); |
1999 | 2032 | ||
2000 | filter_type = find_filter_type(filter, event_id); | 2033 | filter_type = find_filter_type(filter, event_id); |
2001 | |||
2002 | if (!filter_type) | 2034 | if (!filter_type) |
2003 | return FILTER_NOEXIST; | 2035 | return PEVENT_ERRNO__FILTER_NOT_FOUND; |
2036 | |||
2037 | ret = test_filter(filter_type->event, filter_type->filter, record, &err); | ||
2038 | if (err) | ||
2039 | return err; | ||
2004 | 2040 | ||
2005 | return test_filter(filter_type->event, filter_type->filter, record) ? | 2041 | return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS; |
2006 | FILTER_MATCH : FILTER_MISS; | ||
2007 | } | 2042 | } |
2008 | 2043 | ||
2009 | static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) | 2044 | static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) |