This patchset replaces the current event parser hack with a better, more
extensible version. See patch 3 for the details on syntax and usage.
Basically, instead of defining a filter predicate by predicate as in the
current version, you now define the whole thing all at once and in
addition to the current == and != operators, can use >, <, >=, <=,
parens and the logical operators && and ||. Some examples:
# echo "((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter
# echo "common_preempt_count > 4" > filter
# echo "common_preempt_count > 4 && common_pid != 0" > filter
It also does some basic error reporting, which you can see by cat'ing
the filter file after a failed set (this needs a little more work to
report the error position, but is still useful):
# echo "(sig >= 10 && sig < 15) || dsig == 17) && comm != bash" > filter
-bash: echo: write error: Invalid argument
# cat filter
(sig >= 10 && sig < 15) || dsig == 17) && comm != bash
^
parse_error: Unbalanced parens
It should be relatively easy to add new operators; it's implemented as a
standard infix to postfix converter - when a filter is defined, as
before, it creates a set of predicates that are evaluated efficiently at
run-time.
I tried to make the parser itself reusable so that it could also be
pointed at a completely separate set of operators and an unevaluated
operand, with the resulting expression components available in the
intermediate postfix list. e.g. for say a field of type dev_t, the
parser could be set up and pointed at an operand of the form (8,3) or
8:3 or /dev/sda, and the parsed results retrieved from the parse state
object, something like this:
enum kdev_t_filter_op_ids
{
COMMA_OP,
};
struct filter_op kdev_t_filter_ops[] = {
{ COMMA_OP, ",", 1 },
{ NO_OP, "NO_OP", 0 },
{ OPEN_PAREN_OP, "(", 0 },
};
parse_init(parse_state, kdev_t_filter_ops, dev_string);
filter_parse(parse_state);
The parsed operator and operands could then be found in the
parse_state.postfix list and used to generate the dev_t value, or if it
was specified as a string ('sda' or /dev/sda), there would only be one
item in the list which could be used in that case to look up the value.
Tom
* Tom Zanussi <[email protected]> wrote:
> This patchset replaces the current event parser hack with a
> better, more extensible version. See patch 3 for the details on
> syntax and usage.
>
> Basically, instead of defining a filter predicate by predicate as
> in the current version, you now define the whole thing all at once
> and in addition to the current == and != operators, can use >, <,
> >=, <=, parens and the logical operators && and ||. Some
> examples:
>
> # echo "((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter
>
> # echo "common_preempt_count > 4" > filter
>
> # echo "common_preempt_count > 4 && common_pid != 0" > filter
>
> It also does some basic error reporting, which you can see by
> cat'ing the filter file after a failed set (this needs a little
> more work to report the error position, but is still useful):
>
> # echo "(sig >= 10 && sig < 15) || dsig == 17) && comm != bash" > filter
> -bash: echo: write error: Invalid argument
> # cat filter
> (sig >= 10 && sig < 15) || dsig == 17) && comm != bash
> ^
> parse_error: Unbalanced parens
>
> It should be relatively easy to add new operators; it's
> implemented as a standard infix to postfix converter - when a
> filter is defined, as before, it creates a set of predicates that
> are evaluated efficiently at run-time.
>
> I tried to make the parser itself reusable so that it could also
> be pointed at a completely separate set of operators and an
> unevaluated operand, with the resulting expression components
> available in the intermediate postfix list. e.g. for say a field
> of type dev_t, the parser could be set up and pointed at an
> operand of the form (8,3) or 8:3 or /dev/sda, and the parsed
> results retrieved from the parse state object, something like
> this:
>
> enum kdev_t_filter_op_ids
> {
> COMMA_OP,
> };
>
> struct filter_op kdev_t_filter_ops[] = {
> { COMMA_OP, ",", 1 },
> { NO_OP, "NO_OP", 0 },
> { OPEN_PAREN_OP, "(", 0 },
> };
>
> parse_init(parse_state, kdev_t_filter_ops, dev_string);
> filter_parse(parse_state);
>
> The parsed operator and operands could then be found in the
> parse_state.postfix list and used to generate the dev_t value, or
> if it was specified as a string ('sda' or /dev/sda), there would
> only be one item in the list which could be used in that case to
> look up the value.
Very impressive changes! I'll have a closer look later today.
One thing that might make sense to add in future patches is a
negation (logic) operator for integer fields. The expression
"!x" could be equivalent to "x == 0".
( Bitwise operators and basic arithmetics might also make sense in
the longer run, albeit i'm not sure how far we want to push
arithmetics. It would need an extension of the operator result
abstraction, to be able to return a value, beyond true/false. )
Ingo
On Tue, 28 Apr 2009, Tom Zanussi wrote:
> This patchset replaces the current event parser hack with a better, more
> extensible version. See patch 3 for the details on syntax and usage.
>
> Basically, instead of defining a filter predicate by predicate as in the
> current version, you now define the whole thing all at once and in
> addition to the current == and != operators, can use >, <, >=, <=,
> parens and the logical operators && and ||. Some examples:
>
> # echo "((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter
>
> # echo "common_preempt_count > 4" > filter
>
> # echo "common_preempt_count > 4 && common_pid != 0" > filter
>
> It also does some basic error reporting, which you can see by cat'ing
> the filter file after a failed set (this needs a little more work to
> report the error position, but is still useful):
>
> # echo "(sig >= 10 && sig < 15) || dsig == 17) && comm != bash" > filter
> -bash: echo: write error: Invalid argument
> # cat filter
> (sig >= 10 && sig < 15) || dsig == 17) && comm != bash
> ^
> parse_error: Unbalanced parens
>
> It should be relatively easy to add new operators; it's implemented as a
> standard infix to postfix converter - when a filter is defined, as
> before, it creates a set of predicates that are evaluated efficiently at
> run-time.
>
> I tried to make the parser itself reusable so that it could also be
> pointed at a completely separate set of operators and an unevaluated
> operand, with the resulting expression components available in the
> intermediate postfix list. e.g. for say a field of type dev_t, the
> parser could be set up and pointed at an operand of the form (8,3) or
> 8:3 or /dev/sda, and the parsed results retrieved from the parse state
> object, something like this:
>
> enum kdev_t_filter_op_ids
> {
> COMMA_OP,
> };
>
> struct filter_op kdev_t_filter_ops[] = {
> { COMMA_OP, ",", 1 },
> { NO_OP, "NO_OP", 0 },
> { OPEN_PAREN_OP, "(", 0 },
> };
>
> parse_init(parse_state, kdev_t_filter_ops, dev_string);
> filter_parse(parse_state);
>
> The parsed operator and operands could then be found in the
> parse_state.postfix list and used to generate the dev_t value, or if it
> was specified as a string ('sda' or /dev/sda), there would only be one
> item in the list which could be used in that case to look up the value.
>
Hi Tom,
Cool stuff. I just skimmed the patches and did not see anything
I object to.
Acked-by: Steven Rostedt <[email protected]>
-- Steve