Commit | Line | Data |
---|---|---|
c501e90b AH |
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 | |
8bd1b2d2 | 53 | ("$PERF" record -o perf.data.junk "${PERF_OPTIONS[@]}" -- sleep 60) >/dev/null 2>/dev/null & |
c501e90b AH |
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 | ||
8bd1b2d2 | 163 | if echo "${PERF_OPTIONS[@]}" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then |
c501e90b AH |
164 | echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2 |
165 | fi | |
166 | ||
8bd1b2d2 | 167 | if echo "${PERF_OPTIONS[@]}" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then |
c501e90b AH |
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 | ||
8bd1b2d2 | 172 | if echo "${PERF_OPTIONS[@]}" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then |
c501e90b | 173 | true |
8bd1b2d2 | 174 | elif echo "${PERF_OPTIONS[@]}" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then |
c501e90b AH |
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 | ||
8bd1b2d2 AH |
196 | echo "$PERF record -o $PERF_DATA_DIR/perf.data ${PERF_OPTIONS[@]} -- $@" |
197 | "$PERF" record -o "$PERF_DATA_DIR/perf.data" "${PERF_OPTIONS[@]}" -- "$@" || true | |
c501e90b AH |
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 | |
8bd1b2d2 AH |
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" "$@" | |
c501e90b AH |
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 | |
8bd1b2d2 | 237 | PERF_OPTIONS+=("$1") |
c501e90b AH |
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 | |
8bd1b2d2 | 245 | record "$@" |
c501e90b AH |
246 | ;; |
247 | "script") | |
8bd1b2d2 | 248 | subcommand "$@" |
c501e90b AH |
249 | ;; |
250 | "report") | |
8bd1b2d2 | 251 | subcommand "$@" |
c501e90b AH |
252 | ;; |
253 | "inject") | |
8bd1b2d2 | 254 | subcommand "$@" |
c501e90b AH |
255 | ;; |
256 | *) | |
257 | usage | |
258 | ;; | |
259 | esac |