diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-07-26 13:25:32 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-29 12:47:33 -0400 |
commit | fdb65fe265a389144db73cca023266dd6d5ff8d9 (patch) | |
tree | a56997ef3e06615dac869d2fef971b893f7e0ced | |
parent | 29632b10ef02a31dec2918177f6d4244e66d635d (diff) |
tracing: Turn event/id->i_private into call->event.type
commit 1a11126bcb7c93c289bf3218fa546fd3b0c0df8b upstream.
event_id_read() is racy, ftrace_event_call can be already freed
by trace_remove_event_call() callers.
Change event_create_dir() to pass "data = call->event.type", this
is all event_id_read() needs. ftrace_event_id_fops no longer needs
tracing_open_generic().
We add the new helper, event_file_data(), to read ->i_private, it
will have more users.
Note: currently ACCESS_ONCE() and "id != 0" check are not needed,
but we are going to change event_remove/rmdir to clear ->i_private.
Link: http://lkml.kernel.org/r/20130726172532.GA3605@redhat.com
Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | kernel/trace/trace_events.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 5f9a002d17d1..fd16a254173c 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -407,6 +407,11 @@ static void put_system(struct ftrace_subsystem_dir *dir) | |||
407 | mutex_unlock(&event_mutex); | 407 | mutex_unlock(&event_mutex); |
408 | } | 408 | } |
409 | 409 | ||
410 | static void *event_file_data(struct file *filp) | ||
411 | { | ||
412 | return ACCESS_ONCE(file_inode(filp)->i_private); | ||
413 | } | ||
414 | |||
410 | /* | 415 | /* |
411 | * Open and update trace_array ref count. | 416 | * Open and update trace_array ref count. |
412 | * Must have the current trace_array passed to it. | 417 | * Must have the current trace_array passed to it. |
@@ -960,19 +965,22 @@ static int trace_format_open(struct inode *inode, struct file *file) | |||
960 | static ssize_t | 965 | static ssize_t |
961 | event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) | 966 | event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) |
962 | { | 967 | { |
963 | struct ftrace_event_call *call = filp->private_data; | 968 | int id = (long)event_file_data(filp); |
964 | struct trace_seq *s; | 969 | struct trace_seq *s; |
965 | int r; | 970 | int r; |
966 | 971 | ||
967 | if (*ppos) | 972 | if (*ppos) |
968 | return 0; | 973 | return 0; |
969 | 974 | ||
975 | if (unlikely(!id)) | ||
976 | return -ENODEV; | ||
977 | |||
970 | s = kmalloc(sizeof(*s), GFP_KERNEL); | 978 | s = kmalloc(sizeof(*s), GFP_KERNEL); |
971 | if (!s) | 979 | if (!s) |
972 | return -ENOMEM; | 980 | return -ENOMEM; |
973 | 981 | ||
974 | trace_seq_init(s); | 982 | trace_seq_init(s); |
975 | trace_seq_printf(s, "%d\n", call->event.type); | 983 | trace_seq_printf(s, "%d\n", id); |
976 | 984 | ||
977 | r = simple_read_from_buffer(ubuf, cnt, ppos, | 985 | r = simple_read_from_buffer(ubuf, cnt, ppos, |
978 | s->buffer, s->len); | 986 | s->buffer, s->len); |
@@ -1263,7 +1271,6 @@ static const struct file_operations ftrace_event_format_fops = { | |||
1263 | }; | 1271 | }; |
1264 | 1272 | ||
1265 | static const struct file_operations ftrace_event_id_fops = { | 1273 | static const struct file_operations ftrace_event_id_fops = { |
1266 | .open = tracing_open_generic, | ||
1267 | .read = event_id_read, | 1274 | .read = event_id_read, |
1268 | .llseek = default_llseek, | 1275 | .llseek = default_llseek, |
1269 | }; | 1276 | }; |
@@ -1511,8 +1518,8 @@ event_create_dir(struct dentry *parent, | |||
1511 | 1518 | ||
1512 | #ifdef CONFIG_PERF_EVENTS | 1519 | #ifdef CONFIG_PERF_EVENTS |
1513 | if (call->event.type && call->class->reg) | 1520 | if (call->event.type && call->class->reg) |
1514 | trace_create_file("id", 0444, file->dir, call, | 1521 | trace_create_file("id", 0444, file->dir, |
1515 | id); | 1522 | (void *)(long)call->event.type, id); |
1516 | #endif | 1523 | #endif |
1517 | 1524 | ||
1518 | /* | 1525 | /* |