History

io_uring/uring_cmd: implement ->sqe_copy() to avoid unnecessary copies

uring_cmd currently copies the full SQE at prep time, just in case it needs it to be stable. However, for inline completions or requests that get queued up on the device side, there's no need to ever copy the SQE. This is particularly important, as various use cases of uring_cmd will be using 128b sized SQEs. Opt in to using ->sqe_copy() to let the core of io_uring decide when to copy SQEs. This callback will only be called if it is safe to do so.

Jens Axboe committed 1 year ago

Commit ecf47d41 parent ead21053 files · +14 −9Browse files

Unified · Split

3 files
  1. io_uring/opdef.c +1 −0
  2. io_uring/uring_cmd.c +12 −9
  3. io_uring/uring_cmd.h +1 −0
io_uring/opdef.c+1−0
@@ -759,6 +759,7 @@ const struct io_cold_def io_cold_defs[] = { · 758 unmodified lines
759759 },
760760 [IORING_OP_URING_CMD] = {
761761 .name = "URING_CMD",
762+ .sqe_copy = io_uring_cmd_sqe_copy,
762763 .cleanup = io_uring_cmd_cleanup,
763764 },
764765 [IORING_OP_SEND_ZC] = {
io_uring/uring_cmd.c+12−9
@@ -205,17 +205,20 @@ int io_uring_cmd_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 204 unmodified lines
205205 if (!ac)
206206 return -ENOMEM;
207207 ac->data.op_data = NULL;
208+ ioucmd->sqe = sqe;
209+ return 0;
210+}
211+
212+void io_uring_cmd_sqe_copy(struct io_kiocb *req)
213+{
214+ struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
215+ struct io_async_cmd *ac = req->async_data;
208216
209− /*
210− * Unconditionally cache the SQE for now - this is only needed for
211− * requests that go async, but prep handlers must ensure that any
212− * sqe data is stable beyond prep. Since uring_cmd is special in
213− * that it doesn't read in per-op data, play it safe and ensure that
214− * any SQE data is stable beyond prep. This can later get relaxed.
215− */
216− memcpy(ac->sqes, sqe, uring_sqe_size(req->ctx));
217+ /* Should not happen, as REQ_F_SQE_COPIED covers this */
218+ if (WARN_ON_ONCE(ioucmd->sqe == ac->sqes))
219+ return;
220+ memcpy(ac->sqes, ioucmd->sqe, uring_sqe_size(req->ctx));
217221 ioucmd->sqe = ac->sqes;
218− return 0;
219222 }
220223
221224 int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
io_uring/uring_cmd.h+1−0
@@ -11,6 +11,7 @@ struct io_async_cmd { · 10 unmodified lines
1111
1212 int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags);
1313 int io_uring_cmd_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
14+void io_uring_cmd_sqe_copy(struct io_kiocb *req);
1415 void io_uring_cmd_cleanup(struct io_kiocb *req);
1516
1617 bool io_uring_try_cancel_uring_cmd(struct io_ring_ctx *ctx,