Commit 04379068 authored by Joanne Koong's avatar Joanne Koong Committed by Andrew Morton
Browse files

mm: start background writeback based on per-wb threshold for strictlimit BDIs

The proactive nr_dirty > gdtc->bg_thresh check in balance_dirty_pages()
only checks the global dirty threshold to start background writeback while
the writer is still free-running, but for strictlimit BDIs (eg fuse), the
per-wb dirty count can exceed the per-wb background threshold while the
global threshold is not yet exceeded, so background writeback for this
case never gets proactively started.

Add a per-wb threshold check for strictlimit BDIs so that background
writeback is started when wb_dirty exceeds wb_bg_thresh, which drains
dirty pages before the writer hits the throttle wall, matching the
proactive behavior that the global check provides for non-strictlimit
BDIs.

fio runs on fuse show about a 3-4% improvement in perf for buffered
writes:
fio --name=writeback_test --ioengine=psync --rw=write --bs=128k \
    --size=2G --numjobs=4 --ramp_time=10 --runtime=20 \
    --time_based --group_reporting=1 --direct=0

Link: https://lore.kernel.org/20260326234629.840938-2-joannelkoong@gmail.com


Signed-off-by: default avatarJoanne Koong <joannelkoong@gmail.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 9ec95329
Loading
Loading
Loading
Loading
+6 −10
Original line number Diff line number Diff line
@@ -1835,7 +1835,9 @@ static int balance_dirty_pages(struct bdi_writeback *wb,
			balance_domain_limits(mdtc, strictlimit);
		}

		if (nr_dirty > gdtc->bg_thresh && !writeback_in_progress(wb))
		if (!writeback_in_progress(wb) &&
		    (nr_dirty > gdtc->bg_thresh ||
		     (strictlimit && gdtc->wb_dirty > gdtc->wb_bg_thresh)))
			wb_start_background_writeback(wb);

		/*
@@ -1862,15 +1864,9 @@ static int balance_dirty_pages(struct bdi_writeback *wb,
		 * 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
		 * doesn't account for the memcg-based throttling case. 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