aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_functions.c
diff options
context:
space:
mode:
authorSteven Rostedt (VMware) <rostedt@goodmis.org>2017-04-19 22:39:44 -0400
committerSteven Rostedt (VMware) <rostedt@goodmis.org>2017-04-20 22:06:46 -0400
commit6e4443199e5354255e8a4c1e8e5cfc8ef064c3ce (patch)
treeb0e7181d739a1207606bce8f60be5f305e27ea6b /kernel/trace/trace_functions.c
parent7b60f3d8761561d95d7e962522d6338143fc2329 (diff)
tracing/ftrace: Add a better way to pass data via the probe functions
With the redesign of the registration and execution of the function probes (triggers), data can now be passed from the setup of the probe to the probe callers that are specific to the trace_array it is on. Although, all probes still only affect the toplevel trace array, this change will allow for instances to have their own probes separated from other instances and the top array. That is, something like the stacktrace probe can be set to trace only in an instance and not the toplevel trace array. This isn't implement yet, but this change sets the ground work for the change. When a probe callback is triggered (someone writes the probe format into set_ftrace_filter), it calls register_ftrace_function_probe() passing in init_data that will be used to initialize the probe. Then for every matching function, register_ftrace_function_probe() will call the probe_ops->init() function with the init data that was passed to it, as well as an address to a place holder that is associated with the probe and the instance. The first occurrence will have a NULL in the pointer. The init() function will then initialize it. If other probes are added, or more functions are part of the probe, the place holder will be passed to the init() function with the place holder data that it was initialized to the last time. Then this place_holder is passed to each of the other probe_ops functions, where it can be used in the function callback. When the probe_ops free() function is called, it can be called either with the rip of the function that is being removed from the probe, or zero, indicating that there are no more functions attached to the probe, and the place holder is about to be freed. This gives the probe_ops a way to free the data it assigned to the place holder if it was allocade during the first init call. Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace_functions.c')
-rw-r--r--kernel/trace/trace_functions.c79
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
270static void update_traceon_count(struct ftrace_probe_ops *ops, 270static 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,
329static void 330static void
330ftrace_traceon_count(unsigned long ip, unsigned long parent_ip, 331ftrace_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
337static void 338static void
338ftrace_traceoff_count(unsigned long ip, unsigned long parent_ip, 339ftrace_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
345static void 346static void
346ftrace_traceon(unsigned long ip, unsigned long parent_ip, 347ftrace_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,
356static void 357static void
357ftrace_traceoff(unsigned long ip, unsigned long parent_ip, 358ftrace_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,
376static void 377static void
377ftrace_stacktrace(unsigned long ip, unsigned long parent_ip, 378ftrace_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,
384static void 385static void
385ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, 386ftrace_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
426static int update_count(struct ftrace_probe_ops *ops, unsigned long ip) 427static 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)
443static void 445static void
444ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, 446ftrace_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,
453static void 455static void
454ftrace_cpudump_probe(unsigned long ip, unsigned long parent_ip, 456ftrace_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
462static int 464static int
463ftrace_probe_print(const char *name, struct seq_file *m, 465ftrace_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
490static int 493static int
491ftrace_traceoff_print(struct seq_file *m, unsigned long ip, 494ftrace_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
497static int 500static int
498ftrace_stacktrace_print(struct seq_file *m, unsigned long ip, 501ftrace_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
504static int 507static int
505ftrace_dump_print(struct seq_file *m, unsigned long ip, 508ftrace_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
511static int 514static int
512ftrace_cpudump_print(struct seq_file *m, unsigned long ip, 515ftrace_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
519static int 522static int
520ftrace_count_init(struct ftrace_probe_ops *ops, struct trace_array *tr, 523ftrace_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
528static void 538static void
529ftrace_count_free(struct ftrace_probe_ops *ops, struct trace_array *tr, 539ftrace_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.