Skip to content

Commit cece9dc

Browse files
joannekoongakpm00
authored andcommitted
mm: reinstate unconditional writeback start in balance_dirty_pages()
Commit 64dd89a ("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. Link: https://lkml.kernel.org/r/[email protected] Fixes: 64dd89a ("mm/block/fs: remove laptop_mode") Signed-off-by: Joanne Koong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Jan Kara <[email protected]> Acked-by: Johannes Weiner <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 307e0c5 commit cece9dc

1 file changed

Lines changed: 21 additions & 0 deletions

File tree

mm/page-writeback.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,6 +1858,27 @@ static int balance_dirty_pages(struct bdi_writeback *wb,
18581858
break;
18591859
}
18601860

1861+
/*
1862+
* Unconditionally start background writeback if it's not
1863+
* already in progress. We need to do this because the global
1864+
* dirty threshold check above (nr_dirty > gdtc->bg_thresh)
1865+
* doesn't account for these cases:
1866+
*
1867+
* a) strictlimit BDIs: throttling is calculated using per-wb
1868+
* thresholds. The per-wb threshold can be exceeded even when
1869+
* nr_dirty < gdtc->bg_thresh
1870+
*
1871+
* b) memcg-based throttling: memcg uses its own dirty count and
1872+
* thresholds and can trigger throttling even when global
1873+
* nr_dirty < gdtc->bg_thresh
1874+
*
1875+
* Writeback needs to be started else the writer stalls in the
1876+
* throttle loop waiting for dirty pages to be written back
1877+
* while no writeback is running.
1878+
*/
1879+
if (unlikely(!writeback_in_progress(wb)))
1880+
wb_start_background_writeback(wb);
1881+
18611882
mem_cgroup_flush_foreign(wb);
18621883

18631884
/*

0 commit comments

Comments
 (0)