fix(fuse): update ctime for futimens#1296
Merged
Merged
Conversation
Persist an independent metadata change timestamp across master storage, journal replay, RPC transport, and FUSE replies. Preserve compatibility with existing bincode inode layouts and legacy peers that do not send ctime.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes POSIX ctime reporting for FUSE futimens() when metadata changes without changing mtime, by introducing an independent metadata-change timestamp that is persisted, journal-replayed, transported over RPC, and surfaced via FUSE attributes.
Changes:
- Introduces an internal persisted
ctimerepresentation (via an internal xattr key) and aFileStatus::ctime()accessor with legacy fallback tomtime. - Ensures Master
set_attrrecords an operation-timectimeand propagates it through journaling/replay and inode persistence without changing the bincode inode layout. - Extends RPC (
FileStatusProto) to carry optionalctimeand updates FUSE attribute conversion and active-writer merge logic to preserve newerctime.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| curvine-server/src/master/meta/inode/mod.rs | Extends the Inode trait with ctime() support. |
| curvine-server/src/master/meta/inode/inode_view.rs | Applies/reads internal ctime during set_attr and adds unit tests for omit-mtime scenarios and replay. |
| curvine-server/src/master/meta/inode/inode_file.rs | Reads ctime from internal persisted xattr with fallback to mtime. |
| curvine-server/src/master/meta/inode/inode_dir.rs | Reads ctime from internal persisted xattr with fallback to mtime. |
| curvine-server/src/master/meta/fs_dir.rs | Stamps ctime at Master set_attr time and logs it for journal replay. |
| curvine-fuse/src/fuse_utils.rs | Uses FileStatus::ctime() to populate FUSE ctime and adds a preservation test. |
| curvine-fuse/src/fs/state/node_state.rs | Avoids overwriting a newer ctime when merging active-writer mtime. |
| curvine-common/src/utils/proto_utils.rs | Adds ctime to protobuf encoding/decoding and hides internal ctime from protobuf xattr maps. |
| curvine-common/src/state/opts.rs | Preserves internal ctime across recursive setattr via child_opts(). |
| curvine-common/src/state/mod.rs | Re-exports INTERNAL_CTIME_XATTR. |
| curvine-common/src/state/file_status.rs | Introduces INTERNAL_CTIME_XATTR and FileStatus::ctime() accessor. |
| curvine-common/proto/common.proto | Adds optional ctime field to FileStatusProto. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
szbr9486
reviewed
Jul 24, 2026
szbr9486
reviewed
Jul 24, 2026
szbr9486
reviewed
Jul 24, 2026
szbr9486
approved these changes
Jul 25, 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 FUSE
futimens()failing to updatectimewhen metadata changes without changingmtime.Curvine now tracks an independent metadata change timestamp across Master persistence, journal replay, RPC transport, and FUSE attribute replies.
Root cause
Curvine's metadata model only exposed
atimeandmtime. The FUSE attribute conversion derivedctimedirectly frommtime.When
futimens()updatedatimewhile specifyingUTIME_OMITformtime, the metadata operation succeeded, but the returnedctimeremained unchanged becausemtimehad not changed.The failure is reproduced by xfstests
generic/221:Before this fix:
Fix approach
ctimewhenever the Master appliessetattr.ctime.ctimefield toFileStatusProto.mtimewhen communicating with legacy peers or backends that do not providectime.ctime.The internal persisted key starts with a NUL byte, which cannot occur in a FUSE xattr name, preventing collisions with user-visible extended attributes.
Changes
curvine-common/proto/common.protoctimetoFileStatusProtocurvine-common/src/state/file_status.rscurvine-common/src/state/opts.rscurvine-common/src/utils/proto_utils.rscurvine-server/src/master/meta/fs_dir.rscurvine-server/src/master/meta/inode/*curvine-fuse/src/fuse_utils.rsstat(2)now reports POSIX-compatible ctimecurvine-fuse/src/fs/state/node_state.rsTest verified
futimensC reproducergeneric/221Ran: generic/221,Passed all 1 testscargo test -p curvine-common --libcargo test -p curvine-server --libcargo test -p curvine-fuse --lib -- --test-threads=1cargo check --workspacemake formatgit diff --checkAfter the fix: