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:
getattr
(returns error because file doesn't exist)create
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.
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.