feat(ext4): implement recovery-safe delayed allocation - #2160
Conversation
Introduce a reservation-backed delayed-allocation pipeline that keeps foreground admission, PageCache ownership, ext4 mapping, journal publication, and durable EOF updates in one explicit protocol. - reserve data and extent metadata capacity before publishing dirty pages, with mount-scoped linear leases and fail-stop accounting invariants - serialize per-inode append writeback through opaque capabilities, FIFO claims, stable dirty certificates, and bounded journal credit/extent-node pools - publish initialized data, extents, inode size, and timestamps with crash-safe journal ordering and orphan recovery coverage - coordinate truncate, fsync, mmap, reclaim, eviction, and unmount with admission closure, lifecycle ownership, queue draining, and errseq reporting - strengthen PageCache writeback generations, cancellation, deferred retry, MM fault handoff, and post-commit population semantics - add host power-loss fault injection plus dunitest coverage for queue ordering, inode identity, writeback accounting, sync ranges, and memory locking Signed-off-by: longjin <longjin@dragonos.org>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1862b51ed9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Separate the oversized page cache implementation into focused mapping, read-DMA, runtime self-test, and writeback modules while retaining the existing parent facade and public paths. - keep PageCacheManager's Weak<PageCache> ownership model and external API unchanged - isolate VMA invalidation and truncate coordination from cache membership operations - colocate DMA reservation and writeback state machines with their lifecycle helpers - constrain cross-module protocol access to the minimum page-cache-local visibility - preserve all locks, atomic orderings, wait predicates, error paths, and drop semantics Validated with make fmt, make kernel, symbol/declaration equivalence checks, and targeted 2-vCPU QEMU dunitest coverage for page-cache accounting, mmap truncate, sync_file_range, errseq reporting, ext4 I/O, and FUSE.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 10206eb00b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Aggregate contiguous per-inode delayed-allocation entries at the writeback boundary so a bounded batch shares data flush and journal commit costs without weakening foreground space guarantees. - carry one dirty-incarnation certificate and reservation per page through PageCache selection, ext4 FIFO claim, rollback, completion, and terminal failure paths - let the lower mapper consume fragmented physical allocations in one transaction with transaction-aware extent staging and conservative pre-claim credit bounds - query and clear a partial durable EOF tail before staging a promoted extent root, preserving the single successful data flush - make owner-free Claimed admission waits passive and interruptible while keeping published writeback and journal ownership non-cancellable - extend recovery fault injection for real batch submission, sparse forwarding, extent growth and split/merge, partial EOF root promotion, and I/O failure boundaries Signed-off-by: longjin <longjin@dragonos.org>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a2415cc5fc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Preserve frozen range ownership across ordinary reclaim and writeback races by excluding tagged pages, serializing Legacy claims with invalidation, and assigning every Writeback transition a unique incarnation. Replace yield-based tagged retry loops with exact incarnation completion continuations. Dispatch retries from success, failure, detach, and deferred completion paths without blocking shared workers or allocating in infallible completion paths. Propagate mapping errseq failures through O_SYNC and O_DSYNC writes, restore delayed-allocation admission after a failed sibling mount, and make FIFO claim admission constant-time. Add PageCache incarnation/invalidation regression coverage and synchronous-write errseq dunitests. Signed-off-by: longjin <longjin@dragonos.org>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dc459b997d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dc459b997d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Replace the global mount registry critical section with a short lookup of a per-device mount domain. Keep journal recovery and delayed-allocation draining serialized only against mounts of the same block device. Restore delayed-allocation admission through an RAII rollback owner on every failed sibling-mount path, including failures while draining existing owners. Preserve fail-stop fencing while allowing healthy mounts with pending queues to resume. Make O_DIRECT reads persist only the FIFO prefix needed to reach delayed pages overlapping the requested range, then write back eager dirty pages in that range. This matches Linux range-based direct-read coherence without draining an unrelated append tail. Validated with make fmt, make kernel, and the 31-case ext4_inode_identity guest suite. Signed-off-by: longjin <longjin@dragonos.org>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0b42dcfee6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Release the mapping invalidation writer between bounded dirty-tag scan chunks so large sync ranges do not stall file faults and other mapping operations for the complete scan. Serialize only competing freeze scanners across chunk boundaries to preserve epoch ownership. Resample the writeback incarnation frontier under the final exclusion window so ordinary claims which run between chunks remain covered by the frozen operation. Add a deterministic runtime self-test which queues an invalidation reader at the initial freeze boundary and verifies that it acquires before the unscanned tail is tagged. Validated with make fmt, make kernel, page_cache_accounting, sync_file_range, ext4_inode_identity, and repeated proc_self_exec_cmdline guest tests. Signed-off-by: longjin <longjin@dragonos.org>
|
@codex review |
|
Codex Review: Didn't find any major issues. 🚀 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
Ctrl+Cdoes not leave APT helpers blocked behind writeback progressRoot cause
The original eager ext4 path had no ownership protocol spanning foreground space admission, PageCache dirty generations, filesystem allocation, journal publication, and inode lifecycle transitions. Delayed allocation added without such a protocol could expose late capacity failures, stale completion, out-of-order EOF publication, and ambiguous retry ownership around journal commit.
The initial recovery-safe implementation correctly established per-page reservations and publication ownership, but it also forced each 4 KiB page through its own data flush and full journal transaction. That reduced an 8 MiB
dd conv=fsyncworkload to about 147 kB/s and a 31.9 MB coldapt updateto 8m22s. A foreground writer waiting behind aClaimedqueue head also reused an uninterruptible writeback wait before it owned a reservation, so SIGINT could leave APTstoreandhttphelpers alive for tens of seconds.The PageCache implementation had additionally grown beyond 11,000 lines while accumulating independent mapping, DMA, runtime self-test, and writeback state machines, making lock and lifetime boundaries difficult to audit.
Implementation
Reservation-backed delayed allocation
Batched writeback
Progress, signals, and lifecycle
Claimedadmission use a passive interruptible progress wait because the caller has not yet created a reservation ownerPageCache module organization
PageCacheManageras the existingWeak<PageCache>facade used by MM, VFS, ext4, tmpfs, FUSE, readahead, and reclaimmkcleancoordination topage_cache/mapping.rspage_cache/read_dma.rspage_cache/selftest.rspage_cache/writeback.rsThe parent
page_cache.rsis reduced from approximately 11,543 lines to approximately 3,272 lines. Mechanical equivalence checks found the same 372 functions and 73 type declarations before and after the split, with unchangedunsafe,cfg(test), and dead-code allowance counts.Recovery and regression coverage
The host recovery suite now exercises the production batch API rather than a parallel test-only planner, including:
e2fsckvalidation at every enumerated persistence pointThe combined partial-EOF/root-promotion test verifies the old prefix, zeroed tail and logical hole, new payload, metadata-node allocation, and final filesystem consistency.
Performance and user impact
Measured in a 2-vCPU QEMU guest using a newly generated ext4 rootfs and USTC APT sources:
dd conv=fsyncapt update, 31.9 MBapt,http,store, orgpgvprocess remainedThe optimization does not remove required flushes, disable journaling, enlarge dirty limits, modify TTY/PGID signal delivery, require a physically contiguous allocation, or fall back to eager allocation to hide failures.
Validation
Static and host validation:
make fmt— passed, including kernel all-feature Clippy with no new warningmake kernel— passedcargo test --manifest-path kernel/crates/another_ext4/Cargo.toml --features test-api— 153 passedrecovery_fault_injectionmatrix — passedgit diff --check— passedTargeted 2-vCPU QEMU validation:
normal/page_cache_accounting— 1/1 passednormal/mmap_truncate_cow— 2/2 passednormal/sync_file_range— 4/4 passednormal/errseq_writeback_reporting— 6/6 passedfuse/fuse_extended— 70/70 passednormal/ext4_inode_identity— all 30 production I/O, mmap, truncate, FIFO, fsync-frontier, and remount cases passede2fsck -fnafter clean shutdown — passed all five phases with no errorTwo independent adversarial reviews covered architecture, responsibility boundaries, lock ordering, redundancy, performance, recovery, exactly-once ownership, signal handling, security, workaround risk, and overdesign. Their actionable findings—the partial-EOF transaction-view ordering issue and unnecessary Legacy certificate allocation—were fixed and re-reviewed with no remaining blocker.
Current status