diff options
Diffstat (limited to 'tools/perf/perf-with-kcore.sh')
-rw-r--r-- | tools/perf/perf-with-kcore.sh | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/tools/perf/perf-with-kcore.sh b/tools/perf/perf-with-kcore.sh new file mode 100644 index 000000000000..c7ff90a90e4e --- /dev/null +++ b/tools/perf/perf-with-kcore.sh | |||
@@ -0,0 +1,259 @@ | |||
1 | #!/bin/bash | ||
2 | # perf-with-kcore: use perf with a copy of kcore | ||
3 | # Copyright (c) 2014, Intel Corporation. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify it | ||
6 | # under the terms and conditions of the GNU General Public License, | ||
7 | # version 2, as published by the Free Software Foundation. | ||
8 | # | ||
9 | # This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | # more details. | ||
13 | |||
14 | set -e | ||
15 | |||
16 | usage() | ||
17 | { | ||
18 | echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2 | ||
19 | echo " <perf sub-command> can be record, script, report or inject" >&2 | ||
20 | echo " or: perf-with-kcore fix_buildid_cache_permissions" >&2 | ||
21 | exit 1 | ||
22 | } | ||
23 | |||
24 | find_perf() | ||
25 | { | ||
26 | if [ -n "$PERF" ] ; then | ||
27 | return | ||
28 | fi | ||
29 | PERF=`which perf || true` | ||
30 | if [ -z "$PERF" ] ; then | ||
31 | echo "Failed to find perf" >&2 | ||
32 | exit 1 | ||
33 | fi | ||
34 | if [ ! -x "$PERF" ] ; then | ||
35 | echo "Failed to find perf" >&2 | ||
36 | exit 1 | ||
37 | fi | ||
38 | echo "Using $PERF" | ||
39 | "$PERF" version | ||
40 | } | ||
41 | |||
42 | copy_kcore() | ||
43 | { | ||
44 | echo "Copying kcore" | ||
45 | |||
46 | if [ $EUID -eq 0 ] ; then | ||
47 | SUDO="" | ||
48 | else | ||
49 | SUDO="sudo" | ||
50 | fi | ||
51 | |||
52 | rm -f perf.data.junk | ||
53 | ("$PERF" record -o perf.data.junk $PERF_OPTIONS -- sleep 60) >/dev/null 2>/dev/null & | ||
54 | PERF_PID=$! | ||
55 | |||
56 | # Need to make sure that perf has started | ||
57 | sleep 1 | ||
58 | |||
59 | KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1) | ||
60 | case "$KCORE" in | ||
61 | "kcore added to build-id cache directory "*) | ||
62 | KCORE_DIR=${KCORE#"kcore added to build-id cache directory "} | ||
63 | ;; | ||
64 | *) | ||
65 | kill $PERF_PID | ||
66 | wait >/dev/null 2>/dev/null || true | ||
67 | rm perf.data.junk | ||
68 | echo "$KCORE" | ||
69 | echo "Failed to find kcore" >&2 | ||
70 | exit 1 | ||
71 | ;; | ||
72 | esac | ||
73 | |||
74 | kill $PERF_PID | ||
75 | wait >/dev/null 2>/dev/null || true | ||
76 | rm perf.data.junk | ||
77 | |||
78 | $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR" | ||
79 | $SUDO rm -f "$KCORE_DIR/kcore" | ||
80 | $SUDO rm -f "$KCORE_DIR/kallsyms" | ||
81 | $SUDO rm -f "$KCORE_DIR/modules" | ||
82 | $SUDO rmdir "$KCORE_DIR" | ||
83 | |||
84 | KCORE_DIR_BASENAME=$(basename "$KCORE_DIR") | ||
85 | KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME" | ||
86 | |||
87 | $SUDO chown $UID "$KCORE_DIR" | ||
88 | $SUDO chown $UID "$KCORE_DIR/kcore" | ||
89 | $SUDO chown $UID "$KCORE_DIR/kallsyms" | ||
90 | $SUDO chown $UID "$KCORE_DIR/modules" | ||
91 | |||
92 | $SUDO chgrp $GROUPS "$KCORE_DIR" | ||
93 | $SUDO chgrp $GROUPS "$KCORE_DIR/kcore" | ||
94 | $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms" | ||
95 | $SUDO chgrp $GROUPS "$KCORE_DIR/modules" | ||
96 | |||
97 | ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir" | ||
98 | } | ||
99 | |||
100 | fix_buildid_cache_permissions() | ||
101 | { | ||
102 | if [ $EUID -ne 0 ] ; then | ||
103 | echo "This script must be run as root via sudo " >&2 | ||
104 | exit 1 | ||
105 | fi | ||
106 | |||
107 | if [ -z "$SUDO_USER" ] ; then | ||
108 | echo "This script must be run via sudo" >&2 | ||
109 | exit 1 | ||
110 | fi | ||
111 | |||
112 | USER_HOME=$(bash <<< "echo ~$SUDO_USER") | ||
113 | |||
114 | if [ "$HOME" != "$USER_HOME" ] ; then | ||
115 | echo "Fix unnecessary because root has a home: $HOME" >&2 | ||
116 | exit 1 | ||
117 | fi | ||
118 | |||
119 | echo "Fixing buildid cache permissions" | ||
120 | |||
121 | find "$USER_HOME/.debug" -xdev -type d ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \; | ||
122 | find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \; | ||
123 | find "$USER_HOME/.debug" -xdev -type l ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \; | ||
124 | |||
125 | if [ -n "$SUDO_GID" ] ; then | ||
126 | find "$USER_HOME/.debug" -xdev -type d ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \; | ||
127 | find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \; | ||
128 | find "$USER_HOME/.debug" -xdev -type l ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \; | ||
129 | fi | ||
130 | |||
131 | echo "Done" | ||
132 | } | ||
133 | |||
134 | check_buildid_cache_permissions() | ||
135 | { | ||
136 | if [ $EUID -eq 0 ] ; then | ||
137 | return | ||
138 | fi | ||
139 | |||
140 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -user "$USER" -print -quit) | ||
141 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit) | ||
142 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -user "$USER" -print -quit) | ||
143 | |||
144 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -group "$GROUPS" -print -quit) | ||
145 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit) | ||
146 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -group "$GROUPS" -print -quit) | ||
147 | |||
148 | if [ -n "$PERMISSIONS_OK" ] ; then | ||
149 | echo "*** WARNING *** buildid cache permissions may need fixing" >&2 | ||
150 | fi | ||
151 | } | ||
152 | |||
153 | record() | ||
154 | { | ||
155 | echo "Recording" | ||
156 | |||
157 | if [ $EUID -ne 0 ] ; then | ||
158 | |||
159 | if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then | ||
160 | echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2 | ||
161 | fi | ||
162 | |||
163 | if echo "$PERF_OPTIONS" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then | ||
164 | echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2 | ||
165 | fi | ||
166 | |||
167 | if echo "$PERF_OPTIONS" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then | ||
168 | if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then | ||
169 | echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2 | ||
170 | fi | ||
171 | |||
172 | if echo "$PERF_OPTIONS" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then | ||
173 | true | ||
174 | elif echo "$PERF_OPTIONS" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then | ||
175 | true | ||
176 | elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then | ||
177 | echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2 | ||
178 | fi | ||
179 | fi | ||
180 | fi | ||
181 | |||
182 | if [ -z "$1" ] ; then | ||
183 | echo "Workload is required for recording" >&2 | ||
184 | usage | ||
185 | fi | ||
186 | |||
187 | if [ -e "$PERF_DATA_DIR" ] ; then | ||
188 | echo "'$PERF_DATA_DIR' exists" >&2 | ||
189 | exit 1 | ||
190 | fi | ||
191 | |||
192 | find_perf | ||
193 | |||
194 | mkdir "$PERF_DATA_DIR" | ||
195 | |||
196 | echo "$PERF record -o $PERF_DATA_DIR/perf.data $PERF_OPTIONS -- $*" | ||
197 | "$PERF" record -o "$PERF_DATA_DIR/perf.data" $PERF_OPTIONS -- $* || true | ||
198 | |||
199 | if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then | ||
200 | exit 1 | ||
201 | fi | ||
202 | |||
203 | copy_kcore | ||
204 | |||
205 | echo "Done" | ||
206 | } | ||
207 | |||
208 | subcommand() | ||
209 | { | ||
210 | find_perf | ||
211 | check_buildid_cache_permissions | ||
212 | echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $*" | ||
213 | "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" $* | ||
214 | } | ||
215 | |||
216 | if [ "$1" = "fix_buildid_cache_permissions" ] ; then | ||
217 | fix_buildid_cache_permissions | ||
218 | exit 0 | ||
219 | fi | ||
220 | |||
221 | PERF_SUB_COMMAND=$1 | ||
222 | PERF_DATA_DIR=$2 | ||
223 | shift || true | ||
224 | shift || true | ||
225 | |||
226 | if [ -z "$PERF_SUB_COMMAND" ] ; then | ||
227 | usage | ||
228 | fi | ||
229 | |||
230 | if [ -z "$PERF_DATA_DIR" ] ; then | ||
231 | usage | ||
232 | fi | ||
233 | |||
234 | case "$PERF_SUB_COMMAND" in | ||
235 | "record") | ||
236 | while [ "$1" != "--" ] ; do | ||
237 | PERF_OPTIONS+="$1 " | ||
238 | shift || break | ||
239 | done | ||
240 | if [ "$1" != "--" ] ; then | ||
241 | echo "Options and workload are required for recording" >&2 | ||
242 | usage | ||
243 | fi | ||
244 | shift | ||
245 | record $* | ||
246 | ;; | ||
247 | "script") | ||
248 | subcommand $* | ||
249 | ;; | ||
250 | "report") | ||
251 | subcommand $* | ||
252 | ;; | ||
253 | "inject") | ||
254 | subcommand $* | ||
255 | ;; | ||
256 | *) | ||
257 | usage | ||
258 | ;; | ||
259 | esac | ||