summaryrefslogtreecommitdiffstats
path: root/fs/pipe.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-12-07 22:21:01 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2019-12-07 22:21:01 +0100
commita28c8b9db8a1014aa572cd19a3bdb9ddebd3e555 (patch)
tree4f6d8476972bb9b493267df6d0ae021b81519c15 /fs/pipe.c
parentpipe: fix and clarify pipe read wakeup logic (diff)
downloadlinux-a28c8b9db8a1014aa572cd19a3bdb9ddebd3e555.tar.xz
linux-a28c8b9db8a1014aa572cd19a3bdb9ddebd3e555.zip
pipe: remove 'waiting_writers' merging logic
This code is ancient, and goes back to when we only had a single page for the pipe buffers. The exact history is hidden in the mists of time (ie "before git", and in fact predates the BK repository too). At that long-ago point in time, it actually helped to try to merge big back-and-forth pipe reads and writes, and not limit pipe reads to the single pipe buffer in length just because that was all we had at a time. However, since then we've expanded the pipe buffers to multiple pages, and this logic really doesn't seem to make sense. And a lot of it is somewhat questionable (ie "hmm, the user asked for a non-blocking read, but we see that there's a writer pending, so let's wait anyway to get the extra data that the writer will have"). But more importantly, it makes the "go to sleep" logic much less obvious, and considering the wakeup issues we've had, I want to make for less of those kinds of things. Cc: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/pipe.c')
-rw-r--r--fs/pipe.c19
1 files changed, 5 insertions, 14 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index bcc2192d33e2..58f236c65bea 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -348,18 +348,11 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
if (!pipe->writers)
break;
- if (!pipe->waiting_writers) {
- /* syscall merging: Usually we must not sleep
- * if O_NONBLOCK is set, or if we got some data.
- * But if a writer sleeps in kernel space, then
- * we can wait for that data without violating POSIX.
- */
- if (ret)
- break;
- if (filp->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- break;
- }
+ if (ret)
+ break;
+ if (filp->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
}
if (signal_pending(current)) {
if (!ret)
@@ -540,9 +533,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLRDNORM);
kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
}
- pipe->waiting_writers++;
pipe_wait(pipe);
- pipe->waiting_writers--;
was_empty = pipe_empty(head, pipe->tail);
}