Commit ce7b0e42 authored by Alexander Shishkin's avatar Alexander Shishkin Committed by Arnaldo Carvalho de Melo

perf record: Add an option to take an AUX snapshot on exit

It is sometimes useful to generate a snapshot when perf record exits;
I've been using a wrapper script around the workload that would do a
killall -USR2 perf when the workload exits.

This patch makes it easier and also works when perf record is attached
to a pre-existing task. A new snapshot option 'e' can be specified in
-S to enable this behavior:

root@elsewhere:~# perf record -e intel_pt// -Se sleep 1
[ perf record: Woken up 2 times to write data ]
[ perf record: Captured and wrote 0.085 MB perf.data ]
Co-developed-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Signed-off-by: default avatarAlexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20190806144101.62892-1-alexander.shishkin@linux.intel.com
[ Fixed up !HAVE_AUXTRACE_SUPPORT build in builtin-record.c, adding 2 missing __maybe_unused ]
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 73e5de70
...@@ -422,9 +422,14 @@ CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI. ...@@ -422,9 +422,14 @@ CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI.
-S:: -S::
--snapshot:: --snapshot::
Select AUX area tracing Snapshot Mode. This option is valid only with an Select AUX area tracing Snapshot Mode. This option is valid only with an
AUX area tracing event. Optionally the number of bytes to capture per AUX area tracing event. Optionally, certain snapshot capturing parameters
snapshot can be specified. In Snapshot Mode, trace data is captured only when can be specified in a string that follows this option:
signal SIGUSR2 is received. 'e': take one last snapshot on exit; guarantees that there is at least one
snapshot in the output file;
<size>: if the PMU supports this, specify the desired snapshot size.
In Snapshot Mode trace data is captured only when signal SIGUSR2 is received
and on exit if the above 'e' option is given.
--proc-map-timeout:: --proc-map-timeout::
When processing pre-existing threads /proc/XXX/mmap, it may take a long time, When processing pre-existing threads /proc/XXX/mmap, it may take a long time,
......
...@@ -613,19 +613,35 @@ static int record__auxtrace_read_snapshot_all(struct record *rec) ...@@ -613,19 +613,35 @@ static int record__auxtrace_read_snapshot_all(struct record *rec)
return rc; return rc;
} }
static void record__read_auxtrace_snapshot(struct record *rec) static void record__read_auxtrace_snapshot(struct record *rec, bool on_exit)
{ {
pr_debug("Recording AUX area tracing snapshot\n"); pr_debug("Recording AUX area tracing snapshot\n");
if (record__auxtrace_read_snapshot_all(rec) < 0) { if (record__auxtrace_read_snapshot_all(rec) < 0) {
trigger_error(&auxtrace_snapshot_trigger); trigger_error(&auxtrace_snapshot_trigger);
} else { } else {
if (auxtrace_record__snapshot_finish(rec->itr)) if (auxtrace_record__snapshot_finish(rec->itr, on_exit))
trigger_error(&auxtrace_snapshot_trigger); trigger_error(&auxtrace_snapshot_trigger);
else else
trigger_ready(&auxtrace_snapshot_trigger); trigger_ready(&auxtrace_snapshot_trigger);
} }
} }
static int record__auxtrace_snapshot_exit(struct record *rec)
{
if (trigger_is_error(&auxtrace_snapshot_trigger))
return 0;
if (!auxtrace_record__snapshot_started &&
auxtrace_record__snapshot_start(rec->itr))
return -1;
record__read_auxtrace_snapshot(rec, true);
if (trigger_is_error(&auxtrace_snapshot_trigger))
return -1;
return 0;
}
static int record__auxtrace_init(struct record *rec) static int record__auxtrace_init(struct record *rec)
{ {
int err; int err;
...@@ -654,7 +670,8 @@ int record__auxtrace_mmap_read(struct record *rec __maybe_unused, ...@@ -654,7 +670,8 @@ int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
} }
static inline static inline
void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) void record__read_auxtrace_snapshot(struct record *rec __maybe_unused,
bool on_exit __maybe_unused)
{ {
} }
...@@ -664,6 +681,12 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) ...@@ -664,6 +681,12 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
return 0; return 0;
} }
static inline
int record__auxtrace_snapshot_exit(struct record *rec __maybe_unused)
{
return 0;
}
static int record__auxtrace_init(struct record *rec __maybe_unused) static int record__auxtrace_init(struct record *rec __maybe_unused)
{ {
return 0; return 0;
...@@ -1536,7 +1559,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) ...@@ -1536,7 +1559,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
if (auxtrace_record__snapshot_started) { if (auxtrace_record__snapshot_started) {
auxtrace_record__snapshot_started = 0; auxtrace_record__snapshot_started = 0;
if (!trigger_is_error(&auxtrace_snapshot_trigger)) if (!trigger_is_error(&auxtrace_snapshot_trigger))
record__read_auxtrace_snapshot(rec); record__read_auxtrace_snapshot(rec, false);
if (trigger_is_error(&auxtrace_snapshot_trigger)) { if (trigger_is_error(&auxtrace_snapshot_trigger)) {
pr_err("AUX area tracing snapshot failed\n"); pr_err("AUX area tracing snapshot failed\n");
err = -1; err = -1;
...@@ -1609,9 +1632,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) ...@@ -1609,9 +1632,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
disabled = true; disabled = true;
} }
} }
trigger_off(&auxtrace_snapshot_trigger); trigger_off(&auxtrace_snapshot_trigger);
trigger_off(&switch_output_trigger); trigger_off(&switch_output_trigger);
if (opts->auxtrace_snapshot_on_exit)
record__auxtrace_snapshot_exit(rec);
if (forks && workload_exec_errno) { if (forks && workload_exec_errno) {
char msg[STRERR_BUFSIZE]; char msg[STRERR_BUFSIZE];
const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
......
...@@ -57,6 +57,7 @@ struct record_opts { ...@@ -57,6 +57,7 @@ struct record_opts {
bool running_time; bool running_time;
bool full_auxtrace; bool full_auxtrace;
bool auxtrace_snapshot_mode; bool auxtrace_snapshot_mode;
bool auxtrace_snapshot_on_exit;
bool record_namespaces; bool record_namespaces;
bool record_switch_events; bool record_switch_events;
bool all_kernel; bool all_kernel;
......
...@@ -539,9 +539,9 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr) ...@@ -539,9 +539,9 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr)
return 0; return 0;
} }
int auxtrace_record__snapshot_finish(struct auxtrace_record *itr) int auxtrace_record__snapshot_finish(struct auxtrace_record *itr, bool on_exit)
{ {
if (itr && itr->snapshot_finish) if (!on_exit && itr && itr->snapshot_finish)
return itr->snapshot_finish(itr); return itr->snapshot_finish(itr);
return 0; return 0;
} }
...@@ -577,6 +577,16 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr, ...@@ -577,6 +577,16 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
if (!str) if (!str)
return 0; return 0;
/* PMU-agnostic options */
switch (*str) {
case 'e':
opts->auxtrace_snapshot_on_exit = true;
str++;
break;
default:
break;
}
if (itr) if (itr)
return itr->parse_snapshot_options(itr, opts, str); return itr->parse_snapshot_options(itr, opts, str);
......
...@@ -499,7 +499,7 @@ int auxtrace_record__info_fill(struct auxtrace_record *itr, ...@@ -499,7 +499,7 @@ int auxtrace_record__info_fill(struct auxtrace_record *itr,
size_t priv_size); size_t priv_size);
void auxtrace_record__free(struct auxtrace_record *itr); void auxtrace_record__free(struct auxtrace_record *itr);
int auxtrace_record__snapshot_start(struct auxtrace_record *itr); int auxtrace_record__snapshot_start(struct auxtrace_record *itr);
int auxtrace_record__snapshot_finish(struct auxtrace_record *itr); int auxtrace_record__snapshot_finish(struct auxtrace_record *itr, bool on_exit);
int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx, int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
struct auxtrace_mmap *mm, struct auxtrace_mmap *mm,
unsigned char *data, u64 *head, u64 *old); unsigned char *data, u64 *head, u64 *old);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment