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