Message ID | 20220718001405.2236811-3-song@kernel.org (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | ftrace: host klp and bpf trampoline together | expand |
Hi Song, I love your patch! Yet something to improve: [auto build test ERROR on bpf-next/master] url: https://github.com/intel-lab-lkp/linux/commits/Song-Liu/ftrace-host-klp-and-bpf-trampoline-together/20220718-081533 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master config: x86_64-randconfig-a006 (https://download.01.org/0day-ci/archive/20220718/202207181033.RY6WO0I5-lkp@intel.com/config) compiler: gcc-11 (Debian 11.3.0-3) 11.3.0 reproduce (this is a W=1 build): # https://github.com/intel-lab-lkp/linux/commit/1535f287d288f9b7540ec50f56da1fe437ac6512 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Song-Liu/ftrace-host-klp-and-bpf-trampoline-together/20220718-081533 git checkout 1535f287d288f9b7540ec50f56da1fe437ac6512 # save the config file mkdir build_dir && cp config build_dir/.config make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): In file included from include/linux/rhashtable-types.h:14, from include/linux/ipc.h:7, from include/uapi/linux/sem.h:5, from include/linux/sem.h:5, from include/linux/sched.h:15, from include/linux/ratelimit.h:6, from include/linux/dev_printk.h:16, from include/linux/device.h:15, from include/linux/node.h:18, from include/linux/cpu.h:17, from include/linux/stop_machine.h:5, from kernel/trace/ftrace.c:17: kernel/trace/ftrace.c: In function 'prepare_direct_functions_for_ipmodify': >> kernel/trace/ftrace.c:8082:21: error: 'direct_mutex' undeclared (first use in this function); did you mean 'event_mutex'? 8082 | mutex_lock(&direct_mutex); | ^~~~~~~~~~~~ include/linux/mutex.h:187:44: note: in definition of macro 'mutex_lock' 187 | #define mutex_lock(lock) mutex_lock_nested(lock, 0) | ^~~~ kernel/trace/ftrace.c:8082:21: note: each undeclared identifier is reported only once for each function it appears in 8082 | mutex_lock(&direct_mutex); | ^~~~~~~~~~~~ include/linux/mutex.h:187:44: note: in definition of macro 'mutex_lock' 187 | #define mutex_lock(lock) mutex_lock_nested(lock, 0) | ^~~~ >> kernel/trace/ftrace.c:8084:19: error: 'struct ftrace_ops' has no member named 'func_hash' 8084 | hash = ops->func_hash->filter_hash; | ^~ >> kernel/trace/ftrace.c:8095:37: error: implicit declaration of function 'ops_references_ip' [-Werror=implicit-function-declaration] 8095 | if (ops_references_ip(op, ip)) { | ^~~~~~~~~~~~~~~~~ >> kernel/trace/ftrace.c:8103:40: error: 'struct ftrace_ops' has no member named 'ops_func' 8103 | if (!op->ops_func) { | ^~ kernel/trace/ftrace.c:8107:41: error: 'struct ftrace_ops' has no member named 'ops_func' 8107 | ret = op->ops_func(op, FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER); | ^~ kernel/trace/ftrace.c: In function 'register_ftrace_function': kernel/trace/ftrace.c:8158:31: error: 'direct_mutex' undeclared (first use in this function); did you mean 'event_mutex'? 8158 | mutex_unlock(&direct_mutex); | ^~~~~~~~~~~~ | event_mutex In file included from include/linux/rhashtable-types.h:14, from include/linux/ipc.h:7, from include/uapi/linux/sem.h:5, from include/linux/sem.h:5, from include/linux/sched.h:15, from include/linux/ratelimit.h:6, from include/linux/dev_printk.h:16, from include/linux/device.h:15, from include/linux/node.h:18, from include/linux/cpu.h:17, from include/linux/stop_machine.h:5, from kernel/trace/ftrace.c:17: kernel/trace/ftrace.c: In function 'cleanup_direct_functions_after_ipmodify': kernel/trace/ftrace.c:8178:21: error: 'direct_mutex' undeclared (first use in this function); did you mean 'event_mutex'? 8178 | mutex_lock(&direct_mutex); | ^~~~~~~~~~~~ include/linux/mutex.h:187:44: note: in definition of macro 'mutex_lock' 187 | #define mutex_lock(lock) mutex_lock_nested(lock, 0) | ^~~~ kernel/trace/ftrace.c:8180:19: error: 'struct ftrace_ops' has no member named 'func_hash' 8180 | hash = ops->func_hash->filter_hash; | ^~ kernel/trace/ftrace.c:8199:43: error: 'struct ftrace_ops' has no member named 'ops_func' 8199 | if (found_op && op->ops_func) | ^~ kernel/trace/ftrace.c:8200:35: error: 'struct ftrace_ops' has no member named 'ops_func' 8200 | op->ops_func(op, FTRACE_OPS_CMD_DISABLE_SHARE_IPMODIFY_PEER); | ^~ cc1: some warnings being treated as errors vim +8082 kernel/trace/ftrace.c 8051 8052 /* 8053 * When registering ftrace_ops with IPMODIFY, it is necessary to make sure 8054 * it doesn't conflict with any direct ftrace_ops. If there is existing 8055 * direct ftrace_ops on a kernel function being patched, call 8056 * FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER on it to enable sharing. 8057 * 8058 * @ops: ftrace_ops being registered. 8059 * 8060 * Returns: 8061 * 0 - @ops does not have IPMODIFY or @ops itself is DIRECT, no 8062 * change needed; 8063 * 1 - @ops has IPMODIFY, hold direct_mutex; 8064 * -EBUSY - currently registered DIRECT ftrace_ops cannot share the 8065 * same function with IPMODIFY, abort the register. 8066 * -EAGAIN - cannot make changes to currently registered DIRECT 8067 * ftrace_ops due to rare race conditions. Should retry 8068 * later. This is needed to avoid potential deadlocks 8069 * on the DIRECT ftrace_ops side. 8070 */ 8071 static int prepare_direct_functions_for_ipmodify(struct ftrace_ops *ops) 8072 __acquires(&direct_mutex) 8073 { 8074 struct ftrace_func_entry *entry; 8075 struct ftrace_hash *hash; 8076 struct ftrace_ops *op; 8077 int size, i, ret; 8078 8079 if (!(ops->flags & FTRACE_OPS_FL_IPMODIFY)) 8080 return 0; 8081 > 8082 mutex_lock(&direct_mutex); 8083 > 8084 hash = ops->func_hash->filter_hash; 8085 size = 1 << hash->size_bits; 8086 for (i = 0; i < size; i++) { 8087 hlist_for_each_entry(entry, &hash->buckets[i], hlist) { 8088 unsigned long ip = entry->ip; 8089 bool found_op = false; 8090 8091 mutex_lock(&ftrace_lock); 8092 do_for_each_ftrace_op(op, ftrace_ops_list) { 8093 if (!(op->flags & FTRACE_OPS_FL_DIRECT)) 8094 continue; > 8095 if (ops_references_ip(op, ip)) { 8096 found_op = true; 8097 break; 8098 } 8099 } while_for_each_ftrace_op(op); 8100 mutex_unlock(&ftrace_lock); 8101 8102 if (found_op) { > 8103 if (!op->ops_func) { 8104 ret = -EBUSY; 8105 goto err_out; 8106 } 8107 ret = op->ops_func(op, FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER); 8108 if (ret) 8109 goto err_out; 8110 } 8111 } 8112 } 8113 8114 /* 8115 * Didn't find any overlap with direct ftrace_ops, or the direct 8116 * function can share with ipmodify. Hold direct_mutex to make sure 8117 * this doesn't change until we are done. 8118 */ 8119 return 1; 8120 8121 err_out: 8122 mutex_unlock(&direct_mutex); 8123 return ret; 8124 } 8125
Hi Song, I love your patch! Yet something to improve: [auto build test ERROR on bpf-next/master] url: https://github.com/intel-lab-lkp/linux/commits/Song-Liu/ftrace-host-klp-and-bpf-trampoline-together/20220718-081533 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master config: powerpc-randconfig-r023-20220717 (https://download.01.org/0day-ci/archive/20220718/202207181116.PO2cQ09B-lkp@intel.com/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project d74b88c69dc2644bd0dc5d64e2d7413a0d4040e5) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install powerpc cross compiling tool for clang build # apt-get install binutils-powerpc-linux-gnu # https://github.com/intel-lab-lkp/linux/commit/1535f287d288f9b7540ec50f56da1fe437ac6512 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Song-Liu/ftrace-host-klp-and-bpf-trampoline-together/20220718-081533 git checkout 1535f287d288f9b7540ec50f56da1fe437ac6512 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=powerpc SHELL=/bin/bash kernel/trace/ If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): kernel/trace/ftrace.c:299:5: warning: no previous prototype for function '__register_ftrace_function' [-Wmissing-prototypes] int __register_ftrace_function(struct ftrace_ops *ops) ^ kernel/trace/ftrace.c:299:1: note: declare 'static' if the function is not intended to be used outside of this translation unit int __register_ftrace_function(struct ftrace_ops *ops) ^ static kernel/trace/ftrace.c:342:5: warning: no previous prototype for function '__unregister_ftrace_function' [-Wmissing-prototypes] int __unregister_ftrace_function(struct ftrace_ops *ops) ^ kernel/trace/ftrace.c:342:1: note: declare 'static' if the function is not intended to be used outside of this translation unit int __unregister_ftrace_function(struct ftrace_ops *ops) ^ static kernel/trace/ftrace.c:4030:15: warning: no previous prototype for function 'arch_ftrace_match_adjust' [-Wmissing-prototypes] char * __weak arch_ftrace_match_adjust(char *str, const char *search) ^ kernel/trace/ftrace.c:4030:1: note: declare 'static' if the function is not intended to be used outside of this translation unit char * __weak arch_ftrace_match_adjust(char *str, const char *search) ^ static >> kernel/trace/ftrace.c:8082:14: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? mutex_lock(&direct_mutex); ^~~~~~~~~~~~ event_mutex include/linux/mutex.h:187:44: note: expanded from macro 'mutex_lock' #define mutex_lock(lock) mutex_lock_nested(lock, 0) ^ kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here extern struct mutex event_mutex; ^ kernel/trace/ftrace.c:8122:16: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? mutex_unlock(&direct_mutex); ^~~~~~~~~~~~ event_mutex kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here extern struct mutex event_mutex; ^ kernel/trace/ftrace.c:8158:17: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? mutex_unlock(&direct_mutex); ^~~~~~~~~~~~ event_mutex kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here extern struct mutex event_mutex; ^ kernel/trace/ftrace.c:8178:14: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? mutex_lock(&direct_mutex); ^~~~~~~~~~~~ event_mutex include/linux/mutex.h:187:44: note: expanded from macro 'mutex_lock' #define mutex_lock(lock) mutex_lock_nested(lock, 0) ^ kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here extern struct mutex event_mutex; ^ kernel/trace/ftrace.c:8203:16: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? mutex_unlock(&direct_mutex); ^~~~~~~~~~~~ event_mutex kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here extern struct mutex event_mutex; ^ 3 warnings and 5 errors generated. vim +8082 kernel/trace/ftrace.c 8051 8052 /* 8053 * When registering ftrace_ops with IPMODIFY, it is necessary to make sure 8054 * it doesn't conflict with any direct ftrace_ops. If there is existing 8055 * direct ftrace_ops on a kernel function being patched, call 8056 * FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER on it to enable sharing. 8057 * 8058 * @ops: ftrace_ops being registered. 8059 * 8060 * Returns: 8061 * 0 - @ops does not have IPMODIFY or @ops itself is DIRECT, no 8062 * change needed; 8063 * 1 - @ops has IPMODIFY, hold direct_mutex; 8064 * -EBUSY - currently registered DIRECT ftrace_ops cannot share the 8065 * same function with IPMODIFY, abort the register. 8066 * -EAGAIN - cannot make changes to currently registered DIRECT 8067 * ftrace_ops due to rare race conditions. Should retry 8068 * later. This is needed to avoid potential deadlocks 8069 * on the DIRECT ftrace_ops side. 8070 */ 8071 static int prepare_direct_functions_for_ipmodify(struct ftrace_ops *ops) 8072 __acquires(&direct_mutex) 8073 { 8074 struct ftrace_func_entry *entry; 8075 struct ftrace_hash *hash; 8076 struct ftrace_ops *op; 8077 int size, i, ret; 8078 8079 if (!(ops->flags & FTRACE_OPS_FL_IPMODIFY)) 8080 return 0; 8081 > 8082 mutex_lock(&direct_mutex); 8083 8084 hash = ops->func_hash->filter_hash; 8085 size = 1 << hash->size_bits; 8086 for (i = 0; i < size; i++) { 8087 hlist_for_each_entry(entry, &hash->buckets[i], hlist) { 8088 unsigned long ip = entry->ip; 8089 bool found_op = false; 8090 8091 mutex_lock(&ftrace_lock); 8092 do_for_each_ftrace_op(op, ftrace_ops_list) { 8093 if (!(op->flags & FTRACE_OPS_FL_DIRECT)) 8094 continue; 8095 if (ops_references_ip(op, ip)) { 8096 found_op = true; 8097 break; 8098 } 8099 } while_for_each_ftrace_op(op); 8100 mutex_unlock(&ftrace_lock); 8101 8102 if (found_op) { 8103 if (!op->ops_func) { 8104 ret = -EBUSY; 8105 goto err_out; 8106 } 8107 ret = op->ops_func(op, FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER); 8108 if (ret) 8109 goto err_out; 8110 } 8111 } 8112 } 8113 8114 /* 8115 * Didn't find any overlap with direct ftrace_ops, or the direct 8116 * function can share with ipmodify. Hold direct_mutex to make sure 8117 * this doesn't change until we are done. 8118 */ 8119 return 1; 8120 8121 err_out: 8122 mutex_unlock(&direct_mutex); 8123 return ret; 8124 } 8125
Hi Song, I love your patch! Yet something to improve: [auto build test ERROR on bpf-next/master] url: https://github.com/intel-lab-lkp/linux/commits/Song-Liu/ftrace-host-klp-and-bpf-trampoline-together/20220718-081533 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master config: x86_64-randconfig-a001 (https://download.01.org/0day-ci/archive/20220718/202207181140.tqIgD0Jp-lkp@intel.com/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project d74b88c69dc2644bd0dc5d64e2d7413a0d4040e5) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/1535f287d288f9b7540ec50f56da1fe437ac6512 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Song-Liu/ftrace-host-klp-and-bpf-trampoline-together/20220718-081533 git checkout 1535f287d288f9b7540ec50f56da1fe437ac6512 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): >> kernel/trace/ftrace.c:8082:14: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? mutex_lock(&direct_mutex); ^~~~~~~~~~~~ event_mutex include/linux/mutex.h:187:44: note: expanded from macro 'mutex_lock' #define mutex_lock(lock) mutex_lock_nested(lock, 0) ^ kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here extern struct mutex event_mutex; ^ >> kernel/trace/ftrace.c:8084:14: error: no member named 'func_hash' in 'struct ftrace_ops' hash = ops->func_hash->filter_hash; ~~~ ^ >> kernel/trace/ftrace.c:8095:9: error: call to undeclared function 'ops_references_ip'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] if (ops_references_ip(op, ip)) { ^ >> kernel/trace/ftrace.c:8103:14: error: no member named 'ops_func' in 'struct ftrace_ops' if (!op->ops_func) { ~~ ^ kernel/trace/ftrace.c:8107:15: error: no member named 'ops_func' in 'struct ftrace_ops' ret = op->ops_func(op, FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER); ~~ ^ kernel/trace/ftrace.c:8122:16: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? mutex_unlock(&direct_mutex); ^~~~~~~~~~~~ event_mutex kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here extern struct mutex event_mutex; ^ kernel/trace/ftrace.c:8158:17: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? mutex_unlock(&direct_mutex); ^~~~~~~~~~~~ event_mutex kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here extern struct mutex event_mutex; ^ kernel/trace/ftrace.c:8178:14: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? mutex_lock(&direct_mutex); ^~~~~~~~~~~~ event_mutex include/linux/mutex.h:187:44: note: expanded from macro 'mutex_lock' #define mutex_lock(lock) mutex_lock_nested(lock, 0) ^ kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here extern struct mutex event_mutex; ^ kernel/trace/ftrace.c:8180:14: error: no member named 'func_hash' in 'struct ftrace_ops' hash = ops->func_hash->filter_hash; ~~~ ^ kernel/trace/ftrace.c:8191:9: error: call to undeclared function 'ops_references_ip'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] if (ops_references_ip(op, ip)) { ^ kernel/trace/ftrace.c:8199:24: error: no member named 'ops_func' in 'struct ftrace_ops' if (found_op && op->ops_func) ~~ ^ kernel/trace/ftrace.c:8200:9: error: no member named 'ops_func' in 'struct ftrace_ops' op->ops_func(op, FTRACE_OPS_CMD_DISABLE_SHARE_IPMODIFY_PEER); ~~ ^ kernel/trace/ftrace.c:8203:16: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? mutex_unlock(&direct_mutex); ^~~~~~~~~~~~ event_mutex kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here extern struct mutex event_mutex; ^ 13 errors generated. vim +8082 kernel/trace/ftrace.c 8051 8052 /* 8053 * When registering ftrace_ops with IPMODIFY, it is necessary to make sure 8054 * it doesn't conflict with any direct ftrace_ops. If there is existing 8055 * direct ftrace_ops on a kernel function being patched, call 8056 * FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER on it to enable sharing. 8057 * 8058 * @ops: ftrace_ops being registered. 8059 * 8060 * Returns: 8061 * 0 - @ops does not have IPMODIFY or @ops itself is DIRECT, no 8062 * change needed; 8063 * 1 - @ops has IPMODIFY, hold direct_mutex; 8064 * -EBUSY - currently registered DIRECT ftrace_ops cannot share the 8065 * same function with IPMODIFY, abort the register. 8066 * -EAGAIN - cannot make changes to currently registered DIRECT 8067 * ftrace_ops due to rare race conditions. Should retry 8068 * later. This is needed to avoid potential deadlocks 8069 * on the DIRECT ftrace_ops side. 8070 */ 8071 static int prepare_direct_functions_for_ipmodify(struct ftrace_ops *ops) 8072 __acquires(&direct_mutex) 8073 { 8074 struct ftrace_func_entry *entry; 8075 struct ftrace_hash *hash; 8076 struct ftrace_ops *op; 8077 int size, i, ret; 8078 8079 if (!(ops->flags & FTRACE_OPS_FL_IPMODIFY)) 8080 return 0; 8081 > 8082 mutex_lock(&direct_mutex); 8083 > 8084 hash = ops->func_hash->filter_hash; 8085 size = 1 << hash->size_bits; 8086 for (i = 0; i < size; i++) { 8087 hlist_for_each_entry(entry, &hash->buckets[i], hlist) { 8088 unsigned long ip = entry->ip; 8089 bool found_op = false; 8090 8091 mutex_lock(&ftrace_lock); 8092 do_for_each_ftrace_op(op, ftrace_ops_list) { 8093 if (!(op->flags & FTRACE_OPS_FL_DIRECT)) 8094 continue; > 8095 if (ops_references_ip(op, ip)) { 8096 found_op = true; 8097 break; 8098 } 8099 } while_for_each_ftrace_op(op); 8100 mutex_unlock(&ftrace_lock); 8101 8102 if (found_op) { > 8103 if (!op->ops_func) { 8104 ret = -EBUSY; 8105 goto err_out; 8106 } 8107 ret = op->ops_func(op, FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER); 8108 if (ret) 8109 goto err_out; 8110 } 8111 } 8112 } 8113 8114 /* 8115 * Didn't find any overlap with direct ftrace_ops, or the direct 8116 * function can share with ipmodify. Hold direct_mutex to make sure 8117 * this doesn't change until we are done. 8118 */ 8119 return 1; 8120 8121 err_out: 8122 mutex_unlock(&direct_mutex); 8123 return ret; 8124 } 8125
> On Jul 17, 2022, at 8:36 PM, kernel test robot <lkp@intel.com> wrote: > > Hi Song, > > I love your patch! Yet something to improve: > > [auto build test ERROR on bpf-next/master] > > url: https://github.com/intel-lab-lkp/linux/commits/Song-Liu/ftrace-host-klp-and-bpf-trampoline-together/20220718-081533 > base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master > config: x86_64-randconfig-a001 (https://download.01.org/0day-ci/archive/20220718/202207181140.tqIgD0Jp-lkp@intel.com/config ) > compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project d74b88c69dc2644bd0dc5d64e2d7413a0d4040e5) > reproduce (this is a W=1 build): > wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross > chmod +x ~/bin/make.cross > # https://github.com/intel-lab-lkp/linux/commit/1535f287d288f9b7540ec50f56da1fe437ac6512 > git remote add linux-review https://github.com/intel-lab-lkp/linux > git fetch --no-tags linux-review Song-Liu/ftrace-host-klp-and-bpf-trampoline-together/20220718-081533 > git checkout 1535f287d288f9b7540ec50f56da1fe437ac6512 > # save the config file > mkdir build_dir && cp config build_dir/.config > COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash > > If you fix the issue, kindly add following tag where applicable > Reported-by: kernel test robot <lkp@intel.com> > > All errors (new ones prefixed by >>): > >>> kernel/trace/ftrace.c:8082:14: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? > mutex_lock(&direct_mutex); > ^~~~~~~~~~~~ > event_mutex Folded the the fix in. I guess this should also fail on v2, but the kernel test robot didn't seem to find it. Song > include/linux/mutex.h:187:44: note: expanded from macro 'mutex_lock' > #define mutex_lock(lock) mutex_lock_nested(lock, 0) > ^ > kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here > extern struct mutex event_mutex; > ^ >>> kernel/trace/ftrace.c:8084:14: error: no member named 'func_hash' in 'struct ftrace_ops' > hash = ops->func_hash->filter_hash; > ~~~ ^ >>> kernel/trace/ftrace.c:8095:9: error: call to undeclared function 'ops_references_ip'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] > if (ops_references_ip(op, ip)) { > ^ >>> kernel/trace/ftrace.c:8103:14: error: no member named 'ops_func' in 'struct ftrace_ops' > if (!op->ops_func) { > ~~ ^ > kernel/trace/ftrace.c:8107:15: error: no member named 'ops_func' in 'struct ftrace_ops' > ret = op->ops_func(op, FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER); > ~~ ^ > kernel/trace/ftrace.c:8122:16: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? > mutex_unlock(&direct_mutex); > ^~~~~~~~~~~~ > event_mutex > kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here > extern struct mutex event_mutex; > ^ > kernel/trace/ftrace.c:8158:17: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? > mutex_unlock(&direct_mutex); > ^~~~~~~~~~~~ > event_mutex > kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here > extern struct mutex event_mutex; > ^ > kernel/trace/ftrace.c:8178:14: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? > mutex_lock(&direct_mutex); > ^~~~~~~~~~~~ > event_mutex > include/linux/mutex.h:187:44: note: expanded from macro 'mutex_lock' > #define mutex_lock(lock) mutex_lock_nested(lock, 0) > ^ > kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here > extern struct mutex event_mutex; > ^ > kernel/trace/ftrace.c:8180:14: error: no member named 'func_hash' in 'struct ftrace_ops' > hash = ops->func_hash->filter_hash; > ~~~ ^ > kernel/trace/ftrace.c:8191:9: error: call to undeclared function 'ops_references_ip'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] > if (ops_references_ip(op, ip)) { > ^ > kernel/trace/ftrace.c:8199:24: error: no member named 'ops_func' in 'struct ftrace_ops' > if (found_op && op->ops_func) > ~~ ^ > kernel/trace/ftrace.c:8200:9: error: no member named 'ops_func' in 'struct ftrace_ops' > op->ops_func(op, FTRACE_OPS_CMD_DISABLE_SHARE_IPMODIFY_PEER); > ~~ ^ > kernel/trace/ftrace.c:8203:16: error: use of undeclared identifier 'direct_mutex'; did you mean 'event_mutex'? > mutex_unlock(&direct_mutex); > ^~~~~~~~~~~~ > event_mutex > kernel/trace/trace.h:1523:21: note: 'event_mutex' declared here > extern struct mutex event_mutex; > ^ > 13 errors generated. > > > vim +8082 kernel/trace/ftrace.c > > 8051 > 8052 /* > 8053 * When registering ftrace_ops with IPMODIFY, it is necessary to make sure > 8054 * it doesn't conflict with any direct ftrace_ops. If there is existing > 8055 * direct ftrace_ops on a kernel function being patched, call > 8056 * FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER on it to enable sharing. > 8057 * > 8058 * @ops: ftrace_ops being registered. > 8059 * > 8060 * Returns: > 8061 * 0 - @ops does not have IPMODIFY or @ops itself is DIRECT, no > 8062 * change needed; > 8063 * 1 - @ops has IPMODIFY, hold direct_mutex; > 8064 * -EBUSY - currently registered DIRECT ftrace_ops cannot share the > 8065 * same function with IPMODIFY, abort the register. > 8066 * -EAGAIN - cannot make changes to currently registered DIRECT > 8067 * ftrace_ops due to rare race conditions. Should retry > 8068 * later. This is needed to avoid potential deadlocks > 8069 * on the DIRECT ftrace_ops side. > 8070 */ > 8071 static int prepare_direct_functions_for_ipmodify(struct ftrace_ops *ops) > 8072 __acquires(&direct_mutex) > 8073 { > 8074 struct ftrace_func_entry *entry; > 8075 struct ftrace_hash *hash; > 8076 struct ftrace_ops *op; > 8077 int size, i, ret; > 8078 > 8079 if (!(ops->flags & FTRACE_OPS_FL_IPMODIFY)) > 8080 return 0; > 8081 >> 8082 mutex_lock(&direct_mutex); > 8083 >> 8084 hash = ops->func_hash->filter_hash; > 8085 size = 1 << hash->size_bits; > 8086 for (i = 0; i < size; i++) { > 8087 hlist_for_each_entry(entry, &hash->buckets[i], hlist) { > 8088 unsigned long ip = entry->ip; > 8089 bool found_op = false; > 8090 > 8091 mutex_lock(&ftrace_lock); > 8092 do_for_each_ftrace_op(op, ftrace_ops_list) { > 8093 if (!(op->flags & FTRACE_OPS_FL_DIRECT)) > 8094 continue; >> 8095 if (ops_references_ip(op, ip)) { > 8096 found_op = true; > 8097 break; > 8098 } > 8099 } while_for_each_ftrace_op(op); > 8100 mutex_unlock(&ftrace_lock); > 8101 > 8102 if (found_op) { >> 8103 if (!op->ops_func) { > 8104 ret = -EBUSY; > 8105 goto err_out; > 8106 } > 8107 ret = op->ops_func(op, FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER); > 8108 if (ret) > 8109 goto err_out; > 8110 } > 8111 } > 8112 } > 8113 > 8114 /* > 8115 * Didn't find any overlap with direct ftrace_ops, or the direct > 8116 * function can share with ipmodify. Hold direct_mutex to make sure > 8117 * this doesn't change until we are done. > 8118 */ > 8119 return 1; > 8120 > 8121 err_out: > 8122 mutex_unlock(&direct_mutex); > 8123 return ret; > 8124 } > 8125 > > -- > 0-DAY CI Kernel Test Service > https://01.org/lkp
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index acb35243ce5d..306bf08acda6 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -208,6 +208,43 @@ enum { FTRACE_OPS_FL_DIRECT = BIT(17), }; +/* + * FTRACE_OPS_CMD_* commands allow the ftrace core logic to request changes + * to a ftrace_ops. Note, the requests may fail. + * + * ENABLE_SHARE_IPMODIFY_SELF - enable a DIRECT ops to work on the same + * function as an ops with IPMODIFY. Called + * when the DIRECT ops is being registered. + * This is called with both direct_mutex and + * ftrace_lock are locked. + * + * ENABLE_SHARE_IPMODIFY_PEER - enable a DIRECT ops to work on the same + * function as an ops with IPMODIFY. Called + * when the other ops (the one with IPMODIFY) + * is being registered. + * This is called with direct_mutex locked. + * + * DISABLE_SHARE_IPMODIFY_PEER - disable a DIRECT ops to work on the same + * function as an ops with IPMODIFY. Called + * when the other ops (the one with IPMODIFY) + * is being unregistered. + * This is called with direct_mutex locked. + */ +enum ftrace_ops_cmd { + FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_SELF, + FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER, + FTRACE_OPS_CMD_DISABLE_SHARE_IPMODIFY_PEER, +}; + +/* + * For most ftrace_ops_cmd, + * Returns: + * 0 - Success. + * -EBUSY - The operation cannot process + * -EAGAIN - The operation cannot process tempoorarily. + */ +typedef int (*ftrace_ops_func_t)(struct ftrace_ops *op, enum ftrace_ops_cmd cmd); + #ifdef CONFIG_DYNAMIC_FTRACE /* The hash used to know what functions callbacks trace */ struct ftrace_ops_hash { @@ -250,6 +287,7 @@ struct ftrace_ops { unsigned long trampoline; unsigned long trampoline_size; struct list_head list; + ftrace_ops_func_t ops_func; #endif }; diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 0c15ec997c13..aa39c3d8c565 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1861,6 +1861,8 @@ static void ftrace_hash_rec_enable_modify(struct ftrace_ops *ops, ftrace_hash_rec_update_modify(ops, filter_hash, 1); } +static bool ops_references_ip(struct ftrace_ops *ops, unsigned long ip); + /* * Try to update IPMODIFY flag on each ftrace_rec. Return 0 if it is OK * or no-needed to update, -EBUSY if it detects a conflict of the flag @@ -1869,6 +1871,13 @@ static void ftrace_hash_rec_enable_modify(struct ftrace_ops *ops, * - If the hash is NULL, it hits all recs (if IPMODIFY is set, this is rejected) * - If the hash is EMPTY_HASH, it hits nothing * - Anything else hits the recs which match the hash entries. + * + * DIRECT ops does not have IPMODIFY flag, but we still need to check it + * against functions with FTRACE_FL_IPMODIFY. If there is any overlap, call + * ops_func(SHARE_IPMODIFY_SELF) to make sure current ops can share with + * IPMODIFY. If ops_func(SHARE_IPMODIFY_SELF) returns non-zero, propagate + * the return value to the caller and eventually to the owner of the DIRECT + * ops. */ static int __ftrace_hash_update_ipmodify(struct ftrace_ops *ops, struct ftrace_hash *old_hash, @@ -1877,17 +1886,23 @@ static int __ftrace_hash_update_ipmodify(struct ftrace_ops *ops, struct ftrace_page *pg; struct dyn_ftrace *rec, *end = NULL; int in_old, in_new; + bool is_ipmodify, is_direct; /* Only update if the ops has been registered */ if (!(ops->flags & FTRACE_OPS_FL_ENABLED)) return 0; - if (!(ops->flags & FTRACE_OPS_FL_IPMODIFY)) + is_ipmodify = ops->flags & FTRACE_OPS_FL_IPMODIFY; + is_direct = ops->flags & FTRACE_OPS_FL_DIRECT; + + /* either IPMODIFY nor DIRECT, skip */ + if (!is_ipmodify && !is_direct) return 0; /* - * Since the IPMODIFY is a very address sensitive action, we do not - * allow ftrace_ops to set all functions to new hash. + * Since the IPMODIFY and DIRECT are very address sensitive + * actions, we do not allow ftrace_ops to set all functions to new + * hash. */ if (!new_hash || !old_hash) return -EINVAL; @@ -1905,12 +1920,30 @@ static int __ftrace_hash_update_ipmodify(struct ftrace_ops *ops, continue; if (in_new) { - /* New entries must ensure no others are using it */ - if (rec->flags & FTRACE_FL_IPMODIFY) - goto rollback; - rec->flags |= FTRACE_FL_IPMODIFY; - } else /* Removed entry */ + if (rec->flags & FTRACE_FL_IPMODIFY) { + int ret; + + /* Cannot have two ipmodify on same rec */ + if (is_ipmodify) + goto rollback; + + /* + * Another ops with IPMODIFY is already + * attached. We are now attaching a direct + * ops. Run SHARE_IPMODIFY_SELF, to check + * whether sharing is supported. + */ + if (!ops->ops_func) + return -EBUSY; + ret = ops->ops_func(ops, FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_SELF); + if (ret) + return ret; + } else if (is_ipmodify) { + rec->flags |= FTRACE_FL_IPMODIFY; + } + } else if (is_ipmodify) { rec->flags &= ~FTRACE_FL_IPMODIFY; + } } while_for_each_ftrace_rec(); return 0; @@ -2455,7 +2488,7 @@ static void call_direct_funcs(unsigned long ip, unsigned long pip, struct ftrace_ops direct_ops = { .func = call_direct_funcs, .flags = FTRACE_OPS_FL_IPMODIFY - | FTRACE_OPS_FL_DIRECT | FTRACE_OPS_FL_SAVE_REGS + | FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_PERMANENT, /* * By declaring the main trampoline as this trampoline @@ -3072,14 +3105,14 @@ static inline int ops_traces_mod(struct ftrace_ops *ops) } /* - * Check if the current ops references the record. + * Check if the current ops references the given ip. * * If the ops traces all functions, then it was already accounted for. * If the ops does not trace the current record function, skip it. * If the ops ignores the function via notrace filter, skip it. */ -static inline bool -ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec) +static bool +ops_references_ip(struct ftrace_ops *ops, unsigned long ip) { /* If ops isn't enabled, ignore it */ if (!(ops->flags & FTRACE_OPS_FL_ENABLED)) @@ -3091,16 +3124,29 @@ ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec) /* The function must be in the filter */ if (!ftrace_hash_empty(ops->func_hash->filter_hash) && - !__ftrace_lookup_ip(ops->func_hash->filter_hash, rec->ip)) + !__ftrace_lookup_ip(ops->func_hash->filter_hash, ip)) return false; /* If in notrace hash, we ignore it too */ - if (ftrace_lookup_ip(ops->func_hash->notrace_hash, rec->ip)) + if (ftrace_lookup_ip(ops->func_hash->notrace_hash, ip)) return false; return true; } +/* + * Check if the current ops references the record. + * + * If the ops traces all functions, then it was already accounted for. + * If the ops does not trace the current record function, skip it. + * If the ops ignores the function via notrace filter, skip it. + */ +static bool +ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec) +{ + return ops_references_ip(ops, rec->ip); +} + static int ftrace_update_code(struct module *mod, struct ftrace_page *new_pgs) { bool init_nop = ftrace_need_init_nop(); @@ -5545,8 +5591,7 @@ int modify_ftrace_direct(unsigned long ip, } EXPORT_SYMBOL_GPL(modify_ftrace_direct); -#define MULTI_FLAGS (FTRACE_OPS_FL_IPMODIFY | FTRACE_OPS_FL_DIRECT | \ - FTRACE_OPS_FL_SAVE_REGS) +#define MULTI_FLAGS (FTRACE_OPS_FL_DIRECT | FTRACE_OPS_FL_SAVE_REGS) static int check_direct_multi(struct ftrace_ops *ops) { @@ -8004,6 +8049,80 @@ int ftrace_is_dead(void) return ftrace_disabled; } +/* + * When registering ftrace_ops with IPMODIFY, it is necessary to make sure + * it doesn't conflict with any direct ftrace_ops. If there is existing + * direct ftrace_ops on a kernel function being patched, call + * FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER on it to enable sharing. + * + * @ops: ftrace_ops being registered. + * + * Returns: + * 0 - @ops does not have IPMODIFY or @ops itself is DIRECT, no + * change needed; + * 1 - @ops has IPMODIFY, hold direct_mutex; + * -EBUSY - currently registered DIRECT ftrace_ops cannot share the + * same function with IPMODIFY, abort the register. + * -EAGAIN - cannot make changes to currently registered DIRECT + * ftrace_ops due to rare race conditions. Should retry + * later. This is needed to avoid potential deadlocks + * on the DIRECT ftrace_ops side. + */ +static int prepare_direct_functions_for_ipmodify(struct ftrace_ops *ops) + __acquires(&direct_mutex) +{ + struct ftrace_func_entry *entry; + struct ftrace_hash *hash; + struct ftrace_ops *op; + int size, i, ret; + + if (!(ops->flags & FTRACE_OPS_FL_IPMODIFY)) + return 0; + + mutex_lock(&direct_mutex); + + hash = ops->func_hash->filter_hash; + size = 1 << hash->size_bits; + for (i = 0; i < size; i++) { + hlist_for_each_entry(entry, &hash->buckets[i], hlist) { + unsigned long ip = entry->ip; + bool found_op = false; + + mutex_lock(&ftrace_lock); + do_for_each_ftrace_op(op, ftrace_ops_list) { + if (!(op->flags & FTRACE_OPS_FL_DIRECT)) + continue; + if (ops_references_ip(op, ip)) { + found_op = true; + break; + } + } while_for_each_ftrace_op(op); + mutex_unlock(&ftrace_lock); + + if (found_op) { + if (!op->ops_func) { + ret = -EBUSY; + goto err_out; + } + ret = op->ops_func(op, FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER); + if (ret) + goto err_out; + } + } + } + + /* + * Didn't find any overlap with direct ftrace_ops, or the direct + * function can share with ipmodify. Hold direct_mutex to make sure + * this doesn't change until we are done. + */ + return 1; + +err_out: + mutex_unlock(&direct_mutex); + return ret; +} + /** * register_ftrace_function - register a function for profiling * @ops: ops structure that holds the function for profiling. @@ -8016,21 +8135,74 @@ int ftrace_is_dead(void) * recursive loop. */ int register_ftrace_function(struct ftrace_ops *ops) + __releases(&direct_mutex) { + bool direct_mutex_locked = false; int ret; ftrace_ops_init(ops); + ret = prepare_direct_functions_for_ipmodify(ops); + if (ret < 0) + return ret; + else if (ret == 1) + direct_mutex_locked = true; + mutex_lock(&ftrace_lock); ret = ftrace_startup(ops, 0); mutex_unlock(&ftrace_lock); + if (direct_mutex_locked) + mutex_unlock(&direct_mutex); return ret; } EXPORT_SYMBOL_GPL(register_ftrace_function); +/* + * Similar to prepare_direct_functions_for_ipmodify, clean up after ops + * with IPMODIFY is unregistered. The cleanup is optional for most DIRECT + * ops. + */ +static void cleanup_direct_functions_after_ipmodify(struct ftrace_ops *ops) +{ + struct ftrace_func_entry *entry; + struct ftrace_hash *hash; + struct ftrace_ops *op; + int size, i; + + if (!(ops->flags & FTRACE_OPS_FL_IPMODIFY)) + return; + + mutex_lock(&direct_mutex); + + hash = ops->func_hash->filter_hash; + size = 1 << hash->size_bits; + for (i = 0; i < size; i++) { + hlist_for_each_entry(entry, &hash->buckets[i], hlist) { + unsigned long ip = entry->ip; + bool found_op = false; + + mutex_lock(&ftrace_lock); + do_for_each_ftrace_op(op, ftrace_ops_list) { + if (!(op->flags & FTRACE_OPS_FL_DIRECT)) + continue; + if (ops_references_ip(op, ip)) { + found_op = true; + break; + } + } while_for_each_ftrace_op(op); + mutex_unlock(&ftrace_lock); + + /* The cleanup is optional, iggore any errors */ + if (found_op && op->ops_func) + op->ops_func(op, FTRACE_OPS_CMD_DISABLE_SHARE_IPMODIFY_PEER); + } + } + mutex_unlock(&direct_mutex); +} + /** * unregister_ftrace_function - unregister a function for profiling. * @ops: ops structure that holds the function to unregister @@ -8045,6 +8217,7 @@ int unregister_ftrace_function(struct ftrace_ops *ops) ret = ftrace_shutdown(ops, 0); mutex_unlock(&ftrace_lock); + cleanup_direct_functions_after_ipmodify(ops); return ret; } EXPORT_SYMBOL_GPL(unregister_ftrace_function);
IPMODIFY (livepatch) and DIRECT (bpf trampoline) ops are both important users of ftrace. It is necessary to allow them work on the same function at the same time. First, DIRECT ops no longer specify IPMODIFY flag. Instead, DIRECT flag is handled together with IPMODIFY flag in __ftrace_hash_update_ipmodify(). The, a callback function, ops_func, is added to ftrace_ops. This is used by ftrace core code to understand whether the DIRECT ops can share with an IPMODIFY ops. To share with IPMODIFY ops, the DIRECT ops need to implement the callback function and adjust the direct trampoline accordingly. If DIRECT ops is attached before the IPMODIFY ops, ftrace core code calls ENABLE_SHARE_IPMODIFY_PEER on the DIRECT ops before registering the IPMODIFY ops. If IPMODIFY ops is attached before the DIRECT ops, ftrace core code calls ENABLE_SHARE_IPMODIFY_SELF in __ftrace_hash_update_ipmodify. Owner of the DIRECT ops may return 0 if the DIRECT trampoline can share with IPMODIFY, so error code otherwise. The error code is propagated to register_ftrace_direct_multi so that onwer of the DIRECT trampoline can handle it properly. For more details, please refer to comment before enum ftrace_ops_cmd. Link: https://lore.kernel.org/all/20220602193706.2607681-2-song@kernel.org/ Signed-off-by: Song Liu <song@kernel.org> --- include/linux/ftrace.h | 38 ++++++++ kernel/trace/ftrace.c | 205 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 227 insertions(+), 16 deletions(-)