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