diff options
Diffstat (limited to 'kernel/trace/trace_functions.c')
-rw-r--r-- | kernel/trace/trace_functions.c | 79 |
1 files changed, 44 insertions, 35 deletions
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c index b95f56ba9744..7775e1ca5bad 100644 --- a/kernel/trace/trace_functions.c +++ b/kernel/trace/trace_functions.c | |||
@@ -268,9 +268,10 @@ static struct tracer function_trace __tracer_data = | |||
268 | 268 | ||
269 | #ifdef CONFIG_DYNAMIC_FTRACE | 269 | #ifdef CONFIG_DYNAMIC_FTRACE |
270 | static void update_traceon_count(struct ftrace_probe_ops *ops, | 270 | static void update_traceon_count(struct ftrace_probe_ops *ops, |
271 | unsigned long ip, bool on) | 271 | unsigned long ip, bool on, |
272 | void *data) | ||
272 | { | 273 | { |
273 | struct ftrace_func_mapper *mapper = ops->private_data; | 274 | struct ftrace_func_mapper *mapper = data; |
274 | long *count; | 275 | long *count; |
275 | long old_count; | 276 | long old_count; |
276 | 277 | ||
@@ -329,23 +330,23 @@ static void update_traceon_count(struct ftrace_probe_ops *ops, | |||
329 | static void | 330 | static void |
330 | ftrace_traceon_count(unsigned long ip, unsigned long parent_ip, | 331 | ftrace_traceon_count(unsigned long ip, unsigned long parent_ip, |
331 | struct trace_array *tr, struct ftrace_probe_ops *ops, | 332 | struct trace_array *tr, struct ftrace_probe_ops *ops, |
332 | void **data) | 333 | void *data) |
333 | { | 334 | { |
334 | update_traceon_count(ops, ip, 1); | 335 | update_traceon_count(ops, ip, 1, data); |
335 | } | 336 | } |
336 | 337 | ||
337 | static void | 338 | static void |
338 | ftrace_traceoff_count(unsigned long ip, unsigned long parent_ip, | 339 | ftrace_traceoff_count(unsigned long ip, unsigned long parent_ip, |
339 | struct trace_array *tr, struct ftrace_probe_ops *ops, | 340 | struct trace_array *tr, struct ftrace_probe_ops *ops, |
340 | void **data) | 341 | void *data) |
341 | { | 342 | { |
342 | update_traceon_count(ops, ip, 0); | 343 | update_traceon_count(ops, ip, 0, data); |
343 | } | 344 | } |
344 | 345 | ||
345 | static void | 346 | static void |
346 | ftrace_traceon(unsigned long ip, unsigned long parent_ip, | 347 | ftrace_traceon(unsigned long ip, unsigned long parent_ip, |
347 | struct trace_array *tr, struct ftrace_probe_ops *ops, | 348 | struct trace_array *tr, struct ftrace_probe_ops *ops, |
348 | void **data) | 349 | void *data) |
349 | { | 350 | { |
350 | if (tracing_is_on()) | 351 | if (tracing_is_on()) |
351 | return; | 352 | return; |
@@ -356,7 +357,7 @@ ftrace_traceon(unsigned long ip, unsigned long parent_ip, | |||
356 | static void | 357 | static void |
357 | ftrace_traceoff(unsigned long ip, unsigned long parent_ip, | 358 | ftrace_traceoff(unsigned long ip, unsigned long parent_ip, |
358 | struct trace_array *tr, struct ftrace_probe_ops *ops, | 359 | struct trace_array *tr, struct ftrace_probe_ops *ops, |
359 | void **data) | 360 | void *data) |
360 | { | 361 | { |
361 | if (!tracing_is_on()) | 362 | if (!tracing_is_on()) |
362 | return; | 363 | return; |
@@ -376,7 +377,7 @@ ftrace_traceoff(unsigned long ip, unsigned long parent_ip, | |||
376 | static void | 377 | static void |
377 | ftrace_stacktrace(unsigned long ip, unsigned long parent_ip, | 378 | ftrace_stacktrace(unsigned long ip, unsigned long parent_ip, |
378 | struct trace_array *tr, struct ftrace_probe_ops *ops, | 379 | struct trace_array *tr, struct ftrace_probe_ops *ops, |
379 | void **data) | 380 | void *data) |
380 | { | 381 | { |
381 | trace_dump_stack(STACK_SKIP); | 382 | trace_dump_stack(STACK_SKIP); |
382 | } | 383 | } |
@@ -384,9 +385,9 @@ ftrace_stacktrace(unsigned long ip, unsigned long parent_ip, | |||
384 | static void | 385 | static void |
385 | ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, | 386 | ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, |
386 | struct trace_array *tr, struct ftrace_probe_ops *ops, | 387 | struct trace_array *tr, struct ftrace_probe_ops *ops, |
387 | void **data) | 388 | void *data) |
388 | { | 389 | { |
389 | struct ftrace_func_mapper *mapper = ops->private_data; | 390 | struct ftrace_func_mapper *mapper = data; |
390 | long *count; | 391 | long *count; |
391 | long old_count; | 392 | long old_count; |
392 | long new_count; | 393 | long new_count; |
@@ -423,9 +424,10 @@ ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, | |||
423 | } while (new_count != old_count); | 424 | } while (new_count != old_count); |
424 | } | 425 | } |
425 | 426 | ||
426 | static int update_count(struct ftrace_probe_ops *ops, unsigned long ip) | 427 | static int update_count(struct ftrace_probe_ops *ops, unsigned long ip, |
428 | void *data) | ||
427 | { | 429 | { |
428 | struct ftrace_func_mapper *mapper = ops->private_data; | 430 | struct ftrace_func_mapper *mapper = data; |
429 | long *count = NULL; | 431 | long *count = NULL; |
430 | 432 | ||
431 | if (mapper) | 433 | if (mapper) |
@@ -443,9 +445,9 @@ static int update_count(struct ftrace_probe_ops *ops, unsigned long ip) | |||
443 | static void | 445 | static void |
444 | ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, | 446 | ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, |
445 | struct trace_array *tr, struct ftrace_probe_ops *ops, | 447 | struct trace_array *tr, struct ftrace_probe_ops *ops, |
446 | void **data) | 448 | void *data) |
447 | { | 449 | { |
448 | if (update_count(ops, ip)) | 450 | if (update_count(ops, ip, data)) |
449 | ftrace_dump(DUMP_ALL); | 451 | ftrace_dump(DUMP_ALL); |
450 | } | 452 | } |
451 | 453 | ||
@@ -453,17 +455,18 @@ ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, | |||
453 | static void | 455 | static void |
454 | ftrace_cpudump_probe(unsigned long ip, unsigned long parent_ip, | 456 | ftrace_cpudump_probe(unsigned long ip, unsigned long parent_ip, |
455 | struct trace_array *tr, struct ftrace_probe_ops *ops, | 457 | struct trace_array *tr, struct ftrace_probe_ops *ops, |
456 | void **data) | 458 | void *data) |
457 | { | 459 | { |
458 | if (update_count(ops, ip)) | 460 | if (update_count(ops, ip, data)) |
459 | ftrace_dump(DUMP_ORIG); | 461 | ftrace_dump(DUMP_ORIG); |
460 | } | 462 | } |
461 | 463 | ||
462 | static int | 464 | static int |
463 | ftrace_probe_print(const char *name, struct seq_file *m, | 465 | ftrace_probe_print(const char *name, struct seq_file *m, |
464 | unsigned long ip, struct ftrace_probe_ops *ops) | 466 | unsigned long ip, struct ftrace_probe_ops *ops, |
467 | void *data) | ||
465 | { | 468 | { |
466 | struct ftrace_func_mapper *mapper = ops->private_data; | 469 | struct ftrace_func_mapper *mapper = data; |
467 | long *count = NULL; | 470 | long *count = NULL; |
468 | 471 | ||
469 | seq_printf(m, "%ps:%s", (void *)ip, name); | 472 | seq_printf(m, "%ps:%s", (void *)ip, name); |
@@ -484,52 +487,64 @@ ftrace_traceon_print(struct seq_file *m, unsigned long ip, | |||
484 | struct ftrace_probe_ops *ops, | 487 | struct ftrace_probe_ops *ops, |
485 | void *data) | 488 | void *data) |
486 | { | 489 | { |
487 | return ftrace_probe_print("traceon", m, ip, ops); | 490 | return ftrace_probe_print("traceon", m, ip, ops, data); |
488 | } | 491 | } |
489 | 492 | ||
490 | static int | 493 | static int |
491 | ftrace_traceoff_print(struct seq_file *m, unsigned long ip, | 494 | ftrace_traceoff_print(struct seq_file *m, unsigned long ip, |
492 | struct ftrace_probe_ops *ops, void *data) | 495 | struct ftrace_probe_ops *ops, void *data) |
493 | { | 496 | { |
494 | return ftrace_probe_print("traceoff", m, ip, ops); | 497 | return ftrace_probe_print("traceoff", m, ip, ops, data); |
495 | } | 498 | } |
496 | 499 | ||
497 | static int | 500 | static int |
498 | ftrace_stacktrace_print(struct seq_file *m, unsigned long ip, | 501 | ftrace_stacktrace_print(struct seq_file *m, unsigned long ip, |
499 | struct ftrace_probe_ops *ops, void *data) | 502 | struct ftrace_probe_ops *ops, void *data) |
500 | { | 503 | { |
501 | return ftrace_probe_print("stacktrace", m, ip, ops); | 504 | return ftrace_probe_print("stacktrace", m, ip, ops, data); |
502 | } | 505 | } |
503 | 506 | ||
504 | static int | 507 | static int |
505 | ftrace_dump_print(struct seq_file *m, unsigned long ip, | 508 | ftrace_dump_print(struct seq_file *m, unsigned long ip, |
506 | struct ftrace_probe_ops *ops, void *data) | 509 | struct ftrace_probe_ops *ops, void *data) |
507 | { | 510 | { |
508 | return ftrace_probe_print("dump", m, ip, ops); | 511 | return ftrace_probe_print("dump", m, ip, ops, data); |
509 | } | 512 | } |
510 | 513 | ||
511 | static int | 514 | static int |
512 | ftrace_cpudump_print(struct seq_file *m, unsigned long ip, | 515 | ftrace_cpudump_print(struct seq_file *m, unsigned long ip, |
513 | struct ftrace_probe_ops *ops, void *data) | 516 | struct ftrace_probe_ops *ops, void *data) |
514 | { | 517 | { |
515 | return ftrace_probe_print("cpudump", m, ip, ops); | 518 | return ftrace_probe_print("cpudump", m, ip, ops, data); |
516 | } | 519 | } |
517 | 520 | ||
518 | 521 | ||
519 | static int | 522 | static int |
520 | ftrace_count_init(struct ftrace_probe_ops *ops, struct trace_array *tr, | 523 | ftrace_count_init(struct ftrace_probe_ops *ops, struct trace_array *tr, |
521 | unsigned long ip, void *data) | 524 | unsigned long ip, void *init_data, void **data) |
522 | { | 525 | { |
523 | struct ftrace_func_mapper *mapper = ops->private_data; | 526 | struct ftrace_func_mapper *mapper = *data; |
527 | |||
528 | if (!mapper) { | ||
529 | mapper = allocate_ftrace_func_mapper(); | ||
530 | if (!mapper) | ||
531 | return -ENOMEM; | ||
532 | *data = mapper; | ||
533 | } | ||
524 | 534 | ||
525 | return ftrace_func_mapper_add_ip(mapper, ip, data); | 535 | return ftrace_func_mapper_add_ip(mapper, ip, init_data); |
526 | } | 536 | } |
527 | 537 | ||
528 | static void | 538 | static void |
529 | ftrace_count_free(struct ftrace_probe_ops *ops, struct trace_array *tr, | 539 | ftrace_count_free(struct ftrace_probe_ops *ops, struct trace_array *tr, |
530 | unsigned long ip, void **_data) | 540 | unsigned long ip, void *data) |
531 | { | 541 | { |
532 | struct ftrace_func_mapper *mapper = ops->private_data; | 542 | struct ftrace_func_mapper *mapper = data; |
543 | |||
544 | if (!ip) { | ||
545 | free_ftrace_func_mapper(mapper, NULL); | ||
546 | return; | ||
547 | } | ||
533 | 548 | ||
534 | ftrace_func_mapper_remove_ip(mapper, ip); | 549 | ftrace_func_mapper_remove_ip(mapper, ip); |
535 | } | 550 | } |
@@ -607,12 +622,6 @@ ftrace_trace_probe_callback(struct trace_array *tr, | |||
607 | if (!strlen(number)) | 622 | if (!strlen(number)) |
608 | goto out_reg; | 623 | goto out_reg; |
609 | 624 | ||
610 | if (!ops->private_data) { | ||
611 | ops->private_data = allocate_ftrace_func_mapper(); | ||
612 | if (!ops->private_data) | ||
613 | return -ENOMEM; | ||
614 | } | ||
615 | |||
616 | /* | 625 | /* |
617 | * We use the callback data field (which is a pointer) | 626 | * We use the callback data field (which is a pointer) |
618 | * as our counter. | 627 | * as our counter. |