| 1 | clear_trace() { # reset trace output |
| 2 | echo > trace |
| 3 | } |
| 4 | |
| 5 | disable_tracing() { # stop trace recording |
| 6 | echo 0 > tracing_on |
| 7 | } |
| 8 | |
| 9 | enable_tracing() { # start trace recording |
| 10 | echo 1 > tracing_on |
| 11 | } |
| 12 | |
| 13 | reset_tracer() { # reset the current tracer |
| 14 | echo nop > current_tracer |
| 15 | } |
| 16 | |
| 17 | reset_trigger_file() { |
| 18 | # remove action triggers first |
| 19 | grep -H ':on[^:]*(' $@ | |
| 20 | while read line; do |
| 21 | cmd=`echo $line | cut -f2- -d: | cut -f1 -d"["` |
| 22 | file=`echo $line | cut -f1 -d:` |
| 23 | echo "!$cmd" >> $file |
| 24 | done |
| 25 | grep -Hv ^# $@ | |
| 26 | while read line; do |
| 27 | cmd=`echo $line | cut -f2- -d: | cut -f1 -d"["` |
| 28 | file=`echo $line | cut -f1 -d:` |
| 29 | echo "!$cmd" > $file |
| 30 | done |
| 31 | } |
| 32 | |
| 33 | reset_trigger() { # reset all current setting triggers |
| 34 | if [ -d events/synthetic ]; then |
| 35 | reset_trigger_file events/synthetic/*/trigger |
| 36 | fi |
| 37 | reset_trigger_file events/*/*/trigger |
| 38 | } |
| 39 | |
| 40 | reset_events_filter() { # reset all current setting filters |
| 41 | grep -v ^none events/*/*/filter | |
| 42 | while read line; do |
| 43 | echo 0 > `echo $line | cut -f1 -d:` |
| 44 | done |
| 45 | } |
| 46 | |
| 47 | reset_ftrace_filter() { # reset all triggers in set_ftrace_filter |
| 48 | if [ ! -f set_ftrace_filter ]; then |
| 49 | return 0 |
| 50 | fi |
| 51 | echo > set_ftrace_filter |
| 52 | grep -v '^#' set_ftrace_filter | while read t; do |
| 53 | tr=`echo $t | cut -d: -f2` |
| 54 | if [ "$tr" = "" ]; then |
| 55 | continue |
| 56 | fi |
| 57 | if ! grep -q "$t" set_ftrace_filter; then |
| 58 | continue; |
| 59 | fi |
| 60 | name=`echo $t | cut -d: -f1 | cut -d' ' -f1` |
| 61 | if [ $tr = "enable_event" -o $tr = "disable_event" ]; then |
| 62 | tr=`echo $t | cut -d: -f2-4` |
| 63 | limit=`echo $t | cut -d: -f5` |
| 64 | else |
| 65 | tr=`echo $t | cut -d: -f2` |
| 66 | limit=`echo $t | cut -d: -f3` |
| 67 | fi |
| 68 | if [ "$limit" != "unlimited" ]; then |
| 69 | tr="$tr:$limit" |
| 70 | fi |
| 71 | echo "!$name:$tr" > set_ftrace_filter |
| 72 | done |
| 73 | } |
| 74 | |
| 75 | disable_events() { |
| 76 | echo 0 > events/enable |
| 77 | } |
| 78 | |
| 79 | clear_synthetic_events() { # reset all current synthetic events |
| 80 | grep -v ^# synthetic_events | |
| 81 | while read line; do |
| 82 | echo "!$line" >> synthetic_events |
| 83 | done |
| 84 | } |
| 85 | |
| 86 | clear_dynamic_events() { # reset all current dynamic events |
| 87 | again=1 |
| 88 | stop=1 |
| 89 | # loop mulitple times as some events require other to be removed first |
| 90 | while [ $again -eq 1 ]; do |
| 91 | stop=$((stop+1)) |
| 92 | # Prevent infinite loops |
| 93 | if [ $stop -gt 10 ]; then |
| 94 | break; |
| 95 | fi |
| 96 | again=2 |
| 97 | grep -v '^#' dynamic_events| |
| 98 | while read line; do |
| 99 | del=`echo $line | sed -e 's/^.\([^ ]*\).*/-\1/'` |
| 100 | if ! echo "$del" >> dynamic_events; then |
| 101 | again=1 |
| 102 | fi |
| 103 | done |
| 104 | done |
| 105 | } |
| 106 | |
| 107 | initialize_system() { # Reset ftrace to initial-state |
| 108 | # As the initial state, ftrace will be set to nop tracer, |
| 109 | # no events, no triggers, no filters, no function filters, |
| 110 | # no probes, and tracing on. |
| 111 | disable_tracing |
| 112 | reset_tracer |
| 113 | reset_trigger |
| 114 | reset_events_filter |
| 115 | reset_ftrace_filter |
| 116 | disable_events |
| 117 | clear_dynamic_events |
| 118 | [ -f set_event_pid ] && echo > set_event_pid |
| 119 | [ -f set_ftrace_pid ] && echo > set_ftrace_pid |
| 120 | [ -f set_ftrace_notrace ] && echo > set_ftrace_notrace |
| 121 | [ -f set_graph_function ] && echo | tee set_graph_* |
| 122 | [ -f stack_trace_filter ] && echo > stack_trace_filter |
| 123 | [ -f kprobe_events ] && echo > kprobe_events |
| 124 | [ -f uprobe_events ] && echo > uprobe_events |
| 125 | [ -f synthetic_events ] && echo > synthetic_events |
| 126 | [ -f snapshot ] && echo 0 > snapshot |
| 127 | |
| 128 | # Stop tracing while reading the trace file by default, to prevent |
| 129 | # the test results while checking it and to avoid taking a long time |
| 130 | # to check the result. |
| 131 | [ -f options/pause-on-trace ] && echo 1 > options/pause-on-trace |
| 132 | |
| 133 | clear_trace |
| 134 | enable_tracing |
| 135 | } |
| 136 | |
| 137 | finish_system() { |
| 138 | initialize_system |
| 139 | # And recover it to default. |
| 140 | [ -f options/pause-on-trace ] && echo 0 > options/pause-on-trace |
| 141 | } |
| 142 | |
| 143 | check_requires() { # Check required files and tracers |
| 144 | for i in "$@" ; do |
| 145 | p=${i%:program} |
| 146 | r=${i%:README} |
| 147 | t=${i%:tracer} |
| 148 | if [ "$p" != "$i" ]; then |
| 149 | if ! which "$p" ; then |
| 150 | echo "Required program $p is not found." |
| 151 | exit_unresolved |
| 152 | fi |
| 153 | elif [ "$t" != "$i" ]; then |
| 154 | if ! grep -wq "$t" available_tracers ; then |
| 155 | echo "Required tracer $t is not configured." |
| 156 | exit_unsupported |
| 157 | fi |
| 158 | elif [ "$r" != "$i" ]; then |
| 159 | # If this is an instance, check the top directory |
| 160 | if echo $TRACING_DIR | grep -q "/instances/"; then |
| 161 | test="$TRACING_DIR/../.." |
| 162 | else |
| 163 | test=$TRACING_DIR |
| 164 | fi |
| 165 | if ! grep -Fq "$r" "$test"/README ; then |
| 166 | echo "Required feature pattern \"$r\" is not in README." |
| 167 | exit_unsupported |
| 168 | fi |
| 169 | elif [ ! -e "$i" ]; then |
| 170 | echo "Required feature interface $i doesn't exist." |
| 171 | exit_unsupported |
| 172 | fi |
| 173 | done |
| 174 | } |
| 175 | |
| 176 | check_awk_strtonum() { # strtonum is GNU awk extension |
| 177 | awk 'BEGIN{strtonum("0x1")}' |
| 178 | } |
| 179 | |
| 180 | LOCALHOST=127.0.0.1 |
| 181 | |
| 182 | yield() { |
| 183 | ping $LOCALHOST -c 1 || sleep .001 || usleep 1 || sleep 1 |
| 184 | } |
| 185 | |
| 186 | # The fork function in the kernel was renamed from "_do_fork" to |
| 187 | # "kernel_fork". As older tests should still work with older kernels |
| 188 | # as well as newer kernels, check which version of fork is used on this |
| 189 | # kernel so that the tests can use the fork function for the running kernel. |
| 190 | FUNCTION_FORK=`(if grep '\bkernel_clone\b' /proc/kallsyms > /dev/null; then |
| 191 | echo kernel_clone; else echo '_do_fork'; fi)` |
| 192 | |
| 193 | # Since probe event command may include backslash, explicitly use printf "%s" |
| 194 | # to NOT interpret it. |
| 195 | ftrace_errlog_check() { # err-prefix command-with-error-pos-by-^ command-file |
| 196 | pos=$(printf "%s" "${2%^*}" | wc -c) # error position |
| 197 | command=$(printf "%s" "$2" | tr -d ^) |
| 198 | echo "Test command: $command" |
| 199 | echo > error_log |
| 200 | (! printf "%s" "$command" >> "$3" ) 2> /dev/null |
| 201 | grep "$1: error:" -A 3 error_log |
| 202 | N=$(tail -n 1 error_log | wc -c) |
| 203 | # " Command: " and "^\n" => 13 |
| 204 | test $(expr 13 + $pos) -eq $N |
| 205 | } |
| 206 | |
| 207 | # Helper to get the tracefs mount point |
| 208 | get_mount_point() { |
| 209 | local mount_point=`stat -c '%m' .` |
| 210 | |
| 211 | # If stat -c '%m' does not work (e.g. busybox) or failed, try to use the |
| 212 | # current working directory (which should be a tracefs) as the mount point. |
| 213 | if [ ! -d "$mount_point" ]; then |
| 214 | if mount | grep -qw "$PWD"; then |
| 215 | mount_point=$PWD |
| 216 | else |
| 217 | # If PWD doesn't work, that is an environmental problem. |
| 218 | exit_unresolved |
| 219 | fi |
| 220 | fi |
| 221 | echo "$mount_point" |
| 222 | } |
| 223 | |
| 224 | # Helper function to retrieve mount options for a given mount point |
| 225 | get_mnt_options() { |
| 226 | local mnt_point="$1" |
| 227 | local opts=$(mount | grep -m1 "$mnt_point" | sed -e 's/.*(\(.*\)).*/\1/') |
| 228 | |
| 229 | echo "$opts" |
| 230 | } |