perf tool: Fix enable/disable events logic for record command
cover perf tool: Fix enable/disable events logic for record command
hi,
this patchset fixes the event enable/disable logic for record command (patches 1 - 4) plus small fix for event parsing (patch 5).
Attached patches:
1/5 perf tool: Fix attributes for '{}' defined event groups 2/5 perf tool: Fix 'disabled' attribute config for record command 3/5 perf tool: Ensure single disable call per event in record comand 4/5 perf tool: Omit group members from perf_evlist__disable/enable 5/5 perf tool: Add basic event modifier sanity check
Also available in:git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/linux.git
perf/enable5
thanks,
jirka
--- tools/perf/builtin-record.c | 26 ++++++++++++++++++++++---- tools/perf/builtin-stat.c | 11 ++++------- tools/perf/tests/attr/test-record-group | 1 + tools/perf/tests/attr/test-record-group1 | 5 ++--- tools/perf/tests/attr/test-stat-group1 | 6 ++---- tools/perf/tests/open-syscall-tp-fields.c | 2 +- tools/perf/util/evlist.c | 10 ++++++---- tools/perf/util/evsel.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------ tools/perf/util/evsel.h | 3 +-- tools/perf/util/parse-events.c | 20 ++++++++++++++++++++ tools/perf/util/parse-events.l | 2 +- 11 files changed, 104 insertions(+), 32 deletions(-)
PATCH 1/5 perf tool: Fix attributes for '{}' defined event groups
Fixing events attributes for groups defined via '{}'.
Currently 'enable_on_exec' attribute in record command and both 'disabled ' and 'enable_on_exec' attributes in stat command are set based on the 'group' option. This eliminates proper setup for '{}' defined groups as they don't set 'group' option.
Making above attributes values based on the 'evsel->leader' as this is common to both group definition.
Moving perf_evlist__set_leader call within builtin-record ahead perf_evlist__config_attrs call, because the latter needs possible group leader links in place.
--- tools/perf/builtin-record.c | 8 ++++++-- tools/perf/builtin-stat.c | 11 ++++------- tools/perf/tests/attr/test-record-group1 | 4 +--- tools/perf/tests/attr/test-stat-group1 | 6 ++---- tools/perf/tests/open-syscall-tp-fields.c | 2 +- tools/perf/util/evlist.c | 6 ++---- tools/perf/util/evsel.c | 8 +++----- tools/perf/util/evsel.h | 3 +-- 8 files changed, 20 insertions(+), 28 deletions(-)
tools/perf/builtin-record.c +6 -2
@@ -230,11 +230,15 @@ static int perf_record__open(struct perf_record *rec)struct perf_record_opts *opts = &rec->opts;int rc =0 ; -perf_evlist__config_attrs (evlist, opts); - +/* +* Set the evsel leader links before we configure attributes, +* since some might depend on this info. +*/ if (opts->group)perf_evlist__set_leader (evlist); +perf_evlist__config_attrs (evlist, opts); +list_for_each_entry (pos, &evlist->entries, node) {struct perf_event_attr *attr = &pos->attr;/*
tools/perf/builtin-stat.c +4 -7
@@ -129,8 +129,7 @@ static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS ];static struct stats walltime_nsecs_stats; -static int create_perf_stat_counter (struct perf_evsel *evsel, -struct perf_evsel *first) +static int create_perf_stat_counter (struct perf_evsel *evsel) {struct perf_event_attr *attr = &evsel->attr;bool exclude_guest_missing = false;
@@ -153,7 +152,7 @@ retry:return 0 ; } -if (!perf_target__has_task (&target) && (!group || evsel == first)) { +if (!perf_target__has_task (&target) && (!evsel->leader)) { attr->disabled =1 ; attr->enable_on_exec =1 ; }
@@ -272,7 +271,7 @@ static int read_counter(struct perf_evsel *counter)static int __run_perf_stat (int argc__maybe_unused ,const char **argv) {unsigned long long t0, t1; -struct perf_evsel *counter, *first; +struct perf_evsel *counter;int status =0 ;int child_ready_pipe[2 ], go_pipe[2 ];const bool forks = (argc >0 );
@@ -332,10 +331,8 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)if (group)perf_evlist__set_leader (evsel_list); - first =perf_evlist__first (evsel_list); -list_for_each_entry (counter, &evsel_list->entries, node) { -if (create_perf_stat_counter (counter, first) <0 ) { +if (create_perf_stat_counter (counter) <0 ) {/* * PPC returns ENXIO for HW counters until 2.6.37 * (behavior changed with commit b0a873e).
tools/perf/tests/attr/test-record-group1 +1 -3
@@ -15,6 +15,4 @@ config=1 sample_type=327 mmap=0 comm=0 -# TODO this is disabled for --group option, enabled otherwise -# check why.. -enable_on_exec=1 +enable_on_exec=0
tools/perf/tests/attr/test-stat-group1 +2 -4
@@ -11,7 +11,5 @@ group_fd=-1 fd=2 group_fd=1 config=1 -# TODO both disabled and enable_on_exec are disabled for --group option, -# enabled otherwise, check why.. -disabled=1 -enable_on_exec=1 +disabled=0 +enable_on_exec=0
tools/perf/tests/open-syscall-tp-fields.c +1 -1
@@ -41,7 +41,7 @@ int test__syscall_open_tp_fields(void) goto out_delete_evlist; } -perf_evsel__config (evsel, &opts, evsel); +perf_evsel__config (evsel, &opts); evlist->threads->map[0 ] =getpid ();
tools/perf/util/evlist.c +2 -4
@@ -52,15 +52,13 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,void perf_evlist__config_attrs (struct perf_evlist *evlist,struct perf_record_opts *opts) { -struct perf_evsel *evsel, *first; +struct perf_evsel *evsel;if (evlist->cpus->map[0 ] <0 ) opts->no_inherit = true; - first =perf_evlist__first (evlist); -list_for_each_entry (evsel, &evlist->entries, node) { -perf_evsel__config (evsel, opts, first); +perf_evsel__config (evsel, opts);if (evlist->nr_entries >1 ) evsel->attr.sample_type |=PERF_SAMPLE_ID ;
tools/perf/util/evsel.c +3 -5
@@ -404,8 +404,8 @@ const char *perf_evsel__name(struct perf_evsel *evsel)return evsel->name ?:"unknown" ; } -void perf_evsel__config (struct perf_evsel *evsel,struct perf_record_opts *opts, -struct perf_evsel *first) +void perf_evsel__config (struct perf_evsel *evsel, +struct perf_record_opts *opts) {struct perf_event_attr *attr = &evsel->attr;int track = !evsel->idx;/* only the first counter needs these */
@@ -486,10 +486,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, attr->mmap = track; attr->comm = track; -if (perf_target__none (&opts->target) && - (!opts->group || evsel == first)) { +if (perf_target__none (&opts->target) && (!evsel->leader)) attr->enable_on_exec =1 ; - } }int perf_evsel__alloc_fd (struct perf_evsel *evsel,int ncpus,int nthreads)
tools/perf/util/evsel.h +1 -2
@@ -92,8 +92,7 @@ void perf_evsel__exit(struct perf_evsel *evsel);void perf_evsel__delete (struct perf_evsel *evsel);void perf_evsel__config (struct perf_evsel *evsel, -struct perf_record_opts *opts, -struct perf_evsel *first); +struct perf_record_opts *opts);bool perf_evsel__is_cache_op_valid (u8 type,u8 op);
Signature · 1 line
1.7.11.7
[tip:perf/core] perf tools: Fix attributes for '{}' defined event groups
Commit-ID: cac21425578abddc4e9f529845832a57ba27ce0f Gitweb: http://git.kernel.org/tip/cac21425578abddc4e9f529845832a57ba27ce0f Author: Jiri Olsa <[email protected]> AuthorDate: Mon, 12 Nov 2012 18:34:00 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 14 Nov 2012 16:51:50 -0300
perf tools: Fix attributes for '{}' defined event groups
Fixing events attributes for groups defined via '{}'.
Currently 'enable_on_exec' attribute in record command and both 'disabled ' and 'enable_on_exec' attributes in stat command are set based on the 'group' option. This eliminates proper setup for '{}' defined groups as they don't set 'group' option.
Making above attributes values based on the 'evsel->leader' as this is common to both group definition.
Moving perf_evlist__set_leader call within builtin-record ahead perf_evlist__config_attrs call, because the latter needs possible group leader links in place.
--- tools/perf/builtin-record.c | 8 ++++++-- tools/perf/builtin-stat.c | 11 ++++------- tools/perf/tests/attr/test-record-group1 | 4 +--- tools/perf/tests/attr/test-stat-group1 | 6 ++---- tools/perf/tests/open-syscall-tp-fields.c | 2 +- tools/perf/util/evlist.c | 6 ++---- tools/perf/util/evsel.c | 8 +++----- tools/perf/util/evsel.h | 3 +-- 8 files changed, 20 insertions(+), 28 deletions(-)
tools/perf/builtin-record.c +6 -2
@@ -230,11 +230,15 @@ static int perf_record__open(struct perf_record *rec)struct perf_record_opts *opts = &rec->opts;int rc =0 ; -perf_evlist__config_attrs (evlist, opts); - +/* +* Set the evsel leader links before we configure attributes, +* since some might depend on this info. +*/ if (opts->group)perf_evlist__set_leader (evlist); +perf_evlist__config_attrs (evlist, opts); +list_for_each_entry (pos, &evlist->entries, node) {struct perf_event_attr *attr = &pos->attr;/*
tools/perf/builtin-stat.c +4 -7
@@ -129,8 +129,7 @@ static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS ];static struct stats walltime_nsecs_stats; -static int create_perf_stat_counter (struct perf_evsel *evsel, -struct perf_evsel *first) +static int create_perf_stat_counter (struct perf_evsel *evsel) {struct perf_event_attr *attr = &evsel->attr;bool exclude_guest_missing = false;
@@ -153,7 +152,7 @@ retry:return 0 ; } -if (!perf_target__has_task (&target) && (!group || evsel == first)) { +if (!perf_target__has_task (&target) && (!evsel->leader)) { attr->disabled =1 ; attr->enable_on_exec =1 ; }
@@ -272,7 +271,7 @@ static int read_counter(struct perf_evsel *counter)static int __run_perf_stat (int argc__maybe_unused ,const char **argv) {unsigned long long t0, t1; -struct perf_evsel *counter, *first; +struct perf_evsel *counter;int status =0 ;int child_ready_pipe[2 ], go_pipe[2 ];const bool forks = (argc >0 );
@@ -332,10 +331,8 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)if (group)perf_evlist__set_leader (evsel_list); - first =perf_evlist__first (evsel_list); -list_for_each_entry (counter, &evsel_list->entries, node) { -if (create_perf_stat_counter (counter, first) <0 ) { +if (create_perf_stat_counter (counter) <0 ) {/* * PPC returns ENXIO for HW counters until 2.6.37 * (behavior changed with commit b0a873e).
tools/perf/tests/attr/test-record-group1 +1 -3
@@ -15,6 +15,4 @@ config=1 sample_type=327 mmap=0 comm=0 -# TODO this is disabled for --group option, enabled otherwise -# check why.. -enable_on_exec=1 +enable_on_exec=0
tools/perf/tests/attr/test-stat-group1 +2 -4
@@ -11,7 +11,5 @@ group_fd=-1 fd=2 group_fd=1 config=1 -# TODO both disabled and enable_on_exec are disabled for --group option, -# enabled otherwise, check why.. -disabled=1 -enable_on_exec=1 +disabled=0 +enable_on_exec=0
tools/perf/tests/open-syscall-tp-fields.c +1 -1
@@ -41,7 +41,7 @@ int test__syscall_open_tp_fields(void) goto out_delete_evlist; } -perf_evsel__config (evsel, &opts, evsel); +perf_evsel__config (evsel, &opts); evlist->threads->map[0 ] =getpid ();
tools/perf/util/evlist.c +2 -4
@@ -52,15 +52,13 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,void perf_evlist__config_attrs (struct perf_evlist *evlist,struct perf_record_opts *opts) { -struct perf_evsel *evsel, *first; +struct perf_evsel *evsel;if (evlist->cpus->map[0 ] <0 ) opts->no_inherit = true; - first =perf_evlist__first (evlist); -list_for_each_entry (evsel, &evlist->entries, node) { -perf_evsel__config (evsel, opts, first); +perf_evsel__config (evsel, opts);if (evlist->nr_entries >1 ) evsel->attr.sample_type |=PERF_SAMPLE_ID ;
tools/perf/util/evsel.c +3 -5
@@ -404,8 +404,8 @@ const char *perf_evsel__name(struct perf_evsel *evsel)return evsel->name ?:"unknown" ; } -void perf_evsel__config (struct perf_evsel *evsel,struct perf_record_opts *opts, -struct perf_evsel *first) +void perf_evsel__config (struct perf_evsel *evsel, +struct perf_record_opts *opts) {struct perf_event_attr *attr = &evsel->attr;int track = !evsel->idx;/* only the first counter needs these */
@@ -486,10 +486,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, attr->mmap = track; attr->comm = track; -if (perf_target__none (&opts->target) && - (!opts->group || evsel == first)) { +if (perf_target__none (&opts->target) && (!evsel->leader)) attr->enable_on_exec =1 ; - } }int perf_evsel__alloc_fd (struct perf_evsel *evsel,int ncpus,int nthreads)
tools/perf/util/evsel.h +1 -2
@@ -92,8 +92,7 @@ void perf_evsel__exit(struct perf_evsel *evsel);void perf_evsel__delete (struct perf_evsel *evsel);void perf_evsel__config (struct perf_evsel *evsel, -struct perf_record_opts *opts, -struct perf_evsel *first); +struct perf_record_opts *opts);bool perf_evsel__is_cache_op_valid (u8 type,u8 op);
PATCH 2/5 perf tool: Fix 'disabled' attribute config for record command
In reply to Jiri OlsaCurrently the record command sets all events initially as disabled.
There's non conditional perf_evlist__enable call, that enables all events before we exec tracee program. That actually screws whole enable_on_exec logic, because the event is enabled before the traced program got executed.
What we actually want is:
1) For any type of traced program:
- all independent events and group leaders are disabled
- all group members are enabled
Group members are ruled by group leaders. They need to be enabled, because the group scheduling relies on that.
2) For traced programs executed by perf:
- all independent events and group leaders have enable_on_exec set
- we don't specifically enable or disable any event during the record command
Independent events and group leaders are initially disabled and get enabled by exec. Group members are ruled by group leaders as stated in 1).
3) For traced programs attached by perf (pid/tid):
- we specifically enable or disable all events during the record command
When attaching events to already running traced we enable/disable events specifically, as there's no initial traced exec call.
Fixing appropriate perf_event_attr test case to cover this change.
--- tools/perf/builtin-record.c | 15 ++++++++++-- tools/perf/tests/attr/test-record-group | 1 + tools/perf/tests/attr/test-record-group1 | 1 + tools/perf/util/evsel.c | 42 +++++++++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 3 deletions(-)
tools/perf/builtin-record.c +13 -2
@@ -701,7 +701,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) } } -perf_evlist__enable (evsel_list); +/* +* When perf is starting the traced process, all the events +* (apart from group members) have enable_on_exec=1 set, +* so don't spoil it by prematurely enabling them. +*/ +if (!perf_target__none (&opts->target)) +perf_evlist__enable (evsel_list);/* * Let the child rip
@@ -724,7 +730,12 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) waking++; } -if (done) +/* +* When perf is starting the traced process, at the end events +* die with the process and we wait for that. Thus no need to +* disable events in this case. +*/ +if (done && !perf_target__none (&opts->target))perf_evlist__disable (evsel_list); }
tools/perf/tests/attr/test-record-group +1 -0
@@ -15,3 +15,4 @@ sample_type=327 mmap=0 comm=0 enable_on_exec=0 +disabled=0
tools/perf/tests/attr/test-record-group1 +1 -0
@@ -16,3 +16,4 @@ sample_type=327 mmap=0 comm=0 enable_on_exec=0 +disabled=0
tools/perf/util/evsel.c +41 -1
60 lines not on this page · raw message
Signature · 1 line
1.7.11.7
[tip:perf/core] perf tools: Fix 'disabled' attribute config for record command
Commit-ID: 774cb499ca9ab0e5950a149d1fe102b125da1cee Gitweb: http://git.kernel.org/tip/774cb499ca9ab0e5950a149d1fe102b125da1cee Author: Jiri Olsa <[email protected]> AuthorDate: Mon, 12 Nov 2012 18:34:01 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 14 Nov 2012 16:52:03 -0300
perf tools: Fix 'disabled' attribute config for record command
Currently the record command sets all events initially as disabled.
There's non conditional perf_evlist__enable call, that enables all events before we exec tracee program. That actually screws whole enable_on_exec logic, because the event is enabled before the traced program got executed.
What we actually want is:
1) For any type of traced program:
- all independent events and group leaders are disabled
- all group members are enabled
Group members are ruled by group leaders. They need to be enabled, because the group scheduling relies on that.
2) For traced programs executed by perf:
- all independent events and group leaders have enable_on_exec set
- we don't specifically enable or disable any event during the record command
Independent events and group leaders are initially disabled and get enabled by exec. Group members are ruled by group leaders as stated in 1).
3) For traced programs attached by perf (pid/tid):
- we specifically enable or disable all events during the record command
When attaching events to already running traced we enable/disable events specifically, as there's no initial traced exec call.
Fixing appropriate perf_event_attr test case to cover this change.
--- tools/perf/builtin-record.c | 15 ++++++++++-- tools/perf/tests/attr/test-record-group | 1 + tools/perf/tests/attr/test-record-group1 | 1 + tools/perf/util/evsel.c | 42 +++++++++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 3 deletions(-)
tools/perf/builtin-record.c +13 -2
@@ -701,7 +701,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) } } -perf_evlist__enable (evsel_list); +/* +* When perf is starting the traced process, all the events +* (apart from group members) have enable_on_exec=1 set, +* so don't spoil it by prematurely enabling them. +*/ +if (!perf_target__none (&opts->target)) +perf_evlist__enable (evsel_list);/* * Let the child rip
@@ -724,7 +730,12 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) waking++; } -if (done) +/* +* When perf is starting the traced process, at the end events +* die with the process and we wait for that. Thus no need to +* disable events in this case. +*/ +if (done && !perf_target__none (&opts->target))perf_evlist__disable (evsel_list); }
tools/perf/tests/attr/test-record-group +1 -0
@@ -15,3 +15,4 @@ sample_type=327 mmap=0 comm=0 enable_on_exec=0 +disabled=0
tools/perf/tests/attr/test-record-group1 +1 -0
@@ -16,3 +16,4 @@ sample_type=327 mmap=0 comm=0 enable_on_exec=0 +disabled=0
tools/perf/util/evsel.c +41 -1
60 lines not on this page · raw message
PATCH 3/5 perf tool: Ensure single disable call per event in record comand
In reply to Jiri OlsaIt's possible we issue the event disable ioctl multiple times until we read the final portion of the mmap buffer.
Ensuring just single disable ioctl call for event, because there's no need to do that more than once.
--- tools/perf/builtin-record.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
tools/perf/builtin-record.c +4 -1
@@ -502,6 +502,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)struct perf_evlist *evsel_list = rec->evlist;const char *output_name = rec->output_name;struct perf_session *session; +bool disabled = false; rec->progname = argv[0 ];
@@ -735,8 +736,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)* die with the process and we wait for that. Thus no need to * disable events in this case. */ -if (done && !perf_target__none (&opts->target)) +if (done && !disabled && !perf_target__none (&opts->target)) {perf_evlist__disable (evsel_list); + disabled = true; + } }if (quiet || signr ==SIGUSR1 )
Signature · 1 line
1.7.11.7
[tip:perf/core] perf tools: Ensure single disable call per event in record comand
Commit-ID: 2711926a416733b853977a0e014c713955ad0d8a Gitweb: http://git.kernel.org/tip/2711926a416733b853977a0e014c713955ad0d8a Author: Jiri Olsa <[email protected]> AuthorDate: Mon, 12 Nov 2012 18:34:02 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 14 Nov 2012 16:52:09 -0300
perf tools: Ensure single disable call per event in record comand
It's possible we issue the event disable ioctl multiple times until we read the final portion of the mmap buffer.
Ensuring just single disable ioctl call for event, because there's no need to do that more than once.
--- tools/perf/builtin-record.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
tools/perf/builtin-record.c +4 -1
@@ -502,6 +502,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)struct perf_evlist *evsel_list = rec->evlist;const char *output_name = rec->output_name;struct perf_session *session; +bool disabled = false; rec->progname = argv[0 ];
@@ -735,8 +736,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)* die with the process and we wait for that. Thus no need to * disable events in this case. */ -if (done && !perf_target__none (&opts->target)) +if (done && !disabled && !perf_target__none (&opts->target)) {perf_evlist__disable (evsel_list); + disabled = true; + } }if (quiet || signr ==SIGUSR1 )
PATCH 4/5 perf tool: Omit group members from perf_evlist__disable/enable
In reply to Jiri OlsaThere's no need to disable/enable ordinary group member events, because they are initialy enabled and get scheduled by the leader.
--- tools/perf/util/evlist.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/util/evlist.c +4 -0
@@ -222,6 +222,8 @@ void perf_evlist__disable(struct perf_evlist *evlist)for (cpu =0 ; cpu < evlist->cpus->nr; cpu++) {list_for_each_entry (pos, &evlist->entries, node) { +if (pos->leader) +continue ;for (thread =0 ; thread < evlist->threads->nr; thread++)ioctl (FD (pos, cpu, thread),PERF_EVENT_IOC_DISABLE ,0 );
@@ -236,6 +238,8 @@ void perf_evlist__enable(struct perf_evlist *evlist)for (cpu =0 ; cpu <cpu_map__nr (evlist->cpus); cpu++) {list_for_each_entry (pos, &evlist->entries, node) { +if (pos->leader) +continue ;for (thread =0 ; thread < evlist->threads->nr; thread++)ioctl (FD (pos, cpu, thread),PERF_EVENT_IOC_ENABLE ,0 );
Signature · 1 line
1.7.11.7
[tip:perf/core] perf tools: Omit group members from perf_evlist__disable/enable
Commit-ID: 3fe4430dd66837d8fcdb63c167e908655fc842e3 Gitweb: http://git.kernel.org/tip/3fe4430dd66837d8fcdb63c167e908655fc842e3 Author: Jiri Olsa <[email protected]> AuthorDate: Mon, 12 Nov 2012 18:34:03 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 14 Nov 2012 16:52:15 -0300
perf tools: Omit group members from perf_evlist__disable/enable
There's no need to disable/enable ordinary group member events, because they are initialy enabled and get scheduled by the leader.
--- tools/perf/util/evlist.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/util/evlist.c +4 -0
@@ -222,6 +222,8 @@ void perf_evlist__disable(struct perf_evlist *evlist)for (cpu =0 ; cpu < evlist->cpus->nr; cpu++) {list_for_each_entry (pos, &evlist->entries, node) { +if (pos->leader) +continue ;for (thread =0 ; thread < evlist->threads->nr; thread++)ioctl (FD (pos, cpu, thread),PERF_EVENT_IOC_DISABLE ,0 );
@@ -236,6 +238,8 @@ void perf_evlist__enable(struct perf_evlist *evlist)for (cpu =0 ; cpu <cpu_map__nr (evlist->cpus); cpu++) {list_for_each_entry (pos, &evlist->entries, node) { +if (pos->leader) +continue ;for (thread =0 ; thread < evlist->threads->nr; thread++)ioctl (FD (pos, cpu, thread),PERF_EVENT_IOC_ENABLE ,0 );
PATCH 5/5 perf tool: Add basic event modifier sanity check
In reply to Jiri OlsaUpdating event parser to allow any non zero string containing [ukhpGH] characters for event modifier.
The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present.
--- tools/perf/util/parse-events.c | 20 ++++++++++++++++++++ tools/perf/util/parse-events.l | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +20 -0
@@ -722,6 +722,23 @@ static int get_event_modifier(struct event_modifier *mod, char *str,return 0 ; } +/* +* Basic modifier sanity check to validate it contains only one +* instance of any modifier (apart from 'p') present. +*/ +static int check_modifier (char *str) +{ +char *p = str; + +while (*p) { +if (*p !='p' &&strchr (p +1 , *p)) +return -1 ; + p++; + } + +return 0 ; +} +int parse_events__modifier_event (struct list_head *list,char *str,bool add) {struct perf_evsel *evsel;
@@ -730,6 +747,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)if (str ==NULL )return 0 ; +if (check_modifier (str)) +return -EINVAL ; +if (!add &&get_event_modifier (&mod, str,NULL ))return -EINVAL ;
tools/perf/util/parse-events.l +1 -1
@@ -82,7 +82,7 @@ num_hex 0x[a-fA-F0-9]+ num_raw_hex [a-fA-F0-9]+ name [a-zA-Z_*?][a-zA-Z0-9_*?]* name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* -modifier_event [ukhpGH]{1,8} +modifier_event [ukhpGH]+ modifier_bp [rwx]{1,3} %%
Signature · 1 line
1.7.11.7
Namhyung Kim
maintainerRe: [PATCH 5/5] perf tool: Add basic event modifier sanity check
Hi Jiri,
Quoted 6 lines · Jiri Olsa
Updating event parser to allow any non zero string containing [ukhpGH] characters for event modifier.
The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present.
[snip]
tools/perf/util/parse-events.c static int get_event_modifier(struct event_modifier *mod, char *str, · line 737
Quoted 13 lines
tools/perf/util/parse-events.c +13
-0+/* +* Basic modifier sanity check to validate it contains only one +* instance of any modifier (apart from 'p') present. +*/ +static int check_modifier (char *str) +{ +char *p = str; + +while (*p) { +if (*p !='p' &&strchr (p +1 , *p)) +return -1 ; + p++; + }
How about adding a length check too? i.e. something like:
if ((p - str) > strlen("ukhGHppp"))
return -1;Thanks,
Namhyung
Quoted 30 lines
tools/perf/util/parse-events.c +7
-0+ +return 0 ; +} +int parse_events__modifier_event (struct list_head *list,char *str,bool add) {struct perf_evsel *evsel;@@ -730,6 +747,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)if (str ==NULL )return 0 ; +if (check_modifier (str)) +return -EINVAL ; +if (!add &&get_event_modifier (&mod, str,NULL ))return -EINVAL ;tools/perf/util/parse-events.l +1
-1@@ -82,7 +82,7 @@ num_hex 0x[a-fA-F0-9]+ num_raw_hex [a-fA-F0-9]+ name [a-zA-Z_*?][a-zA-Z0-9_*?]* name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* -modifier_event [ukhpGH]{1,8} +modifier_event [ukhpGH]+ modifier_bp [rwx]{1,3} %%
PATCH v2 5/5 perf tool: Add basic event modifier sanity check
Quoted 26 lines · Namhyung Kim
Hi Jiri,
Quoted 6 lines · Jiri Olsa
Updating event parser to allow any non zero string containing [ukhpGH] characters for event modifier.
The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present.
[snip]
Review
Quoted 13 lines
(quoted diff) +13
-0+/* + * Basic modifier sanity check to validate it contains only one + * instance of any modifier (apart from 'p') present. + */ +static int check_modifier(char *str) +{ + char *p = str; + + while (*p) { + if (*p != 'p' && strchr(p + 1, *p)) + return -1; + p++; + }How about adding a length check too? i.e. something like:
Quoted 2 lines
if ((p - str) > strlen("ukhGHppp"))
return -1;ok, v2 attached
thanks,
jirka
---
Updating event parser to allow any non zero string containing [ukhpGH] characters for event modifier.
The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present.
v2:
- added length check suggested Namhyung Kim
--- tools/perf/util/parse-events.c | 24 ++++++++++++++++++++++++ tools/perf/util/parse-events.l | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +24 -0
@@ -722,6 +722,27 @@ static int get_event_modifier(struct event_modifier *mod, char *str,return 0 ; } +/* +* Basic modifier sanity check to validate it contains only one +* instance of any modifier (apart from 'p') present. +*/ +static int check_modifier (char *str) +{ +char *p = str; + +/* The sizeof includes 0 byte as well. */ +if (strlen (str) > (sizeof ("ukhGHppp" ) -1 )) +return -1 ; + +while (*p) { +if (*p !='p' &&strchr (p +1 , *p)) +return -1 ; + p++; + } + +return 0 ; +} +int parse_events__modifier_event (struct list_head *list,char *str,bool add) {struct perf_evsel *evsel;
@@ -730,6 +751,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)if (str ==NULL )return 0 ; +if (check_modifier (str)) +return -EINVAL ; +if (!add &&get_event_modifier (&mod, str,NULL ))return -EINVAL ;
tools/perf/util/parse-events.l +1 -1
@@ -82,7 +82,7 @@ num_hex 0x[a-fA-F0-9]+ num_raw_hex [a-fA-F0-9]+ name [a-zA-Z_*?][a-zA-Z0-9_*?]* name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* -modifier_event [ukhpGH]{1,8} +modifier_event [ukhpGH]+ modifier_bp [rwx]{1,3} %%
Signature · 1 line
1.7.11.7
[tip:perf/core] perf tools: Add basic event modifier sanity check
Commit-ID: 534123f458f196bcc269f97d20ccf125925c2e7b Gitweb: http://git.kernel.org/tip/534123f458f196bcc269f97d20ccf125925c2e7b Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 13 Nov 2012 15:32:58 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 14 Nov 2012 16:52:24 -0300
perf tools: Add basic event modifier sanity check
Updating event parser to allow any non zero string containing [ukhpGH] characters for event modifier.
The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present.
v2:
- added length check suggested Namhyung Kim
--- tools/perf/util/parse-events.c | 24 ++++++++++++++++++++++++ tools/perf/util/parse-events.l | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +24 -0
@@ -722,6 +722,27 @@ static int get_event_modifier(struct event_modifier *mod, char *str,return 0 ; } +/* +* Basic modifier sanity check to validate it contains only one +* instance of any modifier (apart from 'p') present. +*/ +static int check_modifier (char *str) +{ +char *p = str; + +/* The sizeof includes 0 byte as well. */ +if (strlen (str) > (sizeof ("ukhGHppp" ) -1 )) +return -1 ; + +while (*p) { +if (*p !='p' &&strchr (p +1 , *p)) +return -1 ; + p++; + } + +return 0 ; +} +int parse_events__modifier_event (struct list_head *list,char *str,bool add) {struct perf_evsel *evsel;
@@ -730,6 +751,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)if (str ==NULL )return 0 ; +if (check_modifier (str)) +return -EINVAL ; +if (!add &&get_event_modifier (&mod, str,NULL ))return -EINVAL ;
tools/perf/util/parse-events.l +1 -1
@@ -82,7 +82,7 @@ num_hex 0x[a-fA-F0-9]+ num_raw_hex [a-fA-F0-9]+ name [a-zA-Z_*?][a-zA-Z0-9_*?]* name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* -modifier_event [ukhpGH]{1,8} +modifier_event [ukhpGH]+ modifier_bp [rwx]{1,3} %%
Quoted 18 lines · Jiri Olsa
hi,
this patchset fixes the event enable/disable logic for record command (patches 1 - 4) plus small fix for event parsing (patch 5).Attached patches:
1/5 perf tool: Fix attributes for '{}' defined event groups 2/5 perf tool: Fix 'disabled' attribute config for record command 3/5 perf tool: Ensure single disable call per event in record comand 4/5 perf tool: Omit group members from perf_evlist__disable/enable 5/5 perf tool: Add basic event modifier sanity checkAlso available in:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/linux.git
perf/enable5thanks,
jirka
Quoted 7 lines
Cc Corey Ashford <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Ingo Molnar <[email protected]>Cc Namhyung Kim <[email protected]>Cc Paul Mackerras <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>
I commented on the patch 5/5, anyway looks good to me:
Thanks,
Namhyung