Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[GIT PULL 00/86] perf/core improvements and fixes

104 views
Skip to first unread message

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:00:10 AM7/19/17
to
Hi Ingo,

Unusually big one, please conside pulling, details on the signed tag,

- Arnaldo

Test results at the end of this message, as usual.

The following changes since commit 4b1303d0b01440f224cf81493b7e8e43d9b4965e:

perf symbols: Accept zero as the kernel base address (2017-07-12 11:47:05 -0300)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-4.13-20170718

for you to fetch changes up to b851dd49868e295e18c5d72fc3bad85ff1c444b1:

perf report: Show branch type in callchain entry (2017-07-18 23:14:42 -0300)

----------------------------------------------------------------
perf/core improvements and fixes:

User visible:

. Initial support for namespaces, using setns to access files in
namespaces, grabbing their build-ids, etc. We still need to work
more to deal with namespaces that vanish before we can get the
needed data to do analysis, but this should be as good as what is
in bcc now (Krister Johansen)

. Add header record types to pipe-mode, now this command:

$ perf record -o - -e cycles sleep 1 | perf report --stdio --header

Will show the same as in non-pipe mode, i.e. involving a perf.data
file (David Carrillo-Cisneros)

. Implement a visual marker for fused x86 instructions in the annotate
TUI browser, available now in 'perf report', more work needed to have
it available as well in 'perf top' (Jin Yao)

Further explanation from one of Jin's patches:

│ ┌──cmpl $0x0,argp_program_version_hook
81.93 │ ├──je 20
│ │ lock cmpxchg %esi,0x38a9a4(%rip)
│ │↓ jne 29
│ │↓ jmp 43
11.47 │20:└─→cmpxch %esi,0x38a999(%rip)

That means the cmpl+je is a fused instruction pair and they should be
considered together.

. Record the branch type and then show statistics and info about
in callchain entries (Jin Yao)

Example from one of Jin's patches:

# perf record -g -j any,save_type
# perf report --branch-history --stdio --no-children

38.50% div.c:45 [.] main div
|
---main div.c:42 (RET CROSS_2M cycles:2)
compute_flag div.c:28 (cycles:2)
compute_flag div.c:27 (RET CROSS_2M cycles:1)
rand rand.c:28 (cycles:1)
rand rand.c:28 (RET CROSS_2M cycles:1)
__random random.c:298 (cycles:1)
__random random.c:297 (COND_BWD CROSS_2M cycles:1)
__random random.c:295 (cycles:1)
__random random.c:295 (COND_BWD CROSS_2M cycles:1)
__random random.c:295 (cycles:1)
__random random.c:295 (RET CROSS_2M cycles:9)

. Beautify the fcntl syscall, which is an interesting one in the sense
that infrastructure had to be put in place to change the formatters of
some arguments according to the value in a previous one, i.e. cmd
dictates how arg and the syscall return will be formatted.
(Arnaldo Carvalho de Melo

Infrastructure:

. 'perf test attr' fixes (Jiri Olsa)

Vendor events:

- Add POWER9 PMU events Sukadev (Bhattiprolu)

- Support additional POWER8+ PVR in PMU mapfile (Shriya)

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

----------------------------------------------------------------
Arnaldo Carvalho de Melo (39):
perf trace: Remove F_ from some of the fcntl command strings
perf trace: Beautify linux specific fcntl commands
tools: Update include/uapi/linux/fcntl.h copy from the kernel
perf trace beauty: Export the strarrays scnprintf method
perf trace: Only build tools/perf/trace/beauty/ when building 'perf trace'
perf trace beauty: Mask ignored fcntl 'arg' parameter
perf trace beauty: Allow accessing syscall args values in a syscall arg formatter
perf trace beauty: Export the "int" and "hex" syscall arg formatters
perf trace beauty: Introduce syscall arg beautifier for long integers
tools include uapi asm-generic: Grab a copy of fcntl.h
perf trace beauty fcntl: Basic 'arg' beautifier
perf trace: Beautify new write hint fcntl commands
perf beauty open: Detach the syscall_arg agnostic bits from the flags formatter
perf trace: Allow syscall_arg beautifiers to set a different return formatter
perf trace beauty open flags: Support O_TMPFILE and O_NOFOLLOW
perf trace beauty open flags: Do not depend on the system's O_LARGEFILE define
perf trace beauty fcntl: Beautify F_GETFL return value
perf trace beauty open flags: Move RDRW to the start of the output
perf trace beauty fcntl flags: Beautify F_SETFL arg
perf trace beauty fcntl: Beautify F_[GS]ETFD arg/return value
perf trace beauty: Give syscall return beautifier more context
perf trace beauty: Export the fd beautifier for use in more places
perf trace beauty fcntl: Augment the return of F_DUPFD(_CLOEXEC)
perf trace beauty: Export the pid beautifier for use in more places
perf trace beauty fcntl: Beautify F_GETOWN and F_SETOWN
tools include uapi x86: Grab a copy of unistd.h
tools include uapi x86: Add __NR_setns, if missing
tools build: Add test for setns()
perf evsel: Allow asking for max precise_ip in new_cycles()
perf evlist: Allow asking for max precise_ip in add_default()
perf record: Do not ask for precise_ip with --no-samples
perf test sdt: Handle realpath() failure
perf trace beauty: Export strarray for use in per-object beautifiers
perf trace beauty fcntl: Beautify F_GETLEASE and F_SETLEASE arg/return
perf trace: Group per syscall arg formatter info into one struct
perf trace: Allow syscall arg formatters to request non suppression of zeros
perf trace beauty fcntl: Do not suppress 'cmd' when zero, should be DUPFD
perf trace beauty fcntl: Beautify the 'arg' for DUPFD
perf trace beauty: Simplify syscall return formatting

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

Jin Yao (10):
perf annotate: Check for fused instructions
perf annotate: Implement visual marker for macro fusion
perf report: Enable finding kernel inline functions
perf/core: Define the common branch type classification
perf/x86/intel: Record branch type
perf record: Create a new option save_type in --branch-filter
perf report: Refactor the branch info printing code
perf util: Create branch.c/.h for common branch functions
perf report: Show branch type statistics for stdio mode
perf report: Show branch type in callchain entry

Jiri Olsa (13):
perf tests attr: Do not store failed events
perf tests attr: Add test_attr__ready function
perf tests attr: Make compare_data global
perf tests attr: Rename compare_data to data_equal
perf tests attr: Add 1s for exclude_kernel and task base bits
perf tests attr: Fix record dwarf test
perf tests attr: Fix no-delay test
perf tests attr: Add proper return values
perf tests attr: Fix cpu test disabled term setup
perf tests attr: Fix sample_period setup
perf tests attr: Fix precise_ip setup
perf tests attr: Fix stat sample_type setup
perf tests attr: Add optional term

Krister Johansen (5):
perf symbols: Find symbols in different mount namespace
perf maps: Lookup maps in both intitial mountns and inner mountns.
perf probe: Allow placing uprobes in alternate namespaces.
perf buildid-cache: Support binary objects from other namespaces
perf buildid-cache: Cache debuginfo

Shriya (1):
perf pmu-events: Support additional POWER8+ PVR in mapfile

Sukadev Bhattiprolu (2):
perf vendor events: Add POWER9 PMU events
perf vendor events: Add POWER9 PVRs to mapfile

arch/x86/events/intel/lbr.c | 52 +-
include/uapi/linux/perf_event.h | 27 +-
tools/arch/x86/include/asm/unistd_32.h | 3 +
tools/arch/x86/include/asm/unistd_64.h | 3 +
tools/arch/x86/include/uapi/asm/unistd.h | 17 +
tools/build/Makefile.feature | 3 +-
tools/build/feature/Makefile | 6 +-
tools/build/feature/test-all.c | 5 +
tools/build/feature/test-setns.c | 7 +
tools/include/uapi/asm-generic/fcntl.h | 220 +++++
tools/include/uapi/linux/fcntl.h | 21 +
tools/include/uapi/linux/perf_event.h | 27 +-
tools/perf/Build | 2 +-
tools/perf/Documentation/perf-buildid-cache.txt | 5 +
tools/perf/Documentation/perf-probe.txt | 14 +
tools/perf/Documentation/perf-record.txt | 1 +
tools/perf/Documentation/perf.data-file-format.txt | 10 +-
tools/perf/Makefile.config | 5 +
tools/perf/arch/powerpc/util/sym-handling.c | 2 +-
tools/perf/arch/x86/annotate/instructions.c | 46 +
tools/perf/builtin-annotate.c | 1 +
tools/perf/builtin-buildid-cache.c | 54 +-
tools/perf/builtin-inject.c | 1 +
tools/perf/builtin-probe.c | 45 +-
tools/perf/builtin-record.c | 9 +-
tools/perf/builtin-report.c | 30 +
tools/perf/builtin-script.c | 4 +
tools/perf/builtin-top.c | 2 +-
tools/perf/builtin-trace.c | 602 ++++++------
tools/perf/check-headers.sh | 1 +
tools/perf/perf.h | 1 +
tools/perf/pmu-events/arch/powerpc/mapfile.csv | 4 +
.../perf/pmu-events/arch/powerpc/power9/cache.json | 176 ++++
.../arch/powerpc/power9/floating-point.json | 44 +
.../pmu-events/arch/powerpc/power9/frontend.json | 446 +++++++++
.../pmu-events/arch/powerpc/power9/marked.json | 782 +++++++++++++++
.../pmu-events/arch/powerpc/power9/memory.json | 158 +++
.../perf/pmu-events/arch/powerpc/power9/other.json | 836 ++++++++++++++++
.../pmu-events/arch/powerpc/power9/pipeline.json | 680 +++++++++++++
tools/perf/pmu-events/arch/powerpc/power9/pmc.json | 146 +++
.../arch/powerpc/power9/translation.json | 272 ++++++
tools/perf/tests/attr.c | 12 +-
tools/perf/tests/attr.py | 50 +-
tools/perf/tests/attr/base-record | 6 +-
tools/perf/tests/attr/base-stat | 4 +-
tools/perf/tests/attr/test-record-C0 | 1 +
tools/perf/tests/attr/test-record-basic | 1 +
tools/perf/tests/attr/test-record-branch-any | 2 +-
.../perf/tests/attr/test-record-branch-filter-any | 2 +-
.../tests/attr/test-record-branch-filter-any_call | 2 +-
.../tests/attr/test-record-branch-filter-any_ret | 2 +-
tools/perf/tests/attr/test-record-branch-filter-hv | 2 +-
.../tests/attr/test-record-branch-filter-ind_call | 2 +-
tools/perf/tests/attr/test-record-branch-filter-k | 2 +-
tools/perf/tests/attr/test-record-branch-filter-u | 2 +-
tools/perf/tests/attr/test-record-count | 1 +
tools/perf/tests/attr/test-record-data | 3 +-
tools/perf/tests/attr/test-record-freq | 1 +
tools/perf/tests/attr/test-record-graph-default | 1 +
tools/perf/tests/attr/test-record-graph-dwarf | 4 +-
tools/perf/tests/attr/test-record-graph-fp | 1 +
tools/perf/tests/attr/test-record-group | 1 +
tools/perf/tests/attr/test-record-group-sampling | 1 +
tools/perf/tests/attr/test-record-group1 | 1 +
...st-record-no-delay => test-record-no-buffering} | 4 +-
tools/perf/tests/attr/test-record-no-inherit | 1 +
tools/perf/tests/attr/test-record-no-samples | 1 +
tools/perf/tests/attr/test-record-period | 1 +
tools/perf/tests/attr/test-record-raw | 2 +-
tools/perf/tests/attr/test-stat-C0 | 4 +-
tools/perf/tests/attr/test-stat-default | 2 +
tools/perf/tests/attr/test-stat-detailed-1 | 2 +
tools/perf/tests/attr/test-stat-detailed-2 | 3 +
tools/perf/tests/attr/test-stat-detailed-3 | 5 +
tools/perf/tests/sdt.c | 8 +-
tools/perf/trace/beauty/Build | 1 +
tools/perf/trace/beauty/beauty.h | 65 ++
tools/perf/trace/beauty/fcntl.c | 100 ++
tools/perf/trace/beauty/open_flags.c | 29 +-
tools/perf/trace/beauty/pid.c | 4 +-
tools/perf/ui/browser.c | 29 +
tools/perf/ui/browser.h | 2 +
tools/perf/ui/browsers/annotate.c | 30 +-
tools/perf/ui/browsers/hists.c | 3 -
tools/perf/ui/gtk/annotate.c | 2 +-
tools/perf/ui/stdio/hist.c | 3 -
tools/perf/util/Build | 5 +
tools/perf/util/annotate.c | 29 +-
tools/perf/util/annotate.h | 4 +-
tools/perf/util/branch.c | 147 +++
tools/perf/util/branch.h | 24 +
tools/perf/util/build-id.c | 129 ++-
tools/perf/util/build-id.h | 16 +-
tools/perf/util/callchain.c | 134 +--
tools/perf/util/callchain.h | 5 +-
tools/perf/util/dso.c | 21 +-
tools/perf/util/dso.h | 3 +
tools/perf/util/event.c | 1 +
tools/perf/util/event.h | 11 +-
tools/perf/util/evlist.c | 4 +-
tools/perf/util/evlist.h | 9 +-
tools/perf/util/evsel.c | 18 +-
tools/perf/util/evsel.h | 3 +-
tools/perf/util/header.c | 1015 +++++++++++---------
tools/perf/util/header.h | 16 +-
tools/perf/util/hist.c | 5 +-
tools/perf/util/machine.c | 33 +-
tools/perf/util/map.c | 23 +-
tools/perf/util/map.h | 2 +-
tools/perf/util/namespaces.c | 211 ++++
tools/perf/util/namespaces.h | 38 +
tools/perf/util/parse-branch-options.c | 1 +
tools/perf/util/parse-events.c | 2 +-
tools/perf/util/probe-event.c | 86 +-
tools/perf/util/probe-event.h | 10 +-
tools/perf/util/probe-file.c | 19 +-
tools/perf/util/probe-file.h | 4 +-
tools/perf/util/python-ext-sources | 1 +
tools/perf/util/session.c | 4 +
tools/perf/util/setns.c | 8 +
tools/perf/util/symbol.c | 92 +-
tools/perf/util/thread.c | 3 +
tools/perf/util/thread.h | 1 +
tools/perf/util/tool.h | 10 +-
tools/perf/util/util.c | 40 +-
tools/perf/util/util.h | 8 +-
126 files changed, 6339 insertions(+), 1031 deletions(-)
create mode 100644 tools/arch/x86/include/uapi/asm/unistd.h
create mode 100644 tools/build/feature/test-setns.c
create mode 100644 tools/include/uapi/asm-generic/fcntl.h
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/cache.json
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/floating-point.json
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/frontend.json
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/marked.json
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/memory.json
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/other.json
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/pmc.json
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/translation.json
rename tools/perf/tests/attr/{test-record-no-delay => test-record-no-buffering} (61%)
create mode 100644 tools/perf/trace/beauty/fcntl.c
create mode 100644 tools/perf/util/branch.c
create mode 100644 tools/perf/util/branch.h
create mode 100644 tools/perf/util/setns.c

Test results at the end of this message, as usual.

Test results:

The first ones are container (docker) based builds of tools/perf with and
without libelf support, objtool where it is supported and samples/bpf/, ditto.
Where clang is available, it is also used to build perf with/without libelf.

Several are cross builds, the ones with -x-ARCH, and the android one, and those
may not have all the features built, due to lack of multi-arch devel packages,
available and being used so far on just a few, like
debian:experimental-x-{arm64,mipsel}.

The 'perf test' one will perform a variety of tests exercising
tools/perf/util/, tools/lib/{bpf,traceevent,etc}, as well as run perf commands
with a variety of command line event specifications to then intercept the
sys_perf_event syscall to check that the perf_event_attr fields are set up as
expected, among a variety of other unit tests.

Then there is the 'make -C tools/perf build-test' ones, that build tools/perf/
with a variety of feature sets, exercising the build with an incomplete set of
features as well as with a complete one. It is planned to have it run on each
of the containers mentioned above, using some container orchestration
infrastructure. Get in contact if interested in helping having this in place.

The fedora:rawhide case is being investigated, doesn't seem to have been
introduced by this batch:

LINK /tmp/build/perf/perf
LINK /tmp/build/perf/libperf-gtk.so
/usr/bin/ld: /tmp/build/perf/perf-in.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /tmp/build/perf/libperf.a(libperf-in.o): relocation R_X86_64_32S against `.text' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
make[2]: *** [Makefile.perf:420: /tmp/build/perf/perf] Error 1

# dm
1 alpine:3.4: Ok
2 alpine:3.5: Ok
3 alpine:3.6: Ok
4 alpine:edge: Ok
5 android-ndk:r12b-arm: Ok
6 archlinux:latest: Ok
7 centos:5: Ok
8 centos:6: Ok
9 centos:7: Ok
10 debian:7: Ok
11 debian:8: Ok
12 debian:9: Ok
13 debian:experimental: Ok
14 debian:experimental-x-arm64: Ok
15 debian:experimental-x-mips: Ok
16 debian:experimental-x-mips64: Ok
17 debian:experimental-x-mipsel: Ok
18 fedora:20: Ok
19 fedora:21: Ok
20 fedora:22: Ok
21 fedora:23: Ok
22 fedora:24: Ok
23 fedora:24-x-ARC-uClibc: Ok
24 fedora:25: Ok
25 fedora:26: Ok
26 fedora:rawhide: FAIL
27 mageia:5: Ok
28 opensuse:13.2: Ok
29 opensuse:42.1: Ok
30 opensuse:42.2: Ok
31 opensuse:tumbleweed: Ok
32 oraclelinux:6: Ok
33 oraclelinux:7: Ok
34 ubuntu:12.04.5: Ok
35 ubuntu:14.04.4: Ok
36 ubuntu:14.04.4-x-linaro-arm64: Ok
37 ubuntu:15.10: Ok
38 ubuntu:16.04: Ok
39 ubuntu:16.04-x-arm: Ok
40 ubuntu:16.04-x-arm64: Ok
41 ubuntu:16.04-x-powerpc: Ok
42 ubuntu:16.04-x-powerpc64: Ok
43 ubuntu:16.04-x-powerpc64el: Ok
44 ubuntu:16.04-x-s390: Ok
45 ubuntu:16.10: Ok
46 ubuntu:17.04: Ok
47 ubuntu:17.10: Ok
#

# uname -a
Linux jouet 4.12.0-rc6+ #3 SMP Tue Jun 27 15:12:38 -03 2017 x86_64 x86_64 x86_64 GNU/Linux
# perf test
1: vmlinux symtab matches kallsyms : Ok
2: Detect openat syscall event : Ok
3: Detect openat syscall event on all cpus : Ok
4: Read samples using the mmap interface : Ok
5: Parse event definition strings : Ok
6: Simple expression parser : Ok
7: PERF_RECORD_* events & perf_sample fields : Ok
8: Parse perf pmu format : Ok
9: DSO data read : Ok
10: DSO data cache : Ok
11: DSO data reopen : Ok
12: Roundtrip evsel->name : Ok
13: Parse sched tracepoints fields : Ok
14: syscalls:sys_enter_openat event fields : Ok
15: Setup struct perf_event_attr : Ok
16: Match and link multiple hists : Ok
17: 'import perf' in python : Ok
18: Breakpoint overflow signal handler : Ok
19: Breakpoint overflow sampling : Ok
20: Number of exit events of a simple workload : Ok
21: Software clock events period values : Ok
22: Object code reading : Ok
23: Sample parsing : Ok
24: Use a dummy software event to keep tracking: Ok
25: Parse with no sample_id_all bit set : Ok
26: Filter hist entries : Ok
27: Lookup mmap thread : Ok
28: Share thread mg : Ok
29: Sort output of hist entries : Ok
30: Cumulate child hist entries : Ok
31: Track with sched_switch : Ok
32: Filter fds with revents mask in a fdarray : Ok
33: Add fd to a fdarray, making it autogrow : Ok
34: kmod_path__parse : Ok
35: Thread map : Ok
36: LLVM search and compile :
36.1: Basic BPF llvm compile : Ok
36.2: kbuild searching : Ok
36.3: Compile source for BPF prologue generation: Ok
36.4: Compile source for BPF relocation : Ok
37: Session topology : Ok
38: BPF filter :
38.1: Basic BPF filtering : Ok
38.2: BPF pinning : Ok
38.3: BPF prologue generation : Ok
38.4: BPF relocation checker : Ok
39: Synthesize thread map : Ok
40: Remove thread map : Ok
41: Synthesize cpu map : Ok
42: Synthesize stat config : Ok
43: Synthesize stat : Ok
44: Synthesize stat round : Ok
45: Synthesize attr update : Ok
46: Event times : Ok
47: Read backward ring buffer : Ok
48: Print cpu map : Ok
49: Probe SDT events : Ok
50: is_printable_array : Ok
51: Print bitmap : Ok
52: perf hooks : Ok
53: builtin clang support : Skip (not compiled in)
54: unit_number__scnprintf : Ok
55: x86 rdpmc : Ok
56: Convert perf time to TSC : Ok
57: DWARF unwind : Ok
58: x86 instruction decoder - new instructions : Ok
59: Intel cqm nmi context read : Skip
#

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:00:10 AM7/19/17
to
From: Jin Yao <yao...@linux.intel.com>

For marking fused instructions clearly this patch adds a line before the
first instruction of pair and joins it with the arrow of the jump to its
target.

For example, when "je" is selected in annotate view, the line before
cmpl is displayed and joins the arrow of "je".

│ ┌──cmpl $0x0,argp_program_version_hook
81.93 │ ├──je 20
│ │ lock cmpxchg %esi,0x38a9a4(%rip)
│ │↓ jne 29
│ │↓ jmp 43
11.47 │20:└─→cmpxch %esi,0x38a999(%rip)

That means the cmpl+je is a fused instruction pair and they should be
considered together.

Changelog:

v3: Use Arnaldo's fix to improve the arrow origin rendering. To get the
evsel->evlist->env->cpuid, save the evsel in annotate_browser.

v2: new function "ins__is_fused" to check if the instructions are fused.

Signed-off-by: Yao Jin <yao...@linux.intel.com>
Tested-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Kan Liang <kan....@intel.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1499403995-19857-3-g...@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/ui/browser.c | 29 +++++++++++++++++++++++++++++
tools/perf/ui/browser.h | 2 ++
tools/perf/ui/browsers/annotate.c | 26 ++++++++++++++++++++++++++
tools/perf/util/annotate.c | 5 +++++
tools/perf/util/annotate.h | 1 +
5 files changed, 63 insertions(+)

diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 83874b0e266c..f73f3f13e01d 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -738,6 +738,35 @@ void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
__ui_browser__line_arrow_down(browser, column, start, end);
}

+void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column,
+ unsigned int row, bool arrow_down)
+{
+ unsigned int end_row;
+
+ if (row >= browser->top_idx)
+ end_row = row - browser->top_idx;
+ else
+ return;
+
+ SLsmg_set_char_set(1);
+
+ if (arrow_down) {
+ ui_browser__gotorc(browser, end_row, column - 1);
+ SLsmg_write_char(SLSMG_ULCORN_CHAR);
+ ui_browser__gotorc(browser, end_row, column);
+ SLsmg_draw_hline(2);
+ ui_browser__gotorc(browser, end_row + 1, column - 1);
+ SLsmg_write_char(SLSMG_LTEE_CHAR);
+ } else {
+ ui_browser__gotorc(browser, end_row, column - 1);
+ SLsmg_write_char(SLSMG_LTEE_CHAR);
+ ui_browser__gotorc(browser, end_row, column);
+ SLsmg_draw_hline(2);
+ }
+
+ SLsmg_set_char_set(0);
+}
+
void ui_browser__init(void)
{
int i = 0;
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index be3b70eb5fca..a12eff75638b 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -43,6 +43,8 @@ void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...);
void ui_browser__write_graph(struct ui_browser *browser, int graph);
void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
u64 start, u64 end);
+void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column,
+ unsigned int row, bool arrow_down);
void __ui_browser__show_title(struct ui_browser *browser, const char *title);
void ui_browser__show_title(struct ui_browser *browser, const char *title);
int ui_browser__show(struct ui_browser *browser, const char *title,
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index c4336138b673..8d3f6f53c122 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -273,6 +273,25 @@ static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sy
return true;
}

+static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
+{
+ struct disasm_line *pos = list_prev_entry(cursor, node);
+ const char *name;
+
+ if (!pos)
+ return false;
+
+ if (ins__is_lock(&pos->ins))
+ name = pos->ops.locked.ins.name;
+ else
+ name = pos->ins.name;
+
+ if (!name || !cursor->ins.name)
+ return false;
+
+ return ins__is_fused(ab->arch, name, cursor->ins.name);
+}
+
static void annotate_browser__draw_current_jump(struct ui_browser *browser)
{
struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
@@ -308,6 +327,13 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
__ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,
from, to);
+
+ if (is_fused(ab, cursor)) {
+ ui_browser__mark_fused(browser,
+ pcnt_width + 3 + ab->addr_width,
+ from - 1,
+ to > from ? true : false);
+ }
}

static unsigned int annotate_browser__refresh(struct ui_browser *browser)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 8748ebb3f932..ef434b53d849 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -517,6 +517,11 @@ bool ins__is_ret(const struct ins *ins)
return ins->ops == &ret_ops;
}

+bool ins__is_lock(const struct ins *ins)
+{
+ return ins->ops == &lock_ops;
+}
+
static int ins__key_cmp(const void *name, const void *insp)
{
const struct ins *ins = insp;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 72d72728a0fc..bac698d7cc6a 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -52,6 +52,7 @@ struct ins_ops {
bool ins__is_jump(const struct ins *ins);
bool ins__is_call(const struct ins *ins);
bool ins__is_ret(const struct ins *ins);
+bool ins__is_lock(const struct ins *ins);
int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:10:09 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

As we'll call it from the fcntl cmd scnprintf method, that needs to look
at the cmd to mask the next fcntl argument when it is ignored.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-fzlvkhew5v...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 6 ++----
tools/perf/trace/beauty/beauty.h | 3 +++
2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 431ef70067ed..ef1b1d4ea007 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -331,8 +331,8 @@ struct strarrays {
.entries = array, \
}

-static size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size,
+ struct syscall_arg *arg)
{
struct strarrays *sas = arg->parm;
int i;
@@ -351,8 +351,6 @@ static size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size,
return scnprintf(bf, size, "%d", arg->val);
}

-#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays
-
#if defined(__i386__) || defined(__x86_64__)
/*
* FIXME: Make this available to all arches as soon as the ioctl beautifier
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index cf50be3f17a4..a6348073a6e9 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -15,6 +15,9 @@ struct syscall_arg {
u8 mask;
};

+size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays
+
size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:10:09 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

As it calls functions in builtin-trace.c.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-bt3lhw1rvy...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/Build b/tools/perf/Build
index bd8eeb60533c..b48ca40fccf9 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -50,6 +50,6 @@ libperf-y += util/
libperf-y += arch/
libperf-y += ui/
libperf-y += scripts/
-libperf-y += trace/beauty/
+libperf-$(CONFIG_AUDIT) += trace/beauty/

gtk-y += ui/gtk/
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:10:09 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

A series of fcntl cmds ignore the third argument, so mask it.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-6vtl3zq1ta...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 2 +-
tools/perf/trace/beauty/Build | 1 +
tools/perf/trace/beauty/beauty.h | 3 +++
tools/perf/trace/beauty/fcntl.c | 23 +++++++++++++++++++++++
4 files changed, 28 insertions(+), 1 deletion(-)
create mode 100644 tools/perf/trace/beauty/fcntl.c

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index ef1b1d4ea007..b7f79dea3c44 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -661,7 +661,7 @@ static struct syscall_fmt {
{ .name = "fchownat", .errmsg = true,
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
{ .name = "fcntl", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_STRARRAYS, /* cmd */ },
+ .arg_scnprintf = { [1] = SCA_FCNTL_CMD, /* cmd */ },
.arg_parm = { [1] = &strarrays__fcntl_cmds_arrays, /* cmd */ }, },
{ .name = "fdatasync", .errmsg = true, },
{ .name = "flock", .errmsg = true,
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index be95ac6ce845..c9e215b806f1 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -1 +1,2 @@
+libperf-y += fcntl.o
libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index a6348073a6e9..ce01079d8422 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -18,6 +18,9 @@ struct syscall_arg {
size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays

+size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd
+
size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags

diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
new file mode 100644
index 000000000000..7e4582c9308e
--- /dev/null
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -0,0 +1,23 @@
+/*
+ * trace/beauty/fcntl.c
+ *
+ * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <ac...@redhat.com>
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include "trace/beauty/beauty.h"
+#include <uapi/linux/fcntl.h>
+
+size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg)
+{
+ /*
+ * Some commands ignore the third fcntl argument, "arg", so mask it
+ */
+ if (arg->val == F_GETFD || arg->val == F_GETFL ||
+ arg->val == F_GETOWN || arg->val == F_GET_SEALS ||
+ arg->val == F_GETLEASE || arg->val == F_GETSIG)
+ arg->mask |= (1 << 2);
+
+ return syscall_arg__scnprintf_strarrays(bf, size, arg);
+}
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:10:09 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

For instance, fcntl's upcoming 'arg' formatter needs to look at the
'cmd' value to decide how to format its value, sometimes it is a file
flags, sometimes an fd, a pointer to a structure, etc.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-2tw2jfaqm4...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 23 ++++++++++++++++-------
tools/perf/trace/beauty/beauty.h | 13 +++++++++++++
2 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index b7f79dea3c44..40bc0a326096 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1369,19 +1369,32 @@ static int trace__validate_ev_qualifier(struct trace *trace)
* variable to read it. Most notably this avoids extended load instructions
* on unaligned addresses
*/
+static unsigned long __syscall_arg__val(unsigned char *args, u8 idx)
+{
+ unsigned long val;
+ unsigned char *p = args + sizeof(unsigned long) * idx;
+
+ memcpy(&val, p, sizeof(val));
+ return val;
+}
+
+unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx)
+{
+ return __syscall_arg__val(arg->args, idx);
+}

static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
unsigned char *args, struct trace *trace,
struct thread *thread)
{
size_t printed = 0;
- unsigned char *p;
unsigned long val;

if (sc->args != NULL) {
struct format_field *field;
u8 bit = 1;
struct syscall_arg arg = {
+ .args = args,
.idx = 0,
.mask = 0,
.trace = trace,
@@ -1393,9 +1406,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
if (arg.mask & bit)
continue;

- /* special care for unaligned accesses */
- p = args + sizeof(unsigned long) * arg.idx;
- memcpy(&val, p, sizeof(val));
+ val = syscall_arg__val(&arg, arg.idx);

/*
* Suppress this argument if its value is zero and
@@ -1431,9 +1442,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
int i = 0;

while (i < 6) {
- /* special care for unaligned accesses */
- p = args + sizeof(unsigned long) * i;
- memcpy(&val, p, sizeof(val));
+ val = __syscall_arg__val(args, i);
printed += scnprintf(bf + printed, size - printed,
"%sarg%d: %ld",
printed ? ", " : "", i, val);
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index ce01079d8422..6fbac0c8120d 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -6,8 +6,19 @@
struct trace;
struct thread;

+/**
+ * @val: value of syscall argument being formatted
+ * @args: All the args, use syscall_args__val(arg, nth) to access one
+ * @thread: tid state (maps, pid, tid, etc)
+ * @trace: 'perf trace' internals: all threads, etc
+ * @parm: private area, may be an strarray, for instance
+ * @idx: syscall arg idx (is this the first?)
+ * @mask: a syscall arg may mask another arg, see syscall_arg__scnprintf_futex_op
+ */
+
struct syscall_arg {
unsigned long val;
+ unsigned char *args;
struct thread *thread;
struct trace *trace;
void *parm;
@@ -15,6 +26,8 @@ struct syscall_arg {
u8 mask;
};

+unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx);
+
size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:07 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

A series of fcntl cmds ignore the third argument, so mask it.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-6vtl3zq1ta...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 2 +-
tools/perf/trace/beauty/Build | 1 +
tools/perf/trace/beauty/beauty.h | 3 +++
tools/perf/trace/beauty/fcntl.c | 23 +++++++++++++++++++++++
4 files changed, 28 insertions(+), 1 deletion(-)
create mode 100644 tools/perf/trace/beauty/fcntl.c

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index ef1b1d4ea007..b7f79dea3c44 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -661,7 +661,7 @@ static struct syscall_fmt {
{ .name = "fchownat", .errmsg = true,
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
{ .name = "fcntl", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_STRARRAYS, /* cmd */ },
+ .arg_scnprintf = { [1] = SCA_FCNTL_CMD, /* cmd */ },
.arg_parm = { [1] = &strarrays__fcntl_cmds_arrays, /* cmd */ }, },
{ .name = "fdatasync", .errmsg = true, },
{ .name = "flock", .errmsg = true,
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index be95ac6ce845..c9e215b806f1 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -1 +1,2 @@
+libperf-y += fcntl.o
libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index a6348073a6e9..ce01079d8422 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -18,6 +18,9 @@ struct syscall_arg {
size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:07 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

When the user doesn't specify an event with -e/--event, 'perf record'
will use as a default the "cycles" event with the highest level of
precision in perf_event_attr.precise_ip, but --no-samples, if present,
is incompatible with precise_ip != 0, so use the newly introduced
__perf_event__add_default(precise = false) to fix that:

Before:

# perf record -n usleep 1
Please consider tweaking /proc/sys/kernel/perf_event_max_sample_rate.
Error:
The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (cycles:ppp).
/bin/dmesg may provide additional information.
No CONFIG_PERF_EVENTS=y kernel support configured?
#

After:

# perf record -n usleep 1
Please consider tweaking /proc/sys/kernel/perf_event_max_sample_rate.
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.018 MB perf.data ]
[root@jouet /]# perf evlist -v
cycles: size: 112, 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
[root@jouet /]#

Reported-by: Jiri Olsa <jo...@kernel.org>
Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-q991fw6s6r...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-record.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 17a14bcce34a..64eef9a567d9 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1821,7 +1821,7 @@ int cmd_record(int argc, const char **argv)
record.opts.tail_synthesize = true;

if (rec->evlist->nr_entries == 0 &&
- perf_evlist__add_default(rec->evlist) < 0) {
+ __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
pr_err("Not enough memory for event selector list\n");
goto out;
}
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:07 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Things like fcntl will use this to set the right formatter based on its
'cmd' argument.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-4ea3wplb8b...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 27 ++++++++++++++++++++++++++-
tools/perf/trace/beauty/beauty.h | 3 +++
2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 1f070bc43742..d48981c36b70 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -908,6 +908,8 @@ static size_t fprintf_duration(unsigned long t, bool calculated, FILE *fp)
* filename.ptr: The filename char pointer that will be vfs_getname'd
* filename.entry_str_pos: Where to insert the string translated from
* filename.ptr by the vfs_getname tracepoint/kprobe.
+ * ret_scnprintf: syscall args may set this to a different syscall return
+ * formatter, for instance, fcntl may return fds, file flags, etc.
*/
struct thread_trace {
u64 entry_time;
@@ -916,6 +918,7 @@ struct thread_trace {
unsigned long pfmaj, pfmin;
char *entry_str;
double runtime_ms;
+ size_t (*ret_scnprintf)(unsigned long value, char *bf, size_t size);
struct {
unsigned long ptr;
short int entry_str_pos;
@@ -966,6 +969,15 @@ static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
return NULL;
}

+
+void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
+ size_t (*ret_scnprintf)(unsigned long val, char *bf, size_t size))
+{
+ struct thread_trace *ttrace = thread__priv(arg->thread);
+
+ ttrace->ret_scnprintf = ret_scnprintf;
+}
+
#define TRACE_PFMAJ (1 << 0)
#define TRACE_PFMIN (1 << 1)

@@ -1390,6 +1402,14 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
{
size_t printed = 0;
unsigned long val;
+ struct thread_trace *ttrace = thread__priv(thread);
+
+ /*
+ * Things like fcntl will set this in its 'cmd' formatter to pick the
+ * right formatter for the return value (an fd? file flags?), which is
+ * not needed for syscalls that always return a given type, say an fd.
+ */
+ ttrace->ret_scnprintf = NULL;

if (sc->args != NULL) {
struct format_field *field;
@@ -1704,7 +1724,12 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
fprintf(trace->output, ") = -1 %s %s", e, emsg);
} else if (ret == 0 && sc->fmt->timeout)
fprintf(trace->output, ") = 0 Timeout");
- else if (sc->fmt->hexret)
+ else if (ttrace->ret_scnprintf) {
+ char bf[1024];
+ ttrace->ret_scnprintf(ret, bf, sizeof(bf));
+ ttrace->ret_scnprintf = NULL;
+ fprintf(trace->output, ") = %s", bf);
+ } else if (sc->fmt->hexret)
fprintf(trace->output, ") = %#lx", ret);
else if (sc->fmt->errpid) {
struct thread *child = machine__find_thread(trace->host, ret, ret);
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index c05bb2ecf502..a9613d2e6cfe 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -54,4 +54,7 @@ size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_a

size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size);

+void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
+ size_t (*ret_scnprintf)(unsigned long val, char *bf, size_t size));
+
#endif /* _PERF_TRACE_BEAUTY_H */
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:07 AM7/19/17
to
│ ┌──cmpl $0x0,argp_program_version_hook
81.93 │ ├──je 20
│ │ lock cmpxchg %esi,0x38a9a4(%rip)
│ │↓ jne 29
│ │↓ jmp 43
11.47 │20:└─→cmpxch %esi,0x38a999(%rip)

That means the cmpl+je is a fused instruction pair and they should be
considered together.

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

tools/perf/tests/sdt.c | 8 +-
tools/perf/trace/beauty/Build | 1 +

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:07 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Before:

77059.513 ( 0.005 ms): bash/6649 fcntl(fd: 1</dev/pts/12>, cmd: DUPFD, arg: 10) = 10</dev/pts/12>

After:

77059.513 ( 0.005 ms): bash/6649 fcntl(fd: 1</dev/pts/12>, cmd: DUPFD, arg: 10</dev/pts/12>) = 10</dev/pts/12>

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-0k8iszng0s...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/fcntl.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index b6987c468d18..9e8900c13cb1 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -71,6 +71,9 @@ size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_ar
{
int cmd = syscall_arg__val(arg, 1);

+ if (cmd == F_DUPFD)
+ return syscall_arg__scnprintf_fd(bf, size, arg);
+
if (cmd == F_SETFD)
return fcntl__scnprintf_getfd(arg->val, bf, size);

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:07 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

In older distros we were not including our copies of unistd_{32,64}.h,
as we were relying on the system's asm/unistd.h, and a log time ago
the files to be included were asm-{x86_64,i386}/unistd.h.

Fix it by also carrying a copy of asm/unistd.h, that will be the same
as in modern distros and will allow us to provide missing __NR_setns,
for instance, in older distros.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-iwmgm0c4m1...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/arch/x86/include/uapi/asm/unistd.h | 17 +++++++++++++++++
tools/perf/check-headers.sh | 1 +
2 files changed, 18 insertions(+)
create mode 100644 tools/arch/x86/include/uapi/asm/unistd.h

diff --git a/tools/arch/x86/include/uapi/asm/unistd.h b/tools/arch/x86/include/uapi/asm/unistd.h
new file mode 100644
index 000000000000..a26df0d75cd0
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/unistd.h
@@ -0,0 +1,17 @@
+#ifndef _UAPI_ASM_X86_UNISTD_H
+#define _UAPI_ASM_X86_UNISTD_H
+
+/* x32 syscall flag bit */
+#define __X32_SYSCALL_BIT 0x40000000
+
+#ifndef __KERNEL__
+# ifdef __i386__
+# include <asm/unistd_32.h>
+# elif defined(__ILP32__)
+# include <asm/unistd_x32.h>
+# else
+# include <asm/unistd_64.h>
+# endif
+#endif
+
+#endif /* _UAPI_ASM_X86_UNISTD_H */
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 83fe2202382e..47abd3325190 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -16,6 +16,7 @@ arch/x86/include/uapi/asm/perf_regs.h
arch/x86/include/uapi/asm/kvm.h
arch/x86/include/uapi/asm/kvm_perf.h
arch/x86/include/uapi/asm/svm.h
+arch/x86/include/uapi/asm/unistd.h
arch/x86/include/uapi/asm/vmx.h
arch/powerpc/include/uapi/asm/kvm.h
arch/s390/include/uapi/asm/kvm.h
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:08 AM7/19/17
to
From: Krister Johansen <kj...@templeofstupid.com>

If a process is in a mountns and has symbols in /tmp/perf-<pid>.map,
look first in the namespace using the tgid for the pidns that the
process might be in. If the map isn't found there, try looking in the
mountns where perf is running, and use the tgid that's appropriate for
perf's pid namespace. If all else fails, use the original pid.

This allows us to locate a symbol map file in the mount namespace, if it
was generated there. However, we also try the tool's /tmp in case it's
there instead.

Signed-off-by: Krister Johansen <kj...@templeofstupid.com>
Tested-by: Brendan Gregg <brendan...@gmail.com>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Thomas-Mich Richter <tmr...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1499305693-1599-3-...@templeofstupid.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/machine.c | 4 +--
tools/perf/util/map.c | 23 +++++++++---
tools/perf/util/map.h | 2 +-
tools/perf/util/namespaces.c | 83 ++++++++++++++++++++++++++++++++++++++++----
tools/perf/util/namespaces.h | 5 ++-
tools/perf/util/symbol.c | 70 ++++++++++++++++++++++++++++++-------
6 files changed, 160 insertions(+), 27 deletions(-)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 2e9eb6aa3ce2..246b441110a1 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1392,7 +1392,7 @@ int machine__process_mmap2_event(struct machine *machine,

map = map__new(machine, event->mmap2.start,
event->mmap2.len, event->mmap2.pgoff,
- event->mmap2.pid, event->mmap2.maj,
+ event->mmap2.maj,
event->mmap2.min, event->mmap2.ino,
event->mmap2.ino_generation,
event->mmap2.prot,
@@ -1450,7 +1450,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event

map = map__new(machine, event->mmap.start,
event->mmap.len, event->mmap.pgoff,
- event->mmap.pid, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
event->mmap.filename,
type, thread);

diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 5dc60ca5a294..bdaa0a4edc17 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -146,11 +146,13 @@ void map__init(struct map *map, enum map_type type,
}

struct map *map__new(struct machine *machine, u64 start, u64 len,
- u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
+ u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
u64 ino_gen, u32 prot, u32 flags, char *filename,
enum map_type type, struct thread *thread)
{
struct map *map = malloc(sizeof(*map));
+ struct nsinfo *nsi = NULL;
+ struct nsinfo *nnsi;

if (map != NULL) {
char newfilename[PATH_MAX];
@@ -168,9 +170,11 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
map->ino_generation = ino_gen;
map->prot = prot;
map->flags = flags;
+ nsi = nsinfo__get(thread->nsinfo);

- if ((anon || no_dso) && type == MAP__FUNCTION) {
- snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
+ if ((anon || no_dso) && nsi && type == MAP__FUNCTION) {
+ snprintf(newfilename, sizeof(newfilename),
+ "/tmp/perf-%d.map", nsi->pid);
filename = newfilename;
}

@@ -180,6 +184,16 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
}

if (vdso) {
+ /* The vdso maps are always on the host and not the
+ * container. Ensure that we don't use setns to look
+ * them up.
+ */
+ nnsi = nsinfo__copy(nsi);
+ if (nnsi) {
+ nsinfo__put(nsi);
+ nnsi->need_setns = false;
+ nsi = nnsi;
+ }
pgoff = 0;
dso = machine__findnew_vdso(machine, thread);
} else
@@ -201,11 +215,12 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
if (type != MAP__FUNCTION)
dso__set_loaded(dso, map->type);
}
- dso->nsinfo = nsinfo__get(thread->nsinfo);
+ dso->nsinfo = nsi;
dso__put(dso);
}
return map;
out_delete:
+ nsinfo__put(nsi);
free(map);
return NULL;
}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index f9e8ac8a52cd..73aacf7a7dc4 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -141,7 +141,7 @@ struct thread;
void map__init(struct map *map, enum map_type type,
u64 start, u64 end, u64 pgoff, struct dso *dso);
struct map *map__new(struct machine *machine, u64 start, u64 len,
- u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
+ u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
u64 ino_gen, u32 prot, u32 flags,
char *filename, enum map_type type, struct thread *thread);
struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index bcc6bb19cf10..fc5f398779a4 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -40,18 +40,23 @@ void namespaces__free(struct namespaces *namespaces)
free(namespaces);
}

-void nsinfo__init(struct nsinfo *nsi)
+int nsinfo__init(struct nsinfo *nsi)
{
char oldns[PATH_MAX];
+ char spath[PATH_MAX];
char *newns = NULL;
+ char *statln = NULL;
struct stat old_stat;
struct stat new_stat;
+ FILE *f = NULL;
+ size_t linesz = 0;
+ int rv = -1;

if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
- return;
+ return rv;

if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) == -1)
- return;
+ return rv;

if (stat(oldns, &old_stat) < 0)
goto out;
@@ -68,24 +73,89 @@ void nsinfo__init(struct nsinfo *nsi)
newns = NULL;
}

+ /* If we're dealing with a process that is in a different PID namespace,
+ * attempt to work out the innermost tgid for the process.
+ */
+ if (snprintf(spath, PATH_MAX, "/proc/%d/status", nsi->pid) >= PATH_MAX)
+ goto out;
+
+ f = fopen(spath, "r");
+ if (f == NULL)
+ goto out;
+
+ while (getline(&statln, &linesz, f) != -1) {
+ /* Use tgid if CONFIG_PID_NS is not defined. */
+ if (strstr(statln, "Tgid:") != NULL) {
+ nsi->tgid = (pid_t)strtol(strrchr(statln, '\t'),
+ NULL, 10);
+ nsi->nstgid = nsi->tgid;
+ }
+
+ if (strstr(statln, "NStgid:") != NULL) {
+ nsi->nstgid = (pid_t)strtol(strrchr(statln, '\t'),
+ NULL, 10);
+ break;
+ }
+ }
+ rv = 0;
+
out:
+ if (f != NULL)
+ (void) fclose(f);
+ free(statln);
free(newns);
+ return rv;
}

struct nsinfo *nsinfo__new(pid_t pid)
{
- struct nsinfo *nsi = calloc(1, sizeof(*nsi));
+ struct nsinfo *nsi;

+ if (pid == 0)
+ return NULL;
+
+ nsi = calloc(1, sizeof(*nsi));
if (nsi != NULL) {
nsi->pid = pid;
+ nsi->tgid = pid;
+ nsi->nstgid = pid;
nsi->need_setns = false;
- nsinfo__init(nsi);
+ /* Init may fail if the process exits while we're trying to look
+ * at its proc information. In that case, save the pid but
+ * don't try to enter the namespace.
+ */
+ if (nsinfo__init(nsi) == -1)
+ nsi->need_setns = false;
+
refcount_set(&nsi->refcnt, 1);
}

return nsi;
}

+struct nsinfo *nsinfo__copy(struct nsinfo *nsi)
+{
+ struct nsinfo *nnsi;
+
+ nnsi = calloc(1, sizeof(*nnsi));
+ if (nnsi != NULL) {
+ nnsi->pid = nsi->pid;
+ nnsi->tgid = nsi->tgid;
+ nnsi->nstgid = nsi->nstgid;
+ nnsi->need_setns = nsi->need_setns;
+ if (nsi->mntns_path) {
+ nnsi->mntns_path = strdup(nsi->mntns_path);
+ if (!nnsi->mntns_path) {
+ free(nnsi);
+ return NULL;
+ }
+ }
+ refcount_set(&nnsi->refcnt, 1);
+ }
+
+ return nnsi;
+}
+
void nsinfo__delete(struct nsinfo *nsi)
{
zfree(&nsi->mntns_path);
@@ -105,7 +175,8 @@ void nsinfo__put(struct nsinfo *nsi)
nsinfo__delete(nsi);
}

-void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)
+void nsinfo__mountns_enter(struct nsinfo *nsi,
+ struct nscookie *nc)
{
char curpath[PATH_MAX];
int oldns = -1;
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
index b20f6ead7b2d..f19aa41119ae 100644
--- a/tools/perf/util/namespaces.h
+++ b/tools/perf/util/namespaces.h
@@ -26,6 +26,8 @@ void namespaces__free(struct namespaces *namespaces);

struct nsinfo {
pid_t pid;
+ pid_t tgid;
+ pid_t nstgid;
bool need_setns;
char *mntns_path;
refcount_t refcnt;
@@ -36,8 +38,9 @@ struct nscookie {
int newns;
};

-void nsinfo__init(struct nsinfo *nsi);
+int nsinfo__init(struct nsinfo *nsi);
struct nsinfo *nsinfo__new(pid_t pid);
+struct nsinfo *nsinfo__copy(struct nsinfo *nsi);
void nsinfo__delete(struct nsinfo *nsi);

struct nsinfo *nsinfo__get(struct nsinfo *nsi);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 60a9eaa372ef..21c97cc41cfc 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -19,7 +19,6 @@
#include "strlist.h"
#include "intlist.h"
#include "namespaces.h"
-#include "vdso.h"
#include "header.h"
#include "path.h"
#include "sane_ctype.h"
@@ -1327,14 +1326,15 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
return __dso__load_kallsyms(dso, filename, map, false);
}

-static int dso__load_perf_map(struct dso *dso, struct map *map)
+static int dso__load_perf_map(const char *map_path, struct dso *dso,
+ struct map *map)
{
char *line = NULL;
size_t n;
FILE *file;
int nr_syms = 0;

- file = fopen(dso->long_name, "r");
+ file = fopen(map_path, "r");
if (file == NULL)
goto out_failure;

@@ -1426,6 +1426,45 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
}
}

+/* Checks for the existence of the perf-<pid>.map file in two different
+ * locations. First, if the process is a separate mount namespace, check in
+ * that namespace using the pid of the innermost pid namespace. If's not in a
+ * namespace, or the file can't be found there, try in the mount namespace of
+ * the tracing process using our view of its pid.
+ */
+static int dso__find_perf_map(char *filebuf, size_t bufsz,
+ struct nsinfo **nsip)
+{
+ struct nscookie nsc;
+ struct nsinfo *nsi;
+ struct nsinfo *nnsi;
+ int rc = -1;
+
+ nsi = *nsip;
+
+ if (nsi->need_setns) {
+ snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nsi->nstgid);
+ nsinfo__mountns_enter(nsi, &nsc);
+ rc = access(filebuf, R_OK);
+ nsinfo__mountns_exit(&nsc);
+ if (rc == 0)
+ return rc;
+ }
+
+ nnsi = nsinfo__copy(nsi);
+ if (nnsi) {
+ nsinfo__put(nsi);
+
+ nnsi->need_setns = false;
+ snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nnsi->tgid);
+ *nsip = nnsi;
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
int dso__load(struct dso *dso, struct map *map)
{
char *name;
@@ -1437,18 +1476,23 @@ int dso__load(struct dso *dso, struct map *map)
struct symsrc ss_[2];
struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
bool kmod;
+ bool perfmap;
unsigned char build_id[BUILD_ID_SIZE];
struct nscookie nsc;
+ char newmapname[PATH_MAX];
+ const char *map_path = dso->long_name;
+
+ perfmap = strncmp(dso->name, "/tmp/perf-", 10) == 0;
+ if (perfmap) {
+ if (dso->nsinfo && (dso__find_perf_map(newmapname,
+ sizeof(newmapname), &dso->nsinfo) == 0)) {
+ map_path = newmapname;
+ }
+ }

nsinfo__mountns_enter(dso->nsinfo, &nsc);
pthread_mutex_lock(&dso->lock);

- /* The vdso files always live in the host container, so don't go looking
- * for them in the container's mount namespace.
- */
- if (dso__is_vdso(dso))
- nsinfo__mountns_exit(&nsc);
-
/* check again under the dso->lock */
if (dso__loaded(dso, map->type)) {
ret = 1;
@@ -1471,19 +1515,19 @@ int dso__load(struct dso *dso, struct map *map)

dso->adjust_symbols = 0;

- if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
+ if (perfmap) {
struct stat st;

- if (lstat(dso->name, &st) < 0)
+ if (lstat(map_path, &st) < 0)
goto out;

if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) {
pr_warning("File %s not owned by current user or root, "
- "ignoring it (use -f to override).\n", dso->name);
+ "ignoring it (use -f to override).\n", map_path);
goto out;
}

- ret = dso__load_perf_map(dso, map);
+ ret = dso__load_perf_map(map_path, dso, map);
dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
DSO_BINARY_TYPE__NOT_FOUND;
goto out;
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:08 AM7/19/17
to
From: Jin Yao <yao...@linux.intel.com>

Perf already has support for disassembling the branch instruction
and using the branch type for filtering. The patch just records
the branch type in perf_branch_entry.

Before recording, the patch converts the x86 branch type to
common branch type.

Change log:

v10: Set the branch_map array to be static. The previous version
has it on stack then makes the compiler to create it every
time when the function gets called.

v9: Use __ffs() to find first bit in type in common_branch_type().
It lets the code be clear.

v8: Change PERF_BR_NONE to PERF_BR_UNKNOWN.

v7: Just convert following x86 branch types to common branch types.

X86_BR_CALL -> PERF_BR_CALL
X86_BR_RET -> PERF_BR_RET
X86_BR_JCC -> PERF_BR_COND
X86_BR_JMP -> PERF_BR_UNCOND
X86_BR_IND_CALL -> PERF_BR_IND_CALL
X86_BR_ZERO_CALL -> PERF_BR_CALL
X86_BR_IND_JMP -> PERF_BR_IND
X86_BR_SYSCALL -> PERF_BR_SYSCALL
X86_BR_SYSRET -> PERF_BR_SYSRET

Others are set to PERF_BR_NONE

v6: Not changed.

v5: Just fix the merge error. No other update.

v4: Comparing to previous version, the major changes are:

1. Uses a lookup table to convert x86 branch type to common branch
type.

2. Move the JCC forward/JCC backward and cross page computing to
user space.

3. Initialize branch type to 0 in intel_pmu_lbr_read_32 and
intel_pmu_lbr_read_64

Signed-off-by: Yao Jin <yao...@linux.intel.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Acked-by: Peter Zijlstra <pet...@infradead.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Kan Liang <kan....@intel.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Link: http://lkml.kernel.org/r/1500379995-6449-3-gi...@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
arch/x86/events/intel/lbr.c | 52 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index eb261656a320..0edda489cf36 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -109,6 +109,9 @@ enum {
X86_BR_ZERO_CALL = 1 << 15,/* zero length call */
X86_BR_CALL_STACK = 1 << 16,/* call stack */
X86_BR_IND_JMP = 1 << 17,/* indirect jump */
+
+ X86_BR_TYPE_SAVE = 1 << 18,/* indicate to save branch type */
+
};

#define X86_BR_PLM (X86_BR_USER | X86_BR_KERNEL)
@@ -510,6 +513,7 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
cpuc->lbr_entries[i].in_tx = 0;
cpuc->lbr_entries[i].abort = 0;
cpuc->lbr_entries[i].cycles = 0;
+ cpuc->lbr_entries[i].type = 0;
cpuc->lbr_entries[i].reserved = 0;
}
cpuc->lbr_stack.nr = i;
@@ -596,6 +600,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
cpuc->lbr_entries[out].in_tx = in_tx;
cpuc->lbr_entries[out].abort = abort;
cpuc->lbr_entries[out].cycles = cycles;
+ cpuc->lbr_entries[out].type = 0;
cpuc->lbr_entries[out].reserved = 0;
out++;
}
@@ -673,6 +678,10 @@ static int intel_pmu_setup_sw_lbr_filter(struct perf_event *event)

if (br_type & PERF_SAMPLE_BRANCH_CALL)
mask |= X86_BR_CALL | X86_BR_ZERO_CALL;
+
+ if (br_type & PERF_SAMPLE_BRANCH_TYPE_SAVE)
+ mask |= X86_BR_TYPE_SAVE;
+
/*
* stash actual user request into reg, it may
* be used by fixup code for some CPU
@@ -926,6 +935,43 @@ static int branch_type(unsigned long from, unsigned long to, int abort)
return ret;
}

+#define X86_BR_TYPE_MAP_MAX 16
+
+static int branch_map[X86_BR_TYPE_MAP_MAX] = {
+ PERF_BR_CALL, /* X86_BR_CALL */
+ PERF_BR_RET, /* X86_BR_RET */
+ PERF_BR_SYSCALL, /* X86_BR_SYSCALL */
+ PERF_BR_SYSRET, /* X86_BR_SYSRET */
+ PERF_BR_UNKNOWN, /* X86_BR_INT */
+ PERF_BR_UNKNOWN, /* X86_BR_IRET */
+ PERF_BR_COND, /* X86_BR_JCC */
+ PERF_BR_UNCOND, /* X86_BR_JMP */
+ PERF_BR_UNKNOWN, /* X86_BR_IRQ */
+ PERF_BR_IND_CALL, /* X86_BR_IND_CALL */
+ PERF_BR_UNKNOWN, /* X86_BR_ABORT */
+ PERF_BR_UNKNOWN, /* X86_BR_IN_TX */
+ PERF_BR_UNKNOWN, /* X86_BR_NO_TX */
+ PERF_BR_CALL, /* X86_BR_ZERO_CALL */
+ PERF_BR_UNKNOWN, /* X86_BR_CALL_STACK */
+ PERF_BR_IND, /* X86_BR_IND_JMP */
+};
+
+static int
+common_branch_type(int type)
+{
+ int i;
+
+ type >>= 2; /* skip X86_BR_USER and X86_BR_KERNEL */
+
+ if (type) {
+ i = __ffs(type);
+ if (i < X86_BR_TYPE_MAP_MAX)
+ return branch_map[i];
+ }
+
+ return PERF_BR_UNKNOWN;
+}
+
/*
* implement actual branch filter based on user demand.
* Hardware may not exactly satisfy that request, thus
@@ -942,7 +988,8 @@ intel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
bool compress = false;

/* if sampling all branches, then nothing to filter */
- if ((br_sel & X86_BR_ALL) == X86_BR_ALL)
+ if (((br_sel & X86_BR_ALL) == X86_BR_ALL) &&
+ ((br_sel & X86_BR_TYPE_SAVE) != X86_BR_TYPE_SAVE))
return;

for (i = 0; i < cpuc->lbr_stack.nr; i++) {
@@ -963,6 +1010,9 @@ intel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
cpuc->lbr_entries[i].from = 0;
compress = true;
}
+
+ if ((br_sel & X86_BR_TYPE_SAVE) == X86_BR_TYPE_SAVE)
+ cpuc->lbr_entries[i].type = common_branch_type(type);
}

if (!compress)
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:08 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

The final period can differ from what user specifies on command line due
to the perf_event_max_sample_rate sysctl setup.

Thus we can't predixt the sample_period value any more.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Thomas Richter <tmr...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/20170703145030...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr/base-record | 2 +-
tools/perf/tests/attr/test-record-branch-any | 1 -
tools/perf/tests/attr/test-record-branch-filter-any | 1 -
tools/perf/tests/attr/test-record-branch-filter-any_call | 1 -
tools/perf/tests/attr/test-record-branch-filter-any_ret | 1 -
tools/perf/tests/attr/test-record-branch-filter-hv | 1 -
tools/perf/tests/attr/test-record-branch-filter-ind_call | 1 -
tools/perf/tests/attr/test-record-branch-filter-k | 1 -
tools/perf/tests/attr/test-record-branch-filter-u | 1 -
tools/perf/tests/attr/test-record-data | 2 --
tools/perf/tests/attr/test-record-no-buffering | 1 -
tools/perf/tests/attr/test-record-raw | 1 -
12 files changed, 1 insertion(+), 13 deletions(-)

diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index cdf3adf7d389..a9cb72b8fbb1 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -7,7 +7,7 @@ cpu=*
type=0|1
size=112
config=0
-sample_period=4000
+sample_period=*
sample_type=263
read_format=0
disabled=1
diff --git a/tools/perf/tests/attr/test-record-branch-any b/tools/perf/tests/attr/test-record-branch-any
index a2fe031e6f87..81f839e2fad0 100644
--- a/tools/perf/tests/attr/test-record-branch-any
+++ b/tools/perf/tests/attr/test-record-branch-any
@@ -4,6 +4,5 @@ args = -b kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
sample_type=2311
branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any b/tools/perf/tests/attr/test-record-branch-filter-any
index 7df6a489c9ac..357421f4dfce 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-any
+++ b/tools/perf/tests/attr/test-record-branch-filter-any
@@ -4,6 +4,5 @@ args = -j any kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
sample_type=2311
branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_call b/tools/perf/tests/attr/test-record-branch-filter-any_call
index 6c93e07da61c..dbc55f2ab845 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-any_call
+++ b/tools/perf/tests/attr/test-record-branch-filter-any_call
@@ -4,6 +4,5 @@ args = -j any_call kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
sample_type=2311
branch_sample_type=16
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_ret b/tools/perf/tests/attr/test-record-branch-filter-any_ret
index daf8b83e257f..a0824ff8e131 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-any_ret
+++ b/tools/perf/tests/attr/test-record-branch-filter-any_ret
@@ -4,6 +4,5 @@ args = -j any_ret kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
sample_type=2311
branch_sample_type=32
diff --git a/tools/perf/tests/attr/test-record-branch-filter-hv b/tools/perf/tests/attr/test-record-branch-filter-hv
index fbf491da4f33..f34d6f120181 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-hv
+++ b/tools/perf/tests/attr/test-record-branch-filter-hv
@@ -4,6 +4,5 @@ args = -j hv kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
sample_type=2311
branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-ind_call b/tools/perf/tests/attr/test-record-branch-filter-ind_call
index c63cc50d2269..b86a35232248 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-ind_call
+++ b/tools/perf/tests/attr/test-record-branch-filter-ind_call
@@ -4,6 +4,5 @@ args = -j ind_call kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
sample_type=2311
branch_sample_type=64
diff --git a/tools/perf/tests/attr/test-record-branch-filter-k b/tools/perf/tests/attr/test-record-branch-filter-k
index e0f2f09ff07b..d3fbc5e1858a 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-k
+++ b/tools/perf/tests/attr/test-record-branch-filter-k
@@ -4,6 +4,5 @@ args = -j k kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
sample_type=2311
branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-u b/tools/perf/tests/attr/test-record-branch-filter-u
index 6cd36e01b6fc..a318f0dda173 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-u
+++ b/tools/perf/tests/attr/test-record-branch-filter-u
@@ -4,6 +4,5 @@ args = -j u kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
sample_type=2311
branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-data b/tools/perf/tests/attr/test-record-data
index 53c8890f6e5f..a9cf2233b0ce 100644
--- a/tools/perf/tests/attr/test-record-data
+++ b/tools/perf/tests/attr/test-record-data
@@ -4,8 +4,6 @@ args = -d kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
-
# sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME |
# PERF_SAMPLE_ADDR | PERF_SAMPLE_PERIOD | PERF_SAMPLE_DATA_SRC
sample_type=33039
diff --git a/tools/perf/tests/attr/test-record-no-buffering b/tools/perf/tests/attr/test-record-no-buffering
index 5bf349aeeb69..aa3956d8fe20 100644
--- a/tools/perf/tests/attr/test-record-no-buffering
+++ b/tools/perf/tests/attr/test-record-no-buffering
@@ -4,7 +4,6 @@ args = --no-buffering kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
sample_type=263
watermark=0
wakeup_events=1
diff --git a/tools/perf/tests/attr/test-record-raw b/tools/perf/tests/attr/test-record-raw
index 3b89f99c240b..a188a614a44c 100644
--- a/tools/perf/tests/attr/test-record-raw
+++ b/tools/perf/tests/attr/test-record-raw
@@ -4,5 +4,4 @@ args = -R kill >/dev/null 2>&1
ret = 1

[event:base-record]
-sample_period=4000
sample_type=1415
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:08 AM7/19/17
to
From: Krister Johansen <kj...@templeofstupid.com>

If a stripped binary is placed in the cache, the user is in a situation
where there's a cached elf file present, but it doesn't have any symtab
to use for name resolution. Grab the debuginfo for binaries that don't
end in .ko. This yields a better chance of resolving symbols from older
traces.

Signed-off-by: Krister Johansen <kj...@templeofstupid.com>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Brendan Gregg <brendan...@gmail.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Thomas-Mich Richter <tmr...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1499305693-1599-7-...@templeofstupid.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-buildid-cache.c | 2 +-
tools/perf/util/annotate.c | 2 +-
tools/perf/util/build-id.c | 72 +++++++++++++++++++++++++++++++++++---
tools/perf/util/build-id.h | 3 +-
tools/perf/util/dso.c | 8 ++++-
tools/perf/util/dso.h | 1 +
tools/perf/util/machine.c | 3 +-
tools/perf/util/symbol.c | 12 +++++--
8 files changed, 90 insertions(+), 13 deletions(-)

diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index d65bd86bee99..e3eb6240ced0 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -243,7 +243,7 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
char filename[PATH_MAX];
u8 build_id[BUILD_ID_SIZE];

- if (dso__build_id_filename(dso, filename, sizeof(filename)) &&
+ if (dso__build_id_filename(dso, filename, sizeof(filename), false) &&
filename__read_build_id(filename, build_id,
sizeof(build_id)) != sizeof(build_id)) {
if (errno == ENOENT)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index ef434b53d849..1742510f0120 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1347,7 +1347,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
!dso__is_kcore(dso))
return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;

- build_id_filename = dso__build_id_filename(dso, NULL, 0);
+ build_id_filename = dso__build_id_filename(dso, NULL, 0, false);
if (build_id_filename) {
__symbol__join_symfs(filename, filename_size, build_id_filename);
free(build_id_filename);
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index f7bfd90a7388..e9665150e9b1 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -243,12 +243,15 @@ static bool build_id_cache__valid_id(char *sbuild_id)
return result;
}

-static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
+static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso,
+ bool is_debug)
{
- return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
+ return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : (is_debug ?
+ "debug" : "elf"));
}

-char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
+char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size,
+ bool is_debug)
{
bool is_kallsyms = dso__is_kallsyms((struct dso *)dso);
bool is_vdso = dso__is_vdso((struct dso *)dso);
@@ -270,7 +273,8 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
ret = asnprintf(&bf, size, "%s", linkname);
else
ret = asnprintf(&bf, size, "%s/%s", linkname,
- build_id_cache__basename(is_kallsyms, is_vdso));
+ build_id_cache__basename(is_kallsyms, is_vdso,
+ is_debug));
if (ret < 0 || (!alloc && size < (unsigned int)ret))
bf = NULL;
free(linkname);
@@ -603,12 +607,40 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
#define build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) (0)
#endif

+static char *build_id_cache__find_debug(const char *sbuild_id,
+ struct nsinfo *nsi)
+{
+ char *realname = NULL;
+ char *debugfile;
+ struct nscookie nsc;
+ size_t len = 0;
+
+ debugfile = calloc(1, PATH_MAX);
+ if (!debugfile)
+ goto out;
+
+ len = __symbol__join_symfs(debugfile, PATH_MAX,
+ "/usr/lib/debug/.build-id/");
+ snprintf(debugfile + len, PATH_MAX - len, "%.2s/%s.debug", sbuild_id,
+ sbuild_id + 2);
+
+ nsinfo__mountns_enter(nsi, &nsc);
+ realname = realpath(debugfile, NULL);
+ if (realname && access(realname, R_OK))
+ zfree(&realname);
+ nsinfo__mountns_exit(&nsc);
+out:
+ free(debugfile);
+ return realname;
+}
+
int build_id_cache__add_s(const char *sbuild_id, const char *name,
struct nsinfo *nsi, bool is_kallsyms, bool is_vdso)
{
const size_t size = PATH_MAX;
char *realname = NULL, *filename = NULL, *dir_name = NULL,
*linkname = zalloc(size), *tmp;
+ char *debugfile = NULL;
int err = -1;

if (!is_kallsyms) {
@@ -635,7 +667,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,

/* Save the allocated buildid dirname */
if (asprintf(&filename, "%s/%s", dir_name,
- build_id_cache__basename(is_kallsyms, is_vdso)) < 0) {
+ build_id_cache__basename(is_kallsyms, is_vdso,
+ false)) < 0) {
filename = NULL;
goto out_free;
}
@@ -652,6 +685,34 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
goto out_free;
}

+ /* Some binaries are stripped, but have .debug files with their symbol
+ * table. Check to see if we can locate one of those, since the elf
+ * file itself may not be very useful to users of our tools without a
+ * symtab.
+ */
+ if (!is_kallsyms && !is_vdso &&
+ strncmp(".ko", name + strlen(name) - 3, 3)) {
+ debugfile = build_id_cache__find_debug(sbuild_id, nsi);
+ if (debugfile) {
+ zfree(&filename);
+ if (asprintf(&filename, "%s/%s", dir_name,
+ build_id_cache__basename(false, false, true)) < 0) {
+ filename = NULL;
+ goto out_free;
+ }
+ if (access(filename, F_OK)) {
+ if (nsi && nsi->need_setns) {
+ if (copyfile_ns(debugfile, filename,
+ nsi))
+ goto out_free;
+ } else if (link(debugfile, filename) &&
+ errno != EEXIST &&
+ copyfile(debugfile, filename))
+ goto out_free;
+ }
+ }
+ }
+
if (!build_id_cache__linkname(sbuild_id, linkname, size))
goto out_free;
tmp = strrchr(linkname, '/');
@@ -676,6 +737,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
if (!is_kallsyms)
free(realname);
free(filename);
+ free(debugfile);
free(dir_name);
free(linkname);
return err;
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 23970847d4c4..113dc0615c57 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -17,7 +17,8 @@ int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
size_t size);

-char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
+char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size,
+ bool is_debug);

int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
struct perf_sample *sample, struct perf_evsel *evsel,
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index dc9b49533a8f..b9e087fb8247 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -32,6 +32,7 @@ char dso__symtab_origin(const struct dso *dso)
[DSO_BINARY_TYPE__JAVA_JIT] = 'j',
[DSO_BINARY_TYPE__DEBUGLINK] = 'l',
[DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
+ [DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO] = 'D',
[DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
[DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
[DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o',
@@ -97,7 +98,12 @@ int dso__read_binary_type_filename(const struct dso *dso,
break;
}
case DSO_BINARY_TYPE__BUILD_ID_CACHE:
- if (dso__build_id_filename(dso, filename, size) == NULL)
+ if (dso__build_id_filename(dso, filename, size, false) == NULL)
+ ret = -1;
+ break;
+
+ case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
+ if (dso__build_id_filename(dso, filename, size, true) == NULL)
ret = -1;
break;

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 78ec637fc68b..f886141678eb 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -21,6 +21,7 @@ enum dso_binary_type {
DSO_BINARY_TYPE__JAVA_JIT,
DSO_BINARY_TYPE__DEBUGLINK,
DSO_BINARY_TYPE__BUILD_ID_CACHE,
+ DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 246b441110a1..a54a2be5eda4 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -705,7 +705,8 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)

if (kdso->has_build_id) {
char filename[PATH_MAX];
- if (dso__build_id_filename(kdso, filename, sizeof(filename)))
+ if (dso__build_id_filename(kdso, filename, sizeof(filename),
+ false))
printed += fprintf(fp, "[0] %s\n", filename);
}

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 8c7bae545617..971b990557b4 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -53,6 +53,7 @@ static enum dso_binary_type binary_type_symtab[] = {
DSO_BINARY_TYPE__JAVA_JIT,
DSO_BINARY_TYPE__DEBUGLINK,
DSO_BINARY_TYPE__BUILD_ID_CACHE,
+ DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
@@ -1418,6 +1419,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
return kmod && dso->symtab_type == type;

case DSO_BINARY_TYPE__BUILD_ID_CACHE:
+ case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
return true;

case DSO_BINARY_TYPE__NOT_FOUND:
@@ -1565,10 +1567,14 @@ int dso__load(struct dso *dso, struct map *map)
struct symsrc *ss = &ss_[ss_pos];
bool next_slot = false;
bool is_reg;
+ bool nsexit;
int sirc;

enum dso_binary_type symtab_type = binary_type_symtab[i];

+ nsexit = (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE ||
+ symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO);
+
if (!dso__is_compatible_symtab_type(dso, kmod, symtab_type))
continue;

@@ -1576,13 +1582,13 @@ int dso__load(struct dso *dso, struct map *map)
root_dir, name, PATH_MAX))
continue;

- if (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
+ if (nsexit)
nsinfo__mountns_exit(&nsc);

is_reg = is_regular_file(name);
sirc = symsrc__init(ss, dso, name, symtab_type);

- if (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
+ if (nsexit)
nsinfo__mountns_enter(dso->nsinfo, &nsc);

if (!is_reg || sirc < 0) {
@@ -1724,7 +1730,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map)
}

if (!symbol_conf.ignore_vmlinux_buildid)
- filename = dso__build_id_filename(dso, NULL, 0);
+ filename = dso__build_id_filename(dso, NULL, 0, false);
if (filename != NULL) {
err = dso__load_vmlinux(dso, map, filename, true);
if (err > 0)
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:09 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

And provide an alternative implementation to keep perf building on older
distros as we're about to add initial support for namespaces.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Krister Johansen <kj...@templeofstupid.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-bqdwijunhj...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/build/Makefile.feature | 3 ++-
tools/build/feature/Makefile | 6 +++++-
tools/build/feature/test-all.c | 5 +++++
tools/build/feature/test-setns.c | 7 +++++++
tools/perf/Makefile.config | 5 +++++
tools/perf/util/Build | 4 ++++
tools/perf/util/setns.c | 8 ++++++++
tools/perf/util/util.h | 4 ++++
8 files changed, 40 insertions(+), 2 deletions(-)
create mode 100644 tools/build/feature/test-setns.c
create mode 100644 tools/perf/util/setns.c

diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 523911f316ce..c71a05b9c984 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -64,7 +64,8 @@ FEATURE_TESTS_BASIC := \
get_cpuid \
bpf \
sched_getcpu \
- sdt
+ sdt \
+ setns

# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
# of all feature tests
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index e35e4e5ad192..ee2546ddf028 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -49,7 +49,8 @@ FILES= \
test-sdt.bin \
test-cxx.bin \
test-jvmti.bin \
- test-sched_getcpu.bin
+ test-sched_getcpu.bin \
+ test-setns.bin

FILES := $(addprefix $(OUTPUT),$(FILES))

@@ -95,6 +96,9 @@ $(OUTPUT)test-glibc.bin:
$(OUTPUT)test-sched_getcpu.bin:
$(BUILD)

+$(OUTPUT)test-setns.bin:
+ $(BUILD)
+
DWARFLIBS := -ldw
ifeq ($(findstring -static,${LDFLAGS}),-static)
DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index cc6c7c01f4ca..b5cfc6445771 100644
--- a/tools/build/feature/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -153,6 +153,10 @@
# include "test-sdt.c"
#undef main

+#define main main_test_setns
+# include "test-setns.c"
+#undef main
+
int main(int argc, char *argv[])
{
main_test_libpython();
@@ -188,6 +192,7 @@ int main(int argc, char *argv[])
main_test_libcrypto();
main_test_sched_getcpu();
main_test_sdt();
+ main_test_setns();

return 0;
}
diff --git a/tools/build/feature/test-setns.c b/tools/build/feature/test-setns.c
new file mode 100644
index 000000000000..1f714d2a658b
--- /dev/null
+++ b/tools/build/feature/test-setns.c
@@ -0,0 +1,7 @@
+#define _GNU_SOURCE
+#include <sched.h>
+
+int main(void)
+{
+ return setns(0, 0);
+}
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index bdf0e87f9b29..37d203c4cd1f 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -330,6 +330,11 @@ ifeq ($(feature-sched_getcpu), 1)
CFLAGS += -DHAVE_SCHED_GETCPU_SUPPORT
endif

+ifeq ($(feature-setns), 1)
+ CFLAGS += -DHAVE_SETNS_SUPPORT
+ $(call detected,CONFIG_SETNS)
+endif
+
ifndef NO_LIBELF
CFLAGS += -DHAVE_LIBELF_SUPPORT
EXTLIBS += -lelf
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 79dea95a7f68..7580fe4d5d30 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -104,6 +104,10 @@ ifndef CONFIG_LIBELF
libperf-y += symbol-minimal.o
endif

+ifndef CONFIG_SETNS
+libperf-y += setns.o
+endif
+
libperf-$(CONFIG_DWARF) += probe-finder.o
libperf-$(CONFIG_DWARF) += dwarf-aux.o
libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/util/setns.c b/tools/perf/util/setns.c
new file mode 100644
index 000000000000..ce8fc290fce8
--- /dev/null
+++ b/tools/perf/util/setns.c
@@ -0,0 +1,8 @@
+#include "util.h"
+#include <unistd.h>
+#include <sys/syscall.h>
+
+int setns(int fd, int nstype)
+{
+ return syscall(__NR_setns, fd, nstype);
+}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 2c9e58a45310..1e5fe1d9ec32 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -58,4 +58,8 @@ const char *perf_tip(const char *dirpath);
int sched_getcpu(void);
#endif

+#ifndef HAVE_SETNS_SUPPORT
+int setns(int fd, int nstype);
+#endif
+
#endif /* GIT_COMPAT_UTIL_H */
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:09 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

There's an event open fallback which set exclude_kernel=1 in case use
does not have enough privileges. Adding both 0|1 for this attribute,
because we don't know what value it is.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr/base-record | 2 +-
tools/perf/tests/attr/base-stat | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index 7e6d74946e04..cdf3adf7d389 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -15,7 +15,7 @@ inherit=1
pinned=0
exclusive=0
exclude_user=0
-exclude_kernel=0
+exclude_kernel=0|1
exclude_hv=0
exclude_idle=0
mmap=1
diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat
index f4cf148f14cb..ff9b33d4ae9e 100644
--- a/tools/perf/tests/attr/base-stat
+++ b/tools/perf/tests/attr/base-stat
@@ -15,7 +15,7 @@ inherit=1
pinned=0
exclusive=0
exclude_user=0
-exclude_kernel=0
+exclude_kernel=0|1
exclude_hv=0
exclude_idle=0
mmap=0
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:09 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

For instance, fcntl's upcoming 'arg' formatter needs to look at the
'cmd' value to decide how to format its value, sometimes it is a file
flags, sometimes an fd, a pointer to a structure, etc.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-2tw2jfaqm4...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 23 ++++++++++++++++-------
tools/perf/trace/beauty/beauty.h | 13 +++++++++++++
2 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index b7f79dea3c44..40bc0a326096 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1369,19 +1369,32 @@ static int trace__validate_ev_qualifier(struct trace *trace)
* variable to read it. Most notably this avoids extended load instructions
* on unaligned addresses
*/
+static unsigned long __syscall_arg__val(unsigned char *args, u8 idx)
+{
+ unsigned long val;
+ unsigned char *p = args + sizeof(unsigned long) * idx;
+
+ memcpy(&val, p, sizeof(val));
+ return val;
+}
+
+unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx)
+{
+ return __syscall_arg__val(arg->args, idx);
+}

static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
unsigned char *args, struct trace *trace,
struct thread *thread)
{
size_t printed = 0;
- unsigned char *p;
unsigned long val;

if (sc->args != NULL) {
struct format_field *field;
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index ce01079d8422..6fbac0c8120d 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -6,8 +6,19 @@
struct trace;
struct thread;

+/**
+ * @val: value of syscall argument being formatted
+ * @args: All the args, use syscall_args__val(arg, nth) to access one
+ * @thread: tid state (maps, pid, tid, etc)
+ * @trace: 'perf trace' internals: all threads, etc
+ * @parm: private area, may be an strarray, for instance
+ * @idx: syscall arg idx (is this the first?)
+ * @mask: a syscall arg may mask another arg, see syscall_arg__scnprintf_futex_op
+ */
+
struct syscall_arg {
unsigned long val;
+ unsigned char *args;
struct thread *thread;
struct trace *trace;
void *parm;
@@ -15,6 +26,8 @@ struct syscall_arg {
u8 mask;
};

+unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx);
+
size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:09 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

Do 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 errno code and not the number of bytes written.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549....@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/header.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3b833f06c4e7..8dda19b68ac4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -74,6 +74,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) {
@@ -89,6 +90,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];
@@ -103,6 +105,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;
@@ -3200,7 +3203,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;
}
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:09 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

>From following commit:

commit 4979d0c7d0c7 ("perf stat record: Add record command")

we started to assign PERF_SAMPLE_IDENTIFIER to sample_type.

Fixing the attr stat tests accordingly.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr/base-stat | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat
index ff9b33d4ae9e..4d0c2e42b64e 100644
--- a/tools/perf/tests/attr/base-stat
+++ b/tools/perf/tests/attr/base-stat
@@ -8,7 +8,7 @@ type=0
size=112
config=0
sample_period=0
-sample_type=0
+sample_type=65536
read_format=3
disabled=1
inherit=1
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:09 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

To get the changes in the commit c75b1d9421f8 ("fs: add fcntl()
interface for setting/getting write life time hints").

Silencing this perf build warning:

Warning: include/uapi/linux/fcntl.h differs from kernel

We already beautify the fcntl cmd argument, so an upcoming cset will
update the 'cmd' strarray to cover these new commands.

The hints are in the 3rd arg, a pointer, so not yet supported in 'perf
trace', for that we need to copy it somehow, probably using eBPF, a new
attempt at doing that is planned.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jens Axboe <ax...@kernel.dk>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Martin K. Petersen <martin....@oracle.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-al471wzs3x...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/include/uapi/linux/fcntl.h | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/tools/include/uapi/linux/fcntl.h b/tools/include/uapi/linux/fcntl.h
index 813afd6eee71..ec69d55bcec7 100644
--- a/tools/include/uapi/linux/fcntl.h
+++ b/tools/include/uapi/linux/fcntl.h
@@ -43,6 +43,27 @@
/* (1U << 31) is reserved for signed error codes */

/*
+ * Set/Get write life time hints. {GET,SET}_RW_HINT operate on the
+ * underlying inode, while {GET,SET}_FILE_RW_HINT operate only on
+ * the specific file.
+ */
+#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11)
+#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12)
+#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13)
+#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14)
+
+/*
+ * Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be
+ * used to clear any hints previously set.
+ */
+#define RWF_WRITE_LIFE_NOT_SET 0
+#define RWH_WRITE_LIFE_NONE 1
+#define RWH_WRITE_LIFE_SHORT 2
+#define RWH_WRITE_LIFE_MEDIUM 3
+#define RWH_WRITE_LIFE_LONG 4
+#define RWH_WRITE_LIFE_EXTREME 5
+
+/*
* Types of directory notifications that may be requested.
*/
#define DN_ACCESS 0x00000001 /* File accessed */
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:09 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Using the existing 'fd' beautifier, now we can see the path for the just
dup'ed fd:

18031.338 ( 0.009 ms): gnome-terminal/2472 fcntl(fd: 55, cmd: DUPFD_CLOEXEC) = 56</memfd:gdk-wayland (deleted)>

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-z0ggo126p2...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/fcntl.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index 9de80a7eddfa..254ae435780d 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -30,6 +30,10 @@ size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_ar
syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getfd);
goto mask_arg;
}
+ if (arg->val == F_DUPFD_CLOEXEC || arg->val == F_DUPFD) {
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fd);
+ goto out;
+ }
/*
* Some commands ignore the third fcntl argument, "arg", so mask it
*/
@@ -38,7 +42,7 @@ size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_ar
mask_arg:
arg->mask |= (1 << 2);
}
-
+out:
return syscall_arg__scnprintf_strarrays(bf, size, arg);
}

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:10 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

Some of the stat events are quite rare to find on common machines (like
front end cycles).

Adding an 'optional' term to mark such events in attr tests. Event
marked as optional will not fail the test case if it's not found in
results.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr.py | 14 +++++++++++---
tools/perf/tests/attr/test-stat-default | 2 ++
tools/perf/tests/attr/test-stat-detailed-1 | 2 ++
tools/perf/tests/attr/test-stat-detailed-2 | 3 +++
tools/perf/tests/attr/test-stat-detailed-3 | 5 +++++
5 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py
index b03261c6b1ed..6bb50e82a3e3 100644
--- a/tools/perf/tests/attr.py
+++ b/tools/perf/tests/attr.py
@@ -105,6 +105,11 @@ class Event(dict):
return False
return True

+ def optional(self):
+ if self.has_key('optional') and self['optional'] == '1':
+ return True
+ return False
+
def diff(self, other):
for t in Event.terms:
if not self.has_key(t) or not other.has_key(t):
@@ -244,9 +249,12 @@ class Test(object):
log.debug(" match: [%s] matches %s" % (exp_name, str(exp_list)))

# we did not any matching event - fail
- if (not exp_list):
- exp_event.diff(res_event)
- raise Fail(self, 'match failure');
+ if not exp_list:
+ if exp_event.optional():
+ log.debug(" %s does not match, but is optional" % exp_name)
+ else:
+ exp_event.diff(res_event)
+ raise Fail(self, 'match failure');

match[exp_name] = exp_list

diff --git a/tools/perf/tests/attr/test-stat-default b/tools/perf/tests/attr/test-stat-default
index 19270f54c96e..e911dbd4eb47 100644
--- a/tools/perf/tests/attr/test-stat-default
+++ b/tools/perf/tests/attr/test-stat-default
@@ -38,12 +38,14 @@ config=0
fd=6
type=0
config=7
+optional=1

# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
[event7:base-stat]
fd=7
type=0
config=8
+optional=1

# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
[event8:base-stat]
diff --git a/tools/perf/tests/attr/test-stat-detailed-1 b/tools/perf/tests/attr/test-stat-detailed-1
index 51426b87153b..b39270a08e74 100644
--- a/tools/perf/tests/attr/test-stat-detailed-1
+++ b/tools/perf/tests/attr/test-stat-detailed-1
@@ -39,12 +39,14 @@ config=0
fd=6
type=0
config=7
+optional=1

# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
[event7:base-stat]
fd=7
type=0
config=8
+optional=1

# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
[event8:base-stat]
diff --git a/tools/perf/tests/attr/test-stat-detailed-2 b/tools/perf/tests/attr/test-stat-detailed-2
index 8de5acc31c27..45f8e6ea34f8 100644
--- a/tools/perf/tests/attr/test-stat-detailed-2
+++ b/tools/perf/tests/attr/test-stat-detailed-2
@@ -39,12 +39,14 @@ config=0
fd=6
type=0
config=7
+optional=1

# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
[event7:base-stat]
fd=7
type=0
config=8
+optional=1

# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
[event8:base-stat]
@@ -108,6 +110,7 @@ config=65538
fd=15
type=3
config=1
+optional=1

# PERF_TYPE_HW_CACHE,
# PERF_COUNT_HW_CACHE_L1I << 0 |
diff --git a/tools/perf/tests/attr/test-stat-detailed-3 b/tools/perf/tests/attr/test-stat-detailed-3
index 0a1f45bf7d79..30ae0fb7a3fd 100644
--- a/tools/perf/tests/attr/test-stat-detailed-3
+++ b/tools/perf/tests/attr/test-stat-detailed-3
@@ -39,12 +39,14 @@ config=0
fd=6
type=0
config=7
+optional=1

# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
[event7:base-stat]
fd=7
type=0
config=8
+optional=1

# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
[event8:base-stat]
@@ -108,6 +110,7 @@ config=65538
fd=15
type=3
config=1
+optional=1

# PERF_TYPE_HW_CACHE,
# PERF_COUNT_HW_CACHE_L1I << 0 |
@@ -162,6 +165,7 @@ config=65540
fd=21
type=3
config=512
+optional=1

# PERF_TYPE_HW_CACHE,
# PERF_COUNT_HW_CACHE_L1D << 0 |
@@ -171,3 +175,4 @@ config=512
fd=22
type=3
config=66048
+optional=1
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:10 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

The open syscall flags beautifier wasn't considering those flags, fix
it.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-ukzoldh4ar...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/open_flags.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index b3c7f1155d80..5fb57bed7ea2 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -14,6 +14,10 @@
#define O_NOATIME 01000000
#endif

+#ifndef O_TMPFILE
+#define O_TMPFILE 020000000
+#endif
+
size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
{
int printed = 0;
@@ -34,6 +38,8 @@ size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
P_FLAG(DIRECTORY);
P_FLAG(EXCL);
P_FLAG(LARGEFILE);
+ P_FLAG(NOFOLLOW);
+ P_FLAG(TMPFILE);
P_FLAG(NOATIME);
P_FLAG(NOCTTY);
#ifdef O_NONBLOCK
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:10 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Removing syscall_fmt::err_msg and instead always formatting negative
returns as errno values.

With this we can remove a lot of entries that have no special handling
besides the ones we can do by looking at the tracefs format files, i.e.
the types for the fields (e.g. pid_t), well known names (e.g. fd).

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-rg9u7a3qqd...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 209 ++++++++++++++++++---------------------------
1 file changed, 81 insertions(+), 128 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index bab87f612a36..1e4c0657b712 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -611,77 +611,53 @@ static struct syscall_fmt {
const char *name;
const char *alias;
struct syscall_arg_fmt arg[6];
- bool errmsg;
bool errpid;
bool timeout;
bool hexret;
} syscall_fmts[] = {
- { .name = "access", .errmsg = true,
+ { .name = "access",
.arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
- { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
- { .name = "bpf", .errmsg = true,
+ { .name = "arch_prctl", .alias = "prctl", },
+ { .name = "bpf",
.arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
{ .name = "brk", .hexret = true,
.arg = { [0] = { .scnprintf = SCA_HEX, /* brk */ }, }, },
- { .name = "chdir", .errmsg = true, },
- { .name = "chmod", .errmsg = true, },
- { .name = "chroot", .errmsg = true, },
- { .name = "clock_gettime", .errmsg = true,
+ { .name = "clock_gettime",
.arg = { [0] = STRARRAY(clk_id, clockid), }, },
{ .name = "clone", .errpid = true, },
- { .name = "close", .errmsg = true,
+ { .name = "close",
.arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
- { .name = "connect", .errmsg = true, },
- { .name = "creat", .errmsg = true, },
- { .name = "dup", .errmsg = true, },
- { .name = "dup2", .errmsg = true, },
- { .name = "dup3", .errmsg = true, },
- { .name = "epoll_ctl", .errmsg = true,
+ { .name = "epoll_ctl",
.arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, },
- { .name = "eventfd2", .errmsg = true,
+ { .name = "eventfd2",
.arg = { [1] = { .scnprintf = SCA_EFD_FLAGS, /* flags */ }, }, },
- { .name = "faccessat", .errmsg = true, },
- { .name = "fadvise64", .errmsg = true, },
- { .name = "fallocate", .errmsg = true, },
- { .name = "fchdir", .errmsg = true, },
- { .name = "fchmod", .errmsg = true, },
- { .name = "fchmodat", .errmsg = true,
+ { .name = "fchmodat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
- { .name = "fchown", .errmsg = true, },
- { .name = "fchownat", .errmsg = true,
+ { .name = "fchownat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
- { .name = "fcntl", .errmsg = true,
+ { .name = "fcntl",
.arg = { [1] = { .scnprintf = SCA_FCNTL_CMD, /* cmd */
.parm = &strarrays__fcntl_cmds_arrays,
.show_zero = true, },
[2] = { .scnprintf = SCA_FCNTL_ARG, /* arg */ }, }, },
- { .name = "fdatasync", .errmsg = true, },
- { .name = "flock", .errmsg = true,
+ { .name = "flock",
.arg = { [1] = { .scnprintf = SCA_FLOCK, /* cmd */ }, }, },
- { .name = "fsetxattr", .errmsg = true, },
- { .name = "fstat", .errmsg = true, .alias = "newfstat", },
- { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
- { .name = "fstatfs", .errmsg = true, },
- { .name = "fsync", .errmsg = true, },
- { .name = "ftruncate", .errmsg = true, },
- { .name = "futex", .errmsg = true,
+ { .name = "fstat", .alias = "newfstat", },
+ { .name = "fstatat", .alias = "newfstatat", },
+ { .name = "futex",
.arg = { [1] = { .scnprintf = SCA_FUTEX_OP, /* op */ }, }, },
- { .name = "futimesat", .errmsg = true,
+ { .name = "futimesat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
- { .name = "getdents", .errmsg = true, },
- { .name = "getdents64", .errmsg = true, },
- { .name = "getitimer", .errmsg = true,
+ { .name = "getitimer",
.arg = { [0] = STRARRAY(which, itimers), }, },
{ .name = "getpid", .errpid = true, },
{ .name = "getpgid", .errpid = true, },
{ .name = "getppid", .errpid = true, },
- { .name = "getrandom", .errmsg = true,
+ { .name = "getrandom",
.arg = { [2] = { .scnprintf = SCA_GETRANDOM_FLAGS, /* flags */ }, }, },
- { .name = "getrlimit", .errmsg = true,
+ { .name = "getrlimit",
.arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
- { .name = "getxattr", .errmsg = true, },
- { .name = "inotify_add_watch", .errmsg = true, },
- { .name = "ioctl", .errmsg = true,
+ { .name = "ioctl",
.arg = {
#if defined(__i386__) || defined(__x86_64__)
/*
@@ -693,34 +669,25 @@ static struct syscall_fmt {
#else
[2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
#endif
- { .name = "keyctl", .errmsg = true,
+ { .name = "keyctl",
.arg = { [0] = STRARRAY(option, keyctl_options), }, },
- { .name = "kill", .errmsg = true,
+ { .name = "kill",
.arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
- { .name = "lchown", .errmsg = true, },
- { .name = "lgetxattr", .errmsg = true, },
- { .name = "linkat", .errmsg = true,
+ { .name = "linkat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
- { .name = "listxattr", .errmsg = true, },
- { .name = "llistxattr", .errmsg = true, },
- { .name = "lremovexattr", .errmsg = true, },
- { .name = "lseek", .errmsg = true,
+ { .name = "lseek",
.arg = { [2] = STRARRAY(whence, whences), }, },
- { .name = "lsetxattr", .errmsg = true, },
- { .name = "lstat", .errmsg = true, .alias = "newlstat", },
- { .name = "lsxattr", .errmsg = true, },
- { .name = "madvise", .errmsg = true,
+ { .name = "lstat", .alias = "newlstat", },
+ { .name = "madvise",
.arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
[2] = { .scnprintf = SCA_MADV_BHV, /* behavior */ }, }, },
- { .name = "mkdir", .errmsg = true, },
- { .name = "mkdirat", .errmsg = true,
+ { .name = "mkdirat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
- { .name = "mknod", .errmsg = true, },
- { .name = "mknodat", .errmsg = true,
+ { .name = "mknodat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
- { .name = "mlock", .errmsg = true,
+ { .name = "mlock",
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
- { .name = "mlockall", .errmsg = true,
+ { .name = "mlockall",
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
{ .name = "mmap", .hexret = true,
/* The standard mmap maps to old_mmap on s390x */
@@ -730,127 +697,109 @@ static struct syscall_fmt {
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
[2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
[3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, },
- { .name = "mprotect", .errmsg = true,
+ { .name = "mprotect",
.arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
[2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, },
- { .name = "mq_unlink", .errmsg = true,
+ { .name = "mq_unlink",
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* u_name */ }, }, },
{ .name = "mremap", .hexret = true,
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
[3] = { .scnprintf = SCA_MREMAP_FLAGS, /* flags */ },
[4] = { .scnprintf = SCA_HEX, /* new_addr */ }, }, },
- { .name = "munlock", .errmsg = true,
+ { .name = "munlock",
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
- { .name = "munmap", .errmsg = true,
+ { .name = "munmap",
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
- { .name = "name_to_handle_at", .errmsg = true,
+ { .name = "name_to_handle_at",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
- { .name = "newfstatat", .errmsg = true,
+ { .name = "newfstatat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
- { .name = "open", .errmsg = true,
+ { .name = "open",
.arg = { [1] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
- { .name = "open_by_handle_at", .errmsg = true,
+ { .name = "open_by_handle_at",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
[2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
- { .name = "openat", .errmsg = true,
+ { .name = "openat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
[2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
- { .name = "perf_event_open", .errmsg = true,
+ { .name = "perf_event_open",
.arg = { [2] = { .scnprintf = SCA_INT, /* cpu */ },
[3] = { .scnprintf = SCA_FD, /* group_fd */ },
[4] = { .scnprintf = SCA_PERF_FLAGS, /* flags */ }, }, },
- { .name = "pipe2", .errmsg = true,
+ { .name = "pipe2",
.arg = { [1] = { .scnprintf = SCA_PIPE_FLAGS, /* flags */ }, }, },
- { .name = "poll", .errmsg = true, .timeout = true, },
- { .name = "ppoll", .errmsg = true, .timeout = true, },
- { .name = "pread", .errmsg = true, .alias = "pread64", },
- { .name = "preadv", .errmsg = true, .alias = "pread", },
- { .name = "prlimit64", .errmsg = true,
+ { .name = "poll", .timeout = true, },
+ { .name = "ppoll", .timeout = true, },
+ { .name = "pread", .alias = "pread64", },
+ { .name = "preadv", .alias = "pread", },
+ { .name = "prlimit64",
.arg = { [1] = STRARRAY(resource, rlimit_resources), }, },
- { .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
- { .name = "pwritev", .errmsg = true, },
- { .name = "read", .errmsg = true, },
- { .name = "readlink", .errmsg = true, },
- { .name = "readlinkat", .errmsg = true,
+ { .name = "pwrite", .alias = "pwrite64", },
+ { .name = "readlinkat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
- { .name = "readv", .errmsg = true, },
- { .name = "recvfrom", .errmsg = true,
+ { .name = "recvfrom",
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
- { .name = "recvmmsg", .errmsg = true,
+ { .name = "recvmmsg",
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
- { .name = "recvmsg", .errmsg = true,
+ { .name = "recvmsg",
.arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
- { .name = "removexattr", .errmsg = true, },
- { .name = "renameat", .errmsg = true,
+ { .name = "renameat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
- { .name = "rmdir", .errmsg = true, },
- { .name = "rt_sigaction", .errmsg = true,
+ { .name = "rt_sigaction",
.arg = { [0] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
- { .name = "rt_sigprocmask", .errmsg = true,
+ { .name = "rt_sigprocmask",
.arg = { [0] = STRARRAY(how, sighow), }, },
- { .name = "rt_sigqueueinfo", .errmsg = true,
+ { .name = "rt_sigqueueinfo",
.arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
- { .name = "rt_tgsigqueueinfo", .errmsg = true,
+ { .name = "rt_tgsigqueueinfo",
.arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
- { .name = "sched_getattr", .errmsg = true, },
- { .name = "sched_setattr", .errmsg = true, },
- { .name = "sched_setscheduler", .errmsg = true,
+ { .name = "sched_setscheduler",
.arg = { [1] = { .scnprintf = SCA_SCHED_POLICY, /* policy */ }, }, },
- { .name = "seccomp", .errmsg = true,
+ { .name = "seccomp",
.arg = { [0] = { .scnprintf = SCA_SECCOMP_OP, /* op */ },
[1] = { .scnprintf = SCA_SECCOMP_FLAGS, /* flags */ }, }, },
- { .name = "select", .errmsg = true, .timeout = true, },
- { .name = "sendmmsg", .errmsg = true,
+ { .name = "select", .timeout = true, },
+ { .name = "sendmmsg",
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
- { .name = "sendmsg", .errmsg = true,
+ { .name = "sendmsg",
.arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
- { .name = "sendto", .errmsg = true,
+ { .name = "sendto",
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
{ .name = "set_tid_address", .errpid = true, },
- { .name = "setitimer", .errmsg = true,
+ { .name = "setitimer",
.arg = { [0] = STRARRAY(which, itimers), }, },
- { .name = "setpgid", .errmsg = true, },
- { .name = "setrlimit", .errmsg = true,
+ { .name = "setrlimit",
.arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
- { .name = "setxattr", .errmsg = true, },
- { .name = "shutdown", .errmsg = true, },
- { .name = "socket", .errmsg = true,
+ { .name = "socket",
.arg = { [0] = STRARRAY(family, socket_families),
[1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
- { .name = "socketpair", .errmsg = true,
+ { .name = "socketpair",
.arg = { [0] = STRARRAY(family, socket_families),
[1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
- { .name = "stat", .errmsg = true, .alias = "newstat", },
- { .name = "statfs", .errmsg = true, },
- { .name = "statx", .errmsg = true,
+ { .name = "stat", .alias = "newstat", },
+ { .name = "statx",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fdat */ },
[2] = { .scnprintf = SCA_STATX_FLAGS, /* flags */ } ,
[3] = { .scnprintf = SCA_STATX_MASK, /* mask */ }, }, },
- { .name = "swapoff", .errmsg = true,
+ { .name = "swapoff",
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
- { .name = "swapon", .errmsg = true,
+ { .name = "swapon",
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
- { .name = "symlinkat", .errmsg = true,
+ { .name = "symlinkat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
- { .name = "tgkill", .errmsg = true,
+ { .name = "tgkill",
.arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
- { .name = "tkill", .errmsg = true,
+ { .name = "tkill",
.arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
- { .name = "truncate", .errmsg = true, },
- { .name = "uname", .errmsg = true, .alias = "newuname", },
- { .name = "unlinkat", .errmsg = true,
+ { .name = "uname", .alias = "newuname", },
+ { .name = "unlinkat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
- { .name = "utime", .errmsg = true, },
- { .name = "utimensat", .errmsg = true,
+ { .name = "utimensat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ }, }, },
- { .name = "utimes", .errmsg = true, },
- { .name = "vmsplice", .errmsg = true, },
{ .name = "wait4", .errpid = true,
.arg = { [2] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
{ .name = "waitid", .errpid = true,
.arg = { [3] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
- { .name = "write", .errmsg = true, },
- { .name = "writev", .errmsg = true, },
};

static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -1708,14 +1657,18 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
}

if (sc->fmt == NULL) {
+ if (ret < 0)
+ goto errno_print;
signed_print:
- fprintf(trace->output, ") = %ld", ret);
- } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
+ fprintf(trace->output, ") %ld", ret);
+ } else if (ret < 0) {
+errno_print: {
char bf[STRERR_BUFSIZE];
const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
*e = audit_errno_to_name(-ret);

fprintf(trace->output, ") = -1 %s %s", e, emsg);
+ }
} else if (ret == 0 && sc->fmt->timeout)
fprintf(trace->output, ") = 0 Timeout");
else if (ttrace->ret_scnprintf) {
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:10 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Now it will show 0 or CLOEXEC, the only !0 value returned by the kernel
for fcntl(fd, F_GETFD).

And for F_SETFD:

6870.267 ( 0.004 ms): make/29812 fcntl(fd: 7</home/acme/git/linux/tools/build/Build.include>, cmd: SETFD, arg: CLOEXEC) = 0
6873.805 ( 0.002 ms): make/29816 fcntl(fd: 6</home/acme/git/linux/tools/build/Makefile.build>, cmd: SETFD, arg: CLOEXEC) = 0
<SNIP>
77986.150 ( 0.006 ms): alsa-sink-ALC3/2042 fcntl(fd: 45</dev/snd/pcmC1D0p>, cmd: SETFD, arg: CLOEXEC) = 0
77986.271 ( 0.006 ms): alsa-sink-ALC3/2042 fcntl(fd: 23</dev/snd/controlC1>, cmd: SETFD, arg: CLOEXEC) = 0

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-sz9dob7t4z...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/fcntl.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index 3456bf4cdb48..384f177a4304 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -7,19 +7,28 @@
*/

#include "trace/beauty/beauty.h"
+#include <linux/kernel.h>
#include <uapi/linux/fcntl.h>

+static size_t fcntl__scnprintf_getfd(unsigned long val, char *bf, size_t size)
+{
+ return scnprintf(bf, size, "%s", val ? "CLOEXEC" : "0");
+}
+
size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg)
{
if (arg->val == F_GETFL) {
syscall_arg__set_ret_scnprintf(arg, open__scnprintf_flags);
goto mask_arg;
}
+ if (arg->val == F_GETFD) {
+ syscall_arg__set_ret_scnprintf(arg, fcntl__scnprintf_getfd);
+ goto mask_arg;
+ }
/*
* Some commands ignore the third fcntl argument, "arg", so mask it
*/
- if (arg->val == F_GETFD ||
- arg->val == F_GETOWN || arg->val == F_GET_SEALS ||
+ if (arg->val == F_GETOWN || arg->val == F_GET_SEALS ||
arg->val == F_GETLEASE || arg->val == F_GETSIG) {
mask_arg:
arg->mask |= (1 << 2);
@@ -32,6 +41,9 @@ size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_ar
{
int cmd = syscall_arg__val(arg, 1);

+ if (cmd == F_SETFD)
+ return fcntl__scnprintf_getfd(arg->val, bf, size);
+
if (cmd == F_SETFL)
return open__scnprintf_flags(arg->val, bf, size);
/*
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:11 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Those introduced by the commit c75b1d9421f8 ("fs: add fcntl() interface for
setting/getting write life time hints"), tested using the proggie in that
commit comment:

# perf trace -e fcntl ./write_hint write_hint.c
fcntl: F_GET_RW_HINT: Invalid argument
0.000 ( 0.006 ms): write_hint/7576 fcntl(fd: 3, cmd: GET_RW_HINT, arg: 0x7ffc6c918da0) = -1 EINVAL Invalid argument
0.014 ( 0.004 ms): write_hint/7576 fcntl(fd: 4, cmd: GETFL) = 33794
# perf trace -e fcntl ./write_hint write_hint.c 1
fcntl: F_SET_RW_HINT: Invalid argument
0.000 ( 0.007 ms): write_hint/7578 fcntl(fd: 3, cmd: SET_RW_HINT, arg: 0x7fff03866d70) = -1 EINVAL Invalid argument
0.019 ( 0.002 ms): write_hint/7578 fcntl(fd: 4, cmd: GETFL) = 33794
#

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jens Axboe <ax...@kernel.dk>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Martin K. Petersen <martin....@oracle.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-iacglkc99c...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 2a894ea7f540..1f070bc43742 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -449,6 +449,7 @@ static DEFINE_STRARRAY(fcntl_cmds);
static const char *fcntl_linux_specific_cmds[] = {
"SETLEASE", "GETLEASE", "NOTIFY", [5] = "CANCELLK", "DUPFD_CLOEXEC",
"SETPIPE_SZ", "GETPIPE_SZ", "ADD_SEALS", "GET_SEALS",
+ "GET_RW_HINT", "SET_RW_HINT", "GET_FILE_RW_HINT", "SET_FILE_RW_HINT",
};

static DEFINE_STRARRAY_OFFSET(fcntl_linux_specific_cmds, F_LINUX_SPECIFIC_BASE);
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:11 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

struct 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.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549.1...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/header.c | 58 ++++++++++++++++++++----------------------------
1 file changed, 24 insertions(+), 34 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 22b52e5636a6..60394d27e8f5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -62,6 +62,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)
@@ -1593,8 +1595,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; \
@@ -1607,24 +1608,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;
@@ -1641,8 +1639,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;
@@ -1687,8 +1684,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);
@@ -1705,8 +1701,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;
@@ -1716,7 +1711,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;

@@ -1744,8 +1739,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;
@@ -1802,7 +1796,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;
}
@@ -1834,8 +1828,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
return -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;
@@ -1881,8 +1874,7 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
return -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;
@@ -1929,8 +1921,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
return -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;
@@ -2014,23 +2005,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;
@@ -2085,8 +2074,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;
};
@@ -2617,9 +2605,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) {
@@ -2636,7 +2626,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,
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:11 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

The most basic ones, for pointers, unaugmented fds, etc, to be used
in the initial fcntl 'arg' beautifier.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-g0lugj4vv6...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 10 ++--------
tools/perf/trace/beauty/beauty.h | 6 ++++++
2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 40bc0a326096..9e171401b664 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -392,22 +392,16 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,

#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd

-static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg)
{
return scnprintf(bf, size, "%#lx", arg->val);
}

-#define SCA_HEX syscall_arg__scnprintf_hex
-
-static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg)
{
return scnprintf(bf, size, "%d", arg->val);
}

-#define SCA_INT syscall_arg__scnprintf_int
-
static const char *bpf_cmd[] = {
"MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
"MAP_GET_NEXT_KEY", "PROG_LOAD",
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 6fbac0c8120d..d085aacecd49 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -31,6 +31,12 @@ unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx);
size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays

+size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_HEX syscall_arg__scnprintf_hex
+
+size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_INT syscall_arg__scnprintf_int
+
size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:11 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

We may want to use this in other contexts, like when formatting the
return of fcntl(fd, F_GETFL).

Make it have the following signature, so that we can set the formatter
for the return argument while processing the arguments of a syscall, as
fcntl, for instance, may return fds, flags, etc, so need different
return value formatters:

size_t formatter(unsigned long value, char *bf, size_t size);

This gets so detached from 'perf trace' internals that we may well get
all these and move to a tools/lib/syscall_beauty/ library at some point
and use it in other tools/ living utilities.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: Alexei Starovoitov <a...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-9aw8t22ztv...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/beauty.h | 2 ++
tools/perf/trace/beauty/open_flags.c | 19 +++++++++++++------
2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index d76f903bf2ed..c05bb2ecf502 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -52,4 +52,6 @@ size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_
size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STATX_MASK syscall_arg__scnprintf_statx_mask

+size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size);
+
#endif /* _PERF_TRACE_BEAUTY_H */
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index f55a4597fc38..b3c7f1155d80 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -14,13 +14,9 @@
#define O_NOATIME 01000000
#endif

-static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
{
- int printed = 0, flags = arg->val;
-
- if (!(flags & O_CREAT))
- arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
+ int printed = 0;

if (flags == 0)
return scnprintf(bf, size, "RDONLY");
@@ -68,4 +64,15 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
return printed;
}

+static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg)
+{
+ int flags = arg->val;
+
+ if (!(flags & O_CREAT))
+ arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
+
+ return open__scnprintf_flags(flags, bf, size);
+}
+
+
#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:11 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

Introduce 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.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549....@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
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(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 4baa5329439f..c1a06fcd7e70 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -289,7 +289,7 @@ char *dso__build_id_filename(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;
@@ -311,7 +311,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];
@@ -356,7 +357,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);
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 113dc0615c57..c94b0dcbfd74 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -10,6 +10,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);
@@ -27,7 +28,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);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 954f0ef8e712..a5db9aded45b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -59,6 +59,11 @@ struct perf_file_attr {
struct perf_file_section ids;
};

+struct feat_fd {
+ struct perf_header *ph;
+ int fd;
+};
+
void perf_header__set_feat(struct perf_header *header, int feat)
{
set_bit(feat, header->adds_features);
@@ -75,11 +80,11 @@ bool perf_header__has_feat(const struct perf_header *header, int feat)
}

/* Return: 0 if succeded, -ERR if failed. */
-int do_write(int fd, const void *buf, size_t size)
+int do_write(struct feat_fd *ff, const void *buf, size_t size)
{
ssize_t ret;

- ret = writen(fd, buf, size);
+ ret = writen(ff->fd, buf, size);
if (ret != (ssize_t)size)
return ret < 0 ? (int)ret : -1;

@@ -87,13 +92,14 @@ int do_write(int fd, const void *buf, size_t size)
}

/* Return: 0 if succeded, -ERR if failed. */
-int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
+int write_padded(struct feat_fd *ff, const void *bf,
+ size_t count, size_t count_aligned)
{
static const char zero_buf[NAME_ALIGN];
- int err = do_write(fd, bf, count);
+ int err = do_write(ff, bf, count);

if (!err)
- err = do_write(fd, zero_buf, count_aligned - count);
+ err = do_write(ff, zero_buf, count_aligned - count);

return err;
}
@@ -102,7 +108,7 @@ int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
(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)
+static int do_write_string(struct feat_fd *ff, const char *str)
{
u32 len, olen;
int ret;
@@ -111,11 +117,11 @@ static int do_write_string(int fd, const char *str)
len = PERF_ALIGN(olen, NAME_ALIGN);

/* write len, incl. \0 */
- ret = do_write(fd, &len, sizeof(len));
+ ret = do_write(ff, &len, sizeof(len));
if (ret < 0)
return ret;

- return write_padded(fd, str, olen, len);
+ return write_padded(ff, str, olen, len);
}

static int __do_read(int fd, void *addr, ssize_t size)
@@ -178,25 +184,24 @@ static char *do_read_string(int fd, struct perf_header *ph)
return NULL;
}

-static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
- struct perf_evlist *evlist)
+static int write_tracing_data(struct feat_fd *ff,
+ struct perf_evlist *evlist)
{
- return read_tracing_data(fd, &evlist->entries);
+ return read_tracing_data(ff->fd, &evlist->entries);
}

-
-static int write_build_id(int fd, struct perf_header *h,
+static int write_build_id(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
struct perf_session *session;
int err;

- session = container_of(h, struct perf_session, header);
+ session = container_of(ff->ph, struct perf_session, header);

if (!perf_session__read_build_ids(session, true))
return -1;

- err = perf_session__write_buildid_table(session, fd);
+ err = perf_session__write_buildid_table(session, ff);
if (err < 0) {
pr_debug("failed to write buildid table\n");
return err;
@@ -206,7 +211,7 @@ static int write_build_id(int fd, struct perf_header *h,
return 0;
}

-static int write_hostname(int fd, struct perf_header *h __maybe_unused,
+static int write_hostname(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
struct utsname uts;
@@ -216,10 +221,10 @@ static int write_hostname(int fd, struct perf_header *h __maybe_unused,
if (ret < 0)
return -1;

- return do_write_string(fd, uts.nodename);
+ return do_write_string(ff, uts.nodename);
}

-static int write_osrelease(int fd, struct perf_header *h __maybe_unused,
+static int write_osrelease(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
struct utsname uts;
@@ -229,10 +234,10 @@ static int write_osrelease(int fd, struct perf_header *h __maybe_unused,
if (ret < 0)
return -1;

- return do_write_string(fd, uts.release);
+ return do_write_string(ff, uts.release);
}

-static int write_arch(int fd, struct perf_header *h __maybe_unused,
+static int write_arch(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
struct utsname uts;
@@ -242,16 +247,16 @@ static int write_arch(int fd, struct perf_header *h __maybe_unused,
if (ret < 0)
return -1;

- return do_write_string(fd, uts.machine);
+ return do_write_string(ff, uts.machine);
}

-static int write_version(int fd, struct perf_header *h __maybe_unused,
+static int write_version(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
- return do_write_string(fd, perf_version_string);
+ return do_write_string(ff, perf_version_string);
}

-static int __write_cpudesc(int fd, const char *cpuinfo_proc)
+static int __write_cpudesc(struct feat_fd *ff, const char *cpuinfo_proc)
{
FILE *file;
char *buf = NULL;
@@ -301,14 +306,14 @@ static int __write_cpudesc(int fd, const char *cpuinfo_proc)
}
p++;
}
- ret = do_write_string(fd, s);
+ ret = do_write_string(ff, s);
done:
free(buf);
fclose(file);
return ret;
}

-static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
+static int write_cpudesc(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
#ifndef CPUINFO_PROC
@@ -319,7 +324,7 @@ static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,

for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
int ret;
- ret = __write_cpudesc(fd, cpuinfo_procs[i]);
+ ret = __write_cpudesc(ff, cpuinfo_procs[i]);
if (ret >= 0)
return ret;
}
@@ -327,7 +332,7 @@ static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
}


-static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
+static int write_nrcpus(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
long nr;
@@ -342,14 +347,14 @@ static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,

nra = (u32)(nr & UINT_MAX);

- ret = do_write(fd, &nrc, sizeof(nrc));
+ ret = do_write(ff, &nrc, sizeof(nrc));
if (ret < 0)
return ret;

- return do_write(fd, &nra, sizeof(nra));
+ return do_write(ff, &nra, sizeof(nra));
}

-static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
+static int write_event_desc(struct feat_fd *ff,
struct perf_evlist *evlist)
{
struct perf_evsel *evsel;
@@ -361,7 +366,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
/*
* write number of events
*/
- ret = do_write(fd, &nre, sizeof(nre));
+ ret = do_write(ff, &nre, sizeof(nre));
if (ret < 0)
return ret;

@@ -369,12 +374,12 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
* size of perf_event_attr struct
*/
sz = (u32)sizeof(evsel->attr);
- ret = do_write(fd, &sz, sizeof(sz));
+ ret = do_write(ff, &sz, sizeof(sz));
if (ret < 0)
return ret;

evlist__for_each_entry(evlist, evsel) {
- ret = do_write(fd, &evsel->attr, sz);
+ ret = do_write(ff, &evsel->attr, sz);
if (ret < 0)
return ret;
/*
@@ -385,27 +390,27 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
* type of ids,
*/
nri = evsel->ids;
- ret = do_write(fd, &nri, sizeof(nri));
+ ret = do_write(ff, &nri, sizeof(nri));
if (ret < 0)
return ret;

/*
* write event string as passed on cmdline
*/
- ret = do_write_string(fd, perf_evsel__name(evsel));
+ ret = do_write_string(ff, perf_evsel__name(evsel));
if (ret < 0)
return ret;
/*
* write unique ids for this event
*/
- ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
+ ret = do_write(ff, evsel->id, evsel->ids * sizeof(u64));
if (ret < 0)
return ret;
}
return 0;
}

-static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
+static int write_cmdline(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
char buf[MAXPATHLEN];
@@ -423,16 +428,16 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
/* account for binary path */
n = perf_env.nr_cmdline + 1;

- ret = do_write(fd, &n, sizeof(n));
+ ret = do_write(ff, &n, sizeof(n));
if (ret < 0)
return ret;

- ret = do_write_string(fd, buf);
+ ret = do_write_string(ff, buf);
if (ret < 0)
return ret;

for (i = 0 ; i < perf_env.nr_cmdline; i++) {
- ret = do_write_string(fd, perf_env.cmdline_argv[i]);
+ ret = do_write_string(ff, perf_env.cmdline_argv[i]);
if (ret < 0)
return ret;
}
@@ -585,8 +590,8 @@ static struct cpu_topo *build_cpu_topology(void)
return tp;
}

-static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+static int write_cpu_topology(struct feat_fd *ff,
+ struct perf_evlist *evlist __maybe_unused)
{
struct cpu_topo *tp;
u32 i;
@@ -596,21 +601,21 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
if (!tp)
return -1;

- ret = do_write(fd, &tp->core_sib, sizeof(tp->core_sib));
+ ret = do_write(ff, &tp->core_sib, sizeof(tp->core_sib));
if (ret < 0)
goto done;

for (i = 0; i < tp->core_sib; i++) {
- ret = do_write_string(fd, tp->core_siblings[i]);
+ ret = do_write_string(ff, tp->core_siblings[i]);
if (ret < 0)
goto done;
}
- ret = do_write(fd, &tp->thread_sib, sizeof(tp->thread_sib));
+ ret = do_write(ff, &tp->thread_sib, sizeof(tp->thread_sib));
if (ret < 0)
goto done;

for (i = 0; i < tp->thread_sib; i++) {
- ret = do_write_string(fd, tp->thread_siblings[i]);
+ ret = do_write_string(ff, tp->thread_siblings[i]);
if (ret < 0)
break;
}
@@ -620,11 +625,11 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
goto done;

for (j = 0; j < perf_env.nr_cpus_avail; j++) {
- ret = do_write(fd, &perf_env.cpu[j].core_id,
+ ret = do_write(ff, &perf_env.cpu[j].core_id,
sizeof(perf_env.cpu[j].core_id));
if (ret < 0)
return ret;
- ret = do_write(fd, &perf_env.cpu[j].socket_id,
+ ret = do_write(ff, &perf_env.cpu[j].socket_id,
sizeof(perf_env.cpu[j].socket_id));
if (ret < 0)
return ret;
@@ -636,8 +641,8 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,



-static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+static int write_total_mem(struct feat_fd *ff,
+ struct perf_evlist *evlist __maybe_unused)
{
char *buf = NULL;
FILE *fp;
@@ -657,7 +662,7 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
if (!ret) {
n = sscanf(buf, "%*s %"PRIu64, &mem);
if (n == 1)
- ret = do_write(fd, &mem, sizeof(mem));
+ ret = do_write(ff, &mem, sizeof(mem));
} else
ret = -1;
free(buf);
@@ -665,7 +670,7 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
return ret;
}

-static int write_topo_node(int fd, int node)
+static int write_topo_node(struct feat_fd *ff, int node)
{
char str[MAXPATHLEN];
char field[32];
@@ -695,11 +700,11 @@ static int write_topo_node(int fd, int node)
fclose(fp);
fp = NULL;

- ret = do_write(fd, &mem_total, sizeof(u64));
+ ret = do_write(ff, &mem_total, sizeof(u64));
if (ret)
goto done;

- ret = do_write(fd, &mem_free, sizeof(u64));
+ ret = do_write(ff, &mem_free, sizeof(u64));
if (ret)
goto done;

@@ -717,7 +722,7 @@ static int write_topo_node(int fd, int node)
if (p)
*p = '\0';

- ret = do_write_string(fd, buf);
+ ret = do_write_string(ff, buf);
done:
free(buf);
if (fp)
@@ -725,8 +730,8 @@ static int write_topo_node(int fd, int node)
return ret;
}

-static int write_numa_topology(int fd, struct perf_header *h __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+static int write_numa_topology(struct feat_fd *ff,
+ struct perf_evlist *evlist __maybe_unused)
{
char *buf = NULL;
size_t len = 0;
@@ -753,17 +758,17 @@ static int write_numa_topology(int fd, struct perf_header *h __maybe_unused,

nr = (u32)node_map->nr;

- ret = do_write(fd, &nr, sizeof(nr));
+ ret = do_write(ff, &nr, sizeof(nr));
if (ret < 0)
goto done;

for (i = 0; i < nr; i++) {
j = (u32)node_map->map[i];
- ret = do_write(fd, &j, sizeof(j));
+ ret = do_write(ff, &j, sizeof(j));
if (ret < 0)
break;

- ret = write_topo_node(fd, i);
+ ret = write_topo_node(ff, i);
if (ret < 0)
break;
}
@@ -786,16 +791,16 @@ static int write_numa_topology(int fd, struct perf_header *h __maybe_unused,
* };
*/

-static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
+static int write_pmu_mappings(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
struct perf_pmu *pmu = NULL;
- off_t offset = lseek(fd, 0, SEEK_CUR);
+ off_t offset = lseek(ff->fd, 0, SEEK_CUR);
__u32 pmu_num = 0;
int ret;

/* write real pmu_num later */
- ret = do_write(fd, &pmu_num, sizeof(pmu_num));
+ ret = do_write(ff, &pmu_num, sizeof(pmu_num));
if (ret < 0)
return ret;

@@ -804,18 +809,18 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
continue;
pmu_num++;

- ret = do_write(fd, &pmu->type, sizeof(pmu->type));
+ ret = do_write(ff, &pmu->type, sizeof(pmu->type));
if (ret < 0)
return ret;

- ret = do_write_string(fd, pmu->name);
+ ret = do_write_string(ff, pmu->name);
if (ret < 0)
return ret;
}

- if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
+ if (pwrite(ff->fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
/* discard all */
- lseek(fd, offset, SEEK_SET);
+ lseek(ff->fd, offset, SEEK_SET);
return -1;
}

@@ -834,14 +839,14 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
* }[nr_groups];
* };
*/
-static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
+static int write_group_desc(struct feat_fd *ff,
struct perf_evlist *evlist)
{
u32 nr_groups = evlist->nr_groups;
struct perf_evsel *evsel;
int ret;

- ret = do_write(fd, &nr_groups, sizeof(nr_groups));
+ ret = do_write(ff, &nr_groups, sizeof(nr_groups));
if (ret < 0)
return ret;

@@ -852,15 +857,15 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
u32 leader_idx = evsel->idx;
u32 nr_members = evsel->nr_members;

- ret = do_write_string(fd, name);
+ ret = do_write_string(ff, name);
if (ret < 0)
return ret;

- ret = do_write(fd, &leader_idx, sizeof(leader_idx));
+ ret = do_write(ff, &leader_idx, sizeof(leader_idx));
if (ret < 0)
return ret;

- ret = do_write(fd, &nr_members, sizeof(nr_members));
+ ret = do_write(ff, &nr_members, sizeof(nr_members));
if (ret < 0)
return ret;
}
@@ -877,7 +882,7 @@ int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
return -1;
}

-static int write_cpuid(int fd, struct perf_header *h __maybe_unused,
+static int write_cpuid(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
char buffer[64];
@@ -889,25 +894,24 @@ static int write_cpuid(int fd, struct perf_header *h __maybe_unused,

return -1;
write_it:
- return do_write_string(fd, buffer);
+ return do_write_string(ff, buffer);
}

-static int write_branch_stack(int fd __maybe_unused,
- struct perf_header *h __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+static int write_branch_stack(struct feat_fd *ff __maybe_unused,
+ struct perf_evlist *evlist __maybe_unused)
{
return 0;
}

-static int write_auxtrace(int fd, struct perf_header *h,
+static int write_auxtrace(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
struct perf_session *session;
int err;

- session = container_of(h, struct perf_session, header);
+ session = container_of(ff->ph, struct perf_session, header);

- err = auxtrace_index__write(fd, &session->auxtrace_index);
+ err = auxtrace_index__write(ff->fd, &session->auxtrace_index);
if (err < 0)
pr_err("Failed to write auxtrace index\n");
return err;
@@ -1054,8 +1058,8 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)

#define MAX_CACHES 2000

-static int write_cache(int fd, struct perf_header *h __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+static int write_cache(struct feat_fd *ff,
+ struct perf_evlist *evlist __maybe_unused)
{
struct cpu_cache_level caches[MAX_CACHES];
u32 cnt = 0, i, version = 1;
@@ -1067,11 +1071,11 @@ static int write_cache(int fd, struct perf_header *h __maybe_unused,

qsort(&caches, cnt, sizeof(struct cpu_cache_level), cpu_cache_level__sort);

- ret = do_write(fd, &version, sizeof(u32));
+ ret = do_write(ff, &version, sizeof(u32));
if (ret < 0)
goto out;

- ret = do_write(fd, &cnt, sizeof(u32));
+ ret = do_write(ff, &cnt, sizeof(u32));
if (ret < 0)
goto out;

@@ -1079,7 +1083,7 @@ static int write_cache(int fd, struct perf_header *h __maybe_unused,
struct cpu_cache_level *c = &caches[i];

#define _W(v) \
- ret = do_write(fd, &c->v, sizeof(u32)); \
+ ret = do_write(ff, &c->v, sizeof(u32)); \
if (ret < 0) \
goto out;

@@ -1090,7 +1094,7 @@ static int write_cache(int fd, struct perf_header *h __maybe_unused,
#undef _W

#define _W(v) \
- ret = do_write_string(fd, (const char *) c->v); \
+ ret = do_write_string(ff, (const char *) c->v); \
if (ret < 0) \
goto out;

@@ -1106,8 +1110,7 @@ static int write_cache(int fd, struct perf_header *h __maybe_unused,
return ret;
}

-static int write_stat(int fd __maybe_unused,
- struct perf_header *h __maybe_unused,
+static int write_stat(struct feat_fd *ff __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
return 0;
@@ -2105,7 +2108,7 @@ static int process_cache(struct perf_file_section *section __maybe_unused,
}

struct feature_ops {
- int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
+ int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
void (*print)(struct perf_header *h, int fd, FILE *fp);
int (*process)(struct perf_file_section *section,
struct perf_header *h, int fd, void *data);
@@ -2214,29 +2217,29 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
return 0;
}

-static int do_write_feat(int fd, struct perf_header *h, int type,
+static int do_write_feat(struct feat_fd *ff, int type,
struct perf_file_section **p,
struct perf_evlist *evlist)
{
int err;
int ret = 0;

- if (perf_header__has_feat(h, type)) {
+ if (perf_header__has_feat(ff->ph, type)) {
if (!feat_ops[type].write)
return -1;

- (*p)->offset = lseek(fd, 0, SEEK_CUR);
+ (*p)->offset = lseek(ff->fd, 0, SEEK_CUR);

- err = feat_ops[type].write(fd, h, evlist);
+ err = feat_ops[type].write(ff, evlist);
if (err < 0) {
pr_debug("failed to write feature %s\n", feat_ops[type].name);

/* undo anything written */
- lseek(fd, (*p)->offset, SEEK_SET);
+ lseek(ff->fd, (*p)->offset, SEEK_SET);

return -1;
}
- (*p)->size = lseek(fd, 0, SEEK_CUR) - (*p)->offset;
+ (*p)->size = lseek(ff->fd, 0, SEEK_CUR) - (*p)->offset;
(*p)++;
}
return ret;
@@ -2246,12 +2249,18 @@ static int perf_header__adds_write(struct perf_header *header,
struct perf_evlist *evlist, int fd)
{
int nr_sections;
+ struct feat_fd ff;
struct perf_file_section *feat_sec, *p;
int sec_size;
u64 sec_start;
int feat;
int err;

+ ff = (struct feat_fd){
+ .fd = fd,
+ .ph = header,
+ };
+
nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
if (!nr_sections)
return 0;
@@ -2266,7 +2275,7 @@ static int perf_header__adds_write(struct perf_header *header,
lseek(fd, sec_start + sec_size, SEEK_SET);

for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
- if (do_write_feat(fd, header, feat, &p, evlist))
+ if (do_write_feat(&ff, feat, &p, evlist))
perf_header__clear_feat(header, feat);
}

@@ -2275,7 +2284,7 @@ static int perf_header__adds_write(struct perf_header *header,
* may write more than needed due to dropped feature, but
* this is okay, reader will skip the mising entries
*/
- err = do_write(fd, feat_sec, sec_size);
+ err = do_write(&ff, feat_sec, sec_size);
if (err < 0)
pr_debug("failed to write feature section\n");
free(feat_sec);
@@ -2285,14 +2294,17 @@ static int perf_header__adds_write(struct perf_header *header,
int perf_header__write_pipe(int fd)
{
struct perf_pipe_file_header f_header;
+ struct feat_fd ff;
int err;

+ ff = (struct feat_fd){ .fd = fd };
+
f_header = (struct perf_pipe_file_header){
.magic = PERF_MAGIC,
.size = sizeof(f_header),
};

- err = do_write(fd, &f_header, sizeof(f_header));
+ err = do_write(&ff, &f_header, sizeof(f_header));
if (err < 0) {
pr_debug("failed to write perf pipe header\n");
return err;
@@ -2309,21 +2321,23 @@ int perf_session__write_header(struct perf_session *session,
struct perf_file_attr f_attr;
struct perf_header *header = &session->header;
struct perf_evsel *evsel;
+ struct feat_fd ff;
u64 attr_offset;
int err;

+ ff = (struct feat_fd){ .fd = fd};
lseek(fd, sizeof(f_header), SEEK_SET);

evlist__for_each_entry(session->evlist, evsel) {
evsel->id_offset = lseek(fd, 0, SEEK_CUR);
- err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
+ err = do_write(&ff, evsel->id, evsel->ids * sizeof(u64));
if (err < 0) {
pr_debug("failed to write perf header\n");
return err;
}
}

- attr_offset = lseek(fd, 0, SEEK_CUR);
+ attr_offset = lseek(ff.fd, 0, SEEK_CUR);

evlist__for_each_entry(evlist, evsel) {
f_attr = (struct perf_file_attr){
@@ -2333,7 +2347,7 @@ int perf_session__write_header(struct perf_session *session,
.size = evsel->ids * sizeof(u64),
}
};
- err = do_write(fd, &f_attr, sizeof(f_attr));
+ err = do_write(&ff, &f_attr, sizeof(f_attr));
if (err < 0) {
pr_debug("failed to write perf header attribute\n");
return err;
@@ -2368,7 +2382,7 @@ int perf_session__write_header(struct perf_session *session,
memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));

lseek(fd, 0, SEEK_SET);
- err = do_write(fd, &f_header, sizeof(f_header));
+ err = do_write(&ff, &f_header, sizeof(f_header));
if (err < 0) {
pr_debug("failed to write perf header\n");
return err;
@@ -2643,6 +2657,10 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
struct perf_header *ph, int fd,
bool repipe)
{
+ struct feat_fd ff = {
+ .fd = STDOUT_FILENO,
+ .ph = ph,
+ };
ssize_t ret;

ret = readn(fd, header, sizeof(*header));
@@ -2657,7 +2675,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
if (ph->needs_swap)
header->size = bswap_64(header->size);

- if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0)
+ if (repipe && do_write(&ff, header, sizeof(*header)) < 0)
return -1;

return 0;
@@ -3165,6 +3183,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
union perf_event ev;
struct tracing_data *tdata;
ssize_t size = 0, aligned_size = 0, padding;
+ struct feat_fd ff;
int err __maybe_unused = 0;

/*
@@ -3199,7 +3218,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
*/
tracing_data_put(tdata);

- if (write_padded(fd, NULL, 0, padding))
+ ff = (struct feat_fd){ .fd = fd };
+ if (write_padded(&ff, NULL, 0, padding))
return -1;

return aligned_size;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index e98489c8bba7..9d8dcd5eb727 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:11 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

There are cases where we want to leave attr.precise_ip as zero, such
as when using 'perf record --no-samples', where this would make the
kernel return -EINVAL.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-0u2m2a8rqw...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/evlist.c | 4 ++--
tools/perf/util/evlist.h | 9 ++++++++-
2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index f51c3314015c..078b58511595 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -242,9 +242,9 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
}
}

-int perf_evlist__add_default(struct perf_evlist *evlist)
+int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise)
{
- struct perf_evsel *evsel = perf_evsel__new_cycles(true);
+ struct perf_evsel *evsel = perf_evsel__new_cycles(precise);

if (evsel == NULL)
return -ENOMEM;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 8d601fbdd8d6..0843746bc389 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -115,7 +115,14 @@ void perf_evlist__delete(struct perf_evlist *evlist);

void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel);
-int perf_evlist__add_default(struct perf_evlist *evlist);
+
+int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise);
+
+static inline int perf_evlist__add_default(struct perf_evlist *evlist)
+{
+ return __perf_evlist__add_default(evlist, true);
+}
+
int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
struct perf_event_attr *attrs, size_t nr_attrs);

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:11 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Now that the beautifiers are being split into multiple source and object
files, we will need more of them exported, do it for the 'pid' one, will
be used to augment the return of some syscalls that may return a 'pid',
such as fcntl(fd, F_GETOWN).

Will also be used for fcntl(fd, F_SETOWN, pid).

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-7gr5nt9p5s...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/beauty.h | 3 +++
tools/perf/trace/beauty/pid.c | 4 +---
2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 790e8307fc6a..9ccf0f323fe5 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -43,6 +43,9 @@ size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg
size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_LONG syscall_arg__scnprintf_long

+size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_PID syscall_arg__scnprintf_pid
+
size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd

diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c
index 07486ea65ae3..b6d419e16dcf 100644
--- a/tools/perf/trace/beauty/pid.c
+++ b/tools/perf/trace/beauty/pid.c
@@ -1,4 +1,4 @@
-static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
{
int pid = arg->val;
struct trace *trace = arg->trace;
@@ -17,5 +17,3 @@ static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_a

return printed;
}
-
-#define SCA_PID syscall_arg__scnprintf_pid
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:12 AM7/19/17
to
From: Jin Yao <yao...@linux.intel.com>

For marking fused instructions clearly this patch adds a line before the
first instruction of pair and joins it with the arrow of the jump to its
target.

For example, when "je" is selected in annotate view, the line before
cmpl is displayed and joins the arrow of "je".

│ ┌──cmpl $0x0,argp_program_version_hook
81.93 │ ├──je 20
│ │ lock cmpxchg %esi,0x38a9a4(%rip)
│ │↓ jne 29
│ │↓ jmp 43
11.47 │20:└─→cmpxch %esi,0x38a999(%rip)

That means the cmpl+je is a fused instruction pair and they should be
considered together.

Changelog:

v3: Use Arnaldo's fix to improve the arrow origin rendering. To get the
evsel->evlist->env->cpuid, save the evsel in annotate_browser.

v2: new function "ins__is_fused" to check if the instructions are fused.

Signed-off-by: Yao Jin <yao...@linux.intel.com>
Tested-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Kan Liang <kan....@intel.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1499403995-19857-3-g...@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/ui/browser.c | 29 +++++++++++++++++++++++++++++
tools/perf/ui/browser.h | 2 ++
tools/perf/ui/browsers/annotate.c | 26 ++++++++++++++++++++++++++
tools/perf/util/annotate.c | 5 +++++
tools/perf/util/annotate.h | 1 +
5 files changed, 63 insertions(+)

diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 83874b0e266c..f73f3f13e01d 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -738,6 +738,35 @@ void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
__ui_browser__line_arrow_down(browser, column, start, end);
}

+void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column,
+ unsigned int row, bool arrow_down)
+{
+ unsigned int end_row;
+
+ if (row >= browser->top_idx)
+ end_row = row - browser->top_idx;
+ else
+ return;
+
+ SLsmg_set_char_set(1);
+
+ if (arrow_down) {
+ ui_browser__gotorc(browser, end_row, column - 1);
+ SLsmg_write_char(SLSMG_ULCORN_CHAR);
+ ui_browser__gotorc(browser, end_row, column);
+ SLsmg_draw_hline(2);
+ ui_browser__gotorc(browser, end_row + 1, column - 1);
+ SLsmg_write_char(SLSMG_LTEE_CHAR);
+ } else {
+ ui_browser__gotorc(browser, end_row, column - 1);
+ SLsmg_write_char(SLSMG_LTEE_CHAR);
+ ui_browser__gotorc(browser, end_row, column);
+ SLsmg_draw_hline(2);
+ }
+
+ SLsmg_set_char_set(0);
+}
+
void ui_browser__init(void)
{
int i = 0;
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index be3b70eb5fca..a12eff75638b 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -43,6 +43,8 @@ void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...);
void ui_browser__write_graph(struct ui_browser *browser, int graph);
void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
u64 start, u64 end);
+void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column,
+ unsigned int row, bool arrow_down);
void __ui_browser__show_title(struct ui_browser *browser, const char *title);
void ui_browser__show_title(struct ui_browser *browser, const char *title);
int ui_browser__show(struct ui_browser *browser, const char *title,
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index c4336138b673..8d3f6f53c122 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -273,6 +273,25 @@ static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sy
return true;
}

+static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
+{
+ struct disasm_line *pos = list_prev_entry(cursor, node);
+ const char *name;
+
+ if (!pos)
+ return false;
+
+ if (ins__is_lock(&pos->ins))
+ name = pos->ops.locked.ins.name;
+ else
+ name = pos->ins.name;
+
+ if (!name || !cursor->ins.name)
+ return false;
+
+ return ins__is_fused(ab->arch, name, cursor->ins.name);
+}
+
static void annotate_browser__draw_current_jump(struct ui_browser *browser)
{
struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
@@ -308,6 +327,13 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
__ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,
from, to);
+
+ if (is_fused(ab, cursor)) {
+ ui_browser__mark_fused(browser,
+ pcnt_width + 3 + ab->addr_width,
+ from - 1,
+ to > from ? true : false);
+ }
}

static unsigned int annotate_browser__refresh(struct ui_browser *browser)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 8748ebb3f932..ef434b53d849 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -517,6 +517,11 @@ bool ins__is_ret(const struct ins *ins)
return ins->ops == &ret_ops;
}

+bool ins__is_lock(const struct ins *ins)
+{
+ return ins->ops == &lock_ops;
+}
+
static int ins__key_cmp(const void *name, const void *insp)
{
const struct ins *ins = insp;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 72d72728a0fc..bac698d7cc6a 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -52,6 +52,7 @@ struct ins_ops {
bool ins__is_jump(const struct ins *ins);
bool ins__is_call(const struct ins *ins);
bool ins__is_ret(const struct ins *ins);
+bool ins__is_lock(const struct ins *ins);
int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:13 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

The return for fcntl(fd, F_GETFL) is the fd file flags, so reuse the one
for the open syscall flags parameter:

997.992 (0.002 ms): Chrome_IOThrea/19863 fcntl(fd: 144</dev/shm/.com.google.Chrome.OhA8YL>, cmd: GETFL) = RDWR|LARGEFILE

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-5nn3n4p4yf...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/fcntl.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index 8a5f58d9eb7c..8dcbc30427c9 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -11,13 +11,19 @@

size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg)
{
+ if (arg->val == F_GETFL) {
+ syscall_arg__set_ret_scnprintf(arg, open__scnprintf_flags);
+ goto mask_arg;
+ }
/*
* Some commands ignore the third fcntl argument, "arg", so mask it
*/
- if (arg->val == F_GETFD || arg->val == F_GETFL ||
+ if (arg->val == F_GETFD ||
arg->val == F_GETOWN || arg->val == F_GET_SEALS ||
- arg->val == F_GETLEASE || arg->val == F_GETSIG)
+ arg->val == F_GETLEASE || arg->val == F_GETSIG) {
+mask_arg:
arg->mask |= (1 << 2);
+ }

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:15 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

Do not mess up our temp space with files we don't
need - failed event open attempts.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 0e77b2cf61ec..08b1d5ce9020 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -136,7 +136,7 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
{
int errno_saved = errno;

- if (store_event(attr, pid, cpu, fd, group_fd, flags)) {
+ if ((fd != -1) && store_event(attr, pid, cpu, fd, group_fd, flags)) {
pr_err("test attr FAILED");
exit(128);
}
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:21 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Will be used in the fcntl arg beautifier, that nowadays formats as '%ld'
because there is no explicit arg beautifier attached, but as we will
have to first decide what beautifier to use (i.e. it may be a pointer,
etc) then we need to have this exported as a separate beautifier to be
called from there.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-d7bfs3m8m7...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 5 +++++
tools/perf/trace/beauty/beauty.h | 3 +++
2 files changed, 8 insertions(+)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 9e171401b664..a323736043e1 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -402,6 +402,11 @@ size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg
return scnprintf(bf, size, "%d", arg->val);
}

+size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *arg)
+{
+ return scnprintf(bf, size, "%ld", arg->val);
+}
+
static const char *bpf_cmd[] = {
"MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
"MAP_GET_NEXT_KEY", "PROG_LOAD",
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index d085aacecd49..61aec19e55ec 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -37,6 +37,9 @@ size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg
size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_INT syscall_arg__scnprintf_int

+size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_LONG syscall_arg__scnprintf_long

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:21 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

Add 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.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549.1...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/header.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 2e6036d3e584..28bf4442d577 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -67,6 +67,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)
@@ -1359,10 +1360,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;
@@ -1387,6 +1393,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)
@@ -1757,10 +1764,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;
}
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:22 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

Making compare_data global, so it could be used outside
the Test class scope to compare command results.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr.py | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py
index cdf21a9d0c35..bb671cd1d66a 100644
--- a/tools/perf/tests/attr.py
+++ b/tools/perf/tests/attr.py
@@ -9,6 +9,20 @@ import logging
import shutil
import ConfigParser

+def compare_data(a, b):
+ # Allow multiple values in assignment separated by '|'
+ a_list = a.split('|')
+ b_list = b.split('|')
+
+ for a_item in a_list:
+ for b_item in b_list:
+ if (a_item == b_item):
+ return True
+ elif (a_item == '*') or (b_item == '*'):
+ return True
+
+ return False
+
class Fail(Exception):
def __init__(self, test, msg):
self.msg = msg
@@ -82,26 +96,12 @@ class Event(dict):
self.add(base)
self.add(data)

- def compare_data(self, a, b):
- # Allow multiple values in assignment separated by '|'
- a_list = a.split('|')
- b_list = b.split('|')
-
- for a_item in a_list:
- for b_item in b_list:
- if (a_item == b_item):
- return True
- elif (a_item == '*') or (b_item == '*'):
- return True
-
- return False
-
def equal(self, other):
for t in Event.terms:
log.debug(" [%s] %s %s" % (t, self[t], other[t]));
if not self.has_key(t) or not other.has_key(t):
return False
- if not self.compare_data(self[t], other[t]):
+ if not compare_data(self[t], other[t]):
return False
return True

@@ -109,7 +109,7 @@ class Event(dict):
for t in Event.terms:
if not self.has_key(t) or not other.has_key(t):
continue
- if not self.compare_data(self[t], other[t]):
+ if not compare_data(self[t], other[t]):
log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))

# Test file description needs to have following sections:
@@ -218,9 +218,9 @@ class Test(object):
self.perf, self.command, tempdir, self.args)
ret = os.WEXITSTATUS(os.system(cmd))

- log.info(" '%s' ret %d " % (cmd, ret))
+ log.info(" '%s' ret '%s', expected '%s'" % (cmd, str(ret), str(self.ret)))

- if ret != int(self.ret):
+ if not compare_data(str(ret), str(self.ret)):
raise Unsup(self)

def compare(self, expect, result):
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:40:22 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

To help us provide a simple setns() in older distros.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Krister Johansen <kj...@templeofstupid.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-o10a85kf6j...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/arch/x86/include/asm/unistd_32.h | 3 +++
tools/arch/x86/include/asm/unistd_64.h | 3 +++
2 files changed, 6 insertions(+)

diff --git a/tools/arch/x86/include/asm/unistd_32.h b/tools/arch/x86/include/asm/unistd_32.h
index 88b3f8c8920c..0e4312ffc945 100644
--- a/tools/arch/x86/include/asm/unistd_32.h
+++ b/tools/arch/x86/include/asm/unistd_32.h
@@ -10,3 +10,6 @@
#ifndef __NR_getcpu
# define __NR_getcpu 318
#endif
+#ifndef __NR_setns
+# define __NR_setns 346
+#endif
diff --git a/tools/arch/x86/include/asm/unistd_64.h b/tools/arch/x86/include/asm/unistd_64.h
index fbdb70ee8837..dd56bb36132a 100644
--- a/tools/arch/x86/include/asm/unistd_64.h
+++ b/tools/arch/x86/include/asm/unistd_64.h
@@ -10,3 +10,6 @@
#ifndef __NR_getcpu
# define __NR_getcpu 309
#endif
+#ifndef __NR_setns
+#define __NR_setns 308
+#endif
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:05 AM7/19/17
to
From: Jin Yao <yao...@linux.intel.com>

The branch info such as predicted/cycles/... are printed at the
callchain entries.

For example: perf report --branch-history --no-children --stdio

--1.07%--main div.c:39 (predicted:52.4% cycles:1 iterations:17)
main div.c:44 (predicted:52.4% cycles:1)
main div.c:42 (cycles:2)
compute_flag div.c:28 (cycles:2)
compute_flag div.c:27 (cycles:1)
rand rand.c:28 (cycles:1)
rand rand.c:28 (cycles:1)
__random random.c:298 (cycles:1)
__random random.c:297 (cycles:1)
__random random.c:295 (cycles:1)
__random random.c:295 (cycles:1)
__random random.c:295 (cycles:1)

But the current code is difficult to maintain and extend. This patch
refactors the code for easy maintenance.

Change log:

v6: 1. Put the multiline condition code into {} brackets in
counts_str_build()

2. Keep the original display order, that is:
predicted, abort, cycles, iterations

v5: It's a new patch in v5 patch series.

Signed-off-by: Yao Jin <yao...@linux.intel.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Kan Liang <kan....@intel.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1500379995-6449-5-gi...@linux.intel.com
[ Don't use 'index' as a name for a variable, it shadows a globa decl in older distros ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/callchain.c | 100 ++++++++++++++++++--------------------------
1 file changed, 41 insertions(+), 59 deletions(-)

diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index b4204b43ed58..917f4d6510ae 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -1214,83 +1214,65 @@ int callchain_branch_counts(struct callchain_root *root,
cycles_count);
}

+static int count_pri64_printf(int idx, const char *str, u64 value, char *bf, int bfsize)
+{
+ int printed;
+
+ printed = scnprintf(bf, bfsize, "%s%s:%" PRId64 "", (idx) ? " " : " (", str, value);
+
+ return printed;
+}
+
+static int count_float_printf(int idx, const char *str, float value, char *bf, int bfsize)
+{
+ int printed;
+
+ printed = scnprintf(bf, bfsize, "%s%s:%.1f%%", (idx) ? " " : " (", str, value);
+
+ return printed;
+}
+
static int counts_str_build(char *bf, int bfsize,
u64 branch_count, u64 predicted_count,
u64 abort_count, u64 cycles_count,
u64 iter_count, u64 samples_count)
{
- double predicted_percent = 0.0;
- const char *null_str = "";
- char iter_str[32];
- char cycle_str[32];
- char *istr, *cstr;
u64 cycles;
+ int printed = 0, i = 0;

if (branch_count == 0)
return scnprintf(bf, bfsize, " (calltrace)");

- cycles = cycles_count / branch_count;
-
- if (iter_count && samples_count) {
- if (cycles > 0)
- scnprintf(iter_str, sizeof(iter_str),
- " iterations:%" PRId64 "",
- iter_count / samples_count);
- else
- scnprintf(iter_str, sizeof(iter_str),
- "iterations:%" PRId64 "",
- iter_count / samples_count);
- istr = iter_str;
- } else
- istr = (char *)null_str;
-
- if (cycles > 0) {
- scnprintf(cycle_str, sizeof(cycle_str),
- "cycles:%" PRId64 "", cycles);
- cstr = cycle_str;
- } else
- cstr = (char *)null_str;
-
- predicted_percent = predicted_count * 100.0 / branch_count;
+ if (predicted_count < branch_count) {
+ printed += count_float_printf(i++, "predicted",
+ predicted_count * 100.0 / branch_count,
+ bf + printed, bfsize - printed);
+ }

- if ((predicted_count == branch_count) && (abort_count == 0)) {
- if ((cycles > 0) || (istr != (char *)null_str))
- return scnprintf(bf, bfsize, " (%s%s)", cstr, istr);
- else
- return scnprintf(bf, bfsize, "%s", (char *)null_str);
+ if (abort_count) {
+ printed += count_float_printf(i++, "abort",
+ abort_count * 100.0 / branch_count,
+ bf + printed, bfsize - printed);
}

- if ((predicted_count < branch_count) && (abort_count == 0)) {
- if ((cycles > 0) || (istr != (char *)null_str))
- return scnprintf(bf, bfsize,
- " (predicted:%.1f%% %s%s)",
- predicted_percent, cstr, istr);
- else {
- return scnprintf(bf, bfsize,
- " (predicted:%.1f%%)",
- predicted_percent);
- }
+ cycles = cycles_count / branch_count;
+ if (cycles) {
+ printed += count_pri64_printf(i++, "cycles",
+ cycles,
+ bf + printed, bfsize - printed);
}

- if ((predicted_count == branch_count) && (abort_count > 0)) {
- if ((cycles > 0) || (istr != (char *)null_str))
- return scnprintf(bf, bfsize,
- " (abort:%" PRId64 " %s%s)",
- abort_count, cstr, istr);
- else
- return scnprintf(bf, bfsize,
- " (abort:%" PRId64 ")",
- abort_count);
+ if (iter_count && samples_count) {
+ printed += count_pri64_printf(i++, "iterations",
+ iter_count / samples_count,
+ bf + printed, bfsize - printed);
}

- if ((cycles > 0) || (istr != (char *)null_str))
- return scnprintf(bf, bfsize,
- " (predicted:%.1f%% abort:%" PRId64 " %s%s)",
- predicted_percent, abort_count, cstr, istr);
+ if (i)
+ return scnprintf(bf + printed, bfsize - printed, ")");

- return scnprintf(bf, bfsize,
- " (predicted:%.1f%% abort:%" PRId64 ")",
- predicted_percent, abort_count);
+ bf[0] = 0;
+ return 0;
}

static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:06 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

There 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.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549.1...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/header.c | 72 +++++++++++++++++++++++++++++-------------------
1 file changed, 44 insertions(+), 28 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 5e6d4d29a7a3..0fdbf7554ea3 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -12,6 +12,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>
@@ -2139,42 +2140,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 {
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:06 AM7/19/17
to
From: Jin Yao <yao...@linux.intel.com>

Show branch type in callchain entry. The branch type is printed
with other LBR information (such as cycles/abort/...).

For example:

perf record -g -j any,save_type
perf report --branch-history --stdio --no-children

38.50% div.c:45 [.] main div
|
---main div.c:42 (RET CROSS_2M cycles:2)
compute_flag div.c:28 (cycles:2)
compute_flag div.c:27 (RET CROSS_2M cycles:1)
rand rand.c:28 (cycles:1)
rand rand.c:28 (RET CROSS_2M cycles:1)
__random random.c:298 (cycles:1)
__random random.c:297 (COND_BWD CROSS_2M cycles:1)
__random random.c:295 (cycles:1)
__random random.c:295 (COND_BWD CROSS_2M cycles:1)
__random random.c:295 (cycles:1)
__random random.c:295 (RET CROSS_2M cycles:9)

Change log

v6: Remove the branch_type_str() since it's moved to branch.c.

v5: Rewrite the branch info print code in util/callchain.c.

v4: Comparing to previous version, the major changes are:

Signed-off-by: Yao Jin <yao...@linux.intel.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Kan Liang <kan....@intel.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1500379995-6449-8-gi...@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/callchain.c | 38 +++++++++++++++++++++++++++++---------
tools/perf/util/callchain.h | 5 ++++-
tools/perf/util/machine.c | 26 +++++++++++++++++---------
3 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 917f4d6510ae..22d413ae6025 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -23,6 +23,7 @@
#include "sort.h"
#include "machine.h"
#include "callchain.h"
+#include "branch.h"

#define CALLCHAIN_PARAM_DEFAULT \
.mode = CHAIN_GRAPH_ABS, \
@@ -571,6 +572,11 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
call->cycles_count = cursor_node->branch_flags.cycles;
call->iter_count = cursor_node->nr_loop_iter;
call->samples_count = cursor_node->samples;
+
+ branch_type_count(&call->brtype_stat,
+ &cursor_node->branch_flags,
+ cursor_node->branch_from,
+ cursor_node->ip);
}

list_add_tail(&call->list, &node->val);
@@ -688,6 +694,11 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
cnode->cycles_count += node->branch_flags.cycles;
cnode->iter_count += node->nr_loop_iter;
cnode->samples_count += node->samples;
+
+ branch_type_count(&cnode->brtype_stat,
+ &node->branch_flags,
+ node->branch_from,
+ node->ip);
}

return MATCH_EQ;
@@ -922,7 +933,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
list_for_each_entry_safe(list, next_list, &src->val, list) {
callchain_cursor_append(cursor, list->ip,
list->ms.map, list->ms.sym,
- false, NULL, 0, 0);
+ false, NULL, 0, 0, 0);
list_del(&list->list);
map__zput(list->ms.map);
free(list);
@@ -962,7 +973,7 @@ int callchain_merge(struct callchain_cursor *cursor,
int callchain_cursor_append(struct callchain_cursor *cursor,
u64 ip, struct map *map, struct symbol *sym,
bool branch, struct branch_flags *flags,
- int nr_loop_iter, int samples)
+ int nr_loop_iter, int samples, u64 branch_from)
{
struct callchain_cursor_node *node = *cursor->last;

@@ -986,6 +997,7 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
memcpy(&node->branch_flags, flags,
sizeof(struct branch_flags));

+ node->branch_from = branch_from;
cursor->nr++;

cursor->last = &node->next;
@@ -1235,14 +1247,19 @@ static int count_float_printf(int idx, const char *str, float value, char *bf, i
static int counts_str_build(char *bf, int bfsize,
u64 branch_count, u64 predicted_count,
u64 abort_count, u64 cycles_count,
- u64 iter_count, u64 samples_count)
+ u64 iter_count, u64 samples_count,
+ struct branch_type_stat *brtype_stat)
{
u64 cycles;
- int printed = 0, i = 0;
+ int printed, i = 0;

if (branch_count == 0)
return scnprintf(bf, bfsize, " (calltrace)");

+ printed = branch_type_str(brtype_stat, bf, bfsize);
+ if (printed)
+ i++;
+
if (predicted_count < branch_count) {
printed += count_float_printf(i++, "predicted",
predicted_count * 100.0 / branch_count,
@@ -1278,13 +1295,14 @@ static int counts_str_build(char *bf, int bfsize,
static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
u64 branch_count, u64 predicted_count,
u64 abort_count, u64 cycles_count,
- u64 iter_count, u64 samples_count)
+ u64 iter_count, u64 samples_count,
+ struct branch_type_stat *brtype_stat)
{
- char str[128];
+ char str[256];

counts_str_build(str, sizeof(str), branch_count,
predicted_count, abort_count, cycles_count,
- iter_count, samples_count);
+ iter_count, samples_count, brtype_stat);

if (fp)
return fprintf(fp, "%s", str);
@@ -1316,7 +1334,8 @@ int callchain_list_counts__printf_value(struct callchain_node *node,

return callchain_counts_printf(fp, bf, bfsize, branch_count,
predicted_count, abort_count,
- cycles_count, iter_count, samples_count);
+ cycles_count, iter_count, samples_count,
+ &clist->brtype_stat);
}

static void free_callchain_node(struct callchain_node *node)
@@ -1441,7 +1460,8 @@ int callchain_cursor__copy(struct callchain_cursor *dst,

rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
node->branch, &node->branch_flags,
- node->nr_loop_iter, node->samples);
+ node->nr_loop_iter, node->samples,
+ node->branch_from);
if (rc)
break;

diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index c56c23dbbf72..97738201464a 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -7,6 +7,7 @@
#include "event.h"
#include "map.h"
#include "symbol.h"
+#include "branch.h"

#define HELP_PAD "\t\t\t\t"

@@ -119,6 +120,7 @@ struct callchain_list {
u64 cycles_count;
u64 iter_count;
u64 samples_count;
+ struct branch_type_stat brtype_stat;
char *srcline;
struct list_head list;
};
@@ -135,6 +137,7 @@ struct callchain_cursor_node {
struct symbol *sym;
bool branch;
struct branch_flags branch_flags;
+ u64 branch_from;
int nr_loop_iter;
int samples;
struct callchain_cursor_node *next;
@@ -198,7 +201,7 @@ static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
struct map *map, struct symbol *sym,
bool branch, struct branch_flags *flags,
- int nr_loop_iter, int samples);
+ int nr_loop_iter, int samples, u64 branch_from);

/* Close a cursor writing session. Initialize for the reader */
static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index a54a2be5eda4..79d08ea694da 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1682,7 +1682,8 @@ static int add_callchain_ip(struct thread *thread,
bool branch,
struct branch_flags *flags,
int nr_loop_iter,
- int samples)
+ int samples,
+ u64 branch_from)
{
struct addr_location al;

@@ -1735,7 +1736,8 @@ static int add_callchain_ip(struct thread *thread,
if (symbol_conf.hide_unresolved && al.sym == NULL)
return 0;
return callchain_cursor_append(cursor, al.addr, al.map, al.sym,
- branch, flags, nr_loop_iter, samples);
+ branch, flags, nr_loop_iter, samples,
+ branch_from);
}

struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1814,7 +1816,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
struct ip_callchain *chain = sample->callchain;
int chain_nr = min(max_stack, (int)chain->nr), i;
u8 cpumode = PERF_RECORD_MISC_USER;
- u64 ip;
+ u64 ip, branch_from = 0;

for (i = 0; i < chain_nr; i++) {
if (chain->ips[i] == PERF_CONTEXT_USER)
@@ -1856,6 +1858,8 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
ip = lbr_stack->entries[0].to;
branch = true;
flags = &lbr_stack->entries[0].flags;
+ branch_from =
+ lbr_stack->entries[0].from;
}
} else {
if (j < lbr_nr) {
@@ -1870,12 +1874,15 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
ip = lbr_stack->entries[0].to;
branch = true;
flags = &lbr_stack->entries[0].flags;
+ branch_from =
+ lbr_stack->entries[0].from;
}
}

err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, ip,
- branch, flags, 0, 0);
+ branch, flags, 0, 0,
+ branch_from);
if (err)
return (err < 0) ? err : 0;
}
@@ -1974,19 +1981,20 @@ static int thread__resolve_callchain_sample(struct thread *thread,
root_al,
NULL, be[i].to,
true, &be[i].flags,
- nr_loop_iter, 1);
+ nr_loop_iter, 1,
+ be[i].from);
else
err = add_callchain_ip(thread, cursor, parent,
root_al,
NULL, be[i].to,
true, &be[i].flags,
- 0, 0);
+ 0, 0, be[i].from);

if (!err)
err = add_callchain_ip(thread, cursor, parent, root_al,
NULL, be[i].from,
true, &be[i].flags,
- 0, 0);
+ 0, 0, 0);
if (err == -EINVAL)
break;
if (err)
@@ -2016,7 +2024,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,

err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, ip,
- false, NULL, 0, 0);
+ false, NULL, 0, 0, 0);

if (err)
return (err < 0) ? err : 0;
@@ -2033,7 +2041,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
return 0;
return callchain_cursor_append(cursor, entry->ip,
entry->map, entry->sym,
- false, NULL, 0, 0);
+ false, NULL, 0, 0, 0);
}

static int thread__resolve_callchain_unwind(struct thread *thread,
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:10 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

Following commit:

commit 5c0cf22477ea ("perf record: Store data mmaps for dwarf unwind")

have enabled address sampling for dwarf unwind, we need to reflect that
in this test by adding ADDR sample_type and enabling mmap_data.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr/test-record-graph-dwarf | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/tests/attr/test-record-graph-dwarf b/tools/perf/tests/attr/test-record-graph-dwarf
index d6f324ea578c..8321c602dc38 100644
--- a/tools/perf/tests/attr/test-record-graph-dwarf
+++ b/tools/perf/tests/attr/test-record-graph-dwarf
@@ -3,8 +3,9 @@ command = record
args = --call-graph dwarf -- kill >/dev/null 2>&1

[event:base-record]
-sample_type=12583
+sample_type=45359
exclude_callchain_user=1
sample_stack_user=8192
# TODO different for each arch, no support for that now
sample_regs_user=*
+mmap_data=1
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:11 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

We have a test to detect to highest precise possible, so test can't just
predict precise_ip value.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Thomas Richter <tmr...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/20170703145030...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr/base-record | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index a9cb72b8fbb1..31e0b1da830b 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -25,7 +25,7 @@ inherit_stat=0
enable_on_exec=1
task=0
watermark=0
-precise_ip=0
+precise_ip=0|1|2|3
mmap_data=0
sample_id_all=1
exclude_host=0|1
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:11 AM7/19/17
to
From: Jin Yao <yao...@linux.intel.com>

Show the branch type statistics at the end of perf report --stdio.

For example:

perf report --stdio

COND_FWD: 28.5%
COND_BWD: 9.4%
CROSS_4K: 0.7%
CROSS_2M: 14.1%
COND: 37.9%
UNCOND: 0.2%
IND: 6.7%
CALL: 26.5%
RET: 28.7%
SYSRET: 0.0%

The branch types are:

COND_FWD: conditional forward
COND_BWD: conditional backward
COND: conditional branch
UNCOND: unconditional branch
IND: indirect
CALL: function call
IND_CALL: indirect function call
RET: function return
SYSCALL: syscall
SYSRET: syscall return
COND_CALL: conditional function call
COND_RET: conditional function return

CROSS_4K and CROSS_2M:

They are the metrics checking for branches cross 4K or 2MB pages.
It's an approximate computing. We don't know if the area is 4K or
2MB, so always compute both.

To make the output simple, if a branch crosses 2M area, CROSS_4K
will not be incremented.

Change log

v7: Since the common branch type definitions are changed, some
tags/strings are updated accordingly.

v6: Remove branch_type_stat_display() since it's moved to branch.c.

v5: Remove the unnecessary sort__mode checking in
hist_iter__branch_callback().

v4: Comparing to previous version, the major changes are:

Add the computing of JCC forward/JCC backward and cross page checking
by using the from and to addresses.

Signed-off-by: Yao Jin <yao...@linux.intel.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Kan Liang <kan....@intel.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1500379995-6449-7-gi...@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-report.c | 25 +++++++++++++++++++++++++
tools/perf/util/hist.c | 5 +----
2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8e752ba5e887..cea25d03f4dd 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -38,6 +38,7 @@
#include "util/time-utils.h"
#include "util/auxtrace.h"
#include "util/units.h"
+#include "util/branch.h"

#include <dlfcn.h>
#include <errno.h>
@@ -73,6 +74,7 @@ struct report {
u64 queue_size;
int socket_filter;
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+ struct branch_type_stat brtype_stat;
};

static int report__config(const char *var, const char *value, void *cb)
@@ -150,6 +152,22 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
return err;
}

+static int hist_iter__branch_callback(struct hist_entry_iter *iter,
+ struct addr_location *al __maybe_unused,
+ bool single __maybe_unused,
+ void *arg)
+{
+ struct hist_entry *he = iter->he;
+ struct report *rep = arg;
+ struct branch_info *bi;
+
+ bi = he->branch_info;
+ branch_type_count(&rep->brtype_stat, &bi->flags,
+ bi->from.addr, bi->to.addr);
+
+ return 0;
+}
+
static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
@@ -188,6 +206,8 @@ static int process_sample_event(struct perf_tool *tool,
*/
if (!sample->branch_stack)
goto out_put;
+
+ iter.add_entry_cb = hist_iter__branch_callback;
iter.ops = &hist_iter_branch;
} else if (rep->mem_mode) {
iter.ops = &hist_iter_mem;
@@ -410,6 +430,9 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
perf_read_values_destroy(&rep->show_threads_values);
}

+ if (sort__mode == SORT_MODE__BRANCH)
+ branch_type_stat_display(stdout, &rep->brtype_stat);
+
return 0;
}

@@ -944,6 +967,8 @@ int cmd_report(int argc, const char **argv)
if (has_br_stack && branch_call_mode)
symbol_conf.show_branchflag_count = true;

+ memset(&report.brtype_stat, 0, sizeof(struct branch_type_stat));
+
/*
* Branch mode is a tristate:
* -1 means default, so decide based on the file having branch data.
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cf0186a088c1..2f6c5e6c16f9 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -749,12 +749,9 @@ iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al
}

static int
-iter_add_single_branch_entry(struct hist_entry_iter *iter,
+iter_add_single_branch_entry(struct hist_entry_iter *iter __maybe_unused,
struct addr_location *al __maybe_unused)
{
- /* to avoid calling callback function */
- iter->he = NULL;
-
return 0;
}

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:12 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

Following commit:
commit 509051ea8427 ("perf record: Rename --no-delay to --no-buffering")

removed '-D' option and renamed --no-delay into --no-buffering.
Fixing that in the attr tests.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Thomas Richter <tmr...@linux.vnet.ibm.com>
Fixes: 509051ea8427 ("perf record: Rename --no-delay to --no-buffering")
Link: http://lkml.kernel.org/r/20170703145030...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
.../perf/tests/attr/{test-record-no-delay => test-record-no-buffering} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename tools/perf/tests/attr/{test-record-no-delay => test-record-no-buffering} (70%)

diff --git a/tools/perf/tests/attr/test-record-no-delay b/tools/perf/tests/attr/test-record-no-buffering
similarity index 70%
rename from tools/perf/tests/attr/test-record-no-delay
rename to tools/perf/tests/attr/test-record-no-buffering
index f253b78cdbf2..0b0355af013a 100644
--- a/tools/perf/tests/attr/test-record-no-delay
+++ b/tools/perf/tests/attr/test-record-no-buffering
@@ -1,6 +1,6 @@
[config]
command = record
-args = -D kill >/dev/null 2>&1
+args = --no-buffering kill >/dev/null 2>&1

[event:base-record]
sample_period=4000
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:27 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

In 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).

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549.1...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/header.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 14db9f204b0a..d5359e3384e3 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -797,11 +797,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;
@@ -809,7 +817,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)
@@ -820,12 +827,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;
- }

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:50 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

The stat command creates all events disabled and enables them either
manualy or via the enable_on_exec bit.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Thomas Richter <tmr...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/20170703145030...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr/test-stat-C0 | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/tests/attr/test-stat-C0 b/tools/perf/tests/attr/test-stat-C0
index aa835950751f..67717fe6a65d 100644
--- a/tools/perf/tests/attr/test-stat-C0
+++ b/tools/perf/tests/attr/test-stat-C0
@@ -4,6 +4,6 @@ args = -e cycles -C 0 kill >/dev/null 2>&1
ret = 1

[event:base-stat]
-# events are enabled by default when attached to cpu
-disabled=0
+# events are disabled by default when attached to cpu
+disabled=1
enable_on_exec=0
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:51 AM7/19/17
to
From: Jin Yao <yao...@linux.intel.com>

Create new util/branch.c and util/branch.h to contain the common branch
functions. Such as:

branch_type_count(): Count the numbers of branch types
branch_type_name() : Return the name of branch type
branch_type_stat_display(): Display branch type statistics info
branch_type_str(): Construct the branch type string.

The branch type is saved in branch_flags.

Change log:

v8: Change PERF_BR_NONE to PERF_BR_UNKNOWN.

v7: Since the common branch type name is changed (e.g. JCC->COND),
this patch is performed the modification accordingly.

v6: Move that multiline conditional code inside {} brackets.
Move branch_type_stat_display() from builtin-report.c to
branch.c.
Move branch_type_str() from callchain.c to branch.c.

v5: It's a new patch in v5 patch series.

Signed-off-by: Yao Jin <yao...@linux.intel.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Kan Liang <kan....@intel.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1500379995-6449-6-gi...@linux.intel.com
[ Don't use 'index' and 'stat' as names for variables, it shadows global decls in older distros ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/Build | 1 +
tools/perf/util/branch.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/branch.h | 24 ++++++++
tools/perf/util/event.h | 3 +-
4 files changed, 174 insertions(+), 1 deletion(-)
create mode 100644 tools/perf/util/branch.c
create mode 100644 tools/perf/util/branch.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 7580fe4d5d30..8d49a989f193 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -93,6 +93,7 @@ libperf-y += drv_configs.o
libperf-y += units.o
libperf-y += time-utils.o
libperf-y += expr-bison.o
+libperf-y += branch.o

libperf-$(CONFIG_LIBBPF) += bpf-loader.o
libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
diff --git a/tools/perf/util/branch.c b/tools/perf/util/branch.c
new file mode 100644
index 000000000000..a4fce2729e50
--- /dev/null
+++ b/tools/perf/util/branch.c
@@ -0,0 +1,147 @@
+#include "perf.h"
+#include "util/util.h"
+#include "util/debug.h"
+#include "util/branch.h"
+
+static bool cross_area(u64 addr1, u64 addr2, int size)
+{
+ u64 align1, align2;
+
+ align1 = addr1 & ~(size - 1);
+ align2 = addr2 & ~(size - 1);
+
+ return (align1 != align2) ? true : false;
+}
+
+#define AREA_4K 4096
+#define AREA_2M (2 * 1024 * 1024)
+
+void branch_type_count(struct branch_type_stat *st, struct branch_flags *flags,
+ u64 from, u64 to)
+{
+ if (flags->type == PERF_BR_UNKNOWN || from == 0)
+ return;
+
+ st->counts[flags->type]++;
+
+ if (flags->type == PERF_BR_COND) {
+ if (to > from)
+ st->cond_fwd++;
+ else
+ st->cond_bwd++;
+ }
+
+ if (cross_area(from, to, AREA_2M))
+ st->cross_2m++;
+ else if (cross_area(from, to, AREA_4K))
+ st->cross_4k++;
+}
+
+const char *branch_type_name(int type)
+{
+ const char *branch_names[PERF_BR_MAX] = {
+ "N/A",
+ "COND",
+ "UNCOND",
+ "IND",
+ "CALL",
+ "IND_CALL",
+ "RET",
+ "SYSCALL",
+ "SYSRET",
+ "COND_CALL",
+ "COND_RET"
+ };
+
+ if (type >= 0 && type < PERF_BR_MAX)
+ return branch_names[type];
+
+ return NULL;
+}
+
+void branch_type_stat_display(FILE *fp, struct branch_type_stat *st)
+{
+ u64 total = 0;
+ int i;
+
+ for (i = 0; i < PERF_BR_MAX; i++)
+ total += st->counts[i];
+
+ if (total == 0)
+ return;
+
+ fprintf(fp, "\n#");
+ fprintf(fp, "\n# Branch Statistics:");
+ fprintf(fp, "\n#");
+
+ if (st->cond_fwd > 0) {
+ fprintf(fp, "\n%8s: %5.1f%%",
+ "COND_FWD",
+ 100.0 * (double)st->cond_fwd / (double)total);
+ }
+
+ if (st->cond_bwd > 0) {
+ fprintf(fp, "\n%8s: %5.1f%%",
+ "COND_BWD",
+ 100.0 * (double)st->cond_bwd / (double)total);
+ }
+
+ if (st->cross_4k > 0) {
+ fprintf(fp, "\n%8s: %5.1f%%",
+ "CROSS_4K",
+ 100.0 * (double)st->cross_4k / (double)total);
+ }
+
+ if (st->cross_2m > 0) {
+ fprintf(fp, "\n%8s: %5.1f%%",
+ "CROSS_2M",
+ 100.0 * (double)st->cross_2m / (double)total);
+ }
+
+ for (i = 0; i < PERF_BR_MAX; i++) {
+ if (st->counts[i] > 0)
+ fprintf(fp, "\n%8s: %5.1f%%",
+ branch_type_name(i),
+ 100.0 *
+ (double)st->counts[i] / (double)total);
+ }
+}
+
+static int count_str_scnprintf(int idx, const char *str, char *bf, int size)
+{
+ return scnprintf(bf, size, "%s%s", (idx) ? " " : " (", str);
+}
+
+int branch_type_str(struct branch_type_stat *st, char *bf, int size)
+{
+ int i, j = 0, printed = 0;
+ u64 total = 0;
+
+ for (i = 0; i < PERF_BR_MAX; i++)
+ total += st->counts[i];
+
+ if (total == 0)
+ return 0;
+
+ if (st->cond_fwd > 0)
+ printed += count_str_scnprintf(j++, "COND_FWD", bf + printed, size - printed);
+
+ if (st->cond_bwd > 0)
+ printed += count_str_scnprintf(j++, "COND_BWD", bf + printed, size - printed);
+
+ for (i = 0; i < PERF_BR_MAX; i++) {
+ if (i == PERF_BR_COND)
+ continue;
+
+ if (st->counts[i] > 0)
+ printed += count_str_scnprintf(j++, branch_type_name(i), bf + printed, size - printed);
+ }
+
+ if (st->cross_4k > 0)
+ printed += count_str_scnprintf(j++, "CROSS_4K", bf + printed, size - printed);
+
+ if (st->cross_2m > 0)
+ printed += count_str_scnprintf(j++, "CROSS_2M", bf + printed, size - printed);
+
+ return printed;
+}
diff --git a/tools/perf/util/branch.h b/tools/perf/util/branch.h
new file mode 100644
index 000000000000..686f2b65ba84
--- /dev/null
+++ b/tools/perf/util/branch.h
@@ -0,0 +1,24 @@
+#ifndef _PERF_BRANCH_H
+#define _PERF_BRANCH_H 1
+
+#include <stdint.h>
+#include "../perf.h"
+
+struct branch_type_stat {
+ u64 counts[PERF_BR_MAX];
+ u64 cond_fwd;
+ u64 cond_bwd;
+ u64 cross_4k;
+ u64 cross_2m;
+};
+
+struct branch_flags;
+
+void branch_type_count(struct branch_type_stat *st, struct branch_flags *flags,
+ u64 from, u64 to);
+
+const char *branch_type_name(int type);
+void branch_type_stat_display(FILE *fp, struct branch_type_stat *st);
+int branch_type_str(struct branch_type_stat *st, char *bf, int bfsize);
+
+#endif /* _PERF_BRANCH_H */
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 37c5fafb549c..423ac82605f3 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -142,7 +142,8 @@ struct branch_flags {
u64 in_tx:1;
u64 abort:1;
u64 cycles:16;
- u64 reserved:44;
+ u64 type:4;
+ u64 reserved:40;
};

struct branch_entry {
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:53 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

Add show_feat_hdr to control level of printed information of feature
headers.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549.1...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-report.c | 4 ++++
tools/perf/builtin-script.c | 3 +++
tools/perf/util/tool.h | 7 +++++++
3 files changed, 14 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 79a33eb1a10d..40c3a92c8006 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -988,6 +988,10 @@ int cmd_report(int argc, const char **argv)
/* 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;
+ if (report.show_full_info)
+ report.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;

if (strcmp(input_name, "-") != 0)
setup_browser(true);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 83cdc0a61fd6..6e44552a0551 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2972,10 +2972,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;
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 829471a1c6d7..baeca808dfda 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -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 */
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:53 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

Add 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.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549.1...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
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 | 98 ++++++++++++++++++++++
tools/perf/util/header.h | 9 ++
tools/perf/util/session.c | 4 +
tools/perf/util/tool.h | 3 +-
12 files changed, 141 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index de8b39dda7b8..e90c59c6d815 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -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:
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7a5dc7e5c577..5205408e795b 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -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,
},
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index ea8db38eedd1..2b8032908fb2 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -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),
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 64eef9a567d9..36d7117a7562 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -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) {
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 40c3a92c8006..8e752ba5e887 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -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,
},
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 6e44552a0551..d430ff42208a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2682,6 +2682,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,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index dc5c3bb69d73..1c905ba3641b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -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[] = {
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 9967c87af7a6..37c5fafb549c 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -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
};

@@ -609,6 +610,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;
@@ -639,6 +646,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);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 0fdbf7554ea3..2e6036d3e584 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -35,6 +35,7 @@
#include "data.h"
#include <api/fs/fs.h>
#include "asm/bug.h"
+#include "tool.h"

#include "sane_ctype.h"

@@ -2982,6 +2983,103 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
return err;
}

+int perf_event__synthesize_features(struct perf_tool *tool,
+ struct perf_session *session,
+ struct perf_evlist *evlist,
+ perf_event__handler_t process)
+{
+ struct perf_header *header = &session->header;
+ struct feat_fd ff;
+ struct feature_event *fe;
+ size_t sz, sz_hdr;
+ int feat, ret;
+
+ sz_hdr = sizeof(fe->header);
+ sz = sizeof(union perf_event);
+ /* get a nice alignment */
+ sz = PERF_ALIGN(sz, page_size);
+
+ memset(&ff, 0, sizeof(ff));
+
+ ff.buf = malloc(sz);
+ if (!ff.buf)
+ return -ENOMEM;
+
+ ff.size = sz - sz_hdr;
+
+ 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;
+ }
+ /* 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) {
+ free(ff.buf);
+ return ret;
+ }
+ }
+ free(ff.buf);
+ return 0;
+}
+
+int perf_event__process_feature(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_session *session __maybe_unused)
+{
+ struct feat_fd ff = { .fd = 0 };
+ struct feature_event *fe = (struct feature_event *)event;
+ int type = fe->header.type;
+ u64 feat = fe->feat_id;
+
+ if (type < 0 || type >= PERF_RECORD_HEADER_MAX) {
+ pr_warning("invalid record type %d in pipe-mode\n", type);
+ return 0;
+ }
+ if (feat == HEADER_RESERVED || feat > HEADER_LAST_FEATURE) {
+ pr_warning("invalid record type %d in pipe-mode\n", type);
+ return -1;
+ }
+
+ if (!feat_ops[feat].process)
+ return 0;
+
+ ff.buf = (void *)fe->data;
+ ff.size = event->header.size - sizeof(event->header);
+ ff.ph = &session->header;
+
+ if (feat_ops[feat].process(&ff, NULL))
+ return -1;
+
+ if (!feat_ops[feat].print || !tool->show_feat_hdr)
+ return 0;
+
+ if (!feat_ops[feat].full_only ||
+ tool->show_feat_hdr >= SHOW_FEAT_HEADER_FULL_INFO) {
+ feat_ops[feat].print(&ff, stdout);
+ } else {
+ fprintf(stdout, "# %s info available, use -I to display\n",
+ feat_ops[feat].name);
+ }
+
+ return 0;
+}
+
static struct event_update_event *
event_update_event__new(size_t size, u64 type, u64 id)
{
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 9d8dcd5eb727..f7a16ee527b8 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index d19c40a81040..dc453f84a14c 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -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;
}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index baeca808dfda..d549e50db397 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -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;
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:54 AM7/19/17
to
From: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>

Add currently supported POWER9 PVRs to the mapfile

Signed-off-by: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>
Cc: Andi Kleen <an...@firstfloor.org>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Shriya <shr...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/n/tip-k1pe02sn5g...@git.kernel.org
[ Fix conflict with a87006fd5629 ("perf pmu-events: Support additional POWER8+ PVR in mapfile") ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/pmu-events/arch/powerpc/mapfile.csv | 3 +++
1 file changed, 3 insertions(+)

diff --git a/tools/perf/pmu-events/arch/powerpc/mapfile.csv b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
index f03aec70dfc9..14318ef215f8 100644
--- a/tools/perf/pmu-events/arch/powerpc/mapfile.csv
+++ b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
@@ -20,3 +20,6 @@
004d0100,1,power8.json,core
004d0200,1,power8.json,core
004c0100,1,power8.json,core
+004e0100,1,power9.json,core
+004e0200,1,power9.json,core
+004e1200,1,power9.json,core
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:54 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

One more looking prettier.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-ytr7idkese...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/fcntl.c | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index d082fd2e594f..b6987c468d18 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -20,6 +20,19 @@ static size_t syscall_arg__scnprintf_fcntl_getfd(char *bf, size_t size, struct s
return fcntl__scnprintf_getfd(arg->val, bf, size);
}

+static size_t fcntl__scnprintf_getlease(unsigned long val, char *bf, size_t size)
+{
+ static const char *fcntl_setlease[] = { "RDLCK", "WRLCK", "UNLCK", };
+ static DEFINE_STRARRAY(fcntl_setlease);
+
+ return strarray__scnprintf(&strarray__fcntl_setlease, bf, size, "%x", val);
+}
+
+static size_t syscall_arg__scnprintf_fcntl_getlease(char *bf, size_t size, struct syscall_arg *arg)
+{
+ return fcntl__scnprintf_getlease(arg->val, bf, size);
+}
+
size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg)
{
if (arg->val == F_GETFL) {
@@ -38,11 +51,15 @@ size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_ar
syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_pid);
goto mask_arg;
}
+ if (arg->val == F_GETLEASE) {
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getlease);
+ goto mask_arg;
+ }
/*
* Some commands ignore the third fcntl argument, "arg", so mask it
*/
if (arg->val == F_GET_SEALS ||
- arg->val == F_GETLEASE || arg->val == F_GETSIG) {
+ arg->val == F_GETSIG) {
mask_arg:
arg->mask |= (1 << 2);
}
@@ -62,6 +79,9 @@ size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_ar

if (cmd == F_SETOWN)
return syscall_arg__scnprintf_pid(bf, size, arg);
+
+ if (cmd == F_SETLEASE)
+ return fcntl__scnprintf_getlease(arg->val, bf, size);
/*
* We still don't grab the contents of pointers on entry or exit,
* so just print them as hex numbers
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:54 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

As 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.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549.1...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/header.c | 101 +++++++++++++++++++++++------------------------
1 file changed, 50 insertions(+), 51 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 60394d27e8f5..14db9f204b0a 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -126,54 +126,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
@@ -1208,8 +1208,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;
@@ -1218,10 +1217,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 */
@@ -1245,21 +1244,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;

@@ -1273,7 +1272,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++;
}
@@ -1295,7 +1294,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;

@@ -1597,7 +1596,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; \
}

@@ -1627,11 +1626,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;
@@ -1644,7 +1643,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;
@@ -1687,7 +1686,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;
@@ -1706,7 +1705,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;
@@ -1720,7 +1719,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;

@@ -1752,7 +1751,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;
@@ -1761,7 +1760,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;

@@ -1773,14 +1772,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;

@@ -1802,12 +1801,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) {
@@ -1835,7 +1834,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);
@@ -1846,16 +1845,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;

@@ -1881,7 +1880,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) {
@@ -1894,10 +1893,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;

@@ -1933,7 +1932,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;
@@ -1947,14 +1946,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;
}

@@ -2024,13 +2023,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);
@@ -2041,7 +2040,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)
@@ -2051,7 +2050,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;

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:41:57 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

Simplify code by adding a macro to handle the common case of processing
header features that are a simple string.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549....@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/header.c | 65 +++++++++++++-----------------------------------
1 file changed, 17 insertions(+), 48 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 24e842c02027..3b833f06c4e7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1603,6 +1603,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)
@@ -1620,38 +1637,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)
@@ -1671,22 +1656,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)
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:45:25 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

We were only beautifying (transforming from an integer to its name) the
non-linux specific fcntl syscall cmd args, fix it:

Before:

# perf trace -e fcntl -p 2472
0.000 ( 0.017 ms): gnome-terminal/2472 fcntl(fd: 55, cmd: 1030) = 56
^C#

After:

# trace -e fcntl -p 2472
0.000 ( 0.015 ms): gnome-terminal/2472 fcntl(fd: 55, cmd: DUPFD_CLOEXEC) = 56
^C#

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-zigsxruk4w...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 57 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 54 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index cfe1858ed074..431ef70067ed 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -64,6 +64,10 @@
# define O_CLOEXEC 02000000
#endif

+#ifndef F_LINUX_SPECIFIC_BASE
+# define F_LINUX_SPECIFIC_BASE 1024
+#endif
+
struct trace {
struct perf_tool tool;
struct syscalltbl *sctbl;
@@ -317,6 +321,38 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,

#define SCA_STRARRAY syscall_arg__scnprintf_strarray

+struct strarrays {
+ int nr_entries;
+ struct strarray **entries;
+};
+
+#define DEFINE_STRARRAYS(array) struct strarrays strarrays__##array = { \
+ .nr_entries = ARRAY_SIZE(array), \
+ .entries = array, \
+}
+
+static size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size,
+ struct syscall_arg *arg)
+{
+ struct strarrays *sas = arg->parm;
+ int i;
+
+ for (i = 0; i < sas->nr_entries; ++i) {
+ struct strarray *sa = sas->entries[i];
+ int idx = arg->val - sa->offset;
+
+ if (idx >= 0 && idx < sa->nr_entries) {
+ if (sa->entries[idx] == NULL)
+ break;
+ return scnprintf(bf, size, "%s", sa->entries[idx]);
+ }
+ }
+
+ return scnprintf(bf, size, "%d", arg->val);
+}
+
+#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays
+
#if defined(__i386__) || defined(__x86_64__)
/*
* FIXME: Make this available to all arches as soon as the ioctl beautifier
@@ -413,6 +449,20 @@ static const char *fcntl_cmds[] = {
};
static DEFINE_STRARRAY(fcntl_cmds);

+static const char *fcntl_linux_specific_cmds[] = {
+ "SETLEASE", "GETLEASE", "NOTIFY", [5] = "CANCELLK", "DUPFD_CLOEXEC",
+ "SETPIPE_SZ", "GETPIPE_SZ", "ADD_SEALS", "GET_SEALS",
+};
+
+static DEFINE_STRARRAY_OFFSET(fcntl_linux_specific_cmds, F_LINUX_SPECIFIC_BASE);
+
+static struct strarray *fcntl_cmds_arrays[] = {
+ &strarray__fcntl_cmds,
+ &strarray__fcntl_linux_specific_cmds,
+};
+
+static DEFINE_STRARRAYS(fcntl_cmds_arrays);
+
static const char *rlimit_resources[] = {
"CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
"MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
@@ -613,8 +663,8 @@ static struct syscall_fmt {
{ .name = "fchownat", .errmsg = true,
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
{ .name = "fcntl", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
- .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
+ .arg_scnprintf = { [1] = SCA_STRARRAYS, /* cmd */ },
+ .arg_parm = { [1] = &strarrays__fcntl_cmds_arrays, /* cmd */ }, },
{ .name = "fdatasync", .errmsg = true, },
{ .name = "flock", .errmsg = true,
.arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
@@ -1356,7 +1406,8 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
*/
if (val == 0 &&
!(sc->arg_scnprintf &&
- sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
+ (sc->arg_scnprintf[arg.idx] == SCA_STRARRAY ||
+ sc->arg_scnprintf[arg.idx] == SCA_STRARRAYS) &&
sc->arg_parm[arg.idx]))
continue;

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:45:29 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Before:

77059.513 ( 0.005 ms): bash/6649 fcntl(fd: 1</dev/pts/12>, arg: 10) = 10</dev/pts/12>

After:

77059.513 ( 0.005 ms): bash/6649 fcntl(fd: 1</dev/pts/12>, cmd: DUPFD, arg: 10) = 10</dev/pts/12>

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-woois88uwc...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index b842bd93457f..bab87f612a36 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -652,7 +652,8 @@ static struct syscall_fmt {
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
{ .name = "fcntl", .errmsg = true,
.arg = { [1] = { .scnprintf = SCA_FCNTL_CMD, /* cmd */
- .parm = &strarrays__fcntl_cmds_arrays, /* cmd */ },
+ .parm = &strarrays__fcntl_cmds_arrays,
+ .show_zero = true, },
[2] = { .scnprintf = SCA_FCNTL_ARG, /* arg */ }, }, },
{ .name = "fdatasync", .errmsg = true, },
{ .name = "flock", .errmsg = true,
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:45:32 AM7/19/17
to
From: Jin Yao <yao...@linux.intel.com>

The option indicates the kernel to save branch type during sampling.

One example:

perf record -g --branch-filter any,save_type <command>

Signed-off-by: Yao Jin <yao...@linux.intel.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Kan Liang <kan....@intel.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1500379995-6449-4-gi...@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/perf-record.txt | 1 +
tools/perf/util/parse-branch-options.c | 1 +
2 files changed, 2 insertions(+)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index b0e9e921d534..9bdea047c5db 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -332,6 +332,7 @@ following filters are defined:
- no_tx: only when the target is not in a hardware transaction
- abort_tx: only when the target is a hardware transaction abort
- cond: conditional branches
+ - save_type: save branch type during sampling in case binary is not available later

+
The option requires at least one branch type among any, any_call, any_ret, ind_call, cond.
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c
index 38fd11504015..e71fb5f31e84 100644
--- a/tools/perf/util/parse-branch-options.c
+++ b/tools/perf/util/parse-branch-options.c
@@ -28,6 +28,7 @@ static const struct branch_mode branch_modes[] = {
BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND),
BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP),
BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL),
+ BRANCH_OPT("save_type", PERF_SAMPLE_BRANCH_TYPE_SAVE),
BRANCH_END
};

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:45:36 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

We need the current thread and the trace internal state so that we can
use the fd beautifier to augment syscall returns, so use struct
syscall_arg with some fields that make sense on returns (val, thread,
trace).

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-lqag8e86yb...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 11 ++++++++---
tools/perf/trace/beauty/beauty.h | 5 ++++-
tools/perf/trace/beauty/fcntl.c | 9 +++++++--
tools/perf/trace/beauty/open_flags.c | 5 +----
4 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index d48981c36b70..cfa8bf1cca43 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -918,7 +918,7 @@ struct thread_trace {
unsigned long pfmaj, pfmin;
char *entry_str;
double runtime_ms;
- size_t (*ret_scnprintf)(unsigned long value, char *bf, size_t size);
+ size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
struct {
unsigned long ptr;
short int entry_str_pos;
@@ -971,7 +971,7 @@ static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)


void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
- size_t (*ret_scnprintf)(unsigned long val, char *bf, size_t size))
+ size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg))
{
struct thread_trace *ttrace = thread__priv(arg->thread);

@@ -1726,7 +1726,12 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
fprintf(trace->output, ") = 0 Timeout");
else if (ttrace->ret_scnprintf) {
char bf[1024];
- ttrace->ret_scnprintf(ret, bf, sizeof(bf));
+ struct syscall_arg arg = {
+ .val = ret,
+ .thread = thread,
+ .trace = trace,
+ };
+ ttrace->ret_scnprintf(bf, sizeof(bf), &arg);
ttrace->ret_scnprintf = NULL;
fprintf(trace->output, ") = %s", bf);
} else if (sc->fmt->hexret)
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index a9613d2e6cfe..b64c4116cdc4 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -46,6 +46,9 @@ size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_ar
size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_FCNTL_ARG syscall_arg__scnprintf_fcntl_arg

+size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
+
size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags

@@ -55,6 +58,6 @@ size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_a
size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size);

void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
- size_t (*ret_scnprintf)(unsigned long val, char *bf, size_t size));
+ size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg));

#endif /* _PERF_TRACE_BEAUTY_H */
diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index 384f177a4304..9de80a7eddfa 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -15,14 +15,19 @@ static size_t fcntl__scnprintf_getfd(unsigned long val, char *bf, size_t size)
return scnprintf(bf, size, "%s", val ? "CLOEXEC" : "0");
}

+static size_t syscall_arg__scnprintf_fcntl_getfd(char *bf, size_t size, struct syscall_arg *arg)
+{
+ return fcntl__scnprintf_getfd(arg->val, bf, size);
+}
+
size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg)
{
if (arg->val == F_GETFL) {
- syscall_arg__set_ret_scnprintf(arg, open__scnprintf_flags);
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_open_flags);
goto mask_arg;
}
if (arg->val == F_GETFD) {
- syscall_arg__set_ret_scnprintf(arg, fcntl__scnprintf_getfd);
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getfd);
goto mask_arg;
}
/*
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index 3c20683d8cfb..e359e041dc0e 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -73,7 +73,7 @@ size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
return printed;
}

-static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg)
{
int flags = arg->val;

@@ -82,6 +82,3 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct sy

return open__scnprintf_flags(flags, bf, size);
}
-
-
-#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:45:37 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

Extend 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.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549.1...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/header.c | 75 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 70 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index d5359e3384e3..5e6d4d29a7a3 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -62,6 +62,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;
};
@@ -81,19 +82,52 @@ 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)
+{
+ /* struct perf_event_header::size is u16 */
+ const size_t max_size = 0xffff - sizeof(struct perf_event_header);
+ size_t new_size = ff->size;
+ void *addr;
+
+ if (size + ff->offset > max_size)
+ return -E2BIG;
+
+ while (size > (new_size - ff->offset))
+ new_size <<= 1;
+ new_size = min(max_size, new_size);
+
+ if (ff->size < new_size) {
+ addr = realloc(ff->buf, new_size);
+ if (!addr)
+ return -ENOMEM;
+ ff->buf = addr;
+ ff->size = new_size;
+ }
+
+ 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)
{
@@ -126,7 +160,7 @@ 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);

@@ -135,6 +169,25 @@ static int __do_read(struct feat_fd *ff, void *addr, ssize_t size)
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;
+
+ 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)
{
int ret;
@@ -189,6 +242,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);
}

@@ -203,6 +259,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");
@@ -912,6 +971,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);
@@ -2197,6 +2259,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);
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:45:52 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

As we'll call it from the fcntl cmd scnprintf method, that needs to look
at the cmd to mask the next fcntl argument when it is ignored.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-fzlvkhew5v...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 6 ++----
tools/perf/trace/beauty/beauty.h | 3 +++
2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 431ef70067ed..ef1b1d4ea007 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -331,8 +331,8 @@ struct strarrays {
.entries = array, \
}

-static size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size,
+ struct syscall_arg *arg)
{
struct strarrays *sas = arg->parm;
int i;
@@ -351,8 +351,6 @@ static size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size,
return scnprintf(bf, size, "%d", arg->val);
}

-#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays
-
#if defined(__i386__) || defined(__x86_64__)
/*
* FIXME: Make this available to all arches as soon as the ioctl beautifier
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index cf50be3f17a4..a6348073a6e9 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -15,6 +15,9 @@ struct syscall_arg {
u8 mask;
};

+size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays
+
size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:45:53 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

By attaching the pid beautifier to the args in the F_SETOWN case and to
the syscall return on the F_GETOWN one.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-ea1prtqvao...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/fcntl.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index 254ae435780d..d082fd2e594f 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -34,10 +34,14 @@ size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_ar
syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fd);
goto out;
}
+ if (arg->val == F_GETOWN) {
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_pid);
+ goto mask_arg;
+ }
/*
* Some commands ignore the third fcntl argument, "arg", so mask it
*/
- if (arg->val == F_GETOWN || arg->val == F_GET_SEALS ||
+ if (arg->val == F_GET_SEALS ||
arg->val == F_GETLEASE || arg->val == F_GETSIG) {
mask_arg:
arg->mask |= (1 << 2);
@@ -55,6 +59,9 @@ size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_ar

if (cmd == F_SETFL)
return open__scnprintf_flags(arg->val, bf, size);
+
+ if (cmd == F_SETOWN)
+ return syscall_arg__scnprintf_pid(bf, size, arg);

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:45:54 AM7/19/17
to
From: Shriya <shr...@linux.vnet.ibm.com>

Add support for POWER8+ PVR 004c0100 for Garrison

Signed-off-by: Shriya <shr...@linux.vnet.ibm.com>
Reviewed-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1497853842-11023-1-g...@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/pmu-events/arch/powerpc/mapfile.csv | 1 +
1 file changed, 1 insertion(+)

diff --git a/tools/perf/pmu-events/arch/powerpc/mapfile.csv b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
index e925baa0c30b..f03aec70dfc9 100644
--- a/tools/perf/pmu-events/arch/powerpc/mapfile.csv
+++ b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
@@ -19,3 +19,4 @@
004d0000,1,power8.json,core
004d0100,1,power8.json,core
004d0200,1,power8.json,core
+004c0100,1,power8.json,core
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:45:55 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Instead of having syscall_fmt.{arg_scnprintf,arg_parm}, introduce
struct syscall_arg_fmt and have these two, paving the way for more
state to change the formatting algorithms.

For instance, in the 'fcntl' 'cmd' case it is better not to suppress
it when being zero, showing instead its name "DUPFD".

We had that in an ad-hoc way just for strarrays, but with more involved
cases like fcntl, that can't be done with just a strarray, we'll need
a ".show_zero" arg in the 'cmd' syscall_arg_fmt.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-ch06o2j72z...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 256 +++++++++++++++++++++++----------------------
1 file changed, 133 insertions(+), 123 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 0dedce0ca0bb..32778a621a08 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -582,9 +582,9 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,

#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags

-#define STRARRAY(arg, name, array) \
- .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
- .arg_parm = { [arg] = &strarray__##array, }
+#define STRARRAY(name, array) \
+ { .scnprintf = SCA_STRARRAY, \
+ .parm = &strarray__##array, }

#include "trace/beauty/eventfd.c"
#include "trace/beauty/flock.c"
@@ -601,54 +601,61 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
#include "trace/beauty/socket_type.c"
#include "trace/beauty/waitid_options.c"

+struct syscall_arg_fmt {
+ size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
+ void *parm;
+};
+
static struct syscall_fmt {
const char *name;
const char *alias;
- size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
- void *arg_parm[6];
+ struct syscall_arg_fmt arg[6];
bool errmsg;
bool errpid;
bool timeout;
bool hexret;
} syscall_fmts[] = {
{ .name = "access", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
+ .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
{ .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
- { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
+ { .name = "bpf", .errmsg = true,
+ .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
{ .name = "brk", .hexret = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* brk */ }, }, },
{ .name = "chdir", .errmsg = true, },
{ .name = "chmod", .errmsg = true, },
{ .name = "chroot", .errmsg = true, },
- { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
+ { .name = "clock_gettime", .errmsg = true,
+ .arg = { [0] = STRARRAY(clk_id, clockid), }, },
{ .name = "clone", .errpid = true, },
{ .name = "close", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
{ .name = "connect", .errmsg = true, },
{ .name = "creat", .errmsg = true, },
{ .name = "dup", .errmsg = true, },
{ .name = "dup2", .errmsg = true, },
{ .name = "dup3", .errmsg = true, },
- { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
+ { .name = "epoll_ctl", .errmsg = true,
+ .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, },
{ .name = "eventfd2", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
+ .arg = { [1] = { .scnprintf = SCA_EFD_FLAGS, /* flags */ }, }, },
{ .name = "faccessat", .errmsg = true, },
{ .name = "fadvise64", .errmsg = true, },
{ .name = "fallocate", .errmsg = true, },
{ .name = "fchdir", .errmsg = true, },
{ .name = "fchmod", .errmsg = true, },
{ .name = "fchmodat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
{ .name = "fchown", .errmsg = true, },
{ .name = "fchownat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
{ .name = "fcntl", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_FCNTL_CMD, /* cmd */
- [2] = SCA_FCNTL_ARG, /* arg */ },
- .arg_parm = { [1] = &strarrays__fcntl_cmds_arrays, /* cmd */ }, },
+ .arg = { [1] = { .scnprintf = SCA_FCNTL_CMD, /* cmd */
+ .parm = &strarrays__fcntl_cmds_arrays, /* cmd */ },
+ [2] = { .scnprintf = SCA_FCNTL_ARG, /* arg */ }, }, },
{ .name = "fdatasync", .errmsg = true, },
{ .name = "flock", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
+ .arg = { [1] = { .scnprintf = SCA_FLOCK, /* cmd */ }, }, },
{ .name = "fsetxattr", .errmsg = true, },
{ .name = "fstat", .errmsg = true, .alias = "newfstat", },
{ .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
@@ -656,186 +663,190 @@ static struct syscall_fmt {
{ .name = "fsync", .errmsg = true, },
{ .name = "ftruncate", .errmsg = true, },
{ .name = "futex", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
+ .arg = { [1] = { .scnprintf = SCA_FUTEX_OP, /* op */ }, }, },
{ .name = "futimesat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
{ .name = "getdents", .errmsg = true, },
{ .name = "getdents64", .errmsg = true, },
- { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
+ { .name = "getitimer", .errmsg = true,
+ .arg = { [0] = STRARRAY(which, itimers), }, },
{ .name = "getpid", .errpid = true, },
{ .name = "getpgid", .errpid = true, },
{ .name = "getppid", .errpid = true, },
{ .name = "getrandom", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
- { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
+ .arg = { [2] = { .scnprintf = SCA_GETRANDOM_FLAGS, /* flags */ }, }, },
+ { .name = "getrlimit", .errmsg = true,
+ .arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
{ .name = "getxattr", .errmsg = true, },
- { .name = "inotify_add_watch", .errmsg = true, },
+ { .name = "inotify_add_watch", .errmsg = true, },
{ .name = "ioctl", .errmsg = true,
- .arg_scnprintf = {
+ .arg = {
#if defined(__i386__) || defined(__x86_64__)
/*
* FIXME: Make this available to all arches.
*/
- [1] = SCA_STRHEXARRAY, /* cmd */
- [2] = SCA_HEX, /* arg */ },
- .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
+ [1] = { .scnprintf = SCA_STRHEXARRAY, /* cmd */
+ .parm = &strarray__tioctls, },
+ [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
#else
- [2] = SCA_HEX, /* arg */ }, },
+ [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
#endif
- { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
+ { .name = "keyctl", .errmsg = true,
+ .arg = { [0] = STRARRAY(option, keyctl_options), }, },
{ .name = "kill", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
+ .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
{ .name = "lchown", .errmsg = true, },
{ .name = "lgetxattr", .errmsg = true, },
{ .name = "linkat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
{ .name = "listxattr", .errmsg = true, },
{ .name = "llistxattr", .errmsg = true, },
{ .name = "lremovexattr", .errmsg = true, },
{ .name = "lseek", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
- .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
+ .arg = { [2] = STRARRAY(whence, whences), }, },
{ .name = "lsetxattr", .errmsg = true, },
{ .name = "lstat", .errmsg = true, .alias = "newlstat", },
{ .name = "lsxattr", .errmsg = true, },
{ .name = "madvise", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* start */
- [2] = SCA_MADV_BHV, /* behavior */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
+ [2] = { .scnprintf = SCA_MADV_BHV, /* behavior */ }, }, },
{ .name = "mkdir", .errmsg = true, },
{ .name = "mkdirat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
{ .name = "mknod", .errmsg = true, },
{ .name = "mknodat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
{ .name = "mlock", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
{ .name = "mlockall", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
{ .name = "mmap", .hexret = true,
/* The standard mmap maps to old_mmap on s390x */
#if defined(__s390x__)
.alias = "old_mmap",
#endif
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */
- [2] = SCA_MMAP_PROT, /* prot */
- [3] = SCA_MMAP_FLAGS, /* flags */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
+ [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
+ [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, },
{ .name = "mprotect", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* start */
- [2] = SCA_MMAP_PROT, /* prot */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
+ [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, },
{ .name = "mq_unlink", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FILENAME, /* u_name */ }, }, },
{ .name = "mremap", .hexret = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */
- [3] = SCA_MREMAP_FLAGS, /* flags */
- [4] = SCA_HEX, /* new_addr */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
+ [3] = { .scnprintf = SCA_MREMAP_FLAGS, /* flags */ },
+ [4] = { .scnprintf = SCA_HEX, /* new_addr */ }, }, },
{ .name = "munlock", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
{ .name = "munmap", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
{ .name = "name_to_handle_at", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
{ .name = "newfstatat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
{ .name = "open", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
+ .arg = { [1] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
{ .name = "open_by_handle_at", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
- [2] = SCA_OPEN_FLAGS, /* flags */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
+ [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
{ .name = "openat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
- [2] = SCA_OPEN_FLAGS, /* flags */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
+ [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
{ .name = "perf_event_open", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_INT, /* cpu */
- [3] = SCA_FD, /* group_fd */
- [4] = SCA_PERF_FLAGS, /* flags */ }, },
+ .arg = { [2] = { .scnprintf = SCA_INT, /* cpu */ },
+ [3] = { .scnprintf = SCA_FD, /* group_fd */ },
+ [4] = { .scnprintf = SCA_PERF_FLAGS, /* flags */ }, }, },
{ .name = "pipe2", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
+ .arg = { [1] = { .scnprintf = SCA_PIPE_FLAGS, /* flags */ }, }, },
{ .name = "poll", .errmsg = true, .timeout = true, },
{ .name = "ppoll", .errmsg = true, .timeout = true, },
{ .name = "pread", .errmsg = true, .alias = "pread64", },
{ .name = "preadv", .errmsg = true, .alias = "pread", },
- { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
+ { .name = "prlimit64", .errmsg = true,
+ .arg = { [1] = STRARRAY(resource, rlimit_resources), }, },
{ .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
{ .name = "pwritev", .errmsg = true, },
{ .name = "read", .errmsg = true, },
{ .name = "readlink", .errmsg = true, },
{ .name = "readlinkat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
{ .name = "readv", .errmsg = true, },
{ .name = "recvfrom", .errmsg = true,
- .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+ .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
{ .name = "recvmmsg", .errmsg = true,
- .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+ .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
{ .name = "recvmsg", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
+ .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
{ .name = "removexattr", .errmsg = true, },
{ .name = "renameat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
{ .name = "rmdir", .errmsg = true, },
{ .name = "rt_sigaction", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
- { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
+ .arg = { [0] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
+ { .name = "rt_sigprocmask", .errmsg = true,
+ .arg = { [0] = STRARRAY(how, sighow), }, },
{ .name = "rt_sigqueueinfo", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
+ .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
{ .name = "rt_tgsigqueueinfo", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
+ .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
{ .name = "sched_getattr", .errmsg = true, },
{ .name = "sched_setattr", .errmsg = true, },
{ .name = "sched_setscheduler", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
+ .arg = { [1] = { .scnprintf = SCA_SCHED_POLICY, /* policy */ }, }, },
{ .name = "seccomp", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
- [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
+ .arg = { [0] = { .scnprintf = SCA_SECCOMP_OP, /* op */ },
+ [1] = { .scnprintf = SCA_SECCOMP_FLAGS, /* flags */ }, }, },
{ .name = "select", .errmsg = true, .timeout = true, },
{ .name = "sendmmsg", .errmsg = true,
- .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+ .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
{ .name = "sendmsg", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
+ .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
{ .name = "sendto", .errmsg = true,
- .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+ .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
{ .name = "set_tid_address", .errpid = true, },
- { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
+ { .name = "setitimer", .errmsg = true,
+ .arg = { [0] = STRARRAY(which, itimers), }, },
{ .name = "setpgid", .errmsg = true, },
- { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
+ { .name = "setrlimit", .errmsg = true,
+ .arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
{ .name = "setxattr", .errmsg = true, },
{ .name = "shutdown", .errmsg = true, },
{ .name = "socket", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
- [1] = SCA_SK_TYPE, /* type */ },
- .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
+ .arg = { [0] = STRARRAY(family, socket_families),
+ [1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
{ .name = "socketpair", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
- [1] = SCA_SK_TYPE, /* type */ },
- .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
+ .arg = { [0] = STRARRAY(family, socket_families),
+ [1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
{ .name = "stat", .errmsg = true, .alias = "newstat", },
{ .name = "statfs", .errmsg = true, },
{ .name = "statx", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* flags */
- [2] = SCA_STATX_FLAGS, /* flags */
- [3] = SCA_STATX_MASK, /* mask */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fdat */ },
+ [2] = { .scnprintf = SCA_STATX_FLAGS, /* flags */ } ,
+ [3] = { .scnprintf = SCA_STATX_MASK, /* mask */ }, }, },
{ .name = "swapoff", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
{ .name = "swapon", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
{ .name = "symlinkat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
{ .name = "tgkill", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
+ .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
{ .name = "tkill", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
+ .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
{ .name = "truncate", .errmsg = true, },
{ .name = "uname", .errmsg = true, .alias = "newuname", },
{ .name = "unlinkat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
{ .name = "utime", .errmsg = true, },
{ .name = "utimensat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ }, }, },
{ .name = "utimes", .errmsg = true, },
{ .name = "vmsplice", .errmsg = true, },
{ .name = "wait4", .errpid = true,
- .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
+ .arg = { [2] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
{ .name = "waitid", .errpid = true,
- .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
+ .arg = { [3] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
{ .name = "write", .errmsg = true, },
{ .name = "writev", .errmsg = true, },
};
@@ -859,8 +870,7 @@ struct syscall {
const char *name;
bool is_exit;
struct syscall_fmt *fmt;
- size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
- void **arg_parm;
+ struct syscall_arg_fmt *arg_fmt;
};

/*
@@ -1209,27 +1219,29 @@ static int syscall__set_arg_fmts(struct syscall *sc)
struct format_field *field;
int idx = 0, len;

- sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
- if (sc->arg_scnprintf == NULL)
+ sc->arg_fmt = calloc(sc->nr_args, sizeof(*sc->arg_fmt));
+ if (sc->arg_fmt == NULL)
return -1;

- if (sc->fmt)
- sc->arg_parm = sc->fmt->arg_parm;
+ for (field = sc->args; field; field = field->next, ++idx) {
+ if (sc->fmt) {
+ sc->arg_fmt[idx] = sc->fmt->arg[idx];
+
+ if (sc->fmt->arg[idx].scnprintf)
+ continue;
+ }

- for (field = sc->args; field; field = field->next) {
- if (sc->fmt && sc->fmt->arg_scnprintf[idx])
- sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
- else if (strcmp(field->type, "const char *") == 0 &&
+ if (strcmp(field->type, "const char *") == 0 &&
(strcmp(field->name, "filename") == 0 ||
strcmp(field->name, "path") == 0 ||
strcmp(field->name, "pathname") == 0))
- sc->arg_scnprintf[idx] = SCA_FILENAME;
+ sc->arg_fmt[idx].scnprintf = SCA_FILENAME;
else if (field->flags & FIELD_IS_POINTER)
- sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
+ sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex;
else if (strcmp(field->type, "pid_t") == 0)
- sc->arg_scnprintf[idx] = SCA_PID;
+ sc->arg_fmt[idx].scnprintf = SCA_PID;
else if (strcmp(field->type, "umode_t") == 0)
- sc->arg_scnprintf[idx] = SCA_MODE_T;
+ sc->arg_fmt[idx].scnprintf = SCA_MODE_T;
else if ((strcmp(field->type, "int") == 0 ||
strcmp(field->type, "unsigned int") == 0 ||
strcmp(field->type, "long") == 0) &&
@@ -1242,9 +1254,8 @@ static int syscall__set_arg_fmts(struct syscall *sc)
* 23 unsigned int
* 7 unsigned long
*/
- sc->arg_scnprintf[idx] = SCA_FD;
+ sc->arg_fmt[idx].scnprintf = SCA_FD;
}
- ++idx;
}

return 0;
@@ -1416,20 +1427,19 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
* strarray for it.
*/
if (val == 0 &&
- !(sc->arg_scnprintf &&
- (sc->arg_scnprintf[arg.idx] == SCA_STRARRAY ||
- sc->arg_scnprintf[arg.idx] == SCA_STRARRAYS) &&
- sc->arg_parm[arg.idx]))
+ !(sc->arg_fmt &&
+ (sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAY ||
+ sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAYS) &&
+ sc->arg_fmt[arg.idx].parm))
continue;

printed += scnprintf(bf + printed, size - printed,
"%s%s: ", printed ? ", " : "", field->name);
- if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
+ if (sc->arg_fmt && sc->arg_fmt[arg.idx].scnprintf) {
arg.val = val;
- if (sc->arg_parm)
- arg.parm = sc->arg_parm[arg.idx];
- printed += sc->arg_scnprintf[arg.idx](bf + printed,
- size - printed, &arg);
+ if (sc->arg_fmt[arg.idx].parm)
+ arg.parm = sc->arg_fmt[arg.idx].parm;
+ printed += sc->arg_fmt[arg.idx].scnprintf(bf + printed, size - printed, &arg);
} else {
printed += scnprintf(bf + printed, size - printed,
"%ld", val);
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:46:01 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

As it calls functions in builtin-trace.c.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-bt3lhw1rvy...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/Build b/tools/perf/Build
index bd8eeb60533c..b48ca40fccf9 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -50,6 +50,6 @@ libperf-y += util/
libperf-y += arch/
libperf-y += ui/
libperf-y += scripts/
-libperf-y += trace/beauty/
+libperf-$(CONFIG_AUDIT) += trace/beauty/

gtk-y += ui/gtk/
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:46:05 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

We were getting:

62597.859 ( 0.005 ms): TaskSchedulerF/18107 fcntl(fd: 194, cmd: GETFL) = LARGEFILE|RDWR

Instead of the more familiar (from looking at strace output):

62597.859 ( 0.005 ms): TaskSchedulerF/18107 fcntl(fd: 194, cmd: GETFL) = RDWR|LARGEFILE

Fix it.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-d4d9nd88t4...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/open_flags.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index e520112fdb6e..3c20683d8cfb 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -33,6 +33,7 @@ size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
flags &= ~O_##n; \
}

+ P_FLAG(RDWR);
P_FLAG(APPEND);
P_FLAG(ASYNC);
P_FLAG(CLOEXEC);
@@ -53,7 +54,6 @@ size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
#ifdef O_PATH
P_FLAG(PATH);
#endif
- P_FLAG(RDWR);
#ifdef O_DSYNC
if ((flags & O_SYNC) == O_SYNC)
printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:46:06 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Like will be done with fcntl(fd, F_GETLEASE, F_RDLCK|F_WRLCK|F_UNLCK)

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-3p11bgirtn...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 27 +++++++--------------------
tools/perf/trace/beauty/beauty.h | 20 ++++++++++++++++++++
2 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 65fa0126e939..0dedce0ca0bb 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -283,34 +283,21 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
({ struct syscall_tp *fields = evsel->priv; \
fields->name.pointer(&fields->name, sample); })

-struct strarray {
- int offset;
- int nr_entries;
- const char **entries;
-};
+size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val)
+{
+ int idx = val - sa->offset;

-#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
- .nr_entries = ARRAY_SIZE(array), \
- .entries = array, \
-}
+ if (idx < 0 || idx >= sa->nr_entries)
+ return scnprintf(bf, size, intfmt, val);

-#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
- .offset = off, \
- .nr_entries = ARRAY_SIZE(array), \
- .entries = array, \
+ return scnprintf(bf, size, "%s", sa->entries[idx]);
}

static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
const char *intfmt,
struct syscall_arg *arg)
{
- struct strarray *sa = arg->parm;
- int idx = arg->val - sa->offset;
-
- if (idx < 0 || idx >= sa->nr_entries)
- return scnprintf(bf, size, intfmt, arg->val);
-
- return scnprintf(bf, size, "%s", sa->entries[idx]);
+ return strarray__scnprintf(arg->parm, bf, size, intfmt, arg->val);
}

static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 9ccf0f323fe5..f75ef7d0b303 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -1,8 +1,28 @@
#ifndef _PERF_TRACE_BEAUTY_H
#define _PERF_TRACE_BEAUTY_H

+#include <linux/kernel.h>
#include <linux/types.h>

+struct strarray {
+ int offset;
+ int nr_entries;
+ const char **entries;
+};
+
+#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
+ .nr_entries = ARRAY_SIZE(array), \
+ .entries = array, \
+}
+
+#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
+ .offset = off, \
+ .nr_entries = ARRAY_SIZE(array), \
+ .entries = array, \
+}
+
+size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val);
+
struct trace;
struct thread;

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:46:10 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

Make 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.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549....@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/util.c | 6 ++++--
tools/perf/util/util.h | 2 +-
2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 9e4ea852f636..4c360daa4e24 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -281,6 +281,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);

@@ -308,9 +309,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)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 062dd20437f7..b136c271125f 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -38,7 +38,7 @@ int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi);
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);
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:46:18 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

The initial ones already had that "F_" prefix stripped to make things
shorter, some hadn't, do it now.

We do this to make the 'perf trace' output more compact. At some point
perhaps the best thing to do is to have the tool do this stripping
automatically, letting the user also decide if this is to be done or
not. For now, be consistent.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-2iot106xkl...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4b2a5d298197..cfe1858ed074 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -407,9 +407,9 @@ static DEFINE_STRARRAY(whences);

static const char *fcntl_cmds[] = {
"DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
- "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
- "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
- "F_GETOWNER_UIDS",
+ "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "GETLK64",
+ "SETLK64", "SETLKW64", "SETOWN_EX", "GETOWN_EX",
+ "GETOWNER_UIDS",
};
static DEFINE_STRARRAY(fcntl_cmds);

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:46:23 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

The data_equal name fits better to the return value of the function.
It's true when the data is equal.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py
index bb671cd1d66a..b03261c6b1ed 100644
--- a/tools/perf/tests/attr.py
+++ b/tools/perf/tests/attr.py
@@ -9,7 +9,7 @@ import logging
import shutil
import ConfigParser

-def compare_data(a, b):
+def data_equal(a, b):
# Allow multiple values in assignment separated by '|'
a_list = a.split('|')
b_list = b.split('|')
@@ -101,7 +101,7 @@ class Event(dict):
log.debug(" [%s] %s %s" % (t, self[t], other[t]));
if not self.has_key(t) or not other.has_key(t):
return False
- if not compare_data(self[t], other[t]):
+ if not data_equal(self[t], other[t]):
return False
return True

@@ -109,7 +109,7 @@ class Event(dict):
for t in Event.terms:
if not self.has_key(t) or not other.has_key(t):
continue
- if not compare_data(self[t], other[t]):
+ if not data_equal(self[t], other[t]):
log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))

# Test file description needs to have following sections:
@@ -220,7 +220,7 @@ class Test(object):

log.info(" '%s' ret '%s', expected '%s'" % (cmd, str(ret), str(self.ret)))

- if not compare_data(str(ret), str(self.ret)):
+ if not data_equal(str(ret), str(self.ret)):
raise Unsup(self)

def compare(self, expect, result):
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:46:25 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

Now 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 .

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549....@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
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(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index e9665150e9b1..4baa5329439f 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -304,7 +304,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;

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 8dda19b68ac4..954f0ef8e712 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -75,17 +75,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;
}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d30109b421ee..e98489c8bba7 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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);

/*
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:46:58 AM7/19/17
to
From: David Carrillo-Cisneros <dav...@google.com>

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.

Signed-off-by: David Carrillo-Cisneros <dav...@google.com>
Acked-by: David Ahern <dsa...@gmail.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Masami Hiramatsu <mhir...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Turner <p...@google.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Simon Que <sq...@chromium.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549....@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/header.c | 210 +++++++++++++++++------------------------------
1 file changed, 77 insertions(+), 133 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 76ed7d03e500..24e842c02027 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -119,25 +119,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
@@ -1188,24 +1217,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)
@@ -1227,8 +1247,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)
@@ -1236,16 +1255,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;
@@ -1257,11 +1275,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++;
}
}
@@ -1641,26 +1656,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;
}

@@ -1684,17 +1691,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;
}

@@ -1754,17 +1757,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);
@@ -1799,7 +1797,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;
@@ -1810,13 +1807,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)
@@ -1835,13 +1828,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);

@@ -1868,22 +1857,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");
@@ -1907,18 +1888,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;
@@ -1927,24 +1903,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;
@@ -1968,19 +1935,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;
@@ -1991,10 +1953,8 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
return -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)
@@ -2034,12 +1994,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");
@@ -2055,16 +2012,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);
- }
}

/*
@@ -2137,21 +2089,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;
@@ -2160,10 +2106,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)
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:47:10 AM7/19/17
to
From: Krister Johansen <kj...@templeofstupid.com>

Teaches perf how to place a uprobe on a file that's in a different mount
namespace. The user must add the probe using the --target-ns argument
to perf probe. Once it has been placed, it may be recorded against
without further namespace-specific commands.

Signed-off-by: Krister Johansen <kj...@templeofstupid.com>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Brendan Gregg <brendan...@gmail.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ravi Bangoria <ravi.b...@linux.vnet.ibm.com>
[ PPC build fixed by Ravi: ]
Link: http://lkml.kernel.org/r/1500287542-6219-1-git-s...@linux.vnet.ibm.com
Cc: Thomas-Mich Richter <tmr...@linux.vnet.ibm.com>
[ Fix !HAVE_DWARF_SUPPORT build ]
Link: http://lkml.kernel.org/r/1499305693-1599-4-...@templeofstupid.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/perf-probe.txt | 9 ++++
tools/perf/arch/powerpc/util/sym-handling.c | 2 +-
tools/perf/builtin-probe.c | 43 ++++++++++++++--
tools/perf/util/namespaces.c | 13 +++++
tools/perf/util/namespaces.h | 2 +
tools/perf/util/probe-event.c | 80 +++++++++++++++++++----------
tools/perf/util/probe-event.h | 10 ++--
7 files changed, 125 insertions(+), 34 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 165c2b1d4317..a42aabc2b082 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -130,6 +130,11 @@ OPTIONS
--max-probes=NUM::
Set the maximum number of probe points for an event. Default is 128.

+--target-ns=PID:
+ Obtain mount namespace information from the target pid. This is
+ used when creating a uprobe for a process that resides in a
+ different mount namespace from the perf(1) utility.
+
-x::
--exec=PATH::
Specify path to the executable or shared library file for user
@@ -264,6 +269,10 @@ Add probes at malloc() function on libc

./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc

+Add a uprobe to a target process running in a different mount namespace
+
+ ./perf probe --target-ns <target pid> -x /lib64/libc.so.6 malloc
+
SEE ALSO
--------
linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index bf9a2594572c..9c4e23d8c8ce 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -126,7 +126,7 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
struct rb_node *tmp;
int i = 0;

- map = get_target_map(pev->target, pev->uprobes);
+ map = get_target_map(pev->target, pev->nsi, pev->uprobes);
if (!map || map__load(map) < 0)
return;

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index cf9f9e9c2fc0..3fb98d59cd27 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -58,6 +58,7 @@ static struct {
struct line_range line_range;
char *target;
struct strfilter *filter;
+ struct nsinfo *nsi;
} params;

/* Parse an event definition. Note that any error must die. */
@@ -80,6 +81,9 @@ static int parse_probe_event(const char *str)
params.target_used = true;
}

+ if (params.nsi)
+ pev->nsi = nsinfo__get(params.nsi);
+
/* Parse a perf-probe command into event */
ret = parse_perf_probe_command(str, pev);
pr_debug("%d arguments\n", pev->nargs);
@@ -189,7 +193,7 @@ static int opt_set_target(const struct option *opt, const char *str,

/* Expand given path to absolute path, except for modulename */
if (params.uprobes || strchr(str, '/')) {
- tmp = realpath(str, NULL);
+ tmp = nsinfo__realpath(str, params.nsi);
if (!tmp) {
pr_warning("Failed to get the absolute path of %s: %m\n", str);
return ret;
@@ -208,6 +212,34 @@ static int opt_set_target(const struct option *opt, const char *str,
return ret;
}

+static int opt_set_target_ns(const struct option *opt __maybe_unused,
+ const char *str, int unset __maybe_unused)
+{
+ int ret = -ENOENT;
+ pid_t ns_pid;
+ struct nsinfo *nsip;
+
+ if (str) {
+ errno = 0;
+ ns_pid = (pid_t)strtol(str, NULL, 10);
+ if (errno != 0) {
+ ret = -errno;
+ pr_warning("Failed to parse %s as a pid: %s\n", str,
+ strerror(errno));
+ return ret;
+ }
+ nsip = nsinfo__new(ns_pid);
+ if (nsip && nsip->need_setns)
+ params.nsi = nsinfo__get(nsip);
+ nsinfo__put(nsip);
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+
/* Command option callbacks */

#ifdef HAVE_DWARF_SUPPORT
@@ -299,6 +331,7 @@ static void cleanup_params(void)
line_range__clear(&params.line_range);
free(params.target);
strfilter__delete(params.filter);
+ nsinfo__put(params.nsi);
memset(&params, 0, sizeof(params));
}

@@ -554,6 +587,8 @@ __cmd_probe(int argc, const char **argv)
OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
+ OPT_CALLBACK(0, "target-ns", NULL, "pid",
+ "target pid for namespace contexts", opt_set_target_ns),
OPT_END()
};
int ret;
@@ -634,15 +669,15 @@ __cmd_probe(int argc, const char **argv)
pr_err_with_code(" Error: Failed to show event list.", ret);
return ret;
case 'F':
- ret = show_available_funcs(params.target, params.filter,
- params.uprobes);
+ ret = show_available_funcs(params.target, params.nsi,
+ params.filter, params.uprobes);
if (ret < 0)
pr_err_with_code(" Error: Failed to show functions.", ret);
return ret;
#ifdef HAVE_DWARF_SUPPORT
case 'L':
ret = show_line_range(&params.line_range, params.target,
- params.uprobes);
+ params.nsi, params.uprobes);
if (ret < 0)
pr_err_with_code(" Error: Failed to show lines.", ret);
return ret;
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index fc5f398779a4..a58e91197729 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -11,6 +11,7 @@
#include "event.h"
#include <sys/types.h>
#include <sys/stat.h>
+#include <limits.h>
#include <sched.h>
#include <stdlib.h>
#include <stdio.h>
@@ -233,3 +234,15 @@ void nsinfo__mountns_exit(struct nscookie *nc)
nc->newns = -1;
}
}
+
+char *nsinfo__realpath(const char *path, struct nsinfo *nsi)
+{
+ char *rpath;
+ struct nscookie nsc;
+
+ nsinfo__mountns_enter(nsi, &nsc);
+ rpath = realpath(path, NULL);
+ nsinfo__mountns_exit(&nsc);
+
+ return rpath;
+}
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
index f19aa41119ae..05d82601c9a6 100644
--- a/tools/perf/util/namespaces.h
+++ b/tools/perf/util/namespaces.h
@@ -49,6 +49,8 @@ void nsinfo__put(struct nsinfo *nsi);
void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc);
void nsinfo__mountns_exit(struct nscookie *nc);

+char *nsinfo__realpath(const char *path, struct nsinfo *nsi);
+
static inline void __nsinfo__zput(struct nsinfo **nsip)
{
if (nsip) {
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index a2670e9d652d..a80895a7e611 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -184,13 +184,19 @@ static struct map *kernel_get_module_map(const char *module)
return NULL;
}

-struct map *get_target_map(const char *target, bool user)
+struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user)
{
/* Init maps of given executable or kernel */
- if (user)
- return dso__new_map(target);
- else
+ if (user) {
+ struct map *map;
+
+ map = dso__new_map(target);
+ if (map && map->dso)
+ map->dso->nsinfo = nsinfo__get(nsi);
+ return map;
+ } else {
return kernel_get_module_map(target);
+ }
}

static int convert_exec_to_group(const char *exec, char **result)
@@ -366,7 +372,8 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso)
static int find_alternative_probe_point(struct debuginfo *dinfo,
struct perf_probe_point *pp,
struct perf_probe_point *result,
- const char *target, bool uprobes)
+ const char *target, struct nsinfo *nsi,
+ bool uprobes)
{
struct map *map = NULL;
struct symbol *sym;
@@ -377,7 +384,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
if (!pp->function || pp->file)
return -ENOTSUP;

- map = get_target_map(target, uprobes);
+ map = get_target_map(target, nsi, uprobes);
if (!map)
return -EINVAL;

@@ -421,8 +428,8 @@ static int get_alternative_probe_event(struct debuginfo *dinfo,

memcpy(tmp, &pev->point, sizeof(*tmp));
memset(&pev->point, 0, sizeof(pev->point));
- ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
- pev->target, pev->uprobes);
+ ret = find_alternative_probe_point(dinfo, tmp, &pev->point, pev->target,
+ pev->nsi, pev->uprobes);
if (ret < 0)
memcpy(&pev->point, tmp, sizeof(*tmp));

@@ -444,7 +451,7 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
if (lr->end != INT_MAX)
len = lr->end - lr->start;
ret = find_alternative_probe_point(dinfo, &pp, &result,
- target, user);
+ target, NULL, user);
if (!ret) {
lr->function = result.function;
lr->file = result.file;
@@ -457,12 +464,14 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
}

/* Open new debuginfo of given module */
-static struct debuginfo *open_debuginfo(const char *module, bool silent)
+static struct debuginfo *open_debuginfo(const char *module, struct nsinfo *nsi,
+ bool silent)
{
const char *path = module;
char reason[STRERR_BUFSIZE];
struct debuginfo *ret = NULL;
struct dso *dso = NULL;
+ struct nscookie nsc;
int err;

if (!module || !strchr(module, '/')) {
@@ -480,6 +489,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
}
path = dso->long_name;
}
+ nsinfo__mountns_enter(nsi, &nsc);
ret = debuginfo__new(path);
if (!ret && !silent) {
pr_warning("The %s file has no debug information.\n", path);
@@ -489,6 +499,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
pr_warning("Rebuild with -g, ");
pr_warning("or install an appropriate debuginfo package.\n");
}
+ nsinfo__mountns_exit(&nsc);
return ret;
}

@@ -516,7 +527,7 @@ static struct debuginfo *debuginfo_cache__open(const char *module, bool silent)
goto out;
}

- debuginfo_cache = open_debuginfo(module, silent);
+ debuginfo_cache = open_debuginfo(module, NULL, silent);
if (!debuginfo_cache)
zfree(&debuginfo_cache_path);
out:
@@ -531,14 +542,18 @@ static void debuginfo_cache__exit(void)
}


-static int get_text_start_address(const char *exec, unsigned long *address)
+static int get_text_start_address(const char *exec, unsigned long *address,
+ struct nsinfo *nsi)
{
Elf *elf;
GElf_Ehdr ehdr;
GElf_Shdr shdr;
int fd, ret = -ENOENT;
+ struct nscookie nsc;

+ nsinfo__mountns_enter(nsi, &nsc);
fd = open(exec, O_RDONLY);
+ nsinfo__mountns_exit(&nsc);
if (fd < 0)
return -errno;

@@ -582,7 +597,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
ret = -EINVAL;
goto error;
}
- ret = get_text_start_address(tp->module, &stext);
+ ret = get_text_start_address(tp->module, &stext, NULL);
if (ret < 0)
goto error;
addr += stext;
@@ -659,7 +674,7 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs,

/* Prepare a map for offline binary */
map = dso__new_map(pathname);
- if (!map || get_text_start_address(pathname, &stext) < 0) {
+ if (!map || get_text_start_address(pathname, &stext, NULL) < 0) {
pr_warning("Failed to get ELF symbols for %s\n", pathname);
return -EINVAL;
}
@@ -676,7 +691,8 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
}

static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
- int ntevs, const char *exec)
+ int ntevs, const char *exec,
+ struct nsinfo *nsi)
{
int i, ret = 0;
unsigned long stext = 0;
@@ -684,7 +700,7 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
if (!exec)
return 0;

- ret = get_text_start_address(exec, &stext);
+ ret = get_text_start_address(exec, &stext, nsi);
if (ret < 0)
return ret;

@@ -715,7 +731,7 @@ post_process_module_probe_trace_events(struct probe_trace_event *tevs,
if (!module)
return 0;

- map = get_target_map(module, false);
+ map = get_target_map(module, NULL, false);
if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) {
pr_warning("Failed to get ELF symbols for %s\n", module);
return -EINVAL;
@@ -802,7 +818,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev,
int ret;

if (uprobe)
- ret = add_exec_to_probe_trace_events(tevs, ntevs, module);
+ ret = add_exec_to_probe_trace_events(tevs, ntevs, module,
+ pev->nsi);
else if (module)
/* Currently ref_reloc_sym based probe is not for drivers */
ret = post_process_module_probe_trace_events(tevs, ntevs,
@@ -825,7 +842,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
struct debuginfo *dinfo;
int ntevs, ret = 0;

- dinfo = open_debuginfo(pev->target, !need_dwarf);
+ dinfo = open_debuginfo(pev->target, pev->nsi, !need_dwarf);
if (!dinfo) {
if (need_dwarf)
return -ENOENT;
@@ -945,7 +962,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
char sbuf[STRERR_BUFSIZE];

/* Search a line range */
- dinfo = open_debuginfo(module, false);
+ dinfo = open_debuginfo(module, NULL, false);
if (!dinfo)
return -ENOENT;

@@ -1021,14 +1038,18 @@ static int __show_line_range(struct line_range *lr, const char *module,
return ret;
}

-int show_line_range(struct line_range *lr, const char *module, bool user)
+int show_line_range(struct line_range *lr, const char *module,
+ struct nsinfo *nsi, bool user)
{
int ret;
+ struct nscookie nsc;

ret = init_probe_symbol_maps(user);
if (ret < 0)
return ret;
+ nsinfo__mountns_enter(nsi, &nsc);
ret = __show_line_range(lr, module, user);
+ nsinfo__mountns_exit(&nsc);
exit_probe_symbol_maps();

return ret;
@@ -1111,7 +1132,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
if (ret < 0)
return ret;

- dinfo = open_debuginfo(pevs->target, false);
+ dinfo = open_debuginfo(pevs->target, pevs->nsi, false);
if (!dinfo) {
ret = -ENOENT;
goto out;
@@ -1155,6 +1176,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,

int show_line_range(struct line_range *lr __maybe_unused,
const char *module __maybe_unused,
+ struct nsinfo *nsi __maybe_unused,
bool user __maybe_unused)
{
pr_warning("Debuginfo-analysis is not supported.\n");
@@ -2703,6 +2725,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event *tev = NULL;
struct probe_cache *cache = NULL;
struct strlist *namelist[2] = {NULL, NULL};
+ struct nscookie nsc;

up = pev->uprobes ? 1 : 0;
fd[up] = __open_probe_file_and_namelist(up, &namelist[up]);
@@ -2729,7 +2752,9 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
if (ret < 0)
break;

+ nsinfo__mountns_enter(pev->nsi, &nsc);
ret = probe_file__add_event(fd[up], tev);
+ nsinfo__mountns_exit(&nsc);
if (ret < 0)
break;

@@ -2805,7 +2830,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
int ret, i, j, skipped = 0;
char *mod_name;

- map = get_target_map(pev->target, pev->uprobes);
+ map = get_target_map(pev->target, pev->nsi, pev->uprobes);
if (!map) {
ret = -EINVAL;
goto out;
@@ -3345,13 +3370,16 @@ int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs)
{
int i, j;
+ struct perf_probe_event *pev;

/* Loop 3: cleanup and free trace events */
for (i = 0; i < npevs; i++) {
+ pev = &pevs[i];
for (j = 0; j < pevs[i].ntevs; j++)
clear_probe_trace_event(&pevs[i].tevs[j]);
zfree(&pevs[i].tevs);
pevs[i].ntevs = 0;
+ nsinfo__zput(pev->nsi);
clear_perf_probe_event(&pevs[i]);
}
}
@@ -3409,8 +3437,8 @@ int del_perf_probe_events(struct strfilter *filter)
return ret;
}

-int show_available_funcs(const char *target, struct strfilter *_filter,
- bool user)
+int show_available_funcs(const char *target, struct nsinfo *nsi,
+ struct strfilter *_filter, bool user)
{
struct rb_node *nd;
struct map *map;
@@ -3421,7 +3449,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
return ret;

/* Get a symbol map */
- map = get_target_map(target, user);
+ map = get_target_map(target, nsi, user);
if (!map) {
pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
return -EINVAL;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 5812947418dd..078681d12168 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -4,6 +4,7 @@
#include <linux/compiler.h>
#include <stdbool.h>
#include "intlist.h"
+#include "namespaces.h"

/* Probe related configurations */
struct probe_conf {
@@ -92,6 +93,7 @@ struct perf_probe_event {
struct perf_probe_arg *args; /* Arguments */
struct probe_trace_event *tevs;
int ntevs;
+ struct nsinfo *nsi; /* Target namespace */
};

/* Line range */
@@ -163,10 +165,12 @@ int show_perf_probe_event(const char *group, const char *event,
struct perf_probe_event *pev,
const char *module, bool use_stdout);
int show_perf_probe_events(struct strfilter *filter);
-int show_line_range(struct line_range *lr, const char *module, bool user);
+int show_line_range(struct line_range *lr, const char *module,
+ struct nsinfo *nsi, bool user);
int show_available_vars(struct perf_probe_event *pevs, int npevs,
struct strfilter *filter);
-int show_available_funcs(const char *module, struct strfilter *filter, bool user);
+int show_available_funcs(const char *module, struct nsinfo *nsi,
+ struct strfilter *filter, bool user);
void arch__fix_tev_from_maps(struct perf_probe_event *pev,
struct probe_trace_event *tev, struct map *map,
struct symbol *sym);
@@ -180,7 +184,7 @@ int e_snprintf(char *str, size_t size, const char *format, ...) __printf(3, 4);
int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
struct perf_probe_arg *pvar);

-struct map *get_target_map(const char *target, bool user);
+struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user);

void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
int ntevs);
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:47:17 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

In x86_64 /usr/include/bits/fcntl.h sets it to zero, so just undef it
and use the standard 00100000 value when decoding the open flags arg.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-k28megguz5...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/open_flags.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index 5fb57bed7ea2..e520112fdb6e 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -18,6 +18,9 @@
#define O_TMPFILE 020000000
#endif

+#undef O_LARGEFILE
+#define O_LARGEFILE 00100000
+
size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
{
int printed = 0;
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:47:20 AM7/19/17
to
From: Jin Yao <yao...@linux.intel.com>

Macro fusion merges two instructions to a single micro-op. Intel core
platform performs this hardware optimization under limited
circumstances.

For example, CMP + JCC can be "fused" and executed /retired together.
While with sampling this can result in the sample sometimes being on the
JCC and sometimes on the CMP. So for the fused instruction pair, they
could be considered together.

On Nehalem, fused instruction pairs:

cmp/test + jcc.

On other new CPU:

cmp/test/add/sub/and/inc/dec + jcc.

This patch adds an x86-specific function which checks if 2 instructions
are in a "fused" pair. For non-x86 arch, the function is just NULL.

Changelog:

v4: Move the CPU model checking to symbol__disassemble and save the CPU
family/model in arch structure.

It avoids checking every time when jump arrow printed.

v3: Add checking for Nehalem (CMP, TEST). For other newer Intel CPUs
just check it by default (CMP, TEST, ADD, SUB, AND, INC, DEC).

v2: Remove the original weak function. Arnaldo points out that doing it
as a weak function that will be overridden by the host arch doesn't
work. So now it's implemented as an arch-specific function.

Committer fix:

Do not access evsel->evlist->env->cpuid, ->env can be null, introduce
perf_evsel__env_cpuid(), just like perf_evsel__env_arch(), also used in
this function call.

The original patch was segfaulting 'perf top' + annotation.

But this essentially disables this fused instructions augmentation in
'perf top', the right thing is to get the cpuid from the running kernel,
left for a later patch tho.

Signed-off-by: Yao Jin <yao...@linux.intel.com>
Tested-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Kan Liang <kan....@intel.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1499403995-19857-2-g...@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/arch/x86/annotate/instructions.c | 46 +++++++++++++++++++++++++++++
tools/perf/builtin-top.c | 2 +-
tools/perf/ui/browsers/annotate.c | 4 ++-
tools/perf/ui/gtk/annotate.c | 2 +-
tools/perf/util/annotate.c | 22 ++++++++++++--
tools/perf/util/annotate.h | 3 +-
tools/perf/util/evsel.c | 7 +++++
tools/perf/util/evsel.h | 1 +
8 files changed, 81 insertions(+), 6 deletions(-)

diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c
index c1625f256df3..d84b72063a30 100644
--- a/tools/perf/arch/x86/annotate/instructions.c
+++ b/tools/perf/arch/x86/annotate/instructions.c
@@ -76,3 +76,49 @@ static struct ins x86__instructions[] = {
{ .name = "xbeginq", .ops = &jump_ops, },
{ .name = "retq", .ops = &ret_ops, },
};
+
+static bool x86__ins_is_fused(struct arch *arch, const char *ins1,
+ const char *ins2)
+{
+ if (arch->family != 6 || arch->model < 0x1e || strstr(ins2, "jmp"))
+ return false;
+
+ if (arch->model == 0x1e) {
+ /* Nehalem */
+ if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
+ strstr(ins1, "test")) {
+ return true;
+ }
+ } else {
+ /* Newer platform */
+ if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
+ strstr(ins1, "test") ||
+ strstr(ins1, "add") ||
+ strstr(ins1, "sub") ||
+ strstr(ins1, "and") ||
+ strstr(ins1, "inc") ||
+ strstr(ins1, "dec")) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int x86__cpuid_parse(struct arch *arch, char *cpuid)
+{
+ unsigned int family, model, stepping;
+ int ret;
+
+ /*
+ * cpuid = "GenuineIntel,family,model,stepping"
+ */
+ ret = sscanf(cpuid, "%*[^,],%u,%u,%u", &family, &model, &stepping);
+ if (ret == 3) {
+ arch->family = family;
+ arch->model = model;
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 6052376634c0..022486dc67f5 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -134,7 +134,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
return err;
}

- err = symbol__disassemble(sym, map, NULL, 0, NULL);
+ err = symbol__disassemble(sym, map, NULL, 0, NULL, NULL);
if (err == 0) {
out_assign:
top->sym_filter_entry = he;
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 27f41f28dcb4..c4336138b673 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -9,6 +9,7 @@
#include "../../util/symbol.h"
#include "../../util/evsel.h"
#include "../../util/config.h"
+#include "../../util/evlist.h"
#include <inttypes.h>
#include <pthread.h>
#include <linux/kernel.h>
@@ -1074,7 +1075,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
}

err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
- sizeof_bdl, &browser.arch);
+ sizeof_bdl, &browser.arch,
+ perf_evsel__env_cpuid(evsel));
if (err) {
char msg[BUFSIZ];
symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index d903fd493416..87e3760624f2 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -169,7 +169,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
return -1;

err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
- 0, NULL);
+ 0, NULL, NULL);
if (err) {
char msg[BUFSIZ];
symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index be1caabb9290..8748ebb3f932 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -47,7 +47,12 @@ struct arch {
bool sorted_instructions;
bool initialized;
void *priv;
+ unsigned int model;
+ unsigned int family;
int (*init)(struct arch *arch);
+ bool (*ins_is_fused)(struct arch *arch, const char *ins1,
+ const char *ins2);
+ int (*cpuid_parse)(struct arch *arch, char *cpuid);
struct {
char comment_char;
char skip_functions_char;
@@ -129,6 +134,8 @@ static struct arch architectures[] = {
.name = "x86",
.instructions = x86__instructions,
.nr_instructions = ARRAY_SIZE(x86__instructions),
+ .ins_is_fused = x86__ins_is_fused,
+ .cpuid_parse = x86__cpuid_parse,
.objdump = {
.comment_char = '#',
},
@@ -171,6 +178,14 @@ int ins__scnprintf(struct ins *ins, char *bf, size_t size,
return ins__raw_scnprintf(ins, bf, size, ops);
}

+bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
+{
+ if (!arch || !arch->ins_is_fused)
+ return false;
+
+ return arch->ins_is_fused(arch, ins1, ins2);
+}
+
static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map)
{
char *endptr, *tok, *name;
@@ -1381,7 +1396,7 @@ static const char *annotate__norm_arch(const char *arch_name)

int symbol__disassemble(struct symbol *sym, struct map *map,
const char *arch_name, size_t privsize,
- struct arch **parch)
+ struct arch **parch, char *cpuid)
{
struct dso *dso = map->dso;
char command[PATH_MAX * 2];
@@ -1418,6 +1433,9 @@ int symbol__disassemble(struct symbol *sym, struct map *map,
}
}

+ if (arch->cpuid_parse && cpuid)
+ arch->cpuid_parse(arch, cpuid);
+
pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
symfs_filename, sym->name, map->unmap_ip(map, sym->start),
map->unmap_ip(map, sym->end));
@@ -1907,7 +1925,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
u64 len;

if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
- 0, NULL) < 0)
+ 0, NULL, NULL) < 0)
return -1;

len = symbol__size(sym);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 21055034aedd..72d72728a0fc 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -53,6 +53,7 @@ bool ins__is_jump(const struct ins *ins);
bool ins__is_call(const struct ins *ins);
bool ins__is_ret(const struct ins *ins);
int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
+bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);

struct annotation;

@@ -160,7 +161,7 @@ void symbol__annotate_zero_histograms(struct symbol *sym);

int symbol__disassemble(struct symbol *sym, struct map *map,
const char *arch_name, size_t privsize,
- struct arch **parch);
+ struct arch **parch, char *cpuid);

enum symbol_disassemble_errno {
SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 413f74df08de..0e4cd6092564 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2610,3 +2610,10 @@ char *perf_evsel__env_arch(struct perf_evsel *evsel)
return evsel->evlist->env->arch;
return NULL;
}
+
+char *perf_evsel__env_cpuid(struct perf_evsel *evsel)
+{
+ if (evsel && evsel->evlist && evsel->evlist->env)
+ return evsel->evlist->env->cpuid;
+ return NULL;
+}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d101695c482c..219ad0cdb9f4 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -436,5 +436,6 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
attr__fprintf_f attr__fprintf, void *priv);

char *perf_evsel__env_arch(struct perf_evsel *evsel);
+char *perf_evsel__env_cpuid(struct perf_evsel *evsel);

#endif /* __PERF_EVSEL_H */
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:47:48 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Sometimes it should be printed as an hex number, like with F_SETLK,
F_SETLKW and F_GETLK, that treat 'arg' as a struct flock pointer, in
other cases it is just an integer.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-2gykg6enk7...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 3 ++-
tools/perf/trace/beauty/beauty.h | 3 +++
tools/perf/trace/beauty/fcntl.c | 18 ++++++++++++++++++
3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index a323736043e1..2a894ea7f540 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -660,7 +660,8 @@ static struct syscall_fmt {
{ .name = "fchownat", .errmsg = true,
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
{ .name = "fcntl", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_FCNTL_CMD, /* cmd */ },
+ .arg_scnprintf = { [1] = SCA_FCNTL_CMD, /* cmd */
+ [2] = SCA_FCNTL_ARG, /* arg */ },
.arg_parm = { [1] = &strarrays__fcntl_cmds_arrays, /* cmd */ }, },
{ .name = "fdatasync", .errmsg = true, },
{ .name = "flock", .errmsg = true,
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 61aec19e55ec..d76f903bf2ed 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -43,6 +43,9 @@ size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *ar
size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd

+size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FCNTL_ARG syscall_arg__scnprintf_fcntl_arg
+
size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags

diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index 7e4582c9308e..8a5f58d9eb7c 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -21,3 +21,21 @@ size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_ar

return syscall_arg__scnprintf_strarrays(bf, size, arg);
}
+
+size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg)
+{
+ int cmd = syscall_arg__val(arg, 1);
+
+ /*
+ * We still don't grab the contents of pointers on entry or exit,
+ * so just print them as hex numbers
+ */
+ if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK ||
+ cmd == F_OFD_SETLK || cmd == F_OFD_SETLKW || cmd == F_OFD_GETLK ||
+ cmd == F_GETOWN_EX || cmd == F_SETOWN_EX ||
+ cmd == F_GET_RW_HINT || cmd == F_SET_RW_HINT ||
+ cmd == F_GET_FILE_RW_HINT || cmd == F_SET_FILE_RW_HINT)
+ return syscall_arg__scnprintf_hex(bf, size, arg);
+
+ return syscall_arg__scnprintf_long(bf, size, arg);
+}
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:50:06 AM7/19/17
to
From: Jin Yao <yao...@linux.intel.com>

It is often useful to know the branch types while analyzing branch data.
For example, a call is very different from a conditional branch.

Currently we have to look it up in binary while the binary may later not
be available and even the binary is available but user has to take some
time. It is very useful for user to check it directly in perf report.

Perf already has support for disassembling the branch instruction to get
the x86 branch type.

To keep consistent on kernel and userspace and make the classification
more common, the patch adds the common branch type classification
in perf_event.h.

The patch only defines a minimum but most common set of branch types.

PERF_BR_UNKNOWN : unknown
PERF_BR_COND :conditional
PERF_BR_UNCOND : unconditional
PERF_BR_IND : indirect
PERF_BR_CALL : function call
PERF_BR_IND_CALL : indirect function call
PERF_BR_RET : function return
PERF_BR_SYSCALL : syscall
PERF_BR_SYSRET : syscall return
PERF_BR_COND_CALL : conditional function call
PERF_BR_COND_RET : conditional function return

The patch also adds a new field type (4 bits) in perf_branch_entry
to record the branch type.

Since the disassembling of branch instruction needs some overhead,
a new PERF_SAMPLE_BRANCH_TYPE_SAVE is introduced to indicate if it
needs to disassemble the branch instruction and record the branch
type.

Change log:

v10: Not changed.

v9: Not changed.

v8: Change PERF_BR_NONE to PERF_BR_UNKNOWN.
No other change.

v7: Just keep the most common branch types.
Others are removed.

v6: Not changed.

v5: Not changed. The v5 patch series just change the userspace.

v4: Comparing to previous version, the major changes are:

1. Remove the PERF_BR_JCC_FWD/PERF_BR_JCC_BWD, they will be
computed later in userspace.

2. Remove the "cross" field in perf_branch_entry. The cross page
computing will be done later in userspace.

Signed-off-by: Yao Jin <yao...@linux.intel.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Acked-by: Michael Ellerman <m...@ellerman.id.au>
Acked-by: Peter Zijlstra <pet...@infradead.org>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Kan Liang <kan....@intel.com>
Link: http://lkml.kernel.org/r/1500379995-6449-2-gi...@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
include/uapi/linux/perf_event.h | 27 ++++++++++++++++++++++++++-
tools/include/uapi/linux/perf_event.h | 27 ++++++++++++++++++++++++++-
2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index b1c0b187acfe..642db5fa3286 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -174,6 +174,8 @@ enum perf_branch_sample_type_shift {
PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */
PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */

+ PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 16, /* save branch type */
+
PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
};

@@ -198,9 +200,30 @@ enum perf_branch_sample_type {
PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT,
PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,

+ PERF_SAMPLE_BRANCH_TYPE_SAVE =
+ 1U << PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT,
+
PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
};

+/*
+ * Common flow change classification
+ */
+enum {
+ PERF_BR_UNKNOWN = 0, /* unknown */
+ PERF_BR_COND = 1, /* conditional */
+ PERF_BR_UNCOND = 2, /* unconditional */
+ PERF_BR_IND = 3, /* indirect */
+ PERF_BR_CALL = 4, /* function call */
+ PERF_BR_IND_CALL = 5, /* indirect function call */
+ PERF_BR_RET = 6, /* function return */
+ PERF_BR_SYSCALL = 7, /* syscall */
+ PERF_BR_SYSRET = 8, /* syscall return */
+ PERF_BR_COND_CALL = 9, /* conditional function call */
+ PERF_BR_COND_RET = 10, /* conditional function return */
+ PERF_BR_MAX,
+};
+
#define PERF_SAMPLE_BRANCH_PLM_ALL \
(PERF_SAMPLE_BRANCH_USER|\
PERF_SAMPLE_BRANCH_KERNEL|\
@@ -1015,6 +1038,7 @@ union perf_mem_data_src {
* in_tx: running in a hardware transaction
* abort: aborting a hardware transaction
* cycles: cycles from last branch (or 0 if not supported)
+ * type: branch type
*/
struct perf_branch_entry {
__u64 from;
@@ -1024,7 +1048,8 @@ struct perf_branch_entry {
in_tx:1, /* in transaction */
abort:1, /* transaction abort */
cycles:16, /* cycle count to last branch */
- reserved:44;
+ type:4, /* branch type */
+ reserved:40;
};

#endif /* _UAPI_LINUX_PERF_EVENT_H */
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index b1c0b187acfe..642db5fa3286 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -174,6 +174,8 @@ enum perf_branch_sample_type_shift {
PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */
PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */

+ PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 16, /* save branch type */
+
PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
};

@@ -198,9 +200,30 @@ enum perf_branch_sample_type {
PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT,
PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,

+ PERF_SAMPLE_BRANCH_TYPE_SAVE =
+ 1U << PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT,
+
PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
};

+/*
+ * Common flow change classification
+ */
+enum {
+ PERF_BR_UNKNOWN = 0, /* unknown */
+ PERF_BR_COND = 1, /* conditional */
+ PERF_BR_UNCOND = 2, /* unconditional */
+ PERF_BR_IND = 3, /* indirect */
+ PERF_BR_CALL = 4, /* function call */
+ PERF_BR_IND_CALL = 5, /* indirect function call */
+ PERF_BR_RET = 6, /* function return */
+ PERF_BR_SYSCALL = 7, /* syscall */
+ PERF_BR_SYSRET = 8, /* syscall return */
+ PERF_BR_COND_CALL = 9, /* conditional function call */
+ PERF_BR_COND_RET = 10, /* conditional function return */
+ PERF_BR_MAX,
+};
+
#define PERF_SAMPLE_BRANCH_PLM_ALL \
(PERF_SAMPLE_BRANCH_USER|\
PERF_SAMPLE_BRANCH_KERNEL|\
@@ -1015,6 +1038,7 @@ union perf_mem_data_src {
* in_tx: running in a hardware transaction
* abort: aborting a hardware transaction
* cycles: cycles from last branch (or 0 if not supported)
+ * type: branch type
*/
struct perf_branch_entry {
__u64 from;
@@ -1024,7 +1048,8 @@ struct perf_branch_entry {
in_tx:1, /* in transaction */
abort:1, /* transaction abort */
cycles:16, /* cycle count to last branch */
- reserved:44;
+ type:4, /* branch type */
+ reserved:40;
};

#endif /* _UAPI_LINUX_PERF_EVENT_H */
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:50:07 AM7/19/17
to
From: Krister Johansen <kj...@templeofstupid.com>

Teach perf how to resolve symbols from binaries that are in a different
mount namespace from the tool. This allows perf to generate meaningful
stack traces even if the binary resides in a different mount namespace
from the tool.

Signed-off-by: Krister Johansen <kj...@templeofstupid.com>
Tested-by: Brendan Gregg <brendan...@gmail.com>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Thomas-Mich Richter <tmr...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1499305693-1599-2-...@templeofstupid.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/dso.c | 1 +
tools/perf/util/dso.h | 2 +
tools/perf/util/map.c | 2 +
tools/perf/util/namespaces.c | 127 +++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/namespaces.h | 33 +++++++++++
tools/perf/util/symbol.c | 11 ++++
tools/perf/util/thread.c | 3 +
tools/perf/util/thread.h | 1 +
8 files changed, 180 insertions(+)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 4e7ab611377a..beda40ed63b0 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1236,6 +1236,7 @@ void dso__delete(struct dso *dso)
dso_cache__free(dso);
dso__free_a2l(dso);
zfree(&dso->symsrc_filename);
+ nsinfo__zput(dso->nsinfo);
pthread_mutex_destroy(&dso->lock);
free(dso);
}
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index bd061ba7b47c..78ec637fc68b 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -10,6 +10,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include "map.h"
+#include "namespaces.h"
#include "build-id.h"

enum dso_binary_type {
@@ -187,6 +188,7 @@ struct dso {
void *priv;
u64 db_id;
};
+ struct nsinfo *nsinfo;
refcount_t refcnt;
char name[0];
};
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 2179b2deb730..5dc60ca5a294 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -16,6 +16,7 @@
#include "machine.h"
#include <linux/string.h>
#include "srcline.h"
+#include "namespaces.h"
#include "unwind.h"

static void __maps__insert(struct maps *maps, struct map *map);
@@ -200,6 +201,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
if (type != MAP__FUNCTION)
dso__set_loaded(dso, map->type);
}
+ dso->nsinfo = nsinfo__get(thread->nsinfo);
dso__put(dso);
}
return map;
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index 67dcbcc73c7d..bcc6bb19cf10 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -9,9 +9,13 @@
#include "namespaces.h"
#include "util.h"
#include "event.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sched.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>

struct namespaces *namespaces__new(struct namespaces_event *event)
{
@@ -35,3 +39,126 @@ void namespaces__free(struct namespaces *namespaces)
{
free(namespaces);
}
+
+void nsinfo__init(struct nsinfo *nsi)
+{
+ char oldns[PATH_MAX];
+ char *newns = NULL;
+ struct stat old_stat;
+ struct stat new_stat;
+
+ if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
+ return;
+
+ if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) == -1)
+ return;
+
+ if (stat(oldns, &old_stat) < 0)
+ goto out;
+
+ if (stat(newns, &new_stat) < 0)
+ goto out;
+
+ /* Check if the mount namespaces differ, if so then indicate that we
+ * want to switch as part of looking up dso/map data.
+ */
+ if (old_stat.st_ino != new_stat.st_ino) {
+ nsi->need_setns = true;
+ nsi->mntns_path = newns;
+ newns = NULL;
+ }
+
+out:
+ free(newns);
+}
+
+struct nsinfo *nsinfo__new(pid_t pid)
+{
+ struct nsinfo *nsi = calloc(1, sizeof(*nsi));
+
+ if (nsi != NULL) {
+ nsi->pid = pid;
+ nsi->need_setns = false;
+ nsinfo__init(nsi);
+ refcount_set(&nsi->refcnt, 1);
+ }
+
+ return nsi;
+}
+
+void nsinfo__delete(struct nsinfo *nsi)
+{
+ zfree(&nsi->mntns_path);
+ free(nsi);
+}
+
+struct nsinfo *nsinfo__get(struct nsinfo *nsi)
+{
+ if (nsi)
+ refcount_inc(&nsi->refcnt);
+ return nsi;
+}
+
+void nsinfo__put(struct nsinfo *nsi)
+{
+ if (nsi && refcount_dec_and_test(&nsi->refcnt))
+ nsinfo__delete(nsi);
+}
+
+void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)
+{
+ char curpath[PATH_MAX];
+ int oldns = -1;
+ int newns = -1;
+
+ if (nc == NULL)
+ return;
+
+ nc->oldns = -1;
+ nc->newns = -1;
+
+ if (!nsi || !nsi->need_setns)
+ return;
+
+ if (snprintf(curpath, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
+ return;
+
+ oldns = open(curpath, O_RDONLY);
+ if (oldns < 0)
+ return;
+
+ newns = open(nsi->mntns_path, O_RDONLY);
+ if (newns < 0)
+ goto errout;
+
+ if (setns(newns, CLONE_NEWNS) < 0)
+ goto errout;
+
+ nc->oldns = oldns;
+ nc->newns = newns;
+ return;
+
+errout:
+ if (oldns > -1)
+ close(oldns);
+ if (newns > -1)
+ close(newns);
+}
+
+void nsinfo__mountns_exit(struct nscookie *nc)
+{
+ if (nc == NULL || nc->oldns == -1 || nc->newns == -1)
+ return;
+
+ setns(nc->oldns, CLONE_NEWNS);
+
+ if (nc->oldns > -1) {
+ close(nc->oldns);
+ nc->oldns = -1;
+ }
+
+ if (nc->newns > -1) {
+ close(nc->newns);
+ nc->newns = -1;
+ }
+}
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
index 468f1e9a1484..b20f6ead7b2d 100644
--- a/tools/perf/util/namespaces.h
+++ b/tools/perf/util/namespaces.h
@@ -11,6 +11,7 @@

#include "../perf.h"
#include <linux/list.h>
+#include <linux/refcount.h>

struct namespaces_event;

@@ -23,4 +24,36 @@ struct namespaces {
struct namespaces *namespaces__new(struct namespaces_event *event);
void namespaces__free(struct namespaces *namespaces);

+struct nsinfo {
+ pid_t pid;
+ bool need_setns;
+ char *mntns_path;
+ refcount_t refcnt;
+};
+
+struct nscookie {
+ int oldns;
+ int newns;
+};
+
+void nsinfo__init(struct nsinfo *nsi);
+struct nsinfo *nsinfo__new(pid_t pid);
+void nsinfo__delete(struct nsinfo *nsi);
+
+struct nsinfo *nsinfo__get(struct nsinfo *nsi);
+void nsinfo__put(struct nsinfo *nsi);
+
+void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc);
+void nsinfo__mountns_exit(struct nscookie *nc);
+
+static inline void __nsinfo__zput(struct nsinfo **nsip)
+{
+ if (nsip) {
+ nsinfo__put(*nsip);
+ *nsip = NULL;
+ }
+}
+
+#define nsinfo__zput(nsi) __nsinfo__zput(&nsi)
+
#endif /* __PERF_NAMESPACES_H */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e7a98dbd2aed..60a9eaa372ef 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -18,6 +18,8 @@
#include "symbol.h"
#include "strlist.h"
#include "intlist.h"
+#include "namespaces.h"
+#include "vdso.h"
#include "header.h"
#include "path.h"
#include "sane_ctype.h"
@@ -1436,9 +1438,17 @@ int dso__load(struct dso *dso, struct map *map)
struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
bool kmod;
unsigned char build_id[BUILD_ID_SIZE];
+ struct nscookie nsc;

+ nsinfo__mountns_enter(dso->nsinfo, &nsc);
pthread_mutex_lock(&dso->lock);

+ /* The vdso files always live in the host container, so don't go looking
+ * for them in the container's mount namespace.
+ */
+ if (dso__is_vdso(dso))
+ nsinfo__mountns_exit(&nsc);
+
/* check again under the dso->lock */
if (dso__loaded(dso, map->type)) {
ret = 1;
@@ -1584,6 +1594,7 @@ int dso__load(struct dso *dso, struct map *map)
out:
dso__set_loaded(dso, map->type);
pthread_mutex_unlock(&dso->lock);
+ nsinfo__mountns_exit(&nsc);

return ret;
}
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 378c418ca0c1..aee9a42102ba 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -59,6 +59,8 @@ struct thread *thread__new(pid_t pid, pid_t tid)
list_add(&comm->list, &thread->comm_list);
refcount_set(&thread->refcnt, 1);
RB_CLEAR_NODE(&thread->rb_node);
+ /* Thread holds first ref to nsdata. */
+ thread->nsinfo = nsinfo__new(pid);
}

return thread;
@@ -91,6 +93,7 @@ void thread__delete(struct thread *thread)
comm__free(comm);
}
unwind__finish_access(thread);
+ nsinfo__zput(thread->nsinfo);

free(thread);
}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 4eb849e9098f..cb1a5dd5c2b9 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -34,6 +34,7 @@ struct thread {

void *priv;
struct thread_stack *ts;
+ struct nsinfo *nsinfo;
#ifdef HAVE_LIBUNWIND_SUPPORT
void *addr_space;
struct unwind_libunwind_ops *unwind_libunwind_ops;
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:50:07 AM7/19/17
to
From: Jiri Olsa <jo...@kernel.org>

We create many test events before the real ones just to test specific
features. But there's no way for attr tests to separate those test
events from those it needs to check.

Adding 'ready' call from the events open interface to trigger/start
events collection for attr test.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/perf.h | 1 +
tools/perf/tests/attr.c | 10 ++++++++++
tools/perf/util/evsel.c | 4 ++++
3 files changed, 15 insertions(+)

diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 806c216a1078..2c010dd6a79d 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -7,6 +7,7 @@
#include <linux/perf_event.h>

extern bool test_attr__enabled;
+void test_attr__ready(void);
void test_attr__init(void);
void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
int fd, int group_fd, unsigned long flags);
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 08b1d5ce9020..84c0eb598a67 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -36,6 +36,7 @@
#define ENV "PERF_TEST_ATTR"

static char *dir;
+static bool ready;

void test_attr__init(void)
{
@@ -67,6 +68,9 @@ static int store_event(struct perf_event_attr *attr, pid_t pid, int cpu,
FILE *file;
char path[PATH_MAX];

+ if (!ready)
+ return 0;
+
snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir,
attr->type, attr->config, fd);

@@ -144,6 +148,12 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
errno = errno_saved;
}

+void test_attr__ready(void)
+{
+ if (unlikely(test_attr__enabled) && !ready)
+ ready = true;
+}
+
static int run_dir(const char *d, const char *perf)
{
char v[] = "-vvvvv";
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index df567e478a0e..6dd069a41ac3 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -58,6 +58,8 @@ static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused)
return 0;
}

+void __weak test_attr__ready(void) { }
+
static void perf_evsel__no_extra_fini(struct perf_evsel *evsel __maybe_unused)
{
}
@@ -1572,6 +1574,8 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
pid, cpus->map[cpu], group_fd, flags);

+ test_attr__ready();
+
fd = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu],
group_fd, flags);

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:50:09 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

The 'perf trace' tool is suppressing args set to zero, with the
exception of string tables (strarrays), which are kinda like enums, i.e.
we have maps to go from numbers to strings.

But the 'cmd' fcntl arg requires more specialized treatment, as its
value will regulate if the next fcntl syscall arg, 'arg', should be
ignored (not used) and also how to format the syscall return (fd, file
flags, etc), so add a 'show_zero" bool to struct syscall_arg_fmt, to
regulate this more explicitely.

Will be used in a following patch with fcntl, here is just the
mechanism.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-all738jctx...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 32778a621a08..b842bd93457f 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -604,6 +604,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
struct syscall_arg_fmt {
size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
void *parm;
+ bool show_zero;
};

static struct syscall_fmt {
@@ -1428,7 +1429,8 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
*/
if (val == 0 &&
!(sc->arg_fmt &&
- (sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAY ||
+ (sc->arg_fmt[arg.idx].show_zero ||
+ sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAY ||
sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAYS) &&
sc->arg_fmt[arg.idx].parm))
continue;
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:50:17 AM7/19/17
to
From: Krister Johansen <kj...@templeofstupid.com>

Teach buildid-cache how to add, remove, and update binary objects from
other mount namespaces. Allow probe events tracing binaries in
different namespaces to add their objects to the probe and build-id
caches too. As a handy side effect, this also lets us access SDT probes
in binaries from alternate mount namespaces.

Signed-off-by: Krister Johansen <kj...@templeofstupid.com>
Tested-by: Brendan Gregg <brendan...@gmail.com>
Cc: Alexander Shishkin <alexander...@linux.intel.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Thomas-Mich Richter <tmr...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1499305693-1599-5-...@templeofstupid.com
[ Add util/namespaces.c to tools/perf/util/python-ext-sources, to fix the python binding 'perf test' ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/perf-buildid-cache.txt | 5 +++
tools/perf/Documentation/perf-probe.txt | 5 +++
tools/perf/builtin-buildid-cache.c | 52 ++++++++++++++++++-------
tools/perf/builtin-probe.c | 2 +-
tools/perf/tests/sdt.c | 4 +-
tools/perf/util/build-id.c | 47 ++++++++++++++--------
tools/perf/util/build-id.h | 9 +++--
tools/perf/util/dso.c | 12 +++++-
tools/perf/util/parse-events.c | 2 +-
tools/perf/util/probe-event.c | 6 +--
tools/perf/util/probe-file.c | 19 +++++----
tools/perf/util/probe-file.h | 4 +-
tools/perf/util/python-ext-sources | 1 +
tools/perf/util/symbol.c | 19 ++++++---
tools/perf/util/util.c | 34 +++++++++++++---
tools/perf/util/util.h | 2 +
16 files changed, 160 insertions(+), 63 deletions(-)

diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index 058064db39d2..84681007f80f 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -61,6 +61,11 @@ OPTIONS
--verbose::
Be more verbose.

+--target-ns=PID:
+ Obtain mount namespace information from the target pid. This is
+ used when creating a uprobe for a process that resides in a
+ different mount namespace from the perf(1) utility.
+
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-buildid-list[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index a42aabc2b082..d7e4869905f1 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -273,6 +273,11 @@ Add a uprobe to a target process running in a different mount namespace

./perf probe --target-ns <target pid> -x /lib64/libc.so.6 malloc

+Add a USDT probe to a target process running in a different mount namespace
+
+ ./perf probe --target-ns <target pid> -x /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.121-0.b13.el7_3.x86_64/jre/lib/amd64/server/libjvm.so %sdt_hotspot:thread__sleep__end
+
+
SEE ALSO
--------
linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 9eba7f1add1f..d65bd86bee99 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -14,6 +14,7 @@
#include <unistd.h>
#include "builtin.h"
#include "perf.h"
+#include "namespaces.h"
#include "util/cache.h"
#include "util/debug.h"
#include "util/header.h"
@@ -165,33 +166,41 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
return 0;
}

-static int build_id_cache__add_file(const char *filename)
+static int build_id_cache__add_file(const char *filename, struct nsinfo *nsi)
{
char sbuild_id[SBUILD_ID_SIZE];
u8 build_id[BUILD_ID_SIZE];
int err;
+ struct nscookie nsc;

- if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
+ nsinfo__mountns_enter(nsi, &nsc);
+ err = filename__read_build_id(filename, &build_id, sizeof(build_id));
+ nsinfo__mountns_exit(&nsc);
+ if (err < 0) {
pr_debug("Couldn't read a build-id in %s\n", filename);
return -1;
}

build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
- err = build_id_cache__add_s(sbuild_id, filename,
+ err = build_id_cache__add_s(sbuild_id, filename, nsi,
false, false);
pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
err ? "FAIL" : "Ok");
return err;
}

-static int build_id_cache__remove_file(const char *filename)
+static int build_id_cache__remove_file(const char *filename, struct nsinfo *nsi)
{
u8 build_id[BUILD_ID_SIZE];
char sbuild_id[SBUILD_ID_SIZE];
+ struct nscookie nsc;

int err;

- if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
+ nsinfo__mountns_enter(nsi, &nsc);
+ err = filename__read_build_id(filename, &build_id, sizeof(build_id));
+ nsinfo__mountns_exit(&nsc);
+ if (err < 0) {
pr_debug("Couldn't read a build-id in %s\n", filename);
return -1;
}
@@ -204,13 +213,13 @@ static int build_id_cache__remove_file(const char *filename)
return err;
}

-static int build_id_cache__purge_path(const char *pathname)
+static int build_id_cache__purge_path(const char *pathname, struct nsinfo *nsi)
{
struct strlist *list;
struct str_node *pos;
int err;

- err = build_id_cache__list_build_ids(pathname, &list);
+ err = build_id_cache__list_build_ids(pathname, nsi, &list);
if (err)
goto out;

@@ -256,24 +265,30 @@ static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *f
return 0;
}

-static int build_id_cache__update_file(const char *filename)
+static int build_id_cache__update_file(const char *filename, struct nsinfo *nsi)
{
u8 build_id[BUILD_ID_SIZE];
char sbuild_id[SBUILD_ID_SIZE];
+ struct nscookie nsc;

- int err = 0;
+ int err;

- if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
+ nsinfo__mountns_enter(nsi, &nsc);
+ err = filename__read_build_id(filename, &build_id, sizeof(build_id));
+ nsinfo__mountns_exit(&nsc);
+ if (err < 0) {
pr_debug("Couldn't read a build-id in %s\n", filename);
return -1;
}
+ err = 0;

build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
if (build_id_cache__cached(sbuild_id))
err = build_id_cache__remove_s(sbuild_id);

if (!err)
- err = build_id_cache__add_s(sbuild_id, filename, false, false);
+ err = build_id_cache__add_s(sbuild_id, filename, nsi, false,
+ false);

pr_debug("Updating %s %s: %s\n", sbuild_id, filename,
err ? "FAIL" : "Ok");
@@ -286,6 +301,7 @@ int cmd_buildid_cache(int argc, const char **argv)
struct strlist *list;
struct str_node *pos;
int ret = 0;
+ int ns_id = -1;
bool force = false;
char const *add_name_list_str = NULL,
*remove_name_list_str = NULL,
@@ -299,6 +315,7 @@ int cmd_buildid_cache(int argc, const char **argv)
.mode = PERF_DATA_MODE_READ,
};
struct perf_session *session = NULL;
+ struct nsinfo *nsi = NULL;

const struct option buildid_cache_options[] = {
OPT_STRING('a', "add", &add_name_list_str,
@@ -315,6 +332,7 @@ int cmd_buildid_cache(int argc, const char **argv)
OPT_STRING('u', "update", &update_name_list_str, "file list",
"file(s) to update"),
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
+ OPT_INTEGER(0, "target-ns", &ns_id, "target pid for namespace context"),
OPT_END()
};
const char * const buildid_cache_usage[] = {
@@ -330,6 +348,9 @@ int cmd_buildid_cache(int argc, const char **argv)
!missing_filename && !update_name_list_str))
usage_with_options(buildid_cache_usage, buildid_cache_options);

+ if (ns_id > 0)
+ nsi = nsinfo__new(ns_id);
+
if (missing_filename) {
file.path = missing_filename;
file.force = force;
@@ -348,7 +369,7 @@ int cmd_buildid_cache(int argc, const char **argv)
list = strlist__new(add_name_list_str, NULL);
if (list) {
strlist__for_each_entry(pos, list)
- if (build_id_cache__add_file(pos->s)) {
+ if (build_id_cache__add_file(pos->s, nsi)) {
if (errno == EEXIST) {
pr_debug("%s already in the cache\n",
pos->s);
@@ -366,7 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv)
list = strlist__new(remove_name_list_str, NULL);
if (list) {
strlist__for_each_entry(pos, list)
- if (build_id_cache__remove_file(pos->s)) {
+ if (build_id_cache__remove_file(pos->s, nsi)) {
if (errno == ENOENT) {
pr_debug("%s wasn't in the cache\n",
pos->s);
@@ -384,7 +405,7 @@ int cmd_buildid_cache(int argc, const char **argv)
list = strlist__new(purge_name_list_str, NULL);
if (list) {
strlist__for_each_entry(pos, list)
- if (build_id_cache__purge_path(pos->s)) {
+ if (build_id_cache__purge_path(pos->s, nsi)) {
if (errno == ENOENT) {
pr_debug("%s wasn't in the cache\n",
pos->s);
@@ -405,7 +426,7 @@ int cmd_buildid_cache(int argc, const char **argv)
list = strlist__new(update_name_list_str, NULL);
if (list) {
strlist__for_each_entry(pos, list)
- if (build_id_cache__update_file(pos->s)) {
+ if (build_id_cache__update_file(pos->s, nsi)) {
if (errno == ENOENT) {
pr_debug("%s wasn't in the cache\n",
pos->s);
@@ -424,6 +445,7 @@ int cmd_buildid_cache(int argc, const char **argv)

out:
perf_session__delete(session);
+ nsinfo__zput(nsi);

return ret;
}
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 3fb98d59cd27..c0065923a525 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -416,7 +416,7 @@ static int del_perf_probe_caches(struct strfilter *filter)
}

strlist__for_each_entry(nd, bidlist) {
- cache = probe_cache__new(nd->s);
+ cache = probe_cache__new(nd->s, NULL);
if (!cache)
continue;
if (probe_cache__filter_purge(cache, filter) < 0 ||
diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
index 06eda675ae2c..5abe8cea54e6 100644
--- a/tools/perf/tests/sdt.c
+++ b/tools/perf/tests/sdt.c
@@ -33,7 +33,7 @@ static int build_id_cache__add_file(const char *filename)
}

build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
- err = build_id_cache__add_s(sbuild_id, filename, false, false);
+ err = build_id_cache__add_s(sbuild_id, filename, NULL, false, false);
if (err < 0)
pr_debug("Failed to add build id cache of %s\n", filename);
return err;
@@ -54,7 +54,7 @@ static char *get_self_path(void)
static int search_cached_probe(const char *target,
const char *group, const char *event)
{
- struct probe_cache *cache = probe_cache__new(target);
+ struct probe_cache *cache = probe_cache__new(target, NULL);
int ret = 0;

if (!cache) {
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index e0148b081bdf..f7bfd90a7388 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -534,13 +534,14 @@ char *build_id_cache__complement(const char *incomplete_sbuild_id)
}

char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
- bool is_kallsyms, bool is_vdso)
+ struct nsinfo *nsi, bool is_kallsyms,
+ bool is_vdso)
{
char *realname = (char *)name, *filename;
bool slash = is_kallsyms || is_vdso;

if (!slash) {
- realname = realpath(name, NULL);
+ realname = nsinfo__realpath(name, nsi);
if (!realname)
return NULL;
}
@@ -556,13 +557,13 @@ char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
return filename;
}

-int build_id_cache__list_build_ids(const char *pathname,
+int build_id_cache__list_build_ids(const char *pathname, struct nsinfo *nsi,
struct strlist **result)
{
char *dir_name;
int ret = 0;

- dir_name = build_id_cache__cachedir(NULL, pathname, false, false);
+ dir_name = build_id_cache__cachedir(NULL, pathname, nsi, false, false);
if (!dir_name)
return -ENOMEM;

@@ -576,16 +577,20 @@ int build_id_cache__list_build_ids(const char *pathname,

#if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT)
static int build_id_cache__add_sdt_cache(const char *sbuild_id,
- const char *realname)
+ const char *realname,
+ struct nsinfo *nsi)
{
struct probe_cache *cache;
int ret;
+ struct nscookie nsc;

- cache = probe_cache__new(sbuild_id);
+ cache = probe_cache__new(sbuild_id, nsi);
if (!cache)
return -1;

+ nsinfo__mountns_enter(nsi, &nsc);
ret = probe_cache__scan_sdt(cache, realname);
+ nsinfo__mountns_exit(&nsc);
if (ret >= 0) {
pr_debug4("Found %d SDTs in %s\n", ret, realname);
if (probe_cache__commit(cache) < 0)
@@ -595,11 +600,11 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
return ret;
}
#else
-#define build_id_cache__add_sdt_cache(sbuild_id, realname) (0)
+#define build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) (0)
#endif

int build_id_cache__add_s(const char *sbuild_id, const char *name,
- bool is_kallsyms, bool is_vdso)
+ struct nsinfo *nsi, bool is_kallsyms, bool is_vdso)
{
const size_t size = PATH_MAX;
char *realname = NULL, *filename = NULL, *dir_name = NULL,
@@ -607,13 +612,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
int err = -1;

if (!is_kallsyms) {
- realname = realpath(name, NULL);
+ if (!is_vdso)
+ realname = nsinfo__realpath(name, nsi);
+ else
+ realname = realpath(name, NULL);
if (!realname)
goto out_free;
}

- dir_name = build_id_cache__cachedir(sbuild_id, name,
- is_kallsyms, is_vdso);
+ dir_name = build_id_cache__cachedir(sbuild_id, name, nsi, is_kallsyms,
+ is_vdso);
if (!dir_name)
goto out_free;

@@ -634,7 +642,10 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,

if (access(filename, F_OK)) {
if (is_kallsyms) {
- if (copyfile("/proc/kallsyms", filename))
+ if (copyfile("/proc/kallsyms", filename))
+ goto out_free;
+ } else if (nsi && nsi->need_setns) {
+ if (copyfile_ns(name, filename, nsi))
goto out_free;
} else if (link(realname, filename) && errno != EEXIST &&
copyfile(name, filename))
@@ -657,7 +668,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
err = 0;

/* Update SDT cache : error is just warned */
- if (realname && build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
+ if (realname &&
+ build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) < 0)
pr_debug4("Failed to update/scan SDT cache for %s\n", realname);

out_free:
@@ -670,14 +682,15 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
}

static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
- const char *name, bool is_kallsyms,
- bool is_vdso)
+ const char *name, struct nsinfo *nsi,
+ bool is_kallsyms, bool is_vdso)
{
char sbuild_id[SBUILD_ID_SIZE];

build_id__sprintf(build_id, build_id_size, sbuild_id);

- return build_id_cache__add_s(sbuild_id, name, is_kallsyms, is_vdso);
+ return build_id_cache__add_s(sbuild_id, name, nsi, is_kallsyms,
+ is_vdso);
}

bool build_id_cache__cached(const char *sbuild_id)
@@ -743,7 +756,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine)
name = nm;
}
return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
- is_kallsyms, is_vdso);
+ dso->nsinfo, is_kallsyms, is_vdso);
}

static int __dsos__cache_build_ids(struct list_head *head,
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 96690a55c62c..23970847d4c4 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -5,6 +5,7 @@
#define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1)

#include "tool.h"
+#include "namespaces.h"
#include <linux/types.h>

extern struct perf_tool build_id__mark_dso_hit_ops;
@@ -31,17 +32,19 @@ int perf_session__cache_build_ids(struct perf_session *session);
char *build_id_cache__origname(const char *sbuild_id);
char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
- bool is_kallsyms, bool is_vdso);
+ struct nsinfo *nsi, bool is_kallsyms,
+ bool is_vdso);

struct strlist;

struct strlist *build_id_cache__list_all(bool validonly);
char *build_id_cache__complement(const char *incomplete_sbuild_id);
-int build_id_cache__list_build_ids(const char *pathname,
+int build_id_cache__list_build_ids(const char *pathname, struct nsinfo *nsi,
struct strlist **result);
bool build_id_cache__cached(const char *sbuild_id);
int build_id_cache__add_s(const char *sbuild_id,
- const char *name, bool is_kallsyms, bool is_vdso);
+ const char *name, struct nsinfo *nsi,
+ bool is_kallsyms, bool is_vdso);
int build_id_cache__remove_s(const char *sbuild_id);

extern char buildid_dir[];
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index beda40ed63b0..dc9b49533a8f 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -504,7 +504,14 @@ static void check_data_close(void);
*/
static int open_dso(struct dso *dso, struct machine *machine)
{
- int fd = __open_dso(dso, machine);
+ int fd;
+ struct nscookie nsc;
+
+ if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
+ nsinfo__mountns_enter(dso->nsinfo, &nsc);
+ fd = __open_dso(dso, machine);
+ if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
+ nsinfo__mountns_exit(&nsc);

if (fd >= 0) {
dso__list_add(dso);
@@ -1302,6 +1309,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
{
bool have_build_id = false;
struct dso *pos;
+ struct nscookie nsc;

list_for_each_entry(pos, head, node) {
if (with_hits && !pos->hit && !dso__is_vdso(pos))
@@ -1310,11 +1318,13 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
have_build_id = true;
continue;
}
+ nsinfo__mountns_enter(pos->nsinfo, &nsc);
if (filename__read_build_id(pos->long_name, pos->build_id,
sizeof(pos->build_id)) > 0) {
have_build_id = true;
pos->has_build_id = true;
}
+ nsinfo__mountns_exit(&nsc);
}

return have_build_id;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 01e779b91c8e..84e301073885 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -2124,7 +2124,7 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,
return;
}
strlist__for_each_entry(nd, bidlist) {
- pcache = probe_cache__new(nd->s);
+ pcache = probe_cache__new(nd->s, NULL);
if (!pcache)
continue;
list_for_each_entry(ent, &pcache->entries, node) {
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index a80895a7e611..d7cd1142f4c6 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2769,7 +2769,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
if (ret == -EINVAL && pev->uprobes)
warn_uprobe_event_compat(tev);
if (ret == 0 && probe_conf.cache) {
- cache = probe_cache__new(pev->target);
+ cache = probe_cache__new(pev->target, pev->nsi);
if (!cache ||
probe_cache__add_entry(cache, pev, tevs, ntevs) < 0 ||
probe_cache__commit(cache) < 0)
@@ -3119,7 +3119,7 @@ static int find_cached_events(struct perf_probe_event *pev,
int ntevs = 0;
int ret = 0;

- cache = probe_cache__new(target);
+ cache = probe_cache__new(target, pev->nsi);
/* Return 0 ("not found") if the target has no probe cache. */
if (!cache)
return 0;
@@ -3209,7 +3209,7 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
else
return find_cached_events(pev, tevs, pev->target);
}
- cache = probe_cache__new(pev->target);
+ cache = probe_cache__new(pev->target, pev->nsi);
if (!cache)
return 0;

diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index d679389e627c..cdf8d83a484c 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -412,13 +412,15 @@ int probe_cache_entry__get_event(struct probe_cache_entry *entry,
}

/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
-static int probe_cache__open(struct probe_cache *pcache, const char *target)
+static int probe_cache__open(struct probe_cache *pcache, const char *target,
+ struct nsinfo *nsi)
{
char cpath[PATH_MAX];
char sbuildid[SBUILD_ID_SIZE];
char *dir_name = NULL;
bool is_kallsyms = false;
int ret, fd;
+ struct nscookie nsc;

if (target && build_id_cache__cached(target)) {
/* This is a cached buildid */
@@ -431,8 +433,11 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
target = DSO__NAME_KALLSYMS;
is_kallsyms = true;
ret = sysfs__sprintf_build_id("/", sbuildid);
- } else
+ } else {
+ nsinfo__mountns_enter(nsi, &nsc);
ret = filename__sprintf_build_id(target, sbuildid);
+ nsinfo__mountns_exit(&nsc);
+ }

if (ret < 0) {
pr_debug("Failed to get build-id from %s.\n", target);
@@ -441,7 +446,7 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)

/* If we have no buildid cache, make it */
if (!build_id_cache__cached(sbuildid)) {
- ret = build_id_cache__add_s(sbuildid, target,
+ ret = build_id_cache__add_s(sbuildid, target, nsi,
is_kallsyms, NULL);
if (ret < 0) {
pr_debug("Failed to add build-id cache: %s\n", target);
@@ -449,7 +454,7 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
}
}

- dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms,
+ dir_name = build_id_cache__cachedir(sbuildid, target, nsi, is_kallsyms,
false);
found:
if (!dir_name) {
@@ -554,7 +559,7 @@ void probe_cache__delete(struct probe_cache *pcache)
free(pcache);
}

-struct probe_cache *probe_cache__new(const char *target)
+struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi)
{
struct probe_cache *pcache = probe_cache__alloc();
int ret;
@@ -562,7 +567,7 @@ struct probe_cache *probe_cache__new(const char *target)
if (!pcache)
return NULL;

- ret = probe_cache__open(pcache, target);
+ ret = probe_cache__open(pcache, target, nsi);
if (ret < 0) {
pr_debug("Cache open error: %d\n", ret);
goto out_err;
@@ -974,7 +979,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
return -EINVAL;
}
strlist__for_each_entry(nd, bidlist) {
- pcache = probe_cache__new(nd->s);
+ pcache = probe_cache__new(nd->s, NULL);
if (!pcache)
continue;
if (!list_empty(&pcache->entries)) {
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 5ecc9d3925db..2ca4163abafe 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -51,7 +51,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist);
int probe_cache_entry__get_event(struct probe_cache_entry *entry,
struct probe_trace_event **tevs);

-struct probe_cache *probe_cache__new(const char *target);
+struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi);
int probe_cache__add_entry(struct probe_cache *pcache,
struct perf_probe_event *pev,
struct probe_trace_event *tevs, int ntevs);
@@ -69,7 +69,7 @@ int probe_cache__show_all_caches(struct strfilter *filter);
bool probe_type_is_available(enum probe_type type);
bool kretprobe_offset_is_supported(void);
#else /* ! HAVE_LIBELF_SUPPORT */
-static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused)
+static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused, struct nsinfo *nsi __maybe_unused)
{
return NULL;
}
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 9f3b0d9754a8..e66dc495809a 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -10,6 +10,7 @@ util/ctype.c
util/evlist.c
util/evsel.c
util/cpumap.c
+util/namespaces.c
../lib/bitmap.c
../lib/find_bit.c
../lib/hweight.c
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 21c97cc41cfc..8c7bae545617 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1464,7 +1464,6 @@ static int dso__find_perf_map(char *filebuf, size_t bufsz,
return rc;
}

-
int dso__load(struct dso *dso, struct map *map)
{
char *name;
@@ -1565,6 +1564,8 @@ int dso__load(struct dso *dso, struct map *map)
for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) {
struct symsrc *ss = &ss_[ss_pos];
bool next_slot = false;
+ bool is_reg;
+ int sirc;

enum dso_binary_type symtab_type = binary_type_symtab[i];

@@ -1575,12 +1576,20 @@ int dso__load(struct dso *dso, struct map *map)
root_dir, name, PATH_MAX))
continue;

- if (!is_regular_file(name))
- continue;
+ if (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
+ nsinfo__mountns_exit(&nsc);
+
+ is_reg = is_regular_file(name);
+ sirc = symsrc__init(ss, dso, name, symtab_type);

- /* Name is now the name of the next image to try */
- if (symsrc__init(ss, dso, name, symtab_type) < 0)
+ if (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
+ nsinfo__mountns_enter(dso->nsinfo, &nsc);
+
+ if (!is_reg || sirc < 0) {
+ if (sirc >= 0)
+ symsrc__destroy(ss);
continue;
+ }

if (!syms_ss && symsrc__has_symtab(ss)) {
syms_ss = ss;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 988111e0bab5..9e4ea852f636 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -143,13 +143,17 @@ struct strlist *lsdir(const char *name,
return list;
}

-static int slow_copyfile(const char *from, const char *to)
+static int slow_copyfile(const char *from, const char *to, struct nsinfo *nsi)
{
int err = -1;
char *line = NULL;
size_t n;
- FILE *from_fp = fopen(from, "r"), *to_fp;
+ FILE *from_fp, *to_fp;
+ struct nscookie nsc;

+ nsinfo__mountns_enter(nsi, &nsc);
+ from_fp = fopen(from, "r");
+ nsinfo__mountns_exit(&nsc);
if (from_fp == NULL)
goto out;

@@ -198,15 +202,21 @@ int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
return size ? -1 : 0;
}

-int copyfile_mode(const char *from, const char *to, mode_t mode)
+static int copyfile_mode_ns(const char *from, const char *to, mode_t mode,
+ struct nsinfo *nsi)
{
int fromfd, tofd;
struct stat st;
- int err = -1;
+ int err;
char *tmp = NULL, *ptr = NULL;
+ struct nscookie nsc;

- if (stat(from, &st))
+ nsinfo__mountns_enter(nsi, &nsc);
+ err = stat(from, &st);
+ nsinfo__mountns_exit(&nsc);
+ if (err)
goto out;
+ err = -1;

/* extra 'x' at the end is to reserve space for '.' */
if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) {
@@ -227,11 +237,13 @@ int copyfile_mode(const char *from, const char *to, mode_t mode)
goto out_close_to;

if (st.st_size == 0) { /* /proc? do it slowly... */
- err = slow_copyfile(from, tmp);
+ err = slow_copyfile(from, tmp, nsi);
goto out_close_to;
}

+ nsinfo__mountns_enter(nsi, &nsc);
fromfd = open(from, O_RDONLY);
+ nsinfo__mountns_exit(&nsc);
if (fromfd < 0)
goto out_close_to;

@@ -248,6 +260,16 @@ int copyfile_mode(const char *from, const char *to, mode_t mode)
return err;
}

+int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi)
+{
+ return copyfile_mode_ns(from, to, 0755, nsi);
+}
+
+int copyfile_mode(const char *from, const char *to, mode_t mode)
+{
+ return copyfile_mode_ns(from, to, mode, NULL);
+}
+
int copyfile(const char *from, const char *to)
{
return copyfile_mode(from, to, 0755);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 1e5fe1d9ec32..062dd20437f7 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -12,6 +12,7 @@
#include <stdarg.h>
#include <linux/compiler.h>
#include <linux/types.h>
+#include "namespaces.h"

/* General helper functions */
void usage(const char *err) __noreturn;
@@ -33,6 +34,7 @@ struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dire
bool lsdir_no_dot_filter(const char *name, struct dirent *d);
int copyfile(const char *from, const char *to);
int copyfile_mode(const char *from, const char *to, mode_t mode);
+int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi);
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);
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:50:59 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

It can return NULL, in which case we should bail out and remove the
directory created with mkdtemp(), which is stored in the "__tempdir"
variable, not in "tempdir".

Cc: Masami Hiramatsu <mhir...@kernel.org>
Fixes: 8e5dc848356e ("perf test: Add a test case for SDT event")
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/sdt.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
index 5abe8cea54e6..d80171526f6f 100644
--- a/tools/perf/tests/sdt.c
+++ b/tools/perf/tests/sdt.c
@@ -83,6 +83,8 @@ int test__sdt_event(int subtests __maybe_unused)
}
/* Note that buildid_dir must be an absolute path */
tempdir = realpath(__tempdir, NULL);
+ if (tempdir == NULL)
+ goto error_rmdir;

/* At first, scan itself */
set_buildid_dir(tempdir);
@@ -100,7 +102,7 @@ int test__sdt_event(int subtests __maybe_unused)

error_rmdir:
/* Cleanup temporary buildid dir */
- rm_rf(tempdir);
+ rm_rf(__tempdir);
error:
free(tempdir);
free(myself);
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 10:50:59 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

There are cases where we want to leave attr.precise_ip as zero, such
as when using 'perf record --no-samples', where this would make the
kernel return -EINVAL.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-4zq1udecxa...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/evlist.c | 2 +-
tools/perf/util/evsel.c | 7 +++++--
tools/perf/util/evsel.h | 2 +-
3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 46c0faf6c502..f51c3314015c 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -244,7 +244,7 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)

int perf_evlist__add_default(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = perf_evsel__new_cycles();
+ struct perf_evsel *evsel = perf_evsel__new_cycles(true);

if (evsel == NULL)
return -ENOMEM;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 0e4cd6092564..df567e478a0e 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -268,7 +268,7 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
return evsel;
}

-struct perf_evsel *perf_evsel__new_cycles(void)
+struct perf_evsel *perf_evsel__new_cycles(bool precise)
{
struct perf_event_attr attr = {
.type = PERF_TYPE_HARDWARE,
@@ -278,6 +278,9 @@ struct perf_evsel *perf_evsel__new_cycles(void)
struct perf_evsel *evsel;

event_attr_init(&attr);
+
+ if (!precise)
+ goto new_event;
/*
* Unnamed union member, not supported as struct member named
* initializer in older compilers such as gcc 4.4.7
@@ -292,7 +295,7 @@ struct perf_evsel *perf_evsel__new_cycles(void)
* to kick in when we return and before perf_evsel__open() is called.
*/
attr.sample_period = 0;
-
+new_event:
evsel = perf_evsel__new(&attr);
if (evsel == NULL)
goto out;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 219ad0cdb9f4..fb40ca3c6519 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -185,7 +185,7 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *
return perf_evsel__newtp_idx(sys, name, 0);
}

-struct perf_evsel *perf_evsel__new_cycles(void);
+struct perf_evsel *perf_evsel__new_cycles(bool precise);

struct event_format *event_format__new(const char *sys, const char *name);

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 11:00:08 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Result:

0.011 (0.001 ms): Chrome_IOThrea/19863 fcntl(fd: 130</dev/shm/.com.google.Chrome.w5UBtZ (deleted)>, cmd: SETFL, arg: RDWR|APPEND|LARGEFILE) = 0

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-qgf8ggsq9c...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/fcntl.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index 8dcbc30427c9..3456bf4cdb48 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -32,6 +32,8 @@ size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_ar
{
int cmd = syscall_arg__val(arg, 1);

+ if (cmd == F_SETFL)
+ return open__scnprintf_flags(arg->val, bf, size);
/*
* We still don't grab the contents of pointers on entry or exit,
* so just print them as hex numbers
--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 11:00:08 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Now that the beautifiers are being split into multiple source and object
files, we will need more of them exported, do it for the 'fd' one, will
be used to augment the return of some syscalls that may return an 'fd',
such as fcntl(fd, F_DUPFD).

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-39sosu12hh...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 8 +-------
tools/perf/trace/beauty/beauty.h | 3 +++
2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index cfa8bf1cca43..65fa0126e939 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -365,11 +365,6 @@ static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
#endif /* defined(__i386__) || defined(__x86_64__) */

-static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
- struct syscall_arg *arg);
-
-#define SCA_FD syscall_arg__scnprintf_fd
-
#ifndef AT_FDCWD
#define AT_FDCWD -100
#endif
@@ -1057,8 +1052,7 @@ static const char *thread__fd_path(struct thread *thread, int fd,
return ttrace->paths.table[fd];
}

-static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg)
{
int fd = arg->val;
size_t printed = scnprintf(bf, size, "%d", fd);
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index b64c4116cdc4..790e8307fc6a 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -31,6 +31,9 @@ unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx);
size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays

+size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FD syscall_arg__scnprintf_fd
+
size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_HEX syscall_arg__scnprintf_hex

--
2.9.4

Arnaldo Carvalho de Melo

unread,
Jul 19, 2017, 11:00:09 AM7/19/17
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

We'll need defines for beautifying fcntl arguments that are not
available in older distros, these:

trace/beauty/fcntl.c: In function 'syscall_arg__scnprintf_fcntl_arg':
trace/beauty/fcntl.c:93: error: 'F_OFD_SETLK' undeclared (first use in this function)
trace/beauty/fcntl.c:93: error: (Each undeclared identifier is reported only once
trace/beauty/fcntl.c:93: error: for each function it appears in.)
trace/beauty/fcntl.c:93: error: 'F_OFD_SETLKW' undeclared (first use in this function)
trace/beauty/fcntl.c:93: error: 'F_OFD_GETLK' undeclared (first use in this function)
trace/beauty/fcntl.c:94: error: 'F_GETOWN_EX' undeclared (first use in this function)
trace/beauty/fcntl.c:94: error: 'F_SETOWN_EX' undeclared (first use in this function)

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-gvlw67a47e...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/include/uapi/asm-generic/fcntl.h | 220 +++++++++++++++++++++++++++++++++
1 file changed, 220 insertions(+)
create mode 100644 tools/include/uapi/asm-generic/fcntl.h

diff --git a/tools/include/uapi/asm-generic/fcntl.h b/tools/include/uapi/asm-generic/fcntl.h
new file mode 100644
index 000000000000..ac190958c981
--- /dev/null
+++ b/tools/include/uapi/asm-generic/fcntl.h
@@ -0,0 +1,220 @@
+#ifndef _ASM_GENERIC_FCNTL_H
+#define _ASM_GENERIC_FCNTL_H
+
+#include <linux/types.h>
+
+/*
+ * FMODE_EXEC is 0x20
+ * FMODE_NONOTIFY is 0x4000000
+ * These cannot be used by userspace O_* until internal and external open
+ * flags are split.
+ * -Eric Paris
+ */
+
+/*
+ * When introducing new O_* bits, please check its uniqueness in fcntl_init().
+ */
+
+#define O_ACCMODE 00000003
+#define O_RDONLY 00000000
+#define O_WRONLY 00000001
+#define O_RDWR 00000002
+#ifndef O_CREAT
+#define O_CREAT 00000100 /* not fcntl */
+#endif
+#ifndef O_EXCL
+#define O_EXCL 00000200 /* not fcntl */
+#endif
+#ifndef O_NOCTTY
+#define O_NOCTTY 00000400 /* not fcntl */
+#endif
+#ifndef O_TRUNC
+#define O_TRUNC 00001000 /* not fcntl */
+#endif
+#ifndef O_APPEND
+#define O_APPEND 00002000
+#endif
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 00004000
+#endif
+#ifndef O_DSYNC
+#define O_DSYNC 00010000 /* used to be O_SYNC, see below */
+#endif
+#ifndef FASYNC
+#define FASYNC 00020000 /* fcntl, for BSD compatibility */
+#endif
+#ifndef O_DIRECT
+#define O_DIRECT 00040000 /* direct disk access hint */
+#endif
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 00100000
+#endif
+#ifndef O_DIRECTORY
+#define O_DIRECTORY 00200000 /* must be a directory */
+#endif
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 00400000 /* don't follow links */
+#endif
+#ifndef O_NOATIME
+#define O_NOATIME 01000000
+#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 02000000 /* set close_on_exec */
+#endif
+
+/*
+ * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
+ * the O_SYNC flag. We continue to use the existing numerical value
+ * for O_DSYNC semantics now, but using the correct symbolic name for it.
+ * This new value is used to request true Posix O_SYNC semantics. It is
+ * defined in this strange way to make sure applications compiled against
+ * new headers get at least O_DSYNC semantics on older kernels.
+ *
+ * This has the nice side-effect that we can simply test for O_DSYNC
+ * wherever we do not care if O_DSYNC or O_SYNC is used.
+ *
+ * Note: __O_SYNC must never be used directly.
+ */
+#ifndef O_SYNC
+#define __O_SYNC 04000000
+#define O_SYNC (__O_SYNC|O_DSYNC)
+#endif
+
+#ifndef O_PATH
+#define O_PATH 010000000
+#endif
+
+#ifndef __O_TMPFILE
+#define __O_TMPFILE 020000000
+#endif
+
+/* a horrid kludge trying to make sure that this will fail on old kernels */
+#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
+#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT)
+
+#ifndef O_NDELAY
+#define O_NDELAY O_NONBLOCK
+#endif
+
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get close_on_exec */
+#define F_SETFD 2 /* set/clear close_on_exec */
+#define F_GETFL 3 /* get file->f_flags */
+#define F_SETFL 4 /* set file->f_flags */
+#ifndef F_GETLK
+#define F_GETLK 5
+#define F_SETLK 6
+#define F_SETLKW 7
+#endif
+#ifndef F_SETOWN
+#define F_SETOWN 8 /* for sockets. */
+#define F_GETOWN 9 /* for sockets. */
+#endif
+#ifndef F_SETSIG
+#define F_SETSIG 10 /* for sockets. */
+#define F_GETSIG 11 /* for sockets. */
+#endif
+
+#ifndef CONFIG_64BIT
+#ifndef F_GETLK64
+#define F_GETLK64 12 /* using 'struct flock64' */
+#define F_SETLK64 13
+#define F_SETLKW64 14
+#endif
+#endif
+
+#ifndef F_SETOWN_EX
+#define F_SETOWN_EX 15
+#define F_GETOWN_EX 16
+#endif
+
+#ifndef F_GETOWNER_UIDS
+#define F_GETOWNER_UIDS 17
+#endif
+
+/*
+ * Open File Description Locks
+ *
+ * Usually record locks held by a process are released on *any* close and are
+ * not inherited across a fork().
+ *
+ * These cmd values will set locks that conflict with process-associated
+ * record locks, but are "owned" by the open file description, not the
+ * process. This means that they are inherited across fork() like BSD (flock)
+ * locks, and they are only released automatically when the last reference to
+ * the the open file against which they were acquired is put.
+ */
+#define F_OFD_GETLK 36
+#define F_OFD_SETLK 37
+#define F_OFD_SETLKW 38
+
+#define F_OWNER_TID 0
+#define F_OWNER_PID 1
+#define F_OWNER_PGRP 2
+
+struct f_owner_ex {
+ int type;
+ __kernel_pid_t pid;
+};
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#ifndef F_RDLCK
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+#endif
+
+/* for old implementation of bsd flock () */
+#ifndef F_EXLCK
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
+#endif
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+#define LOCK_MAND 32 /* This is a mandatory flock ... */
+#define LOCK_READ 64 /* which allows concurrent read operations */
+#define LOCK_WRITE 128 /* which allows concurrent write operations */
+#define LOCK_RW 192 /* which allows concurrent read & write ops */
+
+#define F_LINUX_SPECIFIC_BASE 1024
+
+#ifndef HAVE_ARCH_STRUCT_FLOCK
+#ifndef __ARCH_FLOCK_PAD
+#define __ARCH_FLOCK_PAD
+#endif
+
+struct flock {
+ short l_type;
+ short l_whence;
+ __kernel_off_t l_start;
+ __kernel_off_t l_len;
+ __kernel_pid_t l_pid;
+ __ARCH_FLOCK_PAD
+};
+#endif
+
+#ifndef HAVE_ARCH_STRUCT_FLOCK64
+#ifndef __ARCH_FLOCK64_PAD
+#define __ARCH_FLOCK64_PAD
+#endif
+
+struct flock64 {
+ short l_type;
+ short l_whence;
+ __kernel_loff_t l_start;
+ __kernel_loff_t l_len;
+ __kernel_pid_t l_pid;
+ __ARCH_FLOCK64_PAD
+};
+#endif
+
+#endif /* _ASM_GENERIC_FCNTL_H */
--
2.9.4

Ingo Molnar

unread,
Jul 20, 2017, 4:40:06 AM7/20/17
to

* Arnaldo Carvalho de Melo <ac...@kernel.org> wrote:

> Hi Ingo,
>
> Unusually big one, please conside pulling, details on the signed tag,
>
> - Arnaldo
>
> Test results at the end of this message, as usual.
>
> The following changes since commit 4b1303d0b01440f224cf81493b7e8e43d9b4965e:
>
> perf symbols: Accept zero as the kernel base address (2017-07-12 11:47:05 -0300)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-4.13-20170718
>
> for you to fetch changes up to b851dd49868e295e18c5d72fc3bad85ff1c444b1:
>
> perf report: Show branch type in callchain entry (2017-07-18 23:14:42 -0300)
>
> ----------------------------------------------------------------
> perf/core improvements and fixes:
>
> User visible:
>
> . Initial support for namespaces, using setns to access files in
> namespaces, grabbing their build-ids, etc. We still need to work
> more to deal with namespaces that vanish before we can get the
> needed data to do analysis, but this should be as good as what is
> in bcc now (Krister Johansen)
>
> . Add header record types to pipe-mode, now this command:
>
> $ perf record -o - -e cycles sleep 1 | perf report --stdio --header
>
> Will show the same as in non-pipe mode, i.e. involving a perf.data
> file (David Carrillo-Cisneros)
>
> . Implement a visual marker for fused x86 instructions in the annotate
> TUI browser, available now in 'perf report', more work needed to have
> it available as well in 'perf top' (Jin Yao)
>
> Further explanation from one of Jin's patches:
>
> │ ┌──cmpl $0x0,argp_program_version_hook
> 81.93 │ ├──je 20
> │ │ lock cmpxchg %esi,0x38a9a4(%rip)
> │ │↓ jne 29
> │ │↓ jmp 43
> 11.47 │20:└─→cmpxch %esi,0x38a999(%rip)
>
> That means the cmpl+je is a fused instruction pair and they should be
> considered together.
>
> . Record the branch type and then show statistics and info about
> in callchain entries (Jin Yao)
>
> Example from one of Jin's patches:
>
> # perf record -g -j any,save_type
> # perf report --branch-history --stdio --no-children
>
> 38.50% div.c:45 [.] main div
> |
> ---main div.c:42 (RET CROSS_2M cycles:2)
> compute_flag div.c:28 (cycles:2)
> compute_flag div.c:27 (RET CROSS_2M cycles:1)
> rand rand.c:28 (cycles:1)
> rand rand.c:28 (RET CROSS_2M cycles:1)
> __random random.c:298 (cycles:1)
> __random random.c:297 (COND_BWD CROSS_2M cycles:1)
> __random random.c:295 (cycles:1)
> __random random.c:295 (COND_BWD CROSS_2M cycles:1)
> __random random.c:295 (cycles:1)
> __random random.c:295 (RET CROSS_2M cycles:9)
>
> . Beautify the fcntl syscall, which is an interesting one in the sense
> that infrastructure had to be put in place to change the formatters of
> some arguments according to the value in a previous one, i.e. cmd
> dictates how arg and the syscall return will be formatted.
> (Arnaldo Carvalho de Melo
>
> Infrastructure:
>
> . 'perf test attr' fixes (Jiri Olsa)
>
> Vendor events:
>
> - Add POWER9 PMU events Sukadev (Bhattiprolu)
>
> - Support additional POWER8+ PVR in PMU mapfile (Shriya)
>
> Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
>
> ----------------------------------------------------------------
> Arnaldo Carvalho de Melo (39):
> perf trace: Remove F_ from some of the fcntl command strings
> perf trace: Beautify linux specific fcntl commands
> tools: Update include/uapi/linux/fcntl.h copy from the kernel
> perf trace beauty: Export the strarrays scnprintf method
> perf trace: Only build tools/perf/trace/beauty/ when building 'perf trace'
> perf trace beauty: Mask ignored fcntl 'arg' parameter
> perf trace beauty: Allow accessing syscall args values in a syscall arg formatter
> perf trace beauty: Export the "int" and "hex" syscall arg formatters
> perf trace beauty: Introduce syscall arg beautifier for long integers
> tools include uapi asm-generic: Grab a copy of fcntl.h
> perf trace beauty fcntl: Basic 'arg' beautifier
> perf trace: Beautify new write hint fcntl commands
> perf beauty open: Detach the syscall_arg agnostic bits from the flags formatter
> perf trace: Allow syscall_arg beautifiers to set a different return formatter
> perf trace beauty open flags: Support O_TMPFILE and O_NOFOLLOW
> perf trace beauty open flags: Do not depend on the system's O_LARGEFILE define
> perf trace beauty fcntl: Beautify F_GETFL return value
> perf trace beauty open flags: Move RDRW to the start of the output
> perf trace beauty fcntl flags: Beautify F_SETFL arg
> perf trace beauty fcntl: Beautify F_[GS]ETFD arg/return value
> perf trace beauty: Give syscall return beautifier more context
> perf trace beauty: Export the fd beautifier for use in more places
> perf trace beauty fcntl: Augment the return of F_DUPFD(_CLOEXEC)
> perf trace beauty: Export the pid beautifier for use in more places
> perf trace beauty fcntl: Beautify F_GETOWN and F_SETOWN
> tools include uapi x86: Grab a copy of unistd.h
> tools include uapi x86: Add __NR_setns, if missing
> tools build: Add test for setns()
> perf evsel: Allow asking for max precise_ip in new_cycles()
> perf evlist: Allow asking for max precise_ip in add_default()
> perf record: Do not ask for precise_ip with --no-samples
> perf test sdt: Handle realpath() failure
> perf trace beauty: Export strarray for use in per-object beautifiers
> perf trace beauty fcntl: Beautify F_GETLEASE and F_SETLEASE arg/return
> perf trace: Group per syscall arg formatter info into one struct
> perf trace: Allow syscall arg formatters to request non suppression of zeros
> perf trace beauty fcntl: Do not suppress 'cmd' when zero, should be DUPFD
> perf trace beauty fcntl: Beautify the 'arg' for DUPFD
> perf trace beauty: Simplify syscall return formatting
>
> 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
>
> Jin Yao (10):
> perf annotate: Check for fused instructions
> perf annotate: Implement visual marker for macro fusion
> perf report: Enable finding kernel inline functions
> perf/core: Define the common branch type classification
> perf/x86/intel: Record branch type
> perf record: Create a new option save_type in --branch-filter
> perf report: Refactor the branch info printing code
> perf util: Create branch.c/.h for common branch functions
> perf report: Show branch type statistics for stdio mode
> perf report: Show branch type in callchain entry
>
> Jiri Olsa (13):
> perf tests attr: Do not store failed events
> perf tests attr: Add test_attr__ready function
> perf tests attr: Make compare_data global
> perf tests attr: Rename compare_data to data_equal
> perf tests attr: Add 1s for exclude_kernel and task base bits
> perf tests attr: Fix record dwarf test
> perf tests attr: Fix no-delay test
> perf tests attr: Add proper return values
> perf tests attr: Fix cpu test disabled term setup
> perf tests attr: Fix sample_period setup
> perf tests attr: Fix precise_ip setup
> perf tests attr: Fix stat sample_type setup
> perf tests attr: Add optional term
>
> Krister Johansen (5):
> perf symbols: Find symbols in different mount namespace
> perf maps: Lookup maps in both intitial mountns and inner mountns.
> perf probe: Allow placing uprobes in alternate namespaces.
> perf buildid-cache: Support binary objects from other namespaces
> perf buildid-cache: Cache debuginfo
>
> Shriya (1):
> perf pmu-events: Support additional POWER8+ PVR in mapfile
>
> Sukadev Bhattiprolu (2):
> perf vendor events: Add POWER9 PMU events
> perf vendor events: Add POWER9 PVRs to mapfile
>
> arch/x86/events/intel/lbr.c | 52 +-
> include/uapi/linux/perf_event.h | 27 +-
> tools/arch/x86/include/asm/unistd_32.h | 3 +
> tools/arch/x86/include/asm/unistd_64.h | 3 +
> tools/arch/x86/include/uapi/asm/unistd.h | 17 +
> tools/build/Makefile.feature | 3 +-
> tools/build/feature/Makefile | 6 +-
> tools/build/feature/test-all.c | 5 +
> tools/build/feature/test-setns.c | 7 +
> tools/include/uapi/asm-generic/fcntl.h | 220 +++++
> tools/include/uapi/linux/fcntl.h | 21 +
> tools/include/uapi/linux/perf_event.h | 27 +-
> tools/perf/Build | 2 +-
> tools/perf/Documentation/perf-buildid-cache.txt | 5 +
> tools/perf/Documentation/perf-probe.txt | 14 +
> tools/perf/Documentation/perf-record.txt | 1 +
> tools/perf/Documentation/perf.data-file-format.txt | 10 +-
> tools/perf/Makefile.config | 5 +
> tools/perf/arch/powerpc/util/sym-handling.c | 2 +-
> tools/perf/arch/x86/annotate/instructions.c | 46 +
> tools/perf/builtin-annotate.c | 1 +
> tools/perf/builtin-buildid-cache.c | 54 +-
> tools/perf/builtin-inject.c | 1 +
> tools/perf/builtin-probe.c | 45 +-
> tools/perf/builtin-record.c | 9 +-
> tools/perf/builtin-report.c | 30 +
> tools/perf/builtin-script.c | 4 +
> tools/perf/builtin-top.c | 2 +-
> tools/perf/builtin-trace.c | 602 ++++++------
> tools/perf/check-headers.sh | 1 +
> tools/perf/perf.h | 1 +
> tools/perf/pmu-events/arch/powerpc/mapfile.csv | 4 +
> .../perf/pmu-events/arch/powerpc/power9/cache.json | 176 ++++
> .../arch/powerpc/power9/floating-point.json | 44 +
> .../pmu-events/arch/powerpc/power9/frontend.json | 446 +++++++++
> .../pmu-events/arch/powerpc/power9/marked.json | 782 +++++++++++++++
> .../pmu-events/arch/powerpc/power9/memory.json | 158 +++
> .../perf/pmu-events/arch/powerpc/power9/other.json | 836 ++++++++++++++++
> .../pmu-events/arch/powerpc/power9/pipeline.json | 680 +++++++++++++
> tools/perf/pmu-events/arch/powerpc/power9/pmc.json | 146 +++
> .../arch/powerpc/power9/translation.json | 272 ++++++
> tools/perf/tests/attr.c | 12 +-
> tools/perf/tests/attr.py | 50 +-
> tools/perf/tests/attr/base-record | 6 +-
> tools/perf/tests/attr/base-stat | 4 +-
> tools/perf/tests/attr/test-record-C0 | 1 +
> tools/perf/tests/attr/test-record-basic | 1 +
> tools/perf/tests/attr/test-record-branch-any | 2 +-
> .../perf/tests/attr/test-record-branch-filter-any | 2 +-
> .../tests/attr/test-record-branch-filter-any_call | 2 +-
> .../tests/attr/test-record-branch-filter-any_ret | 2 +-
> tools/perf/tests/attr/test-record-branch-filter-hv | 2 +-
> .../tests/attr/test-record-branch-filter-ind_call | 2 +-
> tools/perf/tests/attr/test-record-branch-filter-k | 2 +-
> tools/perf/tests/attr/test-record-branch-filter-u | 2 +-
> tools/perf/tests/attr/test-record-count | 1 +
> tools/perf/tests/attr/test-record-data | 3 +-
> tools/perf/tests/attr/test-record-freq | 1 +
> tools/perf/tests/attr/test-record-graph-default | 1 +
> tools/perf/tests/attr/test-record-graph-dwarf | 4 +-
> tools/perf/tests/attr/test-record-graph-fp | 1 +
> tools/perf/tests/attr/test-record-group | 1 +
> tools/perf/tests/attr/test-record-group-sampling | 1 +
> tools/perf/tests/attr/test-record-group1 | 1 +
> ...st-record-no-delay => test-record-no-buffering} | 4 +-
> tools/perf/tests/attr/test-record-no-inherit | 1 +
> tools/perf/tests/attr/test-record-no-samples | 1 +
> tools/perf/tests/attr/test-record-period | 1 +
> tools/perf/tests/attr/test-record-raw | 2 +-
> tools/perf/tests/attr/test-stat-C0 | 4 +-
> tools/perf/tests/attr/test-stat-default | 2 +
> tools/perf/tests/attr/test-stat-detailed-1 | 2 +
> tools/perf/tests/attr/test-stat-detailed-2 | 3 +
> tools/perf/tests/attr/test-stat-detailed-3 | 5 +
> tools/perf/tests/sdt.c | 8 +-
> tools/perf/trace/beauty/Build | 1 +
> tools/perf/trace/beauty/beauty.h | 65 ++
> tools/perf/trace/beauty/fcntl.c | 100 ++
> tools/perf/trace/beauty/open_flags.c | 29 +-
> tools/perf/trace/beauty/pid.c | 4 +-
> tools/perf/ui/browser.c | 29 +
> tools/perf/ui/browser.h | 2 +
> tools/perf/ui/browsers/annotate.c | 30 +-
> tools/perf/ui/browsers/hists.c | 3 -
> tools/perf/ui/gtk/annotate.c | 2 +-
> tools/perf/ui/stdio/hist.c | 3 -
> tools/perf/util/Build | 5 +
> tools/perf/util/annotate.c | 29 +-
> tools/perf/util/annotate.h | 4 +-
> tools/perf/util/branch.c | 147 +++
> tools/perf/util/branch.h | 24 +
> tools/perf/util/build-id.c | 129 ++-
> tools/perf/util/build-id.h | 16 +-
> tools/perf/util/callchain.c | 134 +--
> tools/perf/util/callchain.h | 5 +-
> tools/perf/util/dso.c | 21 +-
> tools/perf/util/dso.h | 3 +
> tools/perf/util/event.c | 1 +
> tools/perf/util/event.h | 11 +-
> tools/perf/util/evlist.c | 4 +-
> tools/perf/util/evlist.h | 9 +-
> tools/perf/util/evsel.c | 18 +-
> tools/perf/util/evsel.h | 3 +-
> tools/perf/util/header.c | 1015 +++++++++++---------
> tools/perf/util/header.h | 16 +-
> tools/perf/util/hist.c | 5 +-
> tools/perf/util/machine.c | 33 +-
> tools/perf/util/map.c | 23 +-
> tools/perf/util/map.h | 2 +-
> tools/perf/util/namespaces.c | 211 ++++
> tools/perf/util/namespaces.h | 38 +
> tools/perf/util/parse-branch-options.c | 1 +
> tools/perf/util/parse-events.c | 2 +-
> tools/perf/util/probe-event.c | 86 +-
> tools/perf/util/probe-event.h | 10 +-
> tools/perf/util/probe-file.c | 19 +-
> tools/perf/util/probe-file.h | 4 +-
> tools/perf/util/python-ext-sources | 1 +
> tools/perf/util/session.c | 4 +
> tools/perf/util/setns.c | 8 +
> tools/perf/util/symbol.c | 92 +-
> tools/perf/util/thread.c | 3 +
> tools/perf/util/thread.h | 1 +
> tools/perf/util/tool.h | 10 +-
> tools/perf/util/util.c | 40 +-
> tools/perf/util/util.h | 8 +-
> 126 files changed, 6339 insertions(+), 1031 deletions(-)
> create mode 100644 tools/arch/x86/include/uapi/asm/unistd.h
> create mode 100644 tools/build/feature/test-setns.c
> create mode 100644 tools/include/uapi/asm-generic/fcntl.h
> create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/cache.json
> create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/floating-point.json
> create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/frontend.json
> create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/marked.json
> create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/memory.json
> create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/other.json
> create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
> create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/pmc.json
> create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/translation.json
> rename tools/perf/tests/attr/{test-record-no-delay => test-record-no-buffering} (61%)
> create mode 100644 tools/perf/trace/beauty/fcntl.c
> create mode 100644 tools/perf/util/branch.c
> create mode 100644 tools/perf/util/branch.h
> create mode 100644 tools/perf/util/setns.c

Pulled, thanks a lot Arnaldo!

Ingo

tip-bot for Sukadev Bhattiprolu

unread,
Jul 20, 2017, 4:50:07 AM7/20/17
to
Commit-ID: 80e63ffb09a1b7ac645e9dd1c16b7b08956a7f5b
Gitweb: http://git.kernel.org/tip/80e63ffb09a1b7ac645e9dd1c16b7b08956a7f5b
Author: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>
AuthorDate: Tue, 11 Jul 2017 13:00:31 -0500
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:14:06 -0300

perf vendor events: Add POWER9 PVRs to mapfile

Add currently supported POWER9 PVRs to the mapfile

Signed-off-by: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>
Cc: Andi Kleen <an...@firstfloor.org>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Shriya <shr...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/n/tip-k1pe02sn5g...@git.kernel.org
[ Fix conflict with a87006fd5629 ("perf pmu-events: Support additional POWER8+ PVR in mapfile") ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/pmu-events/arch/powerpc/mapfile.csv | 3 +++
1 file changed, 3 insertions(+)

diff --git a/tools/perf/pmu-events/arch/powerpc/mapfile.csv b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
index f03aec7..14318ef2 100644
--- a/tools/perf/pmu-events/arch/powerpc/mapfile.csv
+++ b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
@@ -20,3 +20,6 @@
004d0100,1,power8.json,core
004d0200,1,power8.json,core
004c0100,1,power8.json,core
+004e0100,1,power9.json,core
+004e0200,1,power9.json,core
+004e1200,1,power9.json,core

tip-bot for Arnaldo Carvalho de Melo

unread,
Jul 20, 2017, 4:50:07 AM7/20/17
to
Commit-ID: ff2f1b2d35aeb672200af4772db1847fdcdfd77b
Gitweb: http://git.kernel.org/tip/ff2f1b2d35aeb672200af4772db1847fdcdfd77b
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Fri, 14 Jul 2017 15:21:40 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:14:04 -0300

perf trace beauty: Export the pid beautifier for use in more places

Now that the beautifiers are being split into multiple source and object
files, we will need more of them exported, do it for the 'pid' one, will
be used to augment the return of some syscalls that may return a 'pid',
such as fcntl(fd, F_GETOWN).

Will also be used for fcntl(fd, F_SETOWN, pid).

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-7gr5nt9p5s...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/beauty.h | 3 +++
tools/perf/trace/beauty/pid.c | 4 +---
2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 790e830..9ccf0f3 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -43,6 +43,9 @@ size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg
size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_LONG syscall_arg__scnprintf_long

+size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_PID syscall_arg__scnprintf_pid
+
size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd

diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c
index 07486ea..b6d419e 100644
--- a/tools/perf/trace/beauty/pid.c
+++ b/tools/perf/trace/beauty/pid.c
@@ -1,4 +1,4 @@
-static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
{
int pid = arg->val;
struct trace *trace = arg->trace;
@@ -17,5 +17,3 @@ static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_a

return printed;
}
-
-#define SCA_PID syscall_arg__scnprintf_pid

tip-bot for Arnaldo Carvalho de Melo

unread,
Jul 20, 2017, 4:50:07 AM7/20/17
to
Commit-ID: 6b3d5c97dbbc2a8e1f8d7e7d87b8c6637293e803
Gitweb: http://git.kernel.org/tip/6b3d5c97dbbc2a8e1f8d7e7d87b8c6637293e803
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Fri, 14 Jul 2017 11:57:28 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:13:58 -0300

perf trace beauty open flags: Support O_TMPFILE and O_NOFOLLOW

The open syscall flags beautifier wasn't considering those flags, fix
it.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-ukzoldh4ar...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/trace/beauty/open_flags.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index b3c7f11..5fb57be 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -14,6 +14,10 @@
#define O_NOATIME 01000000
#endif

+#ifndef O_TMPFILE
+#define O_TMPFILE 020000000
+#endif
+
size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
{
int printed = 0;
@@ -34,6 +38,8 @@ size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
P_FLAG(DIRECTORY);
P_FLAG(EXCL);
P_FLAG(LARGEFILE);
+ P_FLAG(NOFOLLOW);
+ P_FLAG(TMPFILE);
P_FLAG(NOATIME);
P_FLAG(NOCTTY);
#ifdef O_NONBLOCK

tip-bot for Arnaldo Carvalho de Melo

unread,
Jul 20, 2017, 4:50:07 AM7/20/17
to
Commit-ID: 9cb7cf86440229fd6e6ad1718712742c344653d8
Gitweb: http://git.kernel.org/tip/9cb7cf86440229fd6e6ad1718712742c344653d8
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Fri, 14 Jul 2017 09:44:50 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:13:52 -0300

perf trace beauty: Mask ignored fcntl 'arg' parameter

A series of fcntl cmds ignore the third argument, so mask it.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-6vtl3zq1ta...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 2 +-
tools/perf/trace/beauty/Build | 1 +
tools/perf/trace/beauty/beauty.h | 3 +++
tools/perf/trace/beauty/fcntl.c | 23 +++++++++++++++++++++++
4 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index ef1b1d4..b7f79de 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -661,7 +661,7 @@ static struct syscall_fmt {
{ .name = "fchownat", .errmsg = true,
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
{ .name = "fcntl", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_STRARRAYS, /* cmd */ },
+ .arg_scnprintf = { [1] = SCA_FCNTL_CMD, /* cmd */ },
.arg_parm = { [1] = &strarrays__fcntl_cmds_arrays, /* cmd */ }, },
{ .name = "fdatasync", .errmsg = true, },
{ .name = "flock", .errmsg = true,
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index be95ac6..c9e215b 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -1 +1,2 @@
+libperf-y += fcntl.o
libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index a634807..ce01079 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -18,6 +18,9 @@ struct syscall_arg {
size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays

+size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd
+
size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags

diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
new file mode 100644
index 0000000..7e4582c
--- /dev/null
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -0,0 +1,23 @@
+/*
+ * trace/beauty/fcntl.c
+ *
+ * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <ac...@redhat.com>
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include "trace/beauty/beauty.h"
+#include <uapi/linux/fcntl.h>
+
+size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg)
+{
+ /*
+ * Some commands ignore the third fcntl argument, "arg", so mask it
+ */
+ if (arg->val == F_GETFD || arg->val == F_GETFL ||
+ arg->val == F_GETOWN || arg->val == F_GET_SEALS ||
+ arg->val == F_GETLEASE || arg->val == F_GETSIG)
+ arg->mask |= (1 << 2);
+
+ return syscall_arg__scnprintf_strarrays(bf, size, arg);
+}

tip-bot for Arnaldo Carvalho de Melo

unread,
Jul 20, 2017, 4:50:07 AM7/20/17
to
Commit-ID: 2c2b1623d46ce1f9c0ef5d21ff64a2c3f960e489
Gitweb: http://git.kernel.org/tip/2c2b1623d46ce1f9c0ef5d21ff64a2c3f960e489
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Fri, 14 Jul 2017 10:19:18 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:13:54 -0300

perf trace beauty: Export the "int" and "hex" syscall arg formatters

The most basic ones, for pointers, unaugmented fds, etc, to be used
in the initial fcntl 'arg' beautifier.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-g0lugj4vv6...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 10 ++--------
tools/perf/trace/beauty/beauty.h | 6 ++++++
2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 40bc0a3..9e17140 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -392,22 +392,16 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,

#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd

-static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg)
{
return scnprintf(bf, size, "%#lx", arg->val);
}

-#define SCA_HEX syscall_arg__scnprintf_hex
-
-static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg)
{
return scnprintf(bf, size, "%d", arg->val);
}

-#define SCA_INT syscall_arg__scnprintf_int
-
static const char *bpf_cmd[] = {
"MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
"MAP_GET_NEXT_KEY", "PROG_LOAD",
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 6fbac0c..d085aac 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -31,6 +31,12 @@ unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx);
size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays

+size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_HEX syscall_arg__scnprintf_hex
+
+size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_INT syscall_arg__scnprintf_int
+
size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd

tip-bot for Arnaldo Carvalho de Melo

unread,
Jul 20, 2017, 4:50:07 AM7/20/17
to
Commit-ID: e000e5e33f92f6bb2d24ba2cda143cb6bb872495
Gitweb: http://git.kernel.org/tip/e000e5e33f92f6bb2d24ba2cda143cb6bb872495
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Thu, 13 Jul 2017 13:07:00 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:13:49 -0300

perf trace: Remove F_ from some of the fcntl command strings

The initial ones already had that "F_" prefix stripped to make things
shorter, some hadn't, do it now.

We do this to make the 'perf trace' output more compact. At some point
perhaps the best thing to do is to have the tool do this stripping
automatically, letting the user also decide if this is to be done or
not. For now, be consistent.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-2iot106xkl...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4b2a5d2..cfe1858 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c

tip-bot for Arnaldo Carvalho de Melo

unread,
Jul 20, 2017, 4:50:07 AM7/20/17
to
Commit-ID: 59291f19824200b5a9046b79d37f02fb415335b0
Gitweb: http://git.kernel.org/tip/59291f19824200b5a9046b79d37f02fb415335b0
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Tue, 18 Jul 2017 17:13:40 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:14:07 -0300

tools include uapi x86: Add __NR_setns, if missing

To help us provide a simple setns() in older distros.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Krister Johansen <kj...@templeofstupid.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-o10a85kf6j...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/arch/x86/include/asm/unistd_32.h | 3 +++
tools/arch/x86/include/asm/unistd_64.h | 3 +++
2 files changed, 6 insertions(+)

diff --git a/tools/arch/x86/include/asm/unistd_32.h b/tools/arch/x86/include/asm/unistd_32.h
index 88b3f8c..0e4312ff 100644
--- a/tools/arch/x86/include/asm/unistd_32.h
+++ b/tools/arch/x86/include/asm/unistd_32.h
@@ -10,3 +10,6 @@
#ifndef __NR_getcpu
# define __NR_getcpu 318
#endif
+#ifndef __NR_setns
+# define __NR_setns 346
+#endif
diff --git a/tools/arch/x86/include/asm/unistd_64.h b/tools/arch/x86/include/asm/unistd_64.h
index fbdb70e..dd56bb3 100644
--- a/tools/arch/x86/include/asm/unistd_64.h
+++ b/tools/arch/x86/include/asm/unistd_64.h
@@ -10,3 +10,6 @@
#ifndef __NR_getcpu
# define __NR_getcpu 309
#endif
+#ifndef __NR_setns
+#define __NR_setns 308
+#endif

tip-bot for Arnaldo Carvalho de Melo

unread,
Jul 20, 2017, 4:50:07 AM7/20/17
to
Commit-ID: 047726d1f9ae6b1f3a2144577ffc3a1a92ffedf4
Gitweb: http://git.kernel.org/tip/047726d1f9ae6b1f3a2144577ffc3a1a92ffedf4
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Tue, 18 Jul 2017 17:09:21 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:14:07 -0300

tools include uapi x86: Grab a copy of unistd.h

In older distros we were not including our copies of unistd_{32,64}.h,
as we were relying on the system's asm/unistd.h, and a log time ago
the files to be included were asm-{x86_64,i386}/unistd.h.

Fix it by also carrying a copy of asm/unistd.h, that will be the same
as in modern distros and will allow us to provide missing __NR_setns,
for instance, in older distros.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-iwmgm0c4m1...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
{arch => tools/arch}/x86/include/uapi/asm/unistd.h | 0
tools/perf/check-headers.sh | 1 +
2 files changed, 1 insertion(+)

diff --git a/arch/x86/include/uapi/asm/unistd.h b/tools/arch/x86/include/uapi/asm/unistd.h
similarity index 100%
copy from arch/x86/include/uapi/asm/unistd.h
copy to tools/arch/x86/include/uapi/asm/unistd.h
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 83fe220..47abd33 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -16,6 +16,7 @@ arch/x86/include/uapi/asm/perf_regs.h
arch/x86/include/uapi/asm/kvm.h
arch/x86/include/uapi/asm/kvm_perf.h
arch/x86/include/uapi/asm/svm.h
+arch/x86/include/uapi/asm/unistd.h
arch/x86/include/uapi/asm/vmx.h
arch/powerpc/include/uapi/asm/kvm.h
arch/s390/include/uapi/asm/kvm.h

tip-bot for Arnaldo Carvalho de Melo

unread,
Jul 20, 2017, 4:50:08 AM7/20/17
to
Commit-ID: 7ee5743404e3641f3c11792761632a5a7d583587
Gitweb: http://git.kernel.org/tip/7ee5743404e3641f3c11792761632a5a7d583587
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Fri, 14 Jul 2017 15:16:54 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:14:02 -0300

perf trace beauty: Give syscall return beautifier more context

We need the current thread and the trace internal state so that we can
use the fd beautifier to augment syscall returns, so use struct
syscall_arg with some fields that make sense on returns (val, thread,
trace).

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-lqag8e86yb...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 11 ++++++++---
tools/perf/trace/beauty/beauty.h | 5 ++++-
tools/perf/trace/beauty/fcntl.c | 9 +++++++--
tools/perf/trace/beauty/open_flags.c | 5 +----
4 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index d48981c..cfa8bf1 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -918,7 +918,7 @@ struct thread_trace {
unsigned long pfmaj, pfmin;
char *entry_str;
double runtime_ms;
- size_t (*ret_scnprintf)(unsigned long value, char *bf, size_t size);
+ size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
struct {
unsigned long ptr;
short int entry_str_pos;
@@ -971,7 +971,7 @@ fail:


void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
- size_t (*ret_scnprintf)(unsigned long val, char *bf, size_t size))
+ size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg))
{
struct thread_trace *ttrace = thread__priv(arg->thread);

@@ -1726,7 +1726,12 @@ signed_print:
fprintf(trace->output, ") = 0 Timeout");
else if (ttrace->ret_scnprintf) {
char bf[1024];
- ttrace->ret_scnprintf(ret, bf, sizeof(bf));
+ struct syscall_arg arg = {
+ .val = ret,
+ .thread = thread,
+ .trace = trace,
+ };
+ ttrace->ret_scnprintf(bf, sizeof(bf), &arg);
ttrace->ret_scnprintf = NULL;
fprintf(trace->output, ") = %s", bf);
} else if (sc->fmt->hexret)
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index a9613d2..b64c411 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -46,6 +46,9 @@ size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_ar
size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_FCNTL_ARG syscall_arg__scnprintf_fcntl_arg

+size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
+
size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags

@@ -55,6 +58,6 @@ size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_a
size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size);

void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
- size_t (*ret_scnprintf)(unsigned long val, char *bf, size_t size));
+ size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg));

#endif /* _PERF_TRACE_BEAUTY_H */
diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index 384f177..9de80a7 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -15,14 +15,19 @@ static size_t fcntl__scnprintf_getfd(unsigned long val, char *bf, size_t size)
return scnprintf(bf, size, "%s", val ? "CLOEXEC" : "0");
}

+static size_t syscall_arg__scnprintf_fcntl_getfd(char *bf, size_t size, struct syscall_arg *arg)
+{
+ return fcntl__scnprintf_getfd(arg->val, bf, size);
+}
+
size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg)
{
if (arg->val == F_GETFL) {
- syscall_arg__set_ret_scnprintf(arg, open__scnprintf_flags);
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_open_flags);
goto mask_arg;
}
if (arg->val == F_GETFD) {
- syscall_arg__set_ret_scnprintf(arg, fcntl__scnprintf_getfd);
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getfd);
goto mask_arg;
}
/*
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index 3c20683..e359e04 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -73,7 +73,7 @@ size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
return printed;
}

-static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg)
{
int flags = arg->val;

@@ -82,6 +82,3 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct sy

return open__scnprintf_flags(flags, bf, size);
}
-
-
-#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags

tip-bot for Arnaldo Carvalho de Melo

unread,
Jul 20, 2017, 4:50:08 AM7/20/17
to
Commit-ID: 84d1d8a12df33a3e707866b9a1f9872058c3d1fb
Gitweb: http://git.kernel.org/tip/84d1d8a12df33a3e707866b9a1f9872058c3d1fb
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Tue, 18 Jul 2017 17:09:21 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:13:55 -0300

tools include uapi asm-generic: Grab a copy of fcntl.h

We'll need defines for beautifying fcntl arguments that are not
available in older distros, these:

trace/beauty/fcntl.c: In function 'syscall_arg__scnprintf_fcntl_arg':
trace/beauty/fcntl.c:93: error: 'F_OFD_SETLK' undeclared (first use in this function)
trace/beauty/fcntl.c:93: error: (Each undeclared identifier is reported only once
trace/beauty/fcntl.c:93: error: for each function it appears in.)
trace/beauty/fcntl.c:93: error: 'F_OFD_SETLKW' undeclared (first use in this function)
trace/beauty/fcntl.c:93: error: 'F_OFD_GETLK' undeclared (first use in this function)
trace/beauty/fcntl.c:94: error: 'F_GETOWN_EX' undeclared (first use in this function)
trace/beauty/fcntl.c:94: error: 'F_SETOWN_EX' undeclared (first use in this function)

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-gvlw67a47e...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
{include => tools/include}/uapi/asm-generic/fcntl.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/uapi/asm-generic/fcntl.h b/tools/include/uapi/asm-generic/fcntl.h
similarity index 98%
copy from include/uapi/asm-generic/fcntl.h
copy to tools/include/uapi/asm-generic/fcntl.h
index e063eff..ac19095 100644
--- a/include/uapi/asm-generic/fcntl.h
+++ b/tools/include/uapi/asm-generic/fcntl.h
@@ -90,7 +90,7 @@

/* a horrid kludge trying to make sure that this will fail on old kernels */
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
-#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT)
+#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT)

#ifndef O_NDELAY
#define O_NDELAY O_NONBLOCK

tip-bot for Arnaldo Carvalho de Melo

unread,
Jul 20, 2017, 4:50:08 AM7/20/17
to
Commit-ID: fc65eb8213a437b43e9de7776699aaa25dfa00df
Gitweb: http://git.kernel.org/tip/fc65eb8213a437b43e9de7776699aaa25dfa00df
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Fri, 14 Jul 2017 15:21:40 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 18 Jul 2017 23:14:02 -0300

perf trace beauty: Export the fd beautifier for use in more places

Now that the beautifiers are being split into multiple source and object
files, we will need more of them exported, do it for the 'fd' one, will
be used to augment the return of some syscalls that may return an 'fd',
such as fcntl(fd, F_DUPFD).

Cc: Adrian Hunter <adrian...@intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-39sosu12hh...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 8 +-------
tools/perf/trace/beauty/beauty.h | 3 +++
2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index cfa8bf1..65fa012 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -365,11 +365,6 @@ static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
#endif /* defined(__i386__) || defined(__x86_64__) */

-static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
- struct syscall_arg *arg);
-
-#define SCA_FD syscall_arg__scnprintf_fd
-
#ifndef AT_FDCWD
#define AT_FDCWD -100
#endif
@@ -1057,8 +1052,7 @@ static const char *thread__fd_path(struct thread *thread, int fd,
return ttrace->paths.table[fd];
}

-static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg)
{
int fd = arg->val;
size_t printed = scnprintf(bf, size, "%d", fd);
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index b64c411..790e830 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -31,6 +31,9 @@ unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx);
size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays

+size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FD syscall_arg__scnprintf_fd
+
size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_HEX syscall_arg__scnprintf_hex

It is loading more messages.
0 new messages