All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] perf record: Apply filter to all events in a glob matching
@ 2015-07-10  7:36 Wang Nan
  2015-07-10  7:36 ` [PATCH 2/2] perf record: Allow passing perf's own pid to '--filter' Wang Nan
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Wang Nan @ 2015-07-10  7:36 UTC (permalink / raw)
  To: acme, rostedt, ak, brendan.d.gregg; +Cc: lizefan, linux-kernel, pi3orama

There is an old problem in perf's filter applying which first posted
at Sep. 2014 at https://lkml.org/lkml/2014/9/9/944 that, if passing
multiple events in a glob matching expression in cmdline then add
'--filter' after them, the filter will be applied on only the last one.

For example:

 # dd if=/dev/zero of=/dev/null &
 [1] 464
 # perf record -a -e 'syscalls:sys_*_read' --filter 'common_pid != 464' sleep 0.1
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.239 MB perf.data (2094 samples) ]
 # perf report --stdio | tee
 ...
 # Samples: 2K of event 'syscalls:sys_enter_read'
 # Event count (approx.): 2092
 ...
 # Samples: 2  of event 'syscalls:sys_exit_read'
 # Event count (approx.): 2
 ...

In this example, filter only applied on 'syscalls:sys_exit_read', and
there's no way to set filter for ''syscalls:sys_enter_read'.

This patch adds a 'cmdline_group_boundary' for 'struct evsel', and
apply filter on all events between two boundary marks.

After applying this patch:

 # perf record -a -e 'syscalls:sys_*_read' --filter 'common_pid != 464' sleep 0.1
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.031 MB perf.data (3 samples) ]
 # perf report --stdio | tee
 ...
 # Samples: 1  of event 'syscalls:sys_enter_read'
 # Event count (approx.): 1
 ...
 # Samples: 2  of event 'syscalls:sys_exit_read'
 # Event count (approx.): 2
 ...

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/perf/util/evsel.c        |  1 +
 tools/perf/util/evsel.h        |  1 +
 tools/perf/util/parse-events.c | 30 +++++++++++++++++++++---------
 3 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 83c0803..49fb7b5 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -210,6 +210,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
 	perf_evsel__object.init(evsel);
 	evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
 	perf_evsel__calc_id_pos(evsel);
+	evsel->cmdline_group_boundary = false;
 }
 
 struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index fe9f327..1fc263a 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -86,6 +86,7 @@ struct perf_evsel {
 	unsigned long		*per_pkg_mask;
 	struct perf_evsel	*leader;
 	char			*group_name;
+	bool			cmdline_group_boundary;
 };
 
 union u64_swap {
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a71eeb2..bbb7fbc 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1065,8 +1065,13 @@ int parse_events(struct perf_evlist *evlist, const char *str,
 	perf_pmu__parse_cleanup();
 	if (!ret) {
 		int entries = data.idx - evlist->nr_entries;
+		struct perf_evsel *last;
+
 		perf_evlist__splice_list_tail(evlist, &data.list, entries);
 		evlist->nr_groups += data.nr_groups;
+		last = perf_evlist__last(evlist);
+		last->cmdline_group_boundary = true;
+
 		return 0;
 	}
 
@@ -1171,16 +1176,23 @@ int parse_filter(const struct option *opt, const char *str,
 	if (evlist->nr_entries > 0)
 		last = perf_evlist__last(evlist);
 
-	if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
-		fprintf(stderr,
-			"--filter option should follow a -e tracepoint option\n");
-		return -1;
-	}
+	do {
+		if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
+			fprintf(stderr,
+				"--filter option should follow a -e tracepoint option\n");
+			return -1;
+		}
 
-	if (perf_evsel__set_filter(last, str) < 0) {
-		fprintf(stderr, "not enough memory to hold filter string\n");
-		return -1;
-	}
+		if (perf_evsel__set_filter(last, str) < 0) {
+			fprintf(stderr,
+				"not enough memory to hold filter string\n");
+			return -1;
+		}
+
+		if (last->node.prev == &evlist->entries)
+			return 0;
+		last = list_entry(last->node.prev, struct perf_evsel, node);
+	} while (!last->cmdline_group_boundary);
 
 	return 0;
 }
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-07-21  9:36 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-10  7:36 [PATCH 1/2] perf record: Apply filter to all events in a glob matching Wang Nan
2015-07-10  7:36 ` [PATCH 2/2] perf record: Allow passing perf's own pid to '--filter' Wang Nan
2015-07-21  9:34   ` [tip:perf/core] perf record: Allow filtering perf' s pid via --exclude-perf tip-bot for Wang Nan
2015-07-20 18:30 ` [PATCH 1/2] perf record: Apply filter to all events in a glob matching Arnaldo Carvalho de Melo
2015-07-21  9:34 ` [tip:perf/core] " tip-bot for Wang Nan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.