linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* When to lock pipe->rd_wait.lock?
@ 2023-09-20 12:34 Max Kellermann
  2023-09-20 13:30 ` Christian Brauner
  0 siblings, 1 reply; 9+ messages in thread
From: Max Kellermann @ 2023-09-20 12:34 UTC (permalink / raw)
  To: Alexander Viro, Christian Brauner, linux-fsdevel

Hi,

I'm trying to understand the code that allocates a new buffer from a
pipe's buffer ring. I'd like to write a patch that eliminates some
duplicate code, to make it less error prone.

In fs/pipe.c, pipe_write() locks pipe->rd_wait.lock while the pipe's
head gets evaluated and incremented (all while pipe->mutex is locked).
My limited understand is that holding this spinlock is important
because it protects the head/tail accesses in pipe_readable() which is
gets called by wait_event while the spinlock is held, but without
pipe->mutex.

However in fs/splice.c, splice_pipe_to_pipe() contains very similar
code; a new buffer gets allocated, head gets incremented - but without
caring for pipe->rd_wait.lock.
Please help me understand the point of locking pipe->rd_wait.lock, and
why it's necessary in pipe_write() but not in splice_pipe_to_pipe().
Is that a bug or am I missing something?

Max

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: When to lock pipe->rd_wait.lock?
  2023-09-20 12:34 When to lock pipe->rd_wait.lock? Max Kellermann
@ 2023-09-20 13:30 ` Christian Brauner
  2023-09-20 15:21   ` Max Kellermann
  2023-09-21  7:28   ` Max Kellermann
  0 siblings, 2 replies; 9+ messages in thread
From: Christian Brauner @ 2023-09-20 13:30 UTC (permalink / raw)
  To: Max Kellermann; +Cc: Alexander Viro, linux-fsdevel

On Wed, Sep 20, 2023 at 02:34:51PM +0200, Max Kellermann wrote:
> Hi,
> 
> I'm trying to understand the code that allocates a new buffer from a
> pipe's buffer ring. I'd like to write a patch that eliminates some
> duplicate code, to make it less error prone.
> 
> In fs/pipe.c, pipe_write() locks pipe->rd_wait.lock while the pipe's
> head gets evaluated and incremented (all while pipe->mutex is locked).
> My limited understand is that holding this spinlock is important
> because it protects the head/tail accesses in pipe_readable() which is
> gets called by wait_event while the spinlock is held, but without
> pipe->mutex.
> 
> However in fs/splice.c, splice_pipe_to_pipe() contains very similar
> code; a new buffer gets allocated, head gets incremented - but without
> caring for pipe->rd_wait.lock.
> Please help me understand the point of locking pipe->rd_wait.lock, and
> why it's necessary in pipe_write() but not in splice_pipe_to_pipe().
> Is that a bug or am I missing something?

Afaict, the mutex is sufficient protection unless you're using
watchqueues which use post_one_notification() that cannot acquire the
pipe mutex. Since splice operations aren't supported on such kernel
notification pipes - see get_pipe_info() - it should be unproblematic.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: When to lock pipe->rd_wait.lock?
  2023-09-20 13:30 ` Christian Brauner
@ 2023-09-20 15:21   ` Max Kellermann
  2023-09-20 15:50     ` Christian Brauner
  2023-09-21  7:28   ` Max Kellermann
  1 sibling, 1 reply; 9+ messages in thread
From: Max Kellermann @ 2023-09-20 15:21 UTC (permalink / raw)
  To: Christian Brauner; +Cc: Alexander Viro, linux-fsdevel

On Wed, Sep 20, 2023 at 3:30 PM Christian Brauner <brauner@kernel.org> wrote:
> Afaict, the mutex is sufficient protection unless you're using
> watchqueues which use post_one_notification() that cannot acquire the
> pipe mutex. Since splice operations aren't supported on such kernel
> notification pipes - see get_pipe_info() - it should be unproblematic.

Which means that the spinlocks can safely be removed from
pipe_write(), because they are unnecessary overhead?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: When to lock pipe->rd_wait.lock?
  2023-09-20 15:21   ` Max Kellermann
@ 2023-09-20 15:50     ` Christian Brauner
  2023-09-20 16:14       ` Max Kellermann
  0 siblings, 1 reply; 9+ messages in thread
From: Christian Brauner @ 2023-09-20 15:50 UTC (permalink / raw)
  To: Max Kellermann; +Cc: Alexander Viro, linux-fsdevel

On Wed, Sep 20, 2023 at 05:21:03PM +0200, Max Kellermann wrote:
> On Wed, Sep 20, 2023 at 3:30 PM Christian Brauner <brauner@kernel.org> wrote:
> > Afaict, the mutex is sufficient protection unless you're using
> > watchqueues which use post_one_notification() that cannot acquire the
> > pipe mutex. Since splice operations aren't supported on such kernel
> > notification pipes - see get_pipe_info() - it should be unproblematic.
> 
> Which means that the spinlocks can safely be removed from
> pipe_write(), because they are unnecessary overhead?

I don't think so, O_NOTIFICATION/watch queue pipes allow userspace to
use pipe_read() and pipe_write() but prevent the usage of splice. The
spinlock is there for post_one_notification() which is called from
kernel context.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: When to lock pipe->rd_wait.lock?
  2023-09-20 15:50     ` Christian Brauner
@ 2023-09-20 16:14       ` Max Kellermann
  0 siblings, 0 replies; 9+ messages in thread
From: Max Kellermann @ 2023-09-20 16:14 UTC (permalink / raw)
  To: Christian Brauner; +Cc: Alexander Viro, linux-fsdevel

On Wed, Sep 20, 2023 at 5:50 PM Christian Brauner <brauner@kernel.org> wrote:
> I don't think so, O_NOTIFICATION/watch queue pipes allow userspace to
> use pipe_read() and pipe_write() but prevent the usage of splice. The
> spinlock is there for post_one_notification() which is called from
> kernel context.

Oohh, that was watch_queue, not wait_queue! This is how I
misunderstood your previous email.

So the spinlock is used in pipe_write() only just in case this is a
O_NOTIFICATION_PIPE. If I understand this correctly, it means the
spinlock could be omitted for the majority of pipes that are not
O_NOTIFICATION_PIPE?
Do you think it could be a worthy optimization to make the spinlock
conditional? I mean, how many pipes are there usually, and how many of
these are really O_NOTIFICATION_PIPE? This is a very rare exotic
feature, isn't it?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: When to lock pipe->rd_wait.lock?
  2023-09-20 13:30 ` Christian Brauner
  2023-09-20 15:21   ` Max Kellermann
@ 2023-09-21  7:28   ` Max Kellermann
  2023-09-21  8:05     ` Max Kellermann
  1 sibling, 1 reply; 9+ messages in thread
From: Max Kellermann @ 2023-09-21  7:28 UTC (permalink / raw)
  To: Christian Brauner; +Cc: Alexander Viro, linux-fsdevel

On Wed, Sep 20, 2023 at 3:30 PM Christian Brauner <brauner@kernel.org> wrote:
> Afaict, the mutex is sufficient protection unless you're using
> watchqueues which use post_one_notification() that cannot acquire the
> pipe mutex. Since splice operations aren't supported on such kernel
> notification pipes - see get_pipe_info() - it should be unproblematic.

I had another look at this, and something's fishy with the code or
with your explanation (or I still don't get it). If there is a
watch_queue, pipe_write() fails early with EXDEV - writing to such a
pipe is simply forbidden, the code is not reachable in the presence of
a watch_queue, therefore locking just because there might be a
wait_queue does not appear to make sense?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: When to lock pipe->rd_wait.lock?
  2023-09-21  7:28   ` Max Kellermann
@ 2023-09-21  8:05     ` Max Kellermann
  2023-09-21  9:17       ` Christian Brauner
  0 siblings, 1 reply; 9+ messages in thread
From: Max Kellermann @ 2023-09-21  8:05 UTC (permalink / raw)
  To: Christian Brauner, dhowells; +Cc: Alexander Viro, linux-fsdevel

On Thu, Sep 21, 2023 at 9:28 AM Max Kellermann <max.kellermann@ionos.com> wrote:
> I had another look at this, and something's fishy with the code or
> with your explanation (or I still don't get it). If there is a
> watch_queue, pipe_write() fails early with EXDEV - writing to such a
> pipe is simply forbidden, the code is not reachable in the presence of
> a watch_queue, therefore locking just because there might be a
> wait_queue does not appear to make sense?

Meanwhile I have figured that the spinlock in pipe_write() is
obsolete. It was added by David as preparation for the notification
feature, but the notification was finally merged, it had the EXDEV,
and I believe it was not initially planned to implement it that way?
So I believe the spinlock is really not necessary (anymore) and I have
posted a patch that removes it. (David, you would have received my
submission, unfortunately I misspelled your email address....)

Max

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: When to lock pipe->rd_wait.lock?
  2023-09-21  8:05     ` Max Kellermann
@ 2023-09-21  9:17       ` Christian Brauner
  2023-09-21  9:38         ` Max Kellermann
  0 siblings, 1 reply; 9+ messages in thread
From: Christian Brauner @ 2023-09-21  9:17 UTC (permalink / raw)
  To: Max Kellermann; +Cc: dhowells, Alexander Viro, linux-fsdevel

On Thu, Sep 21, 2023 at 10:05:24AM +0200, Max Kellermann wrote:
> On Thu, Sep 21, 2023 at 9:28 AM Max Kellermann <max.kellermann@ionos.com> wrote:
> > I had another look at this, and something's fishy with the code or
> > with your explanation (or I still don't get it). If there is a
> > watch_queue, pipe_write() fails early with EXDEV - writing to such a
> > pipe is simply forbidden, the code is not reachable in the presence of
> > a watch_queue, therefore locking just because there might be a
> > wait_queue does not appear to make sense?
> 
> Meanwhile I have figured that the spinlock in pipe_write() is
> obsolete. It was added by David as preparation for the notification
> feature, but the notification was finally merged, it had the EXDEV,
> and I believe it was not initially planned to implement it that way?

It was supposed to get write support most likely but never got it.
Good catch.

> So I believe the spinlock is really not necessary (anymore) and I have

For pipe_write() it isn't we still need it for pipe_read().

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: When to lock pipe->rd_wait.lock?
  2023-09-21  9:17       ` Christian Brauner
@ 2023-09-21  9:38         ` Max Kellermann
  0 siblings, 0 replies; 9+ messages in thread
From: Max Kellermann @ 2023-09-21  9:38 UTC (permalink / raw)
  To: Christian Brauner; +Cc: dhowells, Alexander Viro, linux-fsdevel

On Thu, Sep 21, 2023 at 11:18 AM Christian Brauner <brauner@kernel.org> wrote:
> For pipe_write() it isn't we still need it for pipe_read().

Agree. My patch set removes the spinlock from pipe_write(); the next
patch makes it optional for pipe_read(), eliminating the spinlock for
the most common case.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-09-21 20:19 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-20 12:34 When to lock pipe->rd_wait.lock? Max Kellermann
2023-09-20 13:30 ` Christian Brauner
2023-09-20 15:21   ` Max Kellermann
2023-09-20 15:50     ` Christian Brauner
2023-09-20 16:14       ` Max Kellermann
2023-09-21  7:28   ` Max Kellermann
2023-09-21  8:05     ` Max Kellermann
2023-09-21  9:17       ` Christian Brauner
2023-09-21  9:38         ` Max Kellermann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).