Skip to content

Commit 00d9148

Browse files
spikehaxboe
authored andcommitted
io_uring/zcrx: share an ifq between rings
Add a way to share an ifq from a src ring that is real (i.e. bound to a HW RX queue) with other rings. This is done by passing a new flag IORING_ZCRX_IFQ_REG_IMPORT in the registration struct io_uring_zcrx_ifq_reg, alongside the fd of an exported zcrx ifq. Signed-off-by: David Wei <dw@davidwei.uk> Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 0926f94 commit 00d9148

2 files changed

Lines changed: 65 additions & 2 deletions

File tree

include/uapi/linux/io_uring.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,10 @@ struct io_uring_zcrx_area_reg {
10631063
__u64 __resv2[2];
10641064
};
10651065

1066+
enum zcrx_reg_flags {
1067+
ZCRX_REG_IMPORT = 1,
1068+
};
1069+
10661070
/*
10671071
* Argument for IORING_REGISTER_ZCRX_IFQ
10681072
*/

io_uring/zcrx.c

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,63 @@ static int zcrx_export(struct io_ring_ctx *ctx, struct io_zcrx_ifq *ifq,
660660
return 0;
661661
}
662662

663+
static int import_zcrx(struct io_ring_ctx *ctx,
664+
struct io_uring_zcrx_ifq_reg __user *arg,
665+
struct io_uring_zcrx_ifq_reg *reg)
666+
{
667+
struct io_zcrx_ifq *ifq;
668+
struct file *file;
669+
int fd, ret;
670+
u32 id;
671+
672+
if (!(ctx->flags & IORING_SETUP_DEFER_TASKRUN))
673+
return -EINVAL;
674+
if (!(ctx->flags & (IORING_SETUP_CQE32|IORING_SETUP_CQE_MIXED)))
675+
return -EINVAL;
676+
if (reg->if_rxq || reg->rq_entries || reg->area_ptr || reg->region_ptr)
677+
return -EINVAL;
678+
679+
fd = reg->if_idx;
680+
CLASS(fd, f)(fd);
681+
if (fd_empty(f))
682+
return -EBADF;
683+
684+
file = fd_file(f);
685+
if (file->f_op != &zcrx_box_fops || !file->private_data)
686+
return -EBADF;
687+
688+
ifq = file->private_data;
689+
refcount_inc(&ifq->refs);
690+
refcount_inc(&ifq->user_refs);
691+
692+
scoped_guard(mutex, &ctx->mmap_lock) {
693+
ret = xa_alloc(&ctx->zcrx_ctxs, &id, NULL, xa_limit_31b, GFP_KERNEL);
694+
if (ret)
695+
goto err;
696+
}
697+
698+
reg->zcrx_id = id;
699+
io_fill_zcrx_offsets(&reg->offsets);
700+
if (copy_to_user(arg, reg, sizeof(*reg))) {
701+
ret = -EFAULT;
702+
goto err_xa_erase;
703+
}
704+
705+
scoped_guard(mutex, &ctx->mmap_lock) {
706+
ret = -ENOMEM;
707+
if (xa_store(&ctx->zcrx_ctxs, id, ifq, GFP_KERNEL))
708+
goto err_xa_erase;
709+
}
710+
711+
return 0;
712+
err_xa_erase:
713+
scoped_guard(mutex, &ctx->mmap_lock)
714+
xa_erase(&ctx->zcrx_ctxs, id);
715+
err:
716+
zcrx_unregister(ifq);
717+
return ret;
718+
}
719+
663720
int io_register_zcrx_ifq(struct io_ring_ctx *ctx,
664721
struct io_uring_zcrx_ifq_reg __user *arg)
665722
{
@@ -685,11 +742,13 @@ int io_register_zcrx_ifq(struct io_ring_ctx *ctx,
685742
return -EINVAL;
686743
if (copy_from_user(&reg, arg, sizeof(reg)))
687744
return -EFAULT;
688-
if (copy_from_user(&rd, u64_to_user_ptr(reg.region_ptr), sizeof(rd)))
689-
return -EFAULT;
690745
if (!mem_is_zero(&reg.__resv, sizeof(reg.__resv)) ||
691746
reg.__resv2 || reg.zcrx_id)
692747
return -EINVAL;
748+
if (reg.flags & ZCRX_REG_IMPORT)
749+
return import_zcrx(ctx, arg, &reg);
750+
if (copy_from_user(&rd, u64_to_user_ptr(reg.region_ptr), sizeof(rd)))
751+
return -EFAULT;
693752
if (reg.if_rxq == -1 || !reg.rq_entries || reg.flags)
694753
return -EINVAL;
695754
if (reg.rq_entries > IO_RQ_MAX_ENTRIES) {

0 commit comments

Comments
 (0)