Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <dhowells@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+18 -13
+18 -13
fs/pipe.c
··· 276 276 size_t total_len = iov_iter_count(to); 277 277 struct file *filp = iocb->ki_filp; 278 278 struct pipe_inode_info *pipe = filp->private_data; 279 - int do_wakeup; 279 + bool was_full; 280 280 ssize_t ret; 281 281 282 282 /* Null read succeeds. */ 283 283 if (unlikely(total_len == 0)) 284 284 return 0; 285 285 286 - do_wakeup = 0; 287 286 ret = 0; 288 287 __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); 289 298 for (;;) { 290 299 unsigned int head = pipe->head; 291 300 unsigned int tail = pipe->tail; ··· 333 324 } 334 325 335 326 if (!buf->len) { 336 - bool wake; 337 327 pipe_buf_release(pipe, buf); 338 328 spin_lock_irq(&pipe->wait.lock); 339 329 tail++; 340 330 pipe->tail = tail; 341 - do_wakeup = 1; 342 - wake = head - (tail - 1) == pipe->max_usage / 2; 343 - if (wake) 344 - wake_up_locked_poll( 345 - &pipe->wait, EPOLLOUT | EPOLLWRNORM); 346 331 spin_unlock_irq(&pipe->wait.lock); 347 - if (wake) 348 - kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); 349 332 } 350 333 total_len -= chars; 351 334 if (!total_len) ··· 366 365 ret = -ERESTARTSYS; 367 366 break; 368 367 } 368 + if (was_full) { 369 + wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM); 370 + kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); 371 + } 369 372 pipe_wait(pipe); 373 + was_full = pipe_full(pipe->head, pipe->tail, pipe->max_usage); 370 374 } 371 375 __pipe_unlock(pipe); 372 376 373 - /* Signal writers asynchronously that there is more room. */ 374 - if (do_wakeup) { 375 - wake_up_interruptible_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM); 377 + if (was_full) { 378 + wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM); 376 379 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); 377 380 } 378 381 if (ret > 0)