In this patch, when adding real events described in BPF objects, sync
filter and tracking settings with previous dummy placeholder. After
this patch, command like:

 # perf record --test-filter.o --exclude-perf ls

work as we expect.

After all settings are synced, we remove those placeholder from evlist
so they won't appear in the final perf.data.

Signed-off-by: Wang Nan <wangn...@huawei.com>
Cc: Alexei Starovoitov <a...@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gr...@gmail.com>
Cc: Daniel Borkmann <dan...@iogearbox.net>
Cc: David Ahern <dsah...@gmail.com>
Cc: He Kuang <heku...@huawei.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Kaixu Xia <xiaka...@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu...@hitachi.com>
Cc: Namhyung Kim <namhy...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zijls...@chello.nl>
Cc: Zefan Li <lize...@huawei.com>
Cc: pi3or...@163.com
Cc: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 tools/perf/util/bpf-loader.c |  8 ++++-
 tools/perf/util/bpf-loader.h |  1 +
 tools/perf/util/evlist.c     | 75 +++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 2880dbf..3400538 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -325,6 +325,12 @@ int bpf__foreach_tev(bpf_prog_iter_callback_t func, void 
*arg)
        int err;
 
        bpf_object__for_each_safe(obj, tmp) {
+               const char *obj_name;
+
+               obj_name = bpf_object__get_name(obj);
+               if (!obj_name)
+                       obj_name = "[unknown].o";
+
                bpf_object__for_each_program(prog, obj) {
                        struct probe_trace_event *tev;
                        struct perf_probe_event *pev;
@@ -348,7 +354,7 @@ int bpf__foreach_tev(bpf_prog_iter_callback_t func, void 
*arg)
                                        return fd;
                                }
 
-                               err = (*func)(tev, fd, arg);
+                               err = (*func)(tev, obj_name, fd, arg);
                                if (err) {
                                        pr_debug("bpf: call back failed, stop 
iterate\n");
                                        return err;
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 34656f8..5bac423 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -13,6 +13,7 @@
 #define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
 
 typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
+                                       const char *obj_name,
                                        int fd, void *arg);
 
 #ifdef HAVE_LIBBPF_SUPPORT
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 29212dc..7e36563 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -197,7 +197,54 @@ error:
        return -ENOMEM;
 }
 
-static int add_bpf_event(struct probe_trace_event *tev, int fd,
+static void sync_with_bpf_placeholder(struct perf_evlist *evlist,
+                                     const char *obj_name,
+                                     struct list_head *list)
+{
+       struct perf_evsel *dummy_evsel, *pos;
+
+       const char *filter;
+       bool tracking_set = false;
+       bool found = false;
+
+       evlist__for_each(evlist, dummy_evsel) {
+               if (!perf_evsel__is_bpf_placeholder(dummy_evsel))
+                       continue;
+
+               if (strcmp(dummy_evsel->name, obj_name) == 0) {
+                       found = true;
+                       break;
+               }
+       }
+
+       if (!found) {
+               pr_debug("Failed to find dummy event of '%s'\n",
+                        obj_name);
+               return;
+       }
+
+       filter = dummy_evsel->filter;
+
+       list_for_each_entry(pos, list, node) {
+               if (filter && perf_evsel__set_filter(pos, filter)) {
+                       pr_debug("Failed to set filter '%s' to evsel %s\n",
+                                filter, pos->name);
+               }
+
+               /* Sync tracking */
+               if (dummy_evsel->tracking && !tracking_set)
+                       pos->tracking = tracking_set = true;
+
+               /*
+                * If someday we allow to add config terms or modifiers
+                * to placeholder, we should sync them with real events
+                * here. Currently only tracking needs to be considered.
+                */
+       }
+}
+
+static int add_bpf_event(struct probe_trace_event *tev,
+                        const char *obj_name, int fd,
                         void *arg)
 {
        struct perf_evlist *evlist = arg;
@@ -205,8 +252,8 @@ static int add_bpf_event(struct probe_trace_event *tev, int 
fd,
        struct list_head list;
        int err, idx, entries;
 
-       pr_debug("add bpf event %s:%s and attach bpf program %d\n",
-                       tev->group, tev->event, fd);
+       pr_debug("add bpf event %s:%s and attach bpf program %d (from %s)\n",
+                       tev->group, tev->event, fd, obj_name);
        INIT_LIST_HEAD(&list);
        idx = evlist->nr_entries;
 
@@ -228,13 +275,33 @@ static int add_bpf_event(struct probe_trace_event *tev, 
int fd,
        list_for_each_entry(pos, &list, node)
                pos->bpf_fd = fd;
        entries = idx - evlist->nr_entries;
+
+       sync_with_bpf_placeholder(evlist, obj_name, &list);
+       /*
+        * Currectly we don't need to link those new events at the
+        * same place where dummy node reside because order of
+        * events in cmdline won't be used after
+        * 'perf_evlist__add_bpf'.
+        */
        perf_evlist__splice_list_tail(evlist, &list, entries);
        return 0;
 }
 
 int perf_evlist__add_bpf(struct perf_evlist *evlist)
 {
-       return bpf__foreach_tev(add_bpf_event, evlist);
+       struct perf_evsel *pos, *n;
+       int err;
+
+       err = bpf__foreach_tev(add_bpf_event, evlist);
+
+       evlist__for_each_safe(evlist, n, pos) {
+               if (perf_evsel__is_bpf_placeholder(pos)) {
+                       list_del_init(&pos->node);
+                       perf_evsel__delete(pos);
+                       evlist->nr_entries--;
+               }
+       }
+       return err;
 }
 
 static int perf_evlist__add_attrs(struct perf_evlist *evlist,
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to