diff options
author | Steven Rostedt <srostedt@redhat.com> | 2011-01-14 19:48:55 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-01-14 19:48:55 -0500 |
commit | cf8d974439091212a6aa6c72a3d6d2cf3d3b7e8e (patch) | |
tree | ae4d660580d19b8cbe1c9702c81f34a0f326693e | |
parent | 6c696cec3f264a9399241b6e648f58bc97117d49 (diff) |
parse-events: Add filter on task comm
Add a 'COMM' special field to allow the filter in trace-cmd report
to filter on the task's comm.
Most records do not have data about what the comm is of the
task that recorded the record. But comms are stored in various
ways that parse-events can handle.
By adding a special field 'COMM' (all caps) the user can now
filter out tasks based on their name. This is useful when filtering
out (or in) a bunch of threads.
-F 'COMM != "trace-cmd"'
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | Documentation/trace-cmd-report.1.txt | 8 | ||||
-rw-r--r-- | parse-filter.c | 75 |
2 files changed, 65 insertions, 18 deletions
diff --git a/Documentation/trace-cmd-report.1.txt b/Documentation/trace-cmd-report.1.txt index fbab3f4..86169f2 100644 --- a/Documentation/trace-cmd-report.1.txt +++ b/Documentation/trace-cmd-report.1.txt | |||
@@ -98,6 +98,14 @@ OPTIONS | |||
98 | 98 | ||
99 | Although the output displays 'R', having 'prev_stat=="R"' will not work. | 99 | Although the output displays 'R', having 'prev_stat=="R"' will not work. |
100 | 100 | ||
101 | Note: You can also specify 'COMM' as an EVENT_FIELD. This will use the | ||
102 | task name (or comm) of the record to compare. For example, to filter out | ||
103 | all of the "trace-cmd" tasks: | ||
104 | |||
105 | ------------------------------------------ | ||
106 | -F '.*:COMM != "trace-cmd"' | ||
107 | ------------------------------------------ | ||
108 | |||
101 | *-v*:: | 109 | *-v*:: |
102 | This causes the following filters of *-F* to filter out the matching | 110 | This causes the following filters of *-F* to filter out the matching |
103 | events. | 111 | events. |
diff --git a/parse-filter.c b/parse-filter.c index 75512e3..eb2ef6d 100644 --- a/parse-filter.c +++ b/parse-filter.c | |||
@@ -28,6 +28,12 @@ | |||
28 | #include "parse-events.h" | 28 | #include "parse-events.h" |
29 | #include "util.h" | 29 | #include "util.h" |
30 | 30 | ||
31 | #define COMM "COMM" | ||
32 | |||
33 | static struct format_field comm = { | ||
34 | .name = "COMM", | ||
35 | }; | ||
36 | |||
31 | struct event_list { | 37 | struct event_list { |
32 | struct event_list *next; | 38 | struct event_list *next; |
33 | struct event_format *event; | 39 | struct event_format *event; |
@@ -539,13 +545,18 @@ process_value_token(struct event_format *event, struct filter_arg **parg, | |||
539 | } | 545 | } |
540 | /* Consider this a field */ | 546 | /* Consider this a field */ |
541 | field = pevent_find_any_field(event, token); | 547 | field = pevent_find_any_field(event, token); |
542 | free_token(token); | ||
543 | if (!field) { | 548 | if (!field) { |
544 | /* not a field, so NULL it up */ | 549 | if (strcmp(token, COMM) != 0) { |
545 | free_arg(arg); | 550 | /* not a field, so NULL it up */ |
546 | arg = NULL; | 551 | free_token(token); |
547 | break; | 552 | free_arg(arg); |
553 | arg = NULL; | ||
554 | break; | ||
555 | } | ||
556 | /* If token is 'COMM' then it is special */ | ||
557 | field = &comm; | ||
548 | } | 558 | } |
559 | free_token(token); | ||
549 | 560 | ||
550 | arg->type = FILTER_ARG_FIELD; | 561 | arg->type = FILTER_ARG_FIELD; |
551 | arg->field.field = field; | 562 | arg->field.field = field; |
@@ -1414,11 +1425,31 @@ int pevent_filter_event_has_trivial(struct event_filter *filter, | |||
1414 | static int test_filter(struct event_format *event, | 1425 | static int test_filter(struct event_format *event, |
1415 | struct filter_arg *arg, struct record *record); | 1426 | struct filter_arg *arg, struct record *record); |
1416 | 1427 | ||
1428 | static const char * | ||
1429 | get_comm(struct event_format *event, struct record *record) | ||
1430 | { | ||
1431 | const char *comm; | ||
1432 | int pid; | ||
1433 | |||
1434 | pid = pevent_data_pid(event->pevent, record); | ||
1435 | comm = pevent_data_comm_from_pid(event->pevent, pid); | ||
1436 | return comm; | ||
1437 | } | ||
1438 | |||
1417 | static unsigned long long | 1439 | static unsigned long long |
1418 | get_value(struct format_field *field, struct record *record) | 1440 | get_value(struct event_format *event, |
1441 | struct format_field *field, struct record *record) | ||
1419 | { | 1442 | { |
1420 | unsigned long long val; | 1443 | unsigned long long val; |
1421 | 1444 | ||
1445 | /* Handle our dummy "comm" field */ | ||
1446 | if (field == &comm) { | ||
1447 | const char *name; | ||
1448 | |||
1449 | name = get_comm(event, record); | ||
1450 | return (unsigned long long)name; | ||
1451 | } | ||
1452 | |||
1422 | pevent_read_number_field(field, record->data, &val); | 1453 | pevent_read_number_field(field, record->data, &val); |
1423 | 1454 | ||
1424 | if (!(field->flags & FIELD_IS_SIGNED)) | 1455 | if (!(field->flags & FIELD_IS_SIGNED)) |
@@ -1491,7 +1522,7 @@ get_arg_value(struct event_format *event, struct filter_arg *arg, struct record | |||
1491 | { | 1522 | { |
1492 | switch (arg->type) { | 1523 | switch (arg->type) { |
1493 | case FILTER_ARG_FIELD: | 1524 | case FILTER_ARG_FIELD: |
1494 | return get_value(arg->field.field, record); | 1525 | return get_value(event, arg->field.field, record); |
1495 | 1526 | ||
1496 | case FILTER_ARG_VALUE: | 1527 | case FILTER_ARG_VALUE: |
1497 | if (arg->value.type != FILTER_NUMBER) | 1528 | if (arg->value.type != FILTER_NUMBER) |
@@ -1540,11 +1571,9 @@ static int test_num(struct event_format *event, | |||
1540 | } | 1571 | } |
1541 | } | 1572 | } |
1542 | 1573 | ||
1543 | static int test_str(struct event_format *event, | 1574 | static const char *get_field_str(struct filter_arg *arg, struct record *record) |
1544 | struct filter_arg *arg, struct record *record) | ||
1545 | { | 1575 | { |
1546 | const char *val = record->data + arg->str.field->offset; | 1576 | const char *val = record->data + arg->str.field->offset; |
1547 | const char *buffer; | ||
1548 | 1577 | ||
1549 | /* | 1578 | /* |
1550 | * We need to copy the data since we can't be sure the field | 1579 | * We need to copy the data since we can't be sure the field |
@@ -1554,24 +1583,34 @@ static int test_str(struct event_format *event, | |||
1554 | /* copy it */ | 1583 | /* copy it */ |
1555 | memcpy(arg->str.buffer, val, arg->str.field->size); | 1584 | memcpy(arg->str.buffer, val, arg->str.field->size); |
1556 | /* the buffer is already NULL terminated */ | 1585 | /* the buffer is already NULL terminated */ |
1557 | buffer = arg->str.buffer; | 1586 | val = arg->str.buffer; |
1558 | } else | 1587 | } |
1559 | /* OK, it's NULL terminated */ | 1588 | return val; |
1560 | buffer = val; | 1589 | } |
1590 | |||
1591 | static int test_str(struct event_format *event, | ||
1592 | struct filter_arg *arg, struct record *record) | ||
1593 | { | ||
1594 | const char *val; | ||
1595 | |||
1596 | if (arg->str.field == &comm) | ||
1597 | val = get_comm(event, record); | ||
1598 | else | ||
1599 | val = get_field_str(arg, record); | ||
1561 | 1600 | ||
1562 | switch (arg->str.type) { | 1601 | switch (arg->str.type) { |
1563 | case FILTER_CMP_MATCH: | 1602 | case FILTER_CMP_MATCH: |
1564 | return strcmp(buffer, arg->str.val) == 0; | 1603 | return strcmp(val, arg->str.val) == 0; |
1565 | 1604 | ||
1566 | case FILTER_CMP_NOT_MATCH: | 1605 | case FILTER_CMP_NOT_MATCH: |
1567 | return strcmp(buffer, arg->str.val) != 0; | 1606 | return strcmp(val, arg->str.val) != 0; |
1568 | 1607 | ||
1569 | case FILTER_CMP_REGEX: | 1608 | case FILTER_CMP_REGEX: |
1570 | /* Returns zero on match */ | 1609 | /* Returns zero on match */ |
1571 | return !regexec(&arg->str.reg, buffer, 0, NULL, 0); | 1610 | return !regexec(&arg->str.reg, val, 0, NULL, 0); |
1572 | 1611 | ||
1573 | case FILTER_CMP_NOT_REGEX: | 1612 | case FILTER_CMP_NOT_REGEX: |
1574 | return regexec(&arg->str.reg, buffer, 0, NULL, 0); | 1613 | return regexec(&arg->str.reg, val, 0, NULL, 0); |
1575 | 1614 | ||
1576 | default: | 1615 | default: |
1577 | /* ?? */ | 1616 | /* ?? */ |