ftrace: Let unregister_ftrace_direct_multi() call ftrace_free_filter()
authorFlorent Revest <revest@chromium.org>
Tue, 21 Mar 2023 14:04:18 +0000 (15:04 +0100)
committerSteven Rostedt (Google) <rostedt@goodmis.org>
Tue, 21 Mar 2023 17:42:11 +0000 (13:42 -0400)
A common pattern when using the ftrace_direct_multi API is to unregister
the ops and also immediately free its filter. We've noticed it's very
easy for users to miss calling ftrace_free_filter().

This adds a "free_filters" argument to unregister_ftrace_direct_multi()
to both remind the user they should free filters and also to make their
life easier.

Link: https://lkml.kernel.org/r/20230321140424.345218-2-revest@chromium.org
Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Florent Revest <revest@chromium.org>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
include/linux/ftrace.h
kernel/bpf/trampoline.c
kernel/trace/ftrace.c
samples/ftrace/ftrace-direct-multi-modify.c
samples/ftrace/ftrace-direct-multi.c

index 366c730..5b68ee8 100644 (file)
@@ -407,7 +407,8 @@ int ftrace_modify_direct_caller(struct ftrace_func_entry *entry,
                                unsigned long new_addr);
 unsigned long ftrace_find_rec_direct(unsigned long ip);
 int register_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr);
-int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr);
+int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr,
+                                  bool free_filters);
 int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr);
 int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsigned long addr);
 
@@ -446,7 +447,8 @@ static inline int register_ftrace_direct_multi(struct ftrace_ops *ops, unsigned
 {
        return -ENODEV;
 }
-static inline int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
+static inline int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr,
+                                                bool free_filters)
 {
        return -ENODEV;
 }
index d0ed7d6..88bc23f 100644 (file)
@@ -198,7 +198,7 @@ static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr)
        int ret;
 
        if (tr->func.ftrace_managed)
-               ret = unregister_ftrace_direct_multi(tr->fops, (long)old_addr);
+               ret = unregister_ftrace_direct_multi(tr->fops, (long)old_addr, false);
        else
                ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, NULL);
 
index 0feea14..9843419 100644 (file)
@@ -5805,7 +5805,8 @@ EXPORT_SYMBOL_GPL(register_ftrace_direct_multi);
  *  0 on success
  *  -EINVAL - The @ops object was not properly registered.
  */
-int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
+int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr,
+                                  bool free_filters)
 {
        struct ftrace_hash *hash = ops->func_hash->filter_hash;
        int err;
@@ -5823,6 +5824,9 @@ int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
        /* cleanup for possible another register call */
        ops->func = NULL;
        ops->trampoline = 0;
+
+       if (free_filters)
+               ftrace_free_filter(ops);
        return err;
 }
 EXPORT_SYMBOL_GPL(unregister_ftrace_direct_multi);
index b58c594..196b439 100644 (file)
@@ -151,8 +151,7 @@ static int __init ftrace_direct_multi_init(void)
 static void __exit ftrace_direct_multi_exit(void)
 {
        kthread_stop(simple_tsk);
-       unregister_ftrace_direct_multi(&direct, my_tramp);
-       ftrace_free_filter(&direct);
+       unregister_ftrace_direct_multi(&direct, my_tramp, true);
 }
 
 module_init(ftrace_direct_multi_init);
index c27cf13..ea0e88e 100644 (file)
@@ -78,8 +78,7 @@ static int __init ftrace_direct_multi_init(void)
 
 static void __exit ftrace_direct_multi_exit(void)
 {
-       unregister_ftrace_direct_multi(&direct, (unsigned long) my_tramp);
-       ftrace_free_filter(&direct);
+       unregister_ftrace_direct_multi(&direct, (unsigned long) my_tramp, true);
 }
 
 module_init(ftrace_direct_multi_init);