From: Menglong Dong <menglong.dong@linux.dev>
To: Menglong Dong <menglong8.dong@gmail.com>,
Masami Hiramatsu <mhiramat@kernel.org>
Cc: rostedt@goodmis.org, mathieu.desnoyers@efficios.com,
jiang.biao@linux.dev, linux-kernel@vger.kernel.org,
linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org
Subject: Re: [PATCH v2 1/2] tracing: fprobe: optimization for entry only case
Date: Mon, 13 Oct 2025 09:20:42 +0800 [thread overview]
Message-ID: <2802160.mvXUDI8C0e@7950hx> (raw)
In-Reply-To: <20251012130711.0ea063ac467cb5833a81bd54@kernel.org>
On 2025/10/12 12:07, Masami Hiramatsu wrote:
> Hi Menglong,
>
> On Fri, 10 Oct 2025 11:38:46 +0800
> Menglong Dong <menglong8.dong@gmail.com> wrote:
>
> > For now, fgraph is used for the fprobe, even if we need trace the entry
> > only. However, the performance of ftrace is better than fgraph, and we
> > can use ftrace_ops for this case.
> >
> > Then performance of kprobe-multi increases from 54M to 69M. Before this
> > commit:
> >
> > $ ./benchs/run_bench_trigger.sh kprobe-multi
> > kprobe-multi : 54.663 ± 0.493M/s
> >
> > After this commit:
> >
> > $ ./benchs/run_bench_trigger.sh kprobe-multi
> > kprobe-multi : 69.447 ± 0.143M/s
> >
> > Mitigation is disable during the bench testing above.
> >
>
> Thanks for updating!
>
> This looks good to me. Just a nit comment below;
>
> [...]
> > @@ -379,11 +380,82 @@ static void fprobe_return(struct ftrace_graph_ret *trace,
> > NOKPROBE_SYMBOL(fprobe_return);
> >
> > static struct fgraph_ops fprobe_graph_ops = {
> > - .entryfunc = fprobe_entry,
> > + .entryfunc = fprobe_fgraph_entry,
> > .retfunc = fprobe_return,
> > };
> > static int fprobe_graph_active;
> >
> > +/* ftrace_ops callback, this processes fprobes which have only entry_handler. */
> > +static void fprobe_ftrace_entry(unsigned long ip, unsigned long parent_ip,
> > + struct ftrace_ops *ops, struct ftrace_regs *fregs)
> > +{
> > + struct fprobe_hlist_node *node;
> > + struct rhlist_head *head, *pos;
> > + struct fprobe *fp;
> > + int bit;
> > +
> > + bit = ftrace_test_recursion_trylock(ip, parent_ip);
> > + if (bit < 0)
> > + return;
> > +
>
> nit: We'd better to explain why we need this here too;
>
> /*
> * ftrace_test_recursion_trylock() disables preemption, but
> * rhltable_lookup() checks whether rcu_read_lcok is held.
> * So we take rcu_read_lock() here.
> */
It's very nice! I'll send a V3 now.
Thanks!
Menglong Dong
>
> > + rcu_read_lock();
> > + head = rhltable_lookup(&fprobe_ip_table, &ip, fprobe_rht_params);
> > +
> > + rhl_for_each_entry_rcu(node, pos, head, hlist) {
> > + if (node->addr != ip)
> > + break;
> > + fp = READ_ONCE(node->fp);
> > + if (unlikely(!fp || fprobe_disabled(fp) || fp->exit_handler))
> > + continue;
> > +
> > + if (fprobe_shared_with_kprobes(fp))
> > + __fprobe_kprobe_handler(ip, parent_ip, fp, fregs, NULL);
> > + else
> > + __fprobe_handler(ip, parent_ip, fp, fregs, NULL);
> > + }
> > + rcu_read_unlock();
> > + ftrace_test_recursion_unlock(bit);
> > +}
> > +NOKPROBE_SYMBOL(fprobe_ftrace_entry);
>
> Thank you,
>
> > +
> > +static struct ftrace_ops fprobe_ftrace_ops = {
> > + .func = fprobe_ftrace_entry,
> > + .flags = FTRACE_OPS_FL_SAVE_REGS,
> > +};
> > +static int fprobe_ftrace_active;
> > +
> > +static int fprobe_ftrace_add_ips(unsigned long *addrs, int num)
> > +{
> > + int ret;
> > +
> > + lockdep_assert_held(&fprobe_mutex);
> > +
> > + ret = ftrace_set_filter_ips(&fprobe_ftrace_ops, addrs, num, 0, 0);
> > + if (ret)
> > + return ret;
> > +
> > + if (!fprobe_ftrace_active) {
> > + ret = register_ftrace_function(&fprobe_ftrace_ops);
> > + if (ret) {
> > + ftrace_free_filter(&fprobe_ftrace_ops);
> > + return ret;
> > + }
> > + }
> > + fprobe_ftrace_active++;
> > + return 0;
> > +}
> > +
> > +static void fprobe_ftrace_remove_ips(unsigned long *addrs, int num)
> > +{
> > + lockdep_assert_held(&fprobe_mutex);
> > +
> > + fprobe_ftrace_active--;
> > + if (!fprobe_ftrace_active)
> > + unregister_ftrace_function(&fprobe_ftrace_ops);
> > + if (num)
> > + ftrace_set_filter_ips(&fprobe_ftrace_ops, addrs, num, 1, 0);
> > +}
> > +
> > /* Add @addrs to the ftrace filter and register fgraph if needed. */
> > static int fprobe_graph_add_ips(unsigned long *addrs, int num)
> > {
> > @@ -498,9 +570,12 @@ static int fprobe_module_callback(struct notifier_block *nb,
> > } while (node == ERR_PTR(-EAGAIN));
> > rhashtable_walk_exit(&iter);
> >
> > - if (alist.index > 0)
> > + if (alist.index > 0) {
> > ftrace_set_filter_ips(&fprobe_graph_ops.ops,
> > alist.addrs, alist.index, 1, 0);
> > + ftrace_set_filter_ips(&fprobe_ftrace_ops,
> > + alist.addrs, alist.index, 1, 0);
> > + }
> > mutex_unlock(&fprobe_mutex);
> >
> > kfree(alist.addrs);
> > @@ -733,7 +808,11 @@ int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num)
> > mutex_lock(&fprobe_mutex);
> >
> > hlist_array = fp->hlist_array;
> > - ret = fprobe_graph_add_ips(addrs, num);
> > + if (fp->exit_handler)
> > + ret = fprobe_graph_add_ips(addrs, num);
> > + else
> > + ret = fprobe_ftrace_add_ips(addrs, num);
> > +
> > if (!ret) {
> > add_fprobe_hash(fp);
> > for (i = 0; i < hlist_array->size; i++) {
> > @@ -829,7 +908,10 @@ int unregister_fprobe(struct fprobe *fp)
> > }
> > del_fprobe_hash(fp);
> >
> > - fprobe_graph_remove_ips(addrs, count);
> > + if (fp->exit_handler)
> > + fprobe_graph_remove_ips(addrs, count);
> > + else
> > + fprobe_ftrace_remove_ips(addrs, count);
> >
> > kfree_rcu(hlist_array, rcu);
> > fp->hlist_array = NULL;
>
>
>
next prev parent reply other threads:[~2025-10-13 1:21 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-10 3:38 [PATCH v2 0/2] tracing: fprobe: optimization for entry only case Menglong Dong
2025-10-10 3:38 ` [PATCH v2 1/2] " Menglong Dong
2025-10-12 4:07 ` Masami Hiramatsu
2025-10-13 1:20 ` Menglong Dong [this message]
2025-10-14 14:51 ` Masami Hiramatsu
2025-10-15 7:25 ` Menglong Dong
2025-10-10 3:38 ` [PATCH v2 2/2] lib/test_fprobe: add testcase for mixed fprobe Menglong Dong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2802160.mvXUDI8C0e@7950hx \
--to=menglong.dong@linux.dev \
--cc=bpf@vger.kernel.org \
--cc=jiang.biao@linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=menglong8.dong@gmail.com \
--cc=mhiramat@kernel.org \
--cc=rostedt@goodmis.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.