public inbox for io-uring@vger.kernel.org
 help / color / mirror / Atom feed
From: Pavel Begunkov <asml.silence@gmail.com>
To: io-uring@vger.kernel.org
Cc: asml.silence@gmail.com
Subject: [PATCH 2/4] io_uring: move locking inside overflow posting
Date: Wed, 14 May 2025 09:07:21 +0100	[thread overview]
Message-ID: <56fb1f1b3977ae5eec732bd5d39635b69a056b3e.1747209332.git.asml.silence@gmail.com> (raw)
In-Reply-To: <cover.1747209332.git.asml.silence@gmail.com>

A preparation patch moving locking protecting the overflow list into
io_cqring_event_overflow(). The locking needs to be conditional because
callers might already hold the lock. It's not the prettiest option, but
it's not much different from the current state. Hopefully, one day we'll
get rid of this nasty locking pattern.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 io_uring/io_uring.c | 53 +++++++++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 21 deletions(-)

diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 068e140b6bd8..5b253e2b6c49 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -718,8 +718,9 @@ static __cold void io_uring_drop_tctx_refs(struct task_struct *task)
 	}
 }
 
-static bool io_cqring_event_overflow(struct io_ring_ctx *ctx, u64 user_data,
-				     s32 res, u32 cflags, u64 extra1, u64 extra2)
+static bool __io_cqring_event_overflow(struct io_ring_ctx *ctx,
+				       u64 user_data, s32 res, u32 cflags,
+				       u64 extra1, u64 extra2)
 {
 	struct io_overflow_cqe *ocqe;
 	size_t ocq_size = sizeof(struct io_overflow_cqe);
@@ -760,6 +761,24 @@ static bool io_cqring_event_overflow(struct io_ring_ctx *ctx, u64 user_data,
 	return true;
 }
 
+static bool io_cqring_event_overflow(struct io_ring_ctx *ctx, bool locked,
+				     u64 user_data, s32 res, u32 cflags,
+				     u64 extra1, u64 extra2)
+{
+	bool queued;
+
+	if (locked) {
+		queued = __io_cqring_event_overflow(ctx, user_data, res, cflags,
+						    extra1, extra2);
+	} else {
+		spin_lock(&ctx->completion_lock);
+		queued = __io_cqring_event_overflow(ctx, user_data, res, cflags,
+						    extra1, extra2);
+		spin_unlock(&ctx->completion_lock);
+	}
+	return queued;
+}
+
 /*
  * writes to the cq entry need to come after reading head; the
  * control dependency is enough as we're using WRITE_ONCE to
@@ -825,7 +844,8 @@ bool io_post_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags
 	io_cq_lock(ctx);
 	filled = io_fill_cqe_aux(ctx, user_data, res, cflags);
 	if (!filled)
-		filled = io_cqring_event_overflow(ctx, user_data, res, cflags, 0, 0);
+		filled = io_cqring_event_overflow(ctx, true,
+						  user_data, res, cflags, 0, 0);
 	io_cq_unlock_post(ctx);
 	return filled;
 }
@@ -839,11 +859,9 @@ void io_add_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags)
 	lockdep_assert_held(&ctx->uring_lock);
 	lockdep_assert(ctx->lockless_cq);
 
-	if (!io_fill_cqe_aux(ctx, user_data, res, cflags)) {
-		spin_lock(&ctx->completion_lock);
-		io_cqring_event_overflow(ctx, user_data, res, cflags, 0, 0);
-		spin_unlock(&ctx->completion_lock);
-	}
+	if (!io_fill_cqe_aux(ctx, user_data, res, cflags))
+		io_cqring_event_overflow(ctx, false, user_data, res, cflags, 0, 0);
+
 	ctx->submit_state.cq_flush = true;
 }
 
@@ -1432,20 +1450,13 @@ void __io_submit_flush_completions(struct io_ring_ctx *ctx)
 		 */
 		if (!(req->flags & (REQ_F_CQE_SKIP | REQ_F_REISSUE)) &&
 		    unlikely(!io_fill_cqe_req(ctx, req))) {
-			if (ctx->lockless_cq) {
-				spin_lock(&ctx->completion_lock);
-				io_cqring_event_overflow(req->ctx, req->cqe.user_data,
-							req->cqe.res, req->cqe.flags,
-							req->big_cqe.extra1,
-							req->big_cqe.extra2);
-				spin_unlock(&ctx->completion_lock);
-			} else {
-				io_cqring_event_overflow(req->ctx, req->cqe.user_data,
-							req->cqe.res, req->cqe.flags,
-							req->big_cqe.extra1,
-							req->big_cqe.extra2);
-			}
+			bool locked = !ctx->lockless_cq;
 
+			io_cqring_event_overflow(req->ctx, locked,
+						req->cqe.user_data,
+						req->cqe.res, req->cqe.flags,
+						req->big_cqe.extra1,
+						req->big_cqe.extra2);
 			memset(&req->big_cqe, 0, sizeof(req->big_cqe));
 		}
 	}
-- 
2.49.0


  parent reply	other threads:[~2025-05-14  8:06 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-14  8:07 [PATCH 0/4] overflow completion enhancements Pavel Begunkov
2025-05-14  8:07 ` [PATCH 1/4] io_uring: open code io_req_cqe_overflow() Pavel Begunkov
2025-05-14  8:07 ` Pavel Begunkov [this message]
2025-05-14 16:42   ` [PATCH 2/4] io_uring: move locking inside overflow posting Jens Axboe
2025-05-14 17:18     ` Pavel Begunkov
2025-05-14 19:25       ` Jens Axboe
2025-05-14 20:00         ` Pavel Begunkov
2025-05-14 20:05           ` Jens Axboe
2025-05-14 21:52             ` Jens Axboe
2025-05-15 11:04               ` Pavel Begunkov
2025-05-14  8:07 ` [PATCH 3/4] io_uring: alloc overflow entry before locking Pavel Begunkov
2025-05-14  8:07 ` [PATCH 4/4] io_uring: add lockdep warning for overflow posting Pavel Begunkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56fb1f1b3977ae5eec732bd5d39635b69a056b3e.1747209332.git.asml.silence@gmail.com \
    --to=asml.silence@gmail.com \
    --cc=io-uring@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox