• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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