eventpoll: abstract out epoll_ctl() handler

No functional changes in this patch.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Jens Axboe 2020-01-08 14:35:13 -07:00
Родитель f86cd20c94
Коммит 58e41a44c4
1 изменённых файлов: 25 добавлений и 20 удалений

Просмотреть файл

@ -2074,27 +2074,15 @@ SYSCALL_DEFINE1(epoll_create, int, size)
return do_epoll_create(0); return do_epoll_create(0);
} }
/* static int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds)
* The following function implements the controller interface for
* the eventpoll file that enables the insertion/removal/change of
* file descriptors inside the interest set.
*/
SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
struct epoll_event __user *, event)
{ {
int error; int error;
int full_check = 0; int full_check = 0;
struct fd f, tf; struct fd f, tf;
struct eventpoll *ep; struct eventpoll *ep;
struct epitem *epi; struct epitem *epi;
struct epoll_event epds;
struct eventpoll *tep = NULL; struct eventpoll *tep = NULL;
error = -EFAULT;
if (ep_op_has_event(op) &&
copy_from_user(&epds, event, sizeof(struct epoll_event)))
goto error_return;
error = -EBADF; error = -EBADF;
f = fdget(epfd); f = fdget(epfd);
if (!f.file) if (!f.file)
@ -2112,7 +2100,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
/* Check if EPOLLWAKEUP is allowed */ /* Check if EPOLLWAKEUP is allowed */
if (ep_op_has_event(op)) if (ep_op_has_event(op))
ep_take_care_of_epollwakeup(&epds); ep_take_care_of_epollwakeup(epds);
/* /*
* We have to check that the file structure underneath the file descriptor * We have to check that the file structure underneath the file descriptor
@ -2128,11 +2116,11 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
* so EPOLLEXCLUSIVE is not allowed for a EPOLL_CTL_MOD operation. * so EPOLLEXCLUSIVE is not allowed for a EPOLL_CTL_MOD operation.
* Also, we do not currently supported nested exclusive wakeups. * Also, we do not currently supported nested exclusive wakeups.
*/ */
if (ep_op_has_event(op) && (epds.events & EPOLLEXCLUSIVE)) { if (ep_op_has_event(op) && (epds->events & EPOLLEXCLUSIVE)) {
if (op == EPOLL_CTL_MOD) if (op == EPOLL_CTL_MOD)
goto error_tgt_fput; goto error_tgt_fput;
if (op == EPOLL_CTL_ADD && (is_file_epoll(tf.file) || if (op == EPOLL_CTL_ADD && (is_file_epoll(tf.file) ||
(epds.events & ~EPOLLEXCLUSIVE_OK_BITS))) (epds->events & ~EPOLLEXCLUSIVE_OK_BITS)))
goto error_tgt_fput; goto error_tgt_fput;
} }
@ -2192,8 +2180,8 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
switch (op) { switch (op) {
case EPOLL_CTL_ADD: case EPOLL_CTL_ADD:
if (!epi) { if (!epi) {
epds.events |= EPOLLERR | EPOLLHUP; epds->events |= EPOLLERR | EPOLLHUP;
error = ep_insert(ep, &epds, tf.file, fd, full_check); error = ep_insert(ep, epds, tf.file, fd, full_check);
} else } else
error = -EEXIST; error = -EEXIST;
if (full_check) if (full_check)
@ -2208,8 +2196,8 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
case EPOLL_CTL_MOD: case EPOLL_CTL_MOD:
if (epi) { if (epi) {
if (!(epi->event.events & EPOLLEXCLUSIVE)) { if (!(epi->event.events & EPOLLEXCLUSIVE)) {
epds.events |= EPOLLERR | EPOLLHUP; epds->events |= EPOLLERR | EPOLLHUP;
error = ep_modify(ep, epi, &epds); error = ep_modify(ep, epi, epds);
} }
} else } else
error = -ENOENT; error = -ENOENT;
@ -2231,6 +2219,23 @@ error_return:
return error; return error;
} }
/*
* The following function implements the controller interface for
* the eventpoll file that enables the insertion/removal/change of
* file descriptors inside the interest set.
*/
SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
struct epoll_event __user *, event)
{
struct epoll_event epds;
if (ep_op_has_event(op) &&
copy_from_user(&epds, event, sizeof(struct epoll_event)))
return -EFAULT;
return do_epoll_ctl(epfd, op, fd, &epds);
}
/* /*
* Implement the event wait interface for the eventpoll file. It is the kernel * Implement the event wait interface for the eventpoll file. It is the kernel
* part of the user space epoll_wait(2). * part of the user space epoll_wait(2).