Search code examples
clinuxfilesystemsfuse

FUSE open system call mechanism


When calling to the open system call from a program, to create an empty file (with O_WRONLY | O_CREAT | O_TRUNC) in a FUSE managed directory, the following functions from my FUSE file system implementation are executed:

  1. getattr (returns error because file doesn't exist)
  2. create
  3. fgetattr

My question is:

Are these function calls common to all file systems in Linux (including native ones like ext4), or a FUSE internal behaviour?

When strace-ing the program, I can only see an open system call.


Solution

  • After some days spent researching and staring both at Linux kernel and FUSE source code, I understood what was happening.

    First, I have to say that the release after fgetattr wasn't executing when performing the open system call, but when calling close. So I have edited my question to remove it.

    Well, my main problem was that strace showed me a call to the open system call, but my FUSE program log showed that three functions were executed. Hence my question about other filesystems.

    In Linux kernel documentation we can see the kernel VFS explained in detail:

    To look up an inode requires that the VFS calls the lookup() method of the parent directory inode. This method is installed by the specific filesystem implementation that the inode lives in. Once the VFS has the required dentry (and hence the inode), we can do all those boring things like open(2) the file, or stat(2)

    That, in FUSE filesystems, means a lookup call in low level API, or a getattr in the high level API (because inode-path translation is handled by libfuse). Userland code. Other system calls, like mkdir or open with O_CREAT flag, also need a lookup, in this case to confirm a negative dentry before doing anything. Point 1 resolved.

    The dentry you get should not have an inode (i.e. it should be a negative dentry).

    Filesystems implemented into the kernel, like ext4, execute their functions to lookup too. But you can't see them from outside with common tools like strace (you need something like kernelshark, awesome stuff).

    See ext4 lookup function (I'm running a Linux 3.13 kernel)

    The fgetattr function call of point 3 is more related to the libfuse internals. I don't know the exact reason, but a lookup is performed by libfuse after executing functions like mkdir or create. And remember, a lookup is a getattr (or fgetattr for created files) in the high level API. I think it's due to a file/directory attributes checking.

    You can see it in action at libfuse source code for create function.

    Bonus: keep in mind that FUSE uses a file attribute (and entry) cache. Some calls like stat will raise two getattr to the high level API if you set the -o attr_timeout mount option to 0 seconds.