4747#include <linux/time64.h>
4848
4949struct switch_output {
50+ bool enabled ;
5051 bool signal ;
52+ unsigned long size ;
5153 const char * str ;
5254 bool set ;
5355};
@@ -72,6 +74,23 @@ struct record {
7274 unsigned long long samples ;
7375};
7476
77+ static volatile int auxtrace_record__snapshot_started ;
78+ static DEFINE_TRIGGER (auxtrace_snapshot_trigger );
79+ static DEFINE_TRIGGER (switch_output_trigger );
80+
81+ static bool switch_output_signal (struct record * rec )
82+ {
83+ return rec -> switch_output .signal &&
84+ trigger_is_ready (& switch_output_trigger );
85+ }
86+
87+ static bool switch_output_size (struct record * rec )
88+ {
89+ return rec -> switch_output .size &&
90+ trigger_is_ready (& switch_output_trigger ) &&
91+ (rec -> bytes_written >= rec -> switch_output .size );
92+ }
93+
7594static int record__write (struct record * rec , void * bf , size_t size )
7695{
7796 if (perf_data_file__write (rec -> session -> file , bf , size ) < 0 ) {
@@ -80,6 +99,10 @@ static int record__write(struct record *rec, void *bf, size_t size)
8099 }
81100
82101 rec -> bytes_written += size ;
102+
103+ if (switch_output_size (rec ))
104+ trigger_hit (& switch_output_trigger );
105+
83106 return 0 ;
84107}
85108
@@ -199,10 +222,6 @@ static volatile int done;
199222static volatile int signr = -1 ;
200223static volatile int child_finished ;
201224
202- static volatile int auxtrace_record__snapshot_started ;
203- static DEFINE_TRIGGER (auxtrace_snapshot_trigger );
204- static DEFINE_TRIGGER (switch_output_trigger );
205-
206225static void sig_handler (int sig )
207226{
208227 if (sig == SIGCHLD )
@@ -848,11 +867,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
848867 signal (SIGTERM , sig_handler );
849868 signal (SIGSEGV , sigsegv_handler );
850869
851- if (rec -> opts .auxtrace_snapshot_mode || rec -> switch_output .signal ) {
870+ if (rec -> opts .auxtrace_snapshot_mode || rec -> switch_output .enabled ) {
852871 signal (SIGUSR2 , snapshot_sig_handler );
853872 if (rec -> opts .auxtrace_snapshot_mode )
854873 trigger_on (& auxtrace_snapshot_trigger );
855- if (rec -> switch_output .signal )
874+ if (rec -> switch_output .enabled )
856875 trigger_on (& switch_output_trigger );
857876 } else {
858877 signal (SIGUSR2 , SIG_IGN );
@@ -1361,17 +1380,37 @@ static int record__parse_mmap_pages(const struct option *opt,
13611380static int switch_output_setup (struct record * rec )
13621381{
13631382 struct switch_output * s = & rec -> switch_output ;
1383+ static struct parse_tag tags_size [] = {
1384+ { .tag = 'B' , .mult = 1 },
1385+ { .tag = 'K' , .mult = 1 << 10 },
1386+ { .tag = 'M' , .mult = 1 << 20 },
1387+ { .tag = 'G' , .mult = 1 << 30 },
1388+ { .tag = 0 },
1389+ };
1390+ unsigned long val ;
13641391
13651392 if (!s -> set )
13661393 return 0 ;
13671394
13681395 if (!strcmp (s -> str , "signal" )) {
13691396 s -> signal = true;
13701397 pr_debug ("switch-output with SIGUSR2 signal\n" );
1371- return 0 ;
1398+ goto enabled ;
1399+ }
1400+
1401+ val = parse_tag_value (s -> str , tags_size );
1402+ if (val != (unsigned long ) -1 ) {
1403+ s -> size = val ;
1404+ pr_debug ("switch-output with %s size threshold\n" , s -> str );
1405+ goto enabled ;
13721406 }
13731407
13741408 return -1 ;
1409+
1410+ enabled :
1411+ rec -> timestamp_filename = true;
1412+ s -> enabled = true;
1413+ return 0 ;
13751414}
13761415
13771416static const char * const __record_usage [] = {
@@ -1542,8 +1581,9 @@ static struct option __record_options[] = {
15421581 OPT_BOOLEAN (0 , "timestamp-filename" , & record .timestamp_filename ,
15431582 "append timestamp to output filename" ),
15441583 OPT_STRING_OPTARG_SET (0 , "switch-output" , & record .switch_output .str ,
1545- & record .switch_output .set , "signal" ,
1546- "Switch output when receive SIGUSR2" , "signal" ),
1584+ & record .switch_output .set , "signal,size" ,
1585+ "Switch output when receive SIGUSR2 or cross size threshold" ,
1586+ "signal" ),
15471587 OPT_BOOLEAN (0 , "dry-run" , & dry_run ,
15481588 "Parse options then exit" ),
15491589 OPT_END ()
@@ -1606,9 +1646,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
16061646 return - EINVAL ;
16071647 }
16081648
1609- if (rec -> switch_output .signal )
1610- rec -> timestamp_filename = true;
1611-
16121649 if (!rec -> itr ) {
16131650 rec -> itr = auxtrace_record__init (rec -> evlist , & err );
16141651 if (err )
@@ -1657,7 +1694,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
16571694
16581695 if (rec -> no_buildid_cache || rec -> no_buildid ) {
16591696 disable_buildid_cache ();
1660- } else if (rec -> switch_output .signal ) {
1697+ } else if (rec -> switch_output .enabled ) {
16611698 /*
16621699 * In 'perf record --switch-output', disable buildid
16631700 * generation by default to reduce data file switching
@@ -1749,13 +1786,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
17491786
17501787static void snapshot_sig_handler (int sig __maybe_unused )
17511788{
1789+ struct record * rec = & record ;
1790+
17521791 if (trigger_is_ready (& auxtrace_snapshot_trigger )) {
17531792 trigger_hit (& auxtrace_snapshot_trigger );
17541793 auxtrace_record__snapshot_started = 1 ;
17551794 if (auxtrace_record__snapshot_start (record .itr ))
17561795 trigger_error (& auxtrace_snapshot_trigger );
17571796 }
17581797
1759- if (trigger_is_ready ( & switch_output_trigger ))
1798+ if (switch_output_signal ( rec ))
17601799 trigger_hit (& switch_output_trigger );
17611800}
0 commit comments