aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/events/core.c')
-rw-r--r--kernel/events/core.c70
1 files changed, 30 insertions, 40 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 2bd199bfaef..bd9c5bca42a 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -467,14 +467,13 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
467{ 467{
468 struct perf_cgroup *cgrp; 468 struct perf_cgroup *cgrp;
469 struct cgroup_subsys_state *css; 469 struct cgroup_subsys_state *css;
470 struct file *file; 470 struct fd f = fdget(fd);
471 int ret = 0, fput_needed; 471 int ret = 0;
472 472
473 file = fget_light(fd, &fput_needed); 473 if (!f.file)
474 if (!file)
475 return -EBADF; 474 return -EBADF;
476 475
477 css = cgroup_css_from_dir(file, perf_subsys_id); 476 css = cgroup_css_from_dir(f.file, perf_subsys_id);
478 if (IS_ERR(css)) { 477 if (IS_ERR(css)) {
479 ret = PTR_ERR(css); 478 ret = PTR_ERR(css);
480 goto out; 479 goto out;
@@ -500,7 +499,7 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
500 ret = -EINVAL; 499 ret = -EINVAL;
501 } 500 }
502out: 501out:
503 fput_light(file, fput_needed); 502 fdput(f);
504 return ret; 503 return ret;
505} 504}
506 505
@@ -3233,21 +3232,18 @@ unlock:
3233 3232
3234static const struct file_operations perf_fops; 3233static const struct file_operations perf_fops;
3235 3234
3236static struct file *perf_fget_light(int fd, int *fput_needed) 3235static inline int perf_fget_light(int fd, struct fd *p)
3237{ 3236{
3238 struct file *file; 3237 struct fd f = fdget(fd);
3239 3238 if (!f.file)
3240 file = fget_light(fd, fput_needed); 3239 return -EBADF;
3241 if (!file)
3242 return ERR_PTR(-EBADF);
3243 3240
3244 if (file->f_op != &perf_fops) { 3241 if (f.file->f_op != &perf_fops) {
3245 fput_light(file, *fput_needed); 3242 fdput(f);
3246 *fput_needed = 0; 3243 return -EBADF;
3247 return ERR_PTR(-EBADF);
3248 } 3244 }
3249 3245 *p = f;
3250 return file; 3246 return 0;
3251} 3247}
3252 3248
3253static int perf_event_set_output(struct perf_event *event, 3249static int perf_event_set_output(struct perf_event *event,
@@ -3279,22 +3275,19 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3279 3275
3280 case PERF_EVENT_IOC_SET_OUTPUT: 3276 case PERF_EVENT_IOC_SET_OUTPUT:
3281 { 3277 {
3282 struct file *output_file = NULL;
3283 struct perf_event *output_event = NULL;
3284 int fput_needed = 0;
3285 int ret; 3278 int ret;
3286
3287 if (arg != -1) { 3279 if (arg != -1) {
3288 output_file = perf_fget_light(arg, &fput_needed); 3280 struct perf_event *output_event;
3289 if (IS_ERR(output_file)) 3281 struct fd output;
3290 return PTR_ERR(output_file); 3282 ret = perf_fget_light(arg, &output);
3291 output_event = output_file->private_data; 3283 if (ret)
3284 return ret;
3285 output_event = output.file->private_data;
3286 ret = perf_event_set_output(event, output_event);
3287 fdput(output);
3288 } else {
3289 ret = perf_event_set_output(event, NULL);
3292 } 3290 }
3293
3294 ret = perf_event_set_output(event, output_event);
3295 if (output_event)
3296 fput_light(output_file, fput_needed);
3297
3298 return ret; 3291 return ret;
3299 } 3292 }
3300 3293
@@ -6229,12 +6222,11 @@ SYSCALL_DEFINE5(perf_event_open,
6229 struct perf_event_attr attr; 6222 struct perf_event_attr attr;
6230 struct perf_event_context *ctx; 6223 struct perf_event_context *ctx;
6231 struct file *event_file = NULL; 6224 struct file *event_file = NULL;
6232 struct file *group_file = NULL; 6225 struct fd group = {NULL, 0};
6233 struct task_struct *task = NULL; 6226 struct task_struct *task = NULL;
6234 struct pmu *pmu; 6227 struct pmu *pmu;
6235 int event_fd; 6228 int event_fd;
6236 int move_group = 0; 6229 int move_group = 0;
6237 int fput_needed = 0;
6238 int err; 6230 int err;
6239 6231
6240 /* for future expandability... */ 6232 /* for future expandability... */
@@ -6269,12 +6261,10 @@ SYSCALL_DEFINE5(perf_event_open,
6269 return event_fd; 6261 return event_fd;
6270 6262
6271 if (group_fd != -1) { 6263 if (group_fd != -1) {
6272 group_file = perf_fget_light(group_fd, &fput_needed); 6264 err = perf_fget_light(group_fd, &group);
6273 if (IS_ERR(group_file)) { 6265 if (err)
6274 err = PTR_ERR(group_file);
6275 goto err_fd; 6266 goto err_fd;
6276 } 6267 group_leader = group.file->private_data;
6277 group_leader = group_file->private_data;
6278 if (flags & PERF_FLAG_FD_OUTPUT) 6268 if (flags & PERF_FLAG_FD_OUTPUT)
6279 output_event = group_leader; 6269 output_event = group_leader;
6280 if (flags & PERF_FLAG_FD_NO_GROUP) 6270 if (flags & PERF_FLAG_FD_NO_GROUP)
@@ -6450,7 +6440,7 @@ SYSCALL_DEFINE5(perf_event_open,
6450 * of the group leader will find the pointer to itself in 6440 * of the group leader will find the pointer to itself in
6451 * perf_group_detach(). 6441 * perf_group_detach().
6452 */ 6442 */
6453 fput_light(group_file, fput_needed); 6443 fdput(group);
6454 fd_install(event_fd, event_file); 6444 fd_install(event_fd, event_file);
6455 return event_fd; 6445 return event_fd;
6456 6446
@@ -6464,7 +6454,7 @@ err_task:
6464 if (task) 6454 if (task)
6465 put_task_struct(task); 6455 put_task_struct(task);
6466err_group_fd: 6456err_group_fd:
6467 fput_light(group_file, fput_needed); 6457 fdput(group);
6468err_fd: 6458err_fd:
6469 put_unused_fd(event_fd); 6459 put_unused_fd(event_fd);
6470 return err; 6460 return err;