2022-02-18 00:14:59

by Jiri Olsa

[permalink] [raw]
Subject: [PATCHv2 0/3] perf/bpf: Replace deprecated code

hi,
the original patchset [1] removed the whole perf functionality
with the hope nobody's using that. But it turned out there's
actually bpf script using prologue functionality, so there
might be users of this.

This patchset gets rid of and adds workaround (and keeps the
current functionality) for following deprecated libbpf
functions/struct:

bpf_program__set_priv
bpf_program__priv
bpf_map__set_priv
bpf_map__priv
bpf_program__set_prep
bpf_program__nth_fd
struct bpf_prog_prep_result

Basically it implements workarounds suggested by Andrii in [2].

I tested with script from examples/bpf that are working for me:

examples/bpf/hello.c
examples/bpf/5sec.c

The rest seem to fail for various reasons even without this
change.. they seem unmaintained for some time now, but I might
have wrong setup.

Also available in here:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/depre

thanks,
jirka


[1] https://lore.kernel.org/linux-perf-users/YgoPxhE3OEEmZqla@krava/T/#t
[2] https://lore.kernel.org/linux-perf-users/YgoPxhE3OEEmZqla@krava/T/#md3ccab9fe70a4583e94603b1a562e369bd67b17d
---
Jiri Olsa (3):
perf tools: Remove bpf_program__set_priv/bpf_program__priv usage
perf tools: Remove bpf_map__set_priv/bpf_map__priv usage
perf tools: Rework prologue generation code

tools/perf/util/bpf-loader.c | 267 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 230 insertions(+), 37 deletions(-)


2022-02-18 00:16:17

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 1/3] perf tools: Remove bpf_program__set_priv/bpf_program__priv usage

Both bpf_program__set_priv/bpf_program__priv are deprecated
and will be eventually removed.

Using hashmap to replace that functionality.

Suggested-by: Andrii Nakryiko <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/util/bpf-loader.c | 91 +++++++++++++++++++++++++++++-------
1 file changed, 75 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index db61e09be585..ec27aab2bd36 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -26,6 +26,7 @@
#include "util.h"
#include "llvm-utils.h"
#include "c++/clang-c.h"
+#include "hashmap.h"

#include <internal/xyarray.h>

@@ -55,6 +56,7 @@ struct bpf_perf_object {
};

static LIST_HEAD(bpf_objects_list);
+static struct hashmap *bpf_program_hash;

static struct bpf_perf_object *
bpf_perf_object__next(struct bpf_perf_object *prev)
@@ -173,6 +175,35 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
return obj;
}

+static void
+clear_prog_priv(const struct bpf_program *prog __maybe_unused,
+ void *_priv)
+{
+ struct bpf_prog_priv *priv = _priv;
+
+ cleanup_perf_probe_events(&priv->pev, 1);
+ zfree(&priv->insns_buf);
+ zfree(&priv->type_mapping);
+ zfree(&priv->sys_name);
+ zfree(&priv->evt_name);
+ free(priv);
+}
+
+static void bpf_program_hash_free(void)
+{
+ struct hashmap_entry *cur;
+ size_t bkt;
+
+ if (!bpf_program_hash)
+ return;
+
+ hashmap__for_each_entry(bpf_program_hash, cur, bkt)
+ clear_prog_priv(cur->key, cur->value);
+
+ hashmap__free(bpf_program_hash);
+ bpf_program_hash = NULL;
+}
+
void bpf__clear(void)
{
struct bpf_perf_object *perf_obj, *tmp;
@@ -181,20 +212,48 @@ void bpf__clear(void)
bpf__unprobe(perf_obj->obj);
bpf_perf_object__close(perf_obj);
}
+
+ bpf_program_hash_free();
}

-static void
-clear_prog_priv(struct bpf_program *prog __maybe_unused,
- void *_priv)
+static size_t ptr_hash(const void *__key, void *ctx __maybe_unused)
{
- struct bpf_prog_priv *priv = _priv;
+ return (size_t) __key;
+}

- cleanup_perf_probe_events(&priv->pev, 1);
- zfree(&priv->insns_buf);
- zfree(&priv->type_mapping);
- zfree(&priv->sys_name);
- zfree(&priv->evt_name);
- free(priv);
+static bool ptr_equal(const void *key1, const void *key2,
+ void *ctx __maybe_unused)
+{
+ return key1 == key2;
+}
+
+static void *program_priv(const struct bpf_program *prog)
+{
+ void *priv;
+
+ if (!bpf_program_hash)
+ return NULL;
+ if (!hashmap__find(bpf_program_hash, prog, &priv))
+ return NULL;
+ return priv;
+}
+
+static int program_set_priv(struct bpf_program *prog, void *priv)
+{
+ void *old_priv;
+
+ if (!bpf_program_hash) {
+ bpf_program_hash = hashmap__new(ptr_hash, ptr_equal, NULL);
+ if (!bpf_program_hash)
+ return -ENOMEM;
+ }
+
+ old_priv = program_priv(prog);
+ if (old_priv) {
+ clear_prog_priv(prog, old_priv);
+ return hashmap__set(bpf_program_hash, prog, priv, NULL, NULL);
+ }
+ return hashmap__add(bpf_program_hash, prog, priv);
}

static int
@@ -438,7 +497,7 @@ config_bpf_program(struct bpf_program *prog)
pr_debug("bpf: config '%s' is ok\n", config_str);

set_priv:
- err = bpf_program__set_priv(prog, priv, clear_prog_priv);
+ err = program_set_priv(prog, priv);
if (err) {
pr_debug("Failed to set priv for program '%s'\n", config_str);
goto errout;
@@ -479,7 +538,7 @@ preproc_gen_prologue(struct bpf_program *prog, int n,
struct bpf_insn *orig_insns, int orig_insns_cnt,
struct bpf_prog_prep_result *res)
{
- struct bpf_prog_priv *priv = bpf_program__priv(prog);
+ struct bpf_prog_priv *priv = program_priv(prog);
struct probe_trace_event *tev;
struct perf_probe_event *pev;
struct bpf_insn *buf;
@@ -630,7 +689,7 @@ static int map_prologue(struct perf_probe_event *pev, int *mapping,

static int hook_load_preprocessor(struct bpf_program *prog)
{
- struct bpf_prog_priv *priv = bpf_program__priv(prog);
+ struct bpf_prog_priv *priv = program_priv(prog);
struct perf_probe_event *pev;
bool need_prologue = false;
int err, i;
@@ -706,7 +765,7 @@ int bpf__probe(struct bpf_object *obj)
if (err)
goto out;

- priv = bpf_program__priv(prog);
+ priv = program_priv(prog);
if (IS_ERR_OR_NULL(priv)) {
if (!priv)
err = -BPF_LOADER_ERRNO__INTERNAL;
@@ -758,7 +817,7 @@ int bpf__unprobe(struct bpf_object *obj)
struct bpf_program *prog;

bpf_object__for_each_program(prog, obj) {
- struct bpf_prog_priv *priv = bpf_program__priv(prog);
+ struct bpf_prog_priv *priv = program_priv(prog);
int i;

if (IS_ERR_OR_NULL(priv) || priv->is_tp)
@@ -814,7 +873,7 @@ int bpf__foreach_event(struct bpf_object *obj,
int err;

bpf_object__for_each_program(prog, obj) {
- struct bpf_prog_priv *priv = bpf_program__priv(prog);
+ struct bpf_prog_priv *priv = program_priv(prog);
struct probe_trace_event *tev;
struct perf_probe_event *pev;
int i, fd;
--
2.35.1