2014-01-17 14:59:04

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [GIT PULL 00/19] perf/core improvements and fixes

From: Arnaldo Carvalho de Melo <[email protected]>

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit 3e7e09dbd1080de5dcf10092830e39bc2e2932ec:

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2014-01-16 09:34:01 +0100)

are available in the git repository at:


git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-core-for-mingo

for you to fetch changes up to 2a29190c040c0b11e39197c67abf6f87e0a61f9a:

perf tools: Remove unnecessary callchain cursor state restore on unmatch (2014-01-17 11:25:24 -0300)

----------------------------------------------------------------
Developer stuff:

. Improve callchain processing by removing unnecessary work. (Frederic Weisbecker)

. Fix comm override error handling (Frederic Weisbecker)

. Improve 'perf probe' exit path, release resources (Masami Hiramatsu)

. Improve libtraceevent plugins exit path, allowing the registering of
an unregister handler to be called at exit time (Namhyung Kim)

. Add an alias to the build test makefile (make -C tools/perf build-test)
(Namhyung Kim)

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

----------------------------------------------------------------
Frederic Weisbecker (3):
perf tools: Do proper comm override error handling
perf callchain: Spare double comparison of callchain first entry
perf tools: Remove unnecessary callchain cursor state restore on unmatch

Masami Hiramatsu (3):
perf probe: Release allocated probe_trace_event if failed
perf probe: Release all dynamically allocated parameters
perf symbols: Export elf_section_by_name and reuse

Namhyung Kim (13):
tools lib traceevent: Add pevent_unregister_event_handler()
tools lib traceevent: Add pevent_unregister_print_function()
tools lib traceevent: Unregister handler when function plugin is unloaded
tools lib traceevent: Unregister handler when hrtimer plugin is unloaded
tools lib traceevent: Unregister handler when kmem plugin is unloaded
tools lib traceevent: Unregister handler when kvm plugin is unloaded
tools lib traceevent: Unregister handler when sched_switch plugin is unloaded
tools lib traceevent: Unregister handler when mac80211 plugin is unloaded
tools lib traceevent: Unregister handler when cfg80211 plugin is unloaded
tools lib traceevent: Unregister handler when jbd2 plugin is is unloaded
tools lib traceevent: Unregister handler when scsi plugin is unloaded
tools lib traceevent: Unregister handler when xen plugin is unloaded
perf tools: Add 'build-test' make target

tools/lib/traceevent/event-parse.c | 136 ++++++++++++++++++++++++++---
tools/lib/traceevent/event-parse.h | 5 ++
tools/lib/traceevent/plugin_cfg80211.c | 6 ++
tools/lib/traceevent/plugin_function.c | 3 +
tools/lib/traceevent/plugin_hrtimer.c | 10 +++
tools/lib/traceevent/plugin_jbd2.c | 9 ++
tools/lib/traceevent/plugin_kmem.c | 22 +++++
tools/lib/traceevent/plugin_kvm.c | 29 ++++++
tools/lib/traceevent/plugin_mac80211.c | 7 ++
tools/lib/traceevent/plugin_sched_switch.c | 12 +++
tools/lib/traceevent/plugin_scsi.c | 6 ++
tools/lib/traceevent/plugin_xen.c | 6 ++
tools/perf/Makefile | 6 ++
tools/perf/builtin-probe.c | 48 ++++++++--
tools/perf/util/callchain.c | 23 +++--
tools/perf/util/comm.c | 19 ++--
tools/perf/util/comm.h | 2 +-
tools/perf/util/probe-event.c | 111 +++++++++++++----------
tools/perf/util/probe-event.h | 6 ++
tools/perf/util/symbol-elf.c | 5 +-
tools/perf/util/symbol.h | 5 ++
tools/perf/util/thread.c | 5 +-
tools/perf/util/unwind.c | 20 +----
23 files changed, 389 insertions(+), 112 deletions(-)


2014-01-17 14:57:44

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 03/19] tools lib traceevent: Unregister handler when function plugin is unloaded

From: Namhyung Kim <[email protected]>

The function handler should be unregistered when the plugin is unloaded
otherwise it'll try to access invalid memory.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/plugin_function.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c
index 39461485f9a7..80ba4ff1fe84 100644
--- a/tools/lib/traceevent/plugin_function.c
+++ b/tools/lib/traceevent/plugin_function.c
@@ -148,6 +148,9 @@ void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
{
int i, x;

+ pevent_unregister_event_handler(pevent, -1, "ftrace", "function",
+ function_handler, NULL);
+
for (i = 0; i <= cpus; i++) {
for (x = 0; x < fstack[i].size && fstack[i].stack[x]; x++)
free(fstack[i].stack[x]);
--
1.8.1.4

2014-01-17 14:57:47

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 06/19] tools lib traceevent: Unregister handler when kvm plugin is unloaded

From: Namhyung Kim <[email protected]>

The kvm handlers should be unregistered when the plugin is unloaded
otherwise they'll try to access invalid memory.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/plugin_kvm.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)

diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugin_kvm.c
index a0e282c6b967..9e0e8c61b43b 100644
--- a/tools/lib/traceevent/plugin_kvm.c
+++ b/tools/lib/traceevent/plugin_kvm.c
@@ -434,3 +434,32 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
PEVENT_FUNC_ARG_VOID);
return 0;
}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+ pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_exit",
+ kvm_exit_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_emulate_insn",
+ kvm_emulate_insn_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page",
+ kvm_mmu_get_page_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page",
+ kvm_mmu_print_role, NULL);
+
+ pevent_unregister_event_handler(pevent, -1,
+ "kvmmmu", "kvm_mmu_unsync_page",
+ kvm_mmu_print_role, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page",
+ kvm_mmu_print_role, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "kvmmmu",
+ "kvm_mmu_prepare_zap_page", kvm_mmu_print_role,
+ NULL);
+
+ pevent_unregister_print_function(pevent, process_is_writable_pte,
+ "is_writable_pte");
+}
--
1.8.1.4

2014-01-17 14:57:51

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 02/19] tools lib traceevent: Add pevent_unregister_print_function()

From: Namhyung Kim <[email protected]>

When a plugin unloaded it needs to unregister its print handler from
pevent.

So add an unregister function to do it.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/event-parse.c | 23 +++++++++++++++++++++++
tools/lib/traceevent/event-parse.h | 2 ++
2 files changed, 25 insertions(+)

diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index d1973cb8388b..1587ea392ad6 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -5560,6 +5560,29 @@ int pevent_register_print_function(struct pevent *pevent,
return ret;
}

+/**
+ * pevent_unregister_print_function - unregister a helper function
+ * @pevent: the handle to the pevent
+ * @func: the function to process the helper function
+ * @name: the name of the helper function
+ *
+ * This function removes existing print handler for function @name.
+ *
+ * Returns 0 if the handler was removed successully, -1 otherwise.
+ */
+int pevent_unregister_print_function(struct pevent *pevent,
+ pevent_func_handler func, char *name)
+{
+ struct pevent_function_handler *func_handle;
+
+ func_handle = find_func_handler(pevent, name);
+ if (func_handle && func_handle->func == func) {
+ remove_func_handler(pevent, name);
+ return 0;
+ }
+ return -1;
+}
+
static struct event_format *pevent_search_event(struct pevent *pevent, int id,
const char *sys_name,
const char *event_name)
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index c48acfbc6230..791c539374c7 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -631,6 +631,8 @@ int pevent_register_print_function(struct pevent *pevent,
pevent_func_handler func,
enum pevent_func_arg_type ret_type,
char *name, ...);
+int pevent_unregister_print_function(struct pevent *pevent,
+ pevent_func_handler func, char *name);

struct format_field *pevent_find_common_field(struct event_format *event, const char *name);
struct format_field *pevent_find_field(struct event_format *event, const char *name);
--
1.8.1.4

2014-01-17 14:59:21

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 19/19] perf tools: Remove unnecessary callchain cursor state restore on unmatch

From: Frederic Weisbecker <[email protected]>

If a new callchain branch doesn't match a single entry of the node that
it is given against comparison in append_chain(), then the cursor is
expected to be at the same position as it was before the comparison
loop.

As such, there is no need to restore the cursor position on exit in case
of non matching branches.

Signed-off-by: Frederic Weisbecker <[email protected]>
Reviewed-by: Namhyung Kim <[email protected]>
Cc: Adrian Hunter <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/callchain.c | 3 ---
1 file changed, 3 deletions(-)

diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 662867d5c374..8d9db454f1a9 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -388,7 +388,6 @@ append_chain(struct callchain_node *root,
struct callchain_cursor *cursor,
u64 period)
{
- struct callchain_cursor_node *curr_snap = cursor->curr;
struct callchain_list *cnode;
u64 start = cursor->pos;
bool found = false;
@@ -420,8 +419,6 @@ append_chain(struct callchain_node *root,
/* matches not, relay no the parent */
if (!found) {
WARN_ONCE(!cmp, "Chain comparison error\n");
- cursor->curr = curr_snap;
- cursor->pos = start;
return cmp;
}

--
1.8.1.4

2014-01-17 14:59:43

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 18/19] perf callchain: Spare double comparison of callchain first entry

From: Frederic Weisbecker <[email protected]>

When a new callchain child branch matches an existing one in the rbtree,
the comparison of its first entry is performed twice:

1) From append_chain_children() on branch lookup

2) If 1) reports a match, append_chain() then compares all entries of
the new branch against the matching node in the rbtree, and this
comparison includes the first entry of the new branch again.

Lets shortcut this by performing the whole comparison only from
append_chain() which then returns the result of the comparison between
the first entry of the new branch and the iterating node in the rbtree.
If the first entry matches, the lookup on the current level of siblings
stops and propagates to the children of the matching nodes.

This results in less comparisons performed by the CPU.

Signed-off-by: Frederic Weisbecker <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Cc: Adrian Hunter <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/callchain.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 9eb4f57f8663..662867d5c374 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -15,6 +15,8 @@
#include <errno.h>
#include <math.h>

+#include "asm/bug.h"
+
#include "hist.h"
#include "util.h"
#include "sort.h"
@@ -358,19 +360,14 @@ append_chain_children(struct callchain_node *root,
/* lookup in childrens */
while (*p) {
s64 ret;
- struct callchain_list *cnode;

parent = *p;
rnode = rb_entry(parent, struct callchain_node, rb_node_in);
- cnode = list_first_entry(&rnode->val, struct callchain_list,
- list);

- /* just check first entry */
- ret = match_chain(node, cnode);
- if (ret == 0) {
- append_chain(rnode, cursor, period);
+ /* If at least first entry matches, rely to children */
+ ret = append_chain(rnode, cursor, period);
+ if (ret == 0)
goto inc_children_hit;
- }

if (ret < 0)
p = &parent->rb_left;
@@ -396,6 +393,7 @@ append_chain(struct callchain_node *root,
u64 start = cursor->pos;
bool found = false;
u64 matches;
+ int cmp = 0;

/*
* Lookup in the current node
@@ -410,7 +408,8 @@ append_chain(struct callchain_node *root,
if (!node)
break;

- if (match_chain(node, cnode) != 0)
+ cmp = match_chain(node, cnode);
+ if (cmp)
break;

found = true;
@@ -420,9 +419,10 @@ append_chain(struct callchain_node *root,

/* matches not, relay no the parent */
if (!found) {
+ WARN_ONCE(!cmp, "Chain comparison error\n");
cursor->curr = curr_snap;
cursor->pos = start;
- return -1;
+ return cmp;
}

matches = cursor->pos - start;
--
1.8.1.4

2014-01-17 14:59:40

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 15/19] perf probe: Release all dynamically allocated parameters

From: Masami Hiramatsu <[email protected]>

To fix a memory leak, release all dynamically allocated
options/parameters in params data structure. This also
introduces/exports some init/clear routines.

Reported-by: David Ahern <[email protected]>
Signed-off-by: Masami Hiramatsu <[email protected]>
Cc: "David A. Long" <[email protected]>
Cc: "Steven Rostedt (Red Hat)" <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Srikar Dronamraju <[email protected]>
Cc: [email protected]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-probe.c | 48 ++++++++++++++++++++++++++++++++++++++-----
tools/perf/util/probe-event.c | 22 ++++++++++++++++++++
tools/perf/util/probe-event.h | 6 ++++++
3 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 43ff33d0007b..78948882e3de 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -59,7 +59,7 @@ static struct {
struct perf_probe_event events[MAX_PROBES];
struct strlist *dellist;
struct line_range line_range;
- const char *target;
+ char *target;
int max_probe_points;
struct strfilter *filter;
} params;
@@ -98,7 +98,10 @@ static int set_target(const char *ptr)
* short module name.
*/
if (!params.target && ptr && *ptr == '/') {
- params.target = ptr;
+ params.target = strdup(ptr);
+ if (!params.target)
+ return -ENOMEM;
+
found = 1;
buf = ptr + (strlen(ptr) - 3);

@@ -116,6 +119,9 @@ static int parse_probe_event_argv(int argc, const char **argv)
char *buf;

found_target = set_target(argv[0]);
+ if (found_target < 0)
+ return found_target;
+
if (found_target && argc == 1)
return 0;

@@ -217,7 +223,6 @@ static int opt_show_lines(const struct option *opt __maybe_unused,

params.show_lines = true;
ret = parse_line_range_desc(str, &params.line_range);
- INIT_LIST_HEAD(&params.line_range.line_list);

return ret;
}
@@ -263,7 +268,28 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
return 0;
}

-int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
+static void init_params(void)
+{
+ line_range__init(&params.line_range);
+}
+
+static void cleanup_params(void)
+{
+ int i;
+
+ for (i = 0; i < params.nevents; i++)
+ clear_perf_probe_event(params.events + i);
+ if (params.dellist)
+ strlist__delete(params.dellist);
+ line_range__clear(&params.line_range);
+ free(params.target);
+ if (params.filter)
+ strfilter__delete(params.filter);
+ memset(&params, 0, sizeof(params));
+}
+
+static int
+__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
{
const char * const probe_usage[] = {
"perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
@@ -417,6 +443,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
ret = show_available_funcs(params.target, params.filter,
params.uprobes);
strfilter__delete(params.filter);
+ params.filter = NULL;
if (ret < 0)
pr_err(" Error: Failed to show functions."
" (%d)\n", ret);
@@ -456,6 +483,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
params.filter,
params.show_ext_vars);
strfilter__delete(params.filter);
+ params.filter = NULL;
if (ret < 0)
pr_err(" Error: Failed to show vars. (%d)\n", ret);
return ret;
@@ -464,7 +492,6 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)

if (params.dellist) {
ret = del_perf_probe_events(params.dellist);
- strlist__delete(params.dellist);
if (ret < 0) {
pr_err(" Error: Failed to delete events. (%d)\n", ret);
return ret;
@@ -483,3 +510,14 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
}
return 0;
}
+
+int cmd_probe(int argc, const char **argv, const char *prefix)
+{
+ int ret;
+
+ init_params();
+ ret = __cmd_probe(argc, argv, prefix);
+ cleanup_params();
+
+ return ret;
+}
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 579b655c0f93..c68711c50f47 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -794,6 +794,28 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
}
#endif

+void line_range__clear(struct line_range *lr)
+{
+ struct line_node *ln;
+
+ free(lr->function);
+ free(lr->file);
+ free(lr->path);
+ free(lr->comp_dir);
+ while (!list_empty(&lr->line_list)) {
+ ln = list_first_entry(&lr->line_list, struct line_node, list);
+ list_del(&ln->list);
+ free(ln);
+ }
+ memset(lr, 0, sizeof(*lr));
+}
+
+void line_range__init(struct line_range *lr)
+{
+ memset(lr, 0, sizeof(*lr));
+ INIT_LIST_HEAD(&lr->line_list);
+}
+
static int parse_line_num(char **ptr, int *val, const char *what)
{
const char *start = *ptr;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index d481c46e0796..fcaf7273e85a 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -120,6 +120,12 @@ extern void clear_perf_probe_event(struct perf_probe_event *pev);
/* Command string to line-range */
extern int parse_line_range_desc(const char *cmd, struct line_range *lr);

+/* Release line range members */
+extern void line_range__clear(struct line_range *lr);
+
+/* Initialize line range */
+extern void line_range__init(struct line_range *lr);
+
/* Internal use: Return kernel/module path */
extern const char *kernel_get_module_path(const char *module);

--
1.8.1.4

2014-01-17 15:00:36

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 16/19] perf symbols: Export elf_section_by_name and reuse

From: Masami Hiramatsu <[email protected]>

Remove duplicated elf_section_by_name() functions from unwind.c and
probe-event.c and use one exported elf_section_by_name() instance
defined in symbol-elf.c.

Note that this also moves get_text_start_address() to merge
HAVE_DWARF_SUPPORT defined area.

Reported-by: David Ahern <[email protected]>
Signed-off-by: Masami Hiramatsu <[email protected]>
Cc: "David A. Long" <[email protected]>
Cc: "Steven Rostedt (Red Hat)" <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Srikar Dronamraju <[email protected]>
Cc: [email protected]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/probe-event.c | 76 ++++++++++++++++---------------------------
tools/perf/util/symbol-elf.c | 5 ++-
tools/perf/util/symbol.h | 5 +++
tools/perf/util/unwind.c | 20 ++----------
4 files changed, 37 insertions(+), 69 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index c68711c50f47..a8a9b6cd93a8 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -173,54 +173,6 @@ const char *kernel_get_module_path(const char *module)
return (dso) ? dso->long_name : NULL;
}

-#ifdef HAVE_DWARF_SUPPORT
-/* Copied from unwind.c */
-static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
- GElf_Shdr *shp, const char *name)
-{
- Elf_Scn *sec = NULL;
-
- while ((sec = elf_nextscn(elf, sec)) != NULL) {
- char *str;
-
- gelf_getshdr(sec, shp);
- str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
- if (!strcmp(name, str))
- break;
- }
-
- return sec;
-}
-
-static int get_text_start_address(const char *exec, unsigned long *address)
-{
- Elf *elf;
- GElf_Ehdr ehdr;
- GElf_Shdr shdr;
- int fd, ret = -ENOENT;
-
- fd = open(exec, O_RDONLY);
- if (fd < 0)
- return -errno;
-
- elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
- if (elf == NULL)
- return -EINVAL;
-
- if (gelf_getehdr(elf, &ehdr) == NULL)
- goto out;
-
- if (!elf_section_by_name(elf, &ehdr, &shdr, ".text"))
- goto out;
-
- *address = shdr.sh_addr - shdr.sh_offset;
- ret = 0;
-out:
- elf_end(elf);
- return ret;
-}
-#endif
-
static int init_user_exec(void)
{
int ret = 0;
@@ -341,6 +293,34 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
return 0;
}

+static int get_text_start_address(const char *exec, unsigned long *address)
+{
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ GElf_Shdr shdr;
+ int fd, ret = -ENOENT;
+
+ fd = open(exec, O_RDONLY);
+ if (fd < 0)
+ return -errno;
+
+ elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+ if (elf == NULL)
+ return -EINVAL;
+
+ if (gelf_getehdr(elf, &ehdr) == NULL)
+ goto out;
+
+ if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL))
+ goto out;
+
+ *address = shdr.sh_addr - shdr.sh_offset;
+ ret = 0;
+out:
+ elf_end(elf);
+ return ret;
+}
+
static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
int ntevs, const char *exec)
{
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 4b0a127a4d3b..759456728703 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -136,9 +136,8 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
return -1;
}

-static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
- GElf_Shdr *shp, const char *name,
- size_t *idx)
+Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
+ GElf_Shdr *shp, const char *name, size_t *idx)
{
Elf_Scn *sec = NULL;
size_t cnt = 1;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index cbd680361806..fffe2888a1c7 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -52,6 +52,11 @@ static inline char *bfd_demangle(void __maybe_unused *v,
# define PERF_ELF_C_READ_MMAP ELF_C_READ
#endif

+#ifdef HAVE_LIBELF_SUPPORT
+extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
+ GElf_Shdr *shp, const char *name, size_t *idx);
+#endif
+
#ifndef DMGL_PARAMS
#define DMGL_PARAMS (1 << 0) /* Include function args */
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c
index 416f22bf3693..742f23bf35ff 100644
--- a/tools/perf/util/unwind.c
+++ b/tools/perf/util/unwind.c
@@ -28,6 +28,7 @@
#include "session.h"
#include "perf_regs.h"
#include "unwind.h"
+#include "symbol.h"
#include "util.h"

extern int
@@ -158,23 +159,6 @@ static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
__v; \
})

-static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
- GElf_Shdr *shp, const char *name)
-{
- Elf_Scn *sec = NULL;
-
- while ((sec = elf_nextscn(elf, sec)) != NULL) {
- char *str;
-
- gelf_getshdr(sec, shp);
- str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
- if (!strcmp(name, str))
- break;
- }
-
- return sec;
-}
-
static u64 elf_section_offset(int fd, const char *name)
{
Elf *elf;
@@ -190,7 +174,7 @@ static u64 elf_section_offset(int fd, const char *name)
if (gelf_getehdr(elf, &ehdr) == NULL)
break;

- if (!elf_section_by_name(elf, &ehdr, &shdr, name))
+ if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
break;

offset = shdr.sh_offset;
--
1.8.1.4

2014-01-17 15:00:34

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 14/19] perf probe: Release allocated probe_trace_event if failed

From: Masami Hiramatsu <[email protected]>

To fix a memory leak, release all allocated probe_trace_event on the
error path of try_to_find_probe_trace_events.

Reported-by: David Ahern <[email protected]>
Signed-off-by: Masami Hiramatsu <[email protected]>
Cc: "David A. Long" <[email protected]>
Cc: "Steven Rostedt (Red Hat)" <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Srikar Dronamraju <[email protected]>
Cc: [email protected]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/probe-event.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index a4ee6b4a840f..579b655c0f93 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -72,6 +72,7 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
static int convert_name_to_addr(struct perf_probe_event *pev,
const char *exec);
+static void clear_probe_trace_event(struct probe_trace_event *tev);
static struct machine machine;

/* Initialize symbol maps and path of vmlinux/modules */
@@ -407,6 +408,14 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
return ret;
}

+static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
+{
+ int i;
+
+ for (i = 0; i < ntevs; i++)
+ clear_probe_trace_event(tevs + i);
+}
+
/* Try to find perf_probe_event with debuginfo */
static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs,
@@ -442,6 +451,10 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
ret = add_module_to_probe_trace_events(*tevs,
ntevs, target);
}
+ if (ret < 0) {
+ clear_probe_trace_events(*tevs, ntevs);
+ zfree(tevs);
+ }
return ret < 0 ? ret : ntevs;
}

--
1.8.1.4

2014-01-17 15:01:09

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 17/19] perf tools: Do proper comm override error handling

From: Frederic Weisbecker <[email protected]>

The comm overriding API ignores memory allocation failures by silently
keeping the previous and out of date comm.

As a result, the user may get buggy events without ever being notified
about the problem and its source.

Lets start to fix this by propagating the error from the API. Not all
callers may be doing proper error handling on comm set yet but this is
the first step toward it.

Signed-off-by: Frederic Weisbecker <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Cc: Adrian Hunter <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/comm.c | 19 ++++++++++---------
tools/perf/util/comm.h | 2 +-
tools/perf/util/thread.c | 5 ++++-
3 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index 67d1e404c0cb..f9e777629e21 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -94,19 +94,20 @@ struct comm *comm__new(const char *str, u64 timestamp)
return comm;
}

-void comm__override(struct comm *comm, const char *str, u64 timestamp)
+int comm__override(struct comm *comm, const char *str, u64 timestamp)
{
- struct comm_str *old = comm->comm_str;
+ struct comm_str *new, *old = comm->comm_str;

- comm->comm_str = comm_str__findnew(str, &comm_str_root);
- if (!comm->comm_str) {
- comm->comm_str = old;
- return;
- }
+ new = comm_str__findnew(str, &comm_str_root);
+ if (!new)
+ return -ENOMEM;

- comm->start = timestamp;
- comm_str__get(comm->comm_str);
+ comm_str__get(new);
comm_str__put(old);
+ comm->comm_str = new;
+ comm->start = timestamp;
+
+ return 0;
}

void comm__free(struct comm *comm)
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index 7a86e5656710..fac5bd51befc 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -16,6 +16,6 @@ struct comm {
void comm__free(struct comm *comm);
struct comm *comm__new(const char *str, u64 timestamp);
const char *comm__str(const struct comm *comm);
-void comm__override(struct comm *comm, const char *str, u64 timestamp);
+int comm__override(struct comm *comm, const char *str, u64 timestamp);

#endif /* __PERF_COMM_H */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index e3948612543e..0358882c8910 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -66,10 +66,13 @@ struct comm *thread__comm(const struct thread *thread)
int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
{
struct comm *new, *curr = thread__comm(thread);
+ int err;

/* Override latest entry if it had no specific time coverage */
if (!curr->start) {
- comm__override(curr, str, timestamp);
+ err = comm__override(curr, str, timestamp);
+ if (err)
+ return err;
} else {
new = comm__new(str, timestamp);
if (!new)
--
1.8.1.4

2014-01-17 14:57:39

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 09/19] tools lib traceevent: Unregister handler when cfg80211 plugin is unloaded

From: Namhyung Kim <[email protected]>

The function handler should be unregistered when the plugin is unloaded
otherwise it'll try to access invalid memory.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/plugin_cfg80211.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugin_cfg80211.c
index 57e98221db20..c066b25905f8 100644
--- a/tools/lib/traceevent/plugin_cfg80211.c
+++ b/tools/lib/traceevent/plugin_cfg80211.c
@@ -22,3 +22,9 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
PEVENT_FUNC_ARG_VOID);
return 0;
}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+ pevent_unregister_print_function(pevent, process___le16_to_cpup,
+ "__le16_to_cpup");
+}
--
1.8.1.4

2014-01-17 15:01:31

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 01/19] tools lib traceevent: Add pevent_unregister_event_handler()

From: Namhyung Kim <[email protected]>

When a plugin is unloaded it needs to unregister its handler from pevent.

So add an unregister function to do it.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/event-parse.c | 113 ++++++++++++++++++++++++++++++++-----
tools/lib/traceevent/event-parse.h | 3 +
2 files changed, 102 insertions(+), 14 deletions(-)

diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 2ce565a73dd5..d1973cb8388b 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -5560,6 +5560,29 @@ int pevent_register_print_function(struct pevent *pevent,
return ret;
}

+static struct event_format *pevent_search_event(struct pevent *pevent, int id,
+ const char *sys_name,
+ const char *event_name)
+{
+ struct event_format *event;
+
+ if (id >= 0) {
+ /* search by id */
+ event = pevent_find_event(pevent, id);
+ if (!event)
+ return NULL;
+ if (event_name && (strcmp(event_name, event->name) != 0))
+ return NULL;
+ if (sys_name && (strcmp(sys_name, event->system) != 0))
+ return NULL;
+ } else {
+ event = pevent_find_event_by_name(pevent, sys_name, event_name);
+ if (!event)
+ return NULL;
+ }
+ return event;
+}
+
/**
* pevent_register_event_handler - register a way to parse an event
* @pevent: the handle to the pevent
@@ -5584,20 +5607,9 @@ int pevent_register_event_handler(struct pevent *pevent, int id,
struct event_format *event;
struct event_handler *handle;

- if (id >= 0) {
- /* search by id */
- event = pevent_find_event(pevent, id);
- if (!event)
- goto not_found;
- if (event_name && (strcmp(event_name, event->name) != 0))
- goto not_found;
- if (sys_name && (strcmp(sys_name, event->system) != 0))
- goto not_found;
- } else {
- event = pevent_find_event_by_name(pevent, sys_name, event_name);
- if (!event)
- goto not_found;
- }
+ event = pevent_search_event(pevent, id, sys_name, event_name);
+ if (event == NULL)
+ goto not_found;

pr_stat("overriding event (%d) %s:%s with new print handler",
event->id, event->system, event->name);
@@ -5637,6 +5649,79 @@ int pevent_register_event_handler(struct pevent *pevent, int id,
return -1;
}

+static int handle_matches(struct event_handler *handler, int id,
+ const char *sys_name, const char *event_name,
+ pevent_event_handler_func func, void *context)
+{
+ if (id >= 0 && id != handler->id)
+ return 0;
+
+ if (event_name && (strcmp(event_name, handler->event_name) != 0))
+ return 0;
+
+ if (sys_name && (strcmp(sys_name, handler->sys_name) != 0))
+ return 0;
+
+ if (func != handler->func || context != handler->context)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * pevent_unregister_event_handler - unregister an existing event handler
+ * @pevent: the handle to the pevent
+ * @id: the id of the event to unregister
+ * @sys_name: the system name the handler belongs to
+ * @event_name: the name of the event handler
+ * @func: the function to call to parse the event information
+ * @context: the data to be passed to @func
+ *
+ * This function removes existing event handler (parser).
+ *
+ * If @id is >= 0, then it is used to find the event.
+ * else @sys_name and @event_name are used.
+ *
+ * Returns 0 if handler was removed successfully, -1 if event was not found.
+ */
+int pevent_unregister_event_handler(struct pevent *pevent, int id,
+ const char *sys_name, const char *event_name,
+ pevent_event_handler_func func, void *context)
+{
+ struct event_format *event;
+ struct event_handler *handle;
+ struct event_handler **next;
+
+ event = pevent_search_event(pevent, id, sys_name, event_name);
+ if (event == NULL)
+ goto not_found;
+
+ if (event->handler == func && event->context == context) {
+ pr_stat("removing override handler for event (%d) %s:%s. Going back to default handler.",
+ event->id, event->system, event->name);
+
+ event->handler = NULL;
+ event->context = NULL;
+ return 0;
+ }
+
+not_found:
+ for (next = &pevent->handlers; *next; next = &(*next)->next) {
+ handle = *next;
+ if (handle_matches(handle, id, sys_name, event_name,
+ func, context))
+ break;
+ }
+
+ if (!(*next))
+ return -1;
+
+ *next = handle->next;
+ free_handler(handle);
+
+ return 0;
+}
+
/**
* pevent_alloc - create a pevent handle
*/
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index a3beca56cb35..c48acfbc6230 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -624,6 +624,9 @@ int pevent_print_func_field(struct trace_seq *s, const char *fmt,
int pevent_register_event_handler(struct pevent *pevent, int id,
const char *sys_name, const char *event_name,
pevent_event_handler_func func, void *context);
+int pevent_unregister_event_handler(struct pevent *pevent, int id,
+ const char *sys_name, const char *event_name,
+ pevent_event_handler_func func, void *context);
int pevent_register_print_function(struct pevent *pevent,
pevent_func_handler func,
enum pevent_func_arg_type ret_type,
--
1.8.1.4

2014-01-17 15:01:29

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 04/19] tools lib traceevent: Unregister handler when hrtimer plugin is unloaded

From: Namhyung Kim <[email protected]>

The timer handlers should be unregistered when the plugin is unloaded
otherwise they'll try to access invalid memory.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/plugin_hrtimer.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugin_hrtimer.c
index 0b0ebf30aa44..12bf14cc1152 100644
--- a/tools/lib/traceevent/plugin_hrtimer.c
+++ b/tools/lib/traceevent/plugin_hrtimer.c
@@ -76,3 +76,13 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
timer_start_handler, NULL);
return 0;
}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+ pevent_unregister_event_handler(pevent, -1,
+ "timer", "hrtimer_expire_entry",
+ timer_expire_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "timer", "hrtimer_start",
+ timer_start_handler, NULL);
+}
--
1.8.1.4

2014-01-17 15:02:00

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 13/19] perf tools: Add 'build-test' make target

From: Namhyung Kim <[email protected]>

Currently various build test can be performed using a Makefile named
tests/make, so one needs to remember and specify it with -f option on
command line.

Add the 'build-test' target in the main Makefile as a shortcut.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index eefb9fb0c02f..cb2e5868c8e8 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -75,6 +75,12 @@ clean:
$(make)

#
+# The build-test target is not really parallel, don't print the jobs info:
+#
+build-test:
+ @$(MAKE) -f tests/make --no-print-directory
+
+#
# All other targets get passed through:
#
%:
--
1.8.1.4

2014-01-17 15:02:26

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 07/19] tools lib traceevent: Unregister handler when sched_switch plugin is unloaded

From: Namhyung Kim <[email protected]>

The event handlers should be unregistered when the plugin is unloaded
otherwise they'll try to access invalid memory.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/plugin_sched_switch.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c
index fea3724aa24f..f1ce60065258 100644
--- a/tools/lib/traceevent/plugin_sched_switch.c
+++ b/tools/lib/traceevent/plugin_sched_switch.c
@@ -146,3 +146,15 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
sched_wakeup_handler, NULL);
return 0;
}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+ pevent_unregister_event_handler(pevent, -1, "sched", "sched_switch",
+ sched_switch_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup",
+ sched_wakeup_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup_new",
+ sched_wakeup_handler, NULL);
+}
--
1.8.1.4

2014-01-17 15:02:24

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 11/19] tools lib traceevent: Unregister handler when scsi plugin is unloaded

From: Namhyung Kim <[email protected]>

The function handler should be unregistered when the plugin is unloaded
otherwise it'll try to access invalid memory.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/plugin_scsi.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c
index 7ef16cc96562..eda326fc8620 100644
--- a/tools/lib/traceevent/plugin_scsi.c
+++ b/tools/lib/traceevent/plugin_scsi.c
@@ -421,3 +421,9 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
PEVENT_FUNC_ARG_VOID);
return 0;
}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+ pevent_unregister_print_function(pevent, process_scsi_trace_parse_cdb,
+ "scsi_trace_parse_cdb");
+}
--
1.8.1.4

2014-01-17 15:02:22

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 08/19] tools lib traceevent: Unregister handler when mac80211 plugin is unloaded

From: Namhyung Kim <[email protected]>

The event handler should be unregistered when the plugin is unloaded
otherwise it'll try to access invalid memory.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/plugin_mac80211.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugin_mac80211.c
index 558a3b91c046..7e15a0f1c2fd 100644
--- a/tools/lib/traceevent/plugin_mac80211.c
+++ b/tools/lib/traceevent/plugin_mac80211.c
@@ -93,3 +93,10 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
drv_bss_info_changed, NULL);
return 0;
}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+ pevent_unregister_event_handler(pevent, -1, "mac80211",
+ "drv_bss_info_changed",
+ drv_bss_info_changed, NULL);
+}
--
1.8.1.4

2014-01-17 15:02:18

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 12/19] tools lib traceevent: Unregister handler when xen plugin is unloaded

From: Namhyung Kim <[email protected]>

The function handler should be unregistered when the plugin is unloaded
otherwise it'll try to access invalid memory.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/plugin_xen.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/tools/lib/traceevent/plugin_xen.c b/tools/lib/traceevent/plugin_xen.c
index e7794298f3a9..3a413eaada68 100644
--- a/tools/lib/traceevent/plugin_xen.c
+++ b/tools/lib/traceevent/plugin_xen.c
@@ -128,3 +128,9 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
PEVENT_FUNC_ARG_VOID);
return 0;
}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+ pevent_unregister_print_function(pevent, process_xen_hypercall_name,
+ "xen_hypercall_name");
+}
--
1.8.1.4

2014-01-17 15:03:37

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 05/19] tools lib traceevent: Unregister handler when kmem plugin is unloaded

From: Namhyung Kim <[email protected]>

The kmem handlers should be unregistered when the plugin is unloaded
otherwise they'll try to access invalid memory.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/plugin_kmem.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugin_kmem.c
index 7115c8037ea8..70650ff48d78 100644
--- a/tools/lib/traceevent/plugin_kmem.c
+++ b/tools/lib/traceevent/plugin_kmem.c
@@ -70,3 +70,25 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
call_site_handler, NULL);
return 0;
}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+ pevent_unregister_event_handler(pevent, -1, "kmem", "kfree",
+ call_site_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "kmem", "kmalloc",
+ call_site_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "kmem", "kmalloc_node",
+ call_site_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_alloc",
+ call_site_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "kmem",
+ "kmem_cache_alloc_node",
+ call_site_handler, NULL);
+
+ pevent_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_free",
+ call_site_handler, NULL);
+}
--
1.8.1.4

2014-01-17 15:03:35

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 10/19] tools lib traceevent: Unregister handler when jbd2 plugin is is unloaded

From: Namhyung Kim <[email protected]>

The function handlers should be unregistered when the plugin unloaded
otherwise they'll try to access invalid memory.

Signed-off-by: Namhyung Kim <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/lib/traceevent/plugin_jbd2.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/tools/lib/traceevent/plugin_jbd2.c b/tools/lib/traceevent/plugin_jbd2.c
index 2f93f81f0bac..0db714c721be 100644
--- a/tools/lib/traceevent/plugin_jbd2.c
+++ b/tools/lib/traceevent/plugin_jbd2.c
@@ -66,3 +66,12 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
PEVENT_FUNC_ARG_VOID);
return 0;
}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+ pevent_unregister_print_function(pevent, process_jbd2_dev_to_name,
+ "jbd2_dev_to_name");
+
+ pevent_unregister_print_function(pevent, process_jiffies_to_msecs,
+ "jiffies_to_msecs");
+}
--
1.8.1.4

2014-01-19 12:12:03

by Ingo Molnar

[permalink] [raw]
Subject: Re: [GIT PULL 00/19] perf/core improvements and fixes


* Arnaldo Carvalho de Melo <[email protected]> wrote:

> From: Arnaldo Carvalho de Melo <[email protected]>
>
> Hi Ingo,
>
> Please consider pulling,
>
> - Arnaldo
>
> The following changes since commit 3e7e09dbd1080de5dcf10092830e39bc2e2932ec:
>
> Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2014-01-16 09:34:01 +0100)
>
> are available in the git repository at:
>
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-core-for-mingo
>
> for you to fetch changes up to 2a29190c040c0b11e39197c67abf6f87e0a61f9a:
>
> perf tools: Remove unnecessary callchain cursor state restore on unmatch (2014-01-17 11:25:24 -0300)
>
> ----------------------------------------------------------------
> Developer stuff:
>
> . Improve callchain processing by removing unnecessary work. (Frederic Weisbecker)
>
> . Fix comm override error handling (Frederic Weisbecker)
>
> . Improve 'perf probe' exit path, release resources (Masami Hiramatsu)
>
> . Improve libtraceevent plugins exit path, allowing the registering of
> an unregister handler to be called at exit time (Namhyung Kim)
>
> . Add an alias to the build test makefile (make -C tools/perf build-test)
> (Namhyung Kim)
>
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
>
> ----------------------------------------------------------------
> Frederic Weisbecker (3):
> perf tools: Do proper comm override error handling
> perf callchain: Spare double comparison of callchain first entry
> perf tools: Remove unnecessary callchain cursor state restore on unmatch
>
> Masami Hiramatsu (3):
> perf probe: Release allocated probe_trace_event if failed
> perf probe: Release all dynamically allocated parameters
> perf symbols: Export elf_section_by_name and reuse
>
> Namhyung Kim (13):
> tools lib traceevent: Add pevent_unregister_event_handler()
> tools lib traceevent: Add pevent_unregister_print_function()
> tools lib traceevent: Unregister handler when function plugin is unloaded
> tools lib traceevent: Unregister handler when hrtimer plugin is unloaded
> tools lib traceevent: Unregister handler when kmem plugin is unloaded
> tools lib traceevent: Unregister handler when kvm plugin is unloaded
> tools lib traceevent: Unregister handler when sched_switch plugin is unloaded
> tools lib traceevent: Unregister handler when mac80211 plugin is unloaded
> tools lib traceevent: Unregister handler when cfg80211 plugin is unloaded
> tools lib traceevent: Unregister handler when jbd2 plugin is is unloaded
> tools lib traceevent: Unregister handler when scsi plugin is unloaded
> tools lib traceevent: Unregister handler when xen plugin is unloaded
> perf tools: Add 'build-test' make target
>
> tools/lib/traceevent/event-parse.c | 136 ++++++++++++++++++++++++++---
> tools/lib/traceevent/event-parse.h | 5 ++
> tools/lib/traceevent/plugin_cfg80211.c | 6 ++
> tools/lib/traceevent/plugin_function.c | 3 +
> tools/lib/traceevent/plugin_hrtimer.c | 10 +++
> tools/lib/traceevent/plugin_jbd2.c | 9 ++
> tools/lib/traceevent/plugin_kmem.c | 22 +++++
> tools/lib/traceevent/plugin_kvm.c | 29 ++++++
> tools/lib/traceevent/plugin_mac80211.c | 7 ++
> tools/lib/traceevent/plugin_sched_switch.c | 12 +++
> tools/lib/traceevent/plugin_scsi.c | 6 ++
> tools/lib/traceevent/plugin_xen.c | 6 ++
> tools/perf/Makefile | 6 ++
> tools/perf/builtin-probe.c | 48 ++++++++--
> tools/perf/util/callchain.c | 23 +++--
> tools/perf/util/comm.c | 19 ++--
> tools/perf/util/comm.h | 2 +-
> tools/perf/util/probe-event.c | 111 +++++++++++++----------
> tools/perf/util/probe-event.h | 6 ++
> tools/perf/util/symbol-elf.c | 5 +-
> tools/perf/util/symbol.h | 5 ++
> tools/perf/util/thread.c | 5 +-
> tools/perf/util/unwind.c | 20 +----
> 23 files changed, 389 insertions(+), 112 deletions(-)

Pulled, thanks a lot Arnaldo!

Ingo