FAILED: patch "[PATCH] io_uring/rw: end write accounting from ->ki_complete" failed to apply to 6.6-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.6-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.6.y
git checkout FETCH_HEAD
git cherry-pick -x 796aa0547557e63338657ed1c487906f9fac4c73
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026091624-delirium-hangout-abb2@gregkh' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 796aa0547557e63338657ed1c487906f9fac4c73 Mon Sep 17 00:00:00 2001
From: Jens Axboe <[email protected]>
Date: Tue, 8 Sep 2026 17:53:20 -0600
Subject: [PATCH] io_uring/rw: end write accounting from ->ki_complete
Commit b000145e9907 moved both the fsnotify calls and the write accounting out of the kiocb completion handler and into the io_req_rw_complete() task_work. However, only the fsnotify part actually needed to move as it may sleep. Ending the write accounting is just a percpu_up_read() on the superblock writers sem.
Deferring it is a problem, because it makes dropping SB_FREEZE_WRITE protection depend on the ring owner getting to running task_work. But the task may be blocked in freeze_super(), causing it to never get to that:
task io-wq worker
--------------------------------------------------------------
io_write()
io_kiocb_start_write() (takes sb_writers, hidden from
lockdep by __sb_writers_release)
write_iter() -> -EIOCBQUEUED
ioctl(FS_IOC_SHUTDOWN)
bdev_freeze()
freeze_super()
percpu_down_write() <- waits for the reader above
io_write()
kiocb_start_write()
percpu_down_read() <- queued
behind the writer
<bio completes>
io_complete_rw()
queues io_req_rw_complete() <- never runs, task is in D state
End the write from io_complete_rw() instead, and leave only the fsnotify calls in task_work.
io_uring/rw.c +19 -10
@@ -517,20 +517,25 @@ static void io_req_end_write(struct io_kiocb *req) } } -/* -* Trigger the notifications after having done some IO, and finish the write -* accounting, if any. -*/ +/* Trigger the notifications after having done some IO. */ +static void io_req_io_notify (struct io_kiocb *req) +{ + struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw); + +if (rw->kiocb.ki_flags &IOCB_WRITE ) +fsnotify_modify (req->file); +else +fsnotify_access (req->file); +} + +/* Finish write accounting and notify, for inline completions only. */ static void io_req_io_end (struct io_kiocb *req) { struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw); -if (rw->kiocb.ki_flags &IOCB_WRITE ) { +if (rw->kiocb.ki_flags &IOCB_WRITE )io_req_end_write (req); -fsnotify_modify (req->file); - }else { -fsnotify_access (req->file); - } +io_req_io_notify (req); }static void __io_complete_rw_common (struct io_kiocb *req,long res)
@@ -563,7 +568,7 @@ void io_req_rw_complete(struct io_tw_req tw_req, io_tw_token_t tw) {struct io_kiocb *req = tw_req.req; -io_req_io_end (req); +io_req_io_notify (req);if (req->flags & (REQ_F_BUFFER_SELECTED |REQ_F_BUFFER_RING )) req->cqe.flags |=io_put_kbuf (req,max (req->cqe.res,0 ),NULL );
@@ -577,6 +582,10 @@ static void io_complete_rw(struct kiocb *kiocb, long res) struct io_rw *rw = container_of(kiocb, struct io_rw, kiocb);struct io_kiocb *req =cmd_to_io_kiocb (rw); +/* ring owner may block in freeze_super() before task_work runs */ +if (kiocb->ki_flags &IOCB_WRITE ) +io_req_end_write (req); +__io_complete_rw_common (req, res);io_req_set_res (req,io_fixup_rw_res (req, res),0 ); req->io_task_work.func = io_req_rw_complete;
Sasha Levin
maintainerPATCH 1/1 io_uring/rw: end write accounting from ->ki_complete
From: Jens Axboe <[email protected]>
[ Upstream commit 796aa0547557e63338657ed1c487906f9fac4c73 ]
Commit b000145e9907 moved both the fsnotify calls and the write accounting out of the kiocb completion handler and into the io_req_rw_complete() task_work. However, only the fsnotify part actually needed to move as it may sleep. Ending the write accounting is just a percpu_up_read() on the superblock writers sem.
Deferring it is a problem, because it makes dropping SB_FREEZE_WRITE protection depend on the ring owner getting to running task_work. But the task may be blocked in freeze_super(), causing it to never get to that:
task io-wq worker
--------------------------------------------------------------
io_write()
io_kiocb_start_write() (takes sb_writers, hidden from
lockdep by __sb_writers_release)
write_iter() -> -EIOCBQUEUED
ioctl(FS_IOC_SHUTDOWN)
bdev_freeze()
freeze_super()
percpu_down_write() <- waits for the reader above
io_write()
kiocb_start_write()
percpu_down_read() <- queued
behind the writer
<bio completes>
io_complete_rw()
queues io_req_rw_complete() <- never runs, task is in D state
End the write from io_complete_rw() instead, and leave only the fsnotify calls in task_work.
--- io_uring/rw.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-)
io_uring/rw.c +15 -17
@@ -244,20 +244,15 @@ static void io_req_end_write(struct io_kiocb *req) } } -/* -* Trigger the notifications after having done some IO, and finish the write -* accounting, if any. -*/ -static void io_req_io_end (struct io_kiocb *req) +/* Trigger the notifications after having done some IO. */ +static void io_req_io_notify (struct io_kiocb *req) { struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw); -if (rw->kiocb.ki_flags &IOCB_WRITE ) { -io_req_end_write (req); +if (rw->kiocb.ki_flags &IOCB_WRITE )fsnotify_modify (req->file); - }else { +else fsnotify_access (req->file); - } }static bool __io_complete_rw_common (struct io_kiocb *req,long res)
@@ -265,11 +260,8 @@ static bool __io_complete_rw_common(struct io_kiocb *req, long res)if (unlikely (res != req->cqe.res)) {if ((res == -EAGAIN || res == -EOPNOTSUPP ) &&io_rw_should_reissue (req)) { -/* -* Reissue will start accounting again, finish the -* current cycle. -*/ -io_req_io_end (req); +/* Notify for the current cycle before reissuing. */ +io_req_io_notify (req); req->flags |=REQ_F_REISSUE |REQ_F_PARTIAL_IO ;return true; }
@@ -304,7 +296,7 @@ void io_req_rw_complete(struct io_kiocb *req, struct io_tw_state *ts)io_req_set_res (req,io_fixup_rw_res (req, res),0 ); } -io_req_io_end (req); +io_req_io_notify (req);if (req->flags & (REQ_F_BUFFER_SELECTED |REQ_F_BUFFER_RING )) {unsigned issue_flags = ts->locked ?0 :IO_URING_F_UNLOCKED ;
@@ -319,6 +311,10 @@ static void io_complete_rw(struct kiocb *kiocb, long res) struct io_rw *rw = container_of(kiocb, struct io_rw, kiocb);struct io_kiocb *req =cmd_to_io_kiocb (rw); +/* ring owner may block in freeze_super() before task_work runs */ +if (kiocb->ki_flags &IOCB_WRITE ) +io_req_end_write (req); +if (!kiocb->dio_complete || !(kiocb->ki_flags &IOCB_DIO_CALLER_COMP )) {if (__io_complete_rw_common (req, res))return ;
@@ -358,10 +354,12 @@ static int kiocb_done(struct io_kiocb *req, ssize_t ret,if (ret >=0 && (rw->kiocb.ki_complete == io_complete_rw)) {if (!__io_complete_rw_common (req, ret)) {/* -* Safe to call io_end from here as we're inline +* Safe to notify from here as we're inline * from the submission path. */ -io_req_io_end (req); +if (rw->kiocb.ki_flags &IOCB_WRITE ) +io_req_end_write (req); +io_req_io_notify (req);io_req_set_res (req, final_ret,io_put_kbuf (req, issue_flags));return IOU_OK ;
Signature · 1 line
2.53.0