Description
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:
> readdir(ino = 1, off = 0)
< fuse_reply_buf(size = 60), containing:
< direntry(name = "foo", off = 3000)
< direntry(name = "bar", off = 5000)
< direntry(name = "Iggy", off = 2000)
> readdir(ino = 1, off = 2000)
< fuse_reply buf
< direntry(name = "Iggy", off = 2000)
...
Actual behaviour
FUSE-T calls readdir with the size of the buf from a previous call:
> readdir(ino = 1, off = 0)
< fuse_reply_buf(size = 60), containing:
< direntry(name = "foo", off = 3000)
< direntry(name = "bar", off = 5000)
< direntry(name = "Iggy", off = 2000)
> readdir(ino = 1, off = 60)
????
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 arbitrary offset
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:
READDIR call should return all results in the first pass.
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.