1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3 * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4 *
5 * Updates:
6 * Copyright (C) 2019, VMware, Tzvetomir Stoyanov <tz.stoyanov@gmail.com>
7 *
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <ctype.h>
14 #include <errno.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <dirent.h>
18 #include <regex.h>
19 #include <limits.h>
20 #include <pthread.h>
21 #include "tracefs.h"
22 #include "tracefs-local.h"
23
24 enum {
25 FLAG_INSTANCE_NEWLY_CREATED = (1 << 0),
26 FLAG_INSTANCE_DELETED = (1 << 1),
27 };
28
29
30 struct tracefs_options_mask toplevel_supported_opts;
31 struct tracefs_options_mask toplevel_enabled_opts;
32
33 __hidden inline struct tracefs_options_mask *
supported_opts_mask(struct tracefs_instance * instance)34 supported_opts_mask(struct tracefs_instance *instance)
35 {
36 return instance ? &instance->supported_opts : &toplevel_supported_opts;
37 }
38
39 __hidden inline struct tracefs_options_mask *
enabled_opts_mask(struct tracefs_instance * instance)40 enabled_opts_mask(struct tracefs_instance *instance)
41 {
42 return instance ? &instance->enabled_opts : &toplevel_enabled_opts;
43 }
44
45 /**
46 * instance_alloc - allocate a new ftrace instance
47 * @trace_dir - Full path to the tracing directory, where the instance is
48 * @name: The name of the instance (instance will point to this)
49 *
50 * Returns a newly allocated instance, or NULL in case of an error.
51 */
instance_alloc(const char * trace_dir,const char * name)52 static struct tracefs_instance *instance_alloc(const char *trace_dir, const char *name)
53 {
54 struct tracefs_instance *instance;
55
56 instance = calloc(1, sizeof(*instance));
57 if (!instance)
58 goto error;
59 instance->trace_dir = strdup(trace_dir);
60 if (!instance->trace_dir)
61 goto error;
62 if (name) {
63 instance->name = strdup(name);
64 if (!instance->name)
65 goto error;
66 }
67
68 if (pthread_mutex_init(&instance->lock, NULL) < 0)
69 goto error;
70
71 instance->ftrace_filter_fd = -1;
72 instance->ftrace_notrace_fd = -1;
73 instance->ftrace_marker_fd = -1;
74 instance->ftrace_marker_raw_fd = -1;
75
76 return instance;
77
78 error:
79 if (instance) {
80 free(instance->name);
81 free(instance->trace_dir);
82 free(instance);
83 }
84 return NULL;
85 }
86
87
trace_get_instance(struct tracefs_instance * instance)88 __hidden int trace_get_instance(struct tracefs_instance *instance)
89 {
90 int ret;
91
92 pthread_mutex_lock(&instance->lock);
93 if (instance->flags & FLAG_INSTANCE_DELETED) {
94 ret = -1;
95 } else {
96 instance->ref++;
97 ret = 0;
98 }
99 pthread_mutex_unlock(&instance->lock);
100 return ret;
101 }
102
trace_put_instance(struct tracefs_instance * instance)103 __hidden void trace_put_instance(struct tracefs_instance *instance)
104 {
105 pthread_mutex_lock(&instance->lock);
106 if (--instance->ref < 0)
107 instance->flags |= FLAG_INSTANCE_DELETED;
108 pthread_mutex_unlock(&instance->lock);
109
110 if (!(instance->flags & FLAG_INSTANCE_DELETED))
111 return;
112
113 if (instance->ftrace_filter_fd >= 0)
114 close(instance->ftrace_filter_fd);
115
116 if (instance->ftrace_notrace_fd >= 0)
117 close(instance->ftrace_notrace_fd);
118
119 if (instance->ftrace_marker_fd >= 0)
120 close(instance->ftrace_marker_fd);
121
122 if (instance->ftrace_marker_raw_fd >= 0)
123 close(instance->ftrace_marker_raw_fd);
124
125 free(instance->trace_dir);
126 free(instance->followers);
127 free(instance->missed_followers);
128 free(instance->name);
129 pthread_mutex_destroy(&instance->lock);
130 free(instance);
131 }
132
133 /**
134 * tracefs_instance_free - Free an instance, previously allocated by
135 tracefs_instance_create()
136 * @instance: Pointer to the instance to be freed
137 *
138 */
tracefs_instance_free(struct tracefs_instance * instance)139 void tracefs_instance_free(struct tracefs_instance *instance)
140 {
141 if (!instance)
142 return;
143
144 trace_put_instance(instance);
145 }
146
get_trace_file_permissions(char * name)147 static mode_t get_trace_file_permissions(char *name)
148 {
149 mode_t rmode = 0;
150 struct stat st;
151 char *path;
152 int ret;
153
154 path = tracefs_get_tracing_file(name);
155 if (!path)
156 return 0;
157 ret = stat(path, &st);
158 if (ret)
159 goto out;
160 rmode = st.st_mode & ACCESSPERMS;
161 out:
162 tracefs_put_tracing_file(path);
163 return rmode;
164 }
165
166 /**
167 * tracefs_instance_is_new - Check if the instance is newly created by the library
168 * @instance: Pointer to an ftrace instance
169 *
170 * Returns true, if the ftrace instance is newly created by the library or
171 * false otherwise.
172 */
tracefs_instance_is_new(struct tracefs_instance * instance)173 bool tracefs_instance_is_new(struct tracefs_instance *instance)
174 {
175 if (instance && (instance->flags & FLAG_INSTANCE_NEWLY_CREATED))
176 return true;
177 return false;
178 }
179
180 /**
181 * tracefs_instance_create - Create a new ftrace instance
182 * @name: Name of the instance to be created
183 *
184 * Allocates and initializes a new instance structure. If the instance does not
185 * exist in the system, create it.
186 * Returns a pointer to a newly allocated instance, or NULL in case of an error.
187 * The returned instance must be freed by tracefs_instance_free().
188 */
tracefs_instance_create(const char * name)189 struct tracefs_instance *tracefs_instance_create(const char *name)
190 {
191 struct tracefs_instance *inst = NULL;
192 char *path = NULL;
193 const char *tdir;
194 struct stat st;
195 mode_t mode;
196 int ret;
197
198 tdir = tracefs_tracing_dir();
199 if (!tdir)
200 return NULL;
201 inst = instance_alloc(tdir, name);
202 if (!inst)
203 return NULL;
204
205 path = tracefs_instance_get_dir(inst);
206 ret = stat(path, &st);
207 if (ret < 0) {
208 /* Cannot create the top instance, if it does not exist! */
209 if (!name)
210 goto error;
211 mode = get_trace_file_permissions("instances");
212 if (mkdir(path, mode))
213 goto error;
214 inst->flags |= FLAG_INSTANCE_NEWLY_CREATED;
215 }
216 tracefs_put_tracing_file(path);
217 return inst;
218
219 error:
220 tracefs_put_tracing_file(path);
221 tracefs_instance_free(inst);
222 return NULL;
223 }
224
225 /**
226 * tracefs_instance_alloc - Allocate an instance structure for existing trace instance
227 * @tracing_dir: full path to the system trace directory, where the new instance is
228 * if NULL, the default top tracing directory is used.
229 * @name: Name of the instance.
230 *
231 * Allocates and initializes a new instance structure. If the instance does not
232 * exist, do not create it and exit with error.
233 * Returns a pointer to a newly allocated instance, or NULL in case of an error
234 * or the requested instance does not exists.
235 * The returned instance must be freed by tracefs_instance_free().
236 */
tracefs_instance_alloc(const char * tracing_dir,const char * name)237 struct tracefs_instance *tracefs_instance_alloc(const char *tracing_dir,
238 const char *name)
239 {
240 struct tracefs_instance *inst = NULL;
241 char file[PATH_MAX];
242 const char *tdir;
243 struct stat st;
244 int ret;
245
246 if (tracing_dir) {
247 ret = stat(tracing_dir, &st);
248 if (ret < 0 || !S_ISDIR(st.st_mode))
249 return NULL;
250 tdir = tracing_dir;
251
252 } else
253 tdir = tracefs_tracing_dir();
254 if (!tdir)
255 return NULL;
256
257 if (name) {
258 sprintf(file, "%s/instances/%s", tdir, name);
259 ret = stat(file, &st);
260 if (ret < 0 || !S_ISDIR(st.st_mode))
261 return NULL;
262 }
263 inst = instance_alloc(tdir, name);
264
265 return inst;
266 }
267
268 /**
269 * tracefs_instance_destroy - Remove a ftrace instance
270 * @instance: Pointer to the instance to be removed
271 *
272 * Returns -1 in case of an error, or 0 otherwise.
273 */
tracefs_instance_destroy(struct tracefs_instance * instance)274 int tracefs_instance_destroy(struct tracefs_instance *instance)
275 {
276 char *path;
277 int ret = -1;
278
279 if (!instance || !instance->name) {
280 tracefs_warning("Cannot remove top instance");
281 return -1;
282 }
283
284 path = tracefs_instance_get_dir(instance);
285 if (path)
286 ret = rmdir(path);
287 tracefs_put_tracing_file(path);
288 if (ret) {
289 pthread_mutex_lock(&instance->lock);
290 instance->flags |= FLAG_INSTANCE_DELETED;
291 pthread_mutex_unlock(&instance->lock);
292 }
293
294 return ret;
295 }
296
297 /**
298 * tracefs_instance_get_file - return the path to an instance file.
299 * @instance: ftrace instance, can be NULL for the top instance
300 * @file: name of file to return
301 *
302 * Returns the path of the @file for the given @instance, or NULL in
303 * case of an error.
304 *
305 * Must use tracefs_put_tracing_file() to free the returned string.
306 */
307 char *
tracefs_instance_get_file(struct tracefs_instance * instance,const char * file)308 tracefs_instance_get_file(struct tracefs_instance *instance, const char *file)
309 {
310 char *path = NULL;
311 int ret;
312
313 if (!instance)
314 return tracefs_get_tracing_file(file);
315 if (!instance->name)
316 ret = asprintf(&path, "%s/%s", instance->trace_dir, file);
317 else
318 ret = asprintf(&path, "%s/instances/%s/%s",
319 instance->trace_dir, instance->name, file);
320 if (ret < 0)
321 return NULL;
322
323 return path;
324 }
325
326 /**
327 * tracefs_instance_get_dir - return the path to the instance directory.
328 * @instance: ftrace instance, can be NULL for the top instance
329 *
330 * Returns the full path to the instance directory
331 *
332 * Must use tracefs_put_tracing_file() to free the returned string.
333 */
tracefs_instance_get_dir(struct tracefs_instance * instance)334 char *tracefs_instance_get_dir(struct tracefs_instance *instance)
335 {
336 char *path = NULL;
337 int ret;
338
339 if (!instance) /* Top instance of default system trace directory */
340 return trace_find_tracing_dir(false);
341
342 if (!instance->name)
343 return strdup(instance->trace_dir);
344
345 ret = asprintf(&path, "%s/instances/%s", instance->trace_dir, instance->name);
346 if (ret < 0) {
347 tracefs_warning("Failed to allocate path for instance %s",
348 instance->name);
349 return NULL;
350 }
351
352 return path;
353 }
354
355 /**
356 * tracefs_instance_get_name - return the name of an instance
357 * @instance: ftrace instance
358 *
359 * Returns the name of the given @instance.
360 * The returned string must *not* be freed.
361 */
tracefs_instance_get_name(struct tracefs_instance * instance)362 const char *tracefs_instance_get_name(struct tracefs_instance *instance)
363 {
364 if (instance)
365 return instance->name;
366 return NULL;
367 }
368
369 /**
370 * tracefs_instance_get_buffer_size - return the buffer size of the ring buffer
371 * @instance: The instance to get the buffer size from
372 * @cpu: if less that zero, will return the total size, otherwise the cpu size
373 *
374 * Returns the buffer size. If @cpu is less than zero, it returns the total size
375 * of the ring buffer otherwise it returs the size of the buffer for the given
376 * CPU.
377 *
378 * Returns -1 on error.
379 */
tracefs_instance_get_buffer_size(struct tracefs_instance * instance,int cpu)380 ssize_t tracefs_instance_get_buffer_size(struct tracefs_instance *instance, int cpu)
381 {
382 unsigned long long size;
383 char *path;
384 char *val;
385 int ret;
386
387 if (cpu < 0) {
388 val = tracefs_instance_file_read(instance, "buffer_total_size_kb", NULL);
389 } else {
390 ret = asprintf(&path, "per_cpu/cpu%d/buffer_size_kb", cpu);
391 if (ret < 0)
392 return ret;
393
394 val = tracefs_instance_file_read(instance, path, NULL);
395 free(path);
396 }
397
398 if (!val)
399 return -1;
400
401 size = strtoull(val, NULL, 0);
402 free(val);
403 return size;
404 }
405
406 /**
407 * tracefs_instance_set_buffer_size - modify the ring buffer size
408 * @instance: The instance to modify (NULL for the top level)
409 * @size: The size in kilobytes to to set the size to
410 * @cpu: the CPU to set it to (-1 for all CPUs)
411 *
412 * Sets the size of the ring buffer per CPU buffers. If @cpu is negative,
413 * then it sets the ring buffer size for all the per CPU buffers, otherwise
414 * it only sets the per CPU buffer specified by @cpu.
415 *
416 * Returns 0 on success and -1 on error.
417 */
tracefs_instance_set_buffer_size(struct tracefs_instance * instance,size_t size,int cpu)418 int tracefs_instance_set_buffer_size(struct tracefs_instance *instance, size_t size, int cpu)
419 {
420 char *path;
421 char *val;
422 int ret;
423
424 ret = asprintf(&val, "%zd", size);
425 if (ret < 0)
426 return ret;
427
428 if (cpu < 0) {
429 ret = tracefs_instance_file_write(instance, "buffer_size_kb", val);
430 } else {
431 ret = asprintf(&path, "per_cpu/cpu%d/buffer_size_kb", cpu);
432 if (ret < 0) {
433 free(val);
434 return ret;
435 }
436
437 ret = tracefs_instance_file_write(instance, path, val);
438 free(path);
439 }
440 free(val);
441
442 return ret < 0 ? -1 : 0;
443 }
444
445 /**
446 * tracefs_instance_get_subbuf_size - return the sub-buffer size of the ring buffer
447 * @instance: The instance to get the buffer size from
448 *
449 * Returns the sub-buffer size in kilobytes.
450 * Returns -1 on error.
451 */
tracefs_instance_get_subbuf_size(struct tracefs_instance * instance)452 ssize_t tracefs_instance_get_subbuf_size(struct tracefs_instance *instance)
453 {
454 long long size;
455 int ret;
456
457 ret = tracefs_instance_file_read_number(instance, "buffer_subbuf_size_kb", &size);
458 if (ret < 0)
459 return ret;
460
461 return size;
462 }
463
464 /**
465 * tracefs_instance_set_buffer_size - modify the ring buffer sub-buffer size
466 * @instance: The instance to modify (NULL for the top level)
467 * @size: The size in kilobytes to to set the sub-buffer size to
468 *
469 * Sets the sub-buffer size in kilobytes for the given ring buffer.
470 *
471 * Returns 0 on success and -1 on error.
472 */
tracefs_instance_set_subbuf_size(struct tracefs_instance * instance,size_t size)473 int tracefs_instance_set_subbuf_size(struct tracefs_instance *instance, size_t size)
474 {
475 int ret;
476
477 ret = tracefs_instance_file_write_number(instance, "buffer_subbuf_size_kb", size);
478
479 return ret < 0 ? -1 : 0;
480 }
481
482 /**
483 * tracefs_instance_get_trace_dir - return the top trace directory, where the instance is confuigred
484 * @instance: ftrace instance
485 *
486 * Returns the top trace directory where the given @instance is configured.
487 * The returned string must *not* be freed.
488 */
tracefs_instance_get_trace_dir(struct tracefs_instance * instance)489 const char *tracefs_instance_get_trace_dir(struct tracefs_instance *instance)
490 {
491 if (instance)
492 return instance->trace_dir;
493 return NULL;
494 }
495
write_file(const char * file,const char * str,int flags)496 static int write_file(const char *file, const char *str, int flags)
497 {
498 int ret = 0;
499 int fd;
500
501 fd = open(file, flags);
502 if (fd < 0) {
503 tracefs_warning("Failed to open '%s'", file);
504 return -1;
505 }
506
507 if (str)
508 ret = write(fd, str, strlen(str));
509
510 close(fd);
511 return ret;
512 }
513
instance_file_write(struct tracefs_instance * instance,const char * file,const char * str,int flags)514 static int instance_file_write(struct tracefs_instance *instance,
515 const char *file, const char *str, int flags)
516 {
517 struct stat st;
518 char *path;
519 int ret;
520
521 path = tracefs_instance_get_file(instance, file);
522 if (!path)
523 return -1;
524 ret = stat(path, &st);
525 if (ret == 0)
526 ret = write_file(path, str, flags);
527 tracefs_put_tracing_file(path);
528
529 return ret;
530 }
531
532 /**
533 * tracefs_instance_file_write - Write in trace file of specific instance.
534 * @instance: ftrace instance, can be NULL for the top instance
535 * @file: name of the file
536 * @str: nul terminated string, that will be written in the file.
537 *
538 * Returns the number of written bytes, or -1 in case of an error
539 */
tracefs_instance_file_write(struct tracefs_instance * instance,const char * file,const char * str)540 int tracefs_instance_file_write(struct tracefs_instance *instance,
541 const char *file, const char *str)
542 {
543 return instance_file_write(instance, file, str, O_WRONLY | O_TRUNC);
544 }
545
546 /**
547 * tracefs_instance_file_write_number - Write integer from a trace file.
548 * @instance: ftrace instance, can be NULL for the top instance
549 * @file: name of the file
550 * @res: The integer to write to @file
551 *
552 * Returns 0 if the write succeeds, -1 on error.
553 */
tracefs_instance_file_write_number(struct tracefs_instance * instance,const char * file,size_t val)554 int tracefs_instance_file_write_number(struct tracefs_instance *instance,
555 const char *file, size_t val)
556 {
557 char buf[64];
558 int ret;
559
560 snprintf(buf, 64, "%zd\n", val);
561
562 ret = tracefs_instance_file_write(instance, file, buf);
563
564 return ret > 1 ? 0 : -1;
565 }
566
567 /**
568 * tracefs_instance_file_append - Append to a trace file of specific instance.
569 * @instance: ftrace instance, can be NULL for the top instance.
570 * @file: name of the file.
571 * @str: nul terminated string, that will be appended to the file.
572 *
573 * Returns the number of appended bytes, or -1 in case of an error.
574 */
tracefs_instance_file_append(struct tracefs_instance * instance,const char * file,const char * str)575 int tracefs_instance_file_append(struct tracefs_instance *instance,
576 const char *file, const char *str)
577 {
578 return instance_file_write(instance, file, str, O_WRONLY);
579 }
580
581 /**
582 * tracefs_instance_file_clear - Clear a trace file of specific instance.
583 * Note, it only opens with O_TRUNC and closes the file. If the file has
584 * content that does not get cleared in this way, this will not have any
585 * effect. For example, set_ftrace_filter can have probes that are not
586 * cleared by O_TRUNC:
587 *
588 * echo "schedule:stacktrace" > set_ftrace_filter
589 *
590 * This function will not clear the above "set_ftrace_filter" after that
591 * command.
592 * @instance: ftrace instance, can be NULL for the top instance.
593 * @file: name of the file to clear.
594 *
595 * Returns 0 on success, or -1 in case of an error.
596 */
tracefs_instance_file_clear(struct tracefs_instance * instance,const char * file)597 int tracefs_instance_file_clear(struct tracefs_instance *instance,
598 const char *file)
599 {
600 return instance_file_write(instance, file, NULL, O_WRONLY | O_TRUNC);
601 }
602
603 /**
604 * tracefs_instance_file_read - Read from a trace file of specific instance.
605 * @instance: ftrace instance, can be NULL for the top instance
606 * @file: name of the file
607 * @psize: returns the number of bytes read
608 *
609 * Returns a pointer to a nul terminated string, read from the file, or NULL in
610 * case of an error.
611 * The return string must be freed by free()
612 */
tracefs_instance_file_read(struct tracefs_instance * instance,const char * file,int * psize)613 char *tracefs_instance_file_read(struct tracefs_instance *instance,
614 const char *file, int *psize)
615 {
616 char *buf = NULL;
617 int size = 0;
618 char *path;
619
620 path = tracefs_instance_get_file(instance, file);
621 if (!path)
622 return NULL;
623
624 size = str_read_file(path, &buf, true);
625
626 tracefs_put_tracing_file(path);
627 if (buf && psize)
628 *psize = size;
629
630 return buf;
631 }
632
633 /**
634 * tracefs_instance_file_read_number - Read long long integer from a trace file.
635 * @instance: ftrace instance, can be NULL for the top instance
636 * @file: name of the file
637 * @res: The integer from the file.
638 *
639 * Returns 0 if the reading is successful and the result is stored in res, -1
640 * in case of an error.
641 */
tracefs_instance_file_read_number(struct tracefs_instance * instance,const char * file,long long * res)642 int tracefs_instance_file_read_number(struct tracefs_instance *instance,
643 const char *file, long long *res)
644 {
645 long long num;
646 int ret = -1;
647 int size = 0;
648 char *endptr;
649 char *str;
650
651 str = tracefs_instance_file_read(instance, file, &size);
652 if (size && str) {
653 errno = 0;
654 num = strtoll(str, &endptr, 0);
655 if (errno == 0 && str != endptr) {
656 *res = num;
657 ret = 0;
658 }
659 }
660 free(str);
661 return ret;
662 }
663
664 /**
665 * tracefs_instance_file_open - Open a trace file for reading and writing
666 * @instance: ftrace instance, can be NULL for the top instance
667 * @file: name of the file
668 * @mode: file open flags, -1 for default O_RDWR
669 *
670 * Returns -1 in case of an error, or a valid file descriptor otherwise.
671 * The returned FD must be closed with close()
672 */
tracefs_instance_file_open(struct tracefs_instance * instance,const char * file,int mode)673 int tracefs_instance_file_open(struct tracefs_instance *instance,
674 const char *file, int mode)
675 {
676 int flags = O_RDWR;
677 int fd = -1;
678 char *path;
679
680 path = tracefs_instance_get_file(instance, file);
681 if (!path)
682 return -1;
683
684 if (mode >= 0)
685 flags = mode;
686 fd = open(path, flags);
687 tracefs_put_tracing_file(path);
688
689 return fd;
690 }
691
check_file_exists(struct tracefs_instance * instance,const char * name,bool dir)692 static bool check_file_exists(struct tracefs_instance *instance,
693 const char *name, bool dir)
694 {
695 char file[PATH_MAX];
696 struct stat st;
697 char *path;
698 int ret;
699
700 path = tracefs_instance_get_dir(instance);
701 if (name)
702 snprintf(file, PATH_MAX, "%s/%s", path, name);
703 else
704 snprintf(file, PATH_MAX, "%s", path);
705 tracefs_put_tracing_file(path);
706 ret = stat(file, &st);
707 if (ret < 0)
708 return false;
709
710 return !dir == !S_ISDIR(st.st_mode);
711 }
712
713 /**
714 * tracefs_instance_exists - Check an instance with given name exists
715 * @name: name of the instance
716 *
717 * Returns true if the instance exists, false otherwise
718 *
719 */
tracefs_instance_exists(const char * name)720 bool tracefs_instance_exists(const char *name)
721 {
722 char file[PATH_MAX];
723
724 if (!name)
725 return false;
726 snprintf(file, PATH_MAX, "instances/%s", name);
727 return check_file_exists(NULL, file, true);
728 }
729
730 /**
731 * tracefs_file_exists - Check if a file with given name exists in given instance
732 * @instance: ftrace instance, can be NULL for the top instance
733 * @name: name of the file
734 *
735 * Returns true if the file exists, false otherwise
736 *
737 * If a directory with the given name exists, false is returned.
738 */
tracefs_file_exists(struct tracefs_instance * instance,const char * name)739 bool tracefs_file_exists(struct tracefs_instance *instance, const char *name)
740 {
741 return check_file_exists(instance, name, false);
742 }
743
744 /**
745 * tracefs_dir_exists - Check if a directory with given name exists in given instance
746 * @instance: ftrace instance, can be NULL for the top instance
747 * @name: name of the directory
748 *
749 * Returns true if the directory exists, false otherwise
750 */
tracefs_dir_exists(struct tracefs_instance * instance,const char * name)751 bool tracefs_dir_exists(struct tracefs_instance *instance, const char *name)
752 {
753 return check_file_exists(instance, name, true);
754 }
755
756 /**
757 * tracefs_instances_walk - Iterate through all ftrace instances in the system
758 * @callback: user callback, called for each instance. Instance name is passed
759 * as input parameter. If the @callback returns non-zero,
760 * the iteration stops.
761 * @context: user context, passed to the @callback.
762 *
763 * Returns -1 in case of an error, 1 if the iteration was stopped because of the
764 * callback return value or 0 otherwise.
765 */
tracefs_instances_walk(int (* callback)(const char *,void *),void * context)766 int tracefs_instances_walk(int (*callback)(const char *, void *), void *context)
767 {
768 struct dirent *dent;
769 char *path = NULL;
770 DIR *dir = NULL;
771 struct stat st;
772 int fret = -1;
773 int ret;
774
775 path = tracefs_get_tracing_file("instances");
776 if (!path)
777 return -1;
778 ret = stat(path, &st);
779 if (ret < 0 || !S_ISDIR(st.st_mode))
780 goto out;
781
782 dir = opendir(path);
783 if (!dir)
784 goto out;
785 fret = 0;
786 while ((dent = readdir(dir))) {
787 char *instance;
788
789 if (strcmp(dent->d_name, ".") == 0 ||
790 strcmp(dent->d_name, "..") == 0)
791 continue;
792 instance = trace_append_file(path, dent->d_name);
793 ret = stat(instance, &st);
794 free(instance);
795 if (ret < 0 || !S_ISDIR(st.st_mode))
796 continue;
797 if (callback(dent->d_name, context)) {
798 fret = 1;
799 break;
800 }
801 }
802
803 out:
804 if (dir)
805 closedir(dir);
806 tracefs_put_tracing_file(path);
807 return fret;
808 }
809
match(const char * str,regex_t * re)810 static inline bool match(const char *str, regex_t *re)
811 {
812 if (!re)
813 return true;
814 return regexec(re, str, 0, NULL, 0) == 0;
815 }
816
817 struct instance_list {
818 regex_t *re;
819 char **list;
820 int failed;
821 };
822
build_list(const char * name,void * data)823 static int build_list(const char *name, void *data)
824 {
825 struct instance_list *list = data;
826 char **instances;
827 int ret = -1;
828
829 if (!match(name, list->re))
830 return 0;
831
832 instances = tracefs_list_add(list->list, name);
833 if (!instances)
834 goto out;
835
836 list->list = instances;
837 ret = 0;
838
839 out:
840 list->failed = ret;
841 return ret;
842 }
843
844 /**
845 * tracefs_instances - return a list of instance names
846 * @regex: A regex of instances to filter on (NULL to match all)
847 *
848 * Returns a list of names of existing instances, that must be
849 * freed with tracefs_list_free(). Note, if there are no matches
850 * then an empty list will be returned (not NULL).
851 * NULL on error.
852 */
tracefs_instances(const char * regex)853 char **tracefs_instances(const char *regex)
854 {
855 struct instance_list list = { .re = NULL, .list = NULL };
856 regex_t re;
857 int ret;
858
859 if (regex) {
860 ret = regcomp(&re, regex, REG_ICASE|REG_NOSUB);
861 if (ret < 0)
862 return NULL;
863 list.re = &re;
864 }
865
866 ret = tracefs_instances_walk(build_list, &list);
867 if (ret < 0 || list.failed) {
868 tracefs_list_free(list.list);
869 list.list = NULL;
870 } else {
871 /* No matches should produce an empty list */
872 if (!list.list)
873 list.list = trace_list_create_empty();
874 }
875 return list.list;
876 }
877
878 /**
879 * tracefs_get_clock - Get the current trace clock
880 * @instance: ftrace instance, can be NULL for the top instance
881 *
882 * Returns the current trace clock of the given instance, or NULL in
883 * case of an error.
884 * The return string must be freed by free()
885 */
tracefs_get_clock(struct tracefs_instance * instance)886 char *tracefs_get_clock(struct tracefs_instance *instance)
887 {
888 char *all_clocks = NULL;
889 char *ret = NULL;
890 int bytes = 0;
891 char *clock;
892 char *cont;
893
894 all_clocks = tracefs_instance_file_read(instance, "trace_clock", &bytes);
895 if (!all_clocks || !bytes)
896 goto out;
897
898 clock = strstr(all_clocks, "[");
899 if (!clock)
900 goto out;
901 clock++;
902 cont = strstr(clock, "]");
903 if (!cont)
904 goto out;
905 *cont = '\0';
906
907 ret = strdup(clock);
908 out:
909 free(all_clocks);
910 return ret;
911 }
912
913 /**
914 * tracefs_instance_set_affinity_raw - write a hex bitmask into the affinity
915 * @instance: The instance to set affinity to (NULL for top level)
916 * @mask: String containing the hex value to set the tracing affinity to.
917 *
918 * Sets the tracing affinity CPU mask for @instance. The @mask is the raw
919 * value that is used to write into the tracing system.
920 *
921 * Return 0 on success and -1 on error.
922 */
tracefs_instance_set_affinity_raw(struct tracefs_instance * instance,const char * mask)923 int tracefs_instance_set_affinity_raw(struct tracefs_instance *instance,
924 const char *mask)
925 {
926 return tracefs_instance_file_write(instance, "tracing_cpumask", mask);
927 }
928
929 /**
930 * tracefs_instance_set_affinity_set - use a cpu_set to define tracing affinity
931 * @instance: The instance to set affinity to (NULL for top level)
932 * @set: A CPU set that describes the CPU affinity to set tracing to.
933 * @set_size: The size in bytes of @set (use CPU_ALLOC_SIZE() to get this value)
934 *
935 * Sets the tracing affinity CPU mask for @instance. The bits in @set will be
936 * used to set the CPUs to have tracing on.
937 *
938 * If @set is NULL, then all CPUs defined by sysconf(_SC_NPROCESSORS_CONF)
939 * will be set, and @set_size is ignored.
940 *
941 * Return 0 on success and -1 on error.
942 */
tracefs_instance_set_affinity_set(struct tracefs_instance * instance,cpu_set_t * set,size_t set_size)943 int tracefs_instance_set_affinity_set(struct tracefs_instance *instance,
944 cpu_set_t *set, size_t set_size)
945 {
946 struct trace_seq seq;
947 bool free_set = false;
948 bool hit = false;
949 int nr_cpus;
950 int cpu;
951 int ret = -1;
952 int w, n, i;
953
954 trace_seq_init(&seq);
955
956 /* NULL set means all CPUs to be set */
957 if (!set) {
958 nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
959 set = CPU_ALLOC(nr_cpus);
960 if (!set)
961 goto out;
962 set_size = CPU_ALLOC_SIZE(nr_cpus);
963 CPU_ZERO_S(set_size, set);
964 /* Set all CPUS */
965 for (cpu = 0; cpu < nr_cpus; cpu++)
966 CPU_SET_S(cpu, set_size, set);
967 free_set = true;
968 }
969 /* Convert to a bitmask hex string */
970 nr_cpus = (set_size + 1) * 8;
971 if (nr_cpus < 1) {
972 /* Must have at least one bit set */
973 errno = EINVAL;
974 goto out;
975 }
976 /* Start backwards from 32 bits */
977 for (w = ((nr_cpus + 31) / 32) - 1; w >= 0; w--) {
978 /* Now move one nibble at a time */
979 for (n = 7; n >= 0; n--) {
980 int nibble = 0;
981
982 if ((n * 4) + (w * 32) >= nr_cpus)
983 continue;
984
985 /* One bit at a time */
986 for (i = 3; i >= 0; i--) {
987 cpu = (w * 32) + (n * 4) + i;
988 if (cpu >= nr_cpus)
989 continue;
990 if (CPU_ISSET_S(cpu, set_size, set)) {
991 nibble |= 1 << i;
992 hit = true;
993 }
994 }
995 if (hit && trace_seq_printf(&seq, "%x", nibble) < 0)
996 goto out;
997 }
998 if (hit && w)
999 if (trace_seq_putc(&seq, ',') < 0)
1000 goto out;
1001 }
1002 if (!hit) {
1003 errno = EINVAL;
1004 goto out;
1005 }
1006 trace_seq_terminate(&seq);
1007 ret = tracefs_instance_set_affinity_raw(instance, seq.buffer);
1008 out:
1009 trace_seq_destroy(&seq);
1010 if (free_set)
1011 CPU_FREE(set);
1012 return ret;
1013 }
1014
1015 /**
1016 * tracefs_instance_set_affinity - Set the affinity defined by CPU values.
1017 * @instance: The instance to set affinity to (NULL for top level)
1018 * @cpu_str: A string of values that define what CPUs to set.
1019 *
1020 * Sets the tracing affinity CPU mask for @instance. The @cpu_str is a set
1021 * of decimal numbers used to state which CPU should be part of the affinity
1022 * mask. A range may also be specified via a hyphen.
1023 *
1024 * For example, "1,4,6-8"
1025 *
1026 * The numbers do not need to be in order.
1027 *
1028 * If @cpu_str is NULL, then all CPUs defined by sysconf(_SC_NPROCESSORS_CONF)
1029 * will be set.
1030 *
1031 * Return 0 on success and -1 on error.
1032 */
tracefs_instance_set_affinity(struct tracefs_instance * instance,const char * cpu_str)1033 int tracefs_instance_set_affinity(struct tracefs_instance *instance,
1034 const char *cpu_str)
1035 {
1036 cpu_set_t *set = NULL;
1037 size_t set_size;
1038 char *word;
1039 char *cpus;
1040 char *del;
1041 char *c;
1042 int max_cpu = 0;
1043 int cpu1, cpu2;
1044 int len;
1045 int ret = -1;
1046
1047 /* NULL cpu_str means to set all CPUs in the mask */
1048 if (!cpu_str)
1049 return tracefs_instance_set_affinity_set(instance, NULL, 0);
1050
1051 /* First, find out how many CPUs are needed */
1052 cpus = strdup(cpu_str);
1053 if (!cpus)
1054 return -1;
1055 len = strlen(cpus) + 1;
1056 for (word = strtok_r(cpus, ",", &del); word; word = strtok_r(NULL, ",", &del)) {
1057 cpu1 = atoi(word);
1058 if (cpu1 < 0) {
1059 errno = EINVAL;
1060 goto out;
1061 }
1062 if (cpu1 > max_cpu)
1063 max_cpu = cpu1;
1064 cpu2 = -1;
1065 if ((c = strchr(word, '-'))) {
1066 c++;
1067 cpu2 = atoi(c);
1068 if (cpu2 < cpu1) {
1069 errno = EINVAL;
1070 goto out;
1071 }
1072 if (cpu2 > max_cpu)
1073 max_cpu = cpu2;
1074 }
1075 }
1076 /*
1077 * Now ideally, cpus should fit cpu_str as it was orginally allocated
1078 * by strdup(). But I'm paranoid, and can imagine someone playing tricks
1079 * with threads, and changes cpu_str from another thread and messes
1080 * with this. At least only copy what we know is allocated.
1081 */
1082 strncpy(cpus, cpu_str, len);
1083
1084 set = CPU_ALLOC(max_cpu + 1);
1085 if (!set)
1086 goto out;
1087 set_size = CPU_ALLOC_SIZE(max_cpu + 1);
1088 CPU_ZERO_S(set_size, set);
1089
1090 for (word = strtok_r(cpus, ",", &del); word; word = strtok_r(NULL, ",", &del)) {
1091 cpu1 = atoi(word);
1092 if (cpu1 < 0 || cpu1 > max_cpu) {
1093 /* Someone playing games? */
1094 errno = EACCES;
1095 goto out;
1096 }
1097 cpu2 = cpu1;
1098 if ((c = strchr(word, '-'))) {
1099 c++;
1100 cpu2 = atoi(c);
1101 if (cpu2 < cpu1 || cpu2 > max_cpu) {
1102 errno = EACCES;
1103 goto out;
1104 }
1105 }
1106 for ( ; cpu1 <= cpu2; cpu1++)
1107 CPU_SET(cpu1, set);
1108 }
1109 ret = tracefs_instance_set_affinity_set(instance, set, set_size);
1110 out:
1111 free(cpus);
1112 CPU_FREE(set);
1113 return ret;
1114 }
1115
1116 /**
1117 * tracefs_instance_get_affinity_raw - read the affinity instance file
1118 * @instance: The instance to get affinity of (NULL for top level)
1119 *
1120 * Reads the affinity file for @instance (or the top level if @instance
1121 * is NULL) and returns it. The returned string must be freed with free().
1122 *
1123 * Returns the affinity mask on success, and must be freed with free()
1124 * or NULL on error.
1125 */
tracefs_instance_get_affinity_raw(struct tracefs_instance * instance)1126 char *tracefs_instance_get_affinity_raw(struct tracefs_instance *instance)
1127 {
1128 return tracefs_instance_file_read(instance, "tracing_cpumask", NULL);
1129 }
1130
update_cpu_set(int cpus,int cpu_set,int cpu,cpu_set_t * set,size_t set_size)1131 static inline int update_cpu_set(int cpus, int cpu_set, int cpu,
1132 cpu_set_t *set, size_t set_size)
1133 {
1134 int bit = 1 << cpu;
1135
1136 if (!(cpus & bit))
1137 return 0;
1138
1139 CPU_SET_S(cpu_set + cpu, set_size, set);
1140
1141 /*
1142 * It is possible that the passed in set_size is not big enough
1143 * to hold the cpu we just set. If that's the case, do not report
1144 * it as being set.
1145 *
1146 * The CPU_ISSET_S() should return false if the CPU given to it
1147 * is bigger than the set itself.
1148 */
1149 return CPU_ISSET_S(cpu_set + cpu, set_size, set) ? 1 : 0;
1150 }
1151
1152 /**
1153 * tracefs_instance_get_affinity_set - Retrieve the cpuset of an instance affinity
1154 * @instance: The instance to get affinity of (NULL for top level)
1155 * @set: A CPU set to put the affinity into.
1156 * @set_size: The size in bytes of @set (use CPU_ALLOC_SIZE() to get this value)
1157 *
1158 * Reads the affinity of a given instance and updates the CPU set by the
1159 * instance.
1160 *
1161 * Returns the number of CPUS that are set, or -1 on error.
1162 */
tracefs_instance_get_affinity_set(struct tracefs_instance * instance,cpu_set_t * set,size_t set_size)1163 int tracefs_instance_get_affinity_set(struct tracefs_instance *instance,
1164 cpu_set_t *set, size_t set_size)
1165 {
1166 char *affinity;
1167 int cpu_set;
1168 int cpus;
1169 int cnt = 0;
1170 int ch;
1171 int i;
1172
1173 if (!set || !set_size) {
1174 errno = -EINVAL;
1175 return -1;
1176 }
1177
1178 affinity = tracefs_instance_get_affinity_raw(instance);
1179 if (!affinity)
1180 return -1;
1181
1182 /*
1183 * The returned affinity should be a comma delimited
1184 * hex string. Work backwards setting the values.
1185 */
1186 cpu_set = 0;
1187 i = strlen(affinity);
1188 for (i--; i >= 0; i--) {
1189 ch = affinity[i];
1190 if (isalnum(ch)) {
1191 ch = tolower(ch);
1192 if (isdigit(ch))
1193 cpus = ch - '0';
1194 else
1195 cpus = ch - 'a' + 10;
1196
1197 cnt += update_cpu_set(cpus, cpu_set, 0, set, set_size);
1198 cnt += update_cpu_set(cpus, cpu_set, 1, set, set_size);
1199 cnt += update_cpu_set(cpus, cpu_set, 2, set, set_size);
1200 cnt += update_cpu_set(cpus, cpu_set, 3, set, set_size);
1201 /* Next nibble */
1202 cpu_set += 4;
1203 }
1204 }
1205
1206 free(affinity);
1207
1208 return cnt;
1209 }
1210
update_cpu(int cpus,int cpu_set,int cpu,int s,char ** set)1211 static inline int update_cpu(int cpus, int cpu_set, int cpu, int s, char **set)
1212 {
1213 char *list;
1214 int bit = 1 << cpu;
1215 int ret;
1216
1217 if (*set == (char *)-1)
1218 return s;
1219
1220 if (cpus & bit) {
1221 /* If the previous CPU is set just return s */
1222 if (s >= 0)
1223 return s;
1224 /* Otherwise, return this cpu */
1225 return cpu_set + cpu;
1226 }
1227
1228 /* If the last CPU wasn't set, just return s */
1229 if (s < 0)
1230 return s;
1231
1232 /* Update the string */
1233 if (s == cpu_set + cpu - 1) {
1234 ret = asprintf(&list, "%s%s%d",
1235 *set ? *set : "", *set ? "," : "", s);
1236 } else {
1237 ret = asprintf(&list, "%s%s%d-%d",
1238 *set ? *set : "", *set ? "," : "",
1239 s, cpu_set + cpu - 1);
1240 }
1241 free(*set);
1242 /* Force *set to be a failure */
1243 if (ret < 0)
1244 *set = (char *)-1;
1245 else
1246 *set = list;
1247 return -1;
1248 }
1249
1250 /**
1251 * tracefs_instance_get_affinity - Retrieve a string of CPUs for instance affinity
1252 * @instance: The instance to get affinity of (NULL for top level)
1253 *
1254 * Reads the affinity of a given instance and returns a CPU count of the
1255 * instance. For example, if it reads "eb" it will return:
1256 * "0-1,3,5-7"
1257 *
1258 * If no CPUs are set, an empty string is returned "\0", and it too needs
1259 * to be freed.
1260 *
1261 * Returns an allocated string containing the CPU affinity in "human readable"
1262 * format which needs to be freed with free(), or NULL on error.
1263 */
tracefs_instance_get_affinity(struct tracefs_instance * instance)1264 char *tracefs_instance_get_affinity(struct tracefs_instance *instance)
1265 {
1266 char *affinity;
1267 char *set = NULL;
1268 int cpu_set;
1269 int cpus;
1270 int ch;
1271 int s = -1;
1272 int i;
1273
1274 affinity = tracefs_instance_get_affinity_raw(instance);
1275 if (!affinity)
1276 return NULL;
1277
1278 /*
1279 * The returned affinity should be a comma delimited
1280 * hex string. Work backwards setting the values.
1281 */
1282 cpu_set = 0;
1283 i = strlen(affinity);
1284 for (i--; i >= 0; i--) {
1285 ch = affinity[i];
1286 if (isalnum(ch)) {
1287 ch = tolower(ch);
1288 if (isdigit(ch))
1289 cpus = ch - '0';
1290 else
1291 cpus = ch - 'a' + 10;
1292 s = update_cpu(cpus, cpu_set, 0, s, &set);
1293 s = update_cpu(cpus, cpu_set, 1, s, &set);
1294 s = update_cpu(cpus, cpu_set, 2, s, &set);
1295 s = update_cpu(cpus, cpu_set, 3, s, &set);
1296
1297 if (set == (char *)-1) {
1298 set = NULL;
1299 goto out;
1300 }
1301 /* Next nibble */
1302 cpu_set += 4;
1303 }
1304 }
1305 /* Clean up in case the last CPU is set */
1306 s = update_cpu(0, cpu_set, 0, s, &set);
1307
1308 if (!set)
1309 set = strdup("");
1310 out:
1311 free(affinity);
1312
1313 return set;
1314 }
1315
clear_trigger(const char * file)1316 static int clear_trigger(const char *file)
1317 {
1318 char trigger[BUFSIZ];
1319 char *save = NULL;
1320 char *line;
1321 char *buf;
1322 int size;
1323 int len;
1324 int ret;
1325
1326 size = str_read_file(file, &buf, true);
1327 if (size < 1)
1328 return 0;
1329
1330 trigger[0] = '!';
1331
1332 for (line = strtok_r(buf, "\n", &save); line; line = strtok_r(NULL, "\n", &save)) {
1333 if (line[0] == '#')
1334 continue;
1335 len = strlen(line);
1336 if (len > BUFSIZ - 2)
1337 len = BUFSIZ - 2;
1338 strncpy(trigger + 1, line, len);
1339 trigger[len + 1] = '\0';
1340 /* We don't want any filters or extra on the line */
1341 strtok(trigger, " ");
1342 write_file(file, trigger, O_WRONLY);
1343 }
1344
1345 free(buf);
1346
1347 /*
1348 * Some triggers have an order in removing them.
1349 * They will not be removed if done in the wrong order.
1350 */
1351 size = str_read_file(file, &buf, true);
1352 if (size < 1)
1353 return 0;
1354
1355 ret = 0;
1356 for (line = strtok(buf, "\n"); line; line = strtok(NULL, "\n")) {
1357 if (line[0] == '#')
1358 continue;
1359 ret = 1;
1360 break;
1361 }
1362 free(buf);
1363 return ret;
1364 }
1365
disable_func_stack_trace_instance(struct tracefs_instance * instance)1366 static void disable_func_stack_trace_instance(struct tracefs_instance *instance)
1367 {
1368 char *content;
1369 char *cond;
1370 int size;
1371
1372 content = tracefs_instance_file_read(instance, "current_tracer", &size);
1373 if (!content)
1374 return;
1375 cond = strstrip(content);
1376 if (memcmp(cond, "function", size - (cond - content)) != 0)
1377 goto out;
1378
1379 tracefs_option_disable(instance, TRACEFS_OPTION_FUNC_STACKTRACE);
1380 out:
1381 free(content);
1382 }
1383
reset_cpu_mask(struct tracefs_instance * instance)1384 static void reset_cpu_mask(struct tracefs_instance *instance)
1385 {
1386 int cpus = sysconf(_SC_NPROCESSORS_CONF);
1387 int fullwords = (cpus - 1) / 32;
1388 int bits = (cpus - 1) % 32 + 1;
1389 int len = (fullwords + 1) * 9;
1390 char buf[len + 1];
1391
1392 buf[0] = '\0';
1393 sprintf(buf, "%x", (unsigned int)((1ULL << bits) - 1));
1394 while (fullwords-- > 0)
1395 strcat(buf, ",ffffffff");
1396
1397 tracefs_instance_file_write(instance, "tracing_cpumask", buf);
1398 }
1399
clear_func_filter(struct tracefs_instance * instance,const char * file)1400 static void clear_func_filter(struct tracefs_instance *instance, const char *file)
1401 {
1402 char filter[BUFSIZ];
1403 char *line;
1404 char *buf;
1405 char *p;
1406 int len;
1407
1408 buf = tracefs_instance_file_read(instance, file, NULL);
1409 if (!buf)
1410 return;
1411
1412 /* Now remove filters */
1413 filter[0] = '!';
1414
1415 /*
1416 * To delete a filter, we need to write a '!filter'
1417 * to the file for each filter.
1418 */
1419 for (line = strtok(buf, "\n"); line; line = strtok(NULL, "\n")) {
1420 if (line[0] == '#')
1421 continue;
1422 len = strlen(line);
1423 if (len > BUFSIZ - 2)
1424 len = BUFSIZ - 2;
1425
1426 strncpy(filter + 1, line, len);
1427 filter[len + 1] = '\0';
1428 /*
1429 * To remove "unlimited" filters, we must remove
1430 * the ":unlimited" from what we write.
1431 */
1432 p = strstr(filter, ":unlimited");
1433 if (p) {
1434 *p = '\0';
1435 len = p - filter;
1436 }
1437 /*
1438 * The write to this file expects white space
1439 * at the end :-p
1440 */
1441 filter[len] = '\n';
1442 filter[len+1] = '\0';
1443 tracefs_instance_file_append(instance, file, filter);
1444 }
1445 free(buf);
1446 }
1447
clear_func_filters(struct tracefs_instance * instance)1448 static void clear_func_filters(struct tracefs_instance *instance)
1449 {
1450 int i;
1451 const char * const files[] = { "set_ftrace_filter",
1452 "set_ftrace_notrace",
1453 "set_graph_function",
1454 "set_graph_notrace",
1455 "stack_trace_filter",
1456 NULL };
1457
1458 for (i = 0; files[i]; i++)
1459 clear_func_filter(instance, files[i]);
1460 }
1461
1462 /**
1463 * tracefs_instance_clear - clear the trace buffer
1464 * @instance: The instance to clear the trace for.
1465 *
1466 * Returns 0 on succes, -1 on error
1467 */
tracefs_instance_clear(struct tracefs_instance * instance)1468 int tracefs_instance_clear(struct tracefs_instance *instance)
1469 {
1470 return tracefs_instance_file_clear(instance, "trace");
1471 }
1472
1473 /**
1474 * tracefs_instance_reset - Reset a ftrace instance to its default state
1475 * @instance - a ftrace instance to be reseted
1476 *
1477 * The main logic and the helper functions are copied from
1478 * trace-cmd/tracecmd/trace-record.c, trace_reset()
1479 */
tracefs_instance_reset(struct tracefs_instance * instance)1480 void tracefs_instance_reset(struct tracefs_instance *instance)
1481 {
1482 int has_trigger = -1;
1483 char **systems;
1484 struct stat st;
1485 char **file_list = NULL;
1486 int list_size = 0;
1487 char **events;
1488 char *file;
1489 int i, j;
1490 int ret;
1491
1492 tracefs_trace_off(instance);
1493 disable_func_stack_trace_instance(instance);
1494 tracefs_tracer_clear(instance);
1495 tracefs_instance_file_write(instance, "events/enable", "0");
1496 tracefs_instance_file_write(instance, "set_ftrace_pid", "");
1497 tracefs_instance_file_write(instance, "max_graph_depth", "0");
1498 tracefs_instance_file_clear(instance, "trace");
1499
1500 systems = tracefs_event_systems(NULL);
1501 if (systems) {
1502 for (i = 0; systems[i]; i++) {
1503 events = tracefs_system_events(NULL, systems[i]);
1504 if (!events)
1505 continue;
1506 for (j = 0; events[j]; j++) {
1507 file = tracefs_event_get_file(instance, systems[i],
1508 events[j], "filter");
1509 write_file(file, "0", O_WRONLY | O_TRUNC);
1510 tracefs_put_tracing_file(file);
1511
1512 file = tracefs_event_get_file(instance, systems[i],
1513 events[j], "trigger");
1514 if (has_trigger < 0) {
1515 /* Check if the kernel is configured with triggers */
1516 if (stat(file, &st) < 0)
1517 has_trigger = 0;
1518 else
1519 has_trigger = 1;
1520 }
1521 if (has_trigger) {
1522 ret = clear_trigger(file);
1523 if (ret) {
1524 char **list;
1525 list = tracefs_list_add(file_list, file);
1526 if (list)
1527 file_list = list;
1528 }
1529 }
1530 tracefs_put_tracing_file(file);
1531 }
1532 tracefs_list_free(events);
1533 }
1534 tracefs_list_free(systems);
1535 }
1536
1537 while (file_list && list_size != tracefs_list_size(file_list)) {
1538 char **list = file_list;
1539
1540 list_size = tracefs_list_size(file_list);
1541 file_list = NULL;
1542 for (i = 0; list[i]; i++) {
1543 file = list[i];
1544 ret = clear_trigger(file);
1545 if (ret) {
1546 char **tlist;
1547 tlist = tracefs_list_add(file_list, list[i]);
1548 if (tlist)
1549 file_list = tlist;
1550 }
1551 }
1552 tracefs_list_free(list);
1553 }
1554 tracefs_list_free(file_list);
1555
1556 tracefs_instance_file_write(instance, "synthetic_events", " ");
1557 tracefs_instance_file_write(instance, "error_log", " ");
1558 tracefs_instance_file_write(instance, "trace_clock", "local");
1559 tracefs_instance_file_write(instance, "set_event_pid", "");
1560 reset_cpu_mask(instance);
1561 clear_func_filters(instance);
1562 tracefs_instance_file_write(instance, "tracing_max_latency", "0");
1563 tracefs_trace_on(instance);
1564 }
1565