perf(virtiofs): batch non-DAX writeback#2122
Merged
fslongjin merged 2 commits intoJul 15, 2026
Merged
Conversation
Buffer writes in the generic page cache only after FUSE_WRITEBACK_CACHE is negotiated, then claim and submit bounded contiguous batches according to the negotiated write and page limits. Preserve Linux-compatible fsync, close, truncate, mmap, invalidation, stable EOF, redirty, short-write, and errseq behavior. Separate terminal writeback completion from generic page-cache workers so host invalidation cannot strand published Writeback pages behind its own waiters. Harden kernel-thread creation and wakeup ordering required by the new worker pools. Add exact FUSE/page-cache counters, benchmark phase reporting, focused FUSE regressions, and root-only kthread and completion-domain selftests. Validated with make kernel -j2, kernel formatting and diff checks, the completion-domain selftest, targeted close/flush coverage, and FuseExtended 69/69 in a DragonOS guest. Signed-off-by: longjin <longjin@dragonos.org>
Member
Author
|
@codex review |
Pass negotiated read, write, page, capability, and effective payload limits through a dedicated stats value object. This keeps the INIT statistics update cohesive and satisfies the project-wide Clippy argument-count lint enforced by make fmt without changing the negotiated values or publication ordering. Signed-off-by: longjin <longjin@dragonos.org>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
FUSE_WRITEBACK_CACHEis negotiatedmax_write,max_pages, and transport scatter-gather limitsRoot cause
The non-DAX write path submitted small synchronous FUSE writes instead of retaining dirty pages and flushing bounded contiguous batches. This amplified request count and daemon round trips, especially for workloads issuing 4 KiB writes followed by fsync.
Writeback also needed explicit ordering and lifetime rules around mmap dirties, truncate and invalidation barriers, close/flush error reporting, and worker startup. In particular, published Writeback pages could not safely share a FIFO completion domain with invalidation workers that may wait for those pages.
Behavior
The buffered path is enabled only after the daemon negotiates
FUSE_WRITEBACK_CACHE; the existing non-writeback path remains available when the capability is absent. Dirty pages are tagged and claimed in bounded scans, submitted in contiguous batches, and completed with generation-aware redirty and error handling.Close and flush behavior follows Linux 6.6 semantics, including
FOPEN_NOFLUSH,NO_OPENwithfh=0, write-before-flush ordering, and writeback error sequencing. Direct I/O, truncate, mmap faults, and host invalidation synchronize through explicit admission and invalidation barriers.Performance
The frozen A1/B/A2 campaign used 9 fresh mounts per point and covered 16/64 MiB files with 4 KiB/128 KiB/1 MiB syscall sizes. All 162 samples completed without short I/O and with correct host hashes. A1 and A2 are the unmodified
origin/masterbaseline; B is this writeback implementation.Raw 64 MiB/4 KiB medians:
The corresponding
data + fsyncp90 values were 22.940337 s for A1, 0.908964 s for B, and 22.937194 s for A2. Using the faster baseline period conservatively, the candidate improves the median by 29.123x and p90 by 25.234x. The maximum A1/A2 median drift across the full matrix was 6.429%, below the frozen 10% rejection gate.Raw aggregate CPU measurements over 2160 MiB per layer:
Compared with the faster baseline CPU rate, the candidate reduces CPU seconds per MiB by 85.292%.
The accepted WRITE diagnostic conservatively included the 64 MiB data file plus a 107-byte manifest. It observed 265 WRITE requests carrying 67,108,971 bytes, for an average payload of 253,241 bytes against the 258,048-byte effective limit (98.137%). Relative to 16,384 4 KiB data writes, the request count decreased by 98.383%.
The latest post-fix 64 MiB/4 KiB guest smoke measured:
The latest smoke completed with correct contents,
short_io=0, and a successful result. The follow-up lint fix only groups the same negotiated statistics fields into a value object and does not alter runtime I/O behavior.CubeSandbox deployment was also checked. Its current shared filesystem is read-only and has writeback disabled, so it does not exercise this P3 writeback path and no CubeSandbox P3 performance claim is made.
Validation
make fmtmake kernel -j2git diff --checkNO_OPENclose/flush regressions passedRelated to #2019.