diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2018-08-11 19:59:17 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-08-12 18:52:45 -0400 |
commit | e8d2bec0457962e8f348a9a3627b398f7fe5c5fc (patch) | |
tree | 9bda920c6a2940980aeb18a79b827b11e3f1cb0d /kernel/bpf/arraymap.c | |
parent | 9d6f417714c3aaf67b23ffdc1d2b036cce3ecc1c (diff) |
bpf: decouple btf from seq bpf fs dump and enable more maps
Commit a26ca7c982cb ("bpf: btf: Add pretty print support to
the basic arraymap") and 699c86d6ec21 ("bpf: btf: add pretty
print for hash/lru_hash maps") enabled support for BTF and
dumping via BPF fs for array and hash/lru map. However, both
can be decoupled from each other such that regular BPF maps
can be supported for attaching BTF key/value information,
while not all maps necessarily need to dump via map_seq_show_elem()
callback.
The basic sanity check which is a prerequisite for all maps
is that key/value size has to match in any case, and some maps
can have extra checks via map_check_btf() callback, e.g.
probing certain types or indicating no support in general. With
that we can also enable retrieving BTF info for per-cpu map
types and lpm.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Diffstat (limited to 'kernel/bpf/arraymap.c')
-rw-r--r-- | kernel/bpf/arraymap.c | 26 |
1 files changed, 12 insertions, 14 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index f6ca3e712831..0c17aab3ce5f 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c | |||
@@ -358,27 +358,20 @@ static void array_map_seq_show_elem(struct bpf_map *map, void *key, | |||
358 | rcu_read_unlock(); | 358 | rcu_read_unlock(); |
359 | } | 359 | } |
360 | 360 | ||
361 | static int array_map_check_btf(const struct bpf_map *map, const struct btf *btf, | 361 | static int array_map_check_btf(const struct bpf_map *map, |
362 | u32 btf_key_id, u32 btf_value_id) | 362 | const struct btf_type *key_type, |
363 | const struct btf_type *value_type) | ||
363 | { | 364 | { |
364 | const struct btf_type *key_type, *value_type; | ||
365 | u32 key_size, value_size; | ||
366 | u32 int_data; | 365 | u32 int_data; |
367 | 366 | ||
368 | key_type = btf_type_id_size(btf, &btf_key_id, &key_size); | 367 | if (BTF_INFO_KIND(key_type->info) != BTF_KIND_INT) |
369 | if (!key_type || BTF_INFO_KIND(key_type->info) != BTF_KIND_INT) | ||
370 | return -EINVAL; | 368 | return -EINVAL; |
371 | 369 | ||
372 | int_data = *(u32 *)(key_type + 1); | 370 | int_data = *(u32 *)(key_type + 1); |
373 | /* bpf array can only take a u32 key. This check makes | 371 | /* bpf array can only take a u32 key. This check makes sure |
374 | * sure that the btf matches the attr used during map_create. | 372 | * that the btf matches the attr used during map_create. |
375 | */ | 373 | */ |
376 | if (BTF_INT_BITS(int_data) != 32 || key_size != 4 || | 374 | if (BTF_INT_BITS(int_data) != 32 || BTF_INT_OFFSET(int_data)) |
377 | BTF_INT_OFFSET(int_data)) | ||
378 | return -EINVAL; | ||
379 | |||
380 | value_type = btf_type_id_size(btf, &btf_value_id, &value_size); | ||
381 | if (!value_type || value_size != map->value_size) | ||
382 | return -EINVAL; | 375 | return -EINVAL; |
383 | 376 | ||
384 | return 0; | 377 | return 0; |
@@ -405,6 +398,7 @@ const struct bpf_map_ops percpu_array_map_ops = { | |||
405 | .map_lookup_elem = percpu_array_map_lookup_elem, | 398 | .map_lookup_elem = percpu_array_map_lookup_elem, |
406 | .map_update_elem = array_map_update_elem, | 399 | .map_update_elem = array_map_update_elem, |
407 | .map_delete_elem = array_map_delete_elem, | 400 | .map_delete_elem = array_map_delete_elem, |
401 | .map_check_btf = array_map_check_btf, | ||
408 | }; | 402 | }; |
409 | 403 | ||
410 | static int fd_array_map_alloc_check(union bpf_attr *attr) | 404 | static int fd_array_map_alloc_check(union bpf_attr *attr) |
@@ -546,6 +540,7 @@ const struct bpf_map_ops prog_array_map_ops = { | |||
546 | .map_fd_put_ptr = prog_fd_array_put_ptr, | 540 | .map_fd_put_ptr = prog_fd_array_put_ptr, |
547 | .map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem, | 541 | .map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem, |
548 | .map_release_uref = bpf_fd_array_map_clear, | 542 | .map_release_uref = bpf_fd_array_map_clear, |
543 | .map_check_btf = map_check_no_btf, | ||
549 | }; | 544 | }; |
550 | 545 | ||
551 | static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file, | 546 | static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file, |
@@ -634,6 +629,7 @@ const struct bpf_map_ops perf_event_array_map_ops = { | |||
634 | .map_fd_get_ptr = perf_event_fd_array_get_ptr, | 629 | .map_fd_get_ptr = perf_event_fd_array_get_ptr, |
635 | .map_fd_put_ptr = perf_event_fd_array_put_ptr, | 630 | .map_fd_put_ptr = perf_event_fd_array_put_ptr, |
636 | .map_release = perf_event_fd_array_release, | 631 | .map_release = perf_event_fd_array_release, |
632 | .map_check_btf = map_check_no_btf, | ||
637 | }; | 633 | }; |
638 | 634 | ||
639 | #ifdef CONFIG_CGROUPS | 635 | #ifdef CONFIG_CGROUPS |
@@ -665,6 +661,7 @@ const struct bpf_map_ops cgroup_array_map_ops = { | |||
665 | .map_delete_elem = fd_array_map_delete_elem, | 661 | .map_delete_elem = fd_array_map_delete_elem, |
666 | .map_fd_get_ptr = cgroup_fd_array_get_ptr, | 662 | .map_fd_get_ptr = cgroup_fd_array_get_ptr, |
667 | .map_fd_put_ptr = cgroup_fd_array_put_ptr, | 663 | .map_fd_put_ptr = cgroup_fd_array_put_ptr, |
664 | .map_check_btf = map_check_no_btf, | ||
668 | }; | 665 | }; |
669 | #endif | 666 | #endif |
670 | 667 | ||
@@ -749,4 +746,5 @@ const struct bpf_map_ops array_of_maps_map_ops = { | |||
749 | .map_fd_put_ptr = bpf_map_fd_put_ptr, | 746 | .map_fd_put_ptr = bpf_map_fd_put_ptr, |
750 | .map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem, | 747 | .map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem, |
751 | .map_gen_lookup = array_of_map_gen_lookup, | 748 | .map_gen_lookup = array_of_map_gen_lookup, |
749 | .map_check_btf = map_check_no_btf, | ||
752 | }; | 750 | }; |