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

tracing: Adding new functions for kernel access to Ftrace instances

Adding 2 new functions -
1) struct trace_array *trace_array_get_by_name(const char *name);

Return pointer to a trace array with given name. If it does not exist,
create and return pointer to the new trace array.

2) int trace_array_set_clr_event(struct trace_array *tr,
const char *system ,const char *event, bool enable);

Enable/Disable events to this trace array.

Additionally,
- To handle reference counters, export trace_array_put()
- Due to introduction of the above 2 new functions, we no longer need to
export - ftrace_set_clr_event & trace_array_create APIs.

Link: http://lkml.kernel.org/r/1574276919-11119-2-git-send-email-divya.indi@oracle.com

Signed-off-by: Divya Indi <divya.indi@oracle.com>
Reviewed-by: Aruna Ramakrishna <aruna.ramakrishna@oracle.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

authored by

Divya Indi and committed by
Steven Rostedt (VMware)
28879787 fc809bc5

+106 -24
+2 -1
include/linux/trace.h
··· 29 29 void trace_printk_init_buffers(void); 30 30 int trace_array_printk(struct trace_array *tr, unsigned long ip, 31 31 const char *fmt, ...); 32 - struct trace_array *trace_array_create(const char *name); 32 + void trace_array_put(struct trace_array *tr); 33 + struct trace_array *trace_array_get_by_name(const char *name); 33 34 int trace_array_destroy(struct trace_array *tr); 34 35 #endif /* CONFIG_TRACING */ 35 36
+2 -1
include/linux/trace_events.h
··· 555 555 556 556 int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set); 557 557 int trace_set_clr_event(const char *system, const char *event, int set); 558 - 558 + int trace_array_set_clr_event(struct trace_array *tr, const char *system, 559 + const char *event, bool enable); 559 560 /* 560 561 * The double __builtin_constant_p is because gcc will give us an error 561 562 * if we try to allocate the static variable to fmt if it is not a
+76 -20
kernel/trace/trace.c
··· 301 301 this_tr->ref--; 302 302 } 303 303 304 + /** 305 + * trace_array_put - Decrement the reference counter for this trace array. 306 + * 307 + * NOTE: Use this when we no longer need the trace array returned by 308 + * trace_array_get_by_name(). This ensures the trace array can be later 309 + * destroyed. 310 + * 311 + */ 304 312 void trace_array_put(struct trace_array *this_tr) 305 313 { 314 + if (!this_tr) 315 + return; 316 + 306 317 mutex_lock(&trace_types_lock); 307 318 __trace_array_put(this_tr); 308 319 mutex_unlock(&trace_types_lock); 309 320 } 321 + EXPORT_SYMBOL_GPL(trace_array_put); 310 322 311 323 int tracing_check_open_get_tr(struct trace_array *tr) 312 324 { ··· 8449 8437 mutex_unlock(&trace_types_lock); 8450 8438 } 8451 8439 8452 - struct trace_array *trace_array_create(const char *name) 8440 + static struct trace_array *trace_array_create(const char *name) 8453 8441 { 8454 8442 struct trace_array *tr; 8455 8443 int ret; 8456 8444 8457 - mutex_lock(&event_mutex); 8458 - mutex_lock(&trace_types_lock); 8459 - 8460 - ret = -EEXIST; 8461 - list_for_each_entry(tr, &ftrace_trace_arrays, list) { 8462 - if (tr->name && strcmp(tr->name, name) == 0) 8463 - goto out_unlock; 8464 - } 8465 - 8466 8445 ret = -ENOMEM; 8467 8446 tr = kzalloc(sizeof(*tr), GFP_KERNEL); 8468 8447 if (!tr) 8469 - goto out_unlock; 8448 + return ERR_PTR(ret); 8470 8449 8471 8450 tr->name = kstrdup(name, GFP_KERNEL); 8472 8451 if (!tr->name) ··· 8502 8499 8503 8500 list_add(&tr->list, &ftrace_trace_arrays); 8504 8501 8505 - mutex_unlock(&trace_types_lock); 8506 - mutex_unlock(&event_mutex); 8502 + tr->ref++; 8503 + 8507 8504 8508 8505 return tr; 8509 8506 ··· 8513 8510 kfree(tr->name); 8514 8511 kfree(tr); 8515 8512 8516 - out_unlock: 8517 - mutex_unlock(&trace_types_lock); 8518 - mutex_unlock(&event_mutex); 8519 - 8520 8513 return ERR_PTR(ret); 8521 8514 } 8522 - EXPORT_SYMBOL_GPL(trace_array_create); 8523 8515 8524 8516 static int instance_mkdir(const char *name) 8525 8517 { 8526 - return PTR_ERR_OR_ZERO(trace_array_create(name)); 8518 + struct trace_array *tr; 8519 + int ret; 8520 + 8521 + mutex_lock(&event_mutex); 8522 + mutex_lock(&trace_types_lock); 8523 + 8524 + ret = -EEXIST; 8525 + list_for_each_entry(tr, &ftrace_trace_arrays, list) { 8526 + if (tr->name && strcmp(tr->name, name) == 0) 8527 + goto out_unlock; 8528 + } 8529 + 8530 + tr = trace_array_create(name); 8531 + 8532 + ret = PTR_ERR_OR_ZERO(tr); 8533 + 8534 + out_unlock: 8535 + mutex_unlock(&trace_types_lock); 8536 + mutex_unlock(&event_mutex); 8537 + return ret; 8527 8538 } 8539 + 8540 + /** 8541 + * trace_array_get_by_name - Create/Lookup a trace array, given its name. 8542 + * @name: The name of the trace array to be looked up/created. 8543 + * 8544 + * Returns pointer to trace array with given name. 8545 + * NULL, if it cannot be created. 8546 + * 8547 + * NOTE: This function increments the reference counter associated with the 8548 + * trace array returned. This makes sure it cannot be freed while in use. 8549 + * Use trace_array_put() once the trace array is no longer needed. 8550 + * 8551 + */ 8552 + struct trace_array *trace_array_get_by_name(const char *name) 8553 + { 8554 + struct trace_array *tr; 8555 + 8556 + mutex_lock(&event_mutex); 8557 + mutex_lock(&trace_types_lock); 8558 + 8559 + list_for_each_entry(tr, &ftrace_trace_arrays, list) { 8560 + if (tr->name && strcmp(tr->name, name) == 0) 8561 + goto out_unlock; 8562 + } 8563 + 8564 + tr = trace_array_create(name); 8565 + 8566 + if (IS_ERR(tr)) 8567 + tr = NULL; 8568 + out_unlock: 8569 + if (tr) 8570 + tr->ref++; 8571 + 8572 + mutex_unlock(&trace_types_lock); 8573 + mutex_unlock(&event_mutex); 8574 + return tr; 8575 + } 8576 + EXPORT_SYMBOL_GPL(trace_array_get_by_name); 8528 8577 8529 8578 static int __remove_instance(struct trace_array *tr) 8530 8579 { 8531 8580 int i; 8532 8581 8533 - if (tr->ref || (tr->current_trace && tr->current_trace->ref)) 8582 + /* Reference counter for a newly created trace array = 1. */ 8583 + if (tr->ref > 1 || (tr->current_trace && tr->current_trace->ref)) 8534 8584 return -EBUSY; 8535 8585 8536 8586 list_del(&tr->list);
-1
kernel/trace/trace.h
··· 345 345 extern struct mutex trace_types_lock; 346 346 347 347 extern int trace_array_get(struct trace_array *tr); 348 - extern void trace_array_put(struct trace_array *tr); 349 348 extern int tracing_check_open_get_tr(struct trace_array *tr); 350 349 351 350 extern int tracing_set_time_stamp_abs(struct trace_array *tr, bool abs);
+26 -1
kernel/trace/trace_events.c
··· 827 827 828 828 return ret; 829 829 } 830 - EXPORT_SYMBOL_GPL(ftrace_set_clr_event); 831 830 832 831 /** 833 832 * trace_set_clr_event - enable or disable an event ··· 850 851 return __ftrace_set_clr_event(tr, NULL, system, event, set); 851 852 } 852 853 EXPORT_SYMBOL_GPL(trace_set_clr_event); 854 + 855 + /** 856 + * trace_array_set_clr_event - enable or disable an event for a trace array. 857 + * @tr: concerned trace array. 858 + * @system: system name to match (NULL for any system) 859 + * @event: event name to match (NULL for all events, within system) 860 + * @enable: true to enable, false to disable 861 + * 862 + * This is a way for other parts of the kernel to enable or disable 863 + * event recording. 864 + * 865 + * Returns 0 on success, -EINVAL if the parameters do not match any 866 + * registered events. 867 + */ 868 + int trace_array_set_clr_event(struct trace_array *tr, const char *system, 869 + const char *event, bool enable) 870 + { 871 + int set; 872 + 873 + if (!tr) 874 + return -ENOENT; 875 + 876 + set = (enable == true) ? 1 : 0; 877 + return __ftrace_set_clr_event(tr, NULL, system, event, set); 878 + } 879 + EXPORT_SYMBOL_GPL(trace_array_set_clr_event); 853 880 854 881 /* 128 should be much more than enough */ 855 882 #define EVENT_BUF_SIZE 127