fix(fuse): handle fallocate with non-zero offsets - #1176
Merged
szbr9486 merged 2 commits intoJul 20, 2026
Conversation
yangcx000
self-requested a review
July 17, 2026 14:08
szbr9486
approved these changes
Jul 20, 2026
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
Fix valid FUSE
fallocate()calls returningEIOwhen the allocation range starts at a non-zero offset.Curvine forwarded the POSIX
offsetandlengthdirectly into an internal resize API that only acceptedoffset == 0and interpretedlengthas the final file size. As a result, allocating a range at EOF or inside an existing file failed before reaching the resize path.The fix normalizes the POSIX range into Curvine's target-length representation, preserves the current file size for ranges already covered by the file, and handles
FALLOC_FL_KEEP_SIZEwithout exposing a larger logical size.Minimal Reproducer
Run both supported modes on a Curvine FUSE mount:
Before the fix, both calls failed with
EIO:Root Cause
The FUSE request provides a POSIX allocation range as
offsetpluslength. Curvine's internalFileAllocOptsresize path uses a different representation:offwas required to be zero.lenrepresented the target logical file length, not the range length.The FUSE handler copied the request fields directly:
For any valid non-zero offset,
FileAllocOpts::validate()rejected the operation. The internal error was then returned through FUSE asEIO.Removing only the zero-offset validation would not be sufficient. For example, allocating
[4096, 8192)requires a target length of 8192, while passinglen = 4096could leave the file unchanged or even route the operation as a shrink when the existing file was larger.The handler also needs the latest active-writer length. Master metadata may lag behind bytes already accepted by an open writer, so calculating the target from Master state alone could still produce an incorrect file size.
FALLOC_FL_KEEP_SIZErequires that the allocation endpoint is not exposed throughst_size. Curvine allocates distributed storage lazily when data is written, so this mode does not need a logical metadata resize; writes into the requested range continue to allocate blocks normally.Changes
offset + lengtharithmetic.FALLOC_FL_KEEP_SIZEunder Curvine's lazy allocation model.KEEP_SIZE, invalid ranges, and unsupported modes.KEEP_SIZEallocations.Verification
FALLOC_FL_KEEP_SIZEand the file remaining 4096 bytes.4 passed, 0 failed.cargo fmt --checkpasses.cargo build --locked --release -p curvine-fusepasses.git diff --checkpasses.