This adds support for async msgrcv through io_uring. All the information needed after punt to async context is already stored in the io_msgrcv_prep call. Signed-off-by: Usama Arif <usama.arif@xxxxxxxxxxxxx> --- fs/io_uring.c | 45 +++++++++++++++++++++++++++++++++++ include/uapi/linux/io_uring.h | 1 + 2 files changed, 46 insertions(+) diff --git a/fs/io_uring.c b/fs/io_uring.c index 5949fcadb380..124914d8ee50 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -1217,6 +1217,8 @@ static const struct io_op_def io_op_defs[] = { [IORING_OP_MSGSND] = { .async_size = sizeof(struct io_async_msg_msg), }, + [IORING_OP_MSGRCV] = { + }, [IORING_OP_TIMEOUT] = { .audit_skip = 1, .async_size = sizeof(struct io_timeout_data), @@ -1424,6 +1426,8 @@ const char *io_uring_get_opcode(u8 opcode) return "RECVMSG"; case IORING_OP_MSGSND: return "MSGSND"; + case IORING_OP_MSGRCV: + return "MSGRCV"; case IORING_OP_TIMEOUT: return "TIMEOUT"; case IORING_OP_TIMEOUT_REMOVE: @@ -6275,6 +6279,42 @@ static int io_msgsnd(struct io_kiocb *req, unsigned int issue_flags) io_req_complete(req, ret); return ret; } + +static int io_msgrcv_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) +{ + struct io_msg_sr *msg_sr = &req->msg_sr; + + if (unlikely(sqe->file_index)) + return -EINVAL; + + msg_sr->msq_id = READ_ONCE(sqe->fd); + msg_sr->msg_p = u64_to_user_ptr(READ_ONCE(sqe->addr)); + msg_sr->msg_type = READ_ONCE(sqe->off); + msg_sr->msg_sz = READ_ONCE(sqe->len); + msg_sr->msg_flags = READ_ONCE(sqe->msg_flags); + return 0; +} + +static int io_msgrcv(struct io_kiocb *req, unsigned int issue_flags) +{ + struct io_msg_sr *msg_sr = &req->msg_sr; + int ret; + int flags; + bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; + + if (force_nonblock) + flags = msg_sr->msg_flags | IPC_NOWAIT; + + ret = ksys_msgrcv(msg_sr->msq_id, msg_sr->msg_p, msg_sr->msg_sz, + msg_sr->msg_type, flags); + + if (ret == -ENOMSG) + return -EAGAIN; + + io_req_complete(req, ret); + return 0; +} + static int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags) { struct io_async_msghdr iomsg, *kmsg; @@ -8289,6 +8329,8 @@ static int io_req_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) return io_uring_cmd_prep(req, sqe); case IORING_OP_MSGSND: return io_msgsnd_prep(req, sqe); + case IORING_OP_MSGRCV: + return io_msgrcv_prep(req, sqe); } printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", @@ -8636,6 +8678,9 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags) case IORING_OP_MSGSND: ret = io_msgsnd(req, issue_flags); break; + case IORING_OP_MSGRCV: + ret = io_msgrcv(req, issue_flags); + break; default: ret = -EINVAL; break; diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h index fa29bd96207d..b5dcaac30d9d 100644 --- a/include/uapi/linux/io_uring.h +++ b/include/uapi/linux/io_uring.h @@ -191,6 +191,7 @@ enum io_uring_op { IORING_OP_SOCKET, IORING_OP_URING_CMD, IORING_OP_MSGSND, + IORING_OP_MSGRCV, /* this goes last, obviously */ IORING_OP_LAST, -- 2.25.1