1919#include <ctype.h>
2020#include <linux/capability.h>
2121#include <linux/string.h>
22+ #include <sys/stat.h>
2223
2324#include "debug.h"
2425#include <subcmd/pager.h>
@@ -45,6 +46,8 @@ static volatile sig_atomic_t done;
4546
4647static struct stats latency_stats ; /* for tracepoints */
4748
49+ static char tracing_instance [PATH_MAX ]; /* Trace instance directory */
50+
4851static void sig_handler (int sig __maybe_unused )
4952{
5053 done = true;
@@ -100,6 +103,34 @@ static bool is_ftrace_supported(void)
100103 return supported ;
101104}
102105
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+
103134static int __write_tracing_file (const char * name , const char * val , bool append )
104135{
105136 char * file ;
@@ -109,7 +140,7 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
109140 char errbuf [512 ];
110141 char * val_copy ;
111142
112- file = get_tracing_file (name );
143+ file = get_tracing_instance_file (name );
113144 if (!file ) {
114145 pr_debug ("cannot get tracing file: %s\n" , name );
115146 return -1 ;
@@ -167,7 +198,7 @@ static int read_tracing_file_to_stdout(const char *name)
167198 int fd ;
168199 int ret = -1 ;
169200
170- file = get_tracing_file (name );
201+ file = get_tracing_instance_file (name );
171202 if (!file ) {
172203 pr_debug ("cannot get tracing file: %s\n" , name );
173204 return -1 ;
@@ -209,7 +240,7 @@ static int read_tracing_file_by_line(const char *name,
209240 char * file ;
210241 FILE * fp ;
211242
212- file = get_tracing_file (name );
243+ file = get_tracing_instance_file (name );
213244 if (!file ) {
214245 pr_debug ("cannot get tracing file: %s\n" , name );
215246 return -1 ;
@@ -299,6 +330,39 @@ static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
299330 return 0 ;
300331}
301332
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+
302366static int set_tracing_pid (struct perf_ftrace * ftrace )
303367{
304368 int i ;
@@ -629,14 +693,17 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace)
629693
630694 select_tracer (ftrace );
631695
696+ if (init_tracing_instance () < 0 )
697+ goto out ;
698+
632699 if (reset_tracing_files (ftrace ) < 0 ) {
633700 pr_err ("failed to reset ftrace\n" );
634- goto out ;
701+ goto out_reset ;
635702 }
636703
637704 /* reset ftrace buffer */
638705 if (write_tracing_file ("trace" , "0" ) < 0 )
639- goto out ;
706+ goto out_reset ;
640707
641708 if (set_tracing_options (ftrace ) < 0 )
642709 goto out_reset ;
@@ -648,7 +715,7 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace)
648715
649716 setup_pager ();
650717
651- trace_file = get_tracing_file ("trace_pipe" );
718+ trace_file = get_tracing_instance_file ("trace_pipe" );
652719 if (!trace_file ) {
653720 pr_err ("failed to open trace_pipe\n" );
654721 goto out_reset ;
@@ -723,7 +790,7 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace)
723790out_close_fd :
724791 close (trace_fd );
725792out_reset :
726- reset_tracing_files ( ftrace );
793+ exit_tracing_instance ( );
727794out :
728795 return (done && !workload_exec_errno ) ? 0 : -1 ;
729796}
@@ -924,6 +991,9 @@ static int prepare_func_latency(struct perf_ftrace *ftrace)
924991 if (ftrace -> target .use_bpf )
925992 return perf_ftrace__latency_prepare_bpf (ftrace );
926993
994+ if (init_tracing_instance () < 0 )
995+ return -1 ;
996+
927997 if (reset_tracing_files (ftrace ) < 0 ) {
928998 pr_err ("failed to reset ftrace\n" );
929999 return -1 ;
@@ -942,7 +1012,7 @@ static int prepare_func_latency(struct perf_ftrace *ftrace)
9421012 return -1 ;
9431013 }
9441014
945- trace_file = get_tracing_file ("trace_pipe" );
1015+ trace_file = get_tracing_instance_file ("trace_pipe" );
9461016 if (!trace_file ) {
9471017 pr_err ("failed to open trace_pipe\n" );
9481018 return -1 ;
@@ -993,7 +1063,7 @@ static int cleanup_func_latency(struct perf_ftrace *ftrace)
9931063 if (ftrace -> target .use_bpf )
9941064 return perf_ftrace__latency_cleanup_bpf (ftrace );
9951065
996- reset_tracing_files ( ftrace );
1066+ exit_tracing_instance ( );
9971067 return 0 ;
9981068}
9991069
@@ -1304,17 +1374,20 @@ static int __cmd_profile(struct perf_ftrace *ftrace)
13041374 goto out ;
13051375 }
13061376
1377+ if (init_tracing_instance () < 0 )
1378+ goto out ;
1379+
13071380 if (reset_tracing_files (ftrace ) < 0 ) {
13081381 pr_err ("failed to reset ftrace\n" );
1309- goto out ;
1382+ goto out_reset ;
13101383 }
13111384
13121385 /* reset ftrace buffer */
13131386 if (write_tracing_file ("trace" , "0" ) < 0 )
1314- goto out ;
1387+ goto out_reset ;
13151388
13161389 if (set_tracing_options (ftrace ) < 0 )
1317- return -1 ;
1390+ goto out_reset ;
13181391
13191392 if (write_tracing_file ("current_tracer" , ftrace -> tracer ) < 0 ) {
13201393 pr_err ("failed to set current_tracer to %s\n" , ftrace -> tracer );
@@ -1323,7 +1396,7 @@ static int __cmd_profile(struct perf_ftrace *ftrace)
13231396
13241397 setup_pager ();
13251398
1326- trace_file = get_tracing_file ("trace_pipe" );
1399+ trace_file = get_tracing_instance_file ("trace_pipe" );
13271400 if (!trace_file ) {
13281401 pr_err ("failed to open trace_pipe\n" );
13291402 goto out_reset ;
@@ -1385,7 +1458,7 @@ static int __cmd_profile(struct perf_ftrace *ftrace)
13851458out_close_fd :
13861459 close (trace_fd );
13871460out_reset :
1388- reset_tracing_files ( ftrace );
1461+ exit_tracing_instance ( );
13891462out :
13901463 return (done && !workload_exec_errno ) ? 0 : -1 ;
13911464}
0 commit comments