diff mbox series

[v7,16/25] trace-cmd library: Read headers from trace file version 7

Message ID 20211210105448.97850-17-tz.stoyanov@gmail.com (mailing list archive)
State Superseded
Headers show
Series Trace file version 7 - sections | expand

Commit Message

Tzvetomir Stoyanov (VMware) Dec. 10, 2021, 10:54 a.m. UTC
Trace file version 7 has more flexible structure than version 6, headers
are not located at fixed position in the file. A new logic is
implemented to read and parse the headers from this new format.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 lib/trace-cmd/trace-input.c | 137 ++++++++++++++++++++++++++++++++----
 1 file changed, 122 insertions(+), 15 deletions(-)

Comments

Steven Rostedt Jan. 15, 2022, 3:59 p.m. UTC | #1
On Fri, 10 Dec 2021 12:54:39 +0200
"Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com> wrote:

> Trace file version 7 has more flexible structure than version 6, headers
> are not located at fixed position in the file. A new logic is
> implemented to read and parse the headers from this new format.
> 
> Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
> ---
>  lib/trace-cmd/trace-input.c | 137 ++++++++++++++++++++++++++++++++----
>  1 file changed, 122 insertions(+), 15 deletions(-)
> 
> diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c
> index 8f95bf3b..9027729e 100644
> --- a/lib/trace-cmd/trace-input.c
> +++ b/lib/trace-cmd/trace-input.c
> @@ -163,8 +163,7 @@ struct tracecmd_input {
>  	struct pid_addr_maps	*pid_maps;
>  	/* file information */
>  	struct file_section	*sections;
> -	size_t			header_files_start;
> -	size_t			ftrace_files_start;
> +	bool			options_init;
>  	unsigned long long	options_start;
>  	size_t			total_file_size;
>  
> @@ -917,19 +916,7 @@ static int read_cpus(struct tracecmd_input *handle)
>  	return 0;
>  }
>  
> -/**
> - * tracecmd_read_headers - read the header information from trace.dat
> - * @handle: input handle for the trace.dat file
> - * @state: The state to read up to or zero to read up to options.
> - *
> - * This reads the trace.dat file for various information. Like the
> - * format of the ring buffer, event formats, ftrace formats, kallsyms
> - * and printk. This may be called multiple times with different @state
> - * values, to read partial data at a time. It will always continue
> - * where it left off.
> - */
> -int tracecmd_read_headers(struct tracecmd_input *handle,
> -			  enum tracecmd_file_states state)
> +static int read_headers_v6(struct tracecmd_input *handle, enum tracecmd_file_states state)
>  {
>  	int ret;
>  
> @@ -995,6 +982,126 @@ int tracecmd_read_headers(struct tracecmd_input *handle,
>  	return 0;
>  }
>  
> +static int handle_options(struct tracecmd_input *handle);
> +
> +static int read_section_header(struct tracecmd_input *handle, unsigned short *id,
> +			       unsigned short *flags, unsigned long long *size, const char **description)
> +{
> +	unsigned short fl;
> +	unsigned short sec_id;
> +	unsigned long long sz;
> +	int desc;
> +
> +	if (read2(handle, &sec_id))
> +		return -1;
> +	if (read4(handle, (unsigned int *)&desc))
> +		return -1;
> +	if (read2(handle, &fl))
> +		return -1;
> +	if (read8(handle, &sz))
> +		return -1;
> +
> +	if (id)
> +		*id = sec_id;
> +	if (flags)
> +		*flags = fl;
> +	if (size)
> +		*size = sz;
> +
> +	return 0;
> +}
> +
> +static int handle_section(struct tracecmd_input *handle, struct file_section *section)
> +{
> +	unsigned short id, flags;
> +	unsigned long long size;
> +	int ret;
> +
> +	if (lseek64(handle->fd, section->section_offset, SEEK_SET) == (off_t)-1)
> +		return -1;
> +	if (read_section_header(handle, &id, &flags, &size, NULL))
> +		return -1;
> +	section->flags = flags;
> +	if (id != section->id)
> +		return -1;
> +
> +	section->data_offset = lseek64(handle->fd, 0, SEEK_CUR);
> +
> +	switch (section->id) {
> +	case TRACECMD_OPTION_HEADER_INFO:
> +		ret = read_header_files(handle);
> +		break;
> +	case TRACECMD_OPTION_FTRACE_EVENTS:
> +		ret = read_ftrace_files(handle, NULL);
> +		break;
> +	case TRACECMD_OPTION_EVENT_FORMATS:
> +		ret = read_event_files(handle, NULL);
> +		break;
> +	case TRACECMD_OPTION_KALLSYMS:
> +		ret = read_proc_kallsyms(handle);
> +		break;
> +	case TRACECMD_OPTION_PRINTK:
> +		ret = read_ftrace_printk(handle);
> +		break;
> +	case TRACECMD_OPTION_CMDLINES:
> +		ret = read_and_parse_cmdlines(handle);
> +		break;
> +	default:
> +		ret = 0;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int read_headers_v7(struct tracecmd_input *handle)

I really like how these changes are coming. This makes the reading of the
tracing file much more manageable. Great job Tzvetomir!

Only comment to this patch is, as I've said in other patches, I don't think
we need to call this _v7, just "read_headers()" would suffice.

-- Steve


> +{
> +	struct file_section *section;
> +
> +	if (handle->options_init)
> +		return 0;
> +
> +	if (!handle->options_start)
> +		return -1;
> +
> +	if (lseek64(handle->fd, handle->options_start, SEEK_SET) == (off64_t)-1) {
> +		tracecmd_warning("Filed to goto options offset %lld", handle->options_start);
> +		return -1;
> +	}
> +
> +	if (handle_options(handle))
> +		return -1;
> +
> +	section = handle->sections;
> +	while (section) {
> +		if (handle_section(handle, section))
> +			return -1;
> +		section = section->next;
> +	}
> +
> +	handle->options_init = true;
> +	return 0;
> +}
> +
> +/**
> + * tracecmd_read_headers - read the header information from trace.dat
> + * @handle: input handle for the trace.dat file
> + * @state: The state to read up to or zero to read up to options.
> + *
> + * This reads the trace.dat file for various information. Like the
> + * format of the ring buffer, event formats, ftrace formats, kallsyms
> + * and printk. This may be called multiple times with different @state
> + * values, to read partial data at a time. It will always continue
> + * where it left off.
> + */
> +int tracecmd_read_headers(struct tracecmd_input *handle,
> +			  enum tracecmd_file_states state)
> +{
> +	if (!HAS_SECTIONS(handle))
> +		return read_headers_v6(handle, state);
> +	return read_headers_v7(handle);
> +}
> +
>  static unsigned long long calc_page_offset(struct tracecmd_input *handle,
>  					   unsigned long long offset)
>  {
Tzvetomir Stoyanov (VMware) Jan. 17, 2022, 3:47 p.m. UTC | #2
On Sat, Jan 15, 2022 at 6:00 PM Steven Rostedt <rostedt@goodmis.org> wrote:
[...]
> > +
> > +static int read_headers_v7(struct tracecmd_input *handle)
>
> I really like how these changes are coming. This makes the reading of the
> tracing file much more manageable. Great job Tzvetomir!
>
> Only comment to this patch is, as I've said in other patches, I don't think
> we need to call this _v7, just "read_headers()" would suffice.

The read header logic is very different, we should name the old
function somehow. Now we have
           read_headers_v6() / read_headers_v7()
I can rename them to
           read_headers_old() / read_headers()
or
           read_headers_nosections() / read_headers_sections()

>
> -- Steve
[...]
Steven Rostedt Jan. 17, 2022, 4:17 p.m. UTC | #3
On Mon, 17 Jan 2022 17:47:27 +0200
Tzvetomir Stoyanov <tz.stoyanov@gmail.com> wrote:

> The read header logic is very different, we should name the old
> function somehow. Now we have
>            read_headers_v6() / read_headers_v7()
> I can rename them to
>            read_headers_old() / read_headers()
> or
>            read_headers_nosections() / read_headers_sections()

The _v6 names are fine. I'm only talking about the new _v7 ones (as
that's now the main ones, and v8 may use it too).

-- Steve
diff mbox series

Patch

diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c
index 8f95bf3b..9027729e 100644
--- a/lib/trace-cmd/trace-input.c
+++ b/lib/trace-cmd/trace-input.c
@@ -163,8 +163,7 @@  struct tracecmd_input {
 	struct pid_addr_maps	*pid_maps;
 	/* file information */
 	struct file_section	*sections;
-	size_t			header_files_start;
-	size_t			ftrace_files_start;
+	bool			options_init;
 	unsigned long long	options_start;
 	size_t			total_file_size;
 
@@ -917,19 +916,7 @@  static int read_cpus(struct tracecmd_input *handle)
 	return 0;
 }
 
-/**
- * tracecmd_read_headers - read the header information from trace.dat
- * @handle: input handle for the trace.dat file
- * @state: The state to read up to or zero to read up to options.
- *
- * This reads the trace.dat file for various information. Like the
- * format of the ring buffer, event formats, ftrace formats, kallsyms
- * and printk. This may be called multiple times with different @state
- * values, to read partial data at a time. It will always continue
- * where it left off.
- */
-int tracecmd_read_headers(struct tracecmd_input *handle,
-			  enum tracecmd_file_states state)
+static int read_headers_v6(struct tracecmd_input *handle, enum tracecmd_file_states state)
 {
 	int ret;
 
@@ -995,6 +982,126 @@  int tracecmd_read_headers(struct tracecmd_input *handle,
 	return 0;
 }
 
+static int handle_options(struct tracecmd_input *handle);
+
+static int read_section_header(struct tracecmd_input *handle, unsigned short *id,
+			       unsigned short *flags, unsigned long long *size, const char **description)
+{
+	unsigned short fl;
+	unsigned short sec_id;
+	unsigned long long sz;
+	int desc;
+
+	if (read2(handle, &sec_id))
+		return -1;
+	if (read4(handle, (unsigned int *)&desc))
+		return -1;
+	if (read2(handle, &fl))
+		return -1;
+	if (read8(handle, &sz))
+		return -1;
+
+	if (id)
+		*id = sec_id;
+	if (flags)
+		*flags = fl;
+	if (size)
+		*size = sz;
+
+	return 0;
+}
+
+static int handle_section(struct tracecmd_input *handle, struct file_section *section)
+{
+	unsigned short id, flags;
+	unsigned long long size;
+	int ret;
+
+	if (lseek64(handle->fd, section->section_offset, SEEK_SET) == (off_t)-1)
+		return -1;
+	if (read_section_header(handle, &id, &flags, &size, NULL))
+		return -1;
+	section->flags = flags;
+	if (id != section->id)
+		return -1;
+
+	section->data_offset = lseek64(handle->fd, 0, SEEK_CUR);
+
+	switch (section->id) {
+	case TRACECMD_OPTION_HEADER_INFO:
+		ret = read_header_files(handle);
+		break;
+	case TRACECMD_OPTION_FTRACE_EVENTS:
+		ret = read_ftrace_files(handle, NULL);
+		break;
+	case TRACECMD_OPTION_EVENT_FORMATS:
+		ret = read_event_files(handle, NULL);
+		break;
+	case TRACECMD_OPTION_KALLSYMS:
+		ret = read_proc_kallsyms(handle);
+		break;
+	case TRACECMD_OPTION_PRINTK:
+		ret = read_ftrace_printk(handle);
+		break;
+	case TRACECMD_OPTION_CMDLINES:
+		ret = read_and_parse_cmdlines(handle);
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+
+	return ret;
+}
+
+static int read_headers_v7(struct tracecmd_input *handle)
+{
+	struct file_section *section;
+
+	if (handle->options_init)
+		return 0;
+
+	if (!handle->options_start)
+		return -1;
+
+	if (lseek64(handle->fd, handle->options_start, SEEK_SET) == (off64_t)-1) {
+		tracecmd_warning("Filed to goto options offset %lld", handle->options_start);
+		return -1;
+	}
+
+	if (handle_options(handle))
+		return -1;
+
+	section = handle->sections;
+	while (section) {
+		if (handle_section(handle, section))
+			return -1;
+		section = section->next;
+	}
+
+	handle->options_init = true;
+	return 0;
+}
+
+/**
+ * tracecmd_read_headers - read the header information from trace.dat
+ * @handle: input handle for the trace.dat file
+ * @state: The state to read up to or zero to read up to options.
+ *
+ * This reads the trace.dat file for various information. Like the
+ * format of the ring buffer, event formats, ftrace formats, kallsyms
+ * and printk. This may be called multiple times with different @state
+ * values, to read partial data at a time. It will always continue
+ * where it left off.
+ */
+int tracecmd_read_headers(struct tracecmd_input *handle,
+			  enum tracecmd_file_states state)
+{
+	if (!HAS_SECTIONS(handle))
+		return read_headers_v6(handle, state);
+	return read_headers_v7(handle);
+}
+
 static unsigned long long calc_page_offset(struct tracecmd_input *handle,
 					   unsigned long long offset)
 {