From: Roman Gushchin <roman.gushchin@linux.dev>
Introduce bpf_map__attach_struct_ops_opts(), an extended version of
bpf_map__attach_struct_ops(), which takes additional struct
bpf_struct_ops_opts argument.
struct bpf_struct_ops_opts has the relative_fd member, which allows
to pass an additional file descriptor argument. It can be used to
attach struct ops maps to cgroups.
Signed-off-by: Roman Gushchin <roman.gushchin@linux.dev>
---
tools/lib/bpf/bpf.c | 8 ++++++++
tools/lib/bpf/libbpf.c | 18 ++++++++++++++++--
tools/lib/bpf/libbpf.h | 14 ++++++++++++++
tools/lib/bpf/libbpf.map | 1 +
4 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 5846de364209..84a53c594f48 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -884,6 +884,14 @@ int bpf_link_create(int prog_fd, int target_fd,
if (!OPTS_ZEROED(opts, cgroup))
return libbpf_err(-EINVAL);
break;
+ case BPF_STRUCT_OPS:
+ relative_fd = OPTS_GET(opts, cgroup.relative_fd, 0);
+ attr.link_create.cgroup.relative_fd = relative_fd;
+ attr.link_create.cgroup.expected_revision =
+ OPTS_GET(opts, cgroup.expected_revision, 0);
+ if (!OPTS_ZEROED(opts, cgroup))
+ return libbpf_err(-EINVAL);
+ break;
default:
if (!OPTS_ZEROED(opts, flags))
return libbpf_err(-EINVAL);
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 0c8bf0b5cce4..70a00da54ff5 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -13462,12 +13462,19 @@ static int bpf_link__detach_struct_ops(struct bpf_link *link)
return close(link->fd);
}
-struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map)
+struct bpf_link *bpf_map__attach_struct_ops_opts(const struct bpf_map *map,
+ const struct bpf_struct_ops_opts *opts)
{
+ DECLARE_LIBBPF_OPTS(bpf_link_create_opts, link_opts);
struct bpf_link_struct_ops *link;
__u32 zero = 0;
int err, fd;
+ if (!OPTS_VALID(opts, bpf_struct_ops_opts)) {
+ pr_warn("map '%s': invalid opts\n", map->name);
+ return libbpf_err_ptr(-EINVAL);
+ }
+
if (!bpf_map__is_struct_ops(map)) {
pr_warn("map '%s': can't attach non-struct_ops map\n", map->name);
return libbpf_err_ptr(-EINVAL);
@@ -13503,7 +13510,9 @@ struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map)
return &link->link;
}
- fd = bpf_link_create(map->fd, 0, BPF_STRUCT_OPS, NULL);
+ link_opts.cgroup.relative_fd = OPTS_GET(opts, relative_fd, 0);
+
+ fd = bpf_link_create(map->fd, 0, BPF_STRUCT_OPS, &link_opts);
if (fd < 0) {
free(link);
return libbpf_err_ptr(fd);
@@ -13515,6 +13524,11 @@ struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map)
return &link->link;
}
+struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map)
+{
+ return bpf_map__attach_struct_ops_opts(map, NULL);
+}
+
/*
* Swap the back struct_ops of a link with a new struct_ops map.
*/
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index dfc37a615578..5aef44bcfcc2 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -920,6 +920,20 @@ bpf_program__attach_cgroup_opts(const struct bpf_program *prog, int cgroup_fd,
struct bpf_map;
LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map);
+
+struct bpf_struct_ops_opts {
+ /* size of this struct, for forward/backward compatibility */
+ size_t sz;
+ __u32 flags;
+ __u32 relative_fd;
+ __u64 expected_revision;
+ size_t :0;
+};
+#define bpf_struct_ops_opts__last_field expected_revision
+
+LIBBPF_API struct bpf_link *
+bpf_map__attach_struct_ops_opts(const struct bpf_map *map,
+ const struct bpf_struct_ops_opts *opts);
LIBBPF_API int bpf_link__update_map(struct bpf_link *link, const struct bpf_map *map);
struct bpf_iter_attach_opts {
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index d18fbcea7578..4779190c97b6 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -454,4 +454,5 @@ LIBBPF_1.7.0 {
bpf_prog_assoc_struct_ops;
bpf_program__assoc_struct_ops;
btf__permute;
+ bpf_map__attach_struct_ops_opts;
} LIBBPF_1.6.0;
--
2.43.0