diff options
| -rw-r--r-- | kernel/perf_event.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index e099650cd249..bd7ce8ca5bb9 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
| @@ -4999,8 +4999,8 @@ SYSCALL_DEFINE5(perf_event_open, | |||
| 4999 | struct perf_event_context *ctx; | 4999 | struct perf_event_context *ctx; |
| 5000 | struct file *event_file = NULL; | 5000 | struct file *event_file = NULL; |
| 5001 | struct file *group_file = NULL; | 5001 | struct file *group_file = NULL; |
| 5002 | int event_fd; | ||
| 5002 | int fput_needed = 0; | 5003 | int fput_needed = 0; |
| 5003 | int fput_needed2 = 0; | ||
| 5004 | int err; | 5004 | int err; |
| 5005 | 5005 | ||
| 5006 | /* for future expandability... */ | 5006 | /* for future expandability... */ |
| @@ -5021,12 +5021,18 @@ SYSCALL_DEFINE5(perf_event_open, | |||
| 5021 | return -EINVAL; | 5021 | return -EINVAL; |
| 5022 | } | 5022 | } |
| 5023 | 5023 | ||
| 5024 | event_fd = get_unused_fd_flags(O_RDWR); | ||
| 5025 | if (event_fd < 0) | ||
| 5026 | return event_fd; | ||
| 5027 | |||
| 5024 | /* | 5028 | /* |
| 5025 | * Get the target context (task or percpu): | 5029 | * Get the target context (task or percpu): |
| 5026 | */ | 5030 | */ |
| 5027 | ctx = find_get_context(pid, cpu); | 5031 | ctx = find_get_context(pid, cpu); |
| 5028 | if (IS_ERR(ctx)) | 5032 | if (IS_ERR(ctx)) { |
| 5029 | return PTR_ERR(ctx); | 5033 | err = PTR_ERR(ctx); |
| 5034 | goto err_fd; | ||
| 5035 | } | ||
| 5030 | 5036 | ||
| 5031 | /* | 5037 | /* |
| 5032 | * Look up the group leader (we will attach this event to it): | 5038 | * Look up the group leader (we will attach this event to it): |
| @@ -5066,13 +5072,11 @@ SYSCALL_DEFINE5(perf_event_open, | |||
| 5066 | if (IS_ERR(event)) | 5072 | if (IS_ERR(event)) |
| 5067 | goto err_put_context; | 5073 | goto err_put_context; |
| 5068 | 5074 | ||
| 5069 | err = anon_inode_getfd("[perf_event]", &perf_fops, event, O_RDWR); | 5075 | event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR); |
| 5070 | if (err < 0) | 5076 | if (IS_ERR(event_file)) { |
| 5071 | goto err_free_put_context; | 5077 | err = PTR_ERR(event_file); |
| 5072 | |||
| 5073 | event_file = fget_light(err, &fput_needed2); | ||
| 5074 | if (!event_file) | ||
| 5075 | goto err_free_put_context; | 5078 | goto err_free_put_context; |
| 5079 | } | ||
| 5076 | 5080 | ||
| 5077 | if (flags & PERF_FLAG_FD_OUTPUT) { | 5081 | if (flags & PERF_FLAG_FD_OUTPUT) { |
| 5078 | err = perf_event_set_output(event, group_fd); | 5082 | err = perf_event_set_output(event, group_fd); |
| @@ -5093,19 +5097,19 @@ SYSCALL_DEFINE5(perf_event_open, | |||
| 5093 | list_add_tail(&event->owner_entry, ¤t->perf_event_list); | 5097 | list_add_tail(&event->owner_entry, ¤t->perf_event_list); |
| 5094 | mutex_unlock(¤t->perf_event_mutex); | 5098 | mutex_unlock(¤t->perf_event_mutex); |
| 5095 | 5099 | ||
| 5096 | err_fput_free_put_context: | 5100 | fput_light(group_file, fput_needed); |
| 5097 | fput_light(event_file, fput_needed2); | 5101 | fd_install(event_fd, event_file); |
| 5102 | return event_fd; | ||
| 5098 | 5103 | ||
| 5104 | err_fput_free_put_context: | ||
| 5105 | fput(event_file); | ||
| 5099 | err_free_put_context: | 5106 | err_free_put_context: |
| 5100 | if (err < 0) | 5107 | free_event(event); |
| 5101 | free_event(event); | ||
| 5102 | |||
| 5103 | err_put_context: | 5108 | err_put_context: |
| 5104 | if (err < 0) | ||
| 5105 | put_ctx(ctx); | ||
| 5106 | |||
| 5107 | fput_light(group_file, fput_needed); | 5109 | fput_light(group_file, fput_needed); |
| 5108 | 5110 | put_ctx(ctx); | |
| 5111 | err_fd: | ||
| 5112 | put_unused_fd(event_fd); | ||
| 5109 | return err; | 5113 | return err; |
| 5110 | } | 5114 | } |
| 5111 | 5115 | ||
