Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ftrace/x86: Let dynamic trampolines call ops->func even for dynamic fops

Dynamically allocated trampolines call ftrace_ops_get_func to get the
function which they should call. For dynamic fops (FTRACE_OPS_FL_DYNAMIC
flag is set) ftrace_ops_list_func is always returned. This is reasonable
for static trampolines but goes against the main advantage of dynamic
ones, that is avoidance of going through the list of all registered
callbacks for functions that are only being traced by a single callback.

We can fix it by returning ops->func (or recursion safe version) from
ftrace_ops_get_func whenever it is possible for dynamic trampolines.

Note that dynamic trampolines are not allowed for dynamic fops if
CONFIG_PREEMPT=y.

Link: http://lkml.kernel.org/r/alpine.LNX.2.00.1501291023000.25445@pobox.suse.cz
Link: http://lkml.kernel.org/r/1424357773-13536-1-git-send-email-mbenes@suse.cz

Reported-by: Miroslav Benes <mbenes@suse.cz>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

+14 -8
+14 -8
kernel/trace/ftrace.c
··· 249 249 static inline void update_function_graph_func(void) { } 250 250 #endif 251 251 252 + 253 + static ftrace_func_t ftrace_ops_get_list_func(struct ftrace_ops *ops) 254 + { 255 + /* 256 + * If this is a dynamic ops or we force list func, 257 + * then it needs to call the list anyway. 258 + */ 259 + if (ops->flags & FTRACE_OPS_FL_DYNAMIC || FTRACE_FORCE_LIST_FUNC) 260 + return ftrace_ops_list_func; 261 + 262 + return ftrace_ops_get_func(ops); 263 + } 264 + 252 265 static void update_ftrace_function(void) 253 266 { 254 267 ftrace_func_t func; ··· 283 270 * then have the mcount trampoline call the function directly. 284 271 */ 285 272 } else if (ftrace_ops_list->next == &ftrace_list_end) { 286 - func = ftrace_ops_get_func(ftrace_ops_list); 273 + func = ftrace_ops_get_list_func(ftrace_ops_list); 287 274 288 275 } else { 289 276 /* Just use the default ftrace_ops */ ··· 5221 5208 */ 5222 5209 ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops) 5223 5210 { 5224 - /* 5225 - * If this is a dynamic ops or we force list func, 5226 - * then it needs to call the list anyway. 5227 - */ 5228 - if (ops->flags & FTRACE_OPS_FL_DYNAMIC || FTRACE_FORCE_LIST_FUNC) 5229 - return ftrace_ops_list_func; 5230 - 5231 5211 /* 5232 5212 * If the func handles its own recursion, call it directly. 5233 5213 * Otherwise call the recursion protected function that