mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
libbpf: Teach bpf_link_create() to fallback to bpf_raw_tracepoint_open()
Teach bpf_link_create() to fallback to bpf_raw_tracepoint_open() on older kernels for programs that are attachable through BPF_RAW_TRACEPOINT_OPEN. This makes bpf_link_create() more unified and convenient interface for creating bpf_link-based attachments. With this approach end users can just use bpf_link_create() for tp_btf/fentry/fexit/fmod_ret/lsm program attachments without needing to care about kernel support, as libbpf will handle this transparently. On the other hand, as newer features (like BPF cookie) are added to LINK_CREATE interface, they will be readily usable though the same bpf_link_create() API without any major refactoring from user's standpoint. bpf_program__attach_btf_id() is now using bpf_link_create() internally as well and will take advantaged of this unified interface when BPF cookie is added for fentry/fexit. Doing proactive feature detection of LINK_CREATE support for fentry/tp_btf/etc is quite involved. It requires parsing vmlinux BTF, determining some stable and guaranteed to be in all kernels versions target BTF type (either raw tracepoint or fentry target function), actually attaching this program and thus potentially affecting the performance of the host kernel briefly, etc. So instead we are taking much simpler "lazy" approach of falling back to bpf_raw_tracepoint_open() call only if initial LINK_CREATE command fails. For modern kernels this will mean zero added overhead, while older kernels will incur minimal overhead with a single fast-failing LINK_CREATE call. Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Kui-Feng Lee <kuifeng@fb.com> Link: https://lore.kernel.org/bpf/20220421033945.3602803-3-andrii@kernel.org
This commit is contained in:
parent
df86ca0d2f
commit
8462e0b46f
@ -817,7 +817,7 @@ int bpf_link_create(int prog_fd, int target_fd,
|
||||
{
|
||||
__u32 target_btf_id, iter_info_len;
|
||||
union bpf_attr attr;
|
||||
int fd;
|
||||
int fd, err;
|
||||
|
||||
if (!OPTS_VALID(opts, bpf_link_create_opts))
|
||||
return libbpf_err(-EINVAL);
|
||||
@ -870,7 +870,37 @@ int bpf_link_create(int prog_fd, int target_fd,
|
||||
}
|
||||
proceed:
|
||||
fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, sizeof(attr));
|
||||
return libbpf_err_errno(fd);
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
/* we'll get EINVAL if LINK_CREATE doesn't support attaching fentry
|
||||
* and other similar programs
|
||||
*/
|
||||
err = -errno;
|
||||
if (err != -EINVAL)
|
||||
return libbpf_err(err);
|
||||
|
||||
/* if user used features not supported by
|
||||
* BPF_RAW_TRACEPOINT_OPEN command, then just give up immediately
|
||||
*/
|
||||
if (attr.link_create.target_fd || attr.link_create.target_btf_id)
|
||||
return libbpf_err(err);
|
||||
if (!OPTS_ZEROED(opts, sz))
|
||||
return libbpf_err(err);
|
||||
|
||||
/* otherwise, for few select kinds of programs that can be
|
||||
* attached using BPF_RAW_TRACEPOINT_OPEN command, try that as
|
||||
* a fallback for older kernels
|
||||
*/
|
||||
switch (attach_type) {
|
||||
case BPF_TRACE_RAW_TP:
|
||||
case BPF_LSM_MAC:
|
||||
case BPF_TRACE_FENTRY:
|
||||
case BPF_TRACE_FEXIT:
|
||||
case BPF_MODIFY_RETURN:
|
||||
return bpf_raw_tracepoint_open(NULL, prog_fd);
|
||||
default:
|
||||
return libbpf_err(err);
|
||||
}
|
||||
}
|
||||
|
||||
int bpf_link_detach(int link_fd)
|
||||
|
@ -11260,7 +11260,8 @@ static struct bpf_link *bpf_program__attach_btf_id(const struct bpf_program *pro
|
||||
return libbpf_err_ptr(-ENOMEM);
|
||||
link->detach = &bpf_link__detach_fd;
|
||||
|
||||
pfd = bpf_raw_tracepoint_open(NULL, prog_fd);
|
||||
/* libbpf is smart enough to redirect to BPF_RAW_TRACEPOINT_OPEN on old kernels */
|
||||
pfd = bpf_link_create(prog_fd, 0, bpf_program__expected_attach_type(prog), NULL);
|
||||
if (pfd < 0) {
|
||||
pfd = -errno;
|
||||
free(link);
|
||||
|
Loading…
Reference in New Issue
Block a user