Commit | Line | Data |
---|---|---|
36404b09 JA |
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/slab.h> | |
6 | #include <linux/io_uring.h> | |
7 | ||
8 | #include <uapi/linux/io_uring.h> | |
9 | ||
10 | #include "io_uring_types.h" | |
11 | #include "io_uring.h" | |
12 | #include "msg_ring.h" | |
13 | ||
14 | struct io_msg { | |
15 | struct file *file; | |
16 | u64 user_data; | |
17 | u32 len; | |
18 | }; | |
19 | ||
20 | int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) | |
21 | { | |
22 | struct io_msg *msg = io_kiocb_to_cmd(req); | |
23 | ||
24 | if (unlikely(sqe->addr || sqe->rw_flags || sqe->splice_fd_in || | |
25 | sqe->buf_index || sqe->personality)) | |
26 | return -EINVAL; | |
27 | ||
28 | msg->user_data = READ_ONCE(sqe->off); | |
29 | msg->len = READ_ONCE(sqe->len); | |
30 | return 0; | |
31 | } | |
32 | ||
33 | int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags) | |
34 | { | |
35 | struct io_msg *msg = io_kiocb_to_cmd(req); | |
36 | struct io_ring_ctx *target_ctx; | |
37 | bool filled; | |
38 | int ret; | |
39 | ||
40 | ret = -EBADFD; | |
41 | if (!io_is_uring_fops(req->file)) | |
42 | goto done; | |
43 | ||
44 | ret = -EOVERFLOW; | |
45 | target_ctx = req->file->private_data; | |
46 | ||
47 | spin_lock(&target_ctx->completion_lock); | |
48 | filled = io_fill_cqe_aux(target_ctx, msg->user_data, msg->len, 0); | |
49 | io_commit_cqring(target_ctx); | |
50 | spin_unlock(&target_ctx->completion_lock); | |
51 | ||
52 | if (filled) { | |
53 | io_cqring_ev_posted(target_ctx); | |
54 | ret = 0; | |
55 | } | |
56 | ||
57 | done: | |
58 | if (ret < 0) | |
59 | req_set_fail(req); | |
60 | io_req_set_res(req, ret, 0); | |
61 | /* put file to avoid an attempt to IOPOLL the req */ | |
62 | io_put_file(req->file); | |
63 | req->file = NULL; | |
64 | return IOU_OK; | |
65 | } |