All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleg Nesterov <oleg@redhat.com>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: WangYuli <wangyuli@uniontech.com>,
	linux-fsdevel <linux-fsdevel@vger.kernel.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Christian Brauner <brauner@kernel.org>
Subject: Re: [RESEND PATCH] fs/pipe: Introduce a check to skip sleeping processes during pipe read/write
Date: Fri, 27 Dec 2024 17:43:48 +0100	[thread overview]
Message-ID: <20241227164348.GB15300@redhat.com> (raw)
In-Reply-To: <20241227155428.GA15300@redhat.com>

On 12/27, Oleg Nesterov wrote:
>
> Consider
>
> 	int main(void)
> 	{
> 		int fd[2], cnt;
> 		char c;
>
> 		pipe(fd);
>
> 		if (!fork()) {
> 			// wait until the parent blocks in pipe_write() ->
> 			// wait_event_interruptible_exclusive(pipe->wr_wait, pipe_writable(pipe));
> 			sleep(1);
>
> 			for (cnt = 0; cnt < 4096; ++cnt)
> 				read(fd[0], &c, 1);
> 			return 0;
> 		}
>
> 		// parent
> 		for (;;)
> 			write(fd[1], &c, 1);
> 	}
>
> In this case the child will wakeup the parent 4095 times for no reason,
> pipe_writable() == !pipe_pull() will still be true until the last
> read(fd[0], &c, 1) does
>
> 	if (!buf->len)
> 		tail = pipe_update_tail(pipe, buf, tail);
>
> and after that the parent can write the next char.

perhaps something like below makes sense in this particular case.
Incomplete and ugly, just for illustration.

Oleg.

diff --git a/fs/pipe.c b/fs/pipe.c
index 12b22c2723b7..b8eef9e75639 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -253,7 +253,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
 	size_t total_len = iov_iter_count(to);
 	struct file *filp = iocb->ki_filp;
 	struct pipe_inode_info *pipe = filp->private_data;
-	bool was_full, wake_next_reader = false;
+	bool was_full, xxx, wake_next_reader = false;
 	ssize_t ret;
 
 	/* Null read succeeds. */
@@ -277,6 +277,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
 		unsigned int head = smp_load_acquire(&pipe->head);
 		unsigned int tail = pipe->tail;
 		unsigned int mask = pipe->ring_size - 1;
+		xxx = false;
 
 #ifdef CONFIG_WATCH_QUEUE
 		if (pipe->note_loss) {
@@ -340,8 +341,10 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
 				buf->len = 0;
 			}
 
-			if (!buf->len)
+			if (!buf->len) {
 				tail = pipe_update_tail(pipe, buf, tail);
+				xxx = true;
+			}
 			total_len -= chars;
 			if (!total_len)
 				break;	/* common path: read succeeded */
@@ -398,7 +401,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
 		wake_next_reader = false;
 	mutex_unlock(&pipe->mutex);
 
-	if (was_full)
+	if (was_full && xxx)
 		wake_up_interruptible_sync_poll(&pipe->wr_wait, EPOLLOUT | EPOLLWRNORM);
 	if (wake_next_reader)
 		wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM);


  reply	other threads:[~2024-12-27 16:44 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-25  9:42 [RESEND PATCH] fs/pipe: Introduce a check to skip sleeping processes during pipe read/write WangYuli
2024-12-25 13:30 ` Andy Shevchenko
2024-12-25 13:53   ` Kent Overstreet
2024-12-25 16:04     ` Mateusz Guzik
2024-12-25 16:32       ` Kent Overstreet
2024-12-25 17:22         ` Mateusz Guzik
2024-12-25 17:41           ` Kent Overstreet
2024-12-25 15:42   ` WangYuli
2024-12-25 16:00     ` Willy Tarreau
2024-12-25 16:32       ` WangYuli
2024-12-25 16:56         ` Willy Tarreau
2024-12-26 16:00 ` Oleg Nesterov
2024-12-26 19:02 ` Linus Torvalds
2024-12-26 20:11   ` Oleg Nesterov
2024-12-26 20:29     ` Linus Torvalds
2024-12-26 20:57       ` Oleg Nesterov
2024-12-27 15:54         ` Oleg Nesterov
2024-12-27 16:43           ` Oleg Nesterov [this message]
2024-12-27 18:39     ` Manfred Spraul
2024-12-28 14:32       ` Oleg Nesterov
2024-12-28 15:22         ` Oleg Nesterov
2024-12-28 16:32           ` Oleg Nesterov
2024-12-28 18:53             ` Manfred Spraul
2024-12-29 11:54               ` Oleg Nesterov
2024-12-28 16:45           ` Manfred Spraul
2024-12-29 11:57             ` Oleg Nesterov
2024-12-29 12:41               ` Manfred Spraul
2024-12-29 13:05                 ` Oleg Nesterov
2024-12-29 13:13                   ` Oleg Nesterov
2024-12-29 19:54                     ` Manfred Spraul
2024-12-30 15:38                       ` Oleg Nesterov
2024-12-31 11:14                         ` Manfred Spraul
2024-12-31 19:38                           ` Linus Torvalds
2024-12-31 20:24                             ` Oleg Nesterov
2024-12-31 22:31                               ` Linus Torvalds
2025-01-02 13:57                                 ` Oleg Nesterov
2025-01-04 21:15                         ` RFC: Checkpatch: Introduce list of functions that need memory barriers Manfred Spraul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241227164348.GB15300@redhat.com \
    --to=oleg@redhat.com \
    --cc=brauner@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=wangyuli@uniontech.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.