Advance the pipe ring tail pointer inside of wait spinlock in pipe_read()
so that the pipe can be written into with kernel notifications from
contexts where pipe->mutex cannot be taken.

Signed-off-by: David Howells <dhowe...@redhat.com>
---

 fs/pipe.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/fs/pipe.c b/fs/pipe.c
index 0574277bad18..08af7e7bbea2 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -324,9 +324,14 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
 
                        if (!buf->len) {
                                pipe_buf_release(pipe, buf);
+                               spin_lock_irq(&pipe->wait.lock);
                                tail++;
                                pipe_commit_read(pipe, tail);
-                               do_wakeup = 1;
+                               do_wakeup = 0;
+                               prelocked_wake_up_interruptible_sync_poll(
+                                       &pipe->wait, EPOLLOUT | EPOLLWRNORM);
+                               spin_unlock_irq(&pipe->wait.lock);
+                               kill_fasync(&pipe->fasync_writers, SIGIO, 
POLL_OUT);
                        }
                        total_len -= chars;
                        if (!total_len)
@@ -358,6 +363,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
                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);
        }

Reply via email to