• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2014 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4  *
5  */
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <getopt.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <ctype.h>
14 
15 #include "tracefs.h"
16 #include "trace-local.h"
17 
18 #ifndef BUFSIZ
19 #define BUFSIZ 1024
20 #endif
21 
is_top_instance(struct buffer_instance * instance)22 static inline int is_top_instance(struct buffer_instance *instance)
23 {
24 	return instance == &top_instance;
25 }
26 
strstrip(char * str)27 char *strstrip(char *str)
28 {
29 	char *s;
30 
31 	if (!str)
32 		return NULL;
33 
34 	s = str + strlen(str) - 1;
35 	while (s >= str && isspace(*s))
36 		s--;
37 	s++;
38 	*s = '\0';
39 
40 	for (s = str; *s && isspace(*s); s++)
41 		;
42 
43 	return s;
44 }
45 
46 /* FIXME: append_file() is duplicated and could be consolidated */
append_file(const char * dir,const char * name)47 char *append_file(const char *dir, const char *name)
48 {
49 	char *file;
50 	int ret;
51 
52 	ret = asprintf(&file, "%s/%s", dir, name);
53 	if (ret < 0)
54 		die("Failed to allocate %s/%s", dir, name);
55 
56 	return file;
57 }
58 
get_fd_content(int fd,const char * file)59 static char *get_fd_content(int fd, const char *file)
60 {
61 	size_t total = 0;
62 	size_t alloc;
63 	char *str = NULL;
64 	int ret;
65 
66 	for (;;) {
67 		alloc = ((total + BUFSIZ) / BUFSIZ) * BUFSIZ;
68 		str = realloc(str, alloc + 1);
69 		if (!str)
70 			die("malloc");
71 		ret = read(fd, str + total, alloc - total);
72 		if (ret < 0)
73 			die("reading %s\n", file);
74 		total += ret;
75 		if (!ret)
76 			break;
77 	}
78 	str[total] = 0;
79 
80 	return str;
81 }
82 
get_file_content(const char * file)83 char *get_file_content(const char *file)
84 {
85 	char *str;
86 	int fd;
87 
88 	fd = open(file, O_RDONLY);
89 	if (fd < 0)
90 		return NULL;
91 
92 	str = get_fd_content(fd, file);
93 	close(fd);
94 
95 	return str;
96 }
97 
report_file(struct buffer_instance * instance,char * name,char * def_value,char * description)98 static void report_file(struct buffer_instance *instance,
99 			char *name, char *def_value, char *description)
100 {
101 	char *str;
102 	char *cont;
103 
104 	if (!tracefs_file_exists(instance->tracefs, name))
105 		return;
106 	str = tracefs_instance_file_read(instance->tracefs, name, NULL);
107 	if (!str)
108 		return;
109 	cont = strstrip(str);
110 	if (cont[0] && strcmp(cont, def_value) != 0)
111 		printf("\n%s%s\n", description, cont);
112 
113 	free(str);
114 }
115 
report_instance(const char * name,void * data)116 static int report_instance(const char *name, void *data)
117 {
118 	bool *first = (bool *)data;
119 
120 	if (*first) {
121 		*first = false;
122 		printf("\nInstances:\n");
123 	}
124 	printf(" %s\n", name);
125 	return 0;
126 }
127 
report_instances(void)128 static void report_instances(void)
129 {
130 	bool first = true;
131 
132 	tracefs_instances_walk(report_instance, &first);
133 }
134 
trace_event_iter_alloc(const char * path)135 struct event_iter *trace_event_iter_alloc(const char *path)
136 {
137 	struct event_iter *iter;
138 
139 	iter = malloc(sizeof(*iter));
140 	if (!iter)
141 		die("Failed to allocate event_iter for path %s", path);
142 	memset(iter, 0, sizeof(*iter));
143 
144 	iter->system_dir = opendir(path);
145 	if (!iter->system_dir)
146 		die("opendir");
147 
148 	return iter;
149 }
150 
151 enum event_iter_type
trace_event_iter_next(struct event_iter * iter,const char * path,const char * system)152 trace_event_iter_next(struct event_iter *iter, const char *path, const char *system)
153 {
154 	struct dirent *dent;
155 
156 	if (system && !iter->event_dir) {
157 		char *event;
158 		struct stat st;
159 
160 		event = append_file(path, system);
161 
162 		stat(event, &st);
163 		if (!S_ISDIR(st.st_mode)) {
164 			free(event);
165 			goto do_system;
166 		}
167 
168 		iter->event_dir = opendir(event);
169 		if (!iter->event_dir)
170 			die("opendir %s", event);
171 		free(event);
172 	}
173 
174 	if (iter->event_dir) {
175 		while ((dent = readdir(iter->event_dir))) {
176 			const char *name = dent->d_name;
177 
178 			if (strcmp(name, ".") == 0 ||
179 			    strcmp(name, "..") == 0)
180 				continue;
181 
182 			iter->event_dent = dent;
183 			return EVENT_ITER_EVENT;
184 		}
185 		closedir(iter->event_dir);
186 		iter->event_dir = NULL;
187 	}
188 
189  do_system:
190 	while ((dent = readdir(iter->system_dir))) {
191 		const char *name = dent->d_name;
192 
193 		if (strcmp(name, ".") == 0 ||
194 		    strcmp(name, "..") == 0)
195 			continue;
196 
197 		iter->system_dent = dent;
198 
199 		return EVENT_ITER_SYSTEM;
200 	}
201 
202 	return EVENT_ITER_NONE;
203 }
204 
trace_event_iter_free(struct event_iter * iter)205 void trace_event_iter_free(struct event_iter *iter)
206 {
207 	if (!iter)
208 		return;
209 
210 	if (iter->event_dir)
211 		closedir(iter->event_dir);
212 
213 	closedir(iter->system_dir);
214 	free(iter);
215 }
216 
reset_event_iter(struct event_iter * iter)217 static void reset_event_iter(struct event_iter *iter)
218 {
219 	if (iter->event_dir) {
220 		closedir(iter->event_dir);
221 		iter->event_dir = NULL;
222 	}
223 
224 	rewinddir(iter->system_dir);
225 }
226 
process_individual_events(const char * path,struct event_iter * iter)227 static int process_individual_events(const char *path, struct event_iter *iter)
228 {
229 	struct stat st;
230 	const char *system = iter->system_dent->d_name;
231 	char *file;
232 	char *enable = NULL;
233 	char *str;
234 	int ret = 0;
235 
236 	file = append_file(path, system);
237 
238 	stat(file, &st);
239 	if (!S_ISDIR(st.st_mode))
240 		goto out;
241 
242 	enable = append_file(file, "enable");
243 	str = get_file_content(enable);
244 	if (!str)
245 		goto out;
246 
247 	if (*str != '1' && *str != '0')
248 		ret = 1;
249 	free(str);
250 
251  out:
252 	free(enable);
253 	free(file);
254 
255 	return ret;
256 }
257 
258 static void
process_event_enable(char * path,const char * system,const char * name,enum event_process * processed)259 process_event_enable(char *path, const char *system, const char *name,
260 		     enum event_process *processed)
261 {
262 	struct stat st;
263 	char *enable = NULL;
264 	char *file;
265 	char *str;
266 
267 	if (system)
268 		path = append_file(path, system);
269 
270 	file = append_file(path, name);
271 
272 	if (system)
273 		free(path);
274 
275 	stat(file, &st);
276 	if (!S_ISDIR(st.st_mode))
277 		goto out;
278 
279 	enable = append_file(file, "enable");
280 	str = get_file_content(enable);
281 	if (!str)
282 		goto out;
283 
284 	if (*str == '1') {
285 		if (!system) {
286 			if (!*processed)
287 				printf(" Individual systems:\n");
288 			printf( "   %s\n", name);
289 			*processed = PROCESSED_SYSTEM;
290 		} else {
291 			if (!*processed) {
292 				printf(" Individual events:\n");
293 				*processed = PROCESSED_SYSTEM;
294 			}
295 			if (*processed == PROCESSED_SYSTEM) {
296 				printf("    %s\n", system);
297 				*processed = PROCESSED_EVENT;
298 			}
299 			printf( "        %s\n", name);
300 		}
301 	}
302 	free(str);
303 
304  out:
305 	free(enable);
306 	free(file);
307 }
308 
report_events(struct buffer_instance * instance)309 static void report_events(struct buffer_instance *instance)
310 {
311 	struct event_iter *iter;
312 	char *str;
313 	char *cont;
314 	char *path;
315 	char *system;
316 	enum event_iter_type type;
317 	enum event_process processed = PROCESSED_NONE;
318 	enum event_process processed_part = PROCESSED_NONE;
319 
320 	str = tracefs_instance_file_read(instance->tracefs, "events/enable", NULL);
321 	if (!str)
322 		return;
323 
324 	cont = strstrip(str);
325 
326 	printf("\nEvents:\n");
327 
328 	switch(*cont) {
329 	case '1':
330 		printf(" All enabled\n");
331 		free(str);
332 		return;
333 	case '0':
334 		printf(" All disabled\n");
335 		free(str);
336 		return;
337 	}
338 
339 	free(str);
340 
341 	path = tracefs_instance_get_file(instance->tracefs, "events");
342 	if (!path)
343 		die("malloc");
344 
345 	iter = trace_event_iter_alloc(path);
346 
347 	while (trace_event_iter_next(iter, path, NULL)) {
348 		process_event_enable(path, NULL, iter->system_dent->d_name, &processed);
349 	}
350 
351 	reset_event_iter(iter);
352 
353 	system = NULL;
354 	while ((type = trace_event_iter_next(iter, path, system))) {
355 
356 		if (type == EVENT_ITER_SYSTEM) {
357 
358 			/* Only process systems that are not fully enabled */
359 			if (!process_individual_events(path, iter))
360 				continue;
361 
362 			system = iter->system_dent->d_name;
363 			if (processed_part)
364 				processed_part = PROCESSED_SYSTEM;
365 			continue;
366 		}
367 
368 		process_event_enable(path, iter->system_dent->d_name,
369 				     iter->event_dent->d_name, &processed_part);
370 	}
371 
372 	trace_event_iter_free(iter);
373 
374 	if (!processed && !processed_part)
375 		printf("  (none enabled)\n");
376 
377 	tracefs_put_tracing_file(path);
378 }
379 
380 static void
process_event_filter(char * path,struct event_iter * iter,enum event_process * processed)381 process_event_filter(char *path, struct event_iter *iter, enum event_process *processed)
382 {
383 	const char *system = iter->system_dent->d_name;
384 	const char *event = iter->event_dent->d_name;
385 	struct stat st;
386 	char *filter = NULL;
387 	char *file;
388 	char *str;
389 	char *cont;
390 
391 	path = append_file(path, system);
392 	file = append_file(path, event);
393 	free(path);
394 
395 	stat(file, &st);
396 	if (!S_ISDIR(st.st_mode))
397 		goto out;
398 
399 	filter = append_file(file, "filter");
400 	str = get_file_content(filter);
401 	if (!str)
402 		goto out;
403 
404 	cont = strstrip(str);
405 
406 	if (strcmp(cont, "none") == 0) {
407 		free(str);
408 		goto out;
409 	}
410 
411 	if (!*processed)
412 		printf("\nFilters:\n");
413 	printf( "  %s:%s \"%s\"\n", system, event, cont);
414 	*processed = PROCESSED_SYSTEM;
415 	free(str);
416 
417  out:
418 	free(filter);
419 	free(file);
420 }
421 
report_event_filters(struct buffer_instance * instance)422 static void report_event_filters(struct buffer_instance *instance)
423 {
424 	struct event_iter *iter;
425 	char *path;
426 	char *system;
427 	enum event_iter_type type;
428 	enum event_process processed = PROCESSED_NONE;
429 
430 	path = tracefs_instance_get_file(instance->tracefs, "events");
431 	if (!path)
432 		die("malloc");
433 
434 	iter = trace_event_iter_alloc(path);
435 
436 	processed = PROCESSED_NONE;
437 	system = NULL;
438 	while ((type = trace_event_iter_next(iter, path, system))) {
439 
440 		if (type == EVENT_ITER_SYSTEM) {
441 			system = iter->system_dent->d_name;
442 			continue;
443 		}
444 
445 		process_event_filter(path, iter, &processed);
446 	}
447 
448 	trace_event_iter_free(iter);
449 
450 	tracefs_put_tracing_file(path);
451 }
452 
453 static void
process_event_trigger(char * path,struct event_iter * iter,enum event_process * processed)454 process_event_trigger(char *path, struct event_iter *iter, enum event_process *processed)
455 {
456 	const char *system = iter->system_dent->d_name;
457 	const char *event = iter->event_dent->d_name;
458 	struct stat st;
459 	char *trigger = NULL;
460 	char *file;
461 	char *str;
462 	char *cont;
463 
464 	path = append_file(path, system);
465 	file = append_file(path, event);
466 	free(path);
467 
468 	stat(file, &st);
469 	if (!S_ISDIR(st.st_mode))
470 		goto out;
471 
472 	trigger = append_file(file, "trigger");
473 	str = get_file_content(trigger);
474 	if (!str)
475 		goto out;
476 
477 	cont = strstrip(str);
478 
479 	if (cont[0] == '#') {
480 		free(str);
481 		goto out;
482 	}
483 
484 	if (!*processed)
485 		printf("\nTriggers:\n");
486 	printf( "  %s:%s \"%s\"\n", system, event, cont);
487 	*processed = PROCESSED_SYSTEM;
488 	free(str);
489 
490  out:
491 	free(trigger);
492 	free(file);
493 }
494 
report_event_triggers(struct buffer_instance * instance)495 static void report_event_triggers(struct buffer_instance *instance)
496 {
497 	struct event_iter *iter;
498 	char *path;
499 	char *system;
500 	enum event_iter_type type;
501 	enum event_process processed = PROCESSED_NONE;
502 
503 	path = tracefs_instance_get_file(instance->tracefs, "events");
504 	if (!path)
505 		die("malloc");
506 
507 	iter = trace_event_iter_alloc(path);
508 
509 	processed = PROCESSED_NONE;
510 	system = NULL;
511 	while ((type = trace_event_iter_next(iter, path, system))) {
512 
513 		if (type == EVENT_ITER_SYSTEM) {
514 			system = iter->system_dent->d_name;
515 			continue;
516 		}
517 
518 		process_event_trigger(path, iter, &processed);
519 	}
520 
521 	trace_event_iter_free(iter);
522 
523 	tracefs_put_tracing_file(path);
524 }
525 
526 enum func_states {
527 	FUNC_STATE_START,
528 	FUNC_STATE_SKIP,
529 	FUNC_STATE_PRINT,
530 };
531 
list_functions(const char * path,char * string)532 static void list_functions(const char *path, char *string)
533 {
534 	enum func_states state;
535 	struct stat st;
536 	char *str;
537 	int ret = 0;
538 	int len;
539 	int i;
540 	int first = 0;
541 
542 	/* Ignore if it does not exist. */
543 	ret = stat(path, &st);
544 	if (ret < 0)
545 		return;
546 
547 	str = get_file_content(path);
548 	if (!str)
549 		return;
550 
551 	len = strlen(str);
552 
553 	state = FUNC_STATE_START;
554 
555 	/* Skip all lines that start with '#' */
556 	for (i = 0; i < len; i++) {
557 
558 		if (state == FUNC_STATE_PRINT)
559 			putchar(str[i]);
560 
561 		if (str[i] == '\n') {
562 			state = FUNC_STATE_START;
563 			continue;
564 		}
565 
566 		if (state == FUNC_STATE_SKIP)
567 			continue;
568 
569 		if (state == FUNC_STATE_START && str[i] == '#') {
570 			state = FUNC_STATE_SKIP;
571 			continue;
572 		}
573 
574 		if (!first) {
575 			printf("\n%s:\n", string);
576 			first = 1;
577 		}
578 
579 		if (state != FUNC_STATE_PRINT) {
580 			state = FUNC_STATE_PRINT;
581 			printf("   ");
582 			putchar(str[i]);
583 		}
584 	}
585 	free(str);
586 }
587 
report_graph_funcs(struct buffer_instance * instance)588 static void report_graph_funcs(struct buffer_instance *instance)
589 {
590 	char *path;
591 
592 	path = tracefs_instance_get_file(instance->tracefs, "set_graph_function");
593 	if (!path)
594 		die("malloc");
595 
596 	list_functions(path, "Function Graph Filter");
597 
598 	tracefs_put_tracing_file(path);
599 
600 	path = tracefs_instance_get_file(instance->tracefs, "set_graph_notrace");
601 	if (!path)
602 		die("malloc");
603 
604 	list_functions(path, "Function Graph No Trace");
605 
606 	tracefs_put_tracing_file(path);
607 }
608 
report_ftrace_filters(struct buffer_instance * instance)609 static void report_ftrace_filters(struct buffer_instance *instance)
610 {
611 	char *path;
612 
613 	path = tracefs_instance_get_file(instance->tracefs, "set_ftrace_filter");
614 	if (!path)
615 		die("malloc");
616 
617 	list_functions(path, "Function Filter");
618 
619 	tracefs_put_tracing_file(path);
620 
621 	path = tracefs_instance_get_file(instance->tracefs, "set_ftrace_notrace");
622 	if (!path)
623 		die("malloc");
624 
625 	list_functions(path, "Function No Trace");
626 
627 	tracefs_put_tracing_file(path);
628 }
629 
report_buffers(struct buffer_instance * instance)630 static void report_buffers(struct buffer_instance *instance)
631 {
632 #define FILE_SIZE 100
633 	char *str;
634 	char *cont;
635 	char file[FILE_SIZE];
636 	int pagesize;
637 	int bufsize;
638 	int cpu;
639 
640 	str = tracefs_instance_file_read(instance->tracefs, "buffer_size_kb", NULL);
641 	if (!str)
642 		return;
643 
644 	cont = strstrip(str);
645 
646 	/* If it's not expanded yet, just skip */
647 	if (strstr(cont, "expanded") != NULL)
648 		goto out;
649 
650 	if (strcmp(cont, "X") != 0) {
651 		printf("\nBuffer size in kilobytes (per cpu):\n");
652 		printf("   %s\n", str);
653 		goto total;
654 	}
655 
656 	/* Read the sizes of each CPU buffer */
657 	for (cpu = 0; ; cpu++) {
658 
659 		snprintf(file, FILE_SIZE, "per_cpu/cpu%d/buffer_size_kb", cpu);
660 		str = tracefs_instance_file_read(instance->tracefs, file, NULL);
661 		if (!str)
662 			break;
663 
664 		cont = strstrip(str);
665 		if (!cpu)
666 			putchar('\n');
667 
668 		printf("CPU %d buffer size (kb): %s\n", cpu, cont);
669 		free(str);
670 	}
671 
672  total:
673 	free(str);
674 
675 	str = tracefs_instance_file_read(instance->tracefs, "buffer_total_size_kb", NULL);
676 	if (!str)
677 		return;
678 
679 	cont = strstrip(str);
680 	printf("\nBuffer total size in kilobytes:\n");
681 	printf("   %s\n", str);
682 
683 	pagesize = getpagesize();
684 	bufsize = tracefs_instance_get_subbuf_size(instance->tracefs);
685 	if (bufsize > 0 && bufsize * 1024 != pagesize)
686 		printf("\nSub-buffer size in kilobytes:\n   %d\n", bufsize);
687 
688  out:
689 	free(str);
690 }
691 
report_clock(struct buffer_instance * instance)692 static void report_clock(struct buffer_instance *instance)
693 {
694 	struct tracefs_instance *tracefs = instance ? instance->tracefs : NULL;
695 	char *clock;
696 
697 	clock = tracefs_get_clock(tracefs);
698 
699 	/* Default clock is "local", only show others */
700 	if (clock && strcmp(clock, "local") != 0)
701 		printf("\nClock: %s\n", clock);
702 
703 	free(clock);
704 }
705 
report_cpumask(struct buffer_instance * instance)706 static void report_cpumask(struct buffer_instance *instance)
707 {
708 	char *str;
709 	char *cont;
710 	int cpus;
711 	int n;
712 	int i;
713 
714 	str = tracefs_instance_file_read(instance->tracefs, "tracing_cpumask", NULL);
715 	if (!str)
716 		return;
717 
718 	cont = strstrip(str);
719 
720 	/* check to make sure all CPUs on this machine are set */
721 	cpus = tracecmd_count_cpus();
722 
723 	for (i = strlen(cont) - 1; i >= 0 && cpus > 0; i--) {
724 		if (cont[i] == ',')
725 			continue;
726 
727 		if (cont[i] == 'f') {
728 			cpus -= 4;
729 			continue;
730 		}
731 
732 		if (cpus >= 4)
733 			break;
734 
735 		if (cont[i] >= '0' && cont[i] <= '9')
736 			n = cont[i] - '0';
737 		else
738 			n = 10 + (cont[i] - 'a');
739 
740 		while (cpus > 0) {
741 			if (!(n & 1))
742 				break;
743 			n >>= 1;
744 			cpus--;
745 		}
746 		break;
747 	}
748 
749 	/* If cpus is greater than zero, one isn't set */
750 	if (cpus > 0)
751 		printf("\nCPU mask: %s\n", cont);
752 
753 	free(str);
754 }
755 
report_probes(struct buffer_instance * instance,const char * file,const char * string)756 static void report_probes(struct buffer_instance *instance,
757 			  const char *file, const char *string)
758 {
759 	char *str;
760 	char *cont;
761 	int newline;
762 	int i;
763 
764 	str = tracefs_instance_file_read(instance->tracefs, file, NULL);
765 	if (!str)
766 		return;
767 
768 	cont = strstrip(str);
769 	if (strlen(cont) == 0)
770 		goto out;
771 
772 	printf("\n%s:\n", string);
773 
774 	newline = 1;
775 	for (i = 0; cont[i]; i++) {
776 		if (newline)
777 			printf("   ");
778 		putchar(cont[i]);
779 		if (cont[i] == '\n')
780 			newline = 1;
781 		else
782 			newline = 0;
783 	}
784 	putchar('\n');
785  out:
786 	free(str);
787 }
788 
report_kprobes(struct buffer_instance * instance)789 static void report_kprobes(struct buffer_instance *instance)
790 {
791 	report_probes(instance, "kprobe_events", "Kprobe events");
792 }
793 
report_uprobes(struct buffer_instance * instance)794 static void report_uprobes(struct buffer_instance *instance)
795 {
796 	report_probes(instance, "uprobe_events", "Uprobe events");
797 }
798 
report_synthetic(struct buffer_instance * instance)799 static void report_synthetic(struct buffer_instance *instance)
800 {
801 	report_probes(instance, "synthetic_events", "Synthetic events");
802 }
803 
report_traceon(struct buffer_instance * instance)804 static void report_traceon(struct buffer_instance *instance)
805 {
806 	char *str;
807 	char *cont;
808 
809 	str = tracefs_instance_file_read(instance->tracefs, "tracing_on", NULL);
810 	if (!str)
811 		return;
812 
813 	cont = strstrip(str);
814 
815 	/* double newline as this is the last thing printed */
816 	if (strcmp(cont, "0") == 0)
817 		printf("\nTracing is disabled\n\n");
818 	else
819 		printf("\nTracing is enabled\n\n");
820 
821 	free(str);
822 }
823 
stat_instance(struct buffer_instance * instance,bool opt)824 static void stat_instance(struct buffer_instance *instance, bool opt)
825 {
826 	if (instance != &top_instance) {
827 		if (instance != first_instance)
828 			printf("---------------\n");
829 		printf("Instance: %s\n",
830 			tracefs_instance_get_name(instance->tracefs));
831 	}
832 
833 	report_file(instance, "current_tracer", "nop", "Tracer: ");
834 	report_events(instance);
835 	report_event_filters(instance);
836 	report_event_triggers(instance);
837 	report_ftrace_filters(instance);
838 	report_graph_funcs(instance);
839 	report_buffers(instance);
840 	report_clock(instance);
841 	report_cpumask(instance);
842 	report_file(instance, "tracing_max_latency", "0", "Max Latency: ");
843 	report_kprobes(instance);
844 	report_uprobes(instance);
845 	report_synthetic(instance);
846 	report_file(instance, "set_event_pid", "", "Filtered event PIDs:\n");
847 	report_file(instance, "set_event_notrace_pid", "", "Filtered notrace event PIDs:\n");
848 	report_file(instance, "set_ftrace_pid", "no pid",
849 		    "Filtered function tracer PIDs:\n");
850 	report_file(instance, "set_ftrace_notrace_pid", "no pid",
851 		    "Filtered function tracer notrace PIDs:\n");
852 	if (opt) {
853 		printf("\nOptions:\n");
854 		show_options("   ", instance);
855 	}
856 	report_traceon(instance);
857 	report_file(instance, "error_log", "", "Error log:\n");
858 	if (instance == &top_instance)
859 		report_instances();
860 }
861 
trace_stat(int argc,char ** argv)862 void trace_stat (int argc, char **argv)
863 {
864 	struct buffer_instance *instance = &top_instance;
865 	bool opt = false;
866 	int topt = 0;
867 	int status;
868 	int c;
869 
870 	init_top_instance();
871 
872 	for (;;) {
873 		c = getopt(argc-1, argv+1, "htoB:");
874 		if (c == -1)
875 			break;
876 		switch (c) {
877 		case 'h':
878 			usage(argv);
879 			break;
880 		case 'B':
881 			instance = allocate_instance(optarg);
882 			if (!instance)
883 				die("Failed to create instance");
884 			add_instance(instance, tracecmd_count_cpus());
885 			/* top instance requires direct access */
886 			if (!topt && is_top_instance(first_instance))
887 				first_instance = instance;
888 			break;
889 		case 't':
890 			/* Force to use top instance */
891 			topt = 1;
892 			instance = &top_instance;
893 			break;
894 		case 'o':
895 			opt = 1;
896 			break;
897 		default:
898 			usage(argv);
899 		}
900 	}
901 
902 	update_first_instance(instance, topt);
903 
904 	for_all_instances(instance) {
905 		stat_instance(instance, opt);
906 	}
907 
908 	if (tracecmd_stack_tracer_status(&status) >= 0) {
909 		if (status > 0)
910 			printf("Stack tracing is enabled\n\n");
911 	} else {
912 		printf("Error reading stack tracer status\n\n");
913 	}
914 
915 	exit(0);
916 }
917