From: Eduard Zingerman <eddyz87@gmail.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>,
Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: bpf <bpf@vger.kernel.org>, Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Kernel Team <kernel-team@fb.com>, Yonghong Song <yhs@fb.com>,
Alan Maguire <alan.maguire@oracle.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>
Subject: Re: [PATCH bpf-next v3 1/3] libbpf: hashmap interface update to long -> long
Date: Wed, 09 Nov 2022 04:14:23 +0200 [thread overview]
Message-ID: <82d36b7ae03e956f29c01b567aa8ba290b423364.camel@gmail.com> (raw)
In-Reply-To: <CAEf4BzZ8KFneEJxFAaNCCFPGqp20hSpS2aCj76uRk3-qZUH5xg@mail.gmail.com>
On Mon, 2022-11-07 at 16:46 -0800, Andrii Nakryiko wrote:
> On Sun, Nov 6, 2022 at 12:43 PM Alexei Starovoitov
> <alexei.starovoitov@gmail.com> wrote:
> >
> > On Sun, Nov 6, 2022 at 12:29 PM Eduard Zingerman <eddyz87@gmail.com> wrote:
> > >
> > > An update for libbpf's hashmap interface from void* -> void* to
> > > long -> long. Removes / simplifies some type casts when hashmap
> > > keys or values are 32-bit integers.
> > >
> > > In libbpf hashmap is more often used with integral keys / values
> > > rather than with pointer keys / values.
> > >
> > > Perf copies hashmap implementation from libbpf and has to be
> > > updated as well.
> > >
> > > Changes to libbpf, selftests/bpf and perf are packed as a single
> > > commit to avoid compilation issues with any future bisect.
> > >
> > > The net number of casts is decreased after this refactoring. Although
> > > perf mostly uses ptr to ptr maps, thus a lot of casts have to be
> > > added there:
> > >
> > > Casts Casts
> > > removed added
> > > libbpf ~50 ~20
> > > libbpf tests ~55 ~0
> > > perf ~0 ~33
> > > perf tests ~0 ~13
> > >
> > > This is a follow up for [1].
> > >
> > > [1] https://lore.kernel.org/bpf/af1facf9-7bc8-8a3d-0db4-7b3f333589a2@meta.com/T/#m65b28f1d6d969fcd318b556db6a3ad499a42607d
> > >
> > > Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
> > > ---
> > > tools/bpf/bpftool/btf.c | 25 ++---
> > > tools/bpf/bpftool/common.c | 10 +-
> > > tools/bpf/bpftool/gen.c | 19 ++--
> > > tools/bpf/bpftool/link.c | 8 +-
> > > tools/bpf/bpftool/main.h | 14 +--
> > > tools/bpf/bpftool/map.c | 8 +-
> > > tools/bpf/bpftool/pids.c | 16 +--
> > > tools/bpf/bpftool/prog.c | 8 +-
> > > tools/lib/bpf/btf.c | 41 ++++---
> > > tools/lib/bpf/btf_dump.c | 16 +--
> > > tools/lib/bpf/hashmap.c | 16 +--
> > > tools/lib/bpf/hashmap.h | 34 +++---
> > > tools/lib/bpf/libbpf.c | 18 ++--
> > > tools/lib/bpf/strset.c | 18 ++--
> > > tools/lib/bpf/usdt.c | 31 +++---
> > > tools/perf/tests/expr.c | 40 +++----
> > > tools/perf/tests/pmu-events.c | 6 +-
> > > tools/perf/util/bpf-loader.c | 23 ++--
> > > tools/perf/util/expr.c | 32 +++---
> > > tools/perf/util/hashmap.c | 16 +--
> > > tools/perf/util/hashmap.h | 34 +++---
> > > tools/perf/util/metricgroup.c | 12 +--
> > > tools/perf/util/stat.c | 9 +-
> > > .../selftests/bpf/prog_tests/hashmap.c | 102 +++++++++---------
> > > .../bpf/prog_tests/kprobe_multi_test.c | 6 +-
> > > 25 files changed, 257 insertions(+), 305 deletions(-)
> >
> > Looks like the churn is not worth it.
> > I'd keep it as-is.
>
> No-no, this is already a big win for libbpf/bpftool as is, but we can
> do even better for perf and some uses in selftest and libbpf itself.
> Given a hashmap can be used with a pointer or an integer as the
> key/value, we can use a bit of smartness (while keeping the safety)
> through simple macro wrapper for operations like hashmap__find and
> hashmap__insert (and co). That will avoid most of if not all casts for
> hashmap lookups/updates. And then for hashmap__for_each_entry and
> such, we can define hashmap_entry to have a union of long-based and
> void*-based key:
>
> struct hashmap_entry {
> union {
> long key;
> const void *pkey;
> };
> union {
> long value;
> void *pvalue;
> };
> ...
> }
>
> I have it a try in few perf places, and it allows to avoid all the
> casts while thanks to that _Statis_assert we should be even safer than
> it was before. Eduard, please check the diff below and see if you can
> incorporate similar changes for other operations, if necessary.
>
That's a nice hack, thank you. Everything works after interface
function / macro update. I need a bit more time to wrap up the
patch-set, will post it tomorrow.
> $ git diff
> diff --git a/tools/lib/bpf/hashmap.c b/tools/lib/bpf/hashmap.c
> index dfe99e766f30..0c1c1289a694 100644
> --- a/tools/lib/bpf/hashmap.c
> +++ b/tools/lib/bpf/hashmap.c
> @@ -203,7 +203,7 @@ int hashmap__insert(struct hashmap *map, long key,
> long value,
> return 0;
> }
>
> -bool hashmap__find(const struct hashmap *map, long key, long *value)
> +bool hashmap_find(const struct hashmap *map, long key, long *value)
> {
> struct hashmap_entry *entry;
> size_t h;
> diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h
> index 7393ef616920..daec29012808 100644
> --- a/tools/lib/bpf/hashmap.h
> +++ b/tools/lib/bpf/hashmap.h
> @@ -47,8 +47,14 @@ typedef size_t (*hashmap_hash_fn)(long key, void *ctx);
> typedef bool (*hashmap_equal_fn)(long key1, long key2, void *ctx);
>
> struct hashmap_entry {
> - long key;
> - long value;
> + union {
> + long key;
> + const void *pkey;
> + };
> + union {
> + long value;
> + void *pvalue;
> + };
> struct hashmap_entry *next;
> };
>
> @@ -144,7 +150,13 @@ static inline int hashmap__append(struct hashmap
> *map, long key, long value)
>
> bool hashmap__delete(struct hashmap *map, long key, long *old_key,
> long *old_value);
>
> -bool hashmap__find(const struct hashmap *map, long key, long *value);
> +bool hashmap_find(const struct hashmap *map, long key, long *value);
> +
> +#define hashmap__find(map, key, value) ({
> \
> + _Static_assert(value == NULL || sizeof(*value) ==
> sizeof(long), \
> + "Value pointee should be a long-sized
> integer or a pointer"); \
> + hashmap_find(map, (long)key, (long *)value);
> \
> +})
>
> /*
> * hashmap__for_each_entry - iterate over all entries in hashmap
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 96092c9cb34b..1a1a76357f72 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -5669,7 +5669,7 @@ static int bpf_core_resolve_relo(struct bpf_program *prog,
> return -EINVAL;
>
> if (relo->kind != BPF_CORE_TYPE_ID_LOCAL &&
> - !hashmap__find(cand_cache, local_id, (long *)&cands)) {
> + !hashmap__find(cand_cache, local_id, &cands)) {
> cands = bpf_core_find_cands(prog->obj, local_btf, local_id);
> if (IS_ERR(cands)) {
> pr_warn("prog '%s': relo #%d: target candidate
> search failed for [%d] %s %s: %ld\n",
> diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
> index 8107ed0428c2..cb206003c1f0 100644
> --- a/tools/perf/tests/expr.c
> +++ b/tools/perf/tests/expr.c
> @@ -130,12 +130,9 @@ static int test__expr(struct test_suite *t
> __maybe_unused, int subtest __maybe_u
> expr__find_ids("FOO + BAR + BAZ + BOZO", "FOO",
> ctx) == 0);
> TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 3);
> - TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, (long)"BAR",
> - (long *)&val_ptr));
> - TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, (long)"BAZ",
> - (long *)&val_ptr));
> - TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, (long)"BOZO",
> - (long *)&val_ptr));
> + TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
> (long)"BAR", &val_ptr));
> + TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
> (long)"BAZ", &val_ptr));
> + TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
> (long)"BOZO", &val_ptr));
>
> expr__ctx_clear(ctx);
> ctx->sctx.runtime = 3;
> @@ -143,20 +140,16 @@ static int test__expr(struct test_suite *t
> __maybe_unused, int subtest __maybe_u
> expr__find_ids("EVENT1\\,param\\=?@ +
> EVENT2\\,param\\=?@",
> NULL, ctx) == 0);
> TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 2);
> - TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
> (long)"EVENT1,param=3@",
> - (long *)&val_ptr));
> - TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
> (long)"EVENT2,param=3@",
> - (long *)&val_ptr));
> + TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
> (long)"EVENT1,param=3@", &val_ptr));
> + TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
> (long)"EVENT2,param=3@", &val_ptr));
>
> expr__ctx_clear(ctx);
> TEST_ASSERT_VAL("find ids",
> expr__find_ids("dash\\-event1 - dash\\-event2",
> NULL, ctx) == 0);
> TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 2);
> - TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, (long)"dash-event1",
> - (long *)&val_ptr));
> - TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, (long)"dash-event2",
> - (long *)&val_ptr));
> + TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
> (long)"dash-event1", &val_ptr));
> + TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
> (long)"dash-event2", &val_ptr));
>
> /* Only EVENT1 or EVENT2 need be measured depending on the
> value of smt_on. */
> {
> @@ -174,7 +167,7 @@ static int test__expr(struct test_suite *t
> __maybe_unused, int subtest __maybe_u
> TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 1);
> TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
> (long)(smton
> ? "EVENT1" : "EVENT2"),
> - (long *)&val_ptr));
> + &val_ptr));
>
> expr__ctx_clear(ctx);
> TEST_ASSERT_VAL("find ids",
> @@ -183,7 +176,7 @@ static int test__expr(struct test_suite *t
> __maybe_unused, int subtest __maybe_u
> TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 1);
> TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids,
>
> (long)(corewide ? "EVENT1" : "EVENT2"),
> - (long *)&val_ptr));
> + &val_ptr));
>
> }
> /* The expression is a constant 1.0 without needing to
> evaluate EVENT1. */
> @@ -220,8 +213,7 @@ static int test__expr(struct test_suite *t
> __maybe_unused, int subtest __maybe_u
> expr__find_ids("source_count(EVENT1)",
> NULL, ctx) == 0);
> TEST_ASSERT_VAL("source count", hashmap__size(ctx->ids) == 1);
> - TEST_ASSERT_VAL("source count", hashmap__find(ctx->ids, (long)"EVENT1",
> - (long *)&val_ptr));
> + TEST_ASSERT_VAL("source count", hashmap__find(ctx->ids,
> (long)"EVENT1", &val_ptr));
>
> expr__ctx_free(ctx);
>
> diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
> index 55f114450316..2430b8965268 100644
> --- a/tools/perf/util/bpf-loader.c
> +++ b/tools/perf/util/bpf-loader.c
> @@ -131,7 +131,7 @@ static void *program_priv(const struct bpf_program *prog)
>
> if (IS_ERR_OR_NULL(bpf_program_hash))
> return NULL;
> - if (!hashmap__find(bpf_program_hash, (long)prog, (long *)&priv))
> + if (!hashmap__find(bpf_program_hash, prog, &priv))
> return NULL;
> return priv;
> }
> @@ -1170,7 +1170,7 @@ static void *map_priv(const struct bpf_map *map)
>
> if (IS_ERR_OR_NULL(bpf_map_hash))
> return NULL;
> - if (!hashmap__find(bpf_map_hash, (long)map, (long *)&priv))
> + if (!hashmap__find(bpf_map_hash, map, &priv))
> return NULL;
> return priv;
> }
> @@ -1184,7 +1184,7 @@ static void bpf_map_hash_free(void)
> return;
>
> hashmap__for_each_entry(bpf_map_hash, cur, bkt)
> - bpf_map_priv__clear((struct bpf_map *)cur->key, (void
> *)cur->value);
> + bpf_map_priv__clear(cur->pkey, cur->pvalue);
>
> hashmap__free(bpf_map_hash);
> bpf_map_hash = NULL;
> diff --git a/tools/perf/util/hashmap.c b/tools/perf/util/hashmap.c
> index dfe99e766f30..0c1c1289a694 100644
> --- a/tools/perf/util/hashmap.c
> +++ b/tools/perf/util/hashmap.c
> @@ -203,7 +203,7 @@ int hashmap__insert(struct hashmap *map, long key,
> long value,
> return 0;
> }
>
> -bool hashmap__find(const struct hashmap *map, long key, long *value)
> +bool hashmap_find(const struct hashmap *map, long key, long *value)
> {
> struct hashmap_entry *entry;
> size_t h;
> diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h
> index 7393ef616920..edbadb712725 100644
> --- a/tools/perf/util/hashmap.h
> +++ b/tools/perf/util/hashmap.h
> @@ -47,8 +47,14 @@ typedef size_t (*hashmap_hash_fn)(long key, void *ctx);
> typedef bool (*hashmap_equal_fn)(long key1, long key2, void *ctx);
>
> struct hashmap_entry {
> - long key;
> - long value;
> + union {
> + long key;
> + const void *pkey;
> + };
> + union {
> + long value;
> + void *pvalue;
> + };
> struct hashmap_entry *next;
> };
>
> @@ -144,7 +150,13 @@ static inline int hashmap__append(struct hashmap
> *map, long key, long value)
>
> bool hashmap__delete(struct hashmap *map, long key, long *old_key,
> long *old_value);
>
> -bool hashmap__find(const struct hashmap *map, long key, long *value);
> +bool hashmap_find(const struct hashmap *map, long key, long *value);
> +
> +#define hashmap__find(map, key, value) ({
> \
> + _Static_assert(sizeof(*value) == sizeof(long),
> \
> + "Value pointee should be a long-sized
> integer or a pointer"); \
> + hashmap_find(map, (long)key, (long *)value);
> \
> +})
>
> /*
> * hashmap__for_each_entry - iterate over all entries in hashmap
> diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
> index e9bd881c6912..2059ed3164ae 100644
> --- a/tools/perf/util/metricgroup.c
> +++ b/tools/perf/util/metricgroup.c
> @@ -288,7 +288,7 @@ static int setup_metric_events(struct hashmap *ids,
> * combined or shared groups, this metric may not care
> * about this event.
> */
> - if (hashmap__find(ids, (long)metric_id, (long *)&val_ptr)) {
> + if (hashmap__find(ids, metric_id, &val_ptr)) {
> metric_events[matched_events++] = ev;
>
> if (matched_events >= ids_size)
> 11/07 16:45:42.699 andriin@devbig019:~/linux/tools/lib/bpf (master)
> $
next prev parent reply other threads:[~2022-11-09 2:14 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-06 20:29 [PATCH bpf-next v3 0/3] libbpf: Resolve unambigous forward declarations Eduard Zingerman
2022-11-06 20:29 ` [PATCH bpf-next v3 1/3] libbpf: hashmap interface update to long -> long Eduard Zingerman
2022-11-06 20:43 ` Alexei Starovoitov
2022-11-08 0:46 ` Andrii Nakryiko
2022-11-08 7:31 ` Alexei Starovoitov
2022-11-09 2:14 ` Eduard Zingerman [this message]
2022-11-06 20:29 ` [PATCH bpf-next v3 2/3] libbpf: Resolve unambigous forward declarations Eduard Zingerman
2022-11-06 20:29 ` [PATCH bpf-next v3 3/3] selftests/bpf: Tests for btf_dedup_resolve_fwds Eduard Zingerman
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=82d36b7ae03e956f29c01b567aa8ba290b423364.camel@gmail.com \
--to=eddyz87@gmail.com \
--cc=acme@kernel.org \
--cc=alan.maguire@oracle.com \
--cc=alexei.starovoitov@gmail.com \
--cc=andrii.nakryiko@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=kernel-team@fb.com \
--cc=yhs@fb.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