diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-07-26 13:25:32 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2013-07-29 22:04:30 -0400 |
commit | 1a11126bcb7c93c289bf3218fa546fd3b0c0df8b (patch) | |
tree | ffbfb4e73894c00bf674ece92c2531505a877a1b /kernel | |
parent | 5ae90d8e467e625e447000cb4335c4db973b1095 (diff) |
tracing: Turn event/id->i_private into call->event.type
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>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/trace_events.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 898f868833f2..c2d13c528c3c 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -409,6 +409,11 @@ static void put_system(struct ftrace_subsystem_dir *dir) | |||
409 | mutex_unlock(&event_mutex); | 409 | mutex_unlock(&event_mutex); |
410 | } | 410 | } |
411 | 411 | ||
412 | static void *event_file_data(struct file *filp) | ||
413 | { | ||
414 | return ACCESS_ONCE(file_inode(filp)->i_private); | ||
415 | } | ||
416 | |||
412 | /* | 417 | /* |
413 | * Open and update trace_array ref count. | 418 | * Open and update trace_array ref count. |
414 | * Must have the current trace_array passed to it. | 419 | * Must have the current trace_array passed to it. |
@@ -946,14 +951,18 @@ static int trace_format_open(struct inode *inode, struct file *file) | |||
946 | static ssize_t | 951 | static ssize_t |
947 | event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) | 952 | event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) |
948 | { | 953 | { |
949 | struct ftrace_event_call *call = filp->private_data; | 954 | int id = (long)event_file_data(filp); |
950 | char buf[32]; | 955 | char buf[32]; |
951 | int len; | 956 | int len; |
952 | 957 | ||
953 | if (*ppos) | 958 | if (*ppos) |
954 | return 0; | 959 | return 0; |
955 | 960 | ||
956 | len = sprintf(buf, "%d\n", call->event.type); | 961 | if (unlikely(!id)) |
962 | return -ENODEV; | ||
963 | |||
964 | len = sprintf(buf, "%d\n", id); | ||
965 | |||
957 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); | 966 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); |
958 | } | 967 | } |
959 | 968 | ||
@@ -1240,7 +1249,6 @@ static const struct file_operations ftrace_event_format_fops = { | |||
1240 | }; | 1249 | }; |
1241 | 1250 | ||
1242 | static const struct file_operations ftrace_event_id_fops = { | 1251 | static const struct file_operations ftrace_event_id_fops = { |
1243 | .open = tracing_open_generic, | ||
1244 | .read = event_id_read, | 1252 | .read = event_id_read, |
1245 | .llseek = default_llseek, | 1253 | .llseek = default_llseek, |
1246 | }; | 1254 | }; |
@@ -1488,8 +1496,8 @@ event_create_dir(struct dentry *parent, | |||
1488 | 1496 | ||
1489 | #ifdef CONFIG_PERF_EVENTS | 1497 | #ifdef CONFIG_PERF_EVENTS |
1490 | if (call->event.type && call->class->reg) | 1498 | if (call->event.type && call->class->reg) |
1491 | trace_create_file("id", 0444, file->dir, call, | 1499 | trace_create_file("id", 0444, file->dir, |
1492 | id); | 1500 | (void *)(long)call->event.type, id); |
1493 | #endif | 1501 | #endif |
1494 | 1502 | ||
1495 | /* | 1503 | /* |