Commit 99214f67 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'trace-v6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull tracing fixes from Steven Rostedt:

 - Add missing LOCKDOWN checks for eventfs callers

   When LOCKDOWN is active for tracing, it causes inconsistent state
   when some functions succeed and others fail.

 - Use dput() to free the top level eventfs descriptor

   There was a race between accesses and freeing it.

 - Fix a long standing bug that eventfs exposed due to changing timings
   by dynamically creating files. That is, If a event file is opened for
   an instance, there's nothing preventing the instance from being
   removed which will make accessing the files cause use-after-free
   bugs.

 - Fix a ring buffer race that happens when iterating over the ring
   buffer while writers are active. Check to make sure not to read the
   event meta data if it's beyond the end of the ring buffer sub buffer.

 - Fix the print trigger that disappeared because the test to create it
   was looking for the event dir field being filled, but now it has the
   "ef" field filled for the eventfs structure.

 - Remove the unused "dir" field from the event structure.

 - Fix the order of the trace_dynamic_info as it had it backwards for
   the offset and len fields for which one was for which endianess.

 - Fix NULL pointer dereference with eventfs_remove_rec()

   If an allocation fails in one of the eventfs_add_*() functions, the
   caller of it in event_subsystem_dir() or event_create_dir() assigns
   the result to the structure. But it's assigning the ERR_PTR and not
   NULL. This was passed to eventfs_remove_rec() which expects either a
   good pointer or a NULL, not ERR_PTR. The fix is to not assign the
   ERR_PTR to the structure, but to keep it NULL on error.

 - Fix list_for_each_rcu() to use list_for_each_srcu() in
   dcache_dir_open_wrapper(). One iteration of the code used RCU but
   because it had to call sleepable code, it had to be changed to use
   SRCU, but one of the iterations was missed.

 - Fix synthetic event print function to use "as_u64" instead of passing
   in a pointer to the union. To fix big/little endian issues, the u64
   that represented several types was turned into a union to define the
   types properly.

* tag 'trace-v6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  eventfs: Fix the NULL pointer dereference bug in eventfs_remove_rec()
  tracefs/eventfs: Use list_for_each_srcu() in dcache_dir_open_wrapper()
  tracing/synthetic: Print out u64 values properly
  tracing/synthetic: Fix order of struct trace_dynamic_info
  selftests/ftrace: Fix dependencies for some of the synthetic event tests
  tracing: Remove unused trace_event_file dir field
  tracing: Use the new eventfs descriptor for print trigger
  ring-buffer: Do not attempt to read past "commit"
  tracefs/eventfs: Free top level files on removal
  ring-buffer: Avoid softlockup in ring_buffer_resize()
  tracing: Have event inject files inc the trace array ref count
  tracing: Have option files inc the trace array ref count
  tracing: Have current_trace inc the trace array ref count
  tracing: Have tracing_max_latency inc the trace array ref count
  tracing: Increase trace array ref count on enable and filter files
  tracefs/eventfs: Use dput to free the toplevel events directory
  tracefs/eventfs: Add missing lockdown checks
  tracefs: Add missing lockdown check to tracefs_create_dir()
parents 3669558b c8414dab
...@@ -185,17 +185,49 @@ static struct dentry *create_dir(const char *name, struct dentry *parent, void * ...@@ -185,17 +185,49 @@ static struct dentry *create_dir(const char *name, struct dentry *parent, void *
/** /**
* eventfs_set_ef_status_free - set the ef->status to free * eventfs_set_ef_status_free - set the ef->status to free
* @ti: the tracefs_inode of the dentry
* @dentry: dentry who's status to be freed * @dentry: dentry who's status to be freed
* *
* eventfs_set_ef_status_free will be called if no more * eventfs_set_ef_status_free will be called if no more
* references remain * references remain
*/ */
void eventfs_set_ef_status_free(struct dentry *dentry) void eventfs_set_ef_status_free(struct tracefs_inode *ti, struct dentry *dentry)
{ {
struct tracefs_inode *ti_parent; struct tracefs_inode *ti_parent;
struct eventfs_file *ef; struct eventfs_inode *ei;
struct eventfs_file *ef, *tmp;
/* The top level events directory may be freed by this */
if (unlikely(ti->flags & TRACEFS_EVENT_TOP_INODE)) {
LIST_HEAD(ef_del_list);
mutex_lock(&eventfs_mutex); mutex_lock(&eventfs_mutex);
ei = ti->private;
/* Record all the top level files */
list_for_each_entry_srcu(ef, &ei->e_top_files, list,
lockdep_is_held(&eventfs_mutex)) {
list_add_tail(&ef->del_list, &ef_del_list);
}
/* Nothing should access this, but just in case! */
ti->private = NULL;
mutex_unlock(&eventfs_mutex);
/* Now safely free the top level files and their children */
list_for_each_entry_safe(ef, tmp, &ef_del_list, del_list) {
list_del(&ef->del_list);
eventfs_remove(ef);
}
kfree(ei);
return;
}
mutex_lock(&eventfs_mutex);
ti_parent = get_tracefs(dentry->d_parent->d_inode); ti_parent = get_tracefs(dentry->d_parent->d_inode);
if (!ti_parent || !(ti_parent->flags & TRACEFS_EVENT_INODE)) if (!ti_parent || !(ti_parent->flags & TRACEFS_EVENT_INODE))
goto out; goto out;
...@@ -420,7 +452,8 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file) ...@@ -420,7 +452,8 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file)
ei = ti->private; ei = ti->private;
idx = srcu_read_lock(&eventfs_srcu); idx = srcu_read_lock(&eventfs_srcu);
list_for_each_entry_rcu(ef, &ei->e_top_files, list) { list_for_each_entry_srcu(ef, &ei->e_top_files, list,
srcu_read_lock_held(&eventfs_srcu)) {
create_dentry(ef, dentry, false); create_dentry(ef, dentry, false);
} }
srcu_read_unlock(&eventfs_srcu, idx); srcu_read_unlock(&eventfs_srcu, idx);
...@@ -491,6 +524,9 @@ struct dentry *eventfs_create_events_dir(const char *name, ...@@ -491,6 +524,9 @@ struct dentry *eventfs_create_events_dir(const char *name,
struct tracefs_inode *ti; struct tracefs_inode *ti;
struct inode *inode; struct inode *inode;
if (security_locked_down(LOCKDOWN_TRACEFS))
return NULL;
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return dentry; return dentry;
...@@ -507,7 +543,7 @@ struct dentry *eventfs_create_events_dir(const char *name, ...@@ -507,7 +543,7 @@ struct dentry *eventfs_create_events_dir(const char *name,
INIT_LIST_HEAD(&ei->e_top_files); INIT_LIST_HEAD(&ei->e_top_files);
ti = get_tracefs(inode); ti = get_tracefs(inode);
ti->flags |= TRACEFS_EVENT_INODE; ti->flags |= TRACEFS_EVENT_INODE | TRACEFS_EVENT_TOP_INODE;
ti->private = ei; ti->private = ei;
inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
...@@ -538,6 +574,9 @@ struct eventfs_file *eventfs_add_subsystem_dir(const char *name, ...@@ -538,6 +574,9 @@ struct eventfs_file *eventfs_add_subsystem_dir(const char *name,
struct eventfs_inode *ei_parent; struct eventfs_inode *ei_parent;
struct eventfs_file *ef; struct eventfs_file *ef;
if (security_locked_down(LOCKDOWN_TRACEFS))
return NULL;
if (!parent) if (!parent)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
...@@ -569,6 +608,9 @@ struct eventfs_file *eventfs_add_dir(const char *name, ...@@ -569,6 +608,9 @@ struct eventfs_file *eventfs_add_dir(const char *name,
{ {
struct eventfs_file *ef; struct eventfs_file *ef;
if (security_locked_down(LOCKDOWN_TRACEFS))
return NULL;
if (!ef_parent) if (!ef_parent)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
...@@ -606,6 +648,9 @@ int eventfs_add_events_file(const char *name, umode_t mode, ...@@ -606,6 +648,9 @@ int eventfs_add_events_file(const char *name, umode_t mode,
struct eventfs_inode *ei; struct eventfs_inode *ei;
struct eventfs_file *ef; struct eventfs_file *ef;
if (security_locked_down(LOCKDOWN_TRACEFS))
return -ENODEV;
if (!parent) if (!parent)
return -EINVAL; return -EINVAL;
...@@ -654,6 +699,9 @@ int eventfs_add_file(const char *name, umode_t mode, ...@@ -654,6 +699,9 @@ int eventfs_add_file(const char *name, umode_t mode,
{ {
struct eventfs_file *ef; struct eventfs_file *ef;
if (security_locked_down(LOCKDOWN_TRACEFS))
return -ENODEV;
if (!ef_parent) if (!ef_parent)
return -EINVAL; return -EINVAL;
...@@ -791,7 +839,6 @@ void eventfs_remove(struct eventfs_file *ef) ...@@ -791,7 +839,6 @@ void eventfs_remove(struct eventfs_file *ef)
void eventfs_remove_events_dir(struct dentry *dentry) void eventfs_remove_events_dir(struct dentry *dentry)
{ {
struct tracefs_inode *ti; struct tracefs_inode *ti;
struct eventfs_inode *ei;
if (!dentry || !dentry->d_inode) if (!dentry || !dentry->d_inode)
return; return;
...@@ -800,8 +847,6 @@ void eventfs_remove_events_dir(struct dentry *dentry) ...@@ -800,8 +847,6 @@ void eventfs_remove_events_dir(struct dentry *dentry)
if (!ti || !(ti->flags & TRACEFS_EVENT_INODE)) if (!ti || !(ti->flags & TRACEFS_EVENT_INODE))
return; return;
ei = ti->private;
d_invalidate(dentry); d_invalidate(dentry);
dput(dentry); dput(dentry);
kfree(ei);
} }
...@@ -385,7 +385,7 @@ static void tracefs_dentry_iput(struct dentry *dentry, struct inode *inode) ...@@ -385,7 +385,7 @@ static void tracefs_dentry_iput(struct dentry *dentry, struct inode *inode)
ti = get_tracefs(inode); ti = get_tracefs(inode);
if (ti && ti->flags & TRACEFS_EVENT_INODE) if (ti && ti->flags & TRACEFS_EVENT_INODE)
eventfs_set_ef_status_free(dentry); eventfs_set_ef_status_free(ti, dentry);
iput(inode); iput(inode);
} }
...@@ -673,6 +673,9 @@ static struct dentry *__create_dir(const char *name, struct dentry *parent, ...@@ -673,6 +673,9 @@ static struct dentry *__create_dir(const char *name, struct dentry *parent,
*/ */
struct dentry *tracefs_create_dir(const char *name, struct dentry *parent) struct dentry *tracefs_create_dir(const char *name, struct dentry *parent)
{ {
if (security_locked_down(LOCKDOWN_TRACEFS))
return NULL;
return __create_dir(name, parent, &simple_dir_inode_operations); return __create_dir(name, parent, &simple_dir_inode_operations);
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
enum { enum {
TRACEFS_EVENT_INODE = BIT(1), TRACEFS_EVENT_INODE = BIT(1),
TRACEFS_EVENT_TOP_INODE = BIT(2),
}; };
struct tracefs_inode { struct tracefs_inode {
...@@ -24,6 +25,6 @@ struct inode *tracefs_get_inode(struct super_block *sb); ...@@ -24,6 +25,6 @@ struct inode *tracefs_get_inode(struct super_block *sb);
struct dentry *eventfs_start_creating(const char *name, struct dentry *parent); struct dentry *eventfs_start_creating(const char *name, struct dentry *parent);
struct dentry *eventfs_failed_creating(struct dentry *dentry); struct dentry *eventfs_failed_creating(struct dentry *dentry);
struct dentry *eventfs_end_creating(struct dentry *dentry); struct dentry *eventfs_end_creating(struct dentry *dentry);
void eventfs_set_ef_status_free(struct dentry *dentry); void eventfs_set_ef_status_free(struct tracefs_inode *ti, struct dentry *dentry);
#endif /* _TRACEFS_INTERNAL_H */ #endif /* _TRACEFS_INTERNAL_H */
...@@ -62,13 +62,13 @@ void trace_event_printf(struct trace_iterator *iter, const char *fmt, ...); ...@@ -62,13 +62,13 @@ void trace_event_printf(struct trace_iterator *iter, const char *fmt, ...);
/* Used to find the offset and length of dynamic fields in trace events */ /* Used to find the offset and length of dynamic fields in trace events */
struct trace_dynamic_info { struct trace_dynamic_info {
#ifdef CONFIG_CPU_BIG_ENDIAN #ifdef CONFIG_CPU_BIG_ENDIAN
u16 offset;
u16 len; u16 len;
u16 offset;
#else #else
u16 len;
u16 offset; u16 offset;
u16 len;
#endif #endif
}; } __packed;
/* /*
* The trace entry - the most basic unit of tracing. This is what * The trace entry - the most basic unit of tracing. This is what
...@@ -650,7 +650,6 @@ struct trace_event_file { ...@@ -650,7 +650,6 @@ struct trace_event_file {
struct trace_event_call *event_call; struct trace_event_call *event_call;
struct event_filter __rcu *filter; struct event_filter __rcu *filter;
struct eventfs_file *ef; struct eventfs_file *ef;
struct dentry *dir;
struct trace_array *tr; struct trace_array *tr;
struct trace_subsystem_dir *system; struct trace_subsystem_dir *system;
struct list_head triggers; struct list_head triggers;
......
...@@ -2198,6 +2198,8 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size, ...@@ -2198,6 +2198,8 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
err = -ENOMEM; err = -ENOMEM;
goto out_err; goto out_err;
} }
cond_resched();
} }
cpus_read_lock(); cpus_read_lock();
...@@ -2388,6 +2390,11 @@ rb_iter_head_event(struct ring_buffer_iter *iter) ...@@ -2388,6 +2390,11 @@ rb_iter_head_event(struct ring_buffer_iter *iter)
*/ */
commit = rb_page_commit(iter_head_page); commit = rb_page_commit(iter_head_page);
smp_rmb(); smp_rmb();
/* An event needs to be at least 8 bytes in size */
if (iter->head > commit - 8)
goto reset;
event = __rb_page_index(iter_head_page, iter->head); event = __rb_page_index(iter_head_page, iter->head);
length = rb_event_length(event); length = rb_event_length(event);
......
...@@ -1772,7 +1772,7 @@ static void trace_create_maxlat_file(struct trace_array *tr, ...@@ -1772,7 +1772,7 @@ static void trace_create_maxlat_file(struct trace_array *tr,
init_irq_work(&tr->fsnotify_irqwork, latency_fsnotify_workfn_irq); init_irq_work(&tr->fsnotify_irqwork, latency_fsnotify_workfn_irq);
tr->d_max_latency = trace_create_file("tracing_max_latency", tr->d_max_latency = trace_create_file("tracing_max_latency",
TRACE_MODE_WRITE, TRACE_MODE_WRITE,
d_tracer, &tr->max_latency, d_tracer, tr,
&tracing_max_lat_fops); &tracing_max_lat_fops);
} }
...@@ -1805,7 +1805,7 @@ void latency_fsnotify(struct trace_array *tr) ...@@ -1805,7 +1805,7 @@ void latency_fsnotify(struct trace_array *tr)
#define trace_create_maxlat_file(tr, d_tracer) \ #define trace_create_maxlat_file(tr, d_tracer) \
trace_create_file("tracing_max_latency", TRACE_MODE_WRITE, \ trace_create_file("tracing_max_latency", TRACE_MODE_WRITE, \
d_tracer, &tr->max_latency, &tracing_max_lat_fops) d_tracer, tr, &tracing_max_lat_fops)
#endif #endif
...@@ -4973,6 +4973,33 @@ int tracing_open_generic_tr(struct inode *inode, struct file *filp) ...@@ -4973,6 +4973,33 @@ int tracing_open_generic_tr(struct inode *inode, struct file *filp)
return 0; return 0;
} }
/*
* The private pointer of the inode is the trace_event_file.
* Update the tr ref count associated to it.
*/
int tracing_open_file_tr(struct inode *inode, struct file *filp)
{
struct trace_event_file *file = inode->i_private;
int ret;
ret = tracing_check_open_get_tr(file->tr);
if (ret)
return ret;
filp->private_data = inode->i_private;
return 0;
}
int tracing_release_file_tr(struct inode *inode, struct file *filp)
{
struct trace_event_file *file = inode->i_private;
trace_array_put(file->tr);
return 0;
}
static int tracing_mark_open(struct inode *inode, struct file *filp) static int tracing_mark_open(struct inode *inode, struct file *filp)
{ {
stream_open(inode, filp); stream_open(inode, filp);
...@@ -6691,14 +6718,18 @@ static ssize_t ...@@ -6691,14 +6718,18 @@ static ssize_t
tracing_max_lat_read(struct file *filp, char __user *ubuf, tracing_max_lat_read(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos) size_t cnt, loff_t *ppos)
{ {
return tracing_nsecs_read(filp->private_data, ubuf, cnt, ppos); struct trace_array *tr = filp->private_data;
return tracing_nsecs_read(&tr->max_latency, ubuf, cnt, ppos);
} }
static ssize_t static ssize_t
tracing_max_lat_write(struct file *filp, const char __user *ubuf, tracing_max_lat_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *ppos) size_t cnt, loff_t *ppos)
{ {
return tracing_nsecs_write(filp->private_data, ubuf, cnt, ppos); struct trace_array *tr = filp->private_data;
return tracing_nsecs_write(&tr->max_latency, ubuf, cnt, ppos);
} }
#endif #endif
...@@ -7752,18 +7783,20 @@ static const struct file_operations tracing_thresh_fops = { ...@@ -7752,18 +7783,20 @@ static const struct file_operations tracing_thresh_fops = {
#ifdef CONFIG_TRACER_MAX_TRACE #ifdef CONFIG_TRACER_MAX_TRACE
static const struct file_operations tracing_max_lat_fops = { static const struct file_operations tracing_max_lat_fops = {
.open = tracing_open_generic, .open = tracing_open_generic_tr,
.read = tracing_max_lat_read, .read = tracing_max_lat_read,
.write = tracing_max_lat_write, .write = tracing_max_lat_write,
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.release = tracing_release_generic_tr,
}; };
#endif #endif
static const struct file_operations set_tracer_fops = { static const struct file_operations set_tracer_fops = {
.open = tracing_open_generic, .open = tracing_open_generic_tr,
.read = tracing_set_trace_read, .read = tracing_set_trace_read,
.write = tracing_set_trace_write, .write = tracing_set_trace_write,
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.release = tracing_release_generic_tr,
}; };
static const struct file_operations tracing_pipe_fops = { static const struct file_operations tracing_pipe_fops = {
...@@ -8956,12 +8989,33 @@ trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt, ...@@ -8956,12 +8989,33 @@ trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,
return cnt; return cnt;
} }
static int tracing_open_options(struct inode *inode, struct file *filp)
{
struct trace_option_dentry *topt = inode->i_private;
int ret;
ret = tracing_check_open_get_tr(topt->tr);
if (ret)
return ret;
filp->private_data = inode->i_private;
return 0;
}
static int tracing_release_options(struct inode *inode, struct file *file)
{
struct trace_option_dentry *topt = file->private_data;
trace_array_put(topt->tr);
return 0;
}
static const struct file_operations trace_options_fops = { static const struct file_operations trace_options_fops = {
.open = tracing_open_generic, .open = tracing_open_options,
.read = trace_options_read, .read = trace_options_read,
.write = trace_options_write, .write = trace_options_write,
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.release = tracing_release_options,
}; };
/* /*
...@@ -9739,8 +9793,8 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) ...@@ -9739,8 +9793,8 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
tr, &tracing_mark_fops); tr, &tracing_mark_fops);
file = __find_event_file(tr, "ftrace", "print"); file = __find_event_file(tr, "ftrace", "print");
if (file && file->dir) if (file && file->ef)
trace_create_file("trigger", TRACE_MODE_WRITE, file->dir, eventfs_add_file("trigger", TRACE_MODE_WRITE, file->ef,
file, &event_trigger_fops); file, &event_trigger_fops);
tr->trace_marker_file = file; tr->trace_marker_file = file;
......
...@@ -610,6 +610,8 @@ void tracing_reset_all_online_cpus(void); ...@@ -610,6 +610,8 @@ void tracing_reset_all_online_cpus(void);
void tracing_reset_all_online_cpus_unlocked(void); void tracing_reset_all_online_cpus_unlocked(void);
int tracing_open_generic(struct inode *inode, struct file *filp); int tracing_open_generic(struct inode *inode, struct file *filp);
int tracing_open_generic_tr(struct inode *inode, struct file *filp); int tracing_open_generic_tr(struct inode *inode, struct file *filp);
int tracing_open_file_tr(struct inode *inode, struct file *filp);
int tracing_release_file_tr(struct inode *inode, struct file *filp);
bool tracing_is_disabled(void); bool tracing_is_disabled(void);
bool tracer_tracing_is_on(struct trace_array *tr); bool tracer_tracing_is_on(struct trace_array *tr);
void tracer_tracing_on(struct trace_array *tr); void tracer_tracing_on(struct trace_array *tr);
......
...@@ -992,19 +992,6 @@ static void remove_subsystem(struct trace_subsystem_dir *dir) ...@@ -992,19 +992,6 @@ static void remove_subsystem(struct trace_subsystem_dir *dir)
static void remove_event_file_dir(struct trace_event_file *file) static void remove_event_file_dir(struct trace_event_file *file)
{ {
struct dentry *dir = file->dir;
struct dentry *child;
if (dir) {
spin_lock(&dir->d_lock); /* probably unneeded */
list_for_each_entry(child, &dir->d_subdirs, d_child) {
if (d_really_is_positive(child)) /* probably unneeded */
d_inode(child)->i_private = NULL;
}
spin_unlock(&dir->d_lock);
tracefs_remove(dir);
}
eventfs_remove(file->ef); eventfs_remove(file->ef);
list_del(&file->list); list_del(&file->list);
remove_subsystem(file->system); remove_subsystem(file->system);
...@@ -2103,9 +2090,10 @@ static const struct file_operations ftrace_set_event_notrace_pid_fops = { ...@@ -2103,9 +2090,10 @@ static const struct file_operations ftrace_set_event_notrace_pid_fops = {
}; };
static const struct file_operations ftrace_enable_fops = { static const struct file_operations ftrace_enable_fops = {
.open = tracing_open_generic, .open = tracing_open_file_tr,
.read = event_enable_read, .read = event_enable_read,
.write = event_enable_write, .write = event_enable_write,
.release = tracing_release_file_tr,
.llseek = default_llseek, .llseek = default_llseek,
}; };
...@@ -2122,9 +2110,10 @@ static const struct file_operations ftrace_event_id_fops = { ...@@ -2122,9 +2110,10 @@ static const struct file_operations ftrace_event_id_fops = {
}; };
static const struct file_operations ftrace_event_filter_fops = { static const struct file_operations ftrace_event_filter_fops = {
.open = tracing_open_generic, .open = tracing_open_file_tr,
.read = event_filter_read, .read = event_filter_read,
.write = event_filter_write, .write = event_filter_write,
.release = tracing_release_file_tr,
.llseek = default_llseek, .llseek = default_llseek,
}; };
...@@ -2297,6 +2286,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name, ...@@ -2297,6 +2286,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
{ {
struct event_subsystem *system, *iter; struct event_subsystem *system, *iter;
struct trace_subsystem_dir *dir; struct trace_subsystem_dir *dir;
struct eventfs_file *ef;
int res; int res;
/* First see if we did not already create this dir */ /* First see if we did not already create this dir */
...@@ -2329,13 +2319,14 @@ event_subsystem_dir(struct trace_array *tr, const char *name, ...@@ -2329,13 +2319,14 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
} else } else
__get_system(system); __get_system(system);
dir->ef = eventfs_add_subsystem_dir(name, parent); ef = eventfs_add_subsystem_dir(name, parent);
if (IS_ERR(dir->ef)) { if (IS_ERR(ef)) {
pr_warn("Failed to create system directory %s\n", name); pr_warn("Failed to create system directory %s\n", name);
__put_system(system); __put_system(system);
goto out_free; goto out_free;
} }
dir->ef = ef;
dir->tr = tr; dir->tr = tr;
dir->ref_count = 1; dir->ref_count = 1;
dir->nr_events = 1; dir->nr_events = 1;
...@@ -2415,6 +2406,7 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file) ...@@ -2415,6 +2406,7 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
struct trace_event_call *call = file->event_call; struct trace_event_call *call = file->event_call;
struct eventfs_file *ef_subsystem = NULL; struct eventfs_file *ef_subsystem = NULL;
struct trace_array *tr = file->tr; struct trace_array *tr = file->tr;
struct eventfs_file *ef;
const char *name; const char *name;
int ret; int ret;
...@@ -2431,12 +2423,14 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file) ...@@ -2431,12 +2423,14 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
return -ENOMEM; return -ENOMEM;
name = trace_event_name(call); name = trace_event_name(call);
file->ef = eventfs_add_dir(name, ef_subsystem); ef = eventfs_add_dir(name, ef_subsystem);
if (IS_ERR(file->ef)) { if (IS_ERR(ef)) {
pr_warn("Could not create tracefs '%s' directory\n", name); pr_warn("Could not create tracefs '%s' directory\n", name);
return -1; return -1;
} }
file->ef = ef;
if (call->class->reg && !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) if (call->class->reg && !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE))
eventfs_add_file("enable", TRACE_MODE_WRITE, file->ef, file, eventfs_add_file("enable", TRACE_MODE_WRITE, file->ef, file,
&ftrace_enable_fops); &ftrace_enable_fops);
......
...@@ -328,7 +328,8 @@ event_inject_read(struct file *file, char __user *buf, size_t size, ...@@ -328,7 +328,8 @@ event_inject_read(struct file *file, char __user *buf, size_t size,
} }
const struct file_operations event_inject_fops = { const struct file_operations event_inject_fops = {
.open = tracing_open_generic, .open = tracing_open_file_tr,
.read = event_inject_read, .read = event_inject_read,
.write = event_inject_write, .write = event_inject_write,
.release = tracing_release_file_tr,
}; };
...@@ -337,7 +337,7 @@ static void print_synth_event_num_val(struct trace_seq *s, ...@@ -337,7 +337,7 @@ static void print_synth_event_num_val(struct trace_seq *s,
break; break;
default: default:
trace_seq_printf(s, print_fmt, name, val, space); trace_seq_printf(s, print_fmt, name, val->as_u64, space);
break; break;
} }
} }
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event histogram trigger trace action with dynamic string param # description: event trigger - test inter-event histogram trigger trace action with dynamic string param
# requires: set_event synthetic_events events/sched/sched_process_exec/hist "char name[]' >> synthetic_events":README ping:program # requires: set_event synthetic_events events/sched/sched_process_exec/hist "' >> synthetic_events":README ping:program
fail() { #msg fail() { #msg
echo $1 echo $1
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test synthetic_events syntax parser errors # description: event trigger - test synthetic_events syntax parser errors
# requires: synthetic_events error_log "char name[]' >> synthetic_events":README # requires: synthetic_events error_log "' >> synthetic_events":README
check_error() { # command-with-error-pos-by-^ check_error() { # command-with-error-pos-by-^
ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events' ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment