From: Salvatore Dipietro <dipiets@amazon.it>
To: <akpm@linux-foundation.org>, <linux-mm@kvack.org>
Cc: <ryan.roberts@arm.com>, <abuehaze@amazon.com>,
<alisaidi@amazon.com>, <blakgeof@amazon.com>,
<dipietro.salvatore@gmail.com>, <rvvandan@amazon.com>,
<viro@zeniv.linux.org.uk>, <brauner@kernel.org>, <jack@suse.cz>,
<linkinjeon@kernel.org>, <sj1557.seo@samsung.com>,
<yuezhang.mo@sony.com>, <miklos@szeredi.hu>,
<agruenba@redhat.com>, <djwong@kernel.org>, <hyc.lee@gmail.com>,
<almaz.alexandrovich@paragon-software.com>, <cem@kernel.org>,
<dlemoal@kernel.org>, <naohiro.aota@wdc.com>, <jth@kernel.org>,
<willy@infradead.org>, <david@kernel.org>, <ljs@kernel.org>,
<liam@infradead.org>, <vbabka@kernel.org>, <rppt@kernel.org>,
<surenb@google.com>, <mhocko@suse.com>, <ziy@nvidia.com>,
<matthew.brost@intel.com>, <joshua.hahnjy@gmail.com>,
<rakie.kim@sk.com>, <byungchul@sk.com>, <gourry@gourry.net>,
<ying.huang@linux.alibaba.com>, <apopple@nvidia.com>,
<ritesh.list@gmail.com>, <linux-fsdevel@vger.kernel.org>,
<linux-kernel@vger.kernel.org>, <exfat@lists.linux.dev>,
<fuse-devel@lists.linux.dev>, <gfs2@lists.linux.dev>,
<linux-xfs@vger.kernel.org>, <ntfs@lists.linux.dev>,
<ntfs3@lists.linux.dev>
Subject: [PATCH 0/2] mm, iomap: account dirty at page granularity for per-block dirty folios
Date: Tue, 27 Oct 2026 11:27:00 +0000 [thread overview]
Message-ID: <20261027112702.3747009-1-dipiets@amazon.it> (raw)
Since iomap gained per-block dirty tracking, a large folio can be
partially dirty: struct iomap_folio_state records exactly which
blocks are dirty, and writeback only writes those ranges. The mm
dirty accounting, however, still charges the whole folio even if a
single block is dirty (up to 512x over-accounting for a 2 MB folio
over 4 KB blocks).
balance_dirty_pages() then throttles writers against a number that
is unrelated to how much data actually needs writing back. On
workloads that repeatedly dirty small ranges of large folios --
e.g. PostgreSQL, which writes mostly 8/16 KB pages -- dirty_thresh
is crossed and writers are throttled long before the real dirty data
justifies it. On the benchmark below, run on v7.3-rc7, the
unpatched kernel charges ~159 TB of dirtied pages while writing
~6 TB to the array, a factor of 27; with this series the dirtied
pages charged match the data actually written.
This series makes iomap charge and discharge the mm dirty counters
per dirty page for folios that carry per-block dirty state, so a
partially dirty large folio is accounted for the dirty part only:
- Patch 1 adds the mm infrastructure: an AS_DIRTY_PER_BLOCK
mapping flag, an @accounted argument to __folio_mark_dirty()
and __filemap_dirty_folio() to skip the generic per-folio
charge, and an address_space_operations::accounted_dirty_pages()
callback used by the discharge and migration paths instead of
folio_nr_pages(). No filesystem opts in, so it is a no-op on
its own.
- Patch 2 makes iomap charge per dirty page from the per-block
dirty bitmap and wires iomap_accounted_dirty_pages() into every
iomap-based filesystem.
This was benchmarked with PostgreSQL using the pgbench simple-update
workload on v7.3-rc7. Average throughput rises 46.8% (139.8k ->
205.2k tps) and run-to-run variability drops from a 23.60% to a
3.98% coefficient of variation: the worst iteration improves from
97.9k to 191.5k tps, while the best gains 8%, 199.4k -> 215.9k.
Ten iterations per kernel, same database and workload (tps):
Kernel Avg Min Max CV iters iters
1-5 6-10
______________________ ______ ______ ______ ______ ______ ______
v7.3-rc7 139.8k 97.9k 199.4k 23.60% 164.4k 115.2k
v7.3-rc7 + this series 205.2k 191.5k 215.9k 3.98% 200.1k 210.2k
On unpatched v7.3-rc7 the worst iteration lands ~51% below the best,
and throughput decays as the run progresses: iterations 6-10 average
30% below iterations 1-5. With this series the decay is gone -- the
second half is similar to the first -- and the coefficient of
variation stays at 3.98%.
The over-accounting has existed since commit 4ce02c679722 ("iomap: Add
per-block dirty state tracking to improve performance"), merged in
v6.6, where the ifs bitmap started recording partial dirty state while
the mm counters kept charging whole folios.
The throughput collapse bisects to the v6.17 readahead series, first
bad commit c4602f9fa77f ("mm/readahead: store folio order in struct
file_ra_state"), which lets readahead stay at the largest folio order
once it has ramped up, so a single dirty block charges far more than
is written. Patch 2 therefore carries:
Fixes: 4ce02c679722 ("iomap: Add per-block dirty state tracking to improve performance")
Cc: stable@vger.kernel.org # v6.17+
Test environment:
Hardware: 2x AWS EC2 m8g.24xlarge
(SUT with 12x 1TB io2, 32000 IOPS each, RAID0, XFS)
OS: AL2023
Kernels: v7.3-rc7, v7.3-rc7 + this series
Database: PostgreSQL 17 (with huge_pages=on)
Workload: pgbench simple-update
1024 clients, 96 threads, 600s duration
scale factor 8470, fillfactor=90, prepared protocol
Runs: 10 iterations per configuration
How to replicate results:
This script starts two AWS EC2 m8g.24xlarge instances (SUT + driver),
then installs, loads and benchmarks PostgreSQL using the
repro-collection repository. To run it:
# Reproducer code (dirty-folio-regression branch):
git clone -b dirty-folio-regression \
https://github.com/aws/repro-collection.git ~/repro-collection
# Concatenate patches 1 and 2 of this series, in order, into one file:
cat 0001-*.patch 0002-*.patch > dirty-per-block.patch
# Setup and start PostgreSQL benchmark:
KERNEL_REPO="https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git" \
KERNEL_BRANCH="v7.3-rc7" \
ITERS=10 \
PLACEMENT_GROUP="pg-test" \
KEY="$HOME/.ssh/id_rsa" \
KEYPAIR="<aws keypair>" \
./repros/repro-postgresql-dirty-folios/folio-reproduce.sh <benchmark name> \
--patch="<path to dirty-per-block.patch>"
Salvatore Dipietro (2):
mm: add infrastructure for per-dirty-page accounting
mm, iomap: account dirty at page granularity for per-block dirty
folios
fs/buffer.c | 4 +-
fs/exfat/inode.c | 1 +
fs/fuse/file.c | 1 +
fs/gfs2/aops.c | 1 +
fs/iomap/buffered-io.c | 167 ++++++++++++++++++++++++++++++++++++++--
fs/ntfs/aops.c | 2 +
fs/ntfs3/inode.c | 2 +
fs/xfs/xfs_aops.c | 1 +
fs/zonefs/file.c | 1 +
include/linux/fs.h | 7 ++
include/linux/iomap.h | 1 +
include/linux/pagemap.h | 20 ++++-
mm/internal.h | 3 +
mm/migrate.c | 17 +++-
mm/page-writeback.c | 91 +++++++++++++++++-----
15 files changed, 286 insertions(+), 33 deletions(-)
base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
--
2.50.1
AMAZON DEVELOPMENT CENTER ITALY SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2504859, Capitale Sociale: 10.000 EUR i.v., Cod. Fisc. e P.IVA 10100050961, Societa con Socio Unico
next reply other threads:[~2026-10-27 11:27 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-27 11:27 Salvatore Dipietro [this message]
2026-10-27 11:27 ` [PATCH 1/2] mm: add infrastructure for per-dirty-page accounting Salvatore Dipietro
2026-10-27 11:27 ` [PATCH 2/2] mm, iomap: account dirty at page granularity for per-block dirty folios Salvatore Dipietro
2026-10-27 12:22 ` [PATCH 0/2] " David Hildenbrand (Arm)
2026-10-27 13:45 ` Kiryl Shutsemau
2026-10-27 13:59 ` Pedro Falcato
2026-10-27 23:10 ` [syzbot ci] " syzbot ci
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261027112702.3747009-1-dipiets@amazon.it \
--to=dipiets@amazon.it \
--cc=abuehaze@amazon.com \
--cc=agruenba@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=alisaidi@amazon.com \
--cc=almaz.alexandrovich@paragon-software.com \
--cc=apopple@nvidia.com \
--cc=blakgeof@amazon.com \
--cc=brauner@kernel.org \
--cc=byungchul@sk.com \
--cc=cem@kernel.org \
--cc=david@kernel.org \
--cc=dipietro.salvatore@gmail.com \
--cc=djwong@kernel.org \
--cc=dlemoal@kernel.org \
--cc=exfat@lists.linux.dev \
--cc=fuse-devel@lists.linux.dev \
--cc=gfs2@lists.linux.dev \
--cc=gourry@gourry.net \
--cc=hyc.lee@gmail.com \
--cc=jack@suse.cz \
--cc=joshua.hahnjy@gmail.com \
--cc=jth@kernel.org \
--cc=liam@infradead.org \
--cc=linkinjeon@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-xfs@vger.kernel.org \
--cc=ljs@kernel.org \
--cc=matthew.brost@intel.com \
--cc=mhocko@suse.com \
--cc=miklos@szeredi.hu \
--cc=naohiro.aota@wdc.com \
--cc=ntfs3@lists.linux.dev \
--cc=ntfs@lists.linux.dev \
--cc=rakie.kim@sk.com \
--cc=ritesh.list@gmail.com \
--cc=rppt@kernel.org \
--cc=rvvandan@amazon.com \
--cc=ryan.roberts@arm.com \
--cc=sj1557.seo@samsung.com \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=viro@zeniv.linux.org.uk \
--cc=willy@infradead.org \
--cc=ying.huang@linux.alibaba.com \
--cc=yuezhang.mo@sony.com \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox