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