Adding unregister_ftrace_direct_ips function that allows to unregister array of ip addresses and trampolines for direct filter. the interface is: int unregister_ftrace_direct_ips(unsigned long *ips, unsigned long *addrs, int count); It wil be used in following patches to unregister bpf trampolines in batch mode. Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx> --- include/linux/ftrace.h | 2 ++ kernel/trace/ftrace.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 9ed52755667a..24525473043e 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -293,6 +293,8 @@ int ftrace_modify_direct_caller(struct ftrace_func_entry *entry, unsigned long ftrace_find_rec_direct(unsigned long ip); int register_ftrace_direct_ips(unsigned long *ips, unsigned long *addrs, int count); +int unregister_ftrace_direct_ips(unsigned long *ips, unsigned long *addrs, + int count); #else # define ftrace_direct_func_count 0 static inline int register_ftrace_direct(unsigned long ip, unsigned long addr) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 770bcd1a245a..15a13e6c1f31 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -5374,6 +5374,57 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr) } EXPORT_SYMBOL_GPL(unregister_ftrace_direct); +int unregister_ftrace_direct_ips(unsigned long *ips, unsigned long *addrs, + int count) +{ + struct ftrace_direct_func *direct; + struct ftrace_func_entry *entry; + int i, del = 0, ret = -ENODEV; + + mutex_lock(&direct_mutex); + + for (i = 0; i < count; i++) { + entry = find_direct_entry(&ips[i], NULL); + if (!entry) + goto out_unlock; + del++; + } + + if (direct_functions->count - del == 0) + unregister_ftrace_function(&direct_ops); + + ret = ftrace_set_filter_ips(&direct_ops, ips, count, 1); + + WARN_ON(ret); + + for (i = 0; i < count; i++) { + entry = __ftrace_lookup_ip(direct_functions, ips[i]); + if (WARN_ON(!entry)) + continue; + + remove_hash_entry(direct_functions, entry); + + direct = ftrace_find_direct_func(addrs[i]); + if (!WARN_ON(!direct)) { + /* This is the good path (see the ! before WARN) */ + direct->count--; + WARN_ON(direct->count < 0); + if (!direct->count) { + list_del_rcu(&direct->next); + synchronize_rcu_tasks(); + kfree(direct); + kfree(entry); + ftrace_direct_func_count--; + } + } + } + out_unlock: + mutex_unlock(&direct_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(unregister_ftrace_direct_ips); + static struct ftrace_ops stub_ops = { .func = ftrace_stub, }; -- 2.26.2