perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit 51ab7155c08baf45cc2aa911961e5b78422e478f:
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2015-04-08 17:03:47 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo
for you to fetch changes up to 7b8283b56d9fb36106ff1c459dfd399a20bd374d:
perf evlist: Fix type for references to data_head/tail (2015-04-10 11:29:20 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
New user visible features:
- Support multiple probes on different binaries on the same command line (Masami Hiramatsu)
User visible fixes:
- Fix synthesizing fork_event.ppid for non-main thread (David Ahern)
- Fix cross-endian analysis (David Ahern)
- Fix segfault in 'perf buildid-list' when show DSOs with hits (He Kuang)
Infrastructure:
- Fix type for references to data_head/tail (David Ahern)
- Fix error path to do closedir() when synthesizing threads (Arnaldo Carvalho de Melo)
----------------------------------------------------------------
Arnaldo Carvalho de Melo (1):
perf tools: Fix error path to do closedir() when synthesizing threads
David Ahern (3):
perf tools: Fix synthesizing fork_event.ppid for non-main thread perf tools: Fix cross-endian analysis
perf evlist: Fix type for references to data_head/tail
He Kuang (1):
perf buildid-list: Fix segfault when show DSOs with hits
Masami Hiramatsu (2):
perf probe: Support multiple probes on different binaries perf probe: Check the orphaned -x option
tools/perf/builtin-probe.c | 19 +++++++++++++++++-- tools/perf/builtin-record.c | 4 ++-- tools/perf/util/build-id.c | 8 ++------ tools/perf/util/event.c | 31 +++++++++++++++++++++---------- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evlist.h | 9 ++++----- tools/perf/util/header.c | 5 ++++- tools/perf/util/machine.c | 4 +--- tools/perf/util/machine.h | 1 + tools/perf/util/probe-event.c | 5 +++-- tools/perf/util/probe-event.h | 6 +++--- 11 files changed, 61 insertions(+), 37 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/7 perf tools: Fix synthesizing fork_event.ppid for non-main thread
From: David Ahern <[email protected]>
Commit ca6c41c59b9 sets the ppid based on what is read from the /proc/pid/status file when synthesizing fork events.
This is correct thing to do for new processes but not threads of a process.
Fix ppid for threads to be the main thread when synthesizing fork events (ie., assume main thread spawned all sub-threads in a process).
--- tools/perf/util/event.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
tools/perf/util/event.c +12 -2
@@ -183,8 +183,18 @@ static int perf_event__synthesize_fork(struct perf_tool *tool, {memset (&event->fork,0 ,sizeof (event->fork) + machine->id_hdr_size); - event->fork.ppid = ppid; - event->fork.ptid = ppid; +/* +* for main thread set parent to ppid from status file. For other +* threads set parent pid to main thread. ie., assume main thread +* spawns all threads in a process +*/ +if (tgid == pid) { + event->fork.ppid = ppid; + event->fork.ptid = ppid; + }else { + event->fork.ppid = tgid; + event->fork.ptid = tgid; + } event->fork.pid = tgid; event->fork.tid = pid; event->fork.header.type =PERF_RECORD_FORK ;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 2/7 perf tools: Fix error path to do closedir() when synthesizing threads
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
When traversing /proc to synthesize the PERF_RECORD_FORK et al events we were bailing out on errors without calling closedir(), fix it.
--- tools/perf/util/event.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
tools/perf/util/event.c +9 -8
@@ -387,6 +387,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,DIR *tasks;struct dirent dirent, *next;pid_t tgid, ppid; +int rc =0 ;/* special case: only send one comm event using passed in pid */ if (!full) {
@@ -414,38 +415,38 @@ static int __event__synthesize_thread(union perf_event *comm_event,while (!readdir_r (tasks, &dirent, &next) && next) {char *end; -int rc =0 ;pid_t _pid; _pid =strtol (dirent.d_name, &end,10 );if (*end)continue ; + rc =-1 ;if (perf_event__prepare_comm (comm_event, _pid, machine, &tgid, &ppid) !=0 ) -return -1 ; +break ;if (perf_event__synthesize_fork (tool, fork_event, _pid, tgid, ppid, process, machine) <0 ) -return -1 ; +break ;/* * Send the prepared comm event */ if (process (tool, comm_event, &synth_sample, machine) !=0 ) -return -1 ; +break ; + rc =0 ;if (_pid == pid) {/* process the parent's maps too */ rc =perf_event__synthesize_mmap_events (tool, mmap_event, pid, tgid, process, machine, mmap_data); +if (rc) +break ; } - -if (rc) -return rc; }closedir (tasks); -return 0 ; +return rc; } int perf_event__synthesize_thread_map(struct perf_tool *tool,
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 3/7 perf tools: Fix cross-endian analysis
In reply to Arnaldo Carvalho de MeloFrom: David Ahern <[email protected]>
Trying to analyze a big endian data file on little endian system fails with the error:
0xa9b40 [0x70]: failed to process type: 9
The problem is that header parsing is not done correctly because the file attributes are not swapped. Make it so. With this patch able to analyze a sparc64 data file on x86_64.
--- tools/perf/util/header.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
tools/perf/util/header.c +4 -1
@@ -2504,8 +2504,11 @@ int perf_session__read_header(struct perf_session *session)if (read_attr (fd, header, &f_attr) <0 ) goto out_errno; -if (header->needs_swap) +if (header->needs_swap) { + f_attr.ids.size =bswap_64 (f_attr.ids.size); + f_attr.ids.offset =bswap_64 (f_attr.ids.offset);perf_event__attr_swap (&f_attr.attr); + } tmp =lseek (fd,0 ,SEEK_CUR ); evsel =perf_evsel__new (&f_attr.attr);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 4/7 perf buildid-list: Fix segfault when show DSOs with hits
In reply to Arnaldo Carvalho de MeloFrom: He Kuang <[email protected]>
commit: f3b623b8490a ("perf tools: Reference count struct thread") appends every thread->node to dead_threads in machine__remove_thread() and list_del_init() this node in thread__put().
perf_event__exit_del_thread() releases thread wihout using machine__remove_thread(), and causes a NULL pointer crash when list_del_init(&thread->node) is called. Fix this by using machine_remove_thread() instead of using thread__put() directly.
This problem can be reproduced as following:
$ perf record ls $ perf buildid-list --with-hits [ 3874.195070] perf[1018]: segfault at 0 ip 00000000004b0b15 sp 00007ffc35b44780 error 6 in perf[400000+166000] Segmentation fault
After this patch:
$ perf record ls $ perf buildid-list --with-hits bc23e7c3281e542650ba4324421d6acf78f4c23e /proc/kcore 643324cb0e969f30c56d660f167f84a150845511 [vdso] 0000000000000000000000000000000000000000 /bin/busybox ...
--- tools/perf/util/build-id.c | 8 ++------ tools/perf/util/machine.c | 4 +--- tools/perf/util/machine.h | 1 + 3 files changed, 4 insertions(+), 9 deletions(-)
tools/perf/util/build-id.c +2 -6
@@ -59,12 +59,8 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,dump_printf ("(%d:%d):(%d:%d)\n" , event->fork.pid, event->fork.tid, event->fork.ppid, event->fork.ptid); -if (thread) { -rb_erase (&thread->rb_node, &machine->threads); -if (machine->last_match == thread) -thread__zput (machine->last_match); -thread__put (thread); - } +if (thread) +machine__remove_thread (machine, thread);return 0 ; }
tools/perf/util/machine.c +1 -3
@@ -14,8 +14,6 @@#include "unwind.h" #include "linux/hash.h" -static void machine__remove_thread (struct machine *machine,struct thread *th); -static void dsos__init (struct dsos *dsos) {INIT_LIST_HEAD (&dsos->head);
@@ -1256,7 +1254,7 @@ out_problem:return 0 ; } -static void machine__remove_thread (struct machine *machine,struct thread *th) +void machine__remove_thread (struct machine *machine,struct thread *th) {if (machine->last_match == th)thread__zput (machine->last_match);
tools/perf/util/machine.h +1 -0
@@ -120,6 +120,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid);void machine__exit (struct machine *machine);void machine__delete_threads (struct machine *machine);void machine__delete (struct machine *machine); +void machine__remove_thread (struct machine *machine,struct thread *th);struct branch_info *sample__resolve_bstack (struct perf_sample *sample,struct addr_location *al);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 5/7 perf probe: Support multiple probes on different binaries
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
Support multiple probes on different binaries with just one command.
In the result, this example sets up the probes on icmp_rcv in kernel, on main and set_target in perf, and on pcspkr_event in pcspker.ko driver.
-----
# perf probe -a icmp_rcv -x ./perf -a main -a set_target \
-m /lib/modules/4.0.0-rc5+/kernel/drivers/input/misc/pcspkr.ko \
-a pcspkr_event
Added new event:
probe:icmp_rcv (on icmp_rcv)You can now use it in all perf tools, such as:
perf record -e probe:icmp_rcv -aR sleep 1
Added new event:
probe_perf:main (on main in /home/mhiramat/ksrc/linux-3/tools/perf/perf)
You can now use it in all perf tools, such as:
perf record -e probe_perf:main -aR sleep 1
Added new event:
probe_perf:set_target (on set_target in /home/mhiramat/ksrc/linux-3/tools/perf/perf)
You can now use it in all perf tools, such as:
perf record -e probe_perf:set_target -aR sleep 1
Added new event:
probe:pcspkr_event (on pcspkr_event in pcspkr)
You can now use it in all perf tools, such as:
perf record -e probe:pcspkr_event -aR sleep 1
-----
--- tools/perf/builtin-probe.c | 9 +++++++-- tools/perf/util/probe-event.c | 5 +++-- tools/perf/util/probe-event.h | 6 +++--- 3 files changed, 13 insertions(+), 7 deletions(-)
tools/perf/builtin-probe.c +7 -2
@@ -78,6 +78,11 @@ static int parse_probe_event(const char *str) } pev->uprobes = params.uprobes; +if (params.target) { + pev->target =strdup (params.target); +if (!pev->target) +return -ENOMEM ; + }/* Parse a perf-probe command into event */ ret =parse_perf_probe_command (str, pev);
@@ -178,7 +183,7 @@ static int opt_set_target(const struct option *opt, const char *str,int ret = -ENOENT ;char *tmp; -if (str && !params.target) { +if (str) {if (!strcmp (opt->long_name,"exec" )) params.uprobes = true;#ifdef HAVE_DWARF_SUPPORT
@@ -200,6 +205,7 @@ static int opt_set_target(const struct option *opt, const char *str,if (!tmp)return -ENOMEM ; } +free (params.target); params.target = tmp; ret =0 ; }
@@ -487,7 +493,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)if (params.nevents) { ret =add_perf_probe_events (params.events, params.nevents, params.max_probe_points, - params.target, params.force_add);if (ret <0 ) {pr_err_with_code (" Error: Failed to add events." , ret);
tools/perf/util/probe-event.c +3 -2
@@ -1906,6 +1906,7 @@ void clear_perf_probe_event(struct perf_probe_event *pev)free (pev->event);free (pev->group); +free (pev->target);clear_perf_probe_point (&pev->point);for (i =0 ; i < pev->nargs; i++) {
@@ -2654,7 +2655,7 @@ struct __event_package { };int add_perf_probe_events (struct perf_probe_event *pevs,int npevs, -int max_tevs,const char *target,bool force_add) +int max_tevs,bool force_add) {int i, j, ret;struct __event_package *pkgs;
@@ -2678,7 +2679,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, ret =convert_to_probe_trace_events (pkgs[i].pev, &pkgs[i].tevs, max_tevs, - target); + pkgs[i].pev->target);if (ret <0 ) goto end; pkgs[i].ntevs = ret;
tools/perf/util/probe-event.h +3 -3
@@ -73,7 +73,8 @@ struct perf_probe_event {char *group;/* Group name */ struct perf_probe_point point;/* Probe point */ int nargs;/* Number of arguments */ -bool uprobes; +bool uprobes;/* Uprobe event flag */ +char *target;/* Target binary */ struct perf_probe_arg *args;/* Arguments */ };
@@ -124,8 +125,7 @@ extern int line_range__init(struct line_range *lr);extern const char *kernel_get_module_path (const char *module);extern int add_perf_probe_events (struct perf_probe_event *pevs,int npevs, -int max_probe_points,const char *module, -bool force_add); +int max_probe_points,bool force_add);extern int del_perf_probe_events (struct strlist *dellist);extern int show_perf_probe_events (void ); extern int show_line_range(struct line_range *lr, const char *module,
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 6/7 perf probe: Check the orphaned -x option
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
To avoid probing in unintended binary, the orphaned -x option must be checked and warned.
Without this patch, following command sets up the probe in the kernel.
-----
# perf probe -a strcpy -x ./perf
Added new event:
probe:strcpy (on strcpy)You can now use it in all perf tools, such as:
perf record -e probe:strcpy -aR sleep 1
-----
But in this case, it seems that the user may want to probe in the perf binary. With this patch, perf-probe correctly handles the orphaned -x.
-----
# perf probe -a strcpy -x ./perf
Error: -x/-m must follow the probe definitions.
...
-------- tools/perf/builtin-probe.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
tools/perf/builtin-probe.c +10 -0
@@ -56,6 +56,7 @@ static struct {bool mod_events;bool uprobes;bool quiet; +bool target_used;int nevents;struct perf_probe_event events[MAX_PROBES ];struct strlist *dellist;
@@ -82,6 +83,7 @@ static int parse_probe_event(const char *str) pev->target =strdup (params.target);if (!pev->target)return -ENOMEM ; + params.target_used = true; }/* Parse a perf-probe command into event */
@@ -107,6 +109,7 @@ static int set_target(const char *ptr) params.target =strdup (ptr);if (!params.target)return -ENOMEM ; + params.target_used = false; found =1 ; buf = ptr + (strlen (ptr) -3 );
@@ -207,6 +210,7 @@ static int opt_set_target(const struct option *opt, const char *str, }free (params.target); params.target = tmp; + params.target_used = false; ret =0 ; }
@@ -491,6 +495,12 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) }if (params.nevents) { +/* Ensure the last given target is used */ +if (params.target && !params.target_used) { +pr_warning (" Error: -x/-m must follow the probe definitions.\n" ); +usage_with_options (probe_usage, options); + } + ret =add_perf_probe_events (params.events, params.nevents, params.max_probe_points, params.force_add);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 7/7 perf evlist: Fix type for references to data_head/tail
In reply to Arnaldo Carvalho de MeloFrom: David Ahern <[email protected]>
The data_head and data_tail fields are defined as __u64 in linux/perf_event.h, but perf userspace uses int and unsigned int.
Convert all references to u64 for consistency.
--- tools/perf/builtin-record.c | 4 ++-- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evlist.h | 9 ++++----- 3 files changed, 9 insertions(+), 10 deletions(-)
tools/perf/builtin-record.c +2 -2
@@ -70,8 +70,8 @@ static int process_synthesized_event(struct perf_tool *tool,static int record__mmap_read (struct record *rec,int idx) {struct perf_mmap *md = &rec->evlist->mmap[idx]; -unsigned int head =perf_mmap__read_head (md); -unsigned int old = md->prev; +u64 head =perf_mmap__read_head (md); +u64 old = md->prev;unsigned char *data = md->base + page_size;unsigned long size;void *buf;
tools/perf/util/evlist.c +3 -3
@@ -634,8 +634,8 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,union perf_event *perf_evlist__mmap_read (struct perf_evlist *evlist,int idx) {struct perf_mmap *md = &evlist->mmap[idx]; -unsigned int head =perf_mmap__read_head (md); -unsigned int old = md->prev; +u64 head =perf_mmap__read_head (md); +u64 old = md->prev;unsigned char *data = md->base + page_size;union perf_event *event =NULL ;
@@ -716,7 +716,7 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)struct perf_mmap *md = &evlist->mmap[idx];if (!evlist->overwrite) { -unsigned int old = md->prev; +u64 old = md->prev;perf_mmap__write_tail (md, old); }
tools/perf/util/evlist.h +4 -5
@@ -27,7 +27,7 @@ struct perf_mmap {void *base;int mask;int refcnt; -unsigned int prev; +u64 prev; char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); };
@@ -189,16 +189,15 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);int perf_evlist__strerror_open (struct perf_evlist *evlist,int err,char *buf,size_t size);int perf_evlist__strerror_mmap (struct perf_evlist *evlist,int err,char *buf,size_t size); -static inline unsigned int perf_mmap__read_head (struct perf_mmap *mm) +static inline u64 perf_mmap__read_head (struct perf_mmap *mm) {struct perf_event_mmap_page *pc = mm->base; -int head =ACCESS_ONCE (pc->data_head); +u64 head =ACCESS_ONCE (pc->data_head);rmb ();return head; } -static inline void perf_mmap__write_tail (struct perf_mmap *md, -unsigned long tail) +static inline void perf_mmap__write_tail (struct perf_mmap *md,u64 tail) {struct perf_event_mmap_page *pc = md->base;
Signature · 1 line
1.9.3
Quoted 58 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit
51ab7155c08baf45cc2aa911961e5b78422e478f:Merge tag 'perf-core-for-mingo' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxinto perf/core (2015-04-08 17:03:47 +0200)are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingofor you to fetch changes up to
7b8283b56d9fb36106ff1c459dfd399a20bd374d:perf evlist: Fix type for references to data_head/tail (2015-04-10 11:29:20 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:New user visible features:
- Support multiple probes on different binaries on the same command line (Masami Hiramatsu)
User visible fixes:
- Fix synthesizing fork_event.ppid for non-main thread (David Ahern)
- Fix cross-endian analysis (David Ahern)
- Fix segfault in 'perf buildid-list' when show DSOs with hits (He Kuang)
Infrastructure:
- Fix type for references to data_head/tail (David Ahern)
- Fix error path to do
closedir()when synthesizing threads (Arnaldo Carvalho de Melo)Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Arnaldo Carvalho de Melo (1):
perf tools: Fix error path to doclosedir()when synthesizing threadsDavid Ahern (3):
perf tools: Fix synthesizing fork_event.ppid for non-main thread perf tools: Fix cross-endian analysis
perf evlist: Fix type for references to data_head/tailHe Kuang (1):
perf buildid-list: Fix segfault when show DSOs with hitsMasami Hiramatsu (2):
perf probe: Support multiple probes on different binaries perf probe: Check the orphaned -x option
Quoted 12 lines
tools/perf/builtin-probe.c | 19 +++++++++++++++++-- tools/perf/builtin-record.c | 4 ++-- tools/perf/util/build-id.c | 8 ++------ tools/perf/util/event.c | 31 +++++++++++++++++++++---------- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evlist.h | 9 ++++----- tools/perf/util/header.c | 5 ++++- tools/perf/util/machine.c | 4 +--- tools/perf/util/machine.h | 1 + tools/perf/util/probe-event.c | 5 +++-- tools/perf/util/probe-event.h | 6 +++--- 11 files changed, 61 insertions(+), 37 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo