Message ID | 20211210105448.97850-10-tz.stoyanov@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Trace file version 7 - sections | expand |
On Fri, 10 Dec 2021 12:54:32 +0200 "Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com> wrote: I'm going to keep mentioning spacing ;-) > Extended the BUFFER trace option in trace file version 7 with CPU > flyrecord trace metadata. In the version 6 of the trace file, this metadata > is located at several places in the file. Part of the metadata is only for > the top trace instance, thus limiting per-instance configuration. Moving > all CPU trace related metadata in the BUFFER option simplifies the parsing > and makes per-instance configuration more flexible. In the new file > structure, the top instance is treated as any other instances. space > The format of the extended BUFFER option is: > - offset of the buffer in the trace file > - name of the buffer > - trace clock, used in this buffer for events timestamps > - count of CPUs with trace data > - array, describing each CPU with trace data: > - CPU id > - offset of CPU trace data in the trace file > - size of the recorded CPU trace data > > Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com> > --- > lib/trace-cmd/trace-output.c | 191 +++++++++++++++++++++++++---------- > 1 file changed, 137 insertions(+), 54 deletions(-) > > diff --git a/lib/trace-cmd/trace-output.c b/lib/trace-cmd/trace-output.c > index 59093be2..6e40c929 100644 > --- a/lib/trace-cmd/trace-output.c > +++ b/lib/trace-cmd/trace-output.c > @@ -1675,7 +1675,7 @@ int tracecmd_append_options(struct tracecmd_output *handle) > } > > static struct tracecmd_option * > -add_buffer_option(struct tracecmd_output *handle, const char *name, int cpus) > +add_buffer_option_v6(struct tracecmd_output *handle, const char *name, int cpus) > { > struct tracecmd_option *option; > char *buf; > @@ -1725,8 +1725,11 @@ int tracecmd_write_buffer_info(struct tracecmd_output *handle) > struct tracecmd_option *option; > struct tracecmd_buffer *buf; > > + if (HAS_SECTIONS(handle)) > + return 0; > + > list_for_each_entry(buf, &handle->buffers, list) { > - option = add_buffer_option(handle, buf->name, buf->cpus); > + option = add_buffer_option_v6(handle, buf->name, buf->cpus); > if (!option) > return -1; > buf->option = option; > @@ -1777,6 +1780,98 @@ int tracecmd_write_cmdlines(struct tracecmd_output *handle) > return 0; > } > > +static char *get_clock(struct tracecmd_output *handle) > +{ > + struct tracefs_instance *inst; > + > + if (handle->trace_clock) > + return handle->trace_clock; > + > + /* > + * If no clock is set on this handle, get the trace clock of > + * the top instance in the handle's tracing dir > + */ > + inst = tracefs_instance_alloc(handle->tracing_dir, NULL); > + if (!inst) > + return NULL; > + handle->trace_clock = tracefs_get_clock(inst); Why allocate an instance, doesn't: tracefs_get_clock(NULL); do the same? (at least the man page says it does). Or are you worried that this has to do something with the tracing_dir? But do we care? > + tracefs_instance_free(inst); > + return handle->trace_clock; > +} > + > +__hidden struct tracecmd_option * > +out_add_buffer_option_v7(struct tracecmd_output *handle, const char *name, Again, I think it's safe to remove all the references to v7, and just have that be the default. > + unsigned short id, unsigned long long data_offset, > + int cpus, struct data_file_write *cpu_data) > +{ > + struct tracecmd_option *option; > + int i, j = 0, k = 0; > + int *cpu_ids = NULL; > + struct iovec *vect; > + char *clock; > + > + if (!HAS_SECTIONS(handle)) > + return NULL; > + > + clock = get_clock(handle); > + > + /* Buffer flyrecord option, v7: Including here (no need to say "v7") > + * - trace data offset in the file > + * - buffer name > + * - buffer clock > + * - CPU count > + * - for each CPU: > + * - CPU id > + * - CPU trace data offset in the file > + * - CPU trace data size > + */ > + > + /* Buffer latency option, v7: and here. > + * - trace data offset in the file > + * - buffer name > + * - buffer clock > + */ > + > + vect = calloc(5 + (cpus * 3), sizeof(struct iovec)); What's with the magical 5 and 3 numbers above? As from the comments above, I only count 4 and 3. 4 : offset, name, clock, count 3 : cpu offset, name, clock Could include the above in a comment too. -- Steve > + if (!vect) > + return NULL; > + if (cpus) { > + cpu_ids = calloc(cpus, sizeof(int)); > + if (!cpu_ids) { > + free(vect); > + return NULL; > + } > + } > + vect[j].iov_base = (void *) &data_offset; > + vect[j++].iov_len = 8; > + vect[j].iov_base = (void *) name; > + vect[j++].iov_len = strlen(name) + 1; > + vect[j].iov_base = (void *) clock; > + vect[j++].iov_len = strlen(clock) + 1; > + if (id == TRACECMD_OPTION_BUFFER) { > + vect[j].iov_base = (void *) &k; > + vect[j++].iov_len = 4; > + for (i = 0; i < cpus; i++) { > + if (!cpu_data[i].file_size) > + continue; > + cpu_ids[i] = i; > + vect[j].iov_base = &cpu_ids[i]; > + vect[j++].iov_len = 4; > + vect[j].iov_base = &cpu_data[i].data_offset; > + vect[j++].iov_len = 8; > + vect[j].iov_base = &cpu_data[i].write_size; > + vect[j++].iov_len = 8; > + k++; > + } > + } > + > + option = tracecmd_add_option_v(handle, id, vect, j); > + free(vect); > + free(cpu_ids); > + > + return option; > +} > + > struct tracecmd_output *tracecmd_create_file_latency(const char *output_file, int cpus) > { > struct tracecmd_output *handle; > @@ -1847,8 +1942,8 @@ out: > return ret; > }
On Sat, Jan 15, 2022 at 5:12 PM Steven Rostedt <rostedt@goodmis.org> wrote: > > On Fri, 10 Dec 2021 12:54:32 +0200 > "Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com> wrote: > > I'm going to keep mentioning spacing ;-) > > > Extended the BUFFER trace option in trace file version 7 with CPU > > flyrecord trace metadata. In the version 6 of the trace file, this metadata > > is located at several places in the file. Part of the metadata is only for > > the top trace instance, thus limiting per-instance configuration. Moving > > all CPU trace related metadata in the BUFFER option simplifies the parsing > > and makes per-instance configuration more flexible. In the new file > > structure, the top instance is treated as any other instances. > > space > > > The format of the extended BUFFER option is: > > - offset of the buffer in the trace file > > - name of the buffer > > - trace clock, used in this buffer for events timestamps > > - count of CPUs with trace data > > - array, describing each CPU with trace data: > > - CPU id > > - offset of CPU trace data in the trace file > > - size of the recorded CPU trace data > > > > Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com> > > --- > > lib/trace-cmd/trace-output.c | 191 +++++++++++++++++++++++++---------- > > 1 file changed, 137 insertions(+), 54 deletions(-) > > > > diff --git a/lib/trace-cmd/trace-output.c b/lib/trace-cmd/trace-output.c > > index 59093be2..6e40c929 100644 > > --- a/lib/trace-cmd/trace-output.c > > +++ b/lib/trace-cmd/trace-output.c > > @@ -1675,7 +1675,7 @@ int tracecmd_append_options(struct tracecmd_output *handle) > > } > > > > static struct tracecmd_option * > > -add_buffer_option(struct tracecmd_output *handle, const char *name, int cpus) > > +add_buffer_option_v6(struct tracecmd_output *handle, const char *name, int cpus) > > { > > struct tracecmd_option *option; > > char *buf; > > @@ -1725,8 +1725,11 @@ int tracecmd_write_buffer_info(struct tracecmd_output *handle) > > struct tracecmd_option *option; > > struct tracecmd_buffer *buf; > > > > + if (HAS_SECTIONS(handle)) > > + return 0; > > + > > list_for_each_entry(buf, &handle->buffers, list) { > > - option = add_buffer_option(handle, buf->name, buf->cpus); > > + option = add_buffer_option_v6(handle, buf->name, buf->cpus); > > if (!option) > > return -1; > > buf->option = option; > > @@ -1777,6 +1780,98 @@ int tracecmd_write_cmdlines(struct tracecmd_output *handle) > > return 0; > > } > > > > +static char *get_clock(struct tracecmd_output *handle) > > +{ > > + struct tracefs_instance *inst; > > + > > + if (handle->trace_clock) > > + return handle->trace_clock; > > + > > + /* > > + * If no clock is set on this handle, get the trace clock of > > + * the top instance in the handle's tracing dir > > + */ > > + inst = tracefs_instance_alloc(handle->tracing_dir, NULL); > > + if (!inst) > > + return NULL; > > + handle->trace_clock = tracefs_get_clock(inst); > > Why allocate an instance, doesn't: > > tracefs_get_clock(NULL); > > do the same? (at least the man page says it does). > > Or are you worried that this has to do something with the tracing_dir? > But do we care? Yes, because of tracing_dir. I'll add a check: if (!handle->tracing_dir) { handle->trace_clock = tracefs_get_clock(NULL); return handle->trace_clock; } which is the most common case. If there is tracing_dir associated with the handle, the old logic should be used - just to be on the safe side. > > > + tracefs_instance_free(inst); > > + return handle->trace_clock; > > +} > > + > > +__hidden struct tracecmd_option * > > +out_add_buffer_option_v7(struct tracecmd_output *handle, const char *name, > > Again, I think it's safe to remove all the references to v7, and just > have that be the default. > > > + unsigned short id, unsigned long long data_offset, > > + int cpus, struct data_file_write *cpu_data) > > +{ > > + struct tracecmd_option *option; > > + int i, j = 0, k = 0; > > + int *cpu_ids = NULL; > > + struct iovec *vect; > > + char *clock; > > + > > + if (!HAS_SECTIONS(handle)) > > + return NULL; > > + > > + clock = get_clock(handle); > > + > > + /* Buffer flyrecord option, v7: > > Including here (no need to say "v7") > > > + * - trace data offset in the file > > + * - buffer name > > + * - buffer clock > > + * - CPU count > > + * - for each CPU: > > + * - CPU id > > + * - CPU trace data offset in the file > > + * - CPU trace data size > > + */ > > + > > + /* Buffer latency option, v7: > > and here. > > > + * - trace data offset in the file > > + * - buffer name > > + * - buffer clock > > + */ > > + > > + vect = calloc(5 + (cpus * 3), sizeof(struct iovec)); > > What's with the magical 5 and 3 numbers above? > > As from the comments above, I only count 4 and 3. > > 4 : offset, name, clock, count > 3 : cpu offset, name, clock > > Could include the above in a comment too. > > -- Steve > > > + if (!vect) > > + return NULL; > > + if (cpus) { > > + cpu_ids = calloc(cpus, sizeof(int)); > > + if (!cpu_ids) { > > + free(vect); > > + return NULL; > > + } > > + } > > + vect[j].iov_base = (void *) &data_offset; > > + vect[j++].iov_len = 8; > > + vect[j].iov_base = (void *) name; > > + vect[j++].iov_len = strlen(name) + 1; > > + vect[j].iov_base = (void *) clock; > > + vect[j++].iov_len = strlen(clock) + 1; > > + if (id == TRACECMD_OPTION_BUFFER) { > > + vect[j].iov_base = (void *) &k; > > + vect[j++].iov_len = 4; > > + for (i = 0; i < cpus; i++) { > > + if (!cpu_data[i].file_size) > > + continue; > > + cpu_ids[i] = i; > > + vect[j].iov_base = &cpu_ids[i]; > > + vect[j++].iov_len = 4; > > + vect[j].iov_base = &cpu_data[i].data_offset; > > + vect[j++].iov_len = 8; > > + vect[j].iov_base = &cpu_data[i].write_size; > > + vect[j++].iov_len = 8; > > + k++; > > + } > > + } > > + > > + option = tracecmd_add_option_v(handle, id, vect, j); > > + free(vect); > > + free(cpu_ids); > > + > > + return option; > > +} > > + > > struct tracecmd_output *tracecmd_create_file_latency(const char *output_file, int cpus) > > { > > struct tracecmd_output *handle; > > @@ -1847,8 +1942,8 @@ out: > > return ret; > > }
diff --git a/lib/trace-cmd/trace-output.c b/lib/trace-cmd/trace-output.c index 59093be2..6e40c929 100644 --- a/lib/trace-cmd/trace-output.c +++ b/lib/trace-cmd/trace-output.c @@ -1675,7 +1675,7 @@ int tracecmd_append_options(struct tracecmd_output *handle) } static struct tracecmd_option * -add_buffer_option(struct tracecmd_output *handle, const char *name, int cpus) +add_buffer_option_v6(struct tracecmd_output *handle, const char *name, int cpus) { struct tracecmd_option *option; char *buf; @@ -1725,8 +1725,11 @@ int tracecmd_write_buffer_info(struct tracecmd_output *handle) struct tracecmd_option *option; struct tracecmd_buffer *buf; + if (HAS_SECTIONS(handle)) + return 0; + list_for_each_entry(buf, &handle->buffers, list) { - option = add_buffer_option(handle, buf->name, buf->cpus); + option = add_buffer_option_v6(handle, buf->name, buf->cpus); if (!option) return -1; buf->option = option; @@ -1777,6 +1780,98 @@ int tracecmd_write_cmdlines(struct tracecmd_output *handle) return 0; } +static char *get_clock(struct tracecmd_output *handle) +{ + struct tracefs_instance *inst; + + if (handle->trace_clock) + return handle->trace_clock; + + /* + * If no clock is set on this handle, get the trace clock of + * the top instance in the handle's tracing dir + */ + inst = tracefs_instance_alloc(handle->tracing_dir, NULL); + if (!inst) + return NULL; + handle->trace_clock = tracefs_get_clock(inst); + tracefs_instance_free(inst); + return handle->trace_clock; +} + +__hidden struct tracecmd_option * +out_add_buffer_option_v7(struct tracecmd_output *handle, const char *name, + unsigned short id, unsigned long long data_offset, + int cpus, struct data_file_write *cpu_data) +{ + struct tracecmd_option *option; + int i, j = 0, k = 0; + int *cpu_ids = NULL; + struct iovec *vect; + char *clock; + + if (!HAS_SECTIONS(handle)) + return NULL; + + clock = get_clock(handle); + + /* Buffer flyrecord option, v7: + * - trace data offset in the file + * - buffer name + * - buffer clock + * - CPU count + * - for each CPU: + * - CPU id + * - CPU trace data offset in the file + * - CPU trace data size + */ + + /* Buffer latency option, v7: + * - trace data offset in the file + * - buffer name + * - buffer clock + */ + + vect = calloc(5 + (cpus * 3), sizeof(struct iovec)); + if (!vect) + return NULL; + if (cpus) { + cpu_ids = calloc(cpus, sizeof(int)); + if (!cpu_ids) { + free(vect); + return NULL; + } + } + vect[j].iov_base = (void *) &data_offset; + vect[j++].iov_len = 8; + vect[j].iov_base = (void *) name; + vect[j++].iov_len = strlen(name) + 1; + vect[j].iov_base = (void *) clock; + vect[j++].iov_len = strlen(clock) + 1; + if (id == TRACECMD_OPTION_BUFFER) { + vect[j].iov_base = (void *) &k; + vect[j++].iov_len = 4; + for (i = 0; i < cpus; i++) { + if (!cpu_data[i].file_size) + continue; + cpu_ids[i] = i; + vect[j].iov_base = &cpu_ids[i]; + vect[j++].iov_len = 4; + vect[j].iov_base = &cpu_data[i].data_offset; + vect[j++].iov_len = 8; + vect[j].iov_base = &cpu_data[i].write_size; + vect[j++].iov_len = 8; + k++; + } + } + + option = tracecmd_add_option_v(handle, id, vect, j); + free(vect); + free(cpu_ids); + + return option; +} + struct tracecmd_output *tracecmd_create_file_latency(const char *output_file, int cpus) { struct tracecmd_output *handle; @@ -1847,8 +1942,8 @@ out: return ret; } -static int update_buffer_cpu_offset(struct tracecmd_output *handle, - const char *name, tsize_t offset) +static int update_buffer_cpu_offset_v6(struct tracecmd_output *handle, + const char *name, tsize_t offset) { tsize_t b_offset; tsize_t current; @@ -1881,26 +1976,6 @@ static int update_buffer_cpu_offset(struct tracecmd_output *handle, return 0; } - -static char *get_clock(struct tracecmd_output *handle) -{ - struct tracefs_instance *inst; - - if (handle->trace_clock) - return handle->trace_clock; - - /* - * If no clock is set on this handle, get the trace clock of - * the top instance in the handle's tracing dir - */ - inst = tracefs_instance_alloc(handle->tracing_dir, NULL); - if (!inst) - return NULL; - handle->trace_clock = tracefs_get_clock(inst); - tracefs_instance_free(inst); - return handle->trace_clock; -} - __hidden int out_write_cpu_data(struct tracecmd_output *handle, int cpus, struct cpu_data_source *data, const char *buff_name) { @@ -1924,7 +1999,7 @@ __hidden int out_write_cpu_data(struct tracecmd_output *handle, } data_offs = do_lseek(handle, 0, SEEK_CUR); - if (do_write_check(handle, "flyrecord", 10)) + if (!HAS_SECTIONS(handle) && do_write_check(handle, "flyrecord", 10)) goto out_free; data_files = calloc(cpus, sizeof(*data_files)); @@ -1937,19 +2012,23 @@ __hidden int out_write_cpu_data(struct tracecmd_output *handle, * Place 0 for the data offset and size, and save the offsets to * updated them with the correct data later. */ - endian8 = 0; - data_files[i].file_data_offset = do_lseek(handle, 0, SEEK_CUR); - if (do_write_check(handle, &endian8, 8)) - goto out_free; - data_files[i].file_write_size = do_lseek(handle, 0, SEEK_CUR); - if (do_write_check(handle, &endian8, 8)) - goto out_free; + if (!HAS_SECTIONS(handle)) { + endian8 = 0; + data_files[i].file_data_offset = do_lseek(handle, 0, SEEK_CUR); + if (do_write_check(handle, &endian8, 8)) + goto out_free; + data_files[i].file_write_size = do_lseek(handle, 0, SEEK_CUR); + if (do_write_check(handle, &endian8, 8)) + goto out_free; + } } - update_buffer_cpu_offset(handle, buff_name, data_offs); - clock = get_clock(handle); - if (clock && save_clock(handle, clock)) - goto out_free; + if (!HAS_SECTIONS(handle)) { + update_buffer_cpu_offset_v6(handle, buff_name, data_offs); + clock = get_clock(handle); + if (clock && save_clock(handle, clock)) + goto out_free; + } for (i = 0; i < cpus; i++) { data_files[i].data_offset = do_lseek(handle, 0, SEEK_CUR); @@ -1980,29 +2059,33 @@ __hidden int out_write_cpu_data(struct tracecmd_output *handle, data_files[i].write_size = 0; } - /* Write the real CPU data offset in the file */ - if (do_lseek(handle, data_files[i].file_data_offset, SEEK_SET) == (off64_t)-1) - goto out_free; - endian8 = convert_endian_8(handle, data_files[i].data_offset); - if (do_write_check(handle, &endian8, 8)) - goto out_free; - - /* Write the real CPU data size in the file */ - if (do_lseek(handle, data_files[i].file_write_size, SEEK_SET) == (off64_t)-1) - goto out_free; - endian8 = convert_endian_8(handle, data_files[i].write_size); - if (do_write_check(handle, &endian8, 8)) - goto out_free; - - offset = data_files[i].data_offset + data_files[i].write_size; - if (do_lseek(handle, offset, SEEK_SET) == (off64_t)-1) - goto out_free; - + if (!HAS_SECTIONS(handle)) { + /* Write the real CPU data offset in the file */ + if (do_lseek(handle, data_files[i].file_data_offset, SEEK_SET) == (off64_t)-1) + goto out_free; + endian8 = convert_endian_8(handle, data_files[i].data_offset); + if (do_write_check(handle, &endian8, 8)) + goto out_free; + /* Write the real CPU data size in the file */ + if (do_lseek(handle, data_files[i].file_write_size, SEEK_SET) == (off64_t)-1) + goto out_free; + endian8 = convert_endian_8(handle, data_files[i].write_size); + if (do_write_check(handle, &endian8, 8)) + goto out_free; + offset = data_files[i].data_offset + data_files[i].write_size; + if (do_lseek(handle, offset, SEEK_SET) == (off64_t)-1) + goto out_free; + } if (!tracecmd_get_quiet(handle)) fprintf(stderr, " %llu bytes in size\n", (unsigned long long)data_files[i].write_size); } + if (HAS_SECTIONS(handle) && + !out_add_buffer_option_v7(handle, buff_name, + TRACECMD_OPTION_BUFFER, data_offs, cpus, data_files)) + goto out_free; + free(data_files); if (do_lseek(handle, 0, SEEK_END) == (off64_t)-1) return -1;
Extended the BUFFER trace option in trace file version 7 with CPU flyrecord trace metadata. In the version 6 of the trace file, this metadata is located at several places in the file. Part of the metadata is only for the top trace instance, thus limiting per-instance configuration. Moving all CPU trace related metadata in the BUFFER option simplifies the parsing and makes per-instance configuration more flexible. In the new file structure, the top instance is treated as any other instances. The format of the extended BUFFER option is: - offset of the buffer in the trace file - name of the buffer - trace clock, used in this buffer for events timestamps - count of CPUs with trace data - array, describing each CPU with trace data: - CPU id - offset of CPU trace data in the trace file - size of the recorded CPU trace data Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com> --- lib/trace-cmd/trace-output.c | 191 +++++++++++++++++++++++++---------- 1 file changed, 137 insertions(+), 54 deletions(-)