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 <[email protected]>
---
 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 aea534764dfe..38dcb31e8c0e 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(BPF_LINK_CREATE, &attr, attr_sz, 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


Reply via email to