1b1696371SDaniel Bristot de Oliveira // SPDX-License-Identifier: GPL-2.0 2b1696371SDaniel Bristot de Oliveira #define _GNU_SOURCE 3b1696371SDaniel Bristot de Oliveira #include <sys/sendfile.h> 4b1696371SDaniel Bristot de Oliveira #include <tracefs.h> 5b1696371SDaniel Bristot de Oliveira #include <signal.h> 6b1696371SDaniel Bristot de Oliveira #include <stdlib.h> 7b1696371SDaniel Bristot de Oliveira #include <unistd.h> 8b1696371SDaniel Bristot de Oliveira #include <errno.h> 9b1696371SDaniel Bristot de Oliveira 10b1696371SDaniel Bristot de Oliveira #include "trace.h" 11b1696371SDaniel Bristot de Oliveira #include "utils.h" 12b1696371SDaniel Bristot de Oliveira 13b1696371SDaniel Bristot de Oliveira /* 14b1696371SDaniel Bristot de Oliveira * enable_tracer_by_name - enable a tracer on the given instance 15b1696371SDaniel Bristot de Oliveira */ 16b1696371SDaniel Bristot de Oliveira int enable_tracer_by_name(struct tracefs_instance *inst, const char *tracer_name) 17b1696371SDaniel Bristot de Oliveira { 18b1696371SDaniel Bristot de Oliveira enum tracefs_tracers tracer; 19b1696371SDaniel Bristot de Oliveira int retval; 20b1696371SDaniel Bristot de Oliveira 21b1696371SDaniel Bristot de Oliveira tracer = TRACEFS_TRACER_CUSTOM; 22b1696371SDaniel Bristot de Oliveira 231a622909SDaniel Bristot de Oliveira debug_msg("Enabling %s tracer\n", tracer_name); 24b1696371SDaniel Bristot de Oliveira 25b1696371SDaniel Bristot de Oliveira retval = tracefs_tracer_set(inst, tracer, tracer_name); 26b1696371SDaniel Bristot de Oliveira if (retval < 0) { 27b1696371SDaniel Bristot de Oliveira if (errno == ENODEV) 281a622909SDaniel Bristot de Oliveira err_msg("Tracer %s not found!\n", tracer_name); 29b1696371SDaniel Bristot de Oliveira 301a622909SDaniel Bristot de Oliveira err_msg("Failed to enable the %s tracer\n", tracer_name); 31b1696371SDaniel Bristot de Oliveira return -1; 32b1696371SDaniel Bristot de Oliveira } 33b1696371SDaniel Bristot de Oliveira 34b1696371SDaniel Bristot de Oliveira return 0; 35b1696371SDaniel Bristot de Oliveira } 36b1696371SDaniel Bristot de Oliveira 37b1696371SDaniel Bristot de Oliveira /* 38b1696371SDaniel Bristot de Oliveira * disable_tracer - set nop tracer to the insta 39b1696371SDaniel Bristot de Oliveira */ 40b1696371SDaniel Bristot de Oliveira void disable_tracer(struct tracefs_instance *inst) 41b1696371SDaniel Bristot de Oliveira { 42b1696371SDaniel Bristot de Oliveira enum tracefs_tracers t = TRACEFS_TRACER_NOP; 43b1696371SDaniel Bristot de Oliveira int retval; 44b1696371SDaniel Bristot de Oliveira 45b1696371SDaniel Bristot de Oliveira retval = tracefs_tracer_set(inst, t); 46b1696371SDaniel Bristot de Oliveira if (retval < 0) 471a622909SDaniel Bristot de Oliveira err_msg("Oops, error disabling tracer\n"); 48b1696371SDaniel Bristot de Oliveira } 49b1696371SDaniel Bristot de Oliveira 50b1696371SDaniel Bristot de Oliveira /* 51b1696371SDaniel Bristot de Oliveira * create_instance - create a trace instance with *instance_name 52b1696371SDaniel Bristot de Oliveira */ 53b1696371SDaniel Bristot de Oliveira struct tracefs_instance *create_instance(char *instance_name) 54b1696371SDaniel Bristot de Oliveira { 55b1696371SDaniel Bristot de Oliveira return tracefs_instance_create(instance_name); 56b1696371SDaniel Bristot de Oliveira } 57b1696371SDaniel Bristot de Oliveira 58b1696371SDaniel Bristot de Oliveira /* 59b1696371SDaniel Bristot de Oliveira * destroy_instance - remove a trace instance and free the data 60b1696371SDaniel Bristot de Oliveira */ 61b1696371SDaniel Bristot de Oliveira void destroy_instance(struct tracefs_instance *inst) 62b1696371SDaniel Bristot de Oliveira { 63b1696371SDaniel Bristot de Oliveira tracefs_instance_destroy(inst); 64b1696371SDaniel Bristot de Oliveira tracefs_instance_free(inst); 65b1696371SDaniel Bristot de Oliveira } 66b1696371SDaniel Bristot de Oliveira 67b1696371SDaniel Bristot de Oliveira /* 68b1696371SDaniel Bristot de Oliveira * save_trace_to_file - save the trace output of the instance to the file 69b1696371SDaniel Bristot de Oliveira */ 70b1696371SDaniel Bristot de Oliveira int save_trace_to_file(struct tracefs_instance *inst, const char *filename) 71b1696371SDaniel Bristot de Oliveira { 72b1696371SDaniel Bristot de Oliveira const char *file = "trace"; 73b1696371SDaniel Bristot de Oliveira mode_t mode = 0644; 74b1696371SDaniel Bristot de Oliveira char buffer[4096]; 75b1696371SDaniel Bristot de Oliveira int out_fd, in_fd; 76b1696371SDaniel Bristot de Oliveira int retval = -1; 77b1696371SDaniel Bristot de Oliveira 78b1696371SDaniel Bristot de Oliveira in_fd = tracefs_instance_file_open(inst, file, O_RDONLY); 79b1696371SDaniel Bristot de Oliveira if (in_fd < 0) { 80b1696371SDaniel Bristot de Oliveira err_msg("Failed to open trace file\n"); 81b1696371SDaniel Bristot de Oliveira return -1; 82b1696371SDaniel Bristot de Oliveira } 83b1696371SDaniel Bristot de Oliveira 84b1696371SDaniel Bristot de Oliveira out_fd = creat(filename, mode); 85b1696371SDaniel Bristot de Oliveira if (out_fd < 0) { 86b1696371SDaniel Bristot de Oliveira err_msg("Failed to create output file %s\n", filename); 87b1696371SDaniel Bristot de Oliveira goto out_close_in; 88b1696371SDaniel Bristot de Oliveira } 89b1696371SDaniel Bristot de Oliveira 90b1696371SDaniel Bristot de Oliveira do { 91b1696371SDaniel Bristot de Oliveira retval = read(in_fd, buffer, sizeof(buffer)); 92b1696371SDaniel Bristot de Oliveira if (retval <= 0) 93b1696371SDaniel Bristot de Oliveira goto out_close; 94b1696371SDaniel Bristot de Oliveira 95b1696371SDaniel Bristot de Oliveira retval = write(out_fd, buffer, retval); 96b1696371SDaniel Bristot de Oliveira if (retval < 0) 97b1696371SDaniel Bristot de Oliveira goto out_close; 98b1696371SDaniel Bristot de Oliveira } while (retval > 0); 99b1696371SDaniel Bristot de Oliveira 100b1696371SDaniel Bristot de Oliveira retval = 0; 101b1696371SDaniel Bristot de Oliveira out_close: 102b1696371SDaniel Bristot de Oliveira close(out_fd); 103b1696371SDaniel Bristot de Oliveira out_close_in: 104b1696371SDaniel Bristot de Oliveira close(in_fd); 105b1696371SDaniel Bristot de Oliveira return retval; 106b1696371SDaniel Bristot de Oliveira } 107b1696371SDaniel Bristot de Oliveira 108b1696371SDaniel Bristot de Oliveira /* 109b1696371SDaniel Bristot de Oliveira * collect_registered_events - call the existing callback function for the event 110b1696371SDaniel Bristot de Oliveira * 111b1696371SDaniel Bristot de Oliveira * If an event has a registered callback function, call it. 112b1696371SDaniel Bristot de Oliveira * Otherwise, ignore the event. 113b1696371SDaniel Bristot de Oliveira */ 114b1696371SDaniel Bristot de Oliveira int 115b1696371SDaniel Bristot de Oliveira collect_registered_events(struct tep_event *event, struct tep_record *record, 116b1696371SDaniel Bristot de Oliveira int cpu, void *context) 117b1696371SDaniel Bristot de Oliveira { 118b1696371SDaniel Bristot de Oliveira struct trace_instance *trace = context; 119b1696371SDaniel Bristot de Oliveira struct trace_seq *s = trace->seq; 120b1696371SDaniel Bristot de Oliveira 121b1696371SDaniel Bristot de Oliveira if (!event->handler) 122b1696371SDaniel Bristot de Oliveira return 0; 123b1696371SDaniel Bristot de Oliveira 124b1696371SDaniel Bristot de Oliveira event->handler(s, record, event, context); 125b1696371SDaniel Bristot de Oliveira 126b1696371SDaniel Bristot de Oliveira return 0; 127b1696371SDaniel Bristot de Oliveira } 128b1696371SDaniel Bristot de Oliveira 129b1696371SDaniel Bristot de Oliveira /* 130b1696371SDaniel Bristot de Oliveira * trace_instance_destroy - destroy and free a rtla trace instance 131b1696371SDaniel Bristot de Oliveira */ 132b1696371SDaniel Bristot de Oliveira void trace_instance_destroy(struct trace_instance *trace) 133b1696371SDaniel Bristot de Oliveira { 134b1696371SDaniel Bristot de Oliveira if (trace->inst) { 135b1696371SDaniel Bristot de Oliveira disable_tracer(trace->inst); 136b1696371SDaniel Bristot de Oliveira destroy_instance(trace->inst); 137*4f753c3bSAndreas Schwab trace->inst = NULL; 138b1696371SDaniel Bristot de Oliveira } 139b1696371SDaniel Bristot de Oliveira 140*4f753c3bSAndreas Schwab if (trace->seq) { 141b1696371SDaniel Bristot de Oliveira free(trace->seq); 142*4f753c3bSAndreas Schwab trace->seq = NULL; 143*4f753c3bSAndreas Schwab } 144b1696371SDaniel Bristot de Oliveira 145*4f753c3bSAndreas Schwab if (trace->tep) { 146b1696371SDaniel Bristot de Oliveira tep_free(trace->tep); 147*4f753c3bSAndreas Schwab trace->tep = NULL; 148*4f753c3bSAndreas Schwab } 149b1696371SDaniel Bristot de Oliveira } 150b1696371SDaniel Bristot de Oliveira 151b1696371SDaniel Bristot de Oliveira /* 152b1696371SDaniel Bristot de Oliveira * trace_instance_init - create an rtla trace instance 153b1696371SDaniel Bristot de Oliveira * 154b1696371SDaniel Bristot de Oliveira * It is more than the tracefs instance, as it contains other 155b1696371SDaniel Bristot de Oliveira * things required for the tracing, such as the local events and 156b1696371SDaniel Bristot de Oliveira * a seq file. 157b1696371SDaniel Bristot de Oliveira * 158b1696371SDaniel Bristot de Oliveira * Note that the trace instance is returned disabled. This allows 159b1696371SDaniel Bristot de Oliveira * the tool to apply some other configs, like setting priority 160b1696371SDaniel Bristot de Oliveira * to the kernel threads, before starting generating trace entries. 161b1696371SDaniel Bristot de Oliveira */ 162b1696371SDaniel Bristot de Oliveira int trace_instance_init(struct trace_instance *trace, char *tool_name) 163b1696371SDaniel Bristot de Oliveira { 164b1696371SDaniel Bristot de Oliveira trace->seq = calloc(1, sizeof(*trace->seq)); 165b1696371SDaniel Bristot de Oliveira if (!trace->seq) 166b1696371SDaniel Bristot de Oliveira goto out_err; 167b1696371SDaniel Bristot de Oliveira 168b1696371SDaniel Bristot de Oliveira trace_seq_init(trace->seq); 169b1696371SDaniel Bristot de Oliveira 170b1696371SDaniel Bristot de Oliveira trace->inst = create_instance(tool_name); 171b1696371SDaniel Bristot de Oliveira if (!trace->inst) 172b1696371SDaniel Bristot de Oliveira goto out_err; 173b1696371SDaniel Bristot de Oliveira 174b1696371SDaniel Bristot de Oliveira trace->tep = tracefs_local_events(NULL); 175b1696371SDaniel Bristot de Oliveira if (!trace->tep) 176b1696371SDaniel Bristot de Oliveira goto out_err; 177b1696371SDaniel Bristot de Oliveira 178b1696371SDaniel Bristot de Oliveira /* 179b1696371SDaniel Bristot de Oliveira * Let the main enable the record after setting some other 180b1696371SDaniel Bristot de Oliveira * things such as the priority of the tracer's threads. 181b1696371SDaniel Bristot de Oliveira */ 182b1696371SDaniel Bristot de Oliveira tracefs_trace_off(trace->inst); 183b1696371SDaniel Bristot de Oliveira 184b1696371SDaniel Bristot de Oliveira return 0; 185b1696371SDaniel Bristot de Oliveira 186b1696371SDaniel Bristot de Oliveira out_err: 187b1696371SDaniel Bristot de Oliveira trace_instance_destroy(trace); 188b1696371SDaniel Bristot de Oliveira return 1; 189b1696371SDaniel Bristot de Oliveira } 190b1696371SDaniel Bristot de Oliveira 191b1696371SDaniel Bristot de Oliveira /* 192b1696371SDaniel Bristot de Oliveira * trace_instance_start - start tracing a given rtla instance 193b1696371SDaniel Bristot de Oliveira */ 194b1696371SDaniel Bristot de Oliveira int trace_instance_start(struct trace_instance *trace) 195b1696371SDaniel Bristot de Oliveira { 196b1696371SDaniel Bristot de Oliveira return tracefs_trace_on(trace->inst); 197b1696371SDaniel Bristot de Oliveira } 198b5aa0be2SDaniel Bristot de Oliveira 199b5aa0be2SDaniel Bristot de Oliveira /* 200b5aa0be2SDaniel Bristot de Oliveira * trace_events_free - free a list of trace events 201b5aa0be2SDaniel Bristot de Oliveira */ 202b5aa0be2SDaniel Bristot de Oliveira static void trace_events_free(struct trace_events *events) 203b5aa0be2SDaniel Bristot de Oliveira { 204b5aa0be2SDaniel Bristot de Oliveira struct trace_events *tevent = events; 205b5aa0be2SDaniel Bristot de Oliveira struct trace_events *free_event; 206b5aa0be2SDaniel Bristot de Oliveira 207b5aa0be2SDaniel Bristot de Oliveira while (tevent) { 208b5aa0be2SDaniel Bristot de Oliveira free_event = tevent; 209b5aa0be2SDaniel Bristot de Oliveira 210b5aa0be2SDaniel Bristot de Oliveira tevent = tevent->next; 211b5aa0be2SDaniel Bristot de Oliveira 2125487b6ceSDaniel Bristot de Oliveira if (free_event->filter) 2135487b6ceSDaniel Bristot de Oliveira free(free_event->filter); 214336c92b2SDaniel Bristot de Oliveira if (free_event->trigger) 215336c92b2SDaniel Bristot de Oliveira free(free_event->trigger); 216b5aa0be2SDaniel Bristot de Oliveira free(free_event->system); 217b5aa0be2SDaniel Bristot de Oliveira free(free_event); 218b5aa0be2SDaniel Bristot de Oliveira } 219b5aa0be2SDaniel Bristot de Oliveira } 220b5aa0be2SDaniel Bristot de Oliveira 221b5aa0be2SDaniel Bristot de Oliveira /* 222b5aa0be2SDaniel Bristot de Oliveira * trace_event_alloc - alloc and parse a single trace event 223b5aa0be2SDaniel Bristot de Oliveira */ 224b5aa0be2SDaniel Bristot de Oliveira struct trace_events *trace_event_alloc(const char *event_string) 225b5aa0be2SDaniel Bristot de Oliveira { 226b5aa0be2SDaniel Bristot de Oliveira struct trace_events *tevent; 227b5aa0be2SDaniel Bristot de Oliveira 228b5aa0be2SDaniel Bristot de Oliveira tevent = calloc(1, sizeof(*tevent)); 229b5aa0be2SDaniel Bristot de Oliveira if (!tevent) 230b5aa0be2SDaniel Bristot de Oliveira return NULL; 231b5aa0be2SDaniel Bristot de Oliveira 232b5aa0be2SDaniel Bristot de Oliveira tevent->system = strdup(event_string); 233b5aa0be2SDaniel Bristot de Oliveira if (!tevent->system) { 234b5aa0be2SDaniel Bristot de Oliveira free(tevent); 235b5aa0be2SDaniel Bristot de Oliveira return NULL; 236b5aa0be2SDaniel Bristot de Oliveira } 237b5aa0be2SDaniel Bristot de Oliveira 238b5aa0be2SDaniel Bristot de Oliveira tevent->event = strstr(tevent->system, ":"); 239b5aa0be2SDaniel Bristot de Oliveira if (tevent->event) { 240b5aa0be2SDaniel Bristot de Oliveira *tevent->event = '\0'; 241b5aa0be2SDaniel Bristot de Oliveira tevent->event = &tevent->event[1]; 242b5aa0be2SDaniel Bristot de Oliveira } 243b5aa0be2SDaniel Bristot de Oliveira 244b5aa0be2SDaniel Bristot de Oliveira return tevent; 245b5aa0be2SDaniel Bristot de Oliveira } 246b5aa0be2SDaniel Bristot de Oliveira 247b5aa0be2SDaniel Bristot de Oliveira /* 2485487b6ceSDaniel Bristot de Oliveira * trace_event_add_filter - record an event filter 2495487b6ceSDaniel Bristot de Oliveira */ 2505487b6ceSDaniel Bristot de Oliveira int trace_event_add_filter(struct trace_events *event, char *filter) 2515487b6ceSDaniel Bristot de Oliveira { 2525487b6ceSDaniel Bristot de Oliveira if (event->filter) 2535487b6ceSDaniel Bristot de Oliveira free(event->filter); 2545487b6ceSDaniel Bristot de Oliveira 2555487b6ceSDaniel Bristot de Oliveira event->filter = strdup(filter); 2565487b6ceSDaniel Bristot de Oliveira if (!event->filter) 2575487b6ceSDaniel Bristot de Oliveira return 1; 2585487b6ceSDaniel Bristot de Oliveira 2595487b6ceSDaniel Bristot de Oliveira return 0; 2605487b6ceSDaniel Bristot de Oliveira } 2615487b6ceSDaniel Bristot de Oliveira 2625487b6ceSDaniel Bristot de Oliveira /* 263336c92b2SDaniel Bristot de Oliveira * trace_event_add_trigger - record an event trigger action 264336c92b2SDaniel Bristot de Oliveira */ 265336c92b2SDaniel Bristot de Oliveira int trace_event_add_trigger(struct trace_events *event, char *trigger) 266336c92b2SDaniel Bristot de Oliveira { 267336c92b2SDaniel Bristot de Oliveira if (event->trigger) 268336c92b2SDaniel Bristot de Oliveira free(event->trigger); 269336c92b2SDaniel Bristot de Oliveira 270336c92b2SDaniel Bristot de Oliveira event->trigger = strdup(trigger); 271336c92b2SDaniel Bristot de Oliveira if (!event->trigger) 272336c92b2SDaniel Bristot de Oliveira return 1; 273336c92b2SDaniel Bristot de Oliveira 274336c92b2SDaniel Bristot de Oliveira return 0; 275336c92b2SDaniel Bristot de Oliveira } 276336c92b2SDaniel Bristot de Oliveira 277336c92b2SDaniel Bristot de Oliveira /* 2785487b6ceSDaniel Bristot de Oliveira * trace_event_disable_filter - disable an event filter 2795487b6ceSDaniel Bristot de Oliveira */ 2805487b6ceSDaniel Bristot de Oliveira static void trace_event_disable_filter(struct trace_instance *instance, 2815487b6ceSDaniel Bristot de Oliveira struct trace_events *tevent) 2825487b6ceSDaniel Bristot de Oliveira { 2835487b6ceSDaniel Bristot de Oliveira char filter[1024]; 2845487b6ceSDaniel Bristot de Oliveira int retval; 2855487b6ceSDaniel Bristot de Oliveira 2865487b6ceSDaniel Bristot de Oliveira if (!tevent->filter) 2875487b6ceSDaniel Bristot de Oliveira return; 2885487b6ceSDaniel Bristot de Oliveira 2895487b6ceSDaniel Bristot de Oliveira if (!tevent->filter_enabled) 2905487b6ceSDaniel Bristot de Oliveira return; 2915487b6ceSDaniel Bristot de Oliveira 2925487b6ceSDaniel Bristot de Oliveira debug_msg("Disabling %s:%s filter %s\n", tevent->system, 2935487b6ceSDaniel Bristot de Oliveira tevent->event ? : "*", tevent->filter); 2945487b6ceSDaniel Bristot de Oliveira 2955487b6ceSDaniel Bristot de Oliveira snprintf(filter, 1024, "!%s\n", tevent->filter); 2965487b6ceSDaniel Bristot de Oliveira 2975487b6ceSDaniel Bristot de Oliveira retval = tracefs_event_file_write(instance->inst, tevent->system, 2985487b6ceSDaniel Bristot de Oliveira tevent->event, "filter", filter); 2995487b6ceSDaniel Bristot de Oliveira if (retval < 0) 3005487b6ceSDaniel Bristot de Oliveira err_msg("Error disabling %s:%s filter %s\n", tevent->system, 3015487b6ceSDaniel Bristot de Oliveira tevent->event ? : "*", tevent->filter); 3025487b6ceSDaniel Bristot de Oliveira } 3035487b6ceSDaniel Bristot de Oliveira 3045487b6ceSDaniel Bristot de Oliveira /* 305761916fdSDaniel Bristot de Oliveira * trace_event_save_hist - save the content of an event hist 306761916fdSDaniel Bristot de Oliveira * 307761916fdSDaniel Bristot de Oliveira * If the trigger is a hist: one, save the content of the hist file. 308761916fdSDaniel Bristot de Oliveira */ 309761916fdSDaniel Bristot de Oliveira static void trace_event_save_hist(struct trace_instance *instance, 310761916fdSDaniel Bristot de Oliveira struct trace_events *tevent) 311761916fdSDaniel Bristot de Oliveira { 312761916fdSDaniel Bristot de Oliveira int retval, index, out_fd; 313761916fdSDaniel Bristot de Oliveira mode_t mode = 0644; 314761916fdSDaniel Bristot de Oliveira char path[1024]; 315761916fdSDaniel Bristot de Oliveira char *hist; 316761916fdSDaniel Bristot de Oliveira 317761916fdSDaniel Bristot de Oliveira if (!tevent) 318761916fdSDaniel Bristot de Oliveira return; 319761916fdSDaniel Bristot de Oliveira 320761916fdSDaniel Bristot de Oliveira /* trigger enables hist */ 321761916fdSDaniel Bristot de Oliveira if (!tevent->trigger) 322761916fdSDaniel Bristot de Oliveira return; 323761916fdSDaniel Bristot de Oliveira 324761916fdSDaniel Bristot de Oliveira /* is this a hist: trigger? */ 325761916fdSDaniel Bristot de Oliveira retval = strncmp(tevent->trigger, "hist:", strlen("hist:")); 326761916fdSDaniel Bristot de Oliveira if (retval) 327761916fdSDaniel Bristot de Oliveira return; 328761916fdSDaniel Bristot de Oliveira 329761916fdSDaniel Bristot de Oliveira snprintf(path, 1024, "%s_%s_hist.txt", tevent->system, tevent->event); 330761916fdSDaniel Bristot de Oliveira 331761916fdSDaniel Bristot de Oliveira printf(" Saving event %s:%s hist to %s\n", tevent->system, tevent->event, path); 332761916fdSDaniel Bristot de Oliveira 333761916fdSDaniel Bristot de Oliveira out_fd = creat(path, mode); 334761916fdSDaniel Bristot de Oliveira if (out_fd < 0) { 335761916fdSDaniel Bristot de Oliveira err_msg(" Failed to create %s output file\n", path); 336761916fdSDaniel Bristot de Oliveira return; 337761916fdSDaniel Bristot de Oliveira } 338761916fdSDaniel Bristot de Oliveira 339761916fdSDaniel Bristot de Oliveira hist = tracefs_event_file_read(instance->inst, tevent->system, tevent->event, "hist", 0); 340761916fdSDaniel Bristot de Oliveira if (!hist) { 341761916fdSDaniel Bristot de Oliveira err_msg(" Failed to read %s:%s hist file\n", tevent->system, tevent->event); 342761916fdSDaniel Bristot de Oliveira goto out_close; 343761916fdSDaniel Bristot de Oliveira } 344761916fdSDaniel Bristot de Oliveira 345761916fdSDaniel Bristot de Oliveira index = 0; 346761916fdSDaniel Bristot de Oliveira do { 347761916fdSDaniel Bristot de Oliveira index += write(out_fd, &hist[index], strlen(hist) - index); 348761916fdSDaniel Bristot de Oliveira } while (index < strlen(hist)); 349761916fdSDaniel Bristot de Oliveira 350761916fdSDaniel Bristot de Oliveira free(hist); 351761916fdSDaniel Bristot de Oliveira out_close: 352761916fdSDaniel Bristot de Oliveira close(out_fd); 353761916fdSDaniel Bristot de Oliveira } 354761916fdSDaniel Bristot de Oliveira 355761916fdSDaniel Bristot de Oliveira /* 356336c92b2SDaniel Bristot de Oliveira * trace_event_disable_trigger - disable an event trigger 357336c92b2SDaniel Bristot de Oliveira */ 358336c92b2SDaniel Bristot de Oliveira static void trace_event_disable_trigger(struct trace_instance *instance, 359336c92b2SDaniel Bristot de Oliveira struct trace_events *tevent) 360336c92b2SDaniel Bristot de Oliveira { 361336c92b2SDaniel Bristot de Oliveira char trigger[1024]; 362336c92b2SDaniel Bristot de Oliveira int retval; 363336c92b2SDaniel Bristot de Oliveira 364336c92b2SDaniel Bristot de Oliveira if (!tevent->trigger) 365336c92b2SDaniel Bristot de Oliveira return; 366336c92b2SDaniel Bristot de Oliveira 367336c92b2SDaniel Bristot de Oliveira if (!tevent->trigger_enabled) 368336c92b2SDaniel Bristot de Oliveira return; 369336c92b2SDaniel Bristot de Oliveira 370336c92b2SDaniel Bristot de Oliveira debug_msg("Disabling %s:%s trigger %s\n", tevent->system, 371336c92b2SDaniel Bristot de Oliveira tevent->event ? : "*", tevent->trigger); 372336c92b2SDaniel Bristot de Oliveira 373761916fdSDaniel Bristot de Oliveira trace_event_save_hist(instance, tevent); 374761916fdSDaniel Bristot de Oliveira 375336c92b2SDaniel Bristot de Oliveira snprintf(trigger, 1024, "!%s\n", tevent->trigger); 376336c92b2SDaniel Bristot de Oliveira 377336c92b2SDaniel Bristot de Oliveira retval = tracefs_event_file_write(instance->inst, tevent->system, 378336c92b2SDaniel Bristot de Oliveira tevent->event, "trigger", trigger); 379336c92b2SDaniel Bristot de Oliveira if (retval < 0) 380336c92b2SDaniel Bristot de Oliveira err_msg("Error disabling %s:%s trigger %s\n", tevent->system, 381336c92b2SDaniel Bristot de Oliveira tevent->event ? : "*", tevent->trigger); 382336c92b2SDaniel Bristot de Oliveira } 383336c92b2SDaniel Bristot de Oliveira 384336c92b2SDaniel Bristot de Oliveira /* 385b5aa0be2SDaniel Bristot de Oliveira * trace_events_disable - disable all trace events 386b5aa0be2SDaniel Bristot de Oliveira */ 387b5aa0be2SDaniel Bristot de Oliveira void trace_events_disable(struct trace_instance *instance, 388b5aa0be2SDaniel Bristot de Oliveira struct trace_events *events) 389b5aa0be2SDaniel Bristot de Oliveira { 390b5aa0be2SDaniel Bristot de Oliveira struct trace_events *tevent = events; 391b5aa0be2SDaniel Bristot de Oliveira 392b5aa0be2SDaniel Bristot de Oliveira if (!events) 393b5aa0be2SDaniel Bristot de Oliveira return; 394b5aa0be2SDaniel Bristot de Oliveira 395b5aa0be2SDaniel Bristot de Oliveira while (tevent) { 396b5aa0be2SDaniel Bristot de Oliveira debug_msg("Disabling event %s:%s\n", tevent->system, tevent->event ? : "*"); 397336c92b2SDaniel Bristot de Oliveira if (tevent->enabled) { 3985487b6ceSDaniel Bristot de Oliveira trace_event_disable_filter(instance, tevent); 399336c92b2SDaniel Bristot de Oliveira trace_event_disable_trigger(instance, tevent); 400b5aa0be2SDaniel Bristot de Oliveira tracefs_event_disable(instance->inst, tevent->system, tevent->event); 401336c92b2SDaniel Bristot de Oliveira } 402b5aa0be2SDaniel Bristot de Oliveira 403b5aa0be2SDaniel Bristot de Oliveira tevent->enabled = 0; 404b5aa0be2SDaniel Bristot de Oliveira tevent = tevent->next; 405b5aa0be2SDaniel Bristot de Oliveira } 406b5aa0be2SDaniel Bristot de Oliveira } 407b5aa0be2SDaniel Bristot de Oliveira 408b5aa0be2SDaniel Bristot de Oliveira /* 4095487b6ceSDaniel Bristot de Oliveira * trace_event_enable_filter - enable an event filter associated with an event 4105487b6ceSDaniel Bristot de Oliveira */ 4115487b6ceSDaniel Bristot de Oliveira static int trace_event_enable_filter(struct trace_instance *instance, 4125487b6ceSDaniel Bristot de Oliveira struct trace_events *tevent) 4135487b6ceSDaniel Bristot de Oliveira { 4145487b6ceSDaniel Bristot de Oliveira char filter[1024]; 4155487b6ceSDaniel Bristot de Oliveira int retval; 4165487b6ceSDaniel Bristot de Oliveira 4175487b6ceSDaniel Bristot de Oliveira if (!tevent->filter) 4185487b6ceSDaniel Bristot de Oliveira return 0; 4195487b6ceSDaniel Bristot de Oliveira 4205487b6ceSDaniel Bristot de Oliveira if (!tevent->event) { 4215487b6ceSDaniel Bristot de Oliveira err_msg("Filter %s applies only for single events, not for all %s:* events\n", 4225487b6ceSDaniel Bristot de Oliveira tevent->filter, tevent->system); 4235487b6ceSDaniel Bristot de Oliveira return 1; 4245487b6ceSDaniel Bristot de Oliveira } 4255487b6ceSDaniel Bristot de Oliveira 4265487b6ceSDaniel Bristot de Oliveira snprintf(filter, 1024, "%s\n", tevent->filter); 4275487b6ceSDaniel Bristot de Oliveira 4285487b6ceSDaniel Bristot de Oliveira debug_msg("Enabling %s:%s filter %s\n", tevent->system, 4295487b6ceSDaniel Bristot de Oliveira tevent->event ? : "*", tevent->filter); 4305487b6ceSDaniel Bristot de Oliveira 4315487b6ceSDaniel Bristot de Oliveira retval = tracefs_event_file_write(instance->inst, tevent->system, 4325487b6ceSDaniel Bristot de Oliveira tevent->event, "filter", filter); 4335487b6ceSDaniel Bristot de Oliveira if (retval < 0) { 4345487b6ceSDaniel Bristot de Oliveira err_msg("Error enabling %s:%s filter %s\n", tevent->system, 4355487b6ceSDaniel Bristot de Oliveira tevent->event ? : "*", tevent->filter); 4365487b6ceSDaniel Bristot de Oliveira return 1; 4375487b6ceSDaniel Bristot de Oliveira } 4385487b6ceSDaniel Bristot de Oliveira 4395487b6ceSDaniel Bristot de Oliveira tevent->filter_enabled = 1; 4405487b6ceSDaniel Bristot de Oliveira return 0; 4415487b6ceSDaniel Bristot de Oliveira } 4425487b6ceSDaniel Bristot de Oliveira 4435487b6ceSDaniel Bristot de Oliveira /* 444336c92b2SDaniel Bristot de Oliveira * trace_event_enable_trigger - enable an event trigger associated with an event 445336c92b2SDaniel Bristot de Oliveira */ 446336c92b2SDaniel Bristot de Oliveira static int trace_event_enable_trigger(struct trace_instance *instance, 447336c92b2SDaniel Bristot de Oliveira struct trace_events *tevent) 448336c92b2SDaniel Bristot de Oliveira { 449336c92b2SDaniel Bristot de Oliveira char trigger[1024]; 450336c92b2SDaniel Bristot de Oliveira int retval; 451336c92b2SDaniel Bristot de Oliveira 452336c92b2SDaniel Bristot de Oliveira if (!tevent->trigger) 453336c92b2SDaniel Bristot de Oliveira return 0; 454336c92b2SDaniel Bristot de Oliveira 455336c92b2SDaniel Bristot de Oliveira if (!tevent->event) { 456336c92b2SDaniel Bristot de Oliveira err_msg("Trigger %s applies only for single events, not for all %s:* events\n", 457336c92b2SDaniel Bristot de Oliveira tevent->trigger, tevent->system); 458336c92b2SDaniel Bristot de Oliveira return 1; 459336c92b2SDaniel Bristot de Oliveira } 460336c92b2SDaniel Bristot de Oliveira 461336c92b2SDaniel Bristot de Oliveira snprintf(trigger, 1024, "%s\n", tevent->trigger); 462336c92b2SDaniel Bristot de Oliveira 463336c92b2SDaniel Bristot de Oliveira debug_msg("Enabling %s:%s trigger %s\n", tevent->system, 464336c92b2SDaniel Bristot de Oliveira tevent->event ? : "*", tevent->trigger); 465336c92b2SDaniel Bristot de Oliveira 466336c92b2SDaniel Bristot de Oliveira retval = tracefs_event_file_write(instance->inst, tevent->system, 467336c92b2SDaniel Bristot de Oliveira tevent->event, "trigger", trigger); 468336c92b2SDaniel Bristot de Oliveira if (retval < 0) { 469336c92b2SDaniel Bristot de Oliveira err_msg("Error enabling %s:%s trigger %s\n", tevent->system, 470336c92b2SDaniel Bristot de Oliveira tevent->event ? : "*", tevent->trigger); 471336c92b2SDaniel Bristot de Oliveira return 1; 472336c92b2SDaniel Bristot de Oliveira } 473336c92b2SDaniel Bristot de Oliveira 474336c92b2SDaniel Bristot de Oliveira tevent->trigger_enabled = 1; 475336c92b2SDaniel Bristot de Oliveira 476336c92b2SDaniel Bristot de Oliveira return 0; 477336c92b2SDaniel Bristot de Oliveira } 478336c92b2SDaniel Bristot de Oliveira 479336c92b2SDaniel Bristot de Oliveira /* 480b5aa0be2SDaniel Bristot de Oliveira * trace_events_enable - enable all events 481b5aa0be2SDaniel Bristot de Oliveira */ 482b5aa0be2SDaniel Bristot de Oliveira int trace_events_enable(struct trace_instance *instance, 483b5aa0be2SDaniel Bristot de Oliveira struct trace_events *events) 484b5aa0be2SDaniel Bristot de Oliveira { 485b5aa0be2SDaniel Bristot de Oliveira struct trace_events *tevent = events; 486b5aa0be2SDaniel Bristot de Oliveira int retval; 487b5aa0be2SDaniel Bristot de Oliveira 488b5aa0be2SDaniel Bristot de Oliveira while (tevent) { 489b5aa0be2SDaniel Bristot de Oliveira debug_msg("Enabling event %s:%s\n", tevent->system, tevent->event ? : "*"); 490b5aa0be2SDaniel Bristot de Oliveira retval = tracefs_event_enable(instance->inst, tevent->system, tevent->event); 491b5aa0be2SDaniel Bristot de Oliveira if (retval < 0) { 492b5aa0be2SDaniel Bristot de Oliveira err_msg("Error enabling event %s:%s\n", tevent->system, 493b5aa0be2SDaniel Bristot de Oliveira tevent->event ? : "*"); 494b5aa0be2SDaniel Bristot de Oliveira return 1; 495b5aa0be2SDaniel Bristot de Oliveira } 496b5aa0be2SDaniel Bristot de Oliveira 4975487b6ceSDaniel Bristot de Oliveira retval = trace_event_enable_filter(instance, tevent); 4985487b6ceSDaniel Bristot de Oliveira if (retval) 4995487b6ceSDaniel Bristot de Oliveira return 1; 500b5aa0be2SDaniel Bristot de Oliveira 501336c92b2SDaniel Bristot de Oliveira retval = trace_event_enable_trigger(instance, tevent); 502336c92b2SDaniel Bristot de Oliveira if (retval) 503336c92b2SDaniel Bristot de Oliveira return 1; 504336c92b2SDaniel Bristot de Oliveira 505b5aa0be2SDaniel Bristot de Oliveira tevent->enabled = 1; 506b5aa0be2SDaniel Bristot de Oliveira tevent = tevent->next; 507b5aa0be2SDaniel Bristot de Oliveira } 508b5aa0be2SDaniel Bristot de Oliveira 509b5aa0be2SDaniel Bristot de Oliveira return 0; 510b5aa0be2SDaniel Bristot de Oliveira } 511b5aa0be2SDaniel Bristot de Oliveira 512b5aa0be2SDaniel Bristot de Oliveira /* 513b5aa0be2SDaniel Bristot de Oliveira * trace_events_destroy - disable and free all trace events 514b5aa0be2SDaniel Bristot de Oliveira */ 515b5aa0be2SDaniel Bristot de Oliveira void trace_events_destroy(struct trace_instance *instance, 516b5aa0be2SDaniel Bristot de Oliveira struct trace_events *events) 517b5aa0be2SDaniel Bristot de Oliveira { 518b5aa0be2SDaniel Bristot de Oliveira if (!events) 519b5aa0be2SDaniel Bristot de Oliveira return; 520b5aa0be2SDaniel Bristot de Oliveira 521b5aa0be2SDaniel Bristot de Oliveira trace_events_disable(instance, events); 522b5aa0be2SDaniel Bristot de Oliveira trace_events_free(events); 523b5aa0be2SDaniel Bristot de Oliveira } 52428d2160cSDaniel Bristot de Oliveira 52528d2160cSDaniel Bristot de Oliveira int trace_is_off(struct trace_instance *tool, struct trace_instance *trace) 52628d2160cSDaniel Bristot de Oliveira { 52728d2160cSDaniel Bristot de Oliveira /* 52828d2160cSDaniel Bristot de Oliveira * The tool instance is always present, it is the one used to collect 52928d2160cSDaniel Bristot de Oliveira * data. 53028d2160cSDaniel Bristot de Oliveira */ 53128d2160cSDaniel Bristot de Oliveira if (!tracefs_trace_is_on(tool->inst)) 53228d2160cSDaniel Bristot de Oliveira return 1; 53328d2160cSDaniel Bristot de Oliveira 53428d2160cSDaniel Bristot de Oliveira /* 53528d2160cSDaniel Bristot de Oliveira * The trace instance is only enabled when -t is set. IOW, when the system 53628d2160cSDaniel Bristot de Oliveira * is tracing. 53728d2160cSDaniel Bristot de Oliveira */ 53828d2160cSDaniel Bristot de Oliveira if (trace && !tracefs_trace_is_on(trace->inst)) 53928d2160cSDaniel Bristot de Oliveira return 1; 54028d2160cSDaniel Bristot de Oliveira 54128d2160cSDaniel Bristot de Oliveira return 0; 54228d2160cSDaniel Bristot de Oliveira } 543