Commit 5eb6eed7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'trace-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing updates from Steven Rostedt:
 "One new feature was added to ftrace, which is the trace_marker now
  supports triggers. For example:

    # cd /sys/kernel/debug/tracing
    # echo 'snapshot' > events/ftrace/print/trigger
    # echo 'cause snapshot' > trace_marker

  The rest of the changes are various clean ups and also one stable fix
  that was added late in the cycle"

* tag 'trace-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: (21 commits)
  tracing: Use match_string() instead of open coding it in trace_set_options()
  branch-check: fix long->int truncation when profiling branches
  ring-buffer: Fix typo in comment
  ring-buffer: Fix a bunch of typos in comments
  tracing/selftest: Add test to test simple snapshot trigger for trace_marker
  tracing/selftest: Add test to test hist trigger between kernel event and trace_marker
  tracing/selftest: Add selftests to test trace_marker histogram triggers
  ftrace/selftest: Fix reset_trigger() to handle triggers with filters
  ftrace/selftest: Have the reset_trigger code be a bit more careful
  tracing: Document trace_marker triggers
  tracing: Allow histogram triggers to access ftrace internal events
  tracing: Prevent further users of zero size static arrays in trace events
  tracing: Have zero size length in filter logic be full string
  tracing: Add trigger file for trace_markers tracefs/ftrace/print
  tracing: Do not show filter file for ftrace internal events
  tracing: Add brackets in ftrace event dynamic arrays
  tracing: Have event_trace_init() called by trace_init_tracefs()
  tracing: Add __find_event_file() to find event files without restrictions
  tracing: Do not reference event data in post call triggers
  tracepoints: Fix the descriptions of tracepoint_probe_register{_prio}
  ...
parents 8b5c6a3a 591a033d
......@@ -338,10 +338,14 @@ used for conditionally invoking triggers.
The syntax for event triggers is roughly based on the syntax for
set_ftrace_filter 'ftrace filter commands' (see the 'Filter commands'
section of Documentation/trace/ftrace.txt), but there are major
section of Documentation/trace/ftrace.rst), but there are major
differences and the implementation isn't currently tied to it in any
way, so beware about making generalizations between the two.
Note: Writing into trace_marker (See Documentation/trace/ftrace.rst)
can also enable triggers that are written into
/sys/kernel/tracing/events/ftrace/print/trigger
6.1 Expression syntax
---------------------
......
......@@ -512,6 +512,11 @@ of ftrace. Here is a list of some of the key files:
trace_fd = open("trace_marker", WR_ONLY);
Note: Writing into the trace_marker file can also initiate triggers
that are written into /sys/kernel/tracing/events/ftrace/print/trigger
See "Event triggers" in Documentation/trace/events.rst and an
example in Documentation/trace/histogram.rst (Section 3.)
trace_marker_raw:
This is similar to trace_marker above, but is meant for for binary data
......
This diff is collapsed.
......@@ -21,7 +21,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
#define unlikely_notrace(x) __builtin_expect(!!(x), 0)
#define __branch_check__(x, expect, is_constant) ({ \
int ______r; \
long ______r; \
static struct ftrace_likely_data \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_annotated_branch"))) \
......
......@@ -65,7 +65,7 @@ u64 ring_buffer_event_time_stamp(struct ring_buffer_event *event);
/*
* ring_buffer_discard_commit will remove an event that has not
* ben committed yet. If this is used, then ring_buffer_unlock_commit
* been committed yet. If this is used, then ring_buffer_unlock_commit
* must not be called on the discarded event. This function
* will try to remove the event from the ring buffer completely
* if another event has not been written after it.
......
......@@ -435,8 +435,7 @@ event_triggers_call(struct trace_event_file *file, void *rec,
struct ring_buffer_event *event);
extern void
event_triggers_post_call(struct trace_event_file *file,
enum event_trigger_type tt,
void *rec, struct ring_buffer_event *event);
enum event_trigger_type tt);
bool trace_event_ignore_this_pid(struct trace_event_file *trace_file);
......
......@@ -422,6 +422,7 @@ static struct trace_event_functions trace_event_type_funcs_##call = { \
do { \
char *type_str = #type"["__stringify(len)"]"; \
BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \
BUILD_BUG_ON(len <= 0); \
ret = trace_define_field(event_call, type_str, #item, \
offsetof(typeof(field), item), \
sizeof(field.item), \
......
......@@ -809,7 +809,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_normalize_time_stamp);
*
* You can see, it is legitimate for the previous pointer of
* the head (or any page) not to point back to itself. But only
* temporarially.
* temporarily.
*/
#define RB_PAGE_NORMAL 0UL
......@@ -906,7 +906,7 @@ static void rb_list_head_clear(struct list_head *list)
}
/*
* rb_head_page_dactivate - clears head page ptr (for free list)
* rb_head_page_deactivate - clears head page ptr (for free list)
*/
static void
rb_head_page_deactivate(struct ring_buffer_per_cpu *cpu_buffer)
......@@ -1780,7 +1780,7 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
put_online_cpus();
} else {
/* Make sure this CPU has been intitialized */
/* Make sure this CPU has been initialized */
if (!cpumask_test_cpu(cpu_id, buffer->cpumask))
goto out;
......@@ -2325,7 +2325,7 @@ rb_update_event(struct ring_buffer_per_cpu *cpu_buffer,
/*
* If we need to add a timestamp, then we
* add it to the start of the resevered space.
* add it to the start of the reserved space.
*/
if (unlikely(info->add_timestamp)) {
bool abs = ring_buffer_time_stamp_abs(cpu_buffer->buffer);
......@@ -2681,7 +2681,7 @@ trace_recursive_unlock(struct ring_buffer_per_cpu *cpu_buffer)
* ring_buffer_nest_start - Allow to trace while nested
* @buffer: The ring buffer to modify
*
* The ring buffer has a safty mechanism to prevent recursion.
* The ring buffer has a safety mechanism to prevent recursion.
* But there may be a case where a trace needs to be done while
* tracing something else. In this case, calling this function
* will allow this function to nest within a currently active
......@@ -2699,7 +2699,7 @@ void ring_buffer_nest_start(struct ring_buffer *buffer)
preempt_disable_notrace();
cpu = raw_smp_processor_id();
cpu_buffer = buffer->buffers[cpu];
/* This is the shift value for the above recusive locking */
/* This is the shift value for the above recursive locking */
cpu_buffer->nest += NESTED_BITS;
}
......@@ -2718,7 +2718,7 @@ void ring_buffer_nest_end(struct ring_buffer *buffer)
/* disabled by ring_buffer_nest_start() */
cpu = raw_smp_processor_id();
cpu_buffer = buffer->buffers[cpu];
/* This is the shift value for the above recusive locking */
/* This is the shift value for the above recursive locking */
cpu_buffer->nest -= NESTED_BITS;
preempt_enable_notrace();
}
......@@ -2907,7 +2907,7 @@ rb_reserve_next_event(struct ring_buffer *buffer,
* @buffer: the ring buffer to reserve from
* @length: the length of the data to reserve (excluding event header)
*
* Returns a reseverd event on the ring buffer to copy directly to.
* Returns a reserved event on the ring buffer to copy directly to.
* The user of this interface will need to get the body to write into
* and can use the ring_buffer_event_data() interface.
*
......@@ -3009,7 +3009,7 @@ rb_decrement_entry(struct ring_buffer_per_cpu *cpu_buffer,
* This function lets the user discard an event in the ring buffer
* and then that event will not be read later.
*
* This function only works if it is called before the the item has been
* This function only works if it is called before the item has been
* committed. It will try to free the event from the ring buffer
* if another event has not been added behind it.
*
......@@ -4127,7 +4127,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_consume);
* through the buffer. Memory is allocated, buffer recording
* is disabled, and the iterator pointer is returned to the caller.
*
* Disabling buffer recordng prevents the reading from being
* Disabling buffer recording prevents the reading from being
* corrupted. This is not a consuming read, so a producer is not
* expected.
*
......
......@@ -4395,8 +4395,7 @@ static int trace_set_options(struct trace_array *tr, char *option)
{
char *cmp;
int neg = 0;
int ret = -ENODEV;
int i;
int ret;
size_t orig_len = strlen(option);
cmp = strstrip(option);
......@@ -4408,16 +4407,12 @@ static int trace_set_options(struct trace_array *tr, char *option)
mutex_lock(&trace_types_lock);
for (i = 0; trace_options[i]; i++) {
if (strcmp(cmp, trace_options[i]) == 0) {
ret = set_tracer_flag(tr, 1 << i, !neg);
break;
}
}
ret = match_string(trace_options, -1, cmp);
/* If no option could be set, test the specific tracer options */
if (!trace_options[i])
if (ret < 0)
ret = set_tracer_option(tr, cmp, neg);
else
ret = set_tracer_flag(tr, 1 << ret, !neg);
mutex_unlock(&trace_types_lock);
......@@ -6074,6 +6069,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
{
struct trace_array *tr = filp->private_data;
struct ring_buffer_event *event;
enum event_trigger_type tt = ETT_NONE;
struct ring_buffer *buffer;
struct print_entry *entry;
unsigned long irq_flags;
......@@ -6122,6 +6118,12 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
written = cnt;
len = cnt;
if (tr->trace_marker_file && !list_empty(&tr->trace_marker_file->triggers)) {
/* do not add \n before testing triggers, but add \0 */
entry->buf[cnt] = '\0';
tt = event_triggers_call(tr->trace_marker_file, entry, event);
}
if (entry->buf[cnt - 1] != '\n') {
entry->buf[cnt] = '\n';
entry->buf[cnt + 1] = '\0';
......@@ -6130,6 +6132,9 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
__buffer_unlock_commit(buffer, event);
if (tt)
event_triggers_post_call(tr->trace_marker_file, tt);
if (written > 0)
*fpos += written;
......@@ -7896,6 +7901,7 @@ static __init void create_trace_instances(struct dentry *d_tracer)
static void
init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
{
struct trace_event_file *file;
int cpu;
trace_create_file("available_tracers", 0444, d_tracer,
......@@ -7928,6 +7934,12 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
trace_create_file("trace_marker", 0220, d_tracer,
tr, &tracing_mark_fops);
file = __find_event_file(tr, "ftrace", "print");
if (file && file->dir)
trace_create_file("trigger", 0644, file->dir, file,
&event_trigger_fops);
tr->trace_marker_file = file;
trace_create_file("trace_marker_raw", 0220, d_tracer,
tr, &tracing_mark_raw_fops);
......@@ -8111,6 +8123,8 @@ static __init int tracer_init_tracefs(void)
if (IS_ERR(d_tracer))
return 0;
event_trace_init();
init_tracer_tracefs(&global_trace, d_tracer);
ftrace_init_tracefs_toplevel(&global_trace, d_tracer);
......
......@@ -259,6 +259,7 @@ struct trace_array {
struct trace_options *topts;
struct list_head systems;
struct list_head events;
struct trace_event_file *trace_marker_file;
cpumask_var_t tracing_cpumask; /* only trace on set CPUs */
int ref;
#ifdef CONFIG_FUNCTION_TRACER
......@@ -1334,7 +1335,7 @@ event_trigger_unlock_commit(struct trace_event_file *file,
trace_buffer_unlock_commit(file->tr, buffer, event, irq_flags, pc);
if (tt)
event_triggers_post_call(file, tt, entry, event);
event_triggers_post_call(file, tt);
}
/**
......@@ -1367,7 +1368,7 @@ event_trigger_unlock_commit_regs(struct trace_event_file *file,
irq_flags, pc, regs);
if (tt)
event_triggers_post_call(file, tt, entry, event);
event_triggers_post_call(file, tt);
}
#define FILTER_PRED_INVALID ((unsigned short)-1)
......@@ -1451,9 +1452,13 @@ trace_find_event_field(struct trace_event_call *call, char *name);
extern void trace_event_enable_cmd_record(bool enable);
extern void trace_event_enable_tgid_record(bool enable);
extern int event_trace_init(void);
extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr);
extern int event_trace_del_tracer(struct trace_array *tr);
extern struct trace_event_file *__find_event_file(struct trace_array *tr,
const char *system,
const char *event);
extern struct trace_event_file *find_event_file(struct trace_array *tr,
const char *system,
const char *event);
......
......@@ -230,7 +230,7 @@ FTRACE_ENTRY(bprint, bprint_entry,
FILTER_OTHER
);
FTRACE_ENTRY(print, print_entry,
FTRACE_ENTRY_REG(print, print_entry,
TRACE_PRINT,
......@@ -242,7 +242,9 @@ FTRACE_ENTRY(print, print_entry,
F_printk("%ps: %s",
(void *)__entry->ip, __entry->buf),
FILTER_OTHER
FILTER_OTHER,
ftrace_event_register
);
FTRACE_ENTRY(raw_data, raw_data_entry,
......
......@@ -2007,16 +2007,18 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
return -1;
}
}
trace_create_file("filter", 0644, file->dir, file,
&ftrace_event_filter_fops);
/*
* Only event directories that can be enabled should have
* triggers.
* triggers or filters.
*/
if (!(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE))
if (!(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) {
trace_create_file("filter", 0644, file->dir, file,
&ftrace_event_filter_fops);
trace_create_file("trigger", 0644, file->dir, file,
&event_trigger_fops);
}
#ifdef CONFIG_HIST_TRIGGERS
trace_create_file("hist", 0444, file->dir, file,
......@@ -2473,8 +2475,9 @@ __trace_add_event_dirs(struct trace_array *tr)
}
}
/* Returns any file that matches the system and event */
struct trace_event_file *
find_event_file(struct trace_array *tr, const char *system, const char *event)
__find_event_file(struct trace_array *tr, const char *system, const char *event)
{
struct trace_event_file *file;
struct trace_event_call *call;
......@@ -2485,10 +2488,7 @@ find_event_file(struct trace_array *tr, const char *system, const char *event)
call = file->event_call;
name = trace_event_name(call);
if (!name || !call->class || !call->class->reg)
continue;
if (call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)
if (!name || !call->class)
continue;
if (strcmp(event, name) == 0 &&
......@@ -2498,6 +2498,20 @@ find_event_file(struct trace_array *tr, const char *system, const char *event)
return NULL;
}
/* Returns valid trace event files that match system and event */
struct trace_event_file *
find_event_file(struct trace_array *tr, const char *system, const char *event)
{
struct trace_event_file *file;
file = __find_event_file(tr, system, event);
if (!file || !file->event_call->class->reg ||
file->event_call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)
return NULL;
return file;
}
#ifdef CONFIG_DYNAMIC_FTRACE
/* Avoid typos */
......@@ -3132,7 +3146,7 @@ static __init int event_trace_enable_again(void)
early_initcall(event_trace_enable_again);
static __init int event_trace_init(void)
__init int event_trace_init(void)
{
struct trace_array *tr;
struct dentry *d_tracer;
......@@ -3177,8 +3191,6 @@ void __init trace_event_init(void)
event_trace_enable();
}
fs_initcall(event_trace_init);
#ifdef CONFIG_FTRACE_STARTUP_TEST
static DEFINE_SPINLOCK(test_spinlock);
......
......@@ -750,31 +750,32 @@ static int filter_pred_none(struct filter_pred *pred, void *event)
*
* Note:
* - @str might not be NULL-terminated if it's of type DYN_STRING
* or STATIC_STRING
* or STATIC_STRING, unless @len is zero.
*/
static int regex_match_full(char *str, struct regex *r, int len)
{
if (strncmp(str, r->pattern, len) == 0)
return 1;
return 0;
/* len of zero means str is dynamic and ends with '\0' */
if (!len)
return strcmp(str, r->pattern) == 0;
return strncmp(str, r->pattern, len) == 0;
}
static int regex_match_front(char *str, struct regex *r, int len)
{
if (len < r->len)
if (len && len < r->len)
return 0;
if (strncmp(str, r->pattern, r->len) == 0)
return 1;
return 0;
return strncmp(str, r->pattern, r->len) == 0;
}
static int regex_match_middle(char *str, struct regex *r, int len)
{
if (strnstr(str, r->pattern, len))
return 1;
return 0;
if (!len)
return strstr(str, r->pattern) != NULL;
return strnstr(str, r->pattern, len) != NULL;
}
static int regex_match_end(char *str, struct regex *r, int len)
......
......@@ -2865,7 +2865,7 @@ static struct trace_event_file *event_file(struct trace_array *tr,
{
struct trace_event_file *file;
file = find_event_file(tr, system, event_name);
file = __find_event_file(tr, system, event_name);
if (!file)
return ERR_PTR(-EINVAL);
......
......@@ -97,7 +97,6 @@ EXPORT_SYMBOL_GPL(event_triggers_call);
* event_triggers_post_call - Call 'post_triggers' for a trace event
* @file: The trace_event_file associated with the event
* @tt: enum event_trigger_type containing a set bit for each trigger to invoke
* @rec: The trace entry for the event
*
* For each trigger associated with an event, invoke the trigger
* function registered with the associated trigger command, if the
......@@ -108,8 +107,7 @@ EXPORT_SYMBOL_GPL(event_triggers_call);
*/
void
event_triggers_post_call(struct trace_event_file *file,
enum event_trigger_type tt,
void *rec, struct ring_buffer_event *event)
enum event_trigger_type tt)
{
struct event_trigger_data *data;
......@@ -117,7 +115,7 @@ event_triggers_post_call(struct trace_event_file *file,
if (data->paused)
continue;
if (data->cmd_ops->trigger_type & tt)
data->ops->func(data, rec, event);
data->ops->func(data, NULL, NULL);
}
}
EXPORT_SYMBOL_GPL(event_triggers_post_call);
......
......@@ -14,6 +14,13 @@
#include "trace_output.h"
/* Stub function for events with triggers */
static int ftrace_event_register(struct trace_event_call *call,
enum trace_reg type, void *data)
{
return 0;
}
#undef TRACE_SYSTEM
#define TRACE_SYSTEM ftrace
......@@ -117,7 +124,7 @@ static void __always_unused ____ftrace_check_##name(void) \
#undef __dynamic_array
#define __dynamic_array(type, item) \
ret = trace_define_field(event_call, #type, #item, \
ret = trace_define_field(event_call, #type "[]", #item, \
offsetof(typeof(field), item), \
0, is_signed_type(type), filter_type);\
if (ret) \
......
......@@ -257,7 +257,7 @@ static int tracepoint_remove_func(struct tracepoint *tp,
}
/**
* tracepoint_probe_register - Connect a probe to a tracepoint
* tracepoint_probe_register_prio - Connect a probe to a tracepoint with priority
* @tp: tracepoint
* @probe: probe handler
* @data: tracepoint data
......@@ -290,7 +290,6 @@ EXPORT_SYMBOL_GPL(tracepoint_probe_register_prio);
* @tp: tracepoint
* @probe: probe handler
* @data: tracepoint data
* @prio: priority of this function over other registered functions
*
* Returns 0 if ok, error value on error.
* Note: if @tp is within a module, the caller is responsible for
......
......@@ -206,6 +206,11 @@ cmd_modversions_c = \
endif
ifdef CONFIG_FTRACE_MCOUNT_RECORD
# gcc 5 supports generating the mcount tables directly
ifneq ($(call cc-option,-mrecord-mcount,y),y)
KBUILD_CFLAGS += -mrecord-mcount
else
# else do it all manually
ifdef BUILD_C_RECORDMCOUNT
ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
RECORDMCOUNT_FLAGS = -w
......@@ -258,6 +263,7 @@ ifneq ($(RETPOLINE_CFLAGS),)
objtool_args += --retpoline
endif
endif
endif
ifdef CONFIG_MODVERSIONS
......
......@@ -15,14 +15,29 @@ reset_tracer() { # reset the current tracer
echo nop > current_tracer
}
reset_trigger() { # reset all current setting triggers
grep -v ^# events/*/*/trigger |
reset_trigger_file() {
# remove action triggers first
grep -H ':on[^:]*(' $@ |
while read line; do
cmd=`echo $line | cut -f2- -d: | cut -f1 -d"["`
file=`echo $line | cut -f1 -d:`
echo "!$cmd" >> $file
done
grep -Hv ^# $@ |
while read line; do
cmd=`echo $line | cut -f2- -d: | cut -f1 -d" "`
echo "!$cmd" > `echo $line | cut -f1 -d:`
cmd=`echo $line | cut -f2- -d: | cut -f1 -d"["`
file=`echo $line | cut -f1 -d:`
echo "!$cmd" > $file
done
}
reset_trigger() { # reset all current setting triggers
if [ -d events/synthetic ]; then
reset_trigger_file events/synthetic/*/trigger
fi
reset_trigger_file events/*/*/trigger
}
reset_events_filter() { # reset all current setting filters
grep -v ^none events/*/*/filter |
while read line; do
......
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: trace_marker trigger - test histogram trigger
# flags: instance
do_reset() {
reset_trigger
echo > set_event
clear_trace
}
fail() { #msg
do_reset
echo $1
exit_fail
}
if [ ! -f set_event ]; then
echo "event tracing is not supported"
exit_unsupported
fi
if [ ! -d events/ftrace/print ]; then
echo "event trace_marker is not supported"
exit_unsupported
fi
if [ ! -f events/ftrace/print/trigger ]; then
echo "event trigger is not supported"
exit_unsupported
fi
if [ ! -f events/ftrace/print/hist ]; then
echo "hist trigger is not supported"
exit_unsupported
fi
do_reset
echo "Test histogram trace_marker tigger"
echo 'hist:keys=common_pid' > events/ftrace/print/trigger
for i in `seq 1 10` ; do echo "hello" > trace_marker; done
grep 'hitcount: *10$' events/ftrace/print/hist > /dev/null || \
fail "hist trigger did not trigger correct times on trace_marker"
do_reset
exit 0
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: trace_marker trigger - test snapshot trigger
# flags: instance
do_reset() {
reset_trigger
echo > set_event
echo 0 > snapshot
clear_trace
}
fail() { #msg
do_reset
echo $1
exit_fail
}
if [ ! -f set_event ]; then
echo "event tracing is not supported"
exit_unsupported
fi
if [ ! -f snapshot ]; then
echo "snapshot is not supported"
exit_unsupported
fi
if [ ! -d events/ftrace/print ]; then
echo "event trace_marker is not supported"
exit_unsupported
fi
if [ ! -f events/ftrace/print/trigger ]; then
echo "event trigger is not supported"
exit_unsupported
fi
test_trace() {
file=$1
x=$2
cat $file | while read line; do
comment=`echo $line | sed -e 's/^#//'`
if [ "$line" != "$comment" ]; then
continue
fi
echo "testing $line for >$x<"
match=`echo $line | sed -e "s/>$x<//"`
if [ "$line" == "$match" ]; then
fail "$line does not have >$x< in it"
fi
let x=$x+2
done
}
do_reset
echo "Test snapshot trace_marker tigger"
echo 'snapshot' > events/ftrace/print/trigger
# make sure the snapshot is allocated
grep -q 'Snapshot is allocated' snapshot
for i in `seq 1 10` ; do echo "hello >$i<" > trace_marker; done
test_trace trace 1
test_trace snapshot 2
do_reset
exit 0
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: trace_marker trigger - test histogram with synthetic event against kernel event
# flags:
do_reset() {
reset_trigger
echo > set_event
echo > synthetic_events
clear_trace
}
fail() { #msg
do_reset
echo $1
exit_fail
}
if [ ! -f set_event ]; then
echo "event tracing is not supported"
exit_unsupported
fi
if [ ! -f synthetic_events ]; then
echo "synthetic events not supported"
exit_unsupported
fi
if [ ! -d events/ftrace/print ]; then
echo "event trace_marker is not supported"
exit_unsupported
fi
if [ ! -d events/sched/sched_waking ]; then
echo "event sched_waking is not supported"
exit_unsupported
fi
if [ ! -f events/ftrace/print/trigger ]; then
echo "event trigger is not supported"
exit_unsupported