FAILED: patch "[PATCH] io_uring: always arm linked timeouts prior to issue" failed to apply to 6.14-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.14.y
git checkout FETCH_HEAD
git cherry-pick -x b53e523261bf058ea4a518b482222e7a277b186b
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025051224-effects-slightly-6462@gregkh' --subject-prefix 'PATCH 6.14.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From b53e523261bf058ea4a518b482222e7a277b186b Mon Sep 17 00:00:00 2001
From: Jens Axboe <[email protected]>
Date: Sun, 4 May 2025 08:06:28 -0600
Subject: [PATCH] io_uring: always arm linked timeouts prior to issue
There are a few spots where linked timeouts are armed, and not all of them adhere to the pre-arm, attempt issue, post-arm pattern. This can be problematic if the linked request returns that it will trigger a callback later, and does so before the linked timeout is fully armed.
Consolidate all the linked timeout handling into __io_issue_sqe(), rather than have it spread throughout the various issue entry points.
io_uring/io_uring.c +15 -35
@@ -448,24 +448,6 @@ static struct io_kiocb *__io_prep_linked_timeout(struct io_kiocb *req)return req->link; } -static inline struct io_kiocb *io_prep_linked_timeout (struct io_kiocb *req) -{ -if (likely (!(req->flags &REQ_F_ARM_LTIMEOUT ))) -return NULL ; -return __io_prep_linked_timeout (req); -} - -static noinline void __io_arm_ltimeout(struct io_kiocb *req) -{ -io_queue_linked_timeout (__io_prep_linked_timeout (req)); -} - -static inline void io_arm_ltimeout (struct io_kiocb *req) -{ -if (unlikely (req->flags &REQ_F_ARM_LTIMEOUT )) -__io_arm_ltimeout (req); -} -static void io_prep_async_work (struct io_kiocb *req) {const struct io_issue_def *def = &io_issue_defs[req->opcode];
@@ -518,7 +500,6 @@ static void io_prep_async_link(struct io_kiocb *req)static void io_queue_iowq (struct io_kiocb *req) { -struct io_kiocb *link =io_prep_linked_timeout (req);struct io_uring_task *tctx = req->tctx;BUG_ON (!tctx);
@@ -543,8 +524,6 @@ static void io_queue_iowq(struct io_kiocb *req)trace_io_uring_queue_async_work (req,io_wq_is_hashed (&req->work));io_wq_enqueue (tctx->io_wq, &req->work); -if (link) -io_queue_linked_timeout (link); }static void io_req_queue_iowq_tw (struct io_kiocb *req,io_tw_token_t tw)
@@ -1724,15 +1703,22 @@ static bool io_assign_file(struct io_kiocb *req, const struct io_issue_def *def,return !!req->file; } +#define REQ_ISSUE_SLOW_FLAGS (REQ_F_CREDS | REQ_F_ARM_LTIMEOUT) +static inline int __io_issue_sqe (struct io_kiocb *req,unsigned int issue_flags,const struct io_issue_def *def) {const struct cred *creds =NULL ; +struct io_kiocb *link =NULL ;int ret; -if (unlikely ((req->flags &REQ_F_CREDS ) && req->creds !=current_cred ())) - creds =override_creds (req->creds); +if (unlikely (req->flags &REQ_ISSUE_SLOW_FLAGS )) { +if ((req->flags &REQ_F_CREDS ) && req->creds !=current_cred ()) + creds =override_creds (req->creds); +if (req->flags &REQ_F_ARM_LTIMEOUT ) + link =__io_prep_linked_timeout (req); + }if (!def->audit_skip)audit_uring_entry (req->opcode);
@@ -1742,8 +1728,12 @@ static inline int __io_issue_sqe(struct io_kiocb *req,if (!def->audit_skip)audit_uring_exit (!ret, ret); -if (creds) -revert_creds (creds); +if (unlikely (creds || link)) { +if (creds) +revert_creds (creds); +if (link) +io_queue_linked_timeout (link); + }return ret; }
@@ -1769,7 +1759,6 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags)if (ret ==IOU_ISSUE_SKIP_COMPLETE ) { ret =0 ; -io_arm_ltimeout (req);/* If the op doesn't have a file, we're not polling for it */ if ((req->ctx->flags &IORING_SETUP_IOPOLL ) && def->iopoll_queue)
@@ -1824,8 +1813,6 @@ void io_wq_submit_work(struct io_wq_work *work)else req_ref_get (req); -io_arm_ltimeout (req); -/* either cancelled or io-wq is dying, so don't touch tctx->iowq */ if (atomic_read (&work->flags) &IO_WQ_WORK_CANCEL ) { fail:
@@ -1941,15 +1928,11 @@ struct file *io_file_get_normal(struct io_kiocb *req, int fd)static void io_queue_async (struct io_kiocb *req,int ret) __must_hold(&req->ctx->uring_lock) { -struct io_kiocb *linked_timeout; -if (ret != -EAGAIN || (req->flags &REQ_F_NOWAIT )) {io_req_defer_failed (req, ret);return ; } - linked_timeout =io_prep_linked_timeout (req); -switch (io_arm_poll_handler (req,0 )) {case IO_APOLL_READY :io_kbuf_recycle (req,0 );
@@ -1962,9 +1945,6 @@ static void io_queue_async(struct io_kiocb *req, int ret)case IO_APOLL_OK :break ; } - -if (linked_timeout) -io_queue_linked_timeout (linked_timeout); }static inline void io_queue_sqe (struct io_kiocb *req)
Jens Axboe
maintainerQuoted 5 lines · On 5/12/25 4:01 AM, [email protected] wrote:
The patch below does not apply to the 6.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
Here's a tested 6.14-stable backport.
Signature · 1 line
Jens Axboe
From ac2cdbcf56b8ad28319498c78f17f79a73965615 Mon Sep 17 00:00:00 2001
From: Jens Axboe <[email protected]>
Date: Sun, 4 May 2025 08:06:28 -0600
Subject: [PATCH 1/2] io_uring: always arm linked timeouts prior to issue
Commit b53e523261bf058ea4a518b482222e7a277b186b upstream.
There are a few spots where linked timeouts are armed, and not all of them adhere to the pre-arm, attempt issue, post-arm pattern. This can be problematic if the linked request returns that it will trigger a callback later, and does so before the linked timeout is fully armed.
Consolidate all the linked timeout handling into __io_issue_sqe(), rather than have it spread throughout the various issue entry points.
--- io_uring/io_uring.c | 50 ++++++++++++++------------------------------- 1 file changed, 15 insertions(+), 35 deletions(-)
io_uring/io_uring.c +15 -35
@@ -443,24 +443,6 @@ static struct io_kiocb *__io_prep_linked_timeout(struct io_kiocb *req)return req->link; } -static inline struct io_kiocb *io_prep_linked_timeout (struct io_kiocb *req) -{ -if (likely (!(req->flags &REQ_F_ARM_LTIMEOUT ))) -return NULL ; -return __io_prep_linked_timeout (req); -} - -static noinline void __io_arm_ltimeout(struct io_kiocb *req) -{ -io_queue_linked_timeout (__io_prep_linked_timeout (req)); -} - -static inline void io_arm_ltimeout (struct io_kiocb *req) -{ -if (unlikely (req->flags &REQ_F_ARM_LTIMEOUT )) -__io_arm_ltimeout (req); -} -static void io_prep_async_work (struct io_kiocb *req) {const struct io_issue_def *def = &io_issue_defs[req->opcode];
@@ -513,7 +495,6 @@ static void io_prep_async_link(struct io_kiocb *req)static void io_queue_iowq (struct io_kiocb *req) { -struct io_kiocb *link =io_prep_linked_timeout (req);struct io_uring_task *tctx = req->tctx;BUG_ON (!tctx);
@@ -538,8 +519,6 @@ static void io_queue_iowq(struct io_kiocb *req)trace_io_uring_queue_async_work (req,io_wq_is_hashed (&req->work));io_wq_enqueue (tctx->io_wq, &req->work); -if (link) -io_queue_linked_timeout (link); }static void io_req_queue_iowq_tw (struct io_kiocb *req,struct io_tw_state *ts)
@@ -1720,17 +1699,24 @@ static bool io_assign_file(struct io_kiocb *req, const struct io_issue_def *def,return !!req->file; } +#define REQ_ISSUE_SLOW_FLAGS (REQ_F_CREDS | REQ_F_ARM_LTIMEOUT) +static int io_issue_sqe (struct io_kiocb *req,unsigned int issue_flags) {const struct io_issue_def *def = &io_issue_defs[req->opcode];const struct cred *creds =NULL ; +struct io_kiocb *link =NULL ;int ret;if (unlikely (!io_assign_file (req, def, issue_flags)))return -EBADF ; -if (unlikely ((req->flags &REQ_F_CREDS ) && req->creds !=current_cred ())) - creds =override_creds (req->creds); +if (unlikely (req->flags &REQ_ISSUE_SLOW_FLAGS )) { +if ((req->flags &REQ_F_CREDS ) && req->creds !=current_cred ()) + creds =override_creds (req->creds); +if (req->flags &REQ_F_ARM_LTIMEOUT ) + link =__io_prep_linked_timeout (req); + }if (!def->audit_skip)audit_uring_entry (req->opcode);
@@ -1740,8 +1726,12 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags)if (!def->audit_skip)audit_uring_exit (!ret, ret); -if (creds) -revert_creds (creds); +if (unlikely (creds || link)) { +if (creds) +revert_creds (creds); +if (link) +io_queue_linked_timeout (link); + }if (ret ==IOU_OK ) {if (issue_flags &IO_URING_F_COMPLETE_DEFER )
@@ -1754,7 +1744,6 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags)if (ret ==IOU_ISSUE_SKIP_COMPLETE ) { ret =0 ; -io_arm_ltimeout (req);/* If the op doesn't have a file, we're not polling for it */ if ((req->ctx->flags &IORING_SETUP_IOPOLL ) && def->iopoll_queue)
@@ -1797,8 +1786,6 @@ void io_wq_submit_work(struct io_wq_work *work)else req_ref_get (req); -io_arm_ltimeout (req); -/* either cancelled or io-wq is dying, so don't touch tctx->iowq */ if (atomic_read (&work->flags) &IO_WQ_WORK_CANCEL ) { fail:
@@ -1914,15 +1901,11 @@ struct file *io_file_get_normal(struct io_kiocb *req, int fd)static void io_queue_async (struct io_kiocb *req,int ret) __must_hold(&req->ctx->uring_lock) { -struct io_kiocb *linked_timeout; -if (ret != -EAGAIN || (req->flags &REQ_F_NOWAIT )) {io_req_defer_failed (req, ret);return ; } - linked_timeout =io_prep_linked_timeout (req); -switch (io_arm_poll_handler (req,0 )) {case IO_APOLL_READY :io_kbuf_recycle (req,0 );
@@ -1935,9 +1918,6 @@ static void io_queue_async(struct io_kiocb *req, int ret)case IO_APOLL_OK :break ; } - -if (linked_timeout) -io_queue_linked_timeout (linked_timeout); }static inline void io_queue_sqe (struct io_kiocb *req)
Signature · 1 line
2.49.0