Closed wwylele closed 5 years ago
Wow, thanks a lot for the detailed description and analysis. This sounds very plausible to me.
/ping @illicitonion maybe you want to have a look too since you updated this part of the code in #105?
This seems pretty reasonable, and definitely has more research and justification put into it than I've done myself.
I am using libfuse (fuse_lowleve_ops) documentation as the reference, assuming both rust-fuse and libfuse are thin layers on top of the data communication without altering values like +1 or -1.
The doc of
fuse_add_direntry
(assuming equivalent to ReplyDirectory::add) states thatoff
(offset
) is the offset of the next entry, and it does not need to be the actual physical position (read: an element index of a continuous array). This value is passed to the nextreaddir
call as theoffset
parameter. According to the doc ofreaddir
, "readdir() should skip over entries coming before the position defined by the off_t value." (read: the entry defined atoffset
should be returned in this call). The most intuitive design, when the entry forms a continuous array, is to use theoffset
as the index of the first entry that is going to be read in {the next call} (forreply.add
) / {this call} (forreaddir
). This code change is to adopt this intuitive design.The old code is not completely wrong. It almost works, but in a different way, which exploits the fact that "offset does not need to be the actual physical position". Here are two tables showing how exactly the old and the new approach work
The old code:
reply.add
offset
written toreply.add
offset
passed to the nextreaddir
readdir
The new code:
reply.add
offset
written toreply.add
offset
passed to the nextreaddir
readdir
As shown in the table, the old code would give wrong result if the first
readdir
only read one entry at 0. This bug wasn't caught probably because callers rarely only read one entry for one call.