aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-01-14 19:48:55 -0500
committerSteven Rostedt <rostedt@goodmis.org>2011-01-14 19:48:55 -0500
commitcf8d974439091212a6aa6c72a3d6d2cf3d3b7e8e (patch)
treeae4d660580d19b8cbe1c9702c81f34a0f326693e
parent6c696cec3f264a9399241b6e648f58bc97117d49 (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.txt8
-rw-r--r--parse-filter.c75
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
33static struct format_field comm = {
34 .name = "COMM",
35};
36
31struct event_list { 37struct 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,
1414static int test_filter(struct event_format *event, 1425static 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
1428static const char *
1429get_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
1417static unsigned long long 1439static unsigned long long
1418get_value(struct format_field *field, struct record *record) 1440get_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
1543static int test_str(struct event_format *event, 1574static 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
1591static 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 /* ?? */