.c +++ b/io_uring/zcrx.c @@ -22,10 +22,10 @@ #include #include "io_uring.h" -#include "kbuf.h" #include "memmap.h" #include "zcrx.h" #include "rsrc.h" +#include "register.h" #define IO_ZCRX_AREA_SUPPORTED_FLAGS (IORING_ZCRX_AREA_DMABUF) @@ -541,6 +541,74 @@ struct io_mapped_region *io_zcrx_get_region(struct io_ring_ctx *ctx, return ifq ? &ifq->region : NULL; } +static int io_proxy_zcrx_ifq(struct io_ring_ctx *ctx, + struct io_uring_zcrx_ifq_reg __user *arg, + struct io_uring_zcrx_ifq_reg *reg) +{ + struct io_zcrx_ifq *ifq, *src_ifq; + struct io_ring_ctx *src_ctx; + struct file *file; + int src_fd, ret; + u32 src_id, id; + + src_fd = reg->if_idx; + src_id = reg->if_rxq; + + file = io_uring_register_get_file(src_fd, false); + if (IS_ERR(file)) + return PTR_ERR(file); + + src_ctx = file->private_data; + if (src_ctx == ctx) + return -EBADFD; + + mutex_unlock(&ctx->uring_lock); + io_lock_two_rings(ctx, src_ctx); + + ret = -EINVAL; + src_ifq = xa_load(&src_ctx->zcrx_ctxs, src_id); + if (!src_ifq || src_ifq->proxy) + goto err_unlock; + + percpu_ref_get(&src_ctx->refs); + refcount_inc(&src_ifq->refs); + + ifq = kzalloc(sizeof(*ifq), GFP_KERNEL); + ifq->proxy = src_ifq; + ifq->ctx = ctx; + ifq->if_rxq = src_ifq->if_rxq; + + scoped_guard(mutex, &ctx->mmap_lock) { + ret = xa_alloc(&ctx->zcrx_ctxs, &id, NULL, xa_limit_31b, GFP_KERNEL); + if (ret) + goto err_free; + + ret = -ENOMEM; + if (xa_store(&ctx->zcrx_ctxs, id, ifq, GFP_KERNEL)) { + xa_erase(&ctx->zcrx_ctxs, id); + goto err_free; + } + } + + reg->zcrx_id = id; + if (copy_to_user(arg, reg, sizeof(*reg))) { + ret = -EFAULT; + goto err; + } + mutex_unlock(&src_ctx->uring_lock); + fput(file); + return 0; +err: + scoped_guard(mutex, &ctx->mmap_lock) + xa_erase(&ctx->zcrx_ctxs, id); +err_free: + kfree(ifq); +err_unlock: + mutex_unlock(&src_ctx->uring_lock); + fput(file); + return ret; +} + int io_register_zcrx_ifq(struct io_ring_ctx *ctx, struct io_uring_zcrx_ifq_reg __user *arg) { @@ -566,6 +634,8 @@ int io_register_zcrx_ifq(struct io_ring_ctx *ctx, return -EINVAL; if (copy_from_user(®, arg, sizeof(reg))) return -EFAULT; + if (reg.flags & IORING_ZCRX_IFQ_REG_PROXY) + return io_proxy_zcrx_ifq(ctx, arg, ®); if (copy_from_user(&rd, u64_to_user_ptr(reg.region_ptr), sizeof(rd))) return -EFAULT; if (!mem_is_zero(®.__resv, sizeof(reg.__resv)) || diff --git a/io_uring/zcrx.h b/io_uring/zcrx.h index 566d519cbaf6..0df956cb9592 100644 --- a/io_uring/zcrx.h +++ b/io_uring/zcrx.h @@ -62,6 +62,7 @@ struct io_zcrx_ifq { struct io_mapped_region region; refcount_t refs; + struct io_zcrx_ifq *proxy; }; #if defined(CONFIG_IO_URING_ZCRX) -- 2.47.3[PATCH v2 3/5] io_uring/zcrx: share an ifq between ringsDavid Wei undefinedio-uring@vger.kernel.org, netdev@vger.kernel.org undefined undefined undefined undefined\ƒĆu