xref: /linux/io_uring/epoll.c (revision 4f9786035f9e519db41375818e1d0b5f20da2f10)
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 	int ret;
55 	bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
56 
57 	ret = do_epoll_ctl(ie->epfd, ie->op, ie->fd, &ie->event, force_nonblock);
58 	if (force_nonblock && ret == -EAGAIN)
59 		return -EAGAIN;
60 
61 	if (ret < 0)
62 		req_set_fail(req);
63 	io_req_set_res(req, ret, 0);
64 	return IOU_OK;
65 }
66 
67 int io_epoll_wait_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
68 {
69 	struct io_epoll_wait *iew = io_kiocb_to_cmd(req, struct io_epoll_wait);
70 
71 	if (sqe->off || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
72 		return -EINVAL;
73 
74 	iew->maxevents = READ_ONCE(sqe->len);
75 	iew->events = u64_to_user_ptr(READ_ONCE(sqe->addr));
76 	return 0;
77 }
78 
79 int io_epoll_wait(struct io_kiocb *req, unsigned int issue_flags)
80 {
81 	struct io_epoll_wait *iew = io_kiocb_to_cmd(req, struct io_epoll_wait);
82 	int ret;
83 
84 	ret = epoll_sendevents(req->file, iew->events, iew->maxevents);
85 	if (ret == 0)
86 		return -EAGAIN;
87 	if (ret < 0)
88 		req_set_fail(req);
89 
90 	io_req_set_res(req, ret, 0);
91 	return IOU_OK;
92 }
93