From: "Steven Rostedt (VMware)" <rostedt@xxxxxxxxxxx> Now that TRACECMD_FILE_* states are exported, and tracecmd_read_headers() can bring a handle up to a given state and stop, change tracecmd_copy_headers() to use this information and allow a copy of one handle to a file descriptor to start at any given state, and stop at another. Signed-off-by: Steven Rostedt (VMware) <rostedt@xxxxxxxxxxx> --- .../include/private/trace-cmd-private.h | 4 +- lib/trace-cmd/trace-input.c | 109 ++++++++++++++---- lib/trace-cmd/trace-output.c | 4 +- 3 files changed, 92 insertions(+), 25 deletions(-) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index bd14caff93ac..322cdb1eb223 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -159,7 +159,9 @@ int tracecmd_get_parsing_failures(struct tracecmd_input *handle); int tracecmd_long_size(struct tracecmd_input *handle); int tracecmd_page_size(struct tracecmd_input *handle); int tracecmd_cpus(struct tracecmd_input *handle); -int tracecmd_copy_headers(struct tracecmd_input *handle, int fd); +int tracecmd_copy_headers(struct tracecmd_input *handle, int fd, + enum tracecmd_file_states start_state, + enum tracecmd_file_states end_state); void tracecmd_set_flag(struct tracecmd_input *handle, int flag); void tracecmd_clear_flag(struct tracecmd_input *handle, int flag); unsigned long tracecmd_get_flags(struct tracecmd_input *handle); diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c index 24b3aa4001d3..add48f811ac6 100644 --- a/lib/trace-cmd/trace-input.c +++ b/lib/trace-cmd/trace-input.c @@ -3528,14 +3528,9 @@ static int copy_header_files(struct tracecmd_input *handle, int fd) { unsigned long long size; - if (handle->file_state < TRACECMD_FILE_HEADERS) + if (handle->file_state != TRACECMD_FILE_HEADERS - 1) return -1; - lseek64(handle->fd, handle->header_files_start, SEEK_SET); - - /* Now that the file handle has moved, change its state */ - handle->file_state = TRACECMD_FILE_HEADERS; - /* "header_page" */ if (read_copy_data(handle, 12, fd) < 0) return -1; @@ -3556,6 +3551,8 @@ static int copy_header_files(struct tracecmd_input *handle, int fd) if (read_copy_data(handle, size, fd) < 0) return -1; + handle->file_state = TRACECMD_FILE_HEADERS; + return 0; } @@ -3686,35 +3683,101 @@ static int copy_command_lines(struct tracecmd_input *handle, int fd) return 0; } -int tracecmd_copy_headers(struct tracecmd_input *handle, int fd) +/** + * tracecmd_copy_headers - Copy headers from a tracecmd_input handle to a file descriptor + * @handle: input handle for the trace.dat file to copy from. + * @fd: The file descriptor to copy to. + * @start_state: The file state to start copying from (zero for the beginnig) + * @end_state: The file state to stop at (zero for up to cmdlines) + * + * This is used to copy trace header data of a trace.dat file to a + * file descriptor. Using @start_state and @end_state it may be used + * multiple times against the input handle. + * + * NOTE: The input handle is also modified, and ends at the end + * state as well. + */ +int tracecmd_copy_headers(struct tracecmd_input *handle, int fd, + enum tracecmd_file_states start_state, + enum tracecmd_file_states end_state) { int ret; - /* Make sure that the input handle is up to cmd lines */ - if (handle->file_state < TRACECMD_FILE_CMD_LINES) + if (!start_state) + start_state = TRACECMD_FILE_HEADERS; + if (!end_state) + end_state = TRACECMD_FILE_CMD_LINES; + + if (start_state > end_state) return -1; - ret = copy_header_files(handle, fd); - if (ret < 0) - goto out; + if (end_state < TRACECMD_FILE_HEADERS) + return 0; - ret = copy_ftrace_files(handle, fd); - if (ret < 0) - goto out; + if (handle->file_state >= start_state) { + /* Set the handle to just before the start state */ + lseek64(handle->fd, handle->header_files_start, SEEK_SET); + /* Now that the file handle has moved, change its state */ + handle->file_state = TRACECMD_FILE_INIT; + } - ret = copy_event_files(handle, fd); + /* Try to bring the input up to the start state - 1 */ + ret = tracecmd_read_headers(handle, start_state - 1); if (ret < 0) goto out; - ret = copy_proc_kallsyms(handle, fd); - if (ret < 0) - goto out; + switch (start_state) { + case TRACECMD_FILE_HEADERS: + ret = copy_header_files(handle, fd); + if (ret < 0) + goto out; - ret = copy_ftrace_printk(handle, fd); - if (ret < 0) - goto out; + /* fallthrough */ + case TRACECMD_FILE_FTRACE_EVENTS: + /* handle's state is now updating with the copies */ + if (end_state <= handle->file_state) + return 0; + + ret = copy_ftrace_files(handle, fd); + if (ret < 0) + goto out; + + /* fallthrough */ + case TRACECMD_FILE_ALL_EVENTS: + if (end_state <= handle->file_state) + return 0; + + ret = copy_event_files(handle, fd); + if (ret < 0) + goto out; - ret = copy_command_lines(handle, fd); + /* fallthrough */ + case TRACECMD_FILE_KALLSYMS: + if (end_state <= handle->file_state) + return 0; + + ret = copy_proc_kallsyms(handle, fd); + if (ret < 0) + goto out; + + /* fallthrough */ + case TRACECMD_FILE_PRINTK: + if (end_state <= handle->file_state) + return 0; + + ret = copy_ftrace_printk(handle, fd); + if (ret < 0) + goto out; + + /* fallthrough */ + case TRACECMD_FILE_CMD_LINES: + if (end_state <= handle->file_state) + return 0; + + ret = copy_command_lines(handle, fd); + default: + break; + } out: return ret < 0 ? -1 : 0; diff --git a/lib/trace-cmd/trace-output.c b/lib/trace-cmd/trace-output.c index a26fd8537a1d..54ddcb547828 100644 --- a/lib/trace-cmd/trace-output.c +++ b/lib/trace-cmd/trace-output.c @@ -1655,9 +1655,11 @@ struct tracecmd_output *tracecmd_copy(struct tracecmd_input *ihandle, if (!handle) return NULL; - if (tracecmd_copy_headers(ihandle, handle->fd) < 0) + if (tracecmd_copy_headers(ihandle, handle->fd, 0, 0) < 0) goto out_free; + handle->file_state = tracecmd_get_file_state(ihandle); + /* The file is all ready to have cpu data attached */ return handle; -- 2.30.0