|
@@ -196,7 +196,8 @@ static void record_file(const char *file, size_t hdr_sz)
|
|
|
die("Can't read '%s'", file);
|
|
|
|
|
|
/* put in zeros for file size, then fill true size later */
|
|
|
- write_or_die(&size, hdr_sz);
|
|
|
+ if (hdr_sz)
|
|
|
+ write_or_die(&size, hdr_sz);
|
|
|
|
|
|
do {
|
|
|
r = read(fd, buf, BUFSIZ);
|
|
@@ -212,7 +213,7 @@ static void record_file(const char *file, size_t hdr_sz)
|
|
|
if (bigendian())
|
|
|
sizep += sizeof(u64) - hdr_sz;
|
|
|
|
|
|
- if (pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0)
|
|
|
+ if (hdr_sz && pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0)
|
|
|
die("writing to %s", output_file);
|
|
|
}
|
|
|
|
|
@@ -428,6 +429,19 @@ get_tracepoints_path(struct list_head *pattrs)
|
|
|
return nr_tracepoints > 0 ? path.next : NULL;
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+put_tracepoints_path(struct tracepoint_path *tps)
|
|
|
+{
|
|
|
+ while (tps) {
|
|
|
+ struct tracepoint_path *t = tps;
|
|
|
+
|
|
|
+ tps = tps->next;
|
|
|
+ free(t->name);
|
|
|
+ free(t->system);
|
|
|
+ free(t);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
bool have_tracepoints(struct list_head *pattrs)
|
|
|
{
|
|
|
struct perf_evsel *pos;
|
|
@@ -439,19 +453,11 @@ bool have_tracepoints(struct list_head *pattrs)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-int read_tracing_data(int fd, struct list_head *pattrs)
|
|
|
+static void tracing_data_header(void)
|
|
|
{
|
|
|
- char buf[BUFSIZ];
|
|
|
- struct tracepoint_path *tps = get_tracepoints_path(pattrs);
|
|
|
-
|
|
|
- /*
|
|
|
- * What? No tracepoints? No sense writing anything here, bail out.
|
|
|
- */
|
|
|
- if (tps == NULL)
|
|
|
- return -1;
|
|
|
-
|
|
|
- output_fd = fd;
|
|
|
+ char buf[20];
|
|
|
|
|
|
+ /* just guessing this is someone's birthday.. ;) */
|
|
|
buf[0] = 23;
|
|
|
buf[1] = 8;
|
|
|
buf[2] = 68;
|
|
@@ -476,28 +482,86 @@ int read_tracing_data(int fd, struct list_head *pattrs)
|
|
|
/* save page_size */
|
|
|
page_size = sysconf(_SC_PAGESIZE);
|
|
|
write_or_die(&page_size, 4);
|
|
|
+}
|
|
|
+
|
|
|
+struct tracing_data *tracing_data_get(struct list_head *pattrs,
|
|
|
+ int fd, bool temp)
|
|
|
+{
|
|
|
+ struct tracepoint_path *tps;
|
|
|
+ struct tracing_data *tdata;
|
|
|
+
|
|
|
+ output_fd = fd;
|
|
|
+
|
|
|
+ tps = get_tracepoints_path(pattrs);
|
|
|
+ if (!tps)
|
|
|
+ return NULL;
|
|
|
|
|
|
+ tdata = malloc_or_die(sizeof(*tdata));
|
|
|
+ tdata->temp = temp;
|
|
|
+ tdata->size = 0;
|
|
|
+
|
|
|
+ if (temp) {
|
|
|
+ int temp_fd;
|
|
|
+
|
|
|
+ snprintf(tdata->temp_file, sizeof(tdata->temp_file),
|
|
|
+ "/tmp/perf-XXXXXX");
|
|
|
+ if (!mkstemp(tdata->temp_file))
|
|
|
+ die("Can't make temp file");
|
|
|
+
|
|
|
+ temp_fd = open(tdata->temp_file, O_RDWR);
|
|
|
+ if (temp_fd < 0)
|
|
|
+ die("Can't read '%s'", tdata->temp_file);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Set the temp file the default output, so all the
|
|
|
+ * tracing data are stored into it.
|
|
|
+ */
|
|
|
+ output_fd = temp_fd;
|
|
|
+ }
|
|
|
+
|
|
|
+ tracing_data_header();
|
|
|
read_header_files();
|
|
|
read_ftrace_files(tps);
|
|
|
read_event_files(tps);
|
|
|
read_proc_kallsyms();
|
|
|
read_ftrace_printk();
|
|
|
|
|
|
- return 0;
|
|
|
+ /*
|
|
|
+ * All tracing data are stored by now, we can restore
|
|
|
+ * the default output file in case we used temp file.
|
|
|
+ */
|
|
|
+ if (temp) {
|
|
|
+ tdata->size = lseek(output_fd, 0, SEEK_CUR);
|
|
|
+ close(output_fd);
|
|
|
+ output_fd = fd;
|
|
|
+ }
|
|
|
+
|
|
|
+ put_tracepoints_path(tps);
|
|
|
+ return tdata;
|
|
|
}
|
|
|
|
|
|
-ssize_t read_tracing_data_size(int fd, struct list_head *pattrs)
|
|
|
+void tracing_data_put(struct tracing_data *tdata)
|
|
|
{
|
|
|
- ssize_t size;
|
|
|
- int err = 0;
|
|
|
+ if (tdata->temp) {
|
|
|
+ record_file(tdata->temp_file, 0);
|
|
|
+ unlink(tdata->temp_file);
|
|
|
+ }
|
|
|
|
|
|
- calc_data_size = 1;
|
|
|
- err = read_tracing_data(fd, pattrs);
|
|
|
- size = calc_data_size - 1;
|
|
|
- calc_data_size = 0;
|
|
|
+ free(tdata);
|
|
|
+}
|
|
|
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
+int read_tracing_data(int fd, struct list_head *pattrs)
|
|
|
+{
|
|
|
+ struct tracing_data *tdata;
|
|
|
|
|
|
- return size;
|
|
|
+ /*
|
|
|
+ * We work over the real file, so we can write data
|
|
|
+ * directly, no temp file is needed.
|
|
|
+ */
|
|
|
+ tdata = tracing_data_get(pattrs, fd, false);
|
|
|
+ if (!tdata)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ tracing_data_put(tdata);
|
|
|
+ return 0;
|
|
|
}
|