* [PATCH bpf-next 0/2] introduce BPF_F_SHARE_PE @ 2020-09-29 8:47 Song Liu 2020-09-29 8:47 ` [PATCH bpf-next 1/2] bpf: introduce BPF_F_SHARE_PE for perf event array Song Liu 2020-09-29 8:47 ` [PATCH bpf-next 2/2] selftests/bpf: add tests for BPF_F_SHARE_PE Song Liu 0 siblings, 2 replies; 9+ messages in thread From: Song Liu @ 2020-09-29 8:47 UTC (permalink / raw) To: netdev, bpf; +Cc: kernel-team, ast, daniel, john.fastabend, kpsingh, Song Liu This set introduces BPF_F_SHARE_PE to perf event array for better sharing of perf event. By default, perf event array removes the perf event when the map fd used to add the event is closed. With BPF_F_SHARE_PE set, however, the perf event will stay in the array until it is removed, or the map is closed. Song Liu (2): bpf: introduce BPF_F_SHARE_PE for perf event array selftests/bpf: add tests for BPF_F_SHARE_PE include/uapi/linux/bpf.h | 3 + kernel/bpf/arraymap.c | 31 ++++++++- tools/include/uapi/linux/bpf.h | 3 + .../bpf/prog_tests/perf_event_share.c | 68 +++++++++++++++++++ .../bpf/progs/test_perf_event_share.c | 44 ++++++++++++ 5 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/perf_event_share.c create mode 100644 tools/testing/selftests/bpf/progs/test_perf_event_share.c -- 2.24.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH bpf-next 1/2] bpf: introduce BPF_F_SHARE_PE for perf event array 2020-09-29 8:47 [PATCH bpf-next 0/2] introduce BPF_F_SHARE_PE Song Liu @ 2020-09-29 8:47 ` Song Liu 2020-09-29 14:02 ` Daniel Borkmann 2020-09-29 8:47 ` [PATCH bpf-next 2/2] selftests/bpf: add tests for BPF_F_SHARE_PE Song Liu 1 sibling, 1 reply; 9+ messages in thread From: Song Liu @ 2020-09-29 8:47 UTC (permalink / raw) To: netdev, bpf; +Cc: kernel-team, ast, daniel, john.fastabend, kpsingh, Song Liu Currently, perf event in perf event array is removed from the array when the map fd used to add the event is closed. This behavior makes it difficult to the share perf events with perf event array. Introduce perf event map that keeps the perf event open with a new flag BPF_F_SHARE_PE. With this flag set, perf events in the array are not removed when the original map fd is closed. Instead, the perf event will stay in the map until 1) it is explicitly removed from the array; or 2) the array is freed. Signed-off-by: Song Liu <songliubraving@fb.com> --- include/uapi/linux/bpf.h | 3 +++ kernel/bpf/arraymap.c | 31 +++++++++++++++++++++++++++++-- tools/include/uapi/linux/bpf.h | 3 +++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 82522f05c0213..74f7a09e9d1e3 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -414,6 +414,9 @@ enum { /* Enable memory-mapping BPF map */ BPF_F_MMAPABLE = (1U << 10), + +/* Share perf_event among processes */ + BPF_F_SHARE_PE = (1U << 11), }; /* Flags for BPF_PROG_QUERY. */ diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index e5fd31268ae02..4938ff183d846 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -15,7 +15,7 @@ #include "map_in_map.h" #define ARRAY_CREATE_FLAG_MASK \ - (BPF_F_NUMA_NODE | BPF_F_MMAPABLE | BPF_F_ACCESS_MASK) + (BPF_F_NUMA_NODE | BPF_F_MMAPABLE | BPF_F_ACCESS_MASK | BPF_F_SHARE_PE) static void bpf_array_free_percpu(struct bpf_array *array) { @@ -64,6 +64,10 @@ int array_map_alloc_check(union bpf_attr *attr) attr->map_flags & BPF_F_MMAPABLE) return -EINVAL; + if (attr->map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY && + attr->map_flags & BPF_F_SHARE_PE) + return -EINVAL; + if (attr->value_size > KMALLOC_MAX_SIZE) /* if value_size is bigger, the user space won't be able to * access the elements. @@ -778,6 +782,26 @@ static int fd_array_map_delete_elem(struct bpf_map *map, void *key) } } +static void perf_event_fd_array_map_free(struct bpf_map *map) +{ + struct bpf_event_entry *ee; + struct bpf_array *array; + int i; + + if ((map->map_flags & BPF_F_SHARE_PE) == 0) { + fd_array_map_free(map); + return; + } + + array = container_of(map, struct bpf_array, map); + for (i = 0; i < array->map.max_entries; i++) { + ee = READ_ONCE(array->ptrs[i]); + if (ee) + fd_array_map_delete_elem(map, &i); + } + bpf_map_area_free(array); +} + static void *prog_fd_array_get_ptr(struct bpf_map *map, struct file *map_file, int fd) { @@ -1134,6 +1158,9 @@ static void perf_event_fd_array_release(struct bpf_map *map, struct bpf_event_entry *ee; int i; + if (map->map_flags & BPF_F_SHARE_PE) + return; + rcu_read_lock(); for (i = 0; i < array->map.max_entries; i++) { ee = READ_ONCE(array->ptrs[i]); @@ -1148,7 +1175,7 @@ const struct bpf_map_ops perf_event_array_map_ops = { .map_meta_equal = bpf_map_meta_equal, .map_alloc_check = fd_array_map_alloc_check, .map_alloc = array_map_alloc, - .map_free = fd_array_map_free, + .map_free = perf_event_fd_array_map_free, .map_get_next_key = array_map_get_next_key, .map_lookup_elem = fd_array_map_lookup_elem, .map_delete_elem = fd_array_map_delete_elem, diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 82522f05c0213..74f7a09e9d1e3 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -414,6 +414,9 @@ enum { /* Enable memory-mapping BPF map */ BPF_F_MMAPABLE = (1U << 10), + +/* Share perf_event among processes */ + BPF_F_SHARE_PE = (1U << 11), }; /* Flags for BPF_PROG_QUERY. */ -- 2.24.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: introduce BPF_F_SHARE_PE for perf event array 2020-09-29 8:47 ` [PATCH bpf-next 1/2] bpf: introduce BPF_F_SHARE_PE for perf event array Song Liu @ 2020-09-29 14:02 ` Daniel Borkmann 2020-09-29 19:00 ` Alexei Starovoitov 0 siblings, 1 reply; 9+ messages in thread From: Daniel Borkmann @ 2020-09-29 14:02 UTC (permalink / raw) To: Song Liu, netdev, bpf; +Cc: kernel-team, ast, john.fastabend, kpsingh On 9/29/20 10:47 AM, Song Liu wrote: > Currently, perf event in perf event array is removed from the array when > the map fd used to add the event is closed. This behavior makes it > difficult to the share perf events with perf event array. > > Introduce perf event map that keeps the perf event open with a new flag > BPF_F_SHARE_PE. With this flag set, perf events in the array are not > removed when the original map fd is closed. Instead, the perf event will > stay in the map until 1) it is explicitly removed from the array; or 2) > the array is freed. > > Signed-off-by: Song Liu <songliubraving@fb.com> > --- > include/uapi/linux/bpf.h | 3 +++ > kernel/bpf/arraymap.c | 31 +++++++++++++++++++++++++++++-- > tools/include/uapi/linux/bpf.h | 3 +++ > 3 files changed, 35 insertions(+), 2 deletions(-) > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h > index 82522f05c0213..74f7a09e9d1e3 100644 > --- a/include/uapi/linux/bpf.h > +++ b/include/uapi/linux/bpf.h > @@ -414,6 +414,9 @@ enum { > > /* Enable memory-mapping BPF map */ > BPF_F_MMAPABLE = (1U << 10), > + > +/* Share perf_event among processes */ > + BPF_F_SHARE_PE = (1U << 11), nit but given UAPI: maybe name into something more self-descriptive like BPF_F_SHAREABLE_EVENT ? > }; > > /* Flags for BPF_PROG_QUERY. */ > diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c > index e5fd31268ae02..4938ff183d846 100644 > --- a/kernel/bpf/arraymap.c > +++ b/kernel/bpf/arraymap.c > @@ -15,7 +15,7 @@ > #include "map_in_map.h" > > #define ARRAY_CREATE_FLAG_MASK \ > - (BPF_F_NUMA_NODE | BPF_F_MMAPABLE | BPF_F_ACCESS_MASK) > + (BPF_F_NUMA_NODE | BPF_F_MMAPABLE | BPF_F_ACCESS_MASK | BPF_F_SHARE_PE) > > static void bpf_array_free_percpu(struct bpf_array *array) > { > @@ -64,6 +64,10 @@ int array_map_alloc_check(union bpf_attr *attr) > attr->map_flags & BPF_F_MMAPABLE) > return -EINVAL; > > + if (attr->map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY && > + attr->map_flags & BPF_F_SHARE_PE) > + return -EINVAL; > + > if (attr->value_size > KMALLOC_MAX_SIZE) > /* if value_size is bigger, the user space won't be able to > * access the elements. > @@ -778,6 +782,26 @@ static int fd_array_map_delete_elem(struct bpf_map *map, void *key) > } > } > > +static void perf_event_fd_array_map_free(struct bpf_map *map) > +{ > + struct bpf_event_entry *ee; > + struct bpf_array *array; > + int i; > + > + if ((map->map_flags & BPF_F_SHARE_PE) == 0) { > + fd_array_map_free(map); > + return; > + } > + > + array = container_of(map, struct bpf_array, map); > + for (i = 0; i < array->map.max_entries; i++) { > + ee = READ_ONCE(array->ptrs[i]); > + if (ee) > + fd_array_map_delete_elem(map, &i); > + } > + bpf_map_area_free(array); Why not simplify into: if (map->map_flags & BPF_F_SHAREABLE_EVENT) bpf_fd_array_map_clear(map); fd_array_map_free(map); > +} > + > static void *prog_fd_array_get_ptr(struct bpf_map *map, > struct file *map_file, int fd) > { > @@ -1134,6 +1158,9 @@ static void perf_event_fd_array_release(struct bpf_map *map, > struct bpf_event_entry *ee; > int i; > > + if (map->map_flags & BPF_F_SHARE_PE) > + return; > + > rcu_read_lock(); > for (i = 0; i < array->map.max_entries; i++) { > ee = READ_ONCE(array->ptrs[i]); > @@ -1148,7 +1175,7 @@ const struct bpf_map_ops perf_event_array_map_ops = { > .map_meta_equal = bpf_map_meta_equal, > .map_alloc_check = fd_array_map_alloc_check, > .map_alloc = array_map_alloc, > - .map_free = fd_array_map_free, > + .map_free = perf_event_fd_array_map_free, > .map_get_next_key = array_map_get_next_key, > .map_lookup_elem = fd_array_map_lookup_elem, > .map_delete_elem = fd_array_map_delete_elem, > diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h > index 82522f05c0213..74f7a09e9d1e3 100644 > --- a/tools/include/uapi/linux/bpf.h > +++ b/tools/include/uapi/linux/bpf.h > @@ -414,6 +414,9 @@ enum { > > /* Enable memory-mapping BPF map */ > BPF_F_MMAPABLE = (1U << 10), > + > +/* Share perf_event among processes */ > + BPF_F_SHARE_PE = (1U << 11), > }; > > /* Flags for BPF_PROG_QUERY. */ > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: introduce BPF_F_SHARE_PE for perf event array 2020-09-29 14:02 ` Daniel Borkmann @ 2020-09-29 19:00 ` Alexei Starovoitov 2020-09-29 19:18 ` Daniel Borkmann 0 siblings, 1 reply; 9+ messages in thread From: Alexei Starovoitov @ 2020-09-29 19:00 UTC (permalink / raw) To: Daniel Borkmann Cc: Song Liu, netdev, bpf, kernel-team, ast, john.fastabend, kpsingh On Tue, Sep 29, 2020 at 04:02:10PM +0200, Daniel Borkmann wrote: > > + > > +/* Share perf_event among processes */ > > + BPF_F_SHARE_PE = (1U << 11), > > nit but given UAPI: maybe name into something more self-descriptive > like BPF_F_SHAREABLE_EVENT ? I'm not happy with either name. It's not about sharing and not really about perf event. I think the current behavior of perf_event_array is unusual and surprising. Sadly we cannot fix it without breaking user space, so flag is needed. How about BPF_F_STICKY_OBJECTS or BPF_F_PRESERVE_OBJECTS or the same with s/OBJECTS/FILES/ ? > > +static void perf_event_fd_array_map_free(struct bpf_map *map) > > +{ > > + struct bpf_event_entry *ee; > > + struct bpf_array *array; > > + int i; > > + > > + if ((map->map_flags & BPF_F_SHARE_PE) == 0) { > > + fd_array_map_free(map); > > + return; > > + } > > + > > + array = container_of(map, struct bpf_array, map); > > + for (i = 0; i < array->map.max_entries; i++) { > > + ee = READ_ONCE(array->ptrs[i]); > > + if (ee) > > + fd_array_map_delete_elem(map, &i); > > + } > > + bpf_map_area_free(array); > > Why not simplify into: > > if (map->map_flags & BPF_F_SHAREABLE_EVENT) > bpf_fd_array_map_clear(map); > fd_array_map_free(map); +1 > > +} > > + > > static void *prog_fd_array_get_ptr(struct bpf_map *map, > > struct file *map_file, int fd) > > { > > @@ -1134,6 +1158,9 @@ static void perf_event_fd_array_release(struct bpf_map *map, > > struct bpf_event_entry *ee; > > int i; add empty line pls. > > + if (map->map_flags & BPF_F_SHARE_PE) > > + return; > > + ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: introduce BPF_F_SHARE_PE for perf event array 2020-09-29 19:00 ` Alexei Starovoitov @ 2020-09-29 19:18 ` Daniel Borkmann 2020-09-29 19:28 ` Alexei Starovoitov 0 siblings, 1 reply; 9+ messages in thread From: Daniel Borkmann @ 2020-09-29 19:18 UTC (permalink / raw) To: Alexei Starovoitov Cc: Song Liu, netdev, bpf, kernel-team, ast, john.fastabend, kpsingh On 9/29/20 9:00 PM, Alexei Starovoitov wrote: > On Tue, Sep 29, 2020 at 04:02:10PM +0200, Daniel Borkmann wrote: >>> + >>> +/* Share perf_event among processes */ >>> + BPF_F_SHARE_PE = (1U << 11), >> >> nit but given UAPI: maybe name into something more self-descriptive >> like BPF_F_SHAREABLE_EVENT ? > > I'm not happy with either name. > It's not about sharing and not really about perf event. > I think the current behavior of perf_event_array is unusual and surprising. > Sadly we cannot fix it without breaking user space, so flag is needed. > How about BPF_F_STICKY_OBJECTS or BPF_F_PRESERVE_OBJECTS > or the same with s/OBJECTS/FILES/ ? Sounds good to me, BPF_F_PRESERVE_OBJECTS or _ENTRIES seems reasonable. >>> +static void perf_event_fd_array_map_free(struct bpf_map *map) >>> +{ >>> + struct bpf_event_entry *ee; >>> + struct bpf_array *array; >>> + int i; >>> + >>> + if ((map->map_flags & BPF_F_SHARE_PE) == 0) { >>> + fd_array_map_free(map); >>> + return; >>> + } >>> + >>> + array = container_of(map, struct bpf_array, map); >>> + for (i = 0; i < array->map.max_entries; i++) { >>> + ee = READ_ONCE(array->ptrs[i]); >>> + if (ee) >>> + fd_array_map_delete_elem(map, &i); >>> + } >>> + bpf_map_area_free(array); >> >> Why not simplify into: >> >> if (map->map_flags & BPF_F_SHAREABLE_EVENT) >> bpf_fd_array_map_clear(map); >> fd_array_map_free(map); > > +1 > >>> +} >>> + >>> static void *prog_fd_array_get_ptr(struct bpf_map *map, >>> struct file *map_file, int fd) >>> { >>> @@ -1134,6 +1158,9 @@ static void perf_event_fd_array_release(struct bpf_map *map, >>> struct bpf_event_entry *ee; >>> int i; > > add empty line pls. > >>> + if (map->map_flags & BPF_F_SHARE_PE) >>> + return; >>> + ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: introduce BPF_F_SHARE_PE for perf event array 2020-09-29 19:18 ` Daniel Borkmann @ 2020-09-29 19:28 ` Alexei Starovoitov 2020-09-29 21:08 ` Song Liu 0 siblings, 1 reply; 9+ messages in thread From: Alexei Starovoitov @ 2020-09-29 19:28 UTC (permalink / raw) To: Daniel Borkmann Cc: Song Liu, Network Development, bpf, Kernel Team, Alexei Starovoitov, John Fastabend, KP Singh On Tue, Sep 29, 2020 at 12:18 PM Daniel Borkmann <daniel@iogearbox.net> wrote: > > On 9/29/20 9:00 PM, Alexei Starovoitov wrote: > > On Tue, Sep 29, 2020 at 04:02:10PM +0200, Daniel Borkmann wrote: > >>> + > >>> +/* Share perf_event among processes */ > >>> + BPF_F_SHARE_PE = (1U << 11), > >> > >> nit but given UAPI: maybe name into something more self-descriptive > >> like BPF_F_SHAREABLE_EVENT ? > > > > I'm not happy with either name. > > It's not about sharing and not really about perf event. > > I think the current behavior of perf_event_array is unusual and surprising. > > Sadly we cannot fix it without breaking user space, so flag is needed. > > How about BPF_F_STICKY_OBJECTS or BPF_F_PRESERVE_OBJECTS > > or the same with s/OBJECTS/FILES/ ? > > Sounds good to me, BPF_F_PRESERVE_OBJECTS or _ENTRIES seems reasonable. May be BPF_F_PRESERVE_ELEMENTS? or _ELEMS ? I think we refer to map elements more often as elements instead of entries. But both _entries and _elems work for me. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: introduce BPF_F_SHARE_PE for perf event array 2020-09-29 19:28 ` Alexei Starovoitov @ 2020-09-29 21:08 ` Song Liu 0 siblings, 0 replies; 9+ messages in thread From: Song Liu @ 2020-09-29 21:08 UTC (permalink / raw) To: Alexei Starovoitov Cc: Daniel Borkmann, Network Development, bpf, Kernel Team, Alexei Starovoitov, John Fastabend, KP Singh > On Sep 29, 2020, at 12:28 PM, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote: > > On Tue, Sep 29, 2020 at 12:18 PM Daniel Borkmann <daniel@iogearbox.net> wrote: >> >> On 9/29/20 9:00 PM, Alexei Starovoitov wrote: >>> On Tue, Sep 29, 2020 at 04:02:10PM +0200, Daniel Borkmann wrote: >>>>> + >>>>> +/* Share perf_event among processes */ >>>>> + BPF_F_SHARE_PE = (1U << 11), >>>> >>>> nit but given UAPI: maybe name into something more self-descriptive >>>> like BPF_F_SHAREABLE_EVENT ? >>> >>> I'm not happy with either name. >>> It's not about sharing and not really about perf event. >>> I think the current behavior of perf_event_array is unusual and surprising. >>> Sadly we cannot fix it without breaking user space, so flag is needed. >>> How about BPF_F_STICKY_OBJECTS or BPF_F_PRESERVE_OBJECTS >>> or the same with s/OBJECTS/FILES/ ? >> >> Sounds good to me, BPF_F_PRESERVE_OBJECTS or _ENTRIES seems reasonable. > > May be BPF_F_PRESERVE_ELEMENTS? > or _ELEMS ? > I think we refer to map elements more often as elements instead of entries. > But both _entries and _elems work for me. BPF_F_PRESERVE_ELEMS sounds best to me. I will go ahead with it. Thanks, Song ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH bpf-next 2/2] selftests/bpf: add tests for BPF_F_SHARE_PE 2020-09-29 8:47 [PATCH bpf-next 0/2] introduce BPF_F_SHARE_PE Song Liu 2020-09-29 8:47 ` [PATCH bpf-next 1/2] bpf: introduce BPF_F_SHARE_PE for perf event array Song Liu @ 2020-09-29 8:47 ` Song Liu 2020-09-29 14:08 ` Daniel Borkmann 1 sibling, 1 reply; 9+ messages in thread From: Song Liu @ 2020-09-29 8:47 UTC (permalink / raw) To: netdev, bpf; +Cc: kernel-team, ast, daniel, john.fastabend, kpsingh, Song Liu Add tests for perf event array with and without BPF_F_SHARE_PE. Add a perf event to array via fd mfd. Without BPF_F_SHARE_PE, the perf event is removed when mfd is closed. With BPF_F_SHARE_PE, the perf event is removed when the map is freed. Signed-off-by: Song Liu <songliubraving@fb.com> --- .../bpf/prog_tests/perf_event_share.c | 68 +++++++++++++++++++ .../bpf/progs/test_perf_event_share.c | 44 ++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/perf_event_share.c create mode 100644 tools/testing/selftests/bpf/progs/test_perf_event_share.c diff --git a/tools/testing/selftests/bpf/prog_tests/perf_event_share.c b/tools/testing/selftests/bpf/prog_tests/perf_event_share.c new file mode 100644 index 0000000000000..a37cfdd047ea6 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/perf_event_share.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2019 Facebook */ +#include <test_progs.h> +#include <linux/bpf.h> +#include "test_perf_event_share.skel.h" + +static int duration; + +static void test_one_map(struct bpf_map *map, struct bpf_program *prog, + bool has_share_pe) +{ + int err, key = 0, pfd = -1, mfd = bpf_map__fd(map); + DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts); + struct perf_event_attr attr = { + .size = sizeof(struct perf_event_attr), + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_CPU_CLOCK, + }; + + pfd = syscall(__NR_perf_event_open, &attr, 0 /* pid */, + -1 /* cpu 0 */, -1 /* group id */, 0 /* flags */); + if (CHECK(pfd < 0, "perf_event_open", "failed\n")) + return; + + err = bpf_map_update_elem(mfd, &key, &pfd, BPF_ANY); + if (CHECK(err < 0, "bpf_map_update_elem", "failed\n")) + goto cleanup; + + err = bpf_prog_test_run_opts(bpf_program__fd(prog), &opts); + if (CHECK(err < 0, "bpf_prog_test_run_opts", "failed\n")) + goto cleanup; + if (CHECK(opts.retval != 0, "bpf_perf_event_read_value", + "failed with %d\n", opts.retval)) + goto cleanup; + + /* closing mfd, prog still holds a reference on map */ + close(mfd); + + err = bpf_prog_test_run_opts(bpf_program__fd(prog), &opts); + if (CHECK(err < 0, "bpf_prog_test_run_opts", "failed\n")) + goto cleanup; + + if (has_share_pe) { + CHECK(opts.retval != 0, "bpf_perf_event_read_value", + "failed with %d\n", opts.retval); + } else { + CHECK(opts.retval != -ENOENT, "bpf_perf_event_read_value", + "should have failed with %d, but got %d\n", -ENOENT, + opts.retval); + } + +cleanup: + close(pfd); +} + +void test_perf_event_share(void) +{ + struct test_perf_event_share *skel; + + skel = test_perf_event_share__open_and_load(); + if (CHECK(!skel, "skel_open", "failed to open skeleton\n")) + return; + + test_one_map(skel->maps.array_1, skel->progs.read_array_1, false); + test_one_map(skel->maps.array_2, skel->progs.read_array_2, true); + + test_perf_event_share__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/test_perf_event_share.c b/tools/testing/selftests/bpf/progs/test_perf_event_share.c new file mode 100644 index 0000000000000..005bfe375352f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_perf_event_share.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Facebook +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> + +struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(max_entries, 1); + __uint(key_size, sizeof(int)); + __uint(value_size, sizeof(int)); +} array_1 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(max_entries, 1); + __uint(key_size, sizeof(int)); + __uint(value_size, sizeof(int)); + __uint(map_flags, BPF_F_SHARE_PE); /* array_2 has BPF_F_SHARE_PE */ +} array_2 SEC(".maps"); + +SEC("raw_tp/sched_switch") +int BPF_PROG(read_array_1) +{ + struct bpf_perf_event_value val; + long ret; + + ret = bpf_perf_event_read_value(&array_1, 0, &val, sizeof(val)); + bpf_printk("read_array_1 returns %ld", ret); + return ret; +} + +SEC("raw_tp/task_rename") +int BPF_PROG(read_array_2) +{ + struct bpf_perf_event_value val; + long ret; + + ret = bpf_perf_event_read_value(&array_2, 0, &val, sizeof(val)); + bpf_printk("read_array_2 returns %ld", ret); + return ret; +} + +char LICENSE[] SEC("license") = "GPL"; -- 2.24.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH bpf-next 2/2] selftests/bpf: add tests for BPF_F_SHARE_PE 2020-09-29 8:47 ` [PATCH bpf-next 2/2] selftests/bpf: add tests for BPF_F_SHARE_PE Song Liu @ 2020-09-29 14:08 ` Daniel Borkmann 0 siblings, 0 replies; 9+ messages in thread From: Daniel Borkmann @ 2020-09-29 14:08 UTC (permalink / raw) To: Song Liu, netdev, bpf; +Cc: kernel-team, ast, john.fastabend, kpsingh On 9/29/20 10:47 AM, Song Liu wrote: > Add tests for perf event array with and without BPF_F_SHARE_PE. > > Add a perf event to array via fd mfd. Without BPF_F_SHARE_PE, the perf > event is removed when mfd is closed. With BPF_F_SHARE_PE, the perf event > is removed when the map is freed. > > Signed-off-by: Song Liu <songliubraving@fb.com> [...] > +static void test_one_map(struct bpf_map *map, struct bpf_program *prog, > + bool has_share_pe) > +{ > + int err, key = 0, pfd = -1, mfd = bpf_map__fd(map); > + DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts); > + struct perf_event_attr attr = { > + .size = sizeof(struct perf_event_attr), > + .type = PERF_TYPE_SOFTWARE, > + .config = PERF_COUNT_SW_CPU_CLOCK, > + }; > + > + pfd = syscall(__NR_perf_event_open, &attr, 0 /* pid */, > + -1 /* cpu 0 */, -1 /* group id */, 0 /* flags */); > + if (CHECK(pfd < 0, "perf_event_open", "failed\n")) > + return; > + > + err = bpf_map_update_elem(mfd, &key, &pfd, BPF_ANY); > + if (CHECK(err < 0, "bpf_map_update_elem", "failed\n")) > + goto cleanup; > + > + err = bpf_prog_test_run_opts(bpf_program__fd(prog), &opts); > + if (CHECK(err < 0, "bpf_prog_test_run_opts", "failed\n")) > + goto cleanup; > + if (CHECK(opts.retval != 0, "bpf_perf_event_read_value", > + "failed with %d\n", opts.retval)) > + goto cleanup; > + > + /* closing mfd, prog still holds a reference on map */ > + close(mfd); > + > + err = bpf_prog_test_run_opts(bpf_program__fd(prog), &opts); > + if (CHECK(err < 0, "bpf_prog_test_run_opts", "failed\n")) > + goto cleanup; > + > + if (has_share_pe) { > + CHECK(opts.retval != 0, "bpf_perf_event_read_value", > + "failed with %d\n", opts.retval); > + } else { > + CHECK(opts.retval != -ENOENT, "bpf_perf_event_read_value", > + "should have failed with %d, but got %d\n", -ENOENT, > + opts.retval); > + } > + > +cleanup: > + close(pfd); Why holding pfd until the end? The map should already hold a ref after update. So you should be able to just do ... err = bpf_map_update_elem(mfd, &key, &pfd, BPF_ANY); close(pfd); ... and simplify cleanup. > +} > + > +void test_perf_event_share(void) > +{ > + struct test_perf_event_share *skel; > + > + skel = test_perf_event_share__open_and_load(); > + if (CHECK(!skel, "skel_open", "failed to open skeleton\n")) > + return; > + > + test_one_map(skel->maps.array_1, skel->progs.read_array_1, false); > + test_one_map(skel->maps.array_2, skel->progs.read_array_2, true); > + > + test_perf_event_share__destroy(skel); > +} ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2020-09-29 21:08 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-09-29 8:47 [PATCH bpf-next 0/2] introduce BPF_F_SHARE_PE Song Liu 2020-09-29 8:47 ` [PATCH bpf-next 1/2] bpf: introduce BPF_F_SHARE_PE for perf event array Song Liu 2020-09-29 14:02 ` Daniel Borkmann 2020-09-29 19:00 ` Alexei Starovoitov 2020-09-29 19:18 ` Daniel Borkmann 2020-09-29 19:28 ` Alexei Starovoitov 2020-09-29 21:08 ` Song Liu 2020-09-29 8:47 ` [PATCH bpf-next 2/2] selftests/bpf: add tests for BPF_F_SHARE_PE Song Liu 2020-09-29 14:08 ` Daniel Borkmann
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).