mirror of
https://github.com/kvcache-ai/Mooncake.git
synced 2026-11-05 01:17:55 +00:00
[GH-ISSUE #4345] [Bug][Store] BucketStorageBackend: "O_DIRECT mode enabled" is logged but bucket files are opened buffered (O_DIRECT not set) #1087
Labels
No labels
ascend
auto-closed
bug
bug
CI/Build
Common
documentation
enhancement
feature request
good first issue
help wanted
high priority
MetaX
nightly-failure
pull-request
PyTorch Backend
question
RFC
Roadmap
stale
Store
Tests
Transfer Engine
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/Mooncake#1087
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @cloudomate on GitHub (Sep 27, 2026).
Original GitHub issue: https://github.com/kvcache-ai/Mooncake/issues/4345
Bug Report
Version:
mooncake-transfer-engine-cuda13/mooncake-transfer-engine0.3.13.post1 (PyPI),mooncake_clientreal client, x86_64, Ubuntu 24.04 (kernel 6.8), ext4 on NVMe.Config (store / real client):
Expected: bucket files opened with
O_DIRECT, so the SSD tier bypasses the page cache.This is what #3611 describes as the correct behaviour for
BucketStorageBackend.Actual:
/proc/<mooncake_client pid>/fdinfo/<fd>every 200 ms during a 110 GiB spill, on 3 nodes: 69 distinct open bucket files, all with the same flags:Looks like: the same pattern as #3611 (the flag is stored and logged, but
open()/fcntl()never sets it), here on the bucket backend's write path. PR #3615 fixes the OffsetAllocator vector-I/O path only, and isn't in a release yet (v0.3.14-rc1 predates it).How to reproduce:
for fd in /proc/$(pgrep -x mooncake_client)/fd/*; do readlink $fd | grep -q '\.bucket$' && grep flags /proc/$(pgrep -x mooncake_client)/fdinfo/${fd##*/}; doneImpact:
Before submitting...
@github-actions[bot] commented on GitHub (Sep 27, 2026):
Thanks for opening this issue, @cloudomate!
38678537A maintainer will triage this when possible. To help us respond faster, please include:
Useful links: Documentation · Contributing guide
@he-yufeng commented on GitHub (Sep 27, 2026):
Read the bucket write path on current main (and the 0.3.13.post1 tag, which matches it here). What I found:
The log line is intent, not state:
UringFile's ctor prints "O_DIRECT mode enabled" from itsuse_direct_ioargument without ever checking the fd. Any caller that passestruewithoutO_DIRECTin the open flags logs a lie. Worth a small honesty fix (log fromfcntl(fd, F_GETFL)instead of the flag); I can do that PR.On your actual spill symptom: bucket writes deliberately do not get O_DIRECT today.
BucketStorageBackend::OpenFileonly addsO_DIRECTand constructs aUringFileforFileMode::Read(storage_backend.cpp:3452-3470); writes go through plainPosixFile. So the O_WRONLY fds you sampled are by design, and the page-cache growth you measured is consistent with the code's own comment: O_DIRECT writes are avoided because the 4096-byte alignment padding would corrupt meta-file parsing and waste space on data files. The log lines you saw for bucket files came from the read-mode opens (promotion read-backs), not the write fds you sampled.The interesting discovery while tracing this:
WriteBucketalready contains a complete aligned O_DIRECT write implementation (write_alignedwithalign_up+ zero-padding intoaligned_io_buffer_), gated ondynamic_cast<UringFile*>(file.get())— which can never succeed today, becauseOpenFilenever creates a write-modeUringFile. So the O_DIRECT bucket-write path is fully built but dormant. Enabling it for bucket data writes (keeping meta files buffered, since the padding breaks their parsing) is a real option if the store owners want it, and it matches the direction #3615 took for the allocator backend. That's a storage-hot-path behavior change though, so I'd want @stmatengss's call before writing it.@he-yufeng commented on GitHub (Sep 27, 2026):
One correction to my point 1 above, after auditing every
UringFile(..., true)call site on current main: all five set O_DIRECT in the open flags first (storage_backend.cpp:747, 3469, 3828, 4620, 5546), so on main the log does not actually lie. The version you run (0.3.13.post1) did have the real mismatch in the allocator backend — that was #3611, already fixed and merged in #3615. For bucket files the log only fires on read-mode opens, which do carry O_DIRECT; the fds you sampled with O_WRONLY|O_CLOEXEC were the write-mode opens, which are deliberately buffered and never logged. So the "enabled" log and the no-O_DIRECT fd are two different opens of the same path, not one lying open.That leaves the real actionable from your report: the dormant aligned O_DIRECT write path in WriteBucket, and the design question of whether bucket data writes should bypass the page cache at all (the code comment currently argues no, for meta-file and padding reasons). That's the store owners' call; the instrumentation angle for you would be sampling fds in read mode during promotion hits to confirm O_DIRECT on those.
@cloudomate commented on GitHub (Sep 27, 2026):
Thank you @he-yufeng for tracing this so carefully, and for the follow-up audit of the UringFile(..., true) call sites. It cleared up my misreading. My notes, point by point:
The correction is right. My sampler only ran during the spill, so it only saw the write-mode opens (O_WRONLY|O_CLOEXEC, 69 bucket files across 3 nodes). It never sampled the read-mode opens, which log "O_DIRECT mode enabled" and do carry O_DIRECT. So these were two different opens of the same path, not a log that lies. I'll retitle the issue to match.
The meta-file concern makes sense. Padding to 4096 bytes would break meta-file parsing. Meta files are small, so keeping them buffered costs almost nothing.
For data files the padding cost looks small next to the page cache.
Why this matters in our deployment. We run the store as a shared L3 tier behind SGLang HiCache on GPU nodes that also serve production inference. So predictable memory use on the store nodes matters more to us than peak write throughput.
Offer to help. @stmatengss, if either direction sounds reasonable, I'm happy to test a patch on our setup and report before/after write throughput and page-cache use. The setup is 0.3.13.post1, 3 nodes, ext4 on NVMe, io_uring, RDMA.