Re: [PATCH 7/8] ftrace: Add multi direct modify interface

From: Jiri Olsa
Date: Fri Oct 15 2021 - 08:05:35 EST


On Thu, Oct 14, 2021 at 04:28:19PM -0400, Steven Rostedt wrote:
> On Fri, 8 Oct 2021 11:13:35 +0200
> Jiri Olsa <jolsa@xxxxxxxxxx> wrote:
>
> > + /*
> > + * Shutdown the ops, change 'direct' pointer for each
> > + * ops entry in direct_functions hash and startup the
> > + * ops back again.
> > + *
> > + * Note there is no callback called for @ops object after
> > + * this ftrace_shutdown call until ftrace_startup is called
> > + * later on.
> > + */
> > + err = ftrace_shutdown(ops, 0);
> > + if (err)
> > + goto out_unlock;
>
> I believe I said before that we can do this by adding a stub ops that match
> all the functions with the direct ops being modified. This will cause the
> loop function to be called, which will call the direct function helper,
> which will then call the direct function that is found. That is, there is
> no "pause" in calling the direct callers. Either the old direct is called,
> or the new one. When the function returns, all are calling the new one.
>
> That is, instead of:
>
> [ Changing direct call from my_direct_1 to my_direct_2 ]
>
> <traced_func>:
> call my_direct_1
>
> ||||||||||||||||||||
> vvvvvvvvvvvvvvvvvvvv
>
> <traced_func>:
> nop
>
> ||||||||||||||||||||
> vvvvvvvvvvvvvvvvvvvv
>
> <traced_func>:
> call my_direct_2
>
>
> We have it do:
>
> <traced_func>:
> call my_direct_1
>
> ||||||||||||||||||||
> vvvvvvvvvvvvvvvvvvvv
>
> <traced_func>:
> call ftrace_caller
>
>
> <ftrace_caller>:
> [..]
> call ftrace_ops_list_func
>
>
> ftrace_ops_list_func()
> {
> ops->func() -> direct_helper -> set rax to my_direct_1 or my_direct_2
> }
>
> call rax (to either my_direct_1 or my_direct_2

nice! :) I did not see that as a problem and something that can be
done later, thanks for doing this

>
> ||||||||||||||||||||
> vvvvvvvvvvvvvvvvvvvv
>
> <traced_func>:
> call my_direct_2
>
>
> I did this on top of this patch:

ATM I'm bit stuck on the bpf side of this whole change, I'll test
it with my other changes when I unstuck myself ;-)

thanks,
jirka

>
> Signed-off-by: Steven Rostedt (VMware) <rostedt@xxxxxxxxxxx>
> ---
> kernel/trace/ftrace.c | 33 ++++++++++++++++++++-------------
> 1 file changed, 20 insertions(+), 13 deletions(-)
>
> diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
> index 30120342176e..7ad1e8ae5855 100644
> --- a/kernel/trace/ftrace.c
> +++ b/kernel/trace/ftrace.c
> @@ -5561,8 +5561,12 @@ EXPORT_SYMBOL_GPL(unregister_ftrace_direct_multi);
> */
> int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
> {
> - struct ftrace_hash *hash = ops->func_hash->filter_hash;
> + struct ftrace_hash *hash;
> struct ftrace_func_entry *entry, *iter;
> + static struct ftrace_ops tmp_ops = {
> + .func = ftrace_stub,
> + .flags = FTRACE_OPS_FL_STUB,
> + };
> int i, size;
> int err;
>
> @@ -5572,21 +5576,22 @@ int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
> return -EINVAL;
>
> mutex_lock(&direct_mutex);
> - mutex_lock(&ftrace_lock);
> +
> + /* Enable the tmp_ops to have the same functions as the direct ops */
> + ftrace_ops_init(&tmp_ops);
> + tmp_ops.func_hash = ops->func_hash;
> +
> + err = register_ftrace_function(&tmp_ops);
> + if (err)
> + goto out_direct;
>
> /*
> - * Shutdown the ops, change 'direct' pointer for each
> - * ops entry in direct_functions hash and startup the
> - * ops back again.
> - *
> - * Note there is no callback called for @ops object after
> - * this ftrace_shutdown call until ftrace_startup is called
> - * later on.
> + * Now the ftrace_ops_list_func() is called to do the direct callers.
> + * We can safely change the direct functions attached to each entry.
> */
> - err = ftrace_shutdown(ops, 0);
> - if (err)
> - goto out_unlock;
> + mutex_lock(&ftrace_lock);
>
> + hash = ops->func_hash->filter_hash;
> size = 1 << hash->size_bits;
> for (i = 0; i < size; i++) {
> hlist_for_each_entry(iter, &hash->buckets[i], hlist) {
> @@ -5597,10 +5602,12 @@ int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
> }
> }
>
> - err = ftrace_startup(ops, 0);
> + /* Removing the tmp_ops will add the updated direct callers to the functions */
> + unregister_ftrace_function(&tmp_ops);
>
> out_unlock:
> mutex_unlock(&ftrace_lock);
> + out_direct:
> mutex_unlock(&direct_mutex);
> return err;
> }
> --
> 2.31.1
>