diff options
Diffstat (limited to 'io_uring')
| -rw-r--r-- | io_uring/bpf-ops.c | 2 | ||||
| -rw-r--r-- | io_uring/epoll.c | 18 | ||||
| -rw-r--r-- | io_uring/fs.c | 3 | ||||
| -rw-r--r-- | io_uring/kbuf.c | 5 | ||||
| -rw-r--r-- | io_uring/memmap.c | 4 | ||||
| -rw-r--r-- | io_uring/mpscq.h | 9 | ||||
| -rw-r--r-- | io_uring/msg_ring.c | 34 | ||||
| -rw-r--r-- | io_uring/nop.c | 8 | ||||
| -rw-r--r-- | io_uring/opdef.c | 1 | ||||
| -rw-r--r-- | io_uring/query.c | 12 | ||||
| -rw-r--r-- | io_uring/register.c | 31 | ||||
| -rw-r--r-- | io_uring/rw.c | 54 | ||||
| -rw-r--r-- | io_uring/tw.c | 30 | ||||
| -rw-r--r-- | io_uring/uring_cmd.c | 4 | ||||
| -rw-r--r-- | io_uring/zcrx.c | 42 | ||||
| -rw-r--r-- | io_uring/zcrx.h | 7 |
16 files changed, 170 insertions, 94 deletions
diff --git a/io_uring/bpf-ops.c b/io_uring/bpf-ops.c index 5a50f0675fe5..cf2bd068e331 100644 --- a/io_uring/bpf-ops.c +++ b/io_uring/bpf-ops.c @@ -168,6 +168,8 @@ static int io_install_bpf(struct io_ring_ctx *ctx, struct io_uring_bpf_ops *ops) if (ctx->bpf_ops) return -EBUSY; + if (ops->priv) + return -EBUSY; if (WARN_ON_ONCE(!ops->loop_step)) return -EINVAL; diff --git a/io_uring/epoll.c b/io_uring/epoll.c index 8d4610246ba0..eecd748cad01 100644 --- a/io_uring/epoll.c +++ b/io_uring/epoll.c @@ -51,10 +51,24 @@ int io_epoll_ctl_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) int io_epoll_ctl(struct io_kiocb *req, unsigned int issue_flags) { struct io_epoll *ie = io_kiocb_to_cmd(req, struct io_epoll); - int ret; bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; + struct epoll_key key; + int ret; + + CLASS(fd, f)(ie->epfd); + if (fd_empty(f)) + return -EBADF; + + CLASS(fd, tf)(ie->fd); + if (fd_empty(tf)) + return -EBADF; + /* disallow adding an epoll context to another epoll context */ + if (ie->op == EPOLL_CTL_ADD && is_file_epoll(fd_file(tf))) + return -EINVAL; - ret = do_epoll_ctl(ie->epfd, ie->op, ie->fd, &ie->event, force_nonblock); + key.file = fd_file(tf); + key.fd = ie->fd; + ret = do_epoll_ctl_file(fd_file(f), ie->op, &key, &ie->event, force_nonblock); if (force_nonblock && ret == -EAGAIN) return -EAGAIN; diff --git a/io_uring/fs.c b/io_uring/fs.c index d0580c754bf8..26ea841a22e7 100644 --- a/io_uring/fs.c +++ b/io_uring/fs.c @@ -110,7 +110,8 @@ int io_unlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) const char __user *fname; int err; - if (sqe->off || sqe->len || sqe->buf_index || sqe->splice_fd_in) + if (sqe->off || sqe->len || sqe->buf_index || sqe->splice_fd_in || + sqe->addr3 || sqe->__pad2[0]) return -EINVAL; if (unlikely(req->flags & REQ_F_FIXED_FILE)) return -EBADF; diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c index 3cd29477fff2..de0129bceaba 100644 --- a/io_uring/kbuf.c +++ b/io_uring/kbuf.c @@ -287,8 +287,6 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, iov = kmalloc_objs(struct iovec, nr_avail); if (unlikely(!iov)) return -ENOMEM; - if (arg->mode & KBUF_MODE_FREE) - kfree(arg->iovs); arg->iovs = iov; nr_iovs = nr_avail; } else if (nr_avail < nr_iovs) { @@ -330,6 +328,9 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, buf = io_ring_head_to_buf(br, ++head, bl->mask); } while (--nr_iovs); + if (arg->iovs != org_iovs && (arg->mode & KBUF_MODE_FREE)) + kfree(org_iovs); + if (head == tail) req->flags |= REQ_F_BL_EMPTY; diff --git a/io_uring/memmap.c b/io_uring/memmap.c index 4f9b439319c4..23e8a85111bc 100644 --- a/io_uring/memmap.c +++ b/io_uring/memmap.c @@ -53,7 +53,7 @@ struct page **io_pin_pages(unsigned long uaddr, unsigned long len, int *npages) nr_pages = end - start; if (WARN_ON_ONCE(!nr_pages)) return ERR_PTR(-EINVAL); - if (WARN_ON_ONCE(nr_pages > INT_MAX)) + if (nr_pages > INT_MAX / sizeof(struct page *)) return ERR_PTR(-EOVERFLOW); pages = kvmalloc_objs(struct page *, nr_pages, GFP_KERNEL_ACCOUNT); @@ -337,7 +337,7 @@ unsigned long io_uring_get_unmapped_area(struct file *filp, unsigned long addr, ptr = io_uring_validate_mmap_request(filp, pgoff); if (IS_ERR(ptr)) - return -ENOMEM; + return PTR_ERR(ptr); /* * Some architectures have strong cache aliasing requirements. diff --git a/io_uring/mpscq.h b/io_uring/mpscq.h index c801384c6a0a..f910526766fd 100644 --- a/io_uring/mpscq.h +++ b/io_uring/mpscq.h @@ -122,4 +122,13 @@ static inline struct llist_node *mpscq_pop(struct mpscq *q, return NULL; } +/* + * Returns true if the most recent mpscq_pop() that returned a node also + * emptied the queue. Consumer must be serialized. + */ +static inline bool mpscq_pop_emptied(struct mpscq *q, struct llist_node *head) +{ + return head == &q->stub; +} + #endif /* IOU_MPSCQ_H */ diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c index 3ff9098573db..3067c9343991 100644 --- a/io_uring/msg_ring.c +++ b/io_uring/msg_ring.c @@ -93,19 +93,38 @@ static void io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req, io_req_task_work_add_remote(req, IOU_F_TWQ_LAZY_WAKE); } +static int io_msg_ring_cqe_flags(struct io_ring_ctx *target_ctx, + const struct io_msg *msg, u32 *flags) +{ + *flags = 0; + + if (!(msg->flags & IORING_MSG_RING_FLAGS_PASS)) + return 0; + + *flags = msg->cqe_flags; + if ((*flags & IORING_CQE_F_32) && + !(target_ctx->flags & (IORING_SETUP_CQE32 | + IORING_SETUP_CQE_MIXED))) + return -EINVAL; + + return 0; +} + static int io_msg_data_remote(struct io_ring_ctx *target_ctx, struct io_msg *msg) { struct io_kiocb *target; - u32 flags = 0; + u32 flags; + int ret; - target = kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO) ; + ret = io_msg_ring_cqe_flags(target_ctx, msg, &flags); + if (ret) + return ret; + + target = kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO); if (unlikely(!target)) return -ENOMEM; - if (msg->flags & IORING_MSG_RING_FLAGS_PASS) - flags = msg->cqe_flags; - io_msg_remote_post(target_ctx, target, msg->len, flags, msg->user_data); return 0; } @@ -130,8 +149,9 @@ static int __io_msg_ring_data(struct io_ring_ctx *target_ctx, if (io_msg_need_remote(target_ctx)) return io_msg_data_remote(target_ctx, msg); - if (msg->flags & IORING_MSG_RING_FLAGS_PASS) - flags = msg->cqe_flags; + ret = io_msg_ring_cqe_flags(target_ctx, msg, &flags); + if (ret) + return ret; ret = -EOVERFLOW; if (target_ctx->flags & IORING_SETUP_IOPOLL) { diff --git a/io_uring/nop.c b/io_uring/nop.c index 91ae0b2e7e55..60ab19604b36 100644 --- a/io_uring/nop.c +++ b/io_uring/nop.c @@ -40,6 +40,8 @@ int io_nop_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) nop->fd = READ_ONCE(sqe->fd); else nop->fd = -1; + if (nop->flags & IORING_NOP_FIXED_FILE) + req->flags |= REQ_F_FIXED_FILE; if (nop->flags & IORING_NOP_FIXED_BUFFER) req->buf_index = READ_ONCE(sqe->buf_index); if (nop->flags & IORING_NOP_CQE32) { @@ -59,12 +61,10 @@ int io_nop(struct io_kiocb *req, unsigned int issue_flags) int ret = nop->result; if (nop->flags & IORING_NOP_FILE) { - if (nop->flags & IORING_NOP_FIXED_FILE) { + if (req->flags & REQ_F_FIXED_FILE) req->file = io_file_get_fixed(req, nop->fd, issue_flags); - req->flags |= REQ_F_FIXED_FILE; - } else { + else req->file = io_file_get_normal(req, nop->fd); - } if (!req->file) { ret = -EBADF; goto done; diff --git a/io_uring/opdef.c b/io_uring/opdef.c index 88a45c7d897f..4e58eb1344ea 100644 --- a/io_uring/opdef.c +++ b/io_uring/opdef.c @@ -520,6 +520,7 @@ const struct io_issue_def io_issue_defs[] = { #endif }, [IORING_OP_RECV_ZC] = { + .audit_skip = 1, .needs_file = 1, .unbound_nonreg_file = 1, .pollin = 1, diff --git a/io_uring/query.c b/io_uring/query.c index d529d94aa8f4..88a325736992 100644 --- a/io_uring/query.c +++ b/io_uring/query.c @@ -9,7 +9,7 @@ union io_query_data { struct io_uring_query_opcode opcodes; struct io_uring_query_zcrx zcrx; - struct io_uring_query_zcrx_notif zcrx_notif; + struct io_uring_query_zcrx_event zcrx_notif; struct io_uring_query_scq scq; }; @@ -47,11 +47,11 @@ static ssize_t io_query_zcrx(union io_query_data *data) static ssize_t io_query_zcrx_notif(union io_query_data *data) { - struct io_uring_query_zcrx_notif *e = &data->zcrx_notif; + struct io_uring_query_zcrx_event *e = &data->zcrx_notif; - e->notif_flags = ZCRX_NOTIF_TYPE_MASK; - e->notif_stats_size = sizeof(struct zcrx_notif_stats); - e->notif_stats_off_alignment = __alignof__(struct zcrx_notif_stats); + e->event_flags = ZCRX_EVENT_TYPE_MASK; + e->stats_size = sizeof(struct zcrx_stats); + e->stats_off_alignment = __alignof__(struct zcrx_stats); e->__resv1 = 0; memset(&e->__resv2, 0, sizeof(e->__resv2)); return sizeof(*e); @@ -96,7 +96,7 @@ static int io_handle_query_entry(union io_query_data *data, void __user *uhdr, case IO_URING_QUERY_ZCRX: ret = io_query_zcrx(data); break; - case IO_URING_QUERY_ZCRX_NOTIF: + case IO_URING_QUERY_ZCRX_EVENT: ret = io_query_zcrx_notif(data); break; case IO_URING_QUERY_SCQ: diff --git a/io_uring/register.c b/io_uring/register.c index dce5e2f9cf77..02bc103bcc9d 100644 --- a/io_uring/register.c +++ b/io_uring/register.c @@ -503,6 +503,7 @@ static int io_register_resize_rings(struct io_ring_ctx *ctx, void __user *arg) unsigned i, tail, old_head; struct io_uring_params *p = &config.p; struct io_rings_layout *rl = &config.layout; + u32 *o_sq_array, *n_sq_array = NULL; int ret; memset(&config, 0, sizeof(config)); @@ -589,6 +590,9 @@ static int io_register_resize_rings(struct io_ring_ctx *ctx, void __user *arg) ctx->rings = NULL; o.sq_sqes = ctx->sq_sqes; ctx->sq_sqes = NULL; + o_sq_array = ctx->sq_array; + if (!(ctx->flags & IORING_SETUP_NO_SQARRAY)) + n_sq_array = (u32 *)((char *)n.rings + rl->sq_array_offset); /* * Now copy SQ and CQ entries, if any. If either of the destination @@ -599,20 +603,27 @@ static int io_register_resize_rings(struct io_ring_ctx *ctx, void __user *arg) if (tail - old_head > p->sq_entries) goto overflow; for (i = old_head; i < tail; i++) { - unsigned index, dst_mask, src_mask; + unsigned int dst, src; size_t sq_size; - index = i; + dst = i & (p->sq_entries - 1); + src = i & (ctx->sq_entries - 1); + if (n_sq_array) { + src = READ_ONCE(o_sq_array[src]); + if (unlikely(src >= ctx->sq_entries)) { + WRITE_ONCE(n_sq_array[dst], UINT_MAX); + continue; + } + WRITE_ONCE(n_sq_array[dst], dst); + } + sq_size = sizeof(struct io_uring_sqe); - src_mask = ctx->sq_entries - 1; - dst_mask = p->sq_entries - 1; if (ctx->flags & IORING_SETUP_SQE128) { - index <<= 1; + dst <<= 1; + src <<= 1; sq_size <<= 1; - src_mask = (ctx->sq_entries << 1) - 1; - dst_mask = (p->sq_entries << 1) - 1; } - memcpy(&n.sq_sqes[index & dst_mask], &o.sq_sqes[index & src_mask], sq_size); + memcpy(&n.sq_sqes[dst], &o.sq_sqes[src], sq_size); } WRITE_ONCE(n.rings->sq.head, old_head); WRITE_ONCE(n.rings->sq.tail, tail); @@ -655,8 +666,8 @@ overflow: WRITE_ONCE(n.rings->cq_overflow, READ_ONCE(o.rings->cq_overflow)); /* all done, store old pointers and assign new ones */ - if (!(ctx->flags & IORING_SETUP_NO_SQARRAY)) - ctx->sq_array = (u32 *)((char *)n.rings + rl->sq_array_offset); + if (n_sq_array) + ctx->sq_array = n_sq_array; ctx->sq_entries = p->sq_entries; ctx->cq_entries = p->cq_entries; diff --git a/io_uring/rw.c b/io_uring/rw.c index 0c4834645279..95038cfda615 100644 --- a/io_uring/rw.c +++ b/io_uring/rw.c @@ -601,20 +601,38 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res) { struct io_rw *rw = container_of(kiocb, struct io_rw, kiocb); struct io_kiocb *req = cmd_to_io_kiocb(rw); + int final_res = io_fixup_rw_res(req, res); if (kiocb->ki_flags & IOCB_WRITE) io_req_end_write(req); - if (unlikely(res != req->cqe.res)) { - if (res == -EAGAIN && io_rw_should_reissue(req)) - req->flags |= REQ_F_REISSUE | REQ_F_BL_NO_RECYCLE; - else - req->cqe.res = res; - } + + if (res == -EAGAIN && io_rw_should_reissue(req)) + req->flags |= REQ_F_REISSUE | REQ_F_BL_NO_RECYCLE; + else if (unlikely(final_res != req->cqe.res)) + req->cqe.res = final_res; /* order with io_iopoll_complete() checking ->iopoll_completed */ smp_store_release(&req->iopoll_completed, 1); } +static inline ssize_t io_fixup_restart_res(ssize_t ret) +{ + switch (ret) { + case -ERESTARTSYS: + case -ERESTARTNOINTR: + case -ERESTARTNOHAND: + case -ERESTART_RESTARTBLOCK: + /* + * We can't just restart the syscall, since previously + * submitted sqes may already be in progress. Just fail + * this IO with EINTR. + */ + return -EINTR; + default: + return ret; + } +} + static inline void io_rw_done(struct io_kiocb *req, ssize_t ret) { struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw); @@ -624,21 +642,8 @@ static inline void io_rw_done(struct io_kiocb *req, ssize_t ret) return; /* transform internal restart error codes */ - if (unlikely(ret < 0)) { - switch (ret) { - case -ERESTARTSYS: - case -ERESTARTNOINTR: - case -ERESTARTNOHAND: - case -ERESTART_RESTARTBLOCK: - /* - * We can't just restart the syscall, since previously - * submitted sqes may already be in progress. Just fail - * this IO with EINTR. - */ - ret = -EINTR; - break; - } - } + if (unlikely(ret < 0)) + ret = io_fixup_restart_res(ret); if (req->flags & REQ_F_IOPOLL) io_complete_rw_iopoll(&rw->kiocb, ret); @@ -1034,7 +1039,8 @@ int io_read(struct io_kiocb *req, unsigned int issue_flags) if (req->flags & REQ_F_BUFFERS_COMMIT) io_kbuf_recycle(req, sel.buf_list, issue_flags); - return ret; + + return io_fixup_restart_res(ret); } int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags) @@ -1068,8 +1074,10 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags) return IOU_RETRY; } else if (ret <= 0) { io_kbuf_recycle(req, sel.buf_list, issue_flags); - if (ret < 0) + if (ret < 0) { + ret = io_fixup_restart_res(ret); req_set_fail(req); + } } else if (!(req->flags & REQ_F_APOLL_MULTISHOT)) { cflags = io_put_kbuf(req, ret, sel.buf_list); } else { diff --git a/io_uring/tw.c b/io_uring/tw.c index e74372233f40..e6ee15571e85 100644 --- a/io_uring/tw.c +++ b/io_uring/tw.c @@ -34,10 +34,6 @@ void io_tctx_fallback_work(struct work_struct *work) fallback_work); unsigned int count = 0; - /* see tctx_task_work() - a set bit must always have a run coming */ - clear_bit(0, &tctx->tw_pending); - smp_mb__after_atomic(); - /* * Run the entries directly. We're in PF_KTHRED context, hence * io_should_terminate_tw() is true and they will be marked as @@ -55,7 +51,7 @@ static void io_fallback_tw(struct io_uring_task *tctx) * the queued work) stay around until the drain has run. */ get_task_struct(tctx->task); - if (!queue_work(system_unbound_wq, &tctx->fallback_work)) + if (!queue_work(system_dfl_wq, &tctx->fallback_work)) put_task_struct(tctx->task); } @@ -101,6 +97,13 @@ void tctx_task_work_run(struct io_uring_task *tctx, unsigned int max_entries, io_poll_task_func, io_req_rw_complete, (struct io_tw_req){req}, ts); (*count)++; + /* + * Break if most recent pop emptied the queue. This helps + * bound task_work run, and also protects the regular + * task_work addition. + */ + if (mpscq_pop_emptied(&tctx->task_list, tctx->task_head)) + break; if (unlikely(need_resched())) { ctx_flush_and_put(ctx, ts); ctx = NULL; @@ -127,8 +130,6 @@ void tctx_task_work(struct callback_head *cb) unsigned int count = 0; tctx = container_of(cb, struct io_uring_task, task_work); - clear_bit(0, &tctx->tw_pending); - smp_mb__after_atomic(); tctx_task_work_run(tctx, UINT_MAX, &count); } @@ -138,11 +139,11 @@ void tctx_task_work(struct callback_head *cb) */ static void io_ctx_mark_taskrun(struct io_ring_ctx *ctx) { + lockdep_assert_in_rcu_read_lock(); + if (ctx->flags & IORING_SETUP_TASKRUN_FLAG) { - struct io_rings *rings; + struct io_rings *rings = rcu_dereference(ctx->rings_rcu); - guard(rcu)(); - rings = rcu_dereference(ctx->rings_rcu); atomic_or(IORING_SQ_TASKRUN, &rings->sq_flags); } } @@ -152,6 +153,9 @@ void io_req_local_work_add(struct io_kiocb *req, unsigned flags) struct io_ring_ctx *ctx = req->ctx; int nr_wait; + /* pairs with synchronize_rcu() in io_ring_exit_work() */ + guard(rcu)(); + /* * We don't know how many requests there are in the link and whether * they can even be queued lazily, fall back to non-lazy. @@ -206,7 +210,7 @@ void io_req_normal_work_add(struct io_kiocb *req) struct io_uring_task *tctx = req->tctx; struct io_ring_ctx *ctx = req->ctx; - /* task_work already pending, we're done */ + /* tw run already pending, nothing else to do */ if (!mpscq_push(&tctx->task_list, &req->io_task_work.node)) return; @@ -223,10 +227,6 @@ void io_req_normal_work_add(struct io_kiocb *req) return; } - /* task_work must only be added once */ - if (test_and_set_bit(0, &tctx->tw_pending)) - return; - if (likely(!task_work_add(tctx->task, &tctx->task_work, ctx->notify_method))) return; diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c index 7b25dcd9d05f..c14c22cff49e 100644 --- a/io_uring/uring_cmd.c +++ b/io_uring/uring_cmd.c @@ -90,7 +90,7 @@ static void io_uring_cmd_del_cancelable(struct io_uring_cmd *cmd, } /* - * Mark this command as concelable, then io_uring_try_cancel_uring_cmd() + * Mark this command as cancelable, then io_uring_try_cancel_uring_cmd() * will try to cancel this issued command by sending ->uring_cmd() with * issue_flags of IO_URING_F_CANCEL. * @@ -168,7 +168,7 @@ void __io_uring_cmd_done(struct io_uring_cmd *ioucmd, s32 ret, u64 res2, } io_req_uring_cleanup(req, issue_flags); if (req->flags & REQ_F_IOPOLL) { - /* order with io_iopoll_req_issued() checking ->iopoll_complete */ + /* order with io_do_iopoll() checking ->iopoll_completed */ smp_store_release(&req->iopoll_completed, 1); } else if (issue_flags & IO_URING_F_COMPLETE_DEFER) { if (WARN_ON_ONCE(issue_flags & IO_URING_F_UNLOCKED)) diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c index 49163f9c39df..76b9b0d54af9 100644 --- a/io_uring/zcrx.c +++ b/io_uring/zcrx.c @@ -766,7 +766,7 @@ static int import_zcrx(struct io_ring_ctx *ctx, return -EINVAL; if (reg->if_rxq || reg->rq_entries || reg->area_ptr || reg->region_ptr) return -EINVAL; - if (reg->notif_desc) + if (reg->event_desc) return -EINVAL; if (reg->flags & ~ZCRX_REG_IMPORT) return -EINVAL; @@ -855,7 +855,7 @@ netdev_put_unlock: static int zcrx_validate_notif_stats(struct io_zcrx_ifq *ifq, const struct io_uring_zcrx_ifq_reg *reg, - const struct zcrx_notification_desc *notif) + const struct zcrx_event_desc *notif) { size_t stats_off = notif->stats_offset; size_t used, end; @@ -863,12 +863,12 @@ static int zcrx_validate_notif_stats(struct io_zcrx_ifq *ifq, used = reg->offsets.rqes + sizeof(struct io_uring_zcrx_rqe) * reg->rq_entries; - if (!IS_ALIGNED(stats_off, __alignof__(struct zcrx_notif_stats))) + if (!IS_ALIGNED(stats_off, __alignof__(struct zcrx_stats))) return -EINVAL; if (stats_off < used) return -ERANGE; if (check_add_overflow(stats_off, - sizeof(struct zcrx_notif_stats), + sizeof(struct zcrx_stats), &end)) return -ERANGE; if (end > io_region_size(&ifq->rq_region)) @@ -883,7 +883,7 @@ static int zcrx_validate_notif_stats(struct io_zcrx_ifq *ifq, int io_register_zcrx(struct io_ring_ctx *ctx, struct io_uring_zcrx_ifq_reg __user *arg) { - struct zcrx_notification_desc notif; + struct zcrx_event_desc notif; struct io_uring_zcrx_area_reg area; struct io_uring_zcrx_ifq_reg reg; struct io_uring_region_desc rd; @@ -928,14 +928,14 @@ int io_register_zcrx(struct io_ring_ctx *ctx, return -EFAULT; memset(¬if, 0, sizeof(notif)); - if (reg.notif_desc && copy_from_user(¬if, u64_to_user_ptr(reg.notif_desc), + if (reg.event_desc && copy_from_user(¬if, u64_to_user_ptr(reg.event_desc), sizeof(notif))) return -EFAULT; - if (notif.type_mask & ~ZCRX_NOTIF_TYPE_MASK) + if (notif.type_mask & ~ZCRX_EVENT_TYPE_MASK) return -EINVAL; - if (notif.flags & ~ZCRX_NOTIF_DESC_FLAG_STATS) + if (notif.flags & ~ZCRX_EVENT_DESC_FLAG_STATS) return -EINVAL; - if (!(notif.flags & ZCRX_NOTIF_DESC_FLAG_STATS)) { + if (!(notif.flags & ZCRX_EVENT_DESC_FLAG_STATS)) { if (notif.stats_offset) return -EINVAL; } @@ -970,7 +970,7 @@ int io_register_zcrx(struct io_ring_ctx *ctx, if (ret) goto err; - if (notif.flags & ZCRX_NOTIF_DESC_FLAG_STATS) { + if (notif.flags & ZCRX_EVENT_DESC_FLAG_STATS) { ret = zcrx_validate_notif_stats(ifq, ®, ¬if); if (ret) goto err; @@ -1244,7 +1244,7 @@ static netmem_ref io_pp_zc_alloc_netmems(struct page_pool *pp, gfp_t gfp) allocated = io_zcrx_refill_slow(pp, ifq, netmems, to_alloc); if (!allocated) { - zcrx_send_notif(ifq, ZCRX_NOTIF_NO_BUFFERS); + zcrx_send_notif(ifq, ZCRX_EVENT_ALLOC_FAIL); return 0; } out_return: @@ -1294,6 +1294,7 @@ static void io_pp_zc_destroy(struct page_pool *pp) static int io_pp_nl_fill(void *mp_priv, struct sk_buff *rsp, struct netdev_rx_queue *rxq) { + struct io_zcrx_ifq *ifq = mp_priv; struct nlattr *nest; int type; @@ -1301,6 +1302,13 @@ static int io_pp_nl_fill(void *mp_priv, struct sk_buff *rsp, nest = nla_nest_start(rsp, type); if (!nest) return -EMSGSIZE; + + if (nla_put_uint(rsp, NETDEV_A_IO_URING_PROVIDER_INFO_RX_BUF_LEN, + 1ULL << ifq->niov_shift)) { + nla_nest_cancel(rsp, nest); + return -EMSGSIZE; + } + nla_nest_end(rsp, nest); return 0; @@ -1398,16 +1406,16 @@ static int zcrx_flush_rq(struct io_ring_ctx *ctx, struct io_zcrx_ifq *zcrx, static int zcrx_arm_notif(struct io_ring_ctx *ctx, struct io_zcrx_ifq *zcrx, struct zcrx_ctrl *ctrl) { - const struct zcrx_ctrl_arm_notif *an = &ctrl->zc_arm_notif; + const struct zcrx_ctrl_arm_event *an = &ctrl->zc_arm_event; unsigned type_mask; - if (an->notif_type >= __ZCRX_NOTIF_TYPE_LAST) + if (an->event_type >= __ZCRX_EVENT_TYPE_LAST) return -EINVAL; if (!mem_is_zero(&an->__resv, sizeof(an->__resv))) return -EINVAL; guard(spinlock_bh)(&zcrx->ctx_lock); - type_mask = 1U << an->notif_type; + type_mask = 1U << an->event_type; if (type_mask & ~zcrx->fired_notifs) return -EINVAL; zcrx->fired_notifs &= ~type_mask; @@ -1420,7 +1428,7 @@ int io_zcrx_ctrl(struct io_ring_ctx *ctx, void __user *arg, unsigned nr_args) struct io_zcrx_ifq *zcrx; BUILD_BUG_ON(sizeof(ctrl.zc_export) != sizeof(ctrl.zc_flush)); - BUILD_BUG_ON(sizeof(ctrl.zc_export) != sizeof(ctrl.zc_arm_notif)); + BUILD_BUG_ON(sizeof(ctrl.zc_export) != sizeof(ctrl.zc_arm_event)); if (nr_args) return -EINVAL; @@ -1438,7 +1446,7 @@ int io_zcrx_ctrl(struct io_ring_ctx *ctx, void __user *arg, unsigned nr_args) return zcrx_flush_rq(ctx, zcrx, &ctrl); case ZCRX_CTRL_EXPORT: return zcrx_export(ctx, zcrx, &ctrl, arg); - case ZCRX_CTRL_ARM_NOTIFICATION: + case ZCRX_CTRL_ARM_EVENT: return zcrx_arm_notif(ctx, zcrx, &ctrl); } @@ -1584,7 +1592,7 @@ static int io_zcrx_copy_frag(struct io_kiocb *req, struct io_zcrx_ifq *ifq, zcrx_stat_add(&ifq->notif_stats->copy_count, 1); zcrx_stat_add(&ifq->notif_stats->copy_bytes, ret); } - zcrx_send_notif(ifq, ZCRX_NOTIF_COPY); + zcrx_send_notif(ifq, ZCRX_EVENT_COPY); } return ret; diff --git a/io_uring/zcrx.h b/io_uring/zcrx.h index fa00900e479e..c1005f23caff 100644 --- a/io_uring/zcrx.h +++ b/io_uring/zcrx.h @@ -10,8 +10,9 @@ #define ZCRX_SUPPORTED_REG_FLAGS (ZCRX_REG_IMPORT | ZCRX_REG_NODEV) #define ZCRX_FEATURES (ZCRX_FEATURE_RX_PAGE_SIZE |\ - ZCRX_FEATURE_NOTIFICATION) -#define ZCRX_NOTIF_TYPE_MASK ((1U << ZCRX_NOTIF_NO_BUFFERS) | (1U << ZCRX_NOTIF_COPY)) + ZCRX_FEATURE_EVENT) +#define ZCRX_EVENT_TYPE_MASK ((1U << ZCRX_EVENT_ALLOC_FAIL) |\ + (1U << ZCRX_EVENT_COPY)) struct io_zcrx_mem { unsigned long size; @@ -80,7 +81,7 @@ struct io_zcrx_ifq { u32 allowed_notif_mask; u32 fired_notifs; u64 notif_data; - struct zcrx_notif_stats *notif_stats; + struct zcrx_stats *notif_stats; }; #if defined(CONFIG_IO_URING_ZCRX) |