fix: free the held cache page on write-path error returns - #487
fix: free the held cache page on write-path error returns#487thweetkomputer wants to merge 1 commit into
Conversation
A data page promoted into the buffer-pool cache (enable_data_page_cache)
is detached and pinned only by the writing task's handle until a
successful WritePageCallback swizzles it into the mapping. Several
write-path error returns dropped that handle without freeing the page:
Handle::~Handle only unpins, so a detached-but-unpinned page becomes
invisible to eviction yet still counts toward the pool limit, permanently
leaking one buffer-pool slot per occurrence. Under sustained I/O errors
the usable page count ratchets down until AllocPage fails and foreground
writes hit OutOfMem even after the fault clears, requiring a restart.
Add WriteTask::ReleaseHeldPage, which frees the page only when releasing
this handle leaves it detached and unpinned (the sole-owner promoted-page
case); double-pinned index writes (the caller keeps a pin) and pages
already linked into the active/free list are left alone. Call it from:
- AppendWritePage's error returns (flush failure, OnDataFileSealed,
AcquireWriteBuffer/TryReserve OutOfMem);
- BatchWriteTask::Pop's five index-build error returns (prev_handle),
guarded by an assert that an empty handle implies OutOfMem;
- WriteTask::WritePage's non-append path -- IouringMgr::WritePage now
takes the page by reference and consumes it only on success, so a
synchronous OpenOrCreateFD failure no longer orphans it.
Three persist regression tests reproduce each site by stuffing a small
buffer pool via fault injection (SubmitMergedWrite, FlushIndexPage,
WritePageBeforeSubmit) and asserting a later healthy write still commits;
each fails with OutOfMem without the fix.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
Walkthrough
ChangesWrite failure cleanup
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
A data page promoted into the buffer-pool cache (
enable_data_page_cache) is detached and pinned only by the writing task's handle until a successfulWritePageCallbackswizzles it into the mapping. Several write-path error returns dropped that handle without freeing the page. SinceHandle::~Handleonly unpins (it never returns the slot to the free list), a detached-but-unpinned page becomes invisible to eviction yet still counts toward the pool limit — permanently leaking one buffer-pool slot per occurrence.Under sustained I/O errors the usable page count ratchets down until
AllocPagefails and foreground writes hitOutOfMemeven after the fault clears, requiring a restart.Fix
Add
WriteTask::ReleaseHeldPage, which frees the page only when releasing this handle leaves itIsDetached() && !IsPinned()(the sole-owner promoted-page case). Double-pinned index writes (the caller keeps a pin) and pages already linked into the active/free list are left untouched. Called from:AppendWritePageerror returns (flush failure,OnDataFileSealed,AcquireWriteBuffer/TryReserveOutOfMem) — append mode.BatchWriteTask::Pop— its five index-build error returns dropprev_handle; guarded by an assert that an empty handle can only mean the index-pageAllocPageitself OutOfMem'd.WriteTask::WritePagenon-append path —IouringMgr::WritePagenow takes the page by reference and consumes it only on success, so a synchronousOpenOrCreateFDfailure no longer orphans the page the caller still owns.Tests
Three
persistregression tests reproduce each site by stuffing a small (8-page) buffer pool via fault injection (SubmitMergedWrite,FlushIndexPage,WritePageBeforeSubmit) and asserting a later healthy write still commits; each fails withOutOfMemwithout the fix. The existingbatch write abort releases pinned index pagestest also caught (and now guards) a null-handle case in the index-page path.Full suites pass:
batch_write(21143 assertions),persist(835),large_value_e2e(442).Summary by CodeRabbit
Bug Fixes
Tests