mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Wang Nan <wangnan0@huawei.com>
To: <acme@redhat.com>, <ast@plumgrid.com>,
	<masami.hiramatsu.pt@hitachi.com>, <namhyung@kernel.org>
Cc: <a.p.zijlstra@chello.nl>, <brendan.d.gregg@gmail.com>,
	<daniel@iogearbox.net>, <dsahern@gmail.com>, <hekuang@huawei.com>,
	<jolsa@kernel.org>, <lizefan@huawei.com>, <paulus@samba.org>,
	<wangnan0@huawei.com>, <xiakaixu@huawei.com>, <pi3orama@163.com>,
	<linux-kernel@vger.kernel.org>
Subject: [PATCH 04/27] perf tools: Enable passing bpf object file to --event
Date: Sun, 6 Sep 2015 07:13:20 +0000	[thread overview]
Message-ID: <1441523623-152703-5-git-send-email-wangnan0@huawei.com> (raw)
In-Reply-To: <1441523623-152703-1-git-send-email-wangnan0@huawei.com>

By introducing new rules in tools/perf/util/parse-events.[ly], this
patch enables 'perf record --event bpf_file.o' to select events by an
eBPF object file. It calls parse_events_load_bpf() to load that file,
which uses bpf__prepare_load() and finally calls bpf_object__open() for
the object files.

Instead of introducing evsel to evlist during parsing, events selected
by eBPF object files are appended separately. The reason is:

 1. During parsing, the probing points have not been initialized.

 2. Currently we are unable to call add_perf_probe_events() twice,
    therefore we have to wait until all such events are collected,
    then probe all points by one call.

The real probing and selecting is reside in following patches.

To make it compatible with other events, we insert a dummy event onto
evlist. Its name field can be used to connect path of the object file.

Since bpf__prepare_load() is possible to be called during cmdline
parsing, all builtin commands which are possible to call
parse_events_option() should release bpf resources during cleanup.
Add bpf__clear() to stat, record, top and trace commands, although
currently we are going to support 'perf record' only.

Commiter note:

Testing if the event parsing changes indeed call the BPF loading
routines:

  [root@felicio ~]# ls -la foo.o
  ls: cannot access foo.o: No such file or directory
  [root@felicio ~]# perf record --event foo.o sleep
  libbpf: failed to open foo.o: No such file or directory
  bpf: failed to load foo.o
  invalid or unsupported event: 'foo.o'
  Run 'perf list' for a list of valid events

   usage: perf record [<options>] [<command>]
      or: perf record [<options>] -- <command> [<options>]

      -e, --event <event>   event selector. use 'perf list' to list available events
  [root@felicio ~]#

Yes, it does this time around.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/n/1436445342-1402-19-git-send-email-wangnan0@huawei.com
[ The veprintf() and bpf loader parts were split from this one;
  Add bpf__clear() into stat, record, top and trace commands.
  Add dummy evsel as place holder of BPF objects.
]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c    |  7 ++++--
 tools/perf/builtin-stat.c      |  8 ++++--
 tools/perf/builtin-top.c       | 10 +++++---
 tools/perf/builtin-trace.c     |  6 ++++-
 tools/perf/util/Build          |  1 +
 tools/perf/util/parse-events.c | 55 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/parse-events.h |  3 +++
 tools/perf/util/parse-events.l |  3 +++
 tools/perf/util/parse-events.y | 18 +++++++++++++-
 9 files changed, 102 insertions(+), 9 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 142eeb3..f886706 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,6 +31,7 @@
 #include "util/auxtrace.h"
 #include "util/parse-branch-options.h"
 #include "util/parse-regs-options.h"
+#include "util/bpf-loader.h"
 
 #include <unistd.h>
 #include <sched.h>
@@ -1132,13 +1133,13 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (!rec->itr) {
 		rec->itr = auxtrace_record__init(rec->evlist, &err);
 		if (err)
-			return err;
+			goto out_bpf_clear;
 	}
 
 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
 					      rec->opts.auxtrace_snapshot_opts);
 	if (err)
-		return err;
+		goto out_bpf_clear;
 
 	err = -ENOMEM;
 
@@ -1201,6 +1202,8 @@ out_symbol_exit:
 	perf_evlist__delete(rec->evlist);
 	symbol__exit();
 	auxtrace_record__free(rec->itr);
+out_bpf_clear:
+	bpf__clear();
 	return err;
 }
 
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 77e5781..65506eb 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -59,6 +59,7 @@
 #include "util/thread.h"
 #include "util/thread_map.h"
 #include "util/counts.h"
+#include "util/bpf-loader.h"
 
 #include <stdlib.h>
 #include <sys/prctl.h>
@@ -1224,7 +1225,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		output = fopen(output_name, mode);
 		if (!output) {
 			perror("failed to create output file");
-			return -1;
+			status = -1;
+			goto out;
 		}
 		clock_gettime(CLOCK_REALTIME, &tm);
 		fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
@@ -1233,7 +1235,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		output = fdopen(output_fd, mode);
 		if (!output) {
 			perror("Failed opening logfd");
-			return -errno;
+			status = -errno;
+			goto out;
 		}
 	}
 
@@ -1366,5 +1369,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	perf_evlist__free_stats(evsel_list);
 out:
 	perf_evlist__delete(evsel_list);
+	bpf__clear();
 	return status;
 }
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 8c465c8..384ca2e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -41,6 +41,7 @@
 #include "util/sort.h"
 #include "util/intlist.h"
 #include "util/parse-branch-options.h"
+#include "util/bpf-loader.h"
 #include "arch/common.h"
 
 #include "util/debug.h"
@@ -1270,8 +1271,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 	symbol_conf.priv_size = sizeof(struct annotation);
 
 	symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
-	if (symbol__init(NULL) < 0)
-		return -1;
+	if (symbol__init(NULL) < 0) {
+		status = -1;
+		goto out_bpf_clear;
+	}
 
 	sort__setup_elide(stdout);
 
@@ -1289,6 +1292,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 
 out_delete_evlist:
 	perf_evlist__delete(top.evlist);
-
+out_bpf_clear:
+	bpf__clear();
 	return status;
 }
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 2156532..ac96242 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -31,6 +31,7 @@
 #include "util/intlist.h"
 #include "util/thread_map.h"
 #include "util/stat.h"
+#include "util/bpf-loader.h"
 #include "trace-event.h"
 #include "util/parse-events.h"
 
@@ -3109,6 +3110,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (trace.evlist->nr_entries > 0)
 		evlist__set_evsel_handler(trace.evlist, trace__event_handler);
 
+	/* trace__record calls cmd_record, which calls bpf__clear() */
 	if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
 		return trace__record(&trace, argc-1, &argv[1]);
 
@@ -3119,7 +3121,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (!trace.trace_syscalls && !trace.trace_pgfaults &&
 	    trace.evlist->nr_entries == 0 /* Was --events used? */) {
 		pr_err("Please specify something to trace.\n");
-		return -1;
+		err = -1;
+		goto out;
 	}
 
 	if (output_name != NULL) {
@@ -3178,5 +3181,6 @@ out_close:
 	if (output_name != NULL)
 		fclose(trace.output);
 out:
+	bpf__clear();
 	return err;
 }
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 349bc96..f5e9569 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -85,6 +85,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-bts.o
 libperf-y += parse-branch-options.o
 libperf-y += parse-regs-options.o
 
+libperf-$(CONFIG_LIBBPF) += bpf-loader.o
 libperf-$(CONFIG_LIBELF) += symbol-elf.o
 libperf-$(CONFIG_LIBELF) += probe-file.o
 libperf-$(CONFIG_LIBELF) += probe-event.o
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 07ce501..b560f5f 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -19,6 +19,7 @@
 #include "thread_map.h"
 #include "cpumap.h"
 #include "asm/bug.h"
+#include "bpf-loader.h"
 
 #define MAX_NAME_LEN 100
 
@@ -481,6 +482,60 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
 		return add_tracepoint_event(list, idx, sys, event);
 }
 
+int parse_events_load_bpf(struct parse_events_evlist *data,
+			  struct list_head *list,
+			  char *bpf_file_name)
+{
+	int err;
+	char errbuf[BUFSIZ];
+	struct perf_evsel *dummy_evsel;
+
+	/*
+	 * Currently don't link useful event to list. BPF object files
+	 * should be saved to a seprated list and processed together.
+	 *
+	 * Things could be changed if we solve perf probe reentering
+	 * problem. After that probe events file by file is possible.
+	 * However, probing cost is still need to be considered.
+	 *
+	 * We should still link something onto evlist to make it
+	 * compatible with other events, or we have to find another
+	 * way to collect --filter options and modifiers (currently
+	 * modifiers are not allowed lexicically). evsel->tracking
+	 * is another thing needs to be considered. Fortunately we have
+	 * dummy evsel, which is originally designed for collecting
+	 * evsel->tracking.
+	 */
+	err = parse_events_add_numeric(data, list, PERF_TYPE_SOFTWARE,
+				       PERF_COUNT_SW_DUMMY, NULL);
+	if (err)
+		return err;
+	if (list_empty(list) || !list_is_singular(list)) {
+		data->error->str = strdup(
+			"Internal error: failed to alloc dummy evsel");
+		return -ENOENT;
+	}
+
+	dummy_evsel = list_entry(list->prev, struct perf_evsel, node);
+
+	/* Give it a better name so we can connect this list to the object */
+	zfree(&dummy_evsel->name);
+	dummy_evsel->name = strdup(bpf_file_name);
+
+	err = bpf__prepare_load(bpf_file_name);
+	if (err) {
+		bpf__strerror_prepare_load(bpf_file_name, err,
+					   errbuf, sizeof(errbuf));
+		list_del_init(&dummy_evsel->node);
+		perf_evsel__delete(dummy_evsel);
+		data->error->str = strdup(errbuf);
+		data->error->help = strdup("(add -v to see detail)");
+		return err;
+	}
+
+	return 0;
+}
+
 static int
 parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
 {
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index a09b0e2..3652387 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -119,6 +119,9 @@ int parse_events__modifier_group(struct list_head *list, char *event_mod);
 int parse_events_name(struct list_head *list, char *name);
 int parse_events_add_tracepoint(struct list_head *list, int *idx,
 				char *sys, char *event);
+int parse_events_load_bpf(struct parse_events_evlist *data,
+			  struct list_head *list,
+			  char *bpf_file_name);
 int parse_events_add_numeric(struct parse_events_evlist *data,
 			     struct list_head *list,
 			     u32 type, u64 config,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 936d566..22e8f93 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -115,6 +115,7 @@ do {							\
 group		[^,{}/]*[{][^}]*[}][^,{}/]*
 event_pmu	[^,{}/]+[/][^/]*[/][^,{}/]*
 event		[^,{}/]+
+bpf_object	.*\.(o|bpf)
 
 num_dec		[0-9]+
 num_hex		0x[a-fA-F0-9]+
@@ -159,6 +160,7 @@ modifier_bp	[rwx]{1,3}
 		}
 
 {event_pmu}	|
+{bpf_object}	|
 {event}		{
 			BEGIN(INITIAL);
 			REWIND(1);
@@ -264,6 +266,7 @@ r{num_raw_hex}		{ return raw(yyscanner); }
 {num_hex}		{ return value(yyscanner, 16); }
 
 {modifier_event}	{ return str(yyscanner, PE_MODIFIER_EVENT); }
+{bpf_object}		{ return str(yyscanner, PE_BPF_OBJECT); }
 {name}			{ return pmu_str_check(yyscanner); }
 "/"			{ BEGIN(config); return '/'; }
 -			{ return '-'; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 591905a..3ee3a32 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -42,6 +42,7 @@ static inc_group_count(struct list_head *list,
 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
 %token PE_EVENT_NAME
 %token PE_NAME
+%token PE_BPF_OBJECT
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
@@ -53,6 +54,7 @@ static inc_group_count(struct list_head *list,
 %type <num> PE_RAW
 %type <num> PE_TERM
 %type <str> PE_NAME
+%type <str> PE_BPF_OBJECT
 %type <str> PE_NAME_CACHE_TYPE
 %type <str> PE_NAME_CACHE_OP_RESULT
 %type <str> PE_MODIFIER_EVENT
@@ -69,6 +71,7 @@ static inc_group_count(struct list_head *list,
 %type <head> event_legacy_tracepoint
 %type <head> event_legacy_numeric
 %type <head> event_legacy_raw
+%type <head> event_bpf_file
 %type <head> event_def
 %type <head> event_mod
 %type <head> event_name
@@ -198,7 +201,8 @@ event_def: event_pmu |
 	   event_legacy_mem |
 	   event_legacy_tracepoint sep_dc |
 	   event_legacy_numeric sep_dc |
-	   event_legacy_raw sep_dc
+	   event_legacy_raw sep_dc |
+	   event_bpf_file
 
 event_pmu:
 PE_NAME '/' event_config '/'
@@ -420,6 +424,18 @@ PE_RAW
 	$$ = list;
 }
 
+event_bpf_file:
+PE_BPF_OBJECT
+{
+	struct parse_events_evlist *data = _data;
+	struct list_head *list;
+
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_load_bpf(data, list, $1));
+	$$ = list;
+}
+
+
 start_terms: event_config
 {
 	struct parse_events_terms *data = _data;
-- 
2.1.0


  parent reply	other threads:[~2015-09-06  7:15 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-06  7:13 [GIT PULL 00/27] perf tools: filtering events using eBPF programs Wang Nan
2015-09-06  7:13 ` [PATCH 01/27] perf tools: Don't write to evsel if parser doesn't collect evsel Wang Nan
2015-09-23  8:43   ` [tip:perf/core] perf tools: Don' t assume that the parser returns non empty evsel list tip-bot for Wang Nan
2015-09-06  7:13 ` [PATCH 02/27] perf tools: Make perf depend on libbpf Wang Nan
2015-09-06  7:13 ` [PATCH 03/27] perf ebpf: Add the libbpf glue Wang Nan
2015-09-06  7:13 ` Wang Nan [this message]
2015-09-06  7:13 ` [PATCH 05/27] perf record, bpf: Parse and create probe points for BPF programs Wang Nan
2015-09-16 21:43   ` Arnaldo Carvalho de Melo
2015-09-17  2:04     ` Wangnan (F)
2015-09-06  7:13 ` [PATCH 06/27] perf bpf: Collect 'struct perf_probe_event' for bpf_program Wang Nan
2015-09-06  7:13 ` [PATCH 07/27] perf record: Load all eBPF object into kernel Wang Nan
2015-09-06  7:13 ` [PATCH 08/27] perf tools: Add bpf_fd field to evsel and config it Wang Nan
2015-09-06  7:13 ` [PATCH 09/27] perf tools: Attach eBPF program to perf event Wang Nan
2015-09-06  7:13 ` [PATCH 10/27] perf tools: Allow BPF placeholder dummy events to collect --filter options Wang Nan
2015-09-06  7:13 ` [PATCH 11/27] perf tools: Sync setting of real bpf events with placeholder Wang Nan
2015-09-06  7:13 ` [PATCH 12/27] perf record: Add clang options for compiling BPF scripts Wang Nan
2015-09-06  7:13 ` [PATCH 13/27] perf tools: Compile scriptlets to BPF objects when passing '.c' to --event Wang Nan
2015-09-06  7:13 ` [PATCH 14/27] perf test: Enforce LLVM test for BPF test Wang Nan
2015-09-06  7:13 ` [PATCH 15/27] perf test: Add 'perf test BPF' Wang Nan
2015-09-06  7:13 ` [PATCH 16/27] bpf tools: Load a program with different instances using preprocessor Wang Nan
2015-09-06  7:13 ` [PATCH 17/27] perf probe: Reset args and nargs for probe_trace_event when failure Wang Nan
2015-09-06  7:13 ` [PATCH 18/27] perf tools: Add BPF_PROLOGUE config options for further patches Wang Nan
2015-09-16  7:30   ` [tip:perf/core] perf tools: regs_query_register_offset() infrastructure tip-bot for Wang Nan
2015-09-06  7:13 ` [PATCH 19/27] perf tools: Introduce regs_query_register_offset() for x86 Wang Nan
2015-09-14 21:37   ` Arnaldo Carvalho de Melo
2015-09-15  1:36     ` Wangnan (F)
2015-09-16  7:30   ` [tip:perf/core] perf tools: Introduce regs_query_register_offset( ) " tip-bot for Wang Nan
2015-09-06  7:13 ` [PATCH 20/27] perf tools: Add prologue for BPF programs for fetching arguments Wang Nan
2015-09-06  7:13 ` [PATCH 21/27] perf tools: Generate prologue for BPF programs Wang Nan
2015-09-06  7:13 ` [PATCH 22/27] perf tools: Use same BPF program if arguments are identical Wang Nan
2015-09-06  7:13 ` [PATCH 23/27] perf record: Support custom vmlinux path Wang Nan
2015-09-06  7:13 ` [PATCH 24/27] perf probe: Init symbol as kprobe Wang Nan
2015-09-06  7:13 ` [PATCH 25/27] perf tools: Allow BPF program attach to uprobe events Wang Nan
2015-09-06  7:13 ` [PATCH 26/27] perf test: Enforce LLVM test, add kbuild test Wang Nan
2015-09-06  7:13 ` [PATCH 27/27] perf test: Test BPF prologue Wang Nan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1441523623-152703-5-git-send-email-wangnan0@huawei.com \
    --to=wangnan0@huawei.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@redhat.com \
    --cc=ast@plumgrid.com \
    --cc=brendan.d.gregg@gmail.com \
    --cc=daniel@iogearbox.net \
    --cc=dsahern@gmail.com \
    --cc=hekuang@huawei.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizefan@huawei.com \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=namhyung@kernel.org \
    --cc=paulus@samba.org \
    --cc=pi3orama@163.com \
    --cc=xiakaixu@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®