* [PATCHSET v2 0/2] Add support for sending sync MSG_RING @ 2024-09-24 11:57 Jens Axboe 2024-09-24 11:57 ` [PATCH 1/2] io_uring/msg_ring: refactor a few helper functions Jens Axboe ` (2 more replies) 0 siblings, 3 replies; 5+ messages in thread From: Jens Axboe @ 2024-09-24 11:57 UTC (permalink / raw) To: io-uring Hi, Over the last 6 months, several people have asked for if it's possible to send a MSG_RING request to a ring without having a source ring to do it from. The answer is no, as you'd need a source ring to submit such a request in the first place. However, we can easily support this use case of allowing someone to send a message to a ring that their own, without needing to setup a source ring just for that alone. This adds support for "blind" register opcodes for io_uring_register(2), which simply means that there's no io_uring ring fd being passed in. The 'fd' must be set to -1. IORING_REGISTER_SEND_MSG_RING is added, which simply takes a pointer to an io_uring_sqe. That sqe must be setup just like an sqe that would have been otherwise prepared via sending over a normal ring. An sqe pointer is used to keep the app side trivial, as they can just put an sqe on the stack, initialize it to zeroes, and then call io_uring_prep_msg_ring() on it like they would for an async MSG_RING. Once setup, the app can call: io_uring_register(-1, IORING_REGISTER_SEND_MSG_RING, &sqe, 1); which would like like: io_uring_send_msg_ring_sync(&sqe); if using linuring. The return value of this syscall is what would have been in cqe->res using the async approach - 0 on success, or a negative error value in case of failure. Patches can also be found in a kernel branch here: https://git.kernel.dk/cgit/linux/log/?h=io_uring-sync-msg_ring and a liburing branch with support (and test cases) is here: https://git.kernel.dk/cgit/liburing/log/?h=sync-msg Since v1: - Cleanups - Sanity check sqe->flags and the actual opcode - Use fdget/fdput - Add a few comments include/uapi/linux/io_uring.h | 3 ++ io_uring/msg_ring.c | 60 ++++++++++++++++++++++++++++------- io_uring/msg_ring.h | 1 + io_uring/register.c | 30 ++++++++++++++++++ 4 files changed, 83 insertions(+), 11 deletions(-) -- Jens Axboe ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] io_uring/msg_ring: refactor a few helper functions 2024-09-24 11:57 [PATCHSET v2 0/2] Add support for sending sync MSG_RING Jens Axboe @ 2024-09-24 11:57 ` Jens Axboe 2024-09-24 11:57 ` [PATCH 2/2] io_uring/msg_ring: add support for sending a sync message Jens Axboe 2024-09-30 14:28 ` [PATCHSET v2 0/2] Add support for sending sync MSG_RING Jens Axboe 2 siblings, 0 replies; 5+ messages in thread From: Jens Axboe @ 2024-09-24 11:57 UTC (permalink / raw) To: io-uring; +Cc: Jens Axboe Mostly just to skip them taking an io_kiocb, rather just pass in the ctx and io_msg directly. In preparation for being able to issue a MSG_RING request without having an io_kiocb. No functional changes in this patch. Signed-off-by: Jens Axboe <[email protected]> --- io_uring/msg_ring.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c index 7fd9badcfaf8..b8c527f08cd5 100644 --- a/io_uring/msg_ring.c +++ b/io_uring/msg_ring.c @@ -116,14 +116,13 @@ static struct io_kiocb *io_msg_get_kiocb(struct io_ring_ctx *ctx) return kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO); } -static int io_msg_data_remote(struct io_kiocb *req) +static int io_msg_data_remote(struct io_ring_ctx *target_ctx, + struct io_msg *msg) { - struct io_ring_ctx *target_ctx = req->file->private_data; - struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg); struct io_kiocb *target; u32 flags = 0; - target = io_msg_get_kiocb(req->ctx); + target = io_msg_get_kiocb(target_ctx); if (unlikely(!target)) return -ENOMEM; @@ -134,10 +133,9 @@ static int io_msg_data_remote(struct io_kiocb *req) msg->user_data); } -static int io_msg_ring_data(struct io_kiocb *req, unsigned int issue_flags) +static int __io_msg_ring_data(struct io_ring_ctx *target_ctx, + struct io_msg *msg, unsigned int issue_flags) { - struct io_ring_ctx *target_ctx = req->file->private_data; - struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg); u32 flags = 0; int ret; @@ -149,7 +147,7 @@ static int io_msg_ring_data(struct io_kiocb *req, unsigned int issue_flags) return -EBADFD; if (io_msg_need_remote(target_ctx)) - return io_msg_data_remote(req); + return io_msg_data_remote(target_ctx, msg); if (msg->flags & IORING_MSG_RING_FLAGS_PASS) flags = msg->cqe_flags; @@ -166,6 +164,14 @@ static int io_msg_ring_data(struct io_kiocb *req, unsigned int issue_flags) return ret; } +static int io_msg_ring_data(struct io_kiocb *req, unsigned int issue_flags) +{ + struct io_ring_ctx *target_ctx = req->file->private_data; + struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg); + + return __io_msg_ring_data(target_ctx, msg, issue_flags); +} + static struct file *io_msg_grab_file(struct io_kiocb *req, unsigned int issue_flags) { struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg); @@ -271,10 +277,8 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags) return io_msg_install_complete(req, issue_flags); } -int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) +static int __io_msg_ring_prep(struct io_msg *msg, const struct io_uring_sqe *sqe) { - struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg); - if (unlikely(sqe->buf_index || sqe->personality)) return -EINVAL; @@ -291,6 +295,11 @@ int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) return 0; } +int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) +{ + return __io_msg_ring_prep(io_kiocb_to_cmd(req, struct io_msg), sqe); +} + int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags) { struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg); -- 2.45.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] io_uring/msg_ring: add support for sending a sync message 2024-09-24 11:57 [PATCHSET v2 0/2] Add support for sending sync MSG_RING Jens Axboe 2024-09-24 11:57 ` [PATCH 1/2] io_uring/msg_ring: refactor a few helper functions Jens Axboe @ 2024-09-24 11:57 ` Jens Axboe 2024-09-30 14:28 ` [PATCHSET v2 0/2] Add support for sending sync MSG_RING Jens Axboe 2 siblings, 0 replies; 5+ messages in thread From: Jens Axboe @ 2024-09-24 11:57 UTC (permalink / raw) To: io-uring; +Cc: Jens Axboe Normally MSG_RING requires both a source and a destination ring. But some users don't always have a ring avilable to send a message from, yet they still need to notify a target ring. Add support for using io_uring_register(2) without having a source ring, using a file descriptor of -1 for that. Internally those are called blind registration opcodes. Implement IORING_REGISTER_SEND_MSG_RING as a blind opcode, which simply takes an sqe that the application can put on the stack and use the normal liburing helpers to initialize it. Then the app can call: io_uring_register(-1, IORING_REGISTER_SEND_MSG_RING, &sqe, 1); and get the same behavior in terms of the target, where a CQE is posted with the details given in the sqe. For now this takes a single sqe pointer argument, and hence arg must be set to that, and nr_args must be 1. Could easily be extended to take an array of sqes, but for now let's keep it simple. Signed-off-by: Jens Axboe <[email protected]> --- include/uapi/linux/io_uring.h | 3 +++ io_uring/msg_ring.c | 29 +++++++++++++++++++++++++++++ io_uring/msg_ring.h | 1 + io_uring/register.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+) diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h index 1fe79e750470..86cb385fe0b5 100644 --- a/include/uapi/linux/io_uring.h +++ b/include/uapi/linux/io_uring.h @@ -612,6 +612,9 @@ enum io_uring_register_op { /* clone registered buffers from source ring to current ring */ IORING_REGISTER_CLONE_BUFFERS = 30, + /* send MSG_RING without having a ring */ + IORING_REGISTER_SEND_MSG_RING = 31, + /* this goes last */ IORING_REGISTER_LAST, diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c index b8c527f08cd5..edea1ffd501c 100644 --- a/io_uring/msg_ring.c +++ b/io_uring/msg_ring.c @@ -331,6 +331,35 @@ int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags) return IOU_OK; } +int io_uring_sync_msg_ring(struct io_uring_sqe *sqe) +{ + struct io_msg io_msg = { }; + struct fd f; + int ret; + + ret = __io_msg_ring_prep(&io_msg, sqe); + if (unlikely(ret)) + return ret; + + /* + * Only data sending supported, not IORING_MSG_SEND_FD as that one + * doesn't make sense without a source ring to send files from. + */ + if (io_msg.cmd != IORING_MSG_DATA) + return -EINVAL; + + ret = -EBADF; + f = fdget(sqe->fd); + if (fd_file(f)) { + ret = -EBADFD; + if (io_is_uring_fops(fd_file(f))) + ret = __io_msg_ring_data(fd_file(f)->private_data, + &io_msg, IO_URING_F_UNLOCKED); + fdput(f); + } + return ret; +} + void io_msg_cache_free(const void *entry) { struct io_kiocb *req = (struct io_kiocb *) entry; diff --git a/io_uring/msg_ring.h b/io_uring/msg_ring.h index 3030f3942f0f..38e7f8f0c944 100644 --- a/io_uring/msg_ring.h +++ b/io_uring/msg_ring.h @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 +int io_uring_sync_msg_ring(struct io_uring_sqe *sqe); int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags); void io_msg_ring_cleanup(struct io_kiocb *req); diff --git a/io_uring/register.c b/io_uring/register.c index eca26d4884d9..52b2f9b74af8 100644 --- a/io_uring/register.c +++ b/io_uring/register.c @@ -28,6 +28,7 @@ #include "kbuf.h" #include "napi.h" #include "eventfd.h" +#include "msg_ring.h" #define IORING_MAX_RESTRICTIONS (IORING_RESTRICTION_LAST + \ IORING_REGISTER_LAST + IORING_OP_LAST) @@ -588,6 +589,32 @@ struct file *io_uring_register_get_file(unsigned int fd, bool registered) return ERR_PTR(-EOPNOTSUPP); } +/* + * "blind" registration opcodes are ones where there's no ring given, and + * hence the source fd must be -1. + */ +static int io_uring_register_blind(unsigned int opcode, void __user *arg, + unsigned int nr_args) +{ + switch (opcode) { + case IORING_REGISTER_SEND_MSG_RING: { + struct io_uring_sqe sqe; + + if (!arg || nr_args != 1) + return -EINVAL; + if (copy_from_user(&sqe, arg, sizeof(sqe))) + return -EFAULT; + /* no flags supported */ + if (sqe.flags) + return -EINVAL; + if (sqe.opcode == IORING_OP_MSG_RING) + return io_uring_sync_msg_ring(&sqe); + } + } + + return -EINVAL; +} + SYSCALL_DEFINE4(io_uring_register, unsigned int, fd, unsigned int, opcode, void __user *, arg, unsigned int, nr_args) { @@ -602,6 +629,9 @@ SYSCALL_DEFINE4(io_uring_register, unsigned int, fd, unsigned int, opcode, if (opcode >= IORING_REGISTER_LAST) return -EINVAL; + if (fd == -1) + return io_uring_register_blind(opcode, arg, nr_args); + file = io_uring_register_get_file(fd, use_registered_ring); if (IS_ERR(file)) return PTR_ERR(file); -- 2.45.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCHSET v2 0/2] Add support for sending sync MSG_RING 2024-09-24 11:57 [PATCHSET v2 0/2] Add support for sending sync MSG_RING Jens Axboe 2024-09-24 11:57 ` [PATCH 1/2] io_uring/msg_ring: refactor a few helper functions Jens Axboe 2024-09-24 11:57 ` [PATCH 2/2] io_uring/msg_ring: add support for sending a sync message Jens Axboe @ 2024-09-30 14:28 ` Jens Axboe 2 siblings, 0 replies; 5+ messages in thread From: Jens Axboe @ 2024-09-30 14:28 UTC (permalink / raw) To: io-uring, Jens Axboe On Tue, 24 Sep 2024 05:57:29 -0600, Jens Axboe wrote: > Over the last 6 months, several people have asked for if it's possible > to send a MSG_RING request to a ring without having a source ring to do > it from. The answer is no, as you'd need a source ring to submit such a > request in the first place. However, we can easily support this use case > of allowing someone to send a message to a ring that their own, without > needing to setup a source ring just for that alone. > > [...] Applied, thanks! [1/2] io_uring/msg_ring: refactor a few helper functions commit: 6516c5008c88eda9137f0985f419e40d3fc7cee1 [2/2] io_uring/msg_ring: add support for sending a sync message commit: d1e55003c13ca95878afe380ad3da89d37d63b1e Best regards, -- Jens Axboe ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCHSET 0/2] Add support for sending sync MSG_RING @ 2024-09-24 4:59 Jens Axboe 2024-09-24 4:59 ` [PATCH 2/2] io_uring/msg_ring: add support for sending a sync message Jens Axboe 0 siblings, 1 reply; 5+ messages in thread From: Jens Axboe @ 2024-09-24 4:59 UTC (permalink / raw) To: io-uring Hi, Over the last 6 months, several people have asked for if it's possible to send a MSG_RING request to a ring without having a source ring to do it from. The answer is no, as you'd need a source ring to submit such a request in the first place. However, we can easily support this use case of allowing someone to send a message to a ring that their own, without needing to setup a source ring just for that alone. This adds support for "blind" register opcodes for io_uring_register(2), which simply means that there's no io_uring ring fd being passed in. The 'fd' must be set to -1. IORING_REGISTER_SEND_MSG_RING is added, which simply takes a pointer to an io_uring_sqe. That sqe must be setup just like an sqe that would have been otherwise prepared via sending over a normal ring. An sqe pointer is used to keep the app side trivial, as they can just put an sqe on the stack, initialize it to zeroes, and then call io_uring_prep_msg_ring() on it like they would for an async MSG_RING. Once setup, the app can call: io_uring_register(-1, IORING_REGISTER_SEND_MSG_RING, &sqe, 1); which would like like: io_uring_send_msg_ring_sync(&sqe); if using linuring. The return value of this syscall is what would have been in cqe->res using the async approach - 0 on success, or a negative error value in case of failure. Patches can also be found in a kernel branch here: https://git.kernel.dk/cgit/linux/log/?h=io_uring-sync-msg_ring and a liburing branch with support (and test cases) is here: https://git.kernel.dk/cgit/liburing/log/?h=sync-msg include/uapi/linux/io_uring.h | 3 ++ io_uring/msg_ring.c | 60 ++++++++++++++++++++++++++++------- io_uring/msg_ring.h | 1 + io_uring/register.c | 27 ++++++++++++++++ 4 files changed, 80 insertions(+), 11 deletions(-) -- Jens Axboe ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] io_uring/msg_ring: add support for sending a sync message 2024-09-24 4:59 [PATCHSET " Jens Axboe @ 2024-09-24 4:59 ` Jens Axboe 0 siblings, 0 replies; 5+ messages in thread From: Jens Axboe @ 2024-09-24 4:59 UTC (permalink / raw) To: io-uring; +Cc: Jens Axboe Normally MSG_RING requires both a source and a destination ring. But some users don't always have a ring avilable to send a message from, yet they still need to notify a target ring. Add support for using io_uring_register(2) without having a source ring, using a file descriptor of -1 for that. Internally those are called blind registration opcodes. Implement IORING_REGISTER_SEND_MSG_RING as a blind opcode, which simply takes an sqe that the application can put on the stack and use the normal liburing helpers to get it setup. Then it can call: io_uring_register(-1, IORING_REGISTER_SEND_MSG_RING, &sqe, 1); and get the same behavior in terms of the target where a CQE is posted with the details given in the sqe. For now this takes a single sqe pointer argument, and hence arg must be set to that, and nr_args must be 1. Could easily be extended to take an array of sqes, but for now let's keep it simple. Signed-off-by: Jens Axboe <[email protected]> --- include/uapi/linux/io_uring.h | 3 +++ io_uring/msg_ring.c | 27 +++++++++++++++++++++++++++ io_uring/msg_ring.h | 1 + io_uring/register.c | 27 +++++++++++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h index 1fe79e750470..86cb385fe0b5 100644 --- a/include/uapi/linux/io_uring.h +++ b/include/uapi/linux/io_uring.h @@ -612,6 +612,9 @@ enum io_uring_register_op { /* clone registered buffers from source ring to current ring */ IORING_REGISTER_CLONE_BUFFERS = 30, + /* send MSG_RING without having a ring */ + IORING_REGISTER_SEND_MSG_RING = 31, + /* this goes last */ IORING_REGISTER_LAST, diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c index ea4c7a7691e0..e64be6260cc6 100644 --- a/io_uring/msg_ring.c +++ b/io_uring/msg_ring.c @@ -333,6 +333,33 @@ int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags) return IOU_OK; } +int io_uring_sync_msg_ring(struct io_uring_sqe *sqe) +{ + struct io_msg io_msg = { }; + struct fd f; + int ret; + + ret =__io_msg_ring_prep(&io_msg, sqe); + if (unlikely(ret)) + return ret; + + if (io_msg.cmd != IORING_MSG_DATA) + return -EINVAL; + + f = fdget(sqe->fd); + if (!fd_file(f)) + return -EBADF; + + ret = -EBADFD; + if (!io_is_uring_fops(fd_file(f))) + goto err; + + ret = __io_msg_ring_data(fd_file(f)->private_data, &io_msg, 0); +err: + fdput(f); + return ret; +} + void io_msg_cache_free(const void *entry) { struct io_kiocb *req = (struct io_kiocb *) entry; diff --git a/io_uring/msg_ring.h b/io_uring/msg_ring.h index 3030f3942f0f..38e7f8f0c944 100644 --- a/io_uring/msg_ring.h +++ b/io_uring/msg_ring.h @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 +int io_uring_sync_msg_ring(struct io_uring_sqe *sqe); int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags); void io_msg_ring_cleanup(struct io_kiocb *req); diff --git a/io_uring/register.c b/io_uring/register.c index eca26d4884d9..2daa6f48a178 100644 --- a/io_uring/register.c +++ b/io_uring/register.c @@ -28,6 +28,7 @@ #include "kbuf.h" #include "napi.h" #include "eventfd.h" +#include "msg_ring.h" #define IORING_MAX_RESTRICTIONS (IORING_RESTRICTION_LAST + \ IORING_REGISTER_LAST + IORING_OP_LAST) @@ -588,6 +589,29 @@ struct file *io_uring_register_get_file(unsigned int fd, bool registered) return ERR_PTR(-EOPNOTSUPP); } +/* + * "blind" registration opcodes are ones where there's no ring given, and + * hence the source fd must be -1. + */ +static int io_uring_register_blind(unsigned int opcode, void __user *arg, + unsigned int nr_args) +{ + switch (opcode) { + case IORING_REGISTER_SEND_MSG_RING: { + struct io_uring_sqe sqe; + + if (!arg || nr_args != 1) + return -EINVAL; + if (copy_from_user(&sqe, arg, sizeof(sqe))) + return -EFAULT; + if (sqe.opcode == IORING_OP_MSG_RING) + return io_uring_sync_msg_ring(&sqe); + } + } + + return -EINVAL; +} + SYSCALL_DEFINE4(io_uring_register, unsigned int, fd, unsigned int, opcode, void __user *, arg, unsigned int, nr_args) { @@ -602,6 +626,9 @@ SYSCALL_DEFINE4(io_uring_register, unsigned int, fd, unsigned int, opcode, if (opcode >= IORING_REGISTER_LAST) return -EINVAL; + if (fd == -1) + return io_uring_register_blind(opcode, arg, nr_args); + file = io_uring_register_get_file(fd, use_registered_ring); if (IS_ERR(file)) return PTR_ERR(file); -- 2.45.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-09-30 14:28 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-09-24 11:57 [PATCHSET v2 0/2] Add support for sending sync MSG_RING Jens Axboe 2024-09-24 11:57 ` [PATCH 1/2] io_uring/msg_ring: refactor a few helper functions Jens Axboe 2024-09-24 11:57 ` [PATCH 2/2] io_uring/msg_ring: add support for sending a sync message Jens Axboe 2024-09-30 14:28 ` [PATCHSET v2 0/2] Add support for sending sync MSG_RING Jens Axboe -- strict thread matches above, loose matches on Subject: below -- 2024-09-24 4:59 [PATCHSET " Jens Axboe 2024-09-24 4:59 ` [PATCH 2/2] io_uring/msg_ring: add support for sending a sync message Jens Axboe
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox