[PATCH v5 2/2] Add the fp_selection_helper to set the fp for print functions

From: yuzhoujian
Date: Wed Oct 25 2017 - 04:54:32 EST


This patch will make all print functions receive the fp, add the fp_selection_helper
function to select the fp(stdout or the dump_event fp) and open the dump file for
all print functions. When the perf script is over, closes the dump_event file and
calculates its size.

Changes since v4:
- the fp_selection_helper will be invoked by process_event not process_sample_event
- replace some printf with fprintf in process_event

Changes since v3:
- free the evsel->priv by zfree()

Changes since v2:
- remove the file_name variable and get the data file name from struct perf_session
- remove the per_event_dump_file variable and get the dump_event fp from struct
perf_evsel
- add the fp_selection_helper function to select the fp(stdout or the dump_event
fp) and open the dump file for all print functions if evname and last evsel name is not
the same.
- close the dump file for all the evsels and calculate the dump file's size at the end of
the perf script.
- solve the segmentation fault generated by perf script --per-event-dump --show-mmap-events

Changes since v1:
- modify the dump file name to <ORIGINAL PERF DATA FILE NAME>-script-dump-<EVENT NAME>.txt
ect. perf.data-script-dump-cycles.txt, perf.data-script-dump-cs.txt
- split the original patch(Make all those related functions receive the file pointer)
to two patches, and this is the second part of the original one.

Signed-off-by: yuzhoujian <yuzhoujian@xxxxxxxxxxxxxxx>
---
tools/perf/builtin-script.c | 107 +++++++++++++++++++++++++++++++++++---------
tools/perf/util/session.c | 19 ++++++++
2 files changed, 106 insertions(+), 20 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 81f141f..8d98349 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1431,6 +1431,50 @@ static int data_src__fprintf(u64 data_src, FILE *fp)
return fprintf(fp, "%-*s", maxlen, out);
}

+static FILE *fp_selection_helper(struct perf_script *script, struct perf_evsel *evsel)
+{
+ const char *evname;
+ char *filename;
+ FILE *fp;
+ struct perf_tool *tool = &script->tool;
+ struct perf_script_evsel *ps;
+
+ evname = perf_evsel__name(evsel);
+ if (tool->per_event_dump) {
+ ps = (struct perf_script_evsel *)evsel->priv;
+
+ /* if evname and last evsel name is not the same, opens another dump file. */
+ if (evname != tool->last_evsel_name) {
+ if (asprintf(&filename, "%s%s%s%s", script->session->file->path,
+ "-script-dump-", evname, ".txt") < 0)
+ BUG_ON("fail to add the suffix for dump file's name!\n");
+
+ fp = fopen(filename, "a+");
+ if (!fp)
+ BUG_ON("fail to open the dump file!\n");
+
+ if (!ps) {
+ ps = zalloc(sizeof(struct perf_script_evsel));
+ if (!ps)
+ BUG_ON("fail to create a perf_script_evsel struct!\n");
+ ps->samples = 0;
+ }
+ ps->filename = filename;
+ ps->dump_evsel_fp = fp;
+ tool->last_evsel_name = evname;
+ evsel->priv = ps;
+ } else {
+ if (ps->dump_evsel_fp)
+ fp = ps->dump_evsel_fp;
+ else
+ BUG_ON("fail to get the dump file's fp!\n");
+ }
+ } else {
+ fp = stdout;
+ }
+ return fp;
+}
+
static void process_event(struct perf_script *script,
struct perf_sample *sample, struct perf_evsel *evsel,
struct addr_location *al,
@@ -1439,15 +1483,25 @@ static void process_event(struct perf_script *script,
struct thread *thread = al->thread;
struct perf_event_attr *attr = &evsel->attr;
unsigned int type = output_type(attr->type);
- FILE *fp = stdout;
+ struct perf_script_evsel *ps;
+ struct perf_tool *tool = &script->tool;
+ FILE *fp;
+
+ fp = fp_selection_helper(script, evsel);

if (output[type].fields == 0)
return;

+ if (tool->per_event_dump) {
+ ps = (struct perf_script_evsel *)evsel->priv;
+ ps->samples++;
+ evsel->priv = ps;
+ }
+
perf_sample__fprintf_start(sample, thread, evsel, fp);

if (PRINT_FIELD(PERIOD))
- printf("%10" PRIu64 " ", sample->period);
+ fprintf(fp, "%10" PRIu64 " ", sample->period);

if (PRINT_FIELD(EVNAME)) {
const char *evname = perf_evsel__name(evsel);
@@ -1455,7 +1509,7 @@ static void process_event(struct perf_script *script,
if (!script->name_width)
script->name_width = perf_evlist__max_name_len(script->session->evlist);

- printf("%*s: ", script->name_width,
+ fprintf(fp, "%*s: ", script->name_width,
evname ? evname : "[unknown]");
}

@@ -1513,8 +1567,8 @@ static void process_event(struct perf_script *script,
perf_sample__fprintf_insn(sample, attr, thread, machine, fp);

if (PRINT_FIELD(PHYS_ADDR))
- printf("%16" PRIx64, sample->phys_addr);
- printf("\n");
+ fprintf(fp, "%16" PRIx64, sample->phys_addr);
+ fprintf(fp, "\n");
}

static struct scripting_ops *scripting_ops;
@@ -1671,6 +1725,7 @@ static int process_comm_event(struct perf_tool *tool,
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ FILE *fp;
int ret = -1;

thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid);
@@ -1688,8 +1743,9 @@ static int process_comm_event(struct perf_tool *tool,
sample->tid = event->comm.tid;
sample->pid = event->comm.pid;
}
- perf_sample__fprintf_start(sample, thread, evsel, stdout);
- perf_event__fprintf(event, stdout);
+ fp = fp_selection_helper(script, evsel);
+ perf_sample__fprintf_start(sample, thread, evsel, fp);
+ perf_event__fprintf(event, fp);
ret = 0;
out:
thread__put(thread);
@@ -1705,6 +1761,7 @@ static int process_namespaces_event(struct perf_tool *tool,
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ FILE *fp;
int ret = -1;

thread = machine__findnew_thread(machine, event->namespaces.pid,
@@ -1723,8 +1780,9 @@ static int process_namespaces_event(struct perf_tool *tool,
sample->tid = event->namespaces.tid;
sample->pid = event->namespaces.pid;
}
- perf_sample__fprintf_start(sample, thread, evsel, stdout);
- perf_event__fprintf(event, stdout);
+ fp = fp_selection_helper(script, evsel);
+ perf_sample__fprintf_start(sample, thread, evsel, fp);
+ perf_event__fprintf(event, fp);
ret = 0;
out:
thread__put(thread);
@@ -1740,6 +1798,7 @@ static int process_fork_event(struct perf_tool *tool,
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ FILE *fp;

if (perf_event__process_fork(tool, event, sample, machine) < 0)
return -1;
@@ -1756,8 +1815,9 @@ static int process_fork_event(struct perf_tool *tool,
sample->tid = event->fork.tid;
sample->pid = event->fork.pid;
}
- perf_sample__fprintf_start(sample, thread, evsel, stdout);
- perf_event__fprintf(event, stdout);
+ fp = fp_selection_helper(script, evsel);
+ perf_sample__fprintf_start(sample, thread, evsel, fp);
+ perf_event__fprintf(event, fp);
thread__put(thread);

return 0;
@@ -1772,6 +1832,7 @@ static int process_exit_event(struct perf_tool *tool,
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ FILE *fp;

thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
if (thread == NULL) {
@@ -1785,8 +1846,9 @@ static int process_exit_event(struct perf_tool *tool,
sample->tid = event->fork.tid;
sample->pid = event->fork.pid;
}
- perf_sample__fprintf_start(sample, thread, evsel, stdout);
- perf_event__fprintf(event, stdout);
+ fp = fp_selection_helper(script, evsel);
+ perf_sample__fprintf_start(sample, thread, evsel, fp);
+ perf_event__fprintf(event, fp);

if (perf_event__process_exit(tool, event, sample, machine) < 0)
err = -1;
@@ -1804,6 +1866,7 @@ static int process_mmap_event(struct perf_tool *tool,
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ FILE *fp;

if (perf_event__process_mmap(tool, event, sample, machine) < 0)
return -1;
@@ -1820,8 +1883,9 @@ static int process_mmap_event(struct perf_tool *tool,
sample->tid = event->mmap.tid;
sample->pid = event->mmap.pid;
}
- perf_sample__fprintf_start(sample, thread, evsel, stdout);
- perf_event__fprintf(event, stdout);
+ fp = fp_selection_helper(script, evsel);
+ perf_sample__fprintf_start(sample, thread, evsel, fp);
+ perf_event__fprintf(event, fp);
thread__put(thread);
return 0;
}
@@ -1835,6 +1899,7 @@ static int process_mmap2_event(struct perf_tool *tool,
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ FILE *fp;

if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
return -1;
@@ -1851,8 +1916,9 @@ static int process_mmap2_event(struct perf_tool *tool,
sample->tid = event->mmap2.tid;
sample->pid = event->mmap2.pid;
}
- perf_sample__fprintf_start(sample, thread, evsel, stdout);
- perf_event__fprintf(event, stdout);
+ fp = fp_selection_helper(script, evsel);
+ perf_sample__fprintf_start(sample, thread, evsel, fp);
+ perf_event__fprintf(event, fp);
thread__put(thread);
return 0;
}
@@ -1866,6 +1932,7 @@ static int process_switch_event(struct perf_tool *tool,
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ FILE *fp;

if (perf_event__process_switch(tool, event, sample, machine) < 0)
return -1;
@@ -1876,9 +1943,9 @@ static int process_switch_event(struct perf_tool *tool,
pr_debug("problem processing SWITCH event, skipping it.\n");
return -1;
}
-
- perf_sample__fprintf_start(sample, thread, evsel, stdout);
- perf_event__fprintf(event, stdout);
+ fp = fp_selection_helper(script, evsel);
+ perf_sample__fprintf_start(sample, thread, evsel, fp);
+ perf_event__fprintf(event, fp);
thread__put(thread);
return 0;
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b3fd62f..0a4784f 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -8,6 +8,8 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
+#include <sys/stat.h>
+#include <stdio.h>

#include "evlist.h"
#include "evsel.h"
@@ -1828,6 +1830,9 @@ static int __perf_session__process_events(struct perf_session *session,
{
struct ordered_events *oe = &session->ordered_events;
struct perf_tool *tool = session->tool;
+ struct perf_evlist *evlist = session->evlist;
+ struct perf_evsel *evsel;
+ struct perf_script_evsel *ps;
int fd = perf_data_file__fd(session->file);
u64 head, page_offset, file_offset, file_pos, size;
int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1835,6 +1840,7 @@ static int __perf_session__process_events(struct perf_session *session,
char *buf, *mmaps[NUM_MMAPS];
union perf_event *event;
struct ui_progress prog;
+ struct stat statbuf;
s64 skip;

perf_tool__fill_defaults(tool);
@@ -1940,6 +1946,19 @@ static int __perf_session__process_events(struct perf_session *session,
ordered_events__reinit(&session->ordered_events);
auxtrace__free_events(session);
session->one_mmap = false;
+ /* Closes the dump_event file and calculates its size at last. */
+ if (tool->per_event_dump) {
+ evlist__for_each_entry(evlist, evsel) {
+ ps = (struct perf_script_evsel *)evsel->priv;
+ if (!ps)
+ BUG_ON("fail to get the perf_script_evsel\n");
+ stat(ps->filename, &statbuf);
+ fprintf(stderr, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n",
+ statbuf.st_size / 1024.0 / 1024.0, ps->filename, ps->samples);
+ fclose(ps->dump_evsel_fp);
+ zfree(&evsel->priv);
+ }
+ }
return err;
}

--
1.8.3.1