add reset-trace (#766)

diff --git a/tools/reset-trace.sh b/tools/reset-trace.sh
new file mode 100755
index 0000000..fb891a7
--- /dev/null
+++ b/tools/reset-trace.sh
@@ -0,0 +1,135 @@
+#!/bin/bash
+#
+# reset-trace - reset state of tracing, disabling all tracing.
+#               Written for Linux.
+#
+# If a bcc tool crashed and you suspect tracing is partially enabled, you
+# can use this tool to reset the state of tracing, disabling anything still
+# enabled. Only use this tool in the case of error, and, consider filing a
+# bcc ticket so we can fix the error.
+#
+# bcc-used tracing facilities are reset. Other tracing facilities (ftrace) are
+# checked, and if not in an expected state, a note is printed. All tracing
+# files can be reset with -F for force, but this will interfere with any other
+# running tracing sessions (eg, ftrace).
+#
+# USAGE: ./reset-trace [-Fhqv]
+#
+# REQUIREMENTS: debugfs mounted on /sys/kernel/debug
+#
+# COPYRIGHT: Copyright (c) 2016 Brendan Gregg.
+# Licensed under the Apache License, Version 2.0 (the "License")
+#
+# 20-Jul-2014	Brendan Gregg	Created this.
+# 18-Oct-2016      "      "     Updated for bcc use.
+
+tracing=/sys/kernel/debug/tracing
+opt_force=0; opt_verbose=0; opt_quiet=0
+
+function usage {
+	cat <<-END >&2
+	USAGE: reset-trace [-Fhqv]
+	                 -F             # force: reset all tracing files
+	                 -v             # verbose: print details while working
+	                 -h             # this usage message
+	                 -q             # quiet: no output
+	  eg,
+	       reset-trace              # disable semi-enabled tracing
+END
+	exit
+}
+
+function die {
+	echo >&2 "$@"
+	exit 1
+}
+
+function vecho {
+	(( ! opt_verbose )) && return
+	echo "$@"
+}
+
+function writefile {
+	file=$1
+	write=$2
+	if [[ ! -w $file ]]; then
+		echo >&2 "WARNING: file $file not writable/exists. Skipping."
+		return
+	fi
+
+	vecho "Checking $PWD/$file"
+        contents=$(grep -v '^#' $file)
+	if [[ "$contents" != "$expected" ]]; then
+		(( ! opt_quiet )) && echo "Needed to reset $PWD/$file"
+		vecho "$file, before (line enumerated):"
+		(( opt_verbose )) && cat -nv $file
+		cmd="echo $write > $file"
+		if ! eval "$cmd"; then
+			echo >&2 "WARNING: command failed \"$cmd\"." \
+			    "bcc still running? Continuing."
+		fi
+		vecho "$file, after (line enumerated):"
+		(( opt_verbose )) && cat -nv $file
+		vecho
+	fi
+}
+
+# only write when force is used
+function checkfile {
+	file=$1
+	write=$2
+	expected=$3
+	if [[ ! -e $file ]]; then
+		echo >&2 "WARNING: file $file doesn't exist. Skipping."
+		return
+	fi
+	if (( opt_force )); then
+		writefile $file $write
+		return
+	fi
+	(( opt_quiet )) && return
+
+	vecho "Checking $PWD/$file"
+        contents=$(grep -v '^#' $file)
+	if [[ "$contents" != "$expected" ]]; then
+		echo "Noticed unrelated tracing file $PWD/$file isn't set as" \
+		    "expected. Not reseting (-F to force, -v for verbose)."
+		vecho "Contents of $file is (line enumerated):"
+		(( opt_verbose )) && cat -nv $file
+		vecho "Expected \"$expected\"."
+	fi
+}
+
+### process options
+while getopts Fhqv opt
+do
+	case $opt in
+	F)	opt_force=1 ;;
+	q)	opt_quiet=1 ;;
+	v)	opt_verbose=1 ;;
+	h|?)	usage ;;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+### reset tracing state
+vecho "Reseting tracing state..."
+vecho
+cd $tracing || die "ERROR: accessing tracing. Root user? /sys/kernel/debug?"
+
+# files bcc uses
+writefile kprobe_events "" ""
+writefile uprobe_events "" ""
+writefile trace "" ""         # clears trace_pipe
+
+# non-bcc files
+checkfile current_tracer nop nop
+checkfile set_ftrace_filter "" ""
+checkfile set_graph_function "" ""
+checkfile set_ftrace_pid "" "no pid"
+checkfile events/enable 0 0
+checkfile tracing_thresh 0 0
+checkfile tracing_on 1 1
+
+vecho
+vecho "Done."