Commit 59495740 authored by Florent Revest's avatar Florent Revest Committed by Steven Rostedt (Google)
Browse files

ftrace: Let unregister_ftrace_direct_multi() call ftrace_free_filter()

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: default avatarSteven Rostedt <rostedt@goodmis.org>
Signed-off-by: default avatarFlorent Revest <revest@chromium.org>
Acked-by: default avatarMark Rutland <mark.rutland@arm.com>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
parent e8d018dd
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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;
}
+1 −1
Original line number Diff line number Diff line
@@ -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);

+5 −1
Original line number Diff line number Diff line
@@ -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);
+1 −2
Original line number Diff line number Diff line
@@ -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);
+1 −2
Original line number Diff line number Diff line
@@ -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);