Skip to content

Commit 099ada2

Browse files
committed
io_uring/rw: add write support for IOCB_DIO_CALLER_COMP
If the filesystem dio handler understands IOCB_DIO_CALLER_COMP, we'll get a kiocb->ki_complete() callback with kiocb->dio_complete set. In that case, rather than complete the IO directly through task_work, queue up an intermediate task_work handler that first processes this callback and then immediately completes the request. For XFS, this avoids a punt through a workqueue, which is a lot less efficient and adds latency to lower queue depth (or sync) O_DIRECT writes. Only do this for non-polled IO, as polled IO doesn't need this kind of deferral as it always completes within the task itself. This then avoids a check for deferral in the polled IO completion handler. Reviewed-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Dave Chinner <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 9cf3516 commit 099ada2

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

io_uring/rw.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe)
105105
} else {
106106
rw->kiocb.ki_ioprio = get_current_ioprio();
107107
}
108+
rw->kiocb.dio_complete = NULL;
108109

109110
rw->addr = READ_ONCE(sqe->addr);
110111
rw->len = READ_ONCE(sqe->len);
@@ -285,6 +286,15 @@ static inline int io_fixup_rw_res(struct io_kiocb *req, long res)
285286

286287
void io_req_rw_complete(struct io_kiocb *req, struct io_tw_state *ts)
287288
{
289+
struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
290+
struct kiocb *kiocb = &rw->kiocb;
291+
292+
if ((kiocb->ki_flags & IOCB_DIO_CALLER_COMP) && kiocb->dio_complete) {
293+
long res = kiocb->dio_complete(rw->kiocb.private);
294+
295+
io_req_set_res(req, io_fixup_rw_res(req, res), 0);
296+
}
297+
288298
io_req_io_end(req);
289299

290300
if (req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING)) {
@@ -300,9 +310,11 @@ static void io_complete_rw(struct kiocb *kiocb, long res)
300310
struct io_rw *rw = container_of(kiocb, struct io_rw, kiocb);
301311
struct io_kiocb *req = cmd_to_io_kiocb(rw);
302312

303-
if (__io_complete_rw_common(req, res))
304-
return;
305-
io_req_set_res(req, io_fixup_rw_res(req, res), 0);
313+
if (!kiocb->dio_complete || !(kiocb->ki_flags & IOCB_DIO_CALLER_COMP)) {
314+
if (__io_complete_rw_common(req, res))
315+
return;
316+
io_req_set_res(req, io_fixup_rw_res(req, res), 0);
317+
}
306318
req->io_task_work.func = io_req_rw_complete;
307319
__io_req_task_work_add(req, IOU_F_TWQ_LAZY_WAKE);
308320
}
@@ -916,6 +928,15 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags)
916928
}
917929
kiocb->ki_flags |= IOCB_WRITE;
918930

931+
/*
932+
* For non-polled IO, set IOCB_DIO_CALLER_COMP, stating that our handler
933+
* groks deferring the completion to task context. This isn't
934+
* necessary and useful for polled IO as that can always complete
935+
* directly.
936+
*/
937+
if (!(kiocb->ki_flags & IOCB_HIPRI))
938+
kiocb->ki_flags |= IOCB_DIO_CALLER_COMP;
939+
919940
if (likely(req->file->f_op->write_iter))
920941
ret2 = call_write_iter(req->file, kiocb, &s->iter);
921942
else if (req->file->f_op->write)

0 commit comments

Comments
 (0)