Skip to content

Commit 4dd53b8

Browse files
author
Al Viro
committed
get rid of perf_fget_light(), convert kernel/events/core.c to CLASS(fd)
Lift fdget() and fdput() out of perf_fget_light(), turning it into is_perf_file(struct fd f). The life gets easier in both callers if we do fdget() unconditionally, including the case when we are given -1 instead of a descriptor - that avoids a reassignment in perf_event_open(2) and it avoids a nasty temptation in _perf_ioctl() where we must *not* lift output_event out of scope for output. Reviewed-by: Christian Brauner <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 919a7a1 commit 4dd53b8

File tree

1 file changed

+16
-33
lines changed

1 file changed

+16
-33
lines changed

kernel/events/core.c

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5998,18 +5998,9 @@ EXPORT_SYMBOL_GPL(perf_event_period);
59985998

59995999
static const struct file_operations perf_fops;
60006000

6001-
static inline int perf_fget_light(int fd, struct fd *p)
6001+
static inline bool is_perf_file(struct fd f)
60026002
{
6003-
struct fd f = fdget(fd);
6004-
if (!fd_file(f))
6005-
return -EBADF;
6006-
6007-
if (fd_file(f)->f_op != &perf_fops) {
6008-
fdput(f);
6009-
return -EBADF;
6010-
}
6011-
*p = f;
6012-
return 0;
6003+
return !fd_empty(f) && fd_file(f)->f_op == &perf_fops;
60136004
}
60146005

60156006
static int perf_event_set_output(struct perf_event *event,
@@ -6057,20 +6048,14 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
60576048

60586049
case PERF_EVENT_IOC_SET_OUTPUT:
60596050
{
6060-
int ret;
6051+
CLASS(fd, output)(arg); // arg == -1 => empty
6052+
struct perf_event *output_event = NULL;
60616053
if (arg != -1) {
6062-
struct perf_event *output_event;
6063-
struct fd output;
6064-
ret = perf_fget_light(arg, &output);
6065-
if (ret)
6066-
return ret;
6054+
if (!is_perf_file(output))
6055+
return -EBADF;
60676056
output_event = fd_file(output)->private_data;
6068-
ret = perf_event_set_output(event, output_event);
6069-
fdput(output);
6070-
} else {
6071-
ret = perf_event_set_output(event, NULL);
60726057
}
6073-
return ret;
6058+
return perf_event_set_output(event, output_event);
60746059
}
60756060

60766061
case PERF_EVENT_IOC_SET_FILTER:
@@ -12664,7 +12649,6 @@ SYSCALL_DEFINE5(perf_event_open,
1266412649
struct perf_event_attr attr;
1266512650
struct perf_event_context *ctx;
1266612651
struct file *event_file = NULL;
12667-
struct fd group = EMPTY_FD;
1266812652
struct task_struct *task = NULL;
1266912653
struct pmu *pmu;
1267012654
int event_fd;
@@ -12735,10 +12719,12 @@ SYSCALL_DEFINE5(perf_event_open,
1273512719
if (event_fd < 0)
1273612720
return event_fd;
1273712721

12722+
CLASS(fd, group)(group_fd); // group_fd == -1 => empty
1273812723
if (group_fd != -1) {
12739-
err = perf_fget_light(group_fd, &group);
12740-
if (err)
12724+
if (!is_perf_file(group)) {
12725+
err = -EBADF;
1274112726
goto err_fd;
12727+
}
1274212728
group_leader = fd_file(group)->private_data;
1274312729
if (flags & PERF_FLAG_FD_OUTPUT)
1274412730
output_event = group_leader;
@@ -12750,7 +12736,7 @@ SYSCALL_DEFINE5(perf_event_open,
1275012736
task = find_lively_task_by_vpid(pid);
1275112737
if (IS_ERR(task)) {
1275212738
err = PTR_ERR(task);
12753-
goto err_group_fd;
12739+
goto err_fd;
1275412740
}
1275512741
}
1275612742

@@ -13017,12 +13003,11 @@ SYSCALL_DEFINE5(perf_event_open,
1301713003
mutex_unlock(&current->perf_event_mutex);
1301813004

1301913005
/*
13020-
* Drop the reference on the group_event after placing the
13021-
* new event on the sibling_list. This ensures destruction
13022-
* of the group leader will find the pointer to itself in
13023-
* perf_group_detach().
13006+
* File reference in group guarantees that group_leader has been
13007+
* kept alive until we place the new event on the sibling_list.
13008+
* This ensures destruction of the group leader will find
13009+
* the pointer to itself in perf_group_detach().
1302413010
*/
13025-
fdput(group);
1302613011
fd_install(event_fd, event_file);
1302713012
return event_fd;
1302813013

@@ -13041,8 +13026,6 @@ SYSCALL_DEFINE5(perf_event_open,
1304113026
err_task:
1304213027
if (task)
1304313028
put_task_struct(task);
13044-
err_group_fd:
13045-
fdput(group);
1304613029
err_fd:
1304713030
put_unused_fd(event_fd);
1304813031
return err;

0 commit comments

Comments
 (0)