ftrace,bpf: Use single direct ops for bpf trampolines
Jiri Olsa
reviewerv3 cover ftrace,bpf: Use single direct ops for bpf trampolines
hi,
while poking the multi-tracing interface I ended up with just one ftrace_ops object to attach all trampolines.
This change allows to use less direct API calls during the attachment changes in the future code, so in effect speeding up the attachment.
In current code we get a speed up from using just a single ftrace_ops object.
- with current code:
Performance counter stats for 'bpftrace -e fentry:vmlinux:ksys_* {} -c true':
6,364,157,902 cycles:k
828,728,902 cycles:u
1,064,803,824 instructions:u # 1.28 insn per cycle
23,797,500,067 instructions:k # 3.74 insn per cycle 4.416004987 seconds time elapsed
0.164121000 seconds user
1.289550000 seconds sys- with the fix:
Performance counter stats for 'bpftrace -e fentry:vmlinux:ksys_* {} -c true':
6,535,857,905 cycles:k
810,809,429 cycles:u
1,064,594,027 instructions:u # 1.31 insn per cycle
23,962,552,894 instructions:k # 3.67 insn per cycle 1.666961239 seconds time elapsed
0.157412000 seconds user
1.283396000 seconds sysThe speedup seems to be related to the fact that with single ftrace_ops object we don't call ftrace_shutdown anymore (we use ftrace_update_ops instead) and we skip the synchronize rcu calls (each ~100ms) at the end of that function.
rfc: https://lore.kernel.org/bpf/[email protected]/ v1: https://lore.kernel.org/bpf/[email protected]/ v2: https://lore.kernel.org/bpf/[email protected]/
v3 changes:
- rebased on top of bpf-next/master
- fixed update_ftrace_direct_del cleanup path
- added missing inline to update_ftrace_direct_* stubs
v2 changes:
- rebased on top fo bpf-next/master plus Song's livepatch fixes [1]
- renamed the API functions [2] [Steven]
- do not export the new api [Steven]
- kept the original direct interface:
I'm not sure if we want to melt both *_ftrace_direct and the new interface into single one. It's bit different in semantic (hence the name change as Steven suggested [2]) and I don't think the changes are not that big so we could easily keep both APIs.
v1 changes:
- make the change x86 specific, after discussing with Mark options for arm64 [Mark]
thanks,
jirka
[1] https://lore.kernel.org/bpf/[email protected]/
[2] https://lore.kernel.org/bpf/[email protected]/
---
Jiri Olsa (8):
ftrace: Make alloc_and_copy_ftrace_hash direct friendly
ftrace: Export some of hash related functions
ftrace: Add update_ftrace_direct_add function
ftrace: Add update_ftrace_direct_del function
ftrace: Add update_ftrace_direct_mod function
bpf: Add trampoline ip hash table
ftrace: Factor ftrace_ops ops_func interface
bpf, x86: Use single ftrace_ops for direct calls
arch/x86/Kconfig | 1 + include/linux/bpf.h | 7 ++- include/linux/ftrace.h | 37 +++++++++++++- kernel/bpf/trampoline.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ kernel/trace/Kconfig | 3 ++ kernel/trace/ftrace.c | 337 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- kernel/trace/trace.h | 8 --- 7 files changed, 547 insertions(+), 51 deletions(-)
Jiri Olsa
reviewerPATCH v3 1/8 ftrace: Make alloc_and_copy_ftrace_hash direct friendly
Make alloc_and_copy_ftrace_hash to copy also direct address for each hash entry.
--- kernel/trace/ftrace.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
kernel/trace/ftrace.c +9 -2
@@ -1186,7 +1186,7 @@ static void __add_hash_entry(struct ftrace_hash *hash, }static struct ftrace_func_entry * -add_hash_entry (struct ftrace_hash *hash,unsigned long ip) +add_hash_entry_direct (struct ftrace_hash *hash,unsigned long ip,unsigned long direct) {struct ftrace_func_entry *entry;
@@ -1195,11 +1195,18 @@ add_hash_entry(struct ftrace_hash *hash, unsigned long ip)return NULL ; entry->ip = ip; + entry->direct = direct;__add_hash_entry (hash, entry);return entry; } +static struct ftrace_func_entry * +add_hash_entry (struct ftrace_hash *hash,unsigned long ip) +{ +return add_hash_entry_direct (hash, ip,0 ); +} +static void free_hash_entry (struct ftrace_hash *hash,struct ftrace_func_entry *entry)
@@ -1372,7 +1379,7 @@ alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash) size =1 << hash->size_bits;for (i =0 ; i < size; i++) {hlist_for_each_entry (entry, &hash->buckets[i], hlist) { -if (add_hash_entry (new_hash, entry->ip) ==NULL ) +if (add_hash_entry_direct (new_hash, entry->ip, entry->direct) ==NULL ) goto free_hash; } }
Signature · 1 line
2.51.1
Jiri Olsa
reviewerPATCH v3 2/8 ftrace: Export some of hash related functions
In reply to Jiri OlsaWe are going to use these functions in following changes.
--- include/linux/ftrace.h | 16 ++++++++++++++++ kernel/trace/ftrace.c | 7 +++---- kernel/trace/trace.h | 8 -------- 3 files changed, 19 insertions(+), 12 deletions(-)
include/linux/ftrace.h +16 -0
@@ -405,6 +405,22 @@ enum ftrace_ops_cmd {typedef int (*ftrace_ops_func_t )(struct ftrace_ops *op,enum ftrace_ops_cmd cmd); #ifdef CONFIG_DYNAMIC_FTRACE + +#define FTRACE_HASH_DEFAULT_BITS 10 + +struct ftrace_hash { + unsigned long size_bits; + struct hlist_head *buckets; + unsigned long count; + unsigned long flags; + struct rcu_head rcu; +}; + +struct ftrace_hash *alloc_ftrace_hash(int size_bits); +void free_ftrace_hash(struct ftrace_hash *hash); +struct ftrace_func_entry *add_hash_entry_direct(struct ftrace_hash *hash, + unsigned long ip, unsigned long direct); + /* The hash used to know what functions callbacks trace */ struct ftrace_ops_hash { struct ftrace_hash __rcu *notrace_hash;
kernel/trace/ftrace.c +3 -4
@@ -68,7 +68,6 @@ })/* hash bits for specific function selection */ -#define FTRACE_HASH_DEFAULT_BITS 10#define FTRACE_HASH_MAX_BITS 12#ifdef CONFIG_DYNAMIC_FTRACE
@@ -1185,7 +1184,7 @@ static void __add_hash_entry(struct ftrace_hash *hash, hash->count++; } -static struct ftrace_func_entry * +struct ftrace_func_entry *add_hash_entry_direct (struct ftrace_hash *hash,unsigned long ip,unsigned long direct) {struct ftrace_func_entry *entry;
@@ -1265,7 +1264,7 @@ static void clear_ftrace_mod_list(struct list_head *head)mutex_unlock (&ftrace_lock); } -static void free_ftrace_hash (struct ftrace_hash *hash) +void free_ftrace_hash (struct ftrace_hash *hash) {if (!hash || hash ==EMPTY_HASH )return ;
@@ -1305,7 +1304,7 @@ void ftrace_free_filter(struct ftrace_ops *ops) }EXPORT_SYMBOL_GPL (ftrace_free_filter); -static struct ftrace_hash *alloc_ftrace_hash (int size_bits) +struct ftrace_hash *alloc_ftrace_hash (int size_bits) {struct ftrace_hash *hash;int size;
kernel/trace/trace.h +0 -8
@@ -899,14 +899,6 @@ enum { FTRACE_HASH_FL_MOD = (1 << 0), }; -struct ftrace_hash { -unsigned long size_bits; -struct hlist_head *buckets; -unsigned long count; -unsigned long flags; -struct rcu_head rcu; -}; -struct ftrace_func_entry *ftrace_lookup_ip (struct ftrace_hash *hash,unsigned long ip);
Signature · 1 line
2.51.1
Jiri Olsa
reviewerPATCH v3 3/8 ftrace: Add update_ftrace_direct_add function
In reply to Jiri OlsaAdding update_ftrace_direct_add function that adds all entries (ip -> addr) provided in hash argument to direct ftrace ops and updates its attachments.
The difference to current register_ftrace_direct is
- hash argument that allows to register multiple ip -> direct entries at once
- we can call update_ftrace_direct_add multiple times on the same ftrace_ops object, becase after first registration with register_ftrace_function_nolock, it uses ftrace_update_ops to update the ftrace_ops object
This change will allow us to have simple ftrace_ops for all bpf direct interface users in following changes.
--- include/linux/ftrace.h | 7 +++ kernel/trace/ftrace.c | 128 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+)
include/linux/ftrace.h +7 -0
@@ -550,6 +550,8 @@ int unregister_ftrace_direct(struct ftrace_ops *ops, unsigned long addr,int modify_ftrace_direct (struct ftrace_ops *ops,unsigned long addr);int modify_ftrace_direct_nolock (struct ftrace_ops *ops,unsigned long addr); +int update_ftrace_direct_add (struct ftrace_ops *ops,struct ftrace_hash *hash); +void ftrace_stub_direct_tramp (void );#else
@@ -576,6 +578,11 @@ static inline int modify_ftrace_direct_nolock(struct ftrace_ops *ops, unsigned lreturn -ENODEV ; } +static inline int update_ftrace_direct_add (struct ftrace_ops *ops,struct ftrace_hash *hash) +{ +return -ENODEV ; +} +/* * This must be implemented by the architecture. * It is the way the ftrace direct_ops helper, when called
kernel/trace/ftrace.c +128 -0
134 lines not on this page · raw message
Signature · 1 line
2.51.1
kernel test robot
build botRe: [PATCHv3 bpf-next 3/8] ftrace: Add update_ftrace_direct_add function
kernel test robot noticed the following build warnings:
Hi Jiri,
kernel test robot noticed the following build warnings:
[auto build test WARNING on bpf-next/master]
url: https://github.com/intel-lab-lkp/linux/commits/Jiri-Olsa/ftrace-Make-alloc_and_copy_ftrace_hash-direct-friendly/20251121-052934 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master patch link: https://lore.kernel.org/r/20251120212402.466524-4-jolsa%40kernel.org patch subject: [PATCHv3 bpf-next 3/8] ftrace: Add update_ftrace_direct_add function config: s390-randconfig-r132-20251121 (https://download.01.org/0day-ci/archive/20251122/[email protected]/config) compiler: s390-linux-gcc (GCC) 12.5.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251122/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
sparse warnings: (new ones prefixed by >>)
kernel/trace/ftrace.c:317:50: sparse: expected struct ftrace_ops **p
kernel/trace/ftrace.c:317:50: sparse: got struct ftrace_ops [noderef] __rcu **
kernel/trace/ftrace.c:324:12: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_ops * @@ got struct ftrace_ops [noderef] __rcu *next @@
kernel/trace/ftrace.c:324:12: sparse: expected struct ftrace_ops *
kernel/trace/ftrace.c:324:12: sparse: got struct ftrace_ops [noderef] __rcu *next
kernel/trace/ftrace.c:1067:43: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@
kernel/trace/ftrace.c:1067:43: sparse: expected struct ftrace_hash [noderef] __rcu *notrace_hash
kernel/trace/ftrace.c:1067:43: sparse: got struct ftrace_hash *
kernel/trace/ftrace.c:1068:43: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@
kernel/trace/ftrace.c:1068:43: sparse: expected struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:1068:43: sparse: got struct ftrace_hash *
kernel/trace/ftrace.c:1300:40: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@
kernel/trace/ftrace.c:1300:40: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:1300:40: sparse: got struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:1301:40: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@
kernel/trace/ftrace.c:1301:40: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:1301:40: sparse: got struct ftrace_hash [noderef] __rcu *notrace_hash
kernel/trace/ftrace.c:1302:37: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@
kernel/trace/ftrace.c:1302:37: sparse: expected struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:1302:37: sparse: got struct ftrace_hash *
kernel/trace/ftrace.c:1303:38: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@
kernel/trace/ftrace.c:1303:38: sparse: expected struct ftrace_hash [noderef] __rcu *notrace_hash
kernel/trace/ftrace.c:1303:38: sparse: got struct ftrace_hash *
kernel/trace/ftrace.c:2115:54: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *old_hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@
kernel/trace/ftrace.c:2115:54: sparse: expected struct ftrace_hash *old_hash
kernel/trace/ftrace.c:2115:54: sparse: got struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:1507:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/trace/ftrace.c:1507:9: sparse: struct ftrace_hash [noderef] __rcu *
kernel/trace/ftrace.c:1507:9: sparse: struct ftrace_hash *
kernel/trace/ftrace.c:1523:39: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:1524:40: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:1525:40: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:1526:42: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:1697:18: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_ops *ops @@ got struct ftrace_ops [noderef] __rcu *[addressable] [toplevel] ftrace_ops_list @@ kernel/trace/ftrace.c:1698:43: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_ops *ops @@ got struct ftrace_ops [noderef] __rcu *next @@ kernel/trace/ftrace.c:1759:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:1760:22: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *notrace_hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:2093:50: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:2104:50: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:2587:53: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *static [toplevel] direct_functions @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:2598:36: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *static [toplevel] direct_functions @@ kernel/trace/ftrace.c:3394:51: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *B @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3395:66: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:3401:52: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *B @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3402:66: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:3415:41: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3416:51: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *src @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3419:52: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *notrace_hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3423:52: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *src @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3438:39: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3439:42: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3447:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3453:81: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3457:54: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *notrace_hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3459:56: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *new_hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3489:60: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *new_hash1 @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3490:49: sparse: sparse: incorrect type in argument 3 (different address spaces) @@ expected struct ftrace_hash *new_hash2 @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3529:45: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3531:46: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3533:48: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3535:49: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3541:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3542:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3548:34: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *save_filter_hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3549:35: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *save_notrace_hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3551:45: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash *[addressable] filter_hash @@ kernel/trace/ftrace.c:3552:46: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash *[addressable] notrace_hash @@ kernel/trace/ftrace.c:3557:53: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash *save_filter_hash @@ kernel/trace/ftrace.c:3558:54: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash *save_notrace_hash @@ kernel/trace/ftrace.c:3605:31: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3606:32: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3621:59: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *[addressable] filter_hash @@ kernel/trace/ftrace.c:3622:59: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *[addressable] notrace_hash @@ kernel/trace/ftrace.c:3627:43: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *[addressable] filter_hash @@ kernel/trace/ftrace.c:3628:43: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *[addressable] notrace_hash @@ kernel/trace/ftrace.c:3630:39: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *[addressable] filter_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3631:40: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *[addressable] notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3673:48: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3674:48: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3675:45: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3676:46: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3962:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3979:22: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:4665:22: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:4668:22: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:5079:27: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5081:27: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5461:19: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5605:19: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5611:34: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash *[assigned] old_hash @@ kernel/trace/ftrace.c:5876:27: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5878:27: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5959:50: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *static [toplevel] direct_functions @@ kernel/trace/ftrace.c:5961:51: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *static [toplevel] direct_functions @@ kernel/trace/ftrace.c:5977:50: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:6021:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:6071:19: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *free_hash @@ got struct ftrace_hash [noderef] __rcu *static [toplevel] direct_functions @@ kernel/trace/ftrace.c:6136:50: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:6174:52: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *static [addressable] [assigned] [toplevel] direct_functions @@ kernel/trace/ftrace.c:6309:48: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *static [addressable] [assigned] [toplevel] direct_functions @@ >> kernel/trace/ftrace.c:6314:25: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *old_filter_hash @@ got struct ftrace_hash [noderef] __rcu * @@ >> kernel/trace/ftrace.c:6315:30: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *old_direct_functions @@ got struct ftrace_hash [noderef] __rcu *static [addressable] [assigned] [toplevel] direct_functions @@ >> kernel/trace/ftrace.c:6341:45: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash *[assigned] new_filter_hash @@ >> kernel/trace/ftrace.c:6346:53: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash *old_filter_hash @@ kernel/trace/ftrace.c:6629:35: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *extern [addressable] [toplevel] ftrace_graph_hash @@ got struct ftrace_hash *[assigned] hash @@ kernel/trace/ftrace.c:6631:43: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *extern [addressable] [toplevel] ftrace_graph_notrace_hash @@ got struct ftrace_hash *[assigned] hash @@ kernel/trace/ftrace.c:6700:35: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:6708:35: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:6773:47: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *[addressable] [toplevel] ftrace_graph_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:6774:55: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *[addressable] [toplevel] ftrace_graph_notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:7493:46: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:7494:47: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:7498:44: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:7516:18: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_ops *ops @@ got struct ftrace_ops [noderef] __rcu *[addressable] [toplevel] ftrace_ops_list @@ kernel/trace/ftrace.c:7516:66: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_ops *ops @@ got struct ftrace_ops [noderef] __rcu *next @@ kernel/trace/ftrace.c:7568:59: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:7569:59: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:7958:62: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:7959:62: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@
kernel/trace/ftrace.c:8003:36: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/trace/ftrace.c:8003:36: sparse: struct ftrace_ops [noderef] __rcu *
kernel/trace/ftrace.c:8003:36: sparse: struct ftrace_ops *
kernel/trace/ftrace.c:8779:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@
kernel/trace/ftrace.c:8779:14: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:8779:14: sparse: got struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:8828:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@
kernel/trace/ftrace.c:8828:14: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:8828:14: sparse: got struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:230:20: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:230:20: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:230:20: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:6039:30: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:6048:21: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:6050:17: sparse: sparse: dereference of noderef expression
kernel/trace/ftrace.c:3754:48: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@
kernel/trace/ftrace.c:3754:48: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:3754:48: sparse: got struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:3755:49: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@
kernel/trace/ftrace.c:3755:49: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:3755:49: sparse: got struct ftrace_hash [noderef] __rcu *notrace_hash
vim +6314 kernel/trace/ftrace.c
6291
6292 int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash)
6293 {
6294 struct ftrace_hash *old_direct_functions = NULL, *new_direct_functions = NULL;
6295 struct ftrace_hash *old_filter_hash = NULL, *new_filter_hash = NULL;
6296 struct ftrace_func_entry *entry;
6297 int i, size, err = -EINVAL;
6298 bool reg;
6299
6300 if (!hash_count(hash))
6301 return -EINVAL;
6302
6303 mutex_lock(&direct_mutex);
6304
6305 /* Make sure requested entries are not already registered. */
6306 size = 1 << hash->size_bits;
6307 for (i = 0; i < size; i++) {
6308 hlist_for_each_entry(entry, &hash->buckets[i], hlist) {
6309 if (__ftrace_lookup_ip(direct_functions, entry->ip))
6310 goto out_unlock;
6311 }
6312 }
6313
> 6314 old_filter_hash = ops->func_hash ? ops->func_hash->filter_hash : NULL;
> 6315 old_direct_functions = direct_functions;
6316
6317 /* If there's nothing in filter_hash we need to register the ops. */
6318 reg = hash_count(old_filter_hash) == 0;
6319 if (reg) {
6320 if (ops->func || ops->trampoline)
6321 goto out_unlock;
6322 if (ops->flags & FTRACE_OPS_FL_ENABLED)
6323 goto out_unlock;
6324 }
6325
6326 err = -ENOMEM;
6327 new_filter_hash = hash_add(old_filter_hash, hash);
6328 if (!new_filter_hash)
6329 goto out_unlock;
6330
6331 new_direct_functions = hash_add(old_direct_functions, hash);
6332 if (!new_direct_functions)
6333 goto out_unlock;
6334
6335 rcu_assign_pointer(direct_functions, new_direct_functions);
6336
6337 if (reg) {
6338 ops->func = call_direct_funcs;
6339 ops->flags |= MULTI_FLAGS;
6340 ops->trampoline = FTRACE_REGS_ADDR;
> 6341 ops->local_hash.filter_hash = new_filter_hash;
6342
6343 err = register_ftrace_function_nolock(ops);
6344 if (err) {
6345 /* restore old filter on error */
> 6346 ops->local_hash.filter_hash = old_filter_hash; 6347 old_filter_hash = new_filter_hash;
6348
6349 /* cleanup for possible another register call */
6350 ops->func = NULL;
6351 ops->trampoline = 0;
6352 }
6353 } else {
6354 err = ftrace_update_ops(ops, new_filter_hash, EMPTY_HASH);
6355 /*
6356 * new_filter_hash is dup-ed, so we need to release it anyway,
6357 * old_filter_hash either stays on error or is released already
6358 */
6359 old_filter_hash = new_filter_hash;
6360 }
6361
6362 if (err) {
6363 /* reset direct_functions and free the new one */
6364 rcu_assign_pointer(direct_functions, old_direct_functions);
6365 old_direct_functions = new_direct_functions;
6366 }
6367
6368 out_unlock:
6369 mutex_unlock(&direct_mutex);
6370
6371 if (old_direct_functions && old_direct_functions != EMPTY_HASH)
6372 call_rcu_tasks(&old_direct_functions->rcu, register_ftrace_direct_cb);
6373 if (old_filter_hash)
6374 free_ftrace_hash(old_filter_hash);
6375
6376 return err;
6377 }
6378
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Jiri Olsa
reviewerPATCH v3 4/8 ftrace: Add update_ftrace_direct_del function
In reply to Jiri OlsaAdding update_ftrace_direct_del function that removes all entries (ip -> addr) provided in hash argument to direct ftrace ops and updates its attachments.
The difference to current unregister_ftrace_direct is
- hash argument that allows to unregister multiple ip -> direct entries at once
- we can call update_ftrace_direct_del multiple times on the same ftrace_ops object, becase we do not need to unregister all entries at once, we can do it gradualy with the help of ftrace_update_ops function
This change will allow us to have simple ftrace_ops for all bpf direct interface users in following changes.
--- include/linux/ftrace.h | 6 +++ kernel/trace/ftrace.c | 110 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+)
include/linux/ftrace.h +6 -0
@@ -551,6 +551,7 @@ int modify_ftrace_direct(struct ftrace_ops *ops, unsigned long addr);int modify_ftrace_direct_nolock (struct ftrace_ops *ops,unsigned long addr);int update_ftrace_direct_add (struct ftrace_ops *ops,struct ftrace_hash *hash); +int update_ftrace_direct_del (struct ftrace_ops *ops,struct ftrace_hash *hash);void ftrace_stub_direct_tramp (void );
@@ -583,6 +584,11 @@ static inline int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftracereturn -ENODEV ; } +static inline int update_ftrace_direct_del (struct ftrace_ops *ops,struct ftrace_hash *hash) +{ +return -ENODEV ; +} +/* * This must be implemented by the architecture. * It is the way the ftrace direct_ops helper, when called
kernel/trace/ftrace.c +110 -0
116 lines not on this page · raw message
Signature · 1 line
2.51.1
[email protected]
AI reviewRe: [PATCHv3 bpf-next 4/8] ftrace: Add update_ftrace_direct_del function
Can hash_sub() handle a NULL hash pointer in parameter a? I notice the parallel function hash_add() safely handles NULL via hash_count() and alloc_and_copy_ftrace_hash() which checks…
Quoted 21 lines
include/linux/ftrace.h +6
-0@@ -551,6 +551,7 @@ int modify_ftrace_direct(struct ftrace_ops *ops, unsigned long addr);int modify_ftrace_direct_nolock (struct ftrace_ops *ops,unsigned long addr);int update_ftrace_direct_add (struct ftrace_ops *ops,struct ftrace_hash *hash); +int update_ftrace_direct_del (struct ftrace_ops *ops,struct ftrace_hash *hash);void ftrace_stub_direct_tramp (void );@@ -583,6 +584,11 @@ static inline int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftracereturn -ENODEV ; } +static inline int update_ftrace_direct_del (struct ftrace_ops *ops,struct ftrace_hash *hash) +{ +return -ENODEV ; +} +
[ ... ]
Quoted 4 lines
kernel/trace/ftrace.c +0
-0
[ ... ]
Quoted 4 lines
kernel/trace/ftrace.c +4
-0+/** +* hash_sub - substracts @b from @a and returns the result +* @a: struct ftrace_hash object +* @b: struct ftrace_hash object
kernel/trace/ftrace.c int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash) · line 6392
Quoted 10 lines
kernel/trace/ftrace.c +10
-0+* +* Returns struct ftrace_hash object on success, NULL on error. +*/ +static struct ftrace_hash *hash_sub (struct ftrace_hash *a,struct ftrace_hash *b) +{ +struct ftrace_func_entry *entry, *del; +struct ftrace_hash *sub; +int size, i; + + sub =alloc_and_copy_ftrace_hash (a->size_bits, a);
^^^^^^^^^^^^
Can hash_sub() handle a NULL hash pointer in parameter a? I notice the parallel function hash_add() safely handles NULL via hash_count() and alloc_and_copy_ftrace_hash() which checks ftrace_hash_empty().
However, hash_sub() directly dereferences a->size_bits before passing a to alloc_and_copy_ftrace_hash(). This will crash if a is NULL.
This matters because update_ftrace_direct_del() calls hash_sub() with old_filter_hash which can be NULL:
old_filter_hash = ops->func_hash ? ops->func_hash->filter_hash : NULL;
...
new_filter_hash = hash_sub(old_filter_hash, hash);The existing update_ftrace_direct_add() has the same defensive check and passes the potentially-NULL old_filter_hash to hash_add(), which handles it correctly.
Quoted 12 lines
kernel/trace/ftrace.c +12
-0+if (!sub) + goto error; + + size =1 << b->size_bits; +for (i =0 ; i < size; i++) { +hlist_for_each_entry (entry, &b->buckets[i], hlist) { + del =__ftrace_lookup_ip (sub, entry->ip); +if (WARN_ON_ONCE (!del)) + goto error; +remove_hash_entry (sub, del); +kfree (del); + }
kernel/trace/ftrace.c int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash) · line 6414
Quoted 10 lines
kernel/trace/ftrace.c +10
-0+ } +return sub; + + error: +free_ftrace_hash (sub); +return NULL ; +} + +int update_ftrace_direct_del (struct ftrace_ops *ops,struct ftrace_hash *hash) +{
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/19552032346
Re: [PATCHv3 bpf-next 4/8] ftrace: Add update_ftrace_direct_del function
Quoted 57 lines · On Thu, Nov 20, 2025 at 10:23:46PM +0000, [email protected] wrote:
Quoted 21 lines
include/linux/ftrace.h +6
-0@@ -551,6 +551,7 @@ int modify_ftrace_direct(struct ftrace_ops *ops, unsigned long addr);int modify_ftrace_direct_nolock (struct ftrace_ops *ops,unsigned long addr);int update_ftrace_direct_add (struct ftrace_ops *ops,struct ftrace_hash *hash); +int update_ftrace_direct_del (struct ftrace_ops *ops,struct ftrace_hash *hash);void ftrace_stub_direct_tramp (void );@@ -583,6 +584,11 @@ static inline int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftracereturn -ENODEV ; } +static inline int update_ftrace_direct_del (struct ftrace_ops *ops,struct ftrace_hash *hash) +{ +return -ENODEV ; +} +[ ... ]
Quoted 4 lines
kernel/trace/ftrace.c +0
-0[ ... ]
Quoted 4 lines
kernel/trace/ftrace.c +4
-0+/** +* hash_sub - substracts @b from @a and returns the result +* @a: struct ftrace_hash object +* @b: struct ftrace_hash object kernel/trace/ftrace.c int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash) · line 6392
Quoted 10 lines
kernel/trace/ftrace.c +10
-0+* +* Returns struct ftrace_hash object on success, NULL on error. +*/ +static struct ftrace_hash *hash_sub (struct ftrace_hash *a,struct ftrace_hash *b) +{ +struct ftrace_func_entry *entry, *del; +struct ftrace_hash *sub; +int size, i; + + sub =alloc_and_copy_ftrace_hash (a->size_bits, a);^^^^^^^^^^^^Can
hash_sub()handle a NULL hash pointer in parameter a? I notice the parallel functionhash_add()safely handles NULL viahash_count()andalloc_and_copy_ftrace_hash()which checksftrace_hash_empty().However,
hash_sub()directly dereferencesa->size_bitsbefore passing a toalloc_and_copy_ftrace_hash(). This will crash if a is NULL.This matters because
update_ftrace_direct_del()callshash_sub()withold_filter_hashwhich can be NULL:
Quoted 7 lines
old_filter_hash = ops->func_hash ? ops->func_hash->filter_hash : NULL; ... new_filter_hash = hash_sub(old_filter_hash, hash);The existing
update_ftrace_direct_add()has the same defensive check and passes the potentially-NULLold_filter_hashtohash_add(), which handles it correctly.
so we never call update_ftrace_direct_del without having update_ftrace_direct_add called, which ensures the existence of filter_hash, but it's probably good idea to do explicit check for future
thanks,
jirka
Quoted 32 lines
Quoted 13 lines
kernel/trace/ftrace.c +12
-0+if (!sub) + goto error; + + size =1 << b->size_bits; +for (i =0 ; i < size; i++) { +hlist_for_each_entry (entry, &b->buckets[i], hlist) { + del =__ftrace_lookup_ip (sub, entry->ip); +if (WARN_ON_ONCE (!del)) + goto error; +remove_hash_entry (sub, del); +kfree (del); + }kernel/trace/ftrace.c int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash) · line 6414
Quoted 10 lines
kernel/trace/ftrace.c +10
-0+ } +return sub; + + error: +free_ftrace_hash (sub); +return NULL ; +} + +int update_ftrace_direct_del (struct ftrace_ops *ops,struct ftrace_hash *hash) +{[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.mdCI run summary: https://github.com/kernel-patches/bpf/actions/runs/19552032346
Jiri Olsa
reviewerPATCH v3 5/8 ftrace: Add update_ftrace_direct_mod function
In reply to Jiri OlsaAdding update_ftrace_direct_mod function that modifies all entries (ip -> direct) provided in hash argument to direct ftrace ops and updates its attachments.
The difference to current modify_ftrace_direct is:
- hash argument that allows to modify multiple ip -> direct entries at once
This change will allow us to have simple ftrace_ops for all bpf direct interface users in following changes.
--- include/linux/ftrace.h | 6 ++++ kernel/trace/ftrace.c | 68 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+)
include/linux/ftrace.h +6 -0
@@ -552,6 +552,7 @@ int modify_ftrace_direct_nolock(struct ftrace_ops *ops, unsigned long addr);int update_ftrace_direct_add (struct ftrace_ops *ops,struct ftrace_hash *hash);int update_ftrace_direct_del (struct ftrace_ops *ops,struct ftrace_hash *hash); +int update_ftrace_direct_mod (struct ftrace_ops *ops,struct ftrace_hash *hash,bool do_direct_lock);void ftrace_stub_direct_tramp (void );
@@ -589,6 +590,11 @@ static inline int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftracereturn -ENODEV ; } +static inline int update_ftrace_direct_mod (struct ftrace_ops *ops,struct ftrace_hash *hash,bool do_direct_lock) +{ +return -ENODEV ; +} +/* * This must be implemented by the architecture. * It is the way the ftrace direct_ops helper, when called
kernel/trace/ftrace.c +68 -0
74 lines not on this page · raw message
Signature · 1 line
2.51.1
[email protected]
AI reviewRe: [PATCHv3 bpf-next 5/8] ftrace: Add update_ftrace_direct_mod function
Can this crash if ops->func_hash is NULL? In update_ftrace_direct_add() and update_ftrace_direct_del(), there's a defensive check:
Quoted 4 lines
include/linux/ftrace.h +0
-0
[ ... ]
Quoted 4 lines
kernel/trace/ftrace.c +0
-0
[ ... ]
kernel/trace/ftrace.c int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash) · line 6491
Quoted 7 lines
kernel/trace/ftrace.c +3
-0@@ -6486,6 +6486,74 @@ int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash)return err; } +int update_ftrace_direct_mod (struct ftrace_ops *ops,struct ftrace_hash *hash,bool do_direct_lock) +{ +struct ftrace_hash *orig_hash = ops->func_hash->filter_hash;
^^^^^^^^^^^^^^^^
Can this crash if ops->func_hash is NULL? In update_ftrace_direct_add() and update_ftrace_direct_del(), there's a defensive check:
old_filter_hash = ops->func_hash ? ops->func_hash->filter_hash : NULL;
But update_ftrace_direct_mod() dereferences ops->func_hash before any validation checks occur. The check_direct_multi(ops) validation happens later, but the dereference occurs first at function entry.
kernel/trace/ftrace.c int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash) · line 6503
Quoted 12 lines
kernel/trace/ftrace.c +12
-0+struct ftrace_func_entry *entry, *tmp; +static struct ftrace_ops tmp_ops = { + .func = ftrace_stub, + .flags =FTRACE_OPS_FL_STUB , + }; +unsigned long size, i; +int err; + +if (!hash_count (hash)) +return -EINVAL ; +if (check_direct_multi (ops)) +return -EINVAL ;
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/19552032346
Re: [PATCHv3 bpf-next 5/8] ftrace: Add update_ftrace_direct_mod function
Quoted 23 lines · On Thu, Nov 20, 2025 at 10:23:47PM +0000, [email protected] wrote:
Quoted 4 lines
include/linux/ftrace.h +0
-0[ ... ]
Quoted 4 lines
kernel/trace/ftrace.c +0
-0[ ... ]
kernel/trace/ftrace.c int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash) · line 6491
Quoted 7 lines
kernel/trace/ftrace.c +3
-0@@ -6486,6 +6486,74 @@ int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash)return err; } +int update_ftrace_direct_mod (struct ftrace_ops *ops,struct ftrace_hash *hash,bool do_direct_lock) +{ +struct ftrace_hash *orig_hash = ops->func_hash->filter_hash;^^^^^^^^^^^^^^^^
Quoted 8 lines
Can this crash if
ops->func_hashis NULL? Inupdate_ftrace_direct_add()andupdate_ftrace_direct_del(), there's a defensive check:old_filter_hash = ops->func_hash ? ops->func_hash->filter_hash : NULL;But
update_ftrace_direct_mod()dereferencesops->func_hashbefore any validation checks occur. Thecheck_direct_multi(ops)validation happens later, but the dereference occurs first at function entry.
update_ftrace_direct_add is called before update_ftrace_direct_mod which ensures the existence of the filter_hash, but same as for the update_ftrace_direct_del case in the other reply, it's probably better to add the check for future
thanks,
jirka
Quoted 22 lines
kernel/trace/ftrace.c int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash) · line 6503
Quoted 13 lines
kernel/trace/ftrace.c +12
-0+struct ftrace_func_entry *entry, *tmp; +static struct ftrace_ops tmp_ops = { + .func = ftrace_stub, + .flags =FTRACE_OPS_FL_STUB , + }; +unsigned long size, i; +int err; + +if (!hash_count (hash)) +return -EINVAL ; +if (check_direct_multi (ops)) +return -EINVAL ;[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.mdCI run summary: https://github.com/kernel-patches/bpf/actions/runs/19552032346
kernel test robot
build botRe: [PATCHv3 bpf-next 5/8] ftrace: Add update_ftrace_direct_mod function
In reply to Jiri Olsakernel test robot noticed the following build warnings:
Hi Jiri,
kernel test robot noticed the following build warnings:
[auto build test WARNING on bpf-next/master]
url: https://github.com/intel-lab-lkp/linux/commits/Jiri-Olsa/ftrace-Make-alloc_and_copy_ftrace_hash-direct-friendly/20251121-052934 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master patch link: https://lore.kernel.org/r/20251120212402.466524-6-jolsa%40kernel.org patch subject: [PATCHv3 bpf-next 5/8] ftrace: Add update_ftrace_direct_mod function config: s390-randconfig-r132-20251121 (https://download.01.org/0day-ci/archive/20251122/[email protected]/config) compiler: s390-linux-gcc (GCC) 12.5.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251122/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
sparse warnings: (new ones prefixed by >>)
kernel/trace/ftrace.c:1067:43: sparse: got struct ftrace_hash *
kernel/trace/ftrace.c:1068:43: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@
kernel/trace/ftrace.c:1068:43: sparse: expected struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:1068:43: sparse: got struct ftrace_hash *
kernel/trace/ftrace.c:1300:40: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@
kernel/trace/ftrace.c:1300:40: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:1300:40: sparse: got struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:1301:40: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@
kernel/trace/ftrace.c:1301:40: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:1301:40: sparse: got struct ftrace_hash [noderef] __rcu *notrace_hash
kernel/trace/ftrace.c:1302:37: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@
kernel/trace/ftrace.c:1302:37: sparse: expected struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:1302:37: sparse: got struct ftrace_hash *
kernel/trace/ftrace.c:1303:38: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@
kernel/trace/ftrace.c:1303:38: sparse: expected struct ftrace_hash [noderef] __rcu *notrace_hash
kernel/trace/ftrace.c:1303:38: sparse: got struct ftrace_hash *
kernel/trace/ftrace.c:2115:54: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *old_hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@
kernel/trace/ftrace.c:2115:54: sparse: expected struct ftrace_hash *old_hash
kernel/trace/ftrace.c:2115:54: sparse: got struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:1507:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/trace/ftrace.c:1507:9: sparse: struct ftrace_hash [noderef] __rcu *
kernel/trace/ftrace.c:1507:9: sparse: struct ftrace_hash *
kernel/trace/ftrace.c:1523:39: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:1524:40: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:1525:40: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:1526:42: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:1697:18: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_ops *ops @@ got struct ftrace_ops [noderef] __rcu *[addressable] [toplevel] ftrace_ops_list @@ kernel/trace/ftrace.c:1698:43: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_ops *ops @@ got struct ftrace_ops [noderef] __rcu *next @@ kernel/trace/ftrace.c:1759:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:1760:22: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *notrace_hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:2093:50: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:2104:50: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:2587:53: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *static [toplevel] direct_functions @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:2598:36: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *static [toplevel] direct_functions @@ kernel/trace/ftrace.c:3394:51: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *B @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3395:66: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:3401:52: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *B @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3402:66: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:3415:41: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3416:51: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *src @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3419:52: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *notrace_hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3423:52: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *src @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3438:39: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3439:42: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3447:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3453:81: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3457:54: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *notrace_hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3459:56: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *new_hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3489:60: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *new_hash1 @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3490:49: sparse: sparse: incorrect type in argument 3 (different address spaces) @@ expected struct ftrace_hash *new_hash2 @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3529:45: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3531:46: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3533:48: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3535:49: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3541:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3542:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3548:34: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *save_filter_hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3549:35: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *save_notrace_hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3551:45: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash *[addressable] filter_hash @@ kernel/trace/ftrace.c:3552:46: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash *[addressable] notrace_hash @@ kernel/trace/ftrace.c:3557:53: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash *save_filter_hash @@ kernel/trace/ftrace.c:3558:54: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash *save_notrace_hash @@ kernel/trace/ftrace.c:3605:31: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3606:32: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3621:59: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *[addressable] filter_hash @@ kernel/trace/ftrace.c:3622:59: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *[addressable] notrace_hash @@ kernel/trace/ftrace.c:3627:43: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *[addressable] filter_hash @@ kernel/trace/ftrace.c:3628:43: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *[addressable] notrace_hash @@ kernel/trace/ftrace.c:3630:39: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *[addressable] filter_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3631:40: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *[addressable] notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3673:48: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3674:48: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:3675:45: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3676:46: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:3962:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:3979:22: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:4665:22: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:4668:22: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:5079:27: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5081:27: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5461:19: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5605:19: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5611:34: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash *[assigned] old_hash @@ kernel/trace/ftrace.c:5876:27: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5878:27: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:5959:50: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *static [toplevel] direct_functions @@ kernel/trace/ftrace.c:5961:51: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *static [toplevel] direct_functions @@ kernel/trace/ftrace.c:5977:50: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:6021:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:6071:19: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *free_hash @@ got struct ftrace_hash [noderef] __rcu *static [toplevel] direct_functions @@ kernel/trace/ftrace.c:6136:50: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:6174:52: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *static [addressable] [assigned] [toplevel] direct_functions @@ kernel/trace/ftrace.c:6309:48: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *static [addressable] [assigned] [toplevel] direct_functions @@ kernel/trace/ftrace.c:6314:25: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *old_filter_hash @@ got struct ftrace_hash [noderef] __rcu * @@ kernel/trace/ftrace.c:6315:30: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *old_direct_functions @@ got struct ftrace_hash [noderef] __rcu *static [addressable] [assigned] [toplevel] direct_functions @@ kernel/trace/ftrace.c:6341:45: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash *[assigned] new_filter_hash @@ kernel/trace/ftrace.c:6346:53: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *filter_hash @@ got struct ftrace_hash *old_filter_hash @@ kernel/trace/ftrace.c:6427:30: sparse: sparse: incompatible types in comparison expression (different address spaces): kernel/trace/ftrace.c:6427:30: sparse: struct ftrace_hash [noderef] __rcu * kernel/trace/ftrace.c:6427:30: sparse: struct ftrace_hash * >> kernel/trace/ftrace.c:6491:55: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash *orig_hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:6506:30: sparse: sparse: incompatible types in comparison expression (different address spaces): kernel/trace/ftrace.c:6506:30: sparse: struct ftrace_hash [noderef] __rcu * kernel/trace/ftrace.c:6506:30: sparse: struct ftrace_hash * kernel/trace/ftrace.c:6807:35: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *extern [addressable] [toplevel] ftrace_graph_hash @@ got struct ftrace_hash *[assigned] hash @@ kernel/trace/ftrace.c:6809:43: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *extern [addressable] [toplevel] ftrace_graph_notrace_hash @@ got struct ftrace_hash *[assigned] hash @@ kernel/trace/ftrace.c:6878:35: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:6886:35: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash **orig_hash @@ got struct ftrace_hash [noderef] __rcu ** @@ kernel/trace/ftrace.c:6951:47: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *[addressable] [toplevel] ftrace_graph_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:6952:55: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ftrace_hash [noderef] __rcu *[addressable] [toplevel] ftrace_graph_notrace_hash @@ got struct ftrace_hash * @@ kernel/trace/ftrace.c:7671:46: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:7672:47: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:7676:44: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:7694:18: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_ops *ops @@ got struct ftrace_ops [noderef] __rcu *[addressable] [toplevel] ftrace_ops_list @@ kernel/trace/ftrace.c:7694:66: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_ops *ops @@ got struct ftrace_ops [noderef] __rcu *next @@ kernel/trace/ftrace.c:7746:59: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:7747:59: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@ kernel/trace/ftrace.c:8136:62: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@ kernel/trace/ftrace.c:8137:62: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@
kernel/trace/ftrace.c:8181:36: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/trace/ftrace.c:8181:36: sparse: struct ftrace_ops [noderef] __rcu *
kernel/trace/ftrace.c:8181:36: sparse: struct ftrace_ops *
kernel/trace/ftrace.c:8957:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@
kernel/trace/ftrace.c:8957:14: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:8957:14: sparse: got struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:9006:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@
kernel/trace/ftrace.c:9006:14: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:9006:14: sparse: got struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:230:20: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:230:20: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:230:20: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3449:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:3483:29: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:6039:30: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:6048:21: sparse: sparse: dereference of noderef expression kernel/trace/ftrace.c:6050:17: sparse: sparse: dereference of noderef expression
kernel/trace/ftrace.c:3754:48: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *filter_hash @@
kernel/trace/ftrace.c:3754:48: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:3754:48: sparse: got struct ftrace_hash [noderef] __rcu *filter_hash
kernel/trace/ftrace.c:3755:49: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct ftrace_hash *hash @@ got struct ftrace_hash [noderef] __rcu *notrace_hash @@
kernel/trace/ftrace.c:3755:49: sparse: expected struct ftrace_hash *hash
kernel/trace/ftrace.c:3755:49: sparse: got struct ftrace_hash [noderef] __rcu *notrace_hash
vim +6491 kernel/trace/ftrace.c
6488
6489 int update_ftrace_direct_mod(struct ftrace_ops *ops, struct ftrace_hash *hash, bool do_direct_lock)
6490 {
> 6491 struct ftrace_hash *orig_hash = ops->func_hash->filter_hash;
6492 struct ftrace_func_entry *entry, *tmp;
6493 static struct ftrace_ops tmp_ops = {
6494 .func = ftrace_stub,
6495 .flags = FTRACE_OPS_FL_STUB,
6496 };
6497 unsigned long size, i;
6498 int err;
6499
6500 if (!hash_count(hash))
6501 return -EINVAL;
6502 if (check_direct_multi(ops))
6503 return -EINVAL;
6504 if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
6505 return -EINVAL;
6506 if (direct_functions == EMPTY_HASH)
6507 return -EINVAL;
6508
6509 if (do_direct_lock)
6510 mutex_lock(&direct_mutex);
6511
6512 /* Enable the tmp_ops to have the same functions as the direct ops */
6513 ftrace_ops_init(&tmp_ops);
6514 tmp_ops.func_hash = ops->func_hash;
6515
6516 err = register_ftrace_function_nolock(&tmp_ops);
6517 if (err)
6518 goto unlock;
6519
6520 /*
6521 * Call __ftrace_hash_update_ipmodify() here, so that we can call
6522 * ops->ops_func for the ops. This is needed because the above
6523 * register_ftrace_function_nolock() worked on tmp_ops.
6524 */
6525 err = __ftrace_hash_update_ipmodify(ops, orig_hash, orig_hash, true);
6526 if (err)
6527 goto out;
6528
6529 /*
6530 * Now the ftrace_ops_list_func() is called to do the direct callers.
6531 * We can safely change the direct functions attached to each entry.
6532 */
6533 mutex_lock(&ftrace_lock);
6534
6535 size = 1 << hash->size_bits;
6536 for (i = 0; i < size; i++) {
6537 hlist_for_each_entry(entry, &hash->buckets[i], hlist) {
6538 tmp = __ftrace_lookup_ip(direct_functions, entry->ip);
6539 if (!tmp)
6540 continue;
6541 tmp->direct = entry->direct;
6542 }
6543 }
6544
6545 mutex_unlock(&ftrace_lock);
6546
6547 out:
6548 /* Removing the tmp_ops will add the updated direct callers to the functions */
6549 unregister_ftrace_function(&tmp_ops);
6550
6551 unlock:
6552 if (do_direct_lock)
6553 mutex_unlock(&direct_mutex);
6554 return err;
6555 }
6556
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Jiri Olsa
reviewerPATCH v3 6/8 bpf: Add trampoline ip hash table
In reply to Jiri OlsaFollowing changes need to lookup trampoline based on its ip address, adding hash table for that.
--- include/linux/bpf.h | 7 +++++-- kernel/bpf/trampoline.c | 30 +++++++++++++++++++----------- 2 files changed, 24 insertions(+), 13 deletions(-)
include/linux/bpf.h +5 -2
@@ -1295,14 +1295,17 @@ struct bpf_tramp_image { };struct bpf_trampoline { -/* hlist for trampoline_table */ -struct hlist_node hlist; +/* hlist for trampoline_key_table */ +struct hlist_node hlist_key; +/* hlist for trampoline_ip_table */ +struct hlist_node hlist_ip;struct ftrace_ops *fops;/* serializes access to fields of this trampoline */ struct mutex mutex;refcount_t refcnt;u32 flags;u64 key; +unsigned long ip;struct {struct btf_func_model model;void *addr;
kernel/bpf/trampoline.c +19 -11
@@ -24,9 +24,10 @@ const struct bpf_prog_ops bpf_extension_prog_ops = {#define TRAMPOLINE_HASH_BITS 10#define TRAMPOLINE_TABLE_SIZE (1 << TRAMPOLINE_HASH_BITS) -static struct hlist_head trampoline_table[TRAMPOLINE_TABLE_SIZE ]; +static struct hlist_head trampoline_key_table[TRAMPOLINE_TABLE_SIZE ]; +static struct hlist_head trampoline_ip_table[TRAMPOLINE_TABLE_SIZE ]; -/* serializes access to trampoline_table */ +/* serializes access to trampoline tables */ static DEFINE_MUTEX (trampoline_mutex);#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
@@ -135,15 +136,15 @@ void bpf_image_ksym_del(struct bpf_ksym *ksym) PAGE_SIZE, true, ksym->name); } -static struct bpf_trampoline *bpf_trampoline_lookup (u64 key) +static struct bpf_trampoline *bpf_trampoline_lookup (u64 key,unsigned long ip) {struct bpf_trampoline *tr;struct hlist_head *head;int i;mutex_lock (&trampoline_mutex); - head = &trampoline_table[hash_64 (key,TRAMPOLINE_HASH_BITS )]; -hlist_for_each_entry (tr, head, hlist) { + head = &trampoline_key_table[hash_64 (key,TRAMPOLINE_HASH_BITS )]; +hlist_for_each_entry (tr, head, hlist_key) {if (tr->key == key) {refcount_inc (&tr->refcnt); goto out;
@@ -164,8 +165,12 @@ static struct bpf_trampoline *bpf_trampoline_lookup(u64 key)#endif tr->key = key; -INIT_HLIST_NODE (&tr->hlist); -hlist_add_head (&tr->hlist, head); + tr->ip =ftrace_location (ip); +INIT_HLIST_NODE (&tr->hlist_key); +INIT_HLIST_NODE (&tr->hlist_ip); +hlist_add_head (&tr->hlist_key, head); + head = &trampoline_ip_table[hash_64 (tr->ip,TRAMPOLINE_HASH_BITS )]; +hlist_add_head (&tr->hlist_ip, head);refcount_set (&tr->refcnt,1 );mutex_init (&tr->mutex);for (i =0 ; i <BPF_TRAMP_MAX ; i++)
@@ -801,7 +806,7 @@ void bpf_trampoline_unlink_cgroup_shim(struct bpf_prog *prog) prog->aux->attach_btf_id);bpf_lsm_find_cgroup_shim (prog, &bpf_func); - tr =bpf_trampoline_lookup (key); + tr =bpf_trampoline_lookup (key,0 );if (WARN_ON_ONCE (!tr))return ;
@@ -821,7 +826,7 @@ struct bpf_trampoline *bpf_trampoline_get(u64 key, {struct bpf_trampoline *tr; - tr =bpf_trampoline_lookup (key); + tr =bpf_trampoline_lookup (key, tgt_info->tgt_addr);if (!tr)return NULL ;
@@ -857,7 +862,8 @@ void bpf_trampoline_put(struct bpf_trampoline *tr)* fexit progs. The fentry-only trampoline will be freed via * multiple rcu callbacks. */ -hlist_del (&tr->hlist); +hlist_del (&tr->hlist_key); +hlist_del (&tr->hlist_ip);if (tr->fops) {ftrace_free_filter (tr->fops);kfree (tr->fops);
@@ -1130,7 +1136,9 @@ static int __init init_trampolines(void)int i;for (i =0 ; i <TRAMPOLINE_TABLE_SIZE ; i++) -INIT_HLIST_HEAD (&trampoline_table[i]); +INIT_HLIST_HEAD (&trampoline_key_table[i]); +for (i =0 ; i <TRAMPOLINE_TABLE_SIZE ; i++) +INIT_HLIST_HEAD (&trampoline_ip_table[i]);return 0 ; }late_initcall (init_trampolines);
Signature · 1 line
2.51.1
Jiri Olsa
reviewerPATCH v3 7/8 ftrace: Factor ftrace_ops ops_func interface
In reply to Jiri OlsaWe are going to remove "ftrace_ops->private == bpf_trampoline" setup in following changes.
Adding ip argument to ftrace_ops_func_t callback function, so we can use it to look up the trampoline.
--- include/linux/ftrace.h | 2 +- kernel/bpf/trampoline.c | 3 ++- kernel/trace/ftrace.c | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-)
include/linux/ftrace.h +1 -1
@@ -402,7 +402,7 @@ enum ftrace_ops_cmd {* Negative on failure. The return value is dependent on the * callback. */ -typedef int (*ftrace_ops_func_t )(struct ftrace_ops *op,enum ftrace_ops_cmd cmd); +typedef int (*ftrace_ops_func_t )(struct ftrace_ops *op,unsigned long ip,enum ftrace_ops_cmd cmd);#ifdef CONFIG_DYNAMIC_FTRACE
kernel/bpf/trampoline.c +2 -1
@@ -33,7 +33,8 @@ static DEFINE_MUTEX(trampoline_mutex);#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS static int bpf_trampoline_update (struct bpf_trampoline *tr,bool lock_direct_mutex); -static int bpf_tramp_ftrace_ops_func (struct ftrace_ops *ops,enum ftrace_ops_cmd cmd) +static int bpf_tramp_ftrace_ops_func (struct ftrace_ops *ops,unsigned long ip, +enum ftrace_ops_cmd cmd) {struct bpf_trampoline *tr = ops->private;int ret =0 ;
kernel/trace/ftrace.c +3 -3
@@ -2049,7 +2049,7 @@ static int __ftrace_hash_update_ipmodify(struct ftrace_ops *ops,*/ if (!ops->ops_func)return -EBUSY ; - ret = ops->ops_func (ops,FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_SELF ); + ret = ops->ops_func (ops, rec->ip,FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_SELF );if (ret)return ret; }else if (is_ipmodify) {
@@ -8976,7 +8976,7 @@ static int prepare_direct_functions_for_ipmodify(struct ftrace_ops *ops)if (!op->ops_func)return -EBUSY ; - ret = op->ops_func (op,FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER ); + ret = op->ops_func (op, ip,FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER );if (ret)return ret; }
@@ -9023,7 +9023,7 @@ static void cleanup_direct_functions_after_ipmodify(struct ftrace_ops *ops)/* The cleanup is optional, ignore any errors */ if (found_op && op->ops_func) - op->ops_func (op,FTRACE_OPS_CMD_DISABLE_SHARE_IPMODIFY_PEER ); + op->ops_func (op, ip,FTRACE_OPS_CMD_DISABLE_SHARE_IPMODIFY_PEER ); } }mutex_unlock (&direct_mutex);
Signature · 1 line
2.51.1
Jiri Olsa
reviewerPATCH v3 8/8 bpf, x86: Use single ftrace_ops for direct calls
In reply to Jiri OlsaUsing single ftrace_ops for direct calls update instead of allocating ftrace_ops object for each trampoline.
With single ftrace_ops object we can use update_ftrace_direct_* api that allows multiple ip sites updates on single ftrace_ops object.
Adding HAVE_SINGLE_FTRACE_DIRECT_OPS config option to be enabled on each arch that supports this.
At the moment we can enable this only on x86 arch, because arm relies on ftrace_ops object representing just single trampoline image (stored in ftrace_ops::direct_call). Ach that do not support this will continue to use *_ftrace_direct api.
--- arch/x86/Kconfig | 1 + kernel/bpf/trampoline.c | 172 +++++++++++++++++++++++++++++++++++----- kernel/trace/Kconfig | 3 + kernel/trace/ftrace.c | 7 +- 4 files changed, 164 insertions(+), 19 deletions(-)
arch/x86/Kconfig +1 -0
@@ -332,6 +332,7 @@ config X86 select SCHED_SMT if SMP select ARCH_SUPPORTS_SCHED_CLUSTER if SMP select ARCH_SUPPORTS_SCHED_MC if SMP + select HAVE_SINGLE_FTRACE_DIRECT_OPS if X86_64 && DYNAMIC_FTRACE_WITH_DIRECT_CALLS config INSTRUCTION_DECODER def_bool y
kernel/bpf/trampoline.c +154 -18
223 lines not on this page · raw message
kernel/trace/Kconfig +3 -0
@@ -50,6 +50,9 @@ config HAVE_DYNAMIC_FTRACE_WITH_REGS config HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS bool +config HAVE_SINGLE_FTRACE_DIRECT_OPS + bool + config HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS bool
kernel/trace/ftrace.c +6 -1
@@ -2605,8 +2605,13 @@ unsigned long ftrace_find_rec_direct(unsigned long ip)static void call_direct_funcs (unsigned long ip,unsigned long pip,struct ftrace_ops *ops,struct ftrace_regs *fregs) { -unsigned long addr =READ_ONCE (ops->direct_call); +unsigned long addr; +#ifdef CONFIG_HAVE_SINGLE_FTRACE_DIRECT_OPS + addr =ftrace_find_rec_direct (ip); +#else + addr =READ_ONCE (ops->direct_call); +#endif if (!addr)return ;
Signature · 1 line
2.51.1
kernel test robot
build botRe: [PATCHv3 bpf-next 8/8] bpf, x86: Use single ftrace_ops for direct calls
kernel test robot noticed the following build errors:
Hi Jiri,
kernel test robot noticed the following build errors:
[auto build test ERROR on bpf-next/master]
url: https://github.com/intel-lab-lkp/linux/commits/Jiri-Olsa/ftrace-Make-alloc_and_copy_ftrace_hash-direct-friendly/20251121-052934 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master patch link: https://lore.kernel.org/r/20251120212402.466524-9-jolsa%40kernel.org patch subject: [PATCHv3 bpf-next 8/8] bpf, x86: Use single ftrace_ops for direct calls config: i386-randconfig-141-20251121 (https://download.01.org/0day-ci/archive/20251122/[email protected]/config) compiler: gcc-14 (Debian 14.2.0-19) 14.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251122/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
kernel/bpf/trampoline.c: In function 'unregister_fentry':
>> kernel/bpf/trampoline.c:335:23: error: implicit declaration of function 'direct_ops_del'; did you mean 'direct_ops_free'? [-Wimplicit-function-declaration]
335 | ret = direct_ops_del(tr->fops, tr->ip, old_addr);
| ^~~~~~~~~~~~~~
| direct_ops_free
kernel/bpf/trampoline.c: In function 'modify_fentry':
>> kernel/bpf/trampoline.c:349:23: error: implicit declaration of function 'direct_ops_mod'; did you mean 'direct_ops_free'? [-Wimplicit-function-declaration]
349 | ret = direct_ops_mod(tr->fops, tr->ip, new_addr, lock_direct_mutex);
| ^~~~~~~~~~~~~~
| direct_ops_free
kernel/bpf/trampoline.c: In function 'register_fentry':
>> kernel/bpf/trampoline.c:371:23: error: implicit declaration of function 'direct_ops_add'; did you mean 'direct_ops_free'? [-Wimplicit-function-declaration]
371 | ret = direct_ops_add(tr->fops, tr->ip, new_addr);
| ^~~~~~~~~~~~~~
| direct_ops_freevim +335 kernel/bpf/trampoline.c
328
329 static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr)
330 {
331 void *ip = tr->func.addr;
332 int ret;
333
334 if (tr->func.ftrace_managed)
> 335 ret = direct_ops_del(tr->fops, tr->ip, old_addr);
336 else
337 ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, NULL);
338
339 return ret;
340 }
341
342 static int modify_fentry(struct bpf_trampoline *tr, void *old_addr, void *new_addr,
343 bool lock_direct_mutex)
344 {
345 void *ip = tr->func.addr;
346 int ret;
347
348 if (tr->func.ftrace_managed) {
> 349 ret = direct_ops_mod(tr->fops, tr->ip, new_addr, lock_direct_mutex);
350 } else {
351 ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, new_addr);
352 }
353 return ret;
354 }
355
356 /* first time registering */
357 static int register_fentry(struct bpf_trampoline *tr, void *new_addr)
358 {
359 void *ip = tr->func.addr;
360 unsigned long faddr;
361 int ret;
362
363 faddr = ftrace_location((unsigned long)ip);
364 if (faddr) {
365 if (!tr->fops)
366 return -ENOTSUPP;
367 tr->func.ftrace_managed = true;
368 }
369
370 if (tr->func.ftrace_managed) {
> 371 ret = direct_ops_add(tr->fops, tr->ip, new_addr); 372 } else {
373 ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, NULL, new_addr);
374 }
375
376 return ret;
377 }
378
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki