public inbox for linux-mm@kvack.org
 help / color / mirror / Atom feed
* [PATCH v2 0/1] mm: reinstate unconditional writeback start in balance_dirty_pages()
@ 2026-03-26 21:51 Joanne Koong
  2026-03-26 21:51 ` [PATCH v2 1/1] " Joanne Koong
  0 siblings, 1 reply; 6+ messages in thread
From: Joanne Koong @ 2026-03-26 21:51 UTC (permalink / raw)
  To: akpm; +Cc: jack, hch, hannes, willy, linux-mm, linux-fsdevel

Changelog
--------
v1: https://lore.kernel.org/linux-fsdevel/20260326001337.828947-1-joannelkoong@gmail.com/
v1 -> v2:
* fix it by bringing back the removed logic instead of the strictlimit wb
  check (Jan and Christoph)

Joanne Koong (1):
  mm: reinstate unconditional writeback start in balance_dirty_pages()

 mm/page-writeback.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

-- 
2.52.0



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

* [PATCH v2 1/1] mm: reinstate unconditional writeback start in balance_dirty_pages()
  2026-03-26 21:51 [PATCH v2 0/1] mm: reinstate unconditional writeback start in balance_dirty_pages() Joanne Koong
@ 2026-03-26 21:51 ` Joanne Koong
  2026-03-27  0:54   ` Andrew Morton
                     ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Joanne Koong @ 2026-03-26 21:51 UTC (permalink / raw)
  To: akpm; +Cc: jack, hch, hannes, willy, linux-mm, linux-fsdevel

Commit 64dd89ae01f2 ("mm/block/fs: remove laptop_mode") removed this
unconditional writeback start from balance_dirty_pages():

       if (unlikely(!writeback_in_progress(wb)))
	       wb_start_background_writeback(wb);

This logic needs to be reinstated to prevent performance regressions for
strictlimited BDIs and memcg setups. The problem occurs because:

a) For strictlimited BDIs, throttling is calculated using per-wb
thresholds. The per-wb threshold can be exceeded even when the global
dirty threshold was not exceeded (nr_dirty < gdtc->bg_thresh)

b) For memcg-based throttling, memcg uses its own dirty count /
thresholds and can trigger throttling even when the global threshold
isn't exceeded

Without the unconditional writeback start, IO is throttled as it waits
for dirty pages to be written back but there is no writeback running.
This leads to severe stalls. On fuse, buffered write performance
dropped from 1400 MiB/s to 2000 KiB/s.

Reinstate the unconditional writeback start so that writeback is
guaranteed to be running whenever IO needs to be throttled.

Fixes: 64dd89ae01f2 ("mm/block/fs: remove laptop_mode")
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
 mm/page-writeback.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 601a5e048d12..c1a4b32af1a7 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1858,6 +1858,27 @@ static int balance_dirty_pages(struct bdi_writeback *wb,
 			break;
 		}
 
+		/*
+		 * Unconditionally start background writeback if it's not
+		 * already in progress. We need to do this because the global
+		 * dirty threshold check above (nr_dirty > gdtc->bg_thresh)
+		 * doesn't account for these cases:
+		 *
+		 * a) strictlimit BDIs: throttling is calculated using per-wb
+		 * thresholds. The per-wb threshold can be exceeded even when
+		 * nr_dirty < gdtc->bg_thresh
+		 *
+		 * b) memcg-based throttling: memcg uses its own dirty count and
+		 * thresholds and can trigger throttling even when global
+		 * nr_dirty < gdtc->bg_thresh
+		 *
+		 * Writeback needs to be started else the writer stalls in the
+		 * throttle loop waiting for dirty pages to be written back
+		 * while no writeback is running.
+		 */
+		if (unlikely(!writeback_in_progress(wb)))
+			wb_start_background_writeback(wb);
+
 		mem_cgroup_flush_foreign(wb);
 
 		/*
-- 
2.52.0



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

* Re: [PATCH v2 1/1] mm: reinstate unconditional writeback start in balance_dirty_pages()
  2026-03-26 21:51 ` [PATCH v2 1/1] " Joanne Koong
@ 2026-03-27  0:54   ` Andrew Morton
  2026-03-27  6:11   ` Christoph Hellwig
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Andrew Morton @ 2026-03-27  0:54 UTC (permalink / raw)
  To: Joanne Koong; +Cc: jack, hch, hannes, willy, linux-mm, linux-fsdevel

On Thu, 26 Mar 2026 14:51:27 -0700 Joanne Koong <joannelkoong@gmail.com> wrote:

> Commit 64dd89ae01f2 ("mm/block/fs: remove laptop_mode") removed this
> unconditional writeback start from balance_dirty_pages():
> 
>        if (unlikely(!writeback_in_progress(wb)))
> 	       wb_start_background_writeback(wb);
> 
> This logic needs to be reinstated to prevent performance regressions for
> strictlimited BDIs and memcg setups. The problem occurs because:
> 
> a) For strictlimited BDIs, throttling is calculated using per-wb
> thresholds. The per-wb threshold can be exceeded even when the global
> dirty threshold was not exceeded (nr_dirty < gdtc->bg_thresh)
> 
> b) For memcg-based throttling, memcg uses its own dirty count /
> thresholds and can trigger throttling even when the global threshold
> isn't exceeded
> 
> Without the unconditional writeback start, IO is throttled as it waits
> for dirty pages to be written back but there is no writeback running.
> This leads to severe stalls. On fuse, buffered write performance
> dropped from 1400 MiB/s to 2000 KiB/s.
> 
> Reinstate the unconditional writeback start so that writeback is
> guaranteed to be running whenever IO needs to be throttled.

Thanks, I queued this in mm.git's mm-hotfixes-unstable branch for test
and review.  This starts it on the track to mainline before the 7.0
release.

I assume we want to be prompt with this because the fuse regression
sounds pretty horrid.


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

* Re: [PATCH v2 1/1] mm: reinstate unconditional writeback start in balance_dirty_pages()
  2026-03-26 21:51 ` [PATCH v2 1/1] " Joanne Koong
  2026-03-27  0:54   ` Andrew Morton
@ 2026-03-27  6:11   ` Christoph Hellwig
  2026-03-27 16:04   ` Jan Kara
  2026-03-27 16:24   ` Johannes Weiner
  3 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2026-03-27  6:11 UTC (permalink / raw)
  To: Joanne Koong; +Cc: akpm, jack, hch, hannes, willy, linux-mm, linux-fsdevel

Looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>



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

* Re: [PATCH v2 1/1] mm: reinstate unconditional writeback start in balance_dirty_pages()
  2026-03-26 21:51 ` [PATCH v2 1/1] " Joanne Koong
  2026-03-27  0:54   ` Andrew Morton
  2026-03-27  6:11   ` Christoph Hellwig
@ 2026-03-27 16:04   ` Jan Kara
  2026-03-27 16:24   ` Johannes Weiner
  3 siblings, 0 replies; 6+ messages in thread
From: Jan Kara @ 2026-03-27 16:04 UTC (permalink / raw)
  To: Joanne Koong; +Cc: akpm, jack, hch, hannes, willy, linux-mm, linux-fsdevel

On Thu 26-03-26 14:51:27, Joanne Koong wrote:
> Commit 64dd89ae01f2 ("mm/block/fs: remove laptop_mode") removed this
> unconditional writeback start from balance_dirty_pages():
> 
>        if (unlikely(!writeback_in_progress(wb)))
> 	       wb_start_background_writeback(wb);
> 
> This logic needs to be reinstated to prevent performance regressions for
> strictlimited BDIs and memcg setups. The problem occurs because:
> 
> a) For strictlimited BDIs, throttling is calculated using per-wb
> thresholds. The per-wb threshold can be exceeded even when the global
> dirty threshold was not exceeded (nr_dirty < gdtc->bg_thresh)
> 
> b) For memcg-based throttling, memcg uses its own dirty count /
> thresholds and can trigger throttling even when the global threshold
> isn't exceeded
> 
> Without the unconditional writeback start, IO is throttled as it waits
> for dirty pages to be written back but there is no writeback running.
> This leads to severe stalls. On fuse, buffered write performance
> dropped from 1400 MiB/s to 2000 KiB/s.
> 
> Reinstate the unconditional writeback start so that writeback is
> guaranteed to be running whenever IO needs to be throttled.
> 
> Fixes: 64dd89ae01f2 ("mm/block/fs: remove laptop_mode")
> Signed-off-by: Joanne Koong <joannelkoong@gmail.com>

Looks good. Feel free to add:

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

								Honza

> ---
>  mm/page-writeback.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/mm/page-writeback.c b/mm/page-writeback.c
> index 601a5e048d12..c1a4b32af1a7 100644
> --- a/mm/page-writeback.c
> +++ b/mm/page-writeback.c
> @@ -1858,6 +1858,27 @@ static int balance_dirty_pages(struct bdi_writeback *wb,
>  			break;
>  		}
>  
> +		/*
> +		 * Unconditionally start background writeback if it's not
> +		 * already in progress. We need to do this because the global
> +		 * dirty threshold check above (nr_dirty > gdtc->bg_thresh)
> +		 * doesn't account for these cases:
> +		 *
> +		 * a) strictlimit BDIs: throttling is calculated using per-wb
> +		 * thresholds. The per-wb threshold can be exceeded even when
> +		 * nr_dirty < gdtc->bg_thresh
> +		 *
> +		 * b) memcg-based throttling: memcg uses its own dirty count and
> +		 * thresholds and can trigger throttling even when global
> +		 * nr_dirty < gdtc->bg_thresh
> +		 *
> +		 * Writeback needs to be started else the writer stalls in the
> +		 * throttle loop waiting for dirty pages to be written back
> +		 * while no writeback is running.
> +		 */
> +		if (unlikely(!writeback_in_progress(wb)))
> +			wb_start_background_writeback(wb);
> +
>  		mem_cgroup_flush_foreign(wb);
>  
>  		/*
> -- 
> 2.52.0
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR


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

* Re: [PATCH v2 1/1] mm: reinstate unconditional writeback start in balance_dirty_pages()
  2026-03-26 21:51 ` [PATCH v2 1/1] " Joanne Koong
                     ` (2 preceding siblings ...)
  2026-03-27 16:04   ` Jan Kara
@ 2026-03-27 16:24   ` Johannes Weiner
  3 siblings, 0 replies; 6+ messages in thread
From: Johannes Weiner @ 2026-03-27 16:24 UTC (permalink / raw)
  To: Joanne Koong; +Cc: akpm, jack, hch, willy, linux-mm, linux-fsdevel

On Thu, Mar 26, 2026 at 02:51:27PM -0700, Joanne Koong wrote:
> Commit 64dd89ae01f2 ("mm/block/fs: remove laptop_mode") removed this
> unconditional writeback start from balance_dirty_pages():
> 
>        if (unlikely(!writeback_in_progress(wb)))
> 	       wb_start_background_writeback(wb);
> 
> This logic needs to be reinstated to prevent performance regressions for
> strictlimited BDIs and memcg setups. The problem occurs because:
> 
> a) For strictlimited BDIs, throttling is calculated using per-wb
> thresholds. The per-wb threshold can be exceeded even when the global
> dirty threshold was not exceeded (nr_dirty < gdtc->bg_thresh)
> 
> b) For memcg-based throttling, memcg uses its own dirty count /
> thresholds and can trigger throttling even when the global threshold
> isn't exceeded
> 
> Without the unconditional writeback start, IO is throttled as it waits
> for dirty pages to be written back but there is no writeback running.
> This leads to severe stalls. On fuse, buffered write performance
> dropped from 1400 MiB/s to 2000 KiB/s.
> 
> Reinstate the unconditional writeback start so that writeback is
> guaranteed to be running whenever IO needs to be throttled.
> 
> Fixes: 64dd89ae01f2 ("mm/block/fs: remove laptop_mode")
> Signed-off-by: Joanne Koong <joannelkoong@gmail.com>

Thanks for the fix. This was a combination of the old comment and my
overly hasty read of the existing dirty > bg_thresh &&
!writeback_in_progress() block. The patch looks good to me.

Acked-by: Johannes Weiner <hannes@cmpxchg.org>


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

end of thread, other threads:[~2026-03-27 16:24 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-26 21:51 [PATCH v2 0/1] mm: reinstate unconditional writeback start in balance_dirty_pages() Joanne Koong
2026-03-26 21:51 ` [PATCH v2 1/1] " Joanne Koong
2026-03-27  0:54   ` Andrew Morton
2026-03-27  6:11   ` Christoph Hellwig
2026-03-27 16:04   ` Jan Kara
2026-03-27 16:24   ` Johannes Weiner

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