mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher
@ 2026-10-29 17:29 Bryanna Marihugh via B4 Relay
  2026-10-29 19:56 ` OGAWA Hirofumi
  2026-10-29 20:11 ` Matheus Alves de Almeida
  0 siblings, 2 replies; 9+ messages in thread
From: Bryanna Marihugh via B4 Relay @ 2026-10-29 17:29 UTC (permalink / raw)
  To: OGAWA Hirofumi
  Cc: Andrew Morton, Jan Kara, linux-fsdevel, linux-kernel, Bryanna Marihugh

From: Bryanna Marihugh <bryannamarihugh@manhattantech.edu>

On cheap USB 3.0 sticks, copying a large file to one formatted FAT
slows down badly when the background flusher runs at the same time.
This only impacts performance; it does not corrupt data.

udisks mounts FAT with the flush option, so closing a written file
calls fat_flush_inodes(), which starts writeback of the data with
filemap_fdatawrite(). That does not set I_SYNC, so the flusher starts
at the same time, which causes lots of small requests.

Cheap controllers handle small writes poorly and sometimes stall for
seconds. I have found this to be a problem on many cheap USB 3 drives.
Older USB2 hardware, better drives and ones that support UASP
don't show this behavior.

Use write_inode_now(inode, 1) instead. It goes through
writeback_single_inode(), which sets I_SYNC while it writes.
Close now also waits for the data and the directory entry to be written.

Benchmark copying a 3 GiB file to a USB 3 stick (PNY, 154b:00ed),
default writeback settings: 11.6-16.3 MB/s before, 17.6-18.0 MB/s after.

Signed-off-by: Bryanna Marihugh <bryannamarihugh@manhattantech.edu>
---
This is a performance fix for cheap USB 3 sticks on FAT mounted with
flush (the udisks default). It stops close and the flusher from writing
the same file at the same time.

Tested on v7.2.12 (stock and patched) and mainline c339f4010dea
(patched), bare metal, same stick. With the flusher kept busy
(dirty_background_bytes=256M, dirty_writeback_centisecs=100) cp goes
from 6.8-8.7 to 13.5-17.4 MB/s. With the patch one task writes the file
and 96-100% of data bios are 768 KiB or larger (4-16% before).

Only measured on one usb-storage stick. UAS drives I have used did not
show the slowdown, but I haven't traced them.

fsync() and sync_bdevs() can race the flusher the same way on other
filesystems. I kept this patch to FAT, but have numbers for exFAT, ext4
and btrfs if useful.

I am a sysadmin not a C dev haven't written it much since school and so
did use an LLM for help reading the writeback code, analysing the block
traces and drafting the patch and text and who to email. I typed,
reviewed and tested the change myself and feel confident that I
understand it and can answer questions.
---
 fs/fat/inode.c | 21 +++++----------------
 1 file changed, 5 insertions(+), 16 deletions(-)

diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index d85c8fbdcca4..0643244223c5 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -1911,28 +1911,17 @@ EXPORT_SYMBOL_GPL(fat_fill_super);
 
 /*
  * helper function for fat_flush_inodes.  This writes both the inode
- * and the file data blocks, waiting for in flight data blocks before
- * the start of the call.  It does not wait for any io started
- * during the call
+ * and the file data blocks, waiting for in flight data blocks and
+ * ones it starts. write_inode_now() takes I_SYNC, so the flusher
+ * does not try to write at the same time.
  */
 static int writeback_inode(struct inode *inode)
 {
-
-	int ret;
-
-	/* if we used wait=1, sync_inode_metadata waits for the io for the
-	* inode to finish.  So wait=0 is sent down to sync_inode_metadata
-	* and filemap_fdatawrite is used for the data blocks
-	*/
-	ret = sync_inode_metadata(inode, 0);
-	if (!ret)
-		ret = filemap_fdatawrite(inode->i_mapping);
-	return ret;
+	return write_inode_now(inode, 1);
 }
 
 /*
- * write data and metadata corresponding to i1 and i2.  The io is
- * started but we do not wait for any of it to finish.
+ * write data and metadata corresponding to i1 and i2 and wait for them.
  *
  * filemap_flush is used for the block device, so if there is a dirty
  * page for a block already in flight, we will not wait and start the

---
base-commit: c339f4010dea8b0d754f84ace70cd1b089878ef8
change-id: 20261029-fat-flush-isync-ae828e018ee0

Best regards,
-- 
Bryanna Marihugh <bryannamarihugh@manhattantech.edu>



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

* Re: [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher
  2026-10-29 17:29 [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher Bryanna Marihugh via B4 Relay
@ 2026-10-29 19:56 ` OGAWA Hirofumi
  2026-10-30  4:56   ` Bryanna Marihugh
  2026-10-29 20:11 ` Matheus Alves de Almeida
  1 sibling, 1 reply; 9+ messages in thread
From: OGAWA Hirofumi @ 2026-10-29 19:56 UTC (permalink / raw)
  To: bryannamarihugh; +Cc: Andrew Morton, Jan Kara, linux-fsdevel, linux-kernel

Bryanna Marihugh via B4 Relay
<devnull+bryannamarihugh.manhattantech.edu@kernel.org> writes:

> From: Bryanna Marihugh <bryannamarihugh@manhattantech.edu>
>
> On cheap USB 3.0 sticks, copying a large file to one formatted FAT
> slows down badly when the background flusher runs at the same time.
> This only impacts performance; it does not corrupt data.
>
> udisks mounts FAT with the flush option, so closing a written file
> calls fat_flush_inodes(), which starts writeback of the data with
> filemap_fdatawrite(). That does not set I_SYNC, so the flusher starts
> at the same time, which causes lots of small requests.
>
> Cheap controllers handle small writes poorly and sometimes stall for
> seconds. I have found this to be a problem on many cheap USB 3 drives.
> Older USB2 hardware, better drives and ones that support UASP
> don't show this behavior.
>
> Use write_inode_now(inode, 1) instead. It goes through
> writeback_single_inode(), which sets I_SYNC while it writes.
> Close now also waits for the data and the directory entry to be written.
>
> Benchmark copying a 3 GiB file to a USB 3 stick (PNY, 154b:00ed),
> default writeback settings: 11.6-16.3 MB/s before, 17.6-18.0 MB/s after.
>
> Signed-off-by: Bryanna Marihugh <bryannamarihugh@manhattantech.edu>
> ---
> This is a performance fix for cheap USB 3 sticks on FAT mounted with
> flush (the udisks default). It stops close and the flusher from writing
> the same file at the same time.
>
> Tested on v7.2.12 (stock and patched) and mainline c339f4010dea
> (patched), bare metal, same stick. With the flusher kept busy
> (dirty_background_bytes=256M, dirty_writeback_centisecs=100) cp goes
> from 6.8-8.7 to 13.5-17.4 MB/s. With the patch one task writes the file
> and 96-100% of data bios are 768 KiB or larger (4-16% before).
>
> Only measured on one usb-storage stick. UAS drives I have used did not
> show the slowdown, but I haven't traced them.
>
> fsync() and sync_bdevs() can race the flusher the same way on other
> filesystems. I kept this patch to FAT, but have numbers for exFAT, ext4
> and btrfs if useful.
>
> I am a sysadmin not a C dev haven't written it much since school and so
> did use an LLM for help reading the writeback code, analysing the block
> traces and drafting the patch and text and who to email. I typed,
> reviewed and tested the change myself and feel confident that I
> understand it and can answer questions.

Looks like this waits the I/O, and sounds like optimization only for
specific drives. Well, so no slowdown for other drives by this patch?

Thanks.

> ---
>  fs/fat/inode.c | 21 +++++----------------
>  1 file changed, 5 insertions(+), 16 deletions(-)
>
> diff --git a/fs/fat/inode.c b/fs/fat/inode.c
> index d85c8fbdcca4..0643244223c5 100644
> --- a/fs/fat/inode.c
> +++ b/fs/fat/inode.c
> @@ -1911,28 +1911,17 @@ EXPORT_SYMBOL_GPL(fat_fill_super);
>  
>  /*
>   * helper function for fat_flush_inodes.  This writes both the inode
> - * and the file data blocks, waiting for in flight data blocks before
> - * the start of the call.  It does not wait for any io started
> - * during the call
> + * and the file data blocks, waiting for in flight data blocks and
> + * ones it starts. write_inode_now() takes I_SYNC, so the flusher
> + * does not try to write at the same time.
>   */
>  static int writeback_inode(struct inode *inode)
>  {
> -
> -	int ret;
> -
> -	/* if we used wait=1, sync_inode_metadata waits for the io for the
> -	* inode to finish.  So wait=0 is sent down to sync_inode_metadata
> -	* and filemap_fdatawrite is used for the data blocks
> -	*/
> -	ret = sync_inode_metadata(inode, 0);
> -	if (!ret)
> -		ret = filemap_fdatawrite(inode->i_mapping);
> -	return ret;
> +	return write_inode_now(inode, 1);
>  }
>  
>  /*
> - * write data and metadata corresponding to i1 and i2.  The io is
> - * started but we do not wait for any of it to finish.
> + * write data and metadata corresponding to i1 and i2 and wait for them.
>   *
>   * filemap_flush is used for the block device, so if there is a dirty
>   * page for a block already in flight, we will not wait and start the
>
> ---
> base-commit: c339f4010dea8b0d754f84ace70cd1b089878ef8
> change-id: 20261029-fat-flush-isync-ae828e018ee0
>
> Best regards,

-- 
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

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

* Re: [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher
  2026-10-29 17:29 [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher Bryanna Marihugh via B4 Relay
  2026-10-29 19:56 ` OGAWA Hirofumi
@ 2026-10-29 20:11 ` Matheus Alves de Almeida
  2026-10-30  5:43   ` Bryanna Marihugh
  1 sibling, 1 reply; 9+ messages in thread
From: Matheus Alves de Almeida @ 2026-10-29 20:11 UTC (permalink / raw)
  To: Bryanna Marihugh
  Cc: OGAWA Hirofumi, Andrew Morton, Jan Kara, linux-fsdevel, linux-kernel

On Thu, Oct 29, 2026 at 12:29:05PM -0500, Bryanna Marihugh wrote:
>On cheap USB 3.0 sticks, copying a large file to one formatted FAT
>slows down badly when the background flusher runs at the same time.
>This only impacts performance; it does not corrupt data.
>
>udisks mounts FAT with the flush option, so closing a written file
>calls fat_flush_inodes(), which starts writeback of the data with
>filemap_fdatawrite(). That does not set I_SYNC, so the flusher starts
>at the same time, which causes lots of small requests.
>
>Cheap controllers handle small writes poorly and sometimes stall for
>seconds. I have found this to be a problem on many cheap USB 3 drives.
>Older USB2 hardware, better drives and ones that support UASP
>don't show this behavior.
>
>Use write_inode_now(inode, 1) instead. It goes through
>writeback_single_inode(), which sets I_SYNC while it writes.
>Close now also waits for the data and the directory entry to be written.
>
>Benchmark copying a 3 GiB file to a USB 3 stick (PNY, 154b:00ed),
>default writeback settings: 11.6-16.3 MB/s before, 17.6-18.0 MB/s after.
>
>Signed-off-by: Bryanna Marihugh <bryannamarihugh@manhattantech.edu>
>---
>This is a performance fix for cheap USB 3 sticks on FAT mounted with
>flush (the udisks default). It stops close and the flusher from writing
>the same file at the same time.
>
>Tested on v7.2.12 (stock and patched) and mainline c339f4010dea
>(patched), bare metal, same stick. With the flusher kept busy
>(dirty_background_bytes=256M, dirty_writeback_centisecs=100) cp goes
>from 6.8-8.7 to 13.5-17.4 MB/s. With the patch one task writes the file
>and 96-100% of data bios are 768 KiB or larger (4-16% before).
>
>Only measured on one usb-storage stick. UAS drives I have used did not
>show the slowdown, but I haven't traced them.
>
>fsync() and sync_bdevs() can race the flusher the same way on other
>filesystems. I kept this patch to FAT, but have numbers for exFAT, ext4
>and btrfs if useful.
>
>I am a sysadmin not a C dev haven't written it much since school and so
>did use an LLM for help reading the writeback code, analysing the block
>traces and drafting the patch and text and who to email. I typed,
>reviewed and tested the change myself and feel confident that I
>understand it and can answer questions.
>---
> fs/fat/inode.c | 21 +++++----------------
> 1 file changed, 5 insertions(+), 16 deletions(-)
>
>diff --git a/fs/fat/inode.c b/fs/fat/inode.c
>index d85c8fbdcca4..0643244223c5 100644
>--- a/fs/fat/inode.c
>+++ b/fs/fat/inode.c
>@@ -1911,28 +1911,17 @@ EXPORT_SYMBOL_GPL(fat_fill_super);
> 
> /*
>  * helper function for fat_flush_inodes.  This writes both the inode
>- * and the file data blocks, waiting for in flight data blocks before
>- * the start of the call.  It does not wait for any io started
>- * during the call
>+ * and the file data blocks, waiting for in flight data blocks and
>+ * ones it starts. write_inode_now() takes I_SYNC, so the flusher
>+ * does not try to write at the same time.
>  */
> static int writeback_inode(struct inode *inode)
> {
>-
>-	int ret;
>-
>-	/* if we used wait=1, sync_inode_metadata waits for the io for the
>-	* inode to finish.  So wait=0 is sent down to sync_inode_metadata
>-	* and filemap_fdatawrite is used for the data blocks
>-	*/
>-	ret = sync_inode_metadata(inode, 0);
>-	if (!ret)
>-		ret = filemap_fdatawrite(inode->i_mapping);
>-	return ret;
>+	return write_inode_now(inode, 1);
> }
> 
> /*
>- * write data and metadata corresponding to i1 and i2.  The io is
>- * started but we do not wait for any of it to finish.
>+ * write data and metadata corresponding to i1 and i2 and wait for them.
>  *
>  * filemap_flush is used for the block device, so if there is a dirty
>  * page for a block already in flight, we will not wait and start the
>
>---
>base-commit: c339f4010dea8b0d754f84ace70cd1b089878ef8
>change-id: 20261029-fat-flush-isync-ae828e018ee0
>
>Best regards,
>-- 
>Bryanna Marihugh <bryannamarihugh@manhattantech.edu>
>

I Agree with OGAWA.

Also, since writeback_inode() will just be a call to write_inode_now(),
couldn't this helper be removed and instead write_inode_now() be called
directly?

Thanks,
Matheus

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

* Re: [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher
  2026-10-29 19:56 ` OGAWA Hirofumi
@ 2026-10-30  4:56   ` Bryanna Marihugh
  2026-10-30  5:58     ` OGAWA Hirofumi
  0 siblings, 1 reply; 9+ messages in thread
From: Bryanna Marihugh @ 2026-10-30  4:56 UTC (permalink / raw)
  To: OGAWA Hirofumi; +Cc: Andrew Morton, Jan Kara, linux-fsdevel, linux-kernel

On 10/29/26 2:56 PM, OGAWA Hirofumi wrote:
> Looks like this waits the I/O, and sounds like optimization only for
> specific drives. Well, so no slowdown for other drives by this patch?

Thanks for the rapid reply and feedback.

writeback_inode is called only when flush is set. My understanding is
that mode is for storage that could disconnect. I set write_inode_now
to wait as that seemed to be right for flush. Given it does change
behavior I should have explained that better. I can change it to 0 if
you want the old behavior. Because I_SYNC is still set no matter if
it waits or not, it should keep the kernel flusher from writing the
same file.

I focused on the reduced write request size causing the stall, and
tested for slowdowns mostly doing a cp and looking at the times, for
big and small files. Everything in MB/s

PNY 32G stick (usb-storage), copying a 3 GiB file 3x

  before: 16.3, 13.2, 11.6
  after:  18.0, 18.0, 17.6

Samsung 64G stick (usb-storage), copying a 3 GiB file 3x

  before: 33.4, 33.5, 33.5
  after:  33.5, 33.5, 33.5

PNY 250G stick (uas), copying a 4 GiB file 3x

  before: 365, 200, 322
  after:  365, 255, 251

Samsung 870 EVO in a USB-SATA adapter (uas), copying a 4 GiB file 3x

  before: 379, 346, 346
  after:  376, 378, 379

The PNY 250G numbers vary on both kernels because the stick slows
itself down partway through.

For small files I saw maybe improvements on the cheap stick, with no
harm on the nicer Samsung stick.

PNY 32G stick (usb-storage), copying 1000 x 1 MiB files 2x

  before: 5.37, 5.55
  after:  5.64, 5.62

Samsung 64G stick (usb-storage), copying 1000 x 1 MiB files 2x

  before: 7.33, 7.37
  after:  7.35, 7.36

PNY 250G stick (uas), copying 1000 x 1 MiB files 2x

  before: 9.61, 9.61
  after:  9.28, 9.26

870 EVO in USB-SATA adapter (uas), copying 1000 x 1 MiB files 2x

  before: 9.61, 9.61
  after:  9.59, 9.51

There is some regression with small files on the uas drives from the
wait.

Thanks,
Bryanna

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

* Re: [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher
  2026-10-29 20:11 ` Matheus Alves de Almeida
@ 2026-10-30  5:43   ` Bryanna Marihugh
  0 siblings, 0 replies; 9+ messages in thread
From: Bryanna Marihugh @ 2026-10-30  5:43 UTC (permalink / raw)
  To: Matheus Alves de Almeida
  Cc: OGAWA Hirofumi, Andrew Morton, Jan Kara, linux-fsdevel, linux-kernel

On 10/29/26 3:11 PM, Matheus Alves de Almeida wrote:
> I Agree with OGAWA.
>
> Also, since writeback_inode() will just be a call to
> write_inode_now(), couldn't this helper be removed and instead
> write_inode_now() be called directly?

I answered OGAWA with numbers from more drives and offered to drop
the wait in v2:
https://lore.kernel.org/lkml/457c34c8-b52f-41c6-8b58-ed334b0dc483@manhattantech.edu/

I have not contributed before, so I was being cautious and went for a
1 line edit, as I was not sure of the protocol on removing functions.
I will remove writeback_inode() and call write_inode_now() directly in
fat_flush_inodes() in v2, once there is a decision on the wait.

Thanks,
Bryanna

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

* Re: [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher
  2026-10-30  4:56   ` Bryanna Marihugh
@ 2026-10-30  5:58     ` OGAWA Hirofumi
  2026-10-30  6:21       ` OGAWA Hirofumi
  0 siblings, 1 reply; 9+ messages in thread
From: OGAWA Hirofumi @ 2026-10-30  5:58 UTC (permalink / raw)
  To: Bryanna Marihugh; +Cc: Andrew Morton, Jan Kara, linux-fsdevel, linux-kernel

Bryanna Marihugh <bryannamarihugh@manhattantech.edu> writes:

> On 10/29/26 2:56 PM, OGAWA Hirofumi wrote:
>> Looks like this waits the I/O, and sounds like optimization only for
>> specific drives. Well, so no slowdown for other drives by this patch?
>
> Thanks for the rapid reply and feedback.
>
> writeback_inode is called only when flush is set. My understanding is
> that mode is for storage that could disconnect. I set write_inode_now
> to wait as that seemed to be right for flush. Given it does change
> behavior I should have explained that better. I can change it to 0 if
> you want the old behavior. Because I_SYNC is still set no matter if
> it waits or not, it should keep the kernel flusher from writing the
> same file.
>
> I focused on the reduced write request size causing the stall, and
> tested for slowdowns mostly doing a cp and looking at the times, for
> big and small files. Everything in MB/s
>
> PNY 32G stick (usb-storage), copying a 3 GiB file 3x
>
>   before: 16.3, 13.2, 11.6
>   after:  18.0, 18.0, 17.6
>
> Samsung 64G stick (usb-storage), copying a 3 GiB file 3x
>
>   before: 33.4, 33.5, 33.5
>   after:  33.5, 33.5, 33.5
>
> PNY 250G stick (uas), copying a 4 GiB file 3x
>
>   before: 365, 200, 322
>   after:  365, 255, 251
>
> Samsung 870 EVO in a USB-SATA adapter (uas), copying a 4 GiB file 3x
>
>   before: 379, 346, 346
>   after:  376, 378, 379
>
> The PNY 250G numbers vary on both kernels because the stick slows
> itself down partway through.
>
> For small files I saw maybe improvements on the cheap stick, with no
> harm on the nicer Samsung stick.
>
> PNY 32G stick (usb-storage), copying 1000 x 1 MiB files 2x
>
>   before: 5.37, 5.55
>   after:  5.64, 5.62
>
> Samsung 64G stick (usb-storage), copying 1000 x 1 MiB files 2x
>
>   before: 7.33, 7.37
>   after:  7.35, 7.36
>
> PNY 250G stick (uas), copying 1000 x 1 MiB files 2x
>
>   before: 9.61, 9.61
>   after:  9.28, 9.26
>
> 870 EVO in USB-SATA adapter (uas), copying 1000 x 1 MiB files 2x
>
>   before: 9.61, 9.61
>   after:  9.59, 9.51
>
> There is some regression with small files on the uas drives from the
> wait.

Is this wait=1? The flush should just be early flush, no guarantee to
flush completely. So I think it should be wait=0.

And the flush is assuming basically for removable media though, we can't
choose. I think we need to check the result of such HDD/SSD.

Thanks.
-- 
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

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

* Re: [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher
  2026-10-30  5:58     ` OGAWA Hirofumi
@ 2026-10-30  6:21       ` OGAWA Hirofumi
  2026-11-10  5:49         ` Bryanna Marihugh
  0 siblings, 1 reply; 9+ messages in thread
From: OGAWA Hirofumi @ 2026-10-30  6:21 UTC (permalink / raw)
  To: Bryanna Marihugh; +Cc: Andrew Morton, Jan Kara, linux-fsdevel, linux-kernel

OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> writes:

> Bryanna Marihugh <bryannamarihugh@manhattantech.edu> writes:
>
>> On 10/29/26 2:56 PM, OGAWA Hirofumi wrote:
>>> Looks like this waits the I/O, and sounds like optimization only for
>>> specific drives. Well, so no slowdown for other drives by this patch?
>>
>> Thanks for the rapid reply and feedback.
>>
>> writeback_inode is called only when flush is set. My understanding is
>> that mode is for storage that could disconnect. I set write_inode_now
>> to wait as that seemed to be right for flush. Given it does change
>> behavior I should have explained that better. I can change it to 0 if
>> you want the old behavior. Because I_SYNC is still set no matter if
>> it waits or not, it should keep the kernel flusher from writing the
>> same file.
>>
>> I focused on the reduced write request size causing the stall, and
>> tested for slowdowns mostly doing a cp and looking at the times, for
>> big and small files. Everything in MB/s
>>
>> PNY 32G stick (usb-storage), copying a 3 GiB file 3x
>>
>>   before: 16.3, 13.2, 11.6
>>   after:  18.0, 18.0, 17.6
>>
>> Samsung 64G stick (usb-storage), copying a 3 GiB file 3x
>>
>>   before: 33.4, 33.5, 33.5
>>   after:  33.5, 33.5, 33.5
>>
>> PNY 250G stick (uas), copying a 4 GiB file 3x
>>
>>   before: 365, 200, 322
>>   after:  365, 255, 251
>>
>> Samsung 870 EVO in a USB-SATA adapter (uas), copying a 4 GiB file 3x
>>
>>   before: 379, 346, 346
>>   after:  376, 378, 379
>>
>> The PNY 250G numbers vary on both kernels because the stick slows
>> itself down partway through.
>>
>> For small files I saw maybe improvements on the cheap stick, with no
>> harm on the nicer Samsung stick.
>>
>> PNY 32G stick (usb-storage), copying 1000 x 1 MiB files 2x
>>
>>   before: 5.37, 5.55
>>   after:  5.64, 5.62
>>
>> Samsung 64G stick (usb-storage), copying 1000 x 1 MiB files 2x
>>
>>   before: 7.33, 7.37
>>   after:  7.35, 7.36
>>
>> PNY 250G stick (uas), copying 1000 x 1 MiB files 2x
>>
>>   before: 9.61, 9.61
>>   after:  9.28, 9.26
>>
>> 870 EVO in USB-SATA adapter (uas), copying 1000 x 1 MiB files 2x
>>
>>   before: 9.61, 9.61
>>   after:  9.59, 9.51
>>
>> There is some regression with small files on the uas drives from the
>> wait.
>
> Is this wait=1? The flush should just be early flush, no guarantee to
> flush completely. So I think it should be wait=0.
>
> And the flush is assuming basically for removable media though, we can't
> choose. I think we need to check the result of such HDD/SSD.

And maybe it needs to check unmount time (check how many dirty was
missing to flush).

Thanks.
-- 
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

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

* Re: [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher
  2026-10-30  6:21       ` OGAWA Hirofumi
@ 2026-11-10  5:49         ` Bryanna Marihugh
  2026-11-10 10:30           ` OGAWA Hirofumi
  0 siblings, 1 reply; 9+ messages in thread
From: Bryanna Marihugh @ 2026-11-10  5:49 UTC (permalink / raw)
  To: OGAWA Hirofumi; +Cc: Andrew Morton, Jan Kara, linux-fsdevel, linux-kernel

OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> writes:

> > Bryanna Marihugh <bryannamarihugh@manhattantech.edu> writes:
> >
> >> There is some regression with small files on the uas drives from the
> >> wait.
> >
> > Is this wait=1? The flush should just be early flush, no guarantee to
> > flush completely. So I think it should be wait=0.

Everything I have posted so far is wait=1. I just wanted to provide the
benchmarks for my existing patch. I have a wait=0 one I have been
testing now. I labeled it in the benchmarks.

> > And the flush is assuming basically for removable media though, we can't
> > choose. I think we need to check the result of such HDD/SSD.

I did tests with this machine's dirty_background_ratio=5 (the kernel
default is 10), which results in a 3.4-4 GiB threshold, and with a
256 MB threshold (dirty_background_bytes=256M,
dirty_writeback_centisecs=100) to test what a more RAM constrained
device might do. I set FSINFO next_cluster before each HDD run so all
three kernels write to the same part of the disk.

WD Blue 500G 5400RPM HDD SATA
copying a 4 GiB file 3x, then sync, MB/s
(requests and average size are from the third run, which was traced)

  5% threshold
    stock:  89.4, 86.9, 87.8  (8,913 requests, avg 471 KB)
    wait=1: 97.9, 97.3, 95.2  (2,168 requests, avg 1,951 KB)
    wait=0: 96.2, 95.7, 98.7  (1,626 requests, avg 2,580 KB)

  256 MB threshold
    stock:  81.0, 88.1, 81.4  (16,291 requests, avg 258 KB)
    wait=1: 100.7, 99.7, 98.4 (2,257 requests, avg 1,859 KB)
    wait=0: 101.9, 100.5, 98.7 (1,532 requests, avg 2,738 KB)

WD Blue 500G, copying 1000 x 1 MiB files 2x, then sync, MB/s

  5% threshold
    stock:  9.44, 9.45
    wait=1: 9.34, 9.32
    wait=0: 9.55, 9.58


Samsung SSD 870 EVO SATA, copying a 4 GiB file 3x, then sync, MB/s
(requests and average size are from the third run, which was traced)

The wait=0 runs were on a different day.

  5% threshold
    stock:  338, 340, 341     (1,460 requests, avg 2,874 KB)
    wait=1: 333, 339, 339     (1,366 requests, avg 3,071 KB)
    wait=0: 313, 313, 313     (1,792 requests, avg 2,441 KB)

  256 MB threshold
    stock:  377, 378, 377     (11,476 requests, avg 366 KB)
    wait=1: 378, 378, 378     (1,675 requests, avg 2,505 KB)
    wait=0: 346, 344, 345     (2,278 requests, avg 1,938 KB)

870 EVO, copying 1000 x 1 MiB files 2x, then sync, MB/s

  5% threshold
    stock:  9.61, 9.61
    wait=1: 8.92, 8.92
    wait=0: 9.61, 9.61

PNY 32G USB 3.0 (usb-storage), copying a 3 GiB file 3x, then sync, MB/s
(requests and average size are from the third run, which was traced)

  5% threshold
    stock:  6.4, 6.9, 6.9     (12,481 requests, avg 252 KB)
    wait=1: 17.5, 17.9, 18.0  (3,720 requests, avg 846 KB)
    wait=0: 17.9, 13.7, 16.4  (3,809 requests, avg 827 KB)

  256 MB threshold
    stock:  5.8, 6.1, 6.0     (13,996 requests, avg 225 KB)
    wait=1: 17.9, 16.4, 14.7  (3,575 requests, avg 881 KB)
    wait=0: 18.0, 18.2, 17.9  (3,663 requests, avg 860 KB)


PNY 32G stick, copying 1000 x 1 MiB files 2x, then sync, MB/s

  5% threshold
    stock:  5.49, 5.62
    wait=1: 5.82, 5.62
    wait=0: 5.66, 5.65

Samsung 64G USB stick (usb-storage),
copying a 4 GiB file 3x, then sync, MB/s
(requests and average size are from the third run, which was traced)

  5% threshold
    stock:  33.0, 33.0, 33.1  (12,725 requests, avg 330 KB)
    wait=1: 33.2, 33.1, 33.2  (4,521 requests, avg 928 KB)
    wait=0: 33.1, 33.2, 33.2  (4,583 requests, avg 915 KB)

  256 MB threshold
    stock:  33.3, 33.3, 33.3  (15,757 requests, avg 266 KB)
    wait=1: 33.3, 33.5, 33.5  (4,534 requests, avg 925 KB)
    wait=0: 33.5, 33.6, 33.5  (4,645 requests, avg 903 KB)


Samsung 64G stick, copying 1000 x 1 MiB files 2x, then sync, MB/s

  5% threshold
    stock:  7.34, 7.34
    wait=1: 7.33, 7.34
    wait=0: 7.32, 7.35

I was a bit surprised by the improvement on the HDD. I will see if I
can find a high end HDD.

With the SSD the 870 EVO I did the wait=0 test on a different day.
Not sure why but it seemed to be slower on the wait=0 test, I am
blaming the run being on a different day. I think performance is
probably mostly flat with the fix.

> And maybe it needs to check unmount time (check how many dirty was
> missing to flush).

wait=0 does come with that downside. If the flusher is already writing
the file at close, wait=0 skips it and unmount has to write the rest.
At 5% the 3 GiB file on the PNY stays under the threshold, so the
flusher doesn't start until the 30 second expiry. That's why stock is
still slow there and wait=0 behaves like wait=1. The 4 GiB files go
over it.

PNY 32G stick, 3 GiB file, cp then umount right away,
average of 3 runs (5% threshold) and 5 runs (256 MB):

5% threshold   cp returns  dirty at close  umount   total
stock               485 s            3 MB   0.6 s   485 s
wait=1              184 s            3 MB   0.8 s   185 s
wait=0              180 s            3 MB   0.6 s   180 s

256 MB         cp returns  dirty at close  umount   total
stock               513 s            3 MB   0.6 s   514 s
wait=1              176 s            2 MB   0.8 s   176 s
wait=0              2.6 s        3,004 MB   172 s   174 s


WD Blue 500G 5400RPM HDD SATA, 4 GiB file, cp then umount right away,
average of 3 runs (5% threshold) and 5 runs (256 MB):

5% threshold   cp returns  dirty at close  umount   total
stock              47.4 s            3 MB   0.8 s  48.2 s
wait=1             43.5 s            3 MB   1.2 s  44.7 s
wait=0              2.2 s        4,064 MB  42.3 s  44.5 s

256 MB         cp returns  dirty at close  umount   total
stock              51.3 s            3 MB   0.8 s  52.1 s
wait=1             44.0 s            2 MB   1.3 s  45.2 s
wait=0              2.0 s        4,021 MB  43.2 s  45.2 s


870 EVO SSD (internal SATA), 4 GiB file, cp then umount right away,
average of 3 runs (5% threshold) and 5 runs (256 MB):

5% threshold   cp returns  dirty at close  in flight  umount   total
stock              11.9 s            2 MB     362 MB   1.1 s  13.0 s
wait=1             12.2 s            2 MB       0 MB   0.9 s  13.0 s
wait=0              1.5 s        4,006 MB      22 MB  12.3 s  13.8 s

256 MB         cp returns  dirty at close  in flight  umount   total
stock              11.9 s            3 MB     112 MB   1.0 s  12.9 s
wait=1             11.9 s            2 MB       0 MB   0.9 s  12.8 s
wait=0              1.7 s        3,350 MB     180 MB   9.7 s  11.4 s


I can type up an actual patch with wait=0 and removing the helper
that Matheus suggested.

Thanks,
Bryanna

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

* Re: [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher
  2026-11-10  5:49         ` Bryanna Marihugh
@ 2026-11-10 10:30           ` OGAWA Hirofumi
  0 siblings, 0 replies; 9+ messages in thread
From: OGAWA Hirofumi @ 2026-11-10 10:30 UTC (permalink / raw)
  To: Bryanna Marihugh; +Cc: Andrew Morton, Jan Kara, linux-fsdevel, linux-kernel

Bryanna Marihugh <bryannamarihugh@manhattantech.edu> writes:

> OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> writes:
>
>> > Bryanna Marihugh <bryannamarihugh@manhattantech.edu> writes:
>> >
>> >> There is some regression with small files on the uas drives from the
>> >> wait.
>> >
>> > Is this wait=1? The flush should just be early flush, no guarantee to
>> > flush completely. So I think it should be wait=0.
>
> Everything I have posted so far is wait=1. I just wanted to provide the
> benchmarks for my existing patch. I have a wait=0 one I have been
> testing now. I labeled it in the benchmarks.
>
>> > And the flush is assuming basically for removable media though, we can't
>> > choose. I think we need to check the result of such HDD/SSD.
>
> I did tests with this machine's dirty_background_ratio=5 (the kernel
> default is 10), which results in a 3.4-4 GiB threshold, and with a
> 256 MB threshold (dirty_background_bytes=256M,
> dirty_writeback_centisecs=100) to test what a more RAM constrained
> device might do. I set FSINFO next_cluster before each HDD run so all
> three kernels write to the same part of the disk.
>
> WD Blue 500G 5400RPM HDD SATA
> copying a 4 GiB file 3x, then sync, MB/s
> (requests and average size are from the third run, which was traced)
>
>   5% threshold
>     stock:  89.4, 86.9, 87.8  (8,913 requests, avg 471 KB)
>     wait=1: 97.9, 97.3, 95.2  (2,168 requests, avg 1,951 KB)
>     wait=0: 96.2, 95.7, 98.7  (1,626 requests, avg 2,580 KB)
>
>   256 MB threshold
>     stock:  81.0, 88.1, 81.4  (16,291 requests, avg 258 KB)
>     wait=1: 100.7, 99.7, 98.4 (2,257 requests, avg 1,859 KB)
>     wait=0: 101.9, 100.5, 98.7 (1,532 requests, avg 2,738 KB)
>
> WD Blue 500G, copying 1000 x 1 MiB files 2x, then sync, MB/s
>
>   5% threshold
>     stock:  9.44, 9.45
>     wait=1: 9.34, 9.32
>     wait=0: 9.55, 9.58
>
>
> Samsung SSD 870 EVO SATA, copying a 4 GiB file 3x, then sync, MB/s
> (requests and average size are from the third run, which was traced)
>
> The wait=0 runs were on a different day.
>
>   5% threshold
>     stock:  338, 340, 341     (1,460 requests, avg 2,874 KB)
>     wait=1: 333, 339, 339     (1,366 requests, avg 3,071 KB)
>     wait=0: 313, 313, 313     (1,792 requests, avg 2,441 KB)
>
>   256 MB threshold
>     stock:  377, 378, 377     (11,476 requests, avg 366 KB)
>     wait=1: 378, 378, 378     (1,675 requests, avg 2,505 KB)
>     wait=0: 346, 344, 345     (2,278 requests, avg 1,938 KB)
>
> 870 EVO, copying 1000 x 1 MiB files 2x, then sync, MB/s
>
>   5% threshold
>     stock:  9.61, 9.61
>     wait=1: 8.92, 8.92
>     wait=0: 9.61, 9.61
>
> PNY 32G USB 3.0 (usb-storage), copying a 3 GiB file 3x, then sync, MB/s
> (requests and average size are from the third run, which was traced)
>
>   5% threshold
>     stock:  6.4, 6.9, 6.9     (12,481 requests, avg 252 KB)
>     wait=1: 17.5, 17.9, 18.0  (3,720 requests, avg 846 KB)
>     wait=0: 17.9, 13.7, 16.4  (3,809 requests, avg 827 KB)
>
>   256 MB threshold
>     stock:  5.8, 6.1, 6.0     (13,996 requests, avg 225 KB)
>     wait=1: 17.9, 16.4, 14.7  (3,575 requests, avg 881 KB)
>     wait=0: 18.0, 18.2, 17.9  (3,663 requests, avg 860 KB)
>
>
> PNY 32G stick, copying 1000 x 1 MiB files 2x, then sync, MB/s
>
>   5% threshold
>     stock:  5.49, 5.62
>     wait=1: 5.82, 5.62
>     wait=0: 5.66, 5.65
>
> Samsung 64G USB stick (usb-storage),
> copying a 4 GiB file 3x, then sync, MB/s
> (requests and average size are from the third run, which was traced)
>
>   5% threshold
>     stock:  33.0, 33.0, 33.1  (12,725 requests, avg 330 KB)
>     wait=1: 33.2, 33.1, 33.2  (4,521 requests, avg 928 KB)
>     wait=0: 33.1, 33.2, 33.2  (4,583 requests, avg 915 KB)
>
>   256 MB threshold
>     stock:  33.3, 33.3, 33.3  (15,757 requests, avg 266 KB)
>     wait=1: 33.3, 33.5, 33.5  (4,534 requests, avg 925 KB)
>     wait=0: 33.5, 33.6, 33.5  (4,645 requests, avg 903 KB)
>
>
> Samsung 64G stick, copying 1000 x 1 MiB files 2x, then sync, MB/s
>
>   5% threshold
>     stock:  7.34, 7.34
>     wait=1: 7.33, 7.34
>     wait=0: 7.32, 7.35
>
> I was a bit surprised by the improvement on the HDD. I will see if I
> can find a high end HDD.
>
> With the SSD the 870 EVO I did the wait=0 test on a different day.
> Not sure why but it seemed to be slower on the wait=0 test, I am
> blaming the run being on a different day. I think performance is
> probably mostly flat with the fix.
>
>> And maybe it needs to check unmount time (check how many dirty was
>> missing to flush).
>
> wait=0 does come with that downside. If the flusher is already writing
> the file at close, wait=0 skips it and unmount has to write the rest.
> At 5% the 3 GiB file on the PNY stays under the threshold, so the
> flusher doesn't start until the 30 second expiry. That's why stock is
> still slow there and wait=0 behaves like wait=1. The 4 GiB files go
> over it.
>
> PNY 32G stick, 3 GiB file, cp then umount right away,
> average of 3 runs (5% threshold) and 5 runs (256 MB):
>
> 5% threshold   cp returns  dirty at close  umount   total
> stock               485 s            3 MB   0.6 s   485 s
> wait=1              184 s            3 MB   0.8 s   185 s
> wait=0              180 s            3 MB   0.6 s   180 s
>
> 256 MB         cp returns  dirty at close  umount   total
> stock               513 s            3 MB   0.6 s   514 s
> wait=1              176 s            2 MB   0.8 s   176 s
> wait=0              2.6 s        3,004 MB   172 s   174 s
>
>
> WD Blue 500G 5400RPM HDD SATA, 4 GiB file, cp then umount right away,
> average of 3 runs (5% threshold) and 5 runs (256 MB):
>
> 5% threshold   cp returns  dirty at close  umount   total
> stock              47.4 s            3 MB   0.8 s  48.2 s
> wait=1             43.5 s            3 MB   1.2 s  44.7 s
> wait=0              2.2 s        4,064 MB  42.3 s  44.5 s
>
> 256 MB         cp returns  dirty at close  umount   total
> stock              51.3 s            3 MB   0.8 s  52.1 s
> wait=1             44.0 s            2 MB   1.3 s  45.2 s
> wait=0              2.0 s        4,021 MB  43.2 s  45.2 s
>
>
> 870 EVO SSD (internal SATA), 4 GiB file, cp then umount right away,
> average of 3 runs (5% threshold) and 5 runs (256 MB):
>
> 5% threshold   cp returns  dirty at close  in flight  umount   total
> stock              11.9 s            2 MB     362 MB   1.1 s  13.0 s
> wait=1             12.2 s            2 MB       0 MB   0.9 s  13.0 s
> wait=0              1.5 s        4,006 MB      22 MB  12.3 s  13.8 s
>
> 256 MB         cp returns  dirty at close  in flight  umount   total
> stock              11.9 s            3 MB     112 MB   1.0 s  12.9 s
> wait=1             11.9 s            2 MB       0 MB   0.9 s  12.8 s
> wait=0              1.7 s        3,350 MB     180 MB   9.7 s  11.4 s
>
>
> I can type up an actual patch with wait=0 and removing the helper
> that Matheus suggested.

Hm, wait=0 looks like affect umount more than expected. The following is
untested and not perfect though, how about something like this?
(I'm not sure if this is acceptable as generic function though)

Thanks.


/* This want to flush dirty without waiting write completion. */
int writeback_inode(struct inode *inode)
{
	struct writeback_control wbc = {
		.nr_to_write = LONG_MAX,
		.sync_mode = WB_SYNC_ALL,
		.range_start = 0,
		.range_end = LLONG_MAX,
                .for_sync = 1,	/* purpose: don't wait write completion */
	};

	if (!mapping_can_writeback(inode->i_mapping))
		wbc.nr_to_write = 0;

	might_sleep();
	return writeback_single_inode(inode, &wbc);
}
EXPORT_SYMBOL(writeback_inode);


-- 
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

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

end of thread, other threads:[~2026-11-10 10:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-29 17:29 [PATCH RFC] fat: use write_inode_now() on flush to avoid racing the flusher Bryanna Marihugh via B4 Relay
2026-10-29 19:56 ` OGAWA Hirofumi
2026-10-30  4:56   ` Bryanna Marihugh
2026-10-30  5:58     ` OGAWA Hirofumi
2026-10-30  6:21       ` OGAWA Hirofumi
2026-11-10  5:49         ` Bryanna Marihugh
2026-11-10 10:30           ` OGAWA Hirofumi
2026-10-29 20:11 ` Matheus Alves de Almeida
2026-10-30  5:43   ` Bryanna Marihugh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®