+++ /dev/null
-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
-
+++ /dev/null
-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
-
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
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
+++ /dev/null
-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
-
+++ /dev/null
-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
-
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
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
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
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
+++ /dev/null
-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
-
+++ /dev/null
-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
-
+++ /dev/null
-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
-
+++ /dev/null
-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
-
+++ /dev/null
-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
-
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
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
+++ /dev/null
-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
-
+++ /dev/null
-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
-
+++ /dev/null
-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
-
+++ /dev/null
-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
-
+++ /dev/null
-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
-
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
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
+++ /dev/null
-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
-
+++ /dev/null
-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
-
+++ /dev/null
-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
-
+++ /dev/null
-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
-
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
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
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
+++ /dev/null
-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
-
+++ /dev/null
-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
-
+++ /dev/null
-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
-
+++ /dev/null
-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
-
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
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