diff options
| -rw-r--r-- | include/linux/ftrace.h | 20 | ||||
| -rw-r--r-- | kernel/trace/ftrace.c | 152 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 2 | ||||
| -rw-r--r-- | kernel/trace/trace.h | 19 | ||||
| -rw-r--r-- | kernel/trace/trace_functions.c | 55 | ||||
| -rw-r--r-- | kernel/trace/trace_irqsoff.c | 33 | ||||
| -rw-r--r-- | kernel/trace/trace_sched_wakeup.c | 40 | ||||
| -rw-r--r-- | kernel/trace/trace_selftest.c | 33 |
8 files changed, 133 insertions, 221 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 9212b017bc72..f0ff2c2453e7 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
| @@ -62,9 +62,6 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip, | |||
| 62 | * set in the flags member. | 62 | * set in the flags member. |
| 63 | * | 63 | * |
| 64 | * ENABLED - set/unset when ftrace_ops is registered/unregistered | 64 | * ENABLED - set/unset when ftrace_ops is registered/unregistered |
| 65 | * GLOBAL - set manualy by ftrace_ops user to denote the ftrace_ops | ||
| 66 | * is part of the global tracers sharing the same filter | ||
| 67 | * via set_ftrace_* debugfs files. | ||
| 68 | * DYNAMIC - set when ftrace_ops is registered to denote dynamically | 65 | * DYNAMIC - set when ftrace_ops is registered to denote dynamically |
| 69 | * allocated ftrace_ops which need special care | 66 | * allocated ftrace_ops which need special care |
| 70 | * CONTROL - set manualy by ftrace_ops user to denote the ftrace_ops | 67 | * CONTROL - set manualy by ftrace_ops user to denote the ftrace_ops |
| @@ -96,15 +93,14 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip, | |||
| 96 | */ | 93 | */ |
| 97 | enum { | 94 | enum { |
| 98 | FTRACE_OPS_FL_ENABLED = 1 << 0, | 95 | FTRACE_OPS_FL_ENABLED = 1 << 0, |
| 99 | FTRACE_OPS_FL_GLOBAL = 1 << 1, | 96 | FTRACE_OPS_FL_DYNAMIC = 1 << 1, |
| 100 | FTRACE_OPS_FL_DYNAMIC = 1 << 2, | 97 | FTRACE_OPS_FL_CONTROL = 1 << 2, |
| 101 | FTRACE_OPS_FL_CONTROL = 1 << 3, | 98 | FTRACE_OPS_FL_SAVE_REGS = 1 << 3, |
| 102 | FTRACE_OPS_FL_SAVE_REGS = 1 << 4, | 99 | FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 4, |
| 103 | FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 5, | 100 | FTRACE_OPS_FL_RECURSION_SAFE = 1 << 5, |
| 104 | FTRACE_OPS_FL_RECURSION_SAFE = 1 << 6, | 101 | FTRACE_OPS_FL_STUB = 1 << 6, |
| 105 | FTRACE_OPS_FL_STUB = 1 << 7, | 102 | FTRACE_OPS_FL_INITIALIZED = 1 << 7, |
| 106 | FTRACE_OPS_FL_INITIALIZED = 1 << 8, | 103 | FTRACE_OPS_FL_DELETED = 1 << 8, |
| 107 | FTRACE_OPS_FL_DELETED = 1 << 9, | ||
| 108 | }; | 104 | }; |
| 109 | 105 | ||
| 110 | /* | 106 | /* |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 1fd4b9479210..8f61ef70a297 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -62,7 +62,7 @@ | |||
| 62 | #define FTRACE_HASH_DEFAULT_BITS 10 | 62 | #define FTRACE_HASH_DEFAULT_BITS 10 |
| 63 | #define FTRACE_HASH_MAX_BITS 12 | 63 | #define FTRACE_HASH_MAX_BITS 12 |
| 64 | 64 | ||
| 65 | #define FL_GLOBAL_CONTROL_MASK (FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_CONTROL) | 65 | #define FL_GLOBAL_CONTROL_MASK (FTRACE_OPS_FL_CONTROL) |
| 66 | 66 | ||
| 67 | #ifdef CONFIG_DYNAMIC_FTRACE | 67 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 68 | #define INIT_REGEX_LOCK(opsname) \ | 68 | #define INIT_REGEX_LOCK(opsname) \ |
| @@ -103,7 +103,6 @@ static int ftrace_disabled __read_mostly; | |||
| 103 | 103 | ||
| 104 | static DEFINE_MUTEX(ftrace_lock); | 104 | static DEFINE_MUTEX(ftrace_lock); |
| 105 | 105 | ||
| 106 | static struct ftrace_ops *ftrace_global_list __read_mostly = &ftrace_list_end; | ||
| 107 | static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end; | 106 | static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end; |
| 108 | static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end; | 107 | static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end; |
| 109 | ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; | 108 | ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; |
| @@ -171,23 +170,6 @@ int ftrace_nr_registered_ops(void) | |||
| 171 | return cnt; | 170 | return cnt; |
| 172 | } | 171 | } |
| 173 | 172 | ||
| 174 | static void | ||
| 175 | ftrace_global_list_func(unsigned long ip, unsigned long parent_ip, | ||
| 176 | struct ftrace_ops *op, struct pt_regs *regs) | ||
| 177 | { | ||
| 178 | int bit; | ||
| 179 | |||
| 180 | bit = trace_test_and_set_recursion(TRACE_GLOBAL_START, TRACE_GLOBAL_MAX); | ||
| 181 | if (bit < 0) | ||
| 182 | return; | ||
| 183 | |||
| 184 | do_for_each_ftrace_op(op, ftrace_global_list) { | ||
| 185 | op->func(ip, parent_ip, op, regs); | ||
| 186 | } while_for_each_ftrace_op(op); | ||
| 187 | |||
| 188 | trace_clear_recursion(bit); | ||
| 189 | } | ||
| 190 | |||
| 191 | static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip, | 173 | static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip, |
| 192 | struct ftrace_ops *op, struct pt_regs *regs) | 174 | struct ftrace_ops *op, struct pt_regs *regs) |
| 193 | { | 175 | { |
| @@ -237,43 +219,6 @@ static int control_ops_alloc(struct ftrace_ops *ops) | |||
| 237 | return 0; | 219 | return 0; |
| 238 | } | 220 | } |
| 239 | 221 | ||
| 240 | static void update_global_ops(void) | ||
| 241 | { | ||
| 242 | ftrace_func_t func = ftrace_global_list_func; | ||
| 243 | void *private = NULL; | ||
| 244 | |||
| 245 | /* The list has its own recursion protection. */ | ||
| 246 | global_ops.flags |= FTRACE_OPS_FL_RECURSION_SAFE; | ||
| 247 | |||
| 248 | /* | ||
| 249 | * If there's only one function registered, then call that | ||
| 250 | * function directly. Otherwise, we need to iterate over the | ||
| 251 | * registered callers. | ||
| 252 | */ | ||
| 253 | if (ftrace_global_list == &ftrace_list_end || | ||
| 254 | ftrace_global_list->next == &ftrace_list_end) { | ||
| 255 | func = ftrace_global_list->func; | ||
| 256 | private = ftrace_global_list->private; | ||
| 257 | /* | ||
| 258 | * As we are calling the function directly. | ||
| 259 | * If it does not have recursion protection, | ||
| 260 | * the function_trace_op needs to be updated | ||
| 261 | * accordingly. | ||
| 262 | */ | ||
| 263 | if (!(ftrace_global_list->flags & FTRACE_OPS_FL_RECURSION_SAFE)) | ||
| 264 | global_ops.flags &= ~FTRACE_OPS_FL_RECURSION_SAFE; | ||
| 265 | } | ||
| 266 | |||
| 267 | /* If we filter on pids, update to use the pid function */ | ||
| 268 | if (!list_empty(&ftrace_pids)) { | ||
| 269 | set_ftrace_pid_function(func); | ||
| 270 | func = ftrace_pid_func; | ||
| 271 | } | ||
| 272 | |||
| 273 | global_ops.func = func; | ||
| 274 | global_ops.private = private; | ||
| 275 | } | ||
| 276 | |||
| 277 | static void ftrace_sync(struct work_struct *work) | 222 | static void ftrace_sync(struct work_struct *work) |
| 278 | { | 223 | { |
| 279 | /* | 224 | /* |
| @@ -301,8 +246,6 @@ static void update_ftrace_function(void) | |||
| 301 | { | 246 | { |
| 302 | ftrace_func_t func; | 247 | ftrace_func_t func; |
| 303 | 248 | ||
| 304 | update_global_ops(); | ||
| 305 | |||
| 306 | /* | 249 | /* |
| 307 | * If we are at the end of the list and this ops is | 250 | * If we are at the end of the list and this ops is |
| 308 | * recursion safe and not dynamic and the arch supports passing ops, | 251 | * recursion safe and not dynamic and the arch supports passing ops, |
| @@ -314,10 +257,7 @@ static void update_ftrace_function(void) | |||
| 314 | (ftrace_ops_list->flags & FTRACE_OPS_FL_RECURSION_SAFE) && | 257 | (ftrace_ops_list->flags & FTRACE_OPS_FL_RECURSION_SAFE) && |
| 315 | !FTRACE_FORCE_LIST_FUNC)) { | 258 | !FTRACE_FORCE_LIST_FUNC)) { |
| 316 | /* Set the ftrace_ops that the arch callback uses */ | 259 | /* Set the ftrace_ops that the arch callback uses */ |
| 317 | if (ftrace_ops_list == &global_ops) | 260 | set_function_trace_op = ftrace_ops_list; |
| 318 | set_function_trace_op = ftrace_global_list; | ||
| 319 | else | ||
| 320 | set_function_trace_op = ftrace_ops_list; | ||
| 321 | func = ftrace_ops_list->func; | 261 | func = ftrace_ops_list->func; |
| 322 | } else { | 262 | } else { |
| 323 | /* Just use the default ftrace_ops */ | 263 | /* Just use the default ftrace_ops */ |
| @@ -434,16 +374,9 @@ static int __register_ftrace_function(struct ftrace_ops *ops) | |||
| 434 | if (ops->flags & FTRACE_OPS_FL_DELETED) | 374 | if (ops->flags & FTRACE_OPS_FL_DELETED) |
| 435 | return -EINVAL; | 375 | return -EINVAL; |
| 436 | 376 | ||
| 437 | if (FTRACE_WARN_ON(ops == &global_ops)) | ||
| 438 | return -EINVAL; | ||
| 439 | |||
| 440 | if (WARN_ON(ops->flags & FTRACE_OPS_FL_ENABLED)) | 377 | if (WARN_ON(ops->flags & FTRACE_OPS_FL_ENABLED)) |
| 441 | return -EBUSY; | 378 | return -EBUSY; |
| 442 | 379 | ||
| 443 | /* We don't support both control and global flags set. */ | ||
| 444 | if ((ops->flags & FL_GLOBAL_CONTROL_MASK) == FL_GLOBAL_CONTROL_MASK) | ||
| 445 | return -EINVAL; | ||
| 446 | |||
| 447 | #ifndef CONFIG_DYNAMIC_FTRACE_WITH_REGS | 380 | #ifndef CONFIG_DYNAMIC_FTRACE_WITH_REGS |
| 448 | /* | 381 | /* |
| 449 | * If the ftrace_ops specifies SAVE_REGS, then it only can be used | 382 | * If the ftrace_ops specifies SAVE_REGS, then it only can be used |
| @@ -461,10 +394,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops) | |||
| 461 | if (!core_kernel_data((unsigned long)ops)) | 394 | if (!core_kernel_data((unsigned long)ops)) |
| 462 | ops->flags |= FTRACE_OPS_FL_DYNAMIC; | 395 | ops->flags |= FTRACE_OPS_FL_DYNAMIC; |
| 463 | 396 | ||
| 464 | if (ops->flags & FTRACE_OPS_FL_GLOBAL) { | 397 | if (ops->flags & FTRACE_OPS_FL_CONTROL) { |
| 465 | add_ftrace_list_ops(&ftrace_global_list, &global_ops, ops); | ||
| 466 | ops->flags |= FTRACE_OPS_FL_ENABLED; | ||
| 467 | } else if (ops->flags & FTRACE_OPS_FL_CO | ||
