From afed6271f5b0d78ca1a3739c1da4aa3629b26bba Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 7 Mar 2023 17:56:28 -0700 Subject: pipe: set FMODE_NOWAIT on pipes Pipes themselves do not hold the the pipe lock across IO, and hence are safe for RWF_NOWAIT/IOCB_NOWAIT usage. The "contract" for NOWAIT is really "should not do IO under this lock", not strictly that we cannot block or that the below code is in any way atomic. Pipes fulfil that criteria. Acked-by: Dave Chinner Reviewed-by: Christian Brauner Signed-off-by: Jens Axboe --- fs/pipe.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/pipe.c') diff --git a/fs/pipe.c b/fs/pipe.c index 42c7ff41c2db..ceb17d2dfa19 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -976,6 +976,9 @@ static int __do_pipe_flags(int *fd, struct file **files, int flags) audit_fd_pair(fdr, fdw); fd[0] = fdr; fd[1] = fdw; + /* pipe groks IOCB_NOWAIT */ + files[0]->f_mode |= FMODE_NOWAIT; + files[1]->f_mode |= FMODE_NOWAIT; return 0; err_fdr: -- cgit v1.2.3 From c04fe8e32f907ea668f3f802387c1148fdb0e6c9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 9 May 2023 09:12:24 -0600 Subject: pipe: check for IOCB_NOWAIT alongside O_NONBLOCK Pipe reads or writes need to enable nonblocking attempts, if either O_NONBLOCK is set on the file, or IOCB_NOWAIT is set in the iocb being passed in. The latter isn't currently true, ensure we check for both before waiting on data or space. Fixes: afed6271f5b0 ("pipe: set FMODE_NOWAIT on pipes") Signed-off-by: Jens Axboe Message-Id: Signed-off-by: Christian Brauner --- fs/pipe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs/pipe.c') diff --git a/fs/pipe.c b/fs/pipe.c index ceb17d2dfa19..2d88f73f585a 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -342,7 +342,8 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to) break; if (ret) break; - if (filp->f_flags & O_NONBLOCK) { + if ((filp->f_flags & O_NONBLOCK) || + (iocb->ki_flags & IOCB_NOWAIT)) { ret = -EAGAIN; break; } @@ -547,7 +548,8 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) continue; /* Wait for buffer space to become available. */ - if (filp->f_flags & O_NONBLOCK) { + if ((filp->f_flags & O_NONBLOCK) || + (iocb->ki_flags & IOCB_NOWAIT)) { if (!ret) ret = -EAGAIN; break; -- cgit v1.2.3