Skip to content

Commit a377132

Browse files
committed
io_uring/msg_ring: add support for sending a sync message
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. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 95d6c92 commit a377132

File tree

4 files changed

+63
-0
lines changed

4 files changed

+63
-0
lines changed

include/uapi/linux/io_uring.h

+3
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,9 @@ enum io_uring_register_op {
612612
/* clone registered buffers from source ring to current ring */
613613
IORING_REGISTER_CLONE_BUFFERS = 30,
614614

615+
/* send MSG_RING without having a ring */
616+
IORING_REGISTER_SEND_MSG_RING = 31,
617+
615618
/* this goes last */
616619
IORING_REGISTER_LAST,
617620

io_uring/msg_ring.c

+29
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,35 @@ int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags)
331331
return IOU_OK;
332332
}
333333

334+
int io_uring_sync_msg_ring(struct io_uring_sqe *sqe)
335+
{
336+
struct io_msg io_msg = { };
337+
struct fd f;
338+
int ret;
339+
340+
ret = __io_msg_ring_prep(&io_msg, sqe);
341+
if (unlikely(ret))
342+
return ret;
343+
344+
/*
345+
* Only data sending supported, not IORING_MSG_SEND_FD as that one
346+
* doesn't make sense without a source ring to send files from.
347+
*/
348+
if (io_msg.cmd != IORING_MSG_DATA)
349+
return -EINVAL;
350+
351+
ret = -EBADF;
352+
f = fdget(sqe->fd);
353+
if (fd_file(f)) {
354+
ret = -EBADFD;
355+
if (io_is_uring_fops(fd_file(f)))
356+
ret = __io_msg_ring_data(fd_file(f)->private_data,
357+
&io_msg, IO_URING_F_UNLOCKED);
358+
fdput(f);
359+
}
360+
return ret;
361+
}
362+
334363
void io_msg_cache_free(const void *entry)
335364
{
336365
struct io_kiocb *req = (struct io_kiocb *) entry;

io_uring/msg_ring.h

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22

3+
int io_uring_sync_msg_ring(struct io_uring_sqe *sqe);
34
int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
45
int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags);
56
void io_msg_ring_cleanup(struct io_kiocb *req);

io_uring/register.c

+30
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "kbuf.h"
2929
#include "napi.h"
3030
#include "eventfd.h"
31+
#include "msg_ring.h"
3132

3233
#define IORING_MAX_RESTRICTIONS (IORING_RESTRICTION_LAST + \
3334
IORING_REGISTER_LAST + IORING_OP_LAST)
@@ -588,6 +589,32 @@ struct file *io_uring_register_get_file(unsigned int fd, bool registered)
588589
return ERR_PTR(-EOPNOTSUPP);
589590
}
590591

592+
/*
593+
* "blind" registration opcodes are ones where there's no ring given, and
594+
* hence the source fd must be -1.
595+
*/
596+
static int io_uring_register_blind(unsigned int opcode, void __user *arg,
597+
unsigned int nr_args)
598+
{
599+
switch (opcode) {
600+
case IORING_REGISTER_SEND_MSG_RING: {
601+
struct io_uring_sqe sqe;
602+
603+
if (!arg || nr_args != 1)
604+
return -EINVAL;
605+
if (copy_from_user(&sqe, arg, sizeof(sqe)))
606+
return -EFAULT;
607+
/* no flags supported */
608+
if (sqe.flags)
609+
return -EINVAL;
610+
if (sqe.opcode == IORING_OP_MSG_RING)
611+
return io_uring_sync_msg_ring(&sqe);
612+
}
613+
}
614+
615+
return -EINVAL;
616+
}
617+
591618
SYSCALL_DEFINE4(io_uring_register, unsigned int, fd, unsigned int, opcode,
592619
void __user *, arg, unsigned int, nr_args)
593620
{
@@ -602,6 +629,9 @@ SYSCALL_DEFINE4(io_uring_register, unsigned int, fd, unsigned int, opcode,
602629
if (opcode >= IORING_REGISTER_LAST)
603630
return -EINVAL;
604631

632+
if (fd == -1)
633+
return io_uring_register_blind(opcode, arg, nr_args);
634+
605635
file = io_uring_register_get_file(fd, use_registered_ring);
606636
if (IS_ERR(file))
607637
return PTR_ERR(file);

0 commit comments

Comments
 (0)