Re: [PATCHv2 bpf-next 09/11] bpf: Remove trace_in argument from __bpf_get_stack

Andrii Nakryiko <[email protected]>
Newsgroups org.kernel.vger.bpf
Message-ID <CAEf4BzYRzFH+n7Cj2jKpcG6LOZJMh7O38=R7MnoH2jFKxSG1Tg@mail.gmail.com>
On Wed, Jul 29, 2026 at 1:39 AM Jiri Olsa <[email protected]> wrote:
>
> Now with the new callchain_* helper functions we can process trace_in
> case directly in bpf_get_stack_pe function and remove it from
> __bpf_get_stack which makes things easier for preemption fix in
> following change.
>
> Signed-off-by: Jiri Olsa <[email protected]>
> ---
>  kernel/bpf/stackmap.c | 46 ++++++++++++++++++++++++++++++++-----------
>  1 file changed, 34 insertions(+), 12 deletions(-)
>
> diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
> index 875f530f3597..bdf48a7ad2e8 100644
> --- a/kernel/bpf/stackmap.c
> +++ b/kernel/bpf/stackmap.c
> @@ -783,7 +783,6 @@ static long callchain_finalize(void *buf, u32 size, u32 trace_nr, u32 elem_size,
>  }
>
>  static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
> -                           struct perf_callchain_entry *trace_in,
>                             void *buf, u32 size, u64 flags, bool may_fault)
>  {
>         bool user_build_id = flags & BPF_F_USER_BUILD_ID;
> @@ -822,10 +821,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
>         if (may_fault)
>                 rcu_read_lock(); /* need RCU for perf's callchain below */
>
> -       if (trace_in) {
> -               trace = trace_in;
> -               trace->nr = min_t(u32, trace->nr, max_depth);
> -       } else if (kernel && task) {
> +       if (kernel && task) {
>                 trace = get_callchain_entry_for_task(task, max_depth);
>         } else {
>                 trace = get_perf_callchain(regs, kernel, user, max_depth,
> @@ -856,7 +852,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
>  BPF_CALL_4(bpf_get_stack, struct pt_regs *, regs, void *, buf, u32, size,
>            u64, flags)
>  {
> -       return __bpf_get_stack(regs, NULL, NULL, buf, size, flags, false /* !may_fault */);
> +       return __bpf_get_stack(regs, NULL, buf, size, flags, false /* !may_fault */);
>  }
>
>  const struct bpf_func_proto bpf_get_stack_proto = {
> @@ -872,7 +868,7 @@ const struct bpf_func_proto bpf_get_stack_proto = {
>  BPF_CALL_4(bpf_get_stack_sleepable, struct pt_regs *, regs, void *, buf, u32, size,
>            u64, flags)
>  {
> -       return __bpf_get_stack(regs, NULL, NULL, buf, size, flags, true /* may_fault */);
> +       return __bpf_get_stack(regs, NULL, buf, size, flags, true /* may_fault */);
>  }
>
>  const struct bpf_func_proto bpf_get_stack_sleepable_proto = {
> @@ -896,7 +892,7 @@ static long __bpf_get_task_stack(struct task_struct *task, void *buf, u32 size,
>
>         regs = task_pt_regs(task);
>         if (regs)
> -               res = __bpf_get_stack(regs, task, NULL, buf, size, flags, may_fault);
> +               res = __bpf_get_stack(regs, task, buf, size, flags, may_fault);
>         put_task_stack(task);
>
>         return res;
> @@ -936,6 +932,33 @@ const struct bpf_func_proto bpf_get_task_stack_sleepable_proto = {
>         .arg4_type      = ARG_ANYTHING,
>  };
>
> +static int __bpf_get_stack_pe(struct perf_callchain_entry *trace, void *buf, u32 size,
> +                             u64 flags)
> +{
> +       bool user_build_id = flags & BPF_F_USER_BUILD_ID;
> +       u64 skip = flags & BPF_F_SKIP_FIELD_MASK;
> +       bool user = flags & BPF_F_USER_STACK;
> +       u32 elem_size, max_depth, nr_trace;
> +       bool kernel = !user;
> +
> +       if (kernel && user_build_id)
> +               return -EINVAL;
> +
> +       elem_size = user_build_id ? sizeof(struct bpf_stack_build_id) : sizeof(u64);
> +       if (unlikely(size % elem_size))
> +               return -EINVAL;
> +
> +       max_depth = stack_map_calculate_max_depth(size, elem_size, flags);
> +       trace->nr = min_t(u32, trace->nr, max_depth);
> +
> +       if (trace->nr < skip)
> +               return -EFAULT;
> +
> +       nr_trace = callchain_store(trace, buf, elem_size, flags);
> +       return callchain_finalize(buf, size, nr_trace, elem_size, user_build_id,
> +                                 user, false /* !may_fault */);
> +}
> +
>  BPF_CALL_4(bpf_get_stack_pe, struct bpf_perf_event_data_kern *, ctx,
>            void *, buf, u32, size, u64, flags)
>  {
> @@ -947,7 +970,7 @@ BPF_CALL_4(bpf_get_stack_pe, struct bpf_perf_event_data_kern *, ctx,
>         int err = -EINVAL;
>
>         if (!(event->attr.sample_type & PERF_SAMPLE_CALLCHAIN))
> -               return __bpf_get_stack(regs, NULL, NULL, buf, size, flags, false /* !may_fault */);
> +               return __bpf_get_stack(regs, NULL, buf, size, flags, false /* !may_fault */);
>
>         if (unlikely(flags & ~(BPF_F_SKIP_FIELD_MASK | BPF_F_USER_STACK |
>                                BPF_F_USER_BUILD_ID)))
> @@ -966,7 +989,7 @@ BPF_CALL_4(bpf_get_stack_pe, struct bpf_perf_event_data_kern *, ctx,
>
>         if (kernel) {
>                 trace->nr = nr_kernel;

this whole count_kernel_ip() logic above, why do we have it? I don't
think we can have combined user and kernel stack trace, so how can we
end up with PERF_CONTEXT_USER "ip" at all? I might be missing
something subtle here, but can you please check again if this whole
trace->nr calculation/override is even necessary.

> -               err = __bpf_get_stack(regs, NULL, trace, buf, size, flags, false /* !may_fault */);
> +               err = __bpf_get_stack_pe(trace, buf, size, flags);
>
>         } else { /* user */
>                 u64 skip = flags & BPF_F_SKIP_FIELD_MASK;
> @@ -974,9 +997,8 @@ BPF_CALL_4(bpf_get_stack_pe, struct bpf_perf_event_data_kern *, ctx,
>                 skip += nr_kernel;
>                 if (skip > BPF_F_SKIP_FIELD_MASK)
>                         goto clear;
> -
>                 flags = (flags & ~BPF_F_SKIP_FIELD_MASK) | skip;
> -               err = __bpf_get_stack(regs, NULL, trace, buf, size, flags, false /* !may_fault */);
> +               err = __bpf_get_stack_pe(trace, buf, size, flags);
>         }
>
>         /* restore nr */
> --
> 2.54.0
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.