162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/kernel.h>
362306a36Sopenharmony_ci#include <linux/errno.h>
462306a36Sopenharmony_ci#include <linux/file.h>
562306a36Sopenharmony_ci#include <linux/fs.h>
662306a36Sopenharmony_ci#include <linux/uaccess.h>
762306a36Sopenharmony_ci#include <linux/io_uring.h>
862306a36Sopenharmony_ci#include <linux/eventpoll.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <uapi/linux/io_uring.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "io_uring.h"
1362306a36Sopenharmony_ci#include "epoll.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#if defined(CONFIG_EPOLL)
1662306a36Sopenharmony_cistruct io_epoll {
1762306a36Sopenharmony_ci	struct file			*file;
1862306a36Sopenharmony_ci	int				epfd;
1962306a36Sopenharmony_ci	int				op;
2062306a36Sopenharmony_ci	int				fd;
2162306a36Sopenharmony_ci	struct epoll_event		event;
2262306a36Sopenharmony_ci};
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ciint io_epoll_ctl_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	struct io_epoll *epoll = io_kiocb_to_cmd(req, struct io_epoll);
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	if (sqe->buf_index || sqe->splice_fd_in)
2962306a36Sopenharmony_ci		return -EINVAL;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	epoll->epfd = READ_ONCE(sqe->fd);
3262306a36Sopenharmony_ci	epoll->op = READ_ONCE(sqe->len);
3362306a36Sopenharmony_ci	epoll->fd = READ_ONCE(sqe->off);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	if (ep_op_has_event(epoll->op)) {
3662306a36Sopenharmony_ci		struct epoll_event __user *ev;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci		ev = u64_to_user_ptr(READ_ONCE(sqe->addr));
3962306a36Sopenharmony_ci		if (copy_from_user(&epoll->event, ev, sizeof(*ev)))
4062306a36Sopenharmony_ci			return -EFAULT;
4162306a36Sopenharmony_ci	}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	return 0;
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ciint io_epoll_ctl(struct io_kiocb *req, unsigned int issue_flags)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	struct io_epoll *ie = io_kiocb_to_cmd(req, struct io_epoll);
4962306a36Sopenharmony_ci	int ret;
5062306a36Sopenharmony_ci	bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	ret = do_epoll_ctl(ie->epfd, ie->op, ie->fd, &ie->event, force_nonblock);
5362306a36Sopenharmony_ci	if (force_nonblock && ret == -EAGAIN)
5462306a36Sopenharmony_ci		return -EAGAIN;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	if (ret < 0)
5762306a36Sopenharmony_ci		req_set_fail(req);
5862306a36Sopenharmony_ci	io_req_set_res(req, ret, 0);
5962306a36Sopenharmony_ci	return IOU_OK;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci#endif
62