Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/io_uring/epoll.c
26131 views
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_COMPLETE;
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_COMPLETE;
92
}
93
94