Latency trace data is saved the same was as flyrecord buffer data in trace files version 7. There is a BUFFER_LAT option which hols the latency specific trace metadata and points to the secrtion in the file with the trace data. Extended the input hanlder with latency trace context and added new logic to decompress and read the latency data. A new API is added to read latency data: tracecmd_latency_data_read() Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@xxxxxxxxx> --- .../include/private/trace-cmd-private.h | 2 + lib/trace-cmd/trace-input.c | 91 ++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index f2868576..0a3e12cf 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -217,6 +217,8 @@ tracecmd_peek_data_ref(struct tracecmd_input *handle, int cpu) return rec; } +int tracecmd_latency_data_read(struct tracecmd_input *handle, char **buf, size_t *size); + struct tep_record * tracecmd_read_prev(struct tracecmd_input *handle, struct tep_record *record); diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c index f095f304..c0e8187c 100644 --- a/lib/trace-cmd/trace-input.c +++ b/lib/trace-cmd/trace-input.c @@ -175,6 +175,9 @@ struct tracecmd_input { bool read_zpage; /* uncompress pages in memory, do not use tmp files */ bool cpu_compressed; int file_version; + /* temporary file for uncompressed latency data */ + struct cpu_zdata latz; + struct cpu_data *cpu_data; long long ts_offset; struct tsc2nsec tsc_calc; @@ -3431,6 +3434,56 @@ static int read_options_type(struct tracecmd_input *handle) return 0; } +int tracecmd_latency_data_read(struct tracecmd_input *handle, char **buf, size_t *size) +{ + struct cpu_zdata *zdata = &handle->latz; + void *data; + int rsize; + int fd = -1; + int id; + + if (!handle || !buf || !size) + return -1; + if (handle->file_state != TRACECMD_FILE_CPU_LATENCY) + return -1; + + if (!handle->cpu_compressed) { + fd = handle->fd; + } else if (!handle->read_zpage) { + if (zdata->fd < 0) + return -1; + fd = zdata->fd; + } + + /* Read data from a file */ + if (fd >= 0) { + if (!(*buf)) { + *size = BUFSIZ; + *buf = malloc(*size); + if (!(*buf)) + return -1; + } + return do_read_fd(fd, *buf, *size); + } + + /* Uncompress data in memory */ + if (zdata->last_chunk >= zdata->count) + return 0; + id = zdata->last_chunk; + if (!*buf || *size < zdata->chunks[id].size) { + data = realloc(*buf, zdata->chunks[id].size); + if (!data) + return -1; + *buf = data; + *size = zdata->chunks[id].size; + } + if (tracecmd_uncompress_chunk(handle->compress, &zdata->chunks[id], *buf)) + return -1; + rsize = zdata->chunks[id].size; + zdata->last_chunk++; + return rsize; +} + static int init_cpu_data(struct tracecmd_input *handle) { enum kbuffer_long_size long_size; @@ -3494,6 +3547,32 @@ static int init_cpu_data(struct tracecmd_input *handle) return -1; } +int init_latency_data(struct tracecmd_input *handle) +{ + unsigned long long wsize; + int ret; + + if (!handle->cpu_compressed) + return 0; + + if (handle->read_zpage) { + handle->latz.count = tracecmd_load_chunks_info(handle->compress, &handle->latz.chunks); + if (handle->latz.count < 0) + return -1; + } else { + strcpy(handle->latz.file, COMPR_TEMP_FILE); + handle->latz.fd = mkstemp(handle->latz.file); + if (handle->latz.fd < 0) + return -1; + ret = tracecmd_uncompress_copy_to(handle->compress, handle->latz.fd, NULL, &wsize); + if (ret) + return -1; + lseek64(handle->latz.fd, 0, SEEK_SET); + } + + return 0; +} + static int init_buffer_cpu_data(struct tracecmd_input *handle, struct input_buffer_instance *buffer) { unsigned long long offset; @@ -3510,6 +3589,10 @@ static int init_buffer_cpu_data(struct tracecmd_input *handle, struct input_buff return -1; if (flags & TRACECMD_SEC_FL_COMPRESS) handle->cpu_compressed = true; + if (buffer->latency) { + handle->file_state = TRACECMD_FILE_CPU_LATENCY; + return init_latency_data(handle) == 0 ? 1 : -1; + } handle->file_state = TRACECMD_FILE_CPU_FLYRECORD; handle->cpus = buffer->cpus; if (handle->max_cpu < handle->cpus) @@ -3959,7 +4042,7 @@ struct tracecmd_input *tracecmd_alloc_fd(int fd, int flags) handle->fd = fd; handle->ref = 1; - + handle->latz.fd = -1; /* By default, use usecs, unless told otherwise */ handle->flags |= TRACECMD_FL_IN_USECS; @@ -4233,7 +4316,11 @@ void tracecmd_close(struct tracecmd_input *handle) free(handle->trace_clock); free(handle->version); close(handle->fd); - + free(handle->latz.chunks); + if (handle->latz.fd >= 0) { + close(handle->latz.fd); + unlink(handle->latz.file); + } while (handle->sections) { del_sec = handle->sections; handle->sections = handle->sections->next; -- 2.31.1