xref: /linux/io_uring/epoll.c (revision cfa1539b24aff18ecb71c6334e7270f810d145bb)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
4 #include <linux/file.h>
5 #include <linux/fs.h>
6 #include <linux/uaccess.h>
7 #include <linux/io_uring.h>
8 #include <linux/eventpoll.h>
9 
10 #include <uapi/linux/io_uring.h>
11 
12 #include "io_uring.h"
13 #include "epoll.h"
14 
15 struct io_epoll {
16 	struct file			*file;
17 	int				epfd;
18 	int				op;
19 	int				fd;
20 	struct epoll_event		event;
21 };
22 
23 struct io_epoll_wait {
24 	struct file			*file;
25 	int				maxevents;
26 	struct epoll_event __user	*events;
27 };
28 
29 int io_epoll_ctl_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
30 {
31 	struct io_epoll *epoll = io_kiocb_to_cmd(req, struct io_epoll);
32 
33 	if (sqe->buf_index || sqe->splice_fd_in)
34 		return -EINVAL;
35 
36 	epoll->epfd = READ_ONCE(sqe->fd);
37 	epoll->op = READ_ONCE(sqe->len);
38 	epoll->fd = READ_ONCE(sqe->off);
39 
40 	if (ep_op_has_event(epoll->op)) {
41 		struct epoll_event __user *ev;
42 
43 		ev = u64_to_user_ptr(READ_ONCE(sqe->addr));
44 		if (copy_from_user(&epoll->event, ev, sizeof(*ev)))
45 			return -EFAULT;
46 	}
47 
48 	return 0;
49 }
50 
51 int io_epoll_ctl(struct io_kiocb *req, unsigned int issue_flags)
52 {
53 	struct io_epoll *ie = io_kiocb_to_cmd(req, struct io_epoll);
54 	bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
55 	struct epoll_key key;
56 	int ret;
57 
58 	CLASS(fd, f)(ie->epfd);
59 	if (fd_empty(f))
60 		return -EBADF;
61 
62 	CLASS(fd, tf)(ie->fd);
63 	if (fd_empty(tf))
64 		return -EBADF;
65 	/* disallow adding an epoll context to another epoll context */
66 	if (ie->op == EPOLL_CTL_ADD && is_file_epoll(fd_file(tf)))
67 		return -EINVAL;
68 
69 	key.file = fd_file(tf);
70 	key.fd = ie->fd;
71 	ret = do_epoll_ctl_file(fd_file(f), ie->op, &key, &ie->event, force_nonblock);
72 	if (force_nonblock && ret == -EAGAIN)
73 		return -EAGAIN;
74 
75 	if (ret < 0)
76 		req_set_fail(req);
77 	io_req_set_res(req, ret, 0);
78 	return IOU_COMPLETE;
79 }
80 
81 int io_epoll_wait_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
82 {
83 	struct io_epoll_wait *iew = io_kiocb_to_cmd(req, struct io_epoll_wait);
84 
85 	if (sqe->off || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
86 		return -EINVAL;
87 
88 	iew->maxevents = READ_ONCE(sqe->len);
89 	iew->events = u64_to_user_ptr(READ_ONCE(sqe->addr));
90 	return 0;
91 }
92 
93 int io_epoll_wait(struct io_kiocb *req, unsigned int issue_flags)
94 {
95 	struct io_epoll_wait *iew = io_kiocb_to_cmd(req, struct io_epoll_wait);
96 	int ret;
97 
98 	ret = epoll_sendevents(req->file, iew->events, iew->maxevents);
99 	if (ret == 0)
100 		return -EAGAIN;
101 	if (ret < 0)
102 		req_set_fail(req);
103 
104 	io_req_set_res(req, ret, 0);
105 	return IOU_COMPLETE;
106 }
107