tracing: Add binary '&' filter for events
authorSteven Rostedt <rostedt@goodmis.org>
Wed, 12 Jun 2013 17:16:25 +0000 (13:16 -0400)
committerSteven Rostedt <rostedt@goodmis.org>
Thu, 20 Jun 2013 03:30:40 +0000 (23:30 -0400)
There are some cases when filtering on a set flag of a field of a tracepoint
is useful. But currently the only filtering commands for numbered fields
is ==, !=, <, <=, >, >=. This does not help when you just want to trace if
a specific flag is set. For example:

 > # sudo trace-cmd record -e brcmfmac:brcmf_dbg -f 'level & 0x40000'
 > disable all
 > enable brcmfmac:brcmf_dbg
 > path = /sys/kernel/debug/tracing/events/brcmfmac/brcmf_dbg/enable
 > (level & 0x40000)
 > ^
 > parse_error: Invalid operator
 >

When trying to trace brcmf_dbg when level has its 1 << 18 bit set, the
filter fails to perform.

By allowing a binary '&' operation, this gives the user the ability to
test a bit.

Note, a binary '|' is not added, as it doesn't make sense as fields must
be compared to constants (for now), and ORing a constant will always return
true.

Link: http://lkml.kernel.org/r/1371057385.9844.261.camel@gandalf.local.home
Suggested-by: Arend van Spriel <arend@broadcom.com>
Tested-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Documentation/trace/events.txt
kernel/trace/trace_events_filter.c

index bb24c2a0e870dc873ef8e8250f77d44d76a017b9..41911240c65c47f48832f8fd645bedfd47eb12a4 100644 (file)
@@ -183,7 +183,7 @@ The relational-operators depend on the type of the field being tested:
 
 The operators available for numeric fields are:
 
-==, !=, <, <=, >, >=
+==, !=, <, <=, >, >=, &
 
 And for string fields they are:
 
index e1b653f7e1ca101f0861351d610b5c8297a4b3ca..0d883dc057d68fe92bc36f0510298cff725256bb 100644 (file)
@@ -44,6 +44,7 @@ enum filter_op_ids
        OP_LE,
        OP_GT,
        OP_GE,
+       OP_BAND,
        OP_NONE,
        OP_OPEN_PAREN,
 };
@@ -54,6 +55,7 @@ struct filter_op {
        int precedence;
 };
 
+/* Order must be the same as enum filter_op_ids above */
 static struct filter_op filter_ops[] = {
        { OP_OR,        "||",           1 },
        { OP_AND,       "&&",           2 },
@@ -64,6 +66,7 @@ static struct filter_op filter_ops[] = {
        { OP_LE,        "<=",           5 },
        { OP_GT,        ">",            5 },
        { OP_GE,        ">=",           5 },
+       { OP_BAND,      "&",            6 },
        { OP_NONE,      "OP_NONE",      0 },
        { OP_OPEN_PAREN, "(",           0 },
 };
@@ -156,6 +159,9 @@ static int filter_pred_##type(struct filter_pred *pred, void *event)        \
        case OP_GE:                                                     \
                match = (*addr >= val);                                 \
                break;                                                  \
+       case OP_BAND:                                                   \
+               match = (*addr & val);                                  \
+               break;                                                  \
        default:                                                        \
                break;                                                  \
        }                                                               \