Skip to content

Improper use of offset in readdir #63

Open
@vasi

Description

@vasi

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions