lkml.org 
[lkml]   [2015]   [Jul]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v11 35/39] perf tools: Add bpf_fd field to evsel and config it
    Date
    This patch adds a bpf_fd field to 'struct evsel' then introduces method
    to config it. In bpf-loader, a bpf__foreach_tev() function is added,
    Which calls the callback function for each 'struct probe_trace_event'
    events for each bpf program with their file descriptors. In evlist.c,
    perf_evlist__add_bpf() is introduced to add all bpf events into evlist.
    The event names are found from probe_trace_event structure.
    'perf record' calls perf_evlist__add_bpf().

    Since bpf-loader.c will not be built if libbpf is turned off, an empty
    bpf__foreach_tev() is defined in bpf-loader.h to avoid compiling
    error.

    This patch iterates over 'struct probe_trace_event' instead of
    'struct probe_trace_event' during the loop for further patches, which
    will generate multiple instances form one BPF program and install then
    onto different 'struct probe_trace_event'.

    Signed-off-by: Wang Nan <wangnan0@huawei.com>
    ---
    tools/perf/builtin-record.c | 6 ++++++
    tools/perf/util/bpf-loader.c | 42 ++++++++++++++++++++++++++++++++++++++++++
    tools/perf/util/bpf-loader.h | 13 +++++++++++++
    tools/perf/util/evlist.c | 41 +++++++++++++++++++++++++++++++++++++++++
    tools/perf/util/evlist.h | 1 +
    tools/perf/util/evsel.c | 1 +
    tools/perf/util/evsel.h | 1 +
    7 files changed, 105 insertions(+)

    diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
    index 6d943a7..bd189b1 100644
    --- a/tools/perf/builtin-record.c
    +++ b/tools/perf/builtin-record.c
    @@ -1140,6 +1140,12 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
    goto out_symbol_exit;
    }

    + err = perf_evlist__add_bpf(rec->evlist);
    + if (err < 0) {
    + pr_err("Failed to add events from BPF object(s)\n");
    + goto out_symbol_exit;
    + }
    +
    symbol__init(NULL);

    if (symbol_conf.kptr_restrict)
    diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
    index f68ba33..63077b9 100644
    --- a/tools/perf/util/bpf-loader.c
    +++ b/tools/perf/util/bpf-loader.c
    @@ -260,3 +260,45 @@ errout:
    bpf_object__unload(obj);
    return err;
    }
    +
    +int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg)
    +{
    + struct bpf_object *obj, *tmp;
    + struct bpf_program *prog;
    + int err;
    +
    + bpf_object__for_each_safe(obj, tmp) {
    + bpf_object__for_each_program(prog, obj) {
    + struct probe_trace_event *tev;
    + struct perf_probe_event *pev;
    + struct bpf_prog_priv *priv;
    + int i, fd;
    +
    + err = bpf_program__get_private(prog,
    + (void **)&priv);
    + if (err || !priv) {
    + pr_err("bpf: failed to get private field\n");
    + return -EINVAL;
    + }
    +
    + pev = priv->pev;
    + for (i = 0; i < pev->ntevs; i++) {
    + tev = &pev->tevs[i];
    +
    + err = bpf_program__get_fd(prog, &fd);
    +
    + if (err || fd < 0) {
    + pr_err("bpf: failed to get file descriptor\n");
    + return -EINVAL;
    + }
    + err = func(tev, fd, arg);
    + if (err) {
    + pr_err("bpf: call back failed, stop iterate\n");
    + return err;
    + }
    + }
    + }
    + }
    +
    + return 0;
    +}
    diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
    index ae0dc9b..ef9b3bb 100644
    --- a/tools/perf/util/bpf-loader.h
    +++ b/tools/perf/util/bpf-loader.h
    @@ -6,10 +6,14 @@
    #define __BPF_LOADER_H

    #include <linux/compiler.h>
    +#include "probe-event.h"
    #include "debug.h"

    #define PERF_BPF_PROBE_GROUP "perf_bpf_probe"

    +typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
    + int fd, void *arg);
    +
    #ifdef HAVE_LIBBPF_SUPPORT
    int bpf__prepare_load(const char *filename, bool source);
    int bpf__probe(void);
    @@ -17,6 +21,8 @@ int bpf__unprobe(void);
    int bpf__load(void);

    void bpf__clear(void);
    +
    +int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg);
    #else
    static inline int bpf__prepare_load(const char *filename __maybe_unused,
    bool source __maybe_unused)
    @@ -29,5 +35,12 @@ static inline int bpf__probe(void) { return 0; }
    static inline int bpf__unprobe(void) { return 0; }
    static inline int bpf__load(void) { return 0; }
    static inline void bpf__clear(void) { }
    +
    +static inline int
    +bpf__foreach_tev(bpf_prog_iter_callback_t func __maybe_unused,
    + void *arg __maybe_unused)
    +{
    + return 0;
    +}
    #endif
    #endif
    diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
    index f7d9c77..5a01c7f 100644
    --- a/tools/perf/util/evlist.c
    +++ b/tools/perf/util/evlist.c
    @@ -14,6 +14,7 @@
    #include "target.h"
    #include "evlist.h"
    #include "evsel.h"
    +#include "bpf-loader.h"
    #include "debug.h"
    #include <unistd.h>

    @@ -194,6 +195,46 @@ error:
    return -ENOMEM;
    }

    +static int add_bpf_event(struct probe_trace_event *tev, int fd,
    + void *arg)
    +{
    + struct perf_evlist *evlist = arg;
    + struct perf_evsel *pos;
    + 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);
    + INIT_LIST_HEAD(&list);
    + idx = evlist->nr_entries;
    +
    + pr_debug("adding %s:%s\n", tev->group, tev->event);
    + err = parse_events_add_tracepoint(&list, &idx, tev->group,
    + tev->event);
    + if (err) {
    + struct perf_evsel *evsel, *tmp;
    +
    + pr_err("Failed to add BPF event %s:%s\n",
    + tev->group, tev->event);
    + list_for_each_entry_safe(evsel, tmp, &list, node) {
    + list_del(&evsel->node);
    + perf_evsel__delete(evsel);
    + }
    + return -EINVAL;
    + }
    +
    + list_for_each_entry(pos, &list, node)
    + pos->bpf_fd = fd;
    + entries = idx - evlist->nr_entries;
    + 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);
    +}
    +
    static int perf_evlist__add_attrs(struct perf_evlist *evlist,
    struct perf_event_attr *attrs, size_t nr_attrs)
    {
    diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
    index 037633c..4e3b6b0 100644
    --- a/tools/perf/util/evlist.h
    +++ b/tools/perf/util/evlist.h
    @@ -72,6 +72,7 @@ void perf_evlist__delete(struct perf_evlist *evlist);

    void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
    int perf_evlist__add_default(struct perf_evlist *evlist);
    +int perf_evlist__add_bpf(struct perf_evlist *evlist);
    int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
    struct perf_event_attr *attrs, size_t nr_attrs);

    diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
    index 83c0803..fe80047 100644
    --- a/tools/perf/util/evsel.c
    +++ b/tools/perf/util/evsel.c
    @@ -206,6 +206,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
    evsel->leader = evsel;
    evsel->unit = "";
    evsel->scale = 1.0;
    + evsel->bpf_fd = -1;
    INIT_LIST_HEAD(&evsel->node);
    perf_evsel__object.init(evsel);
    evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
    diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
    index fe9f327..4bcd629 100644
    --- a/tools/perf/util/evsel.h
    +++ b/tools/perf/util/evsel.h
    @@ -86,6 +86,7 @@ struct perf_evsel {
    unsigned long *per_pkg_mask;
    struct perf_evsel *leader;
    char *group_name;
    + int bpf_fd;
    };

    union u64_swap {
    --
    1.8.3.4


    \
     
     \ /
      Last update: 2015-07-08 15:21    [W:4.503 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site