FAILED: patch "[PATCH] io_uring/rw: end write accounting from ->ki_complete" failed to apply to 6.18-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.18-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.18.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 '2026091623-wrangle-flammable-47de@gregkh' --subject-prefix 'PATCH 6.18.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 | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-)
io_uring/rw.c +13 -12
@@ -532,20 +532,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 void __io_complete_rw_common (struct io_kiocb *req,long res)
@@ -586,7 +581,7 @@ void io_req_rw_complete(struct io_tw_req tw_req, io_tw_token_t tw)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 )) req->cqe.flags |=io_put_kbuf (req, req->cqe.res,NULL );
@@ -600,6 +595,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 )) {__io_complete_rw_common (req, res);io_req_set_res (req,io_fixup_rw_res (req, res),0 );
@@ -675,10 +674,12 @@ static int kiocb_done(struct io_kiocb *req, ssize_t ret,__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);if (sel) cflags =io_put_kbuf (req, ret, sel->buf_list);io_req_set_res (req, final_ret, cflags);
Signature · 1 line
2.53.0