Skip to content

Commit 5eff57f

Browse files
committed
io_uring/uring_cmd: defer SQE copying until it's needed
The previous commit turned on async data for uring_cmd, and did the basic conversion of setting everything up on the prep side. However, for a lot of use cases, -EIOCBQUEUED will get returned on issue, as the operation got successfully queued. For that case, a persistent SQE isn't needed, as it's just used for issue. Unless execution goes async immediately, defer copying the double SQE until it's necessary. This greatly reduces the overhead of such commands, as evidenced by a perf diff from before and after this change: 10.60% -8.58% [kernel.vmlinux] [k] io_uring_cmd_prep where the prep side drops from 10.60% to ~2%, which is more expected. Performance also rises from ~113M IOPS to ~122M IOPS, bringing us back to where it was before the async command prep. Tested-by: Anuj Gupta <anuj20.g@samsung.com> Reviewed-by: Anuj Gupta <anuj20.g@samsung.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent d10f19d commit 5eff57f

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

io_uring/uring_cmd.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,18 @@ static int io_uring_cmd_prep_setup(struct io_kiocb *req,
182182
struct uring_cache *cache;
183183

184184
cache = io_uring_async_get(req);
185-
if (cache) {
186-
memcpy(cache->sqes, sqe, uring_sqe_size(req->ctx));
187-
ioucmd->sqe = req->async_data;
185+
if (unlikely(!cache))
186+
return -ENOMEM;
187+
188+
if (!(req->flags & REQ_F_FORCE_ASYNC)) {
189+
/* defer memcpy until we need it */
190+
ioucmd->sqe = sqe;
188191
return 0;
189192
}
190-
return -ENOMEM;
193+
194+
memcpy(req->async_data, sqe, uring_sqe_size(req->ctx));
195+
ioucmd->sqe = req->async_data;
196+
return 0;
191197
}
192198

193199
int io_uring_cmd_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
@@ -245,8 +251,15 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
245251
}
246252

247253
ret = file->f_op->uring_cmd(ioucmd, issue_flags);
248-
if (ret == -EAGAIN || ret == -EIOCBQUEUED)
249-
return ret;
254+
if (ret == -EAGAIN) {
255+
struct uring_cache *cache = req->async_data;
256+
257+
if (ioucmd->sqe != (void *) cache)
258+
memcpy(cache, ioucmd->sqe, uring_sqe_size(req->ctx));
259+
return -EAGAIN;
260+
} else if (ret == -EIOCBQUEUED) {
261+
return -EIOCBQUEUED;
262+
}
250263

251264
if (ret < 0)
252265
req_set_fail(req);

0 commit comments

Comments
 (0)