vfs: give stable inode numbers from the backend ID - #9837
Draft
biagiop1986 wants to merge 1 commit into
Draft
Conversation
Before this change, `newInode` handed out inode numbers from a process-wide atomic counter, and `newFile`/`newDir` called it every time they built a node. The directory cache drops its nodes when it expires -- `ForgetAll` empties `d.items` -- so the next listing rebuilt them and the same file came back with a different inode number. That is invisible to a local FUSE mount, but not to one re-exported over NFS: the kernel validates its file handles against the inode number, so once the directory cache had expired, clients saw ESTALE for files they still had open. This change derives the inode number from the backend's own ID when the object or directory implements `fs.IDer` and has one, so it stays the same for as long as the object does, no matter how often the node is dropped and rebuilt. Many backends can supply an ID for their objects, e.g., Drive, Onedrive, Box, Dropbox, B2, and Mega. Anything without an ID keeps the counter as before. That includes the local backend, which has no IDs at all, and most directories, since far fewer backends give a directory an ID than give one to an object. The two are kept in separate halves of the uint64 range -- ID-derived numbers have the top bit set, counter ones do not -- so they cannot collide with each other. This complements the earlier fix to make cmd/mount2 report the VFS inode to the kernel at all: that made the number visible, this makes it stable. The ESTALE path itself needs a kernel NFS server so it isn't covered here; the tests check the property it depends on, that a given backend ID always maps to the same inode and that a file keeps its inode across a `ForgetAll`.
3 tasks
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.
newInodeallocates inode numbers from a process-wide atomic counter, andnewFile/newDircall it every time they construct a node. When the directory cache expires,ForgetAllemptiesd.items, so the next listing rebuilds those nodes and the same file comes back with a different inode number.This derives the inode number from the backend's own object ID when the entry implements
fs.IDerand has one, so it stays the same for as long as the object does, however many times the node is dropped and rebuilt.Many backends can supply an object ID - Drive, Onedrive, Box, Dropbox, B2 and Mega among them - plus the wrapping backends (crypt, union, chunker, compress, hasher, cache, combine) which forward it. Anything without an ID keeps the counter exactly as before: that includes
local, which has no IDs at all, and most directories, since far fewer backends give a directory an ID than give one to an object. The two are kept in separate halves of the uint64 range so they cannot collide.This complements #9548, which made
cmd/mount2report the VFS inode to the kernel at all: that made the number visible, this makes it stable.I have opened this as a draft because the following are open to your preference:
md5.Sum([]byte(...))idiom incmd/serve/nfs/cache.go,fs/newfs.goandfs/filter/filter.go. Happy to change it.Linked issue
Fixes #9830
For new or changed backends
Not a backend change.
Testing
vfs/vfs_test.goaddsTestDeriveInode(same ID gives the same inode number, different IDs give different inode numbers, missing or empty ID falls back to the counter), plusTestFileInodeAfterForgetandTestDirInodeAfterForget, which check a file/dir keeps its inode across aForgetAlland that it does not without an ID. I verified the tests fail without the change and pass with it.The ESTALE path itself needs a kernel NFS server, so as with #9548 it is not covered by the local harness.
make quicktestpasses apart fromcmd/mountlibandcmd/serve/s3, which fail on my machine for environmental reasons (macFUSE too old, andflocknot present on macOS); both fail identically on a clean master.Checklist
test_allpasses for this backend and if submitting a new backend can provide a test account for the integration tester - see CONTRIBUTING.md.