@@ -3327,34 +3327,18 @@ static int read_options_type(struct tracecmd_input *handle)
return 0;
}
-static int read_cpu_data(struct tracecmd_input *handle)
+static int init_cpu_data(struct tracecmd_input *handle)
{
- struct tep_handle *pevent = handle->pevent;
enum kbuffer_long_size long_size;
enum kbuffer_endian endian;
- unsigned long long size;
unsigned long long max_size = 0;
unsigned long long pages;
- int cpus;
int cpu;
- /*
- * Check if this is a latency report or not.
- */
- if (handle->file_state == TRACECMD_FILE_CPU_LATENCY)
- return 1;
-
/* We expect this to be flyrecord */
if (handle->file_state != TRACECMD_FILE_CPU_FLYRECORD)
return -1;
- cpus = handle->cpus;
-
- handle->cpu_data = malloc(sizeof(*handle->cpu_data) * handle->cpus);
- if (!handle->cpu_data)
- return -1;
- memset(handle->cpu_data, 0, sizeof(*handle->cpu_data) * handle->cpus);
-
if (force_read)
handle->read_page = true;
@@ -3369,32 +3353,15 @@ static int read_cpu_data(struct tracecmd_input *handle)
endian = KBUFFER_ENDIAN_LITTLE;
for (cpu = 0; cpu < handle->cpus; cpu++) {
- unsigned long long offset;
-
- handle->cpu_data[cpu].cpu = cpu;
handle->cpu_data[cpu].compress.fd = -1;
handle->cpu_data[cpu].kbuf = kbuffer_alloc(long_size, endian);
if (!handle->cpu_data[cpu].kbuf)
goto out_free;
- if (tep_is_old_format(pevent))
+ if (tep_is_old_format(handle->pevent))
kbuffer_set_old_format(handle->cpu_data[cpu].kbuf);
- read8(handle, &offset);
- read8(handle, &size);
-
- handle->cpu_data[cpu].file_offset = offset;
- handle->cpu_data[cpu].file_size = size;
- if (size > max_size)
- max_size = size;
-
- if (size && (offset + size > handle->total_file_size)) {
- /* this happens if the file got truncated */
- printf("File possibly truncated. "
- "Need at least %llu, but file size is %zu.\n",
- offset + size, handle->total_file_size);
- errno = EINVAL;
- goto out_free;
- }
+ if (handle->cpu_data[cpu].file_size > max_size)
+ max_size = handle->cpu_data[cpu].file_size;
}
/* Calculate about a meg of pages for buffering */
@@ -3412,6 +3379,102 @@ static int read_cpu_data(struct tracecmd_input *handle)
goto out_free;
}
+ return 0;
+
+ out_free:
+ for ( ; cpu >= 0; cpu--) {
+ free_page(handle, cpu);
+ kbuffer_free(handle->cpu_data[cpu].kbuf);
+ handle->cpu_data[cpu].kbuf = NULL;
+ }
+ return -1;
+}
+
+static int init_buffer_cpu_data(struct tracecmd_input *handle, struct input_buffer_instance *buffer)
+{
+ unsigned long long offset;
+ unsigned long long size;
+ unsigned short id, flags;
+ int cpu;
+
+ if (handle->cpu_data)
+ return -1;
+
+ if (lseek64(handle->fd, buffer->offset, SEEK_SET) == (off_t)-1)
+ return -1;
+ if (read_section_header(handle, &id, &flags, NULL, NULL))
+ return -1;
+ if (flags & TRACECMD_SEC_FL_COMPRESS)
+ handle->cpu_compressed = true;
+ handle->file_state = TRACECMD_FILE_CPU_FLYRECORD;
+ handle->cpus = buffer->cpus;
+ if (handle->max_cpu < handle->cpus)
+ handle->max_cpu = handle->cpus;
+
+ handle->cpu_data = calloc(handle->cpus, sizeof(*handle->cpu_data));
+ if (!handle->cpu_data)
+ return -1;
+
+ for (cpu = 0; cpu < handle->cpus; cpu++) {
+ handle->cpu_data[cpu].cpu = buffer->cpu_data[cpu].cpu;
+ offset = buffer->cpu_data[cpu].offset;
+ size = buffer->cpu_data[cpu].size;
+ handle->cpu_data[cpu].file_offset = offset;
+ handle->cpu_data[cpu].file_size = size;
+ if (size && (offset + size > handle->total_file_size)) {
+ /* this happens if the file got truncated */
+ printf("File possibly truncated. "
+ "Need at least %llu, but file size is %zu.\n",
+ offset + size, handle->total_file_size);
+ errno = EINVAL;
+ return -1;
+ }
+ }
+
+ return init_cpu_data(handle);
+}
+
+static int read_cpu_data(struct tracecmd_input *handle)
+{
+ unsigned long long size;
+ int cpus;
+ int cpu;
+
+ /*
+ * Check if this is a latency report or not.
+ */
+ if (handle->file_state == TRACECMD_FILE_CPU_LATENCY)
+ return 1;
+
+ /* We expect this to be flyrecord */
+ if (handle->file_state != TRACECMD_FILE_CPU_FLYRECORD)
+ return -1;
+
+ cpus = handle->cpus;
+
+ handle->cpu_data = malloc(sizeof(*handle->cpu_data) * handle->cpus);
+ if (!handle->cpu_data)
+ return -1;
+ memset(handle->cpu_data, 0, sizeof(*handle->cpu_data) * handle->cpus);
+
+ for (cpu = 0; cpu < handle->cpus; cpu++) {
+ unsigned long long offset;
+
+ handle->cpu_data[cpu].cpu = cpu;
+ read8(handle, &offset);
+ read8(handle, &size);
+ handle->cpu_data[cpu].file_offset = offset;
+ handle->cpu_data[cpu].file_size = size;
+ if (size && (offset + size > handle->total_file_size)) {
+ /* this happens if the file got truncated */
+ printf("File possibly truncated. "
+ "Need at least %llu, but file size is %zu.\n",
+ offset + size, handle->total_file_size);
+ errno = EINVAL;
+ return -1;
+ }
+ }
+
/*
* It is possible that an option changed the number of CPUs.
* If that happened, then there's "empty" cpu data saved for
@@ -3431,15 +3494,7 @@ static int read_cpu_data(struct tracecmd_input *handle)
}
}
- return 0;
-
- out_free:
- for ( ; cpu >= 0; cpu--) {
- free_page(handle, cpu);
- kbuffer_free(handle->cpu_data[cpu].kbuf);
- handle->cpu_data[cpu].kbuf = NULL;
- }
- return -1;
+ return init_cpu_data(handle);
}
static int read_data_and_size(struct tracecmd_input *handle,
@@ -3542,14 +3597,7 @@ static int read_and_parse_trace_clock(struct tracecmd_input *handle,
return 0;
}
-/**
- * tracecmd_init_data - prepare reading the data from trace.dat
- * @handle: input handle for the trace.dat file
- *
- * This prepares reading the data from trace.dat. This is called
- * after tracecmd_read_headers() and before tracecmd_read_data().
- */
-int tracecmd_init_data(struct tracecmd_input *handle)
+static int init_data_v6(struct tracecmd_input *handle)
{
struct tep_handle *pevent = handle->pevent;
int ret;
@@ -3571,7 +3619,29 @@ int tracecmd_init_data(struct tracecmd_input *handle)
tracecmd_parse_trace_clock(handle, clock, 8);
}
}
+ return ret;
+}
+
+static int init_data_v7(struct tracecmd_input *handle)
+{
+ return init_buffer_cpu_data(handle, &handle->top_buffer);
+}
+
+/**
+ * tracecmd_init_data - prepare reading the data from trace.dat
+ * @handle: input handle for the trace.dat file
+ *
+ * This prepares reading the data from trace.dat. This is called
+ * after tracecmd_read_headers() and before tracecmd_read_data().
+ */
+int tracecmd_init_data(struct tracecmd_input *handle)
+{
+ int ret;
+ if (handle->file_version < 7)
+ ret = init_data_v6(handle);
+ else
+ ret = init_data_v7(handle);
tracecmd_blk_hack(handle);
return ret;
In version 7 trace files, CPU trace data is written in slightly different way than in version 6 files. Added new CPU data initialization flow, to handle version 7 files: - the top trace instance is saved in the same way as the other trace instances. - per CPU trace metadata is stored in the buffer option. - trace data section has section header. - trace data can be compressed. Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com> --- lib/trace-cmd/trace-input.c | 178 +++++++++++++++++++++++++----------- 1 file changed, 124 insertions(+), 54 deletions(-)