perf tool: add meta-data header support for pipe-mode
v4 cover perf tool: add meta-data header support for pipe-mode
v4: - Limit write_* functions to page_size.
- Fixed bugs spotted by Jiri.
- Add information about pipe-mode to some error messages.
v3: - Fix header output for event aux record.
- Uniformize variable naming and other cleanup.
- Other fixes suggested by Jiri and Nahmyung.
v2: - Finer patch splitting.
- Add only one record type with a feature id instead of one record per new feature (as suggested by Jiri).
- Add perf.data documentation.
(This is a rebased and updated version of Stephane Eranian's version
in https://patchwork.kernel.org/patch/1499081/)
Up until now, meta-data was only available when perf record was used in "regular" mode, i.e., generating a perf.data file. For users depending on pipe mode, neither host or event header information were gathered. This patch addresses this limitation.
The difficulty in pipe mode is that information needs to be written sequentially to the pipe. Meta data headers are usually generated (and also expected) at the beginning of the file (or piped output). To solve this problem, we introduce new synthetic record types, one for each meta-data type. The approach is similar to what is *ALREADY* used for BUILD_ID and TRACING_DATA.
We have modified util/header.c such that the same routines are used to generate and read the meta-data information regardless of pipe-mode vs. regular mode. To make this work, we added a new struct called feat_fd which encapsulates all the information necessary to read or write meta-data information to a file/pipe or from a file/pipe.
With this series, it is possible to get:
$ perf record -o - -e cycles sleep 1 | perf report --stdio --header
# ========
# captured on: Mon May 22 16:33:43 2017
# ========
#
# hostname : my_hostname
# os release : 4.11.0-dbx-up_perf
# perf version : 4.11.rc6.g6277c80
# arch : x86_64
# nrcpus online : 72
# nrcpus avail : 72
# cpudesc : Intel(R) Xeon(R) CPU E5-2696 v3 @ 2.30GHz
# cpuid : GenuineIntel,6,63,2
# total memory : 263457192 kB
# cmdline : /root/perf record -e cycles sleep 1
# event : name = cycles, , size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|PERIOD, disabled = 1, inherit = 1, mmap = 1, comm = 1, freq = 1, enable_on_exec = 1, task = 1, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1
# CPU_TOPOLOGY info available, use -I to display
# NUMA_TOPOLOGY info available, use -I to display
# pmu mappings: intel_bts = 6, cpu = 4, msr = 49, uncore_cbox_10 = 36, [SNIP]
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.000 MB - ]
...Only patches 14 to 16 have a significant effect in user observed behavior. All other are transparent preparatory changes or bug fixes.
David Carrillo-Cisneros (16):
perf header: encapsulate read and swap
perf header: add PROCESS_STR_FUN macro
perf header: fail on write_padded error
perf util: add const modifier to buf in "writen" function perf header: revamp do_write
perf header: add struct feat_fd for write
perf header: use struct feat_fd for print
perf header: use struct feat_fd to process header records perf header: don't pass struct perf_file_section to process_##_feat perf header: use struct feat_fd in read header records perf header: make write_pmu_mappings pipe-mode friendly perf header: add a buffer to struct feat_fd
perf header: change FEAT_OP* macros
perf tool: add show_feature_header to perf_tool
perf tools: add feature header record to pipe-mode
perf header: add event desc to pipe-mode header
tools/perf/Documentation/perf.data-file-format.txt | 10 +- tools/perf/builtin-annotate.c | 1 + tools/perf/builtin-inject.c | 1 + tools/perf/builtin-record.c | 7 + tools/perf/builtin-report.c | 12 +- tools/perf/builtin-script.c | 4 + tools/perf/util/build-id.c | 10 +- tools/perf/util/build-id.h | 4 +- tools/perf/util/event.c | 1 + tools/perf/util/event.h | 8 + tools/perf/util/header.c | 1009 +++++++++++--------- tools/perf/util/header.h | 16 +- tools/perf/util/session.c | 4 + tools/perf/util/tool.h | 10 +- tools/perf/util/util.c | 6 +- tools/perf/util/util.h | 2 +- 16 files changed, 634 insertions(+), 471 deletions(-)
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 1/16 perf header: encapsulate read and swap
Most callers of readn in perf header read either a 32 or a 64 bits number, error check it and swap it, if necessary.
Create do_read_u32 and do_read_u64 to simplify these use cases.
--- tools/perf/util/header.c | 210 +++++++++++++++++------------------------------ 1 file changed, 77 insertions(+), 133 deletions(-)
tools/perf/util/header.c +77 -133
@@ -118,25 +118,54 @@ static int do_write_string(int fd, const char *str)return write_padded (fd, str, olen, len); } +static int __do_read (int fd,void *addr,ssize_t size) +{ +ssize_t ret =readn (fd, addr, size); + +if (ret != size) +return ret <0 ? (int )ret :-1 ; +return 0 ; +} + +static int do_read_u32 (int fd,struct perf_header *ph,u32 *addr) +{ +int ret; + + ret =__do_read (fd, addr,sizeof (*addr)); +if (ret) +return ret; + +if (ph->needs_swap) + *addr =bswap_32 (*addr); +return 0 ; +} + +static int do_read_u64 (int fd,struct perf_header *ph,u64 *addr) +{ +int ret; + + ret =__do_read (fd, addr,sizeof (*addr)); +if (ret) +return ret; + +if (ph->needs_swap) + *addr =bswap_64 (*addr); +return 0 ; +} +static char *do_read_string (int fd,struct perf_header *ph) { -ssize_t sz, ret;u32 len;char *buf; - sz =readn (fd, &len,sizeof (len)); -if (sz < (ssize_t )sizeof (len)) +if (do_read_u32 (fd, ph, &len))return NULL ; -if (ph->needs_swap) - len =bswap_32 (len); - buf =malloc (len);if (!buf)return NULL ; - ret =readn (fd, buf, len); -if (ret == (ssize_t )len) { +if (!__do_read (fd, buf, len)) {/* * strings are padded by zeroes * thus the actual strlen of buf
@@ -1187,24 +1216,15 @@ read_event_desc(struct perf_header *ph, int fd)u64 *id;void *buf =NULL ;u32 nre, sz, nr, i, j; -ssize_t ret;size_t msz;/* number of events */ - ret =readn (fd, &nre,sizeof (nre)); -if (ret != (ssize_t )sizeof (nre)) +if (do_read_u32 (fd, ph, &nre)) goto error; -if (ph->needs_swap) - nre =bswap_32 (nre); - - ret =readn (fd, &sz,sizeof (sz)); -if (ret != (ssize_t )sizeof (sz)) +if (do_read_u32 (fd, ph, &sz)) goto error; -if (ph->needs_swap) - sz =bswap_32 (sz); -/* buffer to hold on file attr struct */ buf =malloc (sz);if (!buf)
@@ -1226,8 +1246,7 @@ read_event_desc(struct perf_header *ph, int fd)* must read entire on-file attr struct to * sync up with layout. */ - ret =readn (fd, buf, sz); -if (ret != (ssize_t )sz) +if (__do_read (fd, buf, sz)) goto error;if (ph->needs_swap)
@@ -1235,16 +1254,15 @@ read_event_desc(struct perf_header *ph, int fd)memcpy (&evsel->attr, buf, msz); - ret =readn (fd, &nr,sizeof (nr)); -if (ret != (ssize_t )sizeof (nr)) +if (do_read_u32 (fd, ph, &nr)) goto error; -if (ph->needs_swap) { - nr =bswap_32 (nr); +if (ph->needs_swap) evsel->needs_swap = true; - } evsel->name =do_read_string (fd, ph); +if (!evsel->name) + goto error;if (!nr)continue ;
@@ -1256,11 +1274,8 @@ read_event_desc(struct perf_header *ph, int fd) evsel->id = id;for (j =0 ; j < nr; j++) { - ret =readn (fd, id,sizeof (*id)); -if (ret != (ssize_t )sizeof (*id)) +if (do_read_u64 (fd, ph, id)) goto error; -if (ph->needs_swap) - *id =bswap_64 (*id); id++; } }
@@ -1640,26 +1655,18 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused, struct perf_header *ph, int fd, void *data __maybe_unused) { - ssize_t ret; -u32 nr; - - ret =readn (fd, &nr,sizeof (nr)); -if (ret !=sizeof (nr)) -return -1 ; - -if (ph->needs_swap) - nr =bswap_32 (nr); - - ph->env.nr_cpus_avail = nr; - - ret =readn (fd, &nr,sizeof (nr)); -if (ret !=sizeof (nr)) -return -1 ; + int ret; +u32 nr_cpus_avail, nr_cpus_online; -if (ph->needs_swap) - nr =bswap_32 (nr); + ret =do_read_u32 (fd, ph, &nr_cpus_avail); +if (ret) +return ret; - ph->env.nr_cpus_online = nr; + ret =do_read_u32 (fd, ph, &nr_cpus_online); +if (ret) +return ret; + ph->env.nr_cpus_avail = (int )nr_cpus_avail; + ph->env.nr_cpus_online = (int )nr_cpus_online;return 0 ; }
@@ -1683,17 +1690,13 @@ static int process_total_mem(struct perf_file_section *section __maybe_unused, struct perf_header *ph, int fd, void *data __maybe_unused) { - uint64_t mem; -ssize_t ret; + u64 total_mem; +int ret; - ret =readn (fd, &mem,sizeof (mem)); -if (ret !=sizeof (mem)) + ret =do_read_u64 (fd, ph, &total_mem); +if (ret)return -1 ; - -if (ph->needs_swap) - mem =bswap_64 (mem); - - ph->env.total_mem = mem; + ph->env.total_mem = (unsigned long long )total_mem;return 0 ; }
@@ -1753,17 +1756,12 @@ static int process_cmdline(struct perf_file_section *section, struct perf_header *ph, int fd, void *data __maybe_unused) { - ssize_t ret; char *str, *cmdline = NULL, **argv = NULL;u32 nr, i, len =0 ; - ret =readn (fd, &nr,sizeof (nr)); -if (ret !=sizeof (nr)) +if (do_read_u32 (fd, ph, &nr))return -1 ; -if (ph->needs_swap) - nr =bswap_32 (nr); - ph->env.nr_cmdline = nr; cmdline =zalloc (section->size + nr +1 );
@@ -1798,7 +1796,6 @@ static int process_cpu_topology(struct perf_file_section *section, struct perf_header *ph, int fd, void *data __maybe_unused) { - ssize_t ret; u32 nr, i;char *str;struct strbuf sb;
@@ -1809,13 +1806,9 @@ static int process_cpu_topology(struct perf_file_section *section,if (!ph->env.cpu)return -1 ; - ret =readn (fd, &nr,sizeof (nr)); -if (ret !=sizeof (nr)) +if (do_read_u32 (fd, ph, &nr)) goto free_cpu; -if (ph->needs_swap) - nr =bswap_32 (nr); - ph->env.nr_sibling_cores = nr; size +=sizeof (u32);if (strbuf_init (&sb,128 ) <0 )
@@ -1834,13 +1827,9 @@ static int process_cpu_topology(struct perf_file_section *section, } ph->env.sibling_cores =strbuf_detach (&sb,NULL ); - ret =readn (fd, &nr,sizeof (nr)); -if (ret !=sizeof (nr)) +if (do_read_u32 (fd, ph, &nr))return -1 ; -if (ph->needs_swap) - nr =bswap_32 (nr); - ph->env.nr_sibling_threads = nr; size +=sizeof (u32);
@@ -1867,22 +1856,14 @@ static int process_cpu_topology(struct perf_file_section *section, }for (i =0 ; i < (u32 )cpu_nr; i++) { - ret =readn (fd, &nr,sizeof (nr)); -if (ret !=sizeof (nr)) +if (do_read_u32 (fd, ph, &nr)) goto free_cpu; -if (ph->needs_swap) - nr =bswap_32 (nr); - ph->env.cpu[i].core_id = nr; - ret =readn (fd, &nr,sizeof (nr)); -if (ret !=sizeof (nr)) +if (do_read_u32 (fd, ph, &nr)) goto free_cpu; -if (ph->needs_swap) - nr =bswap_32 (nr); -if (nr != (u32)-1 && nr > (u32 )cpu_nr) {pr_debug ("socket_id number is too big." "You may need to upgrade the perf tool.\n" );
@@ -1906,18 +1887,13 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse void *data __maybe_unused) {struct numa_node *nodes, *n; -ssize_t ret;u32 nr, i;char *str;/* nr nodes */ - ret =readn (fd, &nr,sizeof (nr)); -if (ret !=sizeof (nr)) +if (do_read_u32 (fd, ph, &nr))return -1 ; -if (ph->needs_swap) - nr =bswap_32 (nr); - nodes =zalloc (sizeof (*nodes) * nr);if (!nodes)return -ENOMEM ;
@@ -1926,24 +1902,15 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse n = &nodes[i];/* node number */ - ret =readn (fd, &n->node,sizeof (u32)); -if (ret !=sizeof (n->node)) +if (do_read_u32 (fd, ph, &n->node)) goto error; - ret =readn (fd, &n->mem_total,sizeof (u64)); -if (ret !=sizeof (u64)) +if (do_read_u64 (fd, ph, &n->mem_total)) goto error; - ret =readn (fd, &n->mem_free,sizeof (u64)); -if (ret !=sizeof (u64)) +if (do_read_u64 (fd, ph, &n->mem_free)) goto error; -if (ph->needs_swap) { - n->node =bswap_32 (n->node); - n->mem_total =bswap_64 (n->mem_total); - n->mem_free =bswap_64 (n->mem_free); - } - str =do_read_string (fd, ph);if (!str) goto error;
@@ -1967,19 +1934,14 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused struct perf_header *ph, int fd, void *data __maybe_unused) { - ssize_t ret; char *name;u32 pmu_num;u32 type;struct strbuf sb; - ret =readn (fd, &pmu_num,sizeof (pmu_num)); -if (ret !=sizeof (pmu_num)) +if (do_read_u32 (fd, ph, &pmu_num))return -1 ; -if (ph->needs_swap) - pmu_num =bswap_32 (pmu_num); -if (!pmu_num) {pr_debug ("pmu mappings not available\n" );return 0 ;
@@ -1990,10 +1952,8 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unusedreturn -1 ;while (pmu_num) { -if (readn (fd, &type,sizeof (type)) !=sizeof (type)) +if (do_read_u32 (fd, ph, &type)) goto error; -if (ph->needs_swap) - type =bswap_32 (type); name =do_read_string (fd, ph);if (!name)
@@ -2033,12 +1993,9 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,u32 nr_members; } *desc; -if (readn (fd, &nr_groups,sizeof (nr_groups)) !=sizeof (nr_groups)) +if (do_read_u32 (fd, ph, &nr_groups))return -1 ; -if (ph->needs_swap) - nr_groups =bswap_32 (nr_groups); - ph->env.nr_groups = nr_groups;if (!nr_groups) {pr_debug ("group desc not available\n" );
@@ -2054,16 +2011,11 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,if (!desc[i].name) goto out_free; -if (readn (fd, &desc[i].leader_idx,sizeof (u32)) !=sizeof (u32)) +if (do_read_u32 (fd, ph, &desc[i].leader_idx)) goto out_free; -if (readn (fd, &desc[i].nr_members,sizeof (u32)) !=sizeof (u32)) +if (do_read_u32 (fd, ph, &desc[i].nr_members)) goto out_free; - -if (ph->needs_swap) { - desc[i].leader_idx =bswap_32 (desc[i].leader_idx); - desc[i].nr_members =bswap_32 (desc[i].nr_members); - } }/*
@@ -2136,21 +2088,15 @@ static int process_cache(struct perf_file_section *section __maybe_unused,struct cpu_cache_level *caches;u32 cnt, i, version; -if (readn (fd, &version,sizeof (version)) !=sizeof (version)) +if (do_read_u32 (fd, ph, &version))return -1 ; -if (ph->needs_swap) - version =bswap_32 (version); -if (version !=1 )return -1 ; -if (readn (fd, &cnt,sizeof (cnt)) !=sizeof (cnt)) +if (do_read_u32 (fd, ph, &cnt))return -1 ; -if (ph->needs_swap) - cnt =bswap_32 (cnt); - caches =zalloc (sizeof (*caches) * cnt);if (!caches)return -1 ;
@@ -2159,10 +2105,8 @@ static int process_cache(struct perf_file_section *section __maybe_unused,struct cpu_cache_level c;#define _R (v) \ - if (readn(fd, &c.v, sizeof(u32)) != sizeof(u32))\ + if (do_read_u32(fd, ph, &c.v))\ goto out_free_caches; \ - if (ph->needs_swap) \ - c.v = bswap_32(c.v); \_R (level)_R (line_size)
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 2/16 perf header: add PROCESS_STR_FUN macro
In reply to David Carrillo-CisnerosSimplify code by adding a macro to handle the common case of processing header features that are a simple string.
--- tools/perf/util/header.c | 65 +++++++++++++----------------------------------- 1 file changed, 17 insertions(+), 48 deletions(-)
tools/perf/util/header.c +17 -48
@@ -1602,6 +1602,23 @@ static int perf_header__read_build_ids(struct perf_header *header,return err; } +/* Macro for features that simply need to read and store a string. */ +#define FEAT_PROCESS_STR_FUN (__feat, __feat_env) \ +static int process_##__feat(struct perf_file_section *section __maybe_unused, \ + struct perf_header *ph, int fd, \ + void *data __maybe_unused) \ +{\ + ph->env.__feat_env = do_read_string(fd, ph); \ + return ph->env.__feat_env ? 0 : -ENOMEM; \ +} + +FEAT_PROCESS_STR_FUN (hostname, hostname); +FEAT_PROCESS_STR_FUN (osrelease, os_release); +FEAT_PROCESS_STR_FUN (version, version); +FEAT_PROCESS_STR_FUN (arch, arch); +FEAT_PROCESS_STR_FUN (cpudesc, cpu_desc); +FEAT_PROCESS_STR_FUN (cpuid, cpuid); +static int process_tracing_data (struct perf_file_section *section__maybe_unused ,struct perf_header *ph__maybe_unused ,int fd,void *data)
@@ -1619,38 +1636,6 @@ static int process_build_id(struct perf_file_section *section,return 0 ; } -static int process_hostname (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) -{ - ph->env.hostname =do_read_string (fd, ph); -return ph->env.hostname ?0 : -ENOMEM ; -} - -static int process_osrelease (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) -{ - ph->env.os_release =do_read_string (fd, ph); -return ph->env.os_release ?0 : -ENOMEM ; -} - -static int process_version (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) -{ - ph->env.version =do_read_string (fd, ph); -return ph->env.version ?0 : -ENOMEM ; -} - -static int process_arch (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) -{ - ph->env.arch =do_read_string (fd, ph); -return ph->env.arch ?0 : -ENOMEM ; -} -static int process_nrcpus (struct perf_file_section *section__maybe_unused ,struct perf_header *ph,int fd,void *data__maybe_unused )
@@ -1670,22 +1655,6 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,return 0 ; } -static int process_cpudesc (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) -{ - ph->env.cpu_desc =do_read_string (fd, ph); -return ph->env.cpu_desc ?0 : -ENOMEM ; -} - -static int process_cpuid (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) -{ - ph->env.cpuid =do_read_string (fd, ph); -return ph->env.cpuid ?0 : -ENOMEM ; -} -static int process_total_mem (struct perf_file_section *section__maybe_unused ,struct perf_header *ph,int fd,void *data__maybe_unused )
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 3/16 perf header: fail on write_padded error
In reply to David Carrillo-CisnerosDo not proceed if write_padded error failed.
Also, add comments to remind that the return value of write_* functions in util/header.c is an erro code and not the number of bytes written.
--- tools/perf/util/header.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
tools/perf/util/header.c +5 -1
@@ -73,6 +73,7 @@ bool perf_header__has_feat(const struct perf_header *header, int feat)return test_bit (feat, header->adds_features); } +/* Return: 0 if succeded, -ERR if failed. */ static int do_write (int fd,const void *buf,size_t size) {while (size) {
@@ -88,6 +89,7 @@ static int do_write(int fd, const void *buf, size_t size)return 0 ; } +/* Return: 0 if succeded, -ERR if failed. */ int write_padded (int fd,const void *bf,size_t count,size_t count_aligned) {static const char zero_buf[NAME_ALIGN ];
@@ -102,6 +104,7 @@ int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)#define string_size (str) \ (PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32)) +/* Return: 0 if succeded, -ERR if failed. */ static int do_write_string (int fd,const char *str) {u32 len, olen;
@@ -3199,7 +3202,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,*/ tracing_data_put (tdata); -write_padded (fd,NULL ,0 , padding); +if (write_padded (fd,NULL ,0 , padding)) +return -1 ;return aligned_size; }
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 4/16 perf util: add const modifier to buf in "writen" function
In reply to David Carrillo-CisnerosMake buf in helper function "writen" constant to simplify the life of its callers.
This requires to hack a cast of buf prior to passing it to "ion" which is simpler than the alternative of reworking the "ion" function to provide a read and a write paths, the latter with constant buf argument.
--- tools/perf/util/util.c | 6 ++++-- tools/perf/util/util.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-)
tools/perf/util/util.c +4 -2
@@ -259,6 +259,7 @@ static ssize_t ion(bool is_read, int fd, void *buf, size_t n)size_t left = n;while (left) { +/* buf must be treated as const if !is_read. */ ssize_t ret = is_read ?read (fd, buf, left) :write (fd, buf, left);
@@ -286,9 +287,10 @@ ssize_t readn(int fd, void *buf, size_t n)/* * Write exactly 'n' bytes or return an error. */ -ssize_t writen (int fd,void *buf,size_t n) +ssize_t writen (int fd,const void *buf,size_t n) { -return ion (false, fd, buf, n); +/* ion does not modify buf. */ +return ion (false, fd, (void *)buf, n); }size_t hex_width (u64 v)
tools/perf/util/util.h +1 -1
@@ -49,7 +49,7 @@ int copyfile_mode(const char *from, const char *to, mode_t mode);int copyfile_offset (int fromfd,loff_t from_ofs,int tofd,loff_t to_ofs,u64 size);ssize_t readn (int fd,void *buf,size_t n); -ssize_t writen (int fd,void *buf,size_t n); +ssize_t writen (int fd,const void *buf,size_t n);size_t hex_width (u64 v);int hex2u64 (const char *ptr,u64 *val);
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 5/16 perf header: revamp do_write
In reply to David Carrillo-CisnerosNow that writen takes a const buffer, use it in do_write instead of duplicating its functionality.
Export do_write to use it consistently in header.c and build_id.c .
--- tools/perf/util/build-id.c | 2 +- tools/perf/util/header.c | 14 +++++--------- tools/perf/util/header.h | 2 ++ 3 files changed, 8 insertions(+), 10 deletions(-)
tools/perf/util/build-id.c +1 -1
@@ -345,7 +345,7 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id, b.header.misc = misc; b.header.size =sizeof (b) + len; - err =writen (fd, &b,sizeof (b)); + err =do_write (fd, &b,sizeof (b));if (err <0 )return err;
tools/perf/util/header.c +5 -9
@@ -74,17 +74,13 @@ bool perf_header__has_feat(const struct perf_header *header, int feat) }/* Return: 0 if succeded, -ERR if failed. */ -static int do_write (int fd,const void *buf,size_t size) +int do_write (int fd,const void *buf,size_t size) { -while (size) { -int ret =write (fd, buf, size); - -if (ret <0 ) -return -errno; +ssize_t ret; - size -= ret; - buf += ret; - } + ret =writen (fd, buf, size); +if (ret != (ssize_t )size) +return ret <0 ? (int )ret :-1 ;return 0 ; }
tools/perf/util/header.h +2 -0
@@ -144,6 +144,8 @@ bool is_perf_magic(u64 magic);#define NAME_ALIGN 64 +int do_write (int fd,const void *buf,size_t size); +int write_padded (int fd,const void *bf,size_t count,size_t count_aligned);/*
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 6/16 perf header: add struct feat_fd for write
In reply to David Carrillo-CisnerosIntroduce struct feat_fd. This patch uses it as a wrapper around fd in write_* functions for feature headers. Next patches will extend its functionality to other feature header functions.
This patch does not change behavior.
--- tools/perf/util/build-id.c | 8 +- tools/perf/util/build-id.h | 4 +- tools/perf/util/header.c | 230 ++++++++++++++++++++++++--------------------- tools/perf/util/header.h | 7 +- 4 files changed, 138 insertions(+), 111 deletions(-)
tools/perf/util/build-id.c +5 -3
@@ -330,7 +330,7 @@ bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)else static int write_buildid(const char *name, size_t name_len, u8 *build_id, -pid_t pid,u16 misc,int fd) +pid_t pid,u16 misc,struct feat_fd *fd) {int err;struct build_id_event b;
@@ -352,7 +352,8 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id,return write_padded (fd, name, name_len +1 , len); } -static int machine__write_buildid_table (struct machine *machine,int fd) +static int machine__write_buildid_table (struct machine *machine, +struct feat_fd *fd) {int err =0 ;char nm[PATH_MAX ];
@@ -397,7 +398,8 @@ static int machine__write_buildid_table(struct machine *machine, int fd)return err; } -int perf_session__write_buildid_table (struct perf_session *session,int fd) +int perf_session__write_buildid_table (struct perf_session *session, +struct feat_fd *fd) {struct rb_node *nd;int err =machine__write_buildid_table (&session->machines.host, fd);
tools/perf/util/build-id.h +3 -1
@@ -9,6 +9,7 @@extern struct perf_tool build_id__mark_dso_hit_ops;struct dso ; +struct feat_fd ;int build_id__sprintf (const u8 *build_id,int len,char *bf);int sysfs__sprintf_build_id (const char *root_dir,char *sbuild_id);
@@ -26,7 +27,8 @@ int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,int dsos__hit_all (struct perf_session *session);bool perf_session__read_build_ids (struct perf_session *session,bool with_hits); -int perf_session__write_buildid_table (struct perf_session *session,int fd); +int perf_session__write_buildid_table (struct perf_session *session, +struct feat_fd *fd);int perf_session__cache_build_ids (struct perf_session *session);char *build_id_cache__origname (const char *sbuild_id);
tools/perf/util/header.c +125 -105
723 lines not on this page · raw message
tools/perf/util/header.h +5 -2
@@ -144,9 +144,12 @@ bool is_perf_magic(u64 magic);#define NAME_ALIGN 64 -int do_write (int fd,const void *buf,size_t size); +struct feat_fd ; -int write_padded (int fd,const void *bf,size_t count,size_t count_aligned); +int do_write (struct feat_fd *fd,const void *buf,size_t size); + +int write_padded (struct feat_fd *fd,const void *bf, +size_t count,size_t count_aligned);/* * arch specific callback
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 7/16 perf header: use struct feat_fd for print
In reply to David Carrillo-CisnerosAs preparation for using header records in pipe mode, replace int fd with struct feat_fd ff in print functions for all header record types.
--- tools/perf/util/header.c | 102 ++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 55 deletions(-)
tools/perf/util/header.c +47 -55
@@ -1115,62 +1115,56 @@ static int write_stat(struct feat_fd *ff __maybe_unused,return 0 ; } -static void print_hostname (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_hostname (struct feat_fd *ff,FILE *fp) { -fprintf (fp,"# hostname : %s\n" , ph->env.hostname); +fprintf (fp,"# hostname : %s\n" , ff->ph->env.hostname); } -static void print_osrelease (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_osrelease (struct feat_fd *ff,FILE *fp) { -fprintf (fp,"# os release : %s\n" , ph->env.os_release); +fprintf (fp,"# os release : %s\n" , ff->ph->env.os_release); } -static void print_arch (struct perf_header *ph,int fd__maybe_unused ,FILE *fp) +static void print_arch (struct feat_fd *ff,FILE *fp) { -fprintf (fp,"# arch : %s\n" , ph->env.arch); +fprintf (fp,"# arch : %s\n" , ff->ph->env.arch); } -static void print_cpudesc (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_cpudesc (struct feat_fd *ff,FILE *fp) { -fprintf (fp,"# cpudesc : %s\n" , ph->env.cpu_desc); +fprintf (fp,"# cpudesc : %s\n" , ff->ph->env.cpu_desc); } -static void print_nrcpus (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_nrcpus (struct feat_fd *ff,FILE *fp) { -fprintf (fp,"# nrcpus online : %u\n" , ph->env.nr_cpus_online); -fprintf (fp,"# nrcpus avail : %u\n" , ph->env.nr_cpus_avail); +fprintf (fp,"# nrcpus online : %u\n" , ff->ph->env.nr_cpus_online); +fprintf (fp,"# nrcpus avail : %u\n" , ff->ph->env.nr_cpus_avail); } -static void print_version (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_version (struct feat_fd *ff,FILE *fp) { -fprintf (fp,"# perf version : %s\n" , ph->env.version); +fprintf (fp,"# perf version : %s\n" , ff->ph->env.version); } -static void print_cmdline (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_cmdline (struct feat_fd *ff,FILE *fp) {int nr, i; - nr = ph->env.nr_cmdline; + nr = ff->ph->env.nr_cmdline;fprintf (fp,"# cmdline : " );for (i =0 ; i < nr; i++) -fprintf (fp,"%s " , ph->env.cmdline_argv[i]); +fprintf (fp,"%s " , ff->ph->env.cmdline_argv[i]);fputc ('\n' , fp); } -static void print_cpu_topology (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_cpu_topology (struct feat_fd *ff,FILE *fp) { +struct perf_header *ph = ff->ph; +int cpu_nr = ph->env.nr_cpus_avail;int nr, i;char *str; -int cpu_nr = ph->env.nr_cpus_avail; nr = ph->env.nr_sibling_cores; str = ph->env.sibling_cores;
@@ -1296,9 +1290,9 @@ static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,return fprintf (fp,", %s = %s" , name, val); } -static void print_event_desc (struct perf_header *ph,int fd,FILE *fp) +static void print_event_desc (struct feat_fd *ff,FILE *fp) { -struct perf_evsel *evsel, *events =read_event_desc (ph, fd); +struct perf_evsel *evsel, *events =read_event_desc (ff->ph, ff->fd);u32 j;u64 *id;
@@ -1328,20 +1322,18 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)free_event_desc (events); } -static void print_total_mem (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_total_mem (struct feat_fd *ff,FILE *fp) { -fprintf (fp,"# total memory : %Lu kB\n" , ph->env.total_mem); +fprintf (fp,"# total memory : %llu kB\n" , ff->ph->env.total_mem); } -static void print_numa_topology (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_numa_topology (struct feat_fd *ff,FILE *fp) {int i;struct numa_node *n; -for (i =0 ; i < ph->env.nr_numa_nodes; i++) { - n = &ph->env.numa_nodes[i]; +for (i =0 ; i < ff->ph->env.nr_numa_nodes; i++) { + n = &ff->ph->env.numa_nodes[i]; fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," " free = %"PRIu64" kB\n",
@@ -1352,56 +1344,51 @@ static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused, } } -static void print_cpuid (struct perf_header *ph,int fd__maybe_unused ,FILE *fp) +static void print_cpuid (struct feat_fd *ff,FILE *fp) { -fprintf (fp,"# cpuid : %s\n" , ph->env.cpuid); +fprintf (fp,"# cpuid : %s\n" , ff->ph->env.cpuid); } -static void print_branch_stack (struct perf_header *ph__maybe_unused , -int fd__maybe_unused ,FILE *fp) +static void print_branch_stack (struct feat_fd *ff__maybe_unused ,FILE *fp) {fprintf (fp,"# contains samples with branch stack\n" ); } -static void print_auxtrace (struct perf_header *ph__maybe_unused , -int fd__maybe_unused ,FILE *fp) +static void print_auxtrace (struct feat_fd *ff__maybe_unused ,FILE *fp) {fprintf (fp,"# contains AUX area data (e.g. instruction trace)\n" ); } -static void print_stat (struct perf_header *ph__maybe_unused , -int fd__maybe_unused ,FILE *fp) +static void print_stat (struct feat_fd *ff__maybe_unused ,FILE *fp) {fprintf (fp,"# contains stat data\n" ); } -static void print_cache (struct perf_header *ph__maybe_unused , -int fd__maybe_unused ,FILE *fp__maybe_unused ) +static void print_cache (struct feat_fd *ff,FILE *fp__maybe_unused ) {int i;fprintf (fp,"# CPU cache info:\n" ); -for (i =0 ; i < ph->env.caches_cnt; i++) { +for (i =0 ; i < ff->ph->env.caches_cnt; i++) {fprintf (fp,"# " ); -cpu_cache_level__fprintf (fp, &ph->env.caches[i]); +cpu_cache_level__fprintf (fp, &ff->ph->env.caches[i]); } } -static void print_pmu_mappings (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_pmu_mappings (struct feat_fd *ff,FILE *fp) {const char *delimiter ="# pmu mappings: " ;char *str, *tmp;u32 pmu_num;u32 type; - pmu_num = ph->env.nr_pmu_mappings; + pmu_num = ff->ph->env.nr_pmu_mappings;if (!pmu_num) {fprintf (fp,"# pmu mappings: not available\n" );return ; } - str = ph->env.pmu_mappings; + str = ff->ph->env.pmu_mappings;while (pmu_num) { type =strtoul (str, &tmp,0 );
@@ -1424,14 +1411,13 @@ static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused,fprintf (fp,"# pmu mappings: unable to read\n" ); } -static void print_group_desc (struct perf_header *ph,int fd__maybe_unused , -FILE *fp) +static void print_group_desc (struct feat_fd *ff,FILE *fp) {struct perf_session *session;struct perf_evsel *evsel;u32 nr =0 ; - session = container_of(ph, struct perf_session, header); + session = container_of(ff->ph, struct perf_session, header);evlist__for_each_entry (session->evlist, evsel) { if (perf_evsel__is_group_leader(evsel) &&
@@ -2108,7 +2094,7 @@ static int process_cache(struct perf_file_section *section __maybe_unused,struct feature_ops {int (*write)(struct feat_fd *ff,struct perf_evlist *evlist); -void (*print)(struct perf_header *h,int fd,FILE *fp); +void (*print)(struct feat_fd *ff,FILE *fp);int (*process)(struct perf_file_section *section,struct perf_header *h,int fd,void *data);const char *name;
@@ -2161,6 +2147,7 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section, int feat, int fd, void *data) { struct header_print_data *hd = data; +struct feat_fd ff;if (lseek (fd, section->offset,SEEK_SET ) == (off_t)-1 ) { pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
@@ -2174,8 +2161,13 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section,if (!feat_ops[feat].print)return 0 ; + ff = (struct feat_fd ) { + .fd = fd, + .ph = ph, + }; +if (!feat_ops[feat].full_only || hd->full) - feat_ops[feat].else fprintf (hd->fp,"# %s info available, use -I to display\n" , feat_ops[feat].name);
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 8/16 perf header: use struct feat_fd to process header records
In reply to David Carrillo-CisnerosAs preparation for using header records in pipe-mode, replace int fd with struct feat_fd ff in process functions for all header record types.
This patch does not change behavior.
--- tools/perf/util/header.c | 164 +++++++++++++++++++++++------------------------ 1 file changed, 79 insertions(+), 85 deletions(-)
tools/perf/util/header.c +79 -85
@@ -1593,11 +1593,10 @@ static int perf_header__read_build_ids(struct perf_header *header,/* Macro for features that simply need to read and store a string. */ #define FEAT_PROCESS_STR_FUN (__feat, __feat_env) \ static int process_##__feat(struct perf_file_section *section __maybe_unused, \ - struct perf_header *ph, int fd, \ - void *data __maybe_unused) \ + struct feat_fd *ff, void *data __maybe_unused) \ {\ - ph->env.__feat_env = do_read_string(fd, ph); \ - return ph->env.__feat_env ? 0 : -ENOMEM; \ + ff->ph->env.__feat_env = do_read_string(ff->fd, ff->ph); \ + return ff->ph->env.__feat_env ? 0 : -ENOMEM; \ }FEAT_PROCESS_STR_FUN (hostname, hostname);
@@ -1608,52 +1607,49 @@ FEAT_PROCESS_STR_FUN(cpudesc, cpu_desc);FEAT_PROCESS_STR_FUN (cpuid, cpuid);static int process_tracing_data (struct perf_file_section *section__maybe_unused , -struct perf_header *ph__maybe_unused , -int fd,void *data) +struct feat_fd *ff,void *data) { -ssize_t ret =trace_report (fd, data, false); +ssize_t ret =trace_report (ff->fd, data, false); +return ret <0 ?-1 :0 ; }static int process_build_id (struct perf_file_section *section, -struct perf_header *ph,int fd, -void *data__maybe_unused ) +struct feat_fd *ff,void *data__maybe_unused ) { -if (perf_header__read_build_ids (ph, fd, section->offset, section->size)) +if (perf_header__read_build_ids (ff->ph, ff->fd, section->offset, section->size))pr_debug ("Failed to read buildids, continuing...\n" );return 0 ; }static int process_nrcpus (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) +struct feat_fd *ff,void *data__maybe_unused ) {int ret;u32 nr_cpus_avail, nr_cpus_online; - ret =do_read_u32 (fd, ph, &nr_cpus_avail); + ret =do_read_u32 (ff->fd, ff->ph, &nr_cpus_avail);if (ret)return ret; - ret =do_read_u32 (fd, ph, &nr_cpus_online); + ret =do_read_u32 (ff->fd, ff->ph, &nr_cpus_online);if (ret)return ret; - ph->env.nr_cpus_avail = (int )nr_cpus_avail; - ph->env.nr_cpus_online = (int )nr_cpus_online; + ff->ph->env.nr_cpus_avail = (int )nr_cpus_avail; + ff->ph->env.nr_cpus_online = (int )nr_cpus_online;return 0 ; }static int process_total_mem (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) +struct feat_fd *ff,void *data__maybe_unused ) {u64 total_mem;int ret; - ret =do_read_u64 (fd, ph, &total_mem); + ret =do_read_u64 (ff->fd, ff->ph, &total_mem);if (ret)return -1 ; - ph->env.total_mem = (unsigned long long )total_mem; + ff->ph->env.total_mem = (unsigned long long )total_mem;return 0 ; }
@@ -1691,16 +1687,15 @@ perf_evlist__set_event_name(struct perf_evlist *evlist,static int process_event_desc (struct perf_file_section *section__maybe_unused , -struct perf_header *header,int fd, -void *data__maybe_unused ) +struct feat_fd *ff,void *data__maybe_unused ) {struct perf_session *session; -struct perf_evsel *evsel, *events =read_event_desc (header, fd); +struct perf_evsel *evsel, *events =read_event_desc (ff->ph, ff->fd);if (!events)return 0 ; - session = container_of(header, struct perf_session, header); + session = container_of(ff->ph, struct perf_session, header);for (evsel = events; evsel->attr.size; evsel++)perf_evlist__set_event_name (session->evlist, evsel);
@@ -1709,17 +1704,16 @@ process_event_desc(struct perf_file_section *section __maybe_unused,return 0 ; } -static int process_cmdline (struct perf_file_section *section, -struct perf_header *ph,int fd, -void *data__maybe_unused ) +static int process_cmdline (struct perf_file_section *section__maybe_unused , +struct feat_fd *ff,void *data__maybe_unused ) {char *str, *cmdline =NULL , **argv =NULL ;u32 nr, i, len =0 ; -if (do_read_u32 (fd, ph, &nr)) +if (do_read_u32 (ff->fd, ff->ph, &nr))return -1 ; - ph->env.nr_cmdline = nr; + ff->ph->env.nr_cmdline = nr; cmdline =zalloc (section->size + nr +1 );if (!cmdline)
@@ -1730,7 +1724,7 @@ static int process_cmdline(struct perf_file_section *section, goto error;for (i =0 ; i < nr; i++) { - str =do_read_string (fd, ph); + str =do_read_string (ff->fd, ff->ph);if (!str) goto error;
@@ -1739,8 +1733,8 @@ static int process_cmdline(struct perf_file_section *section, len +=strlen (str) +1 ;free (str); } - ph->env.cmdline = cmdline; - ph->env.cmdline_argv = (const char **) argv; + ff->ph->env.cmdline = cmdline; + ff->ph->env.cmdline_argv = (const char **) argv;return 0 ; error:
@@ -1749,21 +1743,21 @@ static int process_cmdline(struct perf_file_section *section,return -1 ; } -static int process_cpu_topology (struct perf_file_section *section, -struct perf_header *ph,int fd, -void *data__maybe_unused ) +static int process_cpu_topology (struct perf_file_section *section__maybe_unused , +struct feat_fd *ff,void *data__maybe_unused ) {u32 nr, i;char *str;struct strbuf sb; -int cpu_nr = ph->env.nr_cpus_avail; +int cpu_nr = ff->ph->env.nr_cpus_avail;u64 size =0 ; +struct perf_header *ph = ff->ph; ph->env.cpu =calloc (cpu_nr,sizeof (*ph->env.cpu));if (!ph->env.cpu)return -1 ; -if (do_read_u32 (fd, ph, &nr)) +if (do_read_u32 (ff->fd, ph, &nr)) goto free_cpu; ph->env.nr_sibling_cores = nr;
@@ -1772,7 +1766,7 @@ static int process_cpu_topology(struct perf_file_section *section, goto free_cpu;for (i =0 ; i < nr; i++) { - str =do_read_string (fd, ph); + str =do_read_string (ff->fd, ph);if (!str) goto error;
@@ -1784,14 +1778,14 @@ static int process_cpu_topology(struct perf_file_section *section, } ph->env.sibling_cores =strbuf_detach (&sb,NULL ); -if (do_read_u32 (fd, ph, &nr)) +if (do_read_u32 (ff->fd, ph, &nr))return -1 ; ph->env.nr_sibling_threads = nr; size +=sizeof (u32);for (i =0 ; i < nr; i++) { - str =do_read_string (fd, ph); + str =do_read_string (ff->fd, ph);if (!str) goto error;
@@ -1813,12 +1807,12 @@ static int process_cpu_topology(struct perf_file_section *section, }for (i =0 ; i < (u32 )cpu_nr; i++) { -if (do_read_u32 (fd, ph, &nr)) +if (do_read_u32 (ff->fd, ph, &nr)) goto free_cpu; ph->env.cpu[i].core_id = nr; -if (do_read_u32 (fd, ph, &nr)) +if (do_read_u32 (ff->fd, ph, &nr)) goto free_cpu;if (nr != (u32)-1 && nr > (u32 )cpu_nr) {
@@ -1840,15 +1834,14 @@ static int process_cpu_topology(struct perf_file_section *section, }static int process_numa_topology (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) +struct feat_fd *ff,void *data__maybe_unused ) {struct numa_node *nodes, *n;u32 nr, i;char *str;/* nr nodes */ -if (do_read_u32 (fd, ph, &nr)) +if (do_read_u32 (ff->fd, ff->ph, &nr))return -1 ; nodes =zalloc (sizeof (*nodes) * nr);
@@ -1859,16 +1852,16 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse n = &nodes[i];/* node number */ -if (do_read_u32 (fd, ph, &n->node)) +if (do_read_u32 (ff->fd, ff->ph, &n->node)) goto error; -if (do_read_u64 (fd, ph, &n->mem_total)) +if (do_read_u64 (ff->fd, ff->ph, &n->mem_total)) goto error; -if (do_read_u64 (fd, ph, &n->mem_free)) +if (do_read_u64 (ff->fd, ff->ph, &n->mem_free)) goto error; - str =do_read_string (fd, ph); + str =do_read_string (ff->fd, ff->ph);if (!str) goto error;
@@ -1878,8 +1871,8 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unusefree (str); } - ph->env.nr_numa_nodes = nr; - ph->env.numa_nodes = nodes; + ff->ph->env.nr_numa_nodes = nr; + ff->ph->env.numa_nodes = nodes;return 0 ; error:
@@ -1888,15 +1881,14 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse }static int process_pmu_mappings (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) +struct feat_fd *ff,void *data__maybe_unused ) {char *name;u32 pmu_num;u32 type;struct strbuf sb; -if (do_read_u32 (fd, ph, &pmu_num)) +if (do_read_u32 (ff->fd, ff->ph, &pmu_num))return -1 ;if (!pmu_num) {
@@ -1904,15 +1896,15 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unusedreturn 0 ; } - ph->env.nr_pmu_mappings = pmu_num; + ff->ph->env.nr_pmu_mappings = pmu_num;if (strbuf_init (&sb,128 ) <0 )return -1 ;while (pmu_num) { -if (do_read_u32 (fd, ph, &type)) +if (do_read_u32 (ff->fd, ff->ph, &type)) goto error; - name =do_read_string (fd, ph); + name =do_read_string (ff->fd, ff->ph);if (!name) goto error;
@@ -1923,12 +1915,12 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused goto error;if (!strcmp (name,"msr" )) - ph->env.msr_pmu_type = type; + ff->ph->env.msr_pmu_type = type;free (name); pmu_num--; } - ph->env.pmu_mappings =strbuf_detach (&sb,NULL ); + ff->ph->env.pmu_mappings =strbuf_detach (&sb,NULL );return 0 ; error:
@@ -1937,8 +1929,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused }static int process_group_desc (struct perf_file_section *section__maybe_unused , -struct perf_header *ph,int fd, -void *data__maybe_unused ) +struct feat_fd *ff,void *data__maybe_unused ) {size_t ret =-1 ;u32 i, nr, nr_groups;
@@ -1950,10 +1941,10 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,u32 nr_members; } *desc; -if (do_read_u32 (fd, ph, &nr_groups)) +if (do_read_u32 (ff->fd, ff->ph, &nr_groups))return -1 ; - ph->env.nr_groups = nr_groups; + ff->ph->env.nr_groups = nr_groups;if (!nr_groups) {pr_debug ("group desc not available\n" );return 0 ;
@@ -1964,21 +1955,21 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,return -1 ;for (i =0 ; i < nr_groups; i++) { - desc[i].name =do_read_string (fd, ph); + desc[i].name =do_read_string (ff->fd, ff->ph);if (!desc[i].name) goto out_free; -if (do_read_u32 (fd, ph, &desc[i].leader_idx)) +if (do_read_u32 (ff->fd, ff->ph, &desc[i].leader_idx)) goto out_free; -if (do_read_u32 (fd, ph, &desc[i].nr_members)) +if (do_read_u32 (ff->fd, ff->ph, &desc[i].nr_members)) goto out_free; }/* * Rebuild group relationship based on the group_desc */ - session = container_of(ph, struct perf_session, header); + session = container_of(ff->ph, struct perf_session, header); session->evlist->nr_groups = nr_groups; i = nr =0 ;
@@ -2022,36 +2013,34 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,return ret; } -static int process_auxtrace (struct perf_file_section *section, -struct perf_header *ph,int fd, -void *data__maybe_unused ) +static int process_auxtrace (struct perf_file_section *section__maybe_unused , +struct feat_fd *ff,void *data__maybe_unused ) {struct perf_session *session;int err; - session = container_of(ph, struct perf_session, header); + session = container_of(ff->ph, struct perf_session, header); - err =auxtrace_index__process (fd, section->size, session, - ph->needs_swap); + err =auxtrace_index__process (ff->fd, section->size, session, + ff->ph->needs_swap);if (err <0 )pr_err ("Failed to process auxtrace index\n" );return err; }static int process_cache (struct perf_file_section *section__maybe_unused , -struct perf_header *ph__maybe_unused ,int fd__maybe_unused , -void *data__maybe_unused ) +struct feat_fd *ff,void *data__maybe_unused ) {struct cpu_cache_level *caches;u32 cnt, i, version; -if (do_read_u32 (fd, ph, &version)) +if (do_read_u32 (ff->fd, ff->ph, &version))return -1 ;if (version !=1 )return -1 ; -if (do_read_u32 (fd, ph, &cnt)) +if (do_read_u32 (ff->fd, ff->ph, &cnt))return -1 ; caches =zalloc (sizeof (*caches) * cnt);
@@ -2062,7 +2051,7 @@ static int process_cache(struct perf_file_section *section __maybe_unused,struct cpu_cache_level c;#define _R (v) \ - if (do_read_u32(fd, ph, &c.v))\ + if (do_read_u32(ff->fd, ff->ph, &c.v))\ goto out_free_caches; \_R (level)
@@ -2071,9 +2060,9 @@ static int process_cache(struct perf_file_section *section __maybe_unused, _R(ways)#undef _R -#define _R (v) \ - c.v = do_read_string(fd, ph); \ - if (!c.v) \ +#define _R (v) \ + c.v = do_read_string(ff->fd, ff->ph); \ + if (!c.v) \ goto out_free_caches;_R (type)
@@ -2084,8 +2073,8 @@ static int process_cache(struct perf_file_section *section __maybe_unused, caches[i] = c; } - ph->env.caches = caches; - ph->env.caches_cnt = cnt; + ff->ph->env.caches = caches; + ff->ph->env.caches_cnt = cnt;return 0 ; out_free_caches:free (caches);
@@ -2096,7 +2085,7 @@ struct feature_ops {int (*write)(struct feat_fd *ff,struct perf_evlist *evlist);void (*print)(struct feat_fd *ff,FILE *fp);int (*process)(struct perf_file_section *section, -struct perf_header *h,int fd,void *data); +struct feat_fd *ff,void *data);const char *name;bool full_only; };
@@ -2627,6 +2616,11 @@ static int perf_file_section__process(struct perf_file_section *section,struct perf_header *ph, int feat, int fd, void *data) { + struct feat_fd ff = { + .fd = fd, + .ph = ph, + }; +if (lseek (fd, section->offset,SEEK_SET ) == (off_t)-1 ) {pr_debug ("Failed to lseek to %" PRIu64" offset for feature " "%d, continuing...\n" , section->offset, feat);
@@ -2641,7 +2635,7 @@ static int perf_file_section__process(struct perf_file_section *section,if (!feat_ops[feat].process)return 0 ; -return feat_ops[feat].process (section, ph, fd, data); +return feat_ops[feat].process (section, &ff, data); } static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 9/16 perf header: don't pass struct perf_file_section to process_##_feat
In reply to David Carrillo-Cisnerosstruct perf_file_section is used in process_##_feat as container for size and offset in the file descriptor. These attributes are meaninful in pipe-mode but struct perf_file_section is not.
Add offset and size variables to struct feat_fd to store perf_file_section's values in file-mode. Later on, the same variables can be reused for pipe-mode.
This patch does not change behavior.
--- tools/perf/util/header.c | 58 ++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 34 deletions(-)
tools/perf/util/header.c +24 -34
@@ -61,6 +61,8 @@ struct perf_file_attr {struct feat_fd {struct perf_header *ph;int fd; +ssize_t offset; +size_t size; };void perf_header__set_feat (struct perf_header *header,int feat)
@@ -1592,8 +1594,7 @@ static int perf_header__read_build_ids(struct perf_header *header,/* Macro for features that simply need to read and store a string. */ #define FEAT_PROCESS_STR_FUN (__feat, __feat_env) \ -static int process_##__feat(struct perf_file_section *section __maybe_unused, \ - struct feat_fd *ff, void *data __maybe_unused) \ +static int process_##__feat(struct feat_fd *ff, void *data __maybe_unused) \ {\ ff->ph->env.__feat_env = do_read_string(ff->fd, ff->ph); \ return ff->ph->env.__feat_env ? 0 : -ENOMEM; \
@@ -1606,24 +1607,21 @@ FEAT_PROCESS_STR_FUN(arch, arch);FEAT_PROCESS_STR_FUN (cpudesc, cpu_desc);FEAT_PROCESS_STR_FUN (cpuid, cpuid); -static int process_tracing_data (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data) +static int process_tracing_data (struct feat_fd *ff,void *data) {ssize_t ret =trace_report (ff->fd, data, false);return ret <0 ?-1 :0 ; } -static int process_build_id (struct perf_file_section *section, -struct feat_fd *ff,void *data__maybe_unused ) +static int process_build_id (struct feat_fd *ff,void *data__maybe_unused ) { -if (perf_header__read_build_ids (ff->ph, ff->fd, section->offset, section->size)) +if (perf_header__read_build_ids (ff->ph, ff->fd, ff->offset, ff->size))pr_debug ("Failed to read buildids, continuing...\n" );return 0 ; } -static int process_nrcpus (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data__maybe_unused ) +static int process_nrcpus (struct feat_fd *ff,void *data__maybe_unused ) {int ret;u32 nr_cpus_avail, nr_cpus_online;
@@ -1640,8 +1638,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,return 0 ; } -static int process_total_mem (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data__maybe_unused ) +static int process_total_mem (struct feat_fd *ff,void *data__maybe_unused ) {u64 total_mem;int ret;
@@ -1686,8 +1683,7 @@ perf_evlist__set_event_name(struct perf_evlist *evlist, }static int -process_event_desc (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data__maybe_unused ) +process_event_desc (struct feat_fd *ff,void *data__maybe_unused ) {struct perf_session *session;struct perf_evsel *evsel, *events =read_event_desc (ff->ph, ff->fd);
@@ -1704,8 +1700,7 @@ process_event_desc(struct perf_file_section *section __maybe_unused,return 0 ; } -static int process_cmdline (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data__maybe_unused ) +static int process_cmdline (struct feat_fd *ff,void *data__maybe_unused ) {char *str, *cmdline =NULL , **argv =NULL ;u32 nr, i, len =0 ;
@@ -1715,7 +1710,7 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused, ff->ph->env.nr_cmdline = nr; - cmdline =zalloc (section->size + nr +1 ); + cmdline =zalloc (ff->size + nr +1 );if (!cmdline)return -1 ;
@@ -1743,8 +1738,7 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused,return -1 ; } -static int process_cpu_topology (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data__maybe_unused ) +static int process_cpu_topology (struct feat_fd *ff,void *data__maybe_unused ) {u32 nr, i;char *str;
@@ -1801,7 +1795,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused* The header may be from old perf, * which doesn't include core id and socket id information. */ -if (section->size <= size) { +if (ff->size <= size) {zfree (&ph->env.cpu);return 0 ; }
@@ -1833,8 +1827,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unusedreturn -1 ; } -static int process_numa_topology (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data__maybe_unused ) +static int process_numa_topology (struct feat_fd *ff,void *data__maybe_unused ) {struct numa_node *nodes, *n;u32 nr, i;
@@ -1880,8 +1873,7 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unusereturn -1 ; } -static int process_pmu_mappings (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data__maybe_unused ) +static int process_pmu_mappings (struct feat_fd *ff,void *data__maybe_unused ) {char *name;u32 pmu_num;
@@ -1928,8 +1920,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unusedreturn -1 ; } -static int process_group_desc (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data__maybe_unused ) +static int process_group_desc (struct feat_fd *ff,void *data__maybe_unused ) {size_t ret =-1 ;u32 i, nr, nr_groups;
@@ -2013,23 +2004,21 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,return ret; } -static int process_auxtrace (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data__maybe_unused ) +static int process_auxtrace (struct feat_fd *ff,void *data__maybe_unused ) {struct perf_session *session;int err; session = container_of(ff->ph, struct perf_session, header); - err =auxtrace_index__process (ff->fd, section->size, session, + err =auxtrace_index__process (ff->fd, ff->size, session, ff->ph->needs_swap);if (err <0 )pr_err ("Failed to process auxtrace index\n" );return err; } -static int process_cache (struct perf_file_section *section__maybe_unused , -struct feat_fd *ff,void *data__maybe_unused ) +static int process_cache (struct feat_fd *ff,void *data__maybe_unused ) {struct cpu_cache_level *caches;u32 cnt, i, version;
@@ -2084,8 +2073,7 @@ static int process_cache(struct perf_file_section *section __maybe_unused,struct feature_ops {int (*write)(struct feat_fd *ff,struct perf_evlist *evlist);void (*print)(struct feat_fd *ff,FILE *fp); -int (*process)(struct perf_file_section *section, -struct feat_fd *ff,void *data); +int (*process)(struct feat_fd *ff,void *data);const char *name;bool full_only; };
@@ -2616,9 +2604,11 @@ static int perf_file_section__process(struct perf_file_section *section,struct perf_header *ph, int feat, int fd, void *data) { - struct feat_fd ff = { + struct feat_fd fdd = { .fd = fd, .ph = ph, + .size = section->size, + .offset = section->offset, };if (lseek (fd, section->offset,SEEK_SET ) == (off_t)-1 ) {
@@ -2635,7 +2625,7 @@ static int perf_file_section__process(struct perf_file_section *section,if (!feat_ops[feat].process)return 0 ; -return feat_ops[feat].process (section, &ff, data); +return feat_ops[feat].process (&fdd, data); } static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
Re: [PATCH v4 09/16] perf header: don't pass struct perf_file_section to process_##_feat
On Mon, Jun 12, 2017 at 09:29:25PM -0700, David Carrillo-Cisneros wrote:
SNIP
Quoted 13 lines
tools/perf/util/header.c +1
-2struct cpu_cache_level *caches;u32 cnt, i, version;@@ -2084,8 +2073,7 @@ static int process_cache(struct perf_file_section *section __maybe_unused,struct feature_ops {int (*write)(struct feat_fd *ff,struct perf_evlist *evlist);void (*print)(struct feat_fd *ff,FILE *fp); -int (*process)(struct perf_file_section *section, -struct feat_fd *ff,void *data); +int (*process)(struct feat_fd *ff,void *data);const char *name;bool full_only; };
tools/perf/util/header.c static int perf_file_section__process(struct perf_file_section *section, · line 2607
Quoted 5 lines
tools/perf/util/header.c +1
-1@@ -2616,9 +2604,11 @@ static int perf_file_section__process(struct perf_file_section *section, struct perf_header *ph, int feat, int fd, void *data) { - struct feat_fd ff = { + struct feat_fd fdd = {
no need to rename to fdd
jirka
Re: [PATCH v4 09/16] perf header: don't pass struct perf_file_section to process_##_feat
Quoted 16 lines · Jiri Olsa
On Mon, Jun 12, 2017 at 09:29:25PM -0700, David Carrillo-Cisneros wrote:
SNIP
Quoted 12 lines
struct cpu_cache_level *caches; u32 cnt, i, version;tools/perf/util/header.c +1
-2@@ -2084,8 +2073,7 @@ static int process_cache(struct perf_file_section *section __maybe_unused,struct feature_ops {int (*write)(struct feat_fd *ff,struct perf_evlist *evlist);void (*print)(struct feat_fd *ff,FILE *fp); -int (*process)(struct perf_file_section *section, -struct feat_fd *ff,void *data); +int (*process)(struct feat_fd *ff,void *data);const char *name;bool full_only; };
Quoted 8 lines
tools/perf/util/header.c static int perf_file_section__process(struct perf_file_section *section, · line 2607
Quoted 6 lines
tools/perf/util/header.c +1
-1@@ -2616,9 +2604,11 @@ static int perf_file_section__process(struct perf_file_section *section, struct perf_header *ph, int feat, int fd, void *data) { - struct feat_fd ff = { + struct feat_fd fdd = {no need to rename to fdd
fixed
Quoted 2 lines
jirka
PATCH v4 10/16 perf header: use struct feat_fd in read header records
In reply to David Carrillo-CisnerosAs preparation for using header records in-pipe mode, replace int fd with struct feat_fd ff in read functions for all header record types.
This patch does not change behavior.
--- tools/perf/util/header.c | 101 +++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 51 deletions(-)
tools/perf/util/header.c +50 -51
@@ -125,54 +125,54 @@ static int do_write_string(struct feat_fd *ff, const char *str)return write_padded (ff, str, olen, len); } -static int __do_read (int fd,void *addr,ssize_t size) +static int __do_read (struct feat_fd *ff,void *addr,ssize_t size) { -ssize_t ret =readn (fd, addr, size); +ssize_t ret =readn (ff->fd, addr, size);if (ret != size)return ret <0 ? (int )ret :-1 ;return 0 ; } -static int do_read_u32 (int fd,struct perf_header *ph,u32 *addr) +static int do_read_u32 (struct feat_fd *ff,u32 *addr) {int ret; - ret =__do_read (fd, addr,sizeof (*addr)); + ret =__do_read (ff, addr,sizeof (*addr));if (ret)return ret; -if (ph->needs_swap) +if (ff->ph->needs_swap) *addr =bswap_32 (*addr);return 0 ; } -static int do_read_u64 (int fd,struct perf_header *ph,u64 *addr) +static int do_read_u64 (struct feat_fd *ff,u64 *addr) {int ret; - ret =__do_read (fd, addr,sizeof (*addr)); + ret =__do_read (ff, addr,sizeof (*addr));if (ret)return ret; -if (ph->needs_swap) +if (ff->ph->needs_swap) *addr =bswap_64 (*addr);return 0 ; } -static char *do_read_string (int fd,struct perf_header *ph) +static char *do_read_string (struct feat_fd *ff) {u32 len;char *buf; -if (do_read_u32 (fd, ph, &len)) +if (do_read_u32 (ff, &len))return NULL ; buf =malloc (len);if (!buf)return NULL ; -if (!__do_read (fd, buf, len)) { +if (!__do_read (ff, buf, len)) {/* * strings are padded by zeroes * thus the actual strlen of buf
@@ -1207,8 +1207,7 @@ static void free_event_desc(struct perf_evsel *events)free (events); } -static struct perf_evsel * -read_event_desc (struct perf_header *ph,int fd) +static struct perf_evsel *read_event_desc (struct feat_fd *ff) {struct perf_evsel *evsel, *events =NULL ;u64 *id;
@@ -1217,10 +1216,10 @@ read_event_desc(struct perf_header *ph, int fd)size_t msz;/* number of events */ -if (do_read_u32 (fd, ph, &nre)) +if (do_read_u32 (ff, &nre)) goto error; -if (do_read_u32 (fd, ph, &sz)) +if (do_read_u32 (ff, &sz)) goto error;/* buffer to hold on file attr struct */
@@ -1244,21 +1243,21 @@ read_event_desc(struct perf_header *ph, int fd)* must read entire on-file attr struct to * sync up with layout. */ -if (__do_read (fd, buf, sz)) +if (__do_read (ff, buf, sz)) goto error; -if (ph->needs_swap) +if (ff->ph->needs_swap)perf_event__attr_swap (buf);memcpy (&evsel->attr, buf, msz); -if (do_read_u32 (fd, ph, &nr)) +if (do_read_u32 (ff, &nr)) goto error; -if (ph->needs_swap) +if (ff->ph->needs_swap) evsel->needs_swap = true; - evsel->name =do_read_string (fd, ph); + evsel->name =do_read_string (ff);if (!evsel->name) goto error;
@@ -1272,7 +1271,7 @@ read_event_desc(struct perf_header *ph, int fd) evsel->id = id;for (j =0 ; j < nr; j++) { -if (do_read_u64 (fd, ph, id)) +if (do_read_u64 (ff, id)) goto error; id++; }
@@ -1294,7 +1293,7 @@ static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,static void print_event_desc (struct feat_fd *ff,FILE *fp) { -struct perf_evsel *evsel, *events =read_event_desc (ff->ph, ff->fd); +struct perf_evsel *evsel, *events =read_event_desc (ff);u32 j;u64 *id;
@@ -1596,7 +1595,7 @@ static int perf_header__read_build_ids(struct perf_header *header,#define FEAT_PROCESS_STR_FUN (__feat, __feat_env) \ static int process_##__feat(struct feat_fd *ff, void *data __maybe_unused) \ {\ - ff->ph->env.__feat_env = do_read_string(ff->fd, ff->ph); \ + ff->ph->env.__feat_env = do_read_string(ff); \ return ff->ph->env.__feat_env ? 0 : -ENOMEM; \ }
@@ -1626,11 +1625,11 @@ static int process_nrcpus(struct feat_fd *ff, void *data __maybe_unused)int ret;u32 nr_cpus_avail, nr_cpus_online; - ret =do_read_u32 (ff->fd, ff->ph, &nr_cpus_avail); + ret =do_read_u32 (ff, &nr_cpus_avail);if (ret)return ret; - ret =do_read_u32 (ff->fd, ff->ph, &nr_cpus_online); + ret =do_read_u32 (ff, &nr_cpus_online);if (ret)return ret; ff->ph->env.nr_cpus_avail = (int )nr_cpus_avail;
@@ -1643,7 +1642,7 @@ static int process_total_mem(struct feat_fd *ff, void *data __maybe_unused)u64 total_mem;int ret; - ret =do_read_u64 (ff->fd, ff->ph, &total_mem); + ret =do_read_u64 (ff, &total_mem);if (ret)return -1 ; ff->ph->env.total_mem = (unsigned long long )total_mem;
@@ -1686,7 +1685,7 @@ static int process_event_desc(struct feat_fd *ff, void *data __maybe_unused) { struct perf_session *session; -struct perf_evsel *evsel, *events =read_event_desc (ff->ph, ff->fd); +struct perf_evsel *evsel, *events =read_event_desc (ff);if (!events)return 0 ;
@@ -1705,7 +1704,7 @@ static int process_cmdline(struct feat_fd *ff, void *data __maybe_unused)char *str, *cmdline =NULL , **argv =NULL ;u32 nr, i, len =0 ; -if (do_read_u32 (ff->fd, ff->ph, &nr)) +if (do_read_u32 (ff, &nr))return -1 ; ff->ph->env.nr_cmdline = nr;
@@ -1719,7 +1718,7 @@ static int process_cmdline(struct feat_fd *ff, void *data __maybe_unused) goto error;for (i =0 ; i < nr; i++) { - str =do_read_string (ff->fd, ff->ph); + str =do_read_string (ff);if (!str) goto error;
@@ -1751,7 +1750,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)if (!ph->env.cpu)return -1 ; -if (do_read_u32 (ff->fd, ph, &nr)) +if (do_read_u32 (ff, &nr)) goto free_cpu; ph->env.nr_sibling_cores = nr;
@@ -1760,7 +1759,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) goto free_cpu;for (i =0 ; i < nr; i++) { - str =do_read_string (ff->fd, ph); + str =do_read_string (ff);if (!str) goto error;
@@ -1772,14 +1771,14 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) } ph->env.sibling_cores =strbuf_detach (&sb,NULL ); -if (do_read_u32 (ff->fd, ph, &nr)) +if (do_read_u32 (ff, &nr))return -1 ; ph->env.nr_sibling_threads = nr; size +=sizeof (u32);for (i =0 ; i < nr; i++) { - str =do_read_string (ff->fd, ph); + str =do_read_string (ff);if (!str) goto error;
@@ -1801,12 +1800,12 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) }for (i =0 ; i < (u32 )cpu_nr; i++) { -if (do_read_u32 (ff->fd, ph, &nr)) +if (do_read_u32 (ff, &nr)) goto free_cpu; ph->env.cpu[i].core_id = nr; -if (do_read_u32 (ff->fd, ph, &nr)) +if (do_read_u32 (ff, &nr)) goto free_cpu;if (nr != (u32)-1 && nr > (u32 )cpu_nr) {
@@ -1834,7 +1833,7 @@ static int process_numa_topology(struct feat_fd *ff, void *data __maybe_unused)char *str;/* nr nodes */ -if (do_read_u32 (ff->fd, ff->ph, &nr)) +if (do_read_u32 (ff, &nr))return -1 ; nodes =zalloc (sizeof (*nodes) * nr);
@@ -1845,16 +1844,16 @@ static int process_numa_topology(struct feat_fd *ff, void *data __maybe_unused) n = &nodes[i];/* node number */ -if (do_read_u32 (ff->fd, ff->ph, &n->node)) +if (do_read_u32 (ff, &n->node)) goto error; -if (do_read_u64 (ff->fd, ff->ph, &n->mem_total)) +if (do_read_u64 (ff, &n->mem_total)) goto error; -if (do_read_u64 (ff->fd, ff->ph, &n->mem_free)) +if (do_read_u64 (ff, &n->mem_free)) goto error; - str =do_read_string (ff->fd, ff->ph); + str =do_read_string (ff);if (!str) goto error;
@@ -1880,7 +1879,7 @@ static int process_pmu_mappings(struct feat_fd *ff, void *data __maybe_unused)u32 type;struct strbuf sb; -if (do_read_u32 (ff->fd, ff->ph, &pmu_num)) +if (do_read_u32 (ff, &pmu_num))return -1 ;if (!pmu_num) {
@@ -1893,10 +1892,10 @@ static int process_pmu_mappings(struct feat_fd *ff, void *data __maybe_unused)return -1 ;while (pmu_num) { -if (do_read_u32 (ff->fd, ff->ph, &type)) +if (do_read_u32 (ff, &type)) goto error; - name =do_read_string (ff->fd, ff->ph); + name =do_read_string (ff);if (!name) goto error;
@@ -1932,7 +1931,7 @@ static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused)u32 nr_members; } *desc; -if (do_read_u32 (ff->fd, ff->ph, &nr_groups)) +if (do_read_u32 (ff, &nr_groups))return -1 ; ff->ph->env.nr_groups = nr_groups;
@@ -1946,14 +1945,14 @@ static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused)return -1 ;for (i =0 ; i < nr_groups; i++) { - desc[i].name =do_read_string (ff->fd, ff->ph); + desc[i].name =do_read_string (ff);if (!desc[i].name) goto out_free; -if (do_read_u32 (ff->fd, ff->ph, &desc[i].leader_idx)) +if (do_read_u32 (ff, &desc[i].leader_idx)) goto out_free; -if (do_read_u32 (ff->fd, ff->ph, &desc[i].nr_members)) +if (do_read_u32 (ff, &desc[i].nr_members)) goto out_free; }
@@ -2023,13 +2022,13 @@ static int process_cache(struct feat_fd *ff, void *data __maybe_unused)struct cpu_cache_level *caches;u32 cnt, i, version; -if (do_read_u32 (ff->fd, ff->ph, &version)) +if (do_read_u32 (ff, &version))return -1 ;if (version !=1 )return -1 ; -if (do_read_u32 (ff->fd, ff->ph, &cnt)) +if (do_read_u32 (ff, &cnt))return -1 ; caches =zalloc (sizeof (*caches) * cnt);
@@ -2040,7 +2039,7 @@ static int process_cache(struct feat_fd *ff, void *data __maybe_unused)struct cpu_cache_level c;#define _R (v) \ - if (do_read_u32(ff->fd, ff->ph, &c.v))\ + if (do_read_u32(ff, &c.v))\ goto out_free_caches; \_R (level)
@@ -2050,7 +2049,7 @@ static int process_cache(struct feat_fd *ff, void *data __maybe_unused)#undef _R#define _R (v) \ - c.v = do_read_string(ff->fd, ff->ph); \ + c.v = do_read_string(ff); \ if (!c.v) \ goto out_free_caches;
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 11/16 perf header: make write_pmu_mappings pipe-mode friendly
In reply to David Carrillo-CisnerosIn pipe-mode, we will operate over a buffer instead of a file descriptor but write_pmu_mappings uses lseek to move over the perf.data file.
Refactor write_pmu_mappings to avoid the usage of lseek and allow reusing the same logic in pipe-mode (next patch).
--- tools/perf/util/header.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
tools/perf/util/header.c +11 -10
@@ -796,11 +796,19 @@ static int write_pmu_mappings(struct feat_fd *ff, struct perf_evlist *evlist __maybe_unused) {struct perf_pmu *pmu =NULL ; -off_t offset =lseek (ff->fd,0 ,SEEK_CUR ); -__u32 pmu_num =0 ; +u32 pmu_num =0 ;int ret; -/* write real pmu_num later */ +/* +* Do a first pass to count number of pmu to avoid lseek so this +* works in pipe mode as well. +*/ +while ((pmu =perf_pmu__scan (pmu))) { +if (!pmu->name) +continue ; + pmu_num++; + } + ret =do_write (ff, &pmu_num,sizeof (pmu_num));if (ret <0 )return ret;
@@ -808,7 +816,6 @@ static int write_pmu_mappings(struct feat_fd *ff,while ((pmu =perf_pmu__scan (pmu))) {if (!pmu->name)continue ; - pmu_num++; ret =do_write (ff, &pmu->type,sizeof (pmu->type));if (ret <0 )
@@ -819,12 +826,6 @@ static int write_pmu_mappings(struct feat_fd *ff,return ret; } -if (pwrite (ff->fd, &pmu_num,sizeof (pmu_num), offset) !=sizeof (pmu_num)) { -/* discard all */ -lseek (ff->fd, offset,SEEK_SET ); -return -1 ; - } -return 0 ; }
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 12/16 perf header: add a buffer to struct feat_fd
In reply to David Carrillo-CisnerosExtend struct feat_fd to use a temporal buffer in pipe-mode, instead of perf.data's file descriptor.
The header features build_id and aux_trace already have logic to print in file-mode that heavily rely on lseek the file. For now, leave such features inactive in pipe-mode and print a warning if their functions are called in pipe-mode.
--- tools/perf/util/header.c | 73 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 8 deletions(-)
tools/perf/util/header.c +65 -8
@@ -61,6 +61,7 @@ struct perf_file_attr {struct feat_fd {struct perf_header *ph;int fd; +void *buf;/* Either buf != NULL or fd >= 0 */ ssize_t offset;size_t size; };
@@ -80,18 +81,43 @@ bool perf_header__has_feat(const struct perf_header *header, int feat)return test_bit (feat, header->adds_features); } -/* Return: 0 if succeded, -ERR if failed. */ -int do_write (struct feat_fd *ff,const void *buf,size_t size) +static int __do_write_fd (struct feat_fd *ff,const void *buf,size_t size) { -ssize_t ret; +ssize_t ret =writen (ff->fd, buf, size); - ret =writen (ff->fd, buf, size);if (ret != (ssize_t )size)return ret <0 ? (int )ret :-1 ; +return 0 ; +} + +static int __do_write_buf (struct feat_fd *ff,const void *buf,size_t size) +{ +void *addr; + +retry: +if (size > (ff->size - ff->offset)) { + addr =realloc (ff->buf, ff->size <<1 ); +if (!addr) +return -ENOSPC ; + ff->buf = addr; + ff->size <<=1 ; + goto retry; + } + +memcpy (ff->buf + ff->offset, buf, size); + ff->offset += size;return 0 ; } +/* Return: 0 if succeded, -ERR if failed. */ +int do_write (struct feat_fd *ff,const void *buf,size_t size) +{ +if (!ff->buf) +return __do_write_fd (ff, buf, size); +return __do_write_buf (ff, buf, size); +} +/* Return: 0 if succeded, -ERR if failed. */ int write_padded (struct feat_fd *ff,const void *bf,size_t count,size_t count_aligned)
@@ -125,13 +151,32 @@ static int do_write_string(struct feat_fd *ff, const char *str)return write_padded (ff, str, olen, len); } -static int __do_read (struct feat_fd *ff,void *addr,ssize_t size) +static int __do_read_fd (struct feat_fd *ff,void *addr,ssize_t size) { -ssize_t ret =readn (ff->fd, addr, size); +ssize_t ret =readn (ff->fd, addr, size); + +if (ret != size) +return ret <0 ? (int )ret :-1 ; +return 0 ; +} + +static int __do_read_buf (struct feat_fd *ff,void *addr,ssize_t size) +{ +if (size > (ssize_t )ff->size - ff->offset) +return -1 ; + +memcpy (addr, ff->buf + ff->offset, size); + ff->offset += size; -if (ret != size) -return ret <0 ? (int )ret :-1 ;return 0 ; + +} + +static int __do_read (struct feat_fd *ff,void *addr,ssize_t size) +{ +if (!ff->buf) +return __do_read_fd (ff, addr, size); +return __do_read_buf (ff, addr, size); }static int do_read_u32 (struct feat_fd *ff,u32 *addr)
@@ -188,6 +233,9 @@ static char *do_read_string(struct feat_fd *ff)static int write_tracing_data (struct feat_fd *ff,struct perf_evlist *evlist) { +if (WARN (ff->buf,"Error: calling %s in pipe-mode.\n" , __func__)) +return -1 ; +return read_tracing_data (ff->fd, &evlist->entries); }
@@ -202,6 +250,9 @@ static int write_build_id(struct feat_fd *ff,if (!perf_session__read_build_ids (session, true))return -1 ; +if (WARN (ff->buf,"Error: calling %s in pipe-mode.\n" , __func__)) +return -1 ; + err =perf_session__write_buildid_table (session, ff);if (err <0 ) {pr_debug ("failed to write buildid table\n" );
@@ -911,6 +962,9 @@ static int write_auxtrace(struct feat_fd *ff,struct perf_session *session;int err; +if (WARN (ff->buf,"Error: calling %s in pipe-mode.\n" , __func__)) +return -1 ; + session = container_of(ff->ph, struct perf_session, header); err =auxtrace_index__write (ff->fd, &session->auxtrace_index);
@@ -2196,6 +2250,9 @@ static int do_write_feat(struct feat_fd *ff, int type,if (!feat_ops[type].write)return -1 ; +if (WARN (ff->buf,"Error: calling %s in pipe-mode.\n" , __func__)) +return -1 ; + (*p)->offset =lseek (ff->fd,0 ,SEEK_CUR ); err = feat_ops[type].write (ff, evlist);
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
Re: [PATCH v4 12/16] perf header: add a buffer to struct feat_fd
On Mon, Jun 12, 2017 at 09:29:28PM -0700, David Carrillo-Cisneros wrote:
SNIP
Quoted 6 lines
/* Return: 0 if succeded,
-ERRif failed. */ int write_padded(structfeat_fd*ff, const void *bf,tools/perf/util/header.c +0
-0size_t count, size_t count_aligned)@@ -125,13 +151,32 @@ static int do_write_string(struct feat_fd *ff, const char *str)return write_padded (ff, str, olen, len); }
tools/perf/util/header.c static int do_write_string(struct feat_fd *ff, const char *str) · line 160
Quoted 10 lines
tools/perf/util/header.c +6
-2-static int __do_read (struct feat_fd *ff,void *addr,ssize_t size) +static int __do_read_fd (struct feat_fd *ff,void *addr,ssize_t size) { -ssize_t ret =readn (ff->fd, addr, size); +ssize_t ret =readn (ff->fd, addr, size); + +if (ret != size) +return ret <0 ? (int )ret :-1 ; +return 0 ;
extra tab in indent
jirka
Re: [PATCH v4 12/16] perf header: add a buffer to struct feat_fd
Quoted 11 lines · Jiri Olsa
On Mon, Jun 12, 2017 at 09:29:28PM -0700, David Carrillo-Cisneros wrote:
SNIP
Quoted 7 lines
/* Return: 0 if succeded,
-ERRif failed. */ int write_padded(structfeat_fd*ff, const void *bf,
size_tcount,size_tcount_aligned)tools/perf/util/header.c +0
-0@@ -125,13 +151,32 @@ static int do_write_string(struct feat_fd *ff, const char *str)return write_padded (ff, str, olen, len); }
Quoted 11 lines
tools/perf/util/header.c static int do_write_string(struct feat_fd *ff, const char *str) · line 160
Quoted 9 lines
tools/perf/util/header.c +6
-2-static int __do_read (struct feat_fd *ff,void *addr,ssize_t size) +static int __do_read_fd (struct feat_fd *ff,void *addr,ssize_t size) { -ssize_t ret =readn (ff->fd, addr, size); +ssize_t ret =readn (ff->fd, addr, size); + +if (ret != size) +return ret <0 ? (int )ret :-1 ; +return 0 ;extra tab in indent
fixed
PATCH v4 13/16 perf header: change FEAT_OP* macros
In reply to David Carrillo-CisnerosThere are three FEAT_OP* macros:
- FEAT_OPA: for features without process record.
- FEAT_OPP: for features with process record.
- FEAT_OPF: like FEAT_OPP but to show only if show_full_info flags is set.
To add pipe-mode headers we need yet another variation of the macros (one to specify whether a feature generates an auxiliar record).
Instead, we redefine macros so that:
- show_full_info is specified as an argument (to remove the FEAT_OPF variation) and,
- it always sets "process" handler (to remove the FEAT_OPA variation). Individual process handlers can be NULLed individually.
This allows to define two variations only:
- FEAT_OPR: synthesizes auxiliar event record.
- FEAT_OPN: doesn't synthesize an auxiliar event record.
--- tools/perf/util/header.c | 72 +++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 28 deletions(-)
tools/perf/util/header.c +44 -28
@@ -11,6 +11,7 @@#include <linux/list.h> #include <linux/kernel.h> #include <linux/bitops.h> +#include <linux/stringify.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/utsname.h>
@@ -2130,42 +2131,57 @@ struct feature_ops {int (*process)(struct feat_fd *ff,void *data);const char *name;bool full_only; +bool synthesize; }; -#define FEAT_OPA (n, func) \ - [n] = { .name = #n, .write = write_##func, .print = print_##func } -#define FEAT_OPP (n, func) \ - [n] = { .name = #n, .write = write_##func, .print = print_##func, \ - .process = process_##func } -#define FEAT_OPF (n, func) \ - [n] = { .name = #n, .write = write_##func, .print = print_##func, \ - .process = process_##func, .full_only = true } +#define FEAT_OPR (n, func, __full_only) \ + [HEADER_##n] = { \ + .name = __stringify(n), \ + .write = write_##func, \ + .print = print_##func, \ + .full_only = __full_only, \ + .process = process_##func, \ + .synthesize = true \ + } + +#define FEAT_OPN (n, func, __full_only) \ + [HEADER_##n] = { \ + .name = __stringify(n), \ + .write = write_##func, \ + .print = print_##func, \ + .full_only = __full_only, \ + .process = process_##func \ + }/* feature_ops not implemented: */ #define print_tracing_data NULL#define print_build_id NULL +#define process_branch_stack NULL +#define process_stat NULL + +static const struct feature_ops feat_ops[HEADER_LAST_FEATURE ] = { -FEAT_OPP (HEADER_TRACING_DATA , tracing_data), -FEAT_OPP (HEADER_BUILD_ID , build_id), -FEAT_OPP (HEADER_HOSTNAME , hostname), -FEAT_OPP (HEADER_OSRELEASE , osrelease), -FEAT_OPP (HEADER_VERSION , version), -FEAT_OPP (HEADER_ARCH , arch), -FEAT_OPP (HEADER_NRCPUS , nrcpus), -FEAT_OPP (HEADER_CPUDESC , cpudesc), -FEAT_OPP (HEADER_CPUID , cpuid), -FEAT_OPP (HEADER_TOTAL_MEM , total_mem), -FEAT_OPP (HEADER_EVENT_DESC , event_desc), -FEAT_OPP (HEADER_CMDLINE , cmdline), -FEAT_OPF (HEADER_CPU_TOPOLOGY , cpu_topology), -FEAT_OPF (HEADER_NUMA_TOPOLOGY , numa_topology), -FEAT_OPA (HEADER_BRANCH_STACK , branch_stack), -FEAT_OPP (HEADER_PMU_MAPPINGS , pmu_mappings), -FEAT_OPP (HEADER_GROUP_DESC , group_desc), -FEAT_OPP (HEADER_AUXTRACE , auxtrace), -FEAT_OPA (HEADER_STAT , stat), -FEAT_OPF (HEADER_CACHE , cache), +FEAT_OPN (TRACING_DATA , tracing_data, false), +FEAT_OPN (BUILD_ID , build_id, false), +FEAT_OPR (HOSTNAME , hostname, false), +FEAT_OPR (OSRELEASE , osrelease, false), +FEAT_OPR (VERSION , version, false), +FEAT_OPR (ARCH , arch, false), +FEAT_OPR (NRCPUS , nrcpus, false), +FEAT_OPR (CPUDESC , cpudesc, false), +FEAT_OPR (CPUID , cpuid, false), +FEAT_OPR (TOTAL_MEM , total_mem, false), +FEAT_OPR (EVENT_DESC , event_desc, false), +FEAT_OPR (CMDLINE , cmdline, false), +FEAT_OPR (CPU_TOPOLOGY , cpu_topology, true), +FEAT_OPR (NUMA_TOPOLOGY , numa_topology, true), +FEAT_OPN (BRANCH_STACK , branch_stack, false), +FEAT_OPR (PMU_MAPPINGS , pmu_mappings, false), +FEAT_OPN (GROUP_DESC , group_desc, false), +FEAT_OPN (AUXTRACE , auxtrace, false), +FEAT_OPN (STAT , stat, false), +FEAT_OPN (CACHE , cache, true), };struct header_print_data {
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
PATCH v4 14/16 perf tool: add show_feature_header to perf_tool
In reply to David Carrillo-CisnerosAdd show_feat_hdr to control level of printed information of feature headers.
--- tools/perf/builtin-report.c | 11 ++++++++--- tools/perf/builtin-script.c | 3 +++ tools/perf/util/tool.h | 7 +++++++ 3 files changed, 18 insertions(+), 3 deletions(-)
tools/perf/builtin-report.c +8 -3
@@ -985,9 +985,14 @@ int cmd_report(int argc, const char **argv) perf_hpp_list.need_collapse = true; } -/* Force tty output for header output and per-thread stat. */ -if (report.header || report.header_only || report.show_threads) - use_browser =0 ; +if (report.header || report.header_only) { + report.tool.show_feat_hdr =SHOW_FEAT_HEADER ; +/* Force tty output for header output and per-thread stat. */ +if (report.show_threads) + use_browser =0 ; + } +if (report.show_full_info) + report.tool.show_feat_hdr =SHOW_FEAT_HEADER_FULL_INFO ;if (strcmp (input_name,"-" ) !=0 )setup_browser (true);
tools/perf/builtin-script.c +3 -0
@@ -2717,10 +2717,13 @@ int cmd_script(int argc, const char **argv)return -1 ;if (header || header_only) { + script.tool.show_feat_hdr =SHOW_FEAT_HEADER ;perf_session__fprintf_info (session, stdout, show_full_info);if (header_only) goto out_delete; } +if (show_full_info) + script.tool.show_feat_hdr =SHOW_FEAT_HEADER_FULL_INFO ;if (symbol__init (&session->header.env) <0 ) goto out_delete;
tools/perf/util/tool.h +7 -0
@@ -34,6 +34,12 @@ typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,typedef s64 (*event_op3 )(struct perf_tool *tool,union perf_event *event,struct perf_session *session); +enum show_feature_header { +SHOW_FEAT_NO_HEADER =0 , +SHOW_FEAT_HEADER , +SHOW_FEAT_HEADER_FULL_INFO , +}; +struct perf_tool {event_sample sample, read;
@@ -68,6 +74,7 @@ struct perf_tool {bool ordered_events;bool ordering_requires_timestamps;bool namespace_events; + enum show_feature_header show_feat_hdr; };#endif /* __PERF_TOOL_H */
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
Re: [PATCH v4 14/16] perf tool: add show_feature_header to perf_tool
Quoted 17 lines · David Carrillo-Cisneros
Add
show_feat_hdrto control level of printed information of feature headers.Signed-off-by David Carrillo-Cisneros <[email protected]>--- tools/perf/builtin-report.c | 11 ++++++++--- tools/perf/builtin-script.c | 3 +++ tools/perf/util/tool.h | 7 +++++++ 3 files changed, 18 insertions(+), 3 deletions(-)tools/perf/builtin-report.c +0
-0@@ -985,9 +985,14 @@ int cmd_report(int argc, const char **argv) perf_hpp_list.need_collapse = true; }
tools/perf/builtin-report.c int cmd_report(int argc, const char **argv) · line 993
Quoted 10 lines
tools/perf/builtin-report.c +6
-3-/* Force tty output for header output and per-thread stat. */ -if (report.header || report.header_only || report.show_threads) - use_browser =0 ; +if (report.header || report.header_only) { + report.tool.show_feat_hdr =SHOW_FEAT_HEADER ; +/* Force tty output for header output and per-thread stat. */ +if (report.show_threads) + use_browser =0 ; + }
this breaks show_threads option.. simple 'perf report -T' will not set use_browser
jirka
PATCH v4 15/16 perf tools: add feature header record to pipe-mode
In reply to David Carrillo-CisnerosAdd header record types to pipe-mode, reusing the functions used in file-mode and leveraging the new struct feat_fd.
For alignment, check that synthesized events don't exceed pagesize.
Add the perf_event__synthesize_feature event call back to process the new header records.
Before this patch:
$ perf record -o - -e cycles sleep 1 | perf report --stdio --header [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.000 MB - ] ...
After this patch:
$ perf record -o - -e cycles sleep 1 | perf report --stdio --header # ======== # captured on: Mon May 22 16:33:43 2017 # ======== # # hostname : my_hostname # os release : 4.11.0-dbx-up_perf # perf version : 4.11.rc6.g6277c80 # arch : x86_64 # nrcpus online : 72 # nrcpus avail : 72 # cpudesc : Intel(R) Xeon(R) CPU E5-2696 v3 @ 2.30GHz # cpuid : GenuineIntel,6,63,2 # total memory : 263457192 kB # cmdline : /root/perf record -o - -e cycles -c 100000 sleep 1 # HEADER_CPU_TOPOLOGY info available, use -I to display # HEADER_NUMA_TOPOLOGY info available, use -I to display # pmu mappings: intel_bts = 6, uncore_imc_4 = 22, uncore_sbox_1 = 47, uncore_cbox_5 = 33, uncore_ha_0 = 16, uncore_cbox [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.000 MB - ] ...
Support added for the subcommands: report, inject, annotate and script.
--- tools/perf/Documentation/perf.data-file-format.txt | 10 +- tools/perf/builtin-annotate.c | 1 + tools/perf/builtin-inject.c | 1 + tools/perf/builtin-record.c | 7 ++ tools/perf/builtin-report.c | 1 + tools/perf/builtin-script.c | 1 + tools/perf/util/event.c | 1 + tools/perf/util/event.h | 8 ++ tools/perf/util/header.c | 104 ++++++++++++++++++++- tools/perf/util/header.h | 9 ++ tools/perf/util/session.c | 4 + tools/perf/util/tool.h | 3 +- 12 files changed, 145 insertions(+), 5 deletions(-)
tools/perf/Documentation/perf.data-file-format.txt +8 -2
@@ -398,6 +398,11 @@ struct auxtrace_error_event { char msg[MAX_AUXTRACE_ERROR_MSG]; }; + PERF_RECORD_HEADER_FEATURE = 80, + +Describes a header feature. These are records used in pipe-mode that +contain information that otherwise would be in perf.data file's header. + Event types Define the event attributes with their IDs.
@@ -422,8 +427,9 @@ struct perf_pipe_file_header { }; The information about attrs, data, and event_types is instead in the -synthesized events PERF_RECORD_ATTR, PERF_RECORD_HEADER_TRACING_DATA and -PERF_RECORD_HEADER_EVENT_TYPE that are generated by perf record in pipe-mode. +synthesized events PERF_RECORD_ATTR, PERF_RECORD_HEADER_TRACING_DATA, +PERF_RECORD_HEADER_EVENT_TYPE, and PERF_RECORD_HEADER_FEATURE +that are generated by perf record in pipe-mode. References:
tools/perf/builtin-annotate.c +1 -0
@@ -397,6 +397,7 @@ int cmd_annotate(int argc, const char **argv) .namespaces = perf_event__process_namespaces, .attr = perf_event__process_attr, .build_id = perf_event__process_build_id, + .feature = perf_event__process_feature, .ordered_events = true, .ordering_requires_timestamps = true, },
tools/perf/builtin-inject.c +1 -0
@@ -770,6 +770,7 @@ int cmd_inject(int argc, const char **argv) .finished_round = perf_event__repipe_oe_synth, .build_id = perf_event__repipe_op2_synth, .id_index = perf_event__repipe_op2_synth, + .feature = perf_event__repipe_op2_synth, }, .input_name = "-", .samples = LIST_HEAD_INIT(inject.samples),
tools/perf/builtin-record.c +7 -0
@@ -799,6 +799,13 @@ static int record__synthesize(struct record *rec, bool tail)return 0 ;if (file->is_pipe) { + err =perf_event__synthesize_features ( + tool, session, rec->evlist, process_synthesized_event); +if (err <0 ) { +pr_err ("Couldn't synthesize features.\n" ); +return err; + } + err =perf_event__synthesize_attrs (tool, session, process_synthesized_event);if (err <0 ) {
tools/perf/builtin-report.c +1 -0
@@ -718,6 +718,7 @@ int cmd_report(int argc, const char **argv) .id_index = perf_event__process_id_index, .auxtrace_info = perf_event__process_auxtrace_info, .auxtrace = perf_event__process_auxtrace, + .feature = perf_event__process_feature, .ordered_events = true, .ordering_requires_timestamps = true, },
tools/perf/builtin-script.c +1 -0
@@ -2427,6 +2427,7 @@ int cmd_script(int argc, const char **argv) .attr = process_attr, .event_update = perf_event__process_event_update, .tracing_data = perf_event__process_tracing_data, + .feature = perf_event__process_feature, .build_id = perf_event__process_build_id, .id_index = perf_event__process_id_index, .auxtrace_info = perf_event__process_auxtrace_info,
tools/perf/util/event.c +1 -0
@@ -57,6 +57,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", [PERF_RECORD_TIME_CONV] = "TIME_CONV", + [PERF_RECORD_HEADER_FEATURE] = "FEATURE", };static const char *perf_ns__names[] = {
tools/perf/util/event.h +8 -0
@@ -244,6 +244,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_STAT_ROUND =77 ,PERF_RECORD_EVENT_UPDATE =78 ,PERF_RECORD_TIME_CONV =79 , +PERF_RECORD_HEADER_FEATURE =80 , PERF_RECORD_HEADER_MAX };
@@ -488,6 +489,12 @@ struct time_conv_event {u64 time_zero; }; +struct feature_event { +struct perf_event_header header; +u64 feat_id; +char data[]; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;
@@ -518,6 +525,7 @@ union perf_event {struct stat_event stat;struct stat_round_event stat_round;struct time_conv_event time_conv; +struct feature_event feat; };void perf_event__print_totals (void );
tools/perf/util/header.c +102 -2
125 lines not on this page · raw message
tools/perf/util/header.h +9 -0
@@ -101,6 +101,15 @@ int perf_header__process_sections(struct perf_header *header, int fd,int perf_header__fprintf_info (struct perf_session *s,FILE *fp,bool full); +int perf_event__synthesize_features (struct perf_tool *tool, +struct perf_session *session, +struct perf_evlist *evlist, +perf_event__handler_t process); + +int perf_event__process_feature (struct perf_tool *tool, +union perf_event *event, +struct perf_session *session); +int perf_event__synthesize_attr (struct perf_tool *tool,struct perf_event_attr *attr,u32 ids,u64 *id,perf_event__handler_t process);
tools/perf/util/session.c +4 -0
@@ -428,6 +428,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->stat_round = process_stat_round_stub;if (tool->time_conv ==NULL ) tool->time_conv = process_event_op2_stub; +if (tool->feature ==NULL ) + tool->feature = process_event_op2_stub; }static void swap_sample_id_all (union perf_event *event,void *data)
@@ -1371,6 +1373,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,case PERF_RECORD_TIME_CONV : session->time_conv = event->time_conv;return tool->time_conv (tool, event, session); +case PERF_RECORD_HEADER_FEATURE : +return tool->feature (tool, event, session);default :return -EINVAL ; }
tools/perf/util/tool.h +2 -1
@@ -69,7 +69,8 @@ struct perf_tool { cpu_map, stat_config, stat, - stat_round; + stat_round, + feature;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
Re: [PATCH v4 15/16] perf tools: add feature header record to pipe-mode
On Mon, Jun 12, 2017 at 09:29:31PM -0700, David Carrillo-Cisneros wrote:
SNIP
Quoted 15 lines
tools/perf/util/header.c +15
-0+ +for_each_set_bit (feat, header->adds_features,HEADER_FEAT_BITS ) { +if (!feat_ops[feat].synthesize) { +pr_debug ("No record header feature for header :%d\n" , feat); +continue ; + } + + ff.offset =sizeof (*fe); + + ret = feat_ops[feat].write (&ff, evlist); +if (ret || ff.offset <= (ssize_t )sizeof (*fe)) { +pr_debug ("Error writing feature\n" ); +continue ; + } +
tools/perf/util/header.c int perf_event__synthesize_attr(struct perf_tool *tool, · line 3027
Quoted 10 lines
tools/perf/util/header.c +10
-0+/* ff.buf may have changed due to realloc in do_write() */ + fe = ff.buf; +memset (fe,0 ,sizeof (*fe)); + + fe->feat_id = feat; + fe->header.type =PERF_RECORD_HEADER_FEATURE ; + fe->header.size = ff.offset; + + ret =process (tool, ff.buf,NULL ,NULL ); +if (ret)
leaking ff.buf
jirka
Quoted 6 lines
tools/perf/util/header.c +6
-0+return ret; + } +free (ff.buf); +return 0 ; +} +
Re: [PATCH v4 15/16] perf tools: add feature header record to pipe-mode
In reply to David Carrillo-CisnerosOn Mon, Jun 12, 2017 at 09:29:31PM -0700, David Carrillo-Cisneros wrote:
SNIP
Quoted 15 lines
void
perf_event__print_totals(void);tools/perf/util/header.c +1
-0@@ -34,6 +34,7 @@#include "data.h" #include <api/fs/fs.h> #include "asm/bug.h" +#include "tool.h" #include "sane_ctype.h"
tools/perf/util/header.c static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size) · line 102
Quoted 6 lines
tools/perf/util/header.c +2
-1@@ -97,11 +98,14 @@ static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size) retry:if (size > (ff->size - ff->offset)) { - addr =realloc (ff->buf, ff->size <<1 ); + size = ff->size <<1 ; +if (size > page_size)
event size could be 0xffff - sizeof(struct perf_event_header) also the initial size is most likely > page_size anyway
please put this into the patch that introduced __do_write_buf
jirka
Re: [PATCH v4 15/16] perf tools: add feature header record to pipe-mode
Quoted 29 lines · Jiri Olsa
On Mon, Jun 12, 2017 at 09:29:31PM -0700, David Carrillo-Cisneros wrote:
SNIP
Quoted 15 lines
void
perf_event__print_totals(void);tools/perf/util/header.c +1
-0@@ -34,6 +34,7 @@#include "data.h" #include <api/fs/fs.h> #include "asm/bug.h" +#include "tool.h" #include "sane_ctype.h" tools/perf/util/header.c static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size) · line 102
Quoted 6 lines
tools/perf/util/header.c +2
-1@@ -97,11 +98,14 @@ static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size) retry:if (size > (ff->size - ff->offset)) { - addr =realloc (ff->buf, ff->size <<1 ); + size = ff->size <<1 ; +if (size > page_size)event size could be
0xffff-sizeof(struct perf_event_header)also the initial size is most likely >page_sizeanyway
Quoted 2 lines
please put this into the patch that introduced
__do_write_buf
Thank you for reviewing this. I just realized that I sent v5 without properly addressing this issue. In v4 I tried to add a quick check without properly understanding the issue. Why is 0xffff the maximum size for an event? where is this constraint coming from?
Thanks,
David
Re: [PATCH v4 15/16] perf tools: add feature header record to pipe-mode
Quoted 30 lines · David Carrillo-Cisneros
Quoted 29 lines · Jiri Olsa
On Mon, Jun 12, 2017 at 09:29:31PM -0700, David Carrillo-Cisneros wrote:
SNIP
Quoted 15 lines
void
perf_event__print_totals(void);tools/perf/util/header.c +1
-0@@ -34,6 +34,7 @@#include "data.h" #include <api/fs/fs.h> #include "asm/bug.h" +#include "tool.h" #include "sane_ctype.h" tools/perf/util/header.c static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size) · line 102
Quoted 6 lines
tools/perf/util/header.c +2
-1@@ -97,11 +98,14 @@ static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size) retry:if (size > (ff->size - ff->offset)) { - addr =realloc (ff->buf, ff->size <<1 ); + size = ff->size <<1 ; +if (size > page_size)event size could be
0xffff-sizeof(struct perf_event_header)also the initial size is most likely >page_sizeanyway
Quoted 7 lines
Quoted 2 lines
please put this into the patch that introduced
__do_write_bufThank you for reviewing this. I just realized that I sent v5 without properly addressing this issue. In v4 I tried to add a quick check without properly understanding the issue. Why is
0xffffthe maximum size for an event? where is this constraint coming from?
the struct perf_event_header::size is u16
jirka
Re: [PATCH v4 15/16] perf tools: add feature header record to pipe-mode
Quoted 34 lines · Jiri Olsa
Quoted 33 lines · David Carrillo-Cisneros
Quoted 31 lines · Jiri Olsa
On Mon, Jun 12, 2017 at 09:29:31PM -0700, David Carrillo-Cisneros wrote:
SNIP
Quoted 15 lines
void
perf_event__print_totals(void);tools/perf/util/header.c +1
-0@@ -34,6 +34,7 @@#include "data.h" #include <api/fs/fs.h> #include "asm/bug.h" +#include "tool.h" #include "sane_ctype.h" tools/perf/util/header.c static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size) · line 102
Quoted 6 lines
tools/perf/util/header.c +2
-1@@ -97,11 +98,14 @@ static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size) retry:if (size > (ff->size - ff->offset)) { - addr =realloc (ff->buf, ff->size <<1 ); + size = ff->size <<1 ; +if (size > page_size)event size could be
0xffff-sizeof(struct perf_event_header)also the initial size is most likely >page_sizeanywayplease put this into the patch that introduced
__do_write_buf
Quoted 6 lines
Quoted 4 lines
Thank you for reviewing this. I just realized that I sent v5 without properly addressing this issue. In v4 I tried to add a quick check without properly understanding the issue. Why is
0xffffthe maximum size for an event? where is this constraint coming from?the struct
perf_event_header::sizeis u16
ok, it makes sense now. I submitted v6, hopefully handling the resize properly.
PATCH v4 16/16 perf header: add event desc to pipe-mode header
In reply to David Carrillo-CisnerosAdd event descriptor to perf header output in pipe-mode.
After this patch:
$ perf record -e cycles sleep 1 | perf report --header
# ========
# captured on: Mon Jun 5 22:52:13 2017
# ========
#
# hostname : lphh20
# os release : 4.3.5-smp-801.43.0.0
# perf version : 4.12.rc2.g439987
# arch : x86_64
# nrcpus online : 72
# nrcpus avail : 72
# cpudesc : Intel(R) Xeon(R) CPU E5-2696 v3 @ 2.30GHz
# cpuid : GenuineIntel,6,63,2
# total memory : 264134144 kB
# cmdline : /root/perf record -e cycles sleep 1
# event : name = cycles, , size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|PERIOD, disabled = 1, inherit = 1, mmap = 1, comm = 1, freq = 1, enable_on_exec = 1, task = 1, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1
# CPU_TOPOLOGY info available, use -I to display
# NUMA_TOPOLOGY info available, use -I to display
# pmu mappings: intel_bts = 6, cpu = 4, msr = 49, uncore_cbox_10 = 36, uncore_cbox_11 = 37, uncore_cbox_12 = 38, uncore_cbox_13 = 39, uncore_cbox_14 = 40, uncore_cbox_15 = 41, uncore_cbox_16 = 42, uncore_cbox_17 = 43, software = 1, power = 7, uncore_irp = 24, uncore_pcu = 48, tracepoint = 2, uncore_imc_0 = 16, uncore_imc_1 = 17, uncore_imc_2 = 18, uncore_imc_3 = 19, uncore_imc_4 = 20, uncore_imc_5 = 21, uncore_imc_6 = 22, uncore_imc_7 = 23, uncore_qpi_0 = 8, uncore_qpi_1 = 9, uncore_cbox_0 = 26, uncore_cbox_1 = 27, uncore_cbox_2 = 28, uncore_cbox_3 = 29, uncore_cbox_4 = 30, uncore_cbox_5 = 31, uncore_cbox_6 = 32, uncore_cbox_7 = 33, uncore_cbox_8 = 34, uncore_cbox_9 = 35, uncore_r2pcie = 13, uncore_r3qpi_0 = 10, uncore_r3qpi_1 = 11, uncore_r3qpi_2 = 12, uncore_sbox_0 = 44, uncore_sbox_1 = 45, uncore_sbox_2 = 46, uncore_sbox_3 = 47, breakpoint = 5, uncore_ha_0 = 14, uncore_ha_1 = 15, uncore_ubox = 25
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.000 MB (null) ]Prior to this patch, event was not printed.
--- tools/perf/util/header.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
tools/perf/util/header.c +17 -2
@@ -66,6 +66,7 @@ struct feat_fd {void *buf;/* Either buf != NULL or fd >= 0 */ ssize_t offset;size_t size; +struct perf_evsel *events; };void perf_header__set_feat (struct perf_header *header,int feat)
@@ -1353,10 +1354,15 @@ static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,static void print_event_desc (struct feat_fd *ff,FILE *fp) { -struct perf_evsel *evsel, *events =read_event_desc (ff); +struct perf_evsel *evsel, *events;u32 j;u64 *id; +if (ff->events) + events = ff->events; +else + events =read_event_desc (ff); +if (!events) {fprintf (fp,"# event desc: not available or unable to read\n" );return ;
@@ -1381,6 +1387,7 @@ static void print_event_desc(struct feat_fd *ff, FILE *fp) }free_event_desc (events); + ff->events =NULL ; }static void print_total_mem (struct feat_fd *ff,FILE *fp)
@@ -1751,10 +1758,18 @@ process_event_desc(struct feat_fd *ff, void *data __maybe_unused)return 0 ; session = container_of(ff->ph, struct perf_session, header); + +if (session->file->is_pipe) { +/* Save events for reading later by print_event_desc, +* since they can't be read again in pipe mode. */ + ff->events = events; + } +for (evsel = events; evsel->attr.size; evsel++)perf_evlist__set_event_name (session->evlist, evsel); -free_event_desc (events); +if (!session->file->is_pipe) +free_event_desc (events);return 0 ; }
Signature · 1 line
2.13.1.508.gb3defc5cc-goog
Quoted 3 lines · David Carrillo-Cisneros
v4: - Limit write_* functions to
page_size.
- Fixed bugs spotted by Jiri.
- Add information about pipe-mode to some error messages.
hum, looks like we have pipe report broken.. on arnaldo's perf/core branch:
[jolsa@krava perf]$ ./perf record ls | ./perf report
# To display the perf.data header info, please use --header/--header-only options. #
...
[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.000 MB (null) ] #
# Total Lost Samples: 0
#
# Samples: 10 of event 'cycles:uhH'
# Event count (approx.): 1810081
#
# Overhead Trace output
# ........ ............ # 100.00% N/A
thanks,
jirka
Quoted 22 lines · Jiri Olsa
Quoted 3 lines · David Carrillo-Cisneros
v4: - Limit write_* functions to
page_size.
- Fixed bugs spotted by Jiri.
- Add information about pipe-mode to some error messages.hum, looks like we have pipe report broken.. on arnaldo's perf/core branch:
[jolsa@krava perf]$ ./perf record ls | ./perf report
# To display the perf.data header info, please use --header/--header-only options. #...
[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.000 MB (null) ] #
# Total Lost Samples: 0
#
# Samples: 10 of event 'cycles:uhH'
# Event count (approx.): 1810081
#
# Overhead Trace output
Quoted 3 lines
# ........ ............ # 100.00% N/A
I saw this bug before, that time I bisected it to commit d49dadea7862 ("perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events") from Dec 2015 but didn't have time to look further into it ...
David
Quoted 3 lines · David Carrillo-Cisneros
v4: - Limit write_* functions to
page_size.
- Fixed bugs spotted by Jiri.
- Add information about pipe-mode to some error messages.
looks like this version breaks the normal report
[jolsa@krava perf]$ ./perf report --header-only -I [jolsa@krava perf]$
jirka
Quoted 9 lines · Jiri Olsa
Quoted 3 lines · David Carrillo-Cisneros
v4: - Limit write_* functions to
page_size.
- Fixed bugs spotted by Jiri.
- Add information about pipe-mode to some error messages.looks like this version breaks the normal report
[jolsa@krava perf]$ ./perf report --header-only -I [jolsa@krava perf]$
Is the command simply terminating without any output? I cannot reproduce it. In my machines it works:
$ ./perf report --header-only -I
# ========
# captured on: Tue Jun 13 23:49:13 2017
# hostname : lphh20
# os release : 4.3.5-smp-801.43.0.0
# perf version : 4.12.rc4.gf2978e
# arch : x86_64
# nrcpus online : 72
# nrcpus avail : 72
# cpudesc : Intel(R) Xeon(R) CPU E5-2696 v3 @ 2.30GHz
# cpuid : GenuineIntel,6,63,2
# total memory : 264134144 kB
# cmdline : /root/perf record ls
# event : name = cycles:pp, , size = 112, { sample_period, sample_freq
} = 4000, sample_type = IP|TID|TIME|PERIOD, disa
# sibling cores : 0-17,36-53
# sibling cores : 18-35,54-71
[SNIP]Is your perf.data from the same version?
Quoted 2 lines
jirka
Quoted 33 lines · David Carrillo-Cisneros
Quoted 9 lines · Jiri Olsa
Quoted 3 lines · David Carrillo-Cisneros
v4: - Limit write_* functions to
page_size.
- Fixed bugs spotted by Jiri.
- Add information about pipe-mode to some error messages.looks like this version breaks the normal report
[jolsa@krava perf]$ ./perf report --header-only -I [jolsa@krava perf]$
Is the command simply terminating without any output? I cannot reproduce it. In my machines it works:
$ ./perf report --header-only -I # ======== # captured on: Tue Jun 13 23:49:13 2017 # hostname : lphh20 # os release : 4.3.5-smp-801.43.0.0 # perf version : 4.12.rc4.gf2978e # arch : x86_64 # nrcpus online : 72 # nrcpus avail : 72 # cpudesc : Intel(R) Xeon(R) CPU E5-2696 v3 @ 2.30GHz # cpuid : GenuineIntel,6,63,2 # total memory : 264134144 kB # cmdline : /root/perf record ls # event : name = cycles:pp, , size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|PERIOD, disa # sibling cores : 0-17,36-53 # sibling cores : 18-35,54-71 [SNIP]
Quoted 1 line
Is your perf.data from the same version?
yes:
[jolsa@krava perf]$ ./perf record kill
kill: not enough arguments
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.016 MB perf.data (7 samples) ] [jolsa@krava perf]$ ./perf report --header-only -I [jolsa@krava perf]$
but I'm actualy using branch I found in your tree: ccdavid/toup_june12_pipeheaders_00, maybe it's not the latest
[jolsa@krava perf]$ git log --oneline | head -1 a16f0acca1d2 perf header: add event desc to pipe-mode header
jirka
Quoted 45 lines · Jiri Olsa
Quoted 33 lines · David Carrillo-Cisneros
Quoted 9 lines · Jiri Olsa
Quoted 3 lines · David Carrillo-Cisneros
v4: - Limit write_* functions to
page_size.
- Fixed bugs spotted by Jiri.
- Add information about pipe-mode to some error messages.looks like this version breaks the normal report
[jolsa@krava perf]$ ./perf report --header-only -I [jolsa@krava perf]$
Is the command simply terminating without any output? I cannot reproduce it. In my machines it works:
$ ./perf report --header-only -I # ======== # captured on: Tue Jun 13 23:49:13 2017 # hostname : lphh20 # os release : 4.3.5-smp-801.43.0.0 # perf version : 4.12.rc4.gf2978e # arch : x86_64 # nrcpus online : 72 # nrcpus avail : 72 # cpudesc : Intel(R) Xeon(R) CPU E5-2696 v3 @ 2.30GHz # cpuid : GenuineIntel,6,63,2 # total memory : 264134144 kB # cmdline : /root/perf record ls # event : name = cycles:pp, , size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|PERIOD, disa # sibling cores : 0-17,36-53 # sibling cores : 18-35,54-71 [SNIP]Quoted 1 line
Is your perf.data from the same version?
yes:
[jolsa@krava perf]$ ./perf record kill
kill: not enough arguments
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.016 MB perf.data (7 samples) ] [jolsa@krava perf]$ ./perf report --header-only -I [jolsa@krava perf]$
Quoted 5 lines
but I'm actualy using branch I found in your tree: ccdavid/toup_june12_pipeheaders_00, maybe it's not the latest
[jolsa@krava perf]$ git log --oneline | head -1
a16f0acca1d2perf header: add event desc to pipe-mode header
Ok, found the problem. Output is hidden by the ui in certain perf configurations. Will fix for next version. Thanks for looking into it.
David