Skip to content

Commit f467a6a

Browse files
committed
pipe: fix and clarify pipe read wakeup logic
This is the read side version of the previous commit: it simplifies the logic to only wake up waiting writers when necessary, and makes sure to use a synchronous wakeup. This time not so much for GNU make jobserver reasons (that pipe never fills up), but simply to get the writer going quickly again. A bit less verbose commentary this time, if only because I assume that the write side commentary isn't going to be ignored if you touch this code. Cc: David Howells <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 1b6b26a commit f467a6a

File tree

1 file changed

+18
-13
lines changed

1 file changed

+18
-13
lines changed

fs/pipe.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -276,16 +276,25 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
276276
size_t total_len = iov_iter_count(to);
277277
struct file *filp = iocb->ki_filp;
278278
struct pipe_inode_info *pipe = filp->private_data;
279-
int do_wakeup;
279+
bool was_full;
280280
ssize_t ret;
281281

282282
/* Null read succeeds. */
283283
if (unlikely(total_len == 0))
284284
return 0;
285285

286-
do_wakeup = 0;
287286
ret = 0;
288287
__pipe_lock(pipe);
288+
289+
/*
290+
* We only wake up writers if the pipe was full when we started
291+
* reading in order to avoid unnecessary wakeups.
292+
*
293+
* But when we do wake up writers, we do so using a sync wakeup
294+
* (WF_SYNC), because we want them to get going and generate more
295+
* data for us.
296+
*/
297+
was_full = pipe_full(pipe->head, pipe->tail, pipe->max_usage);
289298
for (;;) {
290299
unsigned int head = pipe->head;
291300
unsigned int tail = pipe->tail;
@@ -324,19 +333,11 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
324333
}
325334

326335
if (!buf->len) {
327-
bool wake;
328336
pipe_buf_release(pipe, buf);
329337
spin_lock_irq(&pipe->wait.lock);
330338
tail++;
331339
pipe->tail = tail;
332-
do_wakeup = 1;
333-
wake = head - (tail - 1) == pipe->max_usage / 2;
334-
if (wake)
335-
wake_up_locked_poll(
336-
&pipe->wait, EPOLLOUT | EPOLLWRNORM);
337340
spin_unlock_irq(&pipe->wait.lock);
338-
if (wake)
339-
kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
340341
}
341342
total_len -= chars;
342343
if (!total_len)
@@ -365,13 +366,17 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
365366
ret = -ERESTARTSYS;
366367
break;
367368
}
369+
if (was_full) {
370+
wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM);
371+
kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
372+
}
368373
pipe_wait(pipe);
374+
was_full = pipe_full(pipe->head, pipe->tail, pipe->max_usage);
369375
}
370376
__pipe_unlock(pipe);
371377

372-
/* Signal writers asynchronously that there is more room. */
373-
if (do_wakeup) {
374-
wake_up_interruptible_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM);
378+
if (was_full) {
379+
wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM);
375380
kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
376381
}
377382
if (ret > 0)

0 commit comments

Comments
 (0)