On 06/20, Andrii Nakryiko wrote:
> bpf_program__attach_perf_event allows to attach BPF program to existing
> perf event, providing most generic and most low-level way to attach BPF
> programs.
> 
> libbpf_perf_event_disable_and_close API is added to disable and close
> existing perf event by its FD.
> 
> Signed-off-by: Andrii Nakryiko <andr...@fb.com>
> ---
>  tools/lib/bpf/libbpf.c   | 41 ++++++++++++++++++++++++++++++++++++++++
>  tools/lib/bpf/libbpf.h   |  4 ++++
>  tools/lib/bpf/libbpf.map |  2 ++
>  3 files changed, 47 insertions(+)
> 
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 8ce3beba8551..2bb1fa008be3 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -32,6 +32,7 @@
>  #include <linux/limits.h>
>  #include <linux/perf_event.h>
>  #include <linux/ring_buffer.h>
> +#include <sys/ioctl.h>
>  #include <sys/stat.h>
>  #include <sys/types.h>
>  #include <sys/vfs.h>
> @@ -3928,6 +3929,46 @@ int bpf_prog_load_xattr(const struct 
> bpf_prog_load_attr *attr,
>       return 0;
>  }
>  
[..]
> +int libbpf_perf_event_disable_and_close(int pfd)
nit: why not call it libbpf_perf_event_detach[_and_close]?
It's usually attach/detach.

> +{
> +     int err;
> +
> +     if (pfd < 0)
> +             return 0;
> +
> +     err = ioctl(pfd, PERF_EVENT_IOC_DISABLE, 0);
> +     close(pfd);
> +     return err;
> +}
> +
> +int bpf_program__attach_perf_event(struct bpf_program *prog, int pfd)
> +{
> +     char errmsg[STRERR_BUFSIZE];
> +     int bpf_fd, err;
> +
> +     bpf_fd = bpf_program__fd(prog);
> +     if (bpf_fd < 0) {
> +             pr_warning("program '%s': can't attach before loaded\n",
> +                        bpf_program__title(prog, false));
> +             return -EINVAL;
> +     }
> +     if (ioctl(pfd, PERF_EVENT_IOC_SET_BPF, bpf_fd) < 0) {
> +             err = -errno;
> +             pr_warning("program '%s': failed to attach to pfd %d: %s\n",
> +                        bpf_program__title(prog, false), pfd,
> +                        libbpf_strerror_r(err, errmsg, sizeof(errmsg)));
> +             return err;
> +     }
> +     if (ioctl(pfd, PERF_EVENT_IOC_ENABLE, 0) < 0) {
> +             err = -errno;
> +             pr_warning("program '%s': failed to enable pfd %d: %s\n",
> +                        bpf_program__title(prog, false), pfd,
> +                        libbpf_strerror_r(err, errmsg, sizeof(errmsg)));
> +             return err;
> +     }
> +     return 0;
> +}
> +
>  enum bpf_perf_event_ret
>  bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t 
> page_size,
>                          void **copy_mem, size_t *copy_size,
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index d639f47e3110..76db1bbc0dac 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -165,6 +165,10 @@ LIBBPF_API int bpf_program__pin(struct bpf_program 
> *prog, const char *path);
>  LIBBPF_API int bpf_program__unpin(struct bpf_program *prog, const char 
> *path);
>  LIBBPF_API void bpf_program__unload(struct bpf_program *prog);
>  
> +LIBBPF_API int libbpf_perf_event_disable_and_close(int pfd);
> +LIBBPF_API int bpf_program__attach_perf_event(struct bpf_program *prog,
> +                                           int pfd);
> +
>  struct bpf_insn;
>  
>  /*
> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> index 2c6d835620d2..d27406982b5a 100644
> --- a/tools/lib/bpf/libbpf.map
> +++ b/tools/lib/bpf/libbpf.map
> @@ -172,5 +172,7 @@ LIBBPF_0.0.4 {
>               btf_dump__new;
>               btf__parse_elf;
>               bpf_object__load_xattr;
> +             bpf_program__attach_perf_event;
>               libbpf_num_possible_cpus;
> +             libbpf_perf_event_disable_and_close;
>  } LIBBPF_0.0.3;
> -- 
> 2.17.1
> 

Reply via email to