[PATCH bpf-next v4 5/6] libbpf: Add log_opts support for bpf_link_create

From: Leon Hwang

Date: Sat Oct 24 2026 - 11:37:53 EST


Since the iter_info and iter_info_len in struct bpf_link_create_opts are
legacy, reuse the slot of iter_info to place log_opts.

When adding log_opts support for iter link_create in the future, we will
move the iter_info and iter_info_len to the last union, see below. And,
keep the backward compatibility meanwhile, that uses iter_info if
iter_info_len is set.

struct bpf_link_create_opts {
/* ... */
union {
/* ... */
strut {
struct bpf_iter_link_info *info;
__u32 len;
} iter;
};
};

Signed-off-by: Leon Hwang <leon.hwang@xxxxxxxxx>
---
tools/lib/bpf/bpf.c | 20 +++++++++++++++++---
tools/lib/bpf/bpf.h | 5 ++++-
2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 9a2107d4f6d8..00efa90a6ed9 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -794,6 +794,8 @@ int bpf_link_create(int prog_fd, int target_fd,
{
const size_t attr_sz = offsetofend(union bpf_attr, link_create);
__u32 target_btf_id, iter_info_len, relative_id;
+ union bpf_iter_link_info *iter_info = NULL;
+ struct bpf_log_opts *log_opts = NULL;
int fd, err, relative_fd;
union bpf_attr attr;

@@ -803,6 +805,14 @@ int bpf_link_create(int prog_fd, int target_fd,
iter_info_len = OPTS_GET(opts, iter_info_len, 0);
target_btf_id = OPTS_GET(opts, target_btf_id, 0);

+ if (iter_info_len && attach_type != BPF_TRACE_ITER)
+ return libbpf_err(-EINVAL);
+
+ if (iter_info_len)
+ iter_info = OPTS_GET(opts, iter_info, (void *)0);
+ else
+ log_opts = OPTS_GET(opts, log_opts, (void *)0);
+
/* validate we don't have unexpected combinations of non-zero fields */
if (iter_info_len || target_btf_id) {
if (iter_info_len && target_btf_id)
@@ -824,7 +834,7 @@ int bpf_link_create(int prog_fd, int target_fd,

switch (attach_type) {
case BPF_TRACE_ITER:
- attr.link_create.iter_info = ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0));
+ attr.link_create.iter_info = ptr_to_u64(iter_info);
attr.link_create.iter_info_len = iter_info_len;
break;
case BPF_PERF_EVENT:
@@ -960,12 +970,12 @@ int bpf_link_create(int prog_fd, int target_fd,
return libbpf_err(-EINVAL);
break;
default:
- if (!OPTS_ZEROED(opts, flags))
+ if (!OPTS_ZEROED(opts, iter_info_len))
return libbpf_err(-EINVAL);
break;
}
proceed:
- fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, attr_sz);
+ fd = __sys_bpf_fd(&attr, attr_sz, BPF_LINK_CREATE, log_opts);
if (fd >= 0)
return fd;
/* we'll get EINVAL if LINK_CREATE doesn't support attaching fentry
@@ -975,6 +985,10 @@ int bpf_link_create(int prog_fd, int target_fd,
if (err != -EINVAL)
return libbpf_err(err);

+ /* bpf_raw_tracepoint_open() does not support log_opts */
+ if (log_opts)
+ return libbpf_err(err);
+
/* if user used features not supported by
* BPF_RAW_TRACEPOINT_OPEN command, then just give up immediately
*/
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 826d9cc9ab65..fe3b7fd8512b 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -422,7 +422,10 @@ union bpf_iter_link_info; /* defined in up-to-date linux/bpf.h */
struct bpf_link_create_opts {
size_t sz; /* size of this struct for forward/backward compatibility */
__u32 flags;
- union bpf_iter_link_info *iter_info;
+ union {
+ union bpf_iter_link_info *iter_info;
+ struct bpf_log_opts *log_opts;
+ };
__u32 iter_info_len;
__u32 target_btf_id;
union {
--
2.55.0