Linux kernel -stable discussions
 help / color / mirror / Atom feed
* [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable
@ 2026-11-04 18:43 Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 1/8] io_uring/net: keep recvmsg buffer select length within MAX_RW_COUNT Jens Axboe
                   ` (8 more replies)
  0 siblings, 9 replies; 12+ messages in thread
From: Jens Axboe @ 2026-11-04 18:43 UTC (permalink / raw)
  To: stable

Hi Greg,

Here are io_uring fixes for 6.1-stable.

They apply on top of v6.1.191 with the current queue-6.1 applied
(stable-queue 6575ff04f2fd). They don't depend on anything in the queue,
and apply to v6.1.191 alone as well.

"io_uring/io-wq: save worker type before dropping its reference" is
already in queue-6.1, so it's not included here.

Patches 1, 4, 5, 6, 7 and 8 needed changes to apply to 6.1, the
[axboe: ...] note in each says what was changed.

Cheng Yongkang (1):
  io_uring/timeout: count cancelled timeouts in cq_timeouts

Chris Mason (4):
  io_uring/rsrc: charge buffer arrays and nodes to memcg
  io_uring: charge tctx nodes and personalities
  io_uring: free XArray nodes left by a failed store
  io_uring/sqpoll: don't wait for the thread to exit

Daan De Meyer (1):
  io_uring/net: don't retry a non-blocking connect() that fails with
    -EAGAIN

Josef Bacik (1):
  io_uring/io-wq: no new workers once the exit has begun

Yichong Chen (1):
  io_uring/net: keep recvmsg buffer select length within MAX_RW_COUNT

 io_uring/io-wq.c    |  6 ++++++
 io_uring/io_uring.c |  3 ++-
 io_uring/net.c      | 12 ++++++++++++
 io_uring/rsrc.c     |  4 ++--
 io_uring/sqpoll.c   | 28 +++++++++++++++++++++++-----
 io_uring/sqpoll.h   |  3 ++-
 io_uring/tctx.c     |  6 ++++--
 io_uring/timeout.c  |  3 +++
 8 files changed, 54 insertions(+), 11 deletions(-)

-- 
2.56.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 6.1.y 1/8] io_uring/net: keep recvmsg buffer select length within MAX_RW_COUNT
  2026-11-04 18:43 [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Jens Axboe
@ 2026-11-04 18:43 ` Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 2/8] io_uring/net: don't retry a non-blocking connect() that fails with -EAGAIN Jens Axboe
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2026-11-04 18:43 UTC (permalink / raw)
  To: stable

From: Yichong Chen <chenyichong@uniontech.com>

Commit 18d3f56eb6e6500a65d81cf265f0fe74fd9ecab6 upstream.

io_recvmsg() takes the transfer length from the ring provided buffer when
sqe->len is 0, and such a buffer can be up to 4G. min_ret is an int, so 2G
or more makes it negative and the (ret < min_ret) block is skipped, and the
oversized length reaches the socket layer unchanged: an empty socket then
completes with 0 instead of arming poll, and a short read is reported as
complete. Clamp the length to MAX_RW_COUNT, as io_recv() does.

Fixes: c7fb19428d67 ("io_uring: add support for ring mapped supplied buffers")
Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
Link: https://patch.msgid.link/20261023112209.87979-1-chenyichong@uniontech.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[axboe: 6.1 has the older io_buffer_select() interface]
---
 io_uring/net.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/io_uring/net.c b/io_uring/net.c
index cc25cbb27e5d..86a18814c628 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -805,6 +805,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
 		buf = io_buffer_select(req, &len, issue_flags);
 		if (!buf)
 			return -ENOBUFS;
+		len = min_t(size_t, len, MAX_RW_COUNT);
 
 		if (req->flags & REQ_F_APOLL_MULTISHOT) {
 			ret = io_recvmsg_prep_multishot(kmsg, sr, &buf, &len);
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6.1.y 2/8] io_uring/net: don't retry a non-blocking connect() that fails with -EAGAIN
  2026-11-04 18:43 [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 1/8] io_uring/net: keep recvmsg buffer select length within MAX_RW_COUNT Jens Axboe
@ 2026-11-04 18:43 ` Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 3/8] io_uring/io-wq: no new workers once the exit has begun Jens Axboe
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2026-11-04 18:43 UTC (permalink / raw)
  To: stable

From: Daan De Meyer <daan@amutable.com>

Commit 71537ed811107c514c0342e98902d489d6d2b7cd upstream.

IORING_OP_CONNECT on an O_NONBLOCK AF_UNIX stream socket retries a
connect that fails with -EAGAIN because the listener's backlog is full.
Polling the client socket doesn't help: an unconnected stream socket
reports EPOLLOUT and EPOLLHUP right away, before the backlog drains. So
io_uring retries the connect until the apoll retry limit is hit, then
punts the request to io-wq. With a full backlog, io_connect() runs 128
times in the submitting task and once more in a new io-wq worker. That
worker stays in the task's thread group, so a later
unshare(CLONE_NEWUSER) fails with -EINVAL.

None of this changes the result. __sys_connect_file() adds the socket's
own O_NONBLOCK to every attempt, so the attempt from io-wq fails with
-EAGAIN as well. That -EAGAIN becomes the CQE result, and connect(2)
returns the same -EAGAIN.

Let's complete the request with -EAGAIN right away when the socket has
O_NONBLOCK set, like connect(2) does. io_accept() already completes
-EAGAIN this way for IORING_ACCEPT_DONTWAIT. -EINPROGRESS still waits
for the connection to complete. A blocking socket still ends up in
io-wq, where the connect sleeps until the listener accepts.

Fixes: f8e85cf255ad ("io_uring: add support for IORING_OP_CONNECT")
Signed-off-by: Daan De Meyer <daan@amutable.com>
Link: https://patch.msgid.link/20261027-b4-io-uring-connect-eagain-v1-1-f4e3aaaa49ee@amutable.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 io_uring/net.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/io_uring/net.c b/io_uring/net.c
index 86a18814c628..669cd54cccf0 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -1510,6 +1510,17 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
 			if (connect->seen_econnaborted)
 				goto out;
 			connect->seen_econnaborted = true;
+		} else if (req->file->f_flags & O_NONBLOCK) {
+			/*
+			 * __sys_connect_file() adds O_NONBLOCK from the socket
+			 * to every attempt, so a retry from io-wq fails with
+			 * -EAGAIN as well. A poll on the socket doesn't wait
+			 * until a retry can succeed. For example, an AF_UNIX
+			 * client reports EPOLLOUT right away while the
+			 * listener's backlog is full. Complete the request
+			 * with -EAGAIN, like connect(2) does.
+			 */
+			goto out;
 		}
 		if (req_has_async_data(req))
 			return -EAGAIN;
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6.1.y 3/8] io_uring/io-wq: no new workers once the exit has begun
  2026-11-04 18:43 [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 1/8] io_uring/net: keep recvmsg buffer select length within MAX_RW_COUNT Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 2/8] io_uring/net: don't retry a non-blocking connect() that fails with -EAGAIN Jens Axboe
@ 2026-11-04 18:43 ` Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 4/8] io_uring/rsrc: charge buffer arrays and nodes to memcg Jens Axboe
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2026-11-04 18:43 UTC (permalink / raw)
  To: stable

From: Josef Bacik <josef@toxicpanda.com>

Commit 47c68f925062a6013235d06add85a59f7d91e0fb upstream.

io_wq_exit_start() sets IO_WQ_BIT_EXIT, but worker creation task_work
queued before that stays queued until io_wq_exit_workers() cancels it.
In between the task runs its task_work while canceling requests, and a
worker can still get created.

That's a problem for exec. begin_new_exec() calls io_uring_task_cancel()
after de_thread(), when it's supposedly the only thread left, and
io_wq_exit_workers() only waits for ->worker_done, which a worker
completes before do_exit(). So the exiting worker is still in the thread
group, using the mm, files and sighand, while exec replaces them. Easy
to hit with a signal pending when create_io_thread() fails and the retry
gets queued right before execve().

Cancel the queued creation task_work as soon as the exit bit is set.
Pending work that isn't otherwise canceled now ends with -ECANCELED when
the io-wq is destroyed, rather than depending on whether the task
happened to run its task_work first.

Fixes: 685fe7feedb9 ("io-wq: eliminate the need for a manager thread")
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
[axboe: the barrier is already upstream, see 0e5663856b69, only the
 cancel is new]
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 io_uring/io-wq.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c
index a8ef73963dba..0300bc6d17ae 100644
--- a/io_uring/io-wq.c
+++ b/io_uring/io-wq.c
@@ -1335,6 +1335,12 @@ void io_wq_exit_start(struct io_wq *wq)
 	set_bit(IO_WQ_BIT_EXIT, &wq->state);
 	/* Pairs with task_work_add() in io_queue_worker_create(). */
 	smp_mb__after_atomic();
+	/*
+	 * No more workers from here on. The caller is going to run its task
+	 * work, and on exec a thread that is created now would still be
+	 * around, exiting, by the time that the caller must be on its own.
+	 */
+	io_wq_cancel_tw_create(wq);
 }
 
 static void io_wq_cancel_tw_create(struct io_wq *wq)
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6.1.y 4/8] io_uring/rsrc: charge buffer arrays and nodes to memcg
  2026-11-04 18:43 [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Jens Axboe
                   ` (2 preceding siblings ...)
  2026-11-04 18:43 ` [PATCH 6.1.y 3/8] io_uring/io-wq: no new workers once the exit has begun Jens Axboe
@ 2026-11-04 18:43 ` Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 5/8] io_uring: charge tctx nodes and personalities Jens Axboe
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2026-11-04 18:43 UTC (permalink / raw)
  To: stable

From: Chris Mason <mason@kernel.org>

Commit 075d5837bafc317e796548f721b8fbf7add6821d upstream.

The io_mapped_ubuf of a registered buffer has one bio_vec per page,
unless the pages coalesce into huge pages. Huge pages only count against
RLIMIT_MEMLOCK once per ring, so a buffer that maps the same 2MB folio
over and over in a way that defeats coalescing gets a full bvec array
per registration while only the one folio counts as locked. 1GB of that
registered in 100 slots took several times a 64MB memory.max, with 2.6MB
charged.

Allocate the io_mapped_ubuf and the io_rsrc_node with
GFP_KERNEL_ACCOUNT. An object reused from the ring caches stays charged
to whoever allocated it first, same as the io_kiocb cache.

Fixes: de2939388be5 ("io_uring: improve registered buffer accounting for huge pages")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[axboe: 6.1 predates the rsrc node rework, charge the imu kvmalloc() and
the node kzalloc() instead]
---
 io_uring/rsrc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 1c5abe2dcd5e..6fd3dcaa3c42 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -250,7 +250,7 @@ static struct io_rsrc_node *io_rsrc_node_alloc(void)
 {
 	struct io_rsrc_node *ref_node;
 
-	ref_node = kzalloc(sizeof(*ref_node), GFP_KERNEL);
+	ref_node = kzalloc(sizeof(*ref_node), GFP_KERNEL_ACCOUNT);
 	if (!ref_node)
 		return NULL;
 
@@ -1068,7 +1068,7 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
 		goto done;
 	}
 
-	imu = kvmalloc(struct_size(imu, bvec, nr_pages), GFP_KERNEL);
+	imu = kvmalloc(struct_size(imu, bvec, nr_pages), GFP_KERNEL_ACCOUNT);
 	if (!imu)
 		goto done;
 
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6.1.y 5/8] io_uring: charge tctx nodes and personalities
  2026-11-04 18:43 [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Jens Axboe
                   ` (3 preceding siblings ...)
  2026-11-04 18:43 ` [PATCH 6.1.y 4/8] io_uring/rsrc: charge buffer arrays and nodes to memcg Jens Axboe
@ 2026-11-04 18:43 ` Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 6/8] io_uring: free XArray nodes left by a failed store Jens Axboe
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2026-11-04 18:43 UTC (permalink / raw)
  To: stable

From: Chris Mason <mason@kernel.org>

Commit 0b34e7b20a48710b6f53716bf7030920b69fdbdd upstream.

The io_tctx_node allocated the first time a task touches a ring, and
the XArray nodes behind tctx->xa and ctx->personalities, are plain
GFP_KERNEL. tctx->xa is indexed by the ring pointer, so nearly every
entry needs nodes of its own, and a task gets one entry per ring it has
used. 642 threads on 4000 rings held 2.3GB with 59MB charged against a
64MB memory.max.

Allocate the node with GFP_KERNEL_ACCOUNT and set XA_FLAGS_ACCOUNT on
both XArrays.

Fixes: 0f2122045b94 ("io_uring: don't rely on weak ->files references")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[axboe: 6.1 has kmalloc() for the node, inline in
__io_uring_add_tctx_node()]
---
 io_uring/io_uring.c | 2 +-
 io_uring/tctx.c     | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 655674be3859..dc4ff66ac64f 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -299,7 +299,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
 	io_alloc_cache_init(&ctx->apoll_cache);
 	io_alloc_cache_init(&ctx->netmsg_cache);
 	init_completion(&ctx->ref_comp);
-	xa_init_flags(&ctx->personalities, XA_FLAGS_ALLOC1);
+	xa_init_flags(&ctx->personalities, XA_FLAGS_ALLOC1 | XA_FLAGS_ACCOUNT);
 	mutex_init(&ctx->uring_lock);
 	init_waitqueue_head(&ctx->cq_wait);
 	spin_lock_init(&ctx->completion_lock);
diff --git a/io_uring/tctx.c b/io_uring/tctx.c
index e4ec8c0411ab..d2da97d86f44 100644
--- a/io_uring/tctx.c
+++ b/io_uring/tctx.c
@@ -93,7 +93,7 @@ __cold int io_uring_alloc_task_context(struct task_struct *task,
 		return ret;
 	}
 
-	xa_init(&tctx->xa);
+	xa_init_flags(&tctx->xa, XA_FLAGS_ACCOUNT);
 	init_waitqueue_head(&tctx->wait);
 	atomic_set(&tctx->in_idle, 0);
 	atomic_set(&tctx->inflight_tracked, 0);
@@ -125,7 +125,7 @@ int __io_uring_add_tctx_node(struct io_ring_ctx *ctx)
 		}
 	}
 	if (!xa_load(&tctx->xa, (unsigned long)ctx)) {
-		node = kmalloc(sizeof(*node), GFP_KERNEL);
+		node = kmalloc(sizeof(*node), GFP_KERNEL_ACCOUNT);
 		if (!node)
 			return -ENOMEM;
 		node->ctx = ctx;
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6.1.y 6/8] io_uring: free XArray nodes left by a failed store
  2026-11-04 18:43 [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Jens Axboe
                   ` (4 preceding siblings ...)
  2026-11-04 18:43 ` [PATCH 6.1.y 5/8] io_uring: charge tctx nodes and personalities Jens Axboe
@ 2026-11-04 18:43 ` Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 7/8] io_uring/sqpoll: don't wait for the thread to exit Jens Axboe
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2026-11-04 18:43 UTC (permalink / raw)
  To: stable

From: Chris Mason <mason@kernel.org>

Commit 51bab09b7ca1a9a6dd9303a3b7ee346f8128c963 upstream.

A failed xa_store() can leave nodes without entries in the tree, and
erasing every entry doesn't free those. An XArray needs xa_destroy()
before it goes away, even an empty one. That was dropped for tctx->xa in
commit ca6484cd308a ("io_uring: no need to call xa_destroy() on empty
xarray") over a lockdep report from freeing the tctx in softirq context,
and ctx->personalities never had it.

Now that the nodes are charged, a store can fail at memory.max and the
leaked nodes stay charged. Call xa_destroy() in io_uring_clean_tctx(),
which the task runs itself in process context before the tctx is freed,
in the error path of __io_uring_add_tctx_node(), and for
ctx->personalities in io_ring_ctx_free().

Fixes: ca6484cd308a ("io_uring: no need to call xa_destroy() on empty xarray")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[axboe: 6.1 installs the tctx before adding the node and has no error
path that frees it, drop that hunk. There's no ctx->hpage_acct either]
---
 io_uring/io_uring.c | 1 +
 io_uring/tctx.c     | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index dc4ff66ac64f..3392218887d9 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -2797,6 +2797,7 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
 	kfree(ctx->dummy_ubuf);
 	kfree(ctx->io_bl);
 	xa_destroy(&ctx->io_bl_xa);
+	xa_destroy(&ctx->personalities);
 	kfree(ctx);
 }
 
diff --git a/io_uring/tctx.c b/io_uring/tctx.c
index d2da97d86f44..f94ff56fe874 100644
--- a/io_uring/tctx.c
+++ b/io_uring/tctx.c
@@ -197,6 +197,8 @@ __cold void io_uring_clean_tctx(struct io_uring_task *tctx)
 		io_uring_del_tctx_node(index);
 		cond_resched();
 	}
+	/* A failed xa_store() leaves nodes with no entry behind. */
+	xa_destroy(&tctx->xa);
 	if (wq) {
 		/*
 		 * Must be after io_uring_del_tctx_node() (removes nodes under
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6.1.y 7/8] io_uring/sqpoll: don't wait for the thread to exit
  2026-11-04 18:43 [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Jens Axboe
                   ` (5 preceding siblings ...)
  2026-11-04 18:43 ` [PATCH 6.1.y 6/8] io_uring: free XArray nodes left by a failed store Jens Axboe
@ 2026-11-04 18:43 ` Jens Axboe
  2026-11-04 18:43 ` [PATCH 6.1.y 8/8] io_uring/timeout: count cancelled timeouts in cq_timeouts Jens Axboe
  2026-11-04 20:51 ` [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Greg KH
  8 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2026-11-04 18:43 UTC (permalink / raw)
  To: stable

From: Chris Mason <mason@kernel.org>

Commit 360395e8dbf9d23579f74b84a1af11190813b0f8 upstream.

io_sq_thread_stop() wakes the SQPOLL thread and waits for it to exit.
The thread belongs to the thread group that created the ring, so a
SIGSTOP or the cgroup freezer holds it in get_signal(), and the wake up
doesn't change that. io_ring_exit_work() then sleeps in that wait until
someone continues or kills the process. iou_exit has 64 slots, so 64
closed SQPOLL rings of a stopped process keep every other ring from
being freed, for everyone.

Don't wait. Set the stop bit, wake the thread, and let it exit when it
gets to run again. The sqd can now outlive its last ring, so give it a
second refcount with one reference for the rings and one for the thread,
and free it with the last one. The thread can't reach a freed ring,
rings leave ctx_list before dropping their reference, and the io-wq hash
is refcounted.

Fixes: 16efa4fce3b7 ("io_uring: allow IO worker threads to be frozen")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[axboe: 6.1 has a single exit path in io_sq_thread(), drop the thread's
free_refs share there]
---
 io_uring/sqpoll.c | 28 +++++++++++++++++++++++-----
 io_uring/sqpoll.h |  3 ++-
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c
index adc01f65464b..2cbe580d76af 100644
--- a/io_uring/sqpoll.c
+++ b/io_uring/sqpoll.c
@@ -52,6 +52,24 @@ void io_sq_thread_park(struct io_sq_data *sqd)
 		wake_up_process(sqd->thread);
 }
 
+/*
+ * The sqd has two holders: its rings, as one, and its thread. Neither waits
+ * for the other to let go. The one that lets go last frees the sqd.
+ */
+static void io_sq_data_release(struct io_sq_data *sqd)
+{
+	if (refcount_dec_and_test(&sqd->free_refs))
+		kfree(sqd);
+}
+
+/*
+ * Ask the thread to exit, and don't wait for it. A thread that is stopped or
+ * frozen exits only when a user lets it run again, and the exit work of the
+ * ring would keep its place in the workqueue until then. All rings have left
+ * ctx_list by now and have no request left, so the thread can reach none of
+ * them. What it still uses is its own or counted: the sqd by free_refs, the
+ * hash of its io-wq by hash->refs.
+ */
 void io_sq_thread_stop(struct io_sq_data *sqd)
 {
 	WARN_ON_ONCE(sqd->thread == current);
@@ -62,7 +80,6 @@ void io_sq_thread_stop(struct io_sq_data *sqd)
 	if (sqd->thread)
 		wake_up_process(sqd->thread);
 	mutex_unlock(&sqd->lock);
-	wait_for_completion(&sqd->exited);
 }
 
 void io_put_sq_data(struct io_sq_data *sqd)
@@ -71,7 +88,7 @@ void io_put_sq_data(struct io_sq_data *sqd)
 		WARN_ON_ONCE(atomic_read(&sqd->park_pending));
 
 		io_sq_thread_stop(sqd);
-		kfree(sqd);
+		io_sq_data_release(sqd);
 	}
 }
 
@@ -153,10 +170,10 @@ static struct io_sq_data *io_get_sq_data(struct io_uring_params *p,
 
 	atomic_set(&sqd->park_pending, 0);
 	refcount_set(&sqd->refs, 1);
+	refcount_set(&sqd->free_refs, 2);
 	INIT_LIST_HEAD(&sqd->ctx_list);
 	mutex_init(&sqd->lock);
 	init_waitqueue_head(&sqd->wait);
-	init_completion(&sqd->exited);
 	return sqd;
 }
 
@@ -327,7 +344,7 @@ static int io_sq_thread(void *data)
 	io_run_task_work();
 	mutex_unlock(&sqd->lock);
 
-	complete(&sqd->exited);
+	io_sq_data_release(sqd);
 	do_exit(0);
 }
 
@@ -448,7 +465,8 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx,
 		put_task_struct(task_to_put);
 	return 0;
 err_sqpoll:
-	complete(&ctx->sq_data->exited);
+	/* no thread was made: let go of its share */
+	io_sq_data_release(ctx->sq_data);
 err:
 	io_sq_thread_finish(ctx);
 	if (task_to_put)
diff --git a/io_uring/sqpoll.h b/io_uring/sqpoll.h
index 36245f1afa5e..3e41db84014b 100644
--- a/io_uring/sqpoll.h
+++ b/io_uring/sqpoll.h
@@ -2,6 +2,8 @@
 
 struct io_sq_data {
 	refcount_t		refs;
+	/* one for all the rings, one for the thread: the last put frees */
+	refcount_t		free_refs;
 	atomic_t		park_pending;
 	struct mutex		lock;
 
@@ -17,7 +19,6 @@ struct io_sq_data {
 	pid_t			task_tgid;
 
 	unsigned long		state;
-	struct completion	exited;
 };
 
 int io_sq_offload_create(struct io_ring_ctx *ctx, struct io_uring_params *p);
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6.1.y 8/8] io_uring/timeout: count cancelled timeouts in cq_timeouts
  2026-11-04 18:43 [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Jens Axboe
                   ` (6 preceding siblings ...)
  2026-11-04 18:43 ` [PATCH 6.1.y 7/8] io_uring/sqpoll: don't wait for the thread to exit Jens Axboe
@ 2026-11-04 18:43 ` Jens Axboe
  2026-11-04 20:51 ` [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Greg KH
  8 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2026-11-04 18:43 UTC (permalink / raw)
  To: stable

From: Cheng Yongkang <teel4res@gmail.com>

Commit 1c8b49851543f41fc8bb18bcd1f15cc93d14b530 upstream.

io_timeout_cancel() posts the cancelled timeout's -ECANCELED CQE without
advancing ctx->cq_timeouts.  io_timeout_fn() and io_kill_timeout()
advance it for every timeout CQE they post, and io_flush_timeouts()
computes the number of non-timeout completions as

    seq = cached_cq_tail - cq_timeouts

to compare against each off timeout's target_seq.  The cancelled
timeout's CQE is therefore counted as a regular completion, so every
cancellation makes an already armed off timeout fire one completion
early.

A ring with a keep-alive timeout of off=4 completes it after two NOPs
when one off=100 victim is cancelled through IORING_OP_ASYNC_CANCEL, and
before any NOP when two victims are cancelled.  The cancel CQE should
count, but the cancelled timeouts' -ECANCELED CQEs must not: the
expected counts are three and two NOPs respectively.

Advance cq_timeouts when io_timeout_extract() succeeds, under
timeout_lock and before the -ECANCELED completion is queued, matching
io_timeout_fn() and io_kill_timeout().  The -ENOENT and -EALREADY paths
post no new timeout CQE and keep their accounting.  Both the
ASYNC_CANCEL and the TIMEOUT_REMOVE path go through io_timeout_cancel().

Fixes: bfe68a221905 ("io_uring: off timeouts based only on completions")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Cheng Yongkang <teel4res@gmail.com>
Link: https://patch.msgid.link/179328314078.648427.13761781546953594668@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[axboe: 6.1 uses a regular spinlock for ->timeout_lock]
---
 io_uring/timeout.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/io_uring/timeout.c b/io_uring/timeout.c
index 6238187e7966..d793edae44a8 100644
--- a/io_uring/timeout.c
+++ b/io_uring/timeout.c
@@ -267,6 +267,9 @@ int io_timeout_cancel(struct io_ring_ctx *ctx, struct io_cancel_data *cd)
 
 	spin_lock_irq(&ctx->timeout_lock);
 	req = io_timeout_extract(ctx, cd);
+	if (!IS_ERR(req))
+		atomic_set(&ctx->cq_timeouts,
+			   atomic_read(&ctx->cq_timeouts) + 1);
 	spin_unlock_irq(&ctx->timeout_lock);
 
 	if (IS_ERR(req))
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable
  2026-11-04 18:43 [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Jens Axboe
                   ` (7 preceding siblings ...)
  2026-11-04 18:43 ` [PATCH 6.1.y 8/8] io_uring/timeout: count cancelled timeouts in cq_timeouts Jens Axboe
@ 2026-11-04 20:51 ` Greg KH
  2026-11-04 20:53   ` Jens Axboe
  8 siblings, 1 reply; 12+ messages in thread
From: Greg KH @ 2026-11-04 20:51 UTC (permalink / raw)
  To: Jens Axboe; +Cc: stable

On Wed, Nov 04, 2026 at 11:43:20AM -0700, Jens Axboe wrote:
> Hi Greg,
> 
> Here are io_uring fixes for 6.1-stable.

Thanks for all of these different series, all now queued up!

greg k-h

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable
  2026-11-04 20:51 ` [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Greg KH
@ 2026-11-04 20:53   ` Jens Axboe
  2026-11-04 21:00     ` Greg KH
  0 siblings, 1 reply; 12+ messages in thread
From: Jens Axboe @ 2026-11-04 20:53 UTC (permalink / raw)
  To: Greg KH; +Cc: stable

On 11/4/26 1:51 PM, Greg KH wrote:
> On Wed, Nov 04, 2026 at 11:43:20AM -0700, Jens Axboe wrote:
>> Hi Greg,
>>
>> Here are io_uring fixes for 6.1-stable.
> 
> Thanks for all of these different series, all now queued up!

Let's thank my tireless virtual assistant. Have the entire
process dialed in now, we'll never miss another stable
patch again and may even proactively backport things that
are in the "good to have" bucket in terms of behavior or
fixes.

Which makes me ponder if I should just switch the io_uring
side to be entirely self-provided, rather than have any kind
of automatic picking?

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable
  2026-11-04 20:53   ` Jens Axboe
@ 2026-11-04 21:00     ` Greg KH
  0 siblings, 0 replies; 12+ messages in thread
From: Greg KH @ 2026-11-04 21:00 UTC (permalink / raw)
  To: Jens Axboe; +Cc: stable

On Wed, Nov 04, 2026 at 01:53:15PM -0700, Jens Axboe wrote:
> On 11/4/26 1:51 PM, Greg KH wrote:
> > On Wed, Nov 04, 2026 at 11:43:20AM -0700, Jens Axboe wrote:
> >> Hi Greg,
> >>
> >> Here are io_uring fixes for 6.1-stable.
> > 
> > Thanks for all of these different series, all now queued up!
> 
> Let's thank my tireless virtual assistant. Have the entire
> process dialed in now, we'll never miss another stable
> patch again and may even proactively backport things that
> are in the "good to have" bucket in terms of behavior or
> fixes.

Nice!

> Which makes me ponder if I should just switch the io_uring
> side to be entirely self-provided, rather than have any kind
> of automatic picking?

That's your call, I'll do whatever you want here.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-11-04 21:00 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-04 18:43 [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Jens Axboe
2026-11-04 18:43 ` [PATCH 6.1.y 1/8] io_uring/net: keep recvmsg buffer select length within MAX_RW_COUNT Jens Axboe
2026-11-04 18:43 ` [PATCH 6.1.y 2/8] io_uring/net: don't retry a non-blocking connect() that fails with -EAGAIN Jens Axboe
2026-11-04 18:43 ` [PATCH 6.1.y 3/8] io_uring/io-wq: no new workers once the exit has begun Jens Axboe
2026-11-04 18:43 ` [PATCH 6.1.y 4/8] io_uring/rsrc: charge buffer arrays and nodes to memcg Jens Axboe
2026-11-04 18:43 ` [PATCH 6.1.y 5/8] io_uring: charge tctx nodes and personalities Jens Axboe
2026-11-04 18:43 ` [PATCH 6.1.y 6/8] io_uring: free XArray nodes left by a failed store Jens Axboe
2026-11-04 18:43 ` [PATCH 6.1.y 7/8] io_uring/sqpoll: don't wait for the thread to exit Jens Axboe
2026-11-04 18:43 ` [PATCH 6.1.y 8/8] io_uring/timeout: count cancelled timeouts in cq_timeouts Jens Axboe
2026-11-04 20:51 ` [PATCH 6.1.y 0/8] io_uring fixes for 6.1-stable Greg KH
2026-11-04 20:53   ` Jens Axboe
2026-11-04 21:00     ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox