]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
drop some pipe patches from all queues on request of Linus
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 Mar 2025 08:00:07 +0000 (09:00 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 Mar 2025 08:00:07 +0000 (09:00 +0100)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
29 files changed:
queue-5.10/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch [deleted file]
queue-5.10/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch [deleted file]
queue-5.10/series
queue-5.15/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch [deleted file]
queue-5.15/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch [deleted file]
queue-5.15/series
queue-5.4/series
queue-6.1/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch [deleted file]
queue-6.1/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch [deleted file]
queue-6.1/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch [deleted file]
queue-6.1/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch [deleted file]
queue-6.1/mm-pass-info-not-iter-into-filemap_get_pages.patch [deleted file]
queue-6.1/series
queue-6.1/splice-add-a-func-to-do-a-splice-from-a-buffered-fil.patch [deleted file]
queue-6.12/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch [deleted file]
queue-6.12/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch [deleted file]
queue-6.12/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch [deleted file]
queue-6.12/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch [deleted file]
queue-6.12/series
queue-6.13/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch [deleted file]
queue-6.13/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch [deleted file]
queue-6.13/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch [deleted file]
queue-6.13/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch [deleted file]
queue-6.13/series
queue-6.6/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch [deleted file]
queue-6.6/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch [deleted file]
queue-6.6/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch [deleted file]
queue-6.6/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch [deleted file]
queue-6.6/series

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 (file)
index 6b961f3..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 1e3d5c9dfd02647e6dec86789c1c2e23d459a8a0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 5 Mar 2025 07:08:09 -1000
-Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <oleg@redhat.com>
-Cc: Mateusz Guzik <mjguzik@gmail.com>
-Cc: Manfred Spraul <manfred@colorfullife.com>
-Cc: Christian Brauner <brauner@kernel.org>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Cc: Alexey Gladkov <legion@kernel.org>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-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 <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index 7fc9c04..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-From 503fc027723ba35ccd56120915e6f88207c3a476 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Mar 2025 13:51:38 +0000
-Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <swapnil.sapkal@amd.com>
-Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/
-Reported-by: Alexey Gladkov <legion@kernel.org>
-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 <swapnil.sapkal@amd.com>
-Reviewed-by: Oleg Nesterov <oleg@redhat.com>
-Tested-by: Alexey Gladkov <legion@kernel.org>
-Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
index a064ec6374ca7a6998f8cca9cfd1631df78924a6..ffd53963b1571b7cf8477c9f36cb89901b41eb41 100644 (file)
@@ -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 (file)
index acfec84..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From e9234c3542228648bf1fdf47a6bff495df16f2a5 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 5 Mar 2025 07:08:09 -1000
-Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <oleg@redhat.com>
-Cc: Mateusz Guzik <mjguzik@gmail.com>
-Cc: Manfred Spraul <manfred@colorfullife.com>
-Cc: Christian Brauner <brauner@kernel.org>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Cc: Alexey Gladkov <legion@kernel.org>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-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 <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index 36c4374..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-From 4185dc99e91acd9f005ab5a0e68490f4b0eee0da Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Mar 2025 13:51:38 +0000
-Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <swapnil.sapkal@amd.com>
-Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/
-Reported-by: Alexey Gladkov <legion@kernel.org>
-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 <swapnil.sapkal@amd.com>
-Reviewed-by: Oleg Nesterov <oleg@redhat.com>
-Tested-by: Alexey Gladkov <legion@kernel.org>
-Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
index 229f5bc4c066f3a9c7b948710d119aece742d3d2..2cb44500b623593608aa85d916e2c11a4f6f6e42 100644 (file)
@@ -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
index 3982c831718da6f37978f6a4241f5e15167f553f..645f6b0fc986cc09e51e029f400cbb6537491015 100644 (file)
@@ -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 (file)
index 8316d13..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-From 6edd967c49cb625da20260c0598c07268495e6e4 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-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 <torvalds@linux-foundation.org>
-
-[ 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 <ravi@prevas.dk>
-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 <oleg@redhat.com>
-Cc: Mateusz Guzik <mjguzik@gmail.com>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index 72ce532..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-From e8aa712c6c159d7d8973c71684b35381c5753dca Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 6 Mar 2025 07:53:25 -1000
-Subject: fs/pipe: fix pipe buffer index use in FUSE
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <ravi@prevas.dk>
-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 <mjguzik@gmail.com>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index 1f3ffc0..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 2b95e27376134413c4b8b93820c41239d328dc43 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 5 Mar 2025 07:08:09 -1000
-Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <oleg@redhat.com>
-Cc: Mateusz Guzik <mjguzik@gmail.com>
-Cc: Manfred Spraul <manfred@colorfullife.com>
-Cc: Christian Brauner <brauner@kernel.org>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Cc: Alexey Gladkov <legion@kernel.org>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-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 <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index 11dba01..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-From 3c72aff3fa022e1353f317772908d05a5695fdc7 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Mar 2025 13:51:38 +0000
-Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <swapnil.sapkal@amd.com>
-Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/
-Reported-by: Alexey Gladkov <legion@kernel.org>
-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 <swapnil.sapkal@amd.com>
-Reviewed-by: Oleg Nesterov <oleg@redhat.com>
-Tested-by: Alexey Gladkov <legion@kernel.org>
-Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index 563f3ad..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-From 9915cc269582726b40edced5c3024243c6118ced Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 8 Feb 2023 18:18:17 +0000
-Subject: mm: Pass info, not iter, into filemap_get_pages()
-
-From: David Howells <dhowells@redhat.com>
-
-[ 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 <dhowells@redhat.com>
-Reviewed-by: Christoph Hellwig <hch@lst.de>
-Reviewed-by: Jens Axboe <axboe@kernel.dk>
-cc: Christoph Hellwig <hch@lst.de>
-cc: Matthew Wilcox <willy@infradead.org>
-cc: Al Viro <viro@zeniv.linux.org.uk>
-cc: David Hildenbrand <david@redhat.com>
-cc: John Hubbard <jhubbard@nvidia.com>
-cc: linux-mm@kvack.org
-cc: linux-block@vger.kernel.org
-cc: linux-fsdevel@vger.kernel.org
-Signed-off-by: Steve French <stfrench@microsoft.com>
-Stable-dep-of: d810d4c27bf3 ("fs/pipe: do not open-code pipe head/tail logic in FIONREAD")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
index 79177c491557f5d7f21f6764f4c45e7e8f525ef0..e96115b91a50e0cc731d920b002ea41494d74155 100644 (file)
@@ -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 (file)
index 3cc168b..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-From 3a1796e9eecebb93a9e2b6cb7112a480f36ed913 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-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 <dhowells@redhat.com>
-
-[ 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 <dhowells@redhat.com>
-Reviewed-by: Jens Axboe <axboe@kernel.dk>
-cc: Christoph Hellwig <hch@lst.de>
-cc: Al Viro <viro@zeniv.linux.org.uk>
-cc: David Hildenbrand <david@redhat.com>
-cc: John Hubbard <jhubbard@nvidia.com>
-cc: linux-mm@kvack.org
-cc: linux-block@vger.kernel.org
-cc: linux-fsdevel@vger.kernel.org
-Signed-off-by: Steve French <stfrench@microsoft.com>
-Stable-dep-of: d810d4c27bf3 ("fs/pipe: do not open-code pipe head/tail logic in FIONREAD")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 <linux/ramfs.h>
- #include <linux/page_idle.h>
- #include <linux/migrate.h>
-+#include <linux/pipe_fs_i.h>
-+#include <linux/splice.h>
- #include <asm/pgalloc.h>
- #include <asm/tlbflush.h>
- #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 (file)
index 2b7ac75..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-From d74248a89b27d81cc2450c139b019719895ccdc7 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-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 <torvalds@linux-foundation.org>
-
-[ 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 <ravi@prevas.dk>
-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 <oleg@redhat.com>
-Cc: Mateusz Guzik <mjguzik@gmail.com>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index 684c5fe..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-From bb3b60e2c921cb253f99be3580bc23af9e5dc2f1 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 6 Mar 2025 07:53:25 -1000
-Subject: fs/pipe: fix pipe buffer index use in FUSE
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <ravi@prevas.dk>
-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 <mjguzik@gmail.com>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index 76429c0..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 60e10eb27fe5399c6173c917c1b9dda3f2f96333 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 5 Mar 2025 07:08:09 -1000
-Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <oleg@redhat.com>
-Cc: Mateusz Guzik <mjguzik@gmail.com>
-Cc: Manfred Spraul <manfred@colorfullife.com>
-Cc: Christian Brauner <brauner@kernel.org>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Cc: Alexey Gladkov <legion@kernel.org>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-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 <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index b1e9380..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-From 72fecd3b278bbe1df4a004b5dd5b8c721b2a4183 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Mar 2025 13:51:38 +0000
-Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <swapnil.sapkal@amd.com>
-Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/
-Reported-by: Alexey Gladkov <legion@kernel.org>
-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 <swapnil.sapkal@amd.com>
-Reviewed-by: Oleg Nesterov <oleg@redhat.com>
-Tested-by: Alexey Gladkov <legion@kernel.org>
-Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
index 70955c32445943f3166748739ad802fdd1c6db41..ab5b246748bb31cdc8cae80bd52285cf144c975a 100644 (file)
@@ -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 (file)
index 4440670..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-From cff7aa72cf4bb6ff5928f8534d705827ec42b140 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-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 <torvalds@linux-foundation.org>
-
-[ 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 <ravi@prevas.dk>
-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 <oleg@redhat.com>
-Cc: Mateusz Guzik <mjguzik@gmail.com>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index d67dbe3..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-From 097ef18912b9dcbefd6ee19bb430f8f2f3832fde Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 6 Mar 2025 07:53:25 -1000
-Subject: fs/pipe: fix pipe buffer index use in FUSE
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <ravi@prevas.dk>
-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 <mjguzik@gmail.com>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index a9ffd78..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From f0472863c6ef82537b45b7056dd15b42f505097e Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 5 Mar 2025 07:08:09 -1000
-Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <oleg@redhat.com>
-Cc: Mateusz Guzik <mjguzik@gmail.com>
-Cc: Manfred Spraul <manfred@colorfullife.com>
-Cc: Christian Brauner <brauner@kernel.org>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Cc: Alexey Gladkov <legion@kernel.org>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-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 <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index d5b5e9b..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-From 2fa9bc4a929953d776783b960bbbd9b78efed1c0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Mar 2025 13:51:38 +0000
-Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <swapnil.sapkal@amd.com>
-Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/
-Reported-by: Alexey Gladkov <legion@kernel.org>
-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 <swapnil.sapkal@amd.com>
-Reviewed-by: Oleg Nesterov <oleg@redhat.com>
-Tested-by: Alexey Gladkov <legion@kernel.org>
-Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
index 0538077979b70579fce968e3ce1ea7107b72a61f..548d2b71c5ed089b5d95430158c43bfd5d681b3f 100644 (file)
@@ -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 (file)
index aec9749..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-From 1ee8e42441a3a9ae2524d1d90d97a41660f68929 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-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 <torvalds@linux-foundation.org>
-
-[ 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 <ravi@prevas.dk>
-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 <oleg@redhat.com>
-Cc: Mateusz Guzik <mjguzik@gmail.com>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index c9ced6c..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-From 774cf4428e383acaa210f4d7c3ed3ce5dad204d1 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 6 Mar 2025 07:53:25 -1000
-Subject: fs/pipe: fix pipe buffer index use in FUSE
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <ravi@prevas.dk>
-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 <mjguzik@gmail.com>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index 06b0479..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 398c6ca122fcb1cd122f57da18cbd666ad3024da Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 5 Mar 2025 07:08:09 -1000
-Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <oleg@redhat.com>
-Cc: Mateusz Guzik <mjguzik@gmail.com>
-Cc: Manfred Spraul <manfred@colorfullife.com>
-Cc: Christian Brauner <brauner@kernel.org>
-Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
-Cc: Alexey Gladkov <legion@kernel.org>
-Cc: K Prateek Nayak <kprateek.nayak@amd.com>
-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 <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 (file)
index 3c6f5e2..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-From 1363fbeddf4b26f460a9804b2d751dc422560597 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Mar 2025 13:51:38 +0000
-Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex
-
-From: Linus Torvalds <torvalds@linux-foundation.org>
-
-[ 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 <swapnil.sapkal@amd.com>
-Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/
-Reported-by: Alexey Gladkov <legion@kernel.org>
-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 <swapnil.sapkal@amd.com>
-Reviewed-by: Oleg Nesterov <oleg@redhat.com>
-Tested-by: Alexey Gladkov <legion@kernel.org>
-Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
index 16ee83ea7a2812aff3c564841ed5aee8b0187f7e..dfd3312a91d89e61467b5b412864d7d13da604c2 100644 (file)
@@ -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