Commit 41788934 authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov

libbpf: Make perf_buffer__new() use OPTS-based interface

Add new variants of perf_buffer__new() and perf_buffer__new_raw() that
use OPTS-based options for future extensibility ([0]). Given all the
currently used API names are best fits, re-use them and use
___libbpf_override() approach and symbol versioning to preserve ABI and
source code compatibility. struct perf_buffer_opts and struct
perf_buffer_raw_opts are kept as well, but they are restructured such
that they are OPTS-based when used with new APIs. For struct
perf_buffer_raw_opts we keep few fields intact, so we have to also
preserve the memory location of them both when used as OPTS and for
legacy API variants. This is achieved with anonymous padding for OPTS
"incarnation" of the struct.  These pads can be eventually used for new
options.

  [0] Closes: https://github.com/libbpf/libbpf/issues/311Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211111053624.190580-6-andrii@kernel.org
parent 6084f5dc
...@@ -10578,11 +10578,18 @@ perf_buffer__open_cpu_buf(struct perf_buffer *pb, struct perf_event_attr *attr, ...@@ -10578,11 +10578,18 @@ perf_buffer__open_cpu_buf(struct perf_buffer *pb, struct perf_event_attr *attr,
static struct perf_buffer *__perf_buffer__new(int map_fd, size_t page_cnt, static struct perf_buffer *__perf_buffer__new(int map_fd, size_t page_cnt,
struct perf_buffer_params *p); struct perf_buffer_params *p);
struct perf_buffer *perf_buffer__new(int map_fd, size_t page_cnt, DEFAULT_VERSION(perf_buffer__new_v0_6_0, perf_buffer__new, LIBBPF_0.6.0)
const struct perf_buffer_opts *opts) struct perf_buffer *perf_buffer__new_v0_6_0(int map_fd, size_t page_cnt,
perf_buffer_sample_fn sample_cb,
perf_buffer_lost_fn lost_cb,
void *ctx,
const struct perf_buffer_opts *opts)
{ {
struct perf_buffer_params p = {}; struct perf_buffer_params p = {};
struct perf_event_attr attr = { 0, }; struct perf_event_attr attr = {};
if (!OPTS_VALID(opts, perf_buffer_opts))
return libbpf_err_ptr(-EINVAL);
attr.config = PERF_COUNT_SW_BPF_OUTPUT; attr.config = PERF_COUNT_SW_BPF_OUTPUT;
attr.type = PERF_TYPE_SOFTWARE; attr.type = PERF_TYPE_SOFTWARE;
...@@ -10591,29 +10598,62 @@ struct perf_buffer *perf_buffer__new(int map_fd, size_t page_cnt, ...@@ -10591,29 +10598,62 @@ struct perf_buffer *perf_buffer__new(int map_fd, size_t page_cnt,
attr.wakeup_events = 1; attr.wakeup_events = 1;
p.attr = &attr; p.attr = &attr;
p.sample_cb = opts ? opts->sample_cb : NULL; p.sample_cb = sample_cb;
p.lost_cb = opts ? opts->lost_cb : NULL; p.lost_cb = lost_cb;
p.ctx = opts ? opts->ctx : NULL; p.ctx = ctx;
return libbpf_ptr(__perf_buffer__new(map_fd, page_cnt, &p)); return libbpf_ptr(__perf_buffer__new(map_fd, page_cnt, &p));
} }
struct perf_buffer * COMPAT_VERSION(perf_buffer__new_deprecated, perf_buffer__new, LIBBPF_0.0.4)
perf_buffer__new_raw(int map_fd, size_t page_cnt, struct perf_buffer *perf_buffer__new_deprecated(int map_fd, size_t page_cnt,
const struct perf_buffer_raw_opts *opts) const struct perf_buffer_opts *opts)
{
return perf_buffer__new_v0_6_0(map_fd, page_cnt,
opts ? opts->sample_cb : NULL,
opts ? opts->lost_cb : NULL,
opts ? opts->ctx : NULL,
NULL);
}
DEFAULT_VERSION(perf_buffer__new_raw_v0_6_0, perf_buffer__new_raw, LIBBPF_0.6.0)
struct perf_buffer *perf_buffer__new_raw_v0_6_0(int map_fd, size_t page_cnt,
struct perf_event_attr *attr,
perf_buffer_event_fn event_cb, void *ctx,
const struct perf_buffer_raw_opts *opts)
{ {
struct perf_buffer_params p = {}; struct perf_buffer_params p = {};
p.attr = opts->attr; if (page_cnt == 0 || !attr)
p.event_cb = opts->event_cb; return libbpf_err_ptr(-EINVAL);
p.ctx = opts->ctx;
p.cpu_cnt = opts->cpu_cnt; if (!OPTS_VALID(opts, perf_buffer_raw_opts))
p.cpus = opts->cpus; return libbpf_err_ptr(-EINVAL);
p.map_keys = opts->map_keys;
p.attr = attr;
p.event_cb = event_cb;
p.ctx = ctx;
p.cpu_cnt = OPTS_GET(opts, cpu_cnt, 0);
p.cpus = OPTS_GET(opts, cpus, NULL);
p.map_keys = OPTS_GET(opts, map_keys, NULL);
return libbpf_ptr(__perf_buffer__new(map_fd, page_cnt, &p)); return libbpf_ptr(__perf_buffer__new(map_fd, page_cnt, &p));
} }
COMPAT_VERSION(perf_buffer__new_raw_deprecated, perf_buffer__new_raw, LIBBPF_0.0.4)
struct perf_buffer *perf_buffer__new_raw_deprecated(int map_fd, size_t page_cnt,
const struct perf_buffer_raw_opts *opts)
{
LIBBPF_OPTS(perf_buffer_raw_opts, inner_opts,
.cpu_cnt = opts->cpu_cnt,
.cpus = opts->cpus,
.map_keys = opts->map_keys,
);
return perf_buffer__new_raw_v0_6_0(map_fd, page_cnt, opts->attr,
opts->event_cb, opts->ctx, &inner_opts);
}
static struct perf_buffer *__perf_buffer__new(int map_fd, size_t page_cnt, static struct perf_buffer *__perf_buffer__new(int map_fd, size_t page_cnt,
struct perf_buffer_params *p) struct perf_buffer_params *p)
{ {
......
...@@ -778,18 +778,52 @@ typedef void (*perf_buffer_lost_fn)(void *ctx, int cpu, __u64 cnt); ...@@ -778,18 +778,52 @@ typedef void (*perf_buffer_lost_fn)(void *ctx, int cpu, __u64 cnt);
/* common use perf buffer options */ /* common use perf buffer options */
struct perf_buffer_opts { struct perf_buffer_opts {
/* if specified, sample_cb is called for each sample */ union {
perf_buffer_sample_fn sample_cb; size_t sz;
/* if specified, lost_cb is called for each batch of lost samples */ struct { /* DEPRECATED: will be removed in v1.0 */
perf_buffer_lost_fn lost_cb; /* if specified, sample_cb is called for each sample */
/* ctx is provided to sample_cb and lost_cb */ perf_buffer_sample_fn sample_cb;
void *ctx; /* if specified, lost_cb is called for each batch of lost samples */
perf_buffer_lost_fn lost_cb;
/* ctx is provided to sample_cb and lost_cb */
void *ctx;
};
};
}; };
#define perf_buffer_opts__last_field sz
/**
* @brief **perf_buffer__new()** creates BPF perfbuf manager for a specified
* BPF_PERF_EVENT_ARRAY map
* @param map_fd FD of BPF_PERF_EVENT_ARRAY BPF map that will be used by BPF
* code to send data over to user-space
* @param page_cnt number of memory pages allocated for each per-CPU buffer
* @param sample_cb function called on each received data record
* @param lost_cb function called when record loss has occurred
* @param ctx user-provided extra context passed into *sample_cb* and *lost_cb*
* @return a new instance of struct perf_buffer on success, NULL on error with
* *errno* containing an error code
*/
LIBBPF_API struct perf_buffer * LIBBPF_API struct perf_buffer *
perf_buffer__new(int map_fd, size_t page_cnt, perf_buffer__new(int map_fd, size_t page_cnt,
perf_buffer_sample_fn sample_cb, perf_buffer_lost_fn lost_cb, void *ctx,
const struct perf_buffer_opts *opts); const struct perf_buffer_opts *opts);
LIBBPF_API struct perf_buffer *
perf_buffer__new_v0_6_0(int map_fd, size_t page_cnt,
perf_buffer_sample_fn sample_cb, perf_buffer_lost_fn lost_cb, void *ctx,
const struct perf_buffer_opts *opts);
LIBBPF_API LIBBPF_DEPRECATED_SINCE(0, 7, "use new variant of perf_buffer__new() instead")
struct perf_buffer *perf_buffer__new_deprecated(int map_fd, size_t page_cnt,
const struct perf_buffer_opts *opts);
#define perf_buffer__new(...) ___libbpf_overload(___perf_buffer_new, __VA_ARGS__)
#define ___perf_buffer_new6(map_fd, page_cnt, sample_cb, lost_cb, ctx, opts) \
perf_buffer__new(map_fd, page_cnt, sample_cb, lost_cb, ctx, opts)
#define ___perf_buffer_new3(map_fd, page_cnt, opts) \
perf_buffer__new_deprecated(map_fd, page_cnt, opts)
enum bpf_perf_event_ret { enum bpf_perf_event_ret {
LIBBPF_PERF_EVENT_DONE = 0, LIBBPF_PERF_EVENT_DONE = 0,
LIBBPF_PERF_EVENT_ERROR = -1, LIBBPF_PERF_EVENT_ERROR = -1,
...@@ -803,12 +837,21 @@ typedef enum bpf_perf_event_ret ...@@ -803,12 +837,21 @@ typedef enum bpf_perf_event_ret
/* raw perf buffer options, giving most power and control */ /* raw perf buffer options, giving most power and control */
struct perf_buffer_raw_opts { struct perf_buffer_raw_opts {
/* perf event attrs passed directly into perf_event_open() */ union {
struct perf_event_attr *attr; struct {
/* raw event callback */ size_t sz;
perf_buffer_event_fn event_cb; long :0;
/* ctx is provided to event_cb */ long :0;
void *ctx; };
struct { /* DEPRECATED: will be removed in v1.0 */
/* perf event attrs passed directly into perf_event_open() */
struct perf_event_attr *attr;
/* raw event callback */
perf_buffer_event_fn event_cb;
/* ctx is provided to event_cb */
void *ctx;
};
};
/* if cpu_cnt == 0, open all on all possible CPUs (up to the number of /* if cpu_cnt == 0, open all on all possible CPUs (up to the number of
* max_entries of given PERF_EVENT_ARRAY map) * max_entries of given PERF_EVENT_ARRAY map)
*/ */
...@@ -818,11 +861,28 @@ struct perf_buffer_raw_opts { ...@@ -818,11 +861,28 @@ struct perf_buffer_raw_opts {
/* if cpu_cnt > 0, map_keys specify map keys to set per-CPU FDs for */ /* if cpu_cnt > 0, map_keys specify map keys to set per-CPU FDs for */
int *map_keys; int *map_keys;
}; };
#define perf_buffer_raw_opts__last_field map_keys
LIBBPF_API struct perf_buffer * LIBBPF_API struct perf_buffer *
perf_buffer__new_raw(int map_fd, size_t page_cnt, perf_buffer__new_raw(int map_fd, size_t page_cnt, struct perf_event_attr *attr,
perf_buffer_event_fn event_cb, void *ctx,
const struct perf_buffer_raw_opts *opts); const struct perf_buffer_raw_opts *opts);
LIBBPF_API struct perf_buffer *
perf_buffer__new_raw_v0_6_0(int map_fd, size_t page_cnt, struct perf_event_attr *attr,
perf_buffer_event_fn event_cb, void *ctx,
const struct perf_buffer_raw_opts *opts);
LIBBPF_API LIBBPF_DEPRECATED_SINCE(0, 7, "use new variant of perf_buffer__new_raw() instead")
struct perf_buffer *perf_buffer__new_raw_deprecated(int map_fd, size_t page_cnt,
const struct perf_buffer_raw_opts *opts);
#define perf_buffer__new_raw(...) ___libbpf_overload(___perf_buffer_new_raw, __VA_ARGS__)
#define ___perf_buffer_new_raw6(map_fd, page_cnt, attr, event_cb, ctx, opts) \
perf_buffer__new_raw(map_fd, page_cnt, attr, event_cb, ctx, opts)
#define ___perf_buffer_new_raw3(map_fd, page_cnt, opts) \
perf_buffer__new_raw_deprecated(map_fd, page_cnt, opts)
LIBBPF_API void perf_buffer__free(struct perf_buffer *pb); LIBBPF_API void perf_buffer__free(struct perf_buffer *pb);
LIBBPF_API int perf_buffer__epoll_fd(const struct perf_buffer *pb); LIBBPF_API int perf_buffer__epoll_fd(const struct perf_buffer *pb);
LIBBPF_API int perf_buffer__poll(struct perf_buffer *pb, int timeout_ms); LIBBPF_API int perf_buffer__poll(struct perf_buffer *pb, int timeout_ms);
......
...@@ -409,4 +409,8 @@ LIBBPF_0.6.0 { ...@@ -409,4 +409,8 @@ LIBBPF_0.6.0 {
btf__type_cnt; btf__type_cnt;
btf_dump__new; btf_dump__new;
btf_dump__new_deprecated; btf_dump__new_deprecated;
perf_buffer__new;
perf_buffer__new_deprecated;
perf_buffer__new_raw;
perf_buffer__new_raw_deprecated;
} LIBBPF_0.5.0; } LIBBPF_0.5.0;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment