]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fs/pipe: do not open-code pipe head/tail logic in FIONREAD
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 6 Mar 2025 17:33:58 +0000 (07:33 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 6 Mar 2025 17:33:58 +0000 (07:33 -1000)
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>
fs/pipe.c

index e8e6698f3698105b80ce017166a4440a30ae8272..5c872775a6db95087153faa41e3e3cfcd32411c3 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -614,7 +614,7 @@ out:
 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:
@@ -622,10 +622,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);