pipe: Conditionalise wakeup in pipe_read()
authorDavid Howells <dhowells@redhat.com>
Tue, 24 Sep 2019 15:07:04 +0000 (16:07 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 15 Nov 2019 16:22:54 +0000 (16:22 +0000)
Only do a wakeup in pipe_read() if we made space in a completely full
buffer.  The producer shouldn't be waiting on pipe->wait otherwise.

Signed-off-by: David Howells <dhowells@redhat.com>
fs/pipe.c

index ea134f6..c16950e 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -328,11 +328,13 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
                                spin_lock_irq(&pipe->wait.lock);
                                tail++;
                                pipe->tail = tail;
-                               do_wakeup = 0;
-                               wake_up_interruptible_sync_poll_locked(
-                                       &pipe->wait, EPOLLOUT | EPOLLWRNORM);
+                               do_wakeup = 1;
+                               if (head - (tail - 1) == pipe->max_usage)
+                                       wake_up_interruptible_sync_poll_locked(
+                                               &pipe->wait, EPOLLOUT | EPOLLWRNORM);
                                spin_unlock_irq(&pipe->wait.lock);
-                               kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
+                               if (head - (tail - 1) == pipe->max_usage)
+                                       kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
                        }
                        total_len -= chars;
                        if (!total_len)
@@ -361,11 +363,6 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
                                ret = -ERESTARTSYS;
                        break;
                }
-               if (do_wakeup) {
-                       wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM);
-                       kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
-                       do_wakeup = 0;
-               }
                pipe_wait(pipe);
        }
        __pipe_unlock(pipe);