From: Greg Kroah-Hartman Date: Mon, 10 Mar 2025 08:00:07 +0000 (+0100) Subject: drop some pipe patches from all queues on request of Linus X-Git-Tag: v5.4.291~71 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2245810df08763a2e5392d534ede87dc40959d39;p=thirdparty%2Fkernel%2Fstable-queue.git drop some pipe patches from all queues on request of Linus Signed-off-by: Greg Kroah-Hartman --- diff --git a/queue-5.10/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch b/queue-5.10/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch deleted file mode 100644 index 6b961f3708..0000000000 --- a/queue-5.10/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 1e3d5c9dfd02647e6dec86789c1c2e23d459a8a0 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 5 Mar 2025 07:08:09 -1000 -Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes - -From: Linus Torvalds - -[ Upstream commit c27c66afc449b80f3b4b84d123358c0248f2cf63 ] - -The pipe_occupancy() logic implicitly relied on the natural unsigned -modulo arithmetic in C, but that doesn't work for the new 'pipe_index_t' -case, since any arithmetic will be done in 'int' (and here we had also -made it 'unsigned int' due to the function call boundary). - -So make the modulo arithmetic explicit by casting the result to the -proper type. - -Cc: Oleg Nesterov -Cc: Mateusz Guzik -Cc: Manfred Spraul -Cc: Christian Brauner -Cc: Swapnil Sapkal -Cc: Alexey Gladkov -Cc: K Prateek Nayak -Link: https://lore.kernel.org/all/CAHk-=wjyHsGLx=rxg6PKYBNkPYAejgo7=CbyL3=HGLZLsAaJFQ@mail.gmail.com/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex") -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - include/linux/pipe_fs_i.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 646daf99210c0..ab5a9ffc7f641 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -192,7 +192,7 @@ static inline bool pipe_empty(unsigned int head, unsigned int tail) - */ - static inline unsigned int pipe_occupancy(unsigned int head, unsigned int tail) - { -- return head - tail; -+ return (pipe_index_t)(head - tail); - } - - /** --- -2.39.5 - diff --git a/queue-5.10/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch b/queue-5.10/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch deleted file mode 100644 index 7fc9c04ef2..0000000000 --- a/queue-5.10/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 503fc027723ba35ccd56120915e6f88207c3a476 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 4 Mar 2025 13:51:38 +0000 -Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex - -From: Linus Torvalds - -[ Upstream commit 3d252160b818045f3a152b13756f6f37ca34639d ] - -pipe_readable(), pipe_writable(), and pipe_poll() can read "pipe->head" -and "pipe->tail" outside of "pipe->mutex" critical section. When the -head and the tail are read individually in that order, there is a window -for interruption between the two reads in which both the head and the -tail can be updated by concurrent readers and writers. - -One of the problematic scenarios observed with hackbench running -multiple groups on a large server on a particular pipe inode is as -follows: - - pipe->head = 36 - pipe->tail = 36 - - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wakes up: pipe not full* - hackbench-118762 [057] ..... 1029.550548: pipe_write: head: 36 -> 37 [tail: 36] - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next reader 118740* - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next writer 118768* - - hackbench-118768 [206] ..... 1029.55055X: pipe_write: *writer wakes up* - hackbench-118768 [206] ..... 1029.55055X: pipe_write: head = READ_ONCE(pipe->head) [37] - ... CPU 206 interrupted (exact wakeup was not traced but 118768 did read head at 37 in traces) - - hackbench-118740 [057] ..... 1029.550558: pipe_read: *reader wakes up: pipe is not empty* - hackbench-118740 [057] ..... 1029.550558: pipe_read: tail: 36 -> 37 [head = 37] - hackbench-118740 [057] ..... 1029.550559: pipe_read: *pipe is empty; wakeup writer 118768* - hackbench-118740 [057] ..... 1029.550559: pipe_read: *sleeps* - - hackbench-118766 [185] ..... 1029.550592: pipe_write: *New writer comes in* - hackbench-118766 [185] ..... 1029.550592: pipe_write: head: 37 -> 38 [tail: 37] - hackbench-118766 [185] ..... 1029.550592: pipe_write: *wakes up reader 118766* - - hackbench-118740 [185] ..... 1029.550598: pipe_read: *reader wakes up; pipe not empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: tail: 37 -> 38 [head: 38] - hackbench-118740 [185] ..... 1029.550599: pipe_read: *pipe is empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: *reader sleeps; wakeup writer 118768* - - ... CPU 206 switches back to writer - hackbench-118768 [206] ..... 1029.550601: pipe_write: tail = READ_ONCE(pipe->tail) [38] - hackbench-118768 [206] ..... 1029.550601: pipe_write: pipe_full()? (u32)(37 - 38) >= 16? Yes - hackbench-118768 [206] ..... 1029.550601: pipe_write: *writer goes back to sleep* - - [ Tasks 118740 and 118768 can then indefinitely wait on each other. ] - -The unsigned arithmetic in pipe_occupancy() wraps around when -"pipe->tail > pipe->head" leading to pipe_full() returning true despite -the pipe being empty. - -The case of genuine wraparound of "pipe->head" is handled since pipe -buffer has data allowing readers to make progress until the pipe->tail -wraps too after which the reader will wakeup a sleeping writer, however, -mistaking the pipe to be full when it is in fact empty can lead to -readers and writers waiting on each other indefinitely. - -This issue became more problematic and surfaced as a hang in hackbench -after the optimization in commit aaec5a95d596 ("pipe_read: don't wake up -the writer if the pipe is still full") significantly reduced the number -of spurious wakeups of writers that had previously helped mask the -issue. - -To avoid missing any updates between the reads of "pipe->head" and -"pipe->write", unionize the two with a single unsigned long -"pipe->head_tail" member that can be loaded atomically. - -Using "pipe->head_tail" to read the head and the tail ensures the -lockless checks do not miss any updates to the head or the tail and -since those two are only updated under "pipe->mutex", it ensures that -the head is always ahead of, or equal to the tail resulting in correct -calculations. - - [ prateek: commit log, testing on x86 platforms. ] - -Reported-and-debugged-by: Swapnil Sapkal -Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/ -Reported-by: Alexey Gladkov -Closes: https://lore.kernel.org/all/Z8Wn0nTvevLRG_4m@example.org/ -Fixes: 8cefc107ca54 ("pipe: Use head and tail pointers for the ring, not cursor and length") -Tested-by: Swapnil Sapkal -Reviewed-by: Oleg Nesterov -Tested-by: Alexey Gladkov -Signed-off-by: K Prateek Nayak -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/pipe.c | 19 ++++++++----------- - include/linux/pipe_fs_i.h | 39 +++++++++++++++++++++++++++++++++++++-- - 2 files changed, 45 insertions(+), 13 deletions(-) - -diff --git a/fs/pipe.c b/fs/pipe.c -index 588fe37d8d955..57dd35fe48113 100644 ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -219,11 +219,10 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_readable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int writers = READ_ONCE(pipe->writers); - -- return !pipe_empty(head, tail) || !writers; -+ return !pipe_empty(idx.head, idx.tail) || !writers; - } - - static ssize_t -@@ -403,11 +402,10 @@ static inline int is_packetized(struct file *file) - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_writable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int max_usage = READ_ONCE(pipe->max_usage); - -- return !pipe_full(head, tail, max_usage) || -+ return !pipe_full(idx.head, idx.tail, max_usage) || - !READ_ONCE(pipe->readers); - } - -@@ -647,7 +645,7 @@ pipe_poll(struct file *filp, poll_table *wait) - { - __poll_t mask; - struct pipe_inode_info *pipe = filp->private_data; -- unsigned int head, tail; -+ union pipe_index idx; - - /* Epoll has some historical nasty semantics, this enables them */ - WRITE_ONCE(pipe->poll_usage, true); -@@ -668,19 +666,18 @@ pipe_poll(struct file *filp, poll_table *wait) - * if something changes and you got it wrong, the poll - * table entry will wake you up and fix it. - */ -- head = READ_ONCE(pipe->head); -- tail = READ_ONCE(pipe->tail); -+ idx.head_tail = READ_ONCE(pipe->head_tail); - - mask = 0; - if (filp->f_mode & FMODE_READ) { -- if (!pipe_empty(head, tail)) -+ if (!pipe_empty(idx.head, idx.tail)) - mask |= EPOLLIN | EPOLLRDNORM; - if (!pipe->writers && filp->f_version != pipe->w_counter) - mask |= EPOLLHUP; - } - - if (filp->f_mode & FMODE_WRITE) { -- if (!pipe_full(head, tail, pipe->max_usage)) -+ if (!pipe_full(idx.head, idx.tail, pipe->max_usage)) - mask |= EPOLLOUT | EPOLLWRNORM; - /* - * Most Unices do not set EPOLLERR for FIFOs but on Linux they -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 7b72d93c26530..646daf99210c0 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -31,6 +31,33 @@ struct pipe_buffer { - unsigned long private; - }; - -+/* -+ * Really only alpha needs 32-bit fields, but -+ * might as well do it for 64-bit architectures -+ * since that's what we've historically done, -+ * and it makes 'head_tail' always be a simple -+ * 'unsigned long'. -+ */ -+#ifdef CONFIG_64BIT -+typedef unsigned int pipe_index_t; -+#else -+typedef unsigned short pipe_index_t; -+#endif -+ -+/* -+ * We have to declare this outside 'struct pipe_inode_info', -+ * but then we can't use 'union pipe_index' for an anonymous -+ * union, so we end up having to duplicate this declaration -+ * below. Annoying. -+ */ -+union pipe_index { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+}; -+ - /** - * struct pipe_inode_info - a linux kernel pipe - * @mutex: mutex protecting the whole thing -@@ -58,8 +85,16 @@ struct pipe_buffer { - struct pipe_inode_info { - struct mutex mutex; - wait_queue_head_t rd_wait, wr_wait; -- unsigned int head; -- unsigned int tail; -+ -+ /* This has to match the 'union pipe_index' above */ -+ union { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+ }; -+ - unsigned int max_usage; - unsigned int ring_size; - #ifdef CONFIG_WATCH_QUEUE --- -2.39.5 - diff --git a/queue-5.10/series b/queue-5.10/series index a064ec6374..ffd53963b1 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -435,11 +435,9 @@ llc-do-not-use-skb_get-before-dev_queue_xmit.patch hwmon-fix-a-null-vs-is_err_or_null-check-in-xgene_hw.patch drm-sched-fix-preprocessor-guard.patch be2net-fix-sleeping-while-atomic-bugs-in-be_ndo_brid.patch -fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch ppp-fix-kmsan-uninit-value-warning-with-bpf.patch vlan-enforce-underlying-device-type.patch net-timestamp-support-tcp-gso-case-for-a-few-missing.patch -fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch net-ipv6-fix-dst-ref-loop-in-ila-lwtunnel.patch net-ipv6-fix-missing-dst-ref-drop-in-ila-lwtunnel.patch gpio-rcar-fix-missing-of_node_put-call.patch @@ -456,3 +454,4 @@ usb-gadget-fix-setting-self-powered-state-on-suspend.patch usb-gadget-check-bmattributes-only-if-configuration-is-valid.patch kbuild-userprogs-use-correct-lld-when-linking-through-clang.patch xhci-pci-fix-indentation-in-the-pci-device-id-definitions.patch +squashfs-check-the-inode-number-is-not-the-invalid-value-of-zero.patch diff --git a/queue-5.15/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch b/queue-5.15/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch deleted file mode 100644 index acfec84d28..0000000000 --- a/queue-5.15/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch +++ /dev/null @@ -1,48 +0,0 @@ -From e9234c3542228648bf1fdf47a6bff495df16f2a5 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 5 Mar 2025 07:08:09 -1000 -Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes - -From: Linus Torvalds - -[ Upstream commit c27c66afc449b80f3b4b84d123358c0248f2cf63 ] - -The pipe_occupancy() logic implicitly relied on the natural unsigned -modulo arithmetic in C, but that doesn't work for the new 'pipe_index_t' -case, since any arithmetic will be done in 'int' (and here we had also -made it 'unsigned int' due to the function call boundary). - -So make the modulo arithmetic explicit by casting the result to the -proper type. - -Cc: Oleg Nesterov -Cc: Mateusz Guzik -Cc: Manfred Spraul -Cc: Christian Brauner -Cc: Swapnil Sapkal -Cc: Alexey Gladkov -Cc: K Prateek Nayak -Link: https://lore.kernel.org/all/CAHk-=wjyHsGLx=rxg6PKYBNkPYAejgo7=CbyL3=HGLZLsAaJFQ@mail.gmail.com/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex") -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - include/linux/pipe_fs_i.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 03546e26899a3..4cad5521a55f3 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -192,7 +192,7 @@ static inline bool pipe_empty(unsigned int head, unsigned int tail) - */ - static inline unsigned int pipe_occupancy(unsigned int head, unsigned int tail) - { -- return head - tail; -+ return (pipe_index_t)(head - tail); - } - - /** --- -2.39.5 - diff --git a/queue-5.15/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch b/queue-5.15/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch deleted file mode 100644 index 36c4374918..0000000000 --- a/queue-5.15/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 4185dc99e91acd9f005ab5a0e68490f4b0eee0da Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 4 Mar 2025 13:51:38 +0000 -Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex - -From: Linus Torvalds - -[ Upstream commit 3d252160b818045f3a152b13756f6f37ca34639d ] - -pipe_readable(), pipe_writable(), and pipe_poll() can read "pipe->head" -and "pipe->tail" outside of "pipe->mutex" critical section. When the -head and the tail are read individually in that order, there is a window -for interruption between the two reads in which both the head and the -tail can be updated by concurrent readers and writers. - -One of the problematic scenarios observed with hackbench running -multiple groups on a large server on a particular pipe inode is as -follows: - - pipe->head = 36 - pipe->tail = 36 - - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wakes up: pipe not full* - hackbench-118762 [057] ..... 1029.550548: pipe_write: head: 36 -> 37 [tail: 36] - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next reader 118740* - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next writer 118768* - - hackbench-118768 [206] ..... 1029.55055X: pipe_write: *writer wakes up* - hackbench-118768 [206] ..... 1029.55055X: pipe_write: head = READ_ONCE(pipe->head) [37] - ... CPU 206 interrupted (exact wakeup was not traced but 118768 did read head at 37 in traces) - - hackbench-118740 [057] ..... 1029.550558: pipe_read: *reader wakes up: pipe is not empty* - hackbench-118740 [057] ..... 1029.550558: pipe_read: tail: 36 -> 37 [head = 37] - hackbench-118740 [057] ..... 1029.550559: pipe_read: *pipe is empty; wakeup writer 118768* - hackbench-118740 [057] ..... 1029.550559: pipe_read: *sleeps* - - hackbench-118766 [185] ..... 1029.550592: pipe_write: *New writer comes in* - hackbench-118766 [185] ..... 1029.550592: pipe_write: head: 37 -> 38 [tail: 37] - hackbench-118766 [185] ..... 1029.550592: pipe_write: *wakes up reader 118766* - - hackbench-118740 [185] ..... 1029.550598: pipe_read: *reader wakes up; pipe not empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: tail: 37 -> 38 [head: 38] - hackbench-118740 [185] ..... 1029.550599: pipe_read: *pipe is empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: *reader sleeps; wakeup writer 118768* - - ... CPU 206 switches back to writer - hackbench-118768 [206] ..... 1029.550601: pipe_write: tail = READ_ONCE(pipe->tail) [38] - hackbench-118768 [206] ..... 1029.550601: pipe_write: pipe_full()? (u32)(37 - 38) >= 16? Yes - hackbench-118768 [206] ..... 1029.550601: pipe_write: *writer goes back to sleep* - - [ Tasks 118740 and 118768 can then indefinitely wait on each other. ] - -The unsigned arithmetic in pipe_occupancy() wraps around when -"pipe->tail > pipe->head" leading to pipe_full() returning true despite -the pipe being empty. - -The case of genuine wraparound of "pipe->head" is handled since pipe -buffer has data allowing readers to make progress until the pipe->tail -wraps too after which the reader will wakeup a sleeping writer, however, -mistaking the pipe to be full when it is in fact empty can lead to -readers and writers waiting on each other indefinitely. - -This issue became more problematic and surfaced as a hang in hackbench -after the optimization in commit aaec5a95d596 ("pipe_read: don't wake up -the writer if the pipe is still full") significantly reduced the number -of spurious wakeups of writers that had previously helped mask the -issue. - -To avoid missing any updates between the reads of "pipe->head" and -"pipe->write", unionize the two with a single unsigned long -"pipe->head_tail" member that can be loaded atomically. - -Using "pipe->head_tail" to read the head and the tail ensures the -lockless checks do not miss any updates to the head or the tail and -since those two are only updated under "pipe->mutex", it ensures that -the head is always ahead of, or equal to the tail resulting in correct -calculations. - - [ prateek: commit log, testing on x86 platforms. ] - -Reported-and-debugged-by: Swapnil Sapkal -Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/ -Reported-by: Alexey Gladkov -Closes: https://lore.kernel.org/all/Z8Wn0nTvevLRG_4m@example.org/ -Fixes: 8cefc107ca54 ("pipe: Use head and tail pointers for the ring, not cursor and length") -Tested-by: Swapnil Sapkal -Reviewed-by: Oleg Nesterov -Tested-by: Alexey Gladkov -Signed-off-by: K Prateek Nayak -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/pipe.c | 19 ++++++++----------- - include/linux/pipe_fs_i.h | 39 +++++++++++++++++++++++++++++++++++++-- - 2 files changed, 45 insertions(+), 13 deletions(-) - -diff --git a/fs/pipe.c b/fs/pipe.c -index 0a8095070b70e..ef1de18ddcb53 100644 ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -219,11 +219,10 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_readable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int writers = READ_ONCE(pipe->writers); - -- return !pipe_empty(head, tail) || !writers; -+ return !pipe_empty(idx.head, idx.tail) || !writers; - } - - static ssize_t -@@ -403,11 +402,10 @@ static inline int is_packetized(struct file *file) - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_writable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int max_usage = READ_ONCE(pipe->max_usage); - -- return !pipe_full(head, tail, max_usage) || -+ return !pipe_full(idx.head, idx.tail, max_usage) || - !READ_ONCE(pipe->readers); - } - -@@ -654,7 +652,7 @@ pipe_poll(struct file *filp, poll_table *wait) - { - __poll_t mask; - struct pipe_inode_info *pipe = filp->private_data; -- unsigned int head, tail; -+ union pipe_index idx; - - /* Epoll has some historical nasty semantics, this enables them */ - WRITE_ONCE(pipe->poll_usage, true); -@@ -675,19 +673,18 @@ pipe_poll(struct file *filp, poll_table *wait) - * if something changes and you got it wrong, the poll - * table entry will wake you up and fix it. - */ -- head = READ_ONCE(pipe->head); -- tail = READ_ONCE(pipe->tail); -+ idx.head_tail = READ_ONCE(pipe->head_tail); - - mask = 0; - if (filp->f_mode & FMODE_READ) { -- if (!pipe_empty(head, tail)) -+ if (!pipe_empty(idx.head, idx.tail)) - mask |= EPOLLIN | EPOLLRDNORM; - if (!pipe->writers && filp->f_version != pipe->w_counter) - mask |= EPOLLHUP; - } - - if (filp->f_mode & FMODE_WRITE) { -- if (!pipe_full(head, tail, pipe->max_usage)) -+ if (!pipe_full(idx.head, idx.tail, pipe->max_usage)) - mask |= EPOLLOUT | EPOLLWRNORM; - /* - * Most Unices do not set EPOLLERR for FIFOs but on Linux they -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 0613daf8997ac..03546e26899a3 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -31,6 +31,33 @@ struct pipe_buffer { - unsigned long private; - }; - -+/* -+ * Really only alpha needs 32-bit fields, but -+ * might as well do it for 64-bit architectures -+ * since that's what we've historically done, -+ * and it makes 'head_tail' always be a simple -+ * 'unsigned long'. -+ */ -+#ifdef CONFIG_64BIT -+typedef unsigned int pipe_index_t; -+#else -+typedef unsigned short pipe_index_t; -+#endif -+ -+/* -+ * We have to declare this outside 'struct pipe_inode_info', -+ * but then we can't use 'union pipe_index' for an anonymous -+ * union, so we end up having to duplicate this declaration -+ * below. Annoying. -+ */ -+union pipe_index { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+}; -+ - /** - * struct pipe_inode_info - a linux kernel pipe - * @mutex: mutex protecting the whole thing -@@ -58,8 +85,16 @@ struct pipe_buffer { - struct pipe_inode_info { - struct mutex mutex; - wait_queue_head_t rd_wait, wr_wait; -- unsigned int head; -- unsigned int tail; -+ -+ /* This has to match the 'union pipe_index' above */ -+ union { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+ }; -+ - unsigned int max_usage; - unsigned int ring_size; - #ifdef CONFIG_WATCH_QUEUE --- -2.39.5 - diff --git a/queue-5.15/series b/queue-5.15/series index 229f5bc4c0..2cb44500b6 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -573,7 +573,6 @@ hwmon-fix-a-null-vs-is_err_or_null-check-in-xgene_hw.patch drm-sched-fix-preprocessor-guard.patch be2net-fix-sleeping-while-atomic-bugs-in-be_ndo_brid.patch net-hns3-make-sure-ptp-clock-is-unregister-and-freed.patch -fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch ppp-fix-kmsan-uninit-value-warning-with-bpf.patch vlan-enforce-underlying-device-type.patch x86-sgx-support-loading-enclave-page-without-vma-per.patch @@ -584,7 +583,6 @@ x86-sgx-fix-size-overflows-in-sgx_encl_create.patch exfat-fix-soft-lockup-in-exfat_clear_bitmap.patch net-timestamp-support-tcp-gso-case-for-a-few-missing.patch sched-fair-fix-potential-memory-corruption-in-child_.patch -fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch net-ipv6-fix-dst-ref-loop-in-ila-lwtunnel.patch net-ipv6-fix-missing-dst-ref-drop-in-ila-lwtunnel.patch gpio-rcar-fix-missing-of_node_put-call.patch @@ -605,3 +603,4 @@ usb-gadget-check-bmattributes-only-if-configuration-is-valid.patch kbuild-userprogs-use-correct-lld-when-linking-through-clang.patch xhci-pci-fix-indentation-in-the-pci-device-id-definitions.patch usb-xhci-enable-the-trb-overfetch-quirk-on-via-vl805.patch +squashfs-check-the-inode-number-is-not-the-invalid-value-of-zero.patch diff --git a/queue-5.4/series b/queue-5.4/series index 3982c83171..645f6b0fc9 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -319,3 +319,4 @@ usb-gadget-set-self-powered-based-on-maxpower-and-bmattributes.patch usb-gadget-fix-setting-self-powered-state-on-suspend.patch usb-gadget-check-bmattributes-only-if-configuration-is-valid.patch xhci-pci-fix-indentation-in-the-pci-device-id-definitions.patch +squashfs-check-the-inode-number-is-not-the-invalid-value-of-zero.patch diff --git a/queue-6.1/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch b/queue-6.1/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch deleted file mode 100644 index 8316d13542..0000000000 --- a/queue-6.1/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 6edd967c49cb625da20260c0598c07268495e6e4 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 6 Mar 2025 07:33:58 -1000 -Subject: fs/pipe: do not open-code pipe head/tail logic in FIONREAD - -From: Linus Torvalds - -[ Upstream commit d810d4c27bf34c719243bab9feb0d843edc09fd7 ] - -Rasmus points out that we do indeed have other cases of breakage from -the type changes that were introduced on 32-bit targets in order to read -the pipe head and tail values atomically (commit 3d252160b818: "fs/pipe: -Read pipe->{head,tail} atomically outside pipe->mutex"). - -Fix it up by using the proper helper functions that now deal with the -pipe buffer index types properly. This makes the code simpler and more -obvious. - -The compiler does the CSE and loop hoisting of the pipe ring size -masking that we used to do manually, so open-coding this was never a -good idea. - -Reported-by: Rasmus Villemoes -Link: https://lore.kernel.org/all/87cyeu5zgk.fsf@prevas.dk/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg Nesterov -Cc: Mateusz Guzik -Cc: K Prateek Nayak -Cc: Swapnil Sapkal -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/pipe.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/fs/pipe.c b/fs/pipe.c -index fd0c4fc4bd70f..658144268f552 100644 ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -610,7 +610,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) - static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - { - struct pipe_inode_info *pipe = filp->private_data; -- unsigned int count, head, tail, mask; -+ unsigned int count, head, tail; - - switch (cmd) { - case FIONREAD: -@@ -618,10 +618,9 @@ static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - count = 0; - head = pipe->head; - tail = pipe->tail; -- mask = pipe->ring_size - 1; - -- while (tail != head) { -- count += pipe->bufs[tail & mask].len; -+ while (!pipe_empty(head, tail)) { -+ count += pipe_buf(pipe, tail)->len; - tail++; - } - __pipe_unlock(pipe); --- -2.39.5 - diff --git a/queue-6.1/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch b/queue-6.1/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch deleted file mode 100644 index 72ce532194..0000000000 --- a/queue-6.1/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch +++ /dev/null @@ -1,78 +0,0 @@ -From e8aa712c6c159d7d8973c71684b35381c5753dca Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 6 Mar 2025 07:53:25 -1000 -Subject: fs/pipe: fix pipe buffer index use in FUSE - -From: Linus Torvalds - -[ Upstream commit ebb0f38bb47f74b29e267babdbcd2c47d5292aa8 ] - -This was another case that Rasmus pointed out where the direct access to -the pipe head and tail pointers broke on 32-bit configurations due to -the type changes. - -As with the pipe FIONREAD case, fix it by using the appropriate helper -functions that deal with the right pipe index sizing. - -Reported-by: Rasmus Villemoes -Link: https://lore.kernel.org/all/878qpi5wz4.fsf@prevas.dk/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg > -Cc: Mateusz Guzik -Cc: K Prateek Nayak -Cc: Swapnil Sapkal -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/fuse/dev.c | 13 ++++++------- - 1 file changed, 6 insertions(+), 7 deletions(-) - -diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c -index 7e0d4f08a0cf5..cb3fa178ff8c9 100644 ---- a/fs/fuse/dev.c -+++ b/fs/fuse/dev.c -@@ -1965,7 +1965,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - struct file *out, loff_t *ppos, - size_t len, unsigned int flags) - { -- unsigned int head, tail, mask, count; -+ unsigned int head, tail, count; - unsigned nbuf; - unsigned idx; - struct pipe_buffer *bufs; -@@ -1982,8 +1982,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - - head = pipe->head; - tail = pipe->tail; -- mask = pipe->ring_size - 1; -- count = head - tail; -+ count = pipe_occupancy(head, tail); - - bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL); - if (!bufs) { -@@ -1993,8 +1992,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - - nbuf = 0; - rem = 0; -- for (idx = tail; idx != head && rem < len; idx++) -- rem += pipe->bufs[idx & mask].len; -+ for (idx = tail; !pipe_empty(head, idx) && rem < len; idx++) -+ rem += pipe_buf(pipe, idx)->len; - - ret = -EINVAL; - if (rem < len) -@@ -2005,10 +2004,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - struct pipe_buffer *ibuf; - struct pipe_buffer *obuf; - -- if (WARN_ON(nbuf >= count || tail == head)) -+ if (WARN_ON(nbuf >= count || pipe_empty(head, tail))) - goto out_free; - -- ibuf = &pipe->bufs[tail & mask]; -+ ibuf = pipe_buf(pipe, tail); - obuf = &bufs[nbuf]; - - if (rem >= ibuf->len) { --- -2.39.5 - diff --git a/queue-6.1/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch b/queue-6.1/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch deleted file mode 100644 index 1f3ffc0d19..0000000000 --- a/queue-6.1/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 2b95e27376134413c4b8b93820c41239d328dc43 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 5 Mar 2025 07:08:09 -1000 -Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes - -From: Linus Torvalds - -[ Upstream commit c27c66afc449b80f3b4b84d123358c0248f2cf63 ] - -The pipe_occupancy() logic implicitly relied on the natural unsigned -modulo arithmetic in C, but that doesn't work for the new 'pipe_index_t' -case, since any arithmetic will be done in 'int' (and here we had also -made it 'unsigned int' due to the function call boundary). - -So make the modulo arithmetic explicit by casting the result to the -proper type. - -Cc: Oleg Nesterov -Cc: Mateusz Guzik -Cc: Manfred Spraul -Cc: Christian Brauner -Cc: Swapnil Sapkal -Cc: Alexey Gladkov -Cc: K Prateek Nayak -Link: https://lore.kernel.org/all/CAHk-=wjyHsGLx=rxg6PKYBNkPYAejgo7=CbyL3=HGLZLsAaJFQ@mail.gmail.com/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex") -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - include/linux/pipe_fs_i.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index dfd056dfb994c..7f4ee79286d64 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -192,7 +192,7 @@ static inline bool pipe_empty(unsigned int head, unsigned int tail) - */ - static inline unsigned int pipe_occupancy(unsigned int head, unsigned int tail) - { -- return head - tail; -+ return (pipe_index_t)(head - tail); - } - - /** --- -2.39.5 - diff --git a/queue-6.1/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch b/queue-6.1/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch deleted file mode 100644 index 11dba016c2..0000000000 --- a/queue-6.1/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 3c72aff3fa022e1353f317772908d05a5695fdc7 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 4 Mar 2025 13:51:38 +0000 -Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex - -From: Linus Torvalds - -[ Upstream commit 3d252160b818045f3a152b13756f6f37ca34639d ] - -pipe_readable(), pipe_writable(), and pipe_poll() can read "pipe->head" -and "pipe->tail" outside of "pipe->mutex" critical section. When the -head and the tail are read individually in that order, there is a window -for interruption between the two reads in which both the head and the -tail can be updated by concurrent readers and writers. - -One of the problematic scenarios observed with hackbench running -multiple groups on a large server on a particular pipe inode is as -follows: - - pipe->head = 36 - pipe->tail = 36 - - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wakes up: pipe not full* - hackbench-118762 [057] ..... 1029.550548: pipe_write: head: 36 -> 37 [tail: 36] - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next reader 118740* - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next writer 118768* - - hackbench-118768 [206] ..... 1029.55055X: pipe_write: *writer wakes up* - hackbench-118768 [206] ..... 1029.55055X: pipe_write: head = READ_ONCE(pipe->head) [37] - ... CPU 206 interrupted (exact wakeup was not traced but 118768 did read head at 37 in traces) - - hackbench-118740 [057] ..... 1029.550558: pipe_read: *reader wakes up: pipe is not empty* - hackbench-118740 [057] ..... 1029.550558: pipe_read: tail: 36 -> 37 [head = 37] - hackbench-118740 [057] ..... 1029.550559: pipe_read: *pipe is empty; wakeup writer 118768* - hackbench-118740 [057] ..... 1029.550559: pipe_read: *sleeps* - - hackbench-118766 [185] ..... 1029.550592: pipe_write: *New writer comes in* - hackbench-118766 [185] ..... 1029.550592: pipe_write: head: 37 -> 38 [tail: 37] - hackbench-118766 [185] ..... 1029.550592: pipe_write: *wakes up reader 118766* - - hackbench-118740 [185] ..... 1029.550598: pipe_read: *reader wakes up; pipe not empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: tail: 37 -> 38 [head: 38] - hackbench-118740 [185] ..... 1029.550599: pipe_read: *pipe is empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: *reader sleeps; wakeup writer 118768* - - ... CPU 206 switches back to writer - hackbench-118768 [206] ..... 1029.550601: pipe_write: tail = READ_ONCE(pipe->tail) [38] - hackbench-118768 [206] ..... 1029.550601: pipe_write: pipe_full()? (u32)(37 - 38) >= 16? Yes - hackbench-118768 [206] ..... 1029.550601: pipe_write: *writer goes back to sleep* - - [ Tasks 118740 and 118768 can then indefinitely wait on each other. ] - -The unsigned arithmetic in pipe_occupancy() wraps around when -"pipe->tail > pipe->head" leading to pipe_full() returning true despite -the pipe being empty. - -The case of genuine wraparound of "pipe->head" is handled since pipe -buffer has data allowing readers to make progress until the pipe->tail -wraps too after which the reader will wakeup a sleeping writer, however, -mistaking the pipe to be full when it is in fact empty can lead to -readers and writers waiting on each other indefinitely. - -This issue became more problematic and surfaced as a hang in hackbench -after the optimization in commit aaec5a95d596 ("pipe_read: don't wake up -the writer if the pipe is still full") significantly reduced the number -of spurious wakeups of writers that had previously helped mask the -issue. - -To avoid missing any updates between the reads of "pipe->head" and -"pipe->write", unionize the two with a single unsigned long -"pipe->head_tail" member that can be loaded atomically. - -Using "pipe->head_tail" to read the head and the tail ensures the -lockless checks do not miss any updates to the head or the tail and -since those two are only updated under "pipe->mutex", it ensures that -the head is always ahead of, or equal to the tail resulting in correct -calculations. - - [ prateek: commit log, testing on x86 platforms. ] - -Reported-and-debugged-by: Swapnil Sapkal -Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/ -Reported-by: Alexey Gladkov -Closes: https://lore.kernel.org/all/Z8Wn0nTvevLRG_4m@example.org/ -Fixes: 8cefc107ca54 ("pipe: Use head and tail pointers for the ring, not cursor and length") -Tested-by: Swapnil Sapkal -Reviewed-by: Oleg Nesterov -Tested-by: Alexey Gladkov -Signed-off-by: K Prateek Nayak -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/pipe.c | 19 ++++++++----------- - include/linux/pipe_fs_i.h | 39 +++++++++++++++++++++++++++++++++++++-- - 2 files changed, 45 insertions(+), 13 deletions(-) - -diff --git a/fs/pipe.c b/fs/pipe.c -index aa8e6ffe1cb58..fd0c4fc4bd70f 100644 ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -220,11 +220,10 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_readable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int writers = READ_ONCE(pipe->writers); - -- return !pipe_empty(head, tail) || !writers; -+ return !pipe_empty(idx.head, idx.tail) || !writers; - } - - static ssize_t -@@ -404,11 +403,10 @@ static inline int is_packetized(struct file *file) - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_writable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int max_usage = READ_ONCE(pipe->max_usage); - -- return !pipe_full(head, tail, max_usage) || -+ return !pipe_full(idx.head, idx.tail, max_usage) || - !READ_ONCE(pipe->readers); - } - -@@ -655,7 +653,7 @@ pipe_poll(struct file *filp, poll_table *wait) - { - __poll_t mask; - struct pipe_inode_info *pipe = filp->private_data; -- unsigned int head, tail; -+ union pipe_index idx; - - /* Epoll has some historical nasty semantics, this enables them */ - WRITE_ONCE(pipe->poll_usage, true); -@@ -676,19 +674,18 @@ pipe_poll(struct file *filp, poll_table *wait) - * if something changes and you got it wrong, the poll - * table entry will wake you up and fix it. - */ -- head = READ_ONCE(pipe->head); -- tail = READ_ONCE(pipe->tail); -+ idx.head_tail = READ_ONCE(pipe->head_tail); - - mask = 0; - if (filp->f_mode & FMODE_READ) { -- if (!pipe_empty(head, tail)) -+ if (!pipe_empty(idx.head, idx.tail)) - mask |= EPOLLIN | EPOLLRDNORM; - if (!pipe->writers && filp->f_version != pipe->w_counter) - mask |= EPOLLHUP; - } - - if (filp->f_mode & FMODE_WRITE) { -- if (!pipe_full(head, tail, pipe->max_usage)) -+ if (!pipe_full(idx.head, idx.tail, pipe->max_usage)) - mask |= EPOLLOUT | EPOLLWRNORM; - /* - * Most Unices do not set EPOLLERR for FIFOs but on Linux they -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 1f1e7ae953205..dfd056dfb994c 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -31,6 +31,33 @@ struct pipe_buffer { - unsigned long private; - }; - -+/* -+ * Really only alpha needs 32-bit fields, but -+ * might as well do it for 64-bit architectures -+ * since that's what we've historically done, -+ * and it makes 'head_tail' always be a simple -+ * 'unsigned long'. -+ */ -+#ifdef CONFIG_64BIT -+typedef unsigned int pipe_index_t; -+#else -+typedef unsigned short pipe_index_t; -+#endif -+ -+/* -+ * We have to declare this outside 'struct pipe_inode_info', -+ * but then we can't use 'union pipe_index' for an anonymous -+ * union, so we end up having to duplicate this declaration -+ * below. Annoying. -+ */ -+union pipe_index { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+}; -+ - /** - * struct pipe_inode_info - a linux kernel pipe - * @mutex: mutex protecting the whole thing -@@ -58,8 +85,16 @@ struct pipe_buffer { - struct pipe_inode_info { - struct mutex mutex; - wait_queue_head_t rd_wait, wr_wait; -- unsigned int head; -- unsigned int tail; -+ -+ /* This has to match the 'union pipe_index' above */ -+ union { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+ }; -+ - unsigned int max_usage; - unsigned int ring_size; - #ifdef CONFIG_WATCH_QUEUE --- -2.39.5 - diff --git a/queue-6.1/mm-pass-info-not-iter-into-filemap_get_pages.patch b/queue-6.1/mm-pass-info-not-iter-into-filemap_get_pages.patch deleted file mode 100644 index 563f3adb5a..0000000000 --- a/queue-6.1/mm-pass-info-not-iter-into-filemap_get_pages.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 9915cc269582726b40edced5c3024243c6118ced Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 8 Feb 2023 18:18:17 +0000 -Subject: mm: Pass info, not iter, into filemap_get_pages() - -From: David Howells - -[ Upstream commit dd5b9d003ebcb469de05f967af7164e6b9450ca2 ] - -filemap_get_pages() and a number of functions that it calls take an -iterator to provide two things: the number of bytes to be got from the file -specified and whether partially uptodate pages are allowed. Change these -functions so that this information is passed in directly. This allows it -to be called without having an iterator to hand. - -Signed-off-by: David Howells -Reviewed-by: Christoph Hellwig -Reviewed-by: Jens Axboe -cc: Christoph Hellwig -cc: Matthew Wilcox -cc: Al Viro -cc: David Hildenbrand -cc: John Hubbard -cc: linux-mm@kvack.org -cc: linux-block@vger.kernel.org -cc: linux-fsdevel@vger.kernel.org -Signed-off-by: Steve French -Stable-dep-of: d810d4c27bf3 ("fs/pipe: do not open-code pipe head/tail logic in FIONREAD") -Signed-off-by: Sasha Levin ---- - mm/filemap.c | 27 ++++++++++++++------------- - 1 file changed, 14 insertions(+), 13 deletions(-) - -diff --git a/mm/filemap.c b/mm/filemap.c -index 78bf403473fb6..f57bc92e9b46f 100644 ---- a/mm/filemap.c -+++ b/mm/filemap.c -@@ -2503,21 +2503,19 @@ static int filemap_read_folio(struct file *file, filler_t filler, - } - - static bool filemap_range_uptodate(struct address_space *mapping, -- loff_t pos, struct iov_iter *iter, struct folio *folio) -+ loff_t pos, size_t count, struct folio *folio, -+ bool need_uptodate) - { -- int count; -- - if (folio_test_uptodate(folio)) - return true; - /* pipes can't handle partially uptodate pages */ -- if (iov_iter_is_pipe(iter)) -+ if (need_uptodate) - return false; - if (!mapping->a_ops->is_partially_uptodate) - return false; - if (mapping->host->i_blkbits >= folio_shift(folio)) - return false; - -- count = iter->count; - if (folio_pos(folio) > pos) { - count -= folio_pos(folio) - pos; - pos = 0; -@@ -2529,8 +2527,8 @@ static bool filemap_range_uptodate(struct address_space *mapping, - } - - static int filemap_update_page(struct kiocb *iocb, -- struct address_space *mapping, struct iov_iter *iter, -- struct folio *folio) -+ struct address_space *mapping, size_t count, -+ struct folio *folio, bool need_uptodate) - { - int error; - -@@ -2564,7 +2562,8 @@ static int filemap_update_page(struct kiocb *iocb, - goto unlock; - - error = 0; -- if (filemap_range_uptodate(mapping, iocb->ki_pos, iter, folio)) -+ if (filemap_range_uptodate(mapping, iocb->ki_pos, count, folio, -+ need_uptodate)) - goto unlock; - - error = -EAGAIN; -@@ -2640,8 +2639,8 @@ static int filemap_readahead(struct kiocb *iocb, struct file *file, - return 0; - } - --static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter, -- struct folio_batch *fbatch) -+static int filemap_get_pages(struct kiocb *iocb, size_t count, -+ struct folio_batch *fbatch, bool need_uptodate) - { - struct file *filp = iocb->ki_filp; - struct address_space *mapping = filp->f_mapping; -@@ -2652,7 +2651,7 @@ static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter, - int err = 0; - - /* "last_index" is the index of the page beyond the end of the read */ -- last_index = DIV_ROUND_UP(iocb->ki_pos + iter->count, PAGE_SIZE); -+ last_index = DIV_ROUND_UP(iocb->ki_pos + count, PAGE_SIZE); - retry: - if (fatal_signal_pending(current)) - return -EINTR; -@@ -2685,7 +2684,8 @@ static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter, - if ((iocb->ki_flags & IOCB_WAITQ) && - folio_batch_count(fbatch) > 1) - iocb->ki_flags |= IOCB_NOWAIT; -- err = filemap_update_page(iocb, mapping, iter, folio); -+ err = filemap_update_page(iocb, mapping, count, folio, -+ need_uptodate); - if (err) - goto err; - } -@@ -2755,7 +2755,8 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, - if (unlikely(iocb->ki_pos >= i_size_read(inode))) - break; - -- error = filemap_get_pages(iocb, iter, &fbatch); -+ error = filemap_get_pages(iocb, iter->count, &fbatch, -+ iov_iter_is_pipe(iter)); - if (error < 0) - break; - --- -2.39.5 - diff --git a/queue-6.1/series b/queue-6.1/series index 79177c4915..e96115b91a 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -50,7 +50,6 @@ hwmon-fix-a-null-vs-is_err_or_null-check-in-xgene_hw.patch drm-sched-fix-preprocessor-guard.patch be2net-fix-sleeping-while-atomic-bugs-in-be_ndo_brid.patch net-hns3-make-sure-ptp-clock-is-unregister-and-freed.patch -fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch ppp-fix-kmsan-uninit-value-warning-with-bpf.patch vlan-enforce-underlying-device-type.patch x86-sgx-fix-size-overflows-in-sgx_encl_create.patch @@ -58,14 +57,9 @@ exfat-fix-soft-lockup-in-exfat_clear_bitmap.patch net-timestamp-support-tcp-gso-case-for-a-few-missing.patch ublk-set_params-properly-check-if-parameters-can-be-.patch sched-fair-fix-potential-memory-corruption-in-child_.patch -fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch net-ipv6-fix-dst-ref-loop-in-ila-lwtunnel.patch net-ipv6-fix-missing-dst-ref-drop-in-ila-lwtunnel.patch gpio-rcar-fix-missing-of_node_put-call.patch -mm-pass-info-not-iter-into-filemap_get_pages.patch -splice-add-a-func-to-do-a-splice-from-a-buffered-fil.patch -fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch -fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch revert-drivers-card_reader-rtsx_usb-restore-interrupt-based-detection.patch usb-renesas_usbhs-call-clk_put.patch usb-renesas_usbhs-use-devm_usb_get_phy.patch diff --git a/queue-6.1/splice-add-a-func-to-do-a-splice-from-a-buffered-fil.patch b/queue-6.1/splice-add-a-func-to-do-a-splice-from-a-buffered-fil.patch deleted file mode 100644 index 3cc168b84f..0000000000 --- a/queue-6.1/splice-add-a-func-to-do-a-splice-from-a-buffered-fil.patch +++ /dev/null @@ -1,270 +0,0 @@ -From 3a1796e9eecebb93a9e2b6cb7112a480f36ed913 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 14 Feb 2023 15:01:42 +0000 -Subject: splice: Add a func to do a splice from a buffered file without - ITER_PIPE - -From: David Howells - -[ Upstream commit 07073eb01c5f630344bc1c3e56b0e0d94aedf919 ] - -Provide a function to do splice read from a buffered file, pulling the -folios out of the pagecache directly by calling filemap_get_pages() to do -any required reading and then pasting the returned folios into the pipe. - -A helper function is provided to do the actual folio pasting and will -handle multipage folios by splicing as many of the relevant subpages as -will fit into the pipe. - -The code is loosely based on filemap_read() and might belong in -mm/filemap.c with that as it needs to use filemap_get_pages(). - -Signed-off-by: David Howells -Reviewed-by: Jens Axboe -cc: Christoph Hellwig -cc: Al Viro -cc: David Hildenbrand -cc: John Hubbard -cc: linux-mm@kvack.org -cc: linux-block@vger.kernel.org -cc: linux-fsdevel@vger.kernel.org -Signed-off-by: Steve French -Stable-dep-of: d810d4c27bf3 ("fs/pipe: do not open-code pipe head/tail logic in FIONREAD") -Signed-off-by: Sasha Levin ---- - include/linux/fs.h | 3 + - include/linux/pipe_fs_i.h | 20 ++++++ - lib/iov_iter.c | 6 -- - mm/filemap.c | 129 ++++++++++++++++++++++++++++++++++++++ - mm/internal.h | 6 ++ - 5 files changed, 158 insertions(+), 6 deletions(-) - -diff --git a/include/linux/fs.h b/include/linux/fs.h -index 0d32634c5cf0d..ef117325b2552 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -3289,6 +3289,9 @@ ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb, - struct iov_iter *iter); - - /* fs/splice.c */ -+ssize_t filemap_splice_read(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, -+ size_t len, unsigned int flags); - extern ssize_t generic_file_splice_read(struct file *, loff_t *, - struct pipe_inode_info *, size_t, unsigned int); - extern ssize_t iter_file_splice_write(struct pipe_inode_info *, -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 7f4ee79286d64..bfa381f175907 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -207,6 +207,26 @@ static inline bool pipe_full(unsigned int head, unsigned int tail, - return pipe_occupancy(head, tail) >= limit; - } - -+/** -+ * pipe_buf - Return the pipe buffer for the specified slot in the pipe ring -+ * @pipe: The pipe to access -+ * @slot: The slot of interest -+ */ -+static inline struct pipe_buffer *pipe_buf(const struct pipe_inode_info *pipe, -+ unsigned int slot) -+{ -+ return &pipe->bufs[slot & (pipe->ring_size - 1)]; -+} -+ -+/** -+ * pipe_head_buf - Return the pipe buffer at the head of the pipe ring -+ * @pipe: The pipe to access -+ */ -+static inline struct pipe_buffer *pipe_head_buf(const struct pipe_inode_info *pipe) -+{ -+ return pipe_buf(pipe, pipe->head); -+} -+ - /** - * pipe_buf_get - get a reference to a pipe_buffer - * @pipe: the pipe that the buffer belongs to -diff --git a/lib/iov_iter.c b/lib/iov_iter.c -index c3ca28ca68a65..d2d5e41082fe8 100644 ---- a/lib/iov_iter.c -+++ b/lib/iov_iter.c -@@ -186,12 +186,6 @@ static int copyin(void *to, const void __user *from, size_t n) - return res; - } - --static inline struct pipe_buffer *pipe_buf(const struct pipe_inode_info *pipe, -- unsigned int slot) --{ -- return &pipe->bufs[slot & (pipe->ring_size - 1)]; --} -- - #ifdef PIPE_PARANOIA - static bool sanity(const struct iov_iter *i) - { -diff --git a/mm/filemap.c b/mm/filemap.c -index f57bc92e9b46f..ce5e1e443b1c9 100644 ---- a/mm/filemap.c -+++ b/mm/filemap.c -@@ -42,6 +42,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include "internal.h" -@@ -2915,6 +2917,133 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) - } - EXPORT_SYMBOL(generic_file_read_iter); - -+/* -+ * Splice subpages from a folio into a pipe. -+ */ -+size_t splice_folio_into_pipe(struct pipe_inode_info *pipe, -+ struct folio *folio, loff_t fpos, size_t size) -+{ -+ struct page *page; -+ size_t spliced = 0, offset = offset_in_folio(folio, fpos); -+ -+ page = folio_page(folio, offset / PAGE_SIZE); -+ size = min(size, folio_size(folio) - offset); -+ offset %= PAGE_SIZE; -+ -+ while (spliced < size && -+ !pipe_full(pipe->head, pipe->tail, pipe->max_usage)) { -+ struct pipe_buffer *buf = pipe_head_buf(pipe); -+ size_t part = min_t(size_t, PAGE_SIZE - offset, size - spliced); -+ -+ *buf = (struct pipe_buffer) { -+ .ops = &page_cache_pipe_buf_ops, -+ .page = page, -+ .offset = offset, -+ .len = part, -+ }; -+ folio_get(folio); -+ pipe->head++; -+ page++; -+ spliced += part; -+ offset = 0; -+ } -+ -+ return spliced; -+} -+ -+/* -+ * Splice folios from the pagecache of a buffered (ie. non-O_DIRECT) file into -+ * a pipe. -+ */ -+ssize_t filemap_splice_read(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, -+ size_t len, unsigned int flags) -+{ -+ struct folio_batch fbatch; -+ struct kiocb iocb; -+ size_t total_spliced = 0, used, npages; -+ loff_t isize, end_offset; -+ bool writably_mapped; -+ int i, error = 0; -+ -+ init_sync_kiocb(&iocb, in); -+ iocb.ki_pos = *ppos; -+ -+ /* Work out how much data we can actually add into the pipe */ -+ used = pipe_occupancy(pipe->head, pipe->tail); -+ npages = max_t(ssize_t, pipe->max_usage - used, 0); -+ len = min_t(size_t, len, npages * PAGE_SIZE); -+ -+ folio_batch_init(&fbatch); -+ -+ do { -+ cond_resched(); -+ -+ if (*ppos >= i_size_read(file_inode(in))) -+ break; -+ -+ iocb.ki_pos = *ppos; -+ error = filemap_get_pages(&iocb, len, &fbatch, true); -+ if (error < 0) -+ break; -+ -+ /* -+ * i_size must be checked after we know the pages are Uptodate. -+ * -+ * Checking i_size after the check allows us to calculate -+ * the correct value for "nr", which means the zero-filled -+ * part of the page is not copied back to userspace (unless -+ * another truncate extends the file - this is desired though). -+ */ -+ isize = i_size_read(file_inode(in)); -+ if (unlikely(*ppos >= isize)) -+ break; -+ end_offset = min_t(loff_t, isize, *ppos + len); -+ -+ /* -+ * Once we start copying data, we don't want to be touching any -+ * cachelines that might be contended: -+ */ -+ writably_mapped = mapping_writably_mapped(in->f_mapping); -+ -+ for (i = 0; i < folio_batch_count(&fbatch); i++) { -+ struct folio *folio = fbatch.folios[i]; -+ size_t n; -+ -+ if (folio_pos(folio) >= end_offset) -+ goto out; -+ folio_mark_accessed(folio); -+ -+ /* -+ * If users can be writing to this folio using arbitrary -+ * virtual addresses, take care of potential aliasing -+ * before reading the folio on the kernel side. -+ */ -+ if (writably_mapped) -+ flush_dcache_folio(folio); -+ -+ n = min_t(loff_t, len, isize - *ppos); -+ n = splice_folio_into_pipe(pipe, folio, *ppos, n); -+ if (!n) -+ goto out; -+ len -= n; -+ total_spliced += n; -+ *ppos += n; -+ in->f_ra.prev_pos = *ppos; -+ if (pipe_full(pipe->head, pipe->tail, pipe->max_usage)) -+ goto out; -+ } -+ -+ folio_batch_release(&fbatch); -+ } while (len); -+ -+out: -+ folio_batch_release(&fbatch); -+ file_accessed(in); -+ -+ return total_spliced ? total_spliced : error; -+} -+ - static inline loff_t folio_seek_hole_data(struct xa_state *xas, - struct address_space *mapping, struct folio *folio, - loff_t start, loff_t end, bool seek_data) -diff --git a/mm/internal.h b/mm/internal.h -index 16a4a9aece304..5e3f3749527f6 100644 ---- a/mm/internal.h -+++ b/mm/internal.h -@@ -841,6 +841,12 @@ struct migration_target_control { - gfp_t gfp_mask; - }; - -+/* -+ * mm/filemap.c -+ */ -+size_t splice_folio_into_pipe(struct pipe_inode_info *pipe, -+ struct folio *folio, loff_t fpos, size_t size); -+ - /* - * mm/vmalloc.c - */ --- -2.39.5 - diff --git a/queue-6.12/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch b/queue-6.12/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch deleted file mode 100644 index 2b7ac7594b..0000000000 --- a/queue-6.12/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch +++ /dev/null @@ -1,63 +0,0 @@ -From d74248a89b27d81cc2450c139b019719895ccdc7 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 6 Mar 2025 07:33:58 -1000 -Subject: fs/pipe: do not open-code pipe head/tail logic in FIONREAD - -From: Linus Torvalds - -[ Upstream commit d810d4c27bf34c719243bab9feb0d843edc09fd7 ] - -Rasmus points out that we do indeed have other cases of breakage from -the type changes that were introduced on 32-bit targets in order to read -the pipe head and tail values atomically (commit 3d252160b818: "fs/pipe: -Read pipe->{head,tail} atomically outside pipe->mutex"). - -Fix it up by using the proper helper functions that now deal with the -pipe buffer index types properly. This makes the code simpler and more -obvious. - -The compiler does the CSE and loop hoisting of the pipe ring size -masking that we used to do manually, so open-coding this was never a -good idea. - -Reported-by: Rasmus Villemoes -Link: https://lore.kernel.org/all/87cyeu5zgk.fsf@prevas.dk/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg Nesterov -Cc: Mateusz Guzik -Cc: K Prateek Nayak -Cc: Swapnil Sapkal -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/pipe.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/fs/pipe.c b/fs/pipe.c -index 0b2b6ccb8ec52..6e72670a8a0dc 100644 ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -613,7 +613,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) - static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - { - struct pipe_inode_info *pipe = filp->private_data; -- unsigned int count, head, tail, mask; -+ unsigned int count, head, tail; - - switch (cmd) { - case FIONREAD: -@@ -621,10 +621,9 @@ static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - count = 0; - head = pipe->head; - tail = pipe->tail; -- mask = pipe->ring_size - 1; - -- while (tail != head) { -- count += pipe->bufs[tail & mask].len; -+ while (!pipe_empty(head, tail)) { -+ count += pipe_buf(pipe, tail)->len; - tail++; - } - mutex_unlock(&pipe->mutex); --- -2.39.5 - diff --git a/queue-6.12/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch b/queue-6.12/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch deleted file mode 100644 index 684c5fe6e2..0000000000 --- a/queue-6.12/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch +++ /dev/null @@ -1,78 +0,0 @@ -From bb3b60e2c921cb253f99be3580bc23af9e5dc2f1 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 6 Mar 2025 07:53:25 -1000 -Subject: fs/pipe: fix pipe buffer index use in FUSE - -From: Linus Torvalds - -[ Upstream commit ebb0f38bb47f74b29e267babdbcd2c47d5292aa8 ] - -This was another case that Rasmus pointed out where the direct access to -the pipe head and tail pointers broke on 32-bit configurations due to -the type changes. - -As with the pipe FIONREAD case, fix it by using the appropriate helper -functions that deal with the right pipe index sizing. - -Reported-by: Rasmus Villemoes -Link: https://lore.kernel.org/all/878qpi5wz4.fsf@prevas.dk/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg > -Cc: Mateusz Guzik -Cc: K Prateek Nayak -Cc: Swapnil Sapkal -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/fuse/dev.c | 13 ++++++------- - 1 file changed, 6 insertions(+), 7 deletions(-) - -diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c -index 1f64ae6d7a69e..f609701297311 100644 ---- a/fs/fuse/dev.c -+++ b/fs/fuse/dev.c -@@ -2079,7 +2079,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - struct file *out, loff_t *ppos, - size_t len, unsigned int flags) - { -- unsigned int head, tail, mask, count; -+ unsigned int head, tail, count; - unsigned nbuf; - unsigned idx; - struct pipe_buffer *bufs; -@@ -2096,8 +2096,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - - head = pipe->head; - tail = pipe->tail; -- mask = pipe->ring_size - 1; -- count = head - tail; -+ count = pipe_occupancy(head, tail); - - bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL); - if (!bufs) { -@@ -2107,8 +2106,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - - nbuf = 0; - rem = 0; -- for (idx = tail; idx != head && rem < len; idx++) -- rem += pipe->bufs[idx & mask].len; -+ for (idx = tail; !pipe_empty(head, idx) && rem < len; idx++) -+ rem += pipe_buf(pipe, idx)->len; - - ret = -EINVAL; - if (rem < len) -@@ -2119,10 +2118,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - struct pipe_buffer *ibuf; - struct pipe_buffer *obuf; - -- if (WARN_ON(nbuf >= count || tail == head)) -+ if (WARN_ON(nbuf >= count || pipe_empty(head, tail))) - goto out_free; - -- ibuf = &pipe->bufs[tail & mask]; -+ ibuf = pipe_buf(pipe, tail); - obuf = &bufs[nbuf]; - - if (rem >= ibuf->len) { --- -2.39.5 - diff --git a/queue-6.12/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch b/queue-6.12/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch deleted file mode 100644 index 76429c0158..0000000000 --- a/queue-6.12/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 60e10eb27fe5399c6173c917c1b9dda3f2f96333 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 5 Mar 2025 07:08:09 -1000 -Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes - -From: Linus Torvalds - -[ Upstream commit c27c66afc449b80f3b4b84d123358c0248f2cf63 ] - -The pipe_occupancy() logic implicitly relied on the natural unsigned -modulo arithmetic in C, but that doesn't work for the new 'pipe_index_t' -case, since any arithmetic will be done in 'int' (and here we had also -made it 'unsigned int' due to the function call boundary). - -So make the modulo arithmetic explicit by casting the result to the -proper type. - -Cc: Oleg Nesterov -Cc: Mateusz Guzik -Cc: Manfred Spraul -Cc: Christian Brauner -Cc: Swapnil Sapkal -Cc: Alexey Gladkov -Cc: K Prateek Nayak -Link: https://lore.kernel.org/all/CAHk-=wjyHsGLx=rxg6PKYBNkPYAejgo7=CbyL3=HGLZLsAaJFQ@mail.gmail.com/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex") -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - include/linux/pipe_fs_i.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 3cc4f8eab853f..1f013ed7577ef 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -192,7 +192,7 @@ static inline bool pipe_empty(unsigned int head, unsigned int tail) - */ - static inline unsigned int pipe_occupancy(unsigned int head, unsigned int tail) - { -- return head - tail; -+ return (pipe_index_t)(head - tail); - } - - /** --- -2.39.5 - diff --git a/queue-6.12/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch b/queue-6.12/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch deleted file mode 100644 index b1e938006e..0000000000 --- a/queue-6.12/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 72fecd3b278bbe1df4a004b5dd5b8c721b2a4183 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 4 Mar 2025 13:51:38 +0000 -Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex - -From: Linus Torvalds - -[ Upstream commit 3d252160b818045f3a152b13756f6f37ca34639d ] - -pipe_readable(), pipe_writable(), and pipe_poll() can read "pipe->head" -and "pipe->tail" outside of "pipe->mutex" critical section. When the -head and the tail are read individually in that order, there is a window -for interruption between the two reads in which both the head and the -tail can be updated by concurrent readers and writers. - -One of the problematic scenarios observed with hackbench running -multiple groups on a large server on a particular pipe inode is as -follows: - - pipe->head = 36 - pipe->tail = 36 - - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wakes up: pipe not full* - hackbench-118762 [057] ..... 1029.550548: pipe_write: head: 36 -> 37 [tail: 36] - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next reader 118740* - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next writer 118768* - - hackbench-118768 [206] ..... 1029.55055X: pipe_write: *writer wakes up* - hackbench-118768 [206] ..... 1029.55055X: pipe_write: head = READ_ONCE(pipe->head) [37] - ... CPU 206 interrupted (exact wakeup was not traced but 118768 did read head at 37 in traces) - - hackbench-118740 [057] ..... 1029.550558: pipe_read: *reader wakes up: pipe is not empty* - hackbench-118740 [057] ..... 1029.550558: pipe_read: tail: 36 -> 37 [head = 37] - hackbench-118740 [057] ..... 1029.550559: pipe_read: *pipe is empty; wakeup writer 118768* - hackbench-118740 [057] ..... 1029.550559: pipe_read: *sleeps* - - hackbench-118766 [185] ..... 1029.550592: pipe_write: *New writer comes in* - hackbench-118766 [185] ..... 1029.550592: pipe_write: head: 37 -> 38 [tail: 37] - hackbench-118766 [185] ..... 1029.550592: pipe_write: *wakes up reader 118766* - - hackbench-118740 [185] ..... 1029.550598: pipe_read: *reader wakes up; pipe not empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: tail: 37 -> 38 [head: 38] - hackbench-118740 [185] ..... 1029.550599: pipe_read: *pipe is empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: *reader sleeps; wakeup writer 118768* - - ... CPU 206 switches back to writer - hackbench-118768 [206] ..... 1029.550601: pipe_write: tail = READ_ONCE(pipe->tail) [38] - hackbench-118768 [206] ..... 1029.550601: pipe_write: pipe_full()? (u32)(37 - 38) >= 16? Yes - hackbench-118768 [206] ..... 1029.550601: pipe_write: *writer goes back to sleep* - - [ Tasks 118740 and 118768 can then indefinitely wait on each other. ] - -The unsigned arithmetic in pipe_occupancy() wraps around when -"pipe->tail > pipe->head" leading to pipe_full() returning true despite -the pipe being empty. - -The case of genuine wraparound of "pipe->head" is handled since pipe -buffer has data allowing readers to make progress until the pipe->tail -wraps too after which the reader will wakeup a sleeping writer, however, -mistaking the pipe to be full when it is in fact empty can lead to -readers and writers waiting on each other indefinitely. - -This issue became more problematic and surfaced as a hang in hackbench -after the optimization in commit aaec5a95d596 ("pipe_read: don't wake up -the writer if the pipe is still full") significantly reduced the number -of spurious wakeups of writers that had previously helped mask the -issue. - -To avoid missing any updates between the reads of "pipe->head" and -"pipe->write", unionize the two with a single unsigned long -"pipe->head_tail" member that can be loaded atomically. - -Using "pipe->head_tail" to read the head and the tail ensures the -lockless checks do not miss any updates to the head or the tail and -since those two are only updated under "pipe->mutex", it ensures that -the head is always ahead of, or equal to the tail resulting in correct -calculations. - - [ prateek: commit log, testing on x86 platforms. ] - -Reported-and-debugged-by: Swapnil Sapkal -Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/ -Reported-by: Alexey Gladkov -Closes: https://lore.kernel.org/all/Z8Wn0nTvevLRG_4m@example.org/ -Fixes: 8cefc107ca54 ("pipe: Use head and tail pointers for the ring, not cursor and length") -Tested-by: Swapnil Sapkal -Reviewed-by: Oleg Nesterov -Tested-by: Alexey Gladkov -Signed-off-by: K Prateek Nayak -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/pipe.c | 19 ++++++++----------- - include/linux/pipe_fs_i.h | 39 +++++++++++++++++++++++++++++++++++++-- - 2 files changed, 45 insertions(+), 13 deletions(-) - -diff --git a/fs/pipe.c b/fs/pipe.c -index 12b22c2723b7e..0b2b6ccb8ec52 100644 ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -210,11 +210,10 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_readable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int writers = READ_ONCE(pipe->writers); - -- return !pipe_empty(head, tail) || !writers; -+ return !pipe_empty(idx.head, idx.tail) || !writers; - } - - static inline unsigned int pipe_update_tail(struct pipe_inode_info *pipe, -@@ -416,11 +415,10 @@ static inline int is_packetized(struct file *file) - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_writable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int max_usage = READ_ONCE(pipe->max_usage); - -- return !pipe_full(head, tail, max_usage) || -+ return !pipe_full(idx.head, idx.tail, max_usage) || - !READ_ONCE(pipe->readers); - } - -@@ -658,7 +656,7 @@ pipe_poll(struct file *filp, poll_table *wait) - { - __poll_t mask; - struct pipe_inode_info *pipe = filp->private_data; -- unsigned int head, tail; -+ union pipe_index idx; - - /* Epoll has some historical nasty semantics, this enables them */ - WRITE_ONCE(pipe->poll_usage, true); -@@ -679,19 +677,18 @@ pipe_poll(struct file *filp, poll_table *wait) - * if something changes and you got it wrong, the poll - * table entry will wake you up and fix it. - */ -- head = READ_ONCE(pipe->head); -- tail = READ_ONCE(pipe->tail); -+ idx.head_tail = READ_ONCE(pipe->head_tail); - - mask = 0; - if (filp->f_mode & FMODE_READ) { -- if (!pipe_empty(head, tail)) -+ if (!pipe_empty(idx.head, idx.tail)) - mask |= EPOLLIN | EPOLLRDNORM; - if (!pipe->writers && filp->f_pipe != pipe->w_counter) - mask |= EPOLLHUP; - } - - if (filp->f_mode & FMODE_WRITE) { -- if (!pipe_full(head, tail, pipe->max_usage)) -+ if (!pipe_full(idx.head, idx.tail, pipe->max_usage)) - mask |= EPOLLOUT | EPOLLWRNORM; - /* - * Most Unices do not set EPOLLERR for FIFOs but on Linux they -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 8ff23bf5a8197..3cc4f8eab853f 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -31,6 +31,33 @@ struct pipe_buffer { - unsigned long private; - }; - -+/* -+ * Really only alpha needs 32-bit fields, but -+ * might as well do it for 64-bit architectures -+ * since that's what we've historically done, -+ * and it makes 'head_tail' always be a simple -+ * 'unsigned long'. -+ */ -+#ifdef CONFIG_64BIT -+typedef unsigned int pipe_index_t; -+#else -+typedef unsigned short pipe_index_t; -+#endif -+ -+/* -+ * We have to declare this outside 'struct pipe_inode_info', -+ * but then we can't use 'union pipe_index' for an anonymous -+ * union, so we end up having to duplicate this declaration -+ * below. Annoying. -+ */ -+union pipe_index { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+}; -+ - /** - * struct pipe_inode_info - a linux kernel pipe - * @mutex: mutex protecting the whole thing -@@ -58,8 +85,16 @@ struct pipe_buffer { - struct pipe_inode_info { - struct mutex mutex; - wait_queue_head_t rd_wait, wr_wait; -- unsigned int head; -- unsigned int tail; -+ -+ /* This has to match the 'union pipe_index' above */ -+ union { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+ }; -+ - unsigned int max_usage; - unsigned int ring_size; - unsigned int nr_accounted; --- -2.39.5 - diff --git a/queue-6.12/series b/queue-6.12/series index 70955c3244..ab5b246748 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -178,7 +178,6 @@ hwmon-fix-a-null-vs-is_err_or_null-check-in-xgene_hw.patch drm-sched-fix-preprocessor-guard.patch be2net-fix-sleeping-while-atomic-bugs-in-be_ndo_brid.patch net-hns3-make-sure-ptp-clock-is-unregister-and-freed.patch -fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch drm-i915-color-extract-intel_color_modeset.patch drm-i915-plumb-dsb-all-way-to-the-plane-hooks.patch drm-xe-remove-double-pageflip.patch @@ -198,15 +197,12 @@ exfat-short-circuit-zero-byte-writes-in-exfat_file_w.patch net-timestamp-support-tcp-gso-case-for-a-few-missing.patch ublk-set_params-properly-check-if-parameters-can-be-.patch sched-fair-fix-potential-memory-corruption-in-child_.patch -fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch nvme-tcp-fix-signedness-bug-in-nvme_tcp_init_connect.patch net-dsa-mt7530-fix-traffic-flooding-for-mmio-devices.patch mctp-i3c-handle-null-header-address.patch net-ipv6-fix-dst-ref-loop-in-ila-lwtunnel.patch net-ipv6-fix-missing-dst-ref-drop-in-ila-lwtunnel.patch gpio-rcar-fix-missing-of_node_put-call.patch -fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch -fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch revert-drivers-card_reader-rtsx_usb-restore-interrupt-based-detection.patch usb-renesas_usbhs-call-clk_put.patch xhci-restrict-usb4-tunnel-detection-for-usb3-devices-to-intel-hosts.patch diff --git a/queue-6.13/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch b/queue-6.13/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch deleted file mode 100644 index 4440670b6c..0000000000 --- a/queue-6.13/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch +++ /dev/null @@ -1,63 +0,0 @@ -From cff7aa72cf4bb6ff5928f8534d705827ec42b140 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 6 Mar 2025 07:33:58 -1000 -Subject: fs/pipe: do not open-code pipe head/tail logic in FIONREAD - -From: Linus Torvalds - -[ Upstream commit d810d4c27bf34c719243bab9feb0d843edc09fd7 ] - -Rasmus points out that we do indeed have other cases of breakage from -the type changes that were introduced on 32-bit targets in order to read -the pipe head and tail values atomically (commit 3d252160b818: "fs/pipe: -Read pipe->{head,tail} atomically outside pipe->mutex"). - -Fix it up by using the proper helper functions that now deal with the -pipe buffer index types properly. This makes the code simpler and more -obvious. - -The compiler does the CSE and loop hoisting of the pipe ring size -masking that we used to do manually, so open-coding this was never a -good idea. - -Reported-by: Rasmus Villemoes -Link: https://lore.kernel.org/all/87cyeu5zgk.fsf@prevas.dk/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg Nesterov -Cc: Mateusz Guzik -Cc: K Prateek Nayak -Cc: Swapnil Sapkal -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/pipe.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/fs/pipe.c b/fs/pipe.c -index 0b2b6ccb8ec52..6e72670a8a0dc 100644 ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -613,7 +613,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) - static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - { - struct pipe_inode_info *pipe = filp->private_data; -- unsigned int count, head, tail, mask; -+ unsigned int count, head, tail; - - switch (cmd) { - case FIONREAD: -@@ -621,10 +621,9 @@ static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - count = 0; - head = pipe->head; - tail = pipe->tail; -- mask = pipe->ring_size - 1; - -- while (tail != head) { -- count += pipe->bufs[tail & mask].len; -+ while (!pipe_empty(head, tail)) { -+ count += pipe_buf(pipe, tail)->len; - tail++; - } - mutex_unlock(&pipe->mutex); --- -2.39.5 - diff --git a/queue-6.13/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch b/queue-6.13/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch deleted file mode 100644 index d67dbe3d45..0000000000 --- a/queue-6.13/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 097ef18912b9dcbefd6ee19bb430f8f2f3832fde Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 6 Mar 2025 07:53:25 -1000 -Subject: fs/pipe: fix pipe buffer index use in FUSE - -From: Linus Torvalds - -[ Upstream commit ebb0f38bb47f74b29e267babdbcd2c47d5292aa8 ] - -This was another case that Rasmus pointed out where the direct access to -the pipe head and tail pointers broke on 32-bit configurations due to -the type changes. - -As with the pipe FIONREAD case, fix it by using the appropriate helper -functions that deal with the right pipe index sizing. - -Reported-by: Rasmus Villemoes -Link: https://lore.kernel.org/all/878qpi5wz4.fsf@prevas.dk/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg > -Cc: Mateusz Guzik -Cc: K Prateek Nayak -Cc: Swapnil Sapkal -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/fuse/dev.c | 13 ++++++------- - 1 file changed, 6 insertions(+), 7 deletions(-) - -diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c -index 9ce6d1c6cac15..b8fb5da2565ed 100644 ---- a/fs/fuse/dev.c -+++ b/fs/fuse/dev.c -@@ -2097,7 +2097,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - struct file *out, loff_t *ppos, - size_t len, unsigned int flags) - { -- unsigned int head, tail, mask, count; -+ unsigned int head, tail, count; - unsigned nbuf; - unsigned idx; - struct pipe_buffer *bufs; -@@ -2114,8 +2114,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - - head = pipe->head; - tail = pipe->tail; -- mask = pipe->ring_size - 1; -- count = head - tail; -+ count = pipe_occupancy(head, tail); - - bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL); - if (!bufs) { -@@ -2125,8 +2124,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - - nbuf = 0; - rem = 0; -- for (idx = tail; idx != head && rem < len; idx++) -- rem += pipe->bufs[idx & mask].len; -+ for (idx = tail; !pipe_empty(head, idx) && rem < len; idx++) -+ rem += pipe_buf(pipe, idx)->len; - - ret = -EINVAL; - if (rem < len) -@@ -2137,10 +2136,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - struct pipe_buffer *ibuf; - struct pipe_buffer *obuf; - -- if (WARN_ON(nbuf >= count || tail == head)) -+ if (WARN_ON(nbuf >= count || pipe_empty(head, tail))) - goto out_free; - -- ibuf = &pipe->bufs[tail & mask]; -+ ibuf = pipe_buf(pipe, tail); - obuf = &bufs[nbuf]; - - if (rem >= ibuf->len) { --- -2.39.5 - diff --git a/queue-6.13/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch b/queue-6.13/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch deleted file mode 100644 index a9ffd7885c..0000000000 --- a/queue-6.13/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch +++ /dev/null @@ -1,48 +0,0 @@ -From f0472863c6ef82537b45b7056dd15b42f505097e Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 5 Mar 2025 07:08:09 -1000 -Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes - -From: Linus Torvalds - -[ Upstream commit c27c66afc449b80f3b4b84d123358c0248f2cf63 ] - -The pipe_occupancy() logic implicitly relied on the natural unsigned -modulo arithmetic in C, but that doesn't work for the new 'pipe_index_t' -case, since any arithmetic will be done in 'int' (and here we had also -made it 'unsigned int' due to the function call boundary). - -So make the modulo arithmetic explicit by casting the result to the -proper type. - -Cc: Oleg Nesterov -Cc: Mateusz Guzik -Cc: Manfred Spraul -Cc: Christian Brauner -Cc: Swapnil Sapkal -Cc: Alexey Gladkov -Cc: K Prateek Nayak -Link: https://lore.kernel.org/all/CAHk-=wjyHsGLx=rxg6PKYBNkPYAejgo7=CbyL3=HGLZLsAaJFQ@mail.gmail.com/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex") -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - include/linux/pipe_fs_i.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 3cc4f8eab853f..1f013ed7577ef 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -192,7 +192,7 @@ static inline bool pipe_empty(unsigned int head, unsigned int tail) - */ - static inline unsigned int pipe_occupancy(unsigned int head, unsigned int tail) - { -- return head - tail; -+ return (pipe_index_t)(head - tail); - } - - /** --- -2.39.5 - diff --git a/queue-6.13/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch b/queue-6.13/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch deleted file mode 100644 index d5b5e9bfe3..0000000000 --- a/queue-6.13/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 2fa9bc4a929953d776783b960bbbd9b78efed1c0 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 4 Mar 2025 13:51:38 +0000 -Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex - -From: Linus Torvalds - -[ Upstream commit 3d252160b818045f3a152b13756f6f37ca34639d ] - -pipe_readable(), pipe_writable(), and pipe_poll() can read "pipe->head" -and "pipe->tail" outside of "pipe->mutex" critical section. When the -head and the tail are read individually in that order, there is a window -for interruption between the two reads in which both the head and the -tail can be updated by concurrent readers and writers. - -One of the problematic scenarios observed with hackbench running -multiple groups on a large server on a particular pipe inode is as -follows: - - pipe->head = 36 - pipe->tail = 36 - - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wakes up: pipe not full* - hackbench-118762 [057] ..... 1029.550548: pipe_write: head: 36 -> 37 [tail: 36] - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next reader 118740* - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next writer 118768* - - hackbench-118768 [206] ..... 1029.55055X: pipe_write: *writer wakes up* - hackbench-118768 [206] ..... 1029.55055X: pipe_write: head = READ_ONCE(pipe->head) [37] - ... CPU 206 interrupted (exact wakeup was not traced but 118768 did read head at 37 in traces) - - hackbench-118740 [057] ..... 1029.550558: pipe_read: *reader wakes up: pipe is not empty* - hackbench-118740 [057] ..... 1029.550558: pipe_read: tail: 36 -> 37 [head = 37] - hackbench-118740 [057] ..... 1029.550559: pipe_read: *pipe is empty; wakeup writer 118768* - hackbench-118740 [057] ..... 1029.550559: pipe_read: *sleeps* - - hackbench-118766 [185] ..... 1029.550592: pipe_write: *New writer comes in* - hackbench-118766 [185] ..... 1029.550592: pipe_write: head: 37 -> 38 [tail: 37] - hackbench-118766 [185] ..... 1029.550592: pipe_write: *wakes up reader 118766* - - hackbench-118740 [185] ..... 1029.550598: pipe_read: *reader wakes up; pipe not empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: tail: 37 -> 38 [head: 38] - hackbench-118740 [185] ..... 1029.550599: pipe_read: *pipe is empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: *reader sleeps; wakeup writer 118768* - - ... CPU 206 switches back to writer - hackbench-118768 [206] ..... 1029.550601: pipe_write: tail = READ_ONCE(pipe->tail) [38] - hackbench-118768 [206] ..... 1029.550601: pipe_write: pipe_full()? (u32)(37 - 38) >= 16? Yes - hackbench-118768 [206] ..... 1029.550601: pipe_write: *writer goes back to sleep* - - [ Tasks 118740 and 118768 can then indefinitely wait on each other. ] - -The unsigned arithmetic in pipe_occupancy() wraps around when -"pipe->tail > pipe->head" leading to pipe_full() returning true despite -the pipe being empty. - -The case of genuine wraparound of "pipe->head" is handled since pipe -buffer has data allowing readers to make progress until the pipe->tail -wraps too after which the reader will wakeup a sleeping writer, however, -mistaking the pipe to be full when it is in fact empty can lead to -readers and writers waiting on each other indefinitely. - -This issue became more problematic and surfaced as a hang in hackbench -after the optimization in commit aaec5a95d596 ("pipe_read: don't wake up -the writer if the pipe is still full") significantly reduced the number -of spurious wakeups of writers that had previously helped mask the -issue. - -To avoid missing any updates between the reads of "pipe->head" and -"pipe->write", unionize the two with a single unsigned long -"pipe->head_tail" member that can be loaded atomically. - -Using "pipe->head_tail" to read the head and the tail ensures the -lockless checks do not miss any updates to the head or the tail and -since those two are only updated under "pipe->mutex", it ensures that -the head is always ahead of, or equal to the tail resulting in correct -calculations. - - [ prateek: commit log, testing on x86 platforms. ] - -Reported-and-debugged-by: Swapnil Sapkal -Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/ -Reported-by: Alexey Gladkov -Closes: https://lore.kernel.org/all/Z8Wn0nTvevLRG_4m@example.org/ -Fixes: 8cefc107ca54 ("pipe: Use head and tail pointers for the ring, not cursor and length") -Tested-by: Swapnil Sapkal -Reviewed-by: Oleg Nesterov -Tested-by: Alexey Gladkov -Signed-off-by: K Prateek Nayak -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/pipe.c | 19 ++++++++----------- - include/linux/pipe_fs_i.h | 39 +++++++++++++++++++++++++++++++++++++-- - 2 files changed, 45 insertions(+), 13 deletions(-) - -diff --git a/fs/pipe.c b/fs/pipe.c -index 12b22c2723b7e..0b2b6ccb8ec52 100644 ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -210,11 +210,10 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_readable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int writers = READ_ONCE(pipe->writers); - -- return !pipe_empty(head, tail) || !writers; -+ return !pipe_empty(idx.head, idx.tail) || !writers; - } - - static inline unsigned int pipe_update_tail(struct pipe_inode_info *pipe, -@@ -416,11 +415,10 @@ static inline int is_packetized(struct file *file) - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_writable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int max_usage = READ_ONCE(pipe->max_usage); - -- return !pipe_full(head, tail, max_usage) || -+ return !pipe_full(idx.head, idx.tail, max_usage) || - !READ_ONCE(pipe->readers); - } - -@@ -658,7 +656,7 @@ pipe_poll(struct file *filp, poll_table *wait) - { - __poll_t mask; - struct pipe_inode_info *pipe = filp->private_data; -- unsigned int head, tail; -+ union pipe_index idx; - - /* Epoll has some historical nasty semantics, this enables them */ - WRITE_ONCE(pipe->poll_usage, true); -@@ -679,19 +677,18 @@ pipe_poll(struct file *filp, poll_table *wait) - * if something changes and you got it wrong, the poll - * table entry will wake you up and fix it. - */ -- head = READ_ONCE(pipe->head); -- tail = READ_ONCE(pipe->tail); -+ idx.head_tail = READ_ONCE(pipe->head_tail); - - mask = 0; - if (filp->f_mode & FMODE_READ) { -- if (!pipe_empty(head, tail)) -+ if (!pipe_empty(idx.head, idx.tail)) - mask |= EPOLLIN | EPOLLRDNORM; - if (!pipe->writers && filp->f_pipe != pipe->w_counter) - mask |= EPOLLHUP; - } - - if (filp->f_mode & FMODE_WRITE) { -- if (!pipe_full(head, tail, pipe->max_usage)) -+ if (!pipe_full(idx.head, idx.tail, pipe->max_usage)) - mask |= EPOLLOUT | EPOLLWRNORM; - /* - * Most Unices do not set EPOLLERR for FIFOs but on Linux they -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 8ff23bf5a8197..3cc4f8eab853f 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -31,6 +31,33 @@ struct pipe_buffer { - unsigned long private; - }; - -+/* -+ * Really only alpha needs 32-bit fields, but -+ * might as well do it for 64-bit architectures -+ * since that's what we've historically done, -+ * and it makes 'head_tail' always be a simple -+ * 'unsigned long'. -+ */ -+#ifdef CONFIG_64BIT -+typedef unsigned int pipe_index_t; -+#else -+typedef unsigned short pipe_index_t; -+#endif -+ -+/* -+ * We have to declare this outside 'struct pipe_inode_info', -+ * but then we can't use 'union pipe_index' for an anonymous -+ * union, so we end up having to duplicate this declaration -+ * below. Annoying. -+ */ -+union pipe_index { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+}; -+ - /** - * struct pipe_inode_info - a linux kernel pipe - * @mutex: mutex protecting the whole thing -@@ -58,8 +85,16 @@ struct pipe_buffer { - struct pipe_inode_info { - struct mutex mutex; - wait_queue_head_t rd_wait, wr_wait; -- unsigned int head; -- unsigned int tail; -+ -+ /* This has to match the 'union pipe_index' above */ -+ union { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+ }; -+ - unsigned int max_usage; - unsigned int ring_size; - unsigned int nr_accounted; --- -2.39.5 - diff --git a/queue-6.13/series b/queue-6.13/series index 0538077979..548d2b71c5 100644 --- a/queue-6.13/series +++ b/queue-6.13/series @@ -124,7 +124,6 @@ hwmon-fix-a-null-vs-is_err_or_null-check-in-xgene_hw.patch drm-sched-fix-preprocessor-guard.patch be2net-fix-sleeping-while-atomic-bugs-in-be_ndo_brid.patch net-hns3-make-sure-ptp-clock-is-unregister-and-freed.patch -fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch drm-xe-remove-double-pageflip.patch hid-hid-steam-fix-use-after-free-when-detaching-devi.patch net-ipa-fix-v4.7-resource-group-names.patch @@ -142,7 +141,6 @@ exfat-short-circuit-zero-byte-writes-in-exfat_file_w.patch net-timestamp-support-tcp-gso-case-for-a-few-missing.patch ublk-set_params-properly-check-if-parameters-can-be-.patch sched-fair-fix-potential-memory-corruption-in-child_.patch -fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch nvme-tcp-fix-signedness-bug-in-nvme_tcp_init_connect.patch net-dsa-mt7530-fix-traffic-flooding-for-mmio-devices.patch drm-bochs-fix-dpms-regression.patch @@ -150,8 +148,6 @@ mctp-i3c-handle-null-header-address.patch net-ipv6-fix-dst-ref-loop-in-ila-lwtunnel.patch net-ipv6-fix-missing-dst-ref-drop-in-ila-lwtunnel.patch gpio-rcar-fix-missing-of_node_put-call.patch -fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch -fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch revert-drivers-card_reader-rtsx_usb-restore-interrupt-based-detection.patch usb-renesas_usbhs-call-clk_put.patch xhci-restrict-usb4-tunnel-detection-for-usb3-devices-to-intel-hosts.patch diff --git a/queue-6.6/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch b/queue-6.6/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch deleted file mode 100644 index aec974982a..0000000000 --- a/queue-6.6/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 1ee8e42441a3a9ae2524d1d90d97a41660f68929 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 6 Mar 2025 07:33:58 -1000 -Subject: fs/pipe: do not open-code pipe head/tail logic in FIONREAD - -From: Linus Torvalds - -[ Upstream commit d810d4c27bf34c719243bab9feb0d843edc09fd7 ] - -Rasmus points out that we do indeed have other cases of breakage from -the type changes that were introduced on 32-bit targets in order to read -the pipe head and tail values atomically (commit 3d252160b818: "fs/pipe: -Read pipe->{head,tail} atomically outside pipe->mutex"). - -Fix it up by using the proper helper functions that now deal with the -pipe buffer index types properly. This makes the code simpler and more -obvious. - -The compiler does the CSE and loop hoisting of the pipe ring size -masking that we used to do manually, so open-coding this was never a -good idea. - -Reported-by: Rasmus Villemoes -Link: https://lore.kernel.org/all/87cyeu5zgk.fsf@prevas.dk/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg Nesterov -Cc: Mateusz Guzik -Cc: K Prateek Nayak -Cc: Swapnil Sapkal -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/pipe.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/fs/pipe.c b/fs/pipe.c -index d8f7c56d438d7..ac08addbaa638 100644 ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -611,7 +611,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) - static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - { - struct pipe_inode_info *pipe = filp->private_data; -- unsigned int count, head, tail, mask; -+ unsigned int count, head, tail; - - switch (cmd) { - case FIONREAD: -@@ -619,10 +619,9 @@ static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - count = 0; - head = pipe->head; - tail = pipe->tail; -- mask = pipe->ring_size - 1; - -- while (tail != head) { -- count += pipe->bufs[tail & mask].len; -+ while (!pipe_empty(head, tail)) { -+ count += pipe_buf(pipe, tail)->len; - tail++; - } - __pipe_unlock(pipe); --- -2.39.5 - diff --git a/queue-6.6/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch b/queue-6.6/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch deleted file mode 100644 index c9ced6c204..0000000000 --- a/queue-6.6/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 774cf4428e383acaa210f4d7c3ed3ce5dad204d1 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 6 Mar 2025 07:53:25 -1000 -Subject: fs/pipe: fix pipe buffer index use in FUSE - -From: Linus Torvalds - -[ Upstream commit ebb0f38bb47f74b29e267babdbcd2c47d5292aa8 ] - -This was another case that Rasmus pointed out where the direct access to -the pipe head and tail pointers broke on 32-bit configurations due to -the type changes. - -As with the pipe FIONREAD case, fix it by using the appropriate helper -functions that deal with the right pipe index sizing. - -Reported-by: Rasmus Villemoes -Link: https://lore.kernel.org/all/878qpi5wz4.fsf@prevas.dk/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg > -Cc: Mateusz Guzik -Cc: K Prateek Nayak -Cc: Swapnil Sapkal -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/fuse/dev.c | 13 ++++++------- - 1 file changed, 6 insertions(+), 7 deletions(-) - -diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c -index 8573d79ef29c8..7e4fc2d34869e 100644 ---- a/fs/fuse/dev.c -+++ b/fs/fuse/dev.c -@@ -1966,7 +1966,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - struct file *out, loff_t *ppos, - size_t len, unsigned int flags) - { -- unsigned int head, tail, mask, count; -+ unsigned int head, tail, count; - unsigned nbuf; - unsigned idx; - struct pipe_buffer *bufs; -@@ -1983,8 +1983,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - - head = pipe->head; - tail = pipe->tail; -- mask = pipe->ring_size - 1; -- count = head - tail; -+ count = pipe_occupancy(head, tail); - - bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL); - if (!bufs) { -@@ -1994,8 +1993,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - - nbuf = 0; - rem = 0; -- for (idx = tail; idx != head && rem < len; idx++) -- rem += pipe->bufs[idx & mask].len; -+ for (idx = tail; !pipe_empty(head, idx) && rem < len; idx++) -+ rem += pipe_buf(pipe, idx)->len; - - ret = -EINVAL; - if (rem < len) -@@ -2006,10 +2005,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - struct pipe_buffer *ibuf; - struct pipe_buffer *obuf; - -- if (WARN_ON(nbuf >= count || tail == head)) -+ if (WARN_ON(nbuf >= count || pipe_empty(head, tail))) - goto out_free; - -- ibuf = &pipe->bufs[tail & mask]; -+ ibuf = pipe_buf(pipe, tail); - obuf = &bufs[nbuf]; - - if (rem >= ibuf->len) { --- -2.39.5 - diff --git a/queue-6.6/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch b/queue-6.6/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch deleted file mode 100644 index 06b0479d6e..0000000000 --- a/queue-6.6/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 398c6ca122fcb1cd122f57da18cbd666ad3024da Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 5 Mar 2025 07:08:09 -1000 -Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes - -From: Linus Torvalds - -[ Upstream commit c27c66afc449b80f3b4b84d123358c0248f2cf63 ] - -The pipe_occupancy() logic implicitly relied on the natural unsigned -modulo arithmetic in C, but that doesn't work for the new 'pipe_index_t' -case, since any arithmetic will be done in 'int' (and here we had also -made it 'unsigned int' due to the function call boundary). - -So make the modulo arithmetic explicit by casting the result to the -proper type. - -Cc: Oleg Nesterov -Cc: Mateusz Guzik -Cc: Manfred Spraul -Cc: Christian Brauner -Cc: Swapnil Sapkal -Cc: Alexey Gladkov -Cc: K Prateek Nayak -Link: https://lore.kernel.org/all/CAHk-=wjyHsGLx=rxg6PKYBNkPYAejgo7=CbyL3=HGLZLsAaJFQ@mail.gmail.com/ -Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex") -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - include/linux/pipe_fs_i.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 8bffd8252893e..cf737da29fe22 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -192,7 +192,7 @@ static inline bool pipe_empty(unsigned int head, unsigned int tail) - */ - static inline unsigned int pipe_occupancy(unsigned int head, unsigned int tail) - { -- return head - tail; -+ return (pipe_index_t)(head - tail); - } - - /** --- -2.39.5 - diff --git a/queue-6.6/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch b/queue-6.6/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch deleted file mode 100644 index 3c6f5e2d33..0000000000 --- a/queue-6.6/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 1363fbeddf4b26f460a9804b2d751dc422560597 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 4 Mar 2025 13:51:38 +0000 -Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex - -From: Linus Torvalds - -[ Upstream commit 3d252160b818045f3a152b13756f6f37ca34639d ] - -pipe_readable(), pipe_writable(), and pipe_poll() can read "pipe->head" -and "pipe->tail" outside of "pipe->mutex" critical section. When the -head and the tail are read individually in that order, there is a window -for interruption between the two reads in which both the head and the -tail can be updated by concurrent readers and writers. - -One of the problematic scenarios observed with hackbench running -multiple groups on a large server on a particular pipe inode is as -follows: - - pipe->head = 36 - pipe->tail = 36 - - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wakes up: pipe not full* - hackbench-118762 [057] ..... 1029.550548: pipe_write: head: 36 -> 37 [tail: 36] - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next reader 118740* - hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next writer 118768* - - hackbench-118768 [206] ..... 1029.55055X: pipe_write: *writer wakes up* - hackbench-118768 [206] ..... 1029.55055X: pipe_write: head = READ_ONCE(pipe->head) [37] - ... CPU 206 interrupted (exact wakeup was not traced but 118768 did read head at 37 in traces) - - hackbench-118740 [057] ..... 1029.550558: pipe_read: *reader wakes up: pipe is not empty* - hackbench-118740 [057] ..... 1029.550558: pipe_read: tail: 36 -> 37 [head = 37] - hackbench-118740 [057] ..... 1029.550559: pipe_read: *pipe is empty; wakeup writer 118768* - hackbench-118740 [057] ..... 1029.550559: pipe_read: *sleeps* - - hackbench-118766 [185] ..... 1029.550592: pipe_write: *New writer comes in* - hackbench-118766 [185] ..... 1029.550592: pipe_write: head: 37 -> 38 [tail: 37] - hackbench-118766 [185] ..... 1029.550592: pipe_write: *wakes up reader 118766* - - hackbench-118740 [185] ..... 1029.550598: pipe_read: *reader wakes up; pipe not empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: tail: 37 -> 38 [head: 38] - hackbench-118740 [185] ..... 1029.550599: pipe_read: *pipe is empty* - hackbench-118740 [185] ..... 1029.550599: pipe_read: *reader sleeps; wakeup writer 118768* - - ... CPU 206 switches back to writer - hackbench-118768 [206] ..... 1029.550601: pipe_write: tail = READ_ONCE(pipe->tail) [38] - hackbench-118768 [206] ..... 1029.550601: pipe_write: pipe_full()? (u32)(37 - 38) >= 16? Yes - hackbench-118768 [206] ..... 1029.550601: pipe_write: *writer goes back to sleep* - - [ Tasks 118740 and 118768 can then indefinitely wait on each other. ] - -The unsigned arithmetic in pipe_occupancy() wraps around when -"pipe->tail > pipe->head" leading to pipe_full() returning true despite -the pipe being empty. - -The case of genuine wraparound of "pipe->head" is handled since pipe -buffer has data allowing readers to make progress until the pipe->tail -wraps too after which the reader will wakeup a sleeping writer, however, -mistaking the pipe to be full when it is in fact empty can lead to -readers and writers waiting on each other indefinitely. - -This issue became more problematic and surfaced as a hang in hackbench -after the optimization in commit aaec5a95d596 ("pipe_read: don't wake up -the writer if the pipe is still full") significantly reduced the number -of spurious wakeups of writers that had previously helped mask the -issue. - -To avoid missing any updates between the reads of "pipe->head" and -"pipe->write", unionize the two with a single unsigned long -"pipe->head_tail" member that can be loaded atomically. - -Using "pipe->head_tail" to read the head and the tail ensures the -lockless checks do not miss any updates to the head or the tail and -since those two are only updated under "pipe->mutex", it ensures that -the head is always ahead of, or equal to the tail resulting in correct -calculations. - - [ prateek: commit log, testing on x86 platforms. ] - -Reported-and-debugged-by: Swapnil Sapkal -Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/ -Reported-by: Alexey Gladkov -Closes: https://lore.kernel.org/all/Z8Wn0nTvevLRG_4m@example.org/ -Fixes: 8cefc107ca54 ("pipe: Use head and tail pointers for the ring, not cursor and length") -Tested-by: Swapnil Sapkal -Reviewed-by: Oleg Nesterov -Tested-by: Alexey Gladkov -Signed-off-by: K Prateek Nayak -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - fs/pipe.c | 19 ++++++++----------- - include/linux/pipe_fs_i.h | 39 +++++++++++++++++++++++++++++++++++++-- - 2 files changed, 45 insertions(+), 13 deletions(-) - -diff --git a/fs/pipe.c b/fs/pipe.c -index ba4376341ddd2..d8f7c56d438d7 100644 ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -220,11 +220,10 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_readable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int writers = READ_ONCE(pipe->writers); - -- return !pipe_empty(head, tail) || !writers; -+ return !pipe_empty(idx.head, idx.tail) || !writers; - } - - static ssize_t -@@ -405,11 +404,10 @@ static inline int is_packetized(struct file *file) - /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ - static inline bool pipe_writable(const struct pipe_inode_info *pipe) - { -- unsigned int head = READ_ONCE(pipe->head); -- unsigned int tail = READ_ONCE(pipe->tail); -+ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; - unsigned int max_usage = READ_ONCE(pipe->max_usage); - -- return !pipe_full(head, tail, max_usage) || -+ return !pipe_full(idx.head, idx.tail, max_usage) || - !READ_ONCE(pipe->readers); - } - -@@ -656,7 +654,7 @@ pipe_poll(struct file *filp, poll_table *wait) - { - __poll_t mask; - struct pipe_inode_info *pipe = filp->private_data; -- unsigned int head, tail; -+ union pipe_index idx; - - /* Epoll has some historical nasty semantics, this enables them */ - WRITE_ONCE(pipe->poll_usage, true); -@@ -677,19 +675,18 @@ pipe_poll(struct file *filp, poll_table *wait) - * if something changes and you got it wrong, the poll - * table entry will wake you up and fix it. - */ -- head = READ_ONCE(pipe->head); -- tail = READ_ONCE(pipe->tail); -+ idx.head_tail = READ_ONCE(pipe->head_tail); - - mask = 0; - if (filp->f_mode & FMODE_READ) { -- if (!pipe_empty(head, tail)) -+ if (!pipe_empty(idx.head, idx.tail)) - mask |= EPOLLIN | EPOLLRDNORM; - if (!pipe->writers && filp->f_version != pipe->w_counter) - mask |= EPOLLHUP; - } - - if (filp->f_mode & FMODE_WRITE) { -- if (!pipe_full(head, tail, pipe->max_usage)) -+ if (!pipe_full(idx.head, idx.tail, pipe->max_usage)) - mask |= EPOLLOUT | EPOLLWRNORM; - /* - * Most Unices do not set EPOLLERR for FIFOs but on Linux they -diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h -index 288a8081a9db6..8bffd8252893e 100644 ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -31,6 +31,33 @@ struct pipe_buffer { - unsigned long private; - }; - -+/* -+ * Really only alpha needs 32-bit fields, but -+ * might as well do it for 64-bit architectures -+ * since that's what we've historically done, -+ * and it makes 'head_tail' always be a simple -+ * 'unsigned long'. -+ */ -+#ifdef CONFIG_64BIT -+typedef unsigned int pipe_index_t; -+#else -+typedef unsigned short pipe_index_t; -+#endif -+ -+/* -+ * We have to declare this outside 'struct pipe_inode_info', -+ * but then we can't use 'union pipe_index' for an anonymous -+ * union, so we end up having to duplicate this declaration -+ * below. Annoying. -+ */ -+union pipe_index { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+}; -+ - /** - * struct pipe_inode_info - a linux kernel pipe - * @mutex: mutex protecting the whole thing -@@ -58,8 +85,16 @@ struct pipe_buffer { - struct pipe_inode_info { - struct mutex mutex; - wait_queue_head_t rd_wait, wr_wait; -- unsigned int head; -- unsigned int tail; -+ -+ /* This has to match the 'union pipe_index' above */ -+ union { -+ unsigned long head_tail; -+ struct { -+ pipe_index_t head; -+ pipe_index_t tail; -+ }; -+ }; -+ - unsigned int max_usage; - unsigned int ring_size; - #ifdef CONFIG_WATCH_QUEUE --- -2.39.5 - diff --git a/queue-6.6/series b/queue-6.6/series index 16ee83ea7a..dfd3312a91 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -74,7 +74,6 @@ hwmon-fix-a-null-vs-is_err_or_null-check-in-xgene_hw.patch drm-sched-fix-preprocessor-guard.patch be2net-fix-sleeping-while-atomic-bugs-in-be_ndo_brid.patch net-hns3-make-sure-ptp-clock-is-unregister-and-freed.patch -fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch hid-hid-steam-fix-use-after-free-when-detaching-devi.patch net-ipa-fix-v4.7-resource-group-names.patch net-ipa-fix-qsb-data-for-v4.7.patch @@ -86,13 +85,10 @@ exfat-fix-soft-lockup-in-exfat_clear_bitmap.patch net-timestamp-support-tcp-gso-case-for-a-few-missing.patch ublk-set_params-properly-check-if-parameters-can-be-.patch sched-fair-fix-potential-memory-corruption-in-child_.patch -fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch net-dsa-mt7530-fix-traffic-flooding-for-mmio-devices.patch net-ipv6-fix-dst-ref-loop-in-ila-lwtunnel.patch net-ipv6-fix-missing-dst-ref-drop-in-ila-lwtunnel.patch gpio-rcar-fix-missing-of_node_put-call.patch -fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch -fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch revert-drivers-card_reader-rtsx_usb-restore-interrupt-based-detection.patch usb-renesas_usbhs-call-clk_put.patch usb-renesas_usbhs-use-devm_usb_get_phy.patch