Both flags and res have the same lifetime currently. io_req_set_res() sets both of them. Callers of io_req_set_res() like req_fail_link_node(), io_req_complete_failed() and io_req_task_queue_fail() set io_cqe->res to their callers value and force flags to 0. The motivation for this change is the next commit, it will let us keep io_cqe->flags even on error. For IORING_OP_SEND_ZC it is needed to keep IORING_CQE_F_MORE even on a generic failure, userspace needs to know that a IORING_CQE_F_NOTIF will follow. Otherwise the buffers might be reused too early. Fixes: b48c312be05e8 ("io_uring/net: simplify zerocopy send user API") Signed-off-by: Stefan Metzmacher <metze@xxxxxxxxx> Cc: Pavel Begunkov <asml.silence@xxxxxxxxx> Cc: Jens Axboe <axboe@xxxxxxxxx> Cc: io-uring@xxxxxxxxxxxxxxx --- include/linux/io_uring_types.h | 6 +++--- io_uring/io_uring.c | 10 ++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h index 677a25d44d7f..37925db42ae9 100644 --- a/include/linux/io_uring_types.h +++ b/include/linux/io_uring_types.h @@ -473,12 +473,12 @@ struct io_task_work { struct io_cqe { __u64 user_data; - __s32 res; - /* fd initially, then cflags for completion */ + /* fd initially, then res for completion */ union { - __u32 flags; int fd; + __s32 res; }; + __u32 flags; }; /* diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index b9640ad5069f..ae69cff94664 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -837,8 +837,6 @@ static void io_preinit_req(struct io_kiocb *req, struct io_ring_ctx *ctx) req->ctx = ctx; req->link = NULL; req->async_data = NULL; - /* not necessary, but safer to zero */ - req->cqe.res = 0; } static void io_flush_cached_locked_reqs(struct io_ring_ctx *ctx, @@ -1574,6 +1572,12 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags) if (!def->audit_skip) audit_uring_entry(req->opcode); + /* + * req->cqe.fd was resolved by io_assign_file + * now make sure its alias req->cqe.res is reset, + * so we don't use that value by accident. + */ + req->cqe.res = -1; ret = def->issue(req, issue_flags); if (!def->audit_skip) @@ -1902,6 +1906,8 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req, state->need_plug = false; blk_start_plug_nr_ios(&state->plug, state->submit_nr); } + } else { + req->cqe.fd = -1; } personality = READ_ONCE(sqe->personality); -- 2.34.1