From: Sasha Levin Date: Sat, 9 Nov 2024 14:55:50 +0000 (-0500) Subject: Fixes for 5.15 X-Git-Tag: v5.15.172~54^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f180c9ca2e1c15b8c053c84d129d812f8676db92;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/fs-create-kiocb_-start-end-_write-helpers.patch b/queue-5.15/fs-create-kiocb_-start-end-_write-helpers.patch new file mode 100644 index 00000000000..74d9ec73619 --- /dev/null +++ b/queue-5.15/fs-create-kiocb_-start-end-_write-helpers.patch @@ -0,0 +1,76 @@ +From 8f4871d89544a1b4b1b883d93a0f164976b1c431 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Aug 2023 17:13:33 +0300 +Subject: fs: create kiocb_{start,end}_write() helpers + +From: Amir Goldstein + +Commit ed0360bbab72b829437b67ebb2f9cfac19f59dfe upstream. + +aio, io_uring, cachefiles and overlayfs, all open code an ugly variant +of file_{start,end}_write() to silence lockdep warnings. + +Create helpers for this lockdep dance so we can use the helpers in all +the callers. + +Suggested-by: Jan Kara +Signed-off-by: Amir Goldstein +Reviewed-by: Jan Kara +Reviewed-by: Jens Axboe +Message-Id: <20230817141337.1025891-4-amir73il@gmail.com> +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + include/linux/fs.h | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 6ff6ade229a07..2ef0e48c89ec4 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3058,6 +3058,42 @@ static inline void file_end_write(struct file *file) + __sb_end_write(file_inode(file)->i_sb, SB_FREEZE_WRITE); + } + ++/** ++ * kiocb_start_write - get write access to a superblock for async file io ++ * @iocb: the io context we want to submit the write with ++ * ++ * This is a variant of sb_start_write() for async io submission. ++ * Should be matched with a call to kiocb_end_write(). ++ */ ++static inline void kiocb_start_write(struct kiocb *iocb) ++{ ++ struct inode *inode = file_inode(iocb->ki_filp); ++ ++ sb_start_write(inode->i_sb); ++ /* ++ * Fool lockdep by telling it the lock got released so that it ++ * doesn't complain about the held lock when we return to userspace. ++ */ ++ __sb_writers_release(inode->i_sb, SB_FREEZE_WRITE); ++} ++ ++/** ++ * kiocb_end_write - drop write access to a superblock after async file io ++ * @iocb: the io context we sumbitted the write with ++ * ++ * Should be matched with a call to kiocb_start_write(). ++ */ ++static inline void kiocb_end_write(struct kiocb *iocb) ++{ ++ struct inode *inode = file_inode(iocb->ki_filp); ++ ++ /* ++ * Tell lockdep we inherited freeze protection from submission thread. ++ */ ++ __sb_writers_acquired(inode->i_sb, SB_FREEZE_WRITE); ++ sb_end_write(inode->i_sb); ++} ++ + /* + * This is used for regular files where some users -- especially the + * currently executed binary in a process, previously handled via +-- +2.43.0 + diff --git a/queue-5.15/io_uring-rename-kiocb_end_write-local-helper.patch b/queue-5.15/io_uring-rename-kiocb_end_write-local-helper.patch new file mode 100644 index 00000000000..9f7a1f2ee59 --- /dev/null +++ b/queue-5.15/io_uring-rename-kiocb_end_write-local-helper.patch @@ -0,0 +1,65 @@ +From 6c45930377ee21a068c8eccf0124e20c7754a495 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Aug 2023 17:13:31 +0300 +Subject: io_uring: rename kiocb_end_write() local helper + +From: Amir Goldstein + +Commit a370167fe526123637965f60859a9f1f3e1a58b7 upstream. + +This helper does not take a kiocb as input and we want to create a +common helper by that name that takes a kiocb as input. + +Signed-off-by: Amir Goldstein +Reviewed-by: Jan Kara +Reviewed-by: Jens Axboe +Message-Id: <20230817141337.1025891-2-amir73il@gmail.com> +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index f1ab0cd987273..7afa3827bfd5e 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -2672,7 +2672,7 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, long min) + return ret; + } + +-static void kiocb_end_write(struct io_kiocb *req) ++static void io_req_end_write(struct io_kiocb *req) + { + /* + * Tell lockdep we inherited freeze protection from submission +@@ -2742,7 +2742,7 @@ static void io_req_io_end(struct io_kiocb *req) + struct io_rw *rw = &req->rw; + + if (rw->kiocb.ki_flags & IOCB_WRITE) { +- kiocb_end_write(req); ++ io_req_end_write(req); + fsnotify_modify(req->file); + } else { + fsnotify_access(req->file); +@@ -2822,7 +2822,7 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res, long res2) + struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb); + + if (kiocb->ki_flags & IOCB_WRITE) +- kiocb_end_write(req); ++ io_req_end_write(req); + if (unlikely(res != req->result)) { + if (res == -EAGAIN && io_rw_should_reissue(req)) { + req->flags |= REQ_F_REISSUE; +@@ -3822,7 +3822,7 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags) + ret = io_setup_async_rw(req, iovec, inline_vecs, iter, false); + if (!ret) { + if (kiocb->ki_flags & IOCB_WRITE) +- kiocb_end_write(req); ++ io_req_end_write(req); + return -EAGAIN; + } + return ret; +-- +2.43.0 + diff --git a/queue-5.15/io_uring-rw-fix-missing-nowait-check-for-o_direct-st.patch b/queue-5.15/io_uring-rw-fix-missing-nowait-check-for-o_direct-st.patch new file mode 100644 index 00000000000..99f6258791a --- /dev/null +++ b/queue-5.15/io_uring-rw-fix-missing-nowait-check-for-o_direct-st.patch @@ -0,0 +1,121 @@ +From e4520932bc363f59716cf9a4454255fe86a95a68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 31 Oct 2024 08:05:44 -0600 +Subject: io_uring/rw: fix missing NOWAIT check for O_DIRECT start write + +From: Jens Axboe + +Commit 1d60d74e852647255bd8e76f5a22dc42531e4389 upstream. + +When io_uring starts a write, it'll call kiocb_start_write() to bump the +super block rwsem, preventing any freezes from happening while that +write is in-flight. The freeze side will grab that rwsem for writing, +excluding any new writers from happening and waiting for existing writes +to finish. But io_uring unconditionally uses kiocb_start_write(), which +will block if someone is currently attempting to freeze the mount point. +This causes a deadlock where freeze is waiting for previous writes to +complete, but the previous writes cannot complete, as the task that is +supposed to complete them is blocked waiting on starting a new write. +This results in the following stuck trace showing that dependency with +the write blocked starting a new write: + +task:fio state:D stack:0 pid:886 tgid:886 ppid:876 +Call trace: + __switch_to+0x1d8/0x348 + __schedule+0x8e8/0x2248 + schedule+0x110/0x3f0 + percpu_rwsem_wait+0x1e8/0x3f8 + __percpu_down_read+0xe8/0x500 + io_write+0xbb8/0xff8 + io_issue_sqe+0x10c/0x1020 + io_submit_sqes+0x614/0x2110 + __arm64_sys_io_uring_enter+0x524/0x1038 + invoke_syscall+0x74/0x268 + el0_svc_common.constprop.0+0x160/0x238 + do_el0_svc+0x44/0x60 + el0_svc+0x44/0xb0 + el0t_64_sync_handler+0x118/0x128 + el0t_64_sync+0x168/0x170 +INFO: task fsfreeze:7364 blocked for more than 15 seconds. + Not tainted 6.12.0-rc5-00063-g76aaf945701c #7963 + +with the attempting freezer stuck trying to grab the rwsem: + +task:fsfreeze state:D stack:0 pid:7364 tgid:7364 ppid:995 +Call trace: + __switch_to+0x1d8/0x348 + __schedule+0x8e8/0x2248 + schedule+0x110/0x3f0 + percpu_down_write+0x2b0/0x680 + freeze_super+0x248/0x8a8 + do_vfs_ioctl+0x149c/0x1b18 + __arm64_sys_ioctl+0xd0/0x1a0 + invoke_syscall+0x74/0x268 + el0_svc_common.constprop.0+0x160/0x238 + do_el0_svc+0x44/0x60 + el0_svc+0x44/0xb0 + el0t_64_sync_handler+0x118/0x128 + el0t_64_sync+0x168/0x170 + +Fix this by having the io_uring side honor IOCB_NOWAIT, and only attempt a +blocking grab of the super block rwsem if it isn't set. For normal issue +where IOCB_NOWAIT would always be set, this returns -EAGAIN which will +have io_uring core issue a blocking attempt of the write. That will in +turn also get completions run, ensuring forward progress. + +Since freezing requires CAP_SYS_ADMIN in the first place, this isn't +something that can be triggered by a regular user. + +Cc: stable@vger.kernel.org # 5.10+ +Reported-by: Peter Mann +Link: https://lore.kernel.org/io-uring/38c94aec-81c9-4f62-b44e-1d87f5597644@sh.cz +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 718ab6a418425..b53099b595cc7 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -3724,6 +3724,25 @@ static int io_write_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + return io_prep_rw(req, sqe, WRITE); + } + ++static bool io_kiocb_start_write(struct io_kiocb *req, struct kiocb *kiocb) ++{ ++ struct inode *inode; ++ bool ret; ++ ++ if (!(req->flags & REQ_F_ISREG)) ++ return true; ++ if (!(kiocb->ki_flags & IOCB_NOWAIT)) { ++ kiocb_start_write(kiocb); ++ return true; ++ } ++ ++ inode = file_inode(kiocb->ki_filp); ++ ret = sb_start_write_trylock(inode->i_sb); ++ if (ret) ++ __sb_writers_release(inode->i_sb, SB_FREEZE_WRITE); ++ return ret; ++} ++ + static int io_write(struct io_kiocb *req, unsigned int issue_flags) + { + struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; +@@ -3770,8 +3789,8 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags) + if (unlikely(ret)) + goto out_free; + +- if (req->flags & REQ_F_ISREG) +- kiocb_start_write(kiocb); ++ if (unlikely(!io_kiocb_start_write(req, kiocb))) ++ goto copy_iov; + kiocb->ki_flags |= IOCB_WRITE; + + if (req->file->f_op->write_iter) +-- +2.43.0 + diff --git a/queue-5.15/io_uring-use-kiocb_-start-end-_write-helpers.patch b/queue-5.15/io_uring-use-kiocb_-start-end-_write-helpers.patch new file mode 100644 index 00000000000..cb9fbc47f40 --- /dev/null +++ b/queue-5.15/io_uring-use-kiocb_-start-end-_write-helpers.patch @@ -0,0 +1,68 @@ +From 7504263efcd5b686c828e565312820e5aa0bf464 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Aug 2023 17:13:34 +0300 +Subject: io_uring: use kiocb_{start,end}_write() helpers + +From: Amir Goldstein + +Commit e484fd73f4bdcb00c2188100c2d84e9f3f5c9f7d upstream. + +Use helpers instead of the open coded dance to silence lockdep warnings. + +Suggested-by: Jan Kara +Signed-off-by: Amir Goldstein +Reviewed-by: Jan Kara +Reviewed-by: Jens Axboe +Message-Id: <20230817141337.1025891-5-amir73il@gmail.com> +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 23 ++++------------------- + 1 file changed, 4 insertions(+), 19 deletions(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 7afa3827bfd5e..718ab6a418425 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -2674,15 +2674,10 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, long min) + + static void io_req_end_write(struct io_kiocb *req) + { +- /* +- * Tell lockdep we inherited freeze protection from submission +- * thread. +- */ + if (req->flags & REQ_F_ISREG) { +- struct super_block *sb = file_inode(req->file)->i_sb; ++ struct io_rw *rw = &req->rw; + +- __sb_writers_acquired(sb, SB_FREEZE_WRITE); +- sb_end_write(sb); ++ kiocb_end_write(&rw->kiocb); + } + } + +@@ -3775,18 +3770,8 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags) + if (unlikely(ret)) + goto out_free; + +- /* +- * Open-code file_start_write here to grab freeze protection, +- * which will be released by another thread in +- * io_complete_rw(). Fool lockdep by telling it the lock got +- * released so that it doesn't complain about the held lock when +- * we return to userspace. +- */ +- if (req->flags & REQ_F_ISREG) { +- sb_start_write(file_inode(req->file)->i_sb); +- __sb_writers_release(file_inode(req->file)->i_sb, +- SB_FREEZE_WRITE); +- } ++ if (req->flags & REQ_F_ISREG) ++ kiocb_start_write(kiocb); + kiocb->ki_flags |= IOCB_WRITE; + + if (req->file->f_op->write_iter) +-- +2.43.0 + diff --git a/queue-5.15/posix-cpu-timers-clear-tick_dep_bit_posix_timer-on-c.patch b/queue-5.15/posix-cpu-timers-clear-tick_dep_bit_posix_timer-on-c.patch new file mode 100644 index 00000000000..bfad5406cb6 --- /dev/null +++ b/queue-5.15/posix-cpu-timers-clear-tick_dep_bit_posix_timer-on-c.patch @@ -0,0 +1,92 @@ +From b327e48898c1e1c007b104171dbf8d121bfe8d57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Oct 2024 18:35:35 -0700 +Subject: posix-cpu-timers: Clear TICK_DEP_BIT_POSIX_TIMER on clone + +From: Benjamin Segall + +[ Upstream commit b5413156bad91dc2995a5c4eab1b05e56914638a ] + +When cloning a new thread, its posix_cputimers are not inherited, and +are cleared by posix_cputimers_init(). However, this does not clear the +tick dependency it creates in tsk->tick_dep_mask, and the handler does +not reach the code to clear the dependency if there were no timers to +begin with. + +Thus if a thread has a cputimer running before clone/fork, all +descendants will prevent nohz_full unless they create a cputimer of +their own. + +Fix this by entirely clearing the tick_dep_mask in copy_process(). +(There is currently no inherited state that needs a tick dependency) + +Process-wide timers do not have this problem because fork does not copy +signal_struct as a baseline, it creates one from scratch. + +Fixes: b78783000d5c ("posix-cpu-timers: Migrate to use new tick dependency mask model") +Signed-off-by: Ben Segall +Signed-off-by: Thomas Gleixner +Reviewed-by: Frederic Weisbecker +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/all/xm26o737bq8o.fsf@google.com +Signed-off-by: Sasha Levin +--- + include/linux/tick.h | 8 ++++++++ + kernel/fork.c | 2 ++ + 2 files changed, 10 insertions(+) + +diff --git a/include/linux/tick.h b/include/linux/tick.h +index 9459fef5b8573..9701c571a5cfe 100644 +--- a/include/linux/tick.h ++++ b/include/linux/tick.h +@@ -252,12 +252,19 @@ static inline void tick_dep_set_task(struct task_struct *tsk, + if (tick_nohz_full_enabled()) + tick_nohz_dep_set_task(tsk, bit); + } ++ + static inline void tick_dep_clear_task(struct task_struct *tsk, + enum tick_dep_bits bit) + { + if (tick_nohz_full_enabled()) + tick_nohz_dep_clear_task(tsk, bit); + } ++ ++static inline void tick_dep_init_task(struct task_struct *tsk) ++{ ++ atomic_set(&tsk->tick_dep_mask, 0); ++} ++ + static inline void tick_dep_set_signal(struct task_struct *tsk, + enum tick_dep_bits bit) + { +@@ -291,6 +298,7 @@ static inline void tick_dep_set_task(struct task_struct *tsk, + enum tick_dep_bits bit) { } + static inline void tick_dep_clear_task(struct task_struct *tsk, + enum tick_dep_bits bit) { } ++static inline void tick_dep_init_task(struct task_struct *tsk) { } + static inline void tick_dep_set_signal(struct task_struct *tsk, + enum tick_dep_bits bit) { } + static inline void tick_dep_clear_signal(struct signal_struct *signal, +diff --git a/kernel/fork.c b/kernel/fork.c +index fec103ae640ff..23ffcf8a859c5 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -97,6 +97,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -2126,6 +2127,7 @@ static __latent_entropy struct task_struct *copy_process( + acct_clear_integrals(p); + + posix_cputimers_init(&p->posix_cputimers); ++ tick_dep_init_task(p); + + p->io_context = NULL; + audit_set_context(p, NULL); +-- +2.43.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 76cf2207461..ce6f57d4053 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -35,3 +35,8 @@ media-cx24116-prevent-overflows-on-snr-calculus.patch media-pulse8-cec-fix-data-timestamp-at-pulse8_setup.patch media-v4l2-tpg-prevent-the-risk-of-a-division-by-zero.patch media-v4l2-ctrls-api-fix-error-handling-for-v4l2_g_ctrl.patch +posix-cpu-timers-clear-tick_dep_bit_posix_timer-on-c.patch +io_uring-rename-kiocb_end_write-local-helper.patch +fs-create-kiocb_-start-end-_write-helpers.patch +io_uring-use-kiocb_-start-end-_write-helpers.patch +io_uring-rw-fix-missing-nowait-check-for-o_direct-st.patch