xref: /aosp_15_r20/external/libtracefs/src/tracefs-tools.c (revision 287e80b3a36113050663245e7f2c00d274188f18)
1*287e80b3SSadaf Ebrahimi // SPDX-License-Identifier: LGPL-2.1
2*287e80b3SSadaf Ebrahimi /*
3*287e80b3SSadaf Ebrahimi  * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt <[email protected]>
4*287e80b3SSadaf Ebrahimi  *
5*287e80b3SSadaf Ebrahimi  * Updates:
6*287e80b3SSadaf Ebrahimi  * Copyright (C) 2021, VMware, Tzvetomir Stoyanov <[email protected]>
7*287e80b3SSadaf Ebrahimi  *
8*287e80b3SSadaf Ebrahimi  */
9*287e80b3SSadaf Ebrahimi #include <stdlib.h>
10*287e80b3SSadaf Ebrahimi #include <stdarg.h>
11*287e80b3SSadaf Ebrahimi #include <unistd.h>
12*287e80b3SSadaf Ebrahimi #include <fcntl.h>
13*287e80b3SSadaf Ebrahimi #include <sys/types.h>
14*287e80b3SSadaf Ebrahimi #include <sys/stat.h>
15*287e80b3SSadaf Ebrahimi #include <regex.h>
16*287e80b3SSadaf Ebrahimi #include <dirent.h>
17*287e80b3SSadaf Ebrahimi #include <limits.h>
18*287e80b3SSadaf Ebrahimi #include <pthread.h>
19*287e80b3SSadaf Ebrahimi #include <errno.h>
20*287e80b3SSadaf Ebrahimi 
21*287e80b3SSadaf Ebrahimi #include "tracefs.h"
22*287e80b3SSadaf Ebrahimi #include "tracefs-local.h"
23*287e80b3SSadaf Ebrahimi 
24*287e80b3SSadaf Ebrahimi __hidden pthread_mutex_t toplevel_lock = PTHREAD_MUTEX_INITIALIZER;
25*287e80b3SSadaf Ebrahimi 
26*287e80b3SSadaf Ebrahimi #define TRACE_CTRL		"tracing_on"
27*287e80b3SSadaf Ebrahimi #define TRACE_FILTER		"set_ftrace_filter"
28*287e80b3SSadaf Ebrahimi #define TRACE_NOTRACE		"set_ftrace_notrace"
29*287e80b3SSadaf Ebrahimi #define TRACE_FILTER_LIST	"available_filter_functions"
30*287e80b3SSadaf Ebrahimi #define CUR_TRACER		"current_tracer"
31*287e80b3SSadaf Ebrahimi 
32*287e80b3SSadaf Ebrahimi #define TRACERS \
33*287e80b3SSadaf Ebrahimi 	C(NOP,                  "nop"),			\
34*287e80b3SSadaf Ebrahimi 	C(CUSTOM,		"CUSTOM"),		\
35*287e80b3SSadaf Ebrahimi 	C(FUNCTION,             "function"),            \
36*287e80b3SSadaf Ebrahimi 	C(FUNCTION_GRAPH,       "function_graph"),      \
37*287e80b3SSadaf Ebrahimi 	C(IRQSOFF,              "irqsoff"),             \
38*287e80b3SSadaf Ebrahimi 	C(PREEMPTOFF,           "preemptoff"),          \
39*287e80b3SSadaf Ebrahimi 	C(PREEMPTIRQSOFF,       "preemptirqsoff"),      \
40*287e80b3SSadaf Ebrahimi 	C(WAKEUP,               "wakeup"),              \
41*287e80b3SSadaf Ebrahimi 	C(WAKEUP_RT,            "wakeup_rt"),	\
42*287e80b3SSadaf Ebrahimi 	C(WAKEUP_DL,            "wakeup_dl"),           \
43*287e80b3SSadaf Ebrahimi 	C(MMIOTRACE,            "mmiotrace"),           \
44*287e80b3SSadaf Ebrahimi 	C(HWLAT,                "hwlat"),               \
45*287e80b3SSadaf Ebrahimi 	C(BRANCH,               "branch"),              \
46*287e80b3SSadaf Ebrahimi 	C(BLOCK,                "block")
47*287e80b3SSadaf Ebrahimi 
48*287e80b3SSadaf Ebrahimi #undef C
49*287e80b3SSadaf Ebrahimi #define C(a, b) b
50*287e80b3SSadaf Ebrahimi const char *tracers[] = { TRACERS };
51*287e80b3SSadaf Ebrahimi 
52*287e80b3SSadaf Ebrahimi #undef C
53*287e80b3SSadaf Ebrahimi #define C(a, b) TRACEFS_TRACER_##a
54*287e80b3SSadaf Ebrahimi const int tracer_enums[] = { TRACERS };
55*287e80b3SSadaf Ebrahimi 
56*287e80b3SSadaf Ebrahimi /* File descriptor for Top level set_ftrace_filter  */
57*287e80b3SSadaf Ebrahimi static int ftrace_filter_fd = -1;
58*287e80b3SSadaf Ebrahimi static int ftrace_notrace_fd = -1;
59*287e80b3SSadaf Ebrahimi 
60*287e80b3SSadaf Ebrahimi static const char * const options_map[] = {
61*287e80b3SSadaf Ebrahimi 	"unknown",
62*287e80b3SSadaf Ebrahimi 	"annotate",
63*287e80b3SSadaf Ebrahimi 	"bin",
64*287e80b3SSadaf Ebrahimi 	"blk_cgname",
65*287e80b3SSadaf Ebrahimi 	"blk_cgroup",
66*287e80b3SSadaf Ebrahimi 	"blk_classic",
67*287e80b3SSadaf Ebrahimi 	"block",
68*287e80b3SSadaf Ebrahimi 	"context-info",
69*287e80b3SSadaf Ebrahimi 	"disable_on_free",
70*287e80b3SSadaf Ebrahimi 	"display-graph",
71*287e80b3SSadaf Ebrahimi 	"event-fork",
72*287e80b3SSadaf Ebrahimi 	"funcgraph-abstime",
73*287e80b3SSadaf Ebrahimi 	"funcgraph-cpu",
74*287e80b3SSadaf Ebrahimi 	"funcgraph-duration",
75*287e80b3SSadaf Ebrahimi 	"funcgraph-irqs",
76*287e80b3SSadaf Ebrahimi 	"funcgraph-overhead",
77*287e80b3SSadaf Ebrahimi 	"funcgraph-overrun",
78*287e80b3SSadaf Ebrahimi 	"funcgraph-proc",
79*287e80b3SSadaf Ebrahimi 	"funcgraph-tail",
80*287e80b3SSadaf Ebrahimi 	"func_stack_trace",
81*287e80b3SSadaf Ebrahimi 	"function-fork",
82*287e80b3SSadaf Ebrahimi 	"function-trace",
83*287e80b3SSadaf Ebrahimi 	"graph-time",
84*287e80b3SSadaf Ebrahimi 	"hex",
85*287e80b3SSadaf Ebrahimi 	"irq-info",
86*287e80b3SSadaf Ebrahimi 	"latency-format",
87*287e80b3SSadaf Ebrahimi 	"markers",
88*287e80b3SSadaf Ebrahimi 	"overwrite",
89*287e80b3SSadaf Ebrahimi 	"pause-on-trace",
90*287e80b3SSadaf Ebrahimi 	"printk-msg-only",
91*287e80b3SSadaf Ebrahimi 	"print-parent",
92*287e80b3SSadaf Ebrahimi 	"raw",
93*287e80b3SSadaf Ebrahimi 	"record-cmd",
94*287e80b3SSadaf Ebrahimi 	"record-tgid",
95*287e80b3SSadaf Ebrahimi 	"sleep-time",
96*287e80b3SSadaf Ebrahimi 	"stacktrace",
97*287e80b3SSadaf Ebrahimi 	"sym-addr",
98*287e80b3SSadaf Ebrahimi 	"sym-offset",
99*287e80b3SSadaf Ebrahimi 	"sym-userobj",
100*287e80b3SSadaf Ebrahimi 	"trace_printk",
101*287e80b3SSadaf Ebrahimi 	"userstacktrace",
102*287e80b3SSadaf Ebrahimi 	"verbose" };
103*287e80b3SSadaf Ebrahimi 
trace_on_off(int fd,bool on)104*287e80b3SSadaf Ebrahimi static int trace_on_off(int fd, bool on)
105*287e80b3SSadaf Ebrahimi {
106*287e80b3SSadaf Ebrahimi 	const char *val = on ? "1" : "0";
107*287e80b3SSadaf Ebrahimi 	int ret;
108*287e80b3SSadaf Ebrahimi 
109*287e80b3SSadaf Ebrahimi 	ret = write(fd, val, 1);
110*287e80b3SSadaf Ebrahimi 	if (ret == 1)
111*287e80b3SSadaf Ebrahimi 		return 0;
112*287e80b3SSadaf Ebrahimi 
113*287e80b3SSadaf Ebrahimi 	return -1;
114*287e80b3SSadaf Ebrahimi }
115*287e80b3SSadaf Ebrahimi 
trace_on_off_file(struct tracefs_instance * instance,bool on)116*287e80b3SSadaf Ebrahimi static int trace_on_off_file(struct tracefs_instance *instance, bool on)
117*287e80b3SSadaf Ebrahimi {
118*287e80b3SSadaf Ebrahimi 	int ret;
119*287e80b3SSadaf Ebrahimi 	int fd;
120*287e80b3SSadaf Ebrahimi 
121*287e80b3SSadaf Ebrahimi 	fd = tracefs_instance_file_open(instance, TRACE_CTRL, O_WRONLY);
122*287e80b3SSadaf Ebrahimi 	if (fd < 0)
123*287e80b3SSadaf Ebrahimi 		return -1;
124*287e80b3SSadaf Ebrahimi 	ret = trace_on_off(fd, on);
125*287e80b3SSadaf Ebrahimi 	close(fd);
126*287e80b3SSadaf Ebrahimi 
127*287e80b3SSadaf Ebrahimi 	return ret;
128*287e80b3SSadaf Ebrahimi }
129*287e80b3SSadaf Ebrahimi 
130*287e80b3SSadaf Ebrahimi /**
131*287e80b3SSadaf Ebrahimi  * tracefs_trace_is_on - Check if writing traces to the ring buffer is enabled
132*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for the top instance
133*287e80b3SSadaf Ebrahimi  *
134*287e80b3SSadaf Ebrahimi  * Returns -1 in case of an error, 0 if tracing is disable or 1 if tracing
135*287e80b3SSadaf Ebrahimi  * is enabled.
136*287e80b3SSadaf Ebrahimi  */
tracefs_trace_is_on(struct tracefs_instance * instance)137*287e80b3SSadaf Ebrahimi int tracefs_trace_is_on(struct tracefs_instance *instance)
138*287e80b3SSadaf Ebrahimi {
139*287e80b3SSadaf Ebrahimi 	long long res;
140*287e80b3SSadaf Ebrahimi 
141*287e80b3SSadaf Ebrahimi 	if (tracefs_instance_file_read_number(instance, TRACE_CTRL, &res) == 0)
142*287e80b3SSadaf Ebrahimi 		return (int)res;
143*287e80b3SSadaf Ebrahimi 
144*287e80b3SSadaf Ebrahimi 	return -1;
145*287e80b3SSadaf Ebrahimi }
146*287e80b3SSadaf Ebrahimi 
147*287e80b3SSadaf Ebrahimi /**
148*287e80b3SSadaf Ebrahimi  * tracefs_trace_on - Enable writing traces to the ring buffer of the given instance
149*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for the top instance
150*287e80b3SSadaf Ebrahimi  *
151*287e80b3SSadaf Ebrahimi  * Returns -1 in case of an error or 0 otherwise
152*287e80b3SSadaf Ebrahimi  */
tracefs_trace_on(struct tracefs_instance * instance)153*287e80b3SSadaf Ebrahimi int tracefs_trace_on(struct tracefs_instance *instance)
154*287e80b3SSadaf Ebrahimi {
155*287e80b3SSadaf Ebrahimi 	return trace_on_off_file(instance, true);
156*287e80b3SSadaf Ebrahimi }
157*287e80b3SSadaf Ebrahimi 
158*287e80b3SSadaf Ebrahimi /**
159*287e80b3SSadaf Ebrahimi  * tracefs_trace_off - Disable writing traces to the ring buffer of the given instance
160*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for the top instance
161*287e80b3SSadaf Ebrahimi  *
162*287e80b3SSadaf Ebrahimi  * Returns -1 in case of an error or 0 otherwise
163*287e80b3SSadaf Ebrahimi  */
tracefs_trace_off(struct tracefs_instance * instance)164*287e80b3SSadaf Ebrahimi int tracefs_trace_off(struct tracefs_instance *instance)
165*287e80b3SSadaf Ebrahimi {
166*287e80b3SSadaf Ebrahimi 	return trace_on_off_file(instance, false);
167*287e80b3SSadaf Ebrahimi }
168*287e80b3SSadaf Ebrahimi 
169*287e80b3SSadaf Ebrahimi /**
170*287e80b3SSadaf Ebrahimi  * tracefs_trace_on_fd - Enable writing traces to the ring buffer
171*287e80b3SSadaf Ebrahimi  * @fd: File descriptor to ftrace tracing_on file, previously opened
172*287e80b3SSadaf Ebrahimi  *	with tracefs_trace_on_get_fd()
173*287e80b3SSadaf Ebrahimi  *
174*287e80b3SSadaf Ebrahimi  * Returns -1 in case of an error or 0 otherwise
175*287e80b3SSadaf Ebrahimi  */
tracefs_trace_on_fd(int fd)176*287e80b3SSadaf Ebrahimi int tracefs_trace_on_fd(int fd)
177*287e80b3SSadaf Ebrahimi {
178*287e80b3SSadaf Ebrahimi 	if (fd < 0)
179*287e80b3SSadaf Ebrahimi 		return -1;
180*287e80b3SSadaf Ebrahimi 	return trace_on_off(fd, true);
181*287e80b3SSadaf Ebrahimi }
182*287e80b3SSadaf Ebrahimi 
183*287e80b3SSadaf Ebrahimi /**
184*287e80b3SSadaf Ebrahimi  * tracefs_trace_off_fd - Disable writing traces to the ring buffer
185*287e80b3SSadaf Ebrahimi  * @fd: File descriptor to ftrace tracing_on file, previously opened
186*287e80b3SSadaf Ebrahimi  *	with tracefs_trace_on_get_fd()
187*287e80b3SSadaf Ebrahimi  *
188*287e80b3SSadaf Ebrahimi  * Returns -1 in case of an error or 0 otherwise
189*287e80b3SSadaf Ebrahimi  */
tracefs_trace_off_fd(int fd)190*287e80b3SSadaf Ebrahimi int tracefs_trace_off_fd(int fd)
191*287e80b3SSadaf Ebrahimi {
192*287e80b3SSadaf Ebrahimi 	if (fd < 0)
193*287e80b3SSadaf Ebrahimi 		return -1;
194*287e80b3SSadaf Ebrahimi 	return trace_on_off(fd, false);
195*287e80b3SSadaf Ebrahimi }
196*287e80b3SSadaf Ebrahimi 
197*287e80b3SSadaf Ebrahimi /**
198*287e80b3SSadaf Ebrahimi  * tracefs_option_name - Get trace option name from id
199*287e80b3SSadaf Ebrahimi  * @id: trace option id
200*287e80b3SSadaf Ebrahimi  *
201*287e80b3SSadaf Ebrahimi  * Returns string with option name, or "unknown" in case of not known option id.
202*287e80b3SSadaf Ebrahimi  * The returned string must *not* be freed.
203*287e80b3SSadaf Ebrahimi  */
tracefs_option_name(enum tracefs_option_id id)204*287e80b3SSadaf Ebrahimi const char *tracefs_option_name(enum tracefs_option_id id)
205*287e80b3SSadaf Ebrahimi {
206*287e80b3SSadaf Ebrahimi 	/* Make sure options map contains all the options */
207*287e80b3SSadaf Ebrahimi 	BUILD_BUG_ON(ARRAY_SIZE(options_map) != TRACEFS_OPTION_MAX);
208*287e80b3SSadaf Ebrahimi 
209*287e80b3SSadaf Ebrahimi 	if (id < TRACEFS_OPTION_MAX)
210*287e80b3SSadaf Ebrahimi 		return options_map[id];
211*287e80b3SSadaf Ebrahimi 
212*287e80b3SSadaf Ebrahimi 	return options_map[0];
213*287e80b3SSadaf Ebrahimi }
214*287e80b3SSadaf Ebrahimi 
215*287e80b3SSadaf Ebrahimi /**
216*287e80b3SSadaf Ebrahimi  * tracefs_option_id - Get trace option ID from name
217*287e80b3SSadaf Ebrahimi  * @name: trace option name
218*287e80b3SSadaf Ebrahimi  *
219*287e80b3SSadaf Ebrahimi  * Returns trace option ID or TRACEFS_OPTION_INVALID in case of an error or
220*287e80b3SSadaf Ebrahimi  * unknown option name.
221*287e80b3SSadaf Ebrahimi  */
tracefs_option_id(const char * name)222*287e80b3SSadaf Ebrahimi enum tracefs_option_id tracefs_option_id(const char *name)
223*287e80b3SSadaf Ebrahimi {
224*287e80b3SSadaf Ebrahimi 	int i;
225*287e80b3SSadaf Ebrahimi 
226*287e80b3SSadaf Ebrahimi 	if (!name)
227*287e80b3SSadaf Ebrahimi 		return TRACEFS_OPTION_INVALID;
228*287e80b3SSadaf Ebrahimi 
229*287e80b3SSadaf Ebrahimi 	for (i = 0; i < TRACEFS_OPTION_MAX; i++) {
230*287e80b3SSadaf Ebrahimi 		if (strlen(name) == strlen(options_map[i]) &&
231*287e80b3SSadaf Ebrahimi 		    !strcmp(options_map[i], name))
232*287e80b3SSadaf Ebrahimi 			return i;
233*287e80b3SSadaf Ebrahimi 	}
234*287e80b3SSadaf Ebrahimi 
235*287e80b3SSadaf Ebrahimi 	return TRACEFS_OPTION_INVALID;
236*287e80b3SSadaf Ebrahimi }
237*287e80b3SSadaf Ebrahimi 
238*287e80b3SSadaf Ebrahimi const static struct tracefs_options_mask *
trace_get_options(struct tracefs_instance * instance,bool enabled)239*287e80b3SSadaf Ebrahimi trace_get_options(struct tracefs_instance *instance, bool enabled)
240*287e80b3SSadaf Ebrahimi {
241*287e80b3SSadaf Ebrahimi 	pthread_mutex_t *lock = trace_get_lock(instance);
242*287e80b3SSadaf Ebrahimi 	struct tracefs_options_mask *bitmask;
243*287e80b3SSadaf Ebrahimi 	enum tracefs_option_id id;
244*287e80b3SSadaf Ebrahimi 	unsigned long long set;
245*287e80b3SSadaf Ebrahimi 	char file[PATH_MAX];
246*287e80b3SSadaf Ebrahimi 	struct stat st;
247*287e80b3SSadaf Ebrahimi 	long long val;
248*287e80b3SSadaf Ebrahimi 	char *path;
249*287e80b3SSadaf Ebrahimi 	int ret;
250*287e80b3SSadaf Ebrahimi 
251*287e80b3SSadaf Ebrahimi 	bitmask = enabled ? enabled_opts_mask(instance) :
252*287e80b3SSadaf Ebrahimi 			   supported_opts_mask(instance);
253*287e80b3SSadaf Ebrahimi 
254*287e80b3SSadaf Ebrahimi 	for (id = 1; id < TRACEFS_OPTION_MAX; id++) {
255*287e80b3SSadaf Ebrahimi 		snprintf(file, PATH_MAX, "options/%s", options_map[id]);
256*287e80b3SSadaf Ebrahimi 		path = tracefs_instance_get_file(instance, file);
257*287e80b3SSadaf Ebrahimi 		if (!path)
258*287e80b3SSadaf Ebrahimi 			return NULL;
259*287e80b3SSadaf Ebrahimi 
260*287e80b3SSadaf Ebrahimi 		set = 1;
261*287e80b3SSadaf Ebrahimi 		ret = stat(path, &st);
262*287e80b3SSadaf Ebrahimi 		if (ret < 0 || !S_ISREG(st.st_mode)) {
263*287e80b3SSadaf Ebrahimi 			set = 0;
264*287e80b3SSadaf Ebrahimi 		} else if (enabled) {
265*287e80b3SSadaf Ebrahimi 			ret = tracefs_instance_file_read_number(instance, file, &val);
266*287e80b3SSadaf Ebrahimi 			if (ret != 0 || val != 1)
267*287e80b3SSadaf Ebrahimi 				set = 0;
268*287e80b3SSadaf Ebrahimi 		}
269*287e80b3SSadaf Ebrahimi 
270*287e80b3SSadaf Ebrahimi 		pthread_mutex_lock(lock);
271*287e80b3SSadaf Ebrahimi 		bitmask->mask = (bitmask->mask & ~(1ULL << (id - 1))) | (set << (id - 1));
272*287e80b3SSadaf Ebrahimi 		pthread_mutex_unlock(lock);
273*287e80b3SSadaf Ebrahimi 
274*287e80b3SSadaf Ebrahimi 		tracefs_put_tracing_file(path);
275*287e80b3SSadaf Ebrahimi 	}
276*287e80b3SSadaf Ebrahimi 
277*287e80b3SSadaf Ebrahimi 
278*287e80b3SSadaf Ebrahimi 	return bitmask;
279*287e80b3SSadaf Ebrahimi }
280*287e80b3SSadaf Ebrahimi 
281*287e80b3SSadaf Ebrahimi /**
282*287e80b3SSadaf Ebrahimi  * tracefs_options_get_supported - Get all supported trace options in given instance
283*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for the top instance
284*287e80b3SSadaf Ebrahimi  *
285*287e80b3SSadaf Ebrahimi  * Returns bitmask structure with all trace options, supported in given instance,
286*287e80b3SSadaf Ebrahimi  * or NULL in case of an error.
287*287e80b3SSadaf Ebrahimi  */
288*287e80b3SSadaf Ebrahimi const struct tracefs_options_mask *
tracefs_options_get_supported(struct tracefs_instance * instance)289*287e80b3SSadaf Ebrahimi tracefs_options_get_supported(struct tracefs_instance *instance)
290*287e80b3SSadaf Ebrahimi {
291*287e80b3SSadaf Ebrahimi 	return trace_get_options(instance, false);
292*287e80b3SSadaf Ebrahimi }
293*287e80b3SSadaf Ebrahimi 
294*287e80b3SSadaf Ebrahimi /**
295*287e80b3SSadaf Ebrahimi  * tracefs_options_get_enabled - Get all currently enabled trace options in given instance
296*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for the top instance
297*287e80b3SSadaf Ebrahimi  *
298*287e80b3SSadaf Ebrahimi  * Returns bitmask structure with all trace options, enabled in given instance,
299*287e80b3SSadaf Ebrahimi  * or NULL in case of an error.
300*287e80b3SSadaf Ebrahimi  */
301*287e80b3SSadaf Ebrahimi const struct tracefs_options_mask *
tracefs_options_get_enabled(struct tracefs_instance * instance)302*287e80b3SSadaf Ebrahimi tracefs_options_get_enabled(struct tracefs_instance *instance)
303*287e80b3SSadaf Ebrahimi {
304*287e80b3SSadaf Ebrahimi 	return trace_get_options(instance, true);
305*287e80b3SSadaf Ebrahimi }
306*287e80b3SSadaf Ebrahimi 
trace_config_option(struct tracefs_instance * instance,enum tracefs_option_id id,bool set)307*287e80b3SSadaf Ebrahimi static int trace_config_option(struct tracefs_instance *instance,
308*287e80b3SSadaf Ebrahimi 			       enum tracefs_option_id id, bool set)
309*287e80b3SSadaf Ebrahimi {
310*287e80b3SSadaf Ebrahimi 	const char *set_str = set ? "1" : "0";
311*287e80b3SSadaf Ebrahimi 	char file[PATH_MAX];
312*287e80b3SSadaf Ebrahimi 	const char *name;
313*287e80b3SSadaf Ebrahimi 
314*287e80b3SSadaf Ebrahimi 	name = tracefs_option_name(id);
315*287e80b3SSadaf Ebrahimi 	if (!name)
316*287e80b3SSadaf Ebrahimi 		return -1;
317*287e80b3SSadaf Ebrahimi 
318*287e80b3SSadaf Ebrahimi 	snprintf(file, PATH_MAX, "options/%s", name);
319*287e80b3SSadaf Ebrahimi 	if (strlen(set_str) != tracefs_instance_file_write(instance, file, set_str))
320*287e80b3SSadaf Ebrahimi 		return -1;
321*287e80b3SSadaf Ebrahimi 	return 0;
322*287e80b3SSadaf Ebrahimi }
323*287e80b3SSadaf Ebrahimi 
324*287e80b3SSadaf Ebrahimi /**
325*287e80b3SSadaf Ebrahimi  * tracefs_option_enable - Enable trace option
326*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for the top instance
327*287e80b3SSadaf Ebrahimi  * @id: trace option id
328*287e80b3SSadaf Ebrahimi  *
329*287e80b3SSadaf Ebrahimi  * Returns -1 in case of an error or 0 otherwise
330*287e80b3SSadaf Ebrahimi  */
tracefs_option_enable(struct tracefs_instance * instance,enum tracefs_option_id id)331*287e80b3SSadaf Ebrahimi int tracefs_option_enable(struct tracefs_instance *instance, enum tracefs_option_id id)
332*287e80b3SSadaf Ebrahimi {
333*287e80b3SSadaf Ebrahimi 	return trace_config_option(instance, id, true);
334*287e80b3SSadaf Ebrahimi }
335*287e80b3SSadaf Ebrahimi 
336*287e80b3SSadaf Ebrahimi /**
337*287e80b3SSadaf Ebrahimi  * tracefs_option_disable - Disable trace option
338*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for the top instance
339*287e80b3SSadaf Ebrahimi  * @id: trace option id
340*287e80b3SSadaf Ebrahimi  *
341*287e80b3SSadaf Ebrahimi  * Returns -1 in case of an error or 0 otherwise
342*287e80b3SSadaf Ebrahimi  */
tracefs_option_disable(struct tracefs_instance * instance,enum tracefs_option_id id)343*287e80b3SSadaf Ebrahimi int tracefs_option_disable(struct tracefs_instance *instance, enum tracefs_option_id id)
344*287e80b3SSadaf Ebrahimi {
345*287e80b3SSadaf Ebrahimi 	return trace_config_option(instance, id, false);
346*287e80b3SSadaf Ebrahimi }
347*287e80b3SSadaf Ebrahimi 
348*287e80b3SSadaf Ebrahimi /**
349*287e80b3SSadaf Ebrahimi  * tracefs_option_is_supported - Check if an option is supported
350*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for the top instance
351*287e80b3SSadaf Ebrahimi  * @id: trace option id
352*287e80b3SSadaf Ebrahimi  *
353*287e80b3SSadaf Ebrahimi  * Returns true if an option with given id is supported by the system, false if
354*287e80b3SSadaf Ebrahimi  * it is not supported.
355*287e80b3SSadaf Ebrahimi  */
tracefs_option_is_supported(struct tracefs_instance * instance,enum tracefs_option_id id)356*287e80b3SSadaf Ebrahimi bool tracefs_option_is_supported(struct tracefs_instance *instance, enum tracefs_option_id id)
357*287e80b3SSadaf Ebrahimi {
358*287e80b3SSadaf Ebrahimi 	const char *name = tracefs_option_name(id);
359*287e80b3SSadaf Ebrahimi 	char file[PATH_MAX];
360*287e80b3SSadaf Ebrahimi 
361*287e80b3SSadaf Ebrahimi 	if (!name)
362*287e80b3SSadaf Ebrahimi 		return false;
363*287e80b3SSadaf Ebrahimi 	snprintf(file, PATH_MAX, "options/%s", name);
364*287e80b3SSadaf Ebrahimi 	return tracefs_file_exists(instance, file);
365*287e80b3SSadaf Ebrahimi }
366*287e80b3SSadaf Ebrahimi 
367*287e80b3SSadaf Ebrahimi /**
368*287e80b3SSadaf Ebrahimi  * tracefs_option_is_enabled - Check if an option is enabled in given instance
369*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for the top instance
370*287e80b3SSadaf Ebrahimi  * @id: trace option id
371*287e80b3SSadaf Ebrahimi  *
372*287e80b3SSadaf Ebrahimi  * Returns true if an option with given id is enabled in the given instance,
373*287e80b3SSadaf Ebrahimi  * false if it is not enabled.
374*287e80b3SSadaf Ebrahimi  */
tracefs_option_is_enabled(struct tracefs_instance * instance,enum tracefs_option_id id)375*287e80b3SSadaf Ebrahimi bool tracefs_option_is_enabled(struct tracefs_instance *instance, enum tracefs_option_id id)
376*287e80b3SSadaf Ebrahimi {
377*287e80b3SSadaf Ebrahimi 	const char *name = tracefs_option_name(id);
378*287e80b3SSadaf Ebrahimi 	char file[PATH_MAX];
379*287e80b3SSadaf Ebrahimi 	long long res;
380*287e80b3SSadaf Ebrahimi 
381*287e80b3SSadaf Ebrahimi 	if (!name)
382*287e80b3SSadaf Ebrahimi 		return false;
383*287e80b3SSadaf Ebrahimi 	snprintf(file, PATH_MAX, "options/%s", name);
384*287e80b3SSadaf Ebrahimi 	if (!tracefs_instance_file_read_number(instance, file, &res) && res)
385*287e80b3SSadaf Ebrahimi 		return true;
386*287e80b3SSadaf Ebrahimi 
387*287e80b3SSadaf Ebrahimi 	return false;
388*287e80b3SSadaf Ebrahimi }
389*287e80b3SSadaf Ebrahimi 
390*287e80b3SSadaf Ebrahimi /**
391*287e80b3SSadaf Ebrahimi  * tracefs_option_mask_is_set - Check if given option is set in the bitmask
392*287e80b3SSadaf Ebrahimi  * @options: Options bitmask
393*287e80b3SSadaf Ebrahimi  * @id: trace option id
394*287e80b3SSadaf Ebrahimi  *
395*287e80b3SSadaf Ebrahimi  * Returns true if an option with given id is set in the bitmask,
396*287e80b3SSadaf Ebrahimi  * false if it is not set.
397*287e80b3SSadaf Ebrahimi  */
tracefs_option_mask_is_set(const struct tracefs_options_mask * options,enum tracefs_option_id id)398*287e80b3SSadaf Ebrahimi bool tracefs_option_mask_is_set(const struct tracefs_options_mask *options,
399*287e80b3SSadaf Ebrahimi 			   enum tracefs_option_id id)
400*287e80b3SSadaf Ebrahimi {
401*287e80b3SSadaf Ebrahimi 	if (id > TRACEFS_OPTION_INVALID)
402*287e80b3SSadaf Ebrahimi 		return options->mask & (1ULL << (id - 1));
403*287e80b3SSadaf Ebrahimi 	return false;
404*287e80b3SSadaf Ebrahimi }
405*287e80b3SSadaf Ebrahimi 
406*287e80b3SSadaf Ebrahimi struct func_list {
407*287e80b3SSadaf Ebrahimi 	struct func_list	*next;
408*287e80b3SSadaf Ebrahimi 	char			*func;
409*287e80b3SSadaf Ebrahimi 	unsigned int		start;
410*287e80b3SSadaf Ebrahimi 	unsigned int		end;
411*287e80b3SSadaf Ebrahimi };
412*287e80b3SSadaf Ebrahimi 
413*287e80b3SSadaf Ebrahimi struct func_filter {
414*287e80b3SSadaf Ebrahimi 	const char		*filter;
415*287e80b3SSadaf Ebrahimi 	regex_t			re;
416*287e80b3SSadaf Ebrahimi 	bool			set;
417*287e80b3SSadaf Ebrahimi 	bool			is_regex;
418*287e80b3SSadaf Ebrahimi };
419*287e80b3SSadaf Ebrahimi 
is_regex(const char * str)420*287e80b3SSadaf Ebrahimi static bool is_regex(const char *str)
421*287e80b3SSadaf Ebrahimi {
422*287e80b3SSadaf Ebrahimi 	int i;
423*287e80b3SSadaf Ebrahimi 
424*287e80b3SSadaf Ebrahimi 	for (i = 0; str[i]; i++) {
425*287e80b3SSadaf Ebrahimi 		switch (str[i]) {
426*287e80b3SSadaf Ebrahimi 		case 'a' ... 'z':
427*287e80b3SSadaf Ebrahimi 		case 'A'...'Z':
428*287e80b3SSadaf Ebrahimi 		case '_':
429*287e80b3SSadaf Ebrahimi 		case '0'...'9':
430*287e80b3SSadaf Ebrahimi 		case '*':
431*287e80b3SSadaf Ebrahimi 		case '.':
432*287e80b3SSadaf Ebrahimi 			/* Dots can be part of a function name */
433*287e80b3SSadaf Ebrahimi 		case '?':
434*287e80b3SSadaf Ebrahimi 			continue;
435*287e80b3SSadaf Ebrahimi 		default:
436*287e80b3SSadaf Ebrahimi 			return true;
437*287e80b3SSadaf Ebrahimi 		}
438*287e80b3SSadaf Ebrahimi 	}
439*287e80b3SSadaf Ebrahimi 	return false;
440*287e80b3SSadaf Ebrahimi }
441*287e80b3SSadaf Ebrahimi 
update_regex(const char * reg)442*287e80b3SSadaf Ebrahimi static char *update_regex(const char *reg)
443*287e80b3SSadaf Ebrahimi {
444*287e80b3SSadaf Ebrahimi 	int len = strlen(reg);
445*287e80b3SSadaf Ebrahimi 	char *str;
446*287e80b3SSadaf Ebrahimi 
447*287e80b3SSadaf Ebrahimi 	if (reg[0] == '^' && reg[len - 1] == '$')
448*287e80b3SSadaf Ebrahimi 		return strdup(reg);
449*287e80b3SSadaf Ebrahimi 
450*287e80b3SSadaf Ebrahimi 	str = malloc(len + 3);
451*287e80b3SSadaf Ebrahimi 	if (reg[0] == '^') {
452*287e80b3SSadaf Ebrahimi 		strcpy(str, reg);
453*287e80b3SSadaf Ebrahimi 	} else {
454*287e80b3SSadaf Ebrahimi 		str[0] = '^';
455*287e80b3SSadaf Ebrahimi 		strcpy(str + 1, reg);
456*287e80b3SSadaf Ebrahimi 		len++; /* add ^ */
457*287e80b3SSadaf Ebrahimi 	}
458*287e80b3SSadaf Ebrahimi 	if (str[len - 1] != '$')
459*287e80b3SSadaf Ebrahimi 		str[len++]= '$';
460*287e80b3SSadaf Ebrahimi 	str[len] = '\0';
461*287e80b3SSadaf Ebrahimi 	return str;
462*287e80b3SSadaf Ebrahimi }
463*287e80b3SSadaf Ebrahimi 
464*287e80b3SSadaf Ebrahimi /*
465*287e80b3SSadaf Ebrahimi  * Convert a glob into a regular expression.
466*287e80b3SSadaf Ebrahimi  */
make_regex(const char * glob)467*287e80b3SSadaf Ebrahimi static char *make_regex(const char *glob)
468*287e80b3SSadaf Ebrahimi {
469*287e80b3SSadaf Ebrahimi 	char *str;
470*287e80b3SSadaf Ebrahimi 	int cnt = 0;
471*287e80b3SSadaf Ebrahimi 	int i, j;
472*287e80b3SSadaf Ebrahimi 
473*287e80b3SSadaf Ebrahimi 	for (i = 0; glob[i]; i++) {
474*287e80b3SSadaf Ebrahimi 		if (glob[i] == '*'|| glob[i] == '.')
475*287e80b3SSadaf Ebrahimi 			cnt++;
476*287e80b3SSadaf Ebrahimi 	}
477*287e80b3SSadaf Ebrahimi 
478*287e80b3SSadaf Ebrahimi 	/* '^' + ('*'->'.*' or '.' -> '\.') + '$' + '\0' */
479*287e80b3SSadaf Ebrahimi 	str = malloc(i + cnt + 3);
480*287e80b3SSadaf Ebrahimi 	if (!str)
481*287e80b3SSadaf Ebrahimi 		return NULL;
482*287e80b3SSadaf Ebrahimi 
483*287e80b3SSadaf Ebrahimi 	str[0] = '^';
484*287e80b3SSadaf Ebrahimi 	for (i = 0, j = 1; glob[i]; i++, j++) {
485*287e80b3SSadaf Ebrahimi 		if (glob[i] == '*')
486*287e80b3SSadaf Ebrahimi 			str[j++] = '.';
487*287e80b3SSadaf Ebrahimi 		/* Dots can be part of a function name */
488*287e80b3SSadaf Ebrahimi 		if (glob[i] == '.')
489*287e80b3SSadaf Ebrahimi 			str[j++] = '\\';
490*287e80b3SSadaf Ebrahimi 		str[j] = glob[i];
491*287e80b3SSadaf Ebrahimi 	}
492*287e80b3SSadaf Ebrahimi 	str[j++] = '$';
493*287e80b3SSadaf Ebrahimi 	str[j] = '\0';
494*287e80b3SSadaf Ebrahimi 	return str;
495*287e80b3SSadaf Ebrahimi }
496*287e80b3SSadaf Ebrahimi 
match(const char * str,struct func_filter * func_filter)497*287e80b3SSadaf Ebrahimi static bool match(const char *str, struct func_filter *func_filter)
498*287e80b3SSadaf Ebrahimi {
499*287e80b3SSadaf Ebrahimi 	return regexec(&func_filter->re, str, 0, NULL, 0) == 0;
500*287e80b3SSadaf Ebrahimi }
501*287e80b3SSadaf Ebrahimi 
502*287e80b3SSadaf Ebrahimi /*
503*287e80b3SSadaf Ebrahimi  * Return 0 on success, -1 error writing, 1 on other errors.
504*287e80b3SSadaf Ebrahimi  */
write_filter(int fd,const char * filter,const char * module)505*287e80b3SSadaf Ebrahimi static int write_filter(int fd, const char *filter, const char *module)
506*287e80b3SSadaf Ebrahimi {
507*287e80b3SSadaf Ebrahimi 	char *each_str = NULL;
508*287e80b3SSadaf Ebrahimi 	int write_size;
509*287e80b3SSadaf Ebrahimi 	int size;
510*287e80b3SSadaf Ebrahimi 
511*287e80b3SSadaf Ebrahimi 	if (module)
512*287e80b3SSadaf Ebrahimi 		write_size = asprintf(&each_str, "%s:mod:%s ", filter, module);
513*287e80b3SSadaf Ebrahimi 	else
514*287e80b3SSadaf Ebrahimi 		write_size = asprintf(&each_str, "%s ", filter);
515*287e80b3SSadaf Ebrahimi 
516*287e80b3SSadaf Ebrahimi 	if (write_size < 0)
517*287e80b3SSadaf Ebrahimi 		return 1;
518*287e80b3SSadaf Ebrahimi 
519*287e80b3SSadaf Ebrahimi 	size = write(fd, each_str, write_size);
520*287e80b3SSadaf Ebrahimi 	free(each_str);
521*287e80b3SSadaf Ebrahimi 
522*287e80b3SSadaf Ebrahimi 	/* compare written bytes*/
523*287e80b3SSadaf Ebrahimi 	if (size < write_size)
524*287e80b3SSadaf Ebrahimi 		return -1;
525*287e80b3SSadaf Ebrahimi 
526*287e80b3SSadaf Ebrahimi 	return 0;
527*287e80b3SSadaf Ebrahimi }
528*287e80b3SSadaf Ebrahimi 
add_func(struct func_list *** next_func_ptr,unsigned int index)529*287e80b3SSadaf Ebrahimi static int add_func(struct func_list ***next_func_ptr, unsigned int index)
530*287e80b3SSadaf Ebrahimi {
531*287e80b3SSadaf Ebrahimi 	struct func_list **next_func = *next_func_ptr;
532*287e80b3SSadaf Ebrahimi 	struct func_list *func_list = *next_func;
533*287e80b3SSadaf Ebrahimi 
534*287e80b3SSadaf Ebrahimi 	if (!func_list) {
535*287e80b3SSadaf Ebrahimi 		func_list = calloc(1, sizeof(*func_list));
536*287e80b3SSadaf Ebrahimi 		if (!func_list)
537*287e80b3SSadaf Ebrahimi 			return -1;
538*287e80b3SSadaf Ebrahimi 		func_list->start = index;
539*287e80b3SSadaf Ebrahimi 		func_list->end = index;
540*287e80b3SSadaf Ebrahimi 		*next_func = func_list;
541*287e80b3SSadaf Ebrahimi 		return 0;
542*287e80b3SSadaf Ebrahimi 	}
543*287e80b3SSadaf Ebrahimi 
544*287e80b3SSadaf Ebrahimi 	if (index == func_list->end + 1) {
545*287e80b3SSadaf Ebrahimi 		func_list->end = index;
546*287e80b3SSadaf Ebrahimi 		return 0;
547*287e80b3SSadaf Ebrahimi 	}
548*287e80b3SSadaf Ebrahimi 	*next_func_ptr = &func_list->next;
549*287e80b3SSadaf Ebrahimi 	return add_func(next_func_ptr, index);
550*287e80b3SSadaf Ebrahimi }
551*287e80b3SSadaf Ebrahimi 
add_func_str(struct func_list *** next_func_ptr,const char * func)552*287e80b3SSadaf Ebrahimi static int add_func_str(struct func_list ***next_func_ptr, const char *func)
553*287e80b3SSadaf Ebrahimi {
554*287e80b3SSadaf Ebrahimi 	struct func_list **next_func = *next_func_ptr;
555*287e80b3SSadaf Ebrahimi 	struct func_list *func_list = *next_func;
556*287e80b3SSadaf Ebrahimi 
557*287e80b3SSadaf Ebrahimi 	if (!func_list) {
558*287e80b3SSadaf Ebrahimi 		func_list = calloc(1, sizeof(*func_list));
559*287e80b3SSadaf Ebrahimi 		if (!func_list)
560*287e80b3SSadaf Ebrahimi 			return -1;
561*287e80b3SSadaf Ebrahimi 		func_list->func = strdup(func);
562*287e80b3SSadaf Ebrahimi 		if (!func_list->func)
563*287e80b3SSadaf Ebrahimi 			return -1;
564*287e80b3SSadaf Ebrahimi 		*next_func = func_list;
565*287e80b3SSadaf Ebrahimi 		return 0;
566*287e80b3SSadaf Ebrahimi 	}
567*287e80b3SSadaf Ebrahimi 	*next_func_ptr = &func_list->next;
568*287e80b3SSadaf Ebrahimi 	return add_func_str(next_func_ptr, func);
569*287e80b3SSadaf Ebrahimi }
570*287e80b3SSadaf Ebrahimi 
free_func_list(struct func_list * func_list)571*287e80b3SSadaf Ebrahimi static void free_func_list(struct func_list *func_list)
572*287e80b3SSadaf Ebrahimi {
573*287e80b3SSadaf Ebrahimi 	struct func_list *f;
574*287e80b3SSadaf Ebrahimi 
575*287e80b3SSadaf Ebrahimi 	while (func_list) {
576*287e80b3SSadaf Ebrahimi 		f = func_list;
577*287e80b3SSadaf Ebrahimi 		func_list = f->next;
578*287e80b3SSadaf Ebrahimi 		free(f->func);
579*287e80b3SSadaf Ebrahimi 		free(f);
580*287e80b3SSadaf Ebrahimi 	}
581*287e80b3SSadaf Ebrahimi }
582*287e80b3SSadaf Ebrahimi 
583*287e80b3SSadaf Ebrahimi enum match_type {
584*287e80b3SSadaf Ebrahimi 	FILTER_CHECK	= (1 << 0),
585*287e80b3SSadaf Ebrahimi 	FILTER_WRITE	= (1 << 1),
586*287e80b3SSadaf Ebrahimi 	FILTER_FUTURE	= (1 << 2),
587*287e80b3SSadaf Ebrahimi 	SAVE_STRING	= (1 << 2),
588*287e80b3SSadaf Ebrahimi };
589*287e80b3SSadaf Ebrahimi 
match_filters(int fd,struct func_filter * func_filter,const char * module,struct func_list ** func_list,int flags)590*287e80b3SSadaf Ebrahimi static int match_filters(int fd, struct func_filter *func_filter,
591*287e80b3SSadaf Ebrahimi 			 const char *module, struct func_list **func_list,
592*287e80b3SSadaf Ebrahimi 			 int flags)
593*287e80b3SSadaf Ebrahimi {
594*287e80b3SSadaf Ebrahimi 	enum match_type type = flags & (FILTER_CHECK | FILTER_WRITE);
595*287e80b3SSadaf Ebrahimi 	bool save_str = flags & SAVE_STRING;
596*287e80b3SSadaf Ebrahimi 	bool future = flags & FILTER_FUTURE;
597*287e80b3SSadaf Ebrahimi 	bool mod_match = false;
598*287e80b3SSadaf Ebrahimi 	char *line = NULL;
599*287e80b3SSadaf Ebrahimi 	size_t size = 0;
600*287e80b3SSadaf Ebrahimi 	char *path;
601*287e80b3SSadaf Ebrahimi 	FILE *fp;
602*287e80b3SSadaf Ebrahimi 	int index = 0;
603*287e80b3SSadaf Ebrahimi 	int ret = 1;
604*287e80b3SSadaf Ebrahimi 	int mlen;
605*287e80b3SSadaf Ebrahimi 
606*287e80b3SSadaf Ebrahimi 	path = tracefs_get_tracing_file(TRACE_FILTER_LIST);
607*287e80b3SSadaf Ebrahimi 	if (!path)
608*287e80b3SSadaf Ebrahimi 		return 1;
609*287e80b3SSadaf Ebrahimi 
610*287e80b3SSadaf Ebrahimi 	fp = fopen(path, "r");
611*287e80b3SSadaf Ebrahimi 	tracefs_put_tracing_file(path);
612*287e80b3SSadaf Ebrahimi 
613*287e80b3SSadaf Ebrahimi 	if (!fp)
614*287e80b3SSadaf Ebrahimi 		return 1;
615*287e80b3SSadaf Ebrahimi 
616*287e80b3SSadaf Ebrahimi 	if (module)
617*287e80b3SSadaf Ebrahimi 		mlen = strlen(module);
618*287e80b3SSadaf Ebrahimi 
619*287e80b3SSadaf Ebrahimi 	while (getline(&line, &size, fp) >= 0) {
620*287e80b3SSadaf Ebrahimi 		char *saveptr = NULL;
621*287e80b3SSadaf Ebrahimi 		char *tok, *mtok;
622*287e80b3SSadaf Ebrahimi 		int len = strlen(line);
623*287e80b3SSadaf Ebrahimi 
624*287e80b3SSadaf Ebrahimi 		if (line[len - 1] == '\n')
625*287e80b3SSadaf Ebrahimi 			line[len - 1] = '\0';
626*287e80b3SSadaf Ebrahimi 		tok = strtok_r(line, " ", &saveptr);
627*287e80b3SSadaf Ebrahimi 		if (!tok)
628*287e80b3SSadaf Ebrahimi 			goto next;
629*287e80b3SSadaf Ebrahimi 
630*287e80b3SSadaf Ebrahimi 		index++;
631*287e80b3SSadaf Ebrahimi 
632*287e80b3SSadaf Ebrahimi 		if (module) {
633*287e80b3SSadaf Ebrahimi 			mtok = strtok_r(NULL, " ", &saveptr);
634*287e80b3SSadaf Ebrahimi 			if (!mtok)
635*287e80b3SSadaf Ebrahimi 				goto next;
636*287e80b3SSadaf Ebrahimi 			if ((strncmp(mtok + 1, module, mlen) != 0) ||
637*287e80b3SSadaf Ebrahimi 			    (mtok[mlen + 1] != ']'))
638*287e80b3SSadaf Ebrahimi 				goto next;
639*287e80b3SSadaf Ebrahimi 			if (future)
640*287e80b3SSadaf Ebrahimi 				mod_match = true;
641*287e80b3SSadaf Ebrahimi 		}
642*287e80b3SSadaf Ebrahimi 		switch (type) {
643*287e80b3SSadaf Ebrahimi 		case FILTER_CHECK:
644*287e80b3SSadaf Ebrahimi 			if (match(tok, func_filter)) {
645*287e80b3SSadaf Ebrahimi 				func_filter->set = true;
646*287e80b3SSadaf Ebrahimi 				if (save_str)
647*287e80b3SSadaf Ebrahimi 					ret = add_func_str(&func_list, tok);
648*287e80b3SSadaf Ebrahimi 				else
649*287e80b3SSadaf Ebrahimi 					ret = add_func(&func_list, index);
650*287e80b3SSadaf Ebrahimi 				if (ret)
651*287e80b3SSadaf Ebrahimi 					goto out;
652*287e80b3SSadaf Ebrahimi 			}
653*287e80b3SSadaf Ebrahimi 			break;
654*287e80b3SSadaf Ebrahimi 		case FILTER_WRITE:
655*287e80b3SSadaf Ebrahimi 			/* Writes only have one filter */
656*287e80b3SSadaf Ebrahimi 			if (match(tok, func_filter)) {
657*287e80b3SSadaf Ebrahimi 				ret = write_filter(fd, tok, module);
658*287e80b3SSadaf Ebrahimi 				if (ret)
659*287e80b3SSadaf Ebrahimi 					goto out;
660*287e80b3SSadaf Ebrahimi 			}
661*287e80b3SSadaf Ebrahimi 			break;
662*287e80b3SSadaf Ebrahimi 		default:
663*287e80b3SSadaf Ebrahimi 			/* Should never happen */
664*287e80b3SSadaf Ebrahimi 			ret = -1;
665*287e80b3SSadaf Ebrahimi 			goto out;
666*287e80b3SSadaf Ebrahimi 
667*287e80b3SSadaf Ebrahimi 		}
668*287e80b3SSadaf Ebrahimi 	next:
669*287e80b3SSadaf Ebrahimi 		free(line);
670*287e80b3SSadaf Ebrahimi 		line = NULL;
671*287e80b3SSadaf Ebrahimi 		len = 0;
672*287e80b3SSadaf Ebrahimi 	}
673*287e80b3SSadaf Ebrahimi  out:
674*287e80b3SSadaf Ebrahimi 	free(line);
675*287e80b3SSadaf Ebrahimi 	fclose(fp);
676*287e80b3SSadaf Ebrahimi 
677*287e80b3SSadaf Ebrahimi 	/* If there was no matches and future was set, this is a success */
678*287e80b3SSadaf Ebrahimi 	if (future && !mod_match)
679*287e80b3SSadaf Ebrahimi 		ret = 0;
680*287e80b3SSadaf Ebrahimi 
681*287e80b3SSadaf Ebrahimi 	return ret;
682*287e80b3SSadaf Ebrahimi }
683*287e80b3SSadaf Ebrahimi 
check_available_filters(struct func_filter * func_filter,const char * module,struct func_list ** func_list,bool future)684*287e80b3SSadaf Ebrahimi static int check_available_filters(struct func_filter *func_filter,
685*287e80b3SSadaf Ebrahimi 				   const char *module,
686*287e80b3SSadaf Ebrahimi 				   struct func_list **func_list,
687*287e80b3SSadaf Ebrahimi 				   bool future)
688*287e80b3SSadaf Ebrahimi {
689*287e80b3SSadaf Ebrahimi 	int flags = FILTER_CHECK | (future ? FILTER_FUTURE : 0);
690*287e80b3SSadaf Ebrahimi 
691*287e80b3SSadaf Ebrahimi 	return match_filters(-1, func_filter, module, func_list, flags);
692*287e80b3SSadaf Ebrahimi }
693*287e80b3SSadaf Ebrahimi 
694*287e80b3SSadaf Ebrahimi 
list_available_filters(struct func_filter * func_filter,const char * module,struct func_list ** func_list)695*287e80b3SSadaf Ebrahimi static int list_available_filters(struct func_filter *func_filter,
696*287e80b3SSadaf Ebrahimi 				   const char *module,
697*287e80b3SSadaf Ebrahimi 				   struct func_list **func_list)
698*287e80b3SSadaf Ebrahimi {
699*287e80b3SSadaf Ebrahimi 	int flags = FILTER_CHECK | SAVE_STRING;
700*287e80b3SSadaf Ebrahimi 
701*287e80b3SSadaf Ebrahimi 	return match_filters(-1, func_filter, module, func_list, flags);
702*287e80b3SSadaf Ebrahimi }
703*287e80b3SSadaf Ebrahimi 
set_regex_filter(int fd,struct func_filter * func_filter,const char * module)704*287e80b3SSadaf Ebrahimi static int set_regex_filter(int fd, struct func_filter *func_filter,
705*287e80b3SSadaf Ebrahimi 			    const char *module)
706*287e80b3SSadaf Ebrahimi {
707*287e80b3SSadaf Ebrahimi 	return match_filters(fd, func_filter, module, NULL, FILTER_WRITE);
708*287e80b3SSadaf Ebrahimi }
709*287e80b3SSadaf Ebrahimi 
controlled_write(int fd,struct func_filter * func_filter,const char * module)710*287e80b3SSadaf Ebrahimi static int controlled_write(int fd, struct func_filter *func_filter,
711*287e80b3SSadaf Ebrahimi 			    const char *module)
712*287e80b3SSadaf Ebrahimi {
713*287e80b3SSadaf Ebrahimi 	const char *filter = func_filter->filter;
714*287e80b3SSadaf Ebrahimi 	int ret;
715*287e80b3SSadaf Ebrahimi 
716*287e80b3SSadaf Ebrahimi 	if (func_filter->is_regex)
717*287e80b3SSadaf Ebrahimi 		ret = set_regex_filter(fd, func_filter, module);
718*287e80b3SSadaf Ebrahimi 	else
719*287e80b3SSadaf Ebrahimi 		ret = write_filter(fd, filter, module);
720*287e80b3SSadaf Ebrahimi 
721*287e80b3SSadaf Ebrahimi 	return ret;
722*287e80b3SSadaf Ebrahimi }
723*287e80b3SSadaf Ebrahimi 
init_func_filter(struct func_filter * func_filter,const char * filter)724*287e80b3SSadaf Ebrahimi static int init_func_filter(struct func_filter *func_filter, const char *filter)
725*287e80b3SSadaf Ebrahimi {
726*287e80b3SSadaf Ebrahimi 	char *str;
727*287e80b3SSadaf Ebrahimi 	int ret;
728*287e80b3SSadaf Ebrahimi 
729*287e80b3SSadaf Ebrahimi 	if (!(func_filter->is_regex = is_regex(filter)))
730*287e80b3SSadaf Ebrahimi 		str = make_regex(filter);
731*287e80b3SSadaf Ebrahimi 	else
732*287e80b3SSadaf Ebrahimi 		str = update_regex(filter);
733*287e80b3SSadaf Ebrahimi 
734*287e80b3SSadaf Ebrahimi 	if (!str)
735*287e80b3SSadaf Ebrahimi 		return -1;
736*287e80b3SSadaf Ebrahimi 
737*287e80b3SSadaf Ebrahimi 	ret = regcomp(&func_filter->re, str, REG_ICASE|REG_NOSUB);
738*287e80b3SSadaf Ebrahimi 	free(str);
739*287e80b3SSadaf Ebrahimi 
740*287e80b3SSadaf Ebrahimi 	if (ret < 0)
741*287e80b3SSadaf Ebrahimi 		return -1;
742*287e80b3SSadaf Ebrahimi 
743*287e80b3SSadaf Ebrahimi 	func_filter->filter = filter;
744*287e80b3SSadaf Ebrahimi 	return 0;
745*287e80b3SSadaf Ebrahimi }
746*287e80b3SSadaf Ebrahimi 
write_number(int fd,unsigned int start,unsigned int end)747*287e80b3SSadaf Ebrahimi static int write_number(int fd, unsigned int start, unsigned int end)
748*287e80b3SSadaf Ebrahimi {
749*287e80b3SSadaf Ebrahimi 	char buf[64];
750*287e80b3SSadaf Ebrahimi 	unsigned int i;
751*287e80b3SSadaf Ebrahimi 	int n, ret;
752*287e80b3SSadaf Ebrahimi 
753*287e80b3SSadaf Ebrahimi 	for (i = start; i <= end; i++) {
754*287e80b3SSadaf Ebrahimi 		n = snprintf(buf, 64, "%d ", i);
755*287e80b3SSadaf Ebrahimi 		ret = write(fd, buf, n);
756*287e80b3SSadaf Ebrahimi 		if (ret < 0)
757*287e80b3SSadaf Ebrahimi 			return ret;
758*287e80b3SSadaf Ebrahimi 	}
759*287e80b3SSadaf Ebrahimi 
760*287e80b3SSadaf Ebrahimi 	return 0;
761*287e80b3SSadaf Ebrahimi }
762*287e80b3SSadaf Ebrahimi 
763*287e80b3SSadaf Ebrahimi /*
764*287e80b3SSadaf Ebrahimi  * This will try to write the first number, if that fails, it
765*287e80b3SSadaf Ebrahimi  * will assume that it is not supported and return 1.
766*287e80b3SSadaf Ebrahimi  * If the first write succeeds, but a following write fails, then
767*287e80b3SSadaf Ebrahimi  * the kernel does support this, but something else went wrong,
768*287e80b3SSadaf Ebrahimi  * in this case, return -1.
769*287e80b3SSadaf Ebrahimi  */
write_func_list(int fd,struct func_list * list)770*287e80b3SSadaf Ebrahimi static int write_func_list(int fd, struct func_list *list)
771*287e80b3SSadaf Ebrahimi {
772*287e80b3SSadaf Ebrahimi 	int ret;
773*287e80b3SSadaf Ebrahimi 
774*287e80b3SSadaf Ebrahimi 	if (!list)
775*287e80b3SSadaf Ebrahimi 		return 0;
776*287e80b3SSadaf Ebrahimi 
777*287e80b3SSadaf Ebrahimi 	ret = write_number(fd, list->start, list->end);
778*287e80b3SSadaf Ebrahimi 	if (ret)
779*287e80b3SSadaf Ebrahimi 		return 1; // try a different way
780*287e80b3SSadaf Ebrahimi 	list = list->next;
781*287e80b3SSadaf Ebrahimi 	while (list) {
782*287e80b3SSadaf Ebrahimi 		ret = write_number(fd, list->start, list->end);
783*287e80b3SSadaf Ebrahimi 		if (ret)
784*287e80b3SSadaf Ebrahimi 			return -1;
785*287e80b3SSadaf Ebrahimi 		list = list->next;
786*287e80b3SSadaf Ebrahimi 	}
787*287e80b3SSadaf Ebrahimi 	return 0;
788*287e80b3SSadaf Ebrahimi }
789*287e80b3SSadaf Ebrahimi 
update_filter(const char * filter_path,int * fd,struct tracefs_instance * instance,const char * filter,const char * module,unsigned int flags)790*287e80b3SSadaf Ebrahimi static int update_filter(const char *filter_path, int *fd,
791*287e80b3SSadaf Ebrahimi 			 struct tracefs_instance *instance, const char *filter,
792*287e80b3SSadaf Ebrahimi 			 const char *module, unsigned int flags)
793*287e80b3SSadaf Ebrahimi {
794*287e80b3SSadaf Ebrahimi 	struct func_filter func_filter;
795*287e80b3SSadaf Ebrahimi 	struct func_list *func_list = NULL;
796*287e80b3SSadaf Ebrahimi 	bool reset = flags & TRACEFS_FL_RESET;
797*287e80b3SSadaf Ebrahimi 	bool cont = flags & TRACEFS_FL_CONTINUE;
798*287e80b3SSadaf Ebrahimi 	bool future = flags & TRACEFS_FL_FUTURE;
799*287e80b3SSadaf Ebrahimi 	pthread_mutex_t *lock = trace_get_lock(instance);
800*287e80b3SSadaf Ebrahimi 	int open_flags;
801*287e80b3SSadaf Ebrahimi 	int ret = 1;
802*287e80b3SSadaf Ebrahimi 
803*287e80b3SSadaf Ebrahimi 	/* future flag is only applicable to modules */
804*287e80b3SSadaf Ebrahimi 	if (future && !module) {
805*287e80b3SSadaf Ebrahimi 		errno = EINVAL;
806*287e80b3SSadaf Ebrahimi 		return 1;
807*287e80b3SSadaf Ebrahimi 	}
808*287e80b3SSadaf Ebrahimi 
809*287e80b3SSadaf Ebrahimi 	pthread_mutex_lock(lock);
810*287e80b3SSadaf Ebrahimi 
811*287e80b3SSadaf Ebrahimi 	/* RESET is only allowed if the file is not opened yet */
812*287e80b3SSadaf Ebrahimi 	if (reset && *fd >= 0) {
813*287e80b3SSadaf Ebrahimi 		errno = EBUSY;
814*287e80b3SSadaf Ebrahimi 		ret = -1;
815*287e80b3SSadaf Ebrahimi 		goto out;
816*287e80b3SSadaf Ebrahimi 	}
817*287e80b3SSadaf Ebrahimi 
818*287e80b3SSadaf Ebrahimi 	/*
819*287e80b3SSadaf Ebrahimi 	 * Set EINVAL on no matching filter. But errno may still be modified
820*287e80b3SSadaf Ebrahimi 	 * on another type of failure (allocation or opening a file).
821*287e80b3SSadaf Ebrahimi 	 */
822*287e80b3SSadaf Ebrahimi 	errno = EINVAL;
823*287e80b3SSadaf Ebrahimi 
824*287e80b3SSadaf Ebrahimi 	/* module set with NULL filter means to enable all functions in a module */
825*287e80b3SSadaf Ebrahimi 	if (module && !filter)
826*287e80b3SSadaf Ebrahimi 		filter = "*";
827*287e80b3SSadaf Ebrahimi 
828*287e80b3SSadaf Ebrahimi 	if (!filter) {
829*287e80b3SSadaf Ebrahimi 		/* OK to call without filters if this is closing the opened file */
830*287e80b3SSadaf Ebrahimi 		if (!cont && *fd >= 0) {
831*287e80b3SSadaf Ebrahimi 			errno = 0;
832*287e80b3SSadaf Ebrahimi 			ret = 0;
833*287e80b3SSadaf Ebrahimi 			close(*fd);
834*287e80b3SSadaf Ebrahimi 			*fd = -1;
835*287e80b3SSadaf Ebrahimi 		}
836*287e80b3SSadaf Ebrahimi 		/* Also OK to call if reset flag is set */
837*287e80b3SSadaf Ebrahimi 		if (reset)
838*287e80b3SSadaf Ebrahimi 			goto open_file;
839*287e80b3SSadaf Ebrahimi 
840*287e80b3SSadaf Ebrahimi 		goto out;
841*287e80b3SSadaf Ebrahimi 	}
842*287e80b3SSadaf Ebrahimi 
843*287e80b3SSadaf Ebrahimi 	if (init_func_filter(&func_filter, filter) < 0)
844*287e80b3SSadaf Ebrahimi 		goto out;
845*287e80b3SSadaf Ebrahimi 
846*287e80b3SSadaf Ebrahimi 	ret = check_available_filters(&func_filter, module, &func_list, future);
847*287e80b3SSadaf Ebrahimi 	if (ret)
848*287e80b3SSadaf Ebrahimi 		goto out_free;
849*287e80b3SSadaf Ebrahimi 
850*287e80b3SSadaf Ebrahimi  open_file:
851*287e80b3SSadaf Ebrahimi 	ret = 1;
852*287e80b3SSadaf Ebrahimi 
853*287e80b3SSadaf Ebrahimi 	open_flags = reset ? O_TRUNC : O_APPEND;
854*287e80b3SSadaf Ebrahimi 
855*287e80b3SSadaf Ebrahimi 	if (*fd < 0)
856*287e80b3SSadaf Ebrahimi 		*fd = open(filter_path, O_WRONLY | O_CLOEXEC | open_flags);
857*287e80b3SSadaf Ebrahimi 	if (*fd < 0)
858*287e80b3SSadaf Ebrahimi 		goto out_free;
859*287e80b3SSadaf Ebrahimi 
860*287e80b3SSadaf Ebrahimi 	errno = 0;
861*287e80b3SSadaf Ebrahimi 	ret = 0;
862*287e80b3SSadaf Ebrahimi 
863*287e80b3SSadaf Ebrahimi 	if (filter) {
864*287e80b3SSadaf Ebrahimi 		/*
865*287e80b3SSadaf Ebrahimi 		 * If future is set, and no functions were found, then
866*287e80b3SSadaf Ebrahimi 		 * set it directly.
867*287e80b3SSadaf Ebrahimi 		 */
868*287e80b3SSadaf Ebrahimi 		if (func_list)
869*287e80b3SSadaf Ebrahimi 			ret = write_func_list(*fd, func_list);
870*287e80b3SSadaf Ebrahimi 		else
871*287e80b3SSadaf Ebrahimi 			ret = 1;
872*287e80b3SSadaf Ebrahimi 		if (ret > 0)
873*287e80b3SSadaf Ebrahimi 			ret = controlled_write(*fd, &func_filter, module);
874*287e80b3SSadaf Ebrahimi 	}
875*287e80b3SSadaf Ebrahimi 
876*287e80b3SSadaf Ebrahimi 	if (!cont) {
877*287e80b3SSadaf Ebrahimi 		close(*fd);
878*287e80b3SSadaf Ebrahimi 		*fd = -1;
879*287e80b3SSadaf Ebrahimi 	}
880*287e80b3SSadaf Ebrahimi 
881*287e80b3SSadaf Ebrahimi  out_free:
882*287e80b3SSadaf Ebrahimi 	if (filter)
883*287e80b3SSadaf Ebrahimi 		regfree(&func_filter.re);
884*287e80b3SSadaf Ebrahimi 	free_func_list(func_list);
885*287e80b3SSadaf Ebrahimi  out:
886*287e80b3SSadaf Ebrahimi 	pthread_mutex_unlock(lock);
887*287e80b3SSadaf Ebrahimi 
888*287e80b3SSadaf Ebrahimi 	return ret;
889*287e80b3SSadaf Ebrahimi }
890*287e80b3SSadaf Ebrahimi 
891*287e80b3SSadaf Ebrahimi /**
892*287e80b3SSadaf Ebrahimi  * tracefs_function_filter - filter the functions that are traced
893*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
894*287e80b3SSadaf Ebrahimi  * @filter: The filter to filter what functions are to be traced
895*287e80b3SSadaf Ebrahimi  * @module: Module to be traced or NULL if all functions are to be examined.
896*287e80b3SSadaf Ebrahimi  * @flags: flags on modifying the filter file
897*287e80b3SSadaf Ebrahimi  *
898*287e80b3SSadaf Ebrahimi  * @filter may be a full function name, a glob, or a regex. It will be
899*287e80b3SSadaf Ebrahimi  * considered a regex, if there's any characters that are not normally in
900*287e80b3SSadaf Ebrahimi  * function names or "*" or "?" for a glob.
901*287e80b3SSadaf Ebrahimi  *
902*287e80b3SSadaf Ebrahimi  * @flags:
903*287e80b3SSadaf Ebrahimi  *   TRACEFS_FL_RESET - will clear the functions in the filter file
904*287e80b3SSadaf Ebrahimi  *          before applying the @filter. This will error with -1
905*287e80b3SSadaf Ebrahimi  *          and errno of EBUSY if this flag is set and a previous
906*287e80b3SSadaf Ebrahimi  *          call had the same instance and TRACEFS_FL_CONTINUE set.
907*287e80b3SSadaf Ebrahimi  *   TRACEFS_FL_CONTINUE - will keep the filter file open on return.
908*287e80b3SSadaf Ebrahimi  *          The filter is updated on closing of the filter file.
909*287e80b3SSadaf Ebrahimi  *          With this flag set, the file is not closed, and more filters
910*287e80b3SSadaf Ebrahimi  *          may be added before they take effect. The last call of this
911*287e80b3SSadaf Ebrahimi  *          function must be called without this flag for the filter
912*287e80b3SSadaf Ebrahimi  *          to take effect.
913*287e80b3SSadaf Ebrahimi  *   TRACEFS_FL_FUTURE - only applicable if "module" is set. If no match
914*287e80b3SSadaf Ebrahimi  *          is made, and the module is not yet loaded, it will still attempt
915*287e80b3SSadaf Ebrahimi  *          to write the filter plus the module; "<filter>:mod:<module>"
916*287e80b3SSadaf Ebrahimi  *          to the filter file. Starting with Linux kernels 4.13, it is possible
917*287e80b3SSadaf Ebrahimi  *          to load the filter file with module functions for a module that
918*287e80b3SSadaf Ebrahimi  *          is not yet loaded, and when the module is loaded, it will then
919*287e80b3SSadaf Ebrahimi  *          activate the module.
920*287e80b3SSadaf Ebrahimi  *
921*287e80b3SSadaf Ebrahimi  * Returns 0 on success, 1 if there was an error but the filtering has not
922*287e80b3SSadaf Ebrahimi  *  yet started, -1 if there was an error but the filtering has started.
923*287e80b3SSadaf Ebrahimi  *  If -1 is returned and TRACEFS_FL_CONTINUE was set, then this function
924*287e80b3SSadaf Ebrahimi  *  needs to be called again without the TRACEFS_FL_CONTINUE flag to commit
925*287e80b3SSadaf Ebrahimi  *  the changes and close the filter file.
926*287e80b3SSadaf Ebrahimi  */
tracefs_function_filter(struct tracefs_instance * instance,const char * filter,const char * module,unsigned int flags)927*287e80b3SSadaf Ebrahimi int tracefs_function_filter(struct tracefs_instance *instance, const char *filter,
928*287e80b3SSadaf Ebrahimi 			    const char *module, unsigned int flags)
929*287e80b3SSadaf Ebrahimi {
930*287e80b3SSadaf Ebrahimi 	char *filter_path;
931*287e80b3SSadaf Ebrahimi 	int *fd;
932*287e80b3SSadaf Ebrahimi 	int ret;
933*287e80b3SSadaf Ebrahimi 
934*287e80b3SSadaf Ebrahimi 	filter_path = tracefs_instance_get_file(instance, TRACE_FILTER);
935*287e80b3SSadaf Ebrahimi 	if (!filter_path)
936*287e80b3SSadaf Ebrahimi 		return -1;
937*287e80b3SSadaf Ebrahimi 
938*287e80b3SSadaf Ebrahimi 	if (instance)
939*287e80b3SSadaf Ebrahimi 		fd = &instance->ftrace_filter_fd;
940*287e80b3SSadaf Ebrahimi 	else
941*287e80b3SSadaf Ebrahimi 		fd = &ftrace_filter_fd;
942*287e80b3SSadaf Ebrahimi 
943*287e80b3SSadaf Ebrahimi 	ret = update_filter(filter_path, fd, instance, filter, module, flags);
944*287e80b3SSadaf Ebrahimi 	tracefs_put_tracing_file(filter_path);
945*287e80b3SSadaf Ebrahimi 	return ret;
946*287e80b3SSadaf Ebrahimi }
947*287e80b3SSadaf Ebrahimi 
948*287e80b3SSadaf Ebrahimi /**
949*287e80b3SSadaf Ebrahimi  * tracefs_function_notrace - filter the functions that are not to be traced
950*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
951*287e80b3SSadaf Ebrahimi  * @filter: The filter to filter what functions are not to be traced
952*287e80b3SSadaf Ebrahimi  * @module: Module to be traced or NULL if all functions are to be examined.
953*287e80b3SSadaf Ebrahimi  * @flags: flags on modifying the filter file
954*287e80b3SSadaf Ebrahimi  *
955*287e80b3SSadaf Ebrahimi  * See tracefs_function_filter, as this has the same functionality but
956*287e80b3SSadaf Ebrahimi  * for adding to the "notrace" filter.
957*287e80b3SSadaf Ebrahimi  */
tracefs_function_notrace(struct tracefs_instance * instance,const char * filter,const char * module,unsigned int flags)958*287e80b3SSadaf Ebrahimi int tracefs_function_notrace(struct tracefs_instance *instance, const char *filter,
959*287e80b3SSadaf Ebrahimi 			     const char *module, unsigned int flags)
960*287e80b3SSadaf Ebrahimi {
961*287e80b3SSadaf Ebrahimi 	char *filter_path;
962*287e80b3SSadaf Ebrahimi 	int *fd;
963*287e80b3SSadaf Ebrahimi 	int ret;
964*287e80b3SSadaf Ebrahimi 
965*287e80b3SSadaf Ebrahimi 	filter_path = tracefs_instance_get_file(instance, TRACE_NOTRACE);
966*287e80b3SSadaf Ebrahimi 	if (!filter_path)
967*287e80b3SSadaf Ebrahimi 		return -1;
968*287e80b3SSadaf Ebrahimi 
969*287e80b3SSadaf Ebrahimi 	if (instance)
970*287e80b3SSadaf Ebrahimi 		fd = &instance->ftrace_notrace_fd;
971*287e80b3SSadaf Ebrahimi 	else
972*287e80b3SSadaf Ebrahimi 		fd = &ftrace_notrace_fd;
973*287e80b3SSadaf Ebrahimi 
974*287e80b3SSadaf Ebrahimi 	ret = update_filter(filter_path, fd, instance, filter, module, flags);
975*287e80b3SSadaf Ebrahimi 	tracefs_put_tracing_file(filter_path);
976*287e80b3SSadaf Ebrahimi 	return ret;
977*287e80b3SSadaf Ebrahimi }
978*287e80b3SSadaf Ebrahimi 
write_tracer(int fd,const char * tracer)979*287e80b3SSadaf Ebrahimi int write_tracer(int fd, const char *tracer)
980*287e80b3SSadaf Ebrahimi {
981*287e80b3SSadaf Ebrahimi 	int ret;
982*287e80b3SSadaf Ebrahimi 
983*287e80b3SSadaf Ebrahimi 	ret = write(fd, tracer, strlen(tracer));
984*287e80b3SSadaf Ebrahimi 	if (ret < strlen(tracer))
985*287e80b3SSadaf Ebrahimi 		return -1;
986*287e80b3SSadaf Ebrahimi 	return ret;
987*287e80b3SSadaf Ebrahimi }
988*287e80b3SSadaf Ebrahimi 
989*287e80b3SSadaf Ebrahimi /**
990*287e80b3SSadaf Ebrahimi  * tracefs_set_tracer - function to set the tracer
991*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance
992*287e80b3SSadaf Ebrahimi  * @tracer: The tracer enum that defines the tracer to be set
993*287e80b3SSadaf Ebrahimi  * @t: A tracer name if TRACEFS_TRACER_CUSTOM is passed in for @tracer
994*287e80b3SSadaf Ebrahimi  *
995*287e80b3SSadaf Ebrahimi  * Set the tracer for the instance based on the tracefs_tracer enums.
996*287e80b3SSadaf Ebrahimi  * If the user wishes to enable a tracer that is not defined by
997*287e80b3SSadaf Ebrahimi  * the enum (new or custom kernel), the tracer can be set to
998*287e80b3SSadaf Ebrahimi  * TRACEFS_TRACER_CUSTOM, and pass in a const char * name for
999*287e80b3SSadaf Ebrahimi  * the tracer to set.
1000*287e80b3SSadaf Ebrahimi  *
1001*287e80b3SSadaf Ebrahimi  * Returns 0 on succes, negative on error.
1002*287e80b3SSadaf Ebrahimi  */
1003*287e80b3SSadaf Ebrahimi 
tracefs_tracer_set(struct tracefs_instance * instance,enum tracefs_tracers tracer,...)1004*287e80b3SSadaf Ebrahimi int tracefs_tracer_set(struct tracefs_instance *instance,
1005*287e80b3SSadaf Ebrahimi 		       enum tracefs_tracers tracer, ...)
1006*287e80b3SSadaf Ebrahimi {
1007*287e80b3SSadaf Ebrahimi 	char *tracer_path = NULL;
1008*287e80b3SSadaf Ebrahimi 	const char *t = NULL;
1009*287e80b3SSadaf Ebrahimi 	int ret = -1;
1010*287e80b3SSadaf Ebrahimi 	int fd = -1;
1011*287e80b3SSadaf Ebrahimi 	int i;
1012*287e80b3SSadaf Ebrahimi 
1013*287e80b3SSadaf Ebrahimi 	if (tracer < 0 || tracer > ARRAY_SIZE(tracers)) {
1014*287e80b3SSadaf Ebrahimi 		errno = EINVAL;
1015*287e80b3SSadaf Ebrahimi 		return -1;
1016*287e80b3SSadaf Ebrahimi 	}
1017*287e80b3SSadaf Ebrahimi 
1018*287e80b3SSadaf Ebrahimi 	tracer_path = tracefs_instance_get_file(instance, CUR_TRACER);
1019*287e80b3SSadaf Ebrahimi 	if (!tracer_path)
1020*287e80b3SSadaf Ebrahimi 		return -1;
1021*287e80b3SSadaf Ebrahimi 
1022*287e80b3SSadaf Ebrahimi 	fd = open(tracer_path, O_WRONLY);
1023*287e80b3SSadaf Ebrahimi 	if (fd < 0) {
1024*287e80b3SSadaf Ebrahimi 		errno = ENOENT;
1025*287e80b3SSadaf Ebrahimi 		goto out;
1026*287e80b3SSadaf Ebrahimi 	}
1027*287e80b3SSadaf Ebrahimi 
1028*287e80b3SSadaf Ebrahimi 	if (tracer == TRACEFS_TRACER_CUSTOM) {
1029*287e80b3SSadaf Ebrahimi 		va_list ap;
1030*287e80b3SSadaf Ebrahimi 
1031*287e80b3SSadaf Ebrahimi 		va_start(ap, tracer);
1032*287e80b3SSadaf Ebrahimi 		t = va_arg(ap, const char *);
1033*287e80b3SSadaf Ebrahimi 		va_end(ap);
1034*287e80b3SSadaf Ebrahimi 	} else if (tracer == tracer_enums[tracer]) {
1035*287e80b3SSadaf Ebrahimi 		t = tracers[tracer];
1036*287e80b3SSadaf Ebrahimi 	} else {
1037*287e80b3SSadaf Ebrahimi 		for (i = 0; i < ARRAY_SIZE(tracer_enums); i++) {
1038*287e80b3SSadaf Ebrahimi 			if (tracer == tracer_enums[i]) {
1039*287e80b3SSadaf Ebrahimi 				t = tracers[i];
1040*287e80b3SSadaf Ebrahimi 				break;
1041*287e80b3SSadaf Ebrahimi 			}
1042*287e80b3SSadaf Ebrahimi 		}
1043*287e80b3SSadaf Ebrahimi 	}
1044*287e80b3SSadaf Ebrahimi 	if (!t) {
1045*287e80b3SSadaf Ebrahimi 		errno = EINVAL;
1046*287e80b3SSadaf Ebrahimi 		goto out;
1047*287e80b3SSadaf Ebrahimi 	}
1048*287e80b3SSadaf Ebrahimi 	ret = write_tracer(fd, t);
1049*287e80b3SSadaf Ebrahimi 	/*
1050*287e80b3SSadaf Ebrahimi 	 * If the tracer does not exist, EINVAL is returned,
1051*287e80b3SSadaf Ebrahimi 	 * but let the user know this as ENODEV.
1052*287e80b3SSadaf Ebrahimi 	 */
1053*287e80b3SSadaf Ebrahimi 	if (ret < 0 && errno == EINVAL)
1054*287e80b3SSadaf Ebrahimi 		errno = ENODEV;
1055*287e80b3SSadaf Ebrahimi  out:
1056*287e80b3SSadaf Ebrahimi 	tracefs_put_tracing_file(tracer_path);
1057*287e80b3SSadaf Ebrahimi 	close(fd);
1058*287e80b3SSadaf Ebrahimi 	return ret > 0 ? 0 : ret;
1059*287e80b3SSadaf Ebrahimi }
1060*287e80b3SSadaf Ebrahimi 
tracefs_tracer_clear(struct tracefs_instance * instance)1061*287e80b3SSadaf Ebrahimi int  tracefs_tracer_clear(struct tracefs_instance *instance)
1062*287e80b3SSadaf Ebrahimi {
1063*287e80b3SSadaf Ebrahimi 	return tracefs_tracer_set(instance, TRACEFS_TRACER_NOP);
1064*287e80b3SSadaf Ebrahimi }
1065*287e80b3SSadaf Ebrahimi 
splice_safe(int fd,int pfd)1066*287e80b3SSadaf Ebrahimi static bool splice_safe(int fd, int pfd)
1067*287e80b3SSadaf Ebrahimi {
1068*287e80b3SSadaf Ebrahimi 	int ret;
1069*287e80b3SSadaf Ebrahimi 
1070*287e80b3SSadaf Ebrahimi 	errno = 0;
1071*287e80b3SSadaf Ebrahimi 	ret = splice(pfd, NULL, fd, NULL,
1072*287e80b3SSadaf Ebrahimi 		     10, SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
1073*287e80b3SSadaf Ebrahimi 
1074*287e80b3SSadaf Ebrahimi 	return !ret || (ret < 0 && errno == EAGAIN);
1075*287e80b3SSadaf Ebrahimi }
1076*287e80b3SSadaf Ebrahimi 
read_trace_pipe(bool * keep_going,int in_fd,int out_fd)1077*287e80b3SSadaf Ebrahimi static ssize_t read_trace_pipe(bool *keep_going, int in_fd, int out_fd)
1078*287e80b3SSadaf Ebrahimi {
1079*287e80b3SSadaf Ebrahimi 	char buf[BUFSIZ];
1080*287e80b3SSadaf Ebrahimi 	ssize_t bread = 0;
1081*287e80b3SSadaf Ebrahimi 	int ret;
1082*287e80b3SSadaf Ebrahimi 
1083*287e80b3SSadaf Ebrahimi 	while (*(volatile bool *)keep_going) {
1084*287e80b3SSadaf Ebrahimi 		int r;
1085*287e80b3SSadaf Ebrahimi 		ret = read(in_fd, buf, BUFSIZ);
1086*287e80b3SSadaf Ebrahimi 		if (ret <= 0)
1087*287e80b3SSadaf Ebrahimi 			break;
1088*287e80b3SSadaf Ebrahimi 		r = ret;
1089*287e80b3SSadaf Ebrahimi 		ret = write(out_fd, buf, r);
1090*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1091*287e80b3SSadaf Ebrahimi 			break;
1092*287e80b3SSadaf Ebrahimi 		bread += ret;
1093*287e80b3SSadaf Ebrahimi 		/*
1094*287e80b3SSadaf Ebrahimi 		 * If the write does a partial write, then
1095*287e80b3SSadaf Ebrahimi 		 * the iteration should stop. This can happen if
1096*287e80b3SSadaf Ebrahimi 		 * the destination file system ran out of disk space.
1097*287e80b3SSadaf Ebrahimi 		 * Sure, it probably lost a little from the read
1098*287e80b3SSadaf Ebrahimi 		 * but there's not much more that can be
1099*287e80b3SSadaf Ebrahimi 		 * done. Just return what was transferred.
1100*287e80b3SSadaf Ebrahimi 		 */
1101*287e80b3SSadaf Ebrahimi 		if (ret < r)
1102*287e80b3SSadaf Ebrahimi 			break;
1103*287e80b3SSadaf Ebrahimi 	}
1104*287e80b3SSadaf Ebrahimi 
1105*287e80b3SSadaf Ebrahimi 	if (ret < 0 && (errno == EAGAIN || errno == EINTR))
1106*287e80b3SSadaf Ebrahimi 		ret = 0;
1107*287e80b3SSadaf Ebrahimi 
1108*287e80b3SSadaf Ebrahimi 	return ret < 0 ? ret : bread;
1109*287e80b3SSadaf Ebrahimi }
1110*287e80b3SSadaf Ebrahimi 
1111*287e80b3SSadaf Ebrahimi static bool top_pipe_keep_going;
1112*287e80b3SSadaf Ebrahimi 
1113*287e80b3SSadaf Ebrahimi /**
1114*287e80b3SSadaf Ebrahimi  * tracefs_trace_pipe_stream - redirect the stream of trace data to an output
1115*287e80b3SSadaf Ebrahimi  * file. The "splice" system call is used to moves the data without copying
1116*287e80b3SSadaf Ebrahimi  * between kernel address space and user address space. The user can interrupt
1117*287e80b3SSadaf Ebrahimi  * the streaming of the data by pressing Ctrl-c.
1118*287e80b3SSadaf Ebrahimi  * @fd: The file descriptor of the output file.
1119*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
1120*287e80b3SSadaf Ebrahimi  * @flags: flags for opening the trace_pipe file.
1121*287e80b3SSadaf Ebrahimi  *
1122*287e80b3SSadaf Ebrahimi  * Returns -1 in case of an error or number of bytes transferred otherwise.
1123*287e80b3SSadaf Ebrahimi  */
tracefs_trace_pipe_stream(int fd,struct tracefs_instance * instance,int flags)1124*287e80b3SSadaf Ebrahimi ssize_t tracefs_trace_pipe_stream(int fd, struct tracefs_instance *instance,
1125*287e80b3SSadaf Ebrahimi 				 int flags)
1126*287e80b3SSadaf Ebrahimi {
1127*287e80b3SSadaf Ebrahimi 	bool *keep_going = instance ? &instance->pipe_keep_going :
1128*287e80b3SSadaf Ebrahimi 				      &top_pipe_keep_going;
1129*287e80b3SSadaf Ebrahimi 	const char *file = "trace_pipe";
1130*287e80b3SSadaf Ebrahimi 	int brass[2], in_fd, ret = -1;
1131*287e80b3SSadaf Ebrahimi 	int sflags = flags & O_NONBLOCK ? SPLICE_F_NONBLOCK : 0;
1132*287e80b3SSadaf Ebrahimi 	off_t data_size;
1133*287e80b3SSadaf Ebrahimi 	ssize_t bread = 0;
1134*287e80b3SSadaf Ebrahimi 
1135*287e80b3SSadaf Ebrahimi 	(*(volatile bool *)keep_going) = true;
1136*287e80b3SSadaf Ebrahimi 
1137*287e80b3SSadaf Ebrahimi 	in_fd = tracefs_instance_file_open(instance, file, O_RDONLY | flags);
1138*287e80b3SSadaf Ebrahimi 	if (in_fd < 0) {
1139*287e80b3SSadaf Ebrahimi 		tracefs_warning("Failed to open 'trace_pipe'.");
1140*287e80b3SSadaf Ebrahimi 		return ret;
1141*287e80b3SSadaf Ebrahimi 	}
1142*287e80b3SSadaf Ebrahimi 
1143*287e80b3SSadaf Ebrahimi 	if(pipe(brass) < 0) {
1144*287e80b3SSadaf Ebrahimi 		tracefs_warning("Failed to open pipe.");
1145*287e80b3SSadaf Ebrahimi 		goto close_file;
1146*287e80b3SSadaf Ebrahimi 	}
1147*287e80b3SSadaf Ebrahimi 
1148*287e80b3SSadaf Ebrahimi 	data_size = fcntl(brass[0], F_GETPIPE_SZ);
1149*287e80b3SSadaf Ebrahimi 	if (data_size <= 0) {
1150*287e80b3SSadaf Ebrahimi 		tracefs_warning("Failed to open pipe (size=0).");
1151*287e80b3SSadaf Ebrahimi 		goto close_all;
1152*287e80b3SSadaf Ebrahimi 	}
1153*287e80b3SSadaf Ebrahimi 
1154*287e80b3SSadaf Ebrahimi 	/* Test if the output is splice safe */
1155*287e80b3SSadaf Ebrahimi 	if (!splice_safe(fd, brass[0])) {
1156*287e80b3SSadaf Ebrahimi 		bread = read_trace_pipe(keep_going, in_fd, fd);
1157*287e80b3SSadaf Ebrahimi 		ret = 0; /* Force return of bread */
1158*287e80b3SSadaf Ebrahimi 		goto close_all;
1159*287e80b3SSadaf Ebrahimi 	}
1160*287e80b3SSadaf Ebrahimi 
1161*287e80b3SSadaf Ebrahimi 	errno = 0;
1162*287e80b3SSadaf Ebrahimi 
1163*287e80b3SSadaf Ebrahimi 	while (*(volatile bool *)keep_going) {
1164*287e80b3SSadaf Ebrahimi 		ret = splice(in_fd, NULL,
1165*287e80b3SSadaf Ebrahimi 			     brass[1], NULL,
1166*287e80b3SSadaf Ebrahimi 			     data_size, sflags);
1167*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1168*287e80b3SSadaf Ebrahimi 			break;
1169*287e80b3SSadaf Ebrahimi 
1170*287e80b3SSadaf Ebrahimi 		ret = splice(brass[0], NULL,
1171*287e80b3SSadaf Ebrahimi 			     fd, NULL,
1172*287e80b3SSadaf Ebrahimi 			     data_size, sflags);
1173*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1174*287e80b3SSadaf Ebrahimi 			break;
1175*287e80b3SSadaf Ebrahimi 		bread += ret;
1176*287e80b3SSadaf Ebrahimi 	}
1177*287e80b3SSadaf Ebrahimi 
1178*287e80b3SSadaf Ebrahimi 	/*
1179*287e80b3SSadaf Ebrahimi 	 * Do not return error in the case when the "splice" system call
1180*287e80b3SSadaf Ebrahimi 	 * was interrupted by the user (pressing Ctrl-c).
1181*287e80b3SSadaf Ebrahimi 	 * Or if NONBLOCK was specified.
1182*287e80b3SSadaf Ebrahimi 	 */
1183*287e80b3SSadaf Ebrahimi 	if (!keep_going || errno == EAGAIN || errno == EINTR)
1184*287e80b3SSadaf Ebrahimi 		ret = 0;
1185*287e80b3SSadaf Ebrahimi 
1186*287e80b3SSadaf Ebrahimi  close_all:
1187*287e80b3SSadaf Ebrahimi 	close(brass[0]);
1188*287e80b3SSadaf Ebrahimi 	close(brass[1]);
1189*287e80b3SSadaf Ebrahimi  close_file:
1190*287e80b3SSadaf Ebrahimi 	close(in_fd);
1191*287e80b3SSadaf Ebrahimi 
1192*287e80b3SSadaf Ebrahimi 	return ret ? ret : bread;
1193*287e80b3SSadaf Ebrahimi }
1194*287e80b3SSadaf Ebrahimi 
1195*287e80b3SSadaf Ebrahimi /**
1196*287e80b3SSadaf Ebrahimi  * tracefs_trace_pipe_print - redirect the stream of trace data to "stdout".
1197*287e80b3SSadaf Ebrahimi  * The "splice" system call is used to moves the data without copying
1198*287e80b3SSadaf Ebrahimi  * between kernel address space and user address space.
1199*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
1200*287e80b3SSadaf Ebrahimi  * @flags: flags for opening the trace_pipe file.
1201*287e80b3SSadaf Ebrahimi  *
1202*287e80b3SSadaf Ebrahimi  * Returns -1 in case of an error or number of bytes transferred otherwise.
1203*287e80b3SSadaf Ebrahimi  */
1204*287e80b3SSadaf Ebrahimi 
tracefs_trace_pipe_print(struct tracefs_instance * instance,int flags)1205*287e80b3SSadaf Ebrahimi ssize_t tracefs_trace_pipe_print(struct tracefs_instance *instance, int flags)
1206*287e80b3SSadaf Ebrahimi {
1207*287e80b3SSadaf Ebrahimi 	return tracefs_trace_pipe_stream(STDOUT_FILENO, instance, flags);
1208*287e80b3SSadaf Ebrahimi }
1209*287e80b3SSadaf Ebrahimi 
1210*287e80b3SSadaf Ebrahimi /**
1211*287e80b3SSadaf Ebrahimi  * tracefs_trace_pipe_stop - stop the streaming of trace data.
1212*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
1213*287e80b3SSadaf Ebrahimi  */
tracefs_trace_pipe_stop(struct tracefs_instance * instance)1214*287e80b3SSadaf Ebrahimi void tracefs_trace_pipe_stop(struct tracefs_instance *instance)
1215*287e80b3SSadaf Ebrahimi {
1216*287e80b3SSadaf Ebrahimi 	if (instance)
1217*287e80b3SSadaf Ebrahimi 		instance->pipe_keep_going = false;
1218*287e80b3SSadaf Ebrahimi 	else
1219*287e80b3SSadaf Ebrahimi 		top_pipe_keep_going = false;
1220*287e80b3SSadaf Ebrahimi }
1221*287e80b3SSadaf Ebrahimi 
1222*287e80b3SSadaf Ebrahimi /**
1223*287e80b3SSadaf Ebrahimi  * tracefs_filter_functions - return a list of available functons that can be filtered
1224*287e80b3SSadaf Ebrahimi  * @filter: The filter to filter what functions to list (can be NULL for all)
1225*287e80b3SSadaf Ebrahimi  * @module: Module to be traced or NULL if all functions are to be examined.
1226*287e80b3SSadaf Ebrahimi  * @list: The list to return the list from (freed by tracefs_list_free() on success)
1227*287e80b3SSadaf Ebrahimi  *
1228*287e80b3SSadaf Ebrahimi  * Returns a list of function names that match @filter and @module. If both
1229*287e80b3SSadaf Ebrahimi  * @filter and @module is NULL, then all available functions that can be filtered
1230*287e80b3SSadaf Ebrahimi  * will be returned. (Note, there can be duplicates, if there are more than
1231*287e80b3SSadaf Ebrahimi  * one function with the same name.
1232*287e80b3SSadaf Ebrahimi  *
1233*287e80b3SSadaf Ebrahimi  * On success, zero is returned, and @list contains a list of functions that were
1234*287e80b3SSadaf Ebrahimi  * found, and must be freed with tracefs_list_free().
1235*287e80b3SSadaf Ebrahimi  * On failure, a negative number is returned, and @list is ignored.
1236*287e80b3SSadaf Ebrahimi  */
tracefs_filter_functions(const char * filter,const char * module,char *** list)1237*287e80b3SSadaf Ebrahimi int tracefs_filter_functions(const char *filter, const char *module, char ***list)
1238*287e80b3SSadaf Ebrahimi {
1239*287e80b3SSadaf Ebrahimi 	struct func_filter func_filter;
1240*287e80b3SSadaf Ebrahimi 	struct func_list *func_list = NULL, *f;
1241*287e80b3SSadaf Ebrahimi 	char **funcs = NULL;
1242*287e80b3SSadaf Ebrahimi 	int ret;
1243*287e80b3SSadaf Ebrahimi 
1244*287e80b3SSadaf Ebrahimi 	if (!filter)
1245*287e80b3SSadaf Ebrahimi 		filter = ".*";
1246*287e80b3SSadaf Ebrahimi 
1247*287e80b3SSadaf Ebrahimi 	ret = init_func_filter(&func_filter, filter);
1248*287e80b3SSadaf Ebrahimi 	if (ret < 0)
1249*287e80b3SSadaf Ebrahimi 		return ret;
1250*287e80b3SSadaf Ebrahimi 
1251*287e80b3SSadaf Ebrahimi 	ret = list_available_filters(&func_filter, module, &func_list);
1252*287e80b3SSadaf Ebrahimi 	if (ret < 0)
1253*287e80b3SSadaf Ebrahimi 		goto out;
1254*287e80b3SSadaf Ebrahimi 
1255*287e80b3SSadaf Ebrahimi 	ret = -1;
1256*287e80b3SSadaf Ebrahimi 	for (f = func_list; f; f = f->next) {
1257*287e80b3SSadaf Ebrahimi 		char **tmp;
1258*287e80b3SSadaf Ebrahimi 
1259*287e80b3SSadaf Ebrahimi 		tmp = tracefs_list_add(funcs, f->func);
1260*287e80b3SSadaf Ebrahimi 		if (!tmp) {
1261*287e80b3SSadaf Ebrahimi 			tracefs_list_free(funcs);
1262*287e80b3SSadaf Ebrahimi 			goto out;
1263*287e80b3SSadaf Ebrahimi 		}
1264*287e80b3SSadaf Ebrahimi 		funcs = tmp;
1265*287e80b3SSadaf Ebrahimi 	}
1266*287e80b3SSadaf Ebrahimi 
1267*287e80b3SSadaf Ebrahimi 	*list = funcs;
1268*287e80b3SSadaf Ebrahimi 	ret = 0;
1269*287e80b3SSadaf Ebrahimi out:
1270*287e80b3SSadaf Ebrahimi 	regfree(&func_filter.re);
1271*287e80b3SSadaf Ebrahimi 	free_func_list(func_list);
1272*287e80b3SSadaf Ebrahimi 	return ret;
1273*287e80b3SSadaf Ebrahimi }
1274