linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH -next 0/4] fs/buffer: misc optimizations
@ 2025-05-15 17:39 Davidlohr Bueso
  2025-05-15 17:39 ` [PATCH 1/4] fs/buffer: use sleeping lookup in __getblk_slowpath() Davidlohr Bueso
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Davidlohr Bueso @ 2025-05-15 17:39 UTC (permalink / raw)
  To: brauner; +Cc: jack, viro, mcgrof, dave, linux-fsdevel, linux-kernel

Hi,

Four small patches - the first could be sent to Linus for v6.15 considering
it is a missing nonblocking lookup conversion in the getblk slowpath I
had missed. The other two patches are small optimizations found while reading
the code, and one rocket science cleanup patch.

Thanks!

Davidlohr Bueso (4):
  fs/buffer: use sleeping lookup in __getblk_slowpath()
  fs/buffer: avoid redundant lookup in getblk slowpath
  fs/buffer: remove superfluous statements
  fs/buffer: optimize discard_buffer()

 fs/buffer.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

--
2.39.5


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

* [PATCH 1/4] fs/buffer: use sleeping lookup in __getblk_slowpath()
  2025-05-15 17:39 [PATCH -next 0/4] fs/buffer: misc optimizations Davidlohr Bueso
@ 2025-05-15 17:39 ` Davidlohr Bueso
  2025-05-16 10:11   ` Jan Kara
  2025-05-15 17:39 ` [PATCH 2/4] fs/buffer: avoid redundant lookup in getblk slowpath Davidlohr Bueso
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Davidlohr Bueso @ 2025-05-15 17:39 UTC (permalink / raw)
  To: brauner; +Cc: jack, viro, mcgrof, dave, linux-fsdevel, linux-kernel

Just as with the fast path, call the lookup variant depending
on the gfp flags.

Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
---
 fs/buffer.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index b8e1e6e325cd..5a4342881f3b 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1122,6 +1122,8 @@ static struct buffer_head *
 __getblk_slow(struct block_device *bdev, sector_t block,
 	     unsigned size, gfp_t gfp)
 {
+	bool blocking = gfpflags_allow_blocking(gfp);
+
 	/* Size must be multiple of hard sectorsize */
 	if (unlikely(size & (bdev_logical_block_size(bdev)-1) ||
 			(size < 512 || size > PAGE_SIZE))) {
@@ -1137,7 +1139,10 @@ __getblk_slow(struct block_device *bdev, sector_t block,
 	for (;;) {
 		struct buffer_head *bh;
 
-		bh = __find_get_block(bdev, block, size);
+		if (blocking)
+			bh = __find_get_block_nonatomic(bdev, block, size);
+		else
+			bh = __find_get_block(bdev, block, size);
 		if (bh)
 			return bh;
 
-- 
2.39.5


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

* [PATCH 2/4] fs/buffer: avoid redundant lookup in getblk slowpath
  2025-05-15 17:39 [PATCH -next 0/4] fs/buffer: misc optimizations Davidlohr Bueso
  2025-05-15 17:39 ` [PATCH 1/4] fs/buffer: use sleeping lookup in __getblk_slowpath() Davidlohr Bueso
@ 2025-05-15 17:39 ` Davidlohr Bueso
  2025-05-16 10:12   ` Jan Kara
  2025-05-15 17:39 ` [PATCH 3/4] fs/buffer: remove superfluous statements Davidlohr Bueso
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Davidlohr Bueso @ 2025-05-15 17:39 UTC (permalink / raw)
  To: brauner; +Cc: jack, viro, mcgrof, dave, linux-fsdevel, linux-kernel

__getblk_slow() already implies failing a first lookup
as the fastpath, so try to create the buffers immediately
and avoid the redundant lookup. This saves 5-10% of the
total cost/latency of the slowpath.

Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
---
 fs/buffer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index 5a4342881f3b..b02cced96529 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1139,15 +1139,15 @@ __getblk_slow(struct block_device *bdev, sector_t block,
 	for (;;) {
 		struct buffer_head *bh;
 
+		if (!grow_buffers(bdev, block, size, gfp))
+			return NULL;
+
 		if (blocking)
 			bh = __find_get_block_nonatomic(bdev, block, size);
 		else
 			bh = __find_get_block(bdev, block, size);
 		if (bh)
 			return bh;
-
-		if (!grow_buffers(bdev, block, size, gfp))
-			return NULL;
 	}
 }
 
-- 
2.39.5


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

* [PATCH 3/4] fs/buffer: remove superfluous statements
  2025-05-15 17:39 [PATCH -next 0/4] fs/buffer: misc optimizations Davidlohr Bueso
  2025-05-15 17:39 ` [PATCH 1/4] fs/buffer: use sleeping lookup in __getblk_slowpath() Davidlohr Bueso
  2025-05-15 17:39 ` [PATCH 2/4] fs/buffer: avoid redundant lookup in getblk slowpath Davidlohr Bueso
@ 2025-05-15 17:39 ` Davidlohr Bueso
  2025-05-16 10:13   ` Jan Kara
  2025-05-15 17:39 ` [PATCH 4/4] fs/buffer: optimize discard_buffer() Davidlohr Bueso
  2025-05-19 10:06 ` [PATCH -next 0/4] fs/buffer: misc optimizations Christian Brauner
  4 siblings, 1 reply; 10+ messages in thread
From: Davidlohr Bueso @ 2025-05-15 17:39 UTC (permalink / raw)
  To: brauner; +Cc: jack, viro, mcgrof, dave, linux-fsdevel, linux-kernel

Get rid of those unnecessary return statements.

Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
---
 fs/buffer.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index b02cced96529..210b43574a10 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -297,7 +297,6 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
 
 still_busy:
 	spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
-	return;
 }
 
 struct postprocess_bh_ctx {
@@ -422,7 +421,6 @@ static void end_buffer_async_write(struct buffer_head *bh, int uptodate)
 
 still_busy:
 	spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
-	return;
 }
 
 /*
@@ -1684,7 +1682,6 @@ void block_invalidate_folio(struct folio *folio, size_t offset, size_t length)
 		filemap_release_folio(folio, 0);
 out:
 	folio_clear_mappedtodisk(folio);
-	return;
 }
 EXPORT_SYMBOL(block_invalidate_folio);
 
-- 
2.39.5


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

* [PATCH 4/4] fs/buffer: optimize discard_buffer()
  2025-05-15 17:39 [PATCH -next 0/4] fs/buffer: misc optimizations Davidlohr Bueso
                   ` (2 preceding siblings ...)
  2025-05-15 17:39 ` [PATCH 3/4] fs/buffer: remove superfluous statements Davidlohr Bueso
@ 2025-05-15 17:39 ` Davidlohr Bueso
  2025-05-16 10:17   ` Jan Kara
  2025-05-19 10:06 ` [PATCH -next 0/4] fs/buffer: misc optimizations Christian Brauner
  4 siblings, 1 reply; 10+ messages in thread
From: Davidlohr Bueso @ 2025-05-15 17:39 UTC (permalink / raw)
  To: brauner; +Cc: jack, viro, mcgrof, dave, linux-fsdevel, linux-kernel

While invalidating, the clearing of the bits in discard_buffer()
is done in one fully ordered CAS operation. In the past this was
done via individual clear_bit(), until e7470ee89f0 (fs: buffer:
do not use unnecessary atomic operations when discarding buffers).
This implies that there were never strong ordering requirements
outside of being serialized by the buffer lock.

As such relax the ordering for archs that can benefit. Further,
the implied ordering in buffer_unlock() makes current cmpxchg
implied barrier redundant due to release semantics. And while in
theory the unlock could be part of the bulk clearing, it is
best to leave it explicit, but without the double barriers.

Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
---
 fs/buffer.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index 210b43574a10..f0fc78910abf 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1616,8 +1616,8 @@ static void discard_buffer(struct buffer_head * bh)
 	bh->b_bdev = NULL;
 	b_state = READ_ONCE(bh->b_state);
 	do {
-	} while (!try_cmpxchg(&bh->b_state, &b_state,
-			      b_state & ~BUFFER_FLAGS_DISCARD));
+	} while (!try_cmpxchg_relaxed(&bh->b_state, &b_state,
+				      b_state & ~BUFFER_FLAGS_DISCARD));
 	unlock_buffer(bh);
 }
 
-- 
2.39.5


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

* Re: [PATCH 1/4] fs/buffer: use sleeping lookup in __getblk_slowpath()
  2025-05-15 17:39 ` [PATCH 1/4] fs/buffer: use sleeping lookup in __getblk_slowpath() Davidlohr Bueso
@ 2025-05-16 10:11   ` Jan Kara
  0 siblings, 0 replies; 10+ messages in thread
From: Jan Kara @ 2025-05-16 10:11 UTC (permalink / raw)
  To: Davidlohr Bueso; +Cc: brauner, jack, viro, mcgrof, linux-fsdevel, linux-kernel

On Thu 15-05-25 10:39:22, Davidlohr Bueso wrote:
> Just as with the fast path, call the lookup variant depending
> on the gfp flags.
> 
> Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza
> ---
>  fs/buffer.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/buffer.c b/fs/buffer.c
> index b8e1e6e325cd..5a4342881f3b 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -1122,6 +1122,8 @@ static struct buffer_head *
>  __getblk_slow(struct block_device *bdev, sector_t block,
>  	     unsigned size, gfp_t gfp)
>  {
> +	bool blocking = gfpflags_allow_blocking(gfp);
> +
>  	/* Size must be multiple of hard sectorsize */
>  	if (unlikely(size & (bdev_logical_block_size(bdev)-1) ||
>  			(size < 512 || size > PAGE_SIZE))) {
> @@ -1137,7 +1139,10 @@ __getblk_slow(struct block_device *bdev, sector_t block,
>  	for (;;) {
>  		struct buffer_head *bh;
>  
> -		bh = __find_get_block(bdev, block, size);
> +		if (blocking)
> +			bh = __find_get_block_nonatomic(bdev, block, size);
> +		else
> +			bh = __find_get_block(bdev, block, size);
>  		if (bh)
>  			return bh;
>  
> -- 
> 2.39.5
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

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

* Re: [PATCH 2/4] fs/buffer: avoid redundant lookup in getblk slowpath
  2025-05-15 17:39 ` [PATCH 2/4] fs/buffer: avoid redundant lookup in getblk slowpath Davidlohr Bueso
@ 2025-05-16 10:12   ` Jan Kara
  0 siblings, 0 replies; 10+ messages in thread
From: Jan Kara @ 2025-05-16 10:12 UTC (permalink / raw)
  To: Davidlohr Bueso; +Cc: brauner, jack, viro, mcgrof, linux-fsdevel, linux-kernel

On Thu 15-05-25 10:39:23, Davidlohr Bueso wrote:
> __getblk_slow() already implies failing a first lookup
> as the fastpath, so try to create the buffers immediately
> and avoid the redundant lookup. This saves 5-10% of the
> total cost/latency of the slowpath.
> 
> Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>

Makes sense. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  fs/buffer.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/buffer.c b/fs/buffer.c
> index 5a4342881f3b..b02cced96529 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -1139,15 +1139,15 @@ __getblk_slow(struct block_device *bdev, sector_t block,
>  	for (;;) {
>  		struct buffer_head *bh;
>  
> +		if (!grow_buffers(bdev, block, size, gfp))
> +			return NULL;
> +
>  		if (blocking)
>  			bh = __find_get_block_nonatomic(bdev, block, size);
>  		else
>  			bh = __find_get_block(bdev, block, size);
>  		if (bh)
>  			return bh;
> -
> -		if (!grow_buffers(bdev, block, size, gfp))
> -			return NULL;
>  	}
>  }
>  
> -- 
> 2.39.5
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

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

* Re: [PATCH 3/4] fs/buffer: remove superfluous statements
  2025-05-15 17:39 ` [PATCH 3/4] fs/buffer: remove superfluous statements Davidlohr Bueso
@ 2025-05-16 10:13   ` Jan Kara
  0 siblings, 0 replies; 10+ messages in thread
From: Jan Kara @ 2025-05-16 10:13 UTC (permalink / raw)
  To: Davidlohr Bueso; +Cc: brauner, jack, viro, mcgrof, linux-fsdevel, linux-kernel

On Thu 15-05-25 10:39:24, Davidlohr Bueso wrote:
> Get rid of those unnecessary return statements.
> 
> Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>

Sure. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  fs/buffer.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/fs/buffer.c b/fs/buffer.c
> index b02cced96529..210b43574a10 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -297,7 +297,6 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
>  
>  still_busy:
>  	spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
> -	return;
>  }
>  
>  struct postprocess_bh_ctx {
> @@ -422,7 +421,6 @@ static void end_buffer_async_write(struct buffer_head *bh, int uptodate)
>  
>  still_busy:
>  	spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
> -	return;
>  }
>  
>  /*
> @@ -1684,7 +1682,6 @@ void block_invalidate_folio(struct folio *folio, size_t offset, size_t length)
>  		filemap_release_folio(folio, 0);
>  out:
>  	folio_clear_mappedtodisk(folio);
> -	return;
>  }
>  EXPORT_SYMBOL(block_invalidate_folio);
>  
> -- 
> 2.39.5
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

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

* Re: [PATCH 4/4] fs/buffer: optimize discard_buffer()
  2025-05-15 17:39 ` [PATCH 4/4] fs/buffer: optimize discard_buffer() Davidlohr Bueso
@ 2025-05-16 10:17   ` Jan Kara
  0 siblings, 0 replies; 10+ messages in thread
From: Jan Kara @ 2025-05-16 10:17 UTC (permalink / raw)
  To: Davidlohr Bueso; +Cc: brauner, jack, viro, mcgrof, linux-fsdevel, linux-kernel

On Thu 15-05-25 10:39:25, Davidlohr Bueso wrote:
> While invalidating, the clearing of the bits in discard_buffer()
> is done in one fully ordered CAS operation. In the past this was
> done via individual clear_bit(), until e7470ee89f0 (fs: buffer:
> do not use unnecessary atomic operations when discarding buffers).
> This implies that there were never strong ordering requirements
> outside of being serialized by the buffer lock.
> 
> As such relax the ordering for archs that can benefit. Further,
> the implied ordering in buffer_unlock() makes current cmpxchg
> implied barrier redundant due to release semantics. And while in
> theory the unlock could be part of the bulk clearing, it is
> best to leave it explicit, but without the double barriers.
> 
> Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>

Yes, we just want to clear several flag bits as cheaply as possible while
other tasks can be modifying other flags. You change makes sense so feel
free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  fs/buffer.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/buffer.c b/fs/buffer.c
> index 210b43574a10..f0fc78910abf 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -1616,8 +1616,8 @@ static void discard_buffer(struct buffer_head * bh)
>  	bh->b_bdev = NULL;
>  	b_state = READ_ONCE(bh->b_state);
>  	do {
> -	} while (!try_cmpxchg(&bh->b_state, &b_state,
> -			      b_state & ~BUFFER_FLAGS_DISCARD));
> +	} while (!try_cmpxchg_relaxed(&bh->b_state, &b_state,
> +				      b_state & ~BUFFER_FLAGS_DISCARD));
>  	unlock_buffer(bh);
>  }
>  
> -- 
> 2.39.5
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

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

* Re: [PATCH -next 0/4] fs/buffer: misc optimizations
  2025-05-15 17:39 [PATCH -next 0/4] fs/buffer: misc optimizations Davidlohr Bueso
                   ` (3 preceding siblings ...)
  2025-05-15 17:39 ` [PATCH 4/4] fs/buffer: optimize discard_buffer() Davidlohr Bueso
@ 2025-05-19 10:06 ` Christian Brauner
  4 siblings, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2025-05-19 10:06 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: Christian Brauner, jack, viro, mcgrof, linux-fsdevel,
	linux-kernel

On Thu, 15 May 2025 10:39:21 -0700, Davidlohr Bueso wrote:
> Four small patches - the first could be sent to Linus for v6.15 considering
> it is a missing nonblocking lookup conversion in the getblk slowpath I
> had missed. The other two patches are small optimizations found while reading
> the code, and one rocket science cleanup patch.
> 
> Thanks!
> 
> [...]

Applied to the vfs-6.16.misc branch of the vfs/vfs.git tree.
Patches in the vfs-6.16.misc branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs-6.16.misc

[1/4] fs/buffer: use sleeping lookup in __getblk_slowpath()
      https://git.kernel.org/vfs/vfs/c/f13865bcff54
[2/4] fs/buffer: avoid redundant lookup in getblk slowpath
      https://git.kernel.org/vfs/vfs/c/545f109630fc
[3/4] fs/buffer: remove superfluous statements
      https://git.kernel.org/vfs/vfs/c/fd7bedc81a2e
[4/4] fs/buffer: optimize discard_buffer()
      https://git.kernel.org/vfs/vfs/c/a09d25918f3d

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

end of thread, other threads:[~2025-05-19 10:07 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-15 17:39 [PATCH -next 0/4] fs/buffer: misc optimizations Davidlohr Bueso
2025-05-15 17:39 ` [PATCH 1/4] fs/buffer: use sleeping lookup in __getblk_slowpath() Davidlohr Bueso
2025-05-16 10:11   ` Jan Kara
2025-05-15 17:39 ` [PATCH 2/4] fs/buffer: avoid redundant lookup in getblk slowpath Davidlohr Bueso
2025-05-16 10:12   ` Jan Kara
2025-05-15 17:39 ` [PATCH 3/4] fs/buffer: remove superfluous statements Davidlohr Bueso
2025-05-16 10:13   ` Jan Kara
2025-05-15 17:39 ` [PATCH 4/4] fs/buffer: optimize discard_buffer() Davidlohr Bueso
2025-05-16 10:17   ` Jan Kara
2025-05-19 10:06 ` [PATCH -next 0/4] fs/buffer: misc optimizations Christian Brauner

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).