RE:(2) [RFC PATCH v3 0/2] ext4: speed up fast commit on random writes
Daejun Park <[email protected]>
| Newsgroups | org.kernel.vger.linux-ext4,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260723082515epcms2p18b33139192f8ddf493573817c2d21cc3@epcms2p1> |
On Jul 22, 2026, at 01:27, Andreas Dilger <[email protected]> wrote: > Have you looked at implementing a more dynamic structure like another > extent status tree, rbtree, xarray or or similar instead of having a > fixed-size array? [...] It would be useful to do some testing of how > many separate ranges gets worse than the fallback. Thanks -- I implemented the dynamic structure; it replaces the array and the tunable entirely. v4 tracks the modified ranges in a per-inode rbtree, which answered both of your questions. It can't be the shared extent status tree: I probed whether the shrinker reclaims a mapped es entry for a modified-but-not-yet-committed range, and it does (448 in one short run under mild pressure). That "modified" mark is not re-derivable, so marking the shared tree would silently lose modifications -- the tracker has to own its structure. So it is a private rbtree, reusing ext4's own machinery (generic rb_*, as the extent status tree already does for per-inode ranges) -- idiomatic, no new dependency. The node is a dedicated 32-byte struct with its own slab cache, not extent_status: extent_status carries an 8-byte es_pblk that fast commit never uses, and its cache is SLAB_RECLAIM_ACCOUNT, which would misaccount these non-reclaimable nodes. The rb_root is inline in the inode, so only per-range nodes are allocated. (I also built and compared a maple-tree version: behaviour-identical, within ~15% on memory, denser only at the range counts this series already caps -- so the rbtree, with no dependency, is the choice.) On "how many is too many": the cap is EXT4_FC_SNAPSHOT_MAX_RANGES (2048), the limit the snapshot already enforces on emitted ranges -- reused directly, not a new constant. Each disjoint tracked range snapshots to at least one ADD_RANGE, so a tracked set larger than that can never fit under the snapshot cap: the fast commit would overrun it and fall back regardless. That count is exactly where tracking stops paying off, so at the cap the transaction falls back to a full commit. (Verified: R=4096 disjoint writes/fsync falls back there; R=1024 tracks precisely.) Thanks, Daejun