mirror of
https://github.com/netdata/libbpf.git
synced 2026-03-23 01:39:06 +08:00
libbpf: Update a bpf_link with another struct_ops.
Introduce bpf_link__update_map(), which allows to atomically update underlying struct_ops implementation for given struct_ops BPF link. Also add old_map_fd to struct bpf_link_update_opts to handle BPF_F_REPLACE feature. Signed-off-by: Kui-Feng Lee <kuifeng@meta.com> Link: https://lore.kernel.org/r/20230323032405.3735486-7-kuifeng@meta.com Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
This commit is contained in:
committed by
Andrii Nakryiko
parent
055cbdcc9f
commit
e51cdaaca0
@@ -794,11 +794,17 @@ int bpf_link_update(int link_fd, int new_prog_fd,
|
||||
if (!OPTS_VALID(opts, bpf_link_update_opts))
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
if (OPTS_GET(opts, old_prog_fd, 0) && OPTS_GET(opts, old_map_fd, 0))
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
memset(&attr, 0, attr_sz);
|
||||
attr.link_update.link_fd = link_fd;
|
||||
attr.link_update.new_prog_fd = new_prog_fd;
|
||||
attr.link_update.flags = OPTS_GET(opts, flags, 0);
|
||||
attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
|
||||
if (OPTS_GET(opts, old_prog_fd, 0))
|
||||
attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
|
||||
else if (OPTS_GET(opts, old_map_fd, 0))
|
||||
attr.link_update.old_map_fd = OPTS_GET(opts, old_map_fd, 0);
|
||||
|
||||
ret = sys_bpf(BPF_LINK_UPDATE, &attr, attr_sz);
|
||||
return libbpf_err_errno(ret);
|
||||
|
||||
@@ -336,8 +336,9 @@ struct bpf_link_update_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
__u32 flags; /* extra flags */
|
||||
__u32 old_prog_fd; /* expected old program FD */
|
||||
__u32 old_map_fd; /* expected old map FD */
|
||||
};
|
||||
#define bpf_link_update_opts__last_field old_prog_fd
|
||||
#define bpf_link_update_opts__last_field old_map_fd
|
||||
|
||||
LIBBPF_API int bpf_link_update(int link_fd, int new_prog_fd,
|
||||
const struct bpf_link_update_opts *opts);
|
||||
|
||||
35
src/libbpf.c
35
src/libbpf.c
@@ -11677,6 +11677,41 @@ struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map)
|
||||
return &link->link;
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap the back struct_ops of a link with a new struct_ops map.
|
||||
*/
|
||||
int bpf_link__update_map(struct bpf_link *link, const struct bpf_map *map)
|
||||
{
|
||||
struct bpf_link_struct_ops *st_ops_link;
|
||||
__u32 zero = 0;
|
||||
int err;
|
||||
|
||||
if (!bpf_map__is_struct_ops(map) || map->fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
st_ops_link = container_of(link, struct bpf_link_struct_ops, link);
|
||||
/* Ensure the type of a link is correct */
|
||||
if (st_ops_link->map_fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
err = bpf_map_update_elem(map->fd, &zero, map->st_ops->kern_vdata, 0);
|
||||
/* It can be EBUSY if the map has been used to create or
|
||||
* update a link before. We don't allow updating the value of
|
||||
* a struct_ops once it is set. That ensures that the value
|
||||
* never changed. So, it is safe to skip EBUSY.
|
||||
*/
|
||||
if (err && err != -EBUSY)
|
||||
return err;
|
||||
|
||||
err = bpf_link_update(link->fd, map->fd, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
st_ops_link->map_fd = map->fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef enum bpf_perf_event_ret (*bpf_perf_event_print_t)(struct perf_event_header *hdr,
|
||||
void *private_data);
|
||||
|
||||
|
||||
@@ -719,6 +719,7 @@ bpf_program__attach_freplace(const struct bpf_program *prog,
|
||||
struct bpf_map;
|
||||
|
||||
LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map);
|
||||
LIBBPF_API int bpf_link__update_map(struct bpf_link *link, const struct bpf_map *map);
|
||||
|
||||
struct bpf_iter_attach_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
|
||||
@@ -386,6 +386,7 @@ LIBBPF_1.1.0 {
|
||||
LIBBPF_1.2.0 {
|
||||
global:
|
||||
bpf_btf_get_info_by_fd;
|
||||
bpf_link__update_map;
|
||||
bpf_link_get_info_by_fd;
|
||||
bpf_map_get_info_by_fd;
|
||||
bpf_prog_get_info_by_fd;
|
||||
|
||||
Reference in New Issue
Block a user