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: don't use 'pipe_wait() for basic pipe IO

pipe_wait() may be simple, but since it relies on the pipe lock, it
means that we have to do the wakeup while holding the lock. That's
unfortunate, because the very first thing the waked entity will want to
do is to get the pipe lock for itself.

So get rid of the pipe_wait() usage by simply releasing the pipe lock,
doing the wakeup (if required) and then using wait_event_interruptible()
to wait on the right condition instead.

wait_event_interruptible() handles races on its own by comparing the
wakeup condition before and after adding itself to the wait queue, so
you can use an optimistic unlocked condition for it.

Cc: David Howells <dhowells@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+27 -3
+27 -3
fs/pipe.c
··· 270 270 return buf->ops == &anon_pipe_buf_ops; 271 271 } 272 272 273 + /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ 274 + static inline bool pipe_readable(const struct pipe_inode_info *pipe) 275 + { 276 + unsigned int head = READ_ONCE(pipe->head); 277 + unsigned int tail = READ_ONCE(pipe->tail); 278 + unsigned int writers = READ_ONCE(pipe->writers); 279 + 280 + return !pipe_empty(head, tail) || !writers; 281 + } 282 + 273 283 static ssize_t 274 284 pipe_read(struct kiocb *iocb, struct iov_iter *to) 275 285 { ··· 369 359 ret = -ERESTARTSYS; 370 360 break; 371 361 } 362 + __pipe_unlock(pipe); 372 363 if (was_full) { 373 364 wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM); 374 365 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); 375 366 } 376 - pipe_wait(pipe); 367 + wait_event_interruptible(pipe->wait, pipe_readable(pipe)); 368 + __pipe_lock(pipe); 377 369 was_full = pipe_full(pipe->head, pipe->tail, pipe->max_usage); 378 370 } 379 371 __pipe_unlock(pipe); ··· 392 380 static inline int is_packetized(struct file *file) 393 381 { 394 382 return (file->f_flags & O_DIRECT) != 0; 383 + } 384 + 385 + /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ 386 + static inline bool pipe_writable(const struct pipe_inode_info *pipe) 387 + { 388 + unsigned int head = READ_ONCE(pipe->head); 389 + unsigned int tail = READ_ONCE(pipe->tail); 390 + unsigned int max_usage = READ_ONCE(pipe->max_usage); 391 + 392 + return !pipe_full(head, tail, max_usage) || 393 + !READ_ONCE(pipe->readers); 395 394 } 396 395 397 396 static ssize_t ··· 552 529 * after waiting we need to re-check whether the pipe 553 530 * become empty while we dropped the lock. 554 531 */ 532 + __pipe_unlock(pipe); 555 533 if (was_empty) { 556 534 wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLRDNORM); 557 535 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); 558 536 } 559 - pipe_wait(pipe); 560 - 537 + wait_event_interruptible(pipe->wait, pipe_writable(pipe)); 538 + __pipe_lock(pipe); 561 539 was_empty = pipe_empty(head, pipe->tail); 562 540 } 563 541 out: