-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improper use of offset in readdir #63
Comments
As far as I remember there was a reason for such behavior related to NFS macOS client implementation. If I'm not mistaken macOS expects all readdir entries to be returned in a single pass. Your argument is valid however. I think it should be possible to do a workaround by calling FUSE READDIR multiple times. I'll try to correct this. |
Dave, |
Looks good! Thank you for fixing this |
I am writing my first FS running FUSE-T 1.0.41 and MacOS 14.6.1, I have a similar problem. I want to expose 65536 files to my root folder but when It requires 64 readdir requests to complete. Using a log I know I pass and receive my valid offset of the work done matches the expectation. The problem is the right after the directory is released it is hit with another open request followed by 64 readdir calls then a close then an open and the loop never ends. I need to force kill my program otherwise I may end up with a corrupted Finder. It even crashed my Mac... I tried to see in the documentation and examples if I missed a call or signal that tells its over but could not figure it out. This is my filesystem's code It creates enormous files with static random data that can be address directly. I already filed a bug report with apple for letting me using 64 bit offsets but limit effective file size description to 63 bits. Fully deployed one generator create 1 yobibyte of fully addressable random bytes. |
Expected behaviour
FUSE-T should call readdir with an
offset
value returned from a previous call to readdir. For example, the following sequence of calls and return values:Actual behaviour
FUSE-T calls readdir with the size of the buf from a previous call:
Explanation
The FUSE readdir op is documented to take an
offset
parameter, whose value must be an offset previously returned in a direntry by an earlier call to readdir. That means the filesystem can simply provide an arbitraryoffset
value, and use it later—it doesn't have to correspond to a real byte-offset in memory or the FUSE protocol or anywhere else. For example, look at this comment from the sapling filesystem, which talks about returning a hash as the offset.FUSE-T's out-of-spec behaviour is semi-documented in the FUSE-T wiki, which says:
However, this can't be guaranteed by the filesystem. The caller of readdir sets a maximum size, which a sufficiently large directory may exceed.
Impact
When I attempt to use my filesystem, squashfuse with FUSE-T, listing directories yields an error. This is because squashfuse has never seen the offset that FUSE-T provides on the second call to readdir, and so is unable to figure out where it should start listing.
Workarounds
It's possible for filesystems to respect FUSE-T's out-of-spec offsets. For example, see this PR for squashfuse . However, this requires either using sub-optimal code for other FUSE implementations, or making whoever is building the filesystem select which behaviour to use.
If FUSE-T can't fix readdir quickly, it would at least be nice to provide some way for filesystems to automatically detect this improper use of offset, either at runtime or build-time.
The text was updated successfully, but these errors were encountered: