diff mbox series

[1/3] pipe: drop an always true check in anon_pipe_write()

Message ID 20250303230409.452687-2-mjguzik@gmail.com (mailing list archive)
State New
Headers show
Series some pipe + wait stuff | expand

Commit Message

Mateusz Guzik March 3, 2025, 11:04 p.m. UTC
The check operates on the stale value of 'head' and always loops back.

Just do it unconditionally. No functional changes.

Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
---
 fs/pipe.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

Comments

Oleg Nesterov March 4, 2025, 2:07 p.m. UTC | #1
On 03/04, Mateusz Guzik wrote:
>
> @@ -529,10 +529,9 @@ anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
>  
>  			if (!iov_iter_count(from))
>  				break;
> -		}
>  
> -		if (!pipe_full(head, pipe->tail, pipe->max_usage))
>  			continue;
> +		}

Reviewed-by: Oleg Nesterov <oleg@redhat.com>



It seems that we can also remove the unnecessary signal_pending()
check, but I need to recheck and we need to cleanup the poll_usage
logic first.

This will also remove the unnecessary wakeups when the writer is
interrupted by signal/

diff --git a/fs/pipe.c b/fs/pipe.c
index b0641f75b1ba..ed55a86ca03b 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -541,12 +541,6 @@ anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
 				ret = -EAGAIN;
 			break;
 		}
-		if (signal_pending(current)) {
-			if (!ret)
-				ret = -ERESTARTSYS;
-			break;
-		}
-
 		/*
 		 * We're going to release the pipe lock and wait for more
 		 * space. We wake up any readers if necessary, and then
@@ -554,10 +548,11 @@ anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
 		 * become empty while we dropped the lock.
 		 */
 		mutex_unlock(&pipe->mutex);
-		if (was_empty)
+		if (was_empty || pipe->poll_usage)
 			wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM);
 		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
-		wait_event_interruptible_exclusive(pipe->wr_wait, pipe_writable(pipe));
+		if (wait_event_interruptible_exclusive(pipe->wr_wait, pipe_writable(pipe)) < 0)
+			return ret ?: -ERESTARTSYS;
 		mutex_lock(&pipe->mutex);
 		was_empty = pipe_empty(pipe->head, pipe->tail);
 		wake_next_writer = true;
Mateusz Guzik March 4, 2025, 2:58 p.m. UTC | #2
On Tue, Mar 4, 2025 at 3:08 PM Oleg Nesterov <oleg@redhat.com> wrote:
>
> On 03/04, Mateusz Guzik wrote:
> >
> > @@ -529,10 +529,9 @@ anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
> >
> >                       if (!iov_iter_count(from))
> >                               break;
> > -             }
> >
> > -             if (!pipe_full(head, pipe->tail, pipe->max_usage))
> >                       continue;
> > +             }
>
> Reviewed-by: Oleg Nesterov <oleg@redhat.com>
>

thanks

> It seems that we can also remove the unnecessary signal_pending()
> check, but I need to recheck and we need to cleanup the poll_usage
> logic first.
>
> This will also remove the unnecessary wakeups when the writer is
> interrupted by signal/
>
[snip]

There are many touch ups to do here, I don't have an opinion about this diff.

I don't have compiled stats handy, but few months back I asked some
people to query pipe writes with dtrace on FreeBSD. Everything is very
heavily skewed towards < 128 bytes in total, including tons of 1 bytes
(and no, it's not just make). However, there is also quite a bit of
absolutely massive multipage ops as well -- north of  64K even. Doing
that kind of op in one go is way faster than restarting rep mov every
time interleaved with SMAP toggling, which is expensive in its own
right.

Thus I would argue someone(tm) should do it in Linux, but I don't have
immediate plans. Perhaps you would be happy to do it? :)

In the meantime, I would hope any refactoring in the area would make
the above easier (my patch does, I'm not claiming your does not :P)
Oleg Nesterov March 4, 2025, 3:18 p.m. UTC | #3
On 03/04, Mateusz Guzik wrote:
>
> On Tue, Mar 4, 2025 at 3:08 PM Oleg Nesterov <oleg@redhat.com> wrote:
> >
> > It seems that we can also remove the unnecessary signal_pending()
> > check, but I need to recheck and we need to cleanup the poll_usage
> > logic first.
> >
> > This will also remove the unnecessary wakeups when the writer is
> > interrupted by signal/
> >
>
> There are many touch ups to do here, I don't have an opinion about this diff.

...

> Thus I would argue someone(tm) should do it in Linux, but I don't have
> immediate plans. Perhaps you would be happy to do it? :)

Probably. In any case this needs a separate patch, sorry for confusion.

Oleg.
diff mbox series

Patch

diff --git a/fs/pipe.c b/fs/pipe.c
index 19a7948ab234..d5238f6e0f08 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -529,10 +529,9 @@  anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
 
 			if (!iov_iter_count(from))
 				break;
-		}
 
-		if (!pipe_full(head, pipe->tail, pipe->max_usage))
 			continue;
+		}
 
 		/* Wait for buffer space to become available. */
 		if ((filp->f_flags & O_NONBLOCK) ||