19
19
#include <ctype.h>
20
20
#include <linux/capability.h>
21
21
#include <linux/string.h>
22
+ #include <sys/stat.h>
22
23
23
24
#include "debug.h"
24
25
#include <subcmd/pager.h>
@@ -45,6 +46,8 @@ static volatile sig_atomic_t done;
45
46
46
47
static struct stats latency_stats ; /* for tracepoints */
47
48
49
+ static char tracing_instance [PATH_MAX ]; /* Trace instance directory */
50
+
48
51
static void sig_handler (int sig __maybe_unused )
49
52
{
50
53
done = true;
@@ -100,6 +103,34 @@ static bool is_ftrace_supported(void)
100
103
return supported ;
101
104
}
102
105
106
+ /*
107
+ * Wrapper to test if a file in directory .../tracing/instances/XXX
108
+ * exists. If so return the .../tracing/instances/XXX file for use.
109
+ * Otherwise the file exists only in directory .../tracing and
110
+ * is applicable to all instances, for example file available_filter_functions.
111
+ * Return that file name in this case.
112
+ *
113
+ * This functions works similar to get_tracing_file() and expects its caller
114
+ * to free the returned file name.
115
+ *
116
+ * The global variable tracing_instance is set in init_tracing_instance()
117
+ * called at the beginning to a process specific tracing subdirectory.
118
+ */
119
+ static char * get_tracing_instance_file (const char * name )
120
+ {
121
+ char * file ;
122
+
123
+ if (asprintf (& file , "%s/%s" , tracing_instance , name ) < 0 )
124
+ return NULL ;
125
+
126
+ if (!access (file , F_OK ))
127
+ return file ;
128
+
129
+ free (file );
130
+ file = get_tracing_file (name );
131
+ return file ;
132
+ }
133
+
103
134
static int __write_tracing_file (const char * name , const char * val , bool append )
104
135
{
105
136
char * file ;
@@ -109,7 +140,7 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
109
140
char errbuf [512 ];
110
141
char * val_copy ;
111
142
112
- file = get_tracing_file (name );
143
+ file = get_tracing_instance_file (name );
113
144
if (!file ) {
114
145
pr_debug ("cannot get tracing file: %s\n" , name );
115
146
return -1 ;
@@ -167,7 +198,7 @@ static int read_tracing_file_to_stdout(const char *name)
167
198
int fd ;
168
199
int ret = -1 ;
169
200
170
- file = get_tracing_file (name );
201
+ file = get_tracing_instance_file (name );
171
202
if (!file ) {
172
203
pr_debug ("cannot get tracing file: %s\n" , name );
173
204
return -1 ;
@@ -209,7 +240,7 @@ static int read_tracing_file_by_line(const char *name,
209
240
char * file ;
210
241
FILE * fp ;
211
242
212
- file = get_tracing_file (name );
243
+ file = get_tracing_instance_file (name );
213
244
if (!file ) {
214
245
pr_debug ("cannot get tracing file: %s\n" , name );
215
246
return -1 ;
@@ -299,6 +330,39 @@ static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
299
330
return 0 ;
300
331
}
301
332
333
+ /* Remove .../tracing/instances/XXX subdirectory created with
334
+ * init_tracing_instance().
335
+ */
336
+ static void exit_tracing_instance (void )
337
+ {
338
+ if (rmdir (tracing_instance ))
339
+ pr_err ("failed to delete tracing/instances directory\n" );
340
+ }
341
+
342
+ /* Create subdirectory within .../tracing/instances/XXX to have session
343
+ * or process specific setup. To delete this setup, simply remove the
344
+ * subdirectory.
345
+ */
346
+ static int init_tracing_instance (void )
347
+ {
348
+ char dirname [] = "instances/perf-ftrace-XXXXXX" ;
349
+ char * path ;
350
+
351
+ path = get_tracing_file (dirname );
352
+ if (!path )
353
+ goto error ;
354
+ strncpy (tracing_instance , path , sizeof (tracing_instance ) - 1 );
355
+ put_tracing_file (path );
356
+ path = mkdtemp (tracing_instance );
357
+ if (!path )
358
+ goto error ;
359
+ return 0 ;
360
+
361
+ error :
362
+ pr_err ("failed to create tracing/instances directory\n" );
363
+ return -1 ;
364
+ }
365
+
302
366
static int set_tracing_pid (struct perf_ftrace * ftrace )
303
367
{
304
368
int i ;
@@ -629,14 +693,17 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace)
629
693
630
694
select_tracer (ftrace );
631
695
696
+ if (init_tracing_instance () < 0 )
697
+ goto out ;
698
+
632
699
if (reset_tracing_files (ftrace ) < 0 ) {
633
700
pr_err ("failed to reset ftrace\n" );
634
- goto out ;
701
+ goto out_reset ;
635
702
}
636
703
637
704
/* reset ftrace buffer */
638
705
if (write_tracing_file ("trace" , "0" ) < 0 )
639
- goto out ;
706
+ goto out_reset ;
640
707
641
708
if (set_tracing_options (ftrace ) < 0 )
642
709
goto out_reset ;
@@ -648,7 +715,7 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace)
648
715
649
716
setup_pager ();
650
717
651
- trace_file = get_tracing_file ("trace_pipe" );
718
+ trace_file = get_tracing_instance_file ("trace_pipe" );
652
719
if (!trace_file ) {
653
720
pr_err ("failed to open trace_pipe\n" );
654
721
goto out_reset ;
@@ -723,7 +790,7 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace)
723
790
out_close_fd :
724
791
close (trace_fd );
725
792
out_reset :
726
- reset_tracing_files ( ftrace );
793
+ exit_tracing_instance ( );
727
794
out :
728
795
return (done && !workload_exec_errno ) ? 0 : -1 ;
729
796
}
@@ -924,6 +991,9 @@ static int prepare_func_latency(struct perf_ftrace *ftrace)
924
991
if (ftrace -> target .use_bpf )
925
992
return perf_ftrace__latency_prepare_bpf (ftrace );
926
993
994
+ if (init_tracing_instance () < 0 )
995
+ return -1 ;
996
+
927
997
if (reset_tracing_files (ftrace ) < 0 ) {
928
998
pr_err ("failed to reset ftrace\n" );
929
999
return -1 ;
@@ -942,7 +1012,7 @@ static int prepare_func_latency(struct perf_ftrace *ftrace)
942
1012
return -1 ;
943
1013
}
944
1014
945
- trace_file = get_tracing_file ("trace_pipe" );
1015
+ trace_file = get_tracing_instance_file ("trace_pipe" );
946
1016
if (!trace_file ) {
947
1017
pr_err ("failed to open trace_pipe\n" );
948
1018
return -1 ;
@@ -993,7 +1063,7 @@ static int cleanup_func_latency(struct perf_ftrace *ftrace)
993
1063
if (ftrace -> target .use_bpf )
994
1064
return perf_ftrace__latency_cleanup_bpf (ftrace );
995
1065
996
- reset_tracing_files ( ftrace );
1066
+ exit_tracing_instance ( );
997
1067
return 0 ;
998
1068
}
999
1069
@@ -1304,17 +1374,20 @@ static int __cmd_profile(struct perf_ftrace *ftrace)
1304
1374
goto out ;
1305
1375
}
1306
1376
1377
+ if (init_tracing_instance () < 0 )
1378
+ goto out ;
1379
+
1307
1380
if (reset_tracing_files (ftrace ) < 0 ) {
1308
1381
pr_err ("failed to reset ftrace\n" );
1309
- goto out ;
1382
+ goto out_reset ;
1310
1383
}
1311
1384
1312
1385
/* reset ftrace buffer */
1313
1386
if (write_tracing_file ("trace" , "0" ) < 0 )
1314
- goto out ;
1387
+ goto out_reset ;
1315
1388
1316
1389
if (set_tracing_options (ftrace ) < 0 )
1317
- return -1 ;
1390
+ goto out_reset ;
1318
1391
1319
1392
if (write_tracing_file ("current_tracer" , ftrace -> tracer ) < 0 ) {
1320
1393
pr_err ("failed to set current_tracer to %s\n" , ftrace -> tracer );
@@ -1323,7 +1396,7 @@ static int __cmd_profile(struct perf_ftrace *ftrace)
1323
1396
1324
1397
setup_pager ();
1325
1398
1326
- trace_file = get_tracing_file ("trace_pipe" );
1399
+ trace_file = get_tracing_instance_file ("trace_pipe" );
1327
1400
if (!trace_file ) {
1328
1401
pr_err ("failed to open trace_pipe\n" );
1329
1402
goto out_reset ;
@@ -1385,7 +1458,7 @@ static int __cmd_profile(struct perf_ftrace *ftrace)
1385
1458
out_close_fd :
1386
1459
close (trace_fd );
1387
1460
out_reset :
1388
- reset_tracing_files ( ftrace );
1461
+ exit_tracing_instance ( );
1389
1462
out :
1390
1463
return (done && !workload_exec_errno ) ? 0 : -1 ;
1391
1464
}
0 commit comments