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