Skip to contentSkip to conversation

IOSQE_ASYNC patches

PATCH Applied Pavel Begunkov 2 participants 5 messages Jan 22, 2020

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover IOSQE_ASYNC patches

There are 2 problems addressed:
1. it never calls *_prep() when going through IOSQE_ASYNC path.
2. non-head linked reqs ignore IOSQE_ASYNC.

Also, there could be yet another problem, when we bypass io_issue_req() and going straight to async.

Pavel Begunkov (2):
io_uring: prep req when do IOSQE_ASYNC
io_uring: honor IOSQE_ASYNC for linked reqs

 fs/io_uring.c | 8 ++++++++
 1 file changed, 8 insertions(+)
Signature · 1 line
2.24.0
#1 lore raw

PATCH 1/2 io_uring: prep req when do IOSQE_ASYNC

Whenever IOSQE_ASYNC is set, requests will be punted to async without getting into io_issue_req() and without proper preparation done (e.g. io_req_defer_prep()). Hence they will be left uninitialised.

Prepare them before punting.

---
 fs/io_uring.c | 4 ++++
 1 file changed, 4 insertions(+)
fs/io_uring.c +4 -0
index 09503d1e9e45..cdbc711ae5fd 100644
@@ -4558,11 +4558,15 @@ static void io_queue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 	ret = io_req_defer(req, sqe);
 	if (ret) {
 		if (ret != -EIOCBQUEUED) {
+fail_req:
 			io_cqring_add_event(req, ret);
 			req_set_fail_links(req);
 			io_double_put_req(req);
 		}
 	} else if (req->flags & REQ_F_FORCE_ASYNC) {
+		ret = io_req_defer_prep(req, sqe);
+		if (unlikely(ret < 0))
+			goto fail_req;
 		/*
 		 * Never try inline submit of IOSQE_ASYNC is set, go straight
 		 * to async execution.
Signature · 1 line
2.24.0
#2 lore raw

PATCH 2/2 io_uring: honor IOSQE_ASYNC for linked reqs

In reply to Pavel Begunkov

REQ_F_FORCE_ASYNC is checked only for the head of a link. Fix it.

---
 fs/io_uring.c | 4 ++++
 1 file changed, 4 insertions(+)
fs/io_uring.c +4 -0
index cdbc711ae5fd..9f73586dcfb8 100644
@@ -4512,6 +4512,7 @@ static void __io_queue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 	 */
 	if (ret == -EAGAIN && (!(req->flags & REQ_F_NOWAIT) ||
 	    (req->flags & REQ_F_MUST_PUNT))) {
+punt:
 		if (req->work.flags & IO_WQ_WORK_NEEDS_FILES) {
 			ret = io_grab_files(req);
 			if (ret)
@@ -4547,6 +4548,9 @@ static void __io_queue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 	if (nxt) {
 		req = nxt;
 		nxt = NULL;
+
+		if (req->flags & REQ_F_FORCE_ASYNC)
+			goto punt;
 		goto again;
 	}
 }
Signature · 1 line
2.24.0
#3 lore raw
In reply to Pavel Begunkov
Quoted 3 lines · Pavel Begunkov

There are 2 problems addressed:
1. it never calls *_prep() when going through IOSQE_ASYNC path.
2. non-head linked reqs ignore IOSQE_ASYNC.

Those two are intentionally short for quick fix up. I'll prepare something prettier on top of that a bit later.

Quoted 11 lines

Also, there could be yet another problem, when we bypass io_issue_req() and going straight to async.

Pavel Begunkov (2):
io_uring: prep req when do IOSQE_ASYNC
io_uring: honor IOSQE_ASYNC for linked reqs

 fs/io_uring.c | 8 ++++++++
 1 file changed, 8 insertions(+)
Signature · 1 line
Pavel Begunkov
maintainer Applied
#4 lore raw
In reply to Pavel Begunkov
Quoted 6 lines · Pavel Begunkov

There are 2 problems addressed:
1. it never calls *_prep() when going through IOSQE_ASYNC path.
2. non-head linked reqs ignore IOSQE_ASYNC.

Also, there could be yet another problem, when we bypass io_issue_req() and going straight to async.

Thanks, applied.

Signature · 1 line
Jens Axboe