|
@@ -89,6 +89,8 @@ struct trace {
|
|
u64 base_time;
|
|
u64 base_time;
|
|
FILE *output;
|
|
FILE *output;
|
|
unsigned long nr_events;
|
|
unsigned long nr_events;
|
|
|
|
+ unsigned long nr_events_printed;
|
|
|
|
+ unsigned long max_events;
|
|
struct strlist *ev_qualifier;
|
|
struct strlist *ev_qualifier;
|
|
struct {
|
|
struct {
|
|
size_t nr;
|
|
size_t nr;
|
|
@@ -1664,6 +1666,8 @@ static int trace__printf_interrupted_entry(struct trace *trace)
|
|
printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
|
|
printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
|
|
ttrace->entry_pending = false;
|
|
ttrace->entry_pending = false;
|
|
|
|
|
|
|
|
+ ++trace->nr_events_printed;
|
|
|
|
+
|
|
return printed;
|
|
return printed;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1940,6 +1944,13 @@ errno_print: {
|
|
|
|
|
|
fputc('\n', trace->output);
|
|
fputc('\n', trace->output);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * We only consider an 'event' for the sake of --max-events a non-filtered
|
|
|
|
+ * sys_enter + sys_exit and other tracepoint events.
|
|
|
|
+ */
|
|
|
|
+ if (++trace->nr_events_printed == trace->max_events && trace->max_events != ULONG_MAX)
|
|
|
|
+ interrupted = true;
|
|
|
|
+
|
|
if (callchain_ret > 0)
|
|
if (callchain_ret > 0)
|
|
trace__fprintf_callchain(trace, sample);
|
|
trace__fprintf_callchain(trace, sample);
|
|
else if (callchain_ret < 0)
|
|
else if (callchain_ret < 0)
|
|
@@ -2072,6 +2083,7 @@ static void bpf_output__fprintf(struct trace *trace,
|
|
{
|
|
{
|
|
binary__fprintf(sample->raw_data, sample->raw_size, 8,
|
|
binary__fprintf(sample->raw_data, sample->raw_size, 8,
|
|
bpf_output__printer, NULL, trace->output);
|
|
bpf_output__printer, NULL, trace->output);
|
|
|
|
+ ++trace->nr_events_printed;
|
|
}
|
|
}
|
|
|
|
|
|
static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
|
|
static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
|
|
@@ -2127,6 +2139,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
|
|
event_format__fprintf(evsel->tp_format, sample->cpu,
|
|
event_format__fprintf(evsel->tp_format, sample->cpu,
|
|
sample->raw_data, sample->raw_size,
|
|
sample->raw_data, sample->raw_size,
|
|
trace->output);
|
|
trace->output);
|
|
|
|
+ ++trace->nr_events_printed;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2225,6 +2238,8 @@ static int trace__pgfault(struct trace *trace,
|
|
trace__fprintf_callchain(trace, sample);
|
|
trace__fprintf_callchain(trace, sample);
|
|
else if (callchain_ret < 0)
|
|
else if (callchain_ret < 0)
|
|
pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
|
|
pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
|
|
|
|
+
|
|
|
|
+ ++trace->nr_events_printed;
|
|
out:
|
|
out:
|
|
err = 0;
|
|
err = 0;
|
|
out_put:
|
|
out_put:
|
|
@@ -2402,6 +2417,9 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
|
|
tracepoint_handler handler = evsel->handler;
|
|
tracepoint_handler handler = evsel->handler;
|
|
handler(trace, evsel, event, sample);
|
|
handler(trace, evsel, event, sample);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (trace->nr_events_printed >= trace->max_events && trace->max_events != ULONG_MAX)
|
|
|
|
+ interrupted = true;
|
|
}
|
|
}
|
|
|
|
|
|
static int trace__add_syscall_newtp(struct trace *trace)
|
|
static int trace__add_syscall_newtp(struct trace *trace)
|
|
@@ -3249,6 +3267,7 @@ int cmd_trace(int argc, const char **argv)
|
|
.trace_syscalls = false,
|
|
.trace_syscalls = false,
|
|
.kernel_syscallchains = false,
|
|
.kernel_syscallchains = false,
|
|
.max_stack = UINT_MAX,
|
|
.max_stack = UINT_MAX,
|
|
|
|
+ .max_events = ULONG_MAX,
|
|
};
|
|
};
|
|
const char *output_name = NULL;
|
|
const char *output_name = NULL;
|
|
const struct option trace_options[] = {
|
|
const struct option trace_options[] = {
|
|
@@ -3301,6 +3320,8 @@ int cmd_trace(int argc, const char **argv)
|
|
&record_parse_callchain_opt),
|
|
&record_parse_callchain_opt),
|
|
OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
|
|
OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
|
|
"Show the kernel callchains on the syscall exit path"),
|
|
"Show the kernel callchains on the syscall exit path"),
|
|
|
|
+ OPT_ULONG(0, "max-events", &trace.max_events,
|
|
|
|
+ "Set the maximum number of events to print, exit after that is reached. "),
|
|
OPT_UINTEGER(0, "min-stack", &trace.min_stack,
|
|
OPT_UINTEGER(0, "min-stack", &trace.min_stack,
|
|
"Set the minimum stack depth when parsing the callchain, "
|
|
"Set the minimum stack depth when parsing the callchain, "
|
|
"anything below the specified depth will be ignored."),
|
|
"anything below the specified depth will be ignored."),
|