linuxfilesystemsfuse

fuse: Setting offsets for the filler function in readdir


I am implementing a virtual filesystem using the fuse, and need some understanding regarding the offset parameter in readdir.

Earlier we were ignoring the offset and passing 0 in the filler function, in which case the kernel should take care.

Our filesystem database, is storing: directory name, filelength, inode number and parent inode number.

How do i calculate get the offset?

Then is the offset of each components, equal to their size sorted in incremental form of their inode number? What happens is there is a directory inside a directory, is the offset in that case equal to the sum of the files inside?

Example: in case the dir listing is - a.txt b.txt c.txt
And inode number of a.txt=3, b.txt=5, c.txt=7

Offset of a.txt= directory offset
Offset of b.txt=dir offset + size of a.txt
Offset of c.txt=dir offset + size of b.txt

Is the above assumption correct?

P.S: Here are the callbacks of fuse


Solution

  • The offset passed to the filler function is the offset of the next item in the directory. You can have the entries in the directory in any order you want. If you don't want to return an entire directory at once, you need to use the offset to determine what gets asked for and stored. The order of items in the directory is up to you, and doesn't matter what order the names or inodes or anything else is.

    Specifically, in the readdir call, you are passed an offset. You want to start calling the filler function with entries that will be at this callback or later. In the simplest case, the length of each entry is 24 bytes + strlen(name of entry), rounded up to the nearest multiple of 8 bytes. However, see the fuse source code at http://sourceforge.net/projects/fuse/ for when this might not be the case.

    I have a simple example, where I have a loop (pseudo c-code) in my readdir function:

    int my_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
    {
       (a bunch of prep work has been omitted)
       struct stat st;
       int off, nextoff=0, lenentry, i;
       char namebuf[(long enough for any one name)];
    
       for (i=0; i<NumDirectoryEntries; i++)
       {
          (fill st with the stat information, including inode, etc.)
          (fill namebuf with the name of the directory entry)
          lenentry = ((24+strlen(namebuf)+7)&~7);
          off = nextoff; /* offset of this entry */
          nextoff += lenentry;
          /* Skip this entry if we weren't asked for it */
          if (off<offset)
             continue;
          /* Add this to our response until we are asked to stop */
          if (filler(buf, namebuf, &st, nextoff))
             break;
       }
       /* All done because we were asked to stop or because we finished */
       return 0;
    }
    

    I tested this within my own code (I had never used the offset before), and it works fine.