Skip to content

Commit c302378

Browse files
eddyz87anakryiko
authored andcommitted
libbpf: Hashmap interface update to allow both long and void* keys/values
An update for libbpf's hashmap interface from void* -> void* to a polymorphic one, allowing both long and void* keys and values. This simplifies many use cases in libbpf as hashmaps there are mostly integer to integer. 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. Polymorphic interface is acheived by hiding hashmap interface functions behind auxiliary macros that take care of necessary type casts, for example: #define hashmap_cast_ptr(p) \ ({ \ _Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),\ #p " pointee should be a long-sized integer or a pointer"); \ (long *)(p); \ }) bool hashmap_find(const struct hashmap *map, long key, long *value); #define hashmap__find(map, key, value) \ hashmap_find((map), (long)(key), hashmap_cast_ptr(value)) - hashmap__find macro casts key and value parameters to long and long* respectively - hashmap_cast_ptr ensures that value pointer points to a memory of appropriate size. This hack was suggested by Andrii Nakryiko in [1]. This is a follow up for [2]. [1] https://lore.kernel.org/bpf/CAEf4BzZ8KFneEJxFAaNCCFPGqp20hSpS2aCj76uRk3-qZUH5xg@mail.gmail.com/ [2] https://lore.kernel.org/bpf/af1facf9-7bc8-8a3d-0db4-7b3f333589a2@meta.com/T/#m65b28f1d6d969fcd318b556db6a3ad499a42607d Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20221109142611.879983-2-eddyz87@gmail.com
1 parent e5659e4 commit c302378

27 files changed

Lines changed: 410 additions & 340 deletions

tools/bpf/bpftool/btf.c

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -815,8 +815,7 @@ build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
815815
if (!btf_id)
816816
continue;
817817

818-
err = hashmap__append(tab, u32_as_hash_field(btf_id),
819-
u32_as_hash_field(id));
818+
err = hashmap__append(tab, btf_id, id);
820819
if (err) {
821820
p_err("failed to append entry to hashmap for BTF ID %u, object ID %u: %s",
822821
btf_id, id, strerror(-err));
@@ -875,17 +874,13 @@ show_btf_plain(struct bpf_btf_info *info, int fd,
875874
printf("size %uB", info->btf_size);
876875

877876
n = 0;
878-
hashmap__for_each_key_entry(btf_prog_table, entry,
879-
u32_as_hash_field(info->id)) {
880-
printf("%s%u", n++ == 0 ? " prog_ids " : ",",
881-
hash_field_as_u32(entry->value));
877+
hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
878+
printf("%s%lu", n++ == 0 ? " prog_ids " : ",", entry->value);
882879
}
883880

884881
n = 0;
885-
hashmap__for_each_key_entry(btf_map_table, entry,
886-
u32_as_hash_field(info->id)) {
887-
printf("%s%u", n++ == 0 ? " map_ids " : ",",
888-
hash_field_as_u32(entry->value));
882+
hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
883+
printf("%s%lu", n++ == 0 ? " map_ids " : ",", entry->value);
889884
}
890885

891886
emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
@@ -907,17 +902,15 @@ show_btf_json(struct bpf_btf_info *info, int fd,
907902

908903
jsonw_name(json_wtr, "prog_ids");
909904
jsonw_start_array(json_wtr); /* prog_ids */
910-
hashmap__for_each_key_entry(btf_prog_table, entry,
911-
u32_as_hash_field(info->id)) {
912-
jsonw_uint(json_wtr, hash_field_as_u32(entry->value));
905+
hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
906+
jsonw_uint(json_wtr, entry->value);
913907
}
914908
jsonw_end_array(json_wtr); /* prog_ids */
915909

916910
jsonw_name(json_wtr, "map_ids");
917911
jsonw_start_array(json_wtr); /* map_ids */
918-
hashmap__for_each_key_entry(btf_map_table, entry,
919-
u32_as_hash_field(info->id)) {
920-
jsonw_uint(json_wtr, hash_field_as_u32(entry->value));
912+
hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
913+
jsonw_uint(json_wtr, entry->value);
921914
}
922915
jsonw_end_array(json_wtr); /* map_ids */
923916

tools/bpf/bpftool/common.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ static int do_build_table_cb(const char *fpath, const struct stat *sb,
494494
goto out_close;
495495
}
496496

497-
err = hashmap__append(build_fn_table, u32_as_hash_field(pinned_info.id), path);
497+
err = hashmap__append(build_fn_table, pinned_info.id, path);
498498
if (err) {
499499
p_err("failed to append entry to hashmap for ID %u, path '%s': %s",
500500
pinned_info.id, path, strerror(errno));
@@ -545,7 +545,7 @@ void delete_pinned_obj_table(struct hashmap *map)
545545
return;
546546

547547
hashmap__for_each_entry(map, entry, bkt)
548-
free(entry->value);
548+
free(entry->pvalue);
549549

550550
hashmap__free(map);
551551
}
@@ -1041,12 +1041,12 @@ int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len)
10411041
return fd;
10421042
}
10431043

1044-
size_t hash_fn_for_key_as_id(const void *key, void *ctx)
1044+
size_t hash_fn_for_key_as_id(long key, void *ctx)
10451045
{
1046-
return (size_t)key;
1046+
return key;
10471047
}
10481048

1049-
bool equal_fn_for_key_as_id(const void *k1, const void *k2, void *ctx)
1049+
bool equal_fn_for_key_as_id(long k1, long k2, void *ctx)
10501050
{
10511051
return k1 == k2;
10521052
}

tools/bpf/bpftool/gen.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,21 +1660,16 @@ struct btfgen_info {
16601660
struct btf *marked_btf; /* btf structure used to mark used types */
16611661
};
16621662

1663-
static size_t btfgen_hash_fn(const void *key, void *ctx)
1663+
static size_t btfgen_hash_fn(long key, void *ctx)
16641664
{
1665-
return (size_t)key;
1665+
return key;
16661666
}
16671667

1668-
static bool btfgen_equal_fn(const void *k1, const void *k2, void *ctx)
1668+
static bool btfgen_equal_fn(long k1, long k2, void *ctx)
16691669
{
16701670
return k1 == k2;
16711671
}
16721672

1673-
static void *u32_as_hash_key(__u32 x)
1674-
{
1675-
return (void *)(uintptr_t)x;
1676-
}
1677-
16781673
static void btfgen_free_info(struct btfgen_info *info)
16791674
{
16801675
if (!info)
@@ -2086,18 +2081,18 @@ static int btfgen_record_obj(struct btfgen_info *info, const char *obj_path)
20862081
struct bpf_core_spec specs_scratch[3] = {};
20872082
struct bpf_core_relo_res targ_res = {};
20882083
struct bpf_core_cand_list *cands = NULL;
2089-
const void *type_key = u32_as_hash_key(relo->type_id);
20902084
const char *sec_name = btf__name_by_offset(btf, sec->sec_name_off);
20912085

20922086
if (relo->kind != BPF_CORE_TYPE_ID_LOCAL &&
2093-
!hashmap__find(cand_cache, type_key, (void **)&cands)) {
2087+
!hashmap__find(cand_cache, relo->type_id, &cands)) {
20942088
cands = btfgen_find_cands(btf, info->src_btf, relo->type_id);
20952089
if (!cands) {
20962090
err = -errno;
20972091
goto out;
20982092
}
20992093

2100-
err = hashmap__set(cand_cache, type_key, cands, NULL, NULL);
2094+
err = hashmap__set(cand_cache, relo->type_id, cands,
2095+
NULL, NULL);
21012096
if (err)
21022097
goto out;
21032098
}
@@ -2120,7 +2115,7 @@ static int btfgen_record_obj(struct btfgen_info *info, const char *obj_path)
21202115

21212116
if (!IS_ERR_OR_NULL(cand_cache)) {
21222117
hashmap__for_each_entry(cand_cache, entry, i) {
2123-
bpf_core_free_cands(entry->value);
2118+
bpf_core_free_cands(entry->pvalue);
21242119
}
21252120
hashmap__free(cand_cache);
21262121
}

tools/bpf/bpftool/link.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,8 @@ static int show_link_close_json(int fd, struct bpf_link_info *info)
204204

205205
jsonw_name(json_wtr, "pinned");
206206
jsonw_start_array(json_wtr);
207-
hashmap__for_each_key_entry(link_table, entry,
208-
u32_as_hash_field(info->id))
209-
jsonw_string(json_wtr, entry->value);
207+
hashmap__for_each_key_entry(link_table, entry, info->id)
208+
jsonw_string(json_wtr, entry->pvalue);
210209
jsonw_end_array(json_wtr);
211210
}
212211

@@ -309,9 +308,8 @@ static int show_link_close_plain(int fd, struct bpf_link_info *info)
309308
if (!hashmap__empty(link_table)) {
310309
struct hashmap_entry *entry;
311310

312-
hashmap__for_each_key_entry(link_table, entry,
313-
u32_as_hash_field(info->id))
314-
printf("\n\tpinned %s", (char *)entry->value);
311+
hashmap__for_each_key_entry(link_table, entry, info->id)
312+
printf("\n\tpinned %s", (char *)entry->pvalue);
315313
}
316314
emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
317315

tools/bpf/bpftool/main.h

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,8 @@ int do_filter_dump(struct tcmsg *ifinfo, struct nlattr **tb, const char *kind,
240240
int print_all_levels(__maybe_unused enum libbpf_print_level level,
241241
const char *format, va_list args);
242242

243-
size_t hash_fn_for_key_as_id(const void *key, void *ctx);
244-
bool equal_fn_for_key_as_id(const void *k1, const void *k2, void *ctx);
243+
size_t hash_fn_for_key_as_id(long key, void *ctx);
244+
bool equal_fn_for_key_as_id(long k1, long k2, void *ctx);
245245

246246
/* bpf_attach_type_input_str - convert the provided attach type value into a
247247
* textual representation that we accept for input purposes.
@@ -257,16 +257,6 @@ bool equal_fn_for_key_as_id(const void *k1, const void *k2, void *ctx);
257257
*/
258258
const char *bpf_attach_type_input_str(enum bpf_attach_type t);
259259

260-
static inline void *u32_as_hash_field(__u32 x)
261-
{
262-
return (void *)(uintptr_t)x;
263-
}
264-
265-
static inline __u32 hash_field_as_u32(const void *x)
266-
{
267-
return (__u32)(uintptr_t)x;
268-
}
269-
270260
static inline bool hashmap__empty(struct hashmap *map)
271261
{
272262
return map ? hashmap__size(map) == 0 : true;

tools/bpf/bpftool/map.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -518,9 +518,8 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
518518

519519
jsonw_name(json_wtr, "pinned");
520520
jsonw_start_array(json_wtr);
521-
hashmap__for_each_key_entry(map_table, entry,
522-
u32_as_hash_field(info->id))
523-
jsonw_string(json_wtr, entry->value);
521+
hashmap__for_each_key_entry(map_table, entry, info->id)
522+
jsonw_string(json_wtr, entry->pvalue);
524523
jsonw_end_array(json_wtr);
525524
}
526525

@@ -595,9 +594,8 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
595594
if (!hashmap__empty(map_table)) {
596595
struct hashmap_entry *entry;
597596

598-
hashmap__for_each_key_entry(map_table, entry,
599-
u32_as_hash_field(info->id))
600-
printf("\n\tpinned %s", (char *)entry->value);
597+
hashmap__for_each_key_entry(map_table, entry, info->id)
598+
printf("\n\tpinned %s", (char *)entry->pvalue);
601599
}
602600

603601
if (frozen_str) {

tools/bpf/bpftool/pids.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ static void add_ref(struct hashmap *map, struct pid_iter_entry *e)
3636
int err, i;
3737
void *tmp;
3838

39-
hashmap__for_each_key_entry(map, entry, u32_as_hash_field(e->id)) {
40-
refs = entry->value;
39+
hashmap__for_each_key_entry(map, entry, e->id) {
40+
refs = entry->pvalue;
4141

4242
for (i = 0; i < refs->ref_cnt; i++) {
4343
if (refs->refs[i].pid == e->pid)
@@ -81,7 +81,7 @@ static void add_ref(struct hashmap *map, struct pid_iter_entry *e)
8181
refs->has_bpf_cookie = e->has_bpf_cookie;
8282
refs->bpf_cookie = e->bpf_cookie;
8383

84-
err = hashmap__append(map, u32_as_hash_field(e->id), refs);
84+
err = hashmap__append(map, e->id, refs);
8585
if (err)
8686
p_err("failed to append entry to hashmap for ID %u: %s",
8787
e->id, strerror(errno));
@@ -183,7 +183,7 @@ void delete_obj_refs_table(struct hashmap *map)
183183
return;
184184

185185
hashmap__for_each_entry(map, entry, bkt) {
186-
struct obj_refs *refs = entry->value;
186+
struct obj_refs *refs = entry->pvalue;
187187

188188
free(refs->refs);
189189
free(refs);
@@ -200,8 +200,8 @@ void emit_obj_refs_json(struct hashmap *map, __u32 id,
200200
if (hashmap__empty(map))
201201
return;
202202

203-
hashmap__for_each_key_entry(map, entry, u32_as_hash_field(id)) {
204-
struct obj_refs *refs = entry->value;
203+
hashmap__for_each_key_entry(map, entry, id) {
204+
struct obj_refs *refs = entry->pvalue;
205205
int i;
206206

207207
if (refs->ref_cnt == 0)
@@ -232,8 +232,8 @@ void emit_obj_refs_plain(struct hashmap *map, __u32 id, const char *prefix)
232232
if (hashmap__empty(map))
233233
return;
234234

235-
hashmap__for_each_key_entry(map, entry, u32_as_hash_field(id)) {
236-
struct obj_refs *refs = entry->value;
235+
hashmap__for_each_key_entry(map, entry, id) {
236+
struct obj_refs *refs = entry->pvalue;
237237
int i;
238238

239239
if (refs->ref_cnt == 0)

tools/bpf/bpftool/prog.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -486,9 +486,8 @@ static void print_prog_json(struct bpf_prog_info *info, int fd)
486486

487487
jsonw_name(json_wtr, "pinned");
488488
jsonw_start_array(json_wtr);
489-
hashmap__for_each_key_entry(prog_table, entry,
490-
u32_as_hash_field(info->id))
491-
jsonw_string(json_wtr, entry->value);
489+
hashmap__for_each_key_entry(prog_table, entry, info->id)
490+
jsonw_string(json_wtr, entry->pvalue);
492491
jsonw_end_array(json_wtr);
493492
}
494493

@@ -561,9 +560,8 @@ static void print_prog_plain(struct bpf_prog_info *info, int fd)
561560
if (!hashmap__empty(prog_table)) {
562561
struct hashmap_entry *entry;
563562

564-
hashmap__for_each_key_entry(prog_table, entry,
565-
u32_as_hash_field(info->id))
566-
printf("\n\tpinned %s", (char *)entry->value);
563+
hashmap__for_each_key_entry(prog_table, entry, info->id)
564+
printf("\n\tpinned %s", (char *)entry->pvalue);
567565
}
568566

569567
if (info->btf_id)

0 commit comments

Comments
 (0)